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