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}