gix_merge/blob/builtin_driver/text/
mod.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use bstr::BStr;
use std::num::NonZeroU8;

/// The way the built-in [text driver](crate::blob::BuiltinDriver::Text) will express
/// merge conflicts in the resulting file.
#[derive(Default, Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum ConflictStyle {
    /// Only show the zealously minified conflicting lines of the local changes and the incoming (other) changes,
    /// hiding the base version entirely.
    ///
    /// ```text
    /// line1-changed-by-both
    /// <<<<<<< local
    /// line2-to-be-changed-in-incoming
    /// =======
    /// line2-changed
    /// >>>>>>> incoming
    /// ```
    #[default]
    Merge,
    /// Show non-minimized hunks of local changes, the base, and the incoming (other) changes.
    ///
    /// This mode does not hide any information.
    ///
    /// ```text
    /// <<<<<<< local
    /// line1-changed-by-both
    /// line2-to-be-changed-in-incoming
    /// ||||||| 9a8d80c
    /// line1-to-be-changed-by-both
    /// line2-to-be-changed-in-incoming
    /// =======
    /// line1-changed-by-both
    /// line2-changed
    /// >>>>>>> incoming
    /// ```
    Diff3,
    /// Like [`Diff3](Self::Diff3), but will show *minimized* hunks of local change and the incoming (other) changes,
    /// as well as non-minimized hunks of the base.
    ///
    /// ```text
    /// line1-changed-by-both
    /// <<<<<<< local
    /// line2-to-be-changed-in-incoming
    /// ||||||| 9a8d80c
    /// line1-to-be-changed-by-both
    /// line2-to-be-changed-in-incoming
    /// =======
    /// line2-changed
    /// >>>>>>> incoming
    /// ```
    ZealousDiff3,
}

/// The set of labels to annotate conflict markers with.
///
/// That way it becomes clearer where the content of conflicts are originating from.
#[derive(Default, Copy, Clone, Debug, Eq, PartialEq)]
pub struct Labels<'a> {
    /// The label for the common *ancestor*.
    pub ancestor: Option<&'a BStr>,
    /// The label for the *current* (or *our*) side.
    pub current: Option<&'a BStr>,
    /// The label for the *other* (or *their*) side.
    pub other: Option<&'a BStr>,
}

/// Options for the builtin [text driver](crate::blob::BuiltinDriver::Text).
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Options {
    /// Determine of the diff will be performed.
    /// Defaults to [`imara_diff::Algorithm::Myers`].
    pub diff_algorithm: imara_diff::Algorithm,
    /// Decide what to do to automatically resolve conflicts, or to keep them.
    pub conflict: Conflict,
}

impl Default for Options {
    fn default() -> Self {
        Options {
            conflict: Default::default(),
            diff_algorithm: imara_diff::Algorithm::Myers,
        }
    }
}

/// What to do to resolve a conflict.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum Conflict {
    /// Keep the conflict by marking it in the source file.
    Keep {
        /// How to visualize conflicts in merged files.
        style: ConflictStyle,
        /// The amount of markers to draw, defaults to 7, i.e. `<<<<<<<`
        marker_size: NonZeroU8,
    },
    /// Chose our side to resolve a conflict.
    ResolveWithOurs,
    /// Chose their side to resolve a conflict.
    ResolveWithTheirs,
    /// Place our and their lines one after another, in any order
    ResolveWithUnion,
}

impl Conflict {
    /// The amount of conflict marker characters to print by default.
    // TODO: use NonZeroU8::new().unwrap() here once the MSRV supports it.
    pub const DEFAULT_MARKER_SIZE: u8 = 7;

    /// The amount of conflict markers to print if this instance contains them, or `None` otherwise
    pub fn marker_size(&self) -> Option<u8> {
        match self {
            Conflict::Keep { marker_size, .. } => Some(marker_size.get()),
            Conflict::ResolveWithOurs | Conflict::ResolveWithTheirs | Conflict::ResolveWithUnion => None,
        }
    }
}

impl Default for Conflict {
    fn default() -> Self {
        Conflict::Keep {
            style: Default::default(),
            marker_size: Conflict::DEFAULT_MARKER_SIZE.try_into().unwrap(),
        }
    }
}

pub(super) mod function;
mod utils;