rust/rhg/src/commands/files.rs
author Simon Sapin <simon.sapin@octobus.net>
Sat, 13 Mar 2021 09:50:34 +0100
changeset 46925 b5e8bf10436e
parent 46745 63bfcddddac1
child 48174 9ecf802b06e0
permissions -rw-r--r--
rhg: Make `files` work on repo-relative paths when possible When the current directory is outside of the repository we need to turn everything into absolute filesystem paths in order to compute correct relative paths. This was previously done unconditionally, but is not necessary when the current directory is inside the repository. With this change `rhg files > /dev/null` at the root of a mozilla-central snapshot goes from ~150 ms to ~70 ms. My repository is located at a somewhat long path though (93 bytes). The effect may not be as pronounced at a shorter path. Differential Revision: https://phab.mercurial-scm.org/D10200
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
46434
3e2d539d0d1a rust: remove `FooError` structs with only `kind: FooErrorKind` enum field
Simon Sapin <simon.sapin@octobus.net>
parents: 46167
diff changeset
     1
use crate::error::CommandError;
45364
5fe25f8ef5d9 rhg: add a `Files` `Command` to prepare the `rhg files` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     2
use crate::ui::Ui;
46501
1ecaf09d9964 rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents: 46500
diff changeset
     3
use clap::Arg;
46436
252d1bdba33d rhg: replace `map_*_error` functions with `From` impls
Simon Sapin <simon.sapin@octobus.net>
parents: 46434
diff changeset
     4
use hg::operations::list_rev_tracked_files;
252d1bdba33d rhg: replace `map_*_error` functions with `From` impls
Simon Sapin <simon.sapin@octobus.net>
parents: 46434
diff changeset
     5
use hg::operations::Dirstate;
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46135
diff changeset
     6
use hg::repo::Repo;
46740
97ac588b6d9e rhg: Don?t make repository path absolute too early
Simon Sapin <simon.sapin@octobus.net>
parents: 46739
diff changeset
     7
use hg::utils::current_dir;
45436
1b3197047f5c rhg: make output of `files` relative to the current directory and the root
Rapha?l Gom?s <rgomes@octobus.net>
parents: 45364
diff changeset
     8
use hg::utils::files::{get_bytes_from_path, relativize_path};
45537
2f8227a12592 rhg: add `--revision` argument to `rhg files`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45535
diff changeset
     9
use hg::utils::hg_path::{HgPath, HgPathBuf};
45364
5fe25f8ef5d9 rhg: add a `Files` `Command` to prepare the `rhg files` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    10
5fe25f8ef5d9 rhg: add a `Files` `Command` to prepare the `rhg files` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    11
pub const HELP_TEXT: &str = "
5fe25f8ef5d9 rhg: add a `Files` `Command` to prepare the `rhg files` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    12
List tracked files.
5fe25f8ef5d9 rhg: add a `Files` `Command` to prepare the `rhg files` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    13
5fe25f8ef5d9 rhg: add a `Files` `Command` to prepare the `rhg files` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    14
Returns 0 on success.
5fe25f8ef5d9 rhg: add a `Files` `Command` to prepare the `rhg files` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    15
";
5fe25f8ef5d9 rhg: add a `Files` `Command` to prepare the `rhg files` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    16
46501
1ecaf09d9964 rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents: 46500
diff changeset
    17
