rust/hg-core/src/ancestors.rs
author Matt Harbison <matt_harbison@yahoo.com>
Thu, 27 Dec 2018 21:46:03 -0500
changeset 41068 28a4fb793ba1
parent 41054 ef54bd33b476
child 41104 247f51cfc668
permissions -rw-r--r--
extensions: deprecate extsetup without a `ui` argument (API) 9.5 years should be enough time, but there were some tests for the old style still (which are now updated). Exthelper doesn't fallback to the old API, so this is for consistency. .. api:: The extension hook ``extsetup`` without a `ui` argument has been deprecated, and will be removed in the next version. Add a `ui` argument to avoid the deprecation warning.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
40271
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
     1
// ancestors.rs
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
     2
//
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
     3
// Copyright 2018 Georges Racinet <gracinet@anybox.fr>
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
     4
//
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
     5
// This software may be used and distributed according to the terms of the
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
     6
// GNU General Public License version 2 or any later version.
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
     7
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
     8
//! Rust versions of generic DAG ancestors algorithms for Mercurial
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
     9
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    10
use super::{Graph, GraphError, Revision, NULL_REVISION};
40959
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
    11
use std::cmp::max;
40271
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    12
use std::collections::{BinaryHeap, HashSet};
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    13
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    14
/// Iterator over the ancestors of a given list of revisions
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    15
/// This is a generic type, defined and implemented for any Graph, so that
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    16
/// it's easy to
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    17
///
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    18
/// - unit test in pure Rust
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    19
/// - bind to main Mercurial code, potentially in several ways and have these
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    20
///   bindings evolve over time
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    21
pub struct AncestorsIterator<G: Graph> {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    22
    graph: G,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    23
    visit: BinaryHeap<Revision>,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    24
    seen: HashSet<Revision>,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    25
    stoprev: Revision,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    26
}
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    27
41054
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
    28
/// Lazy ancestors set, backed by AncestorsIterator
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
    29
pub struct LazyAncestors<G: Graph + Clone> {
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
    30
    graph: G,
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
    31
    containsiter: AncestorsIterator<G>,
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
    32
    initrevs: Vec<Revision>,
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
    33
    stoprev: Revision,
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
    34
    inclusive: bool,
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
    35
}
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
    36
40959
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
    37
pub struct MissingAncestors<G: Graph> {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
    38
    graph: G,
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
    39
    bases: HashSet<Revision>,
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
    40
}
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
    41
