Mercurial > hg
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 } |