# HG changeset patch # User Antoine Cezar # Date 1599655995 -7200 # Node ID 2f8227a125928a6f1670adb74c7bd117d7e5d958 # Parent 639f33f22faf1bb7627169299fa03ab4fb54ac48 rhg: add `--revision` argument to `rhg files` Add the option to list the tracked files of a revision given its number or full node id. Benched on a clone of moz-central where tip is 1671467:81deaa1a68ebb28db0490954034ab38ab269409d files -r 81deaa1a68ebb28db0490954034ab38ab269409d > out.txt hg 0m1.633s rhg 0m0.157s files -r 81deaa1a68ebb28db0490954034ab38ab269409d > /dev/null hg 0m0.415s rhg 0m0.143s Differential Revision: https://phab.mercurial-scm.org/D9015 diff -r 639f33f22faf -r 2f8227a12592 rust/rhg/src/commands/files.rs --- a/rust/rhg/src/commands/files.rs Fri Sep 18 16:52:16 2020 +0200 +++ b/rust/rhg/src/commands/files.rs Wed Sep 09 14:53:15 2020 +0200 @@ -7,8 +7,13 @@ ListDirstateTrackedFiles, ListDirstateTrackedFilesError, ListDirstateTrackedFilesErrorKind, }; +use hg::operations::{ + ListRevTrackedFiles, ListRevTrackedFilesError, + ListRevTrackedFilesErrorKind, +}; use hg::utils::files::{get_bytes_from_path, relativize_path}; -use hg::utils::hg_path::HgPathBuf; +use hg::utils::hg_path::{HgPath, HgPathBuf}; +use std::path::PathBuf; pub const HELP_TEXT: &str = " List tracked files. @@ -16,21 +21,21 @@ Returns 0 on success. "; -pub struct FilesCommand {} - -impl FilesCommand { - pub fn new() -> Self { - FilesCommand {} - } +pub struct FilesCommand<'a> { + rev: Option<&'a str>, } -impl Command for FilesCommand { - fn run(&self, ui: &Ui) -> Result<(), CommandError> { - let root = FindRoot::new().run()?; - let mut operation = ListDirstateTrackedFiles::new(&root) - .map_err(map_dirstate_error)?; - let files = operation.run().map_err(map_dirstate_error)?; +impl<'a> FilesCommand<'a> { + pub fn new(rev: Option<&'a str>) -> Self { + FilesCommand { rev } + } + fn display_files( + &self, + ui: &Ui, + root: &PathBuf, + files: impl IntoIterator, + ) -> Result<(), CommandError> { let cwd = std::env::current_dir() .or_else(|e| Err(CommandErrorKind::CurrentDirNotFound(e)))?; let rooted_cwd = cwd @@ -49,7 +54,69 @@ } } -/// Convert operation errors to command errors +impl<'a> Command for FilesCommand<'a> { + fn run(&self, ui: &Ui) -> Result<(), CommandError> { + let root = FindRoot::new().run()?; + if let Some(rev) = self.rev { + let mut operation = ListRevTrackedFiles::new(&root, rev) + .map_err(|e| map_rev_error(rev, e))?; + let files = operation.run().map_err(|e| map_rev_error(rev, e))?; + self.display_files(ui, &root, files) + } else { + let mut operation = ListDirstateTrackedFiles::new(&root) + .map_err(map_dirstate_error)?; + let files = operation.run().map_err(map_dirstate_error)?; + self.display_files(ui, &root, files) + } + } +} + +/// Convert `ListRevTrackedFilesErrorKind` to `CommandError` +fn map_rev_error(rev: &str, err: ListRevTrackedFilesError) -> CommandError { + CommandError { + kind: match err.kind { + ListRevTrackedFilesErrorKind::IoError(err) => { + CommandErrorKind::Abort(Some( + utf8_to_local(&format!("abort: {}\n", err)).into(), + )) + } + ListRevTrackedFilesErrorKind::InvalidRevision => { + CommandErrorKind::Abort(Some( + utf8_to_local(&format!( + "abort: invalid revision identifier{}\n", + rev + )) + .into(), + )) + } + ListRevTrackedFilesErrorKind::UnsuportedRevlogVersion(version) => { + CommandErrorKind::Abort(Some( + utf8_to_local(&format!( + "abort: unsupported revlog version {}\n", + version + )) + .into(), + )) + } + ListRevTrackedFilesErrorKind::CorruptedRevlog => { + CommandErrorKind::Abort(Some( + "abort: corrupted revlog\n".into(), + )) + } + ListRevTrackedFilesErrorKind::UnknowRevlogDataFormat(format) => { + CommandErrorKind::Abort(Some( + utf8_to_local(&format!( + "abort: unknow revlog dataformat {:?}\n", + format + )) + .into(), + )) + } + }, + } +} + +/// Convert `ListDirstateTrackedFilesError` to `CommandError` fn map_dirstate_error(err: ListDirstateTrackedFilesError) -> CommandError { CommandError { kind: match err.kind { diff -r 639f33f22faf -r 2f8227a12592 rust/rhg/src/main.rs --- a/rust/rhg/src/main.rs Fri Sep 18 16:52:16 2020 +0200 +++ b/rust/rhg/src/main.rs Wed Sep 09 14:53:15 2020 +0200 @@ -26,7 +26,16 @@ SubCommand::with_name("root").about(commands::root::HELP_TEXT), ) .subcommand( - SubCommand::with_name("files").about(commands::files::HELP_TEXT), + SubCommand::with_name("files") + .arg( + Arg::with_name("rev") + .help("search the repository as it is in REV") + .short("-r") + .long("--revision") + .value_name("REV") + .takes_value(true), + ) + .about(commands::files::HELP_TEXT), ) .subcommand( SubCommand::with_name("debugdata") @@ -86,7 +95,9 @@ ) -> Result<(), CommandError> { match matches.subcommand() { ("root", _) => commands::root::RootCommand::new().run(&ui), - ("files", _) => commands::files::FilesCommand::new().run(&ui), + ("files", Some(matches)) => { + commands::files::FilesCommand::try_from(matches)?.run(&ui) + } ("debugdata", Some(matches)) => { commands::debugdata::DebugDataCommand::try_from(matches)?.run(&ui) } @@ -94,6 +105,15 @@ } } +impl<'a> TryFrom<&'a ArgMatches<'_>> for commands::files::FilesCommand<'a> { + type Error = CommandError; + + fn try_from(args: &'a ArgMatches) -> Result { + let rev = args.value_of("rev"); + Ok(commands::files::FilesCommand::new(rev)) + } +} + impl<'a> TryFrom<&'a ArgMatches<'_>> for commands::debugdata::DebugDataCommand<'a> {