@@ -497,6 +497,35 @@ def index(self):
497
497
#
498
498
# Merging
499
499
#
500
+
501
+ @staticmethod
502
+ def _merge_options (favor ):
503
+ """Return a 'git_merge_opts *'
504
+ """
505
+ def favor_to_enum (favor ):
506
+ if favor == 'normal' :
507
+ return C .GIT_MERGE_FILE_FAVOR_NORMAL
508
+ elif favor == 'ours' :
509
+ return C .GIT_MERGE_FILE_FAVOR_OURS
510
+ elif favor == 'theirs' :
511
+ return C .GIT_MERGE_FILE_FAVOR_THEIRS
512
+ elif favor == 'union' :
513
+ return C .GIT_MERGE_FILE_FAVOR_UNION
514
+ else :
515
+ return None
516
+
517
+ favor_val = favor_to_enum (favor )
518
+ if favor_val is None :
519
+ raise ValueError ("unkown favor value %s" % favor )
520
+
521
+ opts = ffi .new ('git_merge_options *' )
522
+ err = C .git_merge_init_options (opts , C .GIT_MERGE_OPTIONS_VERSION )
523
+ check_error (err )
524
+
525
+ opts .file_favor = favor_val
526
+
527
+ return opts
528
+
500
529
def merge_commits (self , ours , theirs , favor = 'normal' ):
501
530
"""Merge two arbitrary commits
502
531
@@ -522,21 +551,9 @@ def merge_commits(self, ours, theirs, favor='normal'):
522
551
Returns an index with the result of the merge
523
552
524
553
"""
525
- def favor_to_enum (favor ):
526
- if favor == 'normal' :
527
- return C .GIT_MERGE_FILE_FAVOR_NORMAL
528
- elif favor == 'ours' :
529
- return C .GIT_MERGE_FILE_FAVOR_OURS
530
- elif favor == 'theirs' :
531
- return C .GIT_MERGE_FILE_FAVOR_THEIRS
532
- elif favor == 'union' :
533
- return C .GIT_MERGE_FILE_FAVOR_UNION
534
- else :
535
- return None
536
554
537
555
ours_ptr = ffi .new ('git_commit **' )
538
556
theirs_ptr = ffi .new ('git_commit **' )
539
- opts = ffi .new ('git_merge_options *' )
540
557
cindex = ffi .new ('git_index **' )
541
558
542
559
if is_string (ours ) or isinstance (ours , Oid ):
@@ -547,22 +564,67 @@ def favor_to_enum(favor):
547
564
ours = ours .peel (Commit )
548
565
theirs = theirs .peel (Commit )
549
566
550
- err = C .git_merge_init_options (opts , C .GIT_MERGE_OPTIONS_VERSION )
567
+ opts = self ._merge_options (favor )
568
+
569
+ ffi .buffer (ours_ptr )[:] = ours ._pointer [:]
570
+ ffi .buffer (theirs_ptr )[:] = theirs ._pointer [:]
571
+
572
+ err = C .git_merge_commits (cindex , self ._repo , ours_ptr [0 ], theirs_ptr [0 ], opts )
551
573
check_error (err )
552
574
553
- favor_val = favor_to_enum (favor )
554
- if favor_val is None :
555
- raise ValueError ("unkown favor value %s" % favor )
575
+ return Index .from_c (self , cindex )
556
576
557
- opts .file_favor = favor_val
577
+ def merge_trees (self , ancestor , ours , theirs , favor = 'normal' ):
578
+ """Merge two trees
558
579
580
+ Arguments:
581
+
582
+ ancestor
583
+ The tree which is the common ancestor between 'ours' and 'theirs'
584
+ ours
585
+ The commit to take as "ours" or base.
586
+ theirs
587
+ The commit which will be merged into "ours"
588
+ favor
589
+ How to deal with file-level conflicts. Can be one of
590
+
591
+ * normal (default). Conflicts will be preserved.
592
+ * ours. The "ours" side of the conflict region is used.
593
+ * theirs. The "theirs" side of the conflict region is used.
594
+ * union. Unique lines from each side will be used.
595
+
596
+ for all but NORMAL, the index will not record a conflict.
597
+
598
+ Returns an Index that reflects the result of the merge.
599
+ """
600
+
601
+ ancestor_ptr = ffi .new ('git_tree **' )
602
+ ours_ptr = ffi .new ('git_tree **' )
603
+ theirs_ptr = ffi .new ('git_tree **' )
604
+ cindex = ffi .new ('git_index **' )
605
+
606
+ if is_string (ancestor ) or isinstance (ancestor , Oid ):
607
+ ancestor = self [ancestor ]
608
+ if is_string (ours ) or isinstance (ours , Oid ):
609
+ ours = self [ours ]
610
+ if is_string (theirs ) or isinstance (theirs , Oid ):
611
+ theirs = self [theirs ]
612
+
613
+ ancestor = ancestor .peel (Tree )
614
+ ours = ours .peel (Tree )
615
+ theirs = theirs .peel (Tree )
616
+
617
+ opts = self ._merge_options (favor )
618
+
619
+ ffi .buffer (ancestor_ptr )[:] = ancestor ._pointer [:]
559
620
ffi .buffer (ours_ptr )[:] = ours ._pointer [:]
560
621
ffi .buffer (theirs_ptr )[:] = theirs ._pointer [:]
561
622
562
- err = C .git_merge_commits (cindex , self ._repo , ours_ptr [0 ], theirs_ptr [0 ], opts )
623
+ err = C .git_merge_trees (cindex , self ._repo , ancestor_ptr [ 0 ] , ours_ptr [0 ], theirs_ptr [0 ], opts )
563
624
check_error (err )
564
625
565
626
return Index .from_c (self , cindex )
627
+
566
628
#
567
629
# Utility for writing a tree into an archive
568
630
#
0 commit comments