##// END OF EJS Templates
typing: correct the signature of error.CommandError...
typing: correct the signature of error.CommandError There's a place in `mercurial.dispatch._parse()` that passes None if a parse error happens before the command can be parsed out, and casting the error to bytes works fine because the command and message fields are apparently ignored. Likewise, TortoiseHg similarly passes None for the same reason.

File last commit:

r50809:58074252 default
r51258:3dbc7b1e stable
Show More
cat.rs
117 lines | 4.0 KiB | application/rls-services+xml | RustLexer
Simon Sapin
rust: remove `FooError` structs with only `kind: FooErrorKind` enum field...
r47163 use crate::error::CommandError;
Simon Sapin
rhg: Move subcommand CLI arguments definitions to respective modules...
r47251 use clap::Arg;
Simon Sapin
rhg: `cat` command: print error messages for missing files...
r47478 use format_bytes::format_bytes;
Simon Sapin
rhg: replace `map_*_error` functions with `From` impls...
r47165 use hg::operations::cat;
Antoine Cezar
rhg: add a limited `rhg cat -r` subcommand...
r46113 use hg::utils::hg_path::HgPathBuf;
Raphaël Gomès
rhg: upgrade `clap` dependency...
r50534 use std::ffi::OsString;
use std::os::unix::prelude::OsStrExt;
Antoine Cezar
rhg: add a limited `rhg cat -r` subcommand...
r46113
pub const HELP_TEXT: &str = "
Output the current or given revision of files
";
Raphaël Gomès
rhg: upgrade `clap` dependency...
r50534 pub fn args() -> clap::Command {
clap::command!("cat")
Simon Sapin
rhg: Move subcommand CLI arguments definitions to respective modules...
r47251 .arg(
Raphaël Gomès
rhg: upgrade `clap` dependency...
r50534 Arg::new("rev")
Simon Sapin
rhg: Move subcommand CLI arguments definitions to respective modules...
r47251 .help("search the repository as it is in REV")
Raphaël Gomès
rhg: upgrade `clap` dependency...
r50534 .short('r')
.long("rev")
.value_name("REV"),
Simon Sapin
rhg: Move subcommand CLI arguments definitions to respective modules...
r47251 )
.arg(
Raphaël Gomès
rhg: upgrade `clap` dependency...
r50534 clap::Arg::new("files")
Simon Sapin
rhg: Move subcommand CLI arguments definitions to respective modules...
r47251 .required(true)
Raphaël Gomès
rhg: upgrade `clap` dependency...
r50534 .num_args(1..)
Simon Sapin
rhg: Move subcommand CLI arguments definitions to respective modules...
r47251 .value_name("FILE")
Raphaël Gomès
rhg: upgrade `clap` dependency...
r50534 .value_parser(clap::value_parser!(std::ffi::OsString))
Arseniy Alekseyev
rhg: in rhg cat cli, fix the long name of the --rev flag...
r48986 .help("Files to output"),
Simon Sapin
rhg: Move subcommand CLI arguments definitions to respective modules...
r47251 )
.about(HELP_TEXT)
}
Raphaël Gomès
rust: use `logging_timer` instead of `micro_timer`...
r50808 #[logging_timer::time("trace")]
Simon Sapin
rhg: Group values passed to every sub-command into a struct...
r47334 pub fn run(invocation: &crate::CliInvocation) -> Result<(), CommandError> {
Arseniy Alekseyev
rhg: make it possible to opt out of `rhg cat`...
r49129 let cat_enabled_default = true;
let cat_enabled = invocation.config.get_option(b"rhg", b"cat")?;
if !cat_enabled.unwrap_or(cat_enabled_default) {
return Err(CommandError::unsupported(
"cat is disabled in rhg (enable it with 'rhg.cat = true' \
or enable fallback with 'rhg.on-unsupported = fallback')",
));
}
Raphaël Gomès
rhg: upgrade `clap` dependency...
r50534 let rev = invocation.subcommand_args.get_one::<String>("rev");
let file_args =
match invocation.subcommand_args.get_many::<OsString>("files") {
Some(files) => files
.filter(|s| !s.is_empty())
.map(|s| s.as_os_str())
.collect(),
None => vec![],
};
Antoine Cezar
rhg: add a limited `rhg cat -r` subcommand...
r46113
Simon Sapin
rhg: Move `Repo` object creation into `main()`...
r47335 let repo = invocation.repo?;
Simon Sapin
rhg: replace command structs with functions...
r47250 let cwd = hg::utils::current_dir()?;
Simon Sapin
rhg: Don’t make repository path absolute too early...
r47474 let working_directory = repo.working_directory_path();
let working_directory = cwd.join(working_directory); // Make it absolute
Simon Sapin
rhg: replace command structs with functions...
r47250
let mut files = vec![];
Raphaël Gomès
rhg: upgrade `clap` dependency...
r50534 for file in file_args {
if file.as_bytes().starts_with(b"set:") {
Raphaël Gomès
rhg-cat: fallback in presence of a fileset...
r48888 let message = "fileset";
return Err(CommandError::unsupported(message));
}
Raphaël Gomès
rhg-cat: fallback when detecting `.` or `..` path segments...
r48887 let normalized = cwd.join(&file);
Simon Sapin
rhg: replace command structs with functions...
r47250 // TODO: actually normalize `..` path segments etc?
Raphaël Gomès
rhg-cat: fallback when detecting `.` or `..` path segments...
r48887 let dotted = normalized.components().any(|c| c.as_os_str() == "..");
Raphaël Gomès
rhg: upgrade `clap` dependency...
r50534 if file.as_bytes() == b"." || dotted {
Raphaël Gomès
rhg-cat: fallback when detecting `.` or `..` path segments...
r48887 let message = "`..` or `.` path segment";
return Err(CommandError::unsupported(message));
}
Raphaël Gomès
rhg: add error message for paths outside the repository when cwd != root...
r50270 let relative_path = working_directory
.strip_prefix(&cwd)
.unwrap_or(&working_directory);
Simon Sapin
rhg: replace command structs with functions...
r47250 let stripped = normalized
Simon Sapin
rhg: Don’t make repository path absolute too early...
r47474 .strip_prefix(&working_directory)
Raphaël Gomès
rhg: add error message for paths outside the repository when cwd != root...
r50270 .map_err(|_| {
CommandError::abort(format!(
"abort: {} not under root '{}'\n(consider using '--cwd {}')",
Raphaël Gomès
rhg: upgrade `clap` dependency...
r50534 String::from_utf8_lossy(file.as_bytes()),
Raphaël Gomès
rhg: add error message for paths outside the repository when cwd != root...
r50270 working_directory.display(),
relative_path.display(),
))
})?;
Simon Sapin
rhg: replace command structs with functions...
r47250 let hg_file = HgPathBuf::try_from(stripped.to_path_buf())
.map_err(|e| CommandError::abort(e.to_string()))?;
files.push(hg_file);
Antoine Cezar
rhg: add a limited `rhg cat -r` subcommand...
r46113 }
Arseniy Alekseyev
rhg: internally, return a structured representation from hg cat...
r49051 let files = files.iter().map(|file| file.as_ref()).collect();
Raphaël Gomès
rhg: add support for calling `rhg cat` without a revision...
r48886 // TODO probably move this to a util function like `repo.default_rev` or
// something when it's used somewhere else
let rev = match rev {
Some(r) => r.to_string(),
None => format!("{:x}", repo.dirstate_parents()?.p1),
};
Antoine Cezar
rhg: add a limited `rhg cat -r` subcommand...
r46113
Raphaël Gomès
rust: run `cargo clippy`...
r50809 let output = cat(repo, &rev, files).map_err(|e| (e, rev.as_str()))?;
Arseniy Alekseyev
rhg: internally, return a structured representation from hg cat...
r49051 for (_file, contents) in output.results {
invocation.ui.write_stdout(&contents)?;
}
Raphaël Gomès
rhg: add support for calling `rhg cat` without a revision...
r48886 if !output.missing.is_empty() {
let short = format!("{:x}", output.node.short()).into_bytes();
for path in &output.missing {
invocation.ui.write_stderr(&format_bytes!(
b"{}: no such file in rev {}\n",
path.as_bytes(),
short
))?;
Simon Sapin
rhg: replace command structs with functions...
r47250 }
Raphaël Gomès
rhg: add support for calling `rhg cat` without a revision...
r48886 }
if output.found_any {
Ok(())
} else {
Err(CommandError::Unsuccessful)
Antoine Cezar
rhg: add a limited `rhg cat -r` subcommand...
r46113 }
}