##// END OF EJS Templates
rhg: use `Command::exec` instead of `Command::status`...
Raphaël Gomès -
r50043:006688e3 stable
parent child Browse files
Show More
@@ -505,9 +505,9 b' checksum = "e2abad23fbc42b3700f2f279844d'
505
505
506 [[package]]
506 [[package]]
507 name = "libc"
507 name = "libc"
508 version = "0.2.81"
508 version = "0.2.124"
509 source = "registry+https://github.com/rust-lang/crates.io-index"
509 source = "registry+https://github.com/rust-lang/crates.io-index"
510 checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb"
510 checksum = "21a41fed9d98f27ab1c6d161da622a4fa35e8a54a8adc24bbf3ddd0ef70b0e50"
511
511
512 [[package]]
512 [[package]]
513 name = "libm"
513 name = "libm"
@@ -949,6 +949,7 b' dependencies = ['
949 "micro-timer",
949 "micro-timer",
950 "regex",
950 "regex",
951 "users",
951 "users",
952 "which",
952 ]
953 ]
953
954
954 [[package]]
955 [[package]]
@@ -1151,6 +1152,17 b' source = "registry+https://github.com/ru'
1151 checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
1152 checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
1152
1153
1153 [[package]]
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 name = "winapi"
1166 name = "winapi"
1155 version = "0.3.9"
1167 version = "0.3.9"
1156 source = "registry+https://github.com/rust-lang/crates.io-index"
1168 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -17,3 +17,6 b' pub const UNSUCCESSFUL: ExitCode = 1;'
17
17
18 /// Command or feature not implemented by rhg
18 /// Command or feature not implemented by rhg
19 pub const UNIMPLEMENTED: ExitCode = 252;
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 env_logger = "0.7.1"
21 env_logger = "0.7.1"
22 format-bytes = "0.3.0"
22 format-bytes = "0.3.0"
23 users = "0.11.0"
23 users = "0.11.0"
24 which = "4.2.5"
@@ -29,6 +29,9 b' pub enum CommandError {'
29 /// `rhg` may attempt to silently fall back to Python-based `hg`, which
29 /// `rhg` may attempt to silently fall back to Python-based `hg`, which
30 /// may or may not support this feature.
30 /// may or may not support this feature.
31 UnsupportedFeature { message: Vec<u8> },
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 impl CommandError {
37 impl CommandError {
@@ -13,6 +13,7 b' use hg::utils::files::{get_bytes_from_os'
13 use hg::utils::SliceExt;
13 use hg::utils::SliceExt;
14 use std::collections::HashSet;
14 use std::collections::HashSet;
15 use std::ffi::OsString;
15 use std::ffi::OsString;
16 use std::os::unix::prelude::CommandExt;
16 use std::path::PathBuf;
17 use std::path::PathBuf;
17 use std::process::Command;
18 use std::process::Command;
18
19
@@ -365,12 +366,14 b' fn exit_code('
365 }
366 }
366 }
367 }
367 Err(CommandError::Unsuccessful) => exit_codes::UNSUCCESSFUL,
368 Err(CommandError::Unsuccessful) => exit_codes::UNSUCCESSFUL,
368
369 // Exit with a specific code and no error message to let a potential
369 // Exit with a specific code and no error message to let a potential
370 // wrapper script fallback to Python-based Mercurial.
370 // wrapper script fallback to Python-based Mercurial.
371 Err(CommandError::UnsupportedFeature { .. }) => {
371 Err(CommandError::UnsupportedFeature { .. }) => {
372 exit_codes::UNIMPLEMENTED
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 } else {
418 } else {
416 log::debug!("falling back (see trace-level log)");
419 log::debug!("falling back (see trace-level log)");
417 log::trace!("{}", local_to_utf8(message));
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 // `args` is now `argv[1..]` since we’ve already consumed
432 // `args` is now `argv[1..]` since we’ve already consumed
419 // `argv[0]`
433 // `argv[0]`
420 let mut command = Command::new(executable_path);
434 let mut command = Command::new(executable_path);
@@ -422,19 +436,19 b' fn exit('
422 if let Some(initial) = initial_current_dir {
436 if let Some(initial) = initial_current_dir {
423 command.current_dir(initial);
437 command.current_dir(initial);
424 }
438 }
425 let result = command.status();
439 // We don't use subprocess because proper signal handling is harder
426 match result {
440 // and we don't want to keep `rhg` around after a fallback anyway.
427 Ok(status) => std::process::exit(
441 // For example, if `rhg` is run in the background and falls back to
428 status.code().unwrap_or(exit_codes::ABORT),
442 // `hg` which, in turn, waits for a signal, we'll get stuck if
429 ),
443 // we're doing plain subprocess.
430 Err(error) => {
444 //
431 let _ = ui.write_stderr(&format_bytes!(
445 // If `exec` returns, we can only assume our process is very broken
432 b"tried to fall back to a '{}' sub-process but got error {}\n",
446 // (see its documentation), so only try to forward the error code
433 executable, format_bytes::Utf8(error)
447 // when exiting.
434 ));
448 let err = command.exec();
435 on_unsupported = OnUnsupported::Abort
449 std::process::exit(
436 }
450 err.raw_os_error().unwrap_or(exit_codes::ABORT),
437 }
451 );
438 }
452 }
439 }
453 }
440 exit_no_fallback(ui, on_unsupported, result, use_detailed_exit_code)
454 exit_no_fallback(ui, on_unsupported, result, use_detailed_exit_code)
@@ -471,6 +485,13 b' fn exit_no_fallback('
471 OnUnsupported::Fallback { .. } => unreachable!(),
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 std::process::exit(exit_code(&result, use_detailed_exit_code))
496 std::process::exit(exit_code(&result, use_detailed_exit_code))
476 }
497 }
@@ -179,15 +179,8 b' Fallback to Python'
179 [1]
179 [1]
180
180
181 $ rhg cat original --exclude="*.rs" --config rhg.fallback-executable=hg-non-existent
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$
182 abort: invalid fallback 'hg-non-existent': cannot find binary path
183 unsupported feature: error: Found argument '--exclude' which wasn't expected, or isn't valid in this context
183 [253]
184
185 USAGE:
186 rhg cat [OPTIONS] <FILE>...
187
188 For more information try --help
189
190 [252]
191
184
192 $ rhg cat original --exclude="*.rs" --config rhg.fallback-executable=rhg
185 $ rhg cat original --exclude="*.rs" --config rhg.fallback-executable=rhg
193 Blocking recursive fallback. The 'rhg.fallback-executable = rhg' config points to `rhg` itself.
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