rhg-files: add support for narrow when specifying a revision
This makes it so that `rhg files -r NODE` works properly when using narrow.
--- 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