cat.rs
106 lines
| 3.4 KiB
| application/rls-services+xml
|
RustLexer
Antoine Cezar
|
r46113 | use crate::commands::Command; | ||
use crate::error::{CommandError, CommandErrorKind}; | ||||
use crate::ui::utf8_to_local; | ||||
use crate::ui::Ui; | ||||
Simon Sapin
|
r46751 | use hg::operations::find_root; | ||
use hg::operations::{cat, CatRevError, CatRevErrorKind}; | ||||
Simon Sapin
|
r46549 | use hg::requirements; | ||
Antoine Cezar
|
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> { | ||||
Simon Sapin
|
r46751 | let root = find_root()?; | ||
Simon Sapin
|
r46549 | requirements::check(&root)?; | ||
Antoine Cezar
|
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
|
r46178 | .or(Err(CommandErrorKind::Abort(None)))?; | ||
Antoine Cezar
|
r46113 | let hg_file = HgPathBuf::try_from(stripped.to_path_buf()) | ||
Antoine cezar
|
r46178 | .or(Err(CommandErrorKind::Abort(None)))?; | ||
Antoine Cezar
|
r46113 | files.push(hg_file); | ||
} | ||||
match self.rev { | ||||
Some(rev) => { | ||||
Simon Sapin
|
r46751 | let data = cat(&root, rev, &files) | ||
Antoine Cezar
|
r46113 | .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!( | ||||
Simon Sapin
|
r46611 | "abort: invalid revision identifier {}\n", | ||
Antoine Cezar
|
r46113 | rev | ||
)) | ||||
.into(), | ||||
)), | ||||
Simon Sapin
|
r46646 | CatRevErrorKind::AmbiguousPrefix => CommandErrorKind::Abort(Some( | ||
utf8_to_local(&format!( | ||||
"abort: ambiguous revision identifier {}\n", | ||||
rev | ||||
)) | ||||
.into(), | ||||
)), | ||||
Antoine Cezar
|
r46113 | 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(), | ||||
)) | ||||
} | ||||
}, | ||||
} | ||||
} | ||||