rust/hg-core/src/dirstate/status.rs
author Raphaël Gomès <rgomes@octobus.net>
Fri, 06 Mar 2020 18:08:23 +0100
changeset 44541 d880805d5442
parent 44539 fe7d2cf0b429
child 44562 ece43c79333e
permissions -rw-r--r--
hg-core: add function timing information This change makes use of the newly added logging infrastructure to trace the execution time of some important calls. This approach is very much complementary to using a profiler and will not guard against out-of-order execution or other kinds of compiler optimizations. That said, it is useful to get a rough high-level idea of where time is spent. Differential Revision: https://phab.mercurial-scm.org/D8253
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     1
// status.rs
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     2
//
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     3
// Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     4
//
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     5
// This software may be used and distributed according to the terms of the
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     6
// GNU General Public License version 2 or any later version.
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     7
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     8
//! Rust implementation of dirstate.status (dirstate.py).
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     9
//! It is currently missing a lot of functionality compared to the Python one
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    10
//! and will only be triggered in narrow cases.
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    11
43605
8210c3f46912 rust: introduce SIZE_FROM_OTHER_PARENT constant
Raphaël Gomès <rgomes@octobus.net>
parents: 43604
diff changeset
    12
use crate::{
8210c3f46912 rust: introduce SIZE_FROM_OTHER_PARENT constant
Raphaël Gomès <rgomes@octobus.net>
parents: 43604
diff changeset
    13
    dirstate::SIZE_FROM_OTHER_PARENT,
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
    14
    filepatterns::PatternFileWarning,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
    15
    matchers::{get_ignore_function, Matcher, VisitChildrenSet},
43605
8210c3f46912 rust: introduce SIZE_FROM_OTHER_PARENT constant
Raphaël Gomès <rgomes@octobus.net>
parents: 43604
diff changeset
    16
    utils::{
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
    17
        files::{find_dirs, HgMetadata},
44523
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
    18
        hg_path::{
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
    19
            hg_path_to_path_buf, os_string_to_hg_path_buf, HgPath, HgPathBuf,
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
    20
            HgPathError,
44523
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
    21
        },
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
    22
        path_auditor::PathAuditor,
43605
8210c3f46912 rust: introduce SIZE_FROM_OTHER_PARENT constant
Raphaël Gomès <rgomes@octobus.net>
parents: 43604
diff changeset
    23
    },
44527
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
    24
    CopyMap, DirstateEntry, DirstateMap, EntryState, FastHashMap,
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
    25
    PatternError,
43605
8210c3f46912 rust: introduce SIZE_FROM_OTHER_PARENT constant
Raphaël Gomès <rgomes@octobus.net>
parents: 43604
diff changeset
    26
};
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
    27
use lazy_static::lazy_static;
44541
d880805d5442 hg-core: add function timing information
Raphaël Gomès <rgomes@octobus.net>
parents: 44539
diff changeset
    28
use micro_timer::timed;
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    29
use rayon::prelude::*;
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
    30
use std::{
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
    31
    borrow::Cow,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
    32
    collections::HashSet,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
    33
    fs::{read_dir, DirEntry},
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
    34
    io::ErrorKind,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
    35
    ops::Deref,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
    36
    path::Path,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
    37
};
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    38
44526
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    39
/// Wrong type of file from a `BadMatch`
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    40
/// Note: a lot of those don't exist on all platforms.
44536
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
    41
#[derive(Debug, Copy, Clone)]
44526
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    42
pub enum BadType {
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    43
    CharacterDevice,
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    44
    BlockDevice,
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    45
    FIFO,
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    46
    Socket,
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    47
    Directory,
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    48
    Unknown,
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    49
}
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    50
44529
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44528
diff changeset
    51
impl ToString for BadType {
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44528
diff changeset
    52
    fn to_string(&self) -> String {
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44528
diff changeset
    53
        match self {
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44528
diff changeset
    54
            BadType::CharacterDevice => "character device",
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44528
diff changeset
    55
            BadType::BlockDevice => "block device",
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44528
diff changeset
    56
            BadType::FIFO => "fifo",
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44528
diff changeset
    57
            BadType::Socket => "socket",
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44528
diff changeset
    58
            BadType::Directory => "directory",
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44528
diff changeset
    59
            BadType::Unknown => "unknown",
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44528
diff changeset
    60
        }
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44528
diff changeset
    61
        .to_string()
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44528
diff changeset
    62
    }
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44528
diff changeset
    63
}
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44528
diff changeset
    64
44526
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    65
/// Was explicitly matched but cannot be found/accessed
44536
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
    66
#[derive(Debug, Copy, Clone)]
44526
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    67
pub enum BadMatch {
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    68
    OsError(i32),
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    69
    BadType(BadType),
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    70
}
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    71
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    72
/// Marker enum used to dispatch new status entries into the right collections.
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    73
/// Is similar to `crate::EntryState`, but represents the transient state of
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    74
/// entries during the lifetime of a command.
44536
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
    75
#[derive(Debug, Copy, Clone)]
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    76
enum Dispatch {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    77
    Unsure,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    78
    Modified,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    79
    Added,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    80
    Removed,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    81
    Deleted,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    82
    Clean,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    83
    Unknown,
44526
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    84
    Ignored,
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    85
    /// Empty dispatch, the file is not worth listing
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    86
    None,
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    87
    /// Was explicitly matched but cannot be found/accessed
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    88
    Bad(BadMatch),
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    89
    Directory {
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    90
        /// True if the directory used to be a file in the dmap so we can say
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    91
        /// that it's been removed.
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    92
        was_file: bool,
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    93
    },
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    94
}
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    95
43915
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43818
diff changeset
    96
