gix_merge/blob/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 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
// TODO: remove this - only needed while &mut Vec<u8> isn't used.
#![allow(clippy::ptr_arg)]
use crate::blob::platform::{DriverChoice, ResourceRef};
use bstr::BString;
use std::path::PathBuf;
///
pub mod builtin_driver;
///
pub mod pipeline;
///
pub mod platform;
/// Define if a merge is conflicted or not.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum Resolution {
/// Everything could be resolved during the merge, and there was no conflict.
Complete,
/// Conflicts were resolved automatically, even thought the result is complete
/// and free of conflict markers.
/// This can only be the case for text-file content merges.
CompleteWithAutoResolvedConflict,
/// A conflict is still present in the form of conflict markers.
Conflict,
}
/// A way to classify the side of a resource for merging.
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub enum ResourceKind {
/// Our side of the state.
CurrentOrOurs,
/// Their side of the state.
OtherOrTheirs,
/// The state of the common base of both ours and theirs.
CommonAncestorOrBase,
}
/// Define a built-in way of performing a three-way merge, including auto-resolution support.
///
/// Some values are related to diffing, some are related to conversions.
#[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum BuiltinDriver {
/// Perform a merge between text-sources such that conflicts are marked according to
/// `merge.conflictStyle` in the Git configuration.
///
/// If any of the inputs, *base*, *ours* or *theirs* looks like non-text/binary,
/// the [`Binary`](Self::Binary) driver will be used instead.
///
/// Also see [`builtin_driver::text::ConflictStyle`].
#[default]
Text,
/// Merge 'unmergable' content by choosing *ours* or *theirs*, without performing
/// an actual merge.
///
/// Note that if the merge operation is for virtual ancestor (a merge for merge-bases),
/// then *ours* will always be chosen.
Binary,
/// Merge text-sources and resolve conflicts by adding conflicting lines one after another,
/// in random order, without adding conflict markers either.
///
/// This can be useful for files that change a lot, but will remain usable merely by adding
/// all changed lines.
Union,
}
/// Define a driver program that performs a three-way merge.
///
/// Some values are related to diffing, some are related to conversions.
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct Driver {
/// The name of the driver, as referred to by `[merge "name"]` in the git configuration.
pub name: BString,
/// The human-readable version of `name`, only to be used for displaying driver-information to the user.
pub display_name: BString,
/// The command to execute to perform the merge entirely like `<command> %O %A %B %L %P %S %X %Y`.
///
/// * **%O**
/// - the common ancestor version, or *base*.
/// * **%A**
/// - the current version, or *ours*.
/// * **%B**
/// - the other version, or *theirs*.
/// * **%L**
/// - The conflict-marker size as positive number.
/// * **%P**
/// - The path in which the merged result would be stored, as workspace-relative path, of the current/ours side.
/// * **%S**
/// - The conflict-label for the common ancestor or *base*.
/// * **%X**
/// - The conflict-label for the current version or *ours*.
/// * **%Y**
/// - The conflict-label for the other version or *theirs*.
///
/// Note that conflict-labels are behind the conflict markers, to annotate them.
///
/// A typical invocation with all arguments substituted could then look like this:
///
/// ```sh
/// <driver-program> .merge_file_nR2Qs1 .merge_file_WYXCJe .merge_file_UWbzrm 7 file e2a2970 HEAD feature
/// ```
///
/// The driver is expected to leave its version in the file at `%A`, by overwriting it.
pub command: BString,
/// If `true`, this is the `name` of the driver to use when a virtual-merge-base is created, as a merge of all
/// available merge-bases if there are more than one.
///
/// This value can also be special built-in drivers named `text`, `binary` or `union`. Note that user-defined
/// drivers with the same name will be preferred over built-in ones, but only for files whose git attributes
/// specified the driver by *name*.
pub recursive: Option<BString>,
}
/// A conversion pipeline to take an object or path from what's stored in Git to what can be merged, while
/// following the guidance of git-attributes at the respective path to learn how the merge should be performed.
///
/// Depending on the source, different conversions are performed:
///
/// * `worktree on disk` -> `object for storage in git`
/// * `object` -> `possibly renormalized object`
/// - Renormalization means that the `object` is converted to what would be checked out into the work-tree,
/// just to turn it back into an object.
#[derive(Clone)]
pub struct Pipeline {
/// A way to read data directly from the worktree.
pub roots: pipeline::WorktreeRoots,
/// A pipeline to convert objects from the worktree to Git, and also from Git to the worktree, and back to Git.
pub filter: gix_filter::Pipeline,
/// Options affecting the way we read files.
pub options: pipeline::Options,
/// A buffer to produce disk-accessible paths from worktree roots.
path: PathBuf,
}
/// A utility for gathering and processing all state necessary to perform a three-way merge.
///
/// It can re-use buffers if all three parts of participating in the merge are
/// set repeatedly.
#[derive(Clone)]
pub struct Platform {
/// The current version (ours).
current: Option<platform::Resource>,
/// The ancestor version (base).
ancestor: Option<platform::Resource>,
/// The other version (theirs).
other: Option<platform::Resource>,
/// A way to convert objects into a diff-able format.
pub filter: Pipeline,
/// A way to access `.gitattributes`
pub attr_stack: gix_worktree::Stack,
/// Further configuration that affects the merge.
pub options: platform::Options,
/// All available merge drivers.
///
/// They are referenced in git-attributes by name, and we hand out indices into this array.
drivers: Vec<Driver>,
/// Pre-configured attributes to obtain additional merge-related information.
attrs: gix_filter::attributes::search::Outcome,
/// The way we convert resources into mergeable states.
pub filter_mode: pipeline::Mode,
}
/// The product of a [`prepare_merge()`](Platform::prepare_merge()) call to finally
/// perform the merge and retrieve the merge results.
#[derive(Copy, Clone)]
pub struct PlatformRef<'parent> {
/// The platform that hosts the resources, used to access drivers.
pub(super) parent: &'parent Platform,
/// The current or our side of the merge operation.
pub current: ResourceRef<'parent>,
/// The ancestor or base of the merge operation.
pub ancestor: ResourceRef<'parent>,
/// The other or their side of the merge operation.
pub other: ResourceRef<'parent>,
/// Which driver to use according to the resource's configuration,
/// using the path of `current` to read git-attributes.
pub driver: DriverChoice,
/// Possibly processed options for use when performing the actual merge.
///
/// They may be inspected before the merge, or altered at will.
pub options: platform::merge::Options,
}