gix_merge/blob/
mod.rs

1// TODO: remove this - only needed while &mut Vec<u8> isn't used.
2#![allow(clippy::ptr_arg)]
3
4use std::path::PathBuf;
5
6use bstr::BString;
7
8use crate::blob::platform::{DriverChoice, ResourceRef};
9
10///
11pub mod builtin_driver;
12///
13pub mod pipeline;
14///
15pub mod platform;
16
17/// Define if a merge is conflicted or not.
18#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
19pub enum Resolution {
20    /// Everything could be resolved during the merge, and there was no conflict.
21    Complete,
22    /// Conflicts were resolved automatically, even thought the result is complete
23    /// and free of conflict markers.
24    /// This can only be the case for text-file content merges.
25    CompleteWithAutoResolvedConflict,
26    /// A conflict is still present in the form of conflict markers.
27    Conflict,
28}
29
30/// A way to classify the side of a resource for merging.
31#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
32pub enum ResourceKind {
33    /// Our side of the state.
34    CurrentOrOurs,
35    /// Their side of the state.
36    OtherOrTheirs,
37    /// The state of the common base of both ours and theirs.
38    CommonAncestorOrBase,
39}
40
41/// Define a built-in way of performing a three-way merge, including auto-resolution support.
42///
43/// Some values are related to diffing, some are related to conversions.
44#[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
45pub enum BuiltinDriver {
46    /// Perform a merge between text-sources such that conflicts are marked according to
47    /// `merge.conflictStyle` in the Git configuration.
48    ///
49    /// If any of the inputs, *base*, *ours* or *theirs* looks like non-text/binary,
50    /// the [`Binary`](Self::Binary) driver will be used instead.
51    ///
52    /// Also see [`builtin_driver::text::ConflictStyle`].
53    #[default]
54    Text,
55    /// Merge 'unmergable' content by choosing *ours* or *theirs*, without performing
56    /// an actual merge.
57    ///
58    /// Note that if the merge operation is for virtual ancestor (a merge for merge-bases),
59    /// then *ours* will always be chosen.
60    Binary,
61    /// Merge text-sources and resolve conflicts by adding conflicting lines one after another,
62    /// in random order, without adding conflict markers either.
63    ///
64    /// This can be useful for files that change a lot, but will remain usable merely by adding
65    /// all changed lines.
66    Union,
67}
68
69/// Define a driver program that performs a three-way merge.
70///
71/// Some values are related to diffing, some are related to conversions.
72#[derive(Default, Debug, Clone, PartialEq, Eq)]
73pub struct Driver {
74    /// The name of the driver, as referred to by `[merge "name"]` in the git configuration.
75    pub name: BString,
76    /// The human-readable version of `name`, only to be used for displaying driver-information to the user.
77    pub display_name: BString,
78    /// The command to execute to perform the merge entirely like `<command> %O %A %B %L %P %S %X %Y`.
79    ///
80    /// * **%O**
81    ///     - the common ancestor version, or *base*.
82    /// * **%A**
83    ///     - the current version, or *ours*.
84    /// * **%B**
85    ///     - the other version, or *theirs*.
86    /// * **%L**
87    ///     - The conflict-marker size as positive number.
88    /// * **%P**
89    ///     - The path in which the merged result would be stored, as workspace-relative path, of the current/ours side.
90    /// * **%S**
91    ///     - The conflict-label for the common ancestor or *base*.
92    /// * **%X**
93    ///     - The conflict-label for the current version or *ours*.
94    /// * **%Y**
95    ///     - The conflict-label for the other version or *theirs*.
96    ///
97    /// Note that conflict-labels are behind the conflict markers, to annotate them.
98    ///
99    /// A typical invocation with all arguments substituted could then look like this:
100    ///
101    /// ```sh
102    /// <driver-program> .merge_file_nR2Qs1 .merge_file_WYXCJe .merge_file_UWbzrm 7 file e2a2970 HEAD feature
103    /// ```
104    ///
105    /// The driver is expected to leave its version in the file at `%A`, by overwriting it.
106    pub command: BString,
107    /// If `true`, this is the `name` of the driver to use when a virtual-merge-base is created, as a merge of all
108    /// available merge-bases if there are more than one.
109    ///
110    /// This value can also be special built-in drivers named `text`, `binary` or `union`. Note that user-defined
111    /// drivers with the same name will be preferred over built-in ones, but only for files whose git attributes
112    /// specified the driver by *name*.
113    pub recursive: Option<BString>,
114}
115
116/// A conversion pipeline to take an object or path from what's stored in Git to what can be merged, while
117/// following the guidance of git-attributes at the respective path to learn how the merge should be performed.
118///
119/// Depending on the source, different conversions are performed:
120///
121/// * `worktree on disk` -> `object for storage in git`
122/// * `object` -> `possibly renormalized object`
123///     - Renormalization means that the `object` is converted to what would be checked out into the work-tree,
124///       just to turn it back into an object.
125#[derive(Clone)]
126pub struct Pipeline {
127    /// A way to read data directly from the worktree.
128    pub roots: pipeline::WorktreeRoots,
129    /// A pipeline to convert objects from the worktree to Git, and also from Git to the worktree, and back to Git.
130    pub filter: gix_filter::Pipeline,
131    /// Options affecting the way we read files.
132    pub options: pipeline::Options,
133    /// A buffer to produce disk-accessible paths from worktree roots.
134    path: PathBuf,
135}
136
137/// A utility for gathering and processing all state necessary to perform a three-way merge.
138///
139/// It can re-use buffers if all three parts of participating in the merge are
140/// set repeatedly.
141#[derive(Clone)]
142pub struct Platform {
143    /// The current version (ours).
144    current: Option<platform::Resource>,
145    /// The ancestor version (base).
146    ancestor: Option<platform::Resource>,
147    /// The other version (theirs).
148    other: Option<platform::Resource>,
149
150    /// A way to convert objects into a diff-able format.
151    pub filter: Pipeline,
152    /// A way to access `.gitattributes`
153    pub attr_stack: gix_worktree::Stack,
154    /// Further configuration that affects the merge.
155    pub options: platform::Options,
156    /// All available merge drivers.
157    ///
158    /// They are referenced in git-attributes by name, and we hand out indices into this array.
159    drivers: Vec<Driver>,
160    /// Pre-configured attributes to obtain additional merge-related information.
161    attrs: gix_filter::attributes::search::Outcome,
162    /// The way we convert resources into mergeable states.
163    pub filter_mode: pipeline::Mode,
164}
165
166/// The product of a [`prepare_merge()`](Platform::prepare_merge()) call to finally
167/// perform the merge and retrieve the merge results.
168#[derive(Copy, Clone)]
169pub struct PlatformRef<'parent> {
170    /// The platform that hosts the resources, used to access drivers.
171    pub(super) parent: &'parent Platform,
172    /// The current or our side of the merge operation.
173    pub current: ResourceRef<'parent>,
174    /// The ancestor or base of the merge operation.
175    pub ancestor: ResourceRef<'parent>,
176    /// The other or their side of the merge operation.
177    pub other: ResourceRef<'parent>,
178    /// Which driver to use according to the resource's configuration,
179    /// using the path of `current` to read git-attributes.
180    pub driver: DriverChoice,
181    /// Possibly processed options for use when performing the actual merge.
182    ///
183    /// They may be inspected before the merge, or altered at will.
184    pub options: platform::merge::Options,
185}