Show More
@@ -58,8 +58,8 b' impl ConfigLayer {' | |||
|
58 | 58 | fn parse_one(arg: &[u8]) -> Option<(Vec<u8>, Vec<u8>, Vec<u8>)> { |
|
59 | 59 | use crate::utils::SliceExt; |
|
60 | 60 | |
|
61 |
let (section_and_item, value) = split_2( |
|
|
62 |
let (section, item) = |
|
|
61 | let (section_and_item, value) = arg.split_2(b'=')?; | |
|
62 | let (section, item) = section_and_item.trim().split_2(b'.')?; | |
|
63 | 63 | Some(( |
|
64 | 64 | section.to_owned(), |
|
65 | 65 | item.to_owned(), |
@@ -67,13 +67,6 b' impl ConfigLayer {' | |||
|
67 | 67 | )) |
|
68 | 68 | } |
|
69 | 69 | |
|
70 | fn split_2(bytes: &[u8], separator: u8) -> Option<(&[u8], &[u8])> { | |
|
71 | let mut iter = bytes.splitn(2, |&byte| byte == separator); | |
|
72 | let a = iter.next()?; | |
|
73 | let b = iter.next()?; | |
|
74 | Some((a, b)) | |
|
75 | } | |
|
76 | ||
|
77 | 70 | let mut layer = Self::new(ConfigOrigin::CommandLine); |
|
78 | 71 | for arg in cli_config_args { |
|
79 | 72 | let arg = arg.as_ref(); |
@@ -43,10 +43,14 b" pub(crate) struct Vfs<'a> {" | |||
|
43 | 43 | } |
|
44 | 44 | |
|
45 | 45 | impl Repo { |
|
46 | /// Search the current directory and its ancestores for a repository: | |
|
47 | /// a working directory that contains a `.hg` sub-directory. | |
|
46 | /// Find a repository, either at the given path (which must contain a `.hg` | |
|
47 | /// sub-directory) or by searching the current directory and its | |
|
48 | /// ancestors. | |
|
48 | 49 | /// |
|
49 | /// `explicit_path` is for `--repository` command-line arguments. | |
|
50 | /// A method with two very different "modes" like this usually a code smell | |
|
51 | /// to make two methods instead, but in this case an `Option` is what rhg | |
|
52 | /// sub-commands get from Clap for the `-R` / `--repository` CLI argument. | |
|
53 | /// Having two methods would just move that `if` to almost all callers. | |
|
50 | 54 | pub fn find( |
|
51 | 55 | config: &Config, |
|
52 | 56 | explicit_path: Option<&Path>, |
@@ -77,6 +81,28 b' impl Repo {' | |||
|
77 | 81 | } |
|
78 | 82 | } |
|
79 | 83 | |
|
84 | /// Like `Repo::find`, but not finding a repository is not an error if no | |
|
85 | /// explicit path is given. `Ok(None)` is returned in that case. | |
|
86 | /// | |
|
87 | /// If an explicit path *is* given, not finding a repository there is still | |
|
88 | /// an error. | |
|
89 | /// | |
|
90 | /// For sub-commands that don’t need a repository, configuration should | |
|
91 | /// still be affected by a repository’s `.hg/hgrc` file. This is the | |
|
92 | /// constructor to use. | |
|
93 | pub fn find_optional( | |
|
94 | config: &Config, | |
|
95 | explicit_path: Option<&Path>, | |
|
96 | ) -> Result<Option<Self>, RepoError> { | |
|
97 | match Self::find(config, explicit_path) { | |
|
98 | Ok(repo) => Ok(Some(repo)), | |
|
99 | Err(RepoError::NotFound { .. }) if explicit_path.is_none() => { | |
|
100 | Ok(None) | |
|
101 | } | |
|
102 | Err(error) => Err(error), | |
|
103 | } | |
|
104 | } | |
|
105 | ||
|
80 | 106 | /// To be called after checking that `.hg` is a sub-directory |
|
81 | 107 | fn new_at_path( |
|
82 | 108 | working_directory: PathBuf, |
@@ -67,6 +67,7 b' pub trait SliceExt {' | |||
|
67 | 67 | fn trim_start(&self) -> &Self; |
|
68 | 68 | fn trim(&self) -> &Self; |
|
69 | 69 | fn drop_prefix(&self, needle: &Self) -> Option<&Self>; |
|
70 | fn split_2(&self, separator: u8) -> Option<(&[u8], &[u8])>; | |
|
70 | 71 | } |
|
71 | 72 | |
|
72 | 73 | #[allow(clippy::trivially_copy_pass_by_ref)] |
@@ -116,6 +117,13 b' impl SliceExt for [u8] {' | |||
|
116 | 117 | None |
|
117 | 118 | } |
|
118 | 119 | } |
|
120 | ||
|
121 | fn split_2(&self, separator: u8) -> Option<(&[u8], &[u8])> { | |
|
122 | let mut iter = self.splitn(2, |&byte| byte == separator); | |
|
123 | let a = iter.next()?; | |
|
124 | let b = iter.next()?; | |
|
125 | Some((a, b)) | |
|
126 | } | |
|
119 | 127 | } |
|
120 | 128 | |
|
121 | 129 | pub trait Escaped { |
@@ -1,30 +1,52 b'' | |||
|
1 | 1 | use crate::error::CommandError; |
|
2 | 2 | use crate::ui::Ui; |
|
3 | use clap::Arg; | |
|
3 | 4 | use clap::ArgMatches; |
|
4 | 5 | use format_bytes::format_bytes; |
|
5 | 6 | use hg::config::Config; |
|
7 | use hg::errors::HgError; | |
|
6 | 8 | use hg::repo::Repo; |
|
7 | use hg::utils::files::get_bytes_from_path; | |
|
9 | use hg::utils::SliceExt; | |
|
8 | 10 | use std::path::Path; |
|
9 | 11 | |
|
10 | 12 | pub const HELP_TEXT: &str = " |
|
11 | Print the root directory of the current repository. | |
|
12 | ||
|
13 | Returns 0 on success. | |
|
13 | With one argument of the form section.name, print just the value of that config item. | |
|
14 | 14 | "; |
|
15 | 15 | |
|
16 | 16 | pub fn args() -> clap::App<'static, 'static> { |
|
17 |
clap::SubCommand::with_name(" |
|
|
17 | clap::SubCommand::with_name("config") | |
|
18 | .arg( | |
|
19 | Arg::with_name("name") | |
|
20 | .help("the section.name to print") | |
|
21 | .value_name("NAME") | |
|
22 | .required(true) | |
|
23 | .takes_value(true), | |
|
24 | ) | |
|
25 | .about(HELP_TEXT) | |
|
18 | 26 | } |
|
19 | 27 | |
|
20 | 28 | pub fn run( |
|
21 | 29 | ui: &Ui, |
|
22 | 30 | config: &Config, |
|
23 | 31 | repo_path: Option<&Path>, |
|
24 |
|
|
|
32 | args: &ArgMatches, | |
|
25 | 33 | ) -> Result<(), CommandError> { |
|
26 | let repo = Repo::find(config, repo_path)?; | |
|
27 | let bytes = get_bytes_from_path(repo.working_directory_path()); | |
|
28 | ui.write_stdout(&format_bytes!(b"{}\n", bytes.as_slice()))?; | |
|
34 | let opt_repo = Repo::find_optional(config, repo_path)?; | |
|
35 | let config = if let Some(repo) = &opt_repo { | |
|
36 | repo.config() | |
|
37 | } else { | |
|
38 | config | |
|
39 | }; | |
|
40 | ||
|
41 | let (section, name) = args | |
|
42 | .value_of("name") | |
|
43 | .expect("missing required CLI argument") | |
|
44 | .as_bytes() | |
|
45 | .split_2(b'.') | |
|
46 | .ok_or_else(|| HgError::abort(""))?; | |
|
47 | ||
|
48 | let value = config.get(section, name).unwrap_or(b""); | |
|
49 | ||
|
50 | ui.write_stdout(&format_bytes!(b"{}\n", value))?; | |
|
29 | 51 | Ok(()) |
|
30 | 52 | } |
@@ -134,4 +134,5 b' subcommands! {' | |||
|
134 | 134 | debugrequirements |
|
135 | 135 | files |
|
136 | 136 | root |
|
137 | config | |
|
137 | 138 | } |
@@ -30,6 +30,18 b' Finding root' | |||
|
30 | 30 | $ rhg root |
|
31 | 31 | $TESTTMP/repository |
|
32 | 32 | |
|
33 | Reading and setting configuration | |
|
34 | $ echo "[ui]" >> $HGRCPATH | |
|
35 | $ echo "username = user1" >> $HGRCPATH | |
|
36 | $ rhg config ui.username | |
|
37 | user1 | |
|
38 | $ echo "[ui]" >> .hg/hgrc | |
|
39 | $ echo "username = user2" >> .hg/hgrc | |
|
40 | $ rhg config ui.username | |
|
41 | user2 | |
|
42 | $ rhg --config ui.username=user3 config ui.username | |
|
43 | user3 | |
|
44 | ||
|
33 | 45 | Unwritable file descriptor |
|
34 | 46 | $ rhg root > /dev/full |
|
35 | 47 | abort: No space left on device (os error 28) |
General Comments 0
You need to be logged in to leave comments.
Login now