rust/rhg/src/main.rs
changeset 49164 a932cad26d37
parent 49070 137a93125902
parent 49149 006688e36e12
child 49192 2ab79873786e
equal deleted inserted replaced
49147:10b9f11daf15 49164:a932cad26d37
    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;
   379             } else {
   380             } else {
   380                 exit_codes::ABORT
   381                 exit_codes::ABORT
   381             }
   382             }
   382         }
   383         }
   383         Err(CommandError::Unsuccessful) => exit_codes::UNSUCCESSFUL,
   384         Err(CommandError::Unsuccessful) => exit_codes::UNSUCCESSFUL,
   384 
       
   385         // Exit with a specific code and no error message to let a potential
   385         // Exit with a specific code and no error message to let a potential
   386         // wrapper script fallback to Python-based Mercurial.
   386         // wrapper script fallback to Python-based Mercurial.
   387         Err(CommandError::UnsupportedFeature { .. }) => {
   387         Err(CommandError::UnsupportedFeature { .. }) => {
   388             exit_codes::UNIMPLEMENTED
   388             exit_codes::UNIMPLEMENTED
       
   389         }
       
   390         Err(CommandError::InvalidFallback { .. }) => {
       
   391             exit_codes::INVALID_FALLBACK
   389         }
   392         }
   390     }
   393     }
   391 }
   394 }
   392 
   395 
   393 fn exit<'a>(
   396 fn exit<'a>(
   430             ));
   433             ));
   431             on_unsupported = OnUnsupported::Abort
   434             on_unsupported = OnUnsupported::Abort
   432         } else {
   435         } else {
   433             log::debug!("falling back (see trace-level log)");
   436             log::debug!("falling back (see trace-level log)");
   434             log::trace!("{}", local_to_utf8(message));
   437             log::trace!("{}", local_to_utf8(message));
       
   438             if let Err(err) = which::which(executable_path) {
       
   439                 exit_no_fallback(
       
   440                     ui,
       
   441                     OnUnsupported::Abort,
       
   442                     Err(CommandError::InvalidFallback {
       
   443                         path: executable.to_owned(),
       
   444                         err: err.to_string(),
       
   445                     }),
       
   446                     use_detailed_exit_code,
       
   447                 )
       
   448             }
   435             // `args` is now `argv[1..]` since we’ve already consumed
   449             // `args` is now `argv[1..]` since we’ve already consumed
   436             // `argv[0]`
   450             // `argv[0]`
   437             let mut command = Command::new(executable_path);
   451             let mut command = Command::new(executable_path);
   438             command.args(args);
   452             command.args(args);
   439             if let Some(initial) = initial_current_dir {
   453             if let Some(initial) = initial_current_dir {
   440                 command.current_dir(initial);
   454                 command.current_dir(initial);
   441             }
   455             }
   442             let result = command.status();
   456             // We don't use subprocess because proper signal handling is harder
   443             match result {
   457             // and we don't want to keep `rhg` around after a fallback anyway.
   444                 Ok(status) => std::process::exit(
   458             // For example, if `rhg` is run in the background and falls back to
   445                     status.code().unwrap_or(exit_codes::ABORT),
   459             // `hg` which, in turn, waits for a signal, we'll get stuck if
   446                 ),
   460             // we're doing plain subprocess.
   447                 Err(error) => {
   461             //
   448                     let _ = ui.write_stderr(&format_bytes!(
   462             // If `exec` returns, we can only assume our process is very broken
   449                         b"tried to fall back to a '{}' sub-process but got error {}\n",
   463             // (see its documentation), so only try to forward the error code
   450                         executable, format_bytes::Utf8(error)
   464             // when exiting.
   451                     ));
   465             let err = command.exec();
   452                     on_unsupported = OnUnsupported::Abort
   466             std::process::exit(
   453                 }
   467                 err.raw_os_error().unwrap_or(exit_codes::ABORT),
   454             }
   468             );
   455         }
   469         }
   456     }
   470     }
   457     exit_no_fallback(ui, on_unsupported, result, use_detailed_exit_code)
   471     exit_no_fallback(ui, on_unsupported, result, use_detailed_exit_code)
   458 }
   472 }
   459 
   473 
   486                 }
   500                 }
   487                 OnUnsupported::AbortSilent => {}
   501                 OnUnsupported::AbortSilent => {}
   488                 OnUnsupported::Fallback { .. } => unreachable!(),
   502                 OnUnsupported::Fallback { .. } => unreachable!(),
   489             }
   503             }
   490         }
   504         }
       
   505         Err(CommandError::InvalidFallback { path, err }) => {
       
   506             let _ = ui.write_stderr(&format_bytes!(
       
   507                 b"abort: invalid fallback '{}': {}\n",
       
   508                 path,
       
   509                 err.as_bytes(),
       
   510             ));
       
   511         }
   491     }
   512     }
   492     std::process::exit(exit_code(&result, use_detailed_exit_code))
   513     std::process::exit(exit_code(&result, use_detailed_exit_code))
   493 }
   514 }
   494 
   515 
   495 macro_rules! subcommands {
   516 macro_rules! subcommands {