Skip to content

Commit 382aff9

Browse files
committed
feat: add merge::tree::TreeFavor similar to *::FileFavor.
That way it's possible to control how tree-conflicts should be auto-resolved.
1 parent 1ce37d8 commit 382aff9

File tree

1 file changed

+46
-2
lines changed

1 file changed

+46
-2
lines changed

gix/src/merge.rs

+46-2
Original file line numberDiff line numberDiff line change
@@ -160,13 +160,15 @@ pub mod tree {
160160
pub struct Options {
161161
inner: gix_merge::tree::Options,
162162
file_favor: Option<FileFavor>,
163+
tree_favor: Option<TreeFavor>,
163164
}
164165

165166
impl From<gix_merge::tree::Options> for Options {
166167
fn from(opts: gix_merge::tree::Options) -> Self {
167168
Options {
168169
inner: opts,
169170
file_favor: None,
171+
tree_favor: None,
170172
}
171173
}
172174
}
@@ -190,6 +192,7 @@ pub mod tree {
190192
opts.blob_merge.resolve_binary_with = Some(resolve_binary);
191193
opts.blob_merge.text.conflict = resolve_text;
192194
}
195+
opts.tree_conflicts = value.tree_favor.map(Into::into);
193196
opts
194197
}
195198
}
@@ -202,7 +205,7 @@ pub mod tree {
202205
/// * binary files
203206
/// * symlinks (a form of file after all)
204207
///
205-
/// Note that that union merges aren't available as they aren't available for binaries or symlinks.
208+
/// Note that *union* merges aren't available as they aren't available for binaries or symlinks.
206209
#[derive(Debug, Copy, Clone)]
207210
pub enum FileFavor {
208211
/// Choose *our* side in case of a conflict.
@@ -215,6 +218,35 @@ pub mod tree {
215218
Theirs,
216219
}
217220

221+
/// Control how irreconcilable changes to trees should be resolved.
222+
///
223+
/// Examples for such issues are:
224+
///
225+
/// * *we*: delete, *they*: modify
226+
/// * *we*: rename, *they*: rename to something else
227+
/// * *we*: delete, *they*: rename
228+
///
229+
/// Use this to control which entries are visible to in the resulting tree.
230+
/// Also note that this does not apply to the many tree-related changes are reconcilable.
231+
#[derive(Debug, Copy, Clone)]
232+
pub enum TreeFavor {
233+
/// Choose *our* side in case of a conflict.
234+
/// Note that content-merges are *still* performed according to the [FileFavor].
235+
Ours,
236+
/// Choose the state of the shared common ancestor, dropping both *ours* and *their* changes.
237+
/// Content merges are not performed here.
238+
Ancestor,
239+
}
240+
241+
impl From<TreeFavor> for gix_merge::tree::ResolveWith {
242+
fn from(value: TreeFavor) -> Self {
243+
match value {
244+
TreeFavor::Ours => gix_merge::tree::ResolveWith::Ours,
245+
TreeFavor::Ancestor => gix_merge::tree::ResolveWith::Ancestor,
246+
}
247+
}
248+
}
249+
218250
/// Builder
219251
impl Options {
220252
/// If *not* `None`, rename tracking will be performed when determining the changes of each side of the merge.
@@ -233,10 +265,22 @@ pub mod tree {
233265

234266
/// When `None`, the default, both sides will be treated equally, and in case of conflict an unbiased representation
235267
/// is chosen both for content and for trees, causing a conflict.
236-
/// When `Some(favor)` one can choose a side to prefer in order to automatically resolve a conflict meaningfully.
268+
///
269+
/// With `Some(favor)` one can choose a side to prefer in order to forcefully resolve an otherwise irreconcilable conflict,
270+
/// loosing information in the process.
237271
pub fn with_file_favor(mut self, file_favor: Option<FileFavor>) -> Self {
238272
self.file_favor = file_favor;
239273
self
240274
}
275+
276+
/// When `None`, the default, both sides will be treated equally, trying to keep both conflicting changes in the tree, possibly
277+
/// by renaming one side to move it out of the way.
278+
///
279+
/// With `Some(favor)` one can choose a side to prefer in order to forcefully resolve an otherwise irreconcilable conflict,
280+
/// loosing information in the process.
281+
pub fn with_tree_favor(mut self, tree_favor: Option<TreeFavor>) -> Self {
282+
self.tree_favor = tree_favor;
283+
self
284+
}
241285
}
242286
}

0 commit comments

Comments
 (0)