Show More
@@ -3,13 +3,3 b' pub mod debugdata;' | |||||
3 | pub mod debugrequirements; |
|
3 | pub mod debugrequirements; | |
4 | pub mod files; |
|
4 | pub mod files; | |
5 | pub mod root; |
|
5 | pub mod root; | |
6 | use crate::error::CommandError; |
|
|||
7 | use crate::ui::Ui; |
|
|||
8 | use hg::config::Config; |
|
|||
9 |
|
||||
10 | /// The common trait for rhg commands |
|
|||
11 | /// |
|
|||
12 | /// Normalize the interface of the commands provided by rhg |
|
|||
13 | pub trait Command { |
|
|||
14 | fn run(&self, ui: &Ui, config: &Config) -> Result<(), CommandError>; |
|
|||
15 | } |
|
@@ -1,6 +1,6 b'' | |||||
1 | use crate::commands::Command; |
|
|||
2 |
|
|
1 | use crate::error::CommandError; | |
3 | use crate::ui::Ui; |
|
2 | use crate::ui::Ui; | |
|
3 | use clap::ArgMatches; | |||
4 | use hg::config::Config; |
|
4 | use hg::config::Config; | |
5 | use hg::operations::cat; |
|
5 | use hg::operations::cat; | |
6 | use hg::repo::Repo; |
|
6 | use hg::repo::Repo; | |
@@ -12,30 +12,23 b' pub const HELP_TEXT: &str = "' | |||||
12 | Output the current or given revision of files |
|
12 | Output the current or given revision of files | |
13 | "; |
|
13 | "; | |
14 |
|
14 | |||
15 | pub struct CatCommand<'a> { |
|
15 | #[timed] | |
16 | rev: Option<&'a str>, |
|
16 | pub fn run( | |
17 | files: Vec<&'a str>, |
|
17 | ui: &Ui, | |
18 | } |
|
18 | config: &Config, | |
19 |
|
19 | args: &ArgMatches, | ||
20 | impl<'a> CatCommand<'a> { |
|
20 | ) -> Result<(), CommandError> { | |
21 | pub fn new(rev: Option<&'a str>, files: Vec<&'a str>) -> Self { |
|
21 | let rev = args.value_of("rev"); | |
22 | Self { rev, files } |
|
22 | let file_args = match args.values_of("files") { | |
23 | } |
|
23 | Some(files) => files.collect(), | |
|
24 | None => vec![], | |||
|
25 | }; | |||
24 |
|
26 | |||
25 | fn display(&self, ui: &Ui, data: &[u8]) -> Result<(), CommandError> { |
|
|||
26 | ui.write_stdout(data)?; |
|
|||
27 | Ok(()) |
|
|||
28 | } |
|
|||
29 | } |
|
|||
30 |
|
||||
31 | impl<'a> Command for CatCommand<'a> { |
|
|||
32 | #[timed] |
|
|||
33 | fn run(&self, ui: &Ui, config: &Config) -> Result<(), CommandError> { |
|
|||
34 |
|
|
27 | let repo = Repo::find(config)?; | |
35 |
|
|
28 | let cwd = hg::utils::current_dir()?; | |
36 |
|
29 | |||
37 |
|
|
30 | let mut files = vec![]; | |
38 |
|
|
31 | for file in file_args.iter() { | |
39 |
|
|
32 | // TODO: actually normalize `..` path segments etc? | |
40 |
|
|
33 | let normalized = cwd.join(&file); | |
41 |
|
|
34 | let stripped = normalized | |
@@ -47,12 +40,12 b" impl<'a> Command for CatCommand<'a> {" | |||||
47 |
|
|
40 | files.push(hg_file); | |
48 |
|
|
41 | } | |
49 |
|
42 | |||
50 |
|
|
43 | match rev { | |
51 |
|
|
44 | Some(rev) => { | |
52 |
|
|
45 | let data = cat(&repo, rev, &files).map_err(|e| (e, rev))?; | |
53 | self.display(ui, &data) |
|
46 | ui.write_stdout(&data)?; | |
|
47 | Ok(()) | |||
54 |
|
|
48 | } | |
55 |
|
|
49 | None => Err(CommandError::Unimplemented.into()), | |
56 |
|
|
50 | } | |
57 | } |
|
51 | } | |
58 | } |
|
@@ -1,6 +1,6 b'' | |||||
1 | use crate::commands::Command; |
|
|||
2 |
|
|
1 | use crate::error::CommandError; | |
3 | use crate::ui::Ui; |
|
2 | use crate::ui::Ui; | |
|
3 | use clap::ArgMatches; | |||
4 | use hg::config::Config; |
|
4 | use hg::config::Config; | |
5 | use hg::operations::{debug_data, DebugDataKind}; |
|
5 | use hg::operations::{debug_data, DebugDataKind}; | |
6 | use hg::repo::Repo; |
|
6 | use hg::repo::Repo; | |
@@ -10,23 +10,29 b' pub const HELP_TEXT: &str = "' | |||||
10 | Dump the contents of a data file revision |
|
10 | Dump the contents of a data file revision | |
11 | "; |
|
11 | "; | |
12 |
|
12 | |||
13 | pub struct DebugDataCommand<'a> { |
|
13 | #[timed] | |
14 | rev: &'a str, |
|
14 | pub fn run( | |
15 | kind: DebugDataKind, |
|
15 | ui: &Ui, | |
16 | } |
|
16 | config: &Config, | |
17 |
|
17 | args: &ArgMatches, | ||
18 | impl<'a> DebugDataCommand<'a> { |
|
18 | ) -> Result<(), CommandError> { | |
19 | pub fn new(rev: &'a str, kind: DebugDataKind) -> Self { |
|
19 | let rev = args | |
20 | DebugDataCommand { rev, kind } |
|
20 | .value_of("rev") | |
|
21 | .expect("rev should be a required argument"); | |||
|
22 | let kind = | |||
|
23 | match (args.is_present("changelog"), args.is_present("manifest")) { | |||
|
24 | (true, false) => DebugDataKind::Changelog, | |||
|
25 | (false, true) => DebugDataKind::Manifest, | |||
|
26 | (true, true) => { | |||
|
27 | unreachable!("Should not happen since options are exclusive") | |||
21 | } |
|
28 | } | |
|
29 | (false, false) => { | |||
|
30 | unreachable!("Should not happen since options are required") | |||
22 | } |
|
31 | } | |
|
32 | }; | |||
23 |
|
33 | |||
24 | impl<'a> Command for DebugDataCommand<'a> { |
|
|||
25 | #[timed] |
|
|||
26 | fn run(&self, ui: &Ui, config: &Config) -> Result<(), CommandError> { |
|
|||
27 |
|
|
34 | let repo = Repo::find(config)?; | |
28 |
|
|
35 | let data = debug_data(&repo, rev, kind).map_err(|e| (e, rev))?; | |
29 | .map_err(|e| (e, self.rev))?; |
|
|||
30 |
|
36 | |||
31 |
|
|
37 | let mut stdout = ui.stdout_buffer(); | |
32 |
|
|
38 | stdout.write_all(&data)?; | |
@@ -34,4 +40,3 b" impl<'a> Command for DebugDataCommand<'a" | |||||
34 |
|
40 | |||
35 |
|
|
41 | Ok(()) | |
36 | } |
|
42 | } | |
37 | } |
|
@@ -1,6 +1,6 b'' | |||||
1 | use crate::commands::Command; |
|
|||
2 |
|
|
1 | use crate::error::CommandError; | |
3 | use crate::ui::Ui; |
|
2 | use crate::ui::Ui; | |
|
3 | use clap::ArgMatches; | |||
4 | use hg::config::Config; |
|
4 | use hg::config::Config; | |
5 | use hg::repo::Repo; |
|
5 | use hg::repo::Repo; | |
6 |
|
6 | |||
@@ -8,16 +8,11 b' pub const HELP_TEXT: &str = "' | |||||
8 | Print the current repo requirements. |
|
8 | Print the current repo requirements. | |
9 | "; |
|
9 | "; | |
10 |
|
10 | |||
11 | pub struct DebugRequirementsCommand {} |
|
11 | pub fn run( | |
12 |
|
12 | ui: &Ui, | ||
13 | impl DebugRequirementsCommand { |
|
13 | config: &Config, | |
14 | pub fn new() -> Self { |
|
14 | _args: &ArgMatches, | |
15 | DebugRequirementsCommand {} |
|
15 | ) -> Result<(), CommandError> { | |
16 | } |
|
|||
17 | } |
|
|||
18 |
|
||||
19 | impl Command for DebugRequirementsCommand { |
|
|||
20 | fn run(&self, ui: &Ui, config: &Config) -> Result<(), CommandError> { |
|
|||
21 |
|
|
16 | let repo = Repo::find(config)?; | |
22 |
|
|
17 | let mut output = String::new(); | |
23 |
|
|
18 | let mut requirements: Vec<_> = repo.requirements().iter().collect(); | |
@@ -29,4 +24,3 b' impl Command for DebugRequirementsComman' | |||||
29 |
|
|
24 | ui.write_stdout(output.as_bytes())?; | |
30 |
|
|
25 | Ok(()) | |
31 | } |
|
26 | } | |
32 | } |
|
@@ -1,6 +1,6 b'' | |||||
1 | use crate::commands::Command; |
|
|||
2 |
|
|
1 | use crate::error::CommandError; | |
3 | use crate::ui::Ui; |
|
2 | use crate::ui::Ui; | |
|
3 | use clap::ArgMatches; | |||
4 | use hg::config::Config; |
|
4 | use hg::config::Config; | |
5 | use hg::operations::list_rev_tracked_files; |
|
5 | use hg::operations::list_rev_tracked_files; | |
6 | use hg::operations::Dirstate; |
|
6 | use hg::operations::Dirstate; | |
@@ -14,17 +14,26 b' List tracked files.' | |||||
14 | Returns 0 on success. |
|
14 | Returns 0 on success. | |
15 | "; |
|
15 | "; | |
16 |
|
16 | |||
17 | pub struct FilesCommand<'a> { |
|
17 | pub fn run( | |
18 | rev: Option<&'a str>, |
|
18 | ui: &Ui, | |
|
19 | config: &Config, | |||
|
20 | args: &ArgMatches, | |||
|
21 | ) -> Result<(), CommandError> { | |||
|
22 | let rev = args.value_of("rev"); | |||
|
23 | ||||
|
24 | let repo = Repo::find(config)?; | |||
|
25 | if let Some(rev) = rev { | |||
|
26 | let files = | |||
|
27 | list_rev_tracked_files(&repo, rev).map_err(|e| (e, rev))?; | |||
|
28 | display_files(ui, &repo, files.iter()) | |||
|
29 | } else { | |||
|
30 | let distate = Dirstate::new(&repo)?; | |||
|
31 | let files = distate.tracked_files()?; | |||
|
32 | display_files(ui, &repo, files) | |||
|
33 | } | |||
19 | } |
|
34 | } | |
20 |
|
35 | |||
21 | impl<'a> FilesCommand<'a> { |
|
36 | fn display_files<'a>( | |
22 | pub fn new(rev: Option<&'a str>) -> Self { |
|
|||
23 | FilesCommand { rev } |
|
|||
24 | } |
|
|||
25 |
|
||||
26 | fn display_files( |
|
|||
27 | &self, |
|
|||
28 |
|
|
37 | ui: &Ui, | |
29 |
|
|
38 | repo: &Repo, | |
30 |
|
|
39 | files: impl IntoIterator<Item = &'a HgPath>, | |
@@ -44,19 +53,3 b" impl<'a> FilesCommand<'a> {" | |||||
44 |
|
|
53 | stdout.flush()?; | |
45 |
|
|
54 | Ok(()) | |
46 | } |
|
55 | } | |
47 | } |
|
|||
48 |
|
||||
49 | impl<'a> Command for FilesCommand<'a> { |
|
|||
50 | fn run(&self, ui: &Ui, config: &Config) -> Result<(), CommandError> { |
|
|||
51 | let repo = Repo::find(config)?; |
|
|||
52 | if let Some(rev) = self.rev { |
|
|||
53 | let files = |
|
|||
54 | list_rev_tracked_files(&repo, rev).map_err(|e| (e, rev))?; |
|
|||
55 | self.display_files(ui, &repo, files.iter()) |
|
|||
56 | } else { |
|
|||
57 | let distate = Dirstate::new(&repo)?; |
|
|||
58 | let files = distate.tracked_files()?; |
|
|||
59 | self.display_files(ui, &repo, files) |
|
|||
60 | } |
|
|||
61 | } |
|
|||
62 | } |
|
@@ -1,6 +1,6 b'' | |||||
1 | use crate::commands::Command; |
|
|||
2 |
|
|
1 | use crate::error::CommandError; | |
3 | use crate::ui::Ui; |
|
2 | use crate::ui::Ui; | |
|
3 | use clap::ArgMatches; | |||
4 | use format_bytes::format_bytes; |
|
4 | use format_bytes::format_bytes; | |
5 | use hg::config::Config; |
|
5 | use hg::config::Config; | |
6 | use hg::repo::Repo; |
|
6 | use hg::repo::Repo; | |
@@ -12,19 +12,13 b' Print the root directory of the current ' | |||||
12 | Returns 0 on success. |
|
12 | Returns 0 on success. | |
13 | "; |
|
13 | "; | |
14 |
|
14 | |||
15 | pub struct RootCommand {} |
|
15 | pub fn run( | |
16 |
|
16 | ui: &Ui, | ||
17 | impl RootCommand { |
|
17 | config: &Config, | |
18 | pub fn new() -> Self { |
|
18 | _args: &ArgMatches, | |
19 | RootCommand {} |
|
19 | ) -> Result<(), CommandError> { | |
20 | } |
|
|||
21 | } |
|
|||
22 |
|
||||
23 | impl Command for RootCommand { |
|
|||
24 | fn run(&self, ui: &Ui, config: &Config) -> Result<(), CommandError> { |
|
|||
25 |
|
|
20 | let repo = Repo::find(config)?; | |
26 |
|
|
21 | let bytes = get_bytes_from_path(repo.working_directory_path()); | |
27 |
|
|
22 | ui.write_stdout(&format_bytes!(b"{}\n", bytes.as_slice()))?; | |
28 |
|
|
23 | Ok(()) | |
29 | } |
|
24 | } | |
30 | } |
|
@@ -6,14 +6,11 b' use clap::ArgGroup;' | |||||
6 | use clap::ArgMatches; |
|
6 | use clap::ArgMatches; | |
7 | use clap::SubCommand; |
|
7 | use clap::SubCommand; | |
8 | use format_bytes::format_bytes; |
|
8 | use format_bytes::format_bytes; | |
9 | use hg::operations::DebugDataKind; |
|
|||
10 | use std::convert::TryFrom; |
|
|||
11 |
|
9 | |||
12 | mod commands; |
|
10 | mod commands; | |
13 | mod error; |
|
11 | mod error; | |
14 | mod exitcode; |
|
12 | mod exitcode; | |
15 | mod ui; |
|
13 | mod ui; | |
16 | use commands::Command; |
|
|||
17 | use error::CommandError; |
|
14 | use error::CommandError; | |
18 |
|
15 | |||
19 | fn main() { |
|
16 | fn main() { | |
@@ -126,69 +123,15 b' fn match_subcommand(' | |||||
126 | let config = hg::config::Config::load()?; |
|
123 | let config = hg::config::Config::load()?; | |
127 |
|
124 | |||
128 | match matches.subcommand() { |
|
125 | match matches.subcommand() { | |
129 |
("root", |
|
126 | ("root", Some(matches)) => commands::root::run(ui, &config, matches), | |
130 |
("files", Some(matches)) => |
|
127 | ("files", Some(matches)) => commands::files::run(ui, &config, matches), | |
131 | commands::files::FilesCommand::try_from(matches)?.run(&ui, &config) |
|
128 | ("cat", Some(matches)) => commands::cat::run(ui, &config, matches), | |
132 | } |
|
129 | ("debugdata", Some(matches)) => { | |
133 | ("cat", Some(matches)) => { |
|
130 | commands::debugdata::run(ui, &config, matches) | |
134 | commands::cat::CatCommand::try_from(matches)?.run(&ui, &config) |
|
|||
135 | } |
|
131 | } | |
136 |
("debug |
|
132 | ("debugrequirements", Some(matches)) => { | |
137 | commands::debugdata::DebugDataCommand::try_from(matches)? |
|
133 | commands::debugrequirements::run(ui, &config, matches) | |
138 | .run(&ui, &config) |
|
|||
139 | } |
|
|||
140 | ("debugrequirements", _) => { |
|
|||
141 | commands::debugrequirements::DebugRequirementsCommand::new() |
|
|||
142 | .run(&ui, &config) |
|
|||
143 | } |
|
134 | } | |
144 | _ => unreachable!(), // Because of AppSettings::SubcommandRequired, |
|
135 | _ => unreachable!(), // Because of AppSettings::SubcommandRequired, | |
145 | } |
|
136 | } | |
146 | } |
|
137 | } | |
147 |
|
||||
148 | impl<'a> TryFrom<&'a ArgMatches<'_>> for commands::files::FilesCommand<'a> { |
|
|||
149 | type Error = CommandError; |
|
|||
150 |
|
||||
151 | fn try_from(args: &'a ArgMatches) -> Result<Self, Self::Error> { |
|
|||
152 | let rev = args.value_of("rev"); |
|
|||
153 | Ok(commands::files::FilesCommand::new(rev)) |
|
|||
154 | } |
|
|||
155 | } |
|
|||
156 |
|
||||
157 | impl<'a> TryFrom<&'a ArgMatches<'_>> for commands::cat::CatCommand<'a> { |
|
|||
158 | type Error = CommandError; |
|
|||
159 |
|
||||
160 | fn try_from(args: &'a ArgMatches) -> Result<Self, Self::Error> { |
|
|||
161 | let rev = args.value_of("rev"); |
|
|||
162 | let files = match args.values_of("files") { |
|
|||
163 | Some(files) => files.collect(), |
|
|||
164 | None => vec![], |
|
|||
165 | }; |
|
|||
166 | Ok(commands::cat::CatCommand::new(rev, files)) |
|
|||
167 | } |
|
|||
168 | } |
|
|||
169 |
|
||||
170 | impl<'a> TryFrom<&'a ArgMatches<'_>> |
|
|||
171 | for commands::debugdata::DebugDataCommand<'a> |
|
|||
172 | { |
|
|||
173 | type Error = CommandError; |
|
|||
174 |
|
||||
175 | fn try_from(args: &'a ArgMatches) -> Result<Self, Self::Error> { |
|
|||
176 | let rev = args |
|
|||
177 | .value_of("rev") |
|
|||
178 | .expect("rev should be a required argument"); |
|
|||
179 | let kind = match ( |
|
|||
180 | args.is_present("changelog"), |
|
|||
181 | args.is_present("manifest"), |
|
|||
182 | ) { |
|
|||
183 | (true, false) => DebugDataKind::Changelog, |
|
|||
184 | (false, true) => DebugDataKind::Manifest, |
|
|||
185 | (true, true) => { |
|
|||
186 | unreachable!("Should not happen since options are exclusive") |
|
|||
187 | } |
|
|||
188 | (false, false) => { |
|
|||
189 | unreachable!("Should not happen since options are required") |
|
|||
190 | } |
|
|||
191 | }; |
|
|||
192 | Ok(commands::debugdata::DebugDataCommand::new(rev, kind)) |
|
|||
193 | } |
|
|||
194 | } |
|
General Comments 0
You need to be logged in to leave comments.
Login now