rust/rhg/src/commands/files.rs
author Arseniy Alekseyev <aalekseyev@janestreet.com>
Tue, 16 Nov 2021 11:53:58 +0000
changeset 48409 005ae1a343f8
parent 48342 10c32e1b892a
child 48453 9b0e1f64656f
permissions -rw-r--r--
rhg: add support for narrow clones and sparse checkouts This adds a minimal support that can be implemented without parsing the narrowspec. We can parse the narrowspec and add support for more operations later. The reason we need so few code changes is as follows: Most operations need no special treatment of sparse because some of them only read dirstate (`rhg files` without `-r`), which bakes in the filtering, some of them only read store (`rhg files -r`, `rhg cat`), and some of them read no data at all (`rhg root`, `rhg debugrequirements`). `status` is the command that might care about sparse, so we just disable rhg on it. For narrow clones, `rhg files` clearly needs the narrowspec to work correctly, so we fall back. `rhg cat` seems to work consistently with `hg cat` if the file exists. If the file is hidden by narrow spec, the error message is different and confusing, so that's something that we should improve in follow-up patches. Differential Revision: https://phab.mercurial-scm.org/D11764
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;
48174
9ecf802b06e0 rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46925
diff changeset
     3
use crate::ui::UiError;
9ecf802b06e0 rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46925
diff changeset
     4
use crate::utils::path_utils::relativize_paths;
46501
1ecaf09d9964 rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents: 46500
diff changeset
     5
use clap::Arg;
48342
10c32e1b892a rhg: Propogate manifest parse errors instead of panicking
Simon Sapin <simon.sapin@octobus.net>
parents: 48174
diff changeset
     6
use hg::errors::HgError;
46436
252d1bdba33d rhg: replace `map_*_error` functions with `From` impls
Simon Sapin <simon.sapin@octobus.net>
parents: 46434
diff changeset
     7
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
     8
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
     9
use hg::repo::Repo;
48174
9ecf802b06e0 rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46925
diff changeset
    10
use hg::utils::hg_path::HgPath;
9ecf802b06e0 rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46925
diff changeset
    11
use std::borrow::Cow;
45364
5fe25f8ef5d9 rhg: add a `Files` `Command` to prepare the `rhg files` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    12
5fe25f8ef5d9 rhg: add a `Files` `Command` to prepare the `rhg files` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    13
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
    14
List tracked files.
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
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
    17
";
5fe25f8ef5d9 rhg: add a `Files` `Command` to prepare the `rhg files` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    18
46501
1ecaf09d9964 rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents: 46500
diff changeset
    19
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
    20
    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
    21
        .arg(
1ecaf09d9964 rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents: 46500
diff changeset
    22
            Arg::with_name("rev")
1ecaf09d9964 rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents: 46500
diff changeset
    23
                .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
    24
                .short("-r")
1ecaf09d9964 rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents: 46500
diff changeset
    25
                .long("--revision")
1ecaf09d9964 rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents: 46500
diff changeset
    26
                .value_name("REV")
1ecaf09d9964 rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents: 46500
diff changeset
    27
                .takes_value(true),
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
        .about(HELP_TEXT)
1ecaf09d9964 rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents: 46500
diff changeset
    30
}
1ecaf09d9964 rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents: 46500
diff changeset
    31
46592
80840b651721 rhg: Group values passed to every sub-command into a struct
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
    32
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
    33
    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
    34
    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
    35
        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
    36
            "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
    37
        ));
c184b490da37 rhg: Fall back to Python if ui.relative-paths is configured
Simon Sapin <simon.sapin@octobus.net>
parents: 46593
diff changeset
    38
    }
c184b490da37 rhg: Fall back to Python if ui.relative-paths is configured
Simon Sapin <simon.sapin@octobus.net>
parents: 46593
diff changeset
    39
46592
80840b651721 rhg: Group values passed to every sub-command into a struct
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
    40
    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
    41
46593
5ce2aa7c2ad5 rhg: Move `Repo` object creation into `main()`
Simon Sapin <simon.sapin@octobus.net>
parents: 46592
diff changeset
    42
    let repo = invocation.repo?;
