Patchwork D10911: rhg: add relative path output functionality in status command

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

Comments

phabricator - June 25, 2021, 9:34 a.m.
pulkit 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/D10911

AFFECTED FILES
  rust/rhg/src/commands/status.rs

CHANGE DETAILS




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

Patch

diff --git a/rust/rhg/src/commands/status.rs b/rust/rhg/src/commands/status.rs
--- a/rust/rhg/src/commands/status.rs
+++ b/rust/rhg/src/commands/status.rs
@@ -6,9 +6,10 @@ 
 // GNU General Public License version 2 or any later version.
 
 use crate::error::CommandError;
-use crate::ui::Ui;
+use crate::ui::{Ui, UiError};
 use clap::{Arg, SubCommand};
 use hg;
+use hg::config::Config;
 use hg::dirstate_tree::dirstate_map::DirstateMap;
 use hg::errors::HgResultExt;
 use hg::errors::IoResultExt;
@@ -16,6 +17,9 @@ 
 use hg::operations::cat;
 use hg::repo::Repo;
 use hg::revlog::node::Node;
+use hg::utils::current_dir;
+use hg::utils::files::{get_bytes_from_path, relativize_path};
+use hg::utils::hg_path::HgPathBuf;
 use hg::utils::hg_path::{hg_path_to_os_string, HgPath};
 use hg::StatusError;
 use hg::{HgPathCow, StatusOptions};
@@ -154,6 +158,7 @@ 
     }
 
     let ui = invocation.ui;
+    let config = invocation.config;
     let args = invocation.subcommand_args;
     let display_states = if args.is_present("all") {
         // TODO when implementing `--quiet`: it excludes clean files
@@ -247,25 +252,25 @@ 
         }
     }
     if display_states.modified {
-        display_status_paths(ui, &mut ds_status.modified, b"M")?;
+        display_status_paths(ui, repo, config, &mut ds_status.modified, b"M")?;
     }
     if display_states.added {
-        display_status_paths(ui, &mut ds_status.added, b"A")?;
+        display_status_paths(ui, repo, config, &mut ds_status.added, b"A")?;
     }
     if display_states.removed {
-        display_status_paths(ui, &mut ds_status.removed, b"R")?;
+        display_status_paths(ui, repo, config, &mut ds_status.removed, b"R")?;
     }
     if display_states.deleted {
-        display_status_paths(ui, &mut ds_status.deleted, b"!")?;
+        display_status_paths(ui, repo, config, &mut ds_status.deleted, b"!")?;
     }
     if display_states.unknown {
-        display_status_paths(ui, &mut ds_status.unknown, b"?")?;
+        display_status_paths(ui, repo, config, &mut ds_status.unknown, b"?")?;
     }
     if display_states.ignored {
-        display_status_paths(ui, &mut ds_status.ignored, b"I")?;
+        display_status_paths(ui, repo, config, &mut ds_status.ignored, b"I")?;
     }
     if display_states.clean {
-        display_status_paths(ui, &mut ds_status.clean, b"C")?;
+        display_status_paths(ui, repo, config, &mut ds_status.clean, b"C")?;
     }
     Ok(())
 }
@@ -274,16 +279,66 @@ 
 // harcode HgPathBuf, but probably not really useful at this point
 fn display_status_paths(
     ui: &Ui,
+    repo: &Repo,
+    config: &Config,
     paths: &mut [HgPathCow],
     status_prefix: &[u8],
 ) -> Result<(), CommandError> {
     paths.sort_unstable();
-    for path in paths {
-        // Same TODO as in commands::root
-        let bytes: &[u8] = path.as_bytes();
-        // TODO optim, probably lots of unneeded copies here, especially
-        // if out stream is buffered
-        ui.write_stdout(&[status_prefix, b" ", bytes, b"\n"].concat())?;
+    let mut relative: bool =
+        config.get_bool(b"ui", b"relative-paths").unwrap_or(false);
+    relative = config
+        .get_bool(b"commands", b"status.relative")
+        .unwrap_or(relative);
+    if relative {
+        let cwd = current_dir()?;
+        let working_directory = repo.working_directory_path();
+        let working_directory = cwd.join(working_directory); // Make it absolute
+        let working_directory_hgpath =
+            HgPathBuf::from(get_bytes_from_path(working_directory.to_owned()));
+        let outside_repo: bool;
+        let cwd_hgpath: HgPathBuf;
+
+        if let Ok(cwd_relative_to_repo) = cwd.strip_prefix(&working_directory)
+        {
+            // The current directory is inside the repo, so we can work with
+            // relative paths
+            outside_repo = false;
+            cwd_hgpath =
+                HgPathBuf::from(get_bytes_from_path(cwd_relative_to_repo));
+        } else {
+            outside_repo = true;
+            cwd_hgpath = HgPathBuf::from(get_bytes_from_path(cwd));
+        }
+
+        let print_path = |path: &HgPath| -> Result<(), UiError> {
+            ui.write_stdout(
+                &[
+                    status_prefix,
+                    b" ",
+                    relativize_path(path, &cwd_hgpath).as_ref(),
+                    b"\n",
+                ]
+                .concat(),
+            )
+        };
+
+        for file in paths {
+            if outside_repo {
+                let file = working_directory_hgpath.join(file);
+                print_path(&file)?;
+            } else {
+                print_path(file)?;
+            }
+        }
+    } else {
+        for path in paths {
+            // Same TODO as in commands::root
+            let bytes: &[u8] = path.as_bytes();
+            // TODO optim, probably lots of unneeded copies here, especially
+            // if out stream is buffered
+            ui.write_stdout(&[status_prefix, b" ", bytes, b"\n"].concat())?;
+        }
     }
     Ok(())
 }