pub fn args() -> clap::App<'static, 'static> {
1ecaf09d9964 rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents: 46500
diff changeset
    18
    clap::SubCommand::with_name("files")
1ecaf09d9964 rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents: 46500
diff changeset
    19
        .arg(
1ecaf09d9964 rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents: 46500
diff changeset
    20
            Arg::with_name("rev")
1ecaf09d9964 rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents: 46500
diff changeset
    21
                .help("search the repository as it is in REV")
1ecaf09d9964 rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents: 46500
diff changeset
    22
                .short("-r")
1ecaf09d9964 rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents: 46500
diff changeset
    23
                .long("--revision")
1ecaf09d9964 rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents: 46500
diff changeset
    24
                .value_name("REV")
1ecaf09d9964 rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents: 46500
diff changeset
    25
                .takes_value(true),
1ecaf09d9964 rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents: 46500
diff changeset
    26
        )
1ecaf09d9964 rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents: 46500
diff changeset
    27
        .about(HELP_TEXT)
1ecaf09d9964 rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents: 46500
diff changeset
    28
}
1ecaf09d9964 rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents: 46500
diff changeset
    29
46592
80840b651721 rhg: Group values passed to every sub-command into a struct
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
    30
pub fn run(invocation: &crate::CliInvocation) -> Result<(), CommandError> {
46739
c184b490da37 rhg: Fall back to Python if ui.relative-paths is configured
Simon Sapin <simon.sapin@octobus.net>
parents: 46593
diff changeset
    31
    let relative = invocation.config.get(b"ui", b"relative-paths");
c184b490da37 rhg: Fall back to Python if ui.relative-paths is configured
Simon Sapin <simon.sapin@octobus.net>
parents: 46593
diff changeset
    32
    if relative.is_some() {
c184b490da37 rhg: Fall back to Python if ui.relative-paths is configured
Simon Sapin <simon.sapin@octobus.net>
parents: 46593
diff changeset
    33
        return Err(CommandError::unsupported(
c184b490da37 rhg: Fall back to Python if ui.relative-paths is configured
Simon Sapin <simon.sapin@octobus.net>
parents: 46593
diff changeset
    34
            "non-default ui.relative-paths",
c184b490da37 rhg: Fall back to Python if ui.relative-paths is configured
Simon Sapin <simon.sapin@octobus.net>
parents: 46593
diff changeset
    35
        ));
c184b490da37 rhg: Fall back to Python if ui.relative-paths is configured
Simon Sapin <simon.sapin@octobus.net>
parents: 46593
diff changeset
    36
    }
c184b490da37 rhg: Fall back to Python if ui.relative-paths is configured
Simon Sapin <simon.sapin@octobus.net>
parents: 46593
diff changeset
    37
46592
80840b651721 rhg: Group values passed to every sub-command into a struct
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
    38
    let rev = invocation.subcommand_args.value_of("rev");
45364
5fe25f8ef5d9 rhg: add a `Files` `Command` to prepare the `rhg files` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    39
46593
5ce2aa7c2ad5 rhg: Move `Repo` object creation into `main()`
Simon Sapin <simon.sapin@octobus.net>
parents: 46592
diff changeset
    40
    let repo = invocation.repo?;
46500
184e46550dc8 rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46484
diff changeset
    41
    if let Some(rev) = rev {
46593
5ce2aa7c2ad5 rhg: Move `Repo` object creation into `main()`
Simon Sapin <simon.sapin@octobus.net>
parents: 46592
diff changeset
    42
        let files = list_rev_tracked_files(repo, rev).map_err(|e| (e, rev))?;
5ce2aa7c2ad5 rhg: Move `Repo` object creation into `main()`
Simon Sapin <simon.sapin@octobus.net>
parents: 46592
diff changeset
    43
        display_files(invocation.ui, repo, files.iter())
46500
184e46550dc8 rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46484
diff changeset
    44
    } else {
46593
5ce2aa7c2ad5 rhg: Move `Repo` object creation into `main()`
Simon Sapin <simon.sapin@octobus.net>
parents: 46592
diff changeset
    45
        let distate = Dirstate::new(repo)?;
46500
184e46550dc8 rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46484
diff changeset
    46
        let files = distate.tracked_files()?;
46593
5ce2aa7c2ad5 rhg: Move `Repo` object creation into `main()`
Simon Sapin <simon.sapin@octobus.net>
parents: 46592
diff changeset
    47
        display_files(invocation.ui, repo, files)
45364
5fe25f8ef5d9 rhg: add a `Files` `Command` to prepare the `rhg files` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    48
    }
5fe25f8ef5d9 rhg: add a `Files` `Command` to prepare the `rhg files` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    49
}
45535
72b7d58d6e35 hg-core: simplify `list_tracked_files` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45438
diff changeset
    50