48409
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    43
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    44
    // It seems better if this check is removed: this would correspond to
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    45
    // automatically enabling the extension if the repo requires it.
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    46
    // However we need this check to be in sync with vanilla hg so hg tests
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    47
    // pass.
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    48
    if repo.has_sparse()
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    49
        && invocation.config.get(b"extensions", b"sparse").is_none()
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    50
    {
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    51
        return Err(CommandError::unsupported(
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    52
            "repo is using sparse, but sparse extension is not enabled",
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    53
        ));
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    54
    }
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    55
46500
184e46550dc8 rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46484
diff changeset
    56
    if let Some(rev) = rev {
48409
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    57
        if repo.has_narrow() {
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    58
            return Err(CommandError::unsupported(
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    59
                "rhg files -r <rev> is not supported in narrow clones",
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    60
            ));
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    61
        }
46593
5ce2aa7c2ad5 rhg: Move `Repo` object creation into `main()`
Simon Sapin <simon.sapin@octobus.net>
parents: 46592
diff changeset
    62
        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
    63
        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
    64
    } else {
48409
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    65
        // The dirstate always reflects the sparse narrowspec, so if
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    66
        // we only have sparse without narrow all is fine.
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    67
        // If we have narrow, then [hg files] needs to check if
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    68
        // the store narrowspec is in sync with the one of the dirstate,
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    69
        // so we can't support that without explicit code.
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    70
        if repo.has_narrow() {
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    71
            return Err(CommandError::unsupported(
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    72
                "rhg files is not supported in narrow clones",
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    73
            ));
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48342
diff changeset
    74
        }
46593
5ce2aa7c2ad5 rhg: Move `Repo` object creation into `main()`
Simon Sapin <simon.sapin@octobus.net>
parents: 46592
diff changeset
    75
        let distate = Dirstate::new(repo)?;
46500
184e46550dc8 rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46484
diff changeset
    76
        let files = distate.tracked_files()?;
48342
10c32e1b892a rhg: Propogate manifest parse errors instead of panicking
Simon Sapin <simon.sapin@octobus.net>
parents: 48174
diff changeset
    77
        display_files(invocation.ui, repo, files.into_iter().map(Ok))
45364
5fe25f8ef5d9 rhg: add a `Files` `Command` to prepare the `rhg files` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    78
    }
5fe25f8ef5d9 rhg: add a `Files` `Command` to prepare the `rhg files` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    79
}
45535
72b7d58d6e35 hg-core: simplify `list_tracked_files` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45438
diff changeset
    80
46500
184e46550dc8 rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46484
diff changeset
    81
fn display_files<'a>(
184e46550dc8 rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46484
diff changeset
    82
    ui: &Ui,
184e46550dc8 rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46484
diff changeset
    83
    repo: &Repo,
48342
10c32e1b892a rhg: Propogate manifest parse errors instead of panicking
Simon Sapin <simon.sapin@octobus.net>
parents: 48174
diff changeset
    84
    files: impl IntoIterator<Item = Result<&'a HgPath, HgError>>,
46500
184e46550dc8 rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46484
diff changeset
    85
) -> Result<(), CommandError> {
184e46550dc8 rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46484
diff changeset
    86
    let mut stdout = ui.stdout_buffer();
48174
9ecf802b06e0 rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46925
diff changeset
    87
    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
    88
48174
9ecf802b06e0 rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46925
diff changeset
    89
    relativize_paths(repo, files, |path: Cow<[u8]>| -> Result<(), UiError> {
9ecf802b06e0 rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46925
diff changeset
    90
        any = true;
9ecf802b06e0 rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46925
diff changeset
    91
        stdout.write_all(path.as_ref())?;
9ecf802b06e0 rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46925
diff changeset
    92
        stdout.write_all(b"\n")
9ecf802b06e0 rhg: refactor function to relativize paths in utils
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46925
diff changeset
    93
    })?;
46500
184e46550dc8 rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46484
diff changeset
    94
    stdout.flush()?;
46745
63bfcddddac1 rhg: Exit with an error code if `files` finds nothing
Simon Sapin <simon.sapin@octobus.net>
parents: 46740
diff changeset
    95
    if any {
63bfcddddac1 rhg: Exit with an error code if `files` finds nothing
Simon Sapin <simon.sapin@octobus.net>
parents: 46740
diff changeset
    96
        Ok(())
63bfcddddac1 rhg: Exit with an error code if `files` finds nothing
Simon Sapin <simon.sapin@octobus.net>
parents: 46740
diff changeset
    97
    } else {
63bfcddddac1 rhg: Exit with an error code if `files` finds nothing
Simon Sapin <simon.sapin@octobus.net>
parents: 46740
diff changeset
    98
        Err(CommandError::Unsuccessful)
63bfcddddac1 rhg: Exit with an error code if `files` finds nothing
Simon Sapin <simon.sapin@octobus.net>
parents: 46740
diff changeset
    99
    }
45537
2f8227a12592 rhg: add `--revision` argument to `rhg files`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45535
diff changeset
   100
}