##// END OF EJS Templates
upgrade: move optimisation to something more declarative...
upgrade: move optimisation to something more declarative This is not great yet, but still better than the previous state. This get use one step closer to having all the possible "actions" clearly declared and moved in a dedicated module. Differential Revision: https://phab.mercurial-scm.org/D9475

File last commit:

r46549:2ad2745e default
r46610:32dcd783 default
Show More
cat.rs
101 lines | 3.2 KiB | application/rls-services+xml | RustLexer
Antoine Cezar
rhg: add a limited `rhg cat -r` subcommand...
r46113 use crate::commands::Command;
use crate::error::{CommandError, CommandErrorKind};
use crate::ui::utf8_to_local;
use crate::ui::Ui;
use hg::operations::FindRoot;
use hg::operations::{CatRev, CatRevError, CatRevErrorKind};
Simon Sapin
rhg: exit with relevant code for unsupported requirements...
r46549 use hg::requirements;
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
";
pub struct CatCommand<'a> {
rev: Option<&'a str>,
files: Vec<&'a str>,
}
impl<'a> CatCommand<'a> {
pub fn new(rev: Option<&'a str>, files: Vec<&'a str>) -> Self {
Self { rev, files }
}
fn display(&self, ui: &Ui, data: &[u8]) -> Result<(), CommandError> {
ui.write_stdout(data)?;
Ok(())
}
}
impl<'a> Command for CatCommand<'a> {
#[timed]
fn run(&self, ui: &Ui) -> Result<(), CommandError> {
let root = FindRoot::new().run()?;
Simon Sapin
rhg: exit with relevant code for unsupported requirements...
r46549 requirements::check(&root)?;
Antoine Cezar
rhg: add a limited `rhg cat -r` subcommand...
r46113 let cwd = std::env::current_dir()
.or_else(|e| Err(CommandErrorKind::CurrentDirNotFound(e)))?;
let mut files = vec![];
for file in self.files.iter() {
let normalized = cwd.join(&file);
let stripped = normalized
.strip_prefix(&root)
Antoine cezar
rhg: use `.or(Err(Error))` not `.map_err(|_| Error)` (D9100#inline-15067)...
r46178 .or(Err(CommandErrorKind::Abort(None)))?;
Antoine Cezar
rhg: add a limited `rhg cat -r` subcommand...
r46113 let hg_file = HgPathBuf::try_from(stripped.to_path_buf())
Antoine cezar
rhg: use `.or(Err(Error))` not `.map_err(|_| Error)` (D9100#inline-15067)...
r46178 .or(Err(CommandErrorKind::Abort(None)))?;
Antoine Cezar
rhg: add a limited `rhg cat -r` subcommand...
r46113 files.push(hg_file);
}
match self.rev {
Some(rev) => {
let mut operation = CatRev::new(&root, rev, &files)
.map_err(|e| map_rev_error(rev, e))?;
let data =
operation.run().map_err(|e| map_rev_error(rev, e))?;
self.display(ui, &data)
}
None => Err(CommandErrorKind::Unimplemented.into()),
}
}
}
/// Convert `CatRevErrorKind` to `CommandError`
fn map_rev_error(rev: &str, err: CatRevError) -> CommandError {
CommandError {
kind: match err.kind {
CatRevErrorKind::IoError(err) => CommandErrorKind::Abort(Some(
utf8_to_local(&format!("abort: {}\n", err)).into(),
)),
CatRevErrorKind::InvalidRevision => CommandErrorKind::Abort(Some(
utf8_to_local(&format!(
"abort: invalid revision identifier{}\n",
rev
))
.into(),
)),
CatRevErrorKind::UnsuportedRevlogVersion(version) => {
CommandErrorKind::Abort(Some(
utf8_to_local(&format!(
"abort: unsupported revlog version {}\n",
version
))
.into(),
))
}
CatRevErrorKind::CorruptedRevlog => CommandErrorKind::Abort(Some(
"abort: corrupted revlog\n".into(),
)),
CatRevErrorKind::UnknowRevlogDataFormat(format) => {
CommandErrorKind::Abort(Some(
utf8_to_local(&format!(
"abort: unknow revlog dataformat {:?}\n",
format
))
.into(),
))
}
},
}
}