Show More
@@ -1,10 +1,11 b'' | |||
|
1 | 1 | pub mod files; |
|
2 | 2 | pub mod root; |
|
3 | 3 | use crate::error::CommandError; |
|
4 | use crate::ui::Ui; | |
|
4 | 5 | |
|
5 | 6 | /// The common trait for rhg commands |
|
6 | 7 | /// |
|
7 | 8 | /// Normalize the interface of the commands provided by rhg |
|
8 |
pub trait Command |
|
|
9 | fn run(&self) -> Result<(), CommandError>; | |
|
9 | pub trait Command { | |
|
10 | fn run(&self, ui: &Ui) -> Result<(), CommandError>; | |
|
10 | 11 | } |
@@ -1,60 +1,58 b'' | |||
|
1 | 1 | use crate::commands::Command; |
|
2 | 2 | use crate::error::{CommandError, CommandErrorKind}; |
|
3 | 3 | use crate::ui::Ui; |
|
4 | 4 | use hg::operations::{ListTrackedFiles, ListTrackedFilesErrorKind}; |
|
5 | 5 | use hg::utils::files::{get_bytes_from_path, relativize_path}; |
|
6 | 6 | use hg::utils::hg_path::HgPathBuf; |
|
7 | 7 | |
|
8 | 8 | pub const HELP_TEXT: &str = " |
|
9 | 9 | List tracked files. |
|
10 | 10 | |
|
11 | 11 | Returns 0 on success. |
|
12 | 12 | "; |
|
13 | 13 | |
|
14 |
pub struct FilesCommand |
|
|
15 | ui: &'a Ui, | |
|
16 | } | |
|
14 | pub struct FilesCommand {} | |
|
17 | 15 | |
|
18 |
impl |
|
|
19 |
pub fn new( |
|
|
20 |
FilesCommand { |
|
|
16 | impl FilesCommand { | |
|
17 | pub fn new() -> Self { | |
|
18 | FilesCommand {} | |
|
21 | 19 | } |
|
22 | 20 | } |
|
23 | 21 | |
|
24 |
impl |
|
|
25 | fn run(&self) -> Result<(), CommandError> { | |
|
22 | impl Command for FilesCommand { | |
|
23 | fn run(&self, ui: &Ui) -> Result<(), CommandError> { | |
|
26 | 24 | let operation_builder = ListTrackedFiles::new()?; |
|
27 | 25 | let operation = operation_builder.load().map_err(|err| { |
|
28 | 26 | CommandErrorKind::Abort(Some( |
|
29 | 27 | [b"abort: ", err.to_string().as_bytes(), b"\n"] |
|
30 | 28 | .concat() |
|
31 | 29 | .to_vec(), |
|
32 | 30 | )) |
|
33 | 31 | })?; |
|
34 | 32 | let files = operation.run().map_err(|err| match err.kind { |
|
35 | 33 | ListTrackedFilesErrorKind::ParseError(_) => { |
|
36 | 34 | CommandErrorKind::Abort(Some( |
|
37 | 35 | // TODO find a better error message |
|
38 | 36 | b"abort: parse error\n".to_vec(), |
|
39 | 37 | )) |
|
40 | 38 | } |
|
41 | 39 | })?; |
|
42 | 40 | |
|
43 | 41 | let cwd = std::env::current_dir() |
|
44 | 42 | .or_else(|e| Err(CommandErrorKind::CurrentDirNotFound(e)))?; |
|
45 | 43 | let rooted_cwd = cwd |
|
46 | 44 | .strip_prefix(operation_builder.get_root()) |
|
47 | 45 | .expect("cwd was already checked within the repository"); |
|
48 | 46 | let rooted_cwd = HgPathBuf::from(get_bytes_from_path(rooted_cwd)); |
|
49 | 47 | |
|
50 |
let mut stdout = |
|
|
48 | let mut stdout = ui.stdout_buffer(); | |
|
51 | 49 | |
|
52 | 50 | for file in files { |
|
53 | 51 | stdout.write_all(relativize_path(file, &rooted_cwd).as_ref())?; |
|
54 | 52 | stdout.write_all(b"\n")?; |
|
55 | 53 | } |
|
56 | 54 | stdout.flush()?; |
|
57 | 55 | |
|
58 | 56 | Ok(()) |
|
59 | 57 | } |
|
60 | 58 | } |
@@ -1,34 +1,32 b'' | |||
|
1 | 1 | use crate::commands::Command; |
|
2 | 2 | use crate::error::CommandError; |
|
3 | 3 | use crate::ui::Ui; |
|
4 | 4 | use hg::operations::FindRoot; |
|
5 | 5 | use hg::utils::files::get_bytes_from_path; |
|
6 | 6 | |
|
7 | 7 | pub const HELP_TEXT: &str = " |
|
8 | 8 | Print the root directory of the current repository. |
|
9 | 9 | |
|
10 | 10 | Returns 0 on success. |
|
11 | 11 | "; |
|
12 | 12 | |
|
13 |
pub struct RootCommand |
|
|
14 | ui: &'a Ui, | |
|
15 | } | |
|
13 | pub struct RootCommand {} | |
|
16 | 14 | |
|
17 |
impl |
|
|
18 |
pub fn new( |
|
|
19 |
RootCommand { |
|
|
15 | impl RootCommand { | |
|
16 | pub fn new() -> Self { | |
|
17 | RootCommand {} | |
|
20 | 18 | } |
|
21 | 19 | } |
|
22 | 20 | |
|
23 |
impl |
|
|
24 | fn run(&self) -> Result<(), CommandError> { | |
|
21 | impl Command for RootCommand { | |
|
22 | fn run(&self, ui: &Ui) -> Result<(), CommandError> { | |
|
25 | 23 | let path_buf = FindRoot::new().run()?; |
|
26 | 24 | |
|
27 | 25 | let bytes = get_bytes_from_path(path_buf); |
|
28 | 26 | |
|
29 | 27 | // TODO use formating macro |
|
30 |
|
|
|
28 | ui.write_stdout(&[bytes.as_slice(), b"\n"].concat())?; | |
|
31 | 29 | |
|
32 | 30 | Ok(()) |
|
33 | 31 | } |
|
34 | 32 | } |
@@ -1,57 +1,57 b'' | |||
|
1 | 1 | use clap::App; |
|
2 | 2 | use clap::AppSettings; |
|
3 | 3 | use clap::SubCommand; |
|
4 | 4 | |
|
5 | 5 | mod commands; |
|
6 | 6 | mod error; |
|
7 | 7 | mod exitcode; |
|
8 | 8 | mod ui; |
|
9 | 9 | use commands::Command; |
|
10 | 10 | |
|
11 | 11 | fn main() { |
|
12 | 12 | let mut app = App::new("rhg") |
|
13 | 13 | .setting(AppSettings::AllowInvalidUtf8) |
|
14 | 14 | .setting(AppSettings::SubcommandRequired) |
|
15 | 15 | .setting(AppSettings::VersionlessSubcommands) |
|
16 | 16 | .version("0.0.1") |
|
17 | 17 | .subcommand( |
|
18 | 18 | SubCommand::with_name("root").about(commands::root::HELP_TEXT), |
|
19 | 19 | ) |
|
20 | 20 | .subcommand( |
|
21 | 21 | SubCommand::with_name("files").about(commands::files::HELP_TEXT), |
|
22 | 22 | ); |
|
23 | 23 | |
|
24 | 24 | let matches = app.clone().get_matches_safe().unwrap_or_else(|_| { |
|
25 | 25 | std::process::exit(exitcode::UNIMPLEMENTED_COMMAND) |
|
26 | 26 | }); |
|
27 | 27 | |
|
28 | 28 | let ui = ui::Ui::new(); |
|
29 | 29 | |
|
30 | 30 | let command_result = match matches.subcommand_name() { |
|
31 | 31 | Some(name) => match name { |
|
32 |
"root" => commands::root::RootCommand::new( |
|
|
33 |
"files" => commands::files::FilesCommand::new( |
|
|
32 | "root" => commands::root::RootCommand::new().run(&ui), | |
|
33 | "files" => commands::files::FilesCommand::new().run(&ui), | |
|
34 | 34 | _ => std::process::exit(exitcode::UNIMPLEMENTED_COMMAND), |
|
35 | 35 | }, |
|
36 | 36 | _ => { |
|
37 | 37 | match app.print_help() { |
|
38 | 38 | Ok(_) => std::process::exit(exitcode::OK), |
|
39 | 39 | Err(_) => std::process::exit(exitcode::ABORT), |
|
40 | 40 | }; |
|
41 | 41 | } |
|
42 | 42 | }; |
|
43 | 43 | |
|
44 | 44 | match command_result { |
|
45 | 45 | Ok(_) => std::process::exit(exitcode::OK), |
|
46 | 46 | Err(e) => { |
|
47 | 47 | let message = e.get_error_message_bytes(); |
|
48 | 48 | if let Some(msg) = message { |
|
49 | 49 | match ui.write_stderr(&msg) { |
|
50 | 50 | Ok(_) => (), |
|
51 | 51 | Err(_) => std::process::exit(exitcode::ABORT), |
|
52 | 52 | }; |
|
53 | 53 | }; |
|
54 | 54 | e.exit() |
|
55 | 55 | } |
|
56 | 56 | } |
|
57 | 57 | } |
General Comments 0
You need to be logged in to leave comments.
Login now