##// END OF EJS Templates
rhg: make `rhg files` work if `ui.relative-files=true` is specified
Arseniy Alekseyev -
r51432:74e4dbb0 default
parent child Browse files
Show More
@@ -1,110 +1,112 b''
1 1 use crate::error::CommandError;
2 use crate::ui::{print_narrow_sparse_warnings, Ui};
2 use crate::ui::{print_narrow_sparse_warnings, Ui, RelativePaths, relative_paths};
3 3 use crate::utils::path_utils::RelativizePaths;
4 4 use clap::Arg;
5 5 use hg::narrow;
6 6 use hg::operations::list_rev_tracked_files;
7 7 use hg::repo::Repo;
8 8 use hg::utils::filter_map_results;
9 9 use hg::utils::hg_path::HgPath;
10 10 use rayon::prelude::*;
11 11
12 12 pub const HELP_TEXT: &str = "
13 13 List tracked files.
14 14
15 15 Returns 0 on success.
16 16 ";
17 17
18 18 pub fn args() -> clap::Command {
19 19 clap::command!("files")
20 20 .arg(
21 21 Arg::new("rev")
22 22 .help("search the repository as it is in REV")
23 23 .short('r')
24 24 .long("revision")
25 25 .value_name("REV"),
26 26 )
27 27 .about(HELP_TEXT)
28 28 }
29 29
30 30 pub fn run(invocation: &crate::CliInvocation) -> Result<(), CommandError> {
31 let relative = invocation.config.get(b"ui", b"relative-paths");
32 if relative.is_some() {
31 match relative_paths(invocation.config)? {
32 RelativePaths::Legacy | RelativePaths::Bool(true) => (),
33 RelativePaths::Bool(false) => {
33 34 return Err(CommandError::unsupported(
34 35 "non-default ui.relative-paths",
35 36 ));
36 37 }
38 }
37 39
38 40 let rev = invocation.subcommand_args.get_one::<String>("rev");
39 41
40 42 let repo = invocation.repo?;
41 43
42 44 // It seems better if this check is removed: this would correspond to
43 45 // automatically enabling the extension if the repo requires it.
44 46 // However we need this check to be in sync with vanilla hg so hg tests
45 47 // pass.
46 48 if repo.has_sparse()
47 49 && invocation.config.get(b"extensions", b"sparse").is_none()
48 50 {
49 51 return Err(CommandError::unsupported(
50 52 "repo is using sparse, but sparse extension is not enabled",
51 53 ));
52 54 }
53 55
54 56 let (narrow_matcher, narrow_warnings) = narrow::matcher(repo)?;
55 57 print_narrow_sparse_warnings(&narrow_warnings, &[], invocation.ui, repo)?;
56 58
57 59 if let Some(rev) = rev {
58 60 let files = list_rev_tracked_files(repo, rev, narrow_matcher)
59 61 .map_err(|e| (e, rev.as_ref()))?;
60 62 display_files(invocation.ui, repo, files.iter())
61 63 } else {
62 64 // The dirstate always reflects the sparse narrowspec.
63 65 let dirstate = repo.dirstate_map()?;
64 66 let files_res: Result<Vec<_>, _> =
65 67 filter_map_results(dirstate.iter(), |(path, entry)| {
66 68 Ok(if entry.tracked() && narrow_matcher.matches(path) {
67 69 Some(path)
68 70 } else {
69 71 None
70 72 })
71 73 })
72 74 .collect();
73 75
74 76 let mut files = files_res?;
75 77 files.par_sort_unstable();
76 78
77 79 display_files(
78 80 invocation.ui,
79 81 repo,
80 82 files.into_iter().map::<Result<_, CommandError>, _>(Ok),
81 83 )
82 84 }
83 85 }
84 86
85 87 fn display_files<'a, E>(
86 88 ui: &Ui,
87 89 repo: &Repo,
88 90 files: impl IntoIterator<Item = Result<&'a HgPath, E>>,
89 91 ) -> Result<(), CommandError>
90 92 where
91 93 CommandError: From<E>,
92 94 {
93 95 let mut stdout = ui.stdout_buffer();
94 96 let mut any = false;
95 97
96 98 let relativize = RelativizePaths::new(repo)?;
97 99 for result in files {
98 100 let path = result?;
99 101 stdout.write_all(&relativize.relativize(path))?;
100 102 stdout.write_all(b"\n")?;
101 103 any = true;
102 104 }
103 105
104 106 stdout.flush()?;
105 107 if any {
106 108 Ok(())
107 109 } else {
108 110 Err(CommandError::Unsuccessful)
109 111 }
110 112 }
@@ -1,295 +1,307 b''
1 1 use crate::color::ColorConfig;
2 2 use crate::color::Effect;
3 3 use crate::error::CommandError;
4 4 use format_bytes::format_bytes;
5 5 use format_bytes::write_bytes;
6 6 use hg::config::Config;
7 7 use hg::config::PlainInfo;
8 8 use hg::errors::HgError;
9 9 use hg::repo::Repo;
10 10 use hg::sparse;
11 11 use hg::utils::files::get_bytes_from_path;
12 12 use hg::PatternFileWarning;
13 13 use std::borrow::Cow;
14 14 use std::io;
15 15 use std::io::{ErrorKind, Write};
16 16
17 17 pub struct Ui {
18 18 stdout: std::io::Stdout,
19 19 stderr: std::io::Stderr,
20 20 colors: Option<ColorConfig>,
21 21 }
22 22
23 23 /// The kind of user interface error
24 24 pub enum UiError {
25 25 /// The standard output stream cannot be written to
26 26 StdoutError(io::Error),
27 27 /// The standard error stream cannot be written to
28 28 StderrError(io::Error),
29 29 }
30 30
31 31 /// The commandline user interface
32 32 impl Ui {
33 33 pub fn new(config: &Config) -> Result<Self, HgError> {
34 34 Ok(Ui {
35 35 // If using something else, also adapt `isatty()` below.
36 36 stdout: std::io::stdout(),
37 37
38 38 stderr: std::io::stderr(),
39 39 colors: ColorConfig::new(config)?,
40 40 })
41 41 }
42 42
43 43 /// Default to no color if color configuration errors.
44 44 ///
45 45 /// Useful when we’re already handling another error.
46 46 pub fn new_infallible(config: &Config) -> Self {
47 47 Ui {
48 48 // If using something else, also adapt `isatty()` below.
49 49 stdout: std::io::stdout(),
50 50
51 51 stderr: std::io::stderr(),
52 52 colors: ColorConfig::new(config).unwrap_or(None),
53 53 }
54 54 }
55 55
56 56 /// Returns a buffered handle on stdout for faster batch printing
57 57 /// operations.
58 58 pub fn stdout_buffer(&self) -> StdoutBuffer<std::io::StdoutLock> {
59 59 StdoutBuffer::new(self.stdout.lock())
60 60 }
61 61
62 62 /// Write bytes to stdout
63 63 pub fn write_stdout(&self, bytes: &[u8]) -> Result<(), UiError> {
64 64 let mut stdout = self.stdout.lock();
65 65
66 66 stdout.write_all(bytes).or_else(handle_stdout_error)?;
67 67
68 68 stdout.flush().or_else(handle_stdout_error)
69 69 }
70 70
71 71 /// Write bytes to stderr
72 72 pub fn write_stderr(&self, bytes: &[u8]) -> Result<(), UiError> {
73 73 let mut stderr = self.stderr.lock();
74 74
75 75 stderr.write_all(bytes).or_else(handle_stderr_error)?;
76 76
77 77 stderr.flush().or_else(handle_stderr_error)
78 78 }
79 79
80 80 /// Write bytes to stdout with the given label
81 81 ///
82 82 /// Like the optional `label` parameter in `mercurial/ui.py`,
83 83 /// this label influences the color used for this output.
84 84 pub fn write_stdout_labelled(
85 85 &self,
86 86 bytes: &[u8],
87 87 label: &str,
88 88 ) -> Result<(), UiError> {
89 89 if let Some(colors) = &self.colors {
90 90 if let Some(effects) = colors.styles.get(label.as_bytes()) {
91 91 if !effects.is_empty() {
92 92 return self
93 93 .write_stdout_with_effects(bytes, effects)
94 94 .or_else(handle_stdout_error);
95 95 }
96 96 }
97 97 }
98 98 self.write_stdout(bytes)
99 99 }
100 100
101 101 fn write_stdout_with_effects(
102 102 &self,
103 103 bytes: &[u8],
104 104 effects: &[Effect],
105 105 ) -> io::Result<()> {
106 106 let stdout = &mut self.stdout.lock();
107 107 let mut write_line = |line: &[u8], first: bool| {
108 108 // `line` does not include the newline delimiter
109 109 if !first {
110 110 stdout.write_all(b"\n")?;
111 111 }
112 112 if line.is_empty() {
113 113 return Ok(());
114 114 }
115 115 /// 0x1B == 27 == 0o33
116 116 const ASCII_ESCAPE: &[u8] = b"\x1b";
117 117 write_bytes!(stdout, b"{}[0", ASCII_ESCAPE)?;
118 118 for effect in effects {
119 119 write_bytes!(stdout, b";{}", effect)?;
120 120 }
121 121 write_bytes!(stdout, b"m")?;
122 122 stdout.write_all(line)?;
123 123 write_bytes!(stdout, b"{}[0m", ASCII_ESCAPE)
124 124 };
125 125 let mut lines = bytes.split(|&byte| byte == b'\n');
126 126 if let Some(first) = lines.next() {
127 127 write_line(first, true)?;
128 128 for line in lines {
129 129 write_line(line, false)?
130 130 }
131 131 }
132 132 stdout.flush()
133 133 }
134 134 }
135 135
136 136 // TODO: pass the PlainInfo to call sites directly and
137 137 // delete this function
138 138 pub fn plain(opt_feature: Option<&str>) -> bool {
139 139 let plain_info = PlainInfo::from_env();
140 140 match opt_feature {
141 141 None => plain_info.is_plain(),
142 142 Some(feature) => plain_info.is_feature_plain(feature),
143 143 }
144 144 }
145 145
146 146 /// A buffered stdout writer for faster batch printing operations.
147 147 pub struct StdoutBuffer<W: Write> {
148 148 buf: io::BufWriter<W>,
149 149 }
150 150
151 151 impl<W: Write> StdoutBuffer<W> {
152 152 pub fn new(writer: W) -> Self {
153 153 let buf = io::BufWriter::new(writer);
154 154 Self { buf }
155 155 }
156 156
157 157 /// Write bytes to stdout buffer
158 158 pub fn write_all(&mut self, bytes: &[u8]) -> Result<(), UiError> {
159 159 self.buf.write_all(bytes).or_else(handle_stdout_error)
160 160 }
161 161
162 162 /// Flush bytes to stdout
163 163 pub fn flush(&mut self) -> Result<(), UiError> {
164 164 self.buf.flush().or_else(handle_stdout_error)
165 165 }
166 166 }
167 167
168 168 /// Sometimes writing to stdout is not possible, try writing to stderr to
169 169 /// signal that failure, otherwise just bail.
170 170 fn handle_stdout_error(error: io::Error) -> Result<(), UiError> {
171 171 if let ErrorKind::BrokenPipe = error.kind() {
172 172 // This makes `| head` work for example
173 173 return Ok(());
174 174 }
175 175 let mut stderr = io::stderr();
176 176
177 177 stderr
178 178 .write_all(&format_bytes!(
179 179 b"abort: {}\n",
180 180 error.to_string().as_bytes()
181 181 ))
182 182 .map_err(UiError::StderrError)?;
183 183
184 184 stderr.flush().map_err(UiError::StderrError)?;
185 185
186 186 Err(UiError::StdoutError(error))
187 187 }
188 188
189 189 /// Sometimes writing to stderr is not possible.
190 190 fn handle_stderr_error(error: io::Error) -> Result<(), UiError> {
191 191 // A broken pipe should not result in a error
192 192 // like with `| head` for example
193 193 if let ErrorKind::BrokenPipe = error.kind() {
194 194 return Ok(());
195 195 }
196 196 Err(UiError::StdoutError(error))
197 197 }
198 198
199 199 /// Encode rust strings according to the user system.
200 200 pub fn utf8_to_local(s: &str) -> Cow<[u8]> {
201 201 // TODO encode for the user's system //
202 202 let bytes = s.as_bytes();
203 203 Cow::Borrowed(bytes)
204 204 }
205 205
206 206 /// Decode user system bytes to Rust string.
207 207 pub fn local_to_utf8(s: &[u8]) -> Cow<str> {
208 208 // TODO decode from the user's system
209 209 String::from_utf8_lossy(s)
210 210 }
211 211
212 212 /// Should formatted output be used?
213 213 ///
214 214 /// Note: rhg does not have the formatter mechanism yet,
215 215 /// but this is also used when deciding whether to use color.
216 216 pub fn formatted(config: &Config) -> Result<bool, HgError> {
217 217 if let Some(formatted) = config.get_option(b"ui", b"formatted")? {
218 218 Ok(formatted)
219 219 } else {
220 220 isatty(config)
221 221 }
222 222 }
223 223
224 pub enum RelativePaths {
225 Legacy,
226 Bool(bool),
227 }
228
229 pub fn relative_paths(config: &Config) -> Result<RelativePaths, HgError> {
230 Ok(match config.get(b"ui", b"relative-paths") {
231 None | Some(b"legacy") => RelativePaths::Legacy,
232 _ => RelativePaths::Bool(config.get_bool(b"ui", b"relative-paths")?),
233 })
234 }
235
224 236 fn isatty(config: &Config) -> Result<bool, HgError> {
225 237 Ok(if config.get_bool(b"ui", b"nontty")? {
226 238 false
227 239 } else {
228 240 atty::is(atty::Stream::Stdout)
229 241 })
230 242 }
231 243
232 244 /// Return the formatted bytestring corresponding to a pattern file warning,
233 245 /// as expected by the CLI.
234 246 pub(crate) fn format_pattern_file_warning(
235 247 warning: &PatternFileWarning,
236 248 repo: &Repo,
237 249 ) -> Vec<u8> {
238 250 match warning {
239 251 PatternFileWarning::InvalidSyntax(path, syntax) => format_bytes!(
240 252 b"{}: ignoring invalid syntax '{}'\n",
241 253 get_bytes_from_path(path),
242 254 &*syntax
243 255 ),
244 256 PatternFileWarning::NoSuchFile(path) => {
245 257 let path = if let Ok(relative) =
246 258 path.strip_prefix(repo.working_directory_path())
247 259 {
248 260 relative
249 261 } else {
250 262 &*path
251 263 };
252 264 format_bytes!(
253 265 b"skipping unreadable pattern file '{}': \
254 266 No such file or directory\n",
255 267 get_bytes_from_path(path),
256 268 )
257 269 }
258 270 }
259 271 }
260 272
261 273 /// Print with `Ui` the formatted bytestring corresponding to a
262 274 /// sparse/narrow warning, as expected by the CLI.
263 275 pub(crate) fn print_narrow_sparse_warnings(
264 276 narrow_warnings: &[sparse::SparseWarning],
265 277 sparse_warnings: &[sparse::SparseWarning],
266 278 ui: &Ui,
267 279 repo: &Repo,
268 280 ) -> Result<(), CommandError> {
269 281 for warning in narrow_warnings.iter().chain(sparse_warnings) {
270 282 match &warning {
271 283 sparse::SparseWarning::RootWarning { context, line } => {
272 284 let msg = format_bytes!(
273 285 b"warning: {} profile cannot use paths \"
274 286 starting with /, ignoring {}\n",
275 287 context,
276 288 line
277 289 );
278 290 ui.write_stderr(&msg)?;
279 291 }
280 292 sparse::SparseWarning::ProfileNotFound { profile, rev } => {
281 293 let msg = format_bytes!(
282 294 b"warning: sparse profile '{}' not found \"
283 295 in rev {} - ignoring it\n",
284 296 profile,
285 297 rev
286 298 );
287 299 ui.write_stderr(&msg)?;
288 300 }
289 301 sparse::SparseWarning::Pattern(e) => {
290 302 ui.write_stderr(&format_pattern_file_warning(e, repo))?;
291 303 }
292 304 }
293 305 }
294 306 Ok(())
295 307 }
@@ -1,417 +1,419 b''
1 1 #require rhg
2 2
3 3 $ NO_FALLBACK="env RHG_ON_UNSUPPORTED=abort"
4 4
5 5 Unimplemented command
6 6 $ $NO_FALLBACK rhg unimplemented-command
7 7 unsupported feature: error: The subcommand 'unimplemented-command' wasn't recognized
8 8
9 9 Usage: rhg [OPTIONS] <COMMAND>
10 10
11 11 For more information try '--help'
12 12
13 13 [252]
14 14 $ rhg unimplemented-command --config rhg.on-unsupported=abort-silent
15 15 [252]
16 16
17 17 Finding root
18 18 $ $NO_FALLBACK rhg root
19 19 abort: no repository found in '$TESTTMP' (.hg not found)!
20 20 [255]
21 21
22 22 $ hg init repository
23 23 $ cd repository
24 24 $ $NO_FALLBACK rhg root
25 25 $TESTTMP/repository
26 26
27 27 Reading and setting configuration
28 28 $ echo "[ui]" >> $HGRCPATH
29 29 $ echo "username = user1" >> $HGRCPATH
30 30 $ $NO_FALLBACK rhg config ui.username
31 31 user1
32 32 $ echo "[ui]" >> .hg/hgrc
33 33 $ echo "username = user2" >> .hg/hgrc
34 34 $ $NO_FALLBACK rhg config ui.username
35 35 user2
36 36 $ $NO_FALLBACK rhg --config ui.username=user3 config ui.username
37 37 user3
38 38
39 39 Unwritable file descriptor
40 40 $ $NO_FALLBACK rhg root > /dev/full
41 41 abort: No space left on device (os error 28)
42 42 [255]
43 43
44 44 Deleted repository
45 45 $ rm -rf `pwd`
46 46 $ $NO_FALLBACK rhg root
47 47 abort: error getting current working directory: $ENOENT$
48 48 [255]
49 49
50 50 Listing tracked files
51 51 $ cd $TESTTMP
52 52 $ hg init repository
53 53 $ cd repository
54 54 $ for i in 1 2 3; do
55 55 > echo $i >> file$i
56 56 > hg add file$i
57 57 > done
58 58 > hg commit -m "commit $i" -q
59 59
60 60 Listing tracked files from root
61 61 $ $NO_FALLBACK rhg files
62 62 file1
63 63 file2
64 64 file3
65 65
66 66 Listing tracked files from subdirectory
67 67 $ mkdir -p path/to/directory
68 68 $ cd path/to/directory
69 69 $ $NO_FALLBACK rhg files
70 70 ../../../file1
71 71 ../../../file2
72 72 ../../../file3
73 73
74 74 $ $NO_FALLBACK rhg files --config ui.relative-paths=legacy
75 unsupported feature: non-default ui.relative-paths
76 [252]
75 ../../../file1
76 ../../../file2
77 ../../../file3
77 78
78 79 $ $NO_FALLBACK rhg files --config ui.relative-paths=false
79 80 unsupported feature: non-default ui.relative-paths
80 81 [252]
81 82
82 83 $ $NO_FALLBACK rhg files --config ui.relative-paths=true
83 unsupported feature: non-default ui.relative-paths
84 [252]
84 ../../../file1
85 ../../../file2
86 ../../../file3
85 87
86 88 Listing tracked files through broken pipe
87 89 $ $NO_FALLBACK rhg files | head -n 1
88 90 ../../../file1
89 91
90 92 Debuging data in inline index
91 93 $ cd $TESTTMP
92 94 $ rm -rf repository
93 95 $ hg init repository
94 96 $ cd repository
95 97 $ for i in 1 2 3 4 5 6; do
96 98 > echo $i >> file-$i
97 99 > hg add file-$i
98 100 > hg commit -m "Commit $i" -q
99 101 > done
100 102 $ $NO_FALLBACK rhg debugdata -c 2
101 103 8d0267cb034247ebfa5ee58ce59e22e57a492297
102 104 test
103 105 0 0
104 106 file-3
105 107
106 108 Commit 3 (no-eol)
107 109 $ $NO_FALLBACK rhg debugdata -m 2
108 110 file-1\x00b8e02f6433738021a065f94175c7cd23db5f05be (esc)
109 111 file-2\x005d9299349fc01ddd25d0070d149b124d8f10411e (esc)
110 112 file-3\x002661d26c649684b482d10f91960cc3db683c38b4 (esc)
111 113
112 114 Debuging with full node id
113 115 $ $NO_FALLBACK rhg debugdata -c `hg log -r 0 -T '{node}'`
114 116 d1d1c679d3053e8926061b6f45ca52009f011e3f
115 117 test
116 118 0 0
117 119 file-1
118 120
119 121 Commit 1 (no-eol)
120 122
121 123 Specifying revisions by changeset ID
122 124 $ hg log -T '{node}\n'
123 125 c6ad58c44207b6ff8a4fbbca7045a5edaa7e908b
124 126 d654274993d0149eecc3cc03214f598320211900
125 127 f646af7e96481d3a5470b695cf30ad8e3ab6c575
126 128 cf8b83f14ead62b374b6e91a0e9303b85dfd9ed7
127 129 91c6f6e73e39318534dc415ea4e8a09c99cd74d6
128 130 6ae9681c6d30389694d8701faf24b583cf3ccafe
129 131 $ $NO_FALLBACK rhg files -r cf8b83
130 132 file-1
131 133 file-2
132 134 file-3
133 135 $ $NO_FALLBACK rhg cat -r cf8b83 file-2
134 136 2
135 137 $ $NO_FALLBACK rhg cat --rev cf8b83 file-2
136 138 2
137 139 $ $NO_FALLBACK rhg cat -r c file-2
138 140 abort: ambiguous revision identifier: c
139 141 [255]
140 142 $ $NO_FALLBACK rhg cat -r d file-2
141 143 2
142 144 $ $NO_FALLBACK rhg cat -r 0000 file-2
143 145 file-2: no such file in rev 000000000000
144 146 [1]
145 147
146 148 Cat files
147 149 $ cd $TESTTMP
148 150 $ rm -rf repository
149 151 $ hg init repository
150 152 $ cd repository
151 153 $ echo "original content" > original
152 154 $ hg add original
153 155 $ hg commit -m "add original" original
154 156 Without `--rev`
155 157 $ $NO_FALLBACK rhg cat original
156 158 original content
157 159 With `--rev`
158 160 $ $NO_FALLBACK rhg cat -r 0 original
159 161 original content
160 162 Cat copied file should not display copy metadata
161 163 $ hg copy original copy_of_original
162 164 $ hg commit -m "add copy of original"
163 165 $ $NO_FALLBACK rhg cat original
164 166 original content
165 167 $ $NO_FALLBACK rhg cat -r 1 copy_of_original
166 168 original content
167 169
168 170
169 171 Fallback to Python
170 172 $ $NO_FALLBACK rhg cat original --exclude="*.rs"
171 173 unsupported feature: error: Found argument '--exclude' which wasn't expected, or isn't valid in this context
172 174
173 175 If you tried to supply '--exclude' as a value rather than a flag, use '-- --exclude'
174 176
175 177 Usage: rhg cat <FILE>...
176 178
177 179 For more information try '--help'
178 180
179 181 [252]
180 182 $ rhg cat original --exclude="*.rs"
181 183 original content
182 184
183 185 Check that `fallback-immediately` overrides `$NO_FALLBACK`
184 186 $ $NO_FALLBACK rhg cat original --exclude="*.rs" --config rhg.fallback-immediately=1
185 187 original content
186 188
187 189 $ (unset RHG_FALLBACK_EXECUTABLE; rhg cat original --exclude="*.rs")
188 190 abort: 'rhg.on-unsupported=fallback' without 'rhg.fallback-executable' set.
189 191 [255]
190 192
191 193 $ (unset RHG_FALLBACK_EXECUTABLE; rhg cat original)
192 194 original content
193 195
194 196 $ rhg cat original --exclude="*.rs" --config rhg.fallback-executable=false
195 197 [1]
196 198
197 199 $ rhg cat original --exclude="*.rs" --config rhg.fallback-executable=hg-non-existent
198 200 abort: invalid fallback 'hg-non-existent': cannot find binary path
199 201 [253]
200 202
201 203 $ rhg cat original --exclude="*.rs" --config rhg.fallback-executable=rhg
202 204 Blocking recursive fallback. The 'rhg.fallback-executable = rhg' config points to `rhg` itself.
203 205 unsupported feature: error: Found argument '--exclude' which wasn't expected, or isn't valid in this context
204 206
205 207 If you tried to supply '--exclude' as a value rather than a flag, use '-- --exclude'
206 208
207 209 Usage: rhg cat <FILE>...
208 210
209 211 For more information try '--help'
210 212
211 213 [252]
212 214
213 215 Fallback with shell path segments
214 216 $ $NO_FALLBACK rhg cat .
215 217 unsupported feature: `..` or `.` path segment
216 218 [252]
217 219 $ $NO_FALLBACK rhg cat ..
218 220 unsupported feature: `..` or `.` path segment
219 221 [252]
220 222 $ $NO_FALLBACK rhg cat ../..
221 223 unsupported feature: `..` or `.` path segment
222 224 [252]
223 225
224 226 Fallback with filesets
225 227 $ $NO_FALLBACK rhg cat "set:c or b"
226 228 unsupported feature: fileset
227 229 [252]
228 230
229 231 Fallback with generic hooks
230 232 $ $NO_FALLBACK rhg cat original --config hooks.pre-cat=something
231 233 unsupported feature: pre-cat hook defined
232 234 [252]
233 235
234 236 $ $NO_FALLBACK rhg cat original --config hooks.post-cat=something
235 237 unsupported feature: post-cat hook defined
236 238 [252]
237 239
238 240 $ $NO_FALLBACK rhg cat original --config hooks.fail-cat=something
239 241 unsupported feature: fail-cat hook defined
240 242 [252]
241 243
242 244 Fallback with [defaults]
243 245 $ $NO_FALLBACK rhg cat original --config "defaults.cat=-r null"
244 246 unsupported feature: `defaults` config set
245 247 [252]
246 248
247 249
248 250 Requirements
249 251 $ $NO_FALLBACK rhg debugrequirements
250 252 dotencode
251 253 fncache
252 254 generaldelta
253 255 persistent-nodemap
254 256 revlog-compression-zstd (zstd !)
255 257 revlogv1
256 258 share-safe
257 259 sparserevlog
258 260 store
259 261
260 262 $ echo indoor-pool >> .hg/requires
261 263 $ $NO_FALLBACK rhg files
262 264 unsupported feature: repository requires feature unknown to this Mercurial: indoor-pool
263 265 [252]
264 266
265 267 $ $NO_FALLBACK rhg cat -r 1 copy_of_original
266 268 unsupported feature: repository requires feature unknown to this Mercurial: indoor-pool
267 269 [252]
268 270
269 271 $ $NO_FALLBACK rhg debugrequirements
270 272 unsupported feature: repository requires feature unknown to this Mercurial: indoor-pool
271 273 [252]
272 274
273 275 $ echo -e '\xFF' >> .hg/requires
274 276 $ $NO_FALLBACK rhg debugrequirements
275 277 abort: parse error in 'requires' file
276 278 [255]
277 279
278 280 Persistent nodemap
279 281 $ cd $TESTTMP
280 282 $ rm -rf repository
281 283 $ hg --config format.use-persistent-nodemap=no init repository
282 284 $ cd repository
283 285 $ $NO_FALLBACK rhg debugrequirements | grep nodemap
284 286 [1]
285 287 $ hg debugbuilddag .+5000 --overwritten-file --config "storage.revlog.nodemap.mode=warn"
286 288 $ hg id -r tip
287 289 c3ae8dec9fad tip
288 290 $ ls .hg/store/00changelog*
289 291 .hg/store/00changelog.d
290 292 .hg/store/00changelog.i
291 293 $ $NO_FALLBACK rhg files -r c3ae8dec9fad
292 294 of
293 295
294 296 $ cd $TESTTMP
295 297 $ rm -rf repository
296 298 $ hg --config format.use-persistent-nodemap=True init repository
297 299 $ cd repository
298 300 $ $NO_FALLBACK rhg debugrequirements | grep nodemap
299 301 persistent-nodemap
300 302 $ hg debugbuilddag .+5000 --overwritten-file --config "storage.revlog.nodemap.mode=warn"
301 303 $ hg id -r tip
302 304 c3ae8dec9fad tip
303 305 $ ls .hg/store/00changelog*
304 306 .hg/store/00changelog-*.nd (glob)
305 307 .hg/store/00changelog.d
306 308 .hg/store/00changelog.i
307 309 .hg/store/00changelog.n
308 310
309 311 Specifying revisions by changeset ID
310 312 $ $NO_FALLBACK rhg files -r c3ae8dec9fad
311 313 of
312 314 $ $NO_FALLBACK rhg cat -r c3ae8dec9fad of
313 315 r5000
314 316
315 317 Crate a shared repository
316 318
317 319 $ echo "[extensions]" >> $HGRCPATH
318 320 $ echo "share = " >> $HGRCPATH
319 321
320 322 $ cd $TESTTMP
321 323 $ hg init repo1
322 324 $ echo a > repo1/a
323 325 $ hg -R repo1 commit -A -m'init'
324 326 adding a
325 327
326 328 $ hg share repo1 repo2
327 329 updating working directory
328 330 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
329 331
330 332 And check that basic rhg commands work with sharing
331 333
332 334 $ $NO_FALLBACK rhg files -R repo2
333 335 repo2/a
334 336 $ $NO_FALLBACK rhg -R repo2 cat -r 0 repo2/a
335 337 a
336 338
337 339 Same with relative sharing
338 340
339 341 $ hg share repo2 repo3 --relative
340 342 updating working directory
341 343 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
342 344
343 345 $ $NO_FALLBACK rhg files -R repo3
344 346 repo3/a
345 347 $ $NO_FALLBACK rhg -R repo3 cat -r 0 repo3/a
346 348 a
347 349
348 350 Same with share-safe
349 351
350 352 $ echo "[format]" >> $HGRCPATH
351 353 $ echo "use-share-safe = True" >> $HGRCPATH
352 354
353 355 $ cd $TESTTMP
354 356 $ hg init repo4
355 357 $ cd repo4
356 358 $ echo a > a
357 359 $ hg commit -A -m'init'
358 360 adding a
359 361
360 362 $ cd ..
361 363 $ hg share repo4 repo5
362 364 updating working directory
363 365 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
364 366
365 367 And check that basic rhg commands work with sharing
366 368
367 369 $ cd repo5
368 370 $ $NO_FALLBACK rhg files
369 371 a
370 372 $ $NO_FALLBACK rhg cat -r 0 a
371 373 a
372 374
373 375 The blackbox extension is supported
374 376
375 377 $ echo "[extensions]" >> $HGRCPATH
376 378 $ echo "blackbox =" >> $HGRCPATH
377 379 $ echo "[blackbox]" >> $HGRCPATH
378 380 $ echo "maxsize = 1" >> $HGRCPATH
379 381 $ $NO_FALLBACK rhg files > /dev/null
380 382 $ cat .hg/blackbox.log
381 383 ????-??-?? ??:??:??.??? * @d3873e73d99ef67873dac33fbcc66268d5d2b6f4 (*)> (rust) files exited 0 after * seconds (glob)
382 384 $ cat .hg/blackbox.log.1
383 385 ????-??-?? ??:??:??.??? * @d3873e73d99ef67873dac33fbcc66268d5d2b6f4 (*)> (rust) files (glob)
384 386
385 387 Subrepos are not supported
386 388
387 389 $ touch .hgsub
388 390 $ $NO_FALLBACK rhg files
389 391 unsupported feature: subrepos (.hgsub is present)
390 392 [252]
391 393 $ rhg files
392 394 a
393 395 $ rm .hgsub
394 396
395 397 The `:required` extension suboptions are correctly ignored
396 398
397 399 $ echo "[extensions]" >> $HGRCPATH
398 400 $ echo "blackbox:required = yes" >> $HGRCPATH
399 401 $ rhg files
400 402 a
401 403 $ echo "*:required = yes" >> $HGRCPATH
402 404 $ rhg files
403 405 a
404 406
405 407 We can ignore all extensions at once
406 408
407 409 $ echo "[extensions]" >> $HGRCPATH
408 410 $ echo "thisextensionbetternotexist=" >> $HGRCPATH
409 411 $ echo "thisextensionbetternotexisteither=" >> $HGRCPATH
410 412 $ $NO_FALLBACK rhg files
411 413 unsupported feature: extensions: thisextensionbetternotexist, thisextensionbetternotexisteither (consider adding them to 'rhg.ignored-extensions' config)
412 414 [252]
413 415
414 416 $ echo "[rhg]" >> $HGRCPATH
415 417 $ echo "ignored-extensions=*" >> $HGRCPATH
416 418 $ $NO_FALLBACK rhg files
417 419 a
General Comments 0
You need to be logged in to leave comments. Login now