@@ -4,6 +4,7 @@ pub use gix_merge::blob;
44
55///
66pub mod tree {
7+ use gix_merge:: blob:: builtin_driver;
78 pub use gix_merge:: tree:: { Conflict , ContentMerge , Resolution , ResolutionFailure , UnresolvedConflict } ;
89
910 /// The outcome produced by [`Repository::merge_trees()`](crate::Repository::merge_trees()).
@@ -31,4 +32,89 @@ pub mod tree {
3132 self . conflicts . iter ( ) . any ( |c| c. is_unresolved ( how) )
3233 }
3334 }
35+
36+ /// A way to configure [`Repository::merge_trees()`](crate::Repository::merge_trees()).
37+ #[ derive( Default , Debug , Clone ) ]
38+ pub struct Options {
39+ inner : gix_merge:: tree:: Options ,
40+ file_favor : Option < FileFavor > ,
41+ }
42+
43+ impl From < gix_merge:: tree:: Options > for Options {
44+ fn from ( opts : gix_merge:: tree:: Options ) -> Self {
45+ Options {
46+ inner : opts,
47+ file_favor : None ,
48+ }
49+ }
50+ }
51+
52+ impl From < Options > for gix_merge:: tree:: Options {
53+ fn from ( value : Options ) -> Self {
54+ let mut opts = value. inner ;
55+ if let Some ( file_favor) = value. file_favor {
56+ let ( resolve_binary, resolve_text) = match file_favor {
57+ FileFavor :: Ours => (
58+ builtin_driver:: binary:: ResolveWith :: Ours ,
59+ builtin_driver:: text:: Conflict :: ResolveWithOurs ,
60+ ) ,
61+ FileFavor :: Theirs => (
62+ builtin_driver:: binary:: ResolveWith :: Theirs ,
63+ builtin_driver:: text:: Conflict :: ResolveWithTheirs ,
64+ ) ,
65+ } ;
66+
67+ opts. symlink_conflicts = Some ( resolve_binary) ;
68+ opts. blob_merge . resolve_binary_with = Some ( resolve_binary) ;
69+ opts. blob_merge . text . conflict = resolve_text;
70+ }
71+ opts
72+ }
73+ }
74+
75+ /// Identify how files should be resolved in case of conflicts.
76+ ///
77+ /// This works for…
78+ ///
79+ /// * content merges
80+ /// * binary files
81+ /// * symlinks (a form of file after all)
82+ ///
83+ /// Note that that union merges aren't available as they aren't available for binaries or symlinks.
84+ #[ derive( Debug , Copy , Clone ) ]
85+ pub enum FileFavor {
86+ /// Choose *our* side in case of a conflict.
87+ /// Note that this choice is precise, so *ours* hunk will only be chosen if they conflict with *theirs*,
88+ /// so *their* hunks may still show up in the merged result.
89+ Ours ,
90+ /// Choose *their* side in case of a conflict.
91+ /// Note that this choice is precise, so *ours* hunk will only be chosen if they conflict with *theirs*,
92+ /// so *their* hunks may still show up in the merged result.
93+ Theirs ,
94+ }
95+
96+ /// Builder
97+ impl Options {
98+ /// If *not* `None`, rename tracking will be performed when determining the changes of each side of the merge.
99+ pub fn with_rewrites ( mut self , rewrites : Option < gix_diff:: Rewrites > ) -> Self {
100+ self . inner . rewrites = rewrites;
101+ self
102+ }
103+
104+ /// If `Some(what-is-unresolved)`, the first unresolved conflict will cause the entire merge to stop.
105+ /// This is useful to see if there is any conflict, without performing the whole operation, something
106+ /// that can be very relevant during merges that would cause a lot of blob-diffs.
107+ pub fn with_fail_on_conflict ( mut self , fail_on_conflict : Option < UnresolvedConflict > ) -> Self {
108+ self . inner . fail_on_conflict = fail_on_conflict;
109+ self
110+ }
111+
112+ /// When `None`, the default, both sides will be treated equally, and in case of conflict an unbiased representation
113+ /// is chosen both for content and for trees, causing a conflict.
114+ /// When `Some(favor)` one can choose a side to prefer in order to automatically resolve a conflict meaningfully.
115+ pub fn with_file_favor ( mut self , file_favor : Option < FileFavor > ) -> Self {
116+ self . file_favor = file_favor;
117+ self
118+ }
119+ }
34120}
0 commit comments