rust/rhg/src/commands/status.rs
author Georges Racinet <georges.racinet@octobus.net>
Tue, 16 Mar 2021 15:12:03 +0100
changeset 46822 c71e8d9e7f2a
child 47110 9c6b458a08e1
permissions -rw-r--r--
rhg: Initial support for the 'status' command Only comparing the working directory with its first parent revision is supported. The core logic of dirstate handling and `stat`’ing files was already in `hg-core` supporting Python-based hg with Rust extensions, so this is mostly plumbing to rhg’s CLI. For now the command is experimental and disabled by default, since it has some bugs that causes a number of tests to fail. These failures can be seen with: tests/run-tests.py --rhg --extra-config-opt rhg.status=true Differential Revision: https://phab.mercurial-scm.org/D10239
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
46822
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     1
// status.rs
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     2
//
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     3
// Copyright 2020, Georges Racinet <georges.racinets@octobus.net>
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     4
//
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     5
// This software may be used and distributed according to the terms of the
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     6
// GNU General Public License version 2 or any later version.
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     7
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     8
use crate::error::CommandError;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     9
use crate::ui::Ui;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    10
use clap::{Arg, SubCommand};
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    11
use hg;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    12
use hg::errors::IoResultExt;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    13
use hg::matchers::AlwaysMatcher;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    14
use hg::operations::cat;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    15
use hg::repo::Repo;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    16
use hg::revlog::node::Node;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    17
use hg::utils::hg_path::{hg_path_to_os_string, HgPath};
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    18
use hg::{DirstateMap, StatusError};
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    19
use hg::{HgPathCow, StatusOptions};
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    20
use log::{info, warn};
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    21
use std::convert::TryInto;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    22
use std::fs;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    23
use std::io::BufReader;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    24
use std::io::Read;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    25
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    26
pub const HELP_TEXT: &str = "
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    27
Show changed files in the working directory
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    28
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    29
This is a pure Rust version of `hg status`.
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    30
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    31
Some options might be missing, check the list below.
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    32
";
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    33
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    34
pub fn args() -> clap::App<'static, 'static> {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    35
    SubCommand::with_name("status")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    36
        .alias("st")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    37
        .about(HELP_TEXT)
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    38
        .arg(
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    39
            Arg::with_name("all")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    40
                .help("show status of all files")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    41
                .short("-A")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    42
                .long("--all"),
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    43
        )
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    44
        .arg(
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    45
            Arg::with_name("modified")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    46
                .help("show only modified files")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    47
                .short("-m")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    48
                .long("--modified"),
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    49
        )
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    50
        .arg(
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    51
            Arg::with_name("added")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    52
                .help("show only added files")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    53
                .short("-a")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    54
                .long("--added"),
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    55
        )
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    56
        .arg(
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    57
            Arg::with_name("removed")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    58
                .help("show only removed files")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    59
                .short("-r")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    60
                .long("--removed"),
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    61
        )
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    62
        .arg(
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    63
            Arg::with_name("clean")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    64
                .help("show only clean files")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    65
                .short("-c")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    66
                .long("--clean"),
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    67
        )
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    68
        .arg(
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    69
            Arg::with_name("deleted")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    70
                .help("show only deleted files")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    71
                .short("-d")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    72
                .long("--deleted"),
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    73
        )
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    74
        .arg(
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    75
            Arg::with_name("unknown")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    76
                .help("show only unknown (not tracked) files")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    77
                .short("-u")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    78
                .long("--unknown"),
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    79
        )
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    80
        .arg(
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    81
            Arg::with_name("ignored")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    82
                .help("show only ignored files")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    83
                .short("-i")
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    84
                .long("--ignored"),
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    85
        )
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    86
}
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    87
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    88
/// Pure data type allowing the caller to specify file states to display
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    89
#[derive(Copy, Clone, Debug)]
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    90
pub struct DisplayStates {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    91
    pub modified: bool,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    92
    pub added: bool,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    93
    pub removed: bool,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    94
    pub clean: bool,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    95
    pub deleted: bool,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    96
    pub unknown: bool,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    97
    pub ignored: bool,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    98
}
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    99
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   100
pub const DEFAULT_DISPLAY_STATES: DisplayStates = DisplayStates {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   101
    modified: true,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   102
    added: true,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   103
    removed: true,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   104
    clean: false,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   105
    deleted: true,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   106
    unknown: true,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   107
    ignored: false,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   108
};
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   109
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   110
pub const ALL_DISPLAY_STATES: DisplayStates = DisplayStates {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   111
    modified: true,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   112
    added: true,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   113
    removed: true,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   114
    clean: true,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   115
    deleted: true,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   116
    unknown: true,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   117
    ignored: true,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   118
};
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   119
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   120
impl DisplayStates {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   121
    pub fn is_empty(&self) -> bool {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   122
        !(self.modified
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   123
            || self.added
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   124
            || self.removed
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   125
            || self.clean
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   126
            || self.deleted
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   127
            || self.unknown
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   128
            || self.ignored)
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   129
    }
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   130
}
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   131
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   132
pub fn run(invocation: &crate::CliInvocation) -> Result<(), CommandError> {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   133
    let status_enabled_default = false;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   134
    let status_enabled = invocation.config.get_option(b"rhg", b"status")?;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   135
    if !status_enabled.unwrap_or(status_enabled_default) {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   136
        return Err(CommandError::unsupported(
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   137
            "status is experimental in rhg (enable it with 'rhg.status = true' \
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   138
            or enable fallback with 'rhg.on-unsupported = fallback')"
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   139
        ));
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   140
    }
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   141
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   142
    let ui = invocation.ui;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   143
    let args = invocation.subcommand_args;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   144
    let display_states = if args.is_present("all") {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   145
        // TODO when implementing `--quiet`: it excludes clean files
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   146
        // from `--all`
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   147
        ALL_DISPLAY_STATES
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   148
    } else {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   149
        let requested = DisplayStates {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   150
            modified: args.is_present("modified"),
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   151
            added: args.is_present("added"),
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   152
            removed: args.is_present("removed"),
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   153
            clean: args.is_present("clean"),
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   154
            deleted: args.is_present("deleted"),
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   155
            unknown: args.is_present("unknown"),
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   156
            ignored: args.is_present("ignored"),
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   157
        };
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   158
        if requested.is_empty() {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   159
            DEFAULT_DISPLAY_STATES
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   160
        } else {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   161
            requested
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   162
        }
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   163
    };
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   164
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   165
    let repo = invocation.repo?;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   166
    let mut dmap = DirstateMap::new();
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   167
    let dirstate_data = repo.hg_vfs().mmap_open("dirstate")?;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   168
    let parents = dmap.read(&dirstate_data)?;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   169
    let options = StatusOptions {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   170
        // TODO should be provided by the dirstate parsing and
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   171
        // hence be stored on dmap. Using a value that assumes we aren't
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   172
        // below the time resolution granularity of the FS and the
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   173
        // dirstate.
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   174
        last_normal_time: 0,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   175
        // we're currently supporting file systems with exec flags only
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   176
        // anyway
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   177
        check_exec: true,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   178
        list_clean: display_states.clean,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   179
        list_unknown: display_states.unknown,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   180
        list_ignored: display_states.ignored,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   181
        collect_traversed_dirs: false,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   182
    };
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   183
    let ignore_file = repo.working_directory_vfs().join(".hgignore"); // TODO hardcoded
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   184
    let ((lookup, ds_status), pattern_warnings) = hg::status(
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   185
        &dmap,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   186
        &AlwaysMatcher,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   187
        repo.working_directory_path().to_owned(),
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   188
        vec![ignore_file],
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   189
        options,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   190
    )?;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   191
    if !pattern_warnings.is_empty() {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   192
        warn!("Pattern warnings: {:?}", &pattern_warnings);
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   193
    }
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   194
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   195
    if !ds_status.bad.is_empty() {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   196
        warn!("Bad matches {:?}", &(ds_status.bad))
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   197
    }
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   198
    if !lookup.is_empty() {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   199
        info!(
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   200
            "Files to be rechecked by retrieval from filelog: {:?}",
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   201
            &lookup
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   202
        );
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   203
    }
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   204
    // TODO check ordering to match `hg status` output.
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   205
    // (this is as in `hg help status`)
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   206
    if display_states.modified {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   207
        display_status_paths(ui, &(ds_status.modified), b"M")?;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   208
    }
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   209
    if !lookup.is_empty() {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   210
        let p1: Node = parents
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   211
            .expect(
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   212
                "Dirstate with no parents should not list any file to
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   213
                 be rechecked for modifications",
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   214
            )
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   215
            .p1
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   216
            .into();
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   217
        let p1_hex = format!("{:x}", p1);
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   218
        let mut rechecked_modified: Vec<HgPathCow> = Vec::new();
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   219
        let mut rechecked_clean: Vec<HgPathCow> = Vec::new();
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   220
        for to_check in lookup {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   221
            if cat_file_is_modified(repo, &to_check, &p1_hex)? {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   222
                rechecked_modified.push(to_check);
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   223
            } else {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   224
                rechecked_clean.push(to_check);
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   225
            }
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   226
        }
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   227
        if display_states.modified {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   228
            display_status_paths(ui, &rechecked_modified, b"M")?;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   229
        }
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   230
        if display_states.clean {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   231
            display_status_paths(ui, &rechecked_clean, b"C")?;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   232
        }
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   233
    }
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   234
    if display_states.added {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   235
        display_status_paths(ui, &(ds_status.added), b"A")?;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   236
    }
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   237
    if display_states.clean {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   238
        display_status_paths(ui, &(ds_status.clean), b"C")?;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   239
    }
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   240
    if display_states.removed {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   241
        display_status_paths(ui, &(ds_status.removed), b"R")?;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   242
    }
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   243
    if display_states.deleted {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   244
        display_status_paths(ui, &(ds_status.deleted), b"!")?;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   245
    }
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   246
    if display_states.unknown {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   247
        display_status_paths(ui, &(ds_status.unknown), b"?")?;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   248
    }
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   249
    if display_states.ignored {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   250
        display_status_paths(ui, &(ds_status.ignored), b"I")?;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   251
    }
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   252
    Ok(())
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   253
}
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   254
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   255
// Probably more elegant to use a Deref or Borrow trait rather than
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   256
// harcode HgPathBuf, but probably not really useful at this point
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   257
fn display_status_paths(
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   258
    ui: &Ui,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   259
    paths: &[HgPathCow],
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   260
    status_prefix: &[u8],
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   261
) -> Result<(), CommandError> {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   262
    for path in paths {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   263
        // Same TODO as in commands::root
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   264
        let bytes: &[u8] = path.as_bytes();
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   265
        // TODO optim, probably lots of unneeded copies here, especially
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   266
        // if out stream is buffered
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   267
        ui.write_stdout(&[status_prefix, b" ", bytes, b"\n"].concat())?;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   268
    }
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   269
    Ok(())
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   270
}
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   271
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   272
/// Check if a file is modified by comparing actual repo store and file system.
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   273
///
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   274
/// This meant to be used for those that the dirstate cannot resolve, due
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   275
/// to time resolution limits.
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   276
///
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   277
/// TODO: detect permission bits and similar metadata modifications
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   278
fn cat_file_is_modified(
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   279
    repo: &Repo,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   280
    hg_path: &HgPath,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   281
    rev: &str,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   282
) -> Result<bool, CommandError> {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   283
    // TODO CatRev expects &[HgPathBuf], something like
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   284
    // &[impl Deref<HgPath>] would be nicer and should avoid the copy
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   285
    let path_bufs = [hg_path.into()];
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   286
    // TODO IIUC CatRev returns a simple Vec<u8> for all files
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   287
    //      being able to tell them apart as (path, bytes) would be nicer
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   288
    //      and OPTIM would allow manifest resolution just once.
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   289
    let output = cat(repo, rev, &path_bufs).map_err(|e| (e, rev))?;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   290
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   291
    let fs_path = repo
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   292
        .working_directory_vfs()
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   293
        .join(hg_path_to_os_string(hg_path).expect("HgPath conversion"));
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   294
    let hg_data_len: u64 = match output.concatenated.len().try_into() {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   295
        Ok(v) => v,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   296
        Err(_) => {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   297
            // conversion of data length to u64 failed,
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   298
            // good luck for any file to have this content
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   299
            return Ok(true);
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   300
        }
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   301
    };
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   302
    let fobj = fs::File::open(&fs_path).when_reading_file(&fs_path)?;
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   303
    if fobj.metadata().map_err(|e| StatusError::from(e))?.len() != hg_data_len
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   304
    {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   305
        return Ok(true);
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   306
    }
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   307
    for (fs_byte, hg_byte) in
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   308
        BufReader::new(fobj).bytes().zip(output.concatenated)
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   309
    {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   310
        if fs_byte.map_err(|e| StatusError::from(e))? != hg_byte {
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   311
            return Ok(true);
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   312
        }
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   313
    }
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   314
    Ok(false)
c71e8d9e7f2a rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   315
}