@@ -541,6 +541,80 @@ public virtual HistoryDivergence CalculateHistoryDivergence(Commit one, Commit a
541
541
return new HistoryDivergence ( repo , one , another ) ;
542
542
}
543
543
544
+ /// <summary>
545
+ /// Performs a cherry-pick of <paramref name="cherryPickCommit"/> onto <paramref name="cherryPickOnto"/> commit.
546
+ /// </summary>
547
+ /// <param name="cherryPickCommit">The commit to cherry-pick.</param>
548
+ /// <param name="cherryPickOnto">The commit to cherry-pick onto.</param>
549
+ /// <param name="mainline">Which commit to consider the parent for the diff when cherry-picking a merge commit.</param>
550
+ /// <param name="options">The options for the merging in the cherry-pick operation.</param>
551
+ /// <returns>A result containing a <see cref="Tree"/> if the cherry-pick was successful and a list of <see cref="Conflict"/>s if it is not.</returns>
552
+ public virtual MergeTreeResult CherryPickCommit ( Commit cherryPickCommit , Commit cherryPickOnto , int mainline , MergeTreeOptions options )
553
+ {
554
+ Ensure . ArgumentNotNull ( cherryPickCommit , "cherryPickCommit" ) ;
555
+ Ensure . ArgumentNotNull ( cherryPickOnto , "ours" ) ;
556
+
557
+ options = options ?? new MergeTreeOptions ( ) ;
558
+
559
+ // We throw away the index after looking at the conflicts, so we'll never need the REUC
560
+ // entries to be there
561
+ GitMergeFlag mergeFlags = GitMergeFlag . GIT_MERGE_NORMAL | GitMergeFlag . GIT_MERGE_SKIP_REUC ;
562
+ if ( options . FindRenames )
563
+ {
564
+ mergeFlags |= GitMergeFlag . GIT_MERGE_FIND_RENAMES ;
565
+ }
566
+ if ( options . FailOnConflict )
567
+ {
568
+ mergeFlags |= GitMergeFlag . GIT_MERGE_FAIL_ON_CONFLICT ;
569
+ }
570
+
571
+
572
+ var opts = new GitMergeOpts
573
+ {
574
+ Version = 1 ,
575
+ MergeFileFavorFlags = options . MergeFileFavor ,
576
+ MergeTreeFlags = mergeFlags ,
577
+ RenameThreshold = ( uint ) options . RenameThreshold ,
578
+ TargetLimit = ( uint ) options . TargetLimit
579
+ } ;
580
+
581
+ bool earlyStop ;
582
+
583
+ using ( var cherryPickOntoHandle = Proxy . git_object_lookup ( repo . Handle , cherryPickOnto . Id , GitObjectType . Commit ) )
584
+ using ( var cherryPickCommitHandle = Proxy . git_object_lookup ( repo . Handle , cherryPickCommit . Id , GitObjectType . Commit ) )
585
+ using ( var indexHandle = Proxy . git_cherrypick_commit ( repo . Handle , cherryPickCommitHandle , cherryPickOntoHandle , ( uint ) mainline , opts , out earlyStop ) )
586
+ {
587
+ MergeTreeResult cherryPickResult ;
588
+
589
+ // Stopped due to FailOnConflict so there's no index or conflict list
590
+ if ( earlyStop )
591
+ {
592
+ return new MergeTreeResult ( new Conflict [ ] { } ) ;
593
+ }
594
+
595
+ if ( Proxy . git_index_has_conflicts ( indexHandle ) )
596
+ {
597
+ List < Conflict > conflicts = new List < Conflict > ( ) ;
598
+ Conflict conflict ;
599
+ using ( ConflictIteratorHandle iterator = Proxy . git_index_conflict_iterator_new ( indexHandle ) )
600
+ {
601
+ while ( ( conflict = Proxy . git_index_conflict_next ( iterator ) ) != null )
602
+ {
603
+ conflicts . Add ( conflict ) ;
604
+ }
605
+ }
606
+ cherryPickResult = new MergeTreeResult ( conflicts ) ;
607
+ }
608
+ else
609
+ {
610
+ var treeId = Proxy . git_index_write_tree_to ( indexHandle , repo . Handle ) ;
611
+ cherryPickResult = new MergeTreeResult ( this . repo . Lookup < Tree > ( treeId ) ) ;
612
+ }
613
+
614
+ return cherryPickResult ;
615
+ }
616
+ }
617
+
544
618
/// <summary>
545
619
/// Calculates the current shortest abbreviated <see cref="ObjectId"/>
546
620
/// string representation for a <see cref="GitObject"/>.
@@ -806,5 +880,79 @@ private PackBuilderResults InternalPack(PackBuilderOptions options, Action<PackB
806
880
807
881
return results ;
808
882
}
883
+
884
+ /// <summary>
885
+ /// Performs a revert of <paramref name="revertCommit"/> onto <paramref name="revertOnto"/> commit.
886
+ /// </summary>
887
+ /// <param name="revertCommit">The commit to revert.</param>
888
+ /// <param name="revertOnto">The commit to revert onto.</param>
889
+ /// <param name="mainline">Which commit to consider the parent for the diff when reverting a merge commit.</param>
890
+ /// <param name="options">The options for the merging in the revert operation.</param>
891
+ /// <returns>A result containing a <see cref="Tree"/> if the revert was successful and a list of <see cref="Conflict"/>s if it is not.</returns>
892
+ public virtual MergeTreeResult RevertCommit ( Commit revertCommit , Commit revertOnto , int mainline , MergeTreeOptions options )
893
+ {
894
+ Ensure . ArgumentNotNull ( revertCommit , "revertCommit" ) ;
895
+ Ensure . ArgumentNotNull ( revertOnto , "revertOnto" ) ;
896
+
897
+ options = options ?? new MergeTreeOptions ( ) ;
898
+
899
+ // We throw away the index after looking at the conflicts, so we'll never need the REUC
900
+ // entries to be there
901
+ GitMergeFlag mergeFlags = GitMergeFlag . GIT_MERGE_NORMAL | GitMergeFlag . GIT_MERGE_SKIP_REUC ;
902
+ if ( options . FindRenames )
903
+ {
904
+ mergeFlags |= GitMergeFlag . GIT_MERGE_FIND_RENAMES ;
905
+ }
906
+ if ( options . FailOnConflict )
907
+ {
908
+ mergeFlags |= GitMergeFlag . GIT_MERGE_FAIL_ON_CONFLICT ;
909
+ }
910
+
911
+
912
+ var opts = new GitMergeOpts
913
+ {
914
+ Version = 1 ,
915
+ MergeFileFavorFlags = options . MergeFileFavor ,
916
+ MergeTreeFlags = mergeFlags ,
917
+ RenameThreshold = ( uint ) options . RenameThreshold ,
918
+ TargetLimit = ( uint ) options . TargetLimit
919
+ } ;
920
+
921
+ bool earlyStop ;
922
+
923
+ using ( var revertOntoHandle = Proxy . git_object_lookup ( repo . Handle , revertOnto . Id , GitObjectType . Commit ) )
924
+ using ( var revertCommitHandle = Proxy . git_object_lookup ( repo . Handle , revertCommit . Id , GitObjectType . Commit ) )
925
+ using ( var indexHandle = Proxy . git_revert_commit ( repo . Handle , revertCommitHandle , revertOntoHandle , ( uint ) mainline , opts , out earlyStop ) )
926
+ {
927
+ MergeTreeResult revertTreeResult ;
928
+
929
+ // Stopped due to FailOnConflict so there's no index or conflict list
930
+ if ( earlyStop )
931
+ {
932
+ return new MergeTreeResult ( new Conflict [ ] { } ) ;
933
+ }
934
+
935
+ if ( Proxy . git_index_has_conflicts ( indexHandle ) )
936
+ {
937
+ List < Conflict > conflicts = new List < Conflict > ( ) ;
938
+ Conflict conflict ;
939
+ using ( ConflictIteratorHandle iterator = Proxy . git_index_conflict_iterator_new ( indexHandle ) )
940
+ {
941
+ while ( ( conflict = Proxy . git_index_conflict_next ( iterator ) ) != null )
942
+ {
943
+ conflicts . Add ( conflict ) ;
944
+ }
945
+ }
946
+ revertTreeResult = new MergeTreeResult ( conflicts ) ;
947
+ }
948
+ else
949
+ {
950
+ var treeId = Proxy . git_index_write_tree_to ( indexHandle , repo . Handle ) ;
951
+ revertTreeResult = new MergeTreeResult ( this . repo . Lookup < Tree > ( treeId ) ) ;
952
+ }
953
+
954
+ return revertTreeResult ;
955
+ }
956
+ }
809
957
}
810
958
}
0 commit comments