rhg-files: add support for narrow when specifying a revision
authorRaphaël Gomès <rgomes@octobus.net>
Wed, 11 Jan 2023 17:30:55 +0100
changeset 49985 e57f76c28f7b
parent 49984 df9eabc9837b
child 49986 dbcc45221c1f
rhg-files: add support for narrow when specifying a revision This makes it so that `rhg files -r NODE` works properly when using narrow.
rust/hg-core/src/operations/list_tracked_files.rs
rust/rhg/src/commands/files.rs
tests/test-rhg-sparse-narrow.t
--- a/rust/hg-core/src/operations/list_tracked_files.rs	Wed Jan 11 17:08:23 2023 +0100
+++ b/rust/hg-core/src/operations/list_tracked_files.rs	Wed Jan 11 17:30:55 2023 +0100
@@ -6,24 +6,40 @@
 // GNU General Public License version 2 or any later version.
 
 use crate::errors::HgError;
+use crate::matchers::Matcher;
 use crate::repo::Repo;
 use crate::revlog::manifest::Manifest;
 use crate::revlog::RevlogError;
+use crate::utils::filter_map_results;
 use crate::utils::hg_path::HgPath;
 
 /// List files under Mercurial control at a given revision.
 pub fn list_rev_tracked_files(
     repo: &Repo,
     revset: &str,
+    narrow_matcher: Box<dyn Matcher>,
 ) -> Result<FilesForRev, RevlogError> {
     let rev = crate::revset::resolve_single(revset, repo)?;
-    Ok(FilesForRev(repo.manifest_for_rev(rev)?))
+    Ok(FilesForRev {
+        manifest: repo.manifest_for_rev(rev)?,
+        narrow_matcher,
+    })
 }
 
-pub struct FilesForRev(Manifest);
+pub struct FilesForRev {
+    manifest: Manifest,
+    narrow_matcher: Box<dyn Matcher>,
+}
 
 impl FilesForRev {
     pub fn iter(&self) -> impl Iterator<Item = Result<&HgPath, HgError>> {
-        self.0.iter().map(|entry| Ok(entry?.path))
+        filter_map_results(self.manifest.iter(), |entry| {
+            let path = entry.path;
+            Ok(if self.narrow_matcher.matches(path) {
+                Some(path)
+            } else {
+                None
+            })
+        })
     }
 }
--- a/rust/rhg/src/commands/files.rs	Wed Jan 11 17:08:23 2023 +0100
+++ b/rust/rhg/src/commands/files.rs	Wed Jan 11 17:30:55 2023 +0100
@@ -51,24 +51,15 @@
         ));
     }
 
+    let (narrow_matcher, narrow_warnings) = narrow::matcher(repo)?;
+    print_narrow_sparse_warnings(&narrow_warnings, &[], invocation.ui, repo)?;
+
     if let Some(rev) = rev {
-        if repo.has_narrow() {
-            return Err(CommandError::unsupported(
-                "rhg files -r <rev> is not supported in narrow clones",
-            ));
-        }
-        let files = list_rev_tracked_files(repo, rev)
+        let files = list_rev_tracked_files(repo, rev, narrow_matcher)
             .map_err(|e| (e, rev.as_ref()))?;
         display_files(invocation.ui, repo, files.iter())
     } else {
         // The dirstate always reflects the sparse narrowspec.
-        let (narrow_matcher, narrow_warnings) = narrow::matcher(repo)?;
-        print_narrow_sparse_warnings(
-            &narrow_warnings,
-            &[],
-            invocation.ui,
-            repo,
-        )?;
         let dirstate = repo.dirstate_map()?;
         let files_res: Result<Vec<_>, _> =
             filter_map_results(dirstate.iter(), |(path, entry)| {
--- a/tests/test-rhg-sparse-narrow.t	Wed Jan 11 17:08:23 2023 +0100
+++ b/tests/test-rhg-sparse-narrow.t	Wed Jan 11 17:30:55 2023 +0100
@@ -75,12 +75,12 @@
   $ "$real_hg" cat -r "$tip" hide
   [1]
 
-A naive implementation of [rhg files] leaks the paths that are supposed to be
-hidden by narrow, so we just fall back to hg when accessing a revision.
+A naive implementation of `rhg files` would leak the paths that are supposed
+to be hidden by narrow.
 
   $ $NO_FALLBACK rhg files -r "$tip"
-  unsupported feature: rhg files -r <rev> is not supported in narrow clones
-  [252]
+  dir1/x
+  dir1/y
   $ "$real_hg" files -r "$tip"
   dir1/x
   dir1/y