40271
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    42
impl<G: Graph> AncestorsIterator<G> {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    43
    /// Constructor.
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    44
    ///
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    45
    /// if `inclusive` is true, then the init revisions are emitted in
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    46
    /// particular, otherwise iteration starts from their parents.
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    47
    pub fn new<I>(
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    48
        graph: G,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    49
        initrevs: I,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    50
        stoprev: Revision,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    51
        inclusive: bool,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    52
    ) -> Result<Self, GraphError>
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    53
    where
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    54
        I: IntoIterator<Item = Revision>,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    55
    {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    56
        let filtered_initrevs = initrevs.into_iter().filter(|&r| r >= stoprev);
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    57
        if inclusive {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    58
            let visit: BinaryHeap<Revision> = filtered_initrevs.collect();
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    59
            let seen = visit.iter().map(|&x| x).collect();
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    60
            return Ok(AncestorsIterator {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    61
                visit: visit,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    62
                seen: seen,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    63
                stoprev: stoprev,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    64
                graph: graph,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    65
            });
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    66
        }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    67
        let mut this = AncestorsIterator {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    68
            visit: BinaryHeap::new(),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    69
            seen: HashSet::new(),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    70
            stoprev: stoprev,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    71
            graph: graph,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    72
        };
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    73
        this.seen.insert(NULL_REVISION);
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    74
        for rev in filtered_initrevs {
40933
18513d6ef7d4 rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents: 40932
diff changeset
    75
            for parent in this.graph.parents(rev)?.iter().cloned() {
18513d6ef7d4 rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents: 40932
diff changeset
    76
                this.conditionally_push_rev(parent);
18513d6ef7d4 rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents: 40932
diff changeset
    77
            }
40271
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    78
        }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    79
        Ok(this)
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    80
    }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    81
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    82
    #[inline]
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    83
    fn conditionally_push_rev(&mut self, rev: Revision) {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    84
        if self.stoprev <= rev && !self.seen.contains(&rev) {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    85
            self.seen.insert(rev);
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    86
            self.visit.push(rev);
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    87
        }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    88
    }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    89
40300
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
    90
    /// Consumes partially the iterator to tell if the given target
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
    91
    /// revision
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
    92
    /// is in the ancestors it emits.
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
    93
    /// This is meant for iterators actually dedicated to that kind of
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
    94
    /// purpose
40863
443eb4bc41af rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents: 40832
diff changeset
    95
    pub fn contains(&mut self, target: Revision) -> Result<bool, GraphError> {
40300
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
    96
        if self.seen.contains(&target) && target != NULL_REVISION {
40863
443eb4bc41af rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents: 40832
diff changeset
    97
            return Ok(true);
40300
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
    98
        }
40863
443eb4bc41af rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents: 40832
diff changeset
    99
        for item in self {
443eb4bc41af rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents: 40832
diff changeset
   100
            let rev = item?;
40300
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
   101
            if rev == target {
40863
443eb4bc41af rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents: 40832
diff changeset
   102
                return Ok(true);
40300
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
   103
            }
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
   104
            if rev < target {
40863
443eb4bc41af rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents: 40832
diff changeset
   105
                return Ok(false);
40300
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
   106
            }
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
   107
        }
40863
443eb4bc41af rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents: 40832
diff changeset
   108
        Ok(false)
40300
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
   109
    }
41054
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   110
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   111
    pub fn peek(&self) -> Option<Revision> {
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   112
        self.visit.peek().map(|&r| r)
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   113
    }
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   114
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   115
    /// Tell if the iterator is about an empty set
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   116
    ///
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   117
    /// The result does not depend whether the iterator has been consumed
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   118
    /// or not.
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   119
    /// This is mostly meant for iterators backing a lazy ancestors set
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   120
    pub fn is_empty(&self) -> bool {
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   121
        if self.visit.len() > 0 {
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   122
            return false;
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   123
        }
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   124
        if self.seen.len() > 1 {
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   125
            return false;
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   126
        }
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   127
        // at this point, the seen set is at most a singleton.
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   128
        // If not `self.inclusive`, it's still possible that it has only
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   129
        // the null revision
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   130
        self.seen.is_empty() || self.seen.contains(&NULL_REVISION)
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   131
    }
40271
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   132
}
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   133
41054
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   134
/// Main implementation for the iterator
40271
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   135
///
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   136
/// The algorithm is the same as in `_lazyancestorsiter()` from `ancestors.py`
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   137
/// with a few non crucial differences:
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   138
///
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   139
/// - there's no filtering of invalid parent revisions. Actually, it should be
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   140
///   consistent and more efficient to filter them from the end caller.
40932
dc38d976ff4d rust: improved docstring
Georges Racinet <gracinet@anybox.fr>
parents: 40929
diff changeset
   141
/// - we don't have the optimization for adjacent revisions (i.e., the case
dc38d976ff4d rust: improved docstring
Georges Racinet <gracinet@anybox.fr>
parents: 40929
diff changeset
   142
///   where `p1 == rev - 1`), because it amounts to update the first element of
dc38d976ff4d rust: improved docstring
Georges Racinet <gracinet@anybox.fr>
parents: 40929
diff changeset
   143
