rust/hg-core/src/requirements.rs
author Simon Sapin <simon-commits@exyr.org>
Tue, 24 Nov 2020 18:52:38 +0100
changeset 45937 2ad2745e0be9
parent 45924 a2eda1ff22aa
child 45938 f5d62f4d5327
permissions -rw-r--r--
rhg: exit with relevant code for unsupported requirements Differential Revision: https://phab.mercurial-scm.org/D9399
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
45924
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
     1
use std::io;
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
     2
use std::path::Path;
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
     3
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
     4
#[derive(Debug)]
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
     5
pub enum RequirementsError {
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
     6
    // TODO: include a path?
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
     7
    Io(io::Error),
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
     8
    /// The `requires` file is corrupted
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
     9
    Corrupted,
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    10
    /// The repository requires a feature that we don�t support
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    11
    Unsupported {
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    12
        feature: String,
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    13
    },
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    14
}
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    15
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    16
fn parse(bytes: &[u8]) -> Result<Vec<String>, ()> {
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    17
    // The Python code reading this file uses `str.splitlines`
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    18
    // which looks for a number of line separators (even including a couple of
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    19
    // non-ASCII ones), but Python code writing it always uses `\n`.
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    20
    let lines = bytes.split(|&byte| byte == b'\n');
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    21
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    22
    lines
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    23
        .filter(|line| !line.is_empty())
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    24
        .map(|line| {
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    25
            // Python uses Unicode `str.isalnum` but feature names are all
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    26
            // ASCII
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    27
            if line[0].is_ascii_alphanumeric() {
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    28
                Ok(String::from_utf8(line.into()).unwrap())
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    29
            } else {
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    30
                Err(())
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    31
            }
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    32
        })
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    33
        .collect()
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    34
}
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    35
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    36
pub fn load(repo_root: &Path) -> Result<Vec<String>, RequirementsError> {
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    37
    match std::fs::read(repo_root.join(".hg").join("requires")) {
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    38
        Ok(bytes) => parse(&bytes).map_err(|()| RequirementsError::Corrupted),
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    39
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    40
        // Treat a missing file the same as an empty file.
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    41
        // From `mercurial/localrepo.py`:
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    42
        // > requires file contains a newline-delimited list of
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    43
        // > features/capabilities the opener (us) must have in order to use
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    44
        // > the repository. This file was introduced in Mercurial 0.9.2,
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    45
        // > which means very old repositories may not have one. We assume
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    46
        // > a missing file translates to no requirements.
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    47
        Err(error) if error.kind() == std::io::ErrorKind::NotFound => {
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    48
            Ok(Vec::new())
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    49
        }
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    50
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    51
        Err(error) => Err(RequirementsError::Io(error))?,
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    52
    }
a2eda1ff22aa requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
    53
}
45937
2ad2745e0be9 rhg: exit with relevant code for unsupported requirements
Simon Sapin <simon-commits@exyr.org>
parents: 45924
diff changeset
    54
2ad2745e0be9 rhg: exit with relevant code for unsupported requirements
Simon Sapin <simon-commits@exyr.org>
parents: 45924
diff changeset
    55
pub fn check(repo_root: &Path) -> Result<(), RequirementsError> {
2ad2745e0be9 rhg: exit with relevant code for unsupported requirements
Simon Sapin <simon-commits@exyr.org>
parents: 45924
diff changeset
    56
    for feature in load(repo_root)? {
2ad2745e0be9 rhg: exit with relevant code for unsupported requirements
Simon Sapin <simon-commits@exyr.org>
parents: 45924
diff changeset
    57
        if !SUPPORTED.contains(&&*feature) {
2ad2745e0be9 rhg: exit with relevant code for unsupported requirements
Simon Sapin <simon-commits@exyr.org>
parents: 45924
diff changeset
    58
            return Err(RequirementsError::Unsupported { feature })
2ad2745e0be9 rhg: exit with relevant code for unsupported requirements
Simon Sapin <simon-commits@exyr.org>
parents: 45924
diff changeset
    59
        }
2ad2745e0be9 rhg: exit with relevant code for unsupported requirements
Simon Sapin <simon-commits@exyr.org>
parents: 45924
diff changeset
    60
    }
2ad2745e0be9 rhg: exit with relevant code for unsupported requirements
Simon Sapin <simon-commits@exyr.org>
parents: 45924
diff changeset
    61
    Ok(())
2ad2745e0be9 rhg: exit with relevant code for unsupported requirements
Simon Sapin <simon-commits@exyr.org>
parents: 45924
diff changeset
    62
}
2ad2745e0be9 rhg: exit with relevant code for unsupported requirements
Simon Sapin <simon-commits@exyr.org>
parents: 45924
diff changeset
    63
2ad2745e0be9 rhg: exit with relevant code for unsupported requirements
Simon Sapin <simon-commits@exyr.org>
parents: 45924
diff changeset
    64
// TODO: set this to actually-supported features
2ad2745e0be9 rhg: exit with relevant code for unsupported requirements
Simon Sapin <simon-commits@exyr.org>
parents: 45924
diff changeset
    65
const SUPPORTED: &[&str] = &[
2ad2745e0be9 rhg: exit with relevant code for unsupported requirements
Simon Sapin <simon-commits@exyr.org>
parents: 45924
diff changeset
    66
    "dotencode",
2ad2745e0be9 rhg: exit with relevant code for unsupported requirements
Simon Sapin <simon-commits@exyr.org>
parents: 45924
diff changeset
    67
    "fncache",
2ad2745e0be9 rhg: exit with relevant code for unsupported requirements
Simon Sapin <simon-commits@exyr.org>
parents: 45924
diff changeset
    68
    "generaldelta",
2ad2745e0be9 rhg: exit with relevant code for unsupported requirements
Simon Sapin <simon-commits@exyr.org>
parents: 45924
diff changeset
    69
    "revlogv1",
2ad2745e0be9 rhg: exit with relevant code for unsupported requirements
Simon Sapin <simon-commits@exyr.org>
parents: 45924
diff changeset
    70
    "sparserevlog",
2ad2745e0be9 rhg: exit with relevant code for unsupported requirements
Simon Sapin <simon-commits@exyr.org>
parents: 45924
diff changeset
    71
    "store",
2ad2745e0be9 rhg: exit with relevant code for unsupported requirements
Simon Sapin <simon-commits@exyr.org>
parents: 45924
diff changeset
    72
];