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