Commands like files, status supports printing relative paths. Hence we need
to re-use this code in other places too. So let's take this out from rhg files
into a utility function.
Next patch will make rhg status use it.
martinvonz |
hg-reviewers |
Commands like files, status supports printing relative paths. Hence we need
to re-use this code in other places too. So let's take this out from rhg files
into a utility function.
Next patch will make rhg status use it.
Automatic diff as part of commit; lint not applicable. |
Automatic diff as part of commit; unit tests not applicable. |
rust/rhg/src/utils/path_utils.rs | ||
---|---|---|
19 | I generally find iterators easier to work with than callbacks. That makes error handling easier and it makes it easy to stop iteration at any point. I'll take this as is, but consider following up with a rewrite. |
Path | Packages | |||
---|---|---|---|---|
M | rust/rhg/src/commands/files.rs (40 lines) | |||
M | rust/rhg/src/main.rs (3 lines) | |||
A | M | rust/rhg/src/utils/path_utils.rs (48 lines) |
use crate::error::CommandError; | use crate::error::CommandError; | ||||
use crate::ui::Ui; | use crate::ui::Ui; | ||||
use crate::ui::UiError; | |||||
use crate::utils::path_utils::relativize_paths; | |||||
use clap::Arg; | use clap::Arg; | ||||
use hg::operations::list_rev_tracked_files; | use hg::operations::list_rev_tracked_files; | ||||
use hg::operations::Dirstate; | use hg::operations::Dirstate; | ||||
use hg::repo::Repo; | use hg::repo::Repo; | ||||
use hg::utils::current_dir; | use hg::utils::hg_path::HgPath; | ||||
use hg::utils::files::{get_bytes_from_path, relativize_path}; | use std::borrow::Cow; | ||||
use hg::utils::hg_path::{HgPath, HgPathBuf}; | |||||
pub const HELP_TEXT: &str = " | pub const HELP_TEXT: &str = " | ||||
List tracked files. | List tracked files. | ||||
Returns 0 on success. | Returns 0 on success. | ||||
"; | "; | ||||
pub fn args() -> clap::App<'static, 'static> { | pub fn args() -> clap::App<'static, 'static> { | ||||
} | } | ||||
fn display_files<'a>( | fn display_files<'a>( | ||||
ui: &Ui, | ui: &Ui, | ||||
repo: &Repo, | repo: &Repo, | ||||
files: impl IntoIterator<Item = &'a HgPath>, | files: impl IntoIterator<Item = &'a HgPath>, | ||||
) -> Result<(), CommandError> { | ) -> Result<(), CommandError> { | ||||
let mut stdout = ui.stdout_buffer(); | let mut stdout = ui.stdout_buffer(); | ||||
let cwd = current_dir()?; | |||||
let working_directory = repo.working_directory_path(); | |||||
let working_directory = cwd.join(working_directory); // Make it absolute | |||||
let mut any = false; | let mut any = false; | ||||
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 | |||||
let cwd = HgPathBuf::from(get_bytes_from_path(cwd_relative_to_repo)); | |||||
for file in files { | |||||
any = true; | |||||
stdout.write_all(relativize_path(&file, &cwd).as_ref())?; | |||||
stdout.write_all(b"\n")?; | |||||
} | |||||
} else { | |||||
let working_directory = | |||||
HgPathBuf::from(get_bytes_from_path(working_directory)); | |||||
let cwd = HgPathBuf::from(get_bytes_from_path(cwd)); | |||||
for file in files { | |||||
any = true; | |||||
// Absolute path in the filesystem | |||||
let file = working_directory.join(file); | |||||
stdout.write_all(relativize_path(&file, &cwd).as_ref())?; | |||||
stdout.write_all(b"\n")?; | |||||
} | |||||
} | |||||
relativize_paths(repo, files, |path: Cow<[u8]>| -> Result<(), UiError> { | |||||
any = true; | |||||
stdout.write_all(path.as_ref())?; | |||||
stdout.write_all(b"\n") | |||||
})?; | |||||
stdout.flush()?; | stdout.flush()?; | ||||
if any { | if any { | ||||
Ok(()) | Ok(()) | ||||
} else { | } else { | ||||
Err(CommandError::Unsuccessful) | Err(CommandError::Unsuccessful) | ||||
} | } | ||||
} | } |
use hg::utils::SliceExt; | use hg::utils::SliceExt; | ||||
use std::ffi::OsString; | use std::ffi::OsString; | ||||
use std::path::PathBuf; | use std::path::PathBuf; | ||||
use std::process::Command; | use std::process::Command; | ||||
mod blackbox; | mod blackbox; | ||||
mod error; | mod error; | ||||
mod ui; | mod ui; | ||||
pub mod utils { | |||||
pub mod path_utils; | |||||
} | |||||
use error::CommandError; | use error::CommandError; | ||||
fn main_with_result( | fn main_with_result( | ||||
process_start_time: &blackbox::ProcessStartTime, | process_start_time: &blackbox::ProcessStartTime, | ||||
ui: &ui::Ui, | ui: &ui::Ui, | ||||
repo: Result<&Repo, &NoRepoInCwdError>, | repo: Result<&Repo, &NoRepoInCwdError>, | ||||
config: &Config, | config: &Config, | ||||
) -> Result<(), CommandError> { | ) -> Result<(), CommandError> { |
I generally find iterators easier to work with than callbacks. That makes error handling easier and it makes it easy to stop iteration at any point. I'll take this as is, but consider following up with a rewrite.