cat.rs
57 lines
| 1.6 KiB
| application/rls-services+xml
|
RustLexer
Antoine Cezar
|
r46113 | use crate::commands::Command; | ||
Simon Sapin
|
r47163 | use crate::error::CommandError; | ||
Antoine Cezar
|
r46113 | use crate::ui::Ui; | ||
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; | ||||
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
|
r46782 | let repo = Repo::find()?; | ||
Simon Sapin
|
r47174 | let cwd = hg::utils::current_dir()?; | ||
Antoine Cezar
|
r46113 | |||
let mut files = vec![]; | ||||
for file in self.files.iter() { | ||||
Simon Sapin
|
r47174 | // TODO: actually normalize `..` path segments etc? | ||
Antoine Cezar
|
r46113 | let normalized = cwd.join(&file); | ||
let stripped = normalized | ||||
Simon Sapin
|
r46782 | .strip_prefix(&repo.working_directory_path()) | ||
Simon Sapin
|
r47174 | // TODO: error message for path arguments outside of the repo | ||
.map_err(|_| CommandError::abort(""))?; | ||||
Antoine Cezar
|
r46113 | let hg_file = HgPathBuf::try_from(stripped.to_path_buf()) | ||
Simon Sapin
|
r47174 | .map_err(|e| CommandError::abort(e.to_string()))?; | ||
Antoine Cezar
|
r46113 | files.push(hg_file); | ||
} | ||||
match self.rev { | ||||
Some(rev) => { | ||||
Simon Sapin
|
r47165 | let data = cat(&repo, rev, &files).map_err(|e| (e, rev))?; | ||
Antoine Cezar
|
r46113 | self.display(ui, &data) | ||
} | ||||
Simon Sapin
|
r47163 | None => Err(CommandError::Unimplemented.into()), | ||
Antoine Cezar
|
r46113 | } | ||
} | ||||
} | ||||