rust/hg-core/src/dirstate/status.rs
author Raphaël Gomès <rgomes@octobus.net>
Wed, 06 Nov 2019 13:43:18 +0100
changeset 43602 889ac87e8bfd
parent 43456 ab9b0a20b9e6
child 43603 75fe6e71ddb8
permissions -rw-r--r--
rust-status: improve status performance This change does more things in the parallel loop, refactors the file-level logic into two functions for added clarity. This bit of Rust code takes 55ms to execute on a repo where the stat'ing part of Valentin's fast path takes 40ms. While the code differs a bit and it's hard to get an exact measurement of how much of a performance impact it has, I can be fairly certain that this implementation is *at worse* twice as slow. Differential Revision: https://phab.mercurial-scm.org/D7254
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
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    12
use crate::utils::files::HgMetadata;
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    13
use crate::utils::hg_path::{hg_path_to_path_buf, HgPath};
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    14
use crate::{CopyMap, DirstateEntry, DirstateMap, EntryState};
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    15
use rayon::prelude::*;
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    16
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
    17
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    18
/// 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
    19
/// 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
    20
/// entries during the lifetime of a command.
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    21
enum Dispatch {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    22
    Unsure,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    23
    Modified,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    24
    Added,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    25
    Removed,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    26
    Deleted,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    27
    Clean,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    28
    Unknown,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    29
}
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    30
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    31
/// 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
    32
