-
Notifications
You must be signed in to change notification settings - Fork 32
/
list_refs.go
104 lines (89 loc) · 2.53 KB
/
list_refs.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package git
import (
"bytes"
"context"
"fmt"
"github.com/fluxcd/go-git/v5"
"github.com/fluxcd/go-git/v5/config"
"github.com/fluxcd/go-git/v5/plumbing"
"github.com/fluxcd/go-git/v5/plumbing/protocol/packp"
"github.com/fluxcd/go-git/v5/storage/memory"
auth2 "github.com/kluctl/kluctl/v2/pkg/git/auth"
git_url "github.com/kluctl/kluctl/v2/pkg/git/git-url"
ssh_pool "github.com/kluctl/kluctl/v2/pkg/git/ssh-pool"
"strconv"
)
// ListRemoteRefsFastSsh will reuse existing ssh connections from a pool
func ListRemoteRefsFastSsh(ctx context.Context, url git_url.GitUrl, sshPool *ssh_pool.SshPool, auth auth2.AuthMethodAndCA) ([]*plumbing.Reference, error) {
var portInt int64 = 22
if url.Port() != "" {
var err error
portInt, err = strconv.ParseInt(url.Port(), 10, 32)
if err != nil {
return nil, err
}
}
s, err := sshPool.GetSession(ctx, url.Hostname(), int(portInt), auth)
if err != nil {
return nil, err
}
defer s.Close()
cmd := fmt.Sprintf("git-upload-pack %s", url.Path)
stdout := bytes.NewBuffer(nil)
stderr := bytes.NewBuffer(nil)
stdin := bytes.NewBuffer([]byte("0000\n"))
s.Session.Stdout = stdout
s.Session.Stderr = stderr
s.Session.Stdin = stdin
err = s.Session.Run(cmd)
if err != nil {
return nil, fmt.Errorf("git-upload-pack failed: %w\nstderr=%s", err, stderr.String())
}
ar := packp.NewAdvRefs()
err = ar.Decode(stdout)
if err != nil {
return nil, err
}
allRefs, err := ar.AllReferences()
if err != nil {
return nil, err
}
refs, err := allRefs.IterReferences()
if err != nil {
return nil, err
}
var resultRefs []*plumbing.Reference
err = refs.ForEach(func(ref *plumbing.Reference) error {
resultRefs = append(resultRefs, ref)
return nil
})
if err != nil {
return nil, err
}
return resultRefs, nil
}
func ListRemoteRefsSlow(ctx context.Context, url git_url.GitUrl, auth auth2.AuthMethodAndCA) ([]*plumbing.Reference, error) {
storage := memory.NewStorage()
remote := git.NewRemote(storage, &config.RemoteConfig{
Name: "origin",
URLs: []string{url.String()},
Fetch: defaultFetch,
})
remoteRefs, err := remote.ListContext(ctx, &git.ListOptions{
Auth: auth.AuthMethod,
CABundle: auth.CABundle,
})
if err != nil {
return nil, err
}
return remoteRefs, nil
}
func ListRemoteRefs(ctx context.Context, url git_url.GitUrl, sshPool *ssh_pool.SshPool, auth auth2.AuthMethodAndCA) ([]*plumbing.Reference, error) {
if url.IsSsh() {
refs, err := ListRemoteRefsFastSsh(ctx, url, sshPool, auth)
if err == nil {
return refs, nil
}
}
return ListRemoteRefsSlow(ctx, url, auth)
}