Show More
@@ -505,9 +505,9 b' checksum = "e2abad23fbc42b3700f2f279844d' | |||
|
505 | 505 | |
|
506 | 506 | [[package]] |
|
507 | 507 | name = "libc" |
|
508 |
version = "0.2. |
|
|
508 | version = "0.2.124" | |
|
509 | 509 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
510 | checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" | |
|
510 | checksum = "21a41fed9d98f27ab1c6d161da622a4fa35e8a54a8adc24bbf3ddd0ef70b0e50" | |
|
511 | 511 | |
|
512 | 512 | [[package]] |
|
513 | 513 | name = "libm" |
@@ -949,6 +949,7 b' dependencies = [' | |||
|
949 | 949 | "micro-timer", |
|
950 | 950 | "regex", |
|
951 | 951 | "users", |
|
952 | "which", | |
|
952 | 953 | ] |
|
953 | 954 | |
|
954 | 955 | [[package]] |
@@ -1151,6 +1152,17 b' source = "registry+https://github.com/ru' | |||
|
1151 | 1152 | checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" |
|
1152 | 1153 | |
|
1153 | 1154 | [[package]] |
|
1155 | name = "which" | |
|
1156 | version = "4.2.5" | |
|
1157 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
|
1158 | checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae" | |
|
1159 | dependencies = [ | |
|
1160 | "either", | |
|
1161 | "lazy_static", | |
|
1162 | "libc", | |
|
1163 | ] | |
|
1164 | ||
|
1165 | [[package]] | |
|
1154 | 1166 | name = "winapi" |
|
1155 | 1167 | version = "0.3.9" |
|
1156 | 1168 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -17,3 +17,6 b' pub const UNSUCCESSFUL: ExitCode = 1;' | |||
|
17 | 17 | |
|
18 | 18 | /// Command or feature not implemented by rhg |
|
19 | 19 | pub const UNIMPLEMENTED: ExitCode = 252; |
|
20 | ||
|
21 | /// The fallback path is not valid | |
|
22 | pub const INVALID_FALLBACK: ExitCode = 253; |
@@ -21,3 +21,4 b' regex = "1.3.9"' | |||
|
21 | 21 | env_logger = "0.7.1" |
|
22 | 22 | format-bytes = "0.3.0" |
|
23 | 23 | users = "0.11.0" |
|
24 | which = "4.2.5" |
@@ -29,6 +29,9 b' pub enum CommandError {' | |||
|
29 | 29 | /// `rhg` may attempt to silently fall back to Python-based `hg`, which |
|
30 | 30 | /// may or may not support this feature. |
|
31 | 31 | UnsupportedFeature { message: Vec<u8> }, |
|
32 | /// The fallback executable does not exist (or has some other problem if | |
|
33 | /// we end up being more precise about broken fallbacks). | |
|
34 | InvalidFallback { path: Vec<u8>, err: String }, | |
|
32 | 35 | } |
|
33 | 36 | |
|
34 | 37 | impl CommandError { |
@@ -13,6 +13,7 b' use hg::utils::files::{get_bytes_from_os' | |||
|
13 | 13 | use hg::utils::SliceExt; |
|
14 | 14 | use std::collections::HashSet; |
|
15 | 15 | use std::ffi::OsString; |
|
16 | use std::os::unix::prelude::CommandExt; | |
|
16 | 17 | use std::path::PathBuf; |
|
17 | 18 | use std::process::Command; |
|
18 | 19 | |
@@ -365,12 +366,14 b' fn exit_code(' | |||
|
365 | 366 | } |
|
366 | 367 | } |
|
367 | 368 | Err(CommandError::Unsuccessful) => exit_codes::UNSUCCESSFUL, |
|
368 | ||
|
369 | 369 | // Exit with a specific code and no error message to let a potential |
|
370 | 370 | // wrapper script fallback to Python-based Mercurial. |
|
371 | 371 | Err(CommandError::UnsupportedFeature { .. }) => { |
|
372 | 372 | exit_codes::UNIMPLEMENTED |
|
373 | 373 | } |
|
374 | Err(CommandError::InvalidFallback { .. }) => { | |
|
375 | exit_codes::INVALID_FALLBACK | |
|
376 | } | |
|
374 | 377 | } |
|
375 | 378 | } |
|
376 | 379 | |
@@ -415,6 +418,17 b' fn exit(' | |||
|
415 | 418 | } else { |
|
416 | 419 | log::debug!("falling back (see trace-level log)"); |
|
417 | 420 | log::trace!("{}", local_to_utf8(message)); |
|
421 | if let Err(err) = which::which(executable_path) { | |
|
422 | exit_no_fallback( | |
|
423 | ui, | |
|
424 | OnUnsupported::Abort, | |
|
425 | Err(CommandError::InvalidFallback { | |
|
426 | path: executable.to_owned(), | |
|
427 | err: err.to_string(), | |
|
428 | }), | |
|
429 | use_detailed_exit_code, | |
|
430 | ) | |
|
431 | } | |
|
418 | 432 | // `args` is now `argv[1..]` since we’ve already consumed |
|
419 | 433 | // `argv[0]` |
|
420 | 434 | let mut command = Command::new(executable_path); |
@@ -422,19 +436,19 b' fn exit(' | |||
|
422 | 436 | if let Some(initial) = initial_current_dir { |
|
423 | 437 | command.current_dir(initial); |
|
424 | 438 | } |
|
425 | let result = command.status(); | |
|
426 | match result { | |
|
427 | Ok(status) => std::process::exit( | |
|
428 | status.code().unwrap_or(exit_codes::ABORT), | |
|
429 | ), | |
|
430 | Err(error) => { | |
|
431 | let _ = ui.write_stderr(&format_bytes!( | |
|
432 | b"tried to fall back to a '{}' sub-process but got error {}\n", | |
|
433 | executable, format_bytes::Utf8(error) | |
|
434 | )); | |
|
435 | on_unsupported = OnUnsupported::Abort | |
|
436 | } | |
|
437 |
|
|
|
439 | // We don't use subprocess because proper signal handling is harder | |
|
440 | // and we don't want to keep `rhg` around after a fallback anyway. | |
|
441 | // For example, if `rhg` is run in the background and falls back to | |
|
442 | // `hg` which, in turn, waits for a signal, we'll get stuck if | |
|
443 | // we're doing plain subprocess. | |
|
444 | // | |
|
445 | // If `exec` returns, we can only assume our process is very broken | |
|
446 | // (see its documentation), so only try to forward the error code | |
|
447 | // when exiting. | |
|
448 | let err = command.exec(); | |
|
449 | std::process::exit( | |
|
450 | err.raw_os_error().unwrap_or(exit_codes::ABORT), | |
|
451 | ); | |
|
438 | 452 | } |
|
439 | 453 | } |
|
440 | 454 | exit_no_fallback(ui, on_unsupported, result, use_detailed_exit_code) |
@@ -471,6 +485,13 b' fn exit_no_fallback(' | |||
|
471 | 485 | OnUnsupported::Fallback { .. } => unreachable!(), |
|
472 | 486 | } |
|
473 | 487 | } |
|
488 | Err(CommandError::InvalidFallback { path, err }) => { | |
|
489 | let _ = ui.write_stderr(&format_bytes!( | |
|
490 | b"abort: invalid fallback '{}': {}\n", | |
|
491 | path, | |
|
492 | err.as_bytes(), | |
|
493 | )); | |
|
494 | } | |
|
474 | 495 | } |
|
475 | 496 | std::process::exit(exit_code(&result, use_detailed_exit_code)) |
|
476 | 497 | } |
@@ -179,15 +179,8 b' Fallback to Python' | |||
|
179 | 179 | [1] |
|
180 | 180 | |
|
181 | 181 | $ rhg cat original --exclude="*.rs" --config rhg.fallback-executable=hg-non-existent |
|
182 | tried to fall back to a 'hg-non-existent' sub-process but got error $ENOENT$ | |
|
183 | unsupported feature: error: Found argument '--exclude' which wasn't expected, or isn't valid in this context | |
|
184 | ||
|
185 | USAGE: | |
|
186 | rhg cat [OPTIONS] <FILE>... | |
|
187 | ||
|
188 | For more information try --help | |
|
189 | ||
|
190 | [252] | |
|
182 | abort: invalid fallback 'hg-non-existent': cannot find binary path | |
|
183 | [253] | |
|
191 | 184 | |
|
192 | 185 | $ rhg cat original --exclude="*.rs" --config rhg.fallback-executable=rhg |
|
193 | 186 | Blocking recursive fallback. The 'rhg.fallback-executable = rhg' config points to `rhg` itself. |
General Comments 0
You need to be logged in to leave comments.
Login now