rust/hg-core/src/dirstate_tree/status.rs
author Simon Sapin <simon.sapin@octobus.net>
Wed, 19 May 2021 13:15:00 +0200
changeset 47335 ed1583a845d2
parent 47333 69530e5d4fe5
child 47336 8d0260d0dbc9
permissions -rw-r--r--
dirstate-v2: Make more APIs fallible, returning Result When parsing becomes lazy, parse error will potentially happen in more places. This propagates such errors to callers. Differential Revision: https://phab.mercurial-scm.org/D10749
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
     1
use crate::dirstate::status::IgnoreFnType;
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
     2
use crate::dirstate_tree::dirstate_map::ChildNodesRef;
47112
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     3
use crate::dirstate_tree::dirstate_map::DirstateMap;
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
     4
use crate::dirstate_tree::dirstate_map::NodeRef;
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
     5
use crate::dirstate_tree::on_disk::DirstateV2ParseError;
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
     6
use crate::matchers::get_ignore_function;
47112
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     7
use crate::matchers::Matcher;
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
     8
use crate::utils::files::get_bytes_from_os_string;
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
     9
use crate::utils::hg_path::HgPath;
47115
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
    10
use crate::BadMatch;
47112
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    11
use crate::DirstateStatus;
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    12
use crate::EntryState;
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    13
use crate::HgPathBuf;
47112
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    14
use crate::PatternFileWarning;
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    15
use crate::StatusError;
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    16
use crate::StatusOptions;
47118
c92e63762573 dirstate-tree: Add #[timed] attribute to `status` and `DirstateMap::read`
Simon Sapin <simon.sapin@octobus.net>
parents: 47117
diff changeset
    17
use micro_timer::timed;
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
    18
use rayon::prelude::*;
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    19
use std::borrow::Cow;
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    20
use std::io;
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    21
use std::path::Path;
47112
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    22
use std::path::PathBuf;
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
    23
use std::sync::Mutex;
47112
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    24
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    25
/// Returns the status of the working directory compared to its parent
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    26
/// changeset.
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    27
///
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    28
/// This algorithm is based on traversing the filesystem tree (`fs` in function
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    29
/// and variable names) and dirstate tree at the same time. The core of this
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    30
/// traversal is the recursive `traverse_fs_directory_and_dirstate` function
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    31
/// and its use of `itertools::merge_join_by`. When reaching a path that only
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    32
/// exists in one of the two trees, depending on information requested by
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    33
/// `options` we may need to traverse the remaining subtree.
47118
c92e63762573 dirstate-tree: Add #[timed] attribute to `status` and `DirstateMap::read`
Simon Sapin <simon.sapin@octobus.net>
parents: 47117
diff changeset
    34
