/
git.go
120 lines (111 loc) · 3.08 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
package source
import (
"fmt"
"path/filepath"
"regexp"
"strings"
"github.com/go-git/go-billy/v5"
"github.com/go-git/go-billy/v5/memfs"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/transport/http"
"github.com/go-git/go-git/v5/storage/memory"
)
var repoRegex = regexp.MustCompile(`((?P<auth>(.*))(@))?(?P<path>([a-zA-Z0-9./\-_]+))(#(?P<branch>(.*)))?`)
type GitSource struct {
url string
branch string
auth http.AuthMethod
fs billy.Filesystem
refOrigin string
}
func NewGitSource(conn string) *GitSource {
match := repoRegex.FindStringSubmatch(conn)
paramsMap := make(map[string]string)
for i, name := range repoRegex.SubexpNames() {
if i > 0 && i <= len(match) {
paramsMap[name] = match[i]
}
}
s := &GitSource{}
if authVal, ok := paramsMap["auth"]; ok && authVal != "" {
if strings.Contains(authVal, ":") {
authValParts := strings.Split(authVal, ":")
s.auth = &http.BasicAuth{
Username: authValParts[0],
Password: authValParts[1],
}
} else {
s.auth = &http.TokenAuth{
Token: authVal,
}
}
}
s.refOrigin = "origin"
s.branch = paramsMap["branch"]
s.url = fmt.Sprintf("https://%s", paramsMap["path"])
return s
}
func (s *GitSource) GetTemplateContent() (map[string]string, error) {
if err := s.loadFileSystem(); err != nil {
return nil, err
}
out := make(map[string]string, 0)
err := s.iterateOverTheFiles("/", out)
return out, err
}
func (s *GitSource) loadFileSystem() error {
repo, err := git.Clone(memory.NewStorage(), memfs.New(), &git.CloneOptions{
URL: s.url,
Auth: s.auth,
//Progress: os.Stdout,
// InsecureSkipTLS: true,
SingleBranch: true,
})
if err != nil {
return fmt.Errorf("error cloning the repository '%w'", err)
}
w, err := repo.Worktree()
if err != nil {
return fmt.Errorf("error getting the working tree of the repository '%w'", err)
}
if s.branch != "" {
if err := w.Checkout(&git.CheckoutOptions{
Branch: plumbing.NewRemoteReferenceName(s.refOrigin, s.branch),
}); err != nil {
return fmt.Errorf("error checking out branch '%s' from the repository '%w'", s.branch, err)
}
}
s.fs = w.Filesystem
return nil
}
func (s *GitSource) iterateOverTheFiles(path string, files map[string]string) error {
resources, err := s.fs.ReadDir(path)
if err != nil {
return fmt.Errorf("error reading folder '%s' from repository: '%w", path, err)
}
for _, resource := range resources {
filename := filepath.Join(path, resource.Name())
if resource.IsDir() {
if err := s.iterateOverTheFiles(filename, files); err != nil {
return err
}
continue
}
src, err := s.fs.Open(filename)
if err != nil {
return fmt.Errorf("error opening file '%s' from repository: '%w", filename, err)
}
if resource.Size() == 0 {
files[filename] = ""
continue
}
bytes := make([]byte, resource.Size())
if _, err = src.Read(bytes); err != nil {
return fmt.Errorf("error reading '%v' file '%s' size '%v' from repository: '%w", resource, filename,
resource.Size(), err)
}
files[filename] = string(bytes)
}
return nil
}