type IoResult<T> = std::io::Result<T>;
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43818
diff changeset
    97
43604
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
    98
/// Dates and times that are outside the 31-bit signed range are compared
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
    99
/// modulo 2^31. This should prevent hg from behaving badly with very large
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
   100
/// files or corrupt dates while still having a high probability of detecting
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
   101
/// changes. (issue2608)
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
   102
/// TODO I haven't found a way of having `b` be `Into<i32>`, since `From<u64>`
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
   103
/// is not defined for `i32`, and there is no `As` trait. This forces the
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
   104
/// caller to cast `b` as `i32`.
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
   105
fn mod_compare(a: i32, b: i32) -> bool {
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
   106
    a & i32::max_value() != b & i32::max_value()
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
   107
}
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
   108
44523
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   109
/// Return a sorted list containing information about the entries
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   110
/// in the directory.
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   111
///
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   112
/// * `skip_dot_hg` - Return an empty vec if `path` contains a `.hg` directory
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   113
fn list_directory(
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   114
    path: impl AsRef<Path>,
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   115
    skip_dot_hg: bool,
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   116
) -> std::io::Result<Vec<(HgPathBuf, DirEntry)>> {
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   117
    let mut results = vec![];
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   118
    let entries = read_dir(path.as_ref())?;
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   119
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   120
    for entry in entries {
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   121
        let entry = entry?;
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   122
        let filename = os_string_to_hg_path_buf(entry.file_name())?;
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   123
        let file_type = entry.file_type()?;
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   124
        if skip_dot_hg && filename.as_bytes() == b".hg" && file_type.is_dir() {
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   125
            return Ok(vec![]);
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   126
        } else {
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   127
            results.push((HgPathBuf::from(filename), entry))
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   128
        }
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   129
    }
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   130
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   131
    results.sort_unstable_by_key(|e| e.0.clone());
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   132
    Ok(results)
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   133
}
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44193
diff changeset
   134
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   135
/// The file corresponding to the dirstate entry was found on the filesystem.
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   136
fn dispatch_found(
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   137
    filename: impl AsRef<HgPath>,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   138
    entry: DirstateEntry,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   139
    metadata: HgMetadata,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   140
    copy_map: &CopyMap,
44524
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44523
diff changeset
   141
    options: StatusOptions,
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   142
) -> Dispatch {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   143
    let DirstateEntry {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   144
        state,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   145
        mode,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   146
        mtime,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   147
        size,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   148
    } = entry;
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   149
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   150
    let HgMetadata {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   151
        st_mode,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   152
        st_size,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   153
        st_mtime,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   154
        ..
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   155
    } = metadata;
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   156
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   157
    match state {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   158
        EntryState::Normal => {
43604
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
   159
            let size_changed = mod_compare(size, st_size as i32);
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   160
            let mode_changed =
44524
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44523
diff changeset
   161
                (mode ^ st_mode as i32) & 0o100 != 0o000 && options.check_exec;
43604
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
   162
            let metadata_changed = size >= 0 && (size_changed || mode_changed);
43605
8210c3f46912 rust: introduce SIZE_FROM_OTHER_PARENT constant
Raphaël Gomès <rgomes@octobus.net>
parents: 43604
diff changeset
   163
            let other_parent = size == SIZE_FROM_OTHER_PARENT;
43604
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
   164
            if metadata_changed
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
   165
                || other_parent
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
   166
                || copy_map.contains_key(filename.as_ref())
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   167
            {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   168
                Dispatch::Modified
43604
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
   169
            } else if mod_compare(mtime, st_mtime as i32) {
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   170
                Dispatch::Unsure
44524
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44523
diff changeset
   171
            } else if st_mtime == options.last_normal_time {
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   172
                // the file may have just been marked as normal and
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   173
                // it may have changed in the same second without
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   174
                // changing its size. This can happen if we quickly
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   175
                // do multiple commits. Force lookup, so we don't
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   176
                // miss such a racy file change.
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   177
                Dispatch::Unsure
44524
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44523
diff changeset
   178
            } else if options.list_clean {
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   179
                Dispatch::Clean
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   180
            } else {
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   181
                Dispatch::None
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   182
            }
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   183
        }
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   184
        EntryState::Merged => Dispatch::Modified,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   185
        EntryState::Added => Dispatch::Added,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   186
        EntryState::Removed => Dispatch::Removed,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   187
        EntryState::Unknown => Dispatch::Unknown,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   188
    }
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   189
}
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   190
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   191
/// The file corresponding to this Dirstate entry is missing.
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   192
fn dispatch_missing(state: EntryState) -> Dispatch {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   193
    match state {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   194
        // File was removed from the filesystem during commands
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   195
        EntryState::Normal | EntryState::Merged | EntryState::Added => {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   196
            Dispatch::Deleted
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   197
        }
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   198
        // File was removed, everything is normal
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   199
        EntryState::Removed => Dispatch::Removed,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   200
        // File is unknown to Mercurial, everything is normal
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   201
        EntryState::Unknown => Dispatch::Unknown,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   202
    }
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   203
}
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   204
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   205
lazy_static! {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   206
    static ref DEFAULT_WORK: HashSet<&'static HgPath> = {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   207
        let mut h = HashSet::new();
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   208
        h.insert(HgPath::new(b""));
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   209
        h
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   210
    };
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   211
}
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   212
43915
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43818
diff changeset
   213
