Patchwork D10134: rhg: Add support for --cwd

login
register
mail settings
Submitter phabricator
Date March 9, 2021, 9:41 a.m.
Message ID <differential-rev-PHID-DREV-hqb753cpavo762ayi5bp-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/48448/
State Superseded
Headers show

Comments

phabricator - March 9, 2021, 9:41 a.m.
SimonSapin created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D10134

AFFECTED FILES
  rust/rhg/src/main.rs

CHANGE DETAILS




To: SimonSapin, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/rust/rhg/src/main.rs b/rust/rhg/src/main.rs
--- a/rust/rhg/src/main.rs
+++ b/rust/rhg/src/main.rs
@@ -53,6 +53,14 @@ 
                 // Not ok: `--config section.key1=val section.key2=val2`
                 .number_of_values(1),
         )
+        .arg(
+            Arg::with_name("cwd")
+                .help("change working directory")
+                .long("--cwd")
+                .value_name("DIR")
+                .takes_value(true)
+                .global(true),
+        )
         .version("0.0.1");
     let app = add_subcommand_args(app);
 
@@ -87,6 +95,28 @@ 
     let ui = ui::Ui::new();
 
     let early_args = EarlyArgs::parse(std::env::args_os());
+
+    let initial_current_dir = early_args.cwd.map(|cwd| {
+        let cwd = get_path_from_bytes(&cwd);
+        std::env::current_dir()
+            .and_then(|initial| {
+                std::env::set_current_dir(cwd)?;
+                Ok(initial)
+            })
+            .unwrap_or_else(|error| {
+                exit(
+                    &None,
+                    &ui,
+                    OnUnsupported::Abort,
+                    Err(CommandError::abort(format!(
+                        "abort: {}: '{}'",
+                        error,
+                        cwd.display()
+                    ))),
+                )
+            })
+    });
+
     let non_repo_config =
         Config::load(early_args.config).unwrap_or_else(|error| {
             // Normally this is decided based on config, but we don’t have that
@@ -94,12 +124,13 @@ 
             // "unsupported" error but that is not enforced by the type system.
             let on_unsupported = OnUnsupported::Abort;
 
-            exit(&ui, on_unsupported, Err(error.into()))
+            exit(&initial_current_dir, &ui, on_unsupported, Err(error.into()))
         });
 
     if let Some(repo_path_bytes) = &early_args.repo {
         if repo_path_bytes.contains(&b':') {
             exit(
+                &initial_current_dir,
                 &ui,
                 OnUnsupported::from_config(&non_repo_config),
                 Err(CommandError::UnsupportedFeature {
@@ -119,6 +150,7 @@ 
             Err(NoRepoInCwdError { cwd: at })
         }
         Err(error) => exit(
+            &initial_current_dir,
             &ui,
             OnUnsupported::from_config(&non_repo_config),
             Err(error.into()),
@@ -137,7 +169,12 @@ 
         repo_result.as_ref(),
         config,
     );
-    exit(&ui, OnUnsupported::from_config(config), result)
+    exit(
+        &initial_current_dir,
+        &ui,
+        OnUnsupported::from_config(config),
+        result,
+    )
 }
 
 fn exit_code(result: &Result<(), CommandError>) -> i32 {
@@ -154,6 +191,7 @@ 
 }
 
 fn exit(
+    initial_current_dir: &Option<PathBuf>,
     ui: &Ui,
     mut on_unsupported: OnUnsupported,
     result: Result<(), CommandError>,
@@ -177,7 +215,12 @@ 
             on_unsupported = OnUnsupported::Abort
         } else {
             // `args` is now `argv[1..]` since we’ve already consumed `argv[0]`
-            let result = Command::new(executable_path).args(args).status();
+            let mut command = Command::new(executable_path);
+            command.args(args);
+            if let Some(initial) = initial_current_dir {
+                command.current_dir(initial);
+            }
+            let result = command.status();
             match result {
                 Ok(status) => std::process::exit(
                     status.code().unwrap_or(exitcode::ABORT),
@@ -278,6 +321,8 @@ 
     config: Vec<Vec<u8>>,
     /// Value of the `-R` or `--repository` argument, if any.
     repo: Option<Vec<u8>>,
+    /// Value of the `--cwd` argument, if any.
+    cwd: Option<Vec<u8>>,
 }
 
 impl EarlyArgs {
@@ -285,6 +330,7 @@ 
         let mut args = args.into_iter().map(get_bytes_from_os_str);
         let mut config = Vec::new();
         let mut repo = None;
+        let mut cwd = None;
         // Use `while let` instead of `for` so that we can also call
         // `args.next()` inside the loop.
         while let Some(arg) = args.next() {
@@ -296,6 +342,14 @@ 
                 config.push(value.to_owned())
             }
 
+            if arg == b"--cwd" {
+                if let Some(value) = args.next() {
+                    cwd = Some(value)
+                }
+            } else if let Some(value) = arg.drop_prefix(b"--cwd=") {
+                cwd = Some(value.to_owned())
+            }
+
             if arg == b"--repository" || arg == b"-R" {
                 if let Some(value) = args.next() {
                     repo = Some(value)
@@ -306,7 +360,7 @@ 
                 repo = Some(value.to_owned())
             }
         }
-        Self { config, repo }
+        Self { config, repo, cwd }
     }
 }