author | Simon Sapin <simon.sapin@octobus.net> |
Mon, 01 Feb 2021 13:32:00 +0100 | |
changeset 46541 | 39128182f04e |
parent 46540 | 0d734c0ae1cf |
child 46542 | 2845892dd489 |
permissions | -rw-r--r-- |
46187
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
1 |
// layer.rs |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
2 |
// |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
3 |
// Copyright 2020 |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
4 |
// Valentin Gatien-Baron, |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
5 |
// Raphaël Gomès <rgomes@octobus.net> |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
6 |
// |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
7 |
// This software may be used and distributed according to the terms of the |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
8 |
// GNU General Public License version 2 or any later version. |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
9 |
|
46515
0cb1b02228a6
rust: use HgError in ConfigError
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
10 |
use crate::errors::{HgError, IoResultExt}; |
46540
0d734c0ae1cf
rust: replace read_whole_file with std::fs::read
Simon Sapin <simon.sapin@octobus.net>
parents:
46515
diff
changeset
|
11 |
use crate::utils::files::{get_bytes_from_path, get_path_from_bytes}; |
46187
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
12 |
use format_bytes::format_bytes; |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
13 |
use lazy_static::lazy_static; |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
14 |
use regex::bytes::Regex; |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
15 |
use std::collections::HashMap; |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
16 |
use std::path::{Path, PathBuf}; |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
17 |
|
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
18 |
lazy_static! { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
19 |
static ref SECTION_RE: Regex = make_regex(r"^\[([^\[]+)\]"); |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
20 |
static ref ITEM_RE: Regex = make_regex(r"^([^=\s][^=]*?)\s*=\s*((.*\S)?)"); |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
21 |
/// Continuation whitespace |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
22 |
static ref CONT_RE: Regex = make_regex(r"^\s+(\S|\S.*\S)\s*$"); |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
23 |
static ref EMPTY_RE: Regex = make_regex(r"^(;|#|\s*$)"); |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
24 |
static ref COMMENT_RE: Regex = make_regex(r"^(;|#)"); |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
25 |
/// A directive that allows for removing previous entries |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
26 |
static ref UNSET_RE: Regex = make_regex(r"^%unset\s+(\S+)"); |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
27 |
/// A directive that allows for including other config files |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
28 |
static ref INCLUDE_RE: Regex = make_regex(r"^%include\s+(\S|\S.*\S)\s*$"); |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
29 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
30 |
|
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
31 |
/// All config values separated by layers of precedence. |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
32 |
/// Each config source may be split in multiple layers if `%include` directives |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
33 |
/// are used. |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
34 |
/// TODO detail the general precedence |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
35 |
#[derive(Clone)] |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
36 |
pub struct ConfigLayer { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
37 |
/// Mapping of the sections to their items |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
38 |
sections: HashMap<Vec<u8>, ConfigItem>, |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
39 |
/// All sections (and their items/values) in a layer share the same origin |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
40 |
pub origin: ConfigOrigin, |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
41 |
/// Whether this layer comes from a trusted user or group |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
42 |
pub trusted: bool, |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
43 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
44 |
|
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
45 |
impl ConfigLayer { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
46 |
pub fn new(origin: ConfigOrigin) -> Self { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
47 |
ConfigLayer { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
48 |
sections: HashMap::new(), |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
49 |
trusted: true, // TODO check |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
50 |
origin, |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
51 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
52 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
53 |
|
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
54 |
/// Add an entry to the config, overwriting the old one if already present. |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
55 |
pub fn add( |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
56 |
&mut self, |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
57 |
section: Vec<u8>, |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
58 |
item: Vec<u8>, |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
59 |
value: Vec<u8>, |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
60 |
line: Option<usize>, |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
61 |
) { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
62 |
self.sections |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
63 |
.entry(section) |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
64 |
.or_insert_with(|| HashMap::new()) |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
65 |
.insert(item, ConfigValue { bytes: value, line }); |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
66 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
67 |
|
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
68 |
/// Returns the config value in `<section>.<item>` if it exists |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
69 |
pub fn get(&self, section: &[u8], item: &[u8]) -> Option<&ConfigValue> { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
70 |
Some(self.sections.get(section)?.get(item)?) |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
71 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
72 |
|
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
73 |
pub fn is_empty(&self) -> bool { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
74 |
self.sections.is_empty() |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
75 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
76 |
|
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
77 |
/// Returns a `Vec` of layers in order of precedence (so, in read order), |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
78 |
/// recursively parsing the `%include` directives if any. |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
79 |
pub fn parse(src: &Path, data: &[u8]) -> Result<Vec<Self>, ConfigError> { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
80 |
let mut layers = vec![]; |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
81 |
|
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
82 |
// Discard byte order mark if any |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
83 |
let data = if data.starts_with(b"\xef\xbb\xbf") { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
84 |
&data[3..] |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
85 |
} else { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
86 |
data |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
87 |
}; |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
88 |
|
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
89 |
// TODO check if it's trusted |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
90 |
let mut current_layer = Self::new(ConfigOrigin::File(src.to_owned())); |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
91 |
|
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
92 |
let mut lines_iter = |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
93 |
data.split(|b| *b == b'\n').enumerate().peekable(); |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
94 |
let mut section = b"".to_vec(); |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
95 |
|
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
96 |
while let Some((index, bytes)) = lines_iter.next() { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
97 |
if let Some(m) = INCLUDE_RE.captures(&bytes) { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
98 |
let filename_bytes = &m[1]; |
46541
39128182f04e
rust: Remove unnecessary check for absolute path before joining
Simon Sapin <simon.sapin@octobus.net>
parents:
46540
diff
changeset
|
99 |
// `Path::parent` only fails for the root directory, |
39128182f04e
rust: Remove unnecessary check for absolute path before joining
Simon Sapin <simon.sapin@octobus.net>
parents:
46540
diff
changeset
|
100 |
// which `src` can’t be since we’ve managed to open it as a file. |
39128182f04e
rust: Remove unnecessary check for absolute path before joining
Simon Sapin <simon.sapin@octobus.net>
parents:
46540
diff
changeset
|
101 |
let dir = src |
39128182f04e
rust: Remove unnecessary check for absolute path before joining
Simon Sapin <simon.sapin@octobus.net>
parents:
46540
diff
changeset
|
102 |
.parent() |
39128182f04e
rust: Remove unnecessary check for absolute path before joining
Simon Sapin <simon.sapin@octobus.net>
parents:
46540
diff
changeset
|
103 |
.expect("Path::parent fail on a file we’ve read"); |
39128182f04e
rust: Remove unnecessary check for absolute path before joining
Simon Sapin <simon.sapin@octobus.net>
parents:
46540
diff
changeset
|
104 |
// `Path::join` with an absolute argument correctly ignores the base path |
39128182f04e
rust: Remove unnecessary check for absolute path before joining
Simon Sapin <simon.sapin@octobus.net>
parents:
46540
diff
changeset
|
105 |
let filename = dir.join(&get_path_from_bytes(&filename_bytes)); |
39128182f04e
rust: Remove unnecessary check for absolute path before joining
Simon Sapin <simon.sapin@octobus.net>
parents:
46540
diff
changeset
|
106 |
let data = std::fs::read(&filename).for_file(&filename)?; |
46515
0cb1b02228a6
rust: use HgError in ConfigError
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
107 |
layers.push(current_layer); |
46541
39128182f04e
rust: Remove unnecessary check for absolute path before joining
Simon Sapin <simon.sapin@octobus.net>
parents:
46540
diff
changeset
|
108 |
layers.extend(Self::parse(&filename, &data)?); |
46515
0cb1b02228a6
rust: use HgError in ConfigError
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
109 |
current_layer = Self::new(ConfigOrigin::File(src.to_owned())); |
46187
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
110 |
} else if let Some(_) = EMPTY_RE.captures(&bytes) { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
111 |
} else if let Some(m) = SECTION_RE.captures(&bytes) { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
112 |
section = m[1].to_vec(); |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
113 |
} else if let Some(m) = ITEM_RE.captures(&bytes) { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
114 |
let item = m[1].to_vec(); |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
115 |
let mut value = m[2].to_vec(); |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
116 |
loop { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
117 |
match lines_iter.peek() { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
118 |
None => break, |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
119 |
Some((_, v)) => { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
120 |
if let Some(_) = COMMENT_RE.captures(&v) { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
121 |
} else if let Some(_) = CONT_RE.captures(&v) { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
122 |
value.extend(b"\n"); |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
123 |
value.extend(&m[1]); |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
124 |
} else { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
125 |
break; |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
126 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
127 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
128 |
}; |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
129 |
lines_iter.next(); |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
130 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
131 |
current_layer.add( |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
132 |
section.clone(), |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
133 |
item, |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
134 |
value, |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
135 |
Some(index + 1), |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
136 |
); |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
137 |
} else if let Some(m) = UNSET_RE.captures(&bytes) { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
138 |
if let Some(map) = current_layer.sections.get_mut(§ion) { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
139 |
map.remove(&m[1]); |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
140 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
141 |
} else { |
46515
0cb1b02228a6
rust: use HgError in ConfigError
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
142 |
return Err(ConfigParseError { |
46187
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
143 |
origin: ConfigOrigin::File(src.to_owned()), |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
144 |
line: Some(index + 1), |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
145 |
bytes: bytes.to_owned(), |
46515
0cb1b02228a6
rust: use HgError in ConfigError
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
146 |
} |
0cb1b02228a6
rust: use HgError in ConfigError
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
147 |
.into()); |
46187
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
148 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
149 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
150 |
if !current_layer.is_empty() { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
151 |
layers.push(current_layer); |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
152 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
153 |
Ok(layers) |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
154 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
155 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
156 |
|
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
157 |
impl std::fmt::Debug for ConfigLayer { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
158 |
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
159 |
let mut sections: Vec<_> = self.sections.iter().collect(); |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
160 |
sections.sort_by(|e0, e1| e0.0.cmp(e1.0)); |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
161 |
|
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
162 |
for (section, items) in sections.into_iter() { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
163 |
let mut items: Vec<_> = items.into_iter().collect(); |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
164 |
items.sort_by(|e0, e1| e0.0.cmp(e1.0)); |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
165 |
|
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
166 |
for (item, config_entry) in items { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
167 |
writeln!( |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
168 |
f, |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
169 |
"{}", |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
170 |
String::from_utf8_lossy(&format_bytes!( |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
171 |
b"{}.{}={} # {}", |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
172 |
section, |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
173 |
item, |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
174 |
&config_entry.bytes, |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
175 |
&self.origin.to_bytes(), |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
176 |
)) |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
177 |
)? |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
178 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
179 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
180 |
Ok(()) |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
181 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
182 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
183 |
|
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
184 |
/// Mapping of section item to value. |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
185 |
/// In the following: |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
186 |
/// ```text |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
187 |
/// [ui] |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
188 |
/// paginate=no |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
189 |
/// ``` |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
190 |
/// "paginate" is the section item and "no" the value. |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
191 |
pub type ConfigItem = HashMap<Vec<u8>, ConfigValue>; |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
192 |
|
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
193 |
#[derive(Clone, Debug, PartialEq)] |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
194 |
pub struct ConfigValue { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
195 |
/// The raw bytes of the value (be it from the CLI, env or from a file) |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
196 |
pub bytes: Vec<u8>, |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
197 |
/// Only present if the value comes from a file, 1-indexed. |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
198 |
pub line: Option<usize>, |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
199 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
200 |
|
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
201 |
#[derive(Clone, Debug)] |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
202 |
pub enum ConfigOrigin { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
203 |
/// The value comes from a configuration file |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
204 |
File(PathBuf), |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
205 |
/// The value comes from the environment like `$PAGER` or `$EDITOR` |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
206 |
Environment(Vec<u8>), |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
207 |
/* TODO cli |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
208 |
* TODO defaults (configitems.py) |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
209 |
* TODO extensions |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
210 |
* TODO Python resources? |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
211 |
* Others? */ |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
212 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
213 |
|
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
214 |
impl ConfigOrigin { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
215 |
/// TODO use some kind of dedicated trait? |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
216 |
pub fn to_bytes(&self) -> Vec<u8> { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
217 |
match self { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
218 |
ConfigOrigin::File(p) => get_bytes_from_path(p), |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
219 |
ConfigOrigin::Environment(e) => e.to_owned(), |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
220 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
221 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
222 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
223 |
|
46515
0cb1b02228a6
rust: use HgError in ConfigError
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
224 |
#[derive(Debug)] |
0cb1b02228a6
rust: use HgError in ConfigError
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
225 |
pub struct ConfigParseError { |
0cb1b02228a6
rust: use HgError in ConfigError
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
226 |
pub origin: ConfigOrigin, |
0cb1b02228a6
rust: use HgError in ConfigError
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
227 |
pub line: Option<usize>, |
0cb1b02228a6
rust: use HgError in ConfigError
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
228 |
pub bytes: Vec<u8>, |
0cb1b02228a6
rust: use HgError in ConfigError
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
229 |
} |
0cb1b02228a6
rust: use HgError in ConfigError
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
230 |
|
46503
2e2033081274
rust: replace trivial `impl From …` with `#[derive(derive_more::From)]`
Simon Sapin <simon.sapin@octobus.net>
parents:
46187
diff
changeset
|
231 |
#[derive(Debug, derive_more::From)] |
46187
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
232 |
pub enum ConfigError { |
46515
0cb1b02228a6
rust: use HgError in ConfigError
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
233 |
Parse(ConfigParseError), |
0cb1b02228a6
rust: use HgError in ConfigError
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
234 |
Other(HgError), |
46187
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
235 |
} |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
236 |
|
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
237 |
fn make_regex(pattern: &'static str) -> Regex { |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
238 |
Regex::new(pattern).expect("expected a valid regex") |
95d6f31e88db
hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
239 |
} |