/// Get stat data about the files explicitly specified by match.
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43818
diff changeset
   214
/// TODO subrepos
44541
d880805d5442 hg-core: add function timing information
Raphaël Gomès <rgomes@octobus.net>
parents: 44539
diff changeset
   215
#[timed]
43915
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43818
diff changeset
   216
fn walk_explicit<'a>(
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   217
    files: Option<&'a HashSet<&HgPath>>,
43915
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43818
diff changeset
   218
    dmap: &'a DirstateMap,
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   219
    root_dir: impl AsRef<Path> + Sync + Send + 'a,
44524
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44523
diff changeset
   220
    options: StatusOptions,
43915
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43818
diff changeset
   221
) -> impl ParallelIterator<Item = IoResult<(&'a HgPath, Dispatch)>> {
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   222
    files
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   223
        .unwrap_or(&DEFAULT_WORK)
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   224
        .par_iter()
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   225
        .map(move |filename| {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   226
            // TODO normalization
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   227
            let normalized = filename.as_ref();
43915
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43818
diff changeset
   228
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   229
            let buf = match hg_path_to_path_buf(normalized) {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   230
                Ok(x) => x,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   231
                Err(e) => return Some(Err(e.into())),
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   232
            };
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   233
            let target = root_dir.as_ref().join(buf);
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   234
            let st = target.symlink_metadata();
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   235
            let in_dmap = dmap.get(normalized);
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   236
            match st {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   237
                Ok(meta) => {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   238
                    let file_type = meta.file_type();
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   239
                    return if file_type.is_file() || file_type.is_symlink() {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   240
                        if let Some(entry) = in_dmap {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   241
                            return Some(Ok((
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   242
                                normalized,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   243
                                dispatch_found(
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   244
                                    &normalized,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   245
                                    *entry,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   246
                                    HgMetadata::from_metadata(meta),
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   247
                                    &dmap.copy_map,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   248
                                    options,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   249
                                ),
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   250
                            )));
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   251
                        }
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   252
                        Some(Ok((normalized, Dispatch::Unknown)))
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   253
                    } else {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   254
                        if file_type.is_dir() {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   255
                            Some(Ok((
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   256
                                normalized,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   257
                                Dispatch::Directory {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   258
                                    was_file: in_dmap.is_some(),
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   259
                                },
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   260
                            )))
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   261
                        } else {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   262
                            Some(Ok((
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   263
                                normalized,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   264
                                Dispatch::Bad(BadMatch::BadType(
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   265
                                    // TODO do more than unknown
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   266
                                    // Support for all `BadType` variant
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   267
                                    // varies greatly between platforms.
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   268
                                    // So far, no tests check the type and
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   269
                                    // this should be good enough for most
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   270
                                    // users.
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   271
                                    BadType::Unknown,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   272
                                )),
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   273
                            )))
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   274
                        }
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   275
                    };
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   276
                }
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   277
                Err(_) => {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   278
                    if let Some(entry) = in_dmap {
43915
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43818
diff changeset
   279
                        return Some(Ok((
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43818
diff changeset
   280
                            normalized,
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   281
                            dispatch_missing(entry.state),
43915
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43818
diff changeset
   282
                        )));
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43818
diff changeset
   283
                    }
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43818
diff changeset
   284
                }
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   285
            };
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   286
            None
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   287
        })
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   288
        .flatten()
43915
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43818
diff changeset
   289
}
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43818
diff changeset
   290
44524
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44523
diff changeset
   291
#[derive(Debug, Copy, Clone)]
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44523
diff changeset
   292