///   the heap without sifting, which Rust's BinaryHeap doesn't let us do.
40271
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   144
/// - we save a few pushes by comparing with `stoprev` before pushing
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   145
impl<G: Graph> Iterator for AncestorsIterator<G> {
40863
443eb4bc41af rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents: 40832
diff changeset
   146
    type Item = Result<Revision, GraphError>;
40271
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   147
40863
443eb4bc41af rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents: 40832
diff changeset
   148
    fn next(&mut self) -> Option<Self::Item> {
40811
e13ab4acf555 rust: peek_mut optim for lazy ancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40300
diff changeset
   149
        let current = match self.visit.peek() {
40271
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   150
            None => {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   151
                return None;
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   152
            }
40811
e13ab4acf555 rust: peek_mut optim for lazy ancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40300
diff changeset
   153
            Some(c) => *c,
40271
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   154
        };
40933
18513d6ef7d4 rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents: 40932
diff changeset
   155
        let [p1, p2] = match self.graph.parents(current) {
40863
443eb4bc41af rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents: 40832
diff changeset
   156
            Ok(ps) => ps,
443eb4bc41af rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents: 40832
diff changeset
   157
            Err(e) => return Some(Err(e)),
443eb4bc41af rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents: 40832
diff changeset
   158
        };
40811
e13ab4acf555 rust: peek_mut optim for lazy ancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40300
diff changeset
   159
        if p1 < self.stoprev || self.seen.contains(&p1) {
e13ab4acf555 rust: peek_mut optim for lazy ancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40300
diff changeset
   160
            self.visit.pop();
e13ab4acf555 rust: peek_mut optim for lazy ancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40300
diff changeset
   161
        } else {
e13ab4acf555 rust: peek_mut optim for lazy ancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40300
diff changeset
   162
            *(self.visit.peek_mut().unwrap()) = p1;
e13ab4acf555 rust: peek_mut optim for lazy ancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40300
diff changeset
   163
            self.seen.insert(p1);
e13ab4acf555 rust: peek_mut optim for lazy ancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40300
diff changeset
   164
        };
e13ab4acf555 rust: peek_mut optim for lazy ancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40300
diff changeset
   165
40832
70976974c14a rust: rename local variables in AncestorsIterator::next
Georges Racinet <georges@racinet.fr>
parents: 40811
diff changeset
   166
        self.conditionally_push_rev(p2);
40863
443eb4bc41af rust: propagate error of index_get_parents() properly
Yuya Nishihara <yuya@tcha.org>
parents: 40832
diff changeset
   167
        Some(Ok(current))
40271
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   168
    }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   169
}
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   170
41054
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   171
impl<G: Graph + Clone> LazyAncestors<G> {
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   172
    pub fn new(
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   173
        graph: G,
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   174
        initrevs: impl IntoIterator<Item = Revision>,
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   175
        stoprev: Revision,
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   176
        inclusive: bool,
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   177
    ) -> Result<Self, GraphError> {
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   178
        let v: Vec<Revision> = initrevs.into_iter().collect();
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   179
        Ok(LazyAncestors {
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   180
            graph: graph.clone(),
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   181
            containsiter: AncestorsIterator::new(
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   182
                graph,
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   183
                v.iter().cloned(),
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   184
                stoprev,
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   185
                inclusive,
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   186
            )?,
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   187
            initrevs: v,
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   188
            stoprev: stoprev,
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   189
            inclusive: inclusive,
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   190
        })
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   191
    }
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   192
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   193
    pub fn contains(&mut self, rev: Revision) -> Result<bool, GraphError> {
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   194
        self.containsiter.contains(rev)
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   195
    }
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   196
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   197
    pub fn is_empty(&self) -> bool {
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   198
        self.containsiter.is_empty()
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   199
    }
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   200
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   201
    pub fn iter(&self) -> AncestorsIterator<G> {
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   202
        // the arguments being the same as for self.containsiter, we know
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   203
        // for sure that AncestorsIterator constructor can't fail
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   204
        AncestorsIterator::new(
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   205
            self.graph.clone(),
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   206
            self.initrevs.iter().cloned(),
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   207
            self.stoprev,
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   208
            self.inclusive,
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   209
        )
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   210
        .unwrap()
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   211
    }
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   212
}
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   213
40959
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   214
impl<G: Graph> MissingAncestors<G> {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   215
    pub fn new(graph: G, bases: impl IntoIterator<Item = Revision>) -> Self {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   216
        let mut bases: HashSet<Revision> = bases.into_iter().collect();
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   217
        if bases.is_empty() {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   218
            bases.insert(NULL_REVISION);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   219
        }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   220
        MissingAncestors { graph, bases }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   221
    }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   222
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   223
    pub fn has_bases(&self) -> bool {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   224
        self.bases.iter().any(|&b| b != NULL_REVISION)
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   225
    }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   226
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   227
    /// Return a reference to current bases.
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   228
    ///
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   229
    /// This is useful in unit tests, but also setdiscovery.py does
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   230
    /// read the bases attribute of a ancestor.missingancestors instance.
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   231
    pub fn get_bases<'a>(&'a self) -> &'a HashSet<Revision> {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   232
        &self.bases
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   233
    }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   234
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   235
    pub fn add_bases(
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   236
        &mut self,
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   237
        new_bases: impl IntoIterator<Item = Revision>,
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   238
    ) {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   239
        self.bases.extend(new_bases);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   240
    }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   241
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   242
    /// Remove all ancestors of self.bases from the revs set (in place)
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   243
    pub fn remove_ancestors_from(
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   244
        &mut self,
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   245
        revs: &mut HashSet<Revision>,
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   246
    ) -> Result<(), GraphError> {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   247
        revs.retain(|r| !self.bases.contains(r));
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   248
        // the null revision is always an ancestor
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   249
        revs.remove(&NULL_REVISION);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   250
        if revs.is_empty() {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   251
            return Ok(());
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   252
        }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   253
        // anything in revs > start is definitely not an ancestor of bases
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   254
        // revs <= start need to be investigated
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   255
        // TODO optim: if a missingancestors is to be used several times,
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   256
        // we shouldn't need to iterate each time on bases
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   257
        let start = match self.bases.iter().cloned().max() {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   258
            Some(m) => m,
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   259
            None => {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   260
                // bases is empty (shouldn't happen, but let's be safe)
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   261
                return Ok(());
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   262
            }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   263
        };
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   264
        // whatever happens, we'll keep at least keepcount of them
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   265
        // knowing this gives us a earlier stop condition than
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   266
        // going all the way to the root
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   267
        let keepcount = revs.iter().filter(|r| **r > start).count();
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   268
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   269
        let mut curr = start;
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   270
        while curr != NULL_REVISION && revs.len() > keepcount {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   271
            if self.bases.contains(&curr) {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   272
                revs.remove(&curr);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   273
                self.add_parents(curr)?;
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   274
            }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   275
            curr -= 1;
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   276
        }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   277
        Ok(())
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   278
    }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   279
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   280
    /// Add rev's parents to self.bases
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   281
    #[inline]
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   282
    fn add_parents(&mut self, rev: Revision) -> Result<(), GraphError> {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   283
        // No need to bother the set with inserting NULL_REVISION over and
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   284
        // over
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   285
        for p in self.graph.parents(rev)?.iter().cloned() {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   286
            if p != NULL_REVISION {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   287
                self.bases.insert(p);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   288
            }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   289
        }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   290
        Ok(())
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   291
    }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   292
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   293
    /// Return all the ancestors of revs that are not ancestors of self.bases
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   294
    ///
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   295
    /// This may include elements from revs.
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   296
    ///
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   297
    /// Equivalent to the revset (::revs - ::self.bases). Revs are returned in
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   298
    /// revision number order, which is a topological order.
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   299
    pub fn missing_ancestors(
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   300
        &mut self,
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   301
        revs: impl IntoIterator<Item = Revision>,
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   302
    ) -> Result<Vec<Revision>, GraphError> {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   303
        // just for convenience and comparison with Python version
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   304
        let bases_visit = &mut self.bases;
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   305
        let mut revs: HashSet<Revision> = revs
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   306
            .into_iter()
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   307
            .filter(|r| !bases_visit.contains(r))
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   308
            .collect();
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   309
        let revs_visit = &mut revs;
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   310
        let mut both_visit: HashSet<Revision> =
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   311
            revs_visit.intersection(&bases_visit).cloned().collect();
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   312
        if revs_visit.is_empty() {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   313
            return Ok(Vec::new());
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   314
        }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   315
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   316
        let max_bases =
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   317
            bases_visit.iter().cloned().max().unwrap_or(NULL_REVISION);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   318
        let max_revs =
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   319
            revs_visit.iter().cloned().max().unwrap_or(NULL_REVISION);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   320
        let start = max(max_bases, max_revs);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   321
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   322
        // TODO heuristics for with_capacity()?
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   323
        let mut missing: Vec<Revision> = Vec::new();
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   324
        for curr in (0..=start).map(|i| start - i) {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   325
            if revs_visit.is_empty() {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   326
                break;
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   327
            }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   328
            if both_visit.contains(&curr) {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   329
                // curr's parents might have made it into revs_visit through
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   330
                // another path
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   331
                // TODO optim: Rust's HashSet.remove returns a boolean telling
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   332
                // if it happened. This will spare us one set lookup
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   333
                both_visit.remove(&curr);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   334
                for p in self.graph.parents(curr)?.iter().cloned() {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   335
                    if p == NULL_REVISION {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   336
                        continue;
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   337
                    }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   338
                    revs_visit.remove(&p);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   339
                    bases_visit.insert(p);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   340
                    both_visit.insert(p);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   341
                }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   342
                continue;
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   343
            }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   344
            // in Rust, one can't just use mutable variables assignation
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   345
            // to be more straightforward. Instead of Python's
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   346
            // thisvisit and othervisit, we'll differentiate with a boolean
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   347
            let this_visit_is_revs = {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   348
                if revs_visit.remove(&curr) {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   349
                    missing.push(curr);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   350
                    true
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   351
                } else if bases_visit.contains(&curr) {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   352
                    false
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   353
                } else {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   354
                    // not an ancestor of revs or bases: ignore
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   355
                    continue;
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   356
                }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   357
            };
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   358
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   359
            for p in self.graph.parents(curr)?.iter().cloned() {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   360
                if p == NULL_REVISION {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   361
                    continue;
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   362
                }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   363
                let in_other_visit = if this_visit_is_revs {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   364
                    bases_visit.contains(&p)
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   365
                } else {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   366
                    revs_visit.contains(&p)
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   367
                };
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   368
                if in_other_visit || both_visit.contains(&p) {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   369
                    // p is implicitely in this_visit.
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   370
                    // This means p is or should be in bothvisit
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   371
                    // TODO optim: hence if bothvisit, we look up twice
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   372
                    revs_visit.remove(&p);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   373
                    bases_visit.insert(p);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   374
                    both_visit.insert(p);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   375
                } else {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   376
                    // visit later
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   377
                    if this_visit_is_revs {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   378
                        revs_visit.insert(p);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   379
                    } else {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   380
                        bases_visit.insert(p);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   381
                    }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   382
                }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   383
            }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   384
        }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   385
        missing.reverse();
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   386
        Ok(missing)
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   387
    }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   388
}
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   389
40271
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   390
#[cfg(test)]
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   391
mod tests {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   392
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   393
    use super::*;
40959
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   394
    use std::iter::FromIterator;
40271
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   395
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   396
    #[derive(Clone, Debug)]
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   397
    struct Stub;
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   398
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   399
    /// This is the same as the dict from test-ancestors.py
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   400
    impl Graph for Stub {
40933
18513d6ef7d4 rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents: 40932
diff changeset
   401
        fn parents(&self, rev: Revision) -> Result<[Revision; 2], GraphError> {
40271
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   402
            match rev {
40933
18513d6ef7d4 rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents: 40932
diff changeset
   403
                0 => Ok([-1, -1]),
18513d6ef7d4 rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents: 40932
diff changeset
   404
                1 => Ok([0, -1]),
18513d6ef7d4 rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents: 40932
diff changeset
   405
                2 => Ok([1, -1]),
18513d6ef7d4 rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents: 40932
diff changeset
   406
                3 => Ok([1, -1]),
18513d6ef7d4 rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents: 40932
diff changeset
   407
                4 => Ok([2, -1]),
18513d6ef7d4 rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents: 40932
diff changeset
   408
                5 => Ok([4, -1]),
18513d6ef7d4 rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents: 40932
diff changeset
   409
                6 => Ok([4, -1]),
18513d6ef7d4 rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents: 40932
diff changeset
   410
                7 => Ok([4, -1]),
18513d6ef7d4 rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents: 40932
diff changeset
   411
                8 => Ok([-1, -1]),
18513d6ef7d4 rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents: 40932
diff changeset
   412
                9 => Ok([6, 7]),
18513d6ef7d4 rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents: 40932
diff changeset
   413
                10 => Ok([5, -1]),
18513d6ef7d4 rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents: 40932
diff changeset
   414
                11 => Ok([3, 7]),
18513d6ef7d4 rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents: 40932
diff changeset
   415
                12 => Ok([9, -1]),
18513d6ef7d4 rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents: 40932
diff changeset
   416
                13 => Ok([8, -1]),
40271
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   417
                r => Err(GraphError::ParentOutOfRange(r)),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   418
            }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   419
        }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   420
    }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   421
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   422
    fn list_ancestors<G: Graph>(
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   423
        graph: G,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   424
        initrevs: Vec<Revision>,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   425
        stoprev: Revision,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   426
        inclusive: bool,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   427
    ) -> Vec<Revision> {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   428
        AncestorsIterator::new(graph, initrevs, stoprev, inclusive)
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   429
            .unwrap()
40929
43ca24b772d6 rust: adapted hg-core tests for iteration over Result
Georges Racinet <gracinet@anybox.fr>
parents: 40927
diff changeset
   430
            .map(|res| res.unwrap())
40271
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   431
            .collect()
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   432
    }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   433
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   434
    #[test]
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   435
    /// Same tests as test-ancestor.py, without membership
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   436
    /// (see also test-ancestor.py.out)
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   437
    fn test_list_ancestor() {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   438
        assert_eq!(list_ancestors(Stub, vec![], 0, false), vec![]);
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   439
        assert_eq!(
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   440
            list_ancestors(Stub, vec![11, 13], 0, false),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   441
            vec![8, 7, 4, 3, 2, 1, 0]
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   442
        );
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   443
        assert_eq!(list_ancestors(Stub, vec![1, 3], 0, false), vec![1, 0]);
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   444
        assert_eq!(
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   445
            list_ancestors(Stub, vec![11, 13], 0, true),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   446
            vec![13, 11, 8, 7, 4, 3, 2, 1, 0]
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   447
        );
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   448
        assert_eq!(list_ancestors(Stub, vec![11, 13], 6, false), vec![8, 7]);
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   449
        assert_eq!(
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   450
            list_ancestors(Stub, vec![11, 13], 6, true),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   451
            vec![13, 11, 8, 7]
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   452
        );
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   453
        assert_eq!(list_ancestors(Stub, vec![11, 13], 11, true), vec![13, 11]);
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   454
        assert_eq!(list_ancestors(Stub, vec![11, 13], 12, true), vec![13]);
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   455
        assert_eq!(
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   456
            list_ancestors(Stub, vec![10, 1], 0, true),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   457
            vec![10, 5, 4, 2, 1, 0]
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   458
        );
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   459
    }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   460
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   461
    #[test]
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   462
    /// Corner case that's not directly in test-ancestors.py, but
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   463
    /// that happens quite often, as demonstrated by running the whole
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   464
    /// suite.
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   465
    /// For instance, run tests/test-obsolete-checkheads.t
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   466
    fn test_nullrev_input() {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   467
        let mut iter =
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   468
            AncestorsIterator::new(Stub, vec![-1], 0, false).unwrap();
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   469
        assert_eq!(iter.next(), None)
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   470
    }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   471
40300
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
   472
    #[test]
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
   473
    fn test_contains() {
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
   474
        let mut lazy =
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
   475
            AncestorsIterator::new(Stub, vec![10, 1], 0, true).unwrap();
40929
43ca24b772d6 rust: adapted hg-core tests for iteration over Result
Georges Racinet <gracinet@anybox.fr>
parents: 40927
diff changeset
   476
        assert!(lazy.contains(1).unwrap());
43ca24b772d6 rust: adapted hg-core tests for iteration over Result
Georges Racinet <gracinet@anybox.fr>
parents: 40927
diff changeset
   477
        assert!(!lazy.contains(3).unwrap());
40300
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
   478
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
   479
        let mut lazy =
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
   480
            AncestorsIterator::new(Stub, vec![0], 0, false).unwrap();
40929
43ca24b772d6 rust: adapted hg-core tests for iteration over Result
Georges Racinet <gracinet@anybox.fr>
parents: 40927
diff changeset
   481
        assert!(!lazy.contains(NULL_REVISION).unwrap());
40300
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
   482
    }
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
   483
41054
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   484
    #[test]
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   485
    fn test_peek() {
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   486
        let mut iter =
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   487
            AncestorsIterator::new(Stub, vec![10], 0, true).unwrap();
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   488
        // peek() gives us the next value
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   489
        assert_eq!(iter.peek(), Some(10));
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   490
        // but it's not been consumed
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   491
        assert_eq!(iter.next(), Some(Ok(10)));
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   492
        // and iteration resumes normally
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   493
        assert_eq!(iter.next(), Some(Ok(5)));
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   494
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   495
        // let's drain the iterator to test peek() at the end
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   496
        while iter.next().is_some() {}
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   497
        assert_eq!(iter.peek(), None);
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   498
    }
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   499
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   500
    #[test]
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   501
    fn test_empty() {
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   502
        let mut iter =
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   503
            AncestorsIterator::new(Stub, vec![10], 0, true).unwrap();
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   504
        assert!(!iter.is_empty());
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   505
        while iter.next().is_some() {}
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   506
        assert!(!iter.is_empty());
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   507
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   508
        let iter = AncestorsIterator::new(Stub, vec![], 0, true).unwrap();
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   509
        assert!(iter.is_empty());
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   510
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   511
        // case where iter.seen == {NULL_REVISION}
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   512
        let iter = AncestorsIterator::new(Stub, vec![0], 0, false).unwrap();
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   513
        assert!(iter.is_empty());
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   514
    }
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   515
40271
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   516
    /// A corrupted Graph, supporting error handling tests
41054
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   517
    #[derive(Clone, Debug)]
40271
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   518
    struct Corrupted;
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   519
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   520
    impl Graph for Corrupted {
40933
18513d6ef7d4 rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents: 40932
diff changeset
   521
        fn parents(&self, rev: Revision) -> Result<[Revision; 2], GraphError> {
40271
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   522
            match rev {
40933
18513d6ef7d4 rust: changed Graph.parents to return [Revision; 2]
Georges Racinet <gracinet@anybox.fr>
parents: 40932
diff changeset
   523
                1 => Ok([0, -1]),
40271
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   524
                r => Err(GraphError::ParentOutOfRange(r)),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   525
            }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   526
        }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   527
    }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   528
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   529
    #[test]
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   530
    fn test_initrev_out_of_range() {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   531
        // inclusive=false looks up initrev's parents right away
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   532
        match AncestorsIterator::new(Stub, vec![25], 0, false) {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   533
            Ok(_) => panic!("Should have been ParentOutOfRange"),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   534
            Err(e) => assert_eq!(e, GraphError::ParentOutOfRange(25)),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   535
        }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   536
    }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   537
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   538
    #[test]
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   539
    fn test_next_out_of_range() {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   540
        // inclusive=false looks up initrev's parents right away
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   541
        let mut iter =
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   542
            AncestorsIterator::new(Corrupted, vec![1], 0, false).unwrap();
40929
43ca24b772d6 rust: adapted hg-core tests for iteration over Result
Georges Racinet <gracinet@anybox.fr>
parents: 40927
diff changeset
   543
        assert_eq!(iter.next(), Some(Err(GraphError::ParentOutOfRange(0))));
40271
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   544
    }
40959
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   545
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   546
    #[test]
41054
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   547
    fn test_lazy_iter_contains() {
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   548
        let mut lazy =
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   549
            LazyAncestors::new(Stub, vec![11, 13], 0, false).unwrap();
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   550
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   551
        let revs: Vec<Revision> = lazy.iter().map(|r| r.unwrap()).collect();
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   552
        // compare with iterator tests on the same initial revisions
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   553
        assert_eq!(revs, vec![8, 7, 4, 3, 2, 1, 0]);
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   554
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   555
        // contains() results are correct, unaffected by the fact that
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   556
        // we consumed entirely an iterator out of lazy
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   557
        assert_eq!(lazy.contains(2), Ok(true));
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   558
        assert_eq!(lazy.contains(9), Ok(false));
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   559
    }
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   560
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   561
    #[test]
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   562
    fn test_lazy_contains_iter() {
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   563
        let mut lazy =
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   564
            LazyAncestors::new(Stub, vec![11, 13], 0, false).unwrap(); // reminder: [8, 7, 4, 3, 2, 1, 0]
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   565
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   566
        assert_eq!(lazy.contains(2), Ok(true));
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   567
        assert_eq!(lazy.contains(6), Ok(false));
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   568
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   569
        // after consumption of 2 by the inner iterator, results stay
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   570
        // consistent
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   571
        assert_eq!(lazy.contains(2), Ok(true));
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   572
        assert_eq!(lazy.contains(5), Ok(false));
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   573
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   574
        // iter() still gives us a fresh iterator
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   575
        let revs: Vec<Revision> = lazy.iter().map(|r| r.unwrap()).collect();
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   576
        assert_eq!(revs, vec![8, 7, 4, 3, 2, 1, 0]);
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   577
    }
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   578
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40959
diff changeset
   579
    #[test]
40959
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   580
    /// Test constructor, add/get bases
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   581
    fn test_missing_bases() {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   582
        let mut missing_ancestors =
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   583
            MissingAncestors::new(Stub, [5, 3, 1, 3].iter().cloned());
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   584
        let mut as_vec: Vec<Revision> =
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   585
            missing_ancestors.get_bases().iter().cloned().collect();
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   586
        as_vec.sort();
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   587
        assert_eq!(as_vec, [1, 3, 5]);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   588
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   589
        missing_ancestors.add_bases([3, 7, 8].iter().cloned());
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   590
        as_vec = missing_ancestors.get_bases().iter().cloned().collect();
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   591
        as_vec.sort();
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   592
        assert_eq!(as_vec, [1, 3, 5, 7, 8]);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   593
    }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   594
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   595
    fn assert_missing_remove(
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   596
        bases: &[Revision],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   597
        revs: &[Revision],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   598
        expected: &[Revision],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   599
    ) {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   600
        let mut missing_ancestors =
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   601
            MissingAncestors::new(Stub, bases.iter().cloned());
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   602
        let mut revset: HashSet<Revision> = revs.iter().cloned().collect();
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   603
        missing_ancestors
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   604
            .remove_ancestors_from(&mut revset)
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   605
            .unwrap();
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   606
        let mut as_vec: Vec<Revision> = revset.into_iter().collect();
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   607
        as_vec.sort();
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   608
        assert_eq!(as_vec.as_slice(), expected);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   609
    }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   610
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   611
    #[test]
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   612
    fn test_missing_remove() {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   613
        assert_missing_remove(
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   614
            &[1, 2, 3, 4, 7],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   615
            Vec::from_iter(1..10).as_slice(),
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   616
            &[5, 6, 8, 9],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   617
        );
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   618
        assert_missing_remove(&[10], &[11, 12, 13, 14], &[11, 12, 13, 14]);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   619
        assert_missing_remove(&[7], &[1, 2, 3, 4, 5], &[3, 5]);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   620
    }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   621
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   622
    fn assert_missing_ancestors(
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   623
        bases: &[Revision],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   624
        revs: &[Revision],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   625
        expected: &[Revision],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   626
    ) {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   627
        let mut missing_ancestors =
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   628
            MissingAncestors::new(Stub, bases.iter().cloned());
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   629
        let missing = missing_ancestors
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   630
            .missing_ancestors(revs.iter().cloned())
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   631
            .unwrap();
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   632
        assert_eq!(missing.as_slice(), expected);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   633
    }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   634
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   635
    #[test]
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   636
    fn test_missing_ancestors() {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   637
        // examples taken from test-ancestors.py by having it run
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   638
        // on the same graph (both naive and fast Python algs)
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   639
        assert_missing_ancestors(&[10], &[11], &[3, 7, 11]);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   640
        assert_missing_ancestors(&[11], &[10], &[5, 10]);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   641
        assert_missing_ancestors(&[7], &[9, 11], &[3, 6, 9, 11]);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   642
    }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   643
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   644
    // A Graph represented by a vector whose indices are revisions
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   645
    // and values are parents of the revisions
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   646
    type VecGraph = Vec<[Revision; 2]>;
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   647
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   648
    impl Graph for VecGraph {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   649
        fn parents(&self, rev: Revision) -> Result<[Revision; 2], GraphError> {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   650
            Ok(self[rev as usize])
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   651
        }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   652
    }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   653
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   654
    /// An interesting case found by a random generator similar to
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   655
    /// the one in test-ancestor.py. An early version of Rust MissingAncestors
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   656
    /// failed this, yet none of the integration tests of the whole suite
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   657
    /// catched it.
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   658
    #[test]
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   659
    fn test_remove_ancestors_from_case1() {
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   660
        let graph: VecGraph = vec![
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   661
            [NULL_REVISION, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   662
            [0, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   663
            [1, 0],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   664
            [2, 1],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   665
            [3, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   666
            [4, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   667
            [5, 1],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   668
            [2, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   669
            [7, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   670
            [8, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   671
            [9, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   672
            [10, 1],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   673
            [3, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   674
            [12, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   675
            [13, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   676
            [14, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   677
            [4, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   678
            [16, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   679
            [17, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   680
            [18, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   681
            [19, 11],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   682
            [20, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   683
            [21, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   684
            [22, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   685
            [23, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   686
            [2, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   687
            [3, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   688
            [26, 24],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   689
            [27, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   690
            [28, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   691
            [12, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   692
            [1, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   693
            [1, 9],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   694
            [32, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   695
            [33, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   696
            [34, 31],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   697
            [35, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   698
            [36, 26],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   699
            [37, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   700
            [38, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   701
            [39, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   702
            [40, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   703
            [41, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   704
            [42, 26],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   705
            [0, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   706
            [44, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   707
            [45, 4],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   708
            [40, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   709
            [47, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   710
            [36, 0],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   711
            [49, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   712
            [NULL_REVISION, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   713
            [51, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   714
            [52, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   715
            [53, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   716
            [14, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   717
            [55, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   718
            [15, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   719
            [23, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   720
            [58, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   721
            [59, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   722
            [2, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   723
            [61, 59],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   724
            [62, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   725
            [63, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   726
            [NULL_REVISION, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   727
            [65, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   728
            [66, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   729
            [67, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   730
            [68, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   731
            [37, 28],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   732
            [69, 25],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   733
            [71, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   734
            [72, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   735
            [50, 2],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   736
            [74, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   737
            [12, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   738
            [18, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   739
            [77, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   740
            [78, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   741
            [79, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   742
            [43, 33],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   743
            [81, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   744
            [82, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   745
            [83, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   746
            [84, 45],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   747
            [85, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   748
            [86, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   749
            [NULL_REVISION, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   750
            [88, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   751
            [NULL_REVISION, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   752
            [76, 83],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   753
            [44, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   754
            [92, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   755
            [93, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   756
            [9, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   757
            [95, 67],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   758
            [96, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   759
            [97, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   760
            [NULL_REVISION, NULL_REVISION],
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   761
        ];
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   762
        let problem_rev = 28 as Revision;
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   763
        let problem_base = 70 as Revision;
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   764
        // making the problem obvious: problem_rev is a parent of problem_base
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   765
        assert_eq!(graph.parents(problem_base).unwrap()[1], problem_rev);
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   766
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   767
        let mut missing_ancestors: MissingAncestors<VecGraph> =
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   768
            MissingAncestors::new(
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   769
                graph,
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   770
                [60, 26, 70, 3, 96, 19, 98, 49, 97, 47, 1, 6]
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   771
                    .iter()
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   772
                    .cloned(),
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   773
            );
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   774
        assert!(missing_ancestors.bases.contains(&problem_base));
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   775
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   776
        let mut revs: HashSet<Revision> =
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   777
            [4, 12, 41, 28, 68, 38, 1, 30, 56, 44]
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   778
                .iter()
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   779
                .cloned()
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   780
                .collect();
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   781
        missing_ancestors.remove_ancestors_from(&mut revs).unwrap();
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   782
        assert!(!revs.contains(&problem_rev));
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   783
    }
d097dd0afc19 rust: translation of missingancestors
Georges Racinet <gracinet@anybox.fr>
parents: 40933
diff changeset
   784
40271
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   785
}