gix_merge/blob/builtin_driver/text/
mod.rs

1use std::num::NonZeroU8;
2
3use bstr::BStr;
4
5/// The way the built-in [text driver](crate::blob::BuiltinDriver::Text) will express
6/// merge conflicts in the resulting file.
7#[derive(Default, Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
8pub enum ConflictStyle {
9    /// Only show the zealously minified conflicting lines of the local changes and the incoming (other) changes,
10    /// hiding the base version entirely.
11    ///
12    /// ```text
13    /// line1-changed-by-both
14    /// <<<<<<< local
15    /// line2-to-be-changed-in-incoming
16    /// =======
17    /// line2-changed
18    /// >>>>>>> incoming
19    /// ```
20    #[default]
21    Merge,
22    /// Show non-minimized hunks of local changes, the base, and the incoming (other) changes.
23    ///
24    /// This mode does not hide any information.
25    ///
26    /// ```text
27    /// <<<<<<< local
28    /// line1-changed-by-both
29    /// line2-to-be-changed-in-incoming
30    /// ||||||| 9a8d80c
31    /// line1-to-be-changed-by-both
32    /// line2-to-be-changed-in-incoming
33    /// =======
34    /// line1-changed-by-both
35    /// line2-changed
36    /// >>>>>>> incoming
37    /// ```
38    Diff3,
39    /// Like [`Diff3](Self::Diff3), but will show *minimized* hunks of local change and the incoming (other) changes,
40    /// as well as non-minimized hunks of the base.
41    ///
42    /// ```text
43    /// line1-changed-by-both
44    /// <<<<<<< local
45    /// line2-to-be-changed-in-incoming
46    /// ||||||| 9a8d80c
47    /// line1-to-be-changed-by-both
48    /// line2-to-be-changed-in-incoming
49    /// =======
50    /// line2-changed
51    /// >>>>>>> incoming
52    /// ```
53    ZealousDiff3,
54}
55
56/// The set of labels to annotate conflict markers with.
57///
58/// That way it becomes clearer where the content of conflicts are originating from.
59#[derive(Default, Copy, Clone, Debug, Eq, PartialEq)]
60pub struct Labels<'a> {
61    /// The label for the common *ancestor*.
62    pub ancestor: Option<&'a BStr>,
63    /// The label for the *current* (or *our*) side.
64    pub current: Option<&'a BStr>,
65    /// The label for the *other* (or *their*) side.
66    pub other: Option<&'a BStr>,
67}
68
69/// Options for the builtin [text driver](crate::blob::BuiltinDriver::Text).
70#[derive(Copy, Clone, Debug, Eq, PartialEq)]
71pub struct Options {
72    /// Determine of the diff will be performed.
73    /// Defaults to [`imara_diff::Algorithm::Myers`].
74    pub diff_algorithm: imara_diff::Algorithm,
75    /// Decide what to do to automatically resolve conflicts, or to keep them.
76    pub conflict: Conflict,
77}
78
79impl Default for Options {
80    fn default() -> Self {
81        Options {
82            conflict: Default::default(),
83            diff_algorithm: imara_diff::Algorithm::Myers,
84        }
85    }
86}
87
88/// What to do to resolve a conflict.
89#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
90pub enum Conflict {
91    /// Keep the conflict by marking it in the source file.
92    Keep {
93        /// How to visualize conflicts in merged files.
94        style: ConflictStyle,
95        /// The amount of markers to draw, defaults to 7, i.e. `<<<<<<<`
96        marker_size: NonZeroU8,
97    },
98    /// Chose our side to resolve a conflict.
99    ResolveWithOurs,
100    /// Chose their side to resolve a conflict.
101    ResolveWithTheirs,
102    /// Place our and their lines one after another, in any order
103    ResolveWithUnion,
104}
105
106impl Conflict {
107    /// The amount of conflict marker characters to print by default.
108    // TODO: use NonZeroU8::new().unwrap() here once the MSRV supports it.
109    pub const DEFAULT_MARKER_SIZE: u8 = 7;
110
111    /// The amount of conflict markers to print if this instance contains them, or `None` otherwise
112    pub fn marker_size(&self) -> Option<u8> {
113        match self {
114            Conflict::Keep { marker_size, .. } => Some(marker_size.get()),
115            Conflict::ResolveWithOurs | Conflict::ResolveWithTheirs | Conflict::ResolveWithUnion => None,
116        }
117    }
118}
119
120impl Default for Conflict {
121    fn default() -> Self {
122        Conflict::Keep {
123            style: Default::default(),
124            marker_size: Conflict::DEFAULT_MARKER_SIZE.try_into().unwrap(),
125        }
126    }
127}
128
129pub(super) mod function;
130mod utils;