rust/hg-core/src/narrow.rs
author Raphaël Gomès <rgomes@octobus.net>
Thu, 12 Jan 2023 10:28:56 +0100
changeset 49982 7faedeb24eb2
parent 49930 e98fd81bb151
child 50857 796b5d6693a4
permissions -rw-r--r--
rhg: fix user-facing error message so it matches Python implementation
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
49488
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     1
use std::path::Path;
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     2
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     3
use crate::{
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     4
    errors::HgError,
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     5
    exit_codes,
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     6
    filepatterns::parse_pattern_file_contents,
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     7
    matchers::{
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     8
        AlwaysMatcher, DifferenceMatcher, IncludeMatcher, Matcher,
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     9
        NeverMatcher,
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    10
    },
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    11
    repo::Repo,
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    12
    requirements::NARROW_REQUIREMENT,
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    13
    sparse::{self, SparseConfigError, SparseWarning},
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    14
};
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    15
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    16
/// The file in .hg/store/ that indicates which paths exit in the store
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    17
const FILENAME: &str = "narrowspec";
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    18
/// The file in .hg/ that indicates which paths exit in the dirstate
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    19
const DIRSTATE_FILENAME: &str = "narrowspec.dirstate";
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    20
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    21
/// Pattern prefixes that are allowed in narrow patterns. This list MUST
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    22
/// only contain patterns that are fast and safe to evaluate. Keep in mind
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    23
/// that patterns are supplied by clients and executed on remote servers
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    24
/// as part of wire protocol commands. That means that changes to this
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    25
/// data structure influence the wire protocol and should not be taken
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    26
/// lightly - especially removals.
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    27
const VALID_PREFIXES: [&str; 2] = ["path:", "rootfilesin:"];
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    28
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    29
/// Return the matcher for the current narrow spec, and all configuration
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    30
/// warnings to display.
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    31
pub fn matcher(
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    32
    repo: &Repo,
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    33
) -> Result<(Box<dyn Matcher + Sync>, Vec<SparseWarning>), SparseConfigError> {
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    34
    let mut warnings = vec![];
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    35
    if !repo.requirements().contains(NARROW_REQUIREMENT) {
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    36
        return Ok((Box::new(AlwaysMatcher), warnings));
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    37
    }
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    38
    // Treat "narrowspec does not exist" the same as "narrowspec file exists
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    39
    // and is empty".
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49915
diff changeset
    40
    let store_spec = repo.store_vfs().try_read(FILENAME)?.unwrap_or_default();
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49915
diff changeset
    41
    let working_copy_spec = repo
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49915
diff changeset
    42
        .hg_vfs()
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49915
diff changeset
    43
        .try_read(DIRSTATE_FILENAME)?
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49915
diff changeset
    44
        .unwrap_or_default();
49488
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    45
    if store_spec != working_copy_spec {
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    46
        return Err(HgError::abort(
49982
7faedeb24eb2 rhg: fix user-facing error message so it matches Python implementation
Raphaël Gomès <rgomes@octobus.net>
parents: 49930
diff changeset
    47
            "abort: working copy's narrowspec is stale",
49488
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    48
            exit_codes::STATE_ERROR,
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    49
            Some("run 'hg tracked --update-working-copy'".into()),
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    50
        )
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    51
        .into());
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    52
    }
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    53
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    54
    let config = sparse::parse_config(
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    55
        &store_spec,
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    56
        sparse::SparseConfigContext::Narrow,
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    57
    )?;
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    58
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    59
    warnings.extend(config.warnings);
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    60
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    61
    if !config.profiles.is_empty() {
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    62
        // TODO (from Python impl) maybe do something with profiles?
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    63
        return Err(SparseConfigError::IncludesInNarrow);
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    64
    }
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    65
    validate_patterns(&config.includes)?;
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    66
    validate_patterns(&config.excludes)?;
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    67
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    68
    if config.includes.is_empty() {
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    69
        return Ok((Box::new(NeverMatcher), warnings));
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    70
    }
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    71
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    72
    let (patterns, subwarnings) = parse_pattern_file_contents(
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    73
        &config.includes,
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    74
        Path::new(""),
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    75
        None,
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    76
        false,
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    77
    )?;
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    78
    warnings.extend(subwarnings.into_iter().map(From::from));
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    79
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    80
    let mut m: Box<dyn Matcher + Sync> =
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    81
        Box::new(IncludeMatcher::new(patterns)?);
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    82
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    83
    let (patterns, subwarnings) = parse_pattern_file_contents(
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    84
        &config.excludes,
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    85
        Path::new(""),
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    86
        None,
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    87
        false,
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    88
    )?;
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    89
    if !patterns.is_empty() {
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    90
        warnings.extend(subwarnings.into_iter().map(From::from));
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    91
        let exclude_matcher = Box::new(IncludeMatcher::new(patterns)?);
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    92
        m = Box::new(DifferenceMatcher::new(m, exclude_matcher));
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    93
    }
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    94
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    95
    Ok((m, warnings))
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    96
}
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    97
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    98
fn validate_patterns(patterns: &[u8]) -> Result<(), SparseConfigError> {
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    99
    for pattern in patterns.split(|c| *c == b'\n') {
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   100
        if pattern.is_empty() {
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   101
            continue;
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   102
        }
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   103
        for prefix in VALID_PREFIXES.iter() {
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   104
            if pattern.starts_with(prefix.as_bytes()) {
49915
c8ef85ace216 rust-narrow: fix loop that never loops
Raphaël Gomès <rgomes@octobus.net>
parents: 49488
diff changeset
   105
                return Ok(());
49488
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   106
            }
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   107
        }
49915
c8ef85ace216 rust-narrow: fix loop that never loops
Raphaël Gomès <rgomes@octobus.net>
parents: 49488
diff changeset
   108
        return Err(SparseConfigError::InvalidNarrowPrefix(
c8ef85ace216 rust-narrow: fix loop that never loops
Raphaël Gomès <rgomes@octobus.net>
parents: 49488
diff changeset
   109
            pattern.to_owned(),
c8ef85ace216 rust-narrow: fix loop that never loops
Raphaël Gomès <rgomes@octobus.net>
parents: 49488
diff changeset
   110
        ));
49488
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   111
    }
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   112
    Ok(())
7c93e38a0bbd rhg-status: add support for narrow clones
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   113
}