pub struct StatusOptions {
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44523
diff changeset
   293
    /// Remember the most recent modification timeslot for status, to make
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44523
diff changeset
   294
    /// sure we won't miss future size-preserving file content modifications
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44523
diff changeset
   295
    /// that happen within the same timeslot.
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44523
diff changeset
   296
    pub last_normal_time: i64,
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44523
diff changeset
   297
    /// Whether we are on a filesystem with UNIX-like exec flags
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44523
diff changeset
   298
    pub check_exec: bool,
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44523
diff changeset
   299
    pub list_clean: bool,
44527
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   300
    pub list_unknown: bool,
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   301
    pub list_ignored: bool,
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   302
}
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   303
44536
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   304
/// Dispatch a single entry (file, folder, symlink...) found during `traverse`.
44539
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   305
/// If the entry is a folder that needs to be traversed, it will be handled
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   306
/// in a separate thread.
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   307
44536
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   308
fn handle_traversed_entry<'a>(
44539
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   309
    scope: &rayon::Scope<'a>,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   310
    files_sender: &'a crossbeam::Sender<IoResult<(HgPathBuf, Dispatch)>>,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   311
    matcher: &'a (impl Matcher + Sync),
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   312
    root_dir: impl AsRef<Path> + Sync + Send + Copy + 'a,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   313
    dmap: &'a DirstateMap,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   314
    old_results: &'a FastHashMap<Cow<HgPath>, Dispatch>,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   315
    ignore_fn: &'a (impl for<'r> Fn(&'r HgPath) -> bool + Sync),
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   316
    dir_ignore_fn: &'a (impl for<'r> Fn(&'r HgPath) -> bool + Sync),
44527
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   317
    options: StatusOptions,
44539
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   318
    filename: HgPathBuf,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   319
    dir_entry: DirEntry,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   320
) -> IoResult<()> {
44536
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   321
    let file_type = dir_entry.file_type()?;
44539
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   322
    let entry_option = dmap.get(&filename);
44527
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   323
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   324
    if file_type.is_dir() {
44539
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   325
        handle_traversed_dir(
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   326
            scope,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   327
            files_sender,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   328
            matcher,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   329
            root_dir,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   330
            dmap,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   331
            old_results,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   332
            ignore_fn,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   333
            dir_ignore_fn,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   334
            options,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   335
            entry_option,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   336
            filename,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   337
        );
44527
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   338
    } else if file_type.is_file() || file_type.is_symlink() {
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   339
        if let Some(entry) = entry_option {
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   340
            if matcher.matches_everything() || matcher.matches(&filename) {
44536
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   341
                let metadata = dir_entry.metadata()?;
44539
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   342
                files_sender
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   343
                    .send(Ok((
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   344
                        filename.to_owned(),
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   345
                        dispatch_found(
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   346
                            &filename,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   347
                            *entry,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   348
                            HgMetadata::from_metadata(metadata),
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   349
                            &dmap.copy_map,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   350
                            options,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   351
                        ),
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   352
                    )))
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   353
                    .unwrap();
44527
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   354
            }
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   355
        } else if (matcher.matches_everything() || matcher.matches(&filename))
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   356
            && !ignore_fn(&filename)
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   357
        {
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   358
            if (options.list_ignored || matcher.exact_match(&filename))
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   359
                && dir_ignore_fn(&filename)
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   360
            {
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   361
                if options.list_ignored {
44539
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   362
                    files_sender
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   363
                        .send(Ok((filename.to_owned(), Dispatch::Ignored)))
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   364
                        .unwrap();
44527
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   365
                }
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   366
            } else {
44539
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   367
                files_sender
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   368
                    .send(Ok((filename.to_owned(), Dispatch::Unknown)))
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   369
                    .unwrap();
44527
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   370
            }
44536
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   371
        } else if ignore_fn(&filename) && options.list_ignored {
44539
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   372
            files_sender
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   373
                .send(Ok((filename.to_owned(), Dispatch::Ignored)))
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   374
                .unwrap();
44527
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   375
        }
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   376
    } else if let Some(entry) = entry_option {
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   377
        // Used to be a file or a folder, now something else.
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   378
        if matcher.matches_everything() || matcher.matches(&filename) {
44539
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   379
            files_sender
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   380
                .send(Ok((filename.to_owned(), dispatch_missing(entry.state))))
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   381
                .unwrap();
44527
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   382
        }
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   383
    }
44539
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   384
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   385
    Ok(())
44527
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   386
}
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   387
44539
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   388
/// A directory was found in the filesystem and needs to be traversed
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   389
fn handle_traversed_dir<'a>(
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   390
    scope: &rayon::Scope<'a>,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   391
    files_sender: &'a crossbeam::Sender<IoResult<(HgPathBuf, Dispatch)>>,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   392
    matcher: &'a (impl Matcher + Sync),
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   393
    root_dir: impl AsRef<Path> + Sync + Send + Copy + 'a,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   394
    dmap: &'a DirstateMap,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   395
    old_results: &'a FastHashMap<Cow<HgPath>, Dispatch>,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   396
    ignore_fn: &'a (impl for<'r> Fn(&'r HgPath) -> bool + Sync),
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   397
    dir_ignore_fn: &'a (impl for<'r> Fn(&'r HgPath) -> bool + Sync),
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   398
    options: StatusOptions,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   399
    entry_option: Option<&'a DirstateEntry>,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   400
    directory: HgPathBuf,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   401
) {
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   402
    scope.spawn(move |_| {
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   403
        // Nested `if` until `rust-lang/rust#53668` is stable
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   404
        if let Some(entry) = entry_option {
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   405
            // Used to be a file, is now a folder
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   406
            if matcher.matches_everything() || matcher.matches(&directory) {
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   407
                files_sender
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   408
                    .send(Ok((
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   409
                        directory.to_owned(),
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   410
                        dispatch_missing(entry.state),
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   411
                    )))
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   412
                    .unwrap();
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   413
            }
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   414
        }
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   415
        // Do we need to traverse it?
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   416
        if !ignore_fn(&directory) || options.list_ignored {
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   417
            traverse_dir(
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   418
                files_sender,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   419
                matcher,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   420
                root_dir,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   421
                dmap,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   422
                directory,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   423
                &old_results,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   424
                ignore_fn,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   425
                dir_ignore_fn,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   426
                options,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   427
            )
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   428
            .unwrap_or_else(|e| files_sender.send(Err(e)).unwrap())
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   429
        }
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   430
    });
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   431
}
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   432
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   433
/// Decides whether the directory needs to be listed, and if so handles the
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   434
/// entries in a separate thread.
44536
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   435
fn traverse_dir<'a>(
44539
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   436
    files_sender: &crossbeam::Sender<IoResult<(HgPathBuf, Dispatch)>>,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   437
    matcher: &'a (impl Matcher + Sync),
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   438
    root_dir: impl AsRef<Path> + Sync + Send + Copy,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   439
    dmap: &'a DirstateMap,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   440
    directory: impl AsRef<HgPath>,
44536
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   441
    old_results: &FastHashMap<Cow<'a, HgPath>, Dispatch>,
44527
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   442
    ignore_fn: &(impl for<'r> Fn(&'r HgPath) -> bool + Sync),
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   443
    dir_ignore_fn: &(impl for<'r> Fn(&'r HgPath) -> bool + Sync),
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   444
    options: StatusOptions,
