Show More
@@ -4,6 +4,6 b' use crate::error::CommandError;' | |||||
4 | /// The common trait for rhg commands |
|
4 | /// The common trait for rhg commands | |
5 | /// |
|
5 | /// | |
6 | /// Normalize the interface of the commands provided by rhg |
|
6 | /// Normalize the interface of the commands provided by rhg | |
7 | pub trait Command { |
|
7 | pub trait Command<'a> { | |
8 | fn run(&self) -> Result<(), CommandError>; |
|
8 | fn run(&self) -> Result<(), CommandError>; | |
9 | } |
|
9 | } |
@@ -1,9 +1,8 b'' | |||||
1 | use crate::commands::Command; |
|
1 | use crate::commands::Command; | |
2 | use crate::error::{CommandError, CommandErrorKind}; |
|
2 | use crate::error::{CommandError, CommandErrorKind}; | |
3 | use crate::ui::Ui; |
|
3 | use crate::ui::Ui; | |
4 |
use hg::operations::{FindRoot, |
|
4 | use hg::operations::{FindRoot, FindRootErrorKind}; | |
5 | use hg::utils::files::get_bytes_from_path; |
|
5 | use hg::utils::files::get_bytes_from_path; | |
6 | use std::path::PathBuf; |
|
|||
7 |
|
6 | |||
8 | pub const HELP_TEXT: &str = " |
|
7 | pub const HELP_TEXT: &str = " | |
9 | Print the root directory of the current repository. |
|
8 | Print the root directory of the current repository. | |
@@ -11,19 +10,28 b' Print the root directory of the current ' | |||||
11 | Returns 0 on success. |
|
10 | Returns 0 on success. | |
12 | "; |
|
11 | "; | |
13 |
|
12 | |||
14 | pub struct RootCommand { |
|
13 | pub struct RootCommand<'a> { | |
15 | ui: Ui, |
|
14 | ui: &'a Ui, | |
|
15 | } | |||
|
16 | ||||
|
17 | impl<'a> RootCommand<'a> { | |||
|
18 | pub fn new(ui: &'a Ui) -> Self { | |||
|
19 | RootCommand { ui } | |||
|
20 | } | |||
16 | } |
|
21 | } | |
17 |
|
22 | |||
18 | impl RootCommand { |
|
23 | impl<'a> Command<'a> for RootCommand<'a> { | |
19 | pub fn new() -> Self { |
|
24 | fn run(&self) -> Result<(), CommandError> { | |
20 | RootCommand { ui: Ui::new() } |
|
25 | let path_buf = | |
21 | } |
|
26 | FindRoot::new().run().map_err(|err| match err.kind { | |
|
27 | FindRootErrorKind::RootNotFound(path) => { | |||
|
28 | CommandErrorKind::RootNotFound(path) | |||
|
29 | } | |||
|
30 | FindRootErrorKind::GetCurrentDirError(e) => { | |||
|
31 | CommandErrorKind::CurrentDirNotFound(e) | |||
|
32 | } | |||
|
33 | })?; | |||
22 |
|
34 | |||
23 | fn display_found_path( |
|
|||
24 | &self, |
|
|||
25 | path_buf: PathBuf, |
|
|||
26 | ) -> Result<(), CommandError> { |
|
|||
27 | let bytes = get_bytes_from_path(path_buf); |
|
35 | let bytes = get_bytes_from_path(path_buf); | |
28 |
|
36 | |||
29 | // TODO use formating macro |
|
37 | // TODO use formating macro | |
@@ -31,46 +39,4 b' impl RootCommand {' | |||||
31 |
|
39 | |||
32 | Ok(()) |
|
40 | Ok(()) | |
33 | } |
|
41 | } | |
34 |
|
||||
35 | fn display_error(&self, error: FindRootError) -> Result<(), CommandError> { |
|
|||
36 | match error.kind { |
|
|||
37 | FindRootErrorKind::RootNotFound(path) => { |
|
|||
38 | let bytes = get_bytes_from_path(path); |
|
|||
39 |
|
||||
40 | // TODO use formating macro |
|
|||
41 | self.ui.write_stderr( |
|
|||
42 | &[ |
|
|||
43 | b"abort: no repository found in '", |
|
|||
44 | bytes.as_slice(), |
|
|||
45 | b"' (.hg not found)!\n", |
|
|||
46 | ] |
|
|||
47 | .concat(), |
|
|||
48 | )?; |
|
|||
49 |
|
||||
50 | Err(CommandErrorKind::RootNotFound.into()) |
|
|||
51 | } |
|
|||
52 | FindRootErrorKind::GetCurrentDirError(e) => { |
|
|||
53 | // TODO use formating macro |
|
|||
54 | self.ui.write_stderr( |
|
|||
55 | &[ |
|
|||
56 | b"abort: error getting current working directory: ", |
|
|||
57 | e.to_string().as_bytes(), |
|
|||
58 | b"\n", |
|
|||
59 | ] |
|
|||
60 | .concat(), |
|
|||
61 | )?; |
|
|||
62 |
|
||||
63 | Err(CommandErrorKind::CurrentDirNotFound.into()) |
|
|||
64 | } |
|
|||
65 | } |
|
|||
66 | } |
|
|||
67 | } |
|
42 | } | |
68 |
|
||||
69 | impl Command for RootCommand { |
|
|||
70 | fn run(&self) -> Result<(), CommandError> { |
|
|||
71 | match FindRoot::new().run() { |
|
|||
72 | Ok(path_buf) => self.display_found_path(path_buf), |
|
|||
73 | Err(e) => self.display_error(e), |
|
|||
74 | } |
|
|||
75 | } |
|
|||
76 | } |
|
@@ -1,14 +1,16 b'' | |||||
1 | use crate::exitcode; |
|
1 | use crate::exitcode; | |
2 | use crate::ui::UiError; |
|
2 | use crate::ui::UiError; | |
|
3 | use hg::utils::files::get_bytes_from_path; | |||
3 | use std::convert::From; |
|
4 | use std::convert::From; | |
|
5 | use std::path::PathBuf; | |||
4 |
|
6 | |||
5 | /// The kind of command error |
|
7 | /// The kind of command error | |
6 |
#[derive(Debug |
|
8 | #[derive(Debug)] | |
7 | pub enum CommandErrorKind { |
|
9 | pub enum CommandErrorKind { | |
8 | /// The root of the repository cannot be found |
|
10 | /// The root of the repository cannot be found | |
9 | RootNotFound, |
|
11 | RootNotFound(PathBuf), | |
10 | /// The current directory cannot be found |
|
12 | /// The current directory cannot be found | |
11 | CurrentDirNotFound, |
|
13 | CurrentDirNotFound(std::io::Error), | |
12 | /// The standard output stream cannot be written to |
|
14 | /// The standard output stream cannot be written to | |
13 | StdoutError, |
|
15 | StdoutError, | |
14 | /// The standard error stream cannot be written to |
|
16 | /// The standard error stream cannot be written to | |
@@ -18,16 +20,44 b' pub enum CommandErrorKind {' | |||||
18 | impl CommandErrorKind { |
|
20 | impl CommandErrorKind { | |
19 | pub fn get_exit_code(&self) -> exitcode::ExitCode { |
|
21 | pub fn get_exit_code(&self) -> exitcode::ExitCode { | |
20 | match self { |
|
22 | match self { | |
21 | CommandErrorKind::RootNotFound => exitcode::ABORT, |
|
23 | CommandErrorKind::RootNotFound(_) => exitcode::ABORT, | |
22 | CommandErrorKind::CurrentDirNotFound => exitcode::ABORT, |
|
24 | CommandErrorKind::CurrentDirNotFound(_) => exitcode::ABORT, | |
23 | CommandErrorKind::StdoutError => exitcode::ABORT, |
|
25 | CommandErrorKind::StdoutError => exitcode::ABORT, | |
24 | CommandErrorKind::StderrError => exitcode::ABORT, |
|
26 | CommandErrorKind::StderrError => exitcode::ABORT, | |
25 | } |
|
27 | } | |
26 | } |
|
28 | } | |
|
29 | ||||
|
30 | /// Return the message corresponding to the error kind if any | |||
|
31 | pub fn get_error_message_bytes(&self) -> Option<Vec<u8>> { | |||
|
32 | match self { | |||
|
33 | // TODO use formating macro | |||
|
34 | CommandErrorKind::RootNotFound(path) => { | |||
|
35 | let bytes = get_bytes_from_path(path); | |||
|
36 | Some( | |||
|
37 | [ | |||
|
38 | b"abort: no repository found in '", | |||
|
39 | bytes.as_slice(), | |||
|
40 | b"' (.hg not found)!\n", | |||
|
41 | ] | |||
|
42 | .concat(), | |||
|
43 | ) | |||
|
44 | } | |||
|
45 | // TODO use formating macro | |||
|
46 | CommandErrorKind::CurrentDirNotFound(e) => Some( | |||
|
47 | [ | |||
|
48 | b"abort: error getting current working directory: ", | |||
|
49 | e.to_string().as_bytes(), | |||
|
50 | b"\n", | |||
|
51 | ] | |||
|
52 | .concat(), | |||
|
53 | ), | |||
|
54 | _ => None, | |||
|
55 | } | |||
|
56 | } | |||
27 | } |
|
57 | } | |
28 |
|
58 | |||
29 | /// The error type for the Command trait |
|
59 | /// The error type for the Command trait | |
30 |
#[derive(Debug |
|
60 | #[derive(Debug)] | |
31 | pub struct CommandError { |
|
61 | pub struct CommandError { | |
32 | pub kind: CommandErrorKind, |
|
62 | pub kind: CommandErrorKind, | |
33 | } |
|
63 | } | |
@@ -37,6 +67,11 b' impl CommandError {' | |||||
37 | pub fn exit(&self) -> () { |
|
67 | pub fn exit(&self) -> () { | |
38 | std::process::exit(self.kind.get_exit_code()) |
|
68 | std::process::exit(self.kind.get_exit_code()) | |
39 | } |
|
69 | } | |
|
70 | ||||
|
71 | /// Return the message corresponding to the command error if any | |||
|
72 | pub fn get_error_message_bytes(&self) -> Option<Vec<u8>> { | |||
|
73 | self.kind.get_error_message_bytes() | |||
|
74 | } | |||
40 | } |
|
75 | } | |
41 |
|
76 | |||
42 | impl From<CommandErrorKind> for CommandError { |
|
77 | impl From<CommandErrorKind> for CommandError { |
@@ -22,9 +22,11 b' fn main() {' | |||||
22 | std::process::exit(exitcode::UNIMPLEMENTED_COMMAND) |
|
22 | std::process::exit(exitcode::UNIMPLEMENTED_COMMAND) | |
23 | }); |
|
23 | }); | |
24 |
|
24 | |||
|
25 | let ui = ui::Ui::new(); | |||
|
26 | ||||
25 | let command_result = match matches.subcommand_name() { |
|
27 | let command_result = match matches.subcommand_name() { | |
26 | Some(name) => match name { |
|
28 | Some(name) => match name { | |
27 | "root" => commands::root::RootCommand::new().run(), |
|
29 | "root" => commands::root::RootCommand::new(&ui).run(), | |
28 | _ => std::process::exit(exitcode::UNIMPLEMENTED_COMMAND), |
|
30 | _ => std::process::exit(exitcode::UNIMPLEMENTED_COMMAND), | |
29 | }, |
|
31 | }, | |
30 | _ => { |
|
32 | _ => { | |
@@ -37,6 +39,15 b' fn main() {' | |||||
37 |
|
39 | |||
38 | match command_result { |
|
40 | match command_result { | |
39 | Ok(_) => std::process::exit(exitcode::OK), |
|
41 | Ok(_) => std::process::exit(exitcode::OK), | |
40 |
Err(e) => |
|
42 | Err(e) => { | |
|
43 | let message = e.get_error_message_bytes(); | |||
|
44 | if let Some(msg) = message { | |||
|
45 | match ui.write_stderr(&msg) { | |||
|
46 | Ok(_) => (), | |||
|
47 | Err(_) => std::process::exit(exitcode::ABORT), | |||
|
48 | }; | |||
|
49 | }; | |||
|
50 | e.exit() | |||
|
51 | } | |||
41 | } |
|
52 | } | |
42 | } |
|
53 | } |
General Comments 0
You need to be logged in to leave comments.
Login now