@@ -4,6 +4,7 @@ pub use gix_merge::blob;
4
4
5
5
///
6
6
pub mod tree {
7
+ use gix_merge:: blob:: builtin_driver;
7
8
pub use gix_merge:: tree:: { Conflict , ContentMerge , Resolution , ResolutionFailure , UnresolvedConflict } ;
8
9
9
10
/// The outcome produced by [`Repository::merge_trees()`](crate::Repository::merge_trees()).
@@ -31,4 +32,89 @@ pub mod tree {
31
32
self . conflicts . iter ( ) . any ( |c| c. is_unresolved ( how) )
32
33
}
33
34
}
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
+ }
34
120
}
0 commit comments