44539
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   445
) -> IoResult<()> {
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   446
    let directory = directory.as_ref();
44536
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   447
    if directory.as_bytes() == b".hg" {
44539
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   448
        return Ok(());
44536
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   449
    }
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   450
    let visit_entries = match matcher.visit_children_set(directory) {
44539
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   451
        VisitChildrenSet::Empty => return Ok(()),
44536
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   452
        VisitChildrenSet::This | VisitChildrenSet::Recursive => None,
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   453
        VisitChildrenSet::Set(set) => Some(set),
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   454
    };
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   455
    let buf = hg_path_to_path_buf(directory)?;
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   456
    let dir_path = root_dir.as_ref().join(buf);
44527
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   457
44536
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   458
    let skip_dot_hg = !directory.as_bytes().is_empty();
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   459
    let entries = match list_directory(dir_path, skip_dot_hg) {
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   460
        Err(e) => match e.kind() {
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   461
            ErrorKind::NotFound | ErrorKind::PermissionDenied => {
44539
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   462
                files_sender
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   463
                    .send(Ok((
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   464
                        directory.to_owned(),
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   465
                        Dispatch::Bad(BadMatch::OsError(
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   466
                            // Unwrapping here is OK because the error always
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   467
                            // is a real os error
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   468
                            e.raw_os_error().unwrap(),
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   469
                        )),
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   470
                    )))
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   471
                    .unwrap();
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   472
                return Ok(());
44536
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   473
            }
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   474
            _ => return Err(e),
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   475
        },
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   476
        Ok(entries) => entries,
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   477
    };
44527
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   478
44539
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   479
    rayon::scope(|scope| -> IoResult<()> {
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   480
        for (filename, dir_entry) in entries {
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   481
            if let Some(ref set) = visit_entries {
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   482
                if !set.contains(filename.deref()) {
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   483
                    continue;
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   484
                }
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   485
            }
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   486
            // TODO normalize
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   487
            let filename = if directory.is_empty() {
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   488
                filename.to_owned()
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   489
            } else {
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   490
                directory.join(&filename)
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   491
            };
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   492
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   493
            if !old_results.contains_key(filename.deref()) {
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   494
                handle_traversed_entry(
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   495
                    scope,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   496
                    files_sender,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   497
                    matcher,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   498
                    root_dir,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   499
                    dmap,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   500
                    old_results,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   501
                    ignore_fn,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   502
                    dir_ignore_fn,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   503
                    options,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   504
                    filename,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   505
                    dir_entry,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   506
                )?;
44536
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   507
            }
44527
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   508
        }
44539
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   509
        Ok(())
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   510
    })
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   511
}
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   512
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   513
/// Walk the working directory recursively to look for changes compared to the
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   514
/// current `DirstateMap`.
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   515
///
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   516
/// This takes a mutable reference to the results to account for the `extend`
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   517
/// in timings
44541
d880805d5442 hg-core: add function timing information
Raphaël Gomès <rgomes@octobus.net>
parents: 44539
diff changeset
   518