46500
184e46550dc8 rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46484
diff changeset
    51
fn display_files<'a>(
184e46550dc8 rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46484
diff changeset
    52
    ui: &Ui,
184e46550dc8 rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46484
diff changeset
    53
    repo: &Repo,
184e46550dc8 rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46484
diff changeset
    54
    files: impl IntoIterator<Item = &'a HgPath>,
184e46550dc8 rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46484
diff changeset
    55
) -> Result<(), CommandError> {
184e46550dc8 rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46484
diff changeset
    56
    let mut stdout = ui.stdout_buffer();
184e46550dc8 rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46484
diff changeset
    57
46925
b5e8bf10436e rhg: Make `files` work on repo-relative paths when possible
Simon Sapin <simon.sapin@octobus.net>
parents: 46745
diff changeset
    58
    let cwd = current_dir()?;
b5e8bf10436e rhg: Make `files` work on repo-relative paths when possible
Simon Sapin <simon.sapin@octobus.net>
parents: 46745
diff changeset
    59
    let working_directory = repo.working_directory_path();
b5e8bf10436e rhg: Make `files` work on repo-relative paths when possible
Simon Sapin <simon.sapin@octobus.net>
parents: 46745
diff changeset
    60
    let working_directory = cwd.join(working_directory); // Make it absolute
b5e8bf10436e rhg: Make `files` work on repo-relative paths when possible
Simon Sapin <simon.sapin@octobus.net>
parents: 46745
diff changeset
    61
46745
63bfcddddac1 rhg: Exit with an error code if `files` finds nothing
Simon Sapin <simon.sapin@octobus.net>
parents: 46740
diff changeset
    62
    let mut any = false;
46925
b5e8bf10436e rhg: Make `files` work on repo-relative paths when possible
Simon Sapin <simon.sapin@octobus.net>
parents: 46745
diff changeset
    63
    if let Ok(cwd_relative_to_repo) = cwd.strip_prefix(&working_directory) {
b5e8bf10436e rhg: Make `files` work on repo-relative paths when possible
Simon Sapin <simon.sapin@octobus.net>
parents: 46745
diff changeset
    64
        // The current directory is inside the repo, so we can work with
b5e8bf10436e rhg: Make `files` work on repo-relative paths when possible
Simon Sapin <simon.sapin@octobus.net>
parents: 46745
diff changeset
    65
        // relative paths
b5e8bf10436e rhg: Make `files` work on repo-relative paths when possible
Simon Sapin <simon.sapin@octobus.net>
parents: 46745
diff changeset
    66
        let cwd = HgPathBuf::from(get_bytes_from_path(cwd_relative_to_repo));
b5e8bf10436e rhg: Make `files` work on repo-relative paths when possible
Simon Sapin <simon.sapin@octobus.net>
parents: 46745
diff changeset
    67
        for file in files {
b5e8bf10436e rhg: Make `files` work on repo-relative paths when possible
Simon Sapin <simon.sapin@octobus.net>
parents: 46745
diff changeset
    68
            any = true;
b5e8bf10436e rhg: Make `files` work on repo-relative paths when possible
Simon Sapin <simon.sapin@octobus.net>
parents: 46745
diff changeset
    69
            stdout.write_all(relativize_path(&file, &cwd).as_ref())?;
b5e8bf10436e rhg: Make `files` work on repo-relative paths when possible
Simon Sapin <simon.sapin@octobus.net>
parents: 46745
diff changeset
    70
            stdout.write_all(b"\n")?;
b5e8bf10436e rhg: Make `files` work on repo-relative paths when possible
Simon Sapin <simon.sapin@octobus.net>
parents: 46745
diff changeset
    71
        }
b5e8bf10436e rhg: Make `files` work on repo-relative paths when possible
Simon Sapin <simon.sapin@octobus.net>
parents: 46745
diff changeset
    72
    } else {
b5e8bf10436e rhg: Make `files` work on repo-relative paths when possible
Simon Sapin <simon.sapin@octobus.net>
parents: 46745
diff changeset
    73
        let working_directory =
b5e8bf10436e rhg: Make `files` work on repo-relative paths when possible
Simon Sapin <simon.sapin@octobus.net>
parents: 46745
diff changeset
    74
            HgPathBuf::from(get_bytes_from_path(working_directory));
b5e8bf10436e rhg: Make `files` work on repo-relative paths when possible
Simon Sapin <simon.sapin@octobus.net>
parents: 46745
diff changeset
    75
        let cwd = HgPathBuf::from(get_bytes_from_path(cwd));
b5e8bf10436e rhg: Make `files` work on repo-relative paths when possible
Simon Sapin <simon.sapin@octobus.net>
parents: 46745
diff changeset
    76
        for file in files {
b5e8bf10436e rhg: Make `files` work on repo-relative paths when possible
Simon Sapin <simon.sapin@octobus.net>
parents: 46745
diff changeset
    77
            any = true;
b5e8bf10436e rhg: Make `files` work on repo-relative paths when possible
Simon Sapin <simon.sapin@octobus.net>
parents: 46745
diff changeset
    78
            // Absolute path in the filesystem
b5e8bf10436e rhg: Make `files` work on repo-relative paths when possible
Simon Sapin <simon.sapin@octobus.net>
parents: 46745
diff changeset
    79
            let file = working_directory.join(file);
b5e8bf10436e rhg: Make `files` work on repo-relative paths when possible
Simon Sapin <simon.sapin@octobus.net>
parents: 46745
diff changeset
    80
            stdout.write_all(relativize_path(&file, &cwd).as_ref())?;
b5e8bf10436e rhg: Make `files` work on repo-relative paths when possible
Simon Sapin <simon.sapin@octobus.net>
parents: 46745
diff changeset
    81
            stdout.write_all(b"\n")?;
b5e8bf10436e rhg: Make `files` work on repo-relative paths when possible
Simon Sapin <simon.sapin@octobus.net>
parents: 46745
diff changeset
    82
        }
45537
2f8227a12592 rhg: add `--revision` argument to `rhg files`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45535
diff changeset
    83
    }
46925
b5e8bf10436e rhg: Make `files` work on repo-relative paths when possible
Simon Sapin <simon.sapin@octobus.net>
parents: 46745
diff changeset
    84
46500
184e46550dc8 rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46484
diff changeset
    85
    stdout.flush()?;
46745
63bfcddddac1 rhg: Exit with an error code if `files` finds nothing
Simon Sapin <simon.sapin@octobus.net>
parents: 46740
diff changeset
    86
    if any {
63bfcddddac1 rhg: Exit with an error code if `files` finds nothing
Simon Sapin <simon.sapin@octobus.net>
parents: 46740
diff changeset
    87
        Ok(())
63bfcddddac1 rhg: Exit with an error code if `files` finds nothing
Simon Sapin <simon.sapin@octobus.net>
parents: 46740
diff changeset
    88
    } else {
63bfcddddac1 rhg: Exit with an error code if `files` finds nothing
Simon Sapin <simon.sapin@octobus.net>
parents: 46740
diff changeset
    89
        Err(CommandError::Unsuccessful)
63bfcddddac1 rhg: Exit with an error code if `files` finds nothing
Simon Sapin <simon.sapin@octobus.net>
parents: 46740
diff changeset
    90
    }
45537
2f8227a12592 rhg: add `--revision` argument to `rhg files`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45535
diff changeset
    91
}