-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcrawl.go
234 lines (196 loc) · 4.5 KB
/
crawl.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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
package main
import (
"errors"
"github.com/go-git/go-git/v5"
gitobject "github.com/go-git/go-git/v5/plumbing/object"
"io/ioutil"
"log"
"net/url"
"os"
"path/filepath"
"sort"
"strings"
"sync"
"time"
)
var (
pullMutex sync.Mutex
pullTime time.Time
)
// Clone the repo if it doesn't exist of download it if it does.
func cloneIfNotExist() error {
// Check if the repo already exists
if _, err := os.Stat(getGitDir()); err == nil {
log.Println("Repository already exists.")
return nil
}
// Since it doesn't exist, we will clone it now
log.Println("Clone repository...")
_, err := git.PlainClone(getGitDir(), false, &git.CloneOptions{
URL: os.Getenv("GIT_URL"),
RecurseSubmodules: git.DefaultSubmoduleRecursionDepth,
})
if err != nil {
return err
}
log.Println("Done")
return nil
}
// Pull the repo from the origin
func pull() error {
// Lock the Mutex
pullMutex.Lock()
defer pullMutex.Unlock()
// Open the repo
r, err := git.PlainOpen(getGitDir())
if err != nil {
return err
}
// Get the working directory for the repository
w, err := r.Worktree()
if err != nil {
return err
}
// Pull the latest changes from the origin remote and merge into the current branch
err = w.Pull(&git.PullOptions{RemoteName: "origin"})
pullTime = time.Now()
if err != nil && err != git.NoErrAlreadyUpToDate {
return err
}
return nil
}
// The list is chronocally sorted with the newest commits as last
func history() ([]gitobject.Commit, error) {
// Open the repo
r, err := git.PlainOpen(getGitDir())
if err != nil {
return nil, err
}
// Get the HEAD
cIter, err := r.Log(&git.LogOptions{})
if err != nil {
return nil, err
}
// Make a list of commits
var commits []gitobject.Commit
err = cIter.ForEach(func(c *gitobject.Commit) error {
commits = append(commits, *c)
return nil
})
if err != nil {
return nil, err
}
// Sort the commits
sort.Slice(commits, func(i, j int) bool {
return commits[i].Author.When.Local().Unix() < commits[j].Author.When.Local().Unix()
})
return commits, nil
}
// Get all commits between two commits
// Since is not included, until however is
func historyBetween(since string, until string) ([]gitobject.Commit, error) {
all, err := history()
if err != nil {
return nil, err
}
// Filter the commits
var between []gitobject.Commit
sawSince := false
for _, c := range all {
if sawSince {
between = append(between, c)
}
if c.Hash.String() == since {
sawSince = true
}
if c.Hash.String() == until {
break
}
}
return between, nil
}
// Get all commits since a past commit (given with since which is a commit hash)
func historySince(since string) ([]gitobject.Commit, error) {
curr, err := getCurrentCommit()
if err != nil {
return nil, err
}
return historyBetween(since, curr)
}
// Get the username from the git URL (your username).
func getGitUser() string {
url, _ := url.Parse(os.Getenv("GIT_URL"))
return url.User.Username()
}
func getGitDir() string {
return filepath.Join("data", "repo")
}
// Get the current commit hash
func getCurrentCommit() (string, error) {
r, err := git.PlainOpen(getGitDir())
if err != nil {
return "", err
}
ref, err := r.Head()
return ref.Hash().String(), nil
}
func getPullTime() time.Time {
pullMutex.Lock()
defer pullMutex.Unlock()
return pullTime
}
func readFile(path string) ([]byte, error) {
path = filepath.Clean(path)
err := checkPath(path)
if err != nil {
return nil, err
}
return ioutil.ReadFile(filepath.Join(getGitDir(), path))
}
func listFiles(path string) ([]string, error) {
path = filepath.Clean("/" + path)
err := checkPath(path)
if err != nil {
return nil, err
}
files, err := ioutil.ReadDir(filepath.Join(getGitDir(), path))
if err != nil {
log.Println(err)
return nil, err
}
names := make([]string, 0, len(files))
for _, file := range files {
name := ""
if file.IsDir() {
name = "📁 "
} else {
name = "📄 "
}
name += file.Name()
names = append(names, name)
}
return names, nil
}
func listFilesRaw(path string) ([]string, error) {
path = filepath.Clean("/" + path)
err := checkPath(path)
if err != nil {
return nil, err
}
files, err := ioutil.ReadDir(filepath.Join(getGitDir(), path))
if err != nil {
log.Println(err)
return nil, err
}
names := make([]string, 0, len(files))
for _, file := range files {
names = append(names, file.Name())
}
return names, nil
}
func checkPath(path string) error {
if strings.Contains(path, ".git") {
return errors.New("you cannot read the git directory")
}
return nil
}