rust/hg-core/src/dirstate/status.rs
author Simon Sapin <simon.sapin@octobus.net>
Tue, 30 Mar 2021 14:15:23 +0200
changeset 47107 787ff5d21bcd
parent 46890 441024b279a6
child 47124 9c6b458a08e1
permissions -rw-r--r--
dirstate-tree: Make Rust DirstateMap bindings go through a trait object This changeset starts a series that adds an experiment to make status faster by changing the dirstate (first only in memory and later also on disk) to be shaped as a tree matching the directory structure, instead of the current flat collection of entries. The status algorithm can then traverse this tree dirstate at the same time as it traverses the filesystem. We (Octobus) have made prototypes that show promising results but are prone to bitrot. We would like to start upstreaming some experimental Rust code that goes in this direction, but to avoid disrupting users it should only be enabled by some run-time opt-in while keeping the existing dirstate structure and status algorithm as-is. The `DirstateMap` type and `status` function look like the appropriate boundary. This adds a new trait that abstracts everything Python bindings need and makes those bindings go through a `dyn` trait object. Later we’ll have two implementations of this trait, and the same bindings can use either. Differential Revision: https://phab.mercurial-scm.org/D10362
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
45613
496537c9c1b4 rust: start plugging the dirstate tree behind a feature gate
Raphaël Gomès <rgomes@octobus.net>
parents: 45378
diff changeset
    12
use crate::utils::path_auditor::PathAuditor;
43649
8210c3f46912 rust: introduce SIZE_FROM_OTHER_PARENT constant
Raphaël Gomès <rgomes@octobus.net>
parents: 43648
diff changeset
    13
use crate::{
8210c3f46912 rust: introduce SIZE_FROM_OTHER_PARENT constant
Raphaël Gomès <rgomes@octobus.net>
parents: 43648
diff changeset
    14
    dirstate::SIZE_FROM_OTHER_PARENT,
44538
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
    15
    filepatterns::PatternFileWarning,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
    16
    matchers::{get_ignore_function, Matcher, VisitChildrenSet},
43649
8210c3f46912 rust: introduce SIZE_FROM_OTHER_PARENT constant
Raphaël Gomès <rgomes@octobus.net>
parents: 43648
diff changeset
    17
    utils::{
44538
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
    18
        files::{find_dirs, HgMetadata},
44533
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44268
diff changeset
    19
        hg_path::{
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44268
diff changeset
    20
            hg_path_to_path_buf, os_string_to_hg_path_buf, HgPath, HgPathBuf,
44538
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
    21
            HgPathError,
44533
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44268
diff changeset
    22
        },
43649
8210c3f46912 rust: introduce SIZE_FROM_OTHER_PARENT constant
Raphaël Gomès <rgomes@octobus.net>
parents: 43648
diff changeset
    23
    },
44537
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
    24
    CopyMap, DirstateEntry, DirstateMap, EntryState, FastHashMap,
44538
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
    25
    PatternError,
43649
8210c3f46912 rust: introduce SIZE_FROM_OTHER_PARENT constant
Raphaël Gomès <rgomes@octobus.net>
parents: 43648
diff changeset
    26
};
44538
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
    27
use lazy_static::lazy_static;
44551
d880805d5442 hg-core: add function timing information
Raphaël Gomès <rgomes@octobus.net>
parents: 44549
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::*;
44538
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
    30
use std::{
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
    31
    borrow::Cow,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
    32
    collections::HashSet,
46512
6c778d20c8c2 rust: replace ToString impls with Display
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
    33
    fmt,
44538
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
    34
    fs::{read_dir, DirEntry},
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
    35
    io::ErrorKind,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
    36
    ops::Deref,
44604
e62052d0f377 rust-status: only involve ignore mechanism when needed
Raphaël Gomès <rgomes@octobus.net>
parents: 44571
diff changeset
    37
    path::{Path, PathBuf},
44538
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
    38
};
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    39
44536
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
    40
/// Wrong type of file from a `BadMatch`
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
    41
/// Note: a lot of those don't exist on all platforms.
44546
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44545
diff changeset
    42
#[derive(Debug, Copy, Clone)]
44536
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
    43
pub enum BadType {
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
    44
    CharacterDevice,
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
    45
    BlockDevice,
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
    46
    FIFO,
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
    47
    Socket,
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
    48
    Directory,
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
    49
    Unknown,
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
    50
}
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
    51
46512
6c778d20c8c2 rust: replace ToString impls with Display
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
    52
