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
--- 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<Item = &'a HgPath>,
+ ) -> 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 {
--- 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<Self, Self::Error> {
+ let rev = args.value_of("rev");
+ Ok(commands::files::FilesCommand::new(rev))
+ }
+}
+
impl<'a> TryFrom<&'a ArgMatches<'_>>
for commands::debugdata::DebugDataCommand<'a>
{