rust/hg-core/src/dirstate/status.rs
author Raphaël Gomès <rgomes@octobus.net>
Fri, 29 Nov 2019 18:33:56 +0100
changeset 43832 1bb4e9b02984
parent 43818 ce088b38f92b
child 43915 8c77826116f7
permissions -rw-r--r--
rust-matchers: improve `Matcher` trait ergonomics `VisitChildrenSet` has no need to own the set, this will save allocations. The `file_set` return type change is motivated by both ergonomics and... being able to compile code. The `AlwaysMatcher` does not store a `file_set`, which requires it to return an owned `HashSet`, which in turn would change our return type to `Cow<&HgPath>` (lifetimes omitted). This is both un-ergonomic and troublesome for more complex lifetime issues (especially with the upcoming `FileMatcher` in the following patch). Differential Revision: https://phab.mercurial-scm.org/D7525
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     1
// status.rs
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     2
//
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     3
// Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     4
//
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     5
// This software may be used and distributed according to the terms of the
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     6
// GNU General Public License version 2 or any later version.
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     7
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     8
//! Rust implementation of dirstate.status (dirstate.py).
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     9
//! It is currently missing a lot of functionality compared to the Python one
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    10
//! and will only be triggered in narrow cases.
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    11
43605
8210c3f46912 rust: introduce SIZE_FROM_OTHER_PARENT constant
Raphaël Gomès <rgomes@octobus.net>
parents: 43604
diff changeset
    12
use crate::{
8210c3f46912 rust: introduce SIZE_FROM_OTHER_PARENT constant
Raphaël Gomès <rgomes@octobus.net>
parents: 43604
diff changeset
    13
    dirstate::SIZE_FROM_OTHER_PARENT,
8210c3f46912 rust: introduce SIZE_FROM_OTHER_PARENT constant
Raphaël Gomès <rgomes@octobus.net>
parents: 43604
diff changeset
    14
    utils::{
8210c3f46912 rust: introduce SIZE_FROM_OTHER_PARENT constant
Raphaël Gomès <rgomes@octobus.net>
parents: 43604
diff changeset
    15
        files::HgMetadata,
8210c3f46912 rust: introduce SIZE_FROM_OTHER_PARENT constant
Raphaël Gomès <rgomes@octobus.net>
parents: 43604
diff changeset
    16
        hg_path::{hg_path_to_path_buf, HgPath},
8210c3f46912 rust: introduce SIZE_FROM_OTHER_PARENT constant
Raphaël Gomès <rgomes@octobus.net>
parents: 43604
diff changeset
    17
    },
8210c3f46912 rust: introduce SIZE_FROM_OTHER_PARENT constant
Raphaël Gomès <rgomes@octobus.net>
parents: 43604
diff changeset
    18
    CopyMap, DirstateEntry, DirstateMap, EntryState,
8210c3f46912 rust: introduce SIZE_FROM_OTHER_PARENT constant
Raphaël Gomès <rgomes@octobus.net>
parents: 43604
diff changeset
    19
};
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    20
use rayon::prelude::*;
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    21
use std::path::Path;
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    22
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    23
/// Marker enum used to dispatch new status entries into the right collections.
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    24
/// Is similar to `crate::EntryState`, but represents the transient state of
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    25
/// entries during the lifetime of a command.
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    26
enum Dispatch {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    27
    Unsure,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    28
    Modified,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    29
    Added,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    30
    Removed,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    31
    Deleted,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    32
    Clean,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    33
    Unknown,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    34
}
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    35
43604
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
    36
/// Dates and times that are outside the 31-bit signed range are compared
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
    37
/// modulo 2^31. This should prevent hg from behaving badly with very large
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
    38
/// files or corrupt dates while still having a high probability of detecting
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
    39
/// changes. (issue2608)
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
    40
/// TODO I haven't found a way of having `b` be `Into<i32>`, since `From<u64>`
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
    41
/// is not defined for `i32`, and there is no `As` trait. This forces the
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
    42
