rust/hg-core/src/dirstate/dirstate_tree/iter.rs
author Raphaël Gomès <rgomes@octobus.net>
Fri, 25 Sep 2020 17:51:34 +0200
changeset 45562 b51167d70f5a
child 45588 c35db907363d
permissions -rw-r--r--
rust: add `dirstate_tree` module Mercurial needs to represent the filesystem hierarchy on which it operates, for example in the dirstate. Its current on-disk representation is an unsorted, flat structure that gets transformed in the current Rust code into a `HashMap`. This loses the hierarchical information of the dirstate, leading to some unfortunate performance and algorithmic compromises. This module adds an implementation of a radix tree that is specialized for representing the dirstate: its unit is the path component. I have made no efforts to optimize either its memory footprint or its insertion speed: they're pretty bad for now. Following will be a few patches that modify the dirstate.status logic to use that new hierarchical information, fixing issue 6335 in the same swing. Differential Revision: https://phab.mercurial-scm.org/D9085
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
45562
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     1
// iter.rs
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     2
//
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     3
// Copyright 2020, Raphaël Gomès <rgomes@octobus.net>
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     4
//
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     5
// This software may be used and distributed according to the terms of the
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     6
// GNU General Public License version 2 or any later version.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     7
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     8
use super::node::{Node, NodeKind};
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     9
use super::tree::Tree;
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    10
use crate::dirstate::dirstate_tree::node::Directory;
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    11
use crate::dirstate::status::Dispatch;
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    12
use crate::utils::hg_path::{hg_path_to_path_buf, HgPath, HgPathBuf};
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    13
use crate::DirstateEntry;
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    14
use std::borrow::Cow;
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    15
use std::collections::VecDeque;
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    16
use std::iter::{FromIterator, FusedIterator};
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    17
use std::path::PathBuf;
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    18
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    19
impl FromIterator<(HgPathBuf, DirstateEntry)> for Tree {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    20
    fn from_iter<T: IntoIterator<Item = (HgPathBuf, DirstateEntry)>>(iter: T) -> Self {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    21
        let mut tree = Self::new();
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    22
        for (path, entry) in iter {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    23
            tree.insert(path, entry);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    24
        }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    25
        tree
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    26
    }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    27
}
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    28
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    29
/// Iterator of all entries in the dirstate tree.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    30
///
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    31
/// It has no particular ordering.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    32
pub struct Iter<'a> {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    33
    to_visit: VecDeque<(Cow<'a, [u8]>, &'a Node)>,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    34
}
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    35
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    36
impl<'a> Iter<'a> {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    37
    pub fn new(node: &'a Node) -> Iter<'a> {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    38
        let mut to_visit = VecDeque::new();
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    39
        to_visit.push_back((Cow::Borrowed(&b""[..]), node));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    40
        Self { to_visit }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    41
    }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    42
}
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    43
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    44
impl<'a> Iterator for Iter<'a> {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    45
    type Item = (HgPathBuf, DirstateEntry);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    46
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    47
    fn next(&mut self) -> Option<Self::Item> {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    48
        while let Some((base_path, node)) = self.to_visit.pop_front() {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    49
            match &node.kind {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    50
                NodeKind::Directory(dir) => {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    51
                    add_children_to_visit(&mut self.to_visit, &base_path, &dir);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    52
                    if let Some(file) = &dir.was_file {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    53
                        return Some((HgPathBuf::from_bytes(&base_path), file.entry));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    54
                    }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    55
                }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    56
                NodeKind::File(file) => {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    57
                    if let Some(dir) = &file.was_directory {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    58
                        add_children_to_visit(&mut self.to_visit, &base_path, &dir);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    59
                    }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    60
                    return Some((HgPathBuf::from_bytes(&base_path), file.entry));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    61
                }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    62
            }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    63
        }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    64
        None
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    65
    }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    66
}
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    67
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    68
impl<'a> FusedIterator for Iter<'a> {}
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    69
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    70
/// Iterator of all entries in the dirstate tree, with a special filesystem
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    71
/// handling for the directories containing said entries.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    72
///
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    73
/// It checks every directory on-disk to see if it has become a symlink, to
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    74
/// prevent a potential security issue.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    75
/// Using this information, it may dispatch `status` information early: it
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    76
/// returns canonical paths along with `Shortcut`s, which are either a
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    77
/// `DirstateEntry` or a `Dispatch`, if the fate of said path has already been
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    78
/// determined.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    79
///
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    80
/// Like `Iter`, it has no particular ordering.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    81
pub struct FsIter<'a> {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    82
    root_dir: PathBuf,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    83
    to_visit: VecDeque<(Cow<'a, [u8]>, &'a Node)>,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    84
    shortcuts: VecDeque<(HgPathBuf, StatusShortcut)>,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    85
}
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    86
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    87
impl<'a> FsIter<'a> {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    88
    pub fn new(node: &'a Node, root_dir: PathBuf) -> FsIter<'a> {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    89
        let mut to_visit = VecDeque::new();
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    90
        to_visit.push_back((Cow::Borrowed(&b""[..]), node));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    91
        Self {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    92
            root_dir,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    93
            to_visit,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    94
            shortcuts: Default::default(),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    95
        }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    96
    }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    97
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    98
    /// Mercurial tracks symlinks but *not* what they point to.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    99
    /// If a directory is moved and symlinked:
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   100
    ///
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   101
    /// ```bash
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   102
    /// $ mkdir foo
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   103
    /// $ touch foo/a
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   104
    /// $ # commit...
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   105
    /// $ mv foo bar
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   106
    /// $ ln -s bar foo
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   107
    /// ```
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   108
    /// We need to dispatch the new symlink as `Unknown` and all the
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   109
    /// descendents of the directory it replace as `Deleted`.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   110
    fn dispatch_symlinked_directory(&mut self, path: impl AsRef<HgPath>, node: &Node) {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   111
        let path = path.as_ref();
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   112
        self.shortcuts
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   113
            .push_back((path.to_owned(), StatusShortcut::Dispatch(Dispatch::Unknown)));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   114
        for (file, _) in node.iter() {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   115
            self.shortcuts.push_back((
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   116
                path.join(&file),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   117
                StatusShortcut::Dispatch(Dispatch::Deleted),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   118
            ));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   119
        }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   120
    }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   121
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   122
    /// Returns `true` if the canonical `path` of a directory corresponds to a
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   123
    /// symlink on disk. It means it was moved and symlinked after the last
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   124
    /// dirstate update.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   125
    ///
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   126
    /// # Special cases
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   127
    ///
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   128
    /// Returns `false` for the repository root.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   129
    /// Returns `false` on io error, error handling is outside of the iterator.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   130
    fn directory_became_symlink(&mut self, path: &HgPath) -> bool {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   131
        if path.is_empty() {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   132
            return false;
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   133
        }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   134
        let filename_as_path = match hg_path_to_path_buf(&path) {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   135
            Ok(p) => p,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   136
            _ => return false,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   137
        };
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   138
        let meta = self.root_dir.join(filename_as_path).symlink_metadata();
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   139
        match meta {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   140
            Ok(ref m) if m.file_type().is_symlink() => true,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   141
            _ => return false,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   142
        }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   143
    }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   144
}
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   145
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   146
/// Returned by `FsIter`, since the `Dispatch` of any given entry may already
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   147
/// be determined during the iteration. This is necessary for performance
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   148
/// reasons, since hierarchical information is needed to `Dispatch` an entire
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   149
/// subtree efficiently.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   150
#[derive(Debug, Copy, Clone)]
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   151
pub enum StatusShortcut {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   152
    /// A entry in the dirstate for further inspection
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   153
    Entry(DirstateEntry),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   154
    /// The result of the status of the corresponding file
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   155
    Dispatch(Dispatch),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   156
}
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   157
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   158
impl<'a> Iterator for FsIter<'a> {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   159
    type Item = (HgPathBuf, StatusShortcut);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   160
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   161
    fn next(&mut self) -> Option<Self::Item> {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   162
        // If any paths have already been `Dispatch`-ed, return them
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   163
        while let Some(res) = self.shortcuts.pop_front() {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   164
            return Some(res);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   165
        }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   166
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   167
        while let Some((base_path, node)) = self.to_visit.pop_front() {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   168
            match &node.kind {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   169
                NodeKind::Directory(dir) => {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   170
                    let canonical_path = HgPath::new(&base_path);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   171
                    if self.directory_became_symlink(canonical_path) {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   172
                        // Potential security issue, don't do a normal
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   173
                        // traversal, force the results.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   174
                        self.dispatch_symlinked_directory(canonical_path, &node);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   175
                        continue;
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   176
                    }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   177
                    add_children_to_visit(&mut self.to_visit, &base_path, &dir);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   178
                    if let Some(file) = &dir.was_file {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   179
                        return Some((
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   180
                            HgPathBuf::from_bytes(&base_path),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   181
                            StatusShortcut::Entry(file.entry),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   182
                        ));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   183
                    }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   184
                }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   185
                NodeKind::File(file) => {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   186
                    if let Some(dir) = &file.was_directory {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   187
                        add_children_to_visit(&mut self.to_visit, &base_path, &dir);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   188
                    }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   189
                    return Some((
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   190
                        HgPathBuf::from_bytes(&base_path),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   191
                        StatusShortcut::Entry(file.entry),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   192
                    ));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   193
                }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   194
            }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   195
        }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   196
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   197
        None
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   198
    }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   199
}
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   200
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   201
impl<'a> FusedIterator for FsIter<'a> {}
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   202
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   203
fn join_path<'a, 'b>(path: &'a [u8], other: &'b [u8]) -> Cow<'b, [u8]> {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   204
    if path.is_empty() {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   205
        other.into()
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   206
    } else {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   207
        [path, &b"/"[..], other].concat().into()
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   208
    }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   209
}
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   210
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   211
/// Adds all children of a given directory `dir` to the visit queue `to_visit`
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   212
/// prefixed by a `base_path`.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   213
fn add_children_to_visit<'a>(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   214
    to_visit: &mut VecDeque<(Cow<'a, [u8]>, &'a Node)>,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   215
    base_path: &[u8],
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   216
    dir: &'a Directory,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   217
) {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   218
    to_visit.extend(dir.children.iter().map(|(path, child)| {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   219
        let full_path = join_path(&base_path, &path);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   220
        (Cow::from(full_path), child)
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   221
    }));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   222
}
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   223
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   224
#[cfg(test)]
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   225
mod tests {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   226
    use super::*;
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   227
    use crate::utils::hg_path::HgPath;
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   228
    use crate::{EntryState, FastHashMap};
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   229
    use std::collections::HashSet;
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   230
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   231
    #[test]
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   232
    fn test_iteration() {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   233
        let mut tree = Tree::new();
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   234
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   235
        assert_eq!(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   236
            tree.insert(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   237
                HgPathBuf::from_bytes(b"foo/bar"),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   238
                DirstateEntry {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   239
                    state: EntryState::Merged,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   240
                    mode: 41,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   241
                    mtime: 42,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   242
                    size: 43,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   243
                }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   244
            ),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   245
            None
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   246
        );
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   247
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   248
        assert_eq!(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   249
            tree.insert(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   250
                HgPathBuf::from_bytes(b"foo2"),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   251
                DirstateEntry {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   252
                    state: EntryState::Merged,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   253
                    mode: 40,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   254
                    mtime: 41,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   255
                    size: 42,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   256
                }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   257
            ),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   258
            None
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   259
        );
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   260
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   261
        assert_eq!(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   262
            tree.insert(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   263
                HgPathBuf::from_bytes(b"foo/baz"),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   264
                DirstateEntry {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   265
                    state: EntryState::Normal,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   266
                    mode: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   267
                    mtime: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   268
                    size: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   269
                }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   270
            ),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   271
            None
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   272
        );
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   273
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   274
        assert_eq!(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   275
            tree.insert(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   276
                HgPathBuf::from_bytes(b"foo/bap/nested"),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   277
                DirstateEntry {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   278
                    state: EntryState::Normal,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   279
                    mode: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   280
                    mtime: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   281
                    size: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   282
                }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   283
            ),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   284
            None
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   285
        );
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   286
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   287
        assert_eq!(tree.len(), 4);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   288
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   289
        let results: HashSet<_> = tree.iter().map(|(c, _)| c.to_owned()).collect();
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   290
        dbg!(&results);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   291
        assert!(results.contains(HgPath::new(b"foo2")));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   292
        assert!(results.contains(HgPath::new(b"foo/bar")));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   293
        assert!(results.contains(HgPath::new(b"foo/baz")));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   294
        assert!(results.contains(HgPath::new(b"foo/bap/nested")));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   295
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   296
        let mut iter = tree.iter();
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   297
        assert!(iter.next().is_some());
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   298
        assert!(iter.next().is_some());
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   299
        assert!(iter.next().is_some());
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   300
        assert!(iter.next().is_some());
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   301
        assert_eq!(None, iter.next());
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   302
        assert_eq!(None, iter.next());
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   303
        drop(iter);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   304
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   305
        assert_eq!(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   306
            tree.insert(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   307
                HgPathBuf::from_bytes(b"foo/bap/nested/a"),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   308
                DirstateEntry {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   309
                    state: EntryState::Normal,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   310
                    mode: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   311
                    mtime: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   312
                    size: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   313
                }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   314
            ),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   315
            None
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   316
        );
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   317
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   318
        let results: FastHashMap<_, _> = tree.iter().collect();
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   319
        assert!(results.contains_key(HgPath::new(b"foo2")));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   320
        assert!(results.contains_key(HgPath::new(b"foo/bar")));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   321
        assert!(results.contains_key(HgPath::new(b"foo/baz")));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   322
        // Is a dir but `was_file`, so it's listed as a removed file
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   323
        assert!(results.contains_key(HgPath::new(b"foo/bap/nested")));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   324
        assert!(results.contains_key(HgPath::new(b"foo/bap/nested/a")));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   325
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   326
        // insert removed file (now directory) after nested file
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   327
        assert_eq!(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   328
            tree.insert(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   329
                HgPathBuf::from_bytes(b"a/a"),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   330
                DirstateEntry {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   331
                    state: EntryState::Normal,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   332
                    mode: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   333
                    mtime: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   334
                    size: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   335
                }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   336
            ),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   337
            None
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   338
        );
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   339
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   340
        // `insert` returns `None` for a directory
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   341
        assert_eq!(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   342
            tree.insert(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   343
                HgPathBuf::from_bytes(b"a"),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   344
                DirstateEntry {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   345
                    state: EntryState::Removed,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   346
                    mode: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   347
                    mtime: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   348
                    size: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   349
                }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   350
            ),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   351
            None
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   352
        );
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   353
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   354
        let results: FastHashMap<_, _> = tree.iter().collect();
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   355
        assert!(results.contains_key(HgPath::new(b"a")));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   356
        assert!(results.contains_key(HgPath::new(b"a/a")));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   357
    }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   358
}