impl fmt::Display for BadType {
6c778d20c8c2 rust: replace ToString impls with Display
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
    53
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6c778d20c8c2 rust: replace ToString impls with Display
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
    54
        f.write_str(match self {
44539
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
diff changeset
    55
            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: 44538
diff changeset
    56
            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: 44538
diff changeset
    57
            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: 44538
diff changeset
    58
            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: 44538
diff changeset
    59
            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: 44538
diff changeset
    60
            BadType::Unknown => "unknown",
46512
6c778d20c8c2 rust: replace ToString impls with Display
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
    61
        })
44539
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44538
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: 44538
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: 44538
diff changeset
    64
44536
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
    65
/// Was explicitly matched but cannot be found/accessed
44546
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44545
diff changeset
    66
#[derive(Debug, Copy, Clone)]
44536
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
    67
pub enum BadMatch {
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
    68
    OsError(i32),
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
    69
    BadType(BadType),
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
    70
}
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
    71
45112
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
    72
/// Enum used to dispatch new status entries into the right collections.
43646
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
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: 43508
diff changeset
    74
/// entries during the lifetime of a command.
44546
f8a9922a02cb rust-status: move to recursive traversal to prepare for parallel traversal
Raphaël Gomès <rgomes@octobus.net>
parents: 44545
diff changeset
    75
#[derive(Debug, Copy, Clone)]
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
    76
pub enum Dispatch {
43646
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
    77
    Unsure,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
    78
    Modified,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
    79
    Added,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
    80
    Removed,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
    81
    Deleted,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
    82
    Clean,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
    83
    Unknown,
44536
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
    84
    Ignored,
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
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: 44535
diff changeset
    86
    None,
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
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: 44535
diff changeset
    88
    Bad(BadMatch),
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
    89
    Directory {
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
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: 44535
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: 44535
diff changeset
    92
        was_file: bool,
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
    93
    },
43646
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
    94
}
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
    95
43921
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43836
diff changeset
    96
type IoResult<T> = std::io::Result<T>;
45112
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
    97
44604
e62052d0f377 rust-status: only involve ignore mechanism when needed
Raphaël Gomès <rgomes@octobus.net>
parents: 44571
diff changeset
    98
/// `Box<dyn Trait>` is syntactic sugar for `Box<dyn Trait, 'static>`, so add
e62052d0f377 rust-status: only involve ignore mechanism when needed
Raphaël Gomès <rgomes@octobus.net>
parents: 44571
diff changeset
    99
/// an explicit lifetime here to not fight `'static` bounds "out of nowhere".
e62052d0f377 rust-status: only involve ignore mechanism when needed
Raphaël Gomès <rgomes@octobus.net>
parents: 44571
diff changeset
   100
type IgnoreFnType<'a> = Box<dyn for<'r> Fn(&'r HgPath) -> bool + Sync + 'a>;
43921
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43836
diff changeset
   101
45112
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   102
/// We have a good mix of owned (from directory traversal) and borrowed (from
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   103
/// the dirstate/explicit) paths, this comes up a lot.
45113
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Raphaël Gomès <rgomes@octobus.net>
parents: 45112
diff changeset
   104
pub type HgPathCow<'a> = Cow<'a, HgPath>;
45112
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   105
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   106
/// A path with its computed ``Dispatch`` information
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   107
type DispatchedPath<'a> = (HgPathCow<'a>, Dispatch);
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   108
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   109
/// The conversion from `HgPath` to a real fs path failed.
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   110
/// `22` is the error code for "Invalid argument"
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   111
const INVALID_PATH_DISPATCH: Dispatch = Dispatch::Bad(BadMatch::OsError(22));
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   112
43648
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43647
diff changeset
   113
/// 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: 43647
diff changeset
   114
/// 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: 43647
diff changeset
   115
/// 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: 43647
diff changeset
   116
/// changes. (issue2608)
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43647
diff changeset
   117
/// 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: 43647
diff changeset
   118
/// 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: 43647
diff changeset
   119
/// caller to cast `b` as `i32`.
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43647
diff changeset
   120
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: 43647
diff changeset
   121
    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: 43647
diff changeset
   122
}
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43647
diff changeset
   123
44533
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44268
diff changeset
   124
/// 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: 44268
diff changeset
   125
/// in the directory.
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44268
diff changeset
   126
///
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44268
diff changeset
   127
/// * `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: 44268
diff changeset
   128
fn list_directory(
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44268
diff changeset
   129
    path: impl AsRef<Path>,
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44268
diff changeset
   130
    skip_dot_hg: bool,
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44268
diff changeset
   131
) -> std::io::Result<Vec<(HgPathBuf, DirEntry)>> {
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44268
diff changeset
   132
    let mut results = vec![];
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44268
diff changeset
   133
    let entries = read_dir(path.as_ref())?;
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44268
diff changeset
   134
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44268
diff changeset
   135
    for entry in entries {
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44268
diff changeset
   136
        let entry = entry?;
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44268
diff changeset
   137
        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: 44268
diff changeset
   138
        let file_type = entry.file_type()?;
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44268
diff changeset
   139
        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: 44268
diff changeset
   140
            return Ok(vec![]);
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44268
diff changeset
   141
        } else {
44998
26114bd6ec60 rust: do a clippy pass
Raphaël Gomès <rgomes@octobus.net>
parents: 44967
diff changeset
   142
            results.push((filename, entry))
44533
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44268
diff changeset
   143
        }
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44268
diff changeset
   144
    }
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44268
diff changeset
   145
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44268
diff changeset
   146
    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: 44268
diff changeset
   147
    Ok(results)
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44268
diff changeset
   148
}
0d97bcb3cee9 rust-status: add util for listing a directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44268
diff changeset
   149
43646
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   150
/// 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: 43508
diff changeset
   151