#[timed]
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    35
pub fn status<'tree>(
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    36
    dmap: &'tree mut DirstateMap,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    37
    matcher: &(dyn Matcher + Sync),
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    38
    root_dir: PathBuf,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    39
    ignore_files: Vec<PathBuf>,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    40
    options: StatusOptions,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    41
) -> Result<(DirstateStatus<'tree>, Vec<PatternFileWarning>), StatusError> {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    42
    let (ignore_fn, warnings): (IgnoreFnType, _) =
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    43
        if options.list_ignored || options.list_unknown {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    44
            get_ignore_function(ignore_files, &root_dir)?
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    45
        } else {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    46
            (Box::new(|&_| true), vec![])
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    47
        };
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    48
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
    49
    let common = StatusCommon {
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    50
        options,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    51
        matcher,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    52
        ignore_fn,
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
    53
        outcome: Mutex::new(DirstateStatus::default()),
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    54
    };
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    55
    let is_at_repo_root = true;
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    56
    let hg_path = HgPath::new("");
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    57
    let has_ignored_ancestor = false;
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    58
    common.traverse_fs_directory_and_dirstate(
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    59
        has_ignored_ancestor,
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
    60
        dmap.root.as_ref(),
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    61
        hg_path,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    62
        &root_dir,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    63
        is_at_repo_root,
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
    64
    )?;
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
    65
    Ok((common.outcome.into_inner().unwrap(), warnings))
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    66
}
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    67
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    68
/// Bag of random things needed by various parts of the algorithm. Reduces the
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    69
/// number of parameters passed to functions.
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    70
struct StatusCommon<'tree, 'a> {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    71
    options: StatusOptions,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    72
    matcher: &'a (dyn Matcher + Sync),
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    73
    ignore_fn: IgnoreFnType<'a>,
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
    74
    outcome: Mutex<DirstateStatus<'tree>>,
47112
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    75
}
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    76
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    77
impl<'tree, 'a> StatusCommon<'tree, 'a> {
47115
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
    78
    fn read_dir(
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
    79
        &self,
47115
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
    80
        hg_path: &HgPath,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
    81
        fs_path: &Path,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
    82
        is_at_repo_root: bool,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
    83
    ) -> Result<Vec<DirEntry>, ()> {
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
    84
        DirEntry::read_dir(fs_path, is_at_repo_root).map_err(|error| {
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
    85
            let errno = error.raw_os_error().expect("expected real OS error");
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
    86
            self.outcome
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
    87
                .lock()
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
    88
                .unwrap()
47115
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
    89
                .bad
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
    90
                .push((hg_path.to_owned().into(), BadMatch::OsError(errno)))
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
    91
        })
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
    92
    }
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
    93
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    94
    fn traverse_fs_directory_and_dirstate(
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
    95
        &self,
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
    96
        has_ignored_ancestor: bool,
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
    97
        dirstate_nodes: ChildNodesRef<'tree, '_>,
47115
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
    98
        directory_hg_path: &'tree HgPath,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
    99
        directory_fs_path: &Path,
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   100
        is_at_repo_root: bool,
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   101
    ) -> Result<(), DirstateV2ParseError> {
47115
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
   102
        let mut fs_entries = if let Ok(entries) = self.read_dir(
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
   103
            directory_hg_path,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
   104
            directory_fs_path,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
   105
            is_at_repo_root,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
   106
        ) {
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
   107
            entries
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
   108
        } else {
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   109
            return Ok(());
47115
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
   110
        };
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   111
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   112
        // `merge_join_by` requires both its input iterators to be sorted:
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   113
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
   114
        let dirstate_nodes = dirstate_nodes.sorted();
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   115
        // `sort_unstable_by_key` doesn’t allow keys borrowing from the value:
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   116
        // https://github.com/rust-lang/rust/issues/34162
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   117
        fs_entries.sort_unstable_by(|e1, e2| e1.base_name.cmp(&e2.base_name));
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   118
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   119
        // Propagate here any error that would happen inside the comparison
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   120
        // callback below
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   121
        for dirstate_node in &dirstate_nodes {
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   122
            dirstate_node.base_name()?;
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   123
        }
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   124
        itertools::merge_join_by(
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   125
            dirstate_nodes,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   126
            &fs_entries,
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
   127
            |dirstate_node, fs_entry| {
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   128
                // This `unwrap` never panics because we already propagated
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   129
                // those errors above
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   130
                dirstate_node.base_name().unwrap().cmp(&fs_entry.base_name)
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   131
            },
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   132
        )
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   133
        .par_bridge()
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   134
        .map(|pair| {
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   135
            use itertools::EitherOrBoth::*;
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   136
            match pair {
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   137
                Both(dirstate_node, fs_entry) => self
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   138
                    .traverse_fs_and_dirstate(
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   139
                        fs_entry,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   140
                        dirstate_node,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   141
                        has_ignored_ancestor,
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   142
                    ),
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
   143
                Left(dirstate_node) => {
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
   144
                    self.traverse_dirstate_only(dirstate_node)
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
   145
                }
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   146
                Right(fs_entry) => Ok(self.traverse_fs_only(
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   147
                    has_ignored_ancestor,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   148
                    directory_hg_path,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   149
                    fs_entry,
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   150
                )),
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   151
            }
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   152
        })
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   153
        .collect()
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   154
    }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   155
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   156
    fn traverse_fs_and_dirstate(
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   157
        &self,
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   158
        fs_entry: &DirEntry,
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
   159
        dirstate_node: NodeRef<'tree, '_>,
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   160
        has_ignored_ancestor: bool,
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   161
    ) -> Result<(), DirstateV2ParseError> {
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   162
        let hg_path = dirstate_node.full_path()?;
47114
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47113
diff changeset
   163
        let file_type = fs_entry.metadata.file_type();
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47113
diff changeset
   164
        let file_or_symlink = file_type.is_file() || file_type.is_symlink();
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47113
diff changeset
   165
        if !file_or_symlink {
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   166
            // If we previously had a file here, it was removed (with
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   167
            // `hg rm` or similar) or deleted before it could be
47114
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47113
diff changeset
   168
            // replaced by a directory or something else.
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   169
            self.mark_removed_or_deleted_if_file(
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   170
                hg_path,
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   171
                dirstate_node.state()?,
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   172
            );
47114
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47113
diff changeset
   173
        }
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47113
diff changeset
   174
        if file_type.is_dir() {
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47113
diff changeset
   175
            if self.options.collect_traversed_dirs {
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   176
                self.outcome.lock().unwrap().traversed.push(hg_path.into())
47114
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47113
diff changeset
   177
            }
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   178
            let is_ignored = has_ignored_ancestor || (self.ignore_fn)(hg_path);
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   179
            let is_at_repo_root = false;
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   180
            self.traverse_fs_directory_and_dirstate(
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   181
                is_ignored,
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   182
                dirstate_node.children()?,
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   183
                hg_path,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   184
                &fs_entry.full_path,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   185
                is_at_repo_root,
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   186
            )?
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   187
        } else {
47114
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47113
diff changeset
   188
            if file_or_symlink && self.matcher.matches(hg_path) {
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   189
                let full_path = Cow::from(hg_path);
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   190
                if let Some(state) = dirstate_node.state()? {
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
   191
                    match state {
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   192
                        EntryState::Added => {
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   193
                            self.outcome.lock().unwrap().added.push(full_path)
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   194
                        }
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   195
                        EntryState::Removed => self
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   196
                            .outcome
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   197
                            .lock()
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   198
                            .unwrap()
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   199
                            .removed
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   200
                            .push(full_path),
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   201
                        EntryState::Merged => self
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   202
                            .outcome
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   203
                            .lock()
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   204
                            .unwrap()
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   205
                            .modified
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   206
                            .push(full_path),
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   207
                        EntryState::Normal => {
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   208
                            self.handle_normal_file(&dirstate_node, fs_entry)?
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   209
                        }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   210
                        // This variant is not used in DirstateMap
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   211
                        // nodes
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   212
                        EntryState::Unknown => unreachable!(),
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   213
                    }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   214
                } else {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   215
                    // `node.entry.is_none()` indicates a "directory"
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   216
                    // node, but the filesystem has a file
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   217
                    self.mark_unknown_or_ignored(
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   218
                        has_ignored_ancestor,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   219
                        full_path,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   220
                    )
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   221
                }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   222
            }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   223
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   224
            for child_node in dirstate_node.children()?.iter() {
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   225
                self.traverse_dirstate_only(child_node)?
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   226
            }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   227
        }
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   228
        Ok(())
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   229
    }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   230
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   231
    /// A file with `EntryState::Normal` in the dirstate was found in the
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   232
    /// filesystem
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   233
    fn handle_normal_file(
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   234
        &self,
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
   235
        dirstate_node: &NodeRef<'tree, '_>,
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   236
        fs_entry: &DirEntry,
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   237
    ) -> Result<(), DirstateV2ParseError> {
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   238
        // Keep the low 31 bits
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   239
        fn truncate_u64(value: u64) -> i32 {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   240
            (value & 0x7FFF_FFFF) as i32
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   241
        }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   242
        fn truncate_i64(value: i64) -> i32 {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   243
            (value & 0x7FFF_FFFF) as i32
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   244
        }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   245
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
   246
        let entry = dirstate_node
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   247
            .entry()?
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
   248
            .expect("handle_normal_file called with entry-less node");
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   249
        let full_path = Cow::from(dirstate_node.full_path()?);
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   250
        let mode_changed = || {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   251
            self.options.check_exec && entry.mode_changed(&fs_entry.metadata)
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   252
        };
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   253
        let size_changed = entry.size != truncate_u64(fs_entry.metadata.len());
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   254
        if entry.size >= 0
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   255
            && size_changed
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   256
            && fs_entry.metadata.file_type().is_symlink()
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   257
        {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   258
            // issue6456: Size returned may be longer due to encryption
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   259
            // on EXT-4 fscrypt. TODO maybe only do it on EXT4?
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   260
            self.outcome.lock().unwrap().unsure.push(full_path)
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   261
        } else if dirstate_node.has_copy_source()
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   262
            || entry.is_from_other_parent()
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   263
            || (entry.size >= 0 && (size_changed || mode_changed()))
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   264
        {
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   265
            self.outcome.lock().unwrap().modified.push(full_path)
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   266
        } else {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   267
            let mtime = mtime_seconds(&fs_entry.metadata);
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   268
            if truncate_i64(mtime) != entry.mtime
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   269
                || mtime == self.options.last_normal_time
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   270
            {
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   271
                self.outcome.lock().unwrap().unsure.push(full_path)
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   272
            } else if self.options.list_clean {
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   273
                self.outcome.lock().unwrap().clean.push(full_path)
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   274
            }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   275
        }
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   276
        Ok(())
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   277
    }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   278
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   279
    /// A node in the dirstate tree has no corresponding filesystem entry
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   280
    fn traverse_dirstate_only(
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   281
        &self,
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   282
        dirstate_node: NodeRef<'tree, '_>,
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   283
    ) -> Result<(), DirstateV2ParseError> {
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
   284
        self.mark_removed_or_deleted_if_file(
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   285
            dirstate_node.full_path()?,
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   286
            dirstate_node.state()?,
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
   287
        );
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
   288
        dirstate_node
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   289
            .children()?
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
   290
            .par_iter()
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   291
            .map(|child_node| self.traverse_dirstate_only(child_node))
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   292
            .collect()
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   293
    }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   294
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   295
    /// A node in the dirstate tree has no corresponding *file* on the
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   296
    /// filesystem
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   297
    ///
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   298
    /// Does nothing on a "directory" node
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   299
    fn mark_removed_or_deleted_if_file(
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   300
        &self,
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   301
        hg_path: &'tree HgPath,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   302
        dirstate_node_state: Option<EntryState>,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   303
    ) {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   304
        if let Some(state) = dirstate_node_state {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   305
            if self.matcher.matches(hg_path) {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   306
                if let EntryState::Removed = state {
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   307
                    self.outcome.lock().unwrap().removed.push(hg_path.into())
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   308
                } else {
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   309
                    self.outcome.lock().unwrap().deleted.push(hg_path.into())
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   310
                }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   311
            }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   312
        }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   313
    }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   314
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   315
    /// Something in the filesystem has no corresponding dirstate node
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   316
    fn traverse_fs_only(
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   317
        &self,
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   318
        has_ignored_ancestor: bool,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   319
        directory_hg_path: &HgPath,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   320
        fs_entry: &DirEntry,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   321
    ) {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   322
        let hg_path = directory_hg_path.join(&fs_entry.base_name);
47114
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47113
diff changeset
   323
        let file_type = fs_entry.metadata.file_type();
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47113
diff changeset
   324
        let file_or_symlink = file_type.is_file() || file_type.is_symlink();
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47113
diff changeset
   325
        if file_type.is_dir() {
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   326
            let is_ignored =
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   327
                has_ignored_ancestor || (self.ignore_fn)(&hg_path);
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   328
            let traverse_children = if is_ignored {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   329
                // Descendants of an ignored directory are all ignored
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   330
                self.options.list_ignored
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   331
            } else {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   332
                // Descendants of an unknown directory may be either unknown or
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   333
                // ignored
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   334
                self.options.list_unknown || self.options.list_ignored
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   335
            };
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   336
            if traverse_children {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   337
                let is_at_repo_root = false;
47115
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
   338
                if let Ok(children_fs_entries) = self.read_dir(
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
   339
                    &hg_path,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
   340
                    &fs_entry.full_path,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
   341
                    is_at_repo_root,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
   342
                ) {
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   343
                    children_fs_entries.par_iter().for_each(|child_fs_entry| {
47115
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
   344
                        self.traverse_fs_only(
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
   345
                            is_ignored,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
   346
                            &hg_path,
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   347
                            child_fs_entry,
47115
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
   348
                        )
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   349
                    })
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   350
                }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   351
            }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   352
            if self.options.collect_traversed_dirs {
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   353
                self.outcome.lock().unwrap().traversed.push(hg_path.into())
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   354
            }
47114
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47113
diff changeset
   355
        } else if file_or_symlink && self.matcher.matches(&hg_path) {
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   356
            self.mark_unknown_or_ignored(has_ignored_ancestor, hg_path.into())
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   357
        }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   358
    }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   359
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   360
    fn mark_unknown_or_ignored(
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   361
        &self,
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   362
        has_ignored_ancestor: bool,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   363
        hg_path: Cow<'tree, HgPath>,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   364
    ) {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   365
        let is_ignored = has_ignored_ancestor || (self.ignore_fn)(&hg_path);
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   366
        if is_ignored {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   367
            if self.options.list_ignored {
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   368
                self.outcome.lock().unwrap().ignored.push(hg_path)
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   369
            }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   370
        } else {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   371
            if self.options.list_unknown {
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
   372
                self.outcome.lock().unwrap().unknown.push(hg_path)
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   373
            }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   374
        }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   375
    }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   376
}
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   377
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   378
#[cfg(unix)] // TODO
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   379
fn mtime_seconds(metadata: &std::fs::Metadata) -> i64 {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   380
    // Going through `Metadata::modified()` would be portable, but would take
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   381
    // care to construct a `SystemTime` value with sub-second precision just
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   382
    // for us to throw that away here.
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   383
    use std::os::unix::fs::MetadataExt;
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   384
    metadata.mtime()
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   385
}
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   386
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   387
struct DirEntry {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   388
    base_name: HgPathBuf,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   389
    full_path: PathBuf,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   390
    metadata: std::fs::Metadata,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   391
}
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   392
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   393
impl DirEntry {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   394
    /// Returns **unsorted** entries in the given directory, with name and
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   395
    /// metadata.
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   396
    ///
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   397
    /// If a `.hg` sub-directory is encountered:
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   398
    ///
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   399
    /// * At the repository root, ignore that sub-directory
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   400
    /// * Elsewhere, we’re listing the content of a sub-repo. Return an empty
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   401
    ///   list instead.
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   402
    fn read_dir(path: &Path, is_at_repo_root: bool) -> io::Result<Vec<Self>> {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   403
        let mut results = Vec::new();
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   404
        for entry in path.read_dir()? {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   405
            let entry = entry?;
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   406
            let metadata = entry.metadata()?;
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   407
            let name = get_bytes_from_os_string(entry.file_name());
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   408
            // FIXME don't do this when cached
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   409
            if name == b".hg" {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   410
                if is_at_repo_root {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   411
                    // Skip the repo’s own .hg (might be a symlink)
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   412
                    continue;
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   413
                } else if metadata.is_dir() {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   414
                    // A .hg sub-directory at another location means a subrepo,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   415
                    // skip it entirely.
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   416
                    return Ok(Vec::new());
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   417
                }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   418
            }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   419
            results.push(DirEntry {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   420
                base_name: name.into(),
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   421
                full_path: entry.path(),
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   422
                metadata,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   423
            })
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   424
        }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   425
        Ok(results)
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   426
    }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   427
}