rhg: refactor relativize_path into a struct + method
… instead of a function that takes an iterator and a callback.
Differential Revision: https://phab.mercurial-scm.org/D11898
--- a/rust/rhg/src/commands/files.rs Fri Dec 10 16:31:16 2021 +0100
+++ b/rust/rhg/src/commands/files.rs Fri Dec 10 16:57:39 2021 +0100
@@ -1,14 +1,12 @@
use crate::error::CommandError;
use crate::ui::Ui;
-use crate::ui::UiError;
-use crate::utils::path_utils::relativize_paths;
+use crate::utils::path_utils::RelativizePaths;
use clap::Arg;
use hg::errors::HgError;
use hg::operations::list_rev_tracked_files;
use hg::operations::Dirstate;
use hg::repo::Repo;
use hg::utils::hg_path::HgPath;
-use std::borrow::Cow;
pub const HELP_TEXT: &str = "
List tracked files.
@@ -86,11 +84,14 @@
let mut stdout = ui.stdout_buffer();
let mut any = false;
- relativize_paths(repo, files, |path: Cow<[u8]>| -> Result<(), UiError> {
+ let relativize = RelativizePaths::new(repo)?;
+ for result in files {
+ let path = result?;
+ stdout.write_all(&relativize.relativize(path))?;
+ stdout.write_all(b"\n")?;
any = true;
- stdout.write_all(path.as_ref())?;
- stdout.write_all(b"\n")
- })?;
+ }
+
stdout.flush()?;
if any {
Ok(())
--- a/rust/rhg/src/commands/status.rs Fri Dec 10 16:31:16 2021 +0100
+++ b/rust/rhg/src/commands/status.rs Fri Dec 10 16:57:39 2021 +0100
@@ -7,7 +7,7 @@
use crate::error::CommandError;
use crate::ui::Ui;
-use crate::utils::path_utils::relativize_paths;
+use crate::utils::path_utils::RelativizePaths;
use clap::{Arg, SubCommand};
use format_bytes::format_bytes;
use hg;
@@ -261,9 +261,12 @@
.unwrap_or(config.get_bool(b"ui", b"relative-paths")?);
let output = DisplayStatusPaths {
ui,
- repo,
no_status,
- relative_paths,
+ relativize: if relative_paths {
+ Some(RelativizePaths::new(repo)?)
+ } else {
+ None
+ },
};
if display_states.modified {
output.display(b"M", ds_status.modified)?;
@@ -379,9 +382,8 @@
struct DisplayStatusPaths<'a> {
ui: &'a Ui,
- repo: &'a Repo,
no_status: bool,
- relative_paths: bool,
+ relativize: Option<RelativizePaths>,
}
impl DisplayStatusPaths<'_> {
@@ -393,27 +395,24 @@
mut paths: Vec<HgPathCow>,
) -> Result<(), CommandError> {
paths.sort_unstable();
- let print_path = |path: &[u8]| {
+ for path in paths {
+ let relative;
+ let path = if let Some(relativize) = &self.relativize {
+ relative = relativize.relativize(&path);
+ &*relative
+ } else {
+ path.as_bytes()
+ };
// TODO optim, probably lots of unneeded copies here, especially
// if out stream is buffered
if self.no_status {
- self.ui.write_stdout(&format_bytes!(b"{}\n", path))
+ self.ui.write_stdout(&format_bytes!(b"{}\n", path))?
} else {
self.ui.write_stdout(&format_bytes!(
b"{} {}\n",
status_prefix,
path
- ))
- }
- };
-
- if self.relative_paths {
- relativize_paths(self.repo, paths.iter().map(Ok), |path| {
- print_path(&path)
- })?;
- } else {
- for path in paths {
- print_path(path.as_bytes())?
+ ))?
}
}
Ok(())
--- a/rust/rhg/src/utils/path_utils.rs Fri Dec 10 16:31:16 2021 +0100
+++ b/rust/rhg/src/utils/path_utils.rs Fri Dec 10 16:57:39 2021 +0100
@@ -3,8 +3,6 @@
// This software may be used and distributed according to the terms of the
// GNU General Public License version 2 or any later version.
-use crate::error::CommandError;
-use crate::ui::UiError;
use hg::errors::HgError;
use hg::repo::Repo;
use hg::utils::current_dir;
@@ -13,37 +11,45 @@
use hg::utils::hg_path::HgPathBuf;
use std::borrow::Cow;
-pub fn relativize_paths(
- repo: &Repo,
- paths: impl IntoIterator<Item = Result<impl AsRef<HgPath>, HgError>>,
- mut callback: impl FnMut(Cow<[u8]>) -> Result<(), UiError>,
-) -> Result<(), CommandError> {
- let cwd = current_dir()?;
- let repo_root = repo.working_directory_path();
- let repo_root = cwd.join(repo_root); // Make it absolute
- let repo_root_hgpath =
- HgPathBuf::from(get_bytes_from_path(repo_root.to_owned()));
- let outside_repo: bool;
- let cwd_hgpath: HgPathBuf;
+pub struct RelativizePaths {
+ repo_root: HgPathBuf,
+ cwd: HgPathBuf,
+ outside_repo: bool,
+}
+
+impl RelativizePaths {
+ pub fn new(repo: &Repo) -> Result<Self, HgError> {
+ let cwd = current_dir()?;
+ let repo_root = repo.working_directory_path();
+ let repo_root = cwd.join(repo_root); // Make it absolute
+ let repo_root_hgpath =
+ HgPathBuf::from(get_bytes_from_path(repo_root.to_owned()));
- if let Ok(cwd_relative_to_repo) = cwd.strip_prefix(&repo_root) {
- // 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));
+ if let Ok(cwd_relative_to_repo) = cwd.strip_prefix(&repo_root) {
+ // The current directory is inside the repo, so we can work with
+ // relative paths
+ Ok(Self {
+ repo_root: repo_root_hgpath,
+ cwd: HgPathBuf::from(get_bytes_from_path(
+ cwd_relative_to_repo,
+ )),
+ outside_repo: false,
+ })
+ } else {
+ Ok(Self {
+ repo_root: repo_root_hgpath,
+ cwd: HgPathBuf::from(get_bytes_from_path(cwd)),
+ outside_repo: true,
+ })
+ }
}
- for file in paths {
- if outside_repo {
- let file = repo_root_hgpath.join(file?.as_ref());
- callback(relativize_path(&file, &cwd_hgpath))?;
+ pub fn relativize<'a>(&self, path: &'a HgPath) -> Cow<'a, [u8]> {
+ if self.outside_repo {
+ let joined = self.repo_root.join(path);
+ Cow::Owned(relativize_path(&joined, &self.cwd).into_owned())
} else {
- callback(relativize_path(file?.as_ref(), &cwd_hgpath))?;
+ relativize_path(path, &self.cwd)
}
}
- Ok(())
}