fn dispatch_found(
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   152
    filename: impl AsRef<HgPath>,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   153
    entry: DirstateEntry,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   154
    metadata: HgMetadata,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   155
    copy_map: &CopyMap,
44534
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44533
diff changeset
   156
    options: StatusOptions,
43646
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   157
) -> Dispatch {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   158
    let DirstateEntry {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   159
        state,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   160
        mode,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   161
        mtime,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   162
        size,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   163
    } = entry;
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   164
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   165
    let HgMetadata {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   166
        st_mode,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   167
        st_size,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   168
        st_mtime,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   169
        ..
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   170
    } = metadata;
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   171
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   172
    match state {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   173
        EntryState::Normal => {
43648
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43647
diff changeset
   174
            let size_changed = mod_compare(size, st_size as i32);
43646
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   175
            let mode_changed =
44534
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44533
diff changeset
   176
                (mode ^ st_mode as i32) & 0o100 != 0o000 && options.check_exec;
43648
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43647
diff changeset
   177
            let metadata_changed = size >= 0 && (size_changed || mode_changed);
43649
8210c3f46912 rust: introduce SIZE_FROM_OTHER_PARENT constant
Raphaël Gomès <rgomes@octobus.net>
parents: 43648
diff changeset
   178
            let other_parent = size == SIZE_FROM_OTHER_PARENT;
44998
26114bd6ec60 rust: do a clippy pass
Raphaël Gomès <rgomes@octobus.net>
parents: 44967
diff changeset
   179
43648
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43647
diff changeset
   180
            if metadata_changed
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43647
diff changeset
   181
                || other_parent
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43647
diff changeset
   182
                || copy_map.contains_key(filename.as_ref())
43646
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   183
            {
46770
3c9ddb1986a9 rust-status: fix issue6456 for the Rust implementation also
Raphaël Gomès <rgomes@octobus.net>
parents: 46546
diff changeset
   184
                if metadata.is_symlink() && size_changed {
3c9ddb1986a9 rust-status: fix issue6456 for the Rust implementation also
Raphaël Gomès <rgomes@octobus.net>
parents: 46546
diff changeset
   185
                    // issue6456: Size returned may be longer due to encryption
3c9ddb1986a9 rust-status: fix issue6456 for the Rust implementation also
Raphaël Gomès <rgomes@octobus.net>
parents: 46546
diff changeset
   186
                    // on EXT-4 fscrypt. TODO maybe only do it on EXT4?
3c9ddb1986a9 rust-status: fix issue6456 for the Rust implementation also
Raphaël Gomès <rgomes@octobus.net>
parents: 46546
diff changeset
   187
                    Dispatch::Unsure
3c9ddb1986a9 rust-status: fix issue6456 for the Rust implementation also
Raphaël Gomès <rgomes@octobus.net>
parents: 46546
diff changeset
   188
                } else {
3c9ddb1986a9 rust-status: fix issue6456 for the Rust implementation also
Raphaël Gomès <rgomes@octobus.net>
parents: 46546
diff changeset
   189
                    Dispatch::Modified
3c9ddb1986a9 rust-status: fix issue6456 for the Rust implementation also
Raphaël Gomès <rgomes@octobus.net>
parents: 46546
diff changeset
   190
                }
44998
26114bd6ec60 rust: do a clippy pass
Raphaël Gomès <rgomes@octobus.net>
parents: 44967
diff changeset
   191
            } else if mod_compare(mtime, st_mtime as i32)
26114bd6ec60 rust: do a clippy pass
Raphaël Gomès <rgomes@octobus.net>
parents: 44967
diff changeset
   192
                || st_mtime == options.last_normal_time
26114bd6ec60 rust: do a clippy pass
Raphaël Gomès <rgomes@octobus.net>
parents: 44967
diff changeset
   193
            {
43646
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   194
                // the file may have just been marked as normal and
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   195
                // it may have changed in the same second without
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   196
                // changing its size. This can happen if we quickly
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   197
                // do multiple commits. Force lookup, so we don't
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   198
                // miss such a racy file change.
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   199
                Dispatch::Unsure
44534
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44533
diff changeset
   200
            } else if options.list_clean {
43646
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   201
                Dispatch::Clean
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   202
            } else {
44538
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   203
                Dispatch::None
43646
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   204
            }
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   205
        }
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   206
        EntryState::Merged => Dispatch::Modified,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   207
        EntryState::Added => Dispatch::Added,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   208
        EntryState::Removed => Dispatch::Removed,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   209
        EntryState::Unknown => Dispatch::Unknown,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   210
    }
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   211
}
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   212
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   213
/// The file corresponding to this Dirstate entry is missing.
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   214
fn dispatch_missing(state: EntryState) -> Dispatch {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   215
    match state {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   216
        // File was removed from the filesystem during commands
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   217
        EntryState::Normal | EntryState::Merged | EntryState::Added => {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   218
            Dispatch::Deleted
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   219
        }
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   220
        // File was removed, everything is normal
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   221
        EntryState::Removed => Dispatch::Removed,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   222
        // File is unknown to Mercurial, everything is normal
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   223
        EntryState::Unknown => Dispatch::Unknown,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   224
    }
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   225
}
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   226
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   227
fn dispatch_os_error(e: &std::io::Error) -> Dispatch {
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   228
    Dispatch::Bad(BadMatch::OsError(
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   229
        e.raw_os_error().expect("expected real OS error"),
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   230
    ))
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   231
}
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   232
44538
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   233
lazy_static! {
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   234
    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: 44537
diff changeset
   235
        let mut h = HashSet::new();
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   236
        h.insert(HgPath::new(b""));
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   237
        h
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   238
    };
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   239
}
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   240
44534
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44533
diff changeset
   241
#[derive(Debug, Copy, Clone)]
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44533
diff changeset
   242
pub struct StatusOptions {
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44533
diff changeset
   243
    /// 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: 44533
diff changeset
   244
    /// 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: 44533
diff changeset
   245
    /// that happen within the same timeslot.
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44533
diff changeset
   246
    pub last_normal_time: i64,
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44533
diff changeset
   247
    /// 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: 44533
diff changeset
   248
    pub check_exec: bool,
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44533
diff changeset
   249
    pub list_clean: bool,
44537
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   250
    pub list_unknown: bool,
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   251
    pub list_ignored: bool,
44897
c802ec4f7196 rust-status: collect traversed directories if required
Raphaël Gomès <rgomes@octobus.net>
parents: 44896
diff changeset
   252
    /// Whether to collect traversed dirs for applying a callback later.
c802ec4f7196 rust-status: collect traversed directories if required
Raphaël Gomès <rgomes@octobus.net>
parents: 44896
diff changeset
   253
    /// Used by `hg purge` for example.
c802ec4f7196 rust-status: collect traversed directories if required
Raphaël Gomès <rgomes@octobus.net>
parents: 44896
diff changeset
   254
    pub collect_traversed_dirs: bool,
44537
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   255
}
1debb5894b39 rust-status: add function for sequential traversal of the working directory
Raphaël Gomès <rgomes@octobus.net>
parents: 44536
diff changeset
   256
44571
ece43c79333e rust-core: add missing `Debug` traits
Raphaël Gomès <rgomes@octobus.net>
parents: 44551
diff changeset
   257
#[derive(Debug)]
44535
f13d19549efd rust-status: rename `StatusResult` to `DirstateStatus`
Raphaël Gomès <rgomes@octobus.net>
parents: 44534
diff changeset
   258
pub struct DirstateStatus<'a> {
45112
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   259
    pub modified: Vec<HgPathCow<'a>>,
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   260
    pub added: Vec<HgPathCow<'a>>,
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   261
    pub removed: Vec<HgPathCow<'a>>,
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   262
    pub deleted: Vec<HgPathCow<'a>>,
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   263
    pub clean: Vec<HgPathCow<'a>>,
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   264
    pub ignored: Vec<HgPathCow<'a>>,
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   265
    pub unknown: Vec<HgPathCow<'a>>,
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   266
    pub bad: Vec<(HgPathCow<'a>, BadMatch)>,
44897
c802ec4f7196 rust-status: collect traversed directories if required
Raphaël Gomès <rgomes@octobus.net>
parents: 44896
diff changeset
   267
    /// Only filled if `collect_traversed_dirs` is `true`
c802ec4f7196 rust-status: collect traversed directories if required
Raphaël Gomès <rgomes@octobus.net>
parents: 44896
diff changeset
   268
    pub traversed: Vec<HgPathBuf>,
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   269
}
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   270
46503
2e2033081274 rust: replace trivial `impl From …` with `#[derive(derive_more::From)]`
Simon Sapin <simon.sapin@octobus.net>
parents: 46058
diff changeset
   271
