|
1 | 1 | use crate::config::cache::util::ApplyLeniencyDefault;
|
2 | 2 | use crate::config::tree;
|
3 | 3 | use crate::prelude::ObjectIdExt;
|
4 |
| -use crate::repository::{blob_merge_options, merge_commits, merge_resource_cache, merge_trees, tree_merge_options}; |
| 4 | +use crate::repository::{ |
| 5 | + blob_merge_options, merge_commits, merge_resource_cache, merge_trees, tree_merge_options, virtual_merge_base, |
| 6 | +}; |
5 | 7 | use crate::Repository;
|
6 | 8 | use gix_merge::blob::builtin_driver::text;
|
7 | 9 | use gix_object::Write;
|
@@ -223,4 +225,56 @@ impl Repository {
|
223 | 225 | virtual_merge_bases,
|
224 | 226 | })
|
225 | 227 | }
|
| 228 | + |
| 229 | + /// Create a single virtual merge-base by merging all `merge_bases` into one. |
| 230 | + /// If the list is empty, an error will be returned as the histories are then unrelated. |
| 231 | + /// If there is only one commit in the list, it is returned directly with this case clearly marked in the outcome. |
| 232 | + /// |
| 233 | + /// Note that most of `options` are overwritten to match the requirements of a merge-base merge, but they can be useful |
| 234 | + /// to control the diff algorithm or rewrite tracking, for example. |
| 235 | + // TODO: test |
| 236 | + pub fn virtual_merge_base( |
| 237 | + &self, |
| 238 | + merge_bases: impl IntoIterator<Item = impl Into<gix_hash::ObjectId>>, |
| 239 | + options: crate::merge::tree::Options, |
| 240 | + ) -> Result<crate::merge::virtual_merge_base::Outcome<'_>, virtual_merge_base::Error> { |
| 241 | + let mut merge_bases: Vec<_> = merge_bases.into_iter().map(Into::into).collect(); |
| 242 | + let first = merge_bases.pop().ok_or(virtual_merge_base::Error::MissingCommit)?; |
| 243 | + let Some(second) = merge_bases.pop() else { |
| 244 | + let tree_id = self.find_commit(first)?.tree_id()?; |
| 245 | + let commit_id = first.attach(self); |
| 246 | + return Ok(crate::merge::virtual_merge_base::Outcome { |
| 247 | + virtual_merge_bases: Vec::new(), |
| 248 | + commit_id, |
| 249 | + tree_id, |
| 250 | + }); |
| 251 | + }; |
| 252 | + |
| 253 | + let mut diff_cache = self.diff_resource_cache_for_tree_diff()?; |
| 254 | + let mut blob_merge = self.merge_resource_cache(Default::default())?; |
| 255 | + let commit_graph = self.commit_graph_if_enabled()?; |
| 256 | + let mut graph = self.revision_graph(commit_graph.as_ref()); |
| 257 | + |
| 258 | + let gix_merge::commit::virtual_merge_base::Outcome { |
| 259 | + virtual_merge_bases, |
| 260 | + commit_id, |
| 261 | + tree_id, |
| 262 | + } = gix_merge::commit::virtual_merge_base( |
| 263 | + first, |
| 264 | + second, |
| 265 | + merge_bases, |
| 266 | + &mut graph, |
| 267 | + &mut diff_cache, |
| 268 | + &mut blob_merge, |
| 269 | + self, |
| 270 | + &mut |id| id.to_owned().attach(self).shorten_or_id().to_string(), |
| 271 | + options.into(), |
| 272 | + )?; |
| 273 | + |
| 274 | + Ok(crate::merge::virtual_merge_base::Outcome { |
| 275 | + virtual_merge_bases: virtual_merge_bases.into_iter().map(|id| id.attach(self)).collect(), |
| 276 | + commit_id: commit_id.attach(self), |
| 277 | + tree_id: tree_id.attach(self), |
| 278 | + }) |
| 279 | + } |
226 | 280 | }
|
0 commit comments