-
Notifications
You must be signed in to change notification settings - Fork 63
/
Copy pathpull.go
114 lines (95 loc) · 2.87 KB
/
pull.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
105
106
107
108
109
110
111
112
113
114
package src
import (
"context"
"fmt"
"os"
"path"
"strings"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing"
"github.com/spf13/cobra"
)
type PullOnlyFlags struct {
DefaultBranchOnly bool
SourceURL string
}
type PullFlags struct {
CommonFlags
PullOnlyFlags
}
func (f *PullFlags) Init(cmd *cobra.Command) {
f.CommonFlags.Init(cmd)
f.PullOnlyFlags.Init(cmd)
}
func (f *PullOnlyFlags) Init(cmd *cobra.Command) {
cmd.Flags().BoolVar(&f.DefaultBranchOnly, "default-branch-only", false, "Only pull the default branch")
cmd.Flags().StringVar(&f.SourceURL, "source-url", "https://github.com", "The domain to pull from")
}
func (f *PullFlags) Validate() Validations {
return f.CommonFlags.Validate(true).Join(f.PullOnlyFlags.Validate())
}
func (f *PullOnlyFlags) Validate() Validations {
var validations Validations
return validations
}
func Pull(ctx context.Context, flags *PullFlags) error {
repoNames, err := getRepoNamesFromRepoFlags(&flags.CommonFlags)
if err != nil {
return err
}
return PullManyWithGitImpl(ctx, flags.SourceURL, flags.CacheDir, flags.DefaultBranchOnly, repoNames, gitImplementation{})
}
func PullManyWithGitImpl(ctx context.Context, sourceURL, cacheDir string, defaultBranchOnly bool, repoNames []string, gitimpl GitImplementation) error {
for _, repoName := range repoNames {
if err := PullWithGitImpl(ctx, sourceURL, cacheDir, defaultBranchOnly, repoName, gitimpl); err != nil {
return err
}
}
return nil
}
func PullWithGitImpl(ctx context.Context, sourceURL, cacheDir string, defaultBranchOnly bool, repoName string, gitimpl GitImplementation) error {
originRepoName, destRepoName, err := extractSourceDest(repoName)
if err != nil {
return err
}
_ = os.MkdirAll(cacheDir, 0755)
_, err = os.Stat(cacheDir)
if err != nil {
return err
}
dst := path.Join(cacheDir, destRepoName)
if !gitimpl.RepositoryExists(dst) {
fmt.Fprintf(os.Stdout, "pulling %s to %s ...\n", originRepoName, dst)
_, err := gitimpl.CloneRepository(dst, &git.CloneOptions{
ReferenceName: plumbing.HEAD,
SingleBranch: defaultBranchOnly,
URL: fmt.Sprintf("%s/%s", sourceURL, originRepoName),
})
if err != nil {
if strings.Contains(err.Error(), "authentication required") {
return fmt.Errorf("could not pull %s, the repository may require authentication or does not exist", originRepoName)
}
return err
}
}
repo, err := gitimpl.NewGitRepository(dst)
if err != nil {
return err
}
refspec := config.RefSpec("+refs/heads/*:refs/heads/*")
if defaultBranchOnly {
refspec = "+refs/tags/*:refs/tags/*"
}
fmt.Fprintf(os.Stdout, "fetching * refs for %s ...\n", originRepoName)
err = repo.FetchContext(ctx, &git.FetchOptions{
RefSpecs: []config.RefSpec{
refspec,
},
Tags: git.AllTags,
})
if err != nil && err != git.NoErrAlreadyUpToDate {
return err
}
return nil
}