Browse Source

Comment the new code in the Git package

Brendan Abolivier 2 years ago
parent
commit
dce24544fb
Signed by: Brendan Abolivier <contact@brendanabolivier.com> GPG key ID: 8EF1500759F70623
1 changed files with 66 additions and 12 deletions
  1. 66
    12
      src/git/git.go

+ 66
- 12
src/git/git.go View File

@@ -17,13 +17,23 @@ import (
17 17
 	gitssh "gopkg.in/src-d/go-git.v4/plumbing/transport/ssh"
18 18
 )
19 19
 
20
+// Repository represents a Git repository, as an abstraction layer above the
21
+// go-git library in order to also store the current configuration and the
22
+// authentication data needed to talk to the Git remote.
20 23
 type Repository struct {
21 24
 	Repo *gogit.Repository
22 25
 	cfg  config.GitSettings
23 26
 	auth *gitssh.PublicKeys
24 27
 }
25 28
 
29
+// NewRepository creates a new instance of the Repository structure and fills
30
+// it accordingly to the current configuration.
31
+// Returns a boolean if the clone path doesn't contain a valid Git repository
32
+// and needs the repository to be cloned from remote before it is usable.
33
+// Returns an error if there was an issue opening the clone path or loading
34
+// authentication data.
26 35
 func NewRepository(cfg config.GitSettings) (r *Repository, invalidRepo bool, err error) {
36
+	// Load the repository.
27 37
 	repo, err := gogit.PlainOpen(cfg.ClonePath)
28 38
 	if err != nil {
29 39
 		if err == gogit.ErrRepositoryNotExists {
@@ -33,11 +43,14 @@ func NewRepository(cfg config.GitSettings) (r *Repository, invalidRepo bool, err
33 43
 		}
34 44
 	}
35 45
 
46
+	// Fill the structure instance with the gogit.Repository instance and the
47
+	// configuration.
36 48
 	r = &Repository{
37 49
 		Repo: repo,
38 50
 		cfg:  cfg,
39 51
 	}
40 52
 
53
+	// Load authentication data in the structure instance.
41 54
 	err = r.getAuth()
42 55
 	return
43 56
 }
@@ -52,13 +65,13 @@ func NewRepository(cfg config.GitSettings) (r *Repository, invalidRepo bool, err
52 65
 // whether the clone path already exists, or synchronising the repo with the
53 66
 // remote.
54 67
 func (r *Repository) Sync(dontClone bool) (err error) {
55
-	// Check whether the clone path already exists
68
+	// Check whether the clone path already exists.
56 69
 	exists, err := dirExists(r.cfg.ClonePath)
57 70
 	if err != nil {
58 71
 		return
59 72
 	}
60 73
 
61
-	// Check whether the clone path is a Git repository
74
+	// Check whether the clone path is a Git repository.
62 75
 	var isRepo bool
63 76
 	if isRepo, err = dirExists(r.cfg.ClonePath + "/.git"); err != nil {
64 77
 		return
@@ -99,11 +112,11 @@ func (r *Repository) Push() (err error) {
99 112
 		"clone_path": r.cfg.ClonePath,
100 113
 	}).Info("Pushing to the remote")
101 114
 
102
-	// Push to remote
115
+	// Push to remote.
103 116
 	if err = r.Repo.Push(&gogit.PushOptions{
104 117
 		Auth: r.auth,
105 118
 	}); err != nil {
106
-		// Check error against known non-errors
119
+		// Check error against known non-errors.
107 120
 		err = checkRemoteErrors(err, logrus.Fields{
108 121
 			"repo":       r.cfg.User + "@" + r.cfg.URL,
109 122
 			"clone_path": r.cfg.ClonePath,
@@ -114,22 +127,31 @@ func (r *Repository) Push() (err error) {
114 127
 	return err
115 128
 }
116 129
 
130
+// GetLatestCommit retrieves the latest commit from the local Git repository and
131
+// returns it.
132
+// Returns an error if there was an issue fetching the references or loading the
133
+// latest one.
117 134
 func (r *Repository) GetLatestCommit() (*object.Commit, error) {
118
-	// Retrieve latest hash
135
+	// Retrieve the list of references from the repository.
119 136
 	refs, err := r.Repo.References()
120 137
 	if err != nil {
121 138
 		return nil, err
122 139
 	}
123 140
 
141
+	// Extract the latest reference.
124 142
 	ref, err := refs.Next()
125 143
 	if err != nil {
126 144
 		return nil, err
127 145
 	}
128 146
 
147
+	// Load the commit matching the reference's hash and return it.
129 148
 	hash := ref.Hash()
130 149
 	return r.Repo.CommitObject(hash)
131 150
 }
132 151
 
152
+// Log loads the Git repository's log, with the most recent commit having the
153
+// given hash.
154
+// Returns an error if the log couldn't be loaded.
133 155
 func (r *Repository) Log(fromHash string) (object.CommitIter, error) {
134 156
 	hash := plumbing.NewHash(fromHash)
135 157
 
@@ -138,9 +160,20 @@ func (r *Repository) Log(fromHash string) (object.CommitIter, error) {
138 160
 	})
139 161
 }
140 162
 
163
+// GetModifiedAndRemovedFiles takes to commits and returns the name of files
164
+// that were added, modified or removed between these two commits. Note that
165
+// the added/modified files and the removed files are returned in two separated
166
+// slices, mainly because some features using this function need to load the
167
+// files' contents afterwards, and this is done differently depending on whether
168
+// the file was removed or not.
169
+// "from" refers to the oldest commit of both, and "to" to the latest one.
170
+// Returns empty slices and no error if both commits have the same hash.
171
+// Returns an error if there was an issue loading the repository's log, the
172
+// commits' stats, or retrieving a file from the repository.
141 173
 func (r *Repository) GetModifiedAndRemovedFiles(
142 174
 	from *object.Commit, to *object.Commit,
143 175
 ) (modified []string, removed []string, err error) {
176
+	// Initialise the slices.
144 177
 	modified = make([]string, 0)
145 178
 	removed = make([]string, 0)
146 179
 
@@ -153,26 +186,35 @@ func (r *Repository) GetModifiedAndRemovedFiles(
153 186
 		return
154 187
 	}
155 188
 
189
+	// Iterate over the commits contained in the commit's log.
156 190
 	err = iter.ForEach(func(commit *object.Commit) error {
191
+		// If the commit was done by the manager, go to the next iteration.
157 192
 		if commit.Author.Email == r.cfg.CommitsAuthor.Email {
158 193
 			return nil
159 194
 		}
160 195
 
196
+		// If the current commit is the oldest one requested, break the loop.
161 197
 		if commit.Hash.String() == from.Hash.String() {
162 198
 			return storer.ErrStop
163 199
 		}
164 200
 
201
+		// Load stats from the current commit.
165 202
 		stats, err := commit.Stats()
166 203
 		if err != nil {
167 204
 			return err
168 205
 		}
169 206
 
207
+		// Iterate over the files contained in the commit's stats.
170 208
 		for _, stat := range stats {
209
+			// Try to access the file's content.
171 210
 			_, err := commit.File(stat.Name)
172 211
 			if err != nil && err != object.ErrFileNotFound {
173 212
 				return err
174 213
 			}
175 214
 
215
+			// If the content couldn't be retrieved, it means the file was
216
+			// removed in this commit, else it means that it was either added or
217
+			// modified.
176 218
 			if err == object.ErrFileNotFound {
177 219
 				removed = append(removed, stat.Name)
178 220
 			} else {
@@ -186,24 +228,34 @@ func (r *Repository) GetModifiedAndRemovedFiles(
186 228
 	return
187 229
 }
188 230
 
231
+// GetFilesContentsAtCommit retrieves the state of the repository at a given
232
+// commit, and returns a map contaning the contents of all files in the repository
233
+// at this time.
234
+// Returns an error if there was an issue loading the commit's tree, or loading
235
+// a file's content.
189 236
 func (r *Repository) GetFilesContentsAtCommit(commit *object.Commit) (map[string][]byte, error) {
190 237
 	var content string
191 238
 
239
+	// Load the commit's tree.
192 240
 	tree, err := commit.Tree()
193 241
 	if err != nil {
194 242
 		return nil, err
195 243
 	}
196 244
 
245
+	// Initialise the map that will be returned.
197 246
 	filesContents := make(map[string][]byte)
198
-
247
+	// Load the files from the tree.
199 248
 	files := tree.Files()
200 249
 
250
+	// Iterate over the files.
201 251
 	err = files.ForEach(func(file *object.File) error {
252
+		// Try to access the file's content at the given commit.
202 253
 		content, err = file.Contents()
203 254
 		if err != nil {
204 255
 			return err
205 256
 		}
206 257
 
258
+		// Append the content to the map.
207 259
 		filesContents[file.Name] = []byte(content)
208 260
 
209 261
 		return nil
@@ -217,11 +269,13 @@ func (r *Repository) GetFilesContentsAtCommit(commit *object.Commit) (map[string
217 269
 // Returns an error if there was an issue reading the private key file or
218 270
 // parsing it.
219 271
 func (r *Repository) getAuth() error {
272
+	// Load the private key.
220 273
 	privateKey, err := ioutil.ReadFile(r.cfg.PrivateKeyPath)
221 274
 	if err != nil {
222 275
 		return err
223 276
 	}
224 277
 
278
+	// Parse the private key.
225 279
 	signer, err := ssh.ParsePrivateKey(privateKey)
226 280
 	if err != nil {
227 281
 		return err
@@ -250,24 +304,24 @@ func (r *Repository) clone() (err error) {
250 304
 // tree or pulling from the remote. In the latter case, if the error is a known
251 305
 // non-error, doesn't return any error.
252 306
 func (r *Repository) pull() error {
253
-	// Open the repository
307
+	// Open the repository.
254 308
 	repo, err := gogit.PlainOpen(r.cfg.ClonePath)
255 309
 	if err != nil {
256 310
 		return err
257 311
 	}
258 312
 
259
-	// Get its worktree
313
+	// Get its worktree.
260 314
 	w, err := repo.Worktree()
261 315
 	if err != nil {
262 316
 		return err
263 317
 	}
264 318
 
265
-	// Pull from remote
319
+	// Pull from remote.
266 320
 	if err = w.Pull(&gogit.PullOptions{
267 321
 		RemoteName: "origin",
268 322
 		Auth:       r.auth,
269 323
 	}); err != nil {
270
-		// Check error against known non-errors
324
+		// Check error against known non-errors.
271 325
 		err = checkRemoteErrors(err, logrus.Fields{
272 326
 			"clone_path": r.cfg.ClonePath,
273 327
 			"error":      err,
@@ -301,7 +355,7 @@ func dirExists(path string) (bool, error) {
301 355
 func checkRemoteErrors(err error, logFields logrus.Fields) error {
302 356
 	var nonError bool
303 357
 
304
-	// Check against known non-errors
358
+	// Check against known non-errors.
305 359
 	switch err {
306 360
 	case gogit.NoErrAlreadyUpToDate:
307 361
 		nonError = true
@@ -314,7 +368,7 @@ func checkRemoteErrors(err error, logFields logrus.Fields) error {
314 368
 		break
315 369
 	}
316 370
 
317
-	// Log non-error
371
+	// Log non-error.
318 372
 	if nonError {
319 373
 		logrus.WithFields(logFields).Warn("Caught specific non-error")
320 374