comparison rust/hg-core/src/requirements.rs @ 45924:a2eda1ff22aa

requirements: move loading to hg-core and add parsing No functional change, checking comes later. Differential Revision: https://phab.mercurial-scm.org/D9398
author Simon Sapin <simon-commits@exyr.org>
date Tue, 24 Nov 2020 17:49:16 +0100
parents
children 2ad2745e0be9
comparison
equal deleted inserted replaced
45923:ead435aa5294 45924:a2eda1ff22aa
1 use std::io;
2 use std::path::Path;
3
4 #[derive(Debug)]
5 pub enum RequirementsError {
6 // TODO: include a path?
7 Io(io::Error),
8 /// The `requires` file is corrupted
9 Corrupted,
10 /// The repository requires a feature that we don’t support
11 Unsupported {
12 feature: String,
13 },
14 }
15
16 fn parse(bytes: &[u8]) -> Result<Vec<String>, ()> {
17 // The Python code reading this file uses `str.splitlines`
18 // which looks for a number of line separators (even including a couple of
19 // non-ASCII ones), but Python code writing it always uses `\n`.
20 let lines = bytes.split(|&byte| byte == b'\n');
21
22 lines
23 .filter(|line| !line.is_empty())
24 .map(|line| {
25 // Python uses Unicode `str.isalnum` but feature names are all
26 // ASCII
27 if line[0].is_ascii_alphanumeric() {
28 Ok(String::from_utf8(line.into()).unwrap())
29 } else {
30 Err(())
31 }
32 })
33 .collect()
34 }
35
36 pub fn load(repo_root: &Path) -> Result<Vec<String>, RequirementsError> {
37 match std::fs::read(repo_root.join(".hg").join("requires")) {
38 Ok(bytes) => parse(&bytes).map_err(|()| RequirementsError::Corrupted),
39
40 // Treat a missing file the same as an empty file.
41 // From `mercurial/localrepo.py`:
42 // > requires file contains a newline-delimited list of
43 // > features/capabilities the opener (us) must have in order to use
44 // > the repository. This file was introduced in Mercurial 0.9.2,
45 // > which means very old repositories may not have one. We assume
46 // > a missing file translates to no requirements.
47 Err(error) if error.kind() == std::io::ErrorKind::NotFound => {
48 Ok(Vec::new())
49 }
50
51 Err(error) => Err(RequirementsError::Io(error))?,
52 }
53 }