#[derive(Debug, derive_more::From)]
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   272
pub enum StatusError {
45112
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   273
    /// Generic IO error
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   274
    IO(std::io::Error),
45112
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   275
    /// An invalid path that cannot be represented in Mercurial was found
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   276
    Path(HgPathError),
45112
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   277
    /// An invalid "ignore" pattern was found
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   278
    Pattern(PatternError),
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   279
}
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   280
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   281
pub type StatusResult<T> = Result<T, StatusError>;
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   282
46512
6c778d20c8c2 rust: replace ToString impls with Display
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
   283
impl fmt::Display for StatusError {
6c778d20c8c2 rust: replace ToString impls with Display
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
   284
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   285
        match self {
46512
6c778d20c8c2 rust: replace ToString impls with Display
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
   286
            StatusError::IO(error) => error.fmt(f),
6c778d20c8c2 rust: replace ToString impls with Display
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
   287
            StatusError::Path(error) => error.fmt(f),
6c778d20c8c2 rust: replace ToString impls with Display
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
   288
            StatusError::Pattern(error) => error.fmt(f),
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   289
        }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   290
    }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   291
}
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   292
45112
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   293
/// Gives information about which files are changed in the working directory
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   294
/// and how, compared to the revision we're based on
47107
787ff5d21bcd dirstate-tree: Make Rust DirstateMap bindings go through a trait object
Simon Sapin <simon.sapin@octobus.net>
parents: 46890
diff changeset
   295
pub struct Status<'a, M: ?Sized + Matcher + Sync> {
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   296
    dmap: &'a DirstateMap,
45113
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Raphaël Gomès <rgomes@octobus.net>
parents: 45112
diff changeset
   297
    pub(crate) matcher: &'a M,
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   298
    root_dir: PathBuf,
