##// END OF EJS Templates
rhg: pass `ui` to `Command` `run`...
Antoine Cezar -
r46009:ed95ccc9 default
parent child Browse files
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<'a> {
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<'a> {
15 ui: &'a Ui,
16 }
14 pub struct FilesCommand {}
17 15
18 impl<'a> FilesCommand<'a> {
19 pub fn new(ui: &'a Ui) -> Self {
20 FilesCommand { ui }
16 impl FilesCommand {
17 pub fn new() -> Self {
18 FilesCommand {}
21 19 }
22 20 }
23 21
24 impl<'a> Command<'a> for FilesCommand<'a> {
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 = self.ui.stdout_buffer();
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<'a> {
14 ui: &'a Ui,
15 }
13 pub struct RootCommand {}
16 14
17 impl<'a> RootCommand<'a> {
18 pub fn new(ui: &'a Ui) -> Self {
19 RootCommand { ui }
15 impl RootCommand {
16 pub fn new() -> Self {
17 RootCommand {}
20 18 }
21 19 }
22 20
23 impl<'a> Command<'a> for RootCommand<'a> {
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 self.ui.write_stdout(&[bytes.as_slice(), b"\n"].concat())?;
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(&ui).run(),
33 "files" => commands::files::FilesCommand::new(&ui).run(),
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