diff rust/rhg/src/commands/status.rs @ 52430:bde718849153

rhg: support status --change, including --copies It works by parsing copy information from filelog metadata headers. The --rev --rev --copies case still falls back to Python since that will require constructing a map like pathcopies does in copies.py. As in Python, rhg by default only reports copies for newly added files. With devel.copy-tracing.trace-all-files=True, it also does it for modified files.
author Mitchell Kember <mkember@janestreet.com>
date Tue, 03 Dec 2024 09:44:57 -0500
parents 42bd36bbed67
children 65839176cea9
line wrap: on
line diff
--- a/rust/rhg/src/commands/status.rs	Tue Dec 03 09:37:34 2024 -0500
+++ b/rust/rhg/src/commands/status.rs	Tue Dec 03 09:44:57 2024 -0500
@@ -35,7 +35,6 @@
 use hg::{self, narrow, sparse};
 use log::info;
 use rayon::prelude::*;
-use std::borrow::Cow;
 use std::io;
 use std::mem::take;
 use std::path::PathBuf;
@@ -156,6 +155,13 @@
                 .action(clap::ArgAction::Append)
                 .value_name("REV"),
         )
+        .arg(
+            Arg::new("change")
+                .help("list the changed files of a revision")
+                .long("change")
+                .value_name("REV")
+                .conflicts_with("rev"),
+        )
 }
 
 fn parse_revpair(
@@ -263,6 +269,7 @@
     let args = invocation.subcommand_args;
 
     let revs = args.get_many::<String>("rev");
+    let change = args.get_one::<String>("change");
     let print0 = args.get_flag("print0");
     let verbose = args.get_flag("verbose")
         || config.get_bool(b"ui", b"verbose")?
@@ -302,6 +309,9 @@
 
     let repo = invocation.repo?;
     let revpair = parse_revpair(repo, revs.map(|i| i.cloned().collect()))?;
+    let change = change
+        .map(|rev| hg::revset::resolve_single(rev, repo))
+        .transpose()?;
 
     if verbose && has_unfinished_state(repo)? {
         return Err(CommandError::unsupported(
@@ -490,23 +500,33 @@
         repo,
     )?;
 
-    if let Some((rev1, rev2)) = revpair {
+    if revpair.is_some() || change.is_some() {
         let mut ds_status = DirstateStatus::default();
-        if list_copies {
-            return Err(CommandError::unsupported(
-                "status --rev --rev with copy information is not implemented yet",
-            ));
-        }
-
-        let stat = hg::operations::status_rev_rev_no_copies(
-            repo, rev1, rev2, matcher,
-        )?;
+        let list_copies = if list_copies {
+            if config.get_bool(b"devel", b"copy-tracing.trace-all-files")? {
+                Some(hg::operations::ListCopies::AddedOrModified)
+            } else {
+                Some(hg::operations::ListCopies::Added)
+            }
+        } else {
+            None
+        };
+        let stat = if let Some((rev1, rev2)) = revpair {
+            if list_copies.is_some() {
+                return Err(CommandError::unsupported(
+                    "status --rev --rev with copy information is not implemented yet",
+                ));
+            }
+            hg::operations::status_rev_rev_no_copies(
+                repo, rev1, rev2, matcher,
+            )?
+        } else if let Some(rev) = change {
+            hg::operations::status_change(repo, rev, matcher, list_copies)?
+        } else {
+            unreachable!();
+        };
         for entry in stat.iter() {
             let (path, status) = entry?;
-            let path = StatusPath {
-                path: Cow::Borrowed(path),
-                copy_source: None,
-            };
             match status {
                 hg::operations::DiffStatus::Removed => {
                     if display_states.removed {