/// caller to cast `b` as `i32`.
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
    43
fn mod_compare(a: i32, b: i32) -> bool {
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
    44
    a & i32::max_value() != b & i32::max_value()
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
    45
}
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
    46
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    47
/// The file corresponding to the dirstate entry was found on the filesystem.
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    48
fn dispatch_found(
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    49
    filename: impl AsRef<HgPath>,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    50
    entry: DirstateEntry,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    51
    metadata: HgMetadata,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    52
    copy_map: &CopyMap,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    53
    check_exec: bool,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    54
    list_clean: bool,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    55
    last_normal_time: i64,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    56
) -> Dispatch {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    57
    let DirstateEntry {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    58
        state,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    59
        mode,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    60
        mtime,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    61
        size,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    62
    } = entry;
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    63
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    64
    let HgMetadata {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    65
        st_mode,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    66
        st_size,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    67
        st_mtime,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    68
        ..
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    69
    } = metadata;
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    70
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    71
    match state {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    72
        EntryState::Normal => {
43604
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
    73
            let size_changed = mod_compare(size, st_size as i32);
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    74
            let mode_changed =
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    75
                (mode ^ st_mode as i32) & 0o100 != 0o000 && check_exec;
43604
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
    76
            let metadata_changed = size >= 0 && (size_changed || mode_changed);
43605
8210c3f46912 rust: introduce SIZE_FROM_OTHER_PARENT constant
Raphaël Gomès <rgomes@octobus.net>
parents: 43604
diff changeset
    77
            let other_parent = size == SIZE_FROM_OTHER_PARENT;
43604
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
    78
            if metadata_changed
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
    79
                || other_parent
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
    80
                || copy_map.contains_key(filename.as_ref())
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    81
            {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    82
                Dispatch::Modified
43604
51cd86735608 rust-status: refactor dispatch case for normal files
Raphaël Gomès <rgomes@octobus.net>
parents: 43603
diff changeset
    83
            } else if mod_compare(mtime, st_mtime as i32) {
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    84
                Dispatch::Unsure
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    85
            } else if st_mtime == last_normal_time {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    86
                // the file may have just been marked as normal and
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    87
                // it may have changed in the same second without
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    88
                // changing its size. This can happen if we quickly
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    89
                // do multiple commits. Force lookup, so we don't
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    90
                // miss such a racy file change.
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    91
                Dispatch::Unsure
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    92
            } else if list_clean {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    93
                Dispatch::Clean
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    94
            } else {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    95
                Dispatch::Unknown
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    96
            }
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    97
        }
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    98
        EntryState::Merged => Dispatch::Modified,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    99
        EntryState::Added => Dispatch::Added,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   100
        EntryState::Removed => Dispatch::Removed,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   101
        EntryState::Unknown => Dispatch::Unknown,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   102
    }
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   103
}
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   104
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   105
/// The file corresponding to this Dirstate entry is missing.
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   106
fn dispatch_missing(state: EntryState) -> Dispatch {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   107
    match state {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   108
        // File was removed from the filesystem during commands
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   109
        EntryState::Normal | EntryState::Merged | EntryState::Added => {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   110
            Dispatch::Deleted
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   111
        }
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   112
        // File was removed, everything is normal
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   113
        EntryState::Removed => Dispatch::Removed,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   114
        // File is unknown to Mercurial, everything is normal
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   115
        EntryState::Unknown => Dispatch::Unknown,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   116
    }
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   117
}
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   118
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   119
/// Stat all entries in the `DirstateMap` and mark them for dispatch into
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   120
/// the relevant collections.
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   121
fn stat_dmap_entries(
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   122
    dmap: &DirstateMap,
43603
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   123
    root_dir: impl AsRef<Path> + Sync + Send,
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   124
    check_exec: bool,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   125
    list_clean: bool,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   126
    last_normal_time: i64,
43603
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   127
) -> impl ParallelIterator<Item = std::io::Result<(&HgPath, Dispatch)>> {
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   128
    dmap.par_iter().map(move |(filename, entry)| {
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   129
        let filename: &HgPath = filename;
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   130
        let filename_as_path = hg_path_to_path_buf(filename)?;
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   131
        let meta = root_dir.as_ref().join(filename_as_path).symlink_metadata();
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   132
43603
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   133
        match meta {
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   134
            Ok(ref m)
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   135
                if !(m.file_type().is_file()
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   136
                    || m.file_type().is_symlink()) =>
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   137
            {
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   138
                Ok((filename, dispatch_missing(entry.state)))
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   139
            }
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   140
            Ok(m) => Ok((
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   141
                filename,
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   142
                dispatch_found(
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   143
                    filename,
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   144
                    *entry,
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   145
                    HgMetadata::from_metadata(m),
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   146
                    &dmap.copy_map,
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   147
                    check_exec,
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   148
                    list_clean,
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   149
                    last_normal_time,
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   150
                ),
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   151
            )),
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   152
            Err(ref e)
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   153
                if e.kind() == std::io::ErrorKind::NotFound
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   154
                    || e.raw_os_error() == Some(20) =>
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   155
            {
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   156
                // Rust does not yet have an `ErrorKind` for
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   157
                // `NotADirectory` (errno 20)
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   158
                // It happens if the dirstate contains `foo/bar` and
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   159
                // foo is not a directory
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   160
                Ok((filename, dispatch_missing(entry.state)))
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   161
            }
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   162
            Err(e) => Err(e),
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   163
        }
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   164
    })
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   165
}
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   166
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   167
pub struct StatusResult<'a> {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   168
    pub modified: Vec<&'a HgPath>,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   169
    pub added: Vec<&'a HgPath>,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   170
    pub removed: Vec<&'a HgPath>,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   171
    pub deleted: Vec<&'a HgPath>,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   172
    pub clean: Vec<&'a HgPath>,
