@@ -169,19 +169,26 @@ func (self *CommitLoader) MergeRebasingCommits(commits []*models.Commit) ([]*mod
169
169
}
170
170
}
171
171
172
- if ! self .getWorkingTreeState ().Rebasing {
173
- // not in rebase mode so return original commits
174
- return result , nil
172
+ workingTreeState := self .getWorkingTreeState ()
173
+ addConflictedRebasingCommit := true
174
+ if workingTreeState .CherryPicking || workingTreeState .Reverting {
175
+ sequencerCommits , err := self .getHydratedSequencerCommits (workingTreeState )
176
+ if err != nil {
177
+ return nil , err
178
+ }
179
+ result = append (sequencerCommits , result ... )
180
+ addConflictedRebasingCommit = false
175
181
}
176
182
177
- rebasingCommits , err := self .getHydratedRebasingCommits ()
178
- if err != nil {
179
- return nil , err
180
- }
181
- if len (rebasingCommits ) > 0 {
182
- result = append (rebasingCommits , result ... )
183
+ if workingTreeState .Rebasing {
184
+ rebasingCommits , err := self .getHydratedRebasingCommits (addConflictedRebasingCommit )
185
+ if err != nil {
186
+ return nil , err
187
+ }
188
+ if len (rebasingCommits ) > 0 {
189
+ result = append (rebasingCommits , result ... )
190
+ }
183
191
}
184
-
185
192
return result , nil
186
193
}
187
194
@@ -240,14 +247,36 @@ func (self *CommitLoader) extractCommitFromLine(line string, showDivergence bool
240
247
}
241
248
}
242
249
243
- func (self * CommitLoader ) getHydratedRebasingCommits () ([]* models.Commit , error ) {
244
- commits := self .getRebasingCommits ()
250
+ func (self * CommitLoader ) getHydratedRebasingCommits (addConflictingCommit bool ) ([]* models.Commit , error ) {
251
+ todoFileHasShortHashes := self .version .IsOlderThan (2 , 25 , 2 )
252
+ return self .getHydratedTodoCommits (self .getRebasingCommits (addConflictingCommit ), todoFileHasShortHashes )
253
+ }
245
254
246
- if len (commits ) == 0 {
255
+ func (self * CommitLoader ) getHydratedSequencerCommits (workingTreeState models.WorkingTreeState ) ([]* models.Commit , error ) {
256
+ commits := self .getSequencerCommits ()
257
+ if len (commits ) > 0 {
258
+ // If we have any commits in .git/sequencer/todo, then the last one of
259
+ // those is the conflicting one.
260
+ commits [len (commits )- 1 ].Status = models .StatusConflicted
261
+ } else {
262
+ // For single-commit cherry-picks and reverts, git apparently doesn't
263
+ // use the sequencer; in that case, CHERRY_PICK_HEAD or REVERT_HEAD is
264
+ // our conflicting commit, so synthesize it here.
265
+ conflicedCommit := self .getConflictedSequencerCommit (workingTreeState )
266
+ if conflicedCommit != nil {
267
+ commits = append (commits , conflicedCommit )
268
+ }
269
+ }
270
+
271
+ return self .getHydratedTodoCommits (commits , true )
272
+ }
273
+
274
+ func (self * CommitLoader ) getHydratedTodoCommits (todoCommits []* models.Commit , todoFileHasShortHashes bool ) ([]* models.Commit , error ) {
275
+ if len (todoCommits ) == 0 {
247
276
return nil , nil
248
277
}
249
278
250
- commitHashes := lo .FilterMap (commits , func (commit * models.Commit , _ int ) (string , bool ) {
279
+ commitHashes := lo .FilterMap (todoCommits , func (commit * models.Commit , _ int ) (string , bool ) {
251
280
return commit .Hash , commit .Hash != ""
252
281
})
253
282
@@ -271,7 +300,7 @@ func (self *CommitLoader) getHydratedRebasingCommits() ([]*models.Commit, error)
271
300
return nil , err
272
301
}
273
302
274
- findFullCommit := lo .Ternary (self . version . IsOlderThan ( 2 , 25 , 2 ) ,
303
+ findFullCommit := lo .Ternary (todoFileHasShortHashes ,
275
304
func (hash string ) * models.Commit {
276
305
for s , c := range fullCommits {
277
306
if strings .HasPrefix (s , hash ) {
@@ -284,8 +313,8 @@ func (self *CommitLoader) getHydratedRebasingCommits() ([]*models.Commit, error)
284
313
return fullCommits [hash ]
285
314
})
286
315
287
- hydratedCommits := make ([]* models.Commit , 0 , len (commits ))
288
- for _ , rebasingCommit := range commits {
316
+ hydratedCommits := make ([]* models.Commit , 0 , len (todoCommits ))
317
+ for _ , rebasingCommit := range todoCommits {
289
318
if rebasingCommit .Hash == "" {
290
319
hydratedCommits = append (hydratedCommits , rebasingCommit )
291
320
} else if commit := findFullCommit (rebasingCommit .Hash ); commit != nil {
@@ -302,7 +331,7 @@ func (self *CommitLoader) getHydratedRebasingCommits() ([]*models.Commit, error)
302
331
// git-rebase-todo example:
303
332
// pick ac446ae94ee560bdb8d1d057278657b251aaef17 ac446ae
304
333
// pick afb893148791a2fbd8091aeb81deba4930c73031 afb8931
305
- func (self * CommitLoader ) getRebasingCommits () []* models.Commit {
334
+ func (self * CommitLoader ) getRebasingCommits (addConflictingCommit bool ) []* models.Commit {
306
335
bytesContent , err := self .readFile (filepath .Join (self .repoPaths .WorktreeGitDirPath (), "rebase-merge/git-rebase-todo" ))
307
336
if err != nil {
308
337
self .Log .Error (fmt .Sprintf ("error occurred reading git-rebase-todo: %s" , err .Error ()))
@@ -320,8 +349,10 @@ func (self *CommitLoader) getRebasingCommits() []*models.Commit {
320
349
321
350
// See if the current commit couldn't be applied because it conflicted; if
322
351
// so, add a fake entry for it
323
- if conflictedCommit := self .getConflictedCommit (todos ); conflictedCommit != nil {
324
- commits = append (commits , conflictedCommit )
352
+ if addConflictingCommit {
353
+ if conflictedCommit := self .getConflictedCommit (todos ); conflictedCommit != nil {
354
+ commits = append (commits , conflictedCommit )
355
+ }
325
356
}
326
357
327
358
for _ , t := range todos {
@@ -435,6 +466,67 @@ func (self *CommitLoader) getConflictedCommitImpl(todos []todo.Todo, doneTodos [
435
466
}
436
467
}
437
468
469
+ func (self * CommitLoader ) getSequencerCommits () []* models.Commit {
470
+ bytesContent , err := self .readFile (filepath .Join (self .repoPaths .WorktreeGitDirPath (), "sequencer/todo" ))
471
+ if err != nil {
472
+ self .Log .Error (fmt .Sprintf ("error occurred reading sequencer/todo: %s" , err .Error ()))
473
+ // we assume an error means the file doesn't exist so we just return
474
+ return nil
475
+ }
476
+
477
+ commits := []* models.Commit {}
478
+
479
+ todos , err := todo .Parse (bytes .NewBuffer (bytesContent ), self .config .GetCoreCommentChar ())
480
+ if err != nil {
481
+ self .Log .Error (fmt .Sprintf ("error occurred while parsing sequencer/todo file: %s" , err .Error ()))
482
+ return nil
483
+ }
484
+
485
+ for _ , t := range todos {
486
+ if t .Commit == "" {
487
+ // Command does not have a commit associated, skip
488
+ continue
489
+ }
490
+ commits = utils .Prepend (commits , & models.Commit {
491
+ Hash : t .Commit ,
492
+ Name : t .Msg ,
493
+ Status : models .StatusRebasing ,
494
+ Action : t .Command ,
495
+ })
496
+ }
497
+
498
+ return commits
499
+ }
500
+
501
+ func (self * CommitLoader ) getConflictedSequencerCommit (workingTreeState models.WorkingTreeState ) * models.Commit {
502
+ var shaFile string
503
+ var action todo.TodoCommand
504
+ if workingTreeState .CherryPicking {
505
+ shaFile = "CHERRY_PICK_HEAD"
506
+ action = todo .Pick
507
+ } else if workingTreeState .Reverting {
508
+ shaFile = "REVERT_HEAD"
509
+ action = todo .Revert
510
+ } else {
511
+ return nil
512
+ }
513
+ bytesContent , err := self .readFile (filepath .Join (self .repoPaths .WorktreeGitDirPath (), shaFile ))
514
+ if err != nil {
515
+ self .Log .Error (fmt .Sprintf ("error occurred reading %s: %s" , shaFile , err .Error ()))
516
+ // we assume an error means the file doesn't exist so we just return
517
+ return nil
518
+ }
519
+ lines := strings .Split (string (bytesContent ), "\n " )
520
+ if len (lines ) == 0 {
521
+ return nil
522
+ }
523
+ return & models.Commit {
524
+ Hash : lines [0 ],
525
+ Status : models .StatusConflicted ,
526
+ Action : action ,
527
+ }
528
+ }
529
+
438
530
func setCommitMergedStatuses (ancestor string , commits []* models.Commit ) {
439
531
if ancestor == "" {
440
532
return
0 commit comments