Patchwork D8612: rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`

login
register
mail settings
Submitter phabricator
Date June 5, 2020, 2:33 p.m.
Message ID <differential-rev-PHID-DREV-4tlc242avyf2dkhzlzds-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/46475/
State Superseded
Headers show

Comments

phabricator - June 5, 2020, 2:33 p.m.
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

Patch

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<CommandErrorKind> 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"