@@ -36,10 +36,11 @@ import (
36
36
// Where commits "B" and "D" represent reviews that have been submitted, and "G"
37
37
// is a pending review.
38
38
const (
39
- TestTargetRef = "refs/heads/master"
40
- TestReviewRef = "refs/heads/ojarjur/mychange"
41
- TestRequestsRef = "refs/notes/devtools/reviews"
42
- TestCommentsRef = "refs/notes/devtools/discuss"
39
+ TestTargetRef = "refs/heads/master"
40
+ TestReviewRef = "refs/heads/ojarjur/mychange"
41
+ TestAlternateReviewRef = "refs/review/mychange"
42
+ TestRequestsRef = "refs/notes/devtools/reviews"
43
+ TestCommentsRef = "refs/notes/devtools/discuss"
43
44
44
45
TestCommitA = "A"
45
46
TestCommitB = "B"
@@ -78,6 +79,21 @@ type mockRepoForTest struct {
78
79
Notes map [string ]map [string ]string `json:"notes,omitempty"`
79
80
}
80
81
82
+ func (r * mockRepoForTest ) createCommit (message string , time string , parents []string ) (string , error ) {
83
+ newCommit := mockCommit {
84
+ Message : message ,
85
+ Time : time ,
86
+ Parents : parents ,
87
+ }
88
+ newCommitJSON , err := json .Marshal (newCommit )
89
+ if err != nil {
90
+ return "" , err
91
+ }
92
+ newCommitHash := fmt .Sprintf ("%x" , sha1 .Sum ([]byte (newCommitJSON )))
93
+ r .Commits [newCommitHash ] = newCommit
94
+ return newCommitHash , nil
95
+ }
96
+
81
97
// NewMockRepoForTest returns a mocked-out instance of the Repo interface that has been pre-populated with test data.
82
98
func NewMockRepoForTest () Repo {
83
99
commitA := mockCommit {
@@ -130,11 +146,12 @@ func NewMockRepoForTest() Repo {
130
146
Time : "6" ,
131
147
Parents : []string {TestCommitF },
132
148
}
133
- return mockRepoForTest {
149
+ return & mockRepoForTest {
134
150
Head : TestTargetRef ,
135
151
Refs : map [string ]string {
136
- TestTargetRef : TestCommitJ ,
137
- TestReviewRef : TestCommitI ,
152
+ TestTargetRef : TestCommitJ ,
153
+ TestReviewRef : TestCommitI ,
154
+ TestAlternateReviewRef : TestCommitI ,
138
155
},
139
156
Commits : map [string ]mockCommit {
140
157
TestCommitA : commitA ,
@@ -163,10 +180,10 @@ func NewMockRepoForTest() Repo {
163
180
}
164
181
165
182
// GetPath returns the path to the repo.
166
- func (r mockRepoForTest ) GetPath () string { return "~/mockRepo/" }
183
+ func (r * mockRepoForTest ) GetPath () string { return "~/mockRepo/" }
167
184
168
185
// GetRepoStateHash returns a hash which embodies the entire current state of a repository.
169
- func (r mockRepoForTest ) GetRepoStateHash () (string , error ) {
186
+ func (r * mockRepoForTest ) GetRepoStateHash () (string , error ) {
170
187
repoJSON , err := json .Marshal (r )
171
188
if err != nil {
172
189
return "" , err
@@ -175,18 +192,21 @@ func (r mockRepoForTest) GetRepoStateHash() (string, error) {
175
192
}
176
193
177
194
// GetUserEmail returns the email address that the user has used to configure git.
178
- func (r mockRepoForTest ) GetUserEmail () (string , error ) { return "user@example.com" , nil }
195
+ func (r * mockRepoForTest ) GetUserEmail () (string , error ) { return "user@example.com" , nil }
179
196
180
197
// GetCoreEditor returns the name of the editor that the user has used to configure git.
181
- func (r mockRepoForTest ) GetCoreEditor () (string , error ) { return "vi" , nil }
198
+ func (r * mockRepoForTest ) GetCoreEditor () (string , error ) { return "vi" , nil }
182
199
183
200
// GetSubmitStrategy returns the way in which a review is submitted
184
- func (r mockRepoForTest ) GetSubmitStrategy () (string , error ) { return "merge" , nil }
201
+ func (r * mockRepoForTest ) GetSubmitStrategy () (string , error ) { return "merge" , nil }
185
202
186
203
// HasUncommittedChanges returns true if there are local, uncommitted changes.
187
- func (r mockRepoForTest ) HasUncommittedChanges () (bool , error ) { return false , nil }
204
+ func (r * mockRepoForTest ) HasUncommittedChanges () (bool , error ) { return false , nil }
188
205
189
- func (r mockRepoForTest ) resolveLocalRef (ref string ) (string , error ) {
206
+ func (r * mockRepoForTest ) resolveLocalRef (ref string ) (string , error ) {
207
+ if ref == "HEAD" {
208
+ ref = r .Head
209
+ }
190
210
if commit , ok := r .Refs [ref ]; ok {
191
211
return commit , nil
192
212
}
@@ -197,29 +217,29 @@ func (r mockRepoForTest) resolveLocalRef(ref string) (string, error) {
197
217
}
198
218
199
219
// VerifyCommit verifies that the supplied hash points to a known commit.
200
- func (r mockRepoForTest ) VerifyCommit (hash string ) error {
220
+ func (r * mockRepoForTest ) VerifyCommit (hash string ) error {
201
221
if _ , ok := r .Commits [hash ]; ! ok {
202
222
return fmt .Errorf ("The given hash %q is not a known commit" , hash )
203
223
}
204
224
return nil
205
225
}
206
226
207
227
// VerifyGitRef verifies that the supplied ref points to a known commit.
208
- func (r mockRepoForTest ) VerifyGitRef (ref string ) error {
228
+ func (r * mockRepoForTest ) VerifyGitRef (ref string ) error {
209
229
_ , err := r .resolveLocalRef (ref )
210
230
return err
211
231
}
212
232
213
233
// GetHeadRef returns the ref that is the current HEAD.
214
- func (r mockRepoForTest ) GetHeadRef () (string , error ) { return r .Head , nil }
234
+ func (r * mockRepoForTest ) GetHeadRef () (string , error ) { return r .Head , nil }
215
235
216
236
// GetCommitHash returns the hash of the commit pointed to by the given ref.
217
- func (r mockRepoForTest ) GetCommitHash (ref string ) (string , error ) {
237
+ func (r * mockRepoForTest ) GetCommitHash (ref string ) (string , error ) {
218
238
err := r .VerifyGitRef (ref )
219
239
if err != nil {
220
240
return "" , err
221
241
}
222
- return r .Refs [ ref ], nil
242
+ return r .resolveLocalRef ( ref )
223
243
}
224
244
225
245
// ResolveRefCommit returns the commit pointed to by the given ref, which may be a remote ref.
@@ -231,20 +251,20 @@ func (r mockRepoForTest) GetCommitHash(ref string) (string, error) {
231
251
// This method should be used when a command may be performed by either the reviewer or the
232
252
// reviewee, while GetCommitHash should be used when the encompassing command should only be
233
253
// performed by the reviewee.
234
- func (r mockRepoForTest ) ResolveRefCommit (ref string ) (string , error ) {
254
+ func (r * mockRepoForTest ) ResolveRefCommit (ref string ) (string , error ) {
235
255
if commit , err := r .resolveLocalRef (ref ); err == nil {
236
256
return commit , err
237
257
}
238
258
return r .resolveLocalRef (strings .Replace (ref , "refs/heads/" , "refs/remotes/origin/" , 1 ))
239
259
}
240
260
241
- func (r mockRepoForTest ) getCommit (ref string ) (mockCommit , error ) {
261
+ func (r * mockRepoForTest ) getCommit (ref string ) (mockCommit , error ) {
242
262
commit , err := r .resolveLocalRef (ref )
243
263
return r .Commits [commit ], err
244
264
}
245
265
246
266
// GetCommitMessage returns the message stored in the commit pointed to by the given ref.
247
- func (r mockRepoForTest ) GetCommitMessage (ref string ) (string , error ) {
267
+ func (r * mockRepoForTest ) GetCommitMessage (ref string ) (string , error ) {
248
268
commit , err := r .getCommit (ref )
249
269
if err != nil {
250
270
return "" , err
@@ -253,7 +273,7 @@ func (r mockRepoForTest) GetCommitMessage(ref string) (string, error) {
253
273
}
254
274
255
275
// GetCommitTime returns the commit time of the commit pointed to by the given ref.
256
- func (r mockRepoForTest ) GetCommitTime (ref string ) (string , error ) {
276
+ func (r * mockRepoForTest ) GetCommitTime (ref string ) (string , error ) {
257
277
commit , err := r .getCommit (ref )
258
278
if err != nil {
259
279
return "" , err
@@ -262,7 +282,7 @@ func (r mockRepoForTest) GetCommitTime(ref string) (string, error) {
262
282
}
263
283
264
284
// GetLastParent returns the last parent of the given commit (as ordered by git).
265
- func (r mockRepoForTest ) GetLastParent (ref string ) (string , error ) {
285
+ func (r * mockRepoForTest ) GetLastParent (ref string ) (string , error ) {
266
286
commit , err := r .getCommit (ref )
267
287
if len (commit .Parents ) > 0 {
268
288
return commit .Parents [len (commit .Parents )- 1 ], err
@@ -271,7 +291,7 @@ func (r mockRepoForTest) GetLastParent(ref string) (string, error) {
271
291
}
272
292
273
293
// GetCommitDetails returns the details of a commit's metadata.
274
- func (r mockRepoForTest ) GetCommitDetails (ref string ) (* CommitDetails , error ) {
294
+ func (r * mockRepoForTest ) GetCommitDetails (ref string ) (* CommitDetails , error ) {
275
295
commit , err := r .getCommit (ref )
276
296
if err != nil {
277
297
return nil , err
@@ -286,7 +306,7 @@ func (r mockRepoForTest) GetCommitDetails(ref string) (*CommitDetails, error) {
286
306
}
287
307
288
308
// ancestors returns the breadth-first traversal of a commit's ancestors
289
- func (r mockRepoForTest ) ancestors (commit string ) ([]string , error ) {
309
+ func (r * mockRepoForTest ) ancestors (commit string ) ([]string , error ) {
290
310
queue := []string {commit }
291
311
var ancestors []string
292
312
for queue != nil {
@@ -306,7 +326,16 @@ func (r mockRepoForTest) ancestors(commit string) ([]string, error) {
306
326
}
307
327
308
328
// IsAncestor determines if the first argument points to a commit that is an ancestor of the second.
309
- func (r mockRepoForTest ) IsAncestor (ancestor , descendant string ) (bool , error ) {
329
+ func (r * mockRepoForTest ) IsAncestor (ancestor , descendant string ) (bool , error ) {
330
+ var err error
331
+ ancestor , err = r .resolveLocalRef (ancestor )
332
+ if err != nil {
333
+ return false , err
334
+ }
335
+ descendant , err = r .resolveLocalRef (descendant )
336
+ if err != nil {
337
+ return false , err
338
+ }
310
339
if ancestor == descendant {
311
340
return true , nil
312
341
}
@@ -323,7 +352,7 @@ func (r mockRepoForTest) IsAncestor(ancestor, descendant string) (bool, error) {
323
352
}
324
353
325
354
// MergeBase determines if the first commit that is an ancestor of the two arguments.
326
- func (r mockRepoForTest ) MergeBase (a , b string ) (string , error ) {
355
+ func (r * mockRepoForTest ) MergeBase (a , b string ) (string , error ) {
327
356
ancestors , err := r .ancestors (a )
328
357
if err != nil {
329
358
return "" , err
@@ -337,17 +366,17 @@ func (r mockRepoForTest) MergeBase(a, b string) (string, error) {
337
366
}
338
367
339
368
// Diff computes the diff between two given commits.
340
- func (r mockRepoForTest ) Diff (left , right string , diffArgs ... string ) (string , error ) {
369
+ func (r * mockRepoForTest ) Diff (left , right string , diffArgs ... string ) (string , error ) {
341
370
return fmt .Sprintf ("Diff between %q and %q" , left , right ), nil
342
371
}
343
372
344
373
// Show returns the contents of the given file at the given commit.
345
- func (r mockRepoForTest ) Show (commit , path string ) (string , error ) {
374
+ func (r * mockRepoForTest ) Show (commit , path string ) (string , error ) {
346
375
return fmt .Sprintf ("%s:%s" , commit , path ), nil
347
376
}
348
377
349
378
// SwitchToRef changes the currently-checked-out ref.
350
- func (r mockRepoForTest ) SwitchToRef (ref string ) error {
379
+ func (r * mockRepoForTest ) SwitchToRef (ref string ) error {
351
380
r .Head = ref
352
381
return nil
353
382
}
@@ -361,23 +390,82 @@ func (r mockRepoForTest) SwitchToRef(ref string) error {
361
390
//
362
391
// If the ref pointed to by the 'archive' argument does not exist
363
392
// yet, then it will be created.
364
- func (r mockRepoForTest ) ArchiveRef (ref , archive string ) error { return nil }
393
+ func (r * mockRepoForTest ) ArchiveRef (ref , archive string ) error {
394
+ commitToArchive , err := r .resolveLocalRef (ref )
395
+ if err != nil {
396
+ return err
397
+ }
398
+ var archiveParents []string
399
+ if archiveCommit , err := r .resolveLocalRef (archive ); err == nil {
400
+ archiveParents = []string {archiveCommit , commitToArchive }
401
+ } else {
402
+ archiveParents = []string {commitToArchive }
403
+ }
404
+ archiveCommit , err := r .createCommit ("Archiving" , "Nowish" , archiveParents )
405
+ if err != nil {
406
+ return err
407
+ }
408
+ r .Refs [archive ] = archiveCommit
409
+ return nil
410
+ }
365
411
366
412
// MergeRef merges the given ref into the current one.
367
413
//
368
414
// The ref argument is the ref to merge, and fastForward indicates that the
369
415
// current ref should only move forward, as opposed to creating a bubble merge.
370
- func (r mockRepoForTest ) MergeRef (ref string , fastForward bool , messages ... string ) error { return nil }
416
+ func (r * mockRepoForTest ) MergeRef (ref string , fastForward bool , messages ... string ) error {
417
+ newCommitHash , err := r .resolveLocalRef (ref )
418
+ if err != nil {
419
+ return err
420
+ }
421
+ if ! fastForward {
422
+ origCommit , err := r .resolveLocalRef (r .Head )
423
+ if err != nil {
424
+ return err
425
+ }
426
+ newCommit , err := r .getCommit (ref )
427
+ if err != nil {
428
+ return err
429
+ }
430
+ message := strings .Join (messages , "\n \n " )
431
+ time := newCommit .Time
432
+ parents := []string {origCommit , newCommitHash }
433
+ newCommitHash , err = r .createCommit (message , time , parents )
434
+ if err != nil {
435
+ return err
436
+ }
437
+ }
438
+ r .Refs [r .Head ] = newCommitHash
439
+ return nil
440
+ }
371
441
372
442
// RebaseRef rebases the current ref onto the given one.
373
- func (r mockRepoForTest ) RebaseRef (ref string ) error { return nil }
443
+ func (r * mockRepoForTest ) RebaseRef (ref string ) error {
444
+ parentHash := r .Refs [ref ]
445
+ origCommit , err := r .getCommit (r .Head )
446
+ if err != nil {
447
+ return err
448
+ }
449
+ newCommitHash , err := r .createCommit (origCommit .Message , origCommit .Time , []string {parentHash })
450
+ if err != nil {
451
+ return err
452
+ }
453
+ if strings .HasPrefix (r .Head , "refs/heads/" ) {
454
+ r .Refs [r .Head ] = newCommitHash
455
+ } else {
456
+ // The current head is not a branch, so updating
457
+ // it should leave us in a detached-head state.
458
+ r .Head = newCommitHash
459
+ }
460
+ return nil
461
+ }
374
462
375
463
// ListCommits returns the list of commits reachable from the given ref.
376
464
//
377
465
// The generated list is in chronological order (with the oldest commit first).
378
466
//
379
467
// If the specified ref does not exist, then this method returns an empty result.
380
- func (r mockRepoForTest ) ListCommits (ref string ) []string { return nil }
468
+ func (r * mockRepoForTest ) ListCommits (ref string ) []string { return nil }
381
469
382
470
// ListCommitsBetween returns the list of commits between the two given revisions.
383
471
//
@@ -393,7 +481,7 @@ func (r mockRepoForTest) ListCommits(ref string) []string { return nil }
393
481
// method compatible with git's built-in "rev-list" command.
394
482
//
395
483
// The generated list is in chronological order (with the oldest commit first).
396
- func (r mockRepoForTest ) ListCommitsBetween (from , to string ) ([]string , error ) {
484
+ func (r * mockRepoForTest ) ListCommitsBetween (from , to string ) ([]string , error ) {
397
485
commits := []string {to }
398
486
potentialCommits , _ := r .ancestors (to )
399
487
for _ , commit := range potentialCommits {
@@ -409,7 +497,7 @@ func (r mockRepoForTest) ListCommitsBetween(from, to string) ([]string, error) {
409
497
}
410
498
411
499
// GetNotes reads the notes from the given ref that annotate the given revision.
412
- func (r mockRepoForTest ) GetNotes (notesRef , revision string ) []Note {
500
+ func (r * mockRepoForTest ) GetNotes (notesRef , revision string ) []Note {
413
501
notesText := r.Notes [notesRef ][revision ]
414
502
var notes []Note
415
503
for _ , line := range strings .Split (notesText , "\n " ) {
@@ -423,7 +511,7 @@ func (r mockRepoForTest) GetNotes(notesRef, revision string) []Note {
423
511
// The returned value is a mapping from commit hash to the list of notes for that commit.
424
512
//
425
513
// This is the batch version of the corresponding GetNotes(...) method.
426
- func (r mockRepoForTest ) GetAllNotes (notesRef string ) (map [string ][]Note , error ) {
514
+ func (r * mockRepoForTest ) GetAllNotes (notesRef string ) (map [string ][]Note , error ) {
427
515
notesMap := make (map [string ][]Note )
428
516
for _ , commit := range r .ListNotedRevisions (notesRef ) {
429
517
notesMap [commit ] = r .GetNotes (notesRef , commit )
@@ -432,15 +520,15 @@ func (r mockRepoForTest) GetAllNotes(notesRef string) (map[string][]Note, error)
432
520
}
433
521
434
522
// AppendNote appends a note to a revision under the given ref.
435
- func (r mockRepoForTest ) AppendNote (ref , revision string , note Note ) error {
523
+ func (r * mockRepoForTest ) AppendNote (ref , revision string , note Note ) error {
436
524
existingNotes := r.Notes [ref ][revision ]
437
525
newNotes := existingNotes + "\n " + string (note )
438
526
r.Notes [ref ][revision ] = newNotes
439
527
return nil
440
528
}
441
529
442
530
// ListNotedRevisions returns the collection of revisions that are annotated by notes in the given ref.
443
- func (r mockRepoForTest ) ListNotedRevisions (notesRef string ) []string {
531
+ func (r * mockRepoForTest ) ListNotedRevisions (notesRef string ) []string {
444
532
var revisions []string
445
533
for revision := range r .Notes [notesRef ] {
446
534
if _ , ok := r .Commits [revision ]; ok {
@@ -451,15 +539,15 @@ func (r mockRepoForTest) ListNotedRevisions(notesRef string) []string {
451
539
}
452
540
453
541
// PushNotes pushes git notes to a remote repo.
454
- func (r mockRepoForTest ) PushNotes (remote , notesRefPattern string ) error { return nil }
542
+ func (r * mockRepoForTest ) PushNotes (remote , notesRefPattern string ) error { return nil }
455
543
456
544
// PullNotes fetches the contents of the given notes ref from a remote repo,
457
545
// and then merges them with the corresponding local notes using the
458
546
// "cat_sort_uniq" strategy.
459
- func (r mockRepoForTest ) PullNotes (remote , notesRefPattern string ) error { return nil }
547
+ func (r * mockRepoForTest ) PullNotes (remote , notesRefPattern string ) error { return nil }
460
548
461
549
// PushNotesAndArchive pushes the given notes and archive refs to a remote repo.
462
- func (r mockRepoForTest ) PushNotesAndArchive (remote , notesRefPattern , archiveRefPattern string ) error {
550
+ func (r * mockRepoForTest ) PushNotesAndArchive (remote , notesRefPattern , archiveRefPattern string ) error {
463
551
return nil
464
552
}
465
553
@@ -475,6 +563,6 @@ func (r mockRepoForTest) PushNotesAndArchive(remote, notesRefPattern, archiveRef
475
563
// so we do not maintain any consistency with their tree objects. Instead,
476
564
// we merely ensure that their history graph includes every commit that we
477
565
// intend to keep.
478
- func (r mockRepoForTest ) PullNotesAndArchive (remote , notesRefPattern , archiveRefPattern string ) error {
566
+ func (r * mockRepoForTest ) PullNotesAndArchive (remote , notesRefPattern , archiveRefPattern string ) error {
479
567
return nil
480
568
}
0 commit comments