fn dispatch_found(
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    33
    filename: impl AsRef<HgPath>,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    34
    entry: DirstateEntry,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    35
    metadata: HgMetadata,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    36
    copy_map: &CopyMap,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    37
    check_exec: bool,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    38
    list_clean: bool,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    39
    last_normal_time: i64,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    40
) -> Dispatch {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    41
    let DirstateEntry {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    42
        state,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    43
        mode,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    44
        mtime,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    45
        size,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    46
    } = entry;
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    47
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    48
    let HgMetadata {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    49
        st_mode,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    50
        st_size,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    51
        st_mtime,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    52
        ..
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    53
    } = metadata;
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    54
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    55
    match state {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    56
        EntryState::Normal => {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    57
            // Dates and times that are outside the 31-bit signed
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    58
            // range are compared modulo 2^31. This should prevent
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    59
            // it from behaving badly with very large files or
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    60
            // corrupt dates while still having a high probability
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    61
            // of detecting changes. (issue2608)
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    62
            let range_mask = 0x7fffffff;
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 size_changed = (size != st_size as i32)
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    65
                && size != (st_size as i32 & range_mask);
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    66
            let mode_changed =
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    67
                (mode ^ st_mode as i32) & 0o100 != 0o000 && check_exec;
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    68
            if size >= 0
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    69
                            && (size_changed || mode_changed)
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    70
                            || size == -2  // other parent
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    71
                            || copy_map.contains_key(filename.as_ref())
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    72
            {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    73
                Dispatch::Modified
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    74
            } else if mtime != st_mtime as i32
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    75
                && mtime != (st_mtime as i32 & range_mask)
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    76
            {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    77
                Dispatch::Unsure
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    78
            } else if st_mtime == last_normal_time {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    79
                // 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
    80
                // 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
    81
                // 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
    82
                // 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
    83
                // miss such a racy file change.
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 list_clean {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    86
                Dispatch::Clean
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    87
            } else {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    88
                Dispatch::Unknown
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    89
            }
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    90
        }
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    91
        EntryState::Merged => Dispatch::Modified,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    92
        EntryState::Added => Dispatch::Added,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    93
        EntryState::Removed => Dispatch::Removed,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    94
        EntryState::Unknown => Dispatch::Unknown,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
    95
    }
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
/// 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
    99
fn dispatch_missing(state: EntryState) -> Dispatch {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   100
    match state {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   101
        // 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
   102
        EntryState::Normal | EntryState::Merged | EntryState::Added => {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   103
            Dispatch::Deleted
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
        // File was removed, everything is normal
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   106
        EntryState::Removed => Dispatch::Removed,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   107
        // 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
   108
        EntryState::Unknown => Dispatch::Unknown,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   109
    }
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   110
}
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
/// 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
   113
/// the relevant collections.
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   114
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
   115
    dmap: &DirstateMap,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   116
    root_dir: impl AsRef<Path> + Sync,
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   117
    check_exec: bool,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   118
    list_clean: bool,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   119
    last_normal_time: i64,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   120
) -> std::io::Result<Vec<(&HgPath, Dispatch)>> {
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   121
    dmap.par_iter()
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   122
        .filter_map(
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   123
            // Getting file metadata is costly, so we don't do it if the
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   124
            // file is already present in the results, hence `filter_map`
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   125
            |(filename, entry)| -> Option<
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   126
                std::io::Result<(&HgPath, Dispatch)>
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   127
            > {
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   128
                let meta = match hg_path_to_path_buf(filename) {
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   129
                    Ok(p) => root_dir.as_ref().join(p).symlink_metadata(),
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   130
                    Err(e) => return Some(Err(e.into())),
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   131
                };
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   132
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   133
                Some(match meta {
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   134
                    Ok(ref m)
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   135
                        if !(m.file_type().is_file()
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   136
                            || m.file_type().is_symlink()) =>
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   137
                    {
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   138
                        Ok((filename, dispatch_missing(entry.state)))
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   139
                    }
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   140
                    Ok(m) => Ok((filename, dispatch_found(
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   141
                            filename,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   142
                            *entry,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   143
                            HgMetadata::from_metadata(m),
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   144
                            &dmap.copy_map,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   145
                            check_exec,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   146
                            list_clean,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   147
                            last_normal_time))),
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   148
                    Err(ref e)
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   149
                        if e.kind() == std::io::ErrorKind::NotFound
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   150
                            || e.raw_os_error() == Some(20) =>
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   151
                    {
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   152
                        // Rust does not yet have an `ErrorKind` for
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   153
                        // `NotADirectory` (errno 20)
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   154
                        // It happens if the dirstate contains `foo/bar` and
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   155
                        // foo is not a directory
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   156
                        Ok((filename, dispatch_missing(entry.state)))
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   157
                    }
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   158
                    Err(e) => Err(e),
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   159
                })
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   160
            },
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   161
        )
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   162
        .collect()
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   163
}
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   164
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   165
pub struct StatusResult<'a> {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   166
    pub modified: Vec<&'a HgPath>,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   167
    pub added: Vec<&'a HgPath>,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   168
    pub removed: Vec<&'a HgPath>,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   169
    pub deleted: Vec<&'a HgPath>,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   170
    pub clean: Vec<&'a HgPath>,
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   171
    // TODO ignored
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   172
    // TODO unknown
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   173
}
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   174
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   175
fn build_response(
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   176
    results: Vec<(&HgPath, Dispatch)>,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   177
) -> (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
   178
    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
   179
    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
   180
    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
   181
    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
   182
    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
   183
    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
   184
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   185
    for (filename, dispatch) in results.into_iter() {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   186
        match dispatch {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   187
            Dispatch::Unknown => {}
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   188
            Dispatch::Unsure => lookup.push(filename),
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   189
            Dispatch::Modified => modified.push(filename),
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   190
            Dispatch::Added => added.push(filename),
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   191
            Dispatch::Removed => removed.push(filename),
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   192
            Dispatch::Deleted => deleted.push(filename),
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   193
            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
   194
        }
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   195
    }
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
        lookup,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   199
        StatusResult {
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   200
            modified,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   201
            added,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   202
            removed,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   203
            deleted,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   204
            clean,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   205
        },
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   206
    )
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
pub fn status(
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   210
    dmap: &DirstateMap,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   211
    root_dir: impl AsRef<Path> + Sync + Copy,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   212
    list_clean: bool,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   213
    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
   214
    check_exec: bool,
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   215
) -> std::io::Result<(Vec<&HgPath>, StatusResult)> {
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   216
    let results = 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
   217
        &dmap,
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   218
        root_dir,
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   219
        check_exec,
43271
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   220
        list_clean,
99394e6c5d12 rust-dirstate-status: add first Rust implementation of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   221
        last_normal_time,
43602
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   222
    )?;
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   223
889ac87e8bfd rust-status: improve status performance
Raphaël Gomès <rgomes@octobus.net>
parents: 43456
diff changeset
   224
    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
   225
}