gix_merge/blob/platform/mod.rs
1use bstr::{BStr, BString};
2use gix_filter::attributes;
3
4use crate::blob::{pipeline, BuiltinDriver, Pipeline, Platform};
5
6/// A stored value representing a resource that participates in a merge.
7#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
8pub(super) struct Resource {
9 /// The `id` of the value, or `null` if it's only living in a worktree.
10 id: gix_hash::ObjectId,
11 /// The repository-relative path where the resource lives in the tree.
12 rela_path: BString,
13 /// The outcome of converting a resource into a mergable format using [Pipeline::convert_to_mergeable()].
14 data: Option<pipeline::Data>,
15 /// The kind of the resource we are looking at. Only possible values are `Blob` and `BlobExecutable`.
16 mode: gix_object::tree::EntryKind,
17 /// A possibly empty buffer, depending on `conversion.data` which may indicate the data is considered binary
18 /// or the resource doesn't exist.
19 buffer: Vec<u8>,
20}
21
22/// A blob or executable ready to be merged in one way or another.
23#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
24pub struct ResourceRef<'a> {
25 /// The data itself, suitable for merging, and if the object or worktree item is present at all.
26 pub data: resource::Data<'a>,
27 /// The location of the resource, relative to the working tree.
28 pub rela_path: &'a BStr,
29 /// The id of the content as it would be stored in `git`, or `null` if the content doesn't exist anymore at
30 /// `rela_path` or if it was never computed. This can happen with content read from the worktree, which
31 /// after its 'to-git' conversion never had its hash computed.
32 pub id: &'a gix_hash::oid,
33}
34
35/// Options for use in [`Platform::new()`].
36#[derive(Default, Clone, PartialEq, Eq, Debug, Hash, Ord, PartialOrd)]
37pub struct Options {
38 /// Define which driver to use by name if the `merge` attribute for a resource is unspecified.
39 ///
40 /// This is the value of the `merge.default` git configuration.
41 pub default_driver: Option<BString>,
42}
43
44/// The selection of the driver to use by a resource obtained with [`Platform::prepare_merge()`].
45///
46/// If available, an index into the `drivers` field to access more diff-related information of the driver for items
47/// at the given path, as previously determined by git-attributes.
48///
49/// * `merge` is set
50/// - Use the [`BuiltinDriver::Text`]
51/// * `-merge` is unset
52/// - Use the [`BuiltinDriver::Binary`]
53/// * `!merge` is unspecified
54/// - Use [`Options::default_driver`] or [`BuiltinDriver::Text`].
55/// * `merge=name`
56/// - Search for a user-configured or built-in driver called `name`.
57/// - If not found, silently default to [`BuiltinDriver::Text`]
58///
59/// Note that drivers are queried even if there is no object available.
60#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
61pub enum DriverChoice {
62 /// Use the given built-in driver to perform the merge.
63 BuiltIn(BuiltinDriver),
64 /// Use the user-provided driver program using the index into [the platform drivers array](Platform::drivers()).
65 Index(usize),
66}
67
68impl Default for DriverChoice {
69 fn default() -> Self {
70 DriverChoice::BuiltIn(Default::default())
71 }
72}
73
74/// Lifecycle
75impl Platform {
76 /// Create a new instance with a way to `filter` data from the object database and turn it into something that is merge-able.
77 /// `filter_mode` decides how to do that specifically.
78 /// Use `attr_stack` to access attributes pertaining worktree filters and merge settings.
79 /// `drivers` are the list of available merge drivers that individual paths can refer to by means of git attributes.
80 /// `options` further configure the operation.
81 pub fn new(
82 filter: Pipeline,
83 filter_mode: pipeline::Mode,
84 attr_stack: gix_worktree::Stack,
85 mut drivers: Vec<super::Driver>,
86 options: Options,
87 ) -> Self {
88 drivers.sort_by(|a, b| a.name.cmp(&b.name));
89 Platform {
90 drivers,
91 current: None,
92 ancestor: None,
93 other: None,
94 filter,
95 filter_mode,
96 attr_stack,
97 attrs: {
98 let mut out = attributes::search::Outcome::default();
99 out.initialize_with_selection(&Default::default(), ["merge", "conflict-marker-size"]);
100 out
101 },
102 options,
103 }
104 }
105}
106
107/// Access
108impl Platform {
109 /// Return all drivers that this instance was initialized with.
110 ///
111 /// They are sorted by [`name`](super::Driver::name) to support binary searches.
112 pub fn drivers(&self) -> &[super::Driver] {
113 &self.drivers
114 }
115}
116
117///
118pub mod set_resource;
119
120///
121pub mod resource;
122
123///
124pub mod merge;
125pub use merge::inner::{builtin_merge, prepare_external_driver};
126
127///
128pub mod prepare_merge;