forked from hasura/graphql-engine
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgit.go
124 lines (113 loc) · 2.69 KB
/
git.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
115
116
117
118
119
120
121
122
123
124
package util
import (
"os"
"path/filepath"
"github.com/sirupsen/logrus"
"gopkg.in/src-d/go-git.v4"
"gopkg.in/src-d/go-git.v4/config"
"gopkg.in/src-d/go-git.v4/plumbing"
)
// Default Codegen Assets constants
const (
ActionsCodegenOrg string = "hasura/codegen-assets"
ActionsCodegenRepoURI string = "https://github.com/hasura/codegen-assets.git"
ActionsCodegenDirName string = "actions-codegen-assets"
)
// Default init-templates repo constants
const (
InitTemplatesRepoURI string = "https://github.com/hasura/graphql-engine-install-manifests.git"
InitTemplatesDirName string = "init-templates"
)
type GitUtil struct {
URI string
Path string
// Optional
ReferenceName plumbing.ReferenceName
DisableCloneOrUpdate bool
Logger *logrus.Logger
}
func NewGitUtil(uri string, path string, refName string) *GitUtil {
cfg := &GitUtil{
URI: uri,
Path: path,
ReferenceName: plumbing.HEAD,
}
if refName != "" {
cfg.ReferenceName = plumbing.NewBranchReferenceName(refName)
}
return cfg
}
func (g *GitUtil) EnsureCloned() error {
if g.DisableCloneOrUpdate {
g.Logger.Debugf("skipping clone/update for %s", g.URI)
return nil
}
if ok, err := g.IsGitCloned(); err != nil {
return err
} else if !ok {
_, err := git.PlainClone(g.Path, false, &git.CloneOptions{
URL: g.URI,
ReferenceName: g.ReferenceName,
})
if err != nil && err != git.ErrRepositoryAlreadyExists {
return err
}
}
return nil
}
func (g *GitUtil) IsGitCloned() (bool, error) {
f, err := os.Stat(filepath.Join(g.Path, ".git"))
if os.IsNotExist(err) {
return false, nil
}
return err == nil && f.IsDir(), err
}
// EnsureUpdated will ensure the destination path exists and is up to date.
func (g *GitUtil) EnsureUpdated() error {
if g.DisableCloneOrUpdate {
g.Logger.Debugf("skipping clone/update for %s", g.URI)
return nil
}
if err := g.EnsureCloned(); err != nil {
return err
}
return g.updateAndCleanUntracked()
}
func (g *GitUtil) updateAndCleanUntracked() error {
repo, err := git.PlainOpen(g.Path)
if err != nil {
return err
}
err = repo.Fetch(&git.FetchOptions{
RefSpecs: []config.RefSpec{"refs/*:refs/*"},
})
if err != nil && err != git.NoErrAlreadyUpToDate {
return err
}
wt, err := repo.Worktree()
if err != nil {
return err
}
err = wt.Checkout(&git.CheckoutOptions{
Branch: g.ReferenceName,
})
if err != nil {
return err
}
err = wt.Pull(&git.PullOptions{
ReferenceName: g.ReferenceName,
Force: true,
})
if err != nil && err != git.NoErrAlreadyUpToDate {
return err
}
err = wt.Reset(&git.ResetOptions{
Mode: git.HardReset,
})
if err != nil {
return err
}
return wt.Clean(&git.CleanOptions{
Dir: true,
})
}