#[timed]
44539
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   519
fn traverse<'a>(
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   520
    matcher: &'a (impl Matcher + Sync),
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   521
    root_dir: impl AsRef<Path> + Sync + Send + Copy,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   522
    dmap: &'a DirstateMap,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   523
    path: impl AsRef<HgPath>,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   524
    old_results: &FastHashMap<Cow<'a, HgPath>, Dispatch>,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   525
    ignore_fn: &(impl for<'r> Fn(&'r HgPath) -> bool + Sync),
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   526
    dir_ignore_fn: &(impl for<'r> Fn(&'r HgPath) -> bool + Sync),
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   527
    options: StatusOptions,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   528
    results: &mut Vec<(Cow<'a, HgPath>, Dispatch)>,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   529
) -> IoResult<()> {
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   530
    let root_dir = root_dir.as_ref();
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   531
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   532
    // The traversal is done in parallel, so use a channel to gather entries.
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   533
    // `crossbeam::Sender` is `Send`, while `mpsc::Sender` is not.
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   534
    let (files_transmitter, files_receiver) = crossbeam::channel::unbounded();
44527
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44526
diff changeset
   535
44539
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   536
    traverse_dir(
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   537
        &files_transmitter,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   538
        matcher,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   539
        root_dir,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   540
        &dmap,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   541
        path,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   542
        &old_results,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   543
        &ignore_fn,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   544
        &dir_ignore_fn,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   545
        options,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   546
    )?;
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   547
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   548
    // Disconnect the channel so the receiver stops waiting
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   549
    drop(files_transmitter);
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   550
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   551
    // TODO don't collect. Find a way of replicating the behavior of
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   552
    // `itertools::process_results`, but for `rayon::ParallelIterator`
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   553
    let new_results: IoResult<Vec<(Cow<'a, HgPath>, Dispatch)>> =
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   554
        files_receiver
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   555
            .into_iter()
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   556
            .map(|item| {
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   557
                let (f, d) = item?;
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   558
                Ok((Cow::Owned(f), d))
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   559
            })
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   560
            .collect();
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   561
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   562
    results.par_extend(new_results?);
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   563
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   564
    Ok(())
44524
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44523
diff changeset
   565
}
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44523
diff changeset
   566
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   567
/// Stat all entries in the `DirstateMap` and mark them for dispatch.
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   568
fn stat_dmap_entries(
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   569
    dmap: &DirstateMap,
43603
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   570
    root_dir: impl AsRef<Path> + Sync + Send,
44524
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44523
diff changeset
   571
    options: StatusOptions,
43915
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43818
diff changeset
   572
) -> impl ParallelIterator<Item = IoResult<(&HgPath, Dispatch)>> {
43603
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   573
    dmap.par_iter().map(move |(filename, entry)| {
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   574
        let filename: &HgPath = filename;
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   575
        let filename_as_path = hg_path_to_path_buf(filename)?;
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   576
        let meta = root_dir.as_ref().join(filename_as_path).symlink_metadata();
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   577
43603
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   578
        match meta {
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   579
            Ok(ref m)
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   580
                if !(m.file_type().is_file()
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   581
                    || m.file_type().is_symlink()) =>
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   582
            {
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   583
                Ok((filename, dispatch_missing(entry.state)))
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   584
            }
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   585
            Ok(m) => Ok((
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   586
                filename,
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   587
                dispatch_found(
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   588
                    filename,
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   589
                    *entry,
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   590
                    HgMetadata::from_metadata(m),
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   591
                    &dmap.copy_map,
44524
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44523
diff changeset
   592
                    options,
43603
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   593
                ),
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   594
            )),
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   595
            Err(ref e)
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   596
                if e.kind() == ErrorKind::NotFound
43603
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   597
                    || e.raw_os_error() == Some(20) =>
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   598
            {
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   599
                // Rust does not yet have an `ErrorKind` for
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   600
                // `NotADirectory` (errno 20)
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   601
                // It happens if the dirstate contains `foo/bar` and
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   602
                // foo is not a directory
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   603
                Ok((filename, dispatch_missing(entry.state)))
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   604
            }
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   605
            Err(e) => Err(e),
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   606
        }
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   607
    })
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   608
}
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   609
44538
b8ba46c97cdd rust-status: wrap `stat_dmap_entries` to ease profiling
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   610
/// This takes a mutable reference to the results to account for the `extend`
b8ba46c97cdd rust-status: wrap `stat_dmap_entries` to ease profiling
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   611
/// in timings
44541
d880805d5442 hg-core: add function timing information
Raphaël Gomès <rgomes@octobus.net>
parents: 44539
diff changeset
   612
#[timed]
44538
b8ba46c97cdd rust-status: wrap `stat_dmap_entries` to ease profiling
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   613
fn extend_from_dmap<'a>(
b8ba46c97cdd rust-status: wrap `stat_dmap_entries` to ease profiling
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   614
    dmap: &'a DirstateMap,
b8ba46c97cdd rust-status: wrap `stat_dmap_entries` to ease profiling
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   615
    root_dir: impl AsRef<Path> + Sync + Send,
b8ba46c97cdd rust-status: wrap `stat_dmap_entries` to ease profiling
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   616
    options: StatusOptions,
b8ba46c97cdd rust-status: wrap `stat_dmap_entries` to ease profiling
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   617
    results: &mut Vec<(Cow<'a, HgPath>, Dispatch)>,
b8ba46c97cdd rust-status: wrap `stat_dmap_entries` to ease profiling
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   618
) {
b8ba46c97cdd rust-status: wrap `stat_dmap_entries` to ease profiling
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   619
    results.par_extend(
b8ba46c97cdd rust-status: wrap `stat_dmap_entries` to ease profiling
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   620
        stat_dmap_entries(dmap, root_dir, options)
b8ba46c97cdd rust-status: wrap `stat_dmap_entries` to ease profiling
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   621
            .flatten()
b8ba46c97cdd rust-status: wrap `stat_dmap_entries` to ease profiling
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   622
            .map(|(filename, dispatch)| (Cow::Borrowed(filename), dispatch)),
b8ba46c97cdd rust-status: wrap `stat_dmap_entries` to ease profiling
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   623
    );
b8ba46c97cdd rust-status: wrap `stat_dmap_entries` to ease profiling
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   624
}
b8ba46c97cdd rust-status: wrap `stat_dmap_entries` to ease profiling
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   625
44525
f13d19549efd rust-status: rename `StatusResult` to `DirstateStatus`
Raphaël Gomès <rgomes@octobus.net>
parents: 44524
diff changeset
   626
pub struct DirstateStatus<'a> {
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   627
    pub modified: Vec<Cow<'a, HgPath>>,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   628
    pub added: Vec<Cow<'a, HgPath>>,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   629
    pub removed: Vec<Cow<'a, HgPath>>,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   630
    pub deleted: Vec<Cow<'a, HgPath>>,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   631
    pub clean: Vec<Cow<'a, HgPath>>,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   632
    pub ignored: Vec<Cow<'a, HgPath>>,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   633
    pub unknown: Vec<Cow<'a, HgPath>>,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   634
    pub bad: Vec<(Cow<'a, HgPath>, BadMatch)>,
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   635
}
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   636
44541
d880805d5442 hg-core: add function timing information
Raphaël Gomès <rgomes@octobus.net>
parents: 44539
diff changeset
   637
#[timed]
43915
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43818
diff changeset
   638
fn build_response<'a>(
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   639
    results: impl IntoIterator<Item = (Cow<'a, HgPath>, Dispatch)>,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   640
) -> (Vec<Cow<'a, HgPath>>, DirstateStatus<'a>) {
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   641
    let mut lookup = vec![];
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   642
    let mut modified = vec![];
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   643
    let mut added = vec![];
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   644
    let mut removed = vec![];
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   645
    let mut deleted = vec![];
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   646
    let mut clean = vec![];
44526
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   647
    let mut ignored = vec![];
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   648
    let mut unknown = vec![];
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   649
    let mut bad = vec![];
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   650
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   651
    for (filename, dispatch) in results.into_iter() {
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   652
        match dispatch {
44526
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   653
            Dispatch::Unknown => unknown.push(filename),
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   654
            Dispatch::Unsure => lookup.push(filename),
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   655
            Dispatch::Modified => modified.push(filename),
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   656
            Dispatch::Added => added.push(filename),
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   657
            Dispatch::Removed => removed.push(filename),
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   658
            Dispatch::Deleted => deleted.push(filename),
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   659
            Dispatch::Clean => clean.push(filename),
44526
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   660
            Dispatch::Ignored => ignored.push(filename),
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   661
            Dispatch::None => {}
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   662
            Dispatch::Bad(reason) => bad.push((filename, reason)),
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   663
            Dispatch::Directory { .. } => {}
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   664
        }
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   665
    }
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   666
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   667
    (
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   668
        lookup,
44525
f13d19549efd rust-status: rename `StatusResult` to `DirstateStatus`
Raphaël Gomès <rgomes@octobus.net>
parents: 44524
diff changeset
   669
        DirstateStatus {
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   670
            modified,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   671
            added,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   672
            removed,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   673
            deleted,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   674
            clean,
44526
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   675
            ignored,
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   676
            unknown,
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   677
            bad,
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   678
        },
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   679
    )
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   680
}
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   681
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   682
pub enum StatusError {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   683
    IO(std::io::Error),
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   684
    Path(HgPathError),
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   685
    Pattern(PatternError),
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   686
}
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   687
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   688
pub type StatusResult<T> = Result<T, StatusError>;
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   689
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   690
impl From<PatternError> for StatusError {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   691
    fn from(e: PatternError) -> Self {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   692
        StatusError::Pattern(e)
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   693
    }
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   694
}
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   695
impl From<HgPathError> for StatusError {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   696
    fn from(e: HgPathError) -> Self {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   697
        StatusError::Path(e)
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   698
    }
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   699
}
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   700
impl From<std::io::Error> for StatusError {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   701
    fn from(e: std::io::Error) -> Self {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   702
        StatusError::IO(e)
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   703
    }
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   704
}
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   705
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   706
impl ToString for StatusError {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   707
    fn to_string(&self) -> String {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   708
        match self {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   709
            StatusError::IO(e) => e.to_string(),
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   710
            StatusError::Path(e) => e.to_string(),
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   711
            StatusError::Pattern(e) => e.to_string(),
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   712
        }
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   713
    }
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   714
}
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   715
44537
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   716
/// This takes a mutable reference to the results to account for the `extend`
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   717
/// in timings
44541
d880805d5442 hg-core: add function timing information
Raphaël Gomès <rgomes@octobus.net>
parents: 44539
diff changeset
   718
#[timed]
44537
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   719
fn handle_unknowns<'a>(
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   720
    dmap: &'a DirstateMap,
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   721
    matcher: &(impl Matcher + Sync),
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   722
    root_dir: impl AsRef<Path> + Sync + Send + Copy,
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   723
    options: StatusOptions,
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   724
    results: &mut Vec<(Cow<'a, HgPath>, Dispatch)>,
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   725
) -> IoResult<()> {
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   726
    let to_visit: Vec<(&HgPath, &DirstateEntry)> = if results.is_empty()
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   727
        && matcher.matches_everything()
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   728
    {
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   729
        dmap.iter().map(|(f, e)| (f.deref(), e)).collect()
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   730
    } else {
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   731
        // Only convert to a hashmap if needed.
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   732
        let old_results: FastHashMap<_, _> = results.iter().cloned().collect();
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   733
        dmap.iter()
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   734
            .filter_map(move |(f, e)| {
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   735
                if !old_results.contains_key(f.deref()) && matcher.matches(f) {
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   736
                    Some((f.deref(), e))
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   737
                } else {
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   738
                    None
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   739
                }
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   740
            })
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   741
            .collect()
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   742
    };
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   743
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   744
    // We walked all dirs under the roots that weren't ignored, and
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   745
    // everything that matched was stat'ed and is already in results.
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   746
    // The rest must thus be ignored or under a symlink.
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   747
    let path_auditor = PathAuditor::new(root_dir);
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   748
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   749
    // TODO don't collect. Find a way of replicating the behavior of
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   750
    // `itertools::process_results`, but for `rayon::ParallelIterator`
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   751
    let new_results: IoResult<Vec<_>> = to_visit
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   752
        .into_par_iter()
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   753
        .filter_map(|(filename, entry)| -> Option<IoResult<_>> {
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   754
            // Report ignored items in the dmap as long as they are not
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   755
            // under a symlink directory.
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   756
            if path_auditor.check(filename) {
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   757
                // TODO normalize for case-insensitive filesystems
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   758
                let buf = match hg_path_to_path_buf(filename) {
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   759
                    Ok(x) => x,
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   760
                    Err(e) => return Some(Err(e.into())),
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   761
                };
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   762
                Some(Ok((
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   763
                    Cow::Borrowed(filename),
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   764
                    match root_dir.as_ref().join(&buf).symlink_metadata() {
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   765
                        // File was just ignored, no links, and exists
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   766
                        Ok(meta) => {
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   767
                            let metadata = HgMetadata::from_metadata(meta);
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   768
                            dispatch_found(
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   769
                                filename,
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   770
                                *entry,
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   771
                                metadata,
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   772
                                &dmap.copy_map,
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   773
                                options,
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   774
                            )
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   775
                        }
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   776
                        // File doesn't exist
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   777
                        Err(_) => dispatch_missing(entry.state),
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   778
                    },
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   779
                )))
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   780
            } else {
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   781
                // It's either missing or under a symlink directory which
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   782
                // we, in this case, report as missing.
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   783
                Some(Ok((
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   784
                    Cow::Borrowed(filename),
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   785
                    dispatch_missing(entry.state),
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   786
                )))
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   787
            }
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   788
        })
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   789
        .collect();
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   790
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   791
    results.par_extend(new_results?);
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   792
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   793
    Ok(())
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   794
}
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   795
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   796
/// Get the status of files in the working directory.
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   797
///
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   798
/// This is the current entry-point for `hg-core` and is realistically unusable
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   799
/// outside of a Python context because its arguments need to provide a lot of
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   800
/// information that will not be necessary in the future.
44541
d880805d5442 hg-core: add function timing information
Raphaël Gomès <rgomes@octobus.net>
parents: 44539
diff changeset
   801
#[timed]
43915
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43818
diff changeset
   802
pub fn status<'a: 'c, 'b: 'c, 'c>(
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43818
diff changeset
   803
    dmap: &'a DirstateMap,
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   804
    matcher: &'b (impl Matcher + Sync),
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   805
    root_dir: impl AsRef<Path> + Sync + Send + Copy + 'c,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   806
    ignore_files: &[impl AsRef<Path> + 'c],
44524
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44523
diff changeset
   807
    options: StatusOptions,
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   808
) -> StatusResult<(
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   809
    (Vec<Cow<'c, HgPath>>, DirstateStatus<'c>),
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   810
    Vec<PatternFileWarning>,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   811
)> {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   812
    let (ignore_fn, warnings) = get_ignore_function(&ignore_files, root_dir)?;
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   813
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   814
    // Is the path or one of its ancestors ignored?
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   815
    let dir_ignore_fn = |dir: &_| {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   816
        if ignore_fn(dir) {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   817
            true
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   818
        } else {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   819
            for p in find_dirs(dir) {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   820
                if ignore_fn(p) {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   821
                    return true;
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   822
                }
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   823
            }
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   824
            false
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   825
        }
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   826
    };
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   827
43915
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43818
diff changeset
   828
    let files = matcher.file_set();
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   829
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   830
    // Step 1: check the files explicitly mentioned by the user
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   831
    let explicit = walk_explicit(files, &dmap, root_dir, options);
44536
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   832
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   833
    // Collect results into a `Vec` because we do very few lookups in most
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   834
    // cases.
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   835
    let (work, mut results): (Vec<_>, Vec<_>) = explicit
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   836
        .filter_map(Result::ok)
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   837
        .map(|(filename, dispatch)| (Cow::Borrowed(filename), dispatch))
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   838
        .partition(|(_, dispatch)| match dispatch {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   839
            Dispatch::Directory { .. } => true,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   840
            _ => false,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   841
        });
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   842
44536
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   843
    if !work.is_empty() {
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   844
        // Hashmaps are quite a bit slower to build than vecs, so only build it
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   845
        // if needed.
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   846
        let old_results = results.iter().cloned().collect();
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   847
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   848
        // Step 2: recursively check the working directory for changes if
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   849
        // needed
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   850
        for (dir, dispatch) in work {
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   851
            match dispatch {
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   852
                Dispatch::Directory { was_file } => {
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   853
                    if was_file {
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   854
                        results.push((dir.to_owned(), Dispatch::Removed));
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   855
                    }
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   856
                    if options.list_ignored
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   857
                        || options.list_unknown && !dir_ignore_fn(&dir)
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   858
                    {
44539
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   859
                        traverse(
44536
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   860
                            matcher,
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   861
                            root_dir,
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   862
                            &dmap,
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   863
                            &dir,
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   864
                            &old_results,
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   865
                            &ignore_fn,
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   866
                            &dir_ignore_fn,
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   867
                            options,
44539
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   868
                            &mut results,
fe7d2cf0b429 rust-status: traverse working directory in parallel
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
   869
                        )?;
44536
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   870
                    }
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   871
                }
44536
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   872
                _ => unreachable!("There can only be directories in `work`"),
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   873
            }
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   874
        }
43915
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43818
diff changeset
   875
    }
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   876
43915
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43818
diff changeset
   877
    if !matcher.is_exact() {
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   878
        // Step 3: Check the remaining files from the dmap.
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   879
        // If a dmap file is not in results yet, it was either
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   880
        // a) not matched b) ignored, c) missing, or d) under a
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   881
        // symlink directory.
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   882
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   883
        if options.list_unknown {
44537
5f6a504dc0bd rust-status: refactor handling of unknown files
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   884
            handle_unknowns(dmap, matcher, root_dir, options, &mut results)?;
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   885
        } else {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   886
            // We may not have walked the full directory tree above, so stat
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   887
            // and check everything we missed.
44538
b8ba46c97cdd rust-status: wrap `stat_dmap_entries` to ease profiling
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   888
            extend_from_dmap(&dmap, root_dir, options, &mut results);
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   889
        }
43915
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43818
diff changeset
   890
    }
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43818
diff changeset
   891
44528
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44527
diff changeset
   892
    Ok((build_response(results), warnings))
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   893
}