@@ -447,6 +447,248 @@ func TestGetConfigValue(t *testing.T) {
447447 assert .Error (t , err , "git config: non-existing key" )
448448}
449449
450+ func TestFindForkPoint (t * testing.T ) {
451+ repodir := mkOneCommitRepo (t )
452+
453+ gw , err := git .WithConfig (git.Config {
454+ WorkingDir : repodir ,
455+ Isolated : true ,
456+ Env : []string {},
457+ AllowPorcelain : true ,
458+ })
459+ assert .NoError (t , err , "new git wrapper" )
460+
461+ hashToName := map [string ]string {"" : "" }
462+ nameToHash := map [string ]string {"" : "" }
463+
464+ setNamedCommit := func (name string ) {
465+ hash , err := gw .RevParse ("HEAD" )
466+ assert .NoError (t , err )
467+
468+ hashToName [hash ] = name
469+ nameToHash [name ] = hash
470+ }
471+
472+ makeNamedCommit := func (name string ) {
473+ test .WriteFile (t , repodir , name , "" )
474+ assert .NoError (t , gw .Add (name ))
475+ assert .NoError (t , gw .Commit (name ))
476+
477+ setNamedCommit (name )
478+ }
479+
480+ type testcase struct {
481+ Commit string
482+ ForkedFrom string
483+
484+ WantForkPoint string
485+ }
486+
487+ var tests []testcase
488+
489+ setNamedCommit ("main_commit_1" )
490+
491+ tests = append (tests , []testcase {
492+ {
493+ Commit : "main_commit_1" ,
494+ ForkedFrom : "main" ,
495+ WantForkPoint : "main_commit_1" ,
496+ }}... ,
497+ )
498+
499+ assert .NoError (t , gw .Checkout ("branch_a" , true ))
500+ makeNamedCommit ("branch_a_commit_1" )
501+ makeNamedCommit ("branch_a_commit_2" )
502+
503+ tests = append (tests , []testcase {
504+ {
505+ Commit : "branch_a_commit_1" ,
506+ ForkedFrom : "main" ,
507+ WantForkPoint : "main_commit_1" ,
508+ },
509+ {
510+ Commit : "branch_a_commit_2" ,
511+ ForkedFrom : "main" ,
512+ WantForkPoint : "main_commit_1" ,
513+ }}... ,
514+ )
515+
516+ assert .NoError (t , gw .Checkout ("main" , false ))
517+ assert .NoError (t , gw .Merge ("branch_a" ))
518+ setNamedCommit ("main_commit_2" )
519+
520+ tests = append (tests , []testcase {
521+ {
522+ Commit : "main_commit_2" ,
523+ ForkedFrom : "main" ,
524+ WantForkPoint : "main_commit_2" ,
525+ }}... ,
526+ )
527+
528+ assert .NoError (t , gw .Checkout ("branch_b" , true ))
529+ makeNamedCommit ("branch_b_commit_1" )
530+ makeNamedCommit ("branch_b_commit_2" )
531+
532+ tests = append (tests , []testcase {
533+ {
534+ ForkedFrom : "main" ,
535+ Commit : "branch_b_commit_1" ,
536+ WantForkPoint : "main_commit_2" ,
537+ },
538+ {
539+ ForkedFrom : "main" ,
540+ Commit : "branch_b_commit_2" ,
541+ WantForkPoint : "main_commit_2" ,
542+ }}... ,
543+ )
544+
545+ assert .NoError (t , gw .Checkout ("main" , false ))
546+ assert .NoError (t , gw .Merge ("branch_b" ))
547+ setNamedCommit ("main_commit_3" )
548+
549+ tests = append (tests , []testcase {
550+ {
551+ Commit : "main_commit_3" ,
552+ ForkedFrom : "main" ,
553+ WantForkPoint : "main_commit_3" ,
554+ }}... ,
555+ )
556+
557+ assert .NoError (t , gw .Checkout ("branch_unmerged" , true ))
558+ makeNamedCommit ("branch_unmerged_commit_1" )
559+ makeNamedCommit ("branch_unmerged_commit_2" )
560+ makeNamedCommit ("branch_unmerged_commit_3" )
561+
562+ tests = append (tests , []testcase {
563+ {
564+ Commit : "branch_unmerged_commit_1" ,
565+ ForkedFrom : "main" ,
566+ WantForkPoint : "main_commit_3" ,
567+ },
568+ {
569+ Commit : "branch_unmerged_commit_2" ,
570+ ForkedFrom : "main" ,
571+ WantForkPoint : "main_commit_3" ,
572+ },
573+ {
574+ Commit : "branch_unmerged_commit_3" ,
575+ ForkedFrom : "main" ,
576+ WantForkPoint : "main_commit_3" ,
577+ }}... ,
578+ )
579+
580+ assert .NoError (t , gw .Checkout ("main" , false ))
581+ assert .NoError (t , gw .Checkout ("branch_c" , true ))
582+ makeNamedCommit ("branch_c_commit_1" )
583+
584+ assert .NoError (t , gw .Checkout ("branch_d" , true ))
585+ makeNamedCommit ("branch_d_commit_1" )
586+
587+ assert .NoError (t , gw .Checkout ("branch_c" , false ))
588+ assert .NoError (t , gw .Merge ("branch_d" ))
589+ setNamedCommit ("branch_c_commit_2" )
590+
591+ makeNamedCommit ("branch_c_commit_3" )
592+
593+ assert .NoError (t , gw .Checkout ("main" , false ))
594+ assert .NoError (t , gw .Merge ("branch_c" ))
595+ setNamedCommit ("main_commit_4" )
596+
597+ tests = append (tests , []testcase {
598+ {
599+ Commit : "branch_c_commit_1" ,
600+ ForkedFrom : "main" ,
601+ WantForkPoint : "main_commit_3" ,
602+ },
603+ {
604+ Commit : "branch_d_commit_1" ,
605+ ForkedFrom : "main" ,
606+ WantForkPoint : "main_commit_3" ,
607+ },
608+ {
609+ Commit : "branch_d_commit_1" ,
610+ ForkedFrom : "branch_c" ,
611+ WantForkPoint : "branch_c_commit_1" ,
612+ },
613+ {
614+ Commit : "branch_c_commit_2" ,
615+ ForkedFrom : "main" ,
616+ WantForkPoint : "main_commit_3" ,
617+ },
618+ {
619+ Commit : "branch_c_commit_3" ,
620+ ForkedFrom : "main" ,
621+ WantForkPoint : "main_commit_3" ,
622+ },
623+ {
624+ Commit : "main_commit_4" ,
625+ ForkedFrom : "main" ,
626+ WantForkPoint : "main_commit_4" ,
627+ }}... ,
628+ )
629+
630+ assert .NoError (t , gw .Checkout ("branch_wip" , true ))
631+ makeNamedCommit ("branch_wip_commit_1" )
632+ makeNamedCommit ("branch_wip_commit_2" )
633+
634+ tests = append (tests , []testcase {
635+ {
636+ Commit : "branch_wip_commit_1" ,
637+ ForkedFrom : "main" ,
638+ WantForkPoint : "main_commit_4" ,
639+ },
640+ {
641+ Commit : "branch_wip_commit_2" ,
642+ ForkedFrom : "main" ,
643+ WantForkPoint : "main_commit_4" ,
644+ }}... ,
645+ )
646+
647+ /*
648+ * branch_wip_commit_2
649+ * branch_wip_commit_1
650+ /
651+ * main_commit_4
652+ |\
653+ | * branch_c_commit_3
654+ | * branch_c_commit_2
655+ | |\
656+ | | * branch_d_commit_1
657+ | |/
658+ | * branch_c_commit_1
659+ |/
660+ |
661+ | * branch_unmerged_commit_3
662+ | * branch_unmerged_commit_2
663+ | * branch_unmerged_commit_1
664+ |/
665+ * main_commit_3
666+ |\
667+ | * branch_b_commit_2
668+ | * branch_b_commit_1
669+ |/
670+ * main_commit_2
671+ |\
672+ | * branch_a_commit_2
673+ | * branch_a_commit_1
674+ |/
675+ * main_commit_1
676+ */
677+
678+ for _ , tc := range tests {
679+ wantName := tc .WantForkPoint
680+ wantHash := nameToHash [wantName ]
681+
682+ gotHash , err := gw .FindForkPoint (tc .ForkedFrom , nameToHash [tc .Commit ])
683+ assert .NoError (t , err )
684+ gotName := hashToName [gotHash ]
685+
686+ assert .EqualStrings (t , wantHash , gotHash ,
687+ "fork point, wantName=%v gotName=%v, wantHash=%v gotHash=%v" ,
688+ wantName , gotName , wantHash , gotHash )
689+ }
690+ }
691+
450692const defaultBranch = "main"
451693
452694func mkOneCommitRepo (t * testing.T ) string {
0 commit comments