rust/rhg/src/main.rs
branchstable
changeset 48846 006688e36e12
parent 48773 f19be290756a
child 49201 a932cad26d37
equal deleted inserted replaced
48845:db3f8e5cc965 48846:006688e36e12
    11 use hg::repo::{Repo, RepoError};
    11 use hg::repo::{Repo, RepoError};
    12 use hg::utils::files::{get_bytes_from_os_str, get_path_from_bytes};
    12 use hg::utils::files::{get_bytes_from_os_str, get_path_from_bytes};
    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 
    19 mod blackbox;
    20 mod blackbox;
    20 mod color;
    21 mod color;
   363             } else {
   364             } else {
   364                 exit_codes::ABORT
   365                 exit_codes::ABORT
   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         }
       
   374         Err(CommandError::InvalidFallback { .. }) => {
       
   375             exit_codes::INVALID_FALLBACK
   373         }
   376         }
   374     }
   377     }
   375 }
   378 }
   376 
   379 
   377 fn exit(
   380 fn exit(
   413             ));
   416             ));
   414             on_unsupported = OnUnsupported::Abort
   417             on_unsupported = OnUnsupported::Abort
   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);
   421             command.args(args);
   435             command.args(args);
   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)
   441 }
   455 }
   442 
   456 
   469                 }
   483                 }
   470                 OnUnsupported::AbortSilent => {}
   484                 OnUnsupported::AbortSilent => {}
   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 }
   477 
   498 
   478 macro_rules! subcommands {
   499 macro_rules! subcommands {