cat.rs
75 lines
| 2.1 KiB
| application/rls-services+xml
|
RustLexer
Simon Sapin
|
r47163 | use crate::error::CommandError; | ||
Antoine Cezar
|
r46113 | use crate::ui::Ui; | ||
Simon Sapin
|
r47251 | use clap::Arg; | ||
Simon Sapin
|
r47250 | use clap::ArgMatches; | ||
Simon Sapin
|
r47213 | use hg::config::Config; | ||
Simon Sapin
|
r47165 | use hg::operations::cat; | ||
Simon Sapin
|
r46782 | use hg::repo::Repo; | ||
Antoine Cezar
|
r46113 | use hg::utils::hg_path::HgPathBuf; | ||
use micro_timer::timed; | ||||
use std::convert::TryFrom; | ||||
Simon Sapin
|
r47253 | use std::path::Path; | ||
Antoine Cezar
|
r46113 | |||
pub const HELP_TEXT: &str = " | ||||
Output the current or given revision of files | ||||
"; | ||||
Simon Sapin
|
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") | ||||
.long("--revision") | ||||
.value_name("REV") | ||||
.takes_value(true), | ||||
) | ||||
.arg( | ||||
clap::Arg::with_name("files") | ||||
.required(true) | ||||
.multiple(true) | ||||
.empty_values(false) | ||||
.value_name("FILE") | ||||
.help("Activity to start: activity@category"), | ||||
) | ||||
.about(HELP_TEXT) | ||||
} | ||||
Simon Sapin
|
r47250 | #[timed] | ||
pub fn run( | ||||
ui: &Ui, | ||||
config: &Config, | ||||
Simon Sapin
|
r47253 | repo_path: Option<&Path>, | ||
Simon Sapin
|
r47250 | args: &ArgMatches, | ||
) -> Result<(), CommandError> { | ||||
let rev = args.value_of("rev"); | ||||
let file_args = match args.values_of("files") { | ||||
Some(files) => files.collect(), | ||||
None => vec![], | ||||
}; | ||||
Antoine Cezar
|
r46113 | |||
Simon Sapin
|
r47253 | let repo = Repo::find(config, repo_path)?; | ||
Simon Sapin
|
r47250 | let cwd = hg::utils::current_dir()?; | ||
let mut files = vec![]; | ||||
for file in file_args.iter() { | ||||
// TODO: actually normalize `..` path segments etc? | ||||
let normalized = cwd.join(&file); | ||||
let stripped = normalized | ||||
.strip_prefix(&repo.working_directory_path()) | ||||
// 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
|
r46113 | } | ||
Simon Sapin
|
r47250 | match rev { | ||
Some(rev) => { | ||||
let data = cat(&repo, rev, &files).map_err(|e| (e, rev))?; | ||||
ui.write_stdout(&data)?; | ||||
Ok(()) | ||||
} | ||||
None => Err(CommandError::Unimplemented.into()), | ||||
Antoine Cezar
|
r46113 | } | ||
} | ||||