jj_lib/
merge.rs

1// Copyright 2023 The Jujutsu Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Generic algorithms for working with merged values, plus specializations for
16//! some common types of merged values.
17
18use std::borrow::Borrow;
19use std::collections::HashMap;
20use std::fmt::Debug;
21use std::fmt::Formatter;
22use std::fmt::Write as _;
23use std::future::Future;
24use std::hash::Hash;
25use std::iter::zip;
26use std::slice;
27use std::sync::Arc;
28
29use futures::future::try_join_all;
30use itertools::Itertools as _;
31use smallvec::smallvec_inline;
32use smallvec::SmallVec;
33
34use crate::backend;
35use crate::backend::BackendResult;
36use crate::backend::CopyId;
37use crate::backend::FileId;
38use crate::backend::TreeValue;
39use crate::content_hash::ContentHash;
40use crate::content_hash::DigestUpdate;
41use crate::repo_path::RepoPath;
42use crate::store::Store;
43use crate::tree::Tree;
44
45/// Attempt to resolve trivial conflicts between the inputs. There must be
46/// an odd number of terms.
47pub fn trivial_merge<T>(values: &[T]) -> Option<&T>
48where
49    T: Eq + Hash,
50{
51    assert!(
52        values.len() % 2 == 1,
53        "trivial_merge() requires an odd number of terms"
54    );
55    // Optimize the common cases of 3-way merge and 1-way (non-)merge
56    if let [add] = values {
57        return Some(add);
58    } else if let [add0, remove, add1] = values {
59        return if add0 == add1 {
60            Some(add0)
61        } else if add0 == remove {
62            Some(add1)
63        } else if add1 == remove {
64            Some(add0)
65        } else {
66            None
67        };
68    }
69
70    // Number of occurrences of each value, with positive indexes counted as +1 and
71    // negative as -1, thereby letting positive and negative terms with the same
72    // value (i.e. key in the map) cancel each other.
73    let mut counts: HashMap<&T, i32> = HashMap::new();
74    for (value, n) in zip(values, [1, -1].into_iter().cycle()) {
75        counts.entry(value).and_modify(|e| *e += n).or_insert(n);
76    }
77
78    // Collect non-zero value. Values with a count of 0 means that they have
79    // cancelled out.
80    counts.retain(|_, count| *count != 0);
81    if counts.len() == 1 {
82        // If there is a single value with a count of 1 left, then that is the result.
83        let (value, count) = counts.into_iter().next().unwrap();
84        assert_eq!(count, 1);
85        Some(value)
86    } else if counts.len() == 2 {
87        // All sides made the same change.
88        // This matches what Git and Mercurial do (in the 3-way case at least), but not
89        // what Darcs does. It means that repeated 3-way merging of multiple trees may
90        // give different results depending on the order of merging.
91        // TODO: Consider removing this special case, making the algorithm more strict,
92        // and maybe add a more lenient version that is used when the user explicitly
93        // asks for conflict resolution.
94        let [(value1, count1), (value2, count2)] = counts.into_iter().next_array().unwrap();
95        assert_eq!(count1 + count2, 1);
96        if count1 > 0 {
97            Some(value1)
98        } else {
99            Some(value2)
100        }
101    } else {
102        None
103    }
104}
105
106/// A generic representation of merged values.
107///
108/// There is exactly one more `adds()` than `removes()`. When interpreted as a
109/// series of diffs, the merge's (i+1)-st add is matched with the i-th
110/// remove. The zeroth add is considered a diff from the non-existent state.
111#[derive(PartialEq, Eq, Hash, Clone)]
112pub struct Merge<T> {
113    /// Alternates between positive and negative terms, starting with positive.
114    values: SmallVec<[T; 1]>,
115}
116
117impl<T: Debug> Debug for Merge<T> {
118    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
119        // Format like an enum with two variants to make it less verbose in the common
120        // case of a resolved state.
121        if let Some(value) = self.as_resolved() {
122            f.debug_tuple("Resolved").field(value).finish()
123        } else {
124            f.debug_tuple("Conflicted").field(&self.values).finish()
125        }
126    }
127}
128
129impl<T> Merge<T> {
130    /// Creates a `Merge` from the given values, in which positive and negative
131    /// terms alternate.
132    pub fn from_vec(values: impl Into<SmallVec<[T; 1]>>) -> Self {
133        let values = values.into();
134        assert!(values.len() % 2 != 0, "must have an odd number of terms");
135        Merge { values }
136    }
137
138    /// Creates a new merge object from the given removes and adds.
139    pub fn from_removes_adds(
140        removes: impl IntoIterator<Item = T>,
141        adds: impl IntoIterator<Item = T>,
142    ) -> Self {
143        let removes = removes.into_iter();
144        let mut adds = adds.into_iter();
145        let mut values = SmallVec::with_capacity(removes.size_hint().0 * 2 + 1);
146        values.push(adds.next().expect("must have at least one add"));
147        for diff in removes.zip_longest(adds) {
148            let (remove, add) = diff.both().expect("must have one more adds than removes");
149            values.extend([remove, add]);
150        }
151        Merge { values }
152    }
153
154    /// Creates a `Merge` with a single resolved value.
155    pub const fn resolved(value: T) -> Self {
156        Merge {
157            values: smallvec_inline![value],
158        }
159    }
160
161    /// Create a `Merge` from a `removes` and `adds`, padding with `None` to
162    /// make sure that there is exactly one more `adds` than `removes`.
163    pub fn from_legacy_form(
164        removes: impl IntoIterator<Item = T>,
165        adds: impl IntoIterator<Item = T>,
166    ) -> Merge<Option<T>> {
167        let removes = removes.into_iter();
168        let mut adds = adds.into_iter().fuse();
169        let mut values = smallvec_inline![adds.next()];
170        for diff in removes.zip_longest(adds) {
171            let (remove, add) = diff.map_any(Some, Some).or_default();
172            values.extend([remove, add]);
173        }
174        Merge { values }
175    }
176
177    /// The removed values, also called negative terms.
178    pub fn removes(&self) -> impl ExactSizeIterator<Item = &T> {
179        self.values[1..].iter().step_by(2)
180    }
181
182    /// The added values, also called positive terms.
183    pub fn adds(&self) -> impl ExactSizeIterator<Item = &T> {
184        self.values.iter().step_by(2)
185    }
186
187    /// Returns the zeroth added value, which is guaranteed to exist.
188    pub fn first(&self) -> &T {
189        &self.values[0]
190    }
191
192    /// Returns the `index`-th removed value, which is considered belonging to
193    /// the `index`-th diff pair.
194    pub fn get_remove(&self, index: usize) -> Option<&T> {
195        self.values.get(index * 2 + 1)
196    }
197
198    /// Returns the `index`-th added value, which is considered belonging to the
199    /// `index-1`-th diff pair. The zeroth add is a diff from the non-existent
200    /// state.
201    pub fn get_add(&self, index: usize) -> Option<&T> {
202        self.values.get(index * 2)
203    }
204
205    /// Removes the specified "removed"/"added" values. The removed slots are
206    /// replaced by the last "removed"/"added" values.
207    pub fn swap_remove(&mut self, remove_index: usize, add_index: usize) -> (T, T) {
208        // Swap with the last "added" and "removed" values in order.
209        let add = self.values.swap_remove(add_index * 2);
210        let remove = self.values.swap_remove(remove_index * 2 + 1);
211        (remove, add)
212    }
213
214    /// The number of positive terms in the conflict.
215    pub fn num_sides(&self) -> usize {
216        self.values.len() / 2 + 1
217    }
218
219    /// Whether this merge is resolved. Does not resolve trivial merges.
220    pub fn is_resolved(&self) -> bool {
221        self.values.len() == 1
222    }
223
224    /// Returns the resolved value, if this merge is resolved. Does not
225    /// resolve trivial merges.
226    pub fn as_resolved(&self) -> Option<&T> {
227        if let [value] = &self.values[..] {
228            Some(value)
229        } else {
230            None
231        }
232    }
233
234    /// Returns the resolved value, if this merge is resolved. Otherwise returns
235    /// the merge itself as an `Err`. Does not resolve trivial merges.
236    pub fn into_resolved(mut self) -> Result<T, Merge<T>> {
237        if self.values.len() == 1 {
238            Ok(self.values.pop().unwrap())
239        } else {
240            Err(self)
241        }
242    }
243
244    /// Returns a vector mapping of a value's index in the simplified merge to
245    /// its original index in the unsimplified merge.
246    ///
247    /// The merge is simplified by removing identical values in add and remove
248    /// values.
249    fn get_simplified_mapping(&self) -> Vec<usize>
250    where
251        T: PartialEq,
252    {
253        let unsimplified_len = self.values.len();
254        let mut simplified_to_original_indices = (0..unsimplified_len).collect_vec();
255
256        let mut add_index = 0;
257        while add_index < simplified_to_original_indices.len() {
258            let add = &self.values[simplified_to_original_indices[add_index]];
259            let mut remove_indices = simplified_to_original_indices
260                .iter()
261                .enumerate()
262                .skip(1)
263                .step_by(2);
264            if let Some((remove_index, _)) = remove_indices
265                .find(|&(_, original_remove_index)| &self.values[*original_remove_index] == add)
266            {
267                // Align the current "add" value to the `remove_index/2`-th diff, then
268                // delete the diff pair.
269                simplified_to_original_indices.swap(remove_index + 1, add_index);
270                simplified_to_original_indices.drain(remove_index..remove_index + 2);
271            } else {
272                add_index += 2;
273            }
274        }
275
276        simplified_to_original_indices
277    }
278
279    /// Simplify the merge by joining diffs like A->B and B->C into A->C.
280    /// Also drops trivial diffs like A->A.
281    #[must_use]
282    pub fn simplify(&self) -> Self
283    where
284        T: PartialEq + Clone,
285    {
286        let mapping = self.get_simplified_mapping();
287        // Reorder values based on their new indices in the simplified merge.
288        let values = mapping
289            .iter()
290            .map(|index| self.values[*index].clone())
291            .collect();
292        Merge { values }
293    }
294
295    /// Updates the merge based on the given simplified merge.
296    pub fn update_from_simplified(mut self, simplified: Merge<T>) -> Self
297    where
298        T: PartialEq,
299    {
300        let mapping = self.get_simplified_mapping();
301        assert_eq!(mapping.len(), simplified.values.len());
302        for (index, value) in mapping.into_iter().zip(simplified.values.into_iter()) {
303            self.values[index] = value;
304        }
305        self
306    }
307
308    /// If this merge can be trivially resolved, returns the value it resolves
309    /// to.
310    pub fn resolve_trivial(&self) -> Option<&T>
311    where
312        T: Eq + Hash,
313    {
314        trivial_merge(&self.values)
315    }
316
317    /// Pads this merge with to the specified number of sides with the specified
318    /// value. No-op if the requested size is not larger than the current size.
319    pub fn pad_to(&mut self, num_sides: usize, value: &T)
320    where
321        T: Clone,
322    {
323        if num_sides <= self.num_sides() {
324            return;
325        }
326        self.values.resize(num_sides * 2 - 1, value.clone());
327    }
328
329    /// Returns a slice containing the terms. The items will alternate between
330    /// positive and negative terms, starting with positive (since there's one
331    /// more of those).
332    pub fn as_slice(&self) -> &[T] {
333        &self.values
334    }
335
336    /// Returns an iterator over references to the terms. The items will
337    /// alternate between positive and negative terms, starting with
338    /// positive (since there's one more of those).
339    pub fn iter(&self) -> slice::Iter<'_, T> {
340        self.values.iter()
341    }
342
343    /// A version of `Merge::iter()` that iterates over mutable references.
344    pub fn iter_mut(&mut self) -> slice::IterMut<'_, T> {
345        self.values.iter_mut()
346    }
347
348    /// Creates a new merge by applying `f` to each remove and add.
349    pub fn map<'a, U>(&'a self, f: impl FnMut(&'a T) -> U) -> Merge<U> {
350        let values = self.values.iter().map(f).collect();
351        Merge { values }
352    }
353
354    /// Creates a new merge by applying `f` to each remove and add, returning
355    /// `Err if `f` returns `Err` for any of them.
356    pub fn try_map<'a, U, E>(
357        &'a self,
358        f: impl FnMut(&'a T) -> Result<U, E>,
359    ) -> Result<Merge<U>, E> {
360        let values = self.values.iter().map(f).try_collect()?;
361        Ok(Merge { values })
362    }
363
364    /// Creates a new merge by applying the async function `f` to each remove
365    /// and add, running them concurrently, and returning `Err if `f`
366    /// returns `Err` for any of them.
367    pub async fn try_map_async<'a, F, U, E>(
368        &'a self,
369        f: impl FnMut(&'a T) -> F,
370    ) -> Result<Merge<U>, E>
371    where
372        F: Future<Output = Result<U, E>>,
373    {
374        let values = try_join_all(self.values.iter().map(f)).await?;
375        Ok(Merge {
376            values: values.into(),
377        })
378    }
379}
380
381/// Helper for consuming items from an iterator and then creating a `Merge`.
382///
383/// By not collecting directly into `Merge`, we can avoid creating invalid
384/// instances of it. If we had `Merge::from_iter()` we would need to allow it to
385/// accept iterators of any length (including 0). We couldn't make it panic on
386/// even lengths because we can get passed such iterators from e.g.
387/// `Option::from_iter()`. By collecting into `MergeBuilder` instead, we move
388/// the checking until after `from_iter()` (to `MergeBuilder::build()`).
389#[derive(Clone, Debug, PartialEq, Eq)]
390pub struct MergeBuilder<T> {
391    values: SmallVec<[T; 1]>,
392}
393
394impl<T> Default for MergeBuilder<T> {
395    fn default() -> Self {
396        Self {
397            values: Default::default(),
398        }
399    }
400}
401
402impl<T> MergeBuilder<T> {
403    /// Requires that exactly one more "adds" than "removes" have been added to
404    /// this builder.
405    pub fn build(self) -> Merge<T> {
406        Merge::from_vec(self.values)
407    }
408}
409
410impl<T> IntoIterator for Merge<T> {
411    type Item = T;
412    type IntoIter = smallvec::IntoIter<[T; 1]>;
413
414    fn into_iter(self) -> Self::IntoIter {
415        self.values.into_iter()
416    }
417}
418
419impl<T> FromIterator<T> for MergeBuilder<T> {
420    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
421        let mut builder = MergeBuilder::default();
422        builder.extend(iter);
423        builder
424    }
425}
426
427impl<T> Extend<T> for MergeBuilder<T> {
428    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
429        self.values.extend(iter);
430    }
431}
432
433impl<T> Merge<Option<T>> {
434    /// Creates a resolved merge with a value of `None`.
435    pub fn absent() -> Self {
436        Self::resolved(None)
437    }
438
439    /// Creates a resolved merge with a value of `Some(value)`.
440    pub fn normal(value: T) -> Self {
441        Self::resolved(Some(value))
442    }
443
444    /// Whether this represents a resolved value of `None`.
445    pub fn is_absent(&self) -> bool {
446        matches!(self.as_resolved(), Some(None))
447    }
448
449    /// The opposite of `is_absent()`.
450    pub fn is_present(&self) -> bool {
451        !self.is_absent()
452    }
453
454    /// Returns the value if this is present and non-conflicting.
455    pub fn as_normal(&self) -> Option<&T> {
456        self.as_resolved()?.as_ref()
457    }
458
459    /// Creates lists of `removes` and `adds` from a `Merge` by dropping
460    /// `None` values. Note that the conversion is lossy: the order of `None`
461    /// values is not preserved when converting back to a `Merge`.
462    pub fn into_legacy_form(self) -> (Vec<T>, Vec<T>) {
463        // Allocate the maximum size assuming there would be few `None`s.
464        let mut removes = Vec::with_capacity(self.values.len() / 2);
465        let mut adds = Vec::with_capacity(self.values.len() / 2 + 1);
466        let mut values = self.values.into_iter();
467        adds.extend(values.next().unwrap());
468        while let Some(remove) = values.next() {
469            removes.extend(remove);
470            adds.extend(values.next().unwrap());
471        }
472        (removes, adds)
473    }
474}
475
476impl<T: Clone> Merge<Option<&T>> {
477    /// Creates a new merge by cloning inner `Option<&T>`s.
478    pub fn cloned(&self) -> Merge<Option<T>> {
479        self.map(|value| value.cloned())
480    }
481}
482
483impl<T> Merge<Merge<T>> {
484    /// Flattens a nested merge into a regular merge.
485    ///
486    /// Let's say we have a 3-way merge of 3-way merges like this:
487    ///
488    /// 4 5   7 8
489    ///  3     6
490    ///    1 2
491    ///     0
492    ///
493    /// Flattening that results in this 9-way merge:
494    ///
495    /// 4 5 0 7 8
496    ///  3 2 1 6
497    pub fn flatten(self) -> Merge<T> {
498        let mut outer_values = self.values.into_iter();
499        let mut result = outer_values.next().unwrap();
500        while let Some(mut remove) = outer_values.next() {
501            // Add removes reversed, and with the first element moved last, so we preserve
502            // the diffs
503            remove.values.rotate_left(1);
504            for i in 0..remove.values.len() / 2 {
505                remove.values.swap(i * 2, i * 2 + 1);
506            }
507            result.values.extend(remove.values);
508            let add = outer_values.next().unwrap();
509            result.values.extend(add.values);
510        }
511        result
512    }
513}
514
515impl<T: ContentHash> ContentHash for Merge<T> {
516    fn hash(&self, state: &mut impl DigestUpdate) {
517        self.values.hash(state);
518    }
519}
520
521/// Borrowed `MergedTreeValue`.
522pub type MergedTreeVal<'a> = Merge<Option<&'a TreeValue>>;
523
524/// The value at a given path in a commit.
525///
526/// It depends on the context whether it can be absent
527/// (`Merge::is_absent()`). For example, when getting the value at a
528/// specific path, it may be, but when iterating over entries in a
529/// tree, it shouldn't be.
530pub type MergedTreeValue = Merge<Option<TreeValue>>;
531
532impl MergedTreeValue {
533    /// Create a `Merge` from a `backend::Conflict`, padding with `None` to
534    /// make sure that there is exactly one more `adds()` than `removes()`.
535    pub fn from_backend_conflict(conflict: backend::Conflict) -> Self {
536        let removes = conflict.removes.into_iter().map(|term| term.value);
537        let adds = conflict.adds.into_iter().map(|term| term.value);
538        Merge::from_legacy_form(removes, adds)
539    }
540
541    /// Creates a `backend::Conflict` from a `Merge` by dropping `None`
542    /// values. Note that the conversion is lossy: the order of `None` values is
543    /// not preserved when converting back to a `Merge`.
544    pub fn into_backend_conflict(self) -> backend::Conflict {
545        let (removes, adds) = self.into_legacy_form();
546        let removes = removes
547            .into_iter()
548            .map(|value| backend::ConflictTerm { value })
549            .collect();
550        let adds = adds
551            .into_iter()
552            .map(|value| backend::ConflictTerm { value })
553            .collect();
554        backend::Conflict { removes, adds }
555    }
556}
557
558impl<T> Merge<Option<T>>
559where
560    T: Borrow<TreeValue>,
561{
562    /// Whether this merge should be recursed into when doing directory walks.
563    pub fn is_tree(&self) -> bool {
564        self.is_present()
565            && self.iter().all(|value| {
566                matches!(
567                    borrow_tree_value(value.as_ref()),
568                    Some(TreeValue::Tree(_)) | None
569                )
570            })
571    }
572
573    /// If this merge contains only files or absent entries, returns a merge of
574    /// the `FileId`s`. The executable bits and copy IDs will be ignored. Use
575    /// `Merge::with_new_file_ids()` to produce a new merge with the original
576    /// executable bits preserved.
577    pub fn to_file_merge(&self) -> Option<Merge<Option<FileId>>> {
578        let file_ids = self
579            .try_map(|term| match borrow_tree_value(term.as_ref()) {
580                None => Ok(None),
581                Some(TreeValue::File {
582                    id,
583                    executable: _,
584                    copy_id: _,
585                }) => Ok(Some(id.clone())),
586                _ => Err(()),
587            })
588            .ok()?;
589
590        Some(file_ids)
591    }
592
593    /// If this merge contains only files or absent entries, returns a merge of
594    /// the files' executable bits.
595    pub fn to_executable_merge(&self) -> Option<Merge<Option<bool>>> {
596        self.try_map(|term| match borrow_tree_value(term.as_ref()) {
597            None => Ok(None),
598            Some(TreeValue::File {
599                id: _,
600                executable,
601                copy_id: _,
602            }) => Ok(Some(*executable)),
603            _ => Err(()),
604        })
605        .ok()
606    }
607
608    /// If this merge contains only files or absent entries, returns a merge of
609    /// the files' copy IDs.
610    pub fn to_copy_id_merge(&self) -> Option<Merge<Option<CopyId>>> {
611        self.try_map(|term| match borrow_tree_value(term.as_ref()) {
612            None => Ok(None),
613            Some(TreeValue::File {
614                id: _,
615                executable: _,
616                copy_id,
617            }) => Ok(Some(copy_id.clone())),
618            _ => Err(()),
619        })
620        .ok()
621    }
622
623    /// If every non-`None` term of a `MergedTreeValue`
624    /// is a `TreeValue::Tree`, this converts it to
625    /// a `Merge<Tree>`, with empty trees instead of
626    /// any `None` terms. Otherwise, returns `None`.
627    pub async fn to_tree_merge(
628        &self,
629        store: &Arc<Store>,
630        dir: &RepoPath,
631    ) -> BackendResult<Option<Merge<Tree>>> {
632        let tree_id_merge = self.try_map(|term| match borrow_tree_value(term.as_ref()) {
633            None => Ok(None),
634            Some(TreeValue::Tree(id)) => Ok(Some(id)),
635            Some(_) => Err(()),
636        });
637        if let Ok(tree_id_merge) = tree_id_merge {
638            Ok(Some(
639                tree_id_merge
640                    .try_map_async(|id| async move {
641                        if let Some(id) = id {
642                            store.get_tree_async(dir.to_owned(), id).await
643                        } else {
644                            Ok(Tree::empty(store.clone(), dir.to_owned()))
645                        }
646                    })
647                    .await?,
648            ))
649        } else {
650            Ok(None)
651        }
652    }
653
654    /// Creates a new merge with the file ids from the given merge. In other
655    /// words, only the executable bits from `self` will be preserved.
656    ///
657    /// The given `file_ids` should have the same shape as `self`. Only the
658    /// `FileId` values may differ.
659    pub fn with_new_file_ids(&self, file_ids: &Merge<Option<FileId>>) -> Merge<Option<TreeValue>> {
660        assert_eq!(self.values.len(), file_ids.values.len());
661        let values = zip(self.iter(), file_ids.iter().cloned())
662            .map(
663                |(tree_value, file_id)| match (borrow_tree_value(tree_value.as_ref()), file_id) {
664                    (
665                        Some(TreeValue::File {
666                            id: _,
667                            executable,
668                            copy_id,
669                        }),
670                        Some(id),
671                    ) => Some(TreeValue::File {
672                        id,
673                        executable: *executable,
674                        copy_id: copy_id.clone(),
675                    }),
676                    (None, None) => None,
677                    (old, new) => panic!("incompatible update: {old:?} to {new:?}"),
678                },
679            )
680            .collect();
681        Merge { values }
682    }
683
684    /// Give a summary description of the conflict's "removes" and "adds"
685    pub fn describe(&self) -> String {
686        let mut buf = String::new();
687        writeln!(buf, "Conflict:").unwrap();
688        for term in self.removes().flatten() {
689            writeln!(buf, "  Removing {}", describe_conflict_term(term.borrow())).unwrap();
690        }
691        for term in self.adds().flatten() {
692            writeln!(buf, "  Adding {}", describe_conflict_term(term.borrow())).unwrap();
693        }
694        buf
695    }
696}
697
698fn borrow_tree_value<T: Borrow<TreeValue> + ?Sized>(term: Option<&T>) -> Option<&TreeValue> {
699    term.map(|value| value.borrow())
700}
701
702fn describe_conflict_term(value: &TreeValue) -> String {
703    match value {
704        TreeValue::File {
705            id,
706            executable: false,
707            copy_id: _,
708        } => {
709            // TODO: include the copy here once we start using it
710            format!("file with id {id}")
711        }
712        TreeValue::File {
713            id,
714            executable: true,
715            copy_id: _,
716        } => {
717            // TODO: include the copy here once we start using it
718            format!("executable file with id {id}")
719        }
720        TreeValue::Symlink(id) => {
721            format!("symlink with id {id}")
722        }
723        TreeValue::Tree(id) => {
724            format!("tree with id {id}")
725        }
726        TreeValue::GitSubmodule(id) => {
727            format!("Git submodule with id {id}")
728        }
729        TreeValue::Conflict(id) => {
730            format!("Conflict with id {id}")
731        }
732    }
733}
734
735#[cfg(test)]
736mod tests {
737    use super::*;
738
739    fn c<T: Clone>(terms: &[T]) -> Merge<T> {
740        Merge::from_vec(terms.to_vec())
741    }
742
743    #[test]
744    fn test_trivial_merge() {
745        assert_eq!(trivial_merge(&[0]), Some(&0));
746        assert_eq!(trivial_merge(&[0, 0, 0]), Some(&0));
747        assert_eq!(trivial_merge(&[0, 0, 1]), Some(&1));
748        assert_eq!(trivial_merge(&[0, 1, 0]), Some(&0));
749        assert_eq!(trivial_merge(&[0, 1, 1]), Some(&0));
750        assert_eq!(trivial_merge(&[0, 1, 2]), None);
751        assert_eq!(trivial_merge(&[0, 0, 0, 0, 0]), Some(&0));
752        assert_eq!(trivial_merge(&[0, 0, 0, 0, 1]), Some(&1));
753        assert_eq!(trivial_merge(&[0, 0, 0, 1, 0]), Some(&0));
754        assert_eq!(trivial_merge(&[0, 0, 0, 1, 1]), Some(&0));
755        assert_eq!(trivial_merge(&[0, 0, 0, 1, 2]), None);
756        assert_eq!(trivial_merge(&[0, 0, 1, 0, 0]), Some(&1));
757        assert_eq!(trivial_merge(&[0, 0, 1, 0, 1]), Some(&1));
758        assert_eq!(trivial_merge(&[0, 0, 1, 0, 2]), None);
759        assert_eq!(trivial_merge(&[0, 0, 1, 1, 0]), Some(&0));
760        assert_eq!(trivial_merge(&[0, 0, 1, 1, 1]), Some(&1));
761        assert_eq!(trivial_merge(&[0, 0, 1, 1, 2]), Some(&2));
762        assert_eq!(trivial_merge(&[0, 0, 1, 2, 0]), None);
763        assert_eq!(trivial_merge(&[0, 0, 1, 2, 1]), Some(&1));
764        assert_eq!(trivial_merge(&[0, 0, 1, 2, 2]), Some(&1));
765        assert_eq!(trivial_merge(&[0, 0, 1, 2, 3]), None);
766        assert_eq!(trivial_merge(&[0, 1, 0, 0, 0]), Some(&0));
767        assert_eq!(trivial_merge(&[0, 1, 0, 0, 1]), Some(&0));
768        assert_eq!(trivial_merge(&[0, 1, 0, 0, 2]), None);
769        assert_eq!(trivial_merge(&[0, 1, 0, 1, 0]), Some(&0));
770        assert_eq!(trivial_merge(&[0, 1, 0, 1, 1]), Some(&0));
771        assert_eq!(trivial_merge(&[0, 1, 0, 1, 2]), None);
772        assert_eq!(trivial_merge(&[0, 1, 0, 2, 0]), None);
773        assert_eq!(trivial_merge(&[0, 1, 0, 2, 1]), Some(&0));
774        assert_eq!(trivial_merge(&[0, 1, 0, 2, 2]), Some(&0));
775        assert_eq!(trivial_merge(&[0, 1, 0, 2, 3]), None);
776        assert_eq!(trivial_merge(&[0, 1, 1, 0, 0]), Some(&0));
777        assert_eq!(trivial_merge(&[0, 1, 1, 0, 1]), Some(&1));
778        assert_eq!(trivial_merge(&[0, 1, 1, 0, 2]), Some(&2));
779        assert_eq!(trivial_merge(&[0, 1, 1, 1, 0]), Some(&0));
780        assert_eq!(trivial_merge(&[0, 1, 1, 1, 1]), Some(&0));
781        assert_eq!(trivial_merge(&[0, 1, 1, 1, 2]), None);
782        assert_eq!(trivial_merge(&[0, 1, 1, 2, 0]), Some(&0));
783        assert_eq!(trivial_merge(&[0, 1, 1, 2, 1]), None);
784        assert_eq!(trivial_merge(&[0, 1, 1, 2, 2]), Some(&0));
785        assert_eq!(trivial_merge(&[0, 1, 1, 2, 3]), None);
786        assert_eq!(trivial_merge(&[0, 1, 2, 0, 0]), None);
787        assert_eq!(trivial_merge(&[0, 1, 2, 0, 1]), Some(&2));
788        assert_eq!(trivial_merge(&[0, 1, 2, 0, 2]), Some(&2));
789        assert_eq!(trivial_merge(&[0, 1, 2, 0, 3]), None);
790        assert_eq!(trivial_merge(&[0, 1, 2, 1, 0]), None);
791        assert_eq!(trivial_merge(&[0, 1, 2, 1, 1]), None);
792        assert_eq!(trivial_merge(&[0, 1, 2, 1, 2]), None);
793        assert_eq!(trivial_merge(&[0, 1, 2, 1, 3]), None);
794        assert_eq!(trivial_merge(&[0, 1, 2, 2, 0]), Some(&0));
795        assert_eq!(trivial_merge(&[0, 1, 2, 2, 1]), Some(&0));
796        assert_eq!(trivial_merge(&[0, 1, 2, 2, 2]), None);
797        assert_eq!(trivial_merge(&[0, 1, 2, 2, 3]), None);
798        assert_eq!(trivial_merge(&[0, 1, 2, 3, 0]), None);
799        assert_eq!(trivial_merge(&[0, 1, 2, 3, 1]), None);
800        assert_eq!(trivial_merge(&[0, 1, 2, 3, 2]), None);
801        assert_eq!(trivial_merge(&[0, 1, 2, 3, 3]), None);
802        assert_eq!(trivial_merge(&[0, 1, 2, 3, 4]), None);
803    }
804
805    #[test]
806    fn test_legacy_form_conversion() {
807        fn test_equivalent<T>(legacy_form: (Vec<T>, Vec<T>), merge: Merge<Option<T>>)
808        where
809            T: Clone + PartialEq + std::fmt::Debug,
810        {
811            assert_eq!(merge.clone().into_legacy_form(), legacy_form);
812            assert_eq!(Merge::from_legacy_form(legacy_form.0, legacy_form.1), merge);
813        }
814        // Non-conflict
815        test_equivalent(
816            (vec![], vec![0]),
817            Merge::from_removes_adds(vec![], vec![Some(0)]),
818        );
819        // Regular 3-way conflict
820        test_equivalent(
821            (vec![0], vec![1, 2]),
822            Merge::from_removes_adds(vec![Some(0)], vec![Some(1), Some(2)]),
823        );
824        // Modify/delete conflict
825        test_equivalent(
826            (vec![0], vec![1]),
827            Merge::from_removes_adds(vec![Some(0)], vec![Some(1), None]),
828        );
829        // Add/add conflict
830        test_equivalent(
831            (vec![], vec![0, 1]),
832            Merge::from_removes_adds(vec![None], vec![Some(0), Some(1)]),
833        );
834        // 5-way conflict
835        test_equivalent(
836            (vec![0, 1], vec![2, 3, 4]),
837            Merge::from_removes_adds(vec![Some(0), Some(1)], vec![Some(2), Some(3), Some(4)]),
838        );
839        // 5-way delete/delete conflict
840        test_equivalent(
841            (vec![0, 1], vec![]),
842            Merge::from_removes_adds(vec![Some(0), Some(1)], vec![None, None, None]),
843        );
844    }
845
846    #[test]
847    fn test_as_resolved() {
848        assert_eq!(
849            Merge::from_removes_adds(vec![], vec![0]).as_resolved(),
850            Some(&0)
851        );
852        // Even a trivially resolvable merge is not resolved
853        assert_eq!(
854            Merge::from_removes_adds(vec![0], vec![0, 1]).as_resolved(),
855            None
856        );
857    }
858
859    #[test]
860    fn test_get_simplified_mapping() {
861        // 1-way merge
862        assert_eq!(c(&[0]).get_simplified_mapping(), vec![0]);
863        // 3-way merge
864        assert_eq!(c(&[0, 0, 0]).get_simplified_mapping(), vec![2]);
865        assert_eq!(c(&[0, 0, 1]).get_simplified_mapping(), vec![2]);
866        assert_eq!(c(&[0, 1, 0]).get_simplified_mapping(), vec![0, 1, 2]);
867        assert_eq!(c(&[0, 1, 1]).get_simplified_mapping(), vec![0]);
868        assert_eq!(c(&[0, 1, 2]).get_simplified_mapping(), vec![0, 1, 2]);
869        // 5-way merge
870        assert_eq!(c(&[0, 0, 0, 0, 0]).get_simplified_mapping(), vec![4]);
871        assert_eq!(c(&[0, 0, 0, 0, 1]).get_simplified_mapping(), vec![4]);
872        assert_eq!(c(&[0, 0, 0, 1, 0]).get_simplified_mapping(), vec![2, 3, 4]);
873        assert_eq!(c(&[0, 0, 0, 1, 1]).get_simplified_mapping(), vec![2]);
874        assert_eq!(c(&[0, 0, 0, 1, 2]).get_simplified_mapping(), vec![2, 3, 4]);
875        assert_eq!(c(&[0, 0, 1, 0, 0]).get_simplified_mapping(), vec![2]);
876        assert_eq!(c(&[0, 0, 1, 0, 1]).get_simplified_mapping(), vec![2, 3, 4]);
877        assert_eq!(c(&[0, 0, 1, 0, 2]).get_simplified_mapping(), vec![2, 3, 4]);
878        assert_eq!(c(&[0, 0, 1, 1, 0]).get_simplified_mapping(), vec![4]);
879        assert_eq!(c(&[0, 0, 1, 1, 1]).get_simplified_mapping(), vec![4]);
880        assert_eq!(c(&[0, 0, 1, 1, 2]).get_simplified_mapping(), vec![4]);
881        assert_eq!(c(&[0, 0, 2, 1, 0]).get_simplified_mapping(), vec![2, 3, 4]);
882        assert_eq!(c(&[0, 0, 2, 1, 1]).get_simplified_mapping(), vec![2]);
883        assert_eq!(c(&[0, 0, 2, 1, 2]).get_simplified_mapping(), vec![2, 3, 4]);
884        assert_eq!(c(&[0, 0, 2, 1, 3]).get_simplified_mapping(), vec![2, 3, 4]);
885        assert_eq!(c(&[0, 1, 0, 0, 0]).get_simplified_mapping(), vec![4, 1, 2]);
886        assert_eq!(c(&[0, 1, 0, 0, 1]).get_simplified_mapping(), vec![2]);
887        assert_eq!(c(&[0, 1, 0, 0, 2]).get_simplified_mapping(), vec![4, 1, 2]);
888        assert_eq!(
889            c(&[0, 1, 0, 1, 0]).get_simplified_mapping(),
890            vec![0, 1, 2, 3, 4]
891        );
892        assert_eq!(c(&[0, 1, 0, 1, 1]).get_simplified_mapping(), vec![0, 3, 2]);
893        assert_eq!(
894            c(&[0, 1, 0, 1, 2]).get_simplified_mapping(),
895            vec![0, 1, 2, 3, 4]
896        );
897        assert_eq!(
898            c(&[0, 1, 0, 2, 0]).get_simplified_mapping(),
899            vec![0, 1, 2, 3, 4]
900        );
901        assert_eq!(c(&[0, 1, 0, 2, 1]).get_simplified_mapping(), vec![0, 3, 2]);
902        assert_eq!(c(&[0, 1, 0, 2, 2]).get_simplified_mapping(), vec![0, 1, 2]);
903        assert_eq!(
904            c(&[0, 1, 0, 2, 3]).get_simplified_mapping(),
905            vec![0, 1, 2, 3, 4]
906        );
907        assert_eq!(c(&[0, 1, 1, 0, 0]).get_simplified_mapping(), vec![4]);
908        assert_eq!(c(&[0, 1, 1, 0, 1]).get_simplified_mapping(), vec![2]);
909        assert_eq!(c(&[0, 1, 1, 0, 2]).get_simplified_mapping(), vec![4]);
910        assert_eq!(c(&[0, 1, 1, 1, 0]).get_simplified_mapping(), vec![0, 3, 4]);
911        assert_eq!(c(&[0, 1, 1, 1, 1]).get_simplified_mapping(), vec![0]);
912        assert_eq!(c(&[0, 1, 1, 1, 2]).get_simplified_mapping(), vec![0, 3, 4]);
913        assert_eq!(c(&[0, 1, 1, 2, 0]).get_simplified_mapping(), vec![0, 3, 4]);
914        assert_eq!(c(&[0, 1, 1, 2, 1]).get_simplified_mapping(), vec![0, 3, 4]);
915        assert_eq!(c(&[0, 1, 1, 2, 2]).get_simplified_mapping(), vec![0]);
916        assert_eq!(c(&[0, 1, 1, 2, 3]).get_simplified_mapping(), vec![0, 3, 4]);
917        assert_eq!(c(&[0, 1, 2, 0, 0]).get_simplified_mapping(), vec![4, 1, 2]);
918        assert_eq!(c(&[0, 1, 2, 0, 1]).get_simplified_mapping(), vec![2]);
919        assert_eq!(c(&[0, 1, 2, 0, 2]).get_simplified_mapping(), vec![4, 1, 2]);
920        assert_eq!(c(&[0, 1, 2, 0, 3]).get_simplified_mapping(), vec![4, 1, 2]);
921        assert_eq!(
922            c(&[0, 1, 2, 1, 0]).get_simplified_mapping(),
923            vec![0, 1, 2, 3, 4]
924        );
925        assert_eq!(c(&[0, 1, 2, 1, 1]).get_simplified_mapping(), vec![0, 3, 2]);
926        assert_eq!(
927            c(&[0, 1, 2, 1, 2]).get_simplified_mapping(),
928            vec![0, 1, 2, 3, 4]
929        );
930        assert_eq!(
931            c(&[0, 1, 2, 1, 3]).get_simplified_mapping(),
932            vec![0, 1, 2, 3, 4]
933        );
934        assert_eq!(c(&[0, 1, 2, 2, 0]).get_simplified_mapping(), vec![0, 1, 4]);
935        assert_eq!(c(&[0, 1, 2, 2, 1]).get_simplified_mapping(), vec![0]);
936        assert_eq!(c(&[0, 1, 2, 2, 2]).get_simplified_mapping(), vec![0, 1, 4]);
937        assert_eq!(c(&[0, 1, 2, 2, 3]).get_simplified_mapping(), vec![0, 1, 4]);
938        assert_eq!(
939            c(&[0, 1, 2, 3, 0]).get_simplified_mapping(),
940            vec![0, 1, 2, 3, 4]
941        );
942        assert_eq!(c(&[0, 1, 2, 3, 1]).get_simplified_mapping(), vec![0, 3, 2]);
943        assert_eq!(
944            c(&[0, 1, 2, 3, 2]).get_simplified_mapping(),
945            vec![0, 1, 2, 3, 4]
946        );
947        assert_eq!(
948            c(&[0, 1, 2, 3, 4, 5, 1]).get_simplified_mapping(),
949            vec![0, 3, 4, 5, 2]
950        );
951        assert_eq!(
952            c(&[0, 1, 2, 3, 4]).get_simplified_mapping(),
953            vec![0, 1, 2, 3, 4]
954        );
955        assert_eq!(c(&[2, 0, 3, 1, 1]).get_simplified_mapping(), vec![0, 1, 2]);
956    }
957
958    #[test]
959    fn test_simplify() {
960        // 1-way merge
961        assert_eq!(c(&[0]).simplify(), c(&[0]));
962        // 3-way merge
963        assert_eq!(c(&[0, 0, 0]).simplify(), c(&[0]));
964        assert_eq!(c(&[0, 0, 1]).simplify(), c(&[1]));
965        assert_eq!(c(&[1, 0, 0]).simplify(), c(&[1]));
966        assert_eq!(c(&[1, 0, 1]).simplify(), c(&[1, 0, 1]));
967        assert_eq!(c(&[1, 0, 2]).simplify(), c(&[1, 0, 2]));
968        // 5-way merge
969        assert_eq!(c(&[0, 0, 0, 0, 0]).simplify(), c(&[0]));
970        assert_eq!(c(&[0, 0, 0, 0, 1]).simplify(), c(&[1]));
971        assert_eq!(c(&[0, 0, 0, 1, 0]).simplify(), c(&[0, 1, 0]));
972        assert_eq!(c(&[0, 0, 0, 1, 1]).simplify(), c(&[0]));
973        assert_eq!(c(&[0, 0, 0, 1, 2]).simplify(), c(&[0, 1, 2]));
974        assert_eq!(c(&[0, 0, 1, 0, 0]).simplify(), c(&[1]));
975        assert_eq!(c(&[0, 0, 1, 0, 1]).simplify(), c(&[1, 0, 1]));
976        assert_eq!(c(&[0, 0, 1, 0, 2]).simplify(), c(&[1, 0, 2]));
977        assert_eq!(c(&[0, 0, 1, 1, 0]).simplify(), c(&[0]));
978        assert_eq!(c(&[0, 0, 1, 1, 1]).simplify(), c(&[1]));
979        assert_eq!(c(&[0, 0, 1, 1, 2]).simplify(), c(&[2]));
980        assert_eq!(c(&[0, 0, 2, 1, 0]).simplify(), c(&[2, 1, 0]));
981        assert_eq!(c(&[0, 0, 2, 1, 1]).simplify(), c(&[2]));
982        assert_eq!(c(&[0, 0, 2, 1, 2]).simplify(), c(&[2, 1, 2]));
983        assert_eq!(c(&[0, 0, 2, 1, 3]).simplify(), c(&[2, 1, 3]));
984        assert_eq!(c(&[0, 1, 0, 0, 0]).simplify(), c(&[0, 1, 0]));
985        assert_eq!(c(&[0, 1, 0, 0, 1]).simplify(), c(&[0]));
986        assert_eq!(c(&[0, 1, 0, 0, 2]).simplify(), c(&[2, 1, 0]));
987        assert_eq!(c(&[0, 1, 0, 1, 0]).simplify(), c(&[0, 1, 0, 1, 0]));
988        assert_eq!(c(&[0, 1, 0, 1, 1]).simplify(), c(&[0, 1, 0]));
989        assert_eq!(c(&[0, 1, 0, 1, 2]).simplify(), c(&[0, 1, 0, 1, 2]));
990        assert_eq!(c(&[0, 1, 0, 2, 0]).simplify(), c(&[0, 1, 0, 2, 0]));
991        assert_eq!(c(&[0, 1, 0, 2, 1]).simplify(), c(&[0, 2, 0]));
992        assert_eq!(c(&[0, 1, 0, 2, 2]).simplify(), c(&[0, 1, 0]));
993        assert_eq!(c(&[0, 1, 0, 2, 3]).simplify(), c(&[0, 1, 0, 2, 3]));
994        assert_eq!(c(&[0, 1, 1, 0, 0]).simplify(), c(&[0]));
995        assert_eq!(c(&[0, 1, 1, 0, 1]).simplify(), c(&[1]));
996        assert_eq!(c(&[0, 1, 1, 0, 2]).simplify(), c(&[2]));
997        assert_eq!(c(&[0, 1, 1, 1, 0]).simplify(), c(&[0, 1, 0]));
998        assert_eq!(c(&[0, 1, 1, 1, 1]).simplify(), c(&[0]));
999        assert_eq!(c(&[0, 1, 1, 1, 2]).simplify(), c(&[0, 1, 2]));
1000        assert_eq!(c(&[0, 1, 1, 2, 0]).simplify(), c(&[0, 2, 0]));
1001        assert_eq!(c(&[0, 1, 1, 2, 1]).simplify(), c(&[0, 2, 1]));
1002        assert_eq!(c(&[0, 1, 1, 2, 2]).simplify(), c(&[0]));
1003        assert_eq!(c(&[0, 1, 1, 2, 3]).simplify(), c(&[0, 2, 3]));
1004        assert_eq!(c(&[0, 1, 2, 0, 0]).simplify(), c(&[0, 1, 2]));
1005        assert_eq!(c(&[0, 1, 2, 0, 1]).simplify(), c(&[2]));
1006        assert_eq!(c(&[0, 1, 2, 0, 2]).simplify(), c(&[2, 1, 2]));
1007        assert_eq!(c(&[0, 1, 2, 0, 3]).simplify(), c(&[3, 1, 2]));
1008        assert_eq!(c(&[0, 1, 2, 1, 0]).simplify(), c(&[0, 1, 2, 1, 0]));
1009        assert_eq!(c(&[0, 1, 2, 1, 1]).simplify(), c(&[0, 1, 2]));
1010        assert_eq!(c(&[0, 1, 2, 1, 2]).simplify(), c(&[0, 1, 2, 1, 2]));
1011        assert_eq!(c(&[0, 1, 2, 1, 3]).simplify(), c(&[0, 1, 2, 1, 3]));
1012        assert_eq!(c(&[0, 1, 2, 2, 0]).simplify(), c(&[0, 1, 0]));
1013        assert_eq!(c(&[0, 1, 2, 2, 1]).simplify(), c(&[0]));
1014        assert_eq!(c(&[0, 1, 2, 2, 2]).simplify(), c(&[0, 1, 2]));
1015        assert_eq!(c(&[0, 1, 2, 2, 3]).simplify(), c(&[0, 1, 3]));
1016        assert_eq!(c(&[0, 1, 2, 3, 0]).simplify(), c(&[0, 1, 2, 3, 0]));
1017        assert_eq!(c(&[0, 1, 2, 3, 1]).simplify(), c(&[0, 3, 2]));
1018        assert_eq!(c(&[0, 1, 2, 3, 2]).simplify(), c(&[0, 1, 2, 3, 2]));
1019        assert_eq!(c(&[0, 1, 2, 3, 3]).simplify(), c(&[0, 1, 2]));
1020        assert_eq!(c(&[0, 1, 2, 3, 4]).simplify(), c(&[0, 1, 2, 3, 4]));
1021        assert_eq!(c(&[0, 1, 2, 3, 4, 5, 1]).simplify(), c(&[0, 3, 4, 5, 2]));
1022    }
1023
1024    #[test]
1025    fn test_update_from_simplified() {
1026        // 1-way merge
1027        assert_eq!(c(&[0]).update_from_simplified(c(&[1])), c(&[1]));
1028        // 3-way merge
1029        assert_eq!(c(&[0, 0, 0]).update_from_simplified(c(&[1])), c(&[0, 0, 1]));
1030        assert_eq!(c(&[1, 0, 0]).update_from_simplified(c(&[2])), c(&[2, 0, 0]));
1031        assert_eq!(
1032            c(&[1, 0, 2]).update_from_simplified(c(&[2, 1, 3])),
1033            c(&[2, 1, 3])
1034        );
1035        // 5-way merge
1036        assert_eq!(
1037            c(&[0, 0, 0, 0, 0]).update_from_simplified(c(&[1])),
1038            c(&[0, 0, 0, 0, 1])
1039        );
1040        assert_eq!(
1041            c(&[0, 0, 0, 1, 0]).update_from_simplified(c(&[2, 3, 1])),
1042            c(&[0, 0, 2, 3, 1])
1043        );
1044        assert_eq!(
1045            c(&[0, 1, 0, 0, 0]).update_from_simplified(c(&[2, 3, 1])),
1046            c(&[0, 3, 1, 0, 2])
1047        );
1048        assert_eq!(
1049            c(&[2, 0, 3, 1, 4]).update_from_simplified(c(&[3, 1, 4, 2, 5])),
1050            c(&[3, 1, 4, 2, 5])
1051        );
1052
1053        assert_eq!(c(&[0, 0, 3, 1, 3, 2, 4]).simplify(), c(&[3, 1, 3, 2, 4]));
1054        // Check that the `3`s are replaced correctly and that `4` ends up in the
1055        // correct position.
1056        assert_eq!(
1057            c(&[0, 0, 3, 1, 3, 2, 4]).update_from_simplified(c(&[10, 1, 11, 2, 4])),
1058            c(&[0, 0, 10, 1, 11, 2, 4])
1059        );
1060    }
1061
1062    #[test]
1063    fn test_merge_invariants() {
1064        fn check_invariants(terms: &[u32]) {
1065            let merge = Merge::from_vec(terms.to_vec());
1066            // `simplify()` is idempotent
1067            assert_eq!(
1068                merge.simplify().simplify(),
1069                merge.simplify(),
1070                "simplify() not idempotent for {merge:?}"
1071            );
1072            // `resolve_trivial()` is unaffected by `simplify()`
1073            assert_eq!(
1074                merge.simplify().resolve_trivial(),
1075                merge.resolve_trivial(),
1076                "simplify() changed result of resolve_trivial() for {merge:?}"
1077            );
1078        }
1079        // 1-way merge
1080        check_invariants(&[0]);
1081        for i in 0..=1 {
1082            for j in 0..=i + 1 {
1083                // 3-way merge
1084                check_invariants(&[i, 0, j]);
1085                for k in 0..=j + 1 {
1086                    for l in 0..=k + 1 {
1087                        // 5-way merge
1088                        check_invariants(&[0, i, j, k, l]);
1089                    }
1090                }
1091            }
1092        }
1093    }
1094
1095    #[test]
1096    fn test_swap_remove() {
1097        let mut x = c(&[0, 1, 2, 3, 4, 5, 6]);
1098        assert_eq!(x.swap_remove(0, 1), (1, 2));
1099        assert_eq!(x, c(&[0, 5, 6, 3, 4]));
1100        assert_eq!(x.swap_remove(1, 0), (3, 0));
1101        assert_eq!(x, c(&[4, 5, 6]));
1102        assert_eq!(x.swap_remove(0, 1), (5, 6));
1103        assert_eq!(x, c(&[4]));
1104    }
1105
1106    #[test]
1107    fn test_pad_to() {
1108        let mut x = c(&[1]);
1109        x.pad_to(3, &2);
1110        assert_eq!(x, c(&[1, 2, 2, 2, 2]));
1111        // No change if the requested size is smaller
1112        x.pad_to(1, &3);
1113        assert_eq!(x, c(&[1, 2, 2, 2, 2]));
1114    }
1115
1116    #[test]
1117    fn test_iter() {
1118        // 1-way merge
1119        assert_eq!(c(&[1]).iter().collect_vec(), vec![&1]);
1120        // 5-way merge
1121        assert_eq!(
1122            c(&[1, 2, 3, 4, 5]).iter().collect_vec(),
1123            vec![&1, &2, &3, &4, &5]
1124        );
1125    }
1126
1127    #[test]
1128    fn test_from_iter() {
1129        // 1-way merge
1130        assert_eq!(MergeBuilder::from_iter([1]).build(), c(&[1]));
1131        // 5-way merge
1132        assert_eq!(
1133            MergeBuilder::from_iter([1, 2, 3, 4, 5]).build(),
1134            c(&[1, 2, 3, 4, 5])
1135        );
1136    }
1137
1138    #[test]
1139    #[should_panic]
1140    fn test_from_iter_empty() {
1141        MergeBuilder::from_iter([1; 0]).build();
1142    }
1143
1144    #[test]
1145    #[should_panic]
1146    fn test_from_iter_even() {
1147        MergeBuilder::from_iter([1, 2]).build();
1148    }
1149
1150    #[test]
1151    fn test_extend() {
1152        // 1-way merge
1153        let mut builder: MergeBuilder<i32> = Default::default();
1154        builder.extend([1]);
1155        assert_eq!(builder.build(), c(&[1]));
1156        // 5-way merge
1157        let mut builder: MergeBuilder<i32> = Default::default();
1158        builder.extend([1, 2]);
1159        builder.extend([3, 4, 5]);
1160        assert_eq!(builder.build(), c(&[1, 2, 3, 4, 5]));
1161    }
1162
1163    #[test]
1164    fn test_map() {
1165        fn increment(i: &i32) -> i32 {
1166            i + 1
1167        }
1168        // 1-way merge
1169        assert_eq!(c(&[1]).map(increment), c(&[2]));
1170        // 3-way merge
1171        assert_eq!(c(&[1, 3, 5]).map(increment), c(&[2, 4, 6]));
1172    }
1173
1174    #[test]
1175    fn test_try_map() {
1176        fn sqrt(i: &i32) -> Result<i32, ()> {
1177            if *i >= 0 {
1178                Ok((*i as f64).sqrt() as i32)
1179            } else {
1180                Err(())
1181            }
1182        }
1183        // 1-way merge
1184        assert_eq!(c(&[1]).try_map(sqrt), Ok(c(&[1])));
1185        assert_eq!(c(&[-1]).try_map(sqrt), Err(()));
1186        // 3-way merge
1187        assert_eq!(c(&[1, 4, 9]).try_map(sqrt), Ok(c(&[1, 2, 3])));
1188        assert_eq!(c(&[-1, 4, 9]).try_map(sqrt), Err(()));
1189        assert_eq!(c(&[1, -4, 9]).try_map(sqrt), Err(()));
1190    }
1191
1192    #[test]
1193    fn test_flatten() {
1194        // 1-way merge of 1-way merge
1195        assert_eq!(c(&[c(&[0])]).flatten(), c(&[0]));
1196        // 1-way merge of 3-way merge
1197        assert_eq!(c(&[c(&[0, 1, 2])]).flatten(), c(&[0, 1, 2]));
1198        // 3-way merge of 1-way merges
1199        assert_eq!(c(&[c(&[0]), c(&[1]), c(&[2])]).flatten(), c(&[0, 1, 2]));
1200        // 3-way merge of 3-way merges
1201        assert_eq!(
1202            c(&[c(&[0, 1, 2]), c(&[3, 4, 5]), c(&[6, 7, 8])]).flatten(),
1203            c(&[0, 1, 2, 5, 4, 3, 6, 7, 8])
1204        );
1205    }
1206}