view rust/rhg/src/utils/path_utils.rs @ 48391:10c32e1b892a

rhg: Propogate manifest parse errors instead of panicking The Rust parser for the manifest file format is an iterator. Now every item from that iterator is a `Result`, which makes error handling required in multiple new places. This makes better recovery on errors possible, compare to a run time panic. Differential Revision: https://phab.mercurial-scm.org/D11771
author Simon Sapin <simon.sapin@octobus.net>
date Tue, 23 Nov 2021 18:27:42 +0100
parents 9ecf802b06e0
children 9b0e1f64656f
line wrap: on
line source

// path utils module
//
// 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;
use hg::utils::files::{get_bytes_from_path, relativize_path};
use hg::utils::hg_path::HgPath;
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;

    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));
    }

    for file in paths {
        if outside_repo {
            let file = repo_root_hgpath.join(file?.as_ref());
            callback(relativize_path(&file, &cwd_hgpath))?;
        } else {
            callback(relativize_path(file?.as_ref(), &cwd_hgpath))?;
        }
    }
    Ok(())
}