From patchwork Fri Jun 5 14:33:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: D8612: rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root` From: phabricator X-Patchwork-Id: 46475 Message-Id: To: Phabricator Cc: mercurial-devel@mercurial-scm.org Date: Fri, 5 Jun 2020 14:33:03 +0000 acezar created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY The println macro is not used to avoid string usage. Dealing only with bytes allows us to be compatible with any encoding and not just WTF8. Later on, format macro will be made to have more readable code. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D8612 AFFECTED FILES rust/Cargo.lock rust/rhg/Cargo.toml rust/rhg/src/commands/mod.rs rust/rhg/src/commands/root.rs rust/rhg/src/error.rs rust/rhg/src/exitcode.rs CHANGE DETAILS To: acezar, #hg-reviewers Cc: mercurial-patches, mercurial-devel diff --git a/rust/rhg/src/exitcode.rs b/rust/rhg/src/exitcode.rs --- a/rust/rhg/src/exitcode.rs +++ b/rust/rhg/src/exitcode.rs @@ -1,4 +1,10 @@ pub type ExitCode = i32; +/// Successful exit +pub const OK: ExitCode = 0; + +/// Generic abort +pub const ABORT: ExitCode = 255; + /// Command not implemented by rhg pub const UNIMPLEMENTED_COMMAND: ExitCode = 252; diff --git a/rust/rhg/src/error.rs b/rust/rhg/src/error.rs --- a/rust/rhg/src/error.rs +++ b/rust/rhg/src/error.rs @@ -1,4 +1,32 @@ +use crate::exitcode; +use std::convert::From; + +/// The kind of command error +#[derive(Debug, PartialEq)] +pub enum CommandErrorKind { + /// The command finished without error + Ok, + /// The root of the repository cannot be found + RootNotFound, +} + +impl CommandErrorKind { + pub fn get_exit_code(&self) -> exitcode::ExitCode { + match self { + CommandErrorKind::Ok => exitcode::OK, + CommandErrorKind::RootNotFound => exitcode::ABORT, + } + } +} /// The error type for the Command trait #[derive(Debug, PartialEq)] -pub struct CommandError {} +pub struct CommandError { + pub kind: CommandErrorKind, +} + +impl From for CommandError { + fn from(kind: CommandErrorKind) -> Self { + CommandError { kind } + } +} diff --git a/rust/rhg/src/commands/root.rs b/rust/rhg/src/commands/root.rs new file mode 100644 --- /dev/null +++ b/rust/rhg/src/commands/root.rs @@ -0,0 +1,79 @@ +use crate::commands::Command; +use crate::error::{CommandError, CommandErrorKind}; +use hg::operations::{FindRoot, FindRootError, FindRootErrorKind, Operation}; +use hg::utils::files::get_bytes_from_path; +use std::io::Write; +use std::path::PathBuf; + +pub const HELP_TEXT: &str = " +Print the root directory of the current repository. + +Returns 0 on success. +"; + +pub struct RootCommand; + +impl RootCommand { + fn display_found_path(path_buf: PathBuf) -> Result<(), CommandError> { + // TODO use formating macro + let mut stdout = std::io::stdout(); + let bytes = get_bytes_from_path(path_buf); + + stdout + .write_all(&[bytes.as_slice(), b"\n"].concat()) + .expect("Should be able to write to stdout"); + + Err(CommandErrorKind::Ok.into()) + } + + fn display_error(error: FindRootError) -> Result<(), CommandError> { + match error.kind { + FindRootErrorKind::RootNotFound => { + let current_dir = match error.current_dir { + Some(path) => path, + None => panic!("This should not happen"), + }; + + // TODO use formating macro + let mut stderr = std::io::stderr(); + let bytes = get_bytes_from_path(current_dir); + + stderr + .write_all( + &[ + b"abandon : no repository found in ", + bytes.as_slice(), + b" (.hg not found) !\n", + ] + .concat(), + ) + .expect("Should be able to write to stderr"); + } + FindRootErrorKind::GetCurrentDirError => { + // TODO use formating macro + let mut stderr = std::io::stderr(); + + stderr + .write_all( + &concat!( + "Current directory does not exists", + "or permissions are insufficient to get access to it" + ) + .as_bytes(), + ) + .expect("Should be able to write to stderr"); + } + } + Err(CommandErrorKind::RootNotFound.into()) + } +} + +impl Command for RootCommand { + fn run() -> Result<(), CommandError> { + let operation = FindRoot::new(); + match operation.run() { + Ok(path_buf) => RootCommand::display_found_path(path_buf), + Err(e) => RootCommand::display_error(e), + } + } +} diff --git a/rust/rhg/src/commands/mod.rs b/rust/rhg/src/commands/mod.rs --- a/rust/rhg/src/commands/mod.rs +++ b/rust/rhg/src/commands/mod.rs @@ -1,3 +1,4 @@ +pub mod root; use crate::error::CommandError; /// The common trait for rhg commands diff --git a/rust/rhg/Cargo.toml b/rust/rhg/Cargo.toml --- a/rust/rhg/Cargo.toml +++ b/rust/rhg/Cargo.toml @@ -5,4 +5,5 @@ edition = "2018" [dependencies] +hg-core = { path = "../hg-core"} diff --git a/rust/Cargo.lock b/rust/Cargo.lock --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -489,6 +489,9 @@ [[package]] name = "rhg" version = "0.1.0" +dependencies = [ + "hg-core 0.1.0", +] [[package]] name = "rustc_version"