43818
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43605
diff changeset
   173
    /* TODO ignored
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43605
diff changeset
   174
     * TODO unknown */
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   175
}
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   176
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   177
fn build_response(
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   178
    results: Vec<(&HgPath, Dispatch)>,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   179
) -> (Vec<&HgPath>, StatusResult) {
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   180
    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
   181
    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
   182
    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
   183
    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
   184
    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
   185
    let mut clean = vec![];
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   186
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   187
    for (filename, dispatch) in results.into_iter() {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   188
        match dispatch {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   189
            Dispatch::Unknown => {}
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   190
            Dispatch::Unsure => lookup.push(filename),
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   191
            Dispatch::Modified => modified.push(filename),
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   192
            Dispatch::Added => added.push(filename),
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   193
            Dispatch::Removed => removed.push(filename),
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   194
            Dispatch::Deleted => deleted.push(filename),
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   195
            Dispatch::Clean => clean.push(filename),
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   196
        }
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   197
    }
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   198
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   199
    (
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   200
        lookup,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   201
        StatusResult {
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   202
            modified,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   203
            added,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   204
            removed,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   205
            deleted,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   206
            clean,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   207
        },
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   208
    )
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   209
}
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   210
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   211
pub fn status(
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   212
    dmap: &DirstateMap,
43603
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   213
    root_dir: impl AsRef<Path> + Sync + Send + Copy,
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   214
    list_clean: bool,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   215
    last_normal_time: i64,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   216
    check_exec: bool,
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   217
) -> std::io::Result<(Vec<&HgPath>, StatusResult)> {
43603
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   218
    let results: std::io::Result<_> = stat_dmap_entries(
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   219
        &dmap,
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   220
        root_dir,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   221
        check_exec,
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   222
        list_clean,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   223
        last_normal_time,
43603
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   224
    )
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   225
    .collect();
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   226
43603
75fe6e71ddb8 rust-status: return a ParallelIterator instead of a Vec from stat_dmap_entries
Raphaël Gomès <rgomes@octobus.net>
parents: 43602
diff changeset
   227
    Ok(build_response(results?))
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   228
}