##// END OF EJS Templates
tracked-key: remove the dual write and rename to tracked-hint...
tracked-key: remove the dual write and rename to tracked-hint The dual-write approach was mostly useless. As explained in the previous version of the help, the key had to be read twice before we could cache a value. However this "read twice" limitation actually also apply to any usage of the key. If some operation wants to rely of the "same value == same tracked set" property it would need to read the value before, and after running that operation (or at least, after, in all cases). So it cannot be sure the operation it did is "valid" until checking the key after the operation. As a resultat such operation can only be read-only or rollbackable. This reduce the utility of the "same value == same tracked set" a lot. So it seems simpler to drop the double write and to update the documentation to highlight that this file does not garantee race-free operation. As a result the "key" is demoted to a "hint". Documentation is updated accordingly. Differential Revision: https://phab.mercurial-scm.org/D12201

File last commit:

r49129:698b70b9 default
r49644:6e559391 default
Show More
cat.rs
105 lines | 3.5 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;
use micro_timer::timed;
use std::convert::TryFrom;
pub const HELP_TEXT: &str = "
Output the current or given revision of files
";
Simon Sapin
rhg: Move subcommand CLI arguments definitions to respective modules...
r47251 pub fn args() -> clap::App<'static, 'static> {
clap::SubCommand::with_name("cat")
.arg(
Arg::with_name("rev")
.help("search the repository as it is in REV")
.short("-r")
Arseniy Alekseyev
rhg: in rhg cat cli, fix the long name of the --rev flag...
r48986 .long("--rev")
Simon Sapin
rhg: Move subcommand CLI arguments definitions to respective modules...
r47251 .value_name("REV")
.takes_value(true),
)
.arg(
clap::Arg::with_name("files")
.required(true)
.multiple(true)
.empty_values(false)
.value_name("FILE")
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)
}
Simon Sapin
rhg: replace command structs with functions...
r47250 #[timed]
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')",
));
}
Simon Sapin
rhg: Group values passed to every sub-command into a struct...
r47334 let rev = invocation.subcommand_args.value_of("rev");
let file_args = match invocation.subcommand_args.values_of("files") {
Simon Sapin
rhg: replace command structs with functions...
r47250 Some(files) => files.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![];
for file in file_args.iter() {
Raphaël Gomès
rhg-cat: fallback in presence of a fileset...
r48888 if file.starts_with("set:") {
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() == "..");
if file == &"." || dotted {
let message = "`..` or `.` path segment";
return Err(CommandError::unsupported(message));
}
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)
Simon Sapin
rhg: replace command structs with functions...
r47250 // TODO: error message for path arguments outside of the repo
.map_err(|_| CommandError::abort(""))?;
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
Arseniy Alekseyev
rhg: faster hg cat when many files are requested...
r49038 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 }
}