45113
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Raphaël Gomès <rgomes@octobus.net>
parents: 45112
diff changeset
   299
    pub(crate) options: StatusOptions,
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   300
    ignore_fn: IgnoreFnType<'a>,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   301
}
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   302
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   303
impl<'a, M> Status<'a, M>
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   304
where
47107
787ff5d21bcd dirstate-tree: Make Rust DirstateMap bindings go through a trait object
Simon Sapin <simon.sapin@octobus.net>
parents: 46890
diff changeset
   305
    M: ?Sized + Matcher + Sync,
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   306
{
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   307
    pub fn new(
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   308
        dmap: &'a DirstateMap,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   309
        matcher: &'a M,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   310
        root_dir: PathBuf,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   311
        ignore_files: Vec<PathBuf>,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   312
        options: StatusOptions,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   313
    ) -> StatusResult<(Self, Vec<PatternFileWarning>)> {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   314
        // Needs to outlive `dir_ignore_fn` since it's captured.
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   315
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   316
        let (ignore_fn, warnings): (IgnoreFnType, _) =
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   317
            if options.list_ignored || options.list_unknown {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   318
                get_ignore_function(ignore_files, &root_dir)?
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   319
            } else {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   320
                (Box::new(|&_| true), vec![])
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   321
            };
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   322
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   323
        Ok((
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   324
            Self {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   325
                dmap,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   326
                matcher,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   327
                root_dir,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   328
                options,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   329
                ignore_fn,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   330
            },
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   331
            warnings,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   332
        ))
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   333
    }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   334
45112
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   335
    /// Is the path ignored?
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   336
    pub fn is_ignored(&self, path: impl AsRef<HgPath>) -> bool {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   337
        (self.ignore_fn)(path.as_ref())
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   338
    }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   339
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   340
    /// Is the path or one of its ancestors ignored?
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   341
    pub fn dir_ignore(&self, dir: impl AsRef<HgPath>) -> bool {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   342
        // Only involve ignore mechanism if we're listing unknowns or ignored.
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   343
        if self.options.list_ignored || self.options.list_unknown {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   344
            if self.is_ignored(&dir) {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   345
                true
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   346
            } else {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   347
                for p in find_dirs(dir.as_ref()) {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   348
                    if self.is_ignored(p) {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   349
                        return true;
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   350
                    }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   351
                }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   352
                false
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   353
            }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   354
        } else {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   355
            true
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   356
        }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   357
    }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   358
45112
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   359
    /// Get stat data about the files explicitly specified by the matcher.
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   360
    /// Returns a tuple of the directories that need to be traversed and the
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   361
    /// files with their corresponding `Dispatch`.
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   362
    /// TODO subrepos
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   363
    #[timed]
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   364
    pub fn walk_explicit(
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   365
        &self,
46058
fd47483f1645 rust: use crossbeam-channel crate directly
Simon Sapin <simon-commits@exyr.org>
parents: 45877
diff changeset
   366
        traversed_sender: crossbeam_channel::Sender<HgPathBuf>,
45112
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   367
    ) -> (Vec<DispatchedPath<'a>>, Vec<DispatchedPath<'a>>) {
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   368
        self.matcher
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   369
            .file_set()
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   370
            .unwrap_or(&DEFAULT_WORK)
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   371
            .par_iter()
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   372
            .flat_map(|&filename| -> Option<_> {
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   373
                // TODO normalization
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   374
                let normalized = filename;
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   375
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   376
                let buf = match hg_path_to_path_buf(normalized) {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   377
                    Ok(x) => x,
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   378
                    Err(_) => {
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   379
                        return Some((
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   380
                            Cow::Borrowed(normalized),
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   381
                            INVALID_PATH_DISPATCH,
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   382
                        ))
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   383
                    }
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   384
                };
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   385
                let target = self.root_dir.join(buf);
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   386
                let st = target.symlink_metadata();
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   387
                let in_dmap = self.dmap.get(normalized);
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   388
                match st {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   389
                    Ok(meta) => {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   390
                        let file_type = meta.file_type();
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   391
                        return if file_type.is_file() || file_type.is_symlink()
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   392
                        {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   393
                            if let Some(entry) = in_dmap {
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   394
                                return Some((
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   395
                                    Cow::Borrowed(normalized),
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   396
                                    dispatch_found(
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   397
                                        &normalized,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   398
                                        *entry,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   399
                                        HgMetadata::from_metadata(meta),
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   400
                                        &self.dmap.copy_map,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   401
                                        self.options,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   402
                                    ),
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   403
                                ));
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   404
                            }
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   405
                            Some((
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   406
                                Cow::Borrowed(normalized),
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   407
                                Dispatch::Unknown,
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   408
                            ))
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   409
                        } else if file_type.is_dir() {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   410
                            if self.options.collect_traversed_dirs {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   411
                                traversed_sender
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   412
                                    .send(normalized.to_owned())
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   413
                                    .expect("receiver should outlive sender");
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   414
                            }
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   415
                            Some((
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   416
                                Cow::Borrowed(normalized),
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   417
                                Dispatch::Directory {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   418
                                    was_file: in_dmap.is_some(),
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   419
                                },
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   420
                            ))
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   421
                        } else {
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   422
                            Some((
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   423
                                Cow::Borrowed(normalized),
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   424
                                Dispatch::Bad(BadMatch::BadType(
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   425
                                    // TODO do more than unknown
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   426
                                    // Support for all `BadType` variant
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   427
                                    // varies greatly between platforms.
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   428
                                    // So far, no tests check the type and
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   429
                                    // this should be good enough for most
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   430
                                    // users.
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   431
                                    BadType::Unknown,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   432
                                )),
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   433
                            ))
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   434
                        };
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   435
                    }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   436
                    Err(_) => {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   437
                        if let Some(entry) = in_dmap {
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   438
                            return Some((
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   439
                                Cow::Borrowed(normalized),
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   440
                                dispatch_missing(entry.state),
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   441
                            ));
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   442
                        }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   443
                    }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   444
                };
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   445
                None
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   446
            })
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   447
            .partition(|(_, dispatch)| match dispatch {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   448
                Dispatch::Directory { .. } => true,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   449
                _ => false,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   450
            })
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   451
    }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   452
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   453
    /// Walk the working directory recursively to look for changes compared to
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   454
    /// the current `DirstateMap`.
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   455
    ///
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   456
    /// This takes a mutable reference to the results to account for the
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   457
    /// `extend` in timings
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   458
    #[timed]
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   459
    pub fn traverse(
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   460
        &self,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   461
        path: impl AsRef<HgPath>,
45112
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   462
        old_results: &FastHashMap<HgPathCow<'a>, Dispatch>,
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   463
        results: &mut Vec<DispatchedPath<'a>>,
46058
fd47483f1645 rust: use crossbeam-channel crate directly
Simon Sapin <simon-commits@exyr.org>
parents: 45877
diff changeset
   464
        traversed_sender: crossbeam_channel::Sender<HgPathBuf>,
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   465
    ) {
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   466
        // The traversal is done in parallel, so use a channel to gather
46058
fd47483f1645 rust: use crossbeam-channel crate directly
Simon Sapin <simon-commits@exyr.org>
parents: 45877
diff changeset
   467
        // entries. `crossbeam_channel::Sender` is `Sync`, while `mpsc::Sender`
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   468
        // is not.
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   469
        let (files_transmitter, files_receiver) =
46058
fd47483f1645 rust: use crossbeam-channel crate directly
Simon Sapin <simon-commits@exyr.org>
parents: 45877
diff changeset
   470
            crossbeam_channel::unbounded();
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   471
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   472
        self.traverse_dir(
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   473
            &files_transmitter,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   474
            path,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   475
            &old_results,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   476
            traversed_sender,
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   477
        );
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   478
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   479
        // Disconnect the channel so the receiver stops waiting
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   480
        drop(files_transmitter);
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   481
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   482
        let new_results = files_receiver
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   483
            .into_iter()
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   484
            .par_bridge()
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   485
            .map(|(f, d)| (Cow::Owned(f), d));
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   486
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   487
        results.par_extend(new_results);
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   488
    }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   489
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   490
    /// Dispatch a single entry (file, folder, symlink...) found during
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   491
    /// `traverse`. If the entry is a folder that needs to be traversed, it
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   492
    /// will be handled in a separate thread.
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   493
    fn handle_traversed_entry<'b>(
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   494
        &'a self,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   495
        scope: &rayon::Scope<'b>,
46058
fd47483f1645 rust: use crossbeam-channel crate directly
Simon Sapin <simon-commits@exyr.org>
parents: 45877
diff changeset
   496
        files_sender: &'b crossbeam_channel::Sender<(HgPathBuf, Dispatch)>,
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   497
        old_results: &'a FastHashMap<Cow<HgPath>, Dispatch>,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   498
        filename: HgPathBuf,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   499
        dir_entry: DirEntry,
46058
fd47483f1645 rust: use crossbeam-channel crate directly
Simon Sapin <simon-commits@exyr.org>
parents: 45877
diff changeset
   500
        traversed_sender: crossbeam_channel::Sender<HgPathBuf>,
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   501
    ) -> IoResult<()>
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   502
    where
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   503
        'a: 'b,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   504
    {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   505
        let file_type = dir_entry.file_type()?;
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   506
        let entry_option = self.dmap.get(&filename);
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   507
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   508
        if filename.as_bytes() == b".hg" {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   509
            // Could be a directory or a symlink
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   510
            return Ok(());
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   511
        }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   512
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   513
        if file_type.is_dir() {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   514
            self.handle_traversed_dir(
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   515
                scope,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   516
                files_sender,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   517
                old_results,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   518
                entry_option,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   519
                filename,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   520
                traversed_sender,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   521
            );
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   522
        } else if file_type.is_file() || file_type.is_symlink() {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   523
            if let Some(entry) = entry_option {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   524
                if self.matcher.matches_everything()
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   525
                    || self.matcher.matches(&filename)
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   526
                {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   527
                    let metadata = dir_entry.metadata()?;
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   528
                    files_sender
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   529
                        .send((
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   530
                            filename.to_owned(),
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   531
                            dispatch_found(
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   532
                                &filename,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   533
                                *entry,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   534
                                HgMetadata::from_metadata(metadata),
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   535
                                &self.dmap.copy_map,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   536
                                self.options,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   537
                            ),
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   538
                        ))
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   539
                        .unwrap();
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   540
                }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   541
            } else if (self.matcher.matches_everything()
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   542
                || self.matcher.matches(&filename))
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   543
                && !self.is_ignored(&filename)
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   544
            {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   545
                if (self.options.list_ignored
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   546
                    || self.matcher.exact_match(&filename))
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   547
                    && self.dir_ignore(&filename)
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   548
                {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   549
                    if self.options.list_ignored {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   550
                        files_sender
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   551
                            .send((filename.to_owned(), Dispatch::Ignored))
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   552
                            .unwrap();
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   553
                    }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   554
                } else if self.options.list_unknown {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   555
                    files_sender
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   556
                        .send((filename.to_owned(), Dispatch::Unknown))
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   557
                        .unwrap();
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   558
                }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   559
            } else if self.is_ignored(&filename) && self.options.list_ignored {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   560
                files_sender
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   561
                    .send((filename.to_owned(), Dispatch::Ignored))
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   562
                    .unwrap();
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   563
            }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   564
        } else if let Some(entry) = entry_option {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   565
            // Used to be a file or a folder, now something else.
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   566
            if self.matcher.matches_everything()
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   567
                || self.matcher.matches(&filename)
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   568
            {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   569
                files_sender
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   570
                    .send((filename.to_owned(), dispatch_missing(entry.state)))
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   571
                    .unwrap();
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   572
            }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   573
        }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   574
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   575
        Ok(())
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   576
    }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   577
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   578
    /// A directory was found in the filesystem and needs to be traversed
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   579
    fn handle_traversed_dir<'b>(
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   580
        &'a self,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   581
        scope: &rayon::Scope<'b>,
46058
fd47483f1645 rust: use crossbeam-channel crate directly
Simon Sapin <simon-commits@exyr.org>
parents: 45877
diff changeset
   582
        files_sender: &'b crossbeam_channel::Sender<(HgPathBuf, Dispatch)>,
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   583
        old_results: &'a FastHashMap<Cow<HgPath>, Dispatch>,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   584
        entry_option: Option<&'a DirstateEntry>,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   585
        directory: HgPathBuf,
46058
fd47483f1645 rust: use crossbeam-channel crate directly
Simon Sapin <simon-commits@exyr.org>
parents: 45877
diff changeset
   586
        traversed_sender: crossbeam_channel::Sender<HgPathBuf>,
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   587
    ) where
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   588
        'a: 'b,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   589
    {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   590
        scope.spawn(move |_| {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   591
            // Nested `if` until `rust-lang/rust#53668` is stable
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   592
            if let Some(entry) = entry_option {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   593
                // Used to be a file, is now a folder
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   594
                if self.matcher.matches_everything()
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   595
                    || self.matcher.matches(&directory)
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   596
                {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   597
                    files_sender
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   598
                        .send((
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   599
                            directory.to_owned(),
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   600
                            dispatch_missing(entry.state),
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   601
                        ))
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   602
                        .unwrap();
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   603
                }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   604
            }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   605
            // Do we need to traverse it?
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   606
            if !self.is_ignored(&directory) || self.options.list_ignored {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   607
                self.traverse_dir(
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   608
                    files_sender,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   609
                    directory,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   610
                    &old_results,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   611
                    traversed_sender,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   612
                )
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   613
            }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   614
        });
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   615
    }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   616
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   617
    /// Decides whether the directory needs to be listed, and if so handles the
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   618
    /// entries in a separate thread.
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   619
    fn traverse_dir(
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   620
        &self,
46058
fd47483f1645 rust: use crossbeam-channel crate directly
Simon Sapin <simon-commits@exyr.org>
parents: 45877
diff changeset
   621
        files_sender: &crossbeam_channel::Sender<(HgPathBuf, Dispatch)>,
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   622
        directory: impl AsRef<HgPath>,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   623
        old_results: &FastHashMap<Cow<HgPath>, Dispatch>,
46058
fd47483f1645 rust: use crossbeam-channel crate directly
Simon Sapin <simon-commits@exyr.org>
parents: 45877
diff changeset
   624
        traversed_sender: crossbeam_channel::Sender<HgPathBuf>,
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   625
    ) {
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   626
        let directory = directory.as_ref();
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   627
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   628
        if self.options.collect_traversed_dirs {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   629
            traversed_sender
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   630
                .send(directory.to_owned())
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   631
                .expect("receiver should outlive sender");
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   632
        }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   633
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   634
        let visit_entries = match self.matcher.visit_children_set(directory) {
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   635
            VisitChildrenSet::Empty => return,
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   636
            VisitChildrenSet::This | VisitChildrenSet::Recursive => None,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   637
            VisitChildrenSet::Set(set) => Some(set),
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   638
        };
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   639
        let buf = match hg_path_to_path_buf(directory) {
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   640
            Ok(b) => b,
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   641
            Err(_) => {
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   642
                files_sender
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   643
                    .send((directory.to_owned(), INVALID_PATH_DISPATCH))
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   644
                    .expect("receiver should outlive sender");
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   645
                return;
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   646
            }
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   647
        };
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   648
        let dir_path = self.root_dir.join(buf);
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   649
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   650
        let skip_dot_hg = !directory.as_bytes().is_empty();
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   651
        let entries = match list_directory(dir_path, skip_dot_hg) {
45112
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   652
            Err(e) => {
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   653
                files_sender
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   654
                    .send((directory.to_owned(), dispatch_os_error(&e)))
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   655
                    .expect("receiver should outlive sender");
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   656
                return;
45112
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   657
            }
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   658
            Ok(entries) => entries,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   659
        };
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   660
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   661
        rayon::scope(|scope| {
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   662
            for (filename, dir_entry) in entries {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   663
                if let Some(ref set) = visit_entries {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   664
                    if !set.contains(filename.deref()) {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   665
                        continue;
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   666
                    }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   667
                }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   668
                // TODO normalize
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   669
                let filename = if directory.is_empty() {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   670
                    filename.to_owned()
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   671
                } else {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   672
                    directory.join(&filename)
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   673
                };
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   674
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   675
                if !old_results.contains_key(filename.deref()) {
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   676
                    match self.handle_traversed_entry(
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   677
                        scope,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   678
                        files_sender,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   679
                        old_results,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   680
                        filename,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   681
                        dir_entry,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   682
                        traversed_sender.clone(),
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   683
                    ) {
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   684
                        Err(e) => {
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   685
                            files_sender
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   686
                                .send((
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   687
                                    directory.to_owned(),
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   688
                                    dispatch_os_error(&e),
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   689
                                ))
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   690
                                .expect("receiver should outlive sender");
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   691
                        }
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   692
                        Ok(_) => {}
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   693
                    }
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   694
                }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   695
            }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   696
        })
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   697
    }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   698
45613
496537c9c1b4 rust: start plugging the dirstate tree behind a feature gate
Raphaël Gomès <rgomes@octobus.net>
parents: 45378
diff changeset
   699
    /// Add the files in the dirstate to the results.
496537c9c1b4 rust: start plugging the dirstate tree behind a feature gate
Raphaël Gomès <rgomes@octobus.net>
parents: 45378
diff changeset
   700
    ///
496537c9c1b4 rust: start plugging the dirstate tree behind a feature gate
Raphaël Gomès <rgomes@octobus.net>
parents: 45378
diff changeset
   701
    /// This takes a mutable reference to the results to account for the
496537c9c1b4 rust: start plugging the dirstate tree behind a feature gate
Raphaël Gomès <rgomes@octobus.net>
parents: 45378
diff changeset
   702
    /// `extend` in timings
496537c9c1b4 rust: start plugging the dirstate tree behind a feature gate
Raphaël Gomès <rgomes@octobus.net>
parents: 45378
diff changeset
   703
    #[timed]
496537c9c1b4 rust: start plugging the dirstate tree behind a feature gate
Raphaël Gomès <rgomes@octobus.net>
parents: 45378
diff changeset
   704
    pub fn extend_from_dmap(&self, results: &mut Vec<DispatchedPath<'a>>) {
46367
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   705
        results.par_extend(
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   706
            self.dmap
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   707
                .par_iter()
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   708
                .filter(|(path, _)| self.matcher.matches(path))
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   709
                .map(move |(filename, entry)| {
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   710
                    let filename: &HgPath = filename;
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   711
                    let filename_as_path = match hg_path_to_path_buf(filename)
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   712
                    {
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   713
                        Ok(f) => f,
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   714
                        Err(_) => {
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   715
                            return (
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   716
                                Cow::Borrowed(filename),
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   717
                                INVALID_PATH_DISPATCH,
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   718
                            )
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   719
                        }
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   720
                    };
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   721
                    let meta = self
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   722
                        .root_dir
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   723
                        .join(filename_as_path)
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   724
                        .symlink_metadata();
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   725
                    match meta {
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   726
                        Ok(m)
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   727
                            if !(m.file_type().is_file()
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   728
                                || m.file_type().is_symlink()) =>
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   729
                        {
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   730
                            (
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   731
                                Cow::Borrowed(filename),
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   732
                                dispatch_missing(entry.state),
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   733
                            )
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   734
                        }
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   735
                        Ok(m) => (
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   736
                            Cow::Borrowed(filename),
46367
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   737
                            dispatch_found(
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   738
                                filename,
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   739
                                *entry,
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   740
                                HgMetadata::from_metadata(m),
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   741
                                &self.dmap.copy_map,
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   742
                                self.options,
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   743
                            ),
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   744
                        ),
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   745
                        Err(e)
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   746
                            if e.kind() == ErrorKind::NotFound
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   747
                                || e.raw_os_error() == Some(20) =>
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   748
                        {
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   749
                            // Rust does not yet have an `ErrorKind` for
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   750
                            // `NotADirectory` (errno 20)
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   751
                            // It happens if the dirstate contains `foo/bar`
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   752
                            // and foo is not a
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   753
                            // directory
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   754
                            (
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   755
                                Cow::Borrowed(filename),
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   756
                                dispatch_missing(entry.state),
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   757
                            )
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   758
                        }
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   759
                        Err(e) => {
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   760
                            (Cow::Borrowed(filename), dispatch_os_error(&e))
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   761
                        }
45613
496537c9c1b4 rust: start plugging the dirstate tree behind a feature gate
Raphaël Gomès <rgomes@octobus.net>
parents: 45378
diff changeset
   762
                    }
46367
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   763
                }),
fb6eca7b8c63 rust-status: honor matcher when using the dirstate-only fast-path (issue6483)
Raphaël Gomès <rgomes@octobus.net>
parents: 46058
diff changeset
   764
        );
45613
496537c9c1b4 rust: start plugging the dirstate tree behind a feature gate
Raphaël Gomès <rgomes@octobus.net>
parents: 45378
diff changeset
   765
    }
496537c9c1b4 rust: start plugging the dirstate tree behind a feature gate
Raphaël Gomès <rgomes@octobus.net>
parents: 45378
diff changeset
   766
45112
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   767
    /// Checks all files that are in the dirstate but were not found during the
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   768
    /// working directory traversal. This means that the rest must
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   769
    /// be either ignored, under a symlink or under a new nested repo.
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   770
    ///
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   771
    /// This takes a mutable reference to the results to account for the
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   772
    /// `extend` in timings
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   773
    #[timed]
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   774
    pub fn handle_unknowns(&self, results: &mut Vec<DispatchedPath<'a>>) {
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   775
        let to_visit: Vec<(&HgPath, &DirstateEntry)> =
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   776
            if results.is_empty() && self.matcher.matches_everything() {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   777
                self.dmap.iter().map(|(f, e)| (f.deref(), e)).collect()
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   778
            } else {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   779
                // Only convert to a hashmap if needed.
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   780
                let old_results: FastHashMap<_, _> =
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   781
                    results.iter().cloned().collect();
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   782
                self.dmap
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   783
                    .iter()
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   784
                    .filter_map(move |(f, e)| {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   785
                        if !old_results.contains_key(f.deref())
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   786
                            && self.matcher.matches(f)
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   787
                        {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   788
                            Some((f.deref(), e))
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   789
                        } else {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   790
                            None
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   791
                        }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   792
                    })
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   793
                    .collect()
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   794
            };
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   795
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   796
        let path_auditor = PathAuditor::new(&self.root_dir);
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   797
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   798
        let new_results = to_visit.into_par_iter().filter_map(
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   799
            |(filename, entry)| -> Option<_> {
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   800
                // Report ignored items in the dmap as long as they are not
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   801
                // under a symlink directory.
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   802
                if path_auditor.check(filename) {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   803
                    // TODO normalize for case-insensitive filesystems
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   804
                    let buf = match hg_path_to_path_buf(filename) {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   805
                        Ok(x) => x,
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   806
                        Err(_) => {
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   807
                            return Some((
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   808
                                Cow::Owned(filename.to_owned()),
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   809
                                INVALID_PATH_DISPATCH,
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   810
                            ));
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   811
                        }
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   812
                    };
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   813
                    Some((
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   814
                        Cow::Owned(filename.to_owned()),
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   815
                        match self.root_dir.join(&buf).symlink_metadata() {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   816
                            // File was just ignored, no links, and exists
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   817
                            Ok(meta) => {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   818
                                let metadata = HgMetadata::from_metadata(meta);
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   819
                                dispatch_found(
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   820
                                    filename,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   821
                                    *entry,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   822
                                    metadata,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   823
                                    &self.dmap.copy_map,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   824
                                    self.options,
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   825
                                )
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   826
                            }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   827
                            // File doesn't exist
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   828
                            Err(_) => dispatch_missing(entry.state),
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   829
                        },
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   830
                    ))
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   831
                } else {
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   832
                    // It's either missing or under a symlink directory which
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   833
                    // we, in this case, report as missing.
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   834
                    Some((
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   835
                        Cow::Owned(filename.to_owned()),
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   836
                        dispatch_missing(entry.state),
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   837
                    ))
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   838
                }
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   839
            },
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   840
        );
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   841
45877
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Raphaël Gomès <rgomes@octobus.net>
parents: 45618
diff changeset
   842
        results.par_extend(new_results);
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   843
    }
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   844
}
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   845
44551
d880805d5442 hg-core: add function timing information
Raphaël Gomès <rgomes@octobus.net>
parents: 44549
diff changeset
   846
#[timed]
45113
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Raphaël Gomès <rgomes@octobus.net>
parents: 45112
diff changeset
   847
pub fn build_response<'a>(
45112
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   848
    results: impl IntoIterator<Item = DispatchedPath<'a>>,
44897
c802ec4f7196 rust-status: collect traversed directories if required
Raphaël Gomès <rgomes@octobus.net>
parents: 44896
diff changeset
   849
    traversed: Vec<HgPathBuf>,
45112
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   850
) -> (Vec<HgPathCow<'a>>, DirstateStatus<'a>) {
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   851
    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
   852
    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
   853
    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
   854
    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
   855
    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
   856
    let mut clean = vec![];
44536
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   857
    let mut ignored = vec![];
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   858
    let mut unknown = vec![];
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   859
    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
   860
44538
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   861
    for (filename, dispatch) in results.into_iter() {
43646
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   862
        match dispatch {
44536
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   863
            Dispatch::Unknown => unknown.push(filename),
43646
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   864
            Dispatch::Unsure => lookup.push(filename),
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   865
            Dispatch::Modified => modified.push(filename),
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   866
            Dispatch::Added => added.push(filename),
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   867
            Dispatch::Removed => removed.push(filename),
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   868
            Dispatch::Deleted => deleted.push(filename),
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43508
diff changeset
   869
            Dispatch::Clean => clean.push(filename),
44536
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   870
            Dispatch::Ignored => ignored.push(filename),
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   871
            Dispatch::None => {}
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   872
            Dispatch::Bad(reason) => bad.push((filename, reason)),
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   873
            Dispatch::Directory { .. } => {}
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   874
        }
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   875
    }
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   876
44538
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   877
    (
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   878
        lookup,
44535
f13d19549efd rust-status: rename `StatusResult` to `DirstateStatus`
Raphaël Gomès <rgomes@octobus.net>
parents: 44534
diff changeset
   879
        DirstateStatus {
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   880
            modified,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   881
            added,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   882
            removed,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   883
            deleted,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   884
            clean,
44536
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   885
            ignored,
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   886
            unknown,
61709b844420 rust-status: add missing variants to `Dispatch` enum
Raphaël Gomès <rgomes@octobus.net>
parents: 44535
diff changeset
   887
            bad,
44897
c802ec4f7196 rust-status: collect traversed directories if required
Raphaël Gomès <rgomes@octobus.net>
parents: 44896
diff changeset
   888
            traversed,
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   889
        },
44538
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   890
    )
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   891
}
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   892
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   893
/// 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: 44537
diff changeset
   894
///
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   895
/// 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: 44537
diff changeset
   896
/// 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: 44537
diff changeset
   897
/// information that will not be necessary in the future.
44551
d880805d5442 hg-core: add function timing information
Raphaël Gomès <rgomes@octobus.net>
parents: 44549
diff changeset
   898
#[timed]
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   899
pub fn status<'a>(
43921
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43836
diff changeset
   900
    dmap: &'a DirstateMap,
47107
787ff5d21bcd dirstate-tree: Make Rust DirstateMap bindings go through a trait object
Simon Sapin <simon.sapin@octobus.net>
parents: 46890
diff changeset
   901
    matcher: &'a (dyn Matcher + Sync),
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   902
    root_dir: PathBuf,
44604
e62052d0f377 rust-status: only involve ignore mechanism when needed
Raphaël Gomès <rgomes@octobus.net>
parents: 44571
diff changeset
   903
    ignore_files: Vec<PathBuf>,
44534
483fce658e43 rust-status: refactor options into a `StatusOptions` struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44533
diff changeset
   904
    options: StatusOptions,
44538
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   905
) -> StatusResult<(
45112
470d306e616c rust-status: improve documentation and readability
Raphaël Gomès <rgomes@octobus.net>
parents: 45111
diff changeset
   906
    (Vec<HgPathCow<'a>>, DirstateStatus<'a>),
44538
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   907
    Vec<PatternFileWarning>,
c8891bca40fb rust-status: add bare `hg status` support in hg-core
Raphaël Gomès <rgomes@octobus.net>
parents: 44537
diff changeset
   908
)> {
45113
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Raphaël Gomès <rgomes@octobus.net>
parents: 45112
diff changeset
   909
    let (status, warnings) =
45111
7528699c6ccb rust-status: refactor status into a struct
Raphaël Gomès <rgomes@octobus.net>
parents: 44998
diff changeset
   910
        Status::new(dmap, matcher, root_dir, ignore_files, options)?;
44897
c802ec4f7196 rust-status: collect traversed directories if required
Raphaël Gomès <rgomes@octobus.net>
parents: 44896
diff changeset
   911
45113
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Raphaël Gomès <rgomes@octobus.net>
parents: 45112
diff changeset
   912
    Ok((status.run()?, warnings))
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   913
}