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