Show More
This diff has been collapsed as it changes many lines, (669 lines changed) Show them Hide them | |||||
@@ -0,0 +1,669 b'' | |||||
|
1 | //! Code for parsing default Mercurial config items. | |||
|
2 | use itertools::Itertools; | |||
|
3 | use serde::Deserialize; | |||
|
4 | ||||
|
5 | use crate::{errors::HgError, exit_codes, FastHashMap}; | |||
|
6 | ||||
|
7 | /// Corresponds to the structure of `mercurial/configitems.toml`. | |||
|
8 | #[derive(Debug, Deserialize)] | |||
|
9 | pub struct ConfigItems { | |||
|
10 | items: Vec<DefaultConfigItem>, | |||
|
11 | templates: FastHashMap<String, Vec<TemplateItem>>, | |||
|
12 | #[serde(rename = "template-applications")] | |||
|
13 | template_applications: Vec<TemplateApplication>, | |||
|
14 | } | |||
|
15 | ||||
|
16 | /// Corresponds to a config item declaration in `mercurial/configitems.toml`. | |||
|
17 | #[derive(Clone, Debug, PartialEq, Deserialize)] | |||
|
18 | #[serde(try_from = "RawDefaultConfigItem")] | |||
|
19 | pub struct DefaultConfigItem { | |||
|
20 | /// Section of the config the item is in (e.g. `[merge-tools]`) | |||
|
21 | section: String, | |||
|
22 | /// Name of the item (e.g. `meld.gui`) | |||
|
23 | name: String, | |||
|
24 | /// Default value (can be dynamic, see [`DefaultConfigItemType`]) | |||
|
25 | default: Option<DefaultConfigItemType>, | |||
|
26 | /// If the config option is generic (e.g. `merge-tools.*`), defines | |||
|
27 | /// the priority of this item relative to other generic items. | |||
|
28 | /// If we're looking for <pattern>, then all generic items within the same | |||
|
29 | /// section will be sorted by order of priority, and the first regex match | |||
|
30 | /// against `name` is returned. | |||
|
31 | #[serde(default)] | |||
|
32 | priority: Option<isize>, | |||
|
33 | /// Aliases, if any. Each alias is a tuple of `(section, name)` for each | |||
|
34 | /// option that is aliased to this one. | |||
|
35 | #[serde(default)] | |||
|
36 | alias: Vec<(String, String)>, | |||
|
37 | /// Whether the config item is marked as experimental | |||
|
38 | #[serde(default)] | |||
|
39 | experimental: bool, | |||
|
40 | /// The (possibly empty) docstring for the item | |||
|
41 | #[serde(default)] | |||
|
42 | documentation: String, | |||
|
43 | } | |||
|
44 | ||||
|
45 | /// Corresponds to the raw (i.e. on disk) structure of config items. Used as | |||
|
46 | /// an intermediate step in deserialization. | |||
|
47 | #[derive(Clone, Debug, Deserialize)] | |||
|
48 | struct RawDefaultConfigItem { | |||
|
49 | section: String, | |||
|
50 | name: String, | |||
|
51 | default: Option<toml::Value>, | |||
|
52 | #[serde(rename = "default-type")] | |||
|
53 | default_type: Option<String>, | |||
|
54 | #[serde(default)] | |||
|
55 | priority: isize, | |||
|
56 | #[serde(default)] | |||
|
57 | generic: bool, | |||
|
58 | #[serde(default)] | |||
|
59 | alias: Vec<(String, String)>, | |||
|
60 | #[serde(default)] | |||
|
61 | experimental: bool, | |||
|
62 | #[serde(default)] | |||
|
63 | documentation: String, | |||
|
64 | } | |||
|
65 | ||||
|
66 | impl TryFrom<RawDefaultConfigItem> for DefaultConfigItem { | |||
|
67 | type Error = HgError; | |||
|
68 | ||||
|
69 | fn try_from(value: RawDefaultConfigItem) -> Result<Self, Self::Error> { | |||
|
70 | Ok(Self { | |||
|
71 | section: value.section, | |||
|
72 | name: value.name, | |||
|
73 | default: raw_default_to_concrete( | |||
|
74 | value.default_type, | |||
|
75 | value.default, | |||
|
76 | )?, | |||
|
77 | priority: if value.generic { | |||
|
78 | Some(value.priority) | |||
|
79 | } else { | |||
|
80 | None | |||
|
81 | }, | |||
|
82 | alias: value.alias, | |||
|
83 | experimental: value.experimental, | |||
|
84 | documentation: value.documentation, | |||
|
85 | }) | |||
|
86 | } | |||
|
87 | } | |||
|
88 | ||||
|
89 | impl DefaultConfigItem { | |||
|
90 | fn is_generic(&self) -> bool { | |||
|
91 | self.priority.is_some() | |||
|
92 | } | |||
|
93 | } | |||
|
94 | ||||
|
95 | impl<'a> TryFrom<&'a DefaultConfigItem> for Option<&'a str> { | |||
|
96 | type Error = HgError; | |||
|
97 | ||||
|
98 | fn try_from( | |||
|
99 | value: &'a DefaultConfigItem, | |||
|
100 | ) -> Result<Option<&'a str>, Self::Error> { | |||
|
101 | match &value.default { | |||
|
102 | Some(default) => { | |||
|
103 | let err = HgError::abort( | |||
|
104 | format!( | |||
|
105 | "programming error: wrong query on config item '{}.{}'", | |||
|
106 | value.section, | |||
|
107 | value.name | |||
|
108 | ), | |||
|
109 | exit_codes::ABORT, | |||
|
110 | Some(format!( | |||
|
111 | "asked for '&str', type of default is '{}'", | |||
|
112 | default.type_str() | |||
|
113 | )), | |||
|
114 | ); | |||
|
115 | match default { | |||
|
116 | DefaultConfigItemType::Primitive(toml::Value::String( | |||
|
117 | s, | |||
|
118 | )) => Ok(Some(s)), | |||
|
119 | _ => Err(err), | |||
|
120 | } | |||
|
121 | } | |||
|
122 | None => Ok(None), | |||
|
123 | } | |||
|
124 | } | |||
|
125 | } | |||
|
126 | ||||
|
127 | impl TryFrom<&DefaultConfigItem> for Option<bool> { | |||
|
128 | type Error = HgError; | |||
|
129 | ||||
|
130 | fn try_from(value: &DefaultConfigItem) -> Result<Self, Self::Error> { | |||
|
131 | match &value.default { | |||
|
132 | Some(default) => { | |||
|
133 | let err = HgError::abort( | |||
|
134 | format!( | |||
|
135 | "programming error: wrong query on config item '{}.{}'", | |||
|
136 | value.section, | |||
|
137 | value.name | |||
|
138 | ), | |||
|
139 | exit_codes::ABORT, | |||
|
140 | Some(format!( | |||
|
141 | "asked for 'bool', type of default is '{}'", | |||
|
142 | default.type_str() | |||
|
143 | )), | |||
|
144 | ); | |||
|
145 | match default { | |||
|
146 | DefaultConfigItemType::Primitive( | |||
|
147 | toml::Value::Boolean(b), | |||
|
148 | ) => Ok(Some(*b)), | |||
|
149 | _ => Err(err), | |||
|
150 | } | |||
|
151 | } | |||
|
152 | None => Ok(Some(false)), | |||
|
153 | } | |||
|
154 | } | |||
|
155 | } | |||
|
156 | ||||
|
157 | impl TryFrom<&DefaultConfigItem> for Option<u32> { | |||
|
158 | type Error = HgError; | |||
|
159 | ||||
|
160 | fn try_from(value: &DefaultConfigItem) -> Result<Self, Self::Error> { | |||
|
161 | match &value.default { | |||
|
162 | Some(default) => { | |||
|
163 | let err = HgError::abort( | |||
|
164 | format!( | |||
|
165 | "programming error: wrong query on config item '{}.{}'", | |||
|
166 | value.section, | |||
|
167 | value.name | |||
|
168 | ), | |||
|
169 | exit_codes::ABORT, | |||
|
170 | Some(format!( | |||
|
171 | "asked for 'u32', type of default is '{}'", | |||
|
172 | default.type_str() | |||
|
173 | )), | |||
|
174 | ); | |||
|
175 | match default { | |||
|
176 | DefaultConfigItemType::Primitive( | |||
|
177 | toml::Value::Integer(b), | |||
|
178 | ) => { | |||
|
179 | Ok(Some((*b).try_into().expect("TOML integer to u32"))) | |||
|
180 | } | |||
|
181 | _ => Err(err), | |||
|
182 | } | |||
|
183 | } | |||
|
184 | None => Ok(None), | |||
|
185 | } | |||
|
186 | } | |||
|
187 | } | |||
|
188 | ||||
|
189 | impl TryFrom<&DefaultConfigItem> for Option<u64> { | |||
|
190 | type Error = HgError; | |||
|
191 | ||||
|
192 | fn try_from(value: &DefaultConfigItem) -> Result<Self, Self::Error> { | |||
|
193 | match &value.default { | |||
|
194 | Some(default) => { | |||
|
195 | let err = HgError::abort( | |||
|
196 | format!( | |||
|
197 | "programming error: wrong query on config item '{}.{}'", | |||
|
198 | value.section, | |||
|
199 | value.name | |||
|
200 | ), | |||
|
201 | exit_codes::ABORT, | |||
|
202 | Some(format!( | |||
|
203 | "asked for 'u64', type of default is '{}'", | |||
|
204 | default.type_str() | |||
|
205 | )), | |||
|
206 | ); | |||
|
207 | match default { | |||
|
208 | DefaultConfigItemType::Primitive( | |||
|
209 | toml::Value::Integer(b), | |||
|
210 | ) => { | |||
|
211 | Ok(Some((*b).try_into().expect("TOML integer to u64"))) | |||
|
212 | } | |||
|
213 | _ => Err(err), | |||
|
214 | } | |||
|
215 | } | |||
|
216 | None => Ok(None), | |||
|
217 | } | |||
|
218 | } | |||
|
219 | } | |||
|
220 | ||||
|
221 | /// Allows abstracting over more complex default values than just primitives. | |||
|
222 | /// The former `configitems.py` contained some dynamic code that is encoded | |||
|
223 | /// in this enum. | |||
|
224 | #[derive(Debug, PartialEq, Clone, Deserialize)] | |||
|
225 | pub enum DefaultConfigItemType { | |||
|
226 | /// Some primitive type (string, integer, boolean) | |||
|
227 | Primitive(toml::Value), | |||
|
228 | /// A dynamic value that will be given by the code at runtime | |||
|
229 | Dynamic, | |||
|
230 | /// An lazily-returned array (possibly only relevant in the Python impl) | |||
|
231 | /// Example: `lambda: [b"zstd", b"zlib"]` | |||
|
232 | Lambda(Vec<String>), | |||
|
233 | /// For now, a special case for `web.encoding` that points to the | |||
|
234 | /// `encoding.encoding` module in the Python impl so that local encoding | |||
|
235 | /// is correctly resolved at runtime | |||
|
236 | LazyModule(String), | |||
|
237 | ListType, | |||
|
238 | } | |||
|
239 | ||||
|
240 | impl DefaultConfigItemType { | |||
|
241 | pub fn type_str(&self) -> &str { | |||
|
242 | match self { | |||
|
243 | DefaultConfigItemType::Primitive(primitive) => { | |||
|
244 | primitive.type_str() | |||
|
245 | } | |||
|
246 | DefaultConfigItemType::Dynamic => "dynamic", | |||
|
247 | DefaultConfigItemType::Lambda(_) => "lambda", | |||
|
248 | DefaultConfigItemType::LazyModule(_) => "lazy_module", | |||
|
249 | DefaultConfigItemType::ListType => "list_type", | |||
|
250 | } | |||
|
251 | } | |||
|
252 | } | |||
|
253 | ||||
|
254 | /// Most of the fields are shared with [`DefaultConfigItem`]. | |||
|
255 | #[derive(Debug, Clone, Deserialize)] | |||
|
256 | #[serde(try_from = "RawTemplateItem")] | |||
|
257 | struct TemplateItem { | |||
|
258 | suffix: String, | |||
|
259 | default: Option<DefaultConfigItemType>, | |||
|
260 | priority: Option<isize>, | |||
|
261 | #[serde(default)] | |||
|
262 | alias: Vec<(String, String)>, | |||
|
263 | #[serde(default)] | |||
|
264 | experimental: bool, | |||
|
265 | #[serde(default)] | |||
|
266 | documentation: String, | |||
|
267 | } | |||
|
268 | ||||
|
269 | /// Corresponds to the raw (i.e. on disk) representation of a template item. | |||
|
270 | /// Used as an intermediate step in deserialization. | |||
|
271 | #[derive(Clone, Debug, Deserialize)] | |||
|
272 | struct RawTemplateItem { | |||
|
273 | suffix: String, | |||
|
274 | default: Option<toml::Value>, | |||
|
275 | #[serde(rename = "default-type")] | |||
|
276 | default_type: Option<String>, | |||
|
277 | #[serde(default)] | |||
|
278 | priority: isize, | |||
|
279 | #[serde(default)] | |||
|
280 | generic: bool, | |||
|
281 | #[serde(default)] | |||
|
282 | alias: Vec<(String, String)>, | |||
|
283 | #[serde(default)] | |||
|
284 | experimental: bool, | |||
|
285 | #[serde(default)] | |||
|
286 | documentation: String, | |||
|
287 | } | |||
|
288 | ||||
|
289 | impl TemplateItem { | |||
|
290 | fn into_default_item( | |||
|
291 | self, | |||
|
292 | application: TemplateApplication, | |||
|
293 | ) -> DefaultConfigItem { | |||
|
294 | DefaultConfigItem { | |||
|
295 | section: application.section, | |||
|
296 | name: application | |||
|
297 | .prefix | |||
|
298 | .map(|prefix| format!("{}.{}", prefix, self.suffix)) | |||
|
299 | .unwrap_or(self.suffix), | |||
|
300 | default: self.default, | |||
|
301 | priority: self.priority, | |||
|
302 | alias: self.alias, | |||
|
303 | experimental: self.experimental, | |||
|
304 | documentation: self.documentation, | |||
|
305 | } | |||
|
306 | } | |||
|
307 | } | |||
|
308 | ||||
|
309 | impl TryFrom<RawTemplateItem> for TemplateItem { | |||
|
310 | type Error = HgError; | |||
|
311 | ||||
|
312 | fn try_from(value: RawTemplateItem) -> Result<Self, Self::Error> { | |||
|
313 | Ok(Self { | |||
|
314 | suffix: value.suffix, | |||
|
315 | default: raw_default_to_concrete( | |||
|
316 | value.default_type, | |||
|
317 | value.default, | |||
|
318 | )?, | |||
|
319 | priority: if value.generic { | |||
|
320 | Some(value.priority) | |||
|
321 | } else { | |||
|
322 | None | |||
|
323 | }, | |||
|
324 | alias: value.alias, | |||
|
325 | experimental: value.experimental, | |||
|
326 | documentation: value.documentation, | |||
|
327 | }) | |||
|
328 | } | |||
|
329 | } | |||
|
330 | ||||
|
331 | /// Transforms the on-disk string-based representation of complex default types | |||
|
332 | /// to the concrete [`DefaultconfigItemType`]. | |||
|
333 | fn raw_default_to_concrete( | |||
|
334 | default_type: Option<String>, | |||
|
335 | default: Option<toml::Value>, | |||
|
336 | ) -> Result<Option<DefaultConfigItemType>, HgError> { | |||
|
337 | Ok(match default_type.as_deref() { | |||
|
338 | None => default.as_ref().map(|default| { | |||
|
339 | DefaultConfigItemType::Primitive(default.to_owned()) | |||
|
340 | }), | |||
|
341 | Some("dynamic") => Some(DefaultConfigItemType::Dynamic), | |||
|
342 | Some("list_type") => Some(DefaultConfigItemType::ListType), | |||
|
343 | Some("lambda") => match &default { | |||
|
344 | Some(default) => Some(DefaultConfigItemType::Lambda( | |||
|
345 | default.to_owned().try_into().map_err(|e| { | |||
|
346 | HgError::abort( | |||
|
347 | e.to_string(), | |||
|
348 | exit_codes::ABORT, | |||
|
349 | Some("Check 'mercurial/configitems.toml'".into()), | |||
|
350 | ) | |||
|
351 | })?, | |||
|
352 | )), | |||
|
353 | None => { | |||
|
354 | return Err(HgError::abort( | |||
|
355 | "lambda defined with no return value".to_string(), | |||
|
356 | exit_codes::ABORT, | |||
|
357 | Some("Check 'mercurial/configitems.toml'".into()), | |||
|
358 | )) | |||
|
359 | } | |||
|
360 | }, | |||
|
361 | Some("lazy_module") => match &default { | |||
|
362 | Some(default) => { | |||
|
363 | Some(DefaultConfigItemType::LazyModule(match default { | |||
|
364 | toml::Value::String(module) => module.to_owned(), | |||
|
365 | _ => { | |||
|
366 | return Err(HgError::abort( | |||
|
367 | "lazy_module module name should be a string" | |||
|
368 | .to_string(), | |||
|
369 | exit_codes::ABORT, | |||
|
370 | Some("Check 'mercurial/configitems.toml'".into()), | |||
|
371 | )) | |||
|
372 | } | |||
|
373 | })) | |||
|
374 | } | |||
|
375 | None => { | |||
|
376 | return Err(HgError::abort( | |||
|
377 | "lazy_module should have a default value".to_string(), | |||
|
378 | exit_codes::ABORT, | |||
|
379 | Some("Check 'mercurial/configitems.toml'".into()), | |||
|
380 | )) | |||
|
381 | } | |||
|
382 | }, | |||
|
383 | Some(invalid) => { | |||
|
384 | return Err(HgError::abort( | |||
|
385 | format!("invalid default_type '{}'", invalid), | |||
|
386 | exit_codes::ABORT, | |||
|
387 | Some("Check 'mercurial/configitems.toml'".into()), | |||
|
388 | )) | |||
|
389 | } | |||
|
390 | }) | |||
|
391 | } | |||
|
392 | ||||
|
393 | #[derive(Debug, Clone, Deserialize)] | |||
|
394 | struct TemplateApplication { | |||
|
395 | template: String, | |||
|
396 | section: String, | |||
|
397 | #[serde(default)] | |||
|
398 | prefix: Option<String>, | |||
|
399 | } | |||
|
400 | ||||
|
401 | /// Represents the (dynamic) set of default core Mercurial config items from | |||
|
402 | /// `mercurial/configitems.toml`. | |||
|
403 | #[derive(Clone, Debug, Default)] | |||
|
404 | pub struct DefaultConfig { | |||
|
405 | /// Mapping of section -> (mapping of name -> item) | |||
|
406 | items: FastHashMap<String, FastHashMap<String, DefaultConfigItem>>, | |||
|
407 | } | |||
|
408 | ||||
|
409 | impl DefaultConfig { | |||
|
410 | pub fn empty() -> DefaultConfig { | |||
|
411 | Self { | |||
|
412 | items: Default::default(), | |||
|
413 | } | |||
|
414 | } | |||
|
415 | ||||
|
416 | /// Returns `Self`, given the contents of `mercurial/configitems.toml` | |||
|
417 | #[logging_timer::time("trace")] | |||
|
418 | pub fn from_contents(contents: &str) -> Result<Self, HgError> { | |||
|
419 | let mut from_file: ConfigItems = | |||
|
420 | toml::from_str(contents).map_err(|e| { | |||
|
421 | HgError::abort( | |||
|
422 | e.to_string(), | |||
|
423 | exit_codes::ABORT, | |||
|
424 | Some("Check 'mercurial/configitems.toml'".into()), | |||
|
425 | ) | |||
|
426 | })?; | |||
|
427 | ||||
|
428 | let mut flat_items = from_file.items; | |||
|
429 | ||||
|
430 | for application in from_file.template_applications.drain(..) { | |||
|
431 | match from_file.templates.get(&application.template) { | |||
|
432 | None => return Err( | |||
|
433 | HgError::abort( | |||
|
434 | format!( | |||
|
435 | "template application refers to undefined template '{}'", | |||
|
436 | application.template | |||
|
437 | ), | |||
|
438 | exit_codes::ABORT, | |||
|
439 | Some("Check 'mercurial/configitems.toml'".into()) | |||
|
440 | ) | |||
|
441 | ), | |||
|
442 | Some(template_items) => { | |||
|
443 | for template_item in template_items { | |||
|
444 | flat_items.push( | |||
|
445 | template_item | |||
|
446 | .clone() | |||
|
447 | .into_default_item(application.clone()), | |||
|
448 | ) | |||
|
449 | } | |||
|
450 | } | |||
|
451 | }; | |||
|
452 | } | |||
|
453 | ||||
|
454 | let items = flat_items.into_iter().fold( | |||
|
455 | FastHashMap::default(), | |||
|
456 | |mut acc, item| { | |||
|
457 | acc.entry(item.section.to_owned()) | |||
|
458 | .or_insert_with(|| { | |||
|
459 | let mut section = FastHashMap::default(); | |||
|
460 | section.insert(item.name.to_owned(), item.to_owned()); | |||
|
461 | section | |||
|
462 | }) | |||
|
463 | .insert(item.name.to_owned(), item); | |||
|
464 | acc | |||
|
465 | }, | |||
|
466 | ); | |||
|
467 | ||||
|
468 | Ok(Self { items }) | |||
|
469 | } | |||
|
470 | ||||
|
471 | /// Return the default config item that matches `section` and `item`. | |||
|
472 | pub fn get( | |||
|
473 | &self, | |||
|
474 | section: &[u8], | |||
|
475 | item: &[u8], | |||
|
476 | ) -> Option<&DefaultConfigItem> { | |||
|
477 | // Core items must be valid UTF-8 | |||
|
478 | let section = String::from_utf8_lossy(section); | |||
|
479 | let section_map = self.items.get(section.as_ref())?; | |||
|
480 | let item_name_lossy = String::from_utf8_lossy(item); | |||
|
481 | match section_map.get(item_name_lossy.as_ref()) { | |||
|
482 | Some(item) => Some(item), | |||
|
483 | None => { | |||
|
484 | for generic_item in section_map | |||
|
485 | .values() | |||
|
486 | .filter(|item| item.is_generic()) | |||
|
487 | .sorted_by_key(|item| match item.priority { | |||
|
488 | Some(priority) => (priority, &item.name), | |||
|
489 | _ => unreachable!(), | |||
|
490 | }) | |||
|
491 | { | |||
|
492 | if regex::bytes::Regex::new(&generic_item.name) | |||
|
493 | .expect("invalid regex in configitems") | |||
|
494 | .is_match(item) | |||
|
495 | { | |||
|
496 | return Some(generic_item); | |||
|
497 | } | |||
|
498 | } | |||
|
499 | None | |||
|
500 | } | |||
|
501 | } | |||
|
502 | } | |||
|
503 | } | |||
|
504 | ||||
|
505 | #[cfg(test)] | |||
|
506 | mod tests { | |||
|
507 | use crate::config::config_items::{ | |||
|
508 | DefaultConfigItem, DefaultConfigItemType, | |||
|
509 | }; | |||
|
510 | ||||
|
511 | use super::DefaultConfig; | |||
|
512 | ||||
|
513 | #[test] | |||
|
514 | fn test_config_read() { | |||
|
515 | let contents = r#" | |||
|
516 | [[items]] | |||
|
517 | section = "alias" | |||
|
518 | name = "abcd.*" | |||
|
519 | default = 3 | |||
|
520 | generic = true | |||
|
521 | priority = -1 | |||
|
522 | ||||
|
523 | [[items]] | |||
|
524 | section = "alias" | |||
|
525 | name = ".*" | |||
|
526 | default-type = "dynamic" | |||
|
527 | generic = true | |||
|
528 | ||||
|
529 | [[items]] | |||
|
530 | section = "cmdserver" | |||
|
531 | name = "track-log" | |||
|
532 | default-type = "lambda" | |||
|
533 | default = [ "chgserver", "cmdserver", "repocache",] | |||
|
534 | ||||
|
535 | [[items]] | |||
|
536 | section = "chgserver" | |||
|
537 | name = "idletimeout" | |||
|
538 | default = 3600 | |||
|
539 | ||||
|
540 | [[items]] | |||
|
541 | section = "cmdserver" | |||
|
542 | name = "message-encodings" | |||
|
543 | default-type = "list_type" | |||
|
544 | ||||
|
545 | [[items]] | |||
|
546 | section = "web" | |||
|
547 | name = "encoding" | |||
|
548 | default-type = "lazy_module" | |||
|
549 | default = "encoding.encoding" | |||
|
550 | ||||
|
551 | [[items]] | |||
|
552 | section = "command-templates" | |||
|
553 | name = "graphnode" | |||
|
554 | alias = [["ui", "graphnodetemplate"]] | |||
|
555 | documentation = """This is a docstring. | |||
|
556 | This is another line \ | |||
|
557 | but this is not.""" | |||
|
558 | ||||
|
559 | [[items]] | |||
|
560 | section = "censor" | |||
|
561 | name = "policy" | |||
|
562 | default = "abort" | |||
|
563 | experimental = true | |||
|
564 | ||||
|
565 | [[template-applications]] | |||
|
566 | template = "diff-options" | |||
|
567 | section = "commands" | |||
|
568 | prefix = "revert.interactive" | |||
|
569 | ||||
|
570 | [[template-applications]] | |||
|
571 | template = "diff-options" | |||
|
572 | section = "diff" | |||
|
573 | ||||
|
574 | [templates] | |||
|
575 | [[templates.diff-options]] | |||
|
576 | suffix = "nodates" | |||
|
577 | default = false | |||
|
578 | ||||
|
579 | [[templates.diff-options]] | |||
|
580 | suffix = "showfunc" | |||
|
581 | default = false | |||
|
582 | ||||
|
583 | [[templates.diff-options]] | |||
|
584 | suffix = "unified" | |||
|
585 | "#; | |||
|
586 | let res = DefaultConfig::from_contents(contents); | |||
|
587 | let config = match res { | |||
|
588 | Ok(config) => config, | |||
|
589 | Err(e) => panic!("{}", e), | |||
|
590 | }; | |||
|
591 | let expected = DefaultConfigItem { | |||
|
592 | section: "censor".into(), | |||
|
593 | name: "policy".into(), | |||
|
594 | default: Some(DefaultConfigItemType::Primitive("abort".into())), | |||
|
595 | priority: None, | |||
|
596 | alias: vec![], | |||
|
597 | experimental: true, | |||
|
598 | documentation: "".into(), | |||
|
599 | }; | |||
|
600 | assert_eq!(config.get(b"censor", b"policy"), Some(&expected)); | |||
|
601 | ||||
|
602 | // Test generic priority. The `.*` pattern is wider than `abcd.*`, but | |||
|
603 | // `abcd.*` has priority, so it should match first. | |||
|
604 | let expected = DefaultConfigItem { | |||
|
605 | section: "alias".into(), | |||
|
606 | name: "abcd.*".into(), | |||
|
607 | default: Some(DefaultConfigItemType::Primitive(3.into())), | |||
|
608 | priority: Some(-1), | |||
|
609 | alias: vec![], | |||
|
610 | experimental: false, | |||
|
611 | documentation: "".into(), | |||
|
612 | }; | |||
|
613 | assert_eq!(config.get(b"alias", b"abcdsomething"), Some(&expected)); | |||
|
614 | ||||
|
615 | //... but if it doesn't, we should fallback to `.*` | |||
|
616 | let expected = DefaultConfigItem { | |||
|
617 | section: "alias".into(), | |||
|
618 | name: ".*".into(), | |||
|
619 | default: Some(DefaultConfigItemType::Dynamic), | |||
|
620 | priority: Some(0), | |||
|
621 | alias: vec![], | |||
|
622 | experimental: false, | |||
|
623 | documentation: "".into(), | |||
|
624 | }; | |||
|
625 | assert_eq!(config.get(b"alias", b"something"), Some(&expected)); | |||
|
626 | ||||
|
627 | let expected = DefaultConfigItem { | |||
|
628 | section: "chgserver".into(), | |||
|
629 | name: "idletimeout".into(), | |||
|
630 | default: Some(DefaultConfigItemType::Primitive(3600.into())), | |||
|
631 | priority: None, | |||
|
632 | alias: vec![], | |||
|
633 | experimental: false, | |||
|
634 | documentation: "".into(), | |||
|
635 | }; | |||
|
636 | assert_eq!(config.get(b"chgserver", b"idletimeout"), Some(&expected)); | |||
|
637 | ||||
|
638 | let expected = DefaultConfigItem { | |||
|
639 | section: "cmdserver".into(), | |||
|
640 | name: "track-log".into(), | |||
|
641 | default: Some(DefaultConfigItemType::Lambda(vec![ | |||
|
642 | "chgserver".into(), | |||
|
643 | "cmdserver".into(), | |||
|
644 | "repocache".into(), | |||
|
645 | ])), | |||
|
646 | priority: None, | |||
|
647 | alias: vec![], | |||
|
648 | experimental: false, | |||
|
649 | documentation: "".into(), | |||
|
650 | }; | |||
|
651 | assert_eq!(config.get(b"cmdserver", b"track-log"), Some(&expected)); | |||
|
652 | ||||
|
653 | let expected = DefaultConfigItem { | |||
|
654 | section: "command-templates".into(), | |||
|
655 | name: "graphnode".into(), | |||
|
656 | default: None, | |||
|
657 | priority: None, | |||
|
658 | alias: vec![("ui".into(), "graphnodetemplate".into())], | |||
|
659 | experimental: false, | |||
|
660 | documentation: | |||
|
661 | "This is a docstring.\nThis is another line but this is not." | |||
|
662 | .into(), | |||
|
663 | }; | |||
|
664 | assert_eq!( | |||
|
665 | config.get(b"command-templates", b"graphnode"), | |||
|
666 | Some(&expected) | |||
|
667 | ); | |||
|
668 | } | |||
|
669 | } |
@@ -1,1435 +1,1525 b'' | |||||
1 | # This file is automatically @generated by Cargo. |
|
1 | # This file is automatically @generated by Cargo. | |
2 | # It is not intended for manual editing. |
|
2 | # It is not intended for manual editing. | |
3 | version = 3 |
|
3 | version = 3 | |
4 |
|
4 | |||
5 | [[package]] |
|
5 | [[package]] | |
6 | name = "adler" |
|
6 | name = "adler" | |
7 | version = "1.0.2" |
|
7 | version = "1.0.2" | |
8 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
8 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
9 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" |
|
9 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" | |
10 |
|
10 | |||
11 | [[package]] |
|
11 | [[package]] | |
12 | name = "ahash" |
|
12 | name = "ahash" | |
13 | version = "0.8.2" |
|
13 | version = "0.8.2" | |
14 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
14 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
15 | checksum = "bf6ccdb167abbf410dcb915cabd428929d7f6a04980b54a11f26a39f1c7f7107" |
|
15 | checksum = "bf6ccdb167abbf410dcb915cabd428929d7f6a04980b54a11f26a39f1c7f7107" | |
16 | dependencies = [ |
|
16 | dependencies = [ | |
17 | "cfg-if", |
|
17 | "cfg-if", | |
18 | "once_cell", |
|
18 | "once_cell", | |
19 | "version_check", |
|
19 | "version_check", | |
20 | ] |
|
20 | ] | |
21 |
|
21 | |||
22 | [[package]] |
|
22 | [[package]] | |
23 | name = "aho-corasick" |
|
23 | name = "aho-corasick" | |
24 | version = "0.7.19" |
|
24 | version = "0.7.19" | |
25 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
25 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
26 | checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" |
|
26 | checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" | |
27 | dependencies = [ |
|
27 | dependencies = [ | |
28 | "memchr", |
|
28 | "memchr", | |
29 | ] |
|
29 | ] | |
30 |
|
30 | |||
31 | [[package]] |
|
31 | [[package]] | |
32 | name = "android_system_properties" |
|
32 | name = "android_system_properties" | |
33 | version = "0.1.5" |
|
33 | version = "0.1.5" | |
34 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
34 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
35 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" |
|
35 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" | |
36 | dependencies = [ |
|
36 | dependencies = [ | |
37 | "libc", |
|
37 | "libc", | |
38 | ] |
|
38 | ] | |
39 |
|
39 | |||
40 | [[package]] |
|
40 | [[package]] | |
41 | name = "atty" |
|
41 | name = "atty" | |
42 | version = "0.2.14" |
|
42 | version = "0.2.14" | |
43 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
43 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
44 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" |
|
44 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" | |
45 | dependencies = [ |
|
45 | dependencies = [ | |
46 | "hermit-abi", |
|
46 | "hermit-abi", | |
47 | "libc", |
|
47 | "libc", | |
48 | "winapi", |
|
48 | "winapi", | |
49 | ] |
|
49 | ] | |
50 |
|
50 | |||
51 | [[package]] |
|
51 | [[package]] | |
52 | name = "autocfg" |
|
52 | name = "autocfg" | |
53 | version = "1.1.0" |
|
53 | version = "1.1.0" | |
54 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
54 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
55 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" |
|
55 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" | |
56 |
|
56 | |||
57 | [[package]] |
|
57 | [[package]] | |
58 | name = "bitflags" |
|
58 | name = "bitflags" | |
59 | version = "1.3.2" |
|
59 | version = "1.3.2" | |
60 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
60 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
61 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" |
|
61 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" | |
62 |
|
62 | |||
63 | [[package]] |
|
63 | [[package]] | |
64 | name = "bitmaps" |
|
64 | name = "bitmaps" | |
65 | version = "2.1.0" |
|
65 | version = "2.1.0" | |
66 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
66 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
67 | checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" |
|
67 | checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" | |
68 | dependencies = [ |
|
68 | dependencies = [ | |
69 | "typenum", |
|
69 | "typenum", | |
70 | ] |
|
70 | ] | |
71 |
|
71 | |||
72 | [[package]] |
|
72 | [[package]] | |
73 | name = "block-buffer" |
|
73 | name = "block-buffer" | |
74 | version = "0.9.0" |
|
74 | version = "0.9.0" | |
75 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
75 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
76 | checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" |
|
76 | checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" | |
77 | dependencies = [ |
|
77 | dependencies = [ | |
78 | "generic-array", |
|
78 | "generic-array", | |
79 | ] |
|
79 | ] | |
80 |
|
80 | |||
81 | [[package]] |
|
81 | [[package]] | |
82 | name = "block-buffer" |
|
82 | name = "block-buffer" | |
83 | version = "0.10.3" |
|
83 | version = "0.10.3" | |
84 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
84 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
85 | checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" |
|
85 | checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" | |
86 | dependencies = [ |
|
86 | dependencies = [ | |
87 | "generic-array", |
|
87 | "generic-array", | |
88 | ] |
|
88 | ] | |
89 |
|
89 | |||
90 | [[package]] |
|
90 | [[package]] | |
91 | name = "bumpalo" |
|
91 | name = "bumpalo" | |
92 | version = "3.11.1" |
|
92 | version = "3.11.1" | |
93 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
93 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
94 | checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" |
|
94 | checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" | |
95 |
|
95 | |||
96 | [[package]] |
|
96 | [[package]] | |
97 | name = "byteorder" |
|
97 | name = "byteorder" | |
98 | version = "1.4.3" |
|
98 | version = "1.4.3" | |
99 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
99 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
100 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" |
|
100 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" | |
101 |
|
101 | |||
102 | [[package]] |
|
102 | [[package]] | |
103 | name = "bytes-cast" |
|
103 | name = "bytes-cast" | |
104 | version = "0.3.0" |
|
104 | version = "0.3.0" | |
105 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
105 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
106 | checksum = "a20de93b91d7703ca0e39e12930e310acec5ff4d715f4166e0ab026babb352e8" |
|
106 | checksum = "a20de93b91d7703ca0e39e12930e310acec5ff4d715f4166e0ab026babb352e8" | |
107 | dependencies = [ |
|
107 | dependencies = [ | |
108 | "bytes-cast-derive", |
|
108 | "bytes-cast-derive", | |
109 | ] |
|
109 | ] | |
110 |
|
110 | |||
111 | [[package]] |
|
111 | [[package]] | |
112 | name = "bytes-cast-derive" |
|
112 | name = "bytes-cast-derive" | |
113 | version = "0.2.0" |
|
113 | version = "0.2.0" | |
114 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
114 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
115 | checksum = "7470a6fcce58cde3d62cce758bf71007978b75247e6becd9255c9b884bcb4f71" |
|
115 | checksum = "7470a6fcce58cde3d62cce758bf71007978b75247e6becd9255c9b884bcb4f71" | |
116 | dependencies = [ |
|
116 | dependencies = [ | |
117 | "proc-macro2", |
|
117 | "proc-macro2", | |
118 | "quote", |
|
118 | "quote", | |
119 | "syn", |
|
119 | "syn", | |
120 | ] |
|
120 | ] | |
121 |
|
121 | |||
122 | [[package]] |
|
122 | [[package]] | |
123 | name = "cc" |
|
123 | name = "cc" | |
124 | version = "1.0.76" |
|
124 | version = "1.0.76" | |
125 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
125 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
126 | checksum = "76a284da2e6fe2092f2353e51713435363112dfd60030e22add80be333fb928f" |
|
126 | checksum = "76a284da2e6fe2092f2353e51713435363112dfd60030e22add80be333fb928f" | |
127 | dependencies = [ |
|
127 | dependencies = [ | |
128 | "jobserver", |
|
128 | "jobserver", | |
129 | ] |
|
129 | ] | |
130 |
|
130 | |||
131 | [[package]] |
|
131 | [[package]] | |
132 | name = "cfg-if" |
|
132 | name = "cfg-if" | |
133 | version = "1.0.0" |
|
133 | version = "1.0.0" | |
134 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
134 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
135 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" |
|
135 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | |
136 |
|
136 | |||
137 | [[package]] |
|
137 | [[package]] | |
138 | name = "chrono" |
|
138 | name = "chrono" | |
139 | version = "0.4.23" |
|
139 | version = "0.4.23" | |
140 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
140 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
141 | checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" |
|
141 | checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" | |
142 | dependencies = [ |
|
142 | dependencies = [ | |
143 | "iana-time-zone", |
|
143 | "iana-time-zone", | |
144 | "js-sys", |
|
144 | "js-sys", | |
145 | "num-integer", |
|
145 | "num-integer", | |
146 | "num-traits", |
|
146 | "num-traits", | |
147 | "time", |
|
147 | "time", | |
148 | "wasm-bindgen", |
|
148 | "wasm-bindgen", | |
149 | "winapi", |
|
149 | "winapi", | |
150 | ] |
|
150 | ] | |
151 |
|
151 | |||
152 | [[package]] |
|
152 | [[package]] | |
153 | name = "clap" |
|
153 | name = "clap" | |
154 | version = "4.0.24" |
|
154 | version = "4.0.24" | |
155 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
155 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
156 | checksum = "60494cedb60cb47462c0ff7be53de32c0e42a6fc2c772184554fa12bd9489c03" |
|
156 | checksum = "60494cedb60cb47462c0ff7be53de32c0e42a6fc2c772184554fa12bd9489c03" | |
157 | dependencies = [ |
|
157 | dependencies = [ | |
158 | "atty", |
|
158 | "atty", | |
159 | "bitflags", |
|
159 | "bitflags", | |
160 | "clap_derive", |
|
160 | "clap_derive", | |
161 | "clap_lex", |
|
161 | "clap_lex", | |
162 | "once_cell", |
|
162 | "once_cell", | |
163 | "strsim", |
|
163 | "strsim", | |
164 | "termcolor", |
|
164 | "termcolor", | |
165 | ] |
|
165 | ] | |
166 |
|
166 | |||
167 | [[package]] |
|
167 | [[package]] | |
168 | name = "clap_derive" |
|
168 | name = "clap_derive" | |
169 | version = "4.0.21" |
|
169 | version = "4.0.21" | |
170 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
170 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
171 | checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014" |
|
171 | checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014" | |
172 | dependencies = [ |
|
172 | dependencies = [ | |
173 | "heck", |
|
173 | "heck", | |
174 | "proc-macro-error", |
|
174 | "proc-macro-error", | |
175 | "proc-macro2", |
|
175 | "proc-macro2", | |
176 | "quote", |
|
176 | "quote", | |
177 | "syn", |
|
177 | "syn", | |
178 | ] |
|
178 | ] | |
179 |
|
179 | |||
180 | [[package]] |
|
180 | [[package]] | |
181 | name = "clap_lex" |
|
181 | name = "clap_lex" | |
182 | version = "0.3.0" |
|
182 | version = "0.3.0" | |
183 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
183 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
184 | checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" |
|
184 | checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" | |
185 | dependencies = [ |
|
185 | dependencies = [ | |
186 | "os_str_bytes", |
|
186 | "os_str_bytes", | |
187 | ] |
|
187 | ] | |
188 |
|
188 | |||
189 | [[package]] |
|
189 | [[package]] | |
190 | name = "codespan-reporting" |
|
190 | name = "codespan-reporting" | |
191 | version = "0.11.1" |
|
191 | version = "0.11.1" | |
192 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
192 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
193 | checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" |
|
193 | checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" | |
194 | dependencies = [ |
|
194 | dependencies = [ | |
195 | "termcolor", |
|
195 | "termcolor", | |
196 | "unicode-width", |
|
196 | "unicode-width", | |
197 | ] |
|
197 | ] | |
198 |
|
198 | |||
199 | [[package]] |
|
199 | [[package]] | |
200 | name = "convert_case" |
|
200 | name = "convert_case" | |
201 | version = "0.4.0" |
|
201 | version = "0.4.0" | |
202 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
202 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
203 | checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" |
|
203 | checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" | |
204 |
|
204 | |||
205 | [[package]] |
|
205 | [[package]] | |
206 | name = "core-foundation-sys" |
|
206 | name = "core-foundation-sys" | |
207 | version = "0.8.3" |
|
207 | version = "0.8.3" | |
208 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
208 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
209 | checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" |
|
209 | checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" | |
210 |
|
210 | |||
211 | [[package]] |
|
211 | [[package]] | |
212 | name = "cpufeatures" |
|
212 | name = "cpufeatures" | |
213 | version = "0.2.5" |
|
213 | version = "0.2.5" | |
214 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
214 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
215 | checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" |
|
215 | checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" | |
216 | dependencies = [ |
|
216 | dependencies = [ | |
217 | "libc", |
|
217 | "libc", | |
218 | ] |
|
218 | ] | |
219 |
|
219 | |||
220 | [[package]] |
|
220 | [[package]] | |
221 | name = "cpython" |
|
221 | name = "cpython" | |
222 | version = "0.7.1" |
|
222 | version = "0.7.1" | |
223 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
223 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
224 | checksum = "3052106c29da7390237bc2310c1928335733b286287754ea85e6093d2495280e" |
|
224 | checksum = "3052106c29da7390237bc2310c1928335733b286287754ea85e6093d2495280e" | |
225 | dependencies = [ |
|
225 | dependencies = [ | |
226 | "libc", |
|
226 | "libc", | |
227 | "num-traits", |
|
227 | "num-traits", | |
228 | "paste", |
|
228 | "paste", | |
229 | "python3-sys", |
|
229 | "python3-sys", | |
230 | ] |
|
230 | ] | |
231 |
|
231 | |||
232 | [[package]] |
|
232 | [[package]] | |
233 | name = "crc32fast" |
|
233 | name = "crc32fast" | |
234 | version = "1.3.2" |
|
234 | version = "1.3.2" | |
235 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
235 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
236 | checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" |
|
236 | checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" | |
237 | dependencies = [ |
|
237 | dependencies = [ | |
238 | "cfg-if", |
|
238 | "cfg-if", | |
239 | ] |
|
239 | ] | |
240 |
|
240 | |||
241 | [[package]] |
|
241 | [[package]] | |
242 | name = "crossbeam-channel" |
|
242 | name = "crossbeam-channel" | |
243 | version = "0.5.6" |
|
243 | version = "0.5.6" | |
244 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
244 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
245 | checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" |
|
245 | checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" | |
246 | dependencies = [ |
|
246 | dependencies = [ | |
247 | "cfg-if", |
|
247 | "cfg-if", | |
248 | "crossbeam-utils", |
|
248 | "crossbeam-utils", | |
249 | ] |
|
249 | ] | |
250 |
|
250 | |||
251 | [[package]] |
|
251 | [[package]] | |
252 | name = "crossbeam-deque" |
|
252 | name = "crossbeam-deque" | |
253 | version = "0.8.2" |
|
253 | version = "0.8.2" | |
254 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
254 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
255 | checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" |
|
255 | checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" | |
256 | dependencies = [ |
|
256 | dependencies = [ | |
257 | "cfg-if", |
|
257 | "cfg-if", | |
258 | "crossbeam-epoch", |
|
258 | "crossbeam-epoch", | |
259 | "crossbeam-utils", |
|
259 | "crossbeam-utils", | |
260 | ] |
|
260 | ] | |
261 |
|
261 | |||
262 | [[package]] |
|
262 | [[package]] | |
263 | name = "crossbeam-epoch" |
|
263 | name = "crossbeam-epoch" | |
264 | version = "0.9.11" |
|
264 | version = "0.9.11" | |
265 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
265 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
266 | checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348" |
|
266 | checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348" | |
267 | dependencies = [ |
|
267 | dependencies = [ | |
268 | "autocfg", |
|
268 | "autocfg", | |
269 | "cfg-if", |
|
269 | "cfg-if", | |
270 | "crossbeam-utils", |
|
270 | "crossbeam-utils", | |
271 | "memoffset", |
|
271 | "memoffset", | |
272 | "scopeguard", |
|
272 | "scopeguard", | |
273 | ] |
|
273 | ] | |
274 |
|
274 | |||
275 | [[package]] |
|
275 | [[package]] | |
276 | name = "crossbeam-utils" |
|
276 | name = "crossbeam-utils" | |
277 | version = "0.8.12" |
|
277 | version = "0.8.12" | |
278 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
278 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
279 | checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" |
|
279 | checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" | |
280 | dependencies = [ |
|
280 | dependencies = [ | |
281 | "cfg-if", |
|
281 | "cfg-if", | |
282 | ] |
|
282 | ] | |
283 |
|
283 | |||
284 | [[package]] |
|
284 | [[package]] | |
285 | name = "crypto-common" |
|
285 | name = "crypto-common" | |
286 | version = "0.1.6" |
|
286 | version = "0.1.6" | |
287 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
287 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
288 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" |
|
288 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" | |
289 | dependencies = [ |
|
289 | dependencies = [ | |
290 | "generic-array", |
|
290 | "generic-array", | |
291 | "typenum", |
|
291 | "typenum", | |
292 | ] |
|
292 | ] | |
293 |
|
293 | |||
294 | [[package]] |
|
294 | [[package]] | |
295 | name = "ctor" |
|
295 | name = "ctor" | |
296 | version = "0.1.26" |
|
296 | version = "0.1.26" | |
297 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
297 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
298 | checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" |
|
298 | checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" | |
299 | dependencies = [ |
|
299 | dependencies = [ | |
300 | "quote", |
|
300 | "quote", | |
301 | "syn", |
|
301 | "syn", | |
302 | ] |
|
302 | ] | |
303 |
|
303 | |||
304 | [[package]] |
|
304 | [[package]] | |
305 | name = "cxx" |
|
305 | name = "cxx" | |
306 | version = "1.0.81" |
|
306 | version = "1.0.81" | |
307 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
307 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
308 | checksum = "97abf9f0eca9e52b7f81b945524e76710e6cb2366aead23b7d4fbf72e281f888" |
|
308 | checksum = "97abf9f0eca9e52b7f81b945524e76710e6cb2366aead23b7d4fbf72e281f888" | |
309 | dependencies = [ |
|
309 | dependencies = [ | |
310 | "cc", |
|
310 | "cc", | |
311 | "cxxbridge-flags", |
|
311 | "cxxbridge-flags", | |
312 | "cxxbridge-macro", |
|
312 | "cxxbridge-macro", | |
313 | "link-cplusplus", |
|
313 | "link-cplusplus", | |
314 | ] |
|
314 | ] | |
315 |
|
315 | |||
316 | [[package]] |
|
316 | [[package]] | |
317 | name = "cxx-build" |
|
317 | name = "cxx-build" | |
318 | version = "1.0.81" |
|
318 | version = "1.0.81" | |
319 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
319 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
320 | checksum = "7cc32cc5fea1d894b77d269ddb9f192110069a8a9c1f1d441195fba90553dea3" |
|
320 | checksum = "7cc32cc5fea1d894b77d269ddb9f192110069a8a9c1f1d441195fba90553dea3" | |
321 | dependencies = [ |
|
321 | dependencies = [ | |
322 | "cc", |
|
322 | "cc", | |
323 | "codespan-reporting", |
|
323 | "codespan-reporting", | |
324 | "once_cell", |
|
324 | "once_cell", | |
325 | "proc-macro2", |
|
325 | "proc-macro2", | |
326 | "quote", |
|
326 | "quote", | |
327 | "scratch", |
|
327 | "scratch", | |
328 | "syn", |
|
328 | "syn", | |
329 | ] |
|
329 | ] | |
330 |
|
330 | |||
331 | [[package]] |
|
331 | [[package]] | |
332 | name = "cxxbridge-flags" |
|
332 | name = "cxxbridge-flags" | |
333 | version = "1.0.81" |
|
333 | version = "1.0.81" | |
334 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
334 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
335 | checksum = "8ca220e4794c934dc6b1207c3b42856ad4c302f2df1712e9f8d2eec5afaacf1f" |
|
335 | checksum = "8ca220e4794c934dc6b1207c3b42856ad4c302f2df1712e9f8d2eec5afaacf1f" | |
336 |
|
336 | |||
337 | [[package]] |
|
337 | [[package]] | |
338 | name = "cxxbridge-macro" |
|
338 | name = "cxxbridge-macro" | |
339 | version = "1.0.81" |
|
339 | version = "1.0.81" | |
340 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
340 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
341 | checksum = "b846f081361125bfc8dc9d3940c84e1fd83ba54bbca7b17cd29483c828be0704" |
|
341 | checksum = "b846f081361125bfc8dc9d3940c84e1fd83ba54bbca7b17cd29483c828be0704" | |
342 | dependencies = [ |
|
342 | dependencies = [ | |
343 | "proc-macro2", |
|
343 | "proc-macro2", | |
344 | "quote", |
|
344 | "quote", | |
345 | "syn", |
|
345 | "syn", | |
346 | ] |
|
346 | ] | |
347 |
|
347 | |||
348 | [[package]] |
|
348 | [[package]] | |
349 | name = "derive_more" |
|
349 | name = "derive_more" | |
350 | version = "0.99.17" |
|
350 | version = "0.99.17" | |
351 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
351 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
352 | checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" |
|
352 | checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" | |
353 | dependencies = [ |
|
353 | dependencies = [ | |
354 | "convert_case", |
|
354 | "convert_case", | |
355 | "proc-macro2", |
|
355 | "proc-macro2", | |
356 | "quote", |
|
356 | "quote", | |
357 | "rustc_version", |
|
357 | "rustc_version", | |
358 | "syn", |
|
358 | "syn", | |
359 | ] |
|
359 | ] | |
360 |
|
360 | |||
361 | [[package]] |
|
361 | [[package]] | |
362 | name = "diff" |
|
362 | name = "diff" | |
363 | version = "0.1.13" |
|
363 | version = "0.1.13" | |
364 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
364 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
365 | checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" |
|
365 | checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" | |
366 |
|
366 | |||
367 | [[package]] |
|
367 | [[package]] | |
368 | name = "digest" |
|
368 | name = "digest" | |
369 | version = "0.9.0" |
|
369 | version = "0.9.0" | |
370 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
370 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
371 | checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" |
|
371 | checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" | |
372 | dependencies = [ |
|
372 | dependencies = [ | |
373 | "generic-array", |
|
373 | "generic-array", | |
374 | ] |
|
374 | ] | |
375 |
|
375 | |||
376 | [[package]] |
|
376 | [[package]] | |
377 | name = "digest" |
|
377 | name = "digest" | |
378 | version = "0.10.5" |
|
378 | version = "0.10.5" | |
379 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
379 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
380 | checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" |
|
380 | checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" | |
381 | dependencies = [ |
|
381 | dependencies = [ | |
382 | "block-buffer 0.10.3", |
|
382 | "block-buffer 0.10.3", | |
383 | "crypto-common", |
|
383 | "crypto-common", | |
384 | ] |
|
384 | ] | |
385 |
|
385 | |||
386 | [[package]] |
|
386 | [[package]] | |
387 | name = "either" |
|
387 | name = "either" | |
388 | version = "1.8.0" |
|
388 | version = "1.8.0" | |
389 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
389 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
390 | checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" |
|
390 | checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" | |
391 |
|
391 | |||
392 | [[package]] |
|
392 | [[package]] | |
393 | name = "env_logger" |
|
393 | name = "env_logger" | |
394 | version = "0.9.3" |
|
394 | version = "0.9.3" | |
395 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
395 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
396 | checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" |
|
396 | checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" | |
397 | dependencies = [ |
|
397 | dependencies = [ | |
398 | "atty", |
|
398 | "atty", | |
399 | "humantime", |
|
399 | "humantime", | |
400 | "log", |
|
400 | "log", | |
401 | "regex", |
|
401 | "regex", | |
402 | "termcolor", |
|
402 | "termcolor", | |
403 | ] |
|
403 | ] | |
404 |
|
404 | |||
405 | [[package]] |
|
405 | [[package]] | |
406 | name = "fastrand" |
|
406 | name = "fastrand" | |
407 | version = "1.8.0" |
|
407 | version = "1.8.0" | |
408 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
408 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
409 | checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" |
|
409 | checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" | |
410 | dependencies = [ |
|
410 | dependencies = [ | |
411 | "instant", |
|
411 | "instant", | |
412 | ] |
|
412 | ] | |
413 |
|
413 | |||
414 | [[package]] |
|
414 | [[package]] | |
415 | name = "flate2" |
|
415 | name = "flate2" | |
416 | version = "1.0.24" |
|
416 | version = "1.0.24" | |
417 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
417 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
418 | checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" |
|
418 | checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" | |
419 | dependencies = [ |
|
419 | dependencies = [ | |
420 | "crc32fast", |
|
420 | "crc32fast", | |
421 | "libz-sys", |
|
421 | "libz-sys", | |
422 | "miniz_oxide", |
|
422 | "miniz_oxide", | |
423 | ] |
|
423 | ] | |
424 |
|
424 | |||
425 | [[package]] |
|
425 | [[package]] | |
426 | name = "format-bytes" |
|
426 | name = "format-bytes" | |
427 | version = "0.3.0" |
|
427 | version = "0.3.0" | |
428 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
428 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
429 | checksum = "48942366ef93975da38e175ac9e10068c6fc08ca9e85930d4f098f4d5b14c2fd" |
|
429 | checksum = "48942366ef93975da38e175ac9e10068c6fc08ca9e85930d4f098f4d5b14c2fd" | |
430 | dependencies = [ |
|
430 | dependencies = [ | |
431 | "format-bytes-macros", |
|
431 | "format-bytes-macros", | |
432 | ] |
|
432 | ] | |
433 |
|
433 | |||
434 | [[package]] |
|
434 | [[package]] | |
435 | name = "format-bytes-macros" |
|
435 | name = "format-bytes-macros" | |
436 | version = "0.4.0" |
|
436 | version = "0.4.0" | |
437 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
437 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
438 | checksum = "203aadebefcc73d12038296c228eabf830f99cba991b0032adf20e9fa6ce7e4f" |
|
438 | checksum = "203aadebefcc73d12038296c228eabf830f99cba991b0032adf20e9fa6ce7e4f" | |
439 | dependencies = [ |
|
439 | dependencies = [ | |
440 | "proc-macro2", |
|
440 | "proc-macro2", | |
441 | "quote", |
|
441 | "quote", | |
442 | "syn", |
|
442 | "syn", | |
443 | ] |
|
443 | ] | |
444 |
|
444 | |||
445 | [[package]] |
|
445 | [[package]] | |
446 | name = "generic-array" |
|
446 | name = "generic-array" | |
447 | version = "0.14.6" |
|
447 | version = "0.14.6" | |
448 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
448 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
449 | checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" |
|
449 | checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" | |
450 | dependencies = [ |
|
450 | dependencies = [ | |
451 | "typenum", |
|
451 | "typenum", | |
452 | "version_check", |
|
452 | "version_check", | |
453 | ] |
|
453 | ] | |
454 |
|
454 | |||
455 | [[package]] |
|
455 | [[package]] | |
456 | name = "getrandom" |
|
456 | name = "getrandom" | |
457 | version = "0.1.16" |
|
457 | version = "0.1.16" | |
458 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
458 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
459 | checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" |
|
459 | checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" | |
460 | dependencies = [ |
|
460 | dependencies = [ | |
461 | "cfg-if", |
|
461 | "cfg-if", | |
462 | "libc", |
|
462 | "libc", | |
463 | "wasi 0.9.0+wasi-snapshot-preview1", |
|
463 | "wasi 0.9.0+wasi-snapshot-preview1", | |
464 | ] |
|
464 | ] | |
465 |
|
465 | |||
466 | [[package]] |
|
466 | [[package]] | |
467 | name = "getrandom" |
|
467 | name = "getrandom" | |
468 | version = "0.2.8" |
|
468 | version = "0.2.8" | |
469 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
469 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
470 | checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" |
|
470 | checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" | |
471 | dependencies = [ |
|
471 | dependencies = [ | |
472 | "cfg-if", |
|
472 | "cfg-if", | |
473 | "libc", |
|
473 | "libc", | |
474 | "wasi 0.11.0+wasi-snapshot-preview1", |
|
474 | "wasi 0.11.0+wasi-snapshot-preview1", | |
475 | ] |
|
475 | ] | |
476 |
|
476 | |||
477 | [[package]] |
|
477 | [[package]] | |
478 | name = "hashbrown" |
|
478 | name = "hashbrown" | |
|
479 | version = "0.12.3" | |||
|
480 | source = "registry+https://github.com/rust-lang/crates.io-index" | |||
|
481 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" | |||
|
482 | ||||
|
483 | [[package]] | |||
|
484 | name = "hashbrown" | |||
479 | version = "0.13.1" |
|
485 | version = "0.13.1" | |
480 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
486 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
481 | checksum = "33ff8ae62cd3a9102e5637afc8452c55acf3844001bd5374e0b0bd7b6616c038" |
|
487 | checksum = "33ff8ae62cd3a9102e5637afc8452c55acf3844001bd5374e0b0bd7b6616c038" | |
482 | dependencies = [ |
|
488 | dependencies = [ | |
483 | "ahash", |
|
489 | "ahash", | |
484 | "rayon", |
|
490 | "rayon", | |
485 | ] |
|
491 | ] | |
486 |
|
492 | |||
487 | [[package]] |
|
493 | [[package]] | |
488 | name = "heck" |
|
494 | name = "heck" | |
489 | version = "0.4.0" |
|
495 | version = "0.4.0" | |
490 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
496 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
491 | checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" |
|
497 | checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" | |
492 |
|
498 | |||
493 | [[package]] |
|
499 | [[package]] | |
494 | name = "hermit-abi" |
|
500 | name = "hermit-abi" | |
495 | version = "0.1.19" |
|
501 | version = "0.1.19" | |
496 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
502 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
497 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" |
|
503 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" | |
498 | dependencies = [ |
|
504 | dependencies = [ | |
499 | "libc", |
|
505 | "libc", | |
500 | ] |
|
506 | ] | |
501 |
|
507 | |||
502 | [[package]] |
|
508 | [[package]] | |
503 | name = "hex" |
|
509 | name = "hex" | |
504 | version = "0.4.3" |
|
510 | version = "0.4.3" | |
505 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
511 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
506 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" |
|
512 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" | |
507 |
|
513 | |||
508 | [[package]] |
|
514 | [[package]] | |
509 | name = "hg-core" |
|
515 | name = "hg-core" | |
510 | version = "0.1.0" |
|
516 | version = "0.1.0" | |
511 | dependencies = [ |
|
517 | dependencies = [ | |
512 | "bitflags", |
|
518 | "bitflags", | |
513 | "byteorder", |
|
519 | "byteorder", | |
514 | "bytes-cast", |
|
520 | "bytes-cast", | |
515 | "clap", |
|
521 | "clap", | |
516 | "crossbeam-channel", |
|
522 | "crossbeam-channel", | |
517 | "derive_more", |
|
523 | "derive_more", | |
518 | "flate2", |
|
524 | "flate2", | |
519 | "format-bytes", |
|
525 | "format-bytes", | |
520 | "hashbrown", |
|
526 | "hashbrown 0.13.1", | |
521 | "home", |
|
527 | "home", | |
522 | "im-rc", |
|
528 | "im-rc", | |
523 | "itertools", |
|
529 | "itertools", | |
524 | "lazy_static", |
|
530 | "lazy_static", | |
525 | "libc", |
|
531 | "libc", | |
526 | "log", |
|
532 | "log", | |
527 | "logging_timer", |
|
533 | "logging_timer", | |
528 | "memmap2", |
|
534 | "memmap2", | |
529 | "once_cell", |
|
535 | "once_cell", | |
530 | "pretty_assertions", |
|
536 | "pretty_assertions", | |
531 | "rand 0.8.5", |
|
537 | "rand 0.8.5", | |
532 | "rand_distr", |
|
538 | "rand_distr", | |
533 | "rand_pcg", |
|
539 | "rand_pcg", | |
534 | "rayon", |
|
540 | "rayon", | |
535 | "regex", |
|
541 | "regex", | |
536 | "same-file", |
|
542 | "same-file", | |
537 | "self_cell", |
|
543 | "self_cell", | |
|
544 | "serde", | |||
538 | "sha-1 0.10.0", |
|
545 | "sha-1 0.10.0", | |
539 | "tempfile", |
|
546 | "tempfile", | |
540 | "thread_local", |
|
547 | "thread_local", | |
|
548 | "toml", | |||
541 | "twox-hash", |
|
549 | "twox-hash", | |
542 | "zstd", |
|
550 | "zstd", | |
543 | ] |
|
551 | ] | |
544 |
|
552 | |||
545 | [[package]] |
|
553 | [[package]] | |
546 | name = "hg-cpython" |
|
554 | name = "hg-cpython" | |
547 | version = "0.1.0" |
|
555 | version = "0.1.0" | |
548 | dependencies = [ |
|
556 | dependencies = [ | |
549 | "cpython", |
|
557 | "cpython", | |
550 | "crossbeam-channel", |
|
558 | "crossbeam-channel", | |
551 | "env_logger", |
|
559 | "env_logger", | |
552 | "hg-core", |
|
560 | "hg-core", | |
553 | "libc", |
|
561 | "libc", | |
554 | "log", |
|
562 | "log", | |
555 | "stable_deref_trait", |
|
563 | "stable_deref_trait", | |
556 | "vcsgraph", |
|
564 | "vcsgraph", | |
557 | ] |
|
565 | ] | |
558 |
|
566 | |||
559 | [[package]] |
|
567 | [[package]] | |
560 | name = "home" |
|
568 | name = "home" | |
561 | version = "0.5.4" |
|
569 | version = "0.5.4" | |
562 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
570 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
563 | checksum = "747309b4b440c06d57b0b25f2aee03ee9b5e5397d288c60e21fc709bb98a7408" |
|
571 | checksum = "747309b4b440c06d57b0b25f2aee03ee9b5e5397d288c60e21fc709bb98a7408" | |
564 | dependencies = [ |
|
572 | dependencies = [ | |
565 | "winapi", |
|
573 | "winapi", | |
566 | ] |
|
574 | ] | |
567 |
|
575 | |||
568 | [[package]] |
|
576 | [[package]] | |
569 | name = "humantime" |
|
577 | name = "humantime" | |
570 | version = "2.1.0" |
|
578 | version = "2.1.0" | |
571 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
579 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
572 | checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" |
|
580 | checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" | |
573 |
|
581 | |||
574 | [[package]] |
|
582 | [[package]] | |
575 | name = "iana-time-zone" |
|
583 | name = "iana-time-zone" | |
576 | version = "0.1.53" |
|
584 | version = "0.1.53" | |
577 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
585 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
578 | checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" |
|
586 | checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" | |
579 | dependencies = [ |
|
587 | dependencies = [ | |
580 | "android_system_properties", |
|
588 | "android_system_properties", | |
581 | "core-foundation-sys", |
|
589 | "core-foundation-sys", | |
582 | "iana-time-zone-haiku", |
|
590 | "iana-time-zone-haiku", | |
583 | "js-sys", |
|
591 | "js-sys", | |
584 | "wasm-bindgen", |
|
592 | "wasm-bindgen", | |
585 | "winapi", |
|
593 | "winapi", | |
586 | ] |
|
594 | ] | |
587 |
|
595 | |||
588 | [[package]] |
|
596 | [[package]] | |
589 | name = "iana-time-zone-haiku" |
|
597 | name = "iana-time-zone-haiku" | |
590 | version = "0.1.1" |
|
598 | version = "0.1.1" | |
591 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
599 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
592 | checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" |
|
600 | checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" | |
593 | dependencies = [ |
|
601 | dependencies = [ | |
594 | "cxx", |
|
602 | "cxx", | |
595 | "cxx-build", |
|
603 | "cxx-build", | |
596 | ] |
|
604 | ] | |
597 |
|
605 | |||
598 | [[package]] |
|
606 | [[package]] | |
599 | name = "im-rc" |
|
607 | name = "im-rc" | |
600 | version = "15.1.0" |
|
608 | version = "15.1.0" | |
601 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
609 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
602 | checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe" |
|
610 | checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe" | |
603 | dependencies = [ |
|
611 | dependencies = [ | |
604 | "bitmaps", |
|
612 | "bitmaps", | |
605 | "rand_core 0.6.4", |
|
613 | "rand_core 0.6.4", | |
606 | "rand_xoshiro", |
|
614 | "rand_xoshiro", | |
607 | "sized-chunks", |
|
615 | "sized-chunks", | |
608 | "typenum", |
|
616 | "typenum", | |
609 | "version_check", |
|
617 | "version_check", | |
610 | ] |
|
618 | ] | |
611 |
|
619 | |||
612 | [[package]] |
|
620 | [[package]] | |
|
621 | name = "indexmap" | |||
|
622 | version = "1.9.2" | |||
|
623 | source = "registry+https://github.com/rust-lang/crates.io-index" | |||
|
624 | checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" | |||
|
625 | dependencies = [ | |||
|
626 | "autocfg", | |||
|
627 | "hashbrown 0.12.3", | |||
|
628 | ] | |||
|
629 | ||||
|
630 | [[package]] | |||
613 | name = "instant" |
|
631 | name = "instant" | |
614 | version = "0.1.12" |
|
632 | version = "0.1.12" | |
615 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
633 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
616 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" |
|
634 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" | |
617 | dependencies = [ |
|
635 | dependencies = [ | |
618 | "cfg-if", |
|
636 | "cfg-if", | |
619 | ] |
|
637 | ] | |
620 |
|
638 | |||
621 | [[package]] |
|
639 | [[package]] | |
622 | name = "itertools" |
|
640 | name = "itertools" | |
623 | version = "0.10.5" |
|
641 | version = "0.10.5" | |
624 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
642 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
625 | checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" |
|
643 | checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" | |
626 | dependencies = [ |
|
644 | dependencies = [ | |
627 | "either", |
|
645 | "either", | |
628 | ] |
|
646 | ] | |
629 |
|
647 | |||
630 | [[package]] |
|
648 | [[package]] | |
631 | name = "jobserver" |
|
649 | name = "jobserver" | |
632 | version = "0.1.25" |
|
650 | version = "0.1.25" | |
633 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
651 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
634 | checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" |
|
652 | checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" | |
635 | dependencies = [ |
|
653 | dependencies = [ | |
636 | "libc", |
|
654 | "libc", | |
637 | ] |
|
655 | ] | |
638 |
|
656 | |||
639 | [[package]] |
|
657 | [[package]] | |
640 | name = "js-sys" |
|
658 | name = "js-sys" | |
641 | version = "0.3.60" |
|
659 | version = "0.3.60" | |
642 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
660 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
643 | checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" |
|
661 | checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" | |
644 | dependencies = [ |
|
662 | dependencies = [ | |
645 | "wasm-bindgen", |
|
663 | "wasm-bindgen", | |
646 | ] |
|
664 | ] | |
647 |
|
665 | |||
648 | [[package]] |
|
666 | [[package]] | |
649 | name = "lazy_static" |
|
667 | name = "lazy_static" | |
650 | version = "1.4.0" |
|
668 | version = "1.4.0" | |
651 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
669 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
652 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" |
|
670 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" | |
653 |
|
671 | |||
654 | [[package]] |
|
672 | [[package]] | |
655 | name = "libc" |
|
673 | name = "libc" | |
656 | version = "0.2.137" |
|
674 | version = "0.2.137" | |
657 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
675 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
658 | checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" |
|
676 | checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" | |
659 |
|
677 | |||
660 | [[package]] |
|
678 | [[package]] | |
661 | name = "libm" |
|
679 | name = "libm" | |
662 | version = "0.2.6" |
|
680 | version = "0.2.6" | |
663 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
681 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
664 | checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" |
|
682 | checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" | |
665 |
|
683 | |||
666 | [[package]] |
|
684 | [[package]] | |
667 | name = "libz-sys" |
|
685 | name = "libz-sys" | |
668 | version = "1.1.8" |
|
686 | version = "1.1.8" | |
669 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
687 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
670 | checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" |
|
688 | checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" | |
671 | dependencies = [ |
|
689 | dependencies = [ | |
672 | "cc", |
|
690 | "cc", | |
673 | "pkg-config", |
|
691 | "pkg-config", | |
674 | "vcpkg", |
|
692 | "vcpkg", | |
675 | ] |
|
693 | ] | |
676 |
|
694 | |||
677 | [[package]] |
|
695 | [[package]] | |
678 | name = "link-cplusplus" |
|
696 | name = "link-cplusplus" | |
679 | version = "1.0.7" |
|
697 | version = "1.0.7" | |
680 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
698 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
681 | checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" |
|
699 | checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" | |
682 | dependencies = [ |
|
700 | dependencies = [ | |
683 | "cc", |
|
701 | "cc", | |
684 | ] |
|
702 | ] | |
685 |
|
703 | |||
686 | [[package]] |
|
704 | [[package]] | |
687 | name = "log" |
|
705 | name = "log" | |
688 | version = "0.4.17" |
|
706 | version = "0.4.17" | |
689 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
707 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
690 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" |
|
708 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" | |
691 | dependencies = [ |
|
709 | dependencies = [ | |
692 | "cfg-if", |
|
710 | "cfg-if", | |
693 | ] |
|
711 | ] | |
694 |
|
712 | |||
695 | [[package]] |
|
713 | [[package]] | |
696 | name = "logging_timer" |
|
714 | name = "logging_timer" | |
697 | version = "1.1.0" |
|
715 | version = "1.1.0" | |
698 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
716 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
699 | checksum = "64e96f261d684b7089aa576bb74e823241dccd994b27d30fabf1dcb3af284fe9" |
|
717 | checksum = "64e96f261d684b7089aa576bb74e823241dccd994b27d30fabf1dcb3af284fe9" | |
700 | dependencies = [ |
|
718 | dependencies = [ | |
701 | "log", |
|
719 | "log", | |
702 | "logging_timer_proc_macros", |
|
720 | "logging_timer_proc_macros", | |
703 | ] |
|
721 | ] | |
704 |
|
722 | |||
705 | [[package]] |
|
723 | [[package]] | |
706 | name = "logging_timer_proc_macros" |
|
724 | name = "logging_timer_proc_macros" | |
707 | version = "1.1.0" |
|
725 | version = "1.1.0" | |
708 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
726 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
709 | checksum = "10a9062912d7952c5588cc474795e0b9ee008e7e6781127945b85413d4b99d81" |
|
727 | checksum = "10a9062912d7952c5588cc474795e0b9ee008e7e6781127945b85413d4b99d81" | |
710 | dependencies = [ |
|
728 | dependencies = [ | |
711 | "log", |
|
729 | "log", | |
712 | "proc-macro2", |
|
730 | "proc-macro2", | |
713 | "quote", |
|
731 | "quote", | |
714 | "syn", |
|
732 | "syn", | |
715 | ] |
|
733 | ] | |
716 |
|
734 | |||
717 | [[package]] |
|
735 | [[package]] | |
718 | name = "memchr" |
|
736 | name = "memchr" | |
719 | version = "2.5.0" |
|
737 | version = "2.5.0" | |
720 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
738 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
721 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" |
|
739 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" | |
722 |
|
740 | |||
723 | [[package]] |
|
741 | [[package]] | |
724 | name = "memmap2" |
|
742 | name = "memmap2" | |
725 | version = "0.5.8" |
|
743 | version = "0.5.8" | |
726 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
744 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
727 | checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc" |
|
745 | checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc" | |
728 | dependencies = [ |
|
746 | dependencies = [ | |
729 | "libc", |
|
747 | "libc", | |
730 | "stable_deref_trait", |
|
748 | "stable_deref_trait", | |
731 | ] |
|
749 | ] | |
732 |
|
750 | |||
733 | [[package]] |
|
751 | [[package]] | |
734 | name = "memoffset" |
|
752 | name = "memoffset" | |
735 | version = "0.6.5" |
|
753 | version = "0.6.5" | |
736 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
754 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
737 | checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" |
|
755 | checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" | |
738 | dependencies = [ |
|
756 | dependencies = [ | |
739 | "autocfg", |
|
757 | "autocfg", | |
740 | ] |
|
758 | ] | |
741 |
|
759 | |||
742 | [[package]] |
|
760 | [[package]] | |
743 | name = "miniz_oxide" |
|
761 | name = "miniz_oxide" | |
744 | version = "0.5.4" |
|
762 | version = "0.5.4" | |
745 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
763 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
746 | checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" |
|
764 | checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" | |
747 | dependencies = [ |
|
765 | dependencies = [ | |
748 | "adler", |
|
766 | "adler", | |
749 | ] |
|
767 | ] | |
750 |
|
768 | |||
751 | [[package]] |
|
769 | [[package]] | |
|
770 | name = "nom8" | |||
|
771 | version = "0.2.0" | |||
|
772 | source = "registry+https://github.com/rust-lang/crates.io-index" | |||
|
773 | checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" | |||
|
774 | dependencies = [ | |||
|
775 | "memchr", | |||
|
776 | ] | |||
|
777 | ||||
|
778 | [[package]] | |||
752 | name = "num-integer" |
|
779 | name = "num-integer" | |
753 | version = "0.1.45" |
|
780 | version = "0.1.45" | |
754 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
781 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
755 | checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" |
|
782 | checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" | |
756 | dependencies = [ |
|
783 | dependencies = [ | |
757 | "autocfg", |
|
784 | "autocfg", | |
758 | "num-traits", |
|
785 | "num-traits", | |
759 | ] |
|
786 | ] | |
760 |
|
787 | |||
761 | [[package]] |
|
788 | [[package]] | |
762 | name = "num-traits" |
|
789 | name = "num-traits" | |
763 | version = "0.2.15" |
|
790 | version = "0.2.15" | |
764 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
791 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
765 | checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" |
|
792 | checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" | |
766 | dependencies = [ |
|
793 | dependencies = [ | |
767 | "autocfg", |
|
794 | "autocfg", | |
768 | "libm", |
|
795 | "libm", | |
769 | ] |
|
796 | ] | |
770 |
|
797 | |||
771 | [[package]] |
|
798 | [[package]] | |
772 | name = "num_cpus" |
|
799 | name = "num_cpus" | |
773 | version = "1.14.0" |
|
800 | version = "1.14.0" | |
774 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
801 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
775 | checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" |
|
802 | checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" | |
776 | dependencies = [ |
|
803 | dependencies = [ | |
777 | "hermit-abi", |
|
804 | "hermit-abi", | |
778 | "libc", |
|
805 | "libc", | |
779 | ] |
|
806 | ] | |
780 |
|
807 | |||
781 | [[package]] |
|
808 | [[package]] | |
782 | name = "once_cell" |
|
809 | name = "once_cell" | |
783 | version = "1.16.0" |
|
810 | version = "1.16.0" | |
784 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
811 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
785 | checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" |
|
812 | checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" | |
786 |
|
813 | |||
787 | [[package]] |
|
814 | [[package]] | |
788 | name = "opaque-debug" |
|
815 | name = "opaque-debug" | |
789 | version = "0.3.0" |
|
816 | version = "0.3.0" | |
790 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
817 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
791 | checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" |
|
818 | checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" | |
792 |
|
819 | |||
793 | [[package]] |
|
820 | [[package]] | |
794 | name = "os_str_bytes" |
|
821 | name = "os_str_bytes" | |
795 | version = "6.4.0" |
|
822 | version = "6.4.0" | |
796 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
823 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
797 | checksum = "7b5bf27447411e9ee3ff51186bf7a08e16c341efdde93f4d823e8844429bed7e" |
|
824 | checksum = "7b5bf27447411e9ee3ff51186bf7a08e16c341efdde93f4d823e8844429bed7e" | |
798 |
|
825 | |||
799 | [[package]] |
|
826 | [[package]] | |
800 | name = "output_vt100" |
|
827 | name = "output_vt100" | |
801 | version = "0.1.3" |
|
828 | version = "0.1.3" | |
802 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
829 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
803 | checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66" |
|
830 | checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66" | |
804 | dependencies = [ |
|
831 | dependencies = [ | |
805 | "winapi", |
|
832 | "winapi", | |
806 | ] |
|
833 | ] | |
807 |
|
834 | |||
808 | [[package]] |
|
835 | [[package]] | |
809 | name = "paste" |
|
836 | name = "paste" | |
810 | version = "1.0.9" |
|
837 | version = "1.0.9" | |
811 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
838 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
812 | checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" |
|
839 | checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" | |
813 |
|
840 | |||
814 | [[package]] |
|
841 | [[package]] | |
815 | name = "pkg-config" |
|
842 | name = "pkg-config" | |
816 | version = "0.3.26" |
|
843 | version = "0.3.26" | |
817 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
844 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
818 | checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" |
|
845 | checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" | |
819 |
|
846 | |||
820 | [[package]] |
|
847 | [[package]] | |
821 | name = "ppv-lite86" |
|
848 | name = "ppv-lite86" | |
822 | version = "0.2.17" |
|
849 | version = "0.2.17" | |
823 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
850 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
824 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" |
|
851 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" | |
825 |
|
852 | |||
826 | [[package]] |
|
853 | [[package]] | |
827 | name = "pretty_assertions" |
|
854 | name = "pretty_assertions" | |
828 | version = "1.3.0" |
|
855 | version = "1.3.0" | |
829 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
856 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
830 | checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755" |
|
857 | checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755" | |
831 | dependencies = [ |
|
858 | dependencies = [ | |
832 | "ctor", |
|
859 | "ctor", | |
833 | "diff", |
|
860 | "diff", | |
834 | "output_vt100", |
|
861 | "output_vt100", | |
835 | "yansi", |
|
862 | "yansi", | |
836 | ] |
|
863 | ] | |
837 |
|
864 | |||
838 | [[package]] |
|
865 | [[package]] | |
839 | name = "proc-macro-error" |
|
866 | name = "proc-macro-error" | |
840 | version = "1.0.4" |
|
867 | version = "1.0.4" | |
841 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
868 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
842 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" |
|
869 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" | |
843 | dependencies = [ |
|
870 | dependencies = [ | |
844 | "proc-macro-error-attr", |
|
871 | "proc-macro-error-attr", | |
845 | "proc-macro2", |
|
872 | "proc-macro2", | |
846 | "quote", |
|
873 | "quote", | |
847 | "syn", |
|
874 | "syn", | |
848 | "version_check", |
|
875 | "version_check", | |
849 | ] |
|
876 | ] | |
850 |
|
877 | |||
851 | [[package]] |
|
878 | [[package]] | |
852 | name = "proc-macro-error-attr" |
|
879 | name = "proc-macro-error-attr" | |
853 | version = "1.0.4" |
|
880 | version = "1.0.4" | |
854 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
881 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
855 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" |
|
882 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" | |
856 | dependencies = [ |
|
883 | dependencies = [ | |
857 | "proc-macro2", |
|
884 | "proc-macro2", | |
858 | "quote", |
|
885 | "quote", | |
859 | "version_check", |
|
886 | "version_check", | |
860 | ] |
|
887 | ] | |
861 |
|
888 | |||
862 | [[package]] |
|
889 | [[package]] | |
863 | name = "proc-macro2" |
|
890 | name = "proc-macro2" | |
864 | version = "1.0.47" |
|
891 | version = "1.0.47" | |
865 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
892 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
866 | checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" |
|
893 | checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" | |
867 | dependencies = [ |
|
894 | dependencies = [ | |
868 | "unicode-ident", |
|
895 | "unicode-ident", | |
869 | ] |
|
896 | ] | |
870 |
|
897 | |||
871 | [[package]] |
|
898 | [[package]] | |
872 | name = "python3-sys" |
|
899 | name = "python3-sys" | |
873 | version = "0.7.1" |
|
900 | version = "0.7.1" | |
874 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
901 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
875 | checksum = "49f8b50d72fb3015735aa403eebf19bbd72c093bfeeae24ee798be5f2f1aab52" |
|
902 | checksum = "49f8b50d72fb3015735aa403eebf19bbd72c093bfeeae24ee798be5f2f1aab52" | |
876 | dependencies = [ |
|
903 | dependencies = [ | |
877 | "libc", |
|
904 | "libc", | |
878 | "regex", |
|
905 | "regex", | |
879 | ] |
|
906 | ] | |
880 |
|
907 | |||
881 | [[package]] |
|
908 | [[package]] | |
882 | name = "quote" |
|
909 | name = "quote" | |
883 | version = "1.0.21" |
|
910 | version = "1.0.21" | |
884 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
911 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
885 | checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" |
|
912 | checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" | |
886 | dependencies = [ |
|
913 | dependencies = [ | |
887 | "proc-macro2", |
|
914 | "proc-macro2", | |
888 | ] |
|
915 | ] | |
889 |
|
916 | |||
890 | [[package]] |
|
917 | [[package]] | |
891 | name = "rand" |
|
918 | name = "rand" | |
892 | version = "0.7.3" |
|
919 | version = "0.7.3" | |
893 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
920 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
894 | checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" |
|
921 | checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" | |
895 | dependencies = [ |
|
922 | dependencies = [ | |
896 | "getrandom 0.1.16", |
|
923 | "getrandom 0.1.16", | |
897 | "libc", |
|
924 | "libc", | |
898 | "rand_chacha 0.2.2", |
|
925 | "rand_chacha 0.2.2", | |
899 | "rand_core 0.5.1", |
|
926 | "rand_core 0.5.1", | |
900 | "rand_hc", |
|
927 | "rand_hc", | |
901 | ] |
|
928 | ] | |
902 |
|
929 | |||
903 | [[package]] |
|
930 | [[package]] | |
904 | name = "rand" |
|
931 | name = "rand" | |
905 | version = "0.8.5" |
|
932 | version = "0.8.5" | |
906 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
933 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
907 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" |
|
934 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" | |
908 | dependencies = [ |
|
935 | dependencies = [ | |
909 | "libc", |
|
936 | "libc", | |
910 | "rand_chacha 0.3.1", |
|
937 | "rand_chacha 0.3.1", | |
911 | "rand_core 0.6.4", |
|
938 | "rand_core 0.6.4", | |
912 | ] |
|
939 | ] | |
913 |
|
940 | |||
914 | [[package]] |
|
941 | [[package]] | |
915 | name = "rand_chacha" |
|
942 | name = "rand_chacha" | |
916 | version = "0.2.2" |
|
943 | version = "0.2.2" | |
917 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
944 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
918 | checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" |
|
945 | checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" | |
919 | dependencies = [ |
|
946 | dependencies = [ | |
920 | "ppv-lite86", |
|
947 | "ppv-lite86", | |
921 | "rand_core 0.5.1", |
|
948 | "rand_core 0.5.1", | |
922 | ] |
|
949 | ] | |
923 |
|
950 | |||
924 | [[package]] |
|
951 | [[package]] | |
925 | name = "rand_chacha" |
|
952 | name = "rand_chacha" | |
926 | version = "0.3.1" |
|
953 | version = "0.3.1" | |
927 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
954 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
928 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" |
|
955 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" | |
929 | dependencies = [ |
|
956 | dependencies = [ | |
930 | "ppv-lite86", |
|
957 | "ppv-lite86", | |
931 | "rand_core 0.6.4", |
|
958 | "rand_core 0.6.4", | |
932 | ] |
|
959 | ] | |
933 |
|
960 | |||
934 | [[package]] |
|
961 | [[package]] | |
935 | name = "rand_core" |
|
962 | name = "rand_core" | |
936 | version = "0.5.1" |
|
963 | version = "0.5.1" | |
937 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
964 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
938 | checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" |
|
965 | checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" | |
939 | dependencies = [ |
|
966 | dependencies = [ | |
940 | "getrandom 0.1.16", |
|
967 | "getrandom 0.1.16", | |
941 | ] |
|
968 | ] | |
942 |
|
969 | |||
943 | [[package]] |
|
970 | [[package]] | |
944 | name = "rand_core" |
|
971 | name = "rand_core" | |
945 | version = "0.6.4" |
|
972 | version = "0.6.4" | |
946 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
973 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
947 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" |
|
974 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" | |
948 | dependencies = [ |
|
975 | dependencies = [ | |
949 | "getrandom 0.2.8", |
|
976 | "getrandom 0.2.8", | |
950 | ] |
|
977 | ] | |
951 |
|
978 | |||
952 | [[package]] |
|
979 | [[package]] | |
953 | name = "rand_distr" |
|
980 | name = "rand_distr" | |
954 | version = "0.4.3" |
|
981 | version = "0.4.3" | |
955 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
982 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
956 | checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" |
|
983 | checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" | |
957 | dependencies = [ |
|
984 | dependencies = [ | |
958 | "num-traits", |
|
985 | "num-traits", | |
959 | "rand 0.8.5", |
|
986 | "rand 0.8.5", | |
960 | ] |
|
987 | ] | |
961 |
|
988 | |||
962 | [[package]] |
|
989 | [[package]] | |
963 | name = "rand_hc" |
|
990 | name = "rand_hc" | |
964 | version = "0.2.0" |
|
991 | version = "0.2.0" | |
965 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
992 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
966 | checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" |
|
993 | checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" | |
967 | dependencies = [ |
|
994 | dependencies = [ | |
968 | "rand_core 0.5.1", |
|
995 | "rand_core 0.5.1", | |
969 | ] |
|
996 | ] | |
970 |
|
997 | |||
971 | [[package]] |
|
998 | [[package]] | |
972 | name = "rand_pcg" |
|
999 | name = "rand_pcg" | |
973 | version = "0.3.1" |
|
1000 | version = "0.3.1" | |
974 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1001 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
975 | checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e" |
|
1002 | checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e" | |
976 | dependencies = [ |
|
1003 | dependencies = [ | |
977 | "rand_core 0.6.4", |
|
1004 | "rand_core 0.6.4", | |
978 | ] |
|
1005 | ] | |
979 |
|
1006 | |||
980 | [[package]] |
|
1007 | [[package]] | |
981 | name = "rand_xoshiro" |
|
1008 | name = "rand_xoshiro" | |
982 | version = "0.6.0" |
|
1009 | version = "0.6.0" | |
983 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1010 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
984 | checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" |
|
1011 | checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" | |
985 | dependencies = [ |
|
1012 | dependencies = [ | |
986 | "rand_core 0.6.4", |
|
1013 | "rand_core 0.6.4", | |
987 | ] |
|
1014 | ] | |
988 |
|
1015 | |||
989 | [[package]] |
|
1016 | [[package]] | |
990 | name = "rayon" |
|
1017 | name = "rayon" | |
991 | version = "1.7.0" |
|
1018 | version = "1.7.0" | |
992 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1019 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
993 | checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" |
|
1020 | checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" | |
994 | dependencies = [ |
|
1021 | dependencies = [ | |
995 | "either", |
|
1022 | "either", | |
996 | "rayon-core", |
|
1023 | "rayon-core", | |
997 | ] |
|
1024 | ] | |
998 |
|
1025 | |||
999 | [[package]] |
|
1026 | [[package]] | |
1000 | name = "rayon-core" |
|
1027 | name = "rayon-core" | |
1001 | version = "1.11.0" |
|
1028 | version = "1.11.0" | |
1002 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1029 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1003 | checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" |
|
1030 | checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" | |
1004 | dependencies = [ |
|
1031 | dependencies = [ | |
1005 | "crossbeam-channel", |
|
1032 | "crossbeam-channel", | |
1006 | "crossbeam-deque", |
|
1033 | "crossbeam-deque", | |
1007 | "crossbeam-utils", |
|
1034 | "crossbeam-utils", | |
1008 | "num_cpus", |
|
1035 | "num_cpus", | |
1009 | ] |
|
1036 | ] | |
1010 |
|
1037 | |||
1011 | [[package]] |
|
1038 | [[package]] | |
1012 | name = "redox_syscall" |
|
1039 | name = "redox_syscall" | |
1013 | version = "0.2.16" |
|
1040 | version = "0.2.16" | |
1014 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1041 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1015 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" |
|
1042 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" | |
1016 | dependencies = [ |
|
1043 | dependencies = [ | |
1017 | "bitflags", |
|
1044 | "bitflags", | |
1018 | ] |
|
1045 | ] | |
1019 |
|
1046 | |||
1020 | [[package]] |
|
1047 | [[package]] | |
1021 | name = "regex" |
|
1048 | name = "regex" | |
1022 | version = "1.7.0" |
|
1049 | version = "1.7.0" | |
1023 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1050 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1024 | checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" |
|
1051 | checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" | |
1025 | dependencies = [ |
|
1052 | dependencies = [ | |
1026 | "aho-corasick", |
|
1053 | "aho-corasick", | |
1027 | "memchr", |
|
1054 | "memchr", | |
1028 | "regex-syntax", |
|
1055 | "regex-syntax", | |
1029 | ] |
|
1056 | ] | |
1030 |
|
1057 | |||
1031 | [[package]] |
|
1058 | [[package]] | |
1032 | name = "regex-syntax" |
|
1059 | name = "regex-syntax" | |
1033 | version = "0.6.28" |
|
1060 | version = "0.6.28" | |
1034 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1061 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1035 | checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" |
|
1062 | checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" | |
1036 |
|
1063 | |||
1037 | [[package]] |
|
1064 | [[package]] | |
1038 | name = "remove_dir_all" |
|
1065 | name = "remove_dir_all" | |
1039 | version = "0.5.3" |
|
1066 | version = "0.5.3" | |
1040 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1067 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1041 | checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" |
|
1068 | checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" | |
1042 | dependencies = [ |
|
1069 | dependencies = [ | |
1043 | "winapi", |
|
1070 | "winapi", | |
1044 | ] |
|
1071 | ] | |
1045 |
|
1072 | |||
1046 | [[package]] |
|
1073 | [[package]] | |
1047 | name = "rhg" |
|
1074 | name = "rhg" | |
1048 | version = "0.1.0" |
|
1075 | version = "0.1.0" | |
1049 | dependencies = [ |
|
1076 | dependencies = [ | |
1050 | "atty", |
|
1077 | "atty", | |
1051 | "chrono", |
|
1078 | "chrono", | |
1052 | "clap", |
|
1079 | "clap", | |
1053 | "derive_more", |
|
1080 | "derive_more", | |
1054 | "env_logger", |
|
1081 | "env_logger", | |
1055 | "format-bytes", |
|
1082 | "format-bytes", | |
1056 | "hg-core", |
|
1083 | "hg-core", | |
1057 | "home", |
|
1084 | "home", | |
1058 | "lazy_static", |
|
1085 | "lazy_static", | |
1059 | "log", |
|
1086 | "log", | |
1060 | "logging_timer", |
|
1087 | "logging_timer", | |
1061 | "rayon", |
|
1088 | "rayon", | |
1062 | "regex", |
|
1089 | "regex", | |
1063 | "which", |
|
1090 | "which", | |
1064 | "whoami", |
|
1091 | "whoami", | |
1065 | ] |
|
1092 | ] | |
1066 |
|
1093 | |||
1067 | [[package]] |
|
1094 | [[package]] | |
1068 | name = "rustc_version" |
|
1095 | name = "rustc_version" | |
1069 | version = "0.4.0" |
|
1096 | version = "0.4.0" | |
1070 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1097 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1071 | checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" |
|
1098 | checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" | |
1072 | dependencies = [ |
|
1099 | dependencies = [ | |
1073 | "semver", |
|
1100 | "semver", | |
1074 | ] |
|
1101 | ] | |
1075 |
|
1102 | |||
1076 | [[package]] |
|
1103 | [[package]] | |
1077 | name = "same-file" |
|
1104 | name = "same-file" | |
1078 | version = "1.0.6" |
|
1105 | version = "1.0.6" | |
1079 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1106 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1080 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" |
|
1107 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" | |
1081 | dependencies = [ |
|
1108 | dependencies = [ | |
1082 | "winapi-util", |
|
1109 | "winapi-util", | |
1083 | ] |
|
1110 | ] | |
1084 |
|
1111 | |||
1085 | [[package]] |
|
1112 | [[package]] | |
1086 | name = "scopeguard" |
|
1113 | name = "scopeguard" | |
1087 | version = "1.1.0" |
|
1114 | version = "1.1.0" | |
1088 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1115 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1089 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" |
|
1116 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" | |
1090 |
|
1117 | |||
1091 | [[package]] |
|
1118 | [[package]] | |
1092 | name = "scratch" |
|
1119 | name = "scratch" | |
1093 | version = "1.0.2" |
|
1120 | version = "1.0.2" | |
1094 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1121 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1095 | checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" |
|
1122 | checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" | |
1096 |
|
1123 | |||
1097 | [[package]] |
|
1124 | [[package]] | |
1098 | name = "self_cell" |
|
1125 | name = "self_cell" | |
1099 | version = "1.0.0" |
|
1126 | version = "1.0.0" | |
1100 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1127 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1101 | checksum = "4a3926e239738d36060909ffe6f511502f92149a45a1fade7fe031cb2d33e88b" |
|
1128 | checksum = "4a3926e239738d36060909ffe6f511502f92149a45a1fade7fe031cb2d33e88b" | |
1102 |
|
1129 | |||
1103 | [[package]] |
|
1130 | [[package]] | |
1104 | name = "semver" |
|
1131 | name = "semver" | |
1105 | version = "1.0.14" |
|
1132 | version = "1.0.14" | |
1106 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1133 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1107 | checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" |
|
1134 | checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" | |
1108 |
|
1135 | |||
1109 | [[package]] |
|
1136 | [[package]] | |
|
1137 | name = "serde" | |||
|
1138 | version = "1.0.152" | |||
|
1139 | source = "registry+https://github.com/rust-lang/crates.io-index" | |||
|
1140 | checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" | |||
|
1141 | dependencies = [ | |||
|
1142 | "serde_derive", | |||
|
1143 | ] | |||
|
1144 | ||||
|
1145 | [[package]] | |||
|
1146 | name = "serde_derive" | |||
|
1147 | version = "1.0.152" | |||
|
1148 | source = "registry+https://github.com/rust-lang/crates.io-index" | |||
|
1149 | checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" | |||
|
1150 | dependencies = [ | |||
|
1151 | "proc-macro2", | |||
|
1152 | "quote", | |||
|
1153 | "syn", | |||
|
1154 | ] | |||
|
1155 | ||||
|
1156 | [[package]] | |||
|
1157 | name = "serde_spanned" | |||
|
1158 | version = "0.6.1" | |||
|
1159 | source = "registry+https://github.com/rust-lang/crates.io-index" | |||
|
1160 | checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4" | |||
|
1161 | dependencies = [ | |||
|
1162 | "serde", | |||
|
1163 | ] | |||
|
1164 | ||||
|
1165 | [[package]] | |||
1110 | name = "sha-1" |
|
1166 | name = "sha-1" | |
1111 | version = "0.9.8" |
|
1167 | version = "0.9.8" | |
1112 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1168 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1113 | checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" |
|
1169 | checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" | |
1114 | dependencies = [ |
|
1170 | dependencies = [ | |
1115 | "block-buffer 0.9.0", |
|
1171 | "block-buffer 0.9.0", | |
1116 | "cfg-if", |
|
1172 | "cfg-if", | |
1117 | "cpufeatures", |
|
1173 | "cpufeatures", | |
1118 | "digest 0.9.0", |
|
1174 | "digest 0.9.0", | |
1119 | "opaque-debug", |
|
1175 | "opaque-debug", | |
1120 | ] |
|
1176 | ] | |
1121 |
|
1177 | |||
1122 | [[package]] |
|
1178 | [[package]] | |
1123 | name = "sha-1" |
|
1179 | name = "sha-1" | |
1124 | version = "0.10.0" |
|
1180 | version = "0.10.0" | |
1125 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1181 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1126 | checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" |
|
1182 | checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" | |
1127 | dependencies = [ |
|
1183 | dependencies = [ | |
1128 | "cfg-if", |
|
1184 | "cfg-if", | |
1129 | "cpufeatures", |
|
1185 | "cpufeatures", | |
1130 | "digest 0.10.5", |
|
1186 | "digest 0.10.5", | |
1131 | ] |
|
1187 | ] | |
1132 |
|
1188 | |||
1133 | [[package]] |
|
1189 | [[package]] | |
1134 | name = "sized-chunks" |
|
1190 | name = "sized-chunks" | |
1135 | version = "0.6.5" |
|
1191 | version = "0.6.5" | |
1136 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1192 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1137 | checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" |
|
1193 | checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" | |
1138 | dependencies = [ |
|
1194 | dependencies = [ | |
1139 | "bitmaps", |
|
1195 | "bitmaps", | |
1140 | "typenum", |
|
1196 | "typenum", | |
1141 | ] |
|
1197 | ] | |
1142 |
|
1198 | |||
1143 | [[package]] |
|
1199 | [[package]] | |
1144 | name = "stable_deref_trait" |
|
1200 | name = "stable_deref_trait" | |
1145 | version = "1.2.0" |
|
1201 | version = "1.2.0" | |
1146 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1202 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1147 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" |
|
1203 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" | |
1148 |
|
1204 | |||
1149 | [[package]] |
|
1205 | [[package]] | |
1150 | name = "static_assertions" |
|
1206 | name = "static_assertions" | |
1151 | version = "1.1.0" |
|
1207 | version = "1.1.0" | |
1152 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1208 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1153 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" |
|
1209 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" | |
1154 |
|
1210 | |||
1155 | [[package]] |
|
1211 | [[package]] | |
1156 | name = "strsim" |
|
1212 | name = "strsim" | |
1157 | version = "0.10.0" |
|
1213 | version = "0.10.0" | |
1158 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1214 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1159 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" |
|
1215 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" | |
1160 |
|
1216 | |||
1161 | [[package]] |
|
1217 | [[package]] | |
1162 | name = "syn" |
|
1218 | name = "syn" | |
1163 |
version = "1.0.10 |
|
1219 | version = "1.0.109" | |
1164 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1220 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1165 | checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" |
|
1221 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" | |
1166 | dependencies = [ |
|
1222 | dependencies = [ | |
1167 | "proc-macro2", |
|
1223 | "proc-macro2", | |
1168 | "quote", |
|
1224 | "quote", | |
1169 | "unicode-ident", |
|
1225 | "unicode-ident", | |
1170 | ] |
|
1226 | ] | |
1171 |
|
1227 | |||
1172 | [[package]] |
|
1228 | [[package]] | |
1173 | name = "tempfile" |
|
1229 | name = "tempfile" | |
1174 | version = "3.3.0" |
|
1230 | version = "3.3.0" | |
1175 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1231 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1176 | checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" |
|
1232 | checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" | |
1177 | dependencies = [ |
|
1233 | dependencies = [ | |
1178 | "cfg-if", |
|
1234 | "cfg-if", | |
1179 | "fastrand", |
|
1235 | "fastrand", | |
1180 | "libc", |
|
1236 | "libc", | |
1181 | "redox_syscall", |
|
1237 | "redox_syscall", | |
1182 | "remove_dir_all", |
|
1238 | "remove_dir_all", | |
1183 | "winapi", |
|
1239 | "winapi", | |
1184 | ] |
|
1240 | ] | |
1185 |
|
1241 | |||
1186 | [[package]] |
|
1242 | [[package]] | |
1187 | name = "termcolor" |
|
1243 | name = "termcolor" | |
1188 | version = "1.1.3" |
|
1244 | version = "1.1.3" | |
1189 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1245 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1190 | checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" |
|
1246 | checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" | |
1191 | dependencies = [ |
|
1247 | dependencies = [ | |
1192 | "winapi-util", |
|
1248 | "winapi-util", | |
1193 | ] |
|
1249 | ] | |
1194 |
|
1250 | |||
1195 | [[package]] |
|
1251 | [[package]] | |
1196 | name = "thread_local" |
|
1252 | name = "thread_local" | |
1197 | version = "1.1.4" |
|
1253 | version = "1.1.4" | |
1198 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1254 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1199 | checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" |
|
1255 | checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" | |
1200 | dependencies = [ |
|
1256 | dependencies = [ | |
1201 | "once_cell", |
|
1257 | "once_cell", | |
1202 | ] |
|
1258 | ] | |
1203 |
|
1259 | |||
1204 | [[package]] |
|
1260 | [[package]] | |
1205 | name = "time" |
|
1261 | name = "time" | |
1206 | version = "0.1.44" |
|
1262 | version = "0.1.44" | |
1207 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1263 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1208 | checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" |
|
1264 | checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" | |
1209 | dependencies = [ |
|
1265 | dependencies = [ | |
1210 | "libc", |
|
1266 | "libc", | |
1211 | "wasi 0.10.0+wasi-snapshot-preview1", |
|
1267 | "wasi 0.10.0+wasi-snapshot-preview1", | |
1212 | "winapi", |
|
1268 | "winapi", | |
1213 | ] |
|
1269 | ] | |
1214 |
|
1270 | |||
1215 | [[package]] |
|
1271 | [[package]] | |
|
1272 | name = "toml" | |||
|
1273 | version = "0.6.0" | |||
|
1274 | source = "registry+https://github.com/rust-lang/crates.io-index" | |||
|
1275 | checksum = "4fb9d890e4dc9298b70f740f615f2e05b9db37dce531f6b24fb77ac993f9f217" | |||
|
1276 | dependencies = [ | |||
|
1277 | "serde", | |||
|
1278 | "serde_spanned", | |||
|
1279 | "toml_datetime", | |||
|
1280 | "toml_edit", | |||
|
1281 | ] | |||
|
1282 | ||||
|
1283 | [[package]] | |||
|
1284 | name = "toml_datetime" | |||
|
1285 | version = "0.5.1" | |||
|
1286 | source = "registry+https://github.com/rust-lang/crates.io-index" | |||
|
1287 | checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" | |||
|
1288 | dependencies = [ | |||
|
1289 | "serde", | |||
|
1290 | ] | |||
|
1291 | ||||
|
1292 | [[package]] | |||
|
1293 | name = "toml_edit" | |||
|
1294 | version = "0.18.1" | |||
|
1295 | source = "registry+https://github.com/rust-lang/crates.io-index" | |||
|
1296 | checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" | |||
|
1297 | dependencies = [ | |||
|
1298 | "indexmap", | |||
|
1299 | "nom8", | |||
|
1300 | "serde", | |||
|
1301 | "serde_spanned", | |||
|
1302 | "toml_datetime", | |||
|
1303 | ] | |||
|
1304 | ||||
|
1305 | [[package]] | |||
1216 | name = "twox-hash" |
|
1306 | name = "twox-hash" | |
1217 | version = "1.6.3" |
|
1307 | version = "1.6.3" | |
1218 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1308 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1219 | checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" |
|
1309 | checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" | |
1220 | dependencies = [ |
|
1310 | dependencies = [ | |
1221 | "cfg-if", |
|
1311 | "cfg-if", | |
1222 | "rand 0.8.5", |
|
1312 | "rand 0.8.5", | |
1223 | "static_assertions", |
|
1313 | "static_assertions", | |
1224 | ] |
|
1314 | ] | |
1225 |
|
1315 | |||
1226 | [[package]] |
|
1316 | [[package]] | |
1227 | name = "typenum" |
|
1317 | name = "typenum" | |
1228 | version = "1.15.0" |
|
1318 | version = "1.15.0" | |
1229 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1319 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1230 | checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" |
|
1320 | checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" | |
1231 |
|
1321 | |||
1232 | [[package]] |
|
1322 | [[package]] | |
1233 | name = "unicode-ident" |
|
1323 | name = "unicode-ident" | |
1234 | version = "1.0.5" |
|
1324 | version = "1.0.5" | |
1235 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1325 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1236 | checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" |
|
1326 | checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" | |
1237 |
|
1327 | |||
1238 | [[package]] |
|
1328 | [[package]] | |
1239 | name = "unicode-width" |
|
1329 | name = "unicode-width" | |
1240 | version = "0.1.10" |
|
1330 | version = "0.1.10" | |
1241 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1331 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1242 | checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" |
|
1332 | checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" | |
1243 |
|
1333 | |||
1244 | [[package]] |
|
1334 | [[package]] | |
1245 | name = "vcpkg" |
|
1335 | name = "vcpkg" | |
1246 | version = "0.2.15" |
|
1336 | version = "0.2.15" | |
1247 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1337 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1248 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" |
|
1338 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" | |
1249 |
|
1339 | |||
1250 | [[package]] |
|
1340 | [[package]] | |
1251 | name = "vcsgraph" |
|
1341 | name = "vcsgraph" | |
1252 | version = "0.2.0" |
|
1342 | version = "0.2.0" | |
1253 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1343 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1254 | checksum = "4cb68c231e2575f7503a7c19213875f9d4ec2e84e963a56ce3de4b6bee351ef7" |
|
1344 | checksum = "4cb68c231e2575f7503a7c19213875f9d4ec2e84e963a56ce3de4b6bee351ef7" | |
1255 | dependencies = [ |
|
1345 | dependencies = [ | |
1256 | "hex", |
|
1346 | "hex", | |
1257 | "rand 0.7.3", |
|
1347 | "rand 0.7.3", | |
1258 | "sha-1 0.9.8", |
|
1348 | "sha-1 0.9.8", | |
1259 | ] |
|
1349 | ] | |
1260 |
|
1350 | |||
1261 | [[package]] |
|
1351 | [[package]] | |
1262 | name = "version_check" |
|
1352 | name = "version_check" | |
1263 | version = "0.9.4" |
|
1353 | version = "0.9.4" | |
1264 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1354 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1265 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" |
|
1355 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" | |
1266 |
|
1356 | |||
1267 | [[package]] |
|
1357 | [[package]] | |
1268 | name = "wasi" |
|
1358 | name = "wasi" | |
1269 | version = "0.9.0+wasi-snapshot-preview1" |
|
1359 | version = "0.9.0+wasi-snapshot-preview1" | |
1270 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1360 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1271 | checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" |
|
1361 | checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" | |
1272 |
|
1362 | |||
1273 | [[package]] |
|
1363 | [[package]] | |
1274 | name = "wasi" |
|
1364 | name = "wasi" | |
1275 | version = "0.10.0+wasi-snapshot-preview1" |
|
1365 | version = "0.10.0+wasi-snapshot-preview1" | |
1276 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1366 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1277 | checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" |
|
1367 | checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" | |
1278 |
|
1368 | |||
1279 | [[package]] |
|
1369 | [[package]] | |
1280 | name = "wasi" |
|
1370 | name = "wasi" | |
1281 | version = "0.11.0+wasi-snapshot-preview1" |
|
1371 | version = "0.11.0+wasi-snapshot-preview1" | |
1282 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1372 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1283 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" |
|
1373 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" | |
1284 |
|
1374 | |||
1285 | [[package]] |
|
1375 | [[package]] | |
1286 | name = "wasm-bindgen" |
|
1376 | name = "wasm-bindgen" | |
1287 | version = "0.2.83" |
|
1377 | version = "0.2.83" | |
1288 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1378 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1289 | checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" |
|
1379 | checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" | |
1290 | dependencies = [ |
|
1380 | dependencies = [ | |
1291 | "cfg-if", |
|
1381 | "cfg-if", | |
1292 | "wasm-bindgen-macro", |
|
1382 | "wasm-bindgen-macro", | |
1293 | ] |
|
1383 | ] | |
1294 |
|
1384 | |||
1295 | [[package]] |
|
1385 | [[package]] | |
1296 | name = "wasm-bindgen-backend" |
|
1386 | name = "wasm-bindgen-backend" | |
1297 | version = "0.2.83" |
|
1387 | version = "0.2.83" | |
1298 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1388 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1299 | checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" |
|
1389 | checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" | |
1300 | dependencies = [ |
|
1390 | dependencies = [ | |
1301 | "bumpalo", |
|
1391 | "bumpalo", | |
1302 | "log", |
|
1392 | "log", | |
1303 | "once_cell", |
|
1393 | "once_cell", | |
1304 | "proc-macro2", |
|
1394 | "proc-macro2", | |
1305 | "quote", |
|
1395 | "quote", | |
1306 | "syn", |
|
1396 | "syn", | |
1307 | "wasm-bindgen-shared", |
|
1397 | "wasm-bindgen-shared", | |
1308 | ] |
|
1398 | ] | |
1309 |
|
1399 | |||
1310 | [[package]] |
|
1400 | [[package]] | |
1311 | name = "wasm-bindgen-macro" |
|
1401 | name = "wasm-bindgen-macro" | |
1312 | version = "0.2.83" |
|
1402 | version = "0.2.83" | |
1313 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1403 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1314 | checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" |
|
1404 | checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" | |
1315 | dependencies = [ |
|
1405 | dependencies = [ | |
1316 | "quote", |
|
1406 | "quote", | |
1317 | "wasm-bindgen-macro-support", |
|
1407 | "wasm-bindgen-macro-support", | |
1318 | ] |
|
1408 | ] | |
1319 |
|
1409 | |||
1320 | [[package]] |
|
1410 | [[package]] | |
1321 | name = "wasm-bindgen-macro-support" |
|
1411 | name = "wasm-bindgen-macro-support" | |
1322 | version = "0.2.83" |
|
1412 | version = "0.2.83" | |
1323 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1413 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1324 | checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" |
|
1414 | checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" | |
1325 | dependencies = [ |
|
1415 | dependencies = [ | |
1326 | "proc-macro2", |
|
1416 | "proc-macro2", | |
1327 | "quote", |
|
1417 | "quote", | |
1328 | "syn", |
|
1418 | "syn", | |
1329 | "wasm-bindgen-backend", |
|
1419 | "wasm-bindgen-backend", | |
1330 | "wasm-bindgen-shared", |
|
1420 | "wasm-bindgen-shared", | |
1331 | ] |
|
1421 | ] | |
1332 |
|
1422 | |||
1333 | [[package]] |
|
1423 | [[package]] | |
1334 | name = "wasm-bindgen-shared" |
|
1424 | name = "wasm-bindgen-shared" | |
1335 | version = "0.2.83" |
|
1425 | version = "0.2.83" | |
1336 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1426 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1337 | checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" |
|
1427 | checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" | |
1338 |
|
1428 | |||
1339 | [[package]] |
|
1429 | [[package]] | |
1340 | name = "web-sys" |
|
1430 | name = "web-sys" | |
1341 | version = "0.3.60" |
|
1431 | version = "0.3.60" | |
1342 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1432 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1343 | checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" |
|
1433 | checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" | |
1344 | dependencies = [ |
|
1434 | dependencies = [ | |
1345 | "js-sys", |
|
1435 | "js-sys", | |
1346 | "wasm-bindgen", |
|
1436 | "wasm-bindgen", | |
1347 | ] |
|
1437 | ] | |
1348 |
|
1438 | |||
1349 | [[package]] |
|
1439 | [[package]] | |
1350 | name = "which" |
|
1440 | name = "which" | |
1351 | version = "4.3.0" |
|
1441 | version = "4.3.0" | |
1352 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1442 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1353 | checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" |
|
1443 | checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" | |
1354 | dependencies = [ |
|
1444 | dependencies = [ | |
1355 | "either", |
|
1445 | "either", | |
1356 | "libc", |
|
1446 | "libc", | |
1357 | "once_cell", |
|
1447 | "once_cell", | |
1358 | ] |
|
1448 | ] | |
1359 |
|
1449 | |||
1360 | [[package]] |
|
1450 | [[package]] | |
1361 | name = "whoami" |
|
1451 | name = "whoami" | |
1362 | version = "1.4.0" |
|
1452 | version = "1.4.0" | |
1363 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1453 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1364 | checksum = "2c70234412ca409cc04e864e89523cb0fc37f5e1344ebed5a3ebf4192b6b9f68" |
|
1454 | checksum = "2c70234412ca409cc04e864e89523cb0fc37f5e1344ebed5a3ebf4192b6b9f68" | |
1365 | dependencies = [ |
|
1455 | dependencies = [ | |
1366 | "wasm-bindgen", |
|
1456 | "wasm-bindgen", | |
1367 | "web-sys", |
|
1457 | "web-sys", | |
1368 | ] |
|
1458 | ] | |
1369 |
|
1459 | |||
1370 | [[package]] |
|
1460 | [[package]] | |
1371 | name = "winapi" |
|
1461 | name = "winapi" | |
1372 | version = "0.3.9" |
|
1462 | version = "0.3.9" | |
1373 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1463 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1374 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" |
|
1464 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" | |
1375 | dependencies = [ |
|
1465 | dependencies = [ | |
1376 | "winapi-i686-pc-windows-gnu", |
|
1466 | "winapi-i686-pc-windows-gnu", | |
1377 | "winapi-x86_64-pc-windows-gnu", |
|
1467 | "winapi-x86_64-pc-windows-gnu", | |
1378 | ] |
|
1468 | ] | |
1379 |
|
1469 | |||
1380 | [[package]] |
|
1470 | [[package]] | |
1381 | name = "winapi-i686-pc-windows-gnu" |
|
1471 | name = "winapi-i686-pc-windows-gnu" | |
1382 | version = "0.4.0" |
|
1472 | version = "0.4.0" | |
1383 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1473 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1384 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" |
|
1474 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" | |
1385 |
|
1475 | |||
1386 | [[package]] |
|
1476 | [[package]] | |
1387 | name = "winapi-util" |
|
1477 | name = "winapi-util" | |
1388 | version = "0.1.5" |
|
1478 | version = "0.1.5" | |
1389 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1479 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1390 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" |
|
1480 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" | |
1391 | dependencies = [ |
|
1481 | dependencies = [ | |
1392 | "winapi", |
|
1482 | "winapi", | |
1393 | ] |
|
1483 | ] | |
1394 |
|
1484 | |||
1395 | [[package]] |
|
1485 | [[package]] | |
1396 | name = "winapi-x86_64-pc-windows-gnu" |
|
1486 | name = "winapi-x86_64-pc-windows-gnu" | |
1397 | version = "0.4.0" |
|
1487 | version = "0.4.0" | |
1398 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1488 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1399 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" |
|
1489 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" | |
1400 |
|
1490 | |||
1401 | [[package]] |
|
1491 | [[package]] | |
1402 | name = "yansi" |
|
1492 | name = "yansi" | |
1403 | version = "0.5.1" |
|
1493 | version = "0.5.1" | |
1404 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1494 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1405 | checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" |
|
1495 | checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" | |
1406 |
|
1496 | |||
1407 | [[package]] |
|
1497 | [[package]] | |
1408 | name = "zstd" |
|
1498 | name = "zstd" | |
1409 | version = "0.12.3+zstd.1.5.2" |
|
1499 | version = "0.12.3+zstd.1.5.2" | |
1410 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1500 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1411 | checksum = "76eea132fb024e0e13fd9c2f5d5d595d8a967aa72382ac2f9d39fcc95afd0806" |
|
1501 | checksum = "76eea132fb024e0e13fd9c2f5d5d595d8a967aa72382ac2f9d39fcc95afd0806" | |
1412 | dependencies = [ |
|
1502 | dependencies = [ | |
1413 | "zstd-safe", |
|
1503 | "zstd-safe", | |
1414 | ] |
|
1504 | ] | |
1415 |
|
1505 | |||
1416 | [[package]] |
|
1506 | [[package]] | |
1417 | name = "zstd-safe" |
|
1507 | name = "zstd-safe" | |
1418 | version = "6.0.4+zstd.1.5.4" |
|
1508 | version = "6.0.4+zstd.1.5.4" | |
1419 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1509 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1420 | checksum = "7afb4b54b8910cf5447638cb54bf4e8a65cbedd783af98b98c62ffe91f185543" |
|
1510 | checksum = "7afb4b54b8910cf5447638cb54bf4e8a65cbedd783af98b98c62ffe91f185543" | |
1421 | dependencies = [ |
|
1511 | dependencies = [ | |
1422 | "libc", |
|
1512 | "libc", | |
1423 | "zstd-sys", |
|
1513 | "zstd-sys", | |
1424 | ] |
|
1514 | ] | |
1425 |
|
1515 | |||
1426 | [[package]] |
|
1516 | [[package]] | |
1427 | name = "zstd-sys" |
|
1517 | name = "zstd-sys" | |
1428 | version = "2.0.7+zstd.1.5.4" |
|
1518 | version = "2.0.7+zstd.1.5.4" | |
1429 | source = "registry+https://github.com/rust-lang/crates.io-index" |
|
1519 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1430 | checksum = "94509c3ba2fe55294d752b79842c530ccfab760192521df74a081a78d2b3c7f5" |
|
1520 | checksum = "94509c3ba2fe55294d752b79842c530ccfab760192521df74a081a78d2b3c7f5" | |
1431 | dependencies = [ |
|
1521 | dependencies = [ | |
1432 | "cc", |
|
1522 | "cc", | |
1433 | "libc", |
|
1523 | "libc", | |
1434 | "pkg-config", |
|
1524 | "pkg-config", | |
1435 | ] |
|
1525 | ] |
@@ -1,50 +1,52 b'' | |||||
1 | [package] |
|
1 | [package] | |
2 | name = "hg-core" |
|
2 | name = "hg-core" | |
3 | version = "0.1.0" |
|
3 | version = "0.1.0" | |
4 | authors = ["Georges Racinet <gracinet@anybox.fr>"] |
|
4 | authors = ["Georges Racinet <gracinet@anybox.fr>"] | |
5 | description = "Mercurial pure Rust core library, with no assumption on Python bindings (FFI)" |
|
5 | description = "Mercurial pure Rust core library, with no assumption on Python bindings (FFI)" | |
6 | edition = "2021" |
|
6 | edition = "2021" | |
7 |
|
7 | |||
8 | [lib] |
|
8 | [lib] | |
9 | name = "hg" |
|
9 | name = "hg" | |
10 |
|
10 | |||
11 | [dependencies] |
|
11 | [dependencies] | |
12 | bitflags = "1.3.2" |
|
12 | bitflags = "1.3.2" | |
13 | bytes-cast = "0.3.0" |
|
13 | bytes-cast = "0.3.0" | |
14 | byteorder = "1.4.3" |
|
14 | byteorder = "1.4.3" | |
15 | derive_more = "0.99.17" |
|
15 | derive_more = "0.99.17" | |
16 | hashbrown = { version = "0.13.1", features = ["rayon"] } |
|
16 | hashbrown = { version = "0.13.1", features = ["rayon"] } | |
17 | home = "0.5.4" |
|
17 | home = "0.5.4" | |
18 | im-rc = "15.1.0" |
|
18 | im-rc = "15.1.0" | |
19 | itertools = "0.10.5" |
|
19 | itertools = "0.10.5" | |
20 | lazy_static = "1.4.0" |
|
20 | lazy_static = "1.4.0" | |
21 | libc = "0.2.137" |
|
21 | libc = "0.2.137" | |
22 | logging_timer = "1.1.0" |
|
22 | logging_timer = "1.1.0" | |
23 | rand = "0.8.5" |
|
23 | rand = "0.8.5" | |
24 | rand_pcg = "0.3.1" |
|
24 | rand_pcg = "0.3.1" | |
25 | rand_distr = "0.4.3" |
|
25 | rand_distr = "0.4.3" | |
26 | rayon = "1.7.0" |
|
26 | rayon = "1.7.0" | |
27 | regex = "1.7.0" |
|
27 | regex = "1.7.0" | |
28 | self_cell = "1.0" |
|
28 | self_cell = "1.0" | |
|
29 | serde = { version = "1.0", features = ["derive"] } | |||
29 | sha-1 = "0.10.0" |
|
30 | sha-1 = "0.10.0" | |
30 | twox-hash = "1.6.3" |
|
31 | twox-hash = "1.6.3" | |
31 | same-file = "1.0.6" |
|
32 | same-file = "1.0.6" | |
32 | tempfile = "3.3.0" |
|
33 | tempfile = "3.3.0" | |
|
34 | toml = "0.6" | |||
33 | thread_local = "1.1.4" |
|
35 | thread_local = "1.1.4" | |
34 | crossbeam-channel = "0.5.6" |
|
36 | crossbeam-channel = "0.5.6" | |
35 | log = "0.4.17" |
|
37 | log = "0.4.17" | |
36 | memmap2 = { version = "0.5.8", features = ["stable_deref_trait"] } |
|
38 | memmap2 = { version = "0.5.8", features = ["stable_deref_trait"] } | |
37 | zstd = "0.12" |
|
39 | zstd = "0.12" | |
38 | format-bytes = "0.3.0" |
|
40 | format-bytes = "0.3.0" | |
39 | once_cell = "1.16.0" |
|
41 | once_cell = "1.16.0" | |
40 |
|
42 | |||
41 | # We don't use the `miniz-oxide` backend to not change rhg benchmarks and until |
|
43 | # We don't use the `miniz-oxide` backend to not change rhg benchmarks and until | |
42 | # we have a clearer view of which backend is the fastest. |
|
44 | # we have a clearer view of which backend is the fastest. | |
43 | [dependencies.flate2] |
|
45 | [dependencies.flate2] | |
44 | version = "1.0.24" |
|
46 | version = "1.0.24" | |
45 | features = ["zlib"] |
|
47 | features = ["zlib"] | |
46 | default-features = false |
|
48 | default-features = false | |
47 |
|
49 | |||
48 | [dev-dependencies] |
|
50 | [dev-dependencies] | |
49 |
clap = { version = "4.0 |
|
51 | clap = { version = "~4.0", features = ["derive"] } | |
50 | pretty_assertions = "1.1.0" |
|
52 | pretty_assertions = "1.1.0" |
@@ -1,345 +1,349 b'' | |||||
1 | // layer.rs |
|
1 | // layer.rs | |
2 | // |
|
2 | // | |
3 | // Copyright 2020 |
|
3 | // Copyright 2020 | |
4 | // Valentin Gatien-Baron, |
|
4 | // Valentin Gatien-Baron, | |
5 | // Raphaël Gomès <rgomes@octobus.net> |
|
5 | // Raphaël Gomès <rgomes@octobus.net> | |
6 | // |
|
6 | // | |
7 | // This software may be used and distributed according to the terms of the |
|
7 | // This software may be used and distributed according to the terms of the | |
8 | // GNU General Public License version 2 or any later version. |
|
8 | // GNU General Public License version 2 or any later version. | |
9 |
|
9 | |||
10 | use crate::errors::HgError; |
|
10 | use crate::errors::HgError; | |
11 | use crate::exit_codes::CONFIG_PARSE_ERROR_ABORT; |
|
11 | use crate::exit_codes::CONFIG_PARSE_ERROR_ABORT; | |
12 | use crate::utils::files::{get_bytes_from_path, get_path_from_bytes}; |
|
12 | use crate::utils::files::{get_bytes_from_path, get_path_from_bytes}; | |
13 | use format_bytes::{format_bytes, write_bytes, DisplayBytes}; |
|
13 | use format_bytes::{format_bytes, write_bytes, DisplayBytes}; | |
14 | use lazy_static::lazy_static; |
|
14 | use lazy_static::lazy_static; | |
15 | use regex::bytes::Regex; |
|
15 | use regex::bytes::Regex; | |
16 | use std::collections::HashMap; |
|
16 | use std::collections::HashMap; | |
17 | use std::path::{Path, PathBuf}; |
|
17 | use std::path::{Path, PathBuf}; | |
18 |
|
18 | |||
19 | lazy_static! { |
|
19 | lazy_static! { | |
20 | static ref SECTION_RE: Regex = make_regex(r"^\[([^\[]+)\]"); |
|
20 | static ref SECTION_RE: Regex = make_regex(r"^\[([^\[]+)\]"); | |
21 | static ref ITEM_RE: Regex = make_regex(r"^([^=\s][^=]*?)\s*=\s*((.*\S)?)"); |
|
21 | static ref ITEM_RE: Regex = make_regex(r"^([^=\s][^=]*?)\s*=\s*((.*\S)?)"); | |
22 | /// Continuation whitespace |
|
22 | /// Continuation whitespace | |
23 | static ref CONT_RE: Regex = make_regex(r"^\s+(\S|\S.*\S)\s*$"); |
|
23 | static ref CONT_RE: Regex = make_regex(r"^\s+(\S|\S.*\S)\s*$"); | |
24 | static ref EMPTY_RE: Regex = make_regex(r"^(;|#|\s*$)"); |
|
24 | static ref EMPTY_RE: Regex = make_regex(r"^(;|#|\s*$)"); | |
25 | static ref COMMENT_RE: Regex = make_regex(r"^(;|#)"); |
|
25 | static ref COMMENT_RE: Regex = make_regex(r"^(;|#)"); | |
26 | /// A directive that allows for removing previous entries |
|
26 | /// A directive that allows for removing previous entries | |
27 | static ref UNSET_RE: Regex = make_regex(r"^%unset\s+(\S+)"); |
|
27 | static ref UNSET_RE: Regex = make_regex(r"^%unset\s+(\S+)"); | |
28 | /// A directive that allows for including other config files |
|
28 | /// A directive that allows for including other config files | |
29 | static ref INCLUDE_RE: Regex = make_regex(r"^%include\s+(\S|\S.*\S)\s*$"); |
|
29 | static ref INCLUDE_RE: Regex = make_regex(r"^%include\s+(\S|\S.*\S)\s*$"); | |
30 | } |
|
30 | } | |
31 |
|
31 | |||
32 | /// All config values separated by layers of precedence. |
|
32 | /// All config values separated by layers of precedence. | |
33 | /// Each config source may be split in multiple layers if `%include` directives |
|
33 | /// Each config source may be split in multiple layers if `%include` directives | |
34 | /// are used. |
|
34 | /// are used. | |
35 | /// TODO detail the general precedence |
|
35 | /// TODO detail the general precedence | |
36 | #[derive(Clone)] |
|
36 | #[derive(Clone)] | |
37 | pub struct ConfigLayer { |
|
37 | pub struct ConfigLayer { | |
38 | /// Mapping of the sections to their items |
|
38 | /// Mapping of the sections to their items | |
39 | sections: HashMap<Vec<u8>, ConfigItem>, |
|
39 | sections: HashMap<Vec<u8>, ConfigItem>, | |
40 | /// All sections (and their items/values) in a layer share the same origin |
|
40 | /// All sections (and their items/values) in a layer share the same origin | |
41 | pub origin: ConfigOrigin, |
|
41 | pub origin: ConfigOrigin, | |
42 | /// Whether this layer comes from a trusted user or group |
|
42 | /// Whether this layer comes from a trusted user or group | |
43 | pub trusted: bool, |
|
43 | pub trusted: bool, | |
44 | } |
|
44 | } | |
45 |
|
45 | |||
46 | impl ConfigLayer { |
|
46 | impl ConfigLayer { | |
47 | pub fn new(origin: ConfigOrigin) -> Self { |
|
47 | pub fn new(origin: ConfigOrigin) -> Self { | |
48 | ConfigLayer { |
|
48 | ConfigLayer { | |
49 | sections: HashMap::new(), |
|
49 | sections: HashMap::new(), | |
50 | trusted: true, // TODO check |
|
50 | trusted: true, // TODO check | |
51 | origin, |
|
51 | origin, | |
52 | } |
|
52 | } | |
53 | } |
|
53 | } | |
54 |
|
54 | |||
55 | /// Parse `--config` CLI arguments and return a layer if there’s any |
|
55 | /// Parse `--config` CLI arguments and return a layer if there’s any | |
56 | pub(crate) fn parse_cli_args( |
|
56 | pub(crate) fn parse_cli_args( | |
57 | cli_config_args: impl IntoIterator<Item = impl AsRef<[u8]>>, |
|
57 | cli_config_args: impl IntoIterator<Item = impl AsRef<[u8]>>, | |
58 | ) -> Result<Option<Self>, ConfigError> { |
|
58 | ) -> Result<Option<Self>, ConfigError> { | |
59 | fn parse_one(arg: &[u8]) -> Option<(Vec<u8>, Vec<u8>, Vec<u8>)> { |
|
59 | fn parse_one(arg: &[u8]) -> Option<(Vec<u8>, Vec<u8>, Vec<u8>)> { | |
60 | use crate::utils::SliceExt; |
|
60 | use crate::utils::SliceExt; | |
61 |
|
61 | |||
62 | let (section_and_item, value) = arg.split_2(b'=')?; |
|
62 | let (section_and_item, value) = arg.split_2(b'=')?; | |
63 | let (section, item) = section_and_item.trim().split_2(b'.')?; |
|
63 | let (section, item) = section_and_item.trim().split_2(b'.')?; | |
64 | Some(( |
|
64 | Some(( | |
65 | section.to_owned(), |
|
65 | section.to_owned(), | |
66 | item.to_owned(), |
|
66 | item.to_owned(), | |
67 | value.trim().to_owned(), |
|
67 | value.trim().to_owned(), | |
68 | )) |
|
68 | )) | |
69 | } |
|
69 | } | |
70 |
|
70 | |||
71 | let mut layer = Self::new(ConfigOrigin::CommandLine); |
|
71 | let mut layer = Self::new(ConfigOrigin::CommandLine); | |
72 | for arg in cli_config_args { |
|
72 | for arg in cli_config_args { | |
73 | let arg = arg.as_ref(); |
|
73 | let arg = arg.as_ref(); | |
74 | if let Some((section, item, value)) = parse_one(arg) { |
|
74 | if let Some((section, item, value)) = parse_one(arg) { | |
75 | layer.add(section, item, value, None); |
|
75 | layer.add(section, item, value, None); | |
76 | } else { |
|
76 | } else { | |
77 | Err(HgError::abort( |
|
77 | Err(HgError::abort( | |
78 | format!( |
|
78 | format!( | |
79 | "abort: malformed --config option: '{}' \ |
|
79 | "abort: malformed --config option: '{}' \ | |
80 | (use --config section.name=value)", |
|
80 | (use --config section.name=value)", | |
81 | String::from_utf8_lossy(arg), |
|
81 | String::from_utf8_lossy(arg), | |
82 | ), |
|
82 | ), | |
83 | CONFIG_PARSE_ERROR_ABORT, |
|
83 | CONFIG_PARSE_ERROR_ABORT, | |
84 | None, |
|
84 | None, | |
85 | ))? |
|
85 | ))? | |
86 | } |
|
86 | } | |
87 | } |
|
87 | } | |
88 | if layer.sections.is_empty() { |
|
88 | if layer.sections.is_empty() { | |
89 | Ok(None) |
|
89 | Ok(None) | |
90 | } else { |
|
90 | } else { | |
91 | Ok(Some(layer)) |
|
91 | Ok(Some(layer)) | |
92 | } |
|
92 | } | |
93 | } |
|
93 | } | |
94 |
|
94 | |||
95 | /// Returns whether this layer comes from `--config` CLI arguments |
|
95 | /// Returns whether this layer comes from `--config` CLI arguments | |
96 | pub(crate) fn is_from_command_line(&self) -> bool { |
|
96 | pub(crate) fn is_from_command_line(&self) -> bool { | |
97 | matches!(self.origin, ConfigOrigin::CommandLine) |
|
97 | matches!(self.origin, ConfigOrigin::CommandLine) | |
98 | } |
|
98 | } | |
99 |
|
99 | |||
100 | /// Add an entry to the config, overwriting the old one if already present. |
|
100 | /// Add an entry to the config, overwriting the old one if already present. | |
101 | pub fn add( |
|
101 | pub fn add( | |
102 | &mut self, |
|
102 | &mut self, | |
103 | section: Vec<u8>, |
|
103 | section: Vec<u8>, | |
104 | item: Vec<u8>, |
|
104 | item: Vec<u8>, | |
105 | value: Vec<u8>, |
|
105 | value: Vec<u8>, | |
106 | line: Option<usize>, |
|
106 | line: Option<usize>, | |
107 | ) { |
|
107 | ) { | |
108 | self.sections |
|
108 | self.sections | |
109 | .entry(section) |
|
109 | .entry(section) | |
110 | .or_insert_with(HashMap::new) |
|
110 | .or_insert_with(HashMap::new) | |
111 | .insert(item, ConfigValue { bytes: value, line }); |
|
111 | .insert(item, ConfigValue { bytes: value, line }); | |
112 | } |
|
112 | } | |
113 |
|
113 | |||
114 | /// Returns the config value in `<section>.<item>` if it exists |
|
114 | /// Returns the config value in `<section>.<item>` if it exists | |
115 | pub fn get(&self, section: &[u8], item: &[u8]) -> Option<&ConfigValue> { |
|
115 | pub fn get(&self, section: &[u8], item: &[u8]) -> Option<&ConfigValue> { | |
116 | self.sections.get(section)?.get(item) |
|
116 | self.sections.get(section)?.get(item) | |
117 | } |
|
117 | } | |
118 |
|
118 | |||
119 | /// Returns the keys defined in the given section |
|
119 | /// Returns the keys defined in the given section | |
120 | pub fn iter_keys(&self, section: &[u8]) -> impl Iterator<Item = &[u8]> { |
|
120 | pub fn iter_keys(&self, section: &[u8]) -> impl Iterator<Item = &[u8]> { | |
121 | self.sections |
|
121 | self.sections | |
122 | .get(section) |
|
122 | .get(section) | |
123 | .into_iter() |
|
123 | .into_iter() | |
124 | .flat_map(|section| section.keys().map(|vec| &**vec)) |
|
124 | .flat_map(|section| section.keys().map(|vec| &**vec)) | |
125 | } |
|
125 | } | |
126 |
|
126 | |||
127 | /// Returns the (key, value) pairs defined in the given section |
|
127 | /// Returns the (key, value) pairs defined in the given section | |
128 | pub fn iter_section<'layer>( |
|
128 | pub fn iter_section<'layer>( | |
129 | &'layer self, |
|
129 | &'layer self, | |
130 | section: &[u8], |
|
130 | section: &[u8], | |
131 | ) -> impl Iterator<Item = (&'layer [u8], &'layer [u8])> { |
|
131 | ) -> impl Iterator<Item = (&'layer [u8], &'layer [u8])> { | |
132 | self.sections |
|
132 | self.sections | |
133 | .get(section) |
|
133 | .get(section) | |
134 | .into_iter() |
|
134 | .into_iter() | |
135 | .flat_map(|section| section.iter().map(|(k, v)| (&**k, &*v.bytes))) |
|
135 | .flat_map(|section| section.iter().map(|(k, v)| (&**k, &*v.bytes))) | |
136 | } |
|
136 | } | |
137 |
|
137 | |||
138 | /// Returns whether any key is defined in the given section |
|
138 | /// Returns whether any key is defined in the given section | |
139 | pub fn has_non_empty_section(&self, section: &[u8]) -> bool { |
|
139 | pub fn has_non_empty_section(&self, section: &[u8]) -> bool { | |
140 | self.sections |
|
140 | self.sections | |
141 | .get(section) |
|
141 | .get(section) | |
142 | .map_or(false, |section| !section.is_empty()) |
|
142 | .map_or(false, |section| !section.is_empty()) | |
143 | } |
|
143 | } | |
144 |
|
144 | |||
145 | pub fn is_empty(&self) -> bool { |
|
145 | pub fn is_empty(&self) -> bool { | |
146 | self.sections.is_empty() |
|
146 | self.sections.is_empty() | |
147 | } |
|
147 | } | |
148 |
|
148 | |||
149 | /// Returns a `Vec` of layers in order of precedence (so, in read order), |
|
149 | /// Returns a `Vec` of layers in order of precedence (so, in read order), | |
150 | /// recursively parsing the `%include` directives if any. |
|
150 | /// recursively parsing the `%include` directives if any. | |
151 | pub fn parse(src: &Path, data: &[u8]) -> Result<Vec<Self>, ConfigError> { |
|
151 | pub fn parse(src: &Path, data: &[u8]) -> Result<Vec<Self>, ConfigError> { | |
152 | let mut layers = vec![]; |
|
152 | let mut layers = vec![]; | |
153 |
|
153 | |||
154 | // Discard byte order mark if any |
|
154 | // Discard byte order mark if any | |
155 | let data = if data.starts_with(b"\xef\xbb\xbf") { |
|
155 | let data = if data.starts_with(b"\xef\xbb\xbf") { | |
156 | &data[3..] |
|
156 | &data[3..] | |
157 | } else { |
|
157 | } else { | |
158 | data |
|
158 | data | |
159 | }; |
|
159 | }; | |
160 |
|
160 | |||
161 | // TODO check if it's trusted |
|
161 | // TODO check if it's trusted | |
162 | let mut current_layer = Self::new(ConfigOrigin::File(src.to_owned())); |
|
162 | let mut current_layer = Self::new(ConfigOrigin::File(src.to_owned())); | |
163 |
|
163 | |||
164 | let mut lines_iter = |
|
164 | let mut lines_iter = | |
165 | data.split(|b| *b == b'\n').enumerate().peekable(); |
|
165 | data.split(|b| *b == b'\n').enumerate().peekable(); | |
166 | let mut section = b"".to_vec(); |
|
166 | let mut section = b"".to_vec(); | |
167 |
|
167 | |||
168 | while let Some((index, bytes)) = lines_iter.next() { |
|
168 | while let Some((index, bytes)) = lines_iter.next() { | |
169 | let line = Some(index + 1); |
|
169 | let line = Some(index + 1); | |
170 | if let Some(m) = INCLUDE_RE.captures(bytes) { |
|
170 | if let Some(m) = INCLUDE_RE.captures(bytes) { | |
171 | let filename_bytes = &m[1]; |
|
171 | let filename_bytes = &m[1]; | |
172 | let filename_bytes = crate::utils::expand_vars(filename_bytes); |
|
172 | let filename_bytes = crate::utils::expand_vars(filename_bytes); | |
173 | // `Path::parent` only fails for the root directory, |
|
173 | // `Path::parent` only fails for the root directory, | |
174 | // which `src` can’t be since we’ve managed to open it as a |
|
174 | // which `src` can’t be since we’ve managed to open it as a | |
175 | // file. |
|
175 | // file. | |
176 | let dir = src |
|
176 | let dir = src | |
177 | .parent() |
|
177 | .parent() | |
178 | .expect("Path::parent fail on a file we’ve read"); |
|
178 | .expect("Path::parent fail on a file we’ve read"); | |
179 | // `Path::join` with an absolute argument correctly ignores the |
|
179 | // `Path::join` with an absolute argument correctly ignores the | |
180 | // base path |
|
180 | // base path | |
181 | let filename = dir.join(&get_path_from_bytes(&filename_bytes)); |
|
181 | let filename = dir.join(&get_path_from_bytes(&filename_bytes)); | |
182 | match std::fs::read(&filename) { |
|
182 | match std::fs::read(&filename) { | |
183 | Ok(data) => { |
|
183 | Ok(data) => { | |
184 | layers.push(current_layer); |
|
184 | layers.push(current_layer); | |
185 | layers.extend(Self::parse(&filename, &data)?); |
|
185 | layers.extend(Self::parse(&filename, &data)?); | |
186 | current_layer = |
|
186 | current_layer = | |
187 | Self::new(ConfigOrigin::File(src.to_owned())); |
|
187 | Self::new(ConfigOrigin::File(src.to_owned())); | |
188 | } |
|
188 | } | |
189 | Err(error) => { |
|
189 | Err(error) => { | |
190 | if error.kind() != std::io::ErrorKind::NotFound { |
|
190 | if error.kind() != std::io::ErrorKind::NotFound { | |
191 | return Err(ConfigParseError { |
|
191 | return Err(ConfigParseError { | |
192 | origin: ConfigOrigin::File(src.to_owned()), |
|
192 | origin: ConfigOrigin::File(src.to_owned()), | |
193 | line, |
|
193 | line, | |
194 | message: format_bytes!( |
|
194 | message: format_bytes!( | |
195 | b"cannot include {} ({})", |
|
195 | b"cannot include {} ({})", | |
196 | filename_bytes, |
|
196 | filename_bytes, | |
197 | format_bytes::Utf8(error) |
|
197 | format_bytes::Utf8(error) | |
198 | ), |
|
198 | ), | |
199 | } |
|
199 | } | |
200 | .into()); |
|
200 | .into()); | |
201 | } |
|
201 | } | |
202 | } |
|
202 | } | |
203 | } |
|
203 | } | |
204 | } else if EMPTY_RE.captures(bytes).is_some() { |
|
204 | } else if EMPTY_RE.captures(bytes).is_some() { | |
205 | } else if let Some(m) = SECTION_RE.captures(bytes) { |
|
205 | } else if let Some(m) = SECTION_RE.captures(bytes) { | |
206 | section = m[1].to_vec(); |
|
206 | section = m[1].to_vec(); | |
207 | } else if let Some(m) = ITEM_RE.captures(bytes) { |
|
207 | } else if let Some(m) = ITEM_RE.captures(bytes) { | |
208 | let item = m[1].to_vec(); |
|
208 | let item = m[1].to_vec(); | |
209 | let mut value = m[2].to_vec(); |
|
209 | let mut value = m[2].to_vec(); | |
210 | loop { |
|
210 | loop { | |
211 | match lines_iter.peek() { |
|
211 | match lines_iter.peek() { | |
212 | None => break, |
|
212 | None => break, | |
213 | Some((_, v)) => { |
|
213 | Some((_, v)) => { | |
214 | if COMMENT_RE.captures(v).is_some() { |
|
214 | if COMMENT_RE.captures(v).is_some() { | |
215 | } else if CONT_RE.captures(v).is_some() { |
|
215 | } else if CONT_RE.captures(v).is_some() { | |
216 | value.extend(b"\n"); |
|
216 | value.extend(b"\n"); | |
217 | value.extend(&m[1]); |
|
217 | value.extend(&m[1]); | |
218 | } else { |
|
218 | } else { | |
219 | break; |
|
219 | break; | |
220 | } |
|
220 | } | |
221 | } |
|
221 | } | |
222 | }; |
|
222 | }; | |
223 | lines_iter.next(); |
|
223 | lines_iter.next(); | |
224 | } |
|
224 | } | |
225 | current_layer.add(section.clone(), item, value, line); |
|
225 | current_layer.add(section.clone(), item, value, line); | |
226 | } else if let Some(m) = UNSET_RE.captures(bytes) { |
|
226 | } else if let Some(m) = UNSET_RE.captures(bytes) { | |
227 | if let Some(map) = current_layer.sections.get_mut(§ion) { |
|
227 | if let Some(map) = current_layer.sections.get_mut(§ion) { | |
228 | map.remove(&m[1]); |
|
228 | map.remove(&m[1]); | |
229 | } |
|
229 | } | |
230 | } else { |
|
230 | } else { | |
231 | let message = if bytes.starts_with(b" ") { |
|
231 | let message = if bytes.starts_with(b" ") { | |
232 | format_bytes!(b"unexpected leading whitespace: {}", bytes) |
|
232 | format_bytes!(b"unexpected leading whitespace: {}", bytes) | |
233 | } else { |
|
233 | } else { | |
234 | bytes.to_owned() |
|
234 | bytes.to_owned() | |
235 | }; |
|
235 | }; | |
236 | return Err(ConfigParseError { |
|
236 | return Err(ConfigParseError { | |
237 | origin: ConfigOrigin::File(src.to_owned()), |
|
237 | origin: ConfigOrigin::File(src.to_owned()), | |
238 | line, |
|
238 | line, | |
239 | message, |
|
239 | message, | |
240 | } |
|
240 | } | |
241 | .into()); |
|
241 | .into()); | |
242 | } |
|
242 | } | |
243 | } |
|
243 | } | |
244 | if !current_layer.is_empty() { |
|
244 | if !current_layer.is_empty() { | |
245 | layers.push(current_layer); |
|
245 | layers.push(current_layer); | |
246 | } |
|
246 | } | |
247 | Ok(layers) |
|
247 | Ok(layers) | |
248 | } |
|
248 | } | |
249 | } |
|
249 | } | |
250 |
|
250 | |||
251 | impl DisplayBytes for ConfigLayer { |
|
251 | impl DisplayBytes for ConfigLayer { | |
252 | fn display_bytes( |
|
252 | fn display_bytes( | |
253 | &self, |
|
253 | &self, | |
254 | out: &mut dyn std::io::Write, |
|
254 | out: &mut dyn std::io::Write, | |
255 | ) -> std::io::Result<()> { |
|
255 | ) -> std::io::Result<()> { | |
256 | let mut sections: Vec<_> = self.sections.iter().collect(); |
|
256 | let mut sections: Vec<_> = self.sections.iter().collect(); | |
257 | sections.sort_by(|e0, e1| e0.0.cmp(e1.0)); |
|
257 | sections.sort_by(|e0, e1| e0.0.cmp(e1.0)); | |
258 |
|
258 | |||
259 | for (section, items) in sections.into_iter() { |
|
259 | for (section, items) in sections.into_iter() { | |
260 | let mut items: Vec<_> = items.iter().collect(); |
|
260 | let mut items: Vec<_> = items.iter().collect(); | |
261 | items.sort_by(|e0, e1| e0.0.cmp(e1.0)); |
|
261 | items.sort_by(|e0, e1| e0.0.cmp(e1.0)); | |
262 |
|
262 | |||
263 | for (item, config_entry) in items { |
|
263 | for (item, config_entry) in items { | |
264 | write_bytes!( |
|
264 | write_bytes!( | |
265 | out, |
|
265 | out, | |
266 | b"{}.{}={} # {}\n", |
|
266 | b"{}.{}={} # {}\n", | |
267 | section, |
|
267 | section, | |
268 | item, |
|
268 | item, | |
269 | &config_entry.bytes, |
|
269 | &config_entry.bytes, | |
270 | &self.origin, |
|
270 | &self.origin, | |
271 | )? |
|
271 | )? | |
272 | } |
|
272 | } | |
273 | } |
|
273 | } | |
274 | Ok(()) |
|
274 | Ok(()) | |
275 | } |
|
275 | } | |
276 | } |
|
276 | } | |
277 |
|
277 | |||
278 | /// Mapping of section item to value. |
|
278 | /// Mapping of section item to value. | |
279 | /// In the following: |
|
279 | /// In the following: | |
280 | /// ```text |
|
280 | /// ```text | |
281 | /// [ui] |
|
281 | /// [ui] | |
282 | /// paginate=no |
|
282 | /// paginate=no | |
283 | /// ``` |
|
283 | /// ``` | |
284 | /// "paginate" is the section item and "no" the value. |
|
284 | /// "paginate" is the section item and "no" the value. | |
285 | pub type ConfigItem = HashMap<Vec<u8>, ConfigValue>; |
|
285 | pub type ConfigItem = HashMap<Vec<u8>, ConfigValue>; | |
286 |
|
286 | |||
287 | #[derive(Clone, Debug, PartialEq)] |
|
287 | #[derive(Clone, Debug, PartialEq)] | |
288 | pub struct ConfigValue { |
|
288 | pub struct ConfigValue { | |
289 | /// The raw bytes of the value (be it from the CLI, env or from a file) |
|
289 | /// The raw bytes of the value (be it from the CLI, env or from a file) | |
290 | pub bytes: Vec<u8>, |
|
290 | pub bytes: Vec<u8>, | |
291 | /// Only present if the value comes from a file, 1-indexed. |
|
291 | /// Only present if the value comes from a file, 1-indexed. | |
292 | pub line: Option<usize>, |
|
292 | pub line: Option<usize>, | |
293 | } |
|
293 | } | |
294 |
|
294 | |||
295 | #[derive(Clone, Debug, PartialEq, Eq)] |
|
295 | #[derive(Clone, Debug, PartialEq, Eq)] | |
296 | pub enum ConfigOrigin { |
|
296 | pub enum ConfigOrigin { | |
297 | /// From a configuration file |
|
297 | /// From a configuration file | |
298 | File(PathBuf), |
|
298 | File(PathBuf), | |
299 | /// From [ui.tweakdefaults] |
|
299 | /// From [ui.tweakdefaults] | |
300 | Tweakdefaults, |
|
300 | Tweakdefaults, | |
301 | /// From a `--config` CLI argument |
|
301 | /// From a `--config` CLI argument | |
302 | CommandLine, |
|
302 | CommandLine, | |
303 | /// From a `--color` CLI argument |
|
303 | /// From a `--color` CLI argument | |
304 | CommandLineColor, |
|
304 | CommandLineColor, | |
305 | /// From environment variables like `$PAGER` or `$EDITOR` |
|
305 | /// From environment variables like `$PAGER` or `$EDITOR` | |
306 | Environment(Vec<u8>), |
|
306 | Environment(Vec<u8>), | |
307 | /* TODO defaults (configitems.py) |
|
307 | /// From configitems.toml | |
308 | * TODO extensions |
|
308 | Defaults, | |
|
309 | /* TODO extensions | |||
309 | * TODO Python resources? |
|
310 | * TODO Python resources? | |
310 | * Others? */ |
|
311 | * Others? */ | |
311 | } |
|
312 | } | |
312 |
|
313 | |||
313 | impl DisplayBytes for ConfigOrigin { |
|
314 | impl DisplayBytes for ConfigOrigin { | |
314 | fn display_bytes( |
|
315 | fn display_bytes( | |
315 | &self, |
|
316 | &self, | |
316 | out: &mut dyn std::io::Write, |
|
317 | out: &mut dyn std::io::Write, | |
317 | ) -> std::io::Result<()> { |
|
318 | ) -> std::io::Result<()> { | |
318 | match self { |
|
319 | match self { | |
319 | ConfigOrigin::File(p) => out.write_all(&get_bytes_from_path(p)), |
|
320 | ConfigOrigin::File(p) => out.write_all(&get_bytes_from_path(p)), | |
320 | ConfigOrigin::CommandLine => out.write_all(b"--config"), |
|
321 | ConfigOrigin::CommandLine => out.write_all(b"--config"), | |
321 | ConfigOrigin::CommandLineColor => out.write_all(b"--color"), |
|
322 | ConfigOrigin::CommandLineColor => out.write_all(b"--color"), | |
322 | ConfigOrigin::Environment(e) => write_bytes!(out, b"${}", e), |
|
323 | ConfigOrigin::Environment(e) => write_bytes!(out, b"${}", e), | |
323 | ConfigOrigin::Tweakdefaults => { |
|
324 | ConfigOrigin::Tweakdefaults => { | |
324 | write_bytes!(out, b"ui.tweakdefaults") |
|
325 | write_bytes!(out, b"ui.tweakdefaults") | |
325 | } |
|
326 | } | |
|
327 | ConfigOrigin::Defaults => { | |||
|
328 | write_bytes!(out, b"configitems.toml") | |||
|
329 | } | |||
326 | } |
|
330 | } | |
327 | } |
|
331 | } | |
328 | } |
|
332 | } | |
329 |
|
333 | |||
330 | #[derive(Debug)] |
|
334 | #[derive(Debug)] | |
331 | pub struct ConfigParseError { |
|
335 | pub struct ConfigParseError { | |
332 | pub origin: ConfigOrigin, |
|
336 | pub origin: ConfigOrigin, | |
333 | pub line: Option<usize>, |
|
337 | pub line: Option<usize>, | |
334 | pub message: Vec<u8>, |
|
338 | pub message: Vec<u8>, | |
335 | } |
|
339 | } | |
336 |
|
340 | |||
337 | #[derive(Debug, derive_more::From)] |
|
341 | #[derive(Debug, derive_more::From)] | |
338 | pub enum ConfigError { |
|
342 | pub enum ConfigError { | |
339 | Parse(ConfigParseError), |
|
343 | Parse(ConfigParseError), | |
340 | Other(HgError), |
|
344 | Other(HgError), | |
341 | } |
|
345 | } | |
342 |
|
346 | |||
343 | fn make_regex(pattern: &'static str) -> Regex { |
|
347 | fn make_regex(pattern: &'static str) -> Regex { | |
344 | Regex::new(pattern).expect("expected a valid regex") |
|
348 | Regex::new(pattern).expect("expected a valid regex") | |
345 | } |
|
349 | } |
@@ -1,636 +1,674 b'' | |||||
1 | // config.rs |
|
1 | // config.rs | |
2 | // |
|
2 | // | |
3 | // Copyright 2020 |
|
3 | // Copyright 2020 | |
4 | // Valentin Gatien-Baron, |
|
4 | // Valentin Gatien-Baron, | |
5 | // Raphaël Gomès <rgomes@octobus.net> |
|
5 | // Raphaël Gomès <rgomes@octobus.net> | |
6 | // |
|
6 | // | |
7 | // This software may be used and distributed according to the terms of the |
|
7 | // This software may be used and distributed according to the terms of the | |
8 | // GNU General Public License version 2 or any later version. |
|
8 | // GNU General Public License version 2 or any later version. | |
9 |
|
9 | |||
10 | //! Mercurial config parsing and interfaces. |
|
10 | //! Mercurial config parsing and interfaces. | |
11 |
|
11 | |||
|
12 | pub mod config_items; | |||
12 | mod layer; |
|
13 | mod layer; | |
13 | mod plain_info; |
|
14 | mod plain_info; | |
14 | mod values; |
|
15 | mod values; | |
15 | pub use layer::{ConfigError, ConfigOrigin, ConfigParseError}; |
|
16 | pub use layer::{ConfigError, ConfigOrigin, ConfigParseError}; | |
|
17 | use lazy_static::lazy_static; | |||
16 | pub use plain_info::PlainInfo; |
|
18 | pub use plain_info::PlainInfo; | |
17 |
|
19 | |||
|
20 | use self::config_items::DefaultConfig; | |||
|
21 | use self::config_items::DefaultConfigItem; | |||
18 | use self::layer::ConfigLayer; |
|
22 | use self::layer::ConfigLayer; | |
19 | use self::layer::ConfigValue; |
|
23 | use self::layer::ConfigValue; | |
|
24 | use crate::errors::HgError; | |||
20 | use crate::errors::{HgResultExt, IoResultExt}; |
|
25 | use crate::errors::{HgResultExt, IoResultExt}; | |
21 | use crate::utils::files::get_bytes_from_os_str; |
|
26 | use crate::utils::files::get_bytes_from_os_str; | |
22 | use format_bytes::{write_bytes, DisplayBytes}; |
|
27 | use format_bytes::{write_bytes, DisplayBytes}; | |
23 | use std::collections::HashSet; |
|
28 | use std::collections::HashSet; | |
24 | use std::env; |
|
29 | use std::env; | |
25 | use std::fmt; |
|
30 | use std::fmt; | |
26 | use std::path::{Path, PathBuf}; |
|
31 | use std::path::{Path, PathBuf}; | |
27 | use std::str; |
|
32 | use std::str; | |
28 |
|
33 | |||
|
34 | lazy_static! { | |||
|
35 | static ref DEFAULT_CONFIG: Result<DefaultConfig, HgError> = { | |||
|
36 | DefaultConfig::from_contents(include_str!( | |||
|
37 | "../../../../mercurial/configitems.toml" | |||
|
38 | )) | |||
|
39 | }; | |||
|
40 | } | |||
|
41 | ||||
29 | /// Holds the config values for the current repository |
|
42 | /// Holds the config values for the current repository | |
30 | /// TODO update this docstring once we support more sources |
|
43 | /// TODO update this docstring once we support more sources | |
31 | #[derive(Clone)] |
|
44 | #[derive(Clone)] | |
32 | pub struct Config { |
|
45 | pub struct Config { | |
33 | layers: Vec<layer::ConfigLayer>, |
|
46 | layers: Vec<layer::ConfigLayer>, | |
34 | plain: PlainInfo, |
|
47 | plain: PlainInfo, | |
35 | } |
|
48 | } | |
36 |
|
49 | |||
37 | impl DisplayBytes for Config { |
|
50 | impl DisplayBytes for Config { | |
38 | fn display_bytes( |
|
51 | fn display_bytes( | |
39 | &self, |
|
52 | &self, | |
40 | out: &mut dyn std::io::Write, |
|
53 | out: &mut dyn std::io::Write, | |
41 | ) -> std::io::Result<()> { |
|
54 | ) -> std::io::Result<()> { | |
42 | for (index, layer) in self.layers.iter().rev().enumerate() { |
|
55 | for (index, layer) in self.layers.iter().rev().enumerate() { | |
43 | write_bytes!( |
|
56 | write_bytes!( | |
44 | out, |
|
57 | out, | |
45 | b"==== Layer {} (trusted: {}) ====\n{}", |
|
58 | b"==== Layer {} (trusted: {}) ====\n{}", | |
46 | index, |
|
59 | index, | |
47 | if layer.trusted { |
|
60 | if layer.trusted { | |
48 | &b"yes"[..] |
|
61 | &b"yes"[..] | |
49 | } else { |
|
62 | } else { | |
50 | &b"no"[..] |
|
63 | &b"no"[..] | |
51 | }, |
|
64 | }, | |
52 | layer |
|
65 | layer | |
53 | )?; |
|
66 | )?; | |
54 | } |
|
67 | } | |
55 | Ok(()) |
|
68 | Ok(()) | |
56 | } |
|
69 | } | |
57 | } |
|
70 | } | |
58 |
|
71 | |||
59 | pub enum ConfigSource { |
|
72 | pub enum ConfigSource { | |
60 | /// Absolute path to a config file |
|
73 | /// Absolute path to a config file | |
61 | AbsPath(PathBuf), |
|
74 | AbsPath(PathBuf), | |
62 | /// Already parsed (from the CLI, env, Python resources, etc.) |
|
75 | /// Already parsed (from the CLI, env, Python resources, etc.) | |
63 | Parsed(layer::ConfigLayer), |
|
76 | Parsed(layer::ConfigLayer), | |
64 | } |
|
77 | } | |
65 |
|
78 | |||
66 | #[derive(Debug)] |
|
79 | #[derive(Debug)] | |
67 | pub struct ConfigValueParseErrorDetails { |
|
80 | pub struct ConfigValueParseErrorDetails { | |
68 | pub origin: ConfigOrigin, |
|
81 | pub origin: ConfigOrigin, | |
69 | pub line: Option<usize>, |
|
82 | pub line: Option<usize>, | |
70 | pub section: Vec<u8>, |
|
83 | pub section: Vec<u8>, | |
71 | pub item: Vec<u8>, |
|
84 | pub item: Vec<u8>, | |
72 | pub value: Vec<u8>, |
|
85 | pub value: Vec<u8>, | |
73 | pub expected_type: &'static str, |
|
86 | pub expected_type: &'static str, | |
74 | } |
|
87 | } | |
75 |
|
88 | |||
76 | // boxed to avoid very large Result types |
|
89 | // boxed to avoid very large Result types | |
77 | pub type ConfigValueParseError = Box<ConfigValueParseErrorDetails>; |
|
90 | pub type ConfigValueParseError = Box<ConfigValueParseErrorDetails>; | |
78 |
|
91 | |||
79 | impl fmt::Display for ConfigValueParseError { |
|
92 | impl fmt::Display for ConfigValueParseError { | |
80 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
|
93 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
81 | // TODO: add origin and line number information, here and in |
|
94 | // TODO: add origin and line number information, here and in | |
82 | // corresponding python code |
|
95 | // corresponding python code | |
83 | write!( |
|
96 | write!( | |
84 | f, |
|
97 | f, | |
85 | "config error: {}.{} is not a {} ('{}')", |
|
98 | "config error: {}.{} is not a {} ('{}')", | |
86 | String::from_utf8_lossy(&self.section), |
|
99 | String::from_utf8_lossy(&self.section), | |
87 | String::from_utf8_lossy(&self.item), |
|
100 | String::from_utf8_lossy(&self.item), | |
88 | self.expected_type, |
|
101 | self.expected_type, | |
89 | String::from_utf8_lossy(&self.value) |
|
102 | String::from_utf8_lossy(&self.value) | |
90 | ) |
|
103 | ) | |
91 | } |
|
104 | } | |
92 | } |
|
105 | } | |
93 |
|
106 | |||
94 | /// Returns true if the config item is disabled by PLAIN or PLAINEXCEPT |
|
107 | /// Returns true if the config item is disabled by PLAIN or PLAINEXCEPT | |
95 | fn should_ignore(plain: &PlainInfo, section: &[u8], item: &[u8]) -> bool { |
|
108 | fn should_ignore(plain: &PlainInfo, section: &[u8], item: &[u8]) -> bool { | |
96 | // duplication with [_applyconfig] in [ui.py], |
|
109 | // duplication with [_applyconfig] in [ui.py], | |
97 | if !plain.is_plain() { |
|
110 | if !plain.is_plain() { | |
98 | return false; |
|
111 | return false; | |
99 | } |
|
112 | } | |
100 | if section == b"alias" { |
|
113 | if section == b"alias" { | |
101 | return plain.plainalias(); |
|
114 | return plain.plainalias(); | |
102 | } |
|
115 | } | |
103 | if section == b"revsetalias" { |
|
116 | if section == b"revsetalias" { | |
104 | return plain.plainrevsetalias(); |
|
117 | return plain.plainrevsetalias(); | |
105 | } |
|
118 | } | |
106 | if section == b"templatealias" { |
|
119 | if section == b"templatealias" { | |
107 | return plain.plaintemplatealias(); |
|
120 | return plain.plaintemplatealias(); | |
108 | } |
|
121 | } | |
109 | if section == b"ui" { |
|
122 | if section == b"ui" { | |
110 | let to_delete: &[&[u8]] = &[ |
|
123 | let to_delete: &[&[u8]] = &[ | |
111 | b"debug", |
|
124 | b"debug", | |
112 | b"fallbackencoding", |
|
125 | b"fallbackencoding", | |
113 | b"quiet", |
|
126 | b"quiet", | |
114 | b"slash", |
|
127 | b"slash", | |
115 | b"logtemplate", |
|
128 | b"logtemplate", | |
116 | b"message-output", |
|
129 | b"message-output", | |
117 | b"statuscopies", |
|
130 | b"statuscopies", | |
118 | b"style", |
|
131 | b"style", | |
119 | b"traceback", |
|
132 | b"traceback", | |
120 | b"verbose", |
|
133 | b"verbose", | |
121 | ]; |
|
134 | ]; | |
122 | return to_delete.contains(&item); |
|
135 | return to_delete.contains(&item); | |
123 | } |
|
136 | } | |
124 | let sections_to_delete: &[&[u8]] = |
|
137 | let sections_to_delete: &[&[u8]] = | |
125 | &[b"defaults", b"commands", b"command-templates"]; |
|
138 | &[b"defaults", b"commands", b"command-templates"]; | |
126 | sections_to_delete.contains(§ion) |
|
139 | sections_to_delete.contains(§ion) | |
127 | } |
|
140 | } | |
128 |
|
141 | |||
129 | impl Config { |
|
142 | impl Config { | |
130 | /// The configuration to use when printing configuration-loading errors |
|
143 | /// The configuration to use when printing configuration-loading errors | |
131 | pub fn empty() -> Self { |
|
144 | pub fn empty() -> Self { | |
132 | Self { |
|
145 | Self { | |
133 | layers: Vec::new(), |
|
146 | layers: Vec::new(), | |
134 | plain: PlainInfo::empty(), |
|
147 | plain: PlainInfo::empty(), | |
135 | } |
|
148 | } | |
136 | } |
|
149 | } | |
137 |
|
150 | |||
138 | /// Load system and user configuration from various files. |
|
151 | /// Load system and user configuration from various files. | |
139 | /// |
|
152 | /// | |
140 | /// This is also affected by some environment variables. |
|
153 | /// This is also affected by some environment variables. | |
141 | pub fn load_non_repo() -> Result<Self, ConfigError> { |
|
154 | pub fn load_non_repo() -> Result<Self, ConfigError> { | |
142 | let mut config = Self::empty(); |
|
155 | let mut config = Self::empty(); | |
143 | let opt_rc_path = env::var_os("HGRCPATH"); |
|
156 | let opt_rc_path = env::var_os("HGRCPATH"); | |
144 | // HGRCPATH replaces system config |
|
157 | // HGRCPATH replaces system config | |
145 | if opt_rc_path.is_none() { |
|
158 | if opt_rc_path.is_none() { | |
146 | config.add_system_config()? |
|
159 | config.add_system_config()? | |
147 | } |
|
160 | } | |
148 |
|
161 | |||
149 | config.add_for_environment_variable("EDITOR", b"ui", b"editor"); |
|
162 | config.add_for_environment_variable("EDITOR", b"ui", b"editor"); | |
150 | config.add_for_environment_variable("VISUAL", b"ui", b"editor"); |
|
163 | config.add_for_environment_variable("VISUAL", b"ui", b"editor"); | |
151 | config.add_for_environment_variable("PAGER", b"pager", b"pager"); |
|
164 | config.add_for_environment_variable("PAGER", b"pager", b"pager"); | |
152 |
|
165 | |||
153 | // These are set by `run-tests.py --rhg` to enable fallback for the |
|
166 | // These are set by `run-tests.py --rhg` to enable fallback for the | |
154 | // entire test suite. Alternatives would be setting configuration |
|
167 | // entire test suite. Alternatives would be setting configuration | |
155 | // through `$HGRCPATH` but some tests override that, or changing the |
|
168 | // through `$HGRCPATH` but some tests override that, or changing the | |
156 | // `hg` shell alias to include `--config` but that disrupts tests that |
|
169 | // `hg` shell alias to include `--config` but that disrupts tests that | |
157 | // print command lines and check expected output. |
|
170 | // print command lines and check expected output. | |
158 | config.add_for_environment_variable( |
|
171 | config.add_for_environment_variable( | |
159 | "RHG_ON_UNSUPPORTED", |
|
172 | "RHG_ON_UNSUPPORTED", | |
160 | b"rhg", |
|
173 | b"rhg", | |
161 | b"on-unsupported", |
|
174 | b"on-unsupported", | |
162 | ); |
|
175 | ); | |
163 | config.add_for_environment_variable( |
|
176 | config.add_for_environment_variable( | |
164 | "RHG_FALLBACK_EXECUTABLE", |
|
177 | "RHG_FALLBACK_EXECUTABLE", | |
165 | b"rhg", |
|
178 | b"rhg", | |
166 | b"fallback-executable", |
|
179 | b"fallback-executable", | |
167 | ); |
|
180 | ); | |
168 |
|
181 | |||
169 | // HGRCPATH replaces user config |
|
182 | // HGRCPATH replaces user config | |
170 | if opt_rc_path.is_none() { |
|
183 | if opt_rc_path.is_none() { | |
171 | config.add_user_config()? |
|
184 | config.add_user_config()? | |
172 | } |
|
185 | } | |
173 | if let Some(rc_path) = &opt_rc_path { |
|
186 | if let Some(rc_path) = &opt_rc_path { | |
174 | for path in env::split_paths(rc_path) { |
|
187 | for path in env::split_paths(rc_path) { | |
175 | if !path.as_os_str().is_empty() { |
|
188 | if !path.as_os_str().is_empty() { | |
176 | if path.is_dir() { |
|
189 | if path.is_dir() { | |
177 | config.add_trusted_dir(&path)? |
|
190 | config.add_trusted_dir(&path)? | |
178 | } else { |
|
191 | } else { | |
179 | config.add_trusted_file(&path)? |
|
192 | config.add_trusted_file(&path)? | |
180 | } |
|
193 | } | |
181 | } |
|
194 | } | |
182 | } |
|
195 | } | |
183 | } |
|
196 | } | |
184 | Ok(config) |
|
197 | Ok(config) | |
185 | } |
|
198 | } | |
186 |
|
199 | |||
187 | pub fn load_cli_args( |
|
200 | pub fn load_cli_args( | |
188 | &mut self, |
|
201 | &mut self, | |
189 | cli_config_args: impl IntoIterator<Item = impl AsRef<[u8]>>, |
|
202 | cli_config_args: impl IntoIterator<Item = impl AsRef<[u8]>>, | |
190 | color_arg: Option<Vec<u8>>, |
|
203 | color_arg: Option<Vec<u8>>, | |
191 | ) -> Result<(), ConfigError> { |
|
204 | ) -> Result<(), ConfigError> { | |
192 | if let Some(layer) = ConfigLayer::parse_cli_args(cli_config_args)? { |
|
205 | if let Some(layer) = ConfigLayer::parse_cli_args(cli_config_args)? { | |
193 | self.layers.push(layer) |
|
206 | self.layers.push(layer) | |
194 | } |
|
207 | } | |
195 | if let Some(arg) = color_arg { |
|
208 | if let Some(arg) = color_arg { | |
196 | let mut layer = ConfigLayer::new(ConfigOrigin::CommandLineColor); |
|
209 | let mut layer = ConfigLayer::new(ConfigOrigin::CommandLineColor); | |
197 | layer.add(b"ui"[..].into(), b"color"[..].into(), arg, None); |
|
210 | layer.add(b"ui"[..].into(), b"color"[..].into(), arg, None); | |
198 | self.layers.push(layer) |
|
211 | self.layers.push(layer) | |
199 | } |
|
212 | } | |
200 | Ok(()) |
|
213 | Ok(()) | |
201 | } |
|
214 | } | |
202 |
|
215 | |||
203 | fn add_trusted_dir(&mut self, path: &Path) -> Result<(), ConfigError> { |
|
216 | fn add_trusted_dir(&mut self, path: &Path) -> Result<(), ConfigError> { | |
204 | if let Some(entries) = std::fs::read_dir(path) |
|
217 | if let Some(entries) = std::fs::read_dir(path) | |
205 | .when_reading_file(path) |
|
218 | .when_reading_file(path) | |
206 | .io_not_found_as_none()? |
|
219 | .io_not_found_as_none()? | |
207 | { |
|
220 | { | |
208 | let mut file_paths = entries |
|
221 | let mut file_paths = entries | |
209 | .map(|result| { |
|
222 | .map(|result| { | |
210 | result.when_reading_file(path).map(|entry| entry.path()) |
|
223 | result.when_reading_file(path).map(|entry| entry.path()) | |
211 | }) |
|
224 | }) | |
212 | .collect::<Result<Vec<_>, _>>()?; |
|
225 | .collect::<Result<Vec<_>, _>>()?; | |
213 | file_paths.sort(); |
|
226 | file_paths.sort(); | |
214 | for file_path in &file_paths { |
|
227 | for file_path in &file_paths { | |
215 | if file_path.extension() == Some(std::ffi::OsStr::new("rc")) { |
|
228 | if file_path.extension() == Some(std::ffi::OsStr::new("rc")) { | |
216 | self.add_trusted_file(file_path)? |
|
229 | self.add_trusted_file(file_path)? | |
217 | } |
|
230 | } | |
218 | } |
|
231 | } | |
219 | } |
|
232 | } | |
220 | Ok(()) |
|
233 | Ok(()) | |
221 | } |
|
234 | } | |
222 |
|
235 | |||
223 | fn add_trusted_file(&mut self, path: &Path) -> Result<(), ConfigError> { |
|
236 | fn add_trusted_file(&mut self, path: &Path) -> Result<(), ConfigError> { | |
224 | if let Some(data) = std::fs::read(path) |
|
237 | if let Some(data) = std::fs::read(path) | |
225 | .when_reading_file(path) |
|
238 | .when_reading_file(path) | |
226 | .io_not_found_as_none()? |
|
239 | .io_not_found_as_none()? | |
227 | { |
|
240 | { | |
228 | self.layers.extend(ConfigLayer::parse(path, &data)?) |
|
241 | self.layers.extend(ConfigLayer::parse(path, &data)?) | |
229 | } |
|
242 | } | |
230 | Ok(()) |
|
243 | Ok(()) | |
231 | } |
|
244 | } | |
232 |
|
245 | |||
233 | fn add_for_environment_variable( |
|
246 | fn add_for_environment_variable( | |
234 | &mut self, |
|
247 | &mut self, | |
235 | var: &str, |
|
248 | var: &str, | |
236 | section: &[u8], |
|
249 | section: &[u8], | |
237 | key: &[u8], |
|
250 | key: &[u8], | |
238 | ) { |
|
251 | ) { | |
239 | if let Some(value) = env::var_os(var) { |
|
252 | if let Some(value) = env::var_os(var) { | |
240 | let origin = layer::ConfigOrigin::Environment(var.into()); |
|
253 | let origin = layer::ConfigOrigin::Environment(var.into()); | |
241 | let mut layer = ConfigLayer::new(origin); |
|
254 | let mut layer = ConfigLayer::new(origin); | |
242 | layer.add( |
|
255 | layer.add( | |
243 | section.to_owned(), |
|
256 | section.to_owned(), | |
244 | key.to_owned(), |
|
257 | key.to_owned(), | |
245 | get_bytes_from_os_str(value), |
|
258 | get_bytes_from_os_str(value), | |
246 | None, |
|
259 | None, | |
247 | ); |
|
260 | ); | |
248 | self.layers.push(layer) |
|
261 | self.layers.push(layer) | |
249 | } |
|
262 | } | |
250 | } |
|
263 | } | |
251 |
|
264 | |||
252 | #[cfg(unix)] // TODO: other platforms |
|
265 | #[cfg(unix)] // TODO: other platforms | |
253 | fn add_system_config(&mut self) -> Result<(), ConfigError> { |
|
266 | fn add_system_config(&mut self) -> Result<(), ConfigError> { | |
254 | let mut add_for_prefix = |prefix: &Path| -> Result<(), ConfigError> { |
|
267 | let mut add_for_prefix = |prefix: &Path| -> Result<(), ConfigError> { | |
255 | let etc = prefix.join("etc").join("mercurial"); |
|
268 | let etc = prefix.join("etc").join("mercurial"); | |
256 | self.add_trusted_file(&etc.join("hgrc"))?; |
|
269 | self.add_trusted_file(&etc.join("hgrc"))?; | |
257 | self.add_trusted_dir(&etc.join("hgrc.d")) |
|
270 | self.add_trusted_dir(&etc.join("hgrc.d")) | |
258 | }; |
|
271 | }; | |
259 | let root = Path::new("/"); |
|
272 | let root = Path::new("/"); | |
260 | // TODO: use `std::env::args_os().next().unwrap()` a.k.a. argv[0] |
|
273 | // TODO: use `std::env::args_os().next().unwrap()` a.k.a. argv[0] | |
261 | // instead? TODO: can this be a relative path? |
|
274 | // instead? TODO: can this be a relative path? | |
262 | let hg = crate::utils::current_exe()?; |
|
275 | let hg = crate::utils::current_exe()?; | |
263 | // TODO: this order (per-installation then per-system) matches |
|
276 | // TODO: this order (per-installation then per-system) matches | |
264 | // `systemrcpath()` in `mercurial/scmposix.py`, but |
|
277 | // `systemrcpath()` in `mercurial/scmposix.py`, but | |
265 | // `mercurial/helptext/config.txt` suggests it should be reversed |
|
278 | // `mercurial/helptext/config.txt` suggests it should be reversed | |
266 | if let Some(installation_prefix) = hg.parent().and_then(Path::parent) { |
|
279 | if let Some(installation_prefix) = hg.parent().and_then(Path::parent) { | |
267 | if installation_prefix != root { |
|
280 | if installation_prefix != root { | |
268 | add_for_prefix(installation_prefix)? |
|
281 | add_for_prefix(installation_prefix)? | |
269 | } |
|
282 | } | |
270 | } |
|
283 | } | |
271 | add_for_prefix(root)?; |
|
284 | add_for_prefix(root)?; | |
272 | Ok(()) |
|
285 | Ok(()) | |
273 | } |
|
286 | } | |
274 |
|
287 | |||
275 | #[cfg(unix)] // TODO: other plateforms |
|
288 | #[cfg(unix)] // TODO: other plateforms | |
276 | fn add_user_config(&mut self) -> Result<(), ConfigError> { |
|
289 | fn add_user_config(&mut self) -> Result<(), ConfigError> { | |
277 | let opt_home = home::home_dir(); |
|
290 | let opt_home = home::home_dir(); | |
278 | if let Some(home) = &opt_home { |
|
291 | if let Some(home) = &opt_home { | |
279 | self.add_trusted_file(&home.join(".hgrc"))? |
|
292 | self.add_trusted_file(&home.join(".hgrc"))? | |
280 | } |
|
293 | } | |
281 | let darwin = cfg!(any(target_os = "macos", target_os = "ios")); |
|
294 | let darwin = cfg!(any(target_os = "macos", target_os = "ios")); | |
282 | if !darwin { |
|
295 | if !darwin { | |
283 | if let Some(config_home) = env::var_os("XDG_CONFIG_HOME") |
|
296 | if let Some(config_home) = env::var_os("XDG_CONFIG_HOME") | |
284 | .map(PathBuf::from) |
|
297 | .map(PathBuf::from) | |
285 | .or_else(|| opt_home.map(|home| home.join(".config"))) |
|
298 | .or_else(|| opt_home.map(|home| home.join(".config"))) | |
286 | { |
|
299 | { | |
287 | self.add_trusted_file(&config_home.join("hg").join("hgrc"))? |
|
300 | self.add_trusted_file(&config_home.join("hg").join("hgrc"))? | |
288 | } |
|
301 | } | |
289 | } |
|
302 | } | |
290 | Ok(()) |
|
303 | Ok(()) | |
291 | } |
|
304 | } | |
292 |
|
305 | |||
293 | /// Loads in order, which means that the precedence is the same |
|
306 | /// Loads in order, which means that the precedence is the same | |
294 | /// as the order of `sources`. |
|
307 | /// as the order of `sources`. | |
295 | pub fn load_from_explicit_sources( |
|
308 | pub fn load_from_explicit_sources( | |
296 | sources: Vec<ConfigSource>, |
|
309 | sources: Vec<ConfigSource>, | |
297 | ) -> Result<Self, ConfigError> { |
|
310 | ) -> Result<Self, ConfigError> { | |
298 | let mut layers = vec![]; |
|
311 | let mut layers = vec![]; | |
299 |
|
312 | |||
300 | for source in sources.into_iter() { |
|
313 | for source in sources.into_iter() { | |
301 | match source { |
|
314 | match source { | |
302 | ConfigSource::Parsed(c) => layers.push(c), |
|
315 | ConfigSource::Parsed(c) => layers.push(c), | |
303 | ConfigSource::AbsPath(c) => { |
|
316 | ConfigSource::AbsPath(c) => { | |
304 | // TODO check if it should be trusted |
|
317 | // TODO check if it should be trusted | |
305 | // mercurial/ui.py:427 |
|
318 | // mercurial/ui.py:427 | |
306 | let data = match std::fs::read(&c) { |
|
319 | let data = match std::fs::read(&c) { | |
307 | Err(_) => continue, // same as the python code |
|
320 | Err(_) => continue, // same as the python code | |
308 | Ok(data) => data, |
|
321 | Ok(data) => data, | |
309 | }; |
|
322 | }; | |
310 | layers.extend(ConfigLayer::parse(&c, &data)?) |
|
323 | layers.extend(ConfigLayer::parse(&c, &data)?) | |
311 | } |
|
324 | } | |
312 | } |
|
325 | } | |
313 | } |
|
326 | } | |
314 |
|
327 | |||
315 | Ok(Config { |
|
328 | Ok(Config { | |
316 | layers, |
|
329 | layers, | |
317 | plain: PlainInfo::empty(), |
|
330 | plain: PlainInfo::empty(), | |
318 | }) |
|
331 | }) | |
319 | } |
|
332 | } | |
320 |
|
333 | |||
321 | /// Loads the per-repository config into a new `Config` which is combined |
|
334 | /// Loads the per-repository config into a new `Config` which is combined | |
322 | /// with `self`. |
|
335 | /// with `self`. | |
323 | pub(crate) fn combine_with_repo( |
|
336 | pub(crate) fn combine_with_repo( | |
324 | &self, |
|
337 | &self, | |
325 | repo_config_files: &[PathBuf], |
|
338 | repo_config_files: &[PathBuf], | |
326 | ) -> Result<Self, ConfigError> { |
|
339 | ) -> Result<Self, ConfigError> { | |
327 | let (cli_layers, other_layers) = self |
|
340 | let (cli_layers, other_layers) = self | |
328 | .layers |
|
341 | .layers | |
329 | .iter() |
|
342 | .iter() | |
330 | .cloned() |
|
343 | .cloned() | |
331 | .partition(ConfigLayer::is_from_command_line); |
|
344 | .partition(ConfigLayer::is_from_command_line); | |
332 |
|
345 | |||
333 | let mut repo_config = Self { |
|
346 | let mut repo_config = Self { | |
334 | layers: other_layers, |
|
347 | layers: other_layers, | |
335 | plain: PlainInfo::empty(), |
|
348 | plain: PlainInfo::empty(), | |
336 | }; |
|
349 | }; | |
337 | for path in repo_config_files { |
|
350 | for path in repo_config_files { | |
338 | // TODO: check if this file should be trusted: |
|
351 | // TODO: check if this file should be trusted: | |
339 | // `mercurial/ui.py:427` |
|
352 | // `mercurial/ui.py:427` | |
340 | repo_config.add_trusted_file(path)?; |
|
353 | repo_config.add_trusted_file(path)?; | |
341 | } |
|
354 | } | |
342 | repo_config.layers.extend(cli_layers); |
|
355 | repo_config.layers.extend(cli_layers); | |
343 | Ok(repo_config) |
|
356 | Ok(repo_config) | |
344 | } |
|
357 | } | |
345 |
|
358 | |||
346 | pub fn apply_plain(&mut self, plain: PlainInfo) { |
|
359 | pub fn apply_plain(&mut self, plain: PlainInfo) { | |
347 | self.plain = plain; |
|
360 | self.plain = plain; | |
348 | } |
|
361 | } | |
349 |
|
362 | |||
|
363 | /// Returns the default value for the given config item, if any. | |||
|
364 | pub fn get_default( | |||
|
365 | &self, | |||
|
366 | section: &[u8], | |||
|
367 | item: &[u8], | |||
|
368 | ) -> Result<Option<&DefaultConfigItem>, HgError> { | |||
|
369 | let default_config = DEFAULT_CONFIG.as_ref().map_err(|e| { | |||
|
370 | HgError::abort( | |||
|
371 | e.to_string(), | |||
|
372 | crate::exit_codes::ABORT, | |||
|
373 | Some("`mercurial/configitems.toml` is not valid".into()), | |||
|
374 | ) | |||
|
375 | })?; | |||
|
376 | Ok(default_config.get(section, item)) | |||
|
377 | } | |||
|
378 | ||||
350 | fn get_parse<'config, T: 'config>( |
|
379 | fn get_parse<'config, T: 'config>( | |
351 | &'config self, |
|
380 | &'config self, | |
352 | section: &[u8], |
|
381 | section: &[u8], | |
353 | item: &[u8], |
|
382 | item: &[u8], | |
354 | expected_type: &'static str, |
|
383 | expected_type: &'static str, | |
355 | parse: impl Fn(&'config [u8]) -> Option<T>, |
|
384 | parse: impl Fn(&'config [u8]) -> Option<T>, | |
356 |
) -> Result<Option<T>, |
|
385 | ) -> Result<Option<T>, HgError> | |
|
386 | where | |||
|
387 | Option<T>: TryFrom<&'config DefaultConfigItem, Error = HgError>, | |||
|
388 | { | |||
357 | match self.get_inner(section, item) { |
|
389 | match self.get_inner(section, item) { | |
358 | Some((layer, v)) => match parse(&v.bytes) { |
|
390 | Some((layer, v)) => match parse(&v.bytes) { | |
359 | Some(b) => Ok(Some(b)), |
|
391 | Some(b) => Ok(Some(b)), | |
360 | None => Err(Box::new(ConfigValueParseErrorDetails { |
|
392 | None => Err(Box::new(ConfigValueParseErrorDetails { | |
361 | origin: layer.origin.to_owned(), |
|
393 | origin: layer.origin.to_owned(), | |
362 | line: v.line, |
|
394 | line: v.line, | |
363 | value: v.bytes.to_owned(), |
|
395 | value: v.bytes.to_owned(), | |
364 | section: section.to_owned(), |
|
396 | section: section.to_owned(), | |
365 | item: item.to_owned(), |
|
397 | item: item.to_owned(), | |
366 | expected_type, |
|
398 | expected_type, | |
367 |
}) |
|
399 | }) | |
|
400 | .into()), | |||
368 | }, |
|
401 | }, | |
369 | None => Ok(None), |
|
402 | None => match self.get_default(section, item)? { | |
|
403 | Some(default) => Ok(default.try_into()?), | |||
|
404 | None => { | |||
|
405 | Ok(None) | |||
|
406 | } | |||
|
407 | }, | |||
370 | } |
|
408 | } | |
371 | } |
|
409 | } | |
372 |
|
410 | |||
373 | /// Returns an `Err` if the first value found is not a valid UTF-8 string. |
|
411 | /// Returns an `Err` if the first value found is not a valid UTF-8 string. | |
374 | /// Otherwise, returns an `Ok(value)` if found, or `None`. |
|
412 | /// Otherwise, returns an `Ok(value)` if found, or `None`. | |
375 | pub fn get_str( |
|
413 | pub fn get_str( | |
376 | &self, |
|
414 | &self, | |
377 | section: &[u8], |
|
415 | section: &[u8], | |
378 | item: &[u8], |
|
416 | item: &[u8], | |
379 |
) -> Result<Option<&str>, |
|
417 | ) -> Result<Option<&str>, HgError> { | |
380 | self.get_parse(section, item, "ASCII or UTF-8 string", |value| { |
|
418 | self.get_parse(section, item, "ASCII or UTF-8 string", |value| { | |
381 | str::from_utf8(value).ok() |
|
419 | str::from_utf8(value).ok() | |
382 | }) |
|
420 | }) | |
383 | } |
|
421 | } | |
384 |
|
422 | |||
385 | /// Returns an `Err` if the first value found is not a valid unsigned |
|
423 | /// Returns an `Err` if the first value found is not a valid unsigned | |
386 | /// integer. Otherwise, returns an `Ok(value)` if found, or `None`. |
|
424 | /// integer. Otherwise, returns an `Ok(value)` if found, or `None`. | |
387 | pub fn get_u32( |
|
425 | pub fn get_u32( | |
388 | &self, |
|
426 | &self, | |
389 | section: &[u8], |
|
427 | section: &[u8], | |
390 | item: &[u8], |
|
428 | item: &[u8], | |
391 |
) -> Result<Option<u32>, |
|
429 | ) -> Result<Option<u32>, HgError> { | |
392 | self.get_parse(section, item, "valid integer", |value| { |
|
430 | self.get_parse(section, item, "valid integer", |value| { | |
393 | str::from_utf8(value).ok()?.parse().ok() |
|
431 | str::from_utf8(value).ok()?.parse().ok() | |
394 | }) |
|
432 | }) | |
395 | } |
|
433 | } | |
396 |
|
434 | |||
397 | /// Returns an `Err` if the first value found is not a valid file size |
|
435 | /// Returns an `Err` if the first value found is not a valid file size | |
398 | /// value such as `30` (default unit is bytes), `7 MB`, or `42.5 kb`. |
|
436 | /// value such as `30` (default unit is bytes), `7 MB`, or `42.5 kb`. | |
399 | /// Otherwise, returns an `Ok(value_in_bytes)` if found, or `None`. |
|
437 | /// Otherwise, returns an `Ok(value_in_bytes)` if found, or `None`. | |
400 | pub fn get_byte_size( |
|
438 | pub fn get_byte_size( | |
401 | &self, |
|
439 | &self, | |
402 | section: &[u8], |
|
440 | section: &[u8], | |
403 | item: &[u8], |
|
441 | item: &[u8], | |
404 |
) -> Result<Option<u64>, |
|
442 | ) -> Result<Option<u64>, HgError> { | |
405 | self.get_parse(section, item, "byte quantity", values::parse_byte_size) |
|
443 | self.get_parse(section, item, "byte quantity", values::parse_byte_size) | |
406 | } |
|
444 | } | |
407 |
|
445 | |||
408 | /// Returns an `Err` if the first value found is not a valid boolean. |
|
446 | /// Returns an `Err` if the first value found is not a valid boolean. | |
409 | /// Otherwise, returns an `Ok(option)`, where `option` is the boolean if |
|
447 | /// Otherwise, returns an `Ok(option)`, where `option` is the boolean if | |
410 | /// found, or `None`. |
|
448 | /// found, or `None`. | |
411 | pub fn get_option( |
|
449 | pub fn get_option( | |
412 | &self, |
|
450 | &self, | |
413 | section: &[u8], |
|
451 | section: &[u8], | |
414 | item: &[u8], |
|
452 | item: &[u8], | |
415 |
) -> Result<Option<bool>, |
|
453 | ) -> Result<Option<bool>, HgError> { | |
416 | self.get_parse(section, item, "boolean", values::parse_bool) |
|
454 | self.get_parse(section, item, "boolean", values::parse_bool) | |
417 | } |
|
455 | } | |
418 |
|
456 | |||
419 | /// Returns the corresponding boolean in the config. Returns `Ok(false)` |
|
457 | /// Returns the corresponding boolean in the config. Returns `Ok(false)` | |
420 | /// if the value is not found, an `Err` if it's not a valid boolean. |
|
458 | /// if the value is not found, an `Err` if it's not a valid boolean. | |
421 | pub fn get_bool( |
|
459 | pub fn get_bool( | |
422 | &self, |
|
460 | &self, | |
423 | section: &[u8], |
|
461 | section: &[u8], | |
424 | item: &[u8], |
|
462 | item: &[u8], | |
425 |
) -> Result<bool, |
|
463 | ) -> Result<bool, HgError> { | |
426 | Ok(self.get_option(section, item)?.unwrap_or(false)) |
|
464 | Ok(self.get_option(section, item)?.unwrap_or(false)) | |
427 | } |
|
465 | } | |
428 |
|
466 | |||
429 | /// Returns `true` if the extension is enabled, `false` otherwise |
|
467 | /// Returns `true` if the extension is enabled, `false` otherwise | |
430 | pub fn is_extension_enabled(&self, extension: &[u8]) -> bool { |
|
468 | pub fn is_extension_enabled(&self, extension: &[u8]) -> bool { | |
431 | let value = self.get(b"extensions", extension); |
|
469 | let value = self.get(b"extensions", extension); | |
432 | match value { |
|
470 | match value { | |
433 | Some(c) => !c.starts_with(b"!"), |
|
471 | Some(c) => !c.starts_with(b"!"), | |
434 | None => false, |
|
472 | None => false, | |
435 | } |
|
473 | } | |
436 | } |
|
474 | } | |
437 |
|
475 | |||
438 | /// If there is an `item` value in `section`, parse and return a list of |
|
476 | /// If there is an `item` value in `section`, parse and return a list of | |
439 | /// byte strings. |
|
477 | /// byte strings. | |
440 | pub fn get_list( |
|
478 | pub fn get_list( | |
441 | &self, |
|
479 | &self, | |
442 | section: &[u8], |
|
480 | section: &[u8], | |
443 | item: &[u8], |
|
481 | item: &[u8], | |
444 | ) -> Option<Vec<Vec<u8>>> { |
|
482 | ) -> Option<Vec<Vec<u8>>> { | |
445 | self.get(section, item).map(values::parse_list) |
|
483 | self.get(section, item).map(values::parse_list) | |
446 | } |
|
484 | } | |
447 |
|
485 | |||
448 | /// Returns the raw value bytes of the first one found, or `None`. |
|
486 | /// Returns the raw value bytes of the first one found, or `None`. | |
449 | pub fn get(&self, section: &[u8], item: &[u8]) -> Option<&[u8]> { |
|
487 | pub fn get(&self, section: &[u8], item: &[u8]) -> Option<&[u8]> { | |
450 | self.get_inner(section, item) |
|
488 | self.get_inner(section, item) | |
451 | .map(|(_, value)| value.bytes.as_ref()) |
|
489 | .map(|(_, value)| value.bytes.as_ref()) | |
452 | } |
|
490 | } | |
453 |
|
491 | |||
454 | /// Returns the raw value bytes of the first one found, or `None`. |
|
492 | /// Returns the raw value bytes of the first one found, or `None`. | |
455 | pub fn get_with_origin( |
|
493 | pub fn get_with_origin( | |
456 | &self, |
|
494 | &self, | |
457 | section: &[u8], |
|
495 | section: &[u8], | |
458 | item: &[u8], |
|
496 | item: &[u8], | |
459 | ) -> Option<(&[u8], &ConfigOrigin)> { |
|
497 | ) -> Option<(&[u8], &ConfigOrigin)> { | |
460 | self.get_inner(section, item) |
|
498 | self.get_inner(section, item) | |
461 | .map(|(layer, value)| (value.bytes.as_ref(), &layer.origin)) |
|
499 | .map(|(layer, value)| (value.bytes.as_ref(), &layer.origin)) | |
462 | } |
|
500 | } | |
463 |
|
501 | |||
464 | /// Returns the layer and the value of the first one found, or `None`. |
|
502 | /// Returns the layer and the value of the first one found, or `None`. | |
465 | fn get_inner( |
|
503 | fn get_inner( | |
466 | &self, |
|
504 | &self, | |
467 | section: &[u8], |
|
505 | section: &[u8], | |
468 | item: &[u8], |
|
506 | item: &[u8], | |
469 | ) -> Option<(&ConfigLayer, &ConfigValue)> { |
|
507 | ) -> Option<(&ConfigLayer, &ConfigValue)> { | |
470 | // Filter out the config items that are hidden by [PLAIN]. |
|
508 | // Filter out the config items that are hidden by [PLAIN]. | |
471 | // This differs from python hg where we delete them from the config. |
|
509 | // This differs from python hg where we delete them from the config. | |
472 | let should_ignore = should_ignore(&self.plain, section, item); |
|
510 | let should_ignore = should_ignore(&self.plain, section, item); | |
473 | for layer in self.layers.iter().rev() { |
|
511 | for layer in self.layers.iter().rev() { | |
474 | if !layer.trusted { |
|
512 | if !layer.trusted { | |
475 | continue; |
|
513 | continue; | |
476 | } |
|
514 | } | |
477 | //The [PLAIN] config should not affect the defaults. |
|
515 | //The [PLAIN] config should not affect the defaults. | |
478 | // |
|
516 | // | |
479 | // However, PLAIN should also affect the "tweaked" defaults (unless |
|
517 | // However, PLAIN should also affect the "tweaked" defaults (unless | |
480 | // "tweakdefault" is part of "HGPLAINEXCEPT"). |
|
518 | // "tweakdefault" is part of "HGPLAINEXCEPT"). | |
481 | // |
|
519 | // | |
482 | // In practice the tweak-default layer is only added when it is |
|
520 | // In practice the tweak-default layer is only added when it is | |
483 | // relevant, so we can safely always take it into |
|
521 | // relevant, so we can safely always take it into | |
484 | // account here. |
|
522 | // account here. | |
485 | if should_ignore && !(layer.origin == ConfigOrigin::Tweakdefaults) |
|
523 | if should_ignore && !(layer.origin == ConfigOrigin::Tweakdefaults) | |
486 | { |
|
524 | { | |
487 | continue; |
|
525 | continue; | |
488 | } |
|
526 | } | |
489 | if let Some(v) = layer.get(section, item) { |
|
527 | if let Some(v) = layer.get(section, item) { | |
490 | return Some((layer, v)); |
|
528 | return Some((layer, v)); | |
491 | } |
|
529 | } | |
492 | } |
|
530 | } | |
493 | None |
|
531 | None | |
494 | } |
|
532 | } | |
495 |
|
533 | |||
496 | /// Return all keys defined for the given section |
|
534 | /// Return all keys defined for the given section | |
497 | pub fn get_section_keys(&self, section: &[u8]) -> HashSet<&[u8]> { |
|
535 | pub fn get_section_keys(&self, section: &[u8]) -> HashSet<&[u8]> { | |
498 | self.layers |
|
536 | self.layers | |
499 | .iter() |
|
537 | .iter() | |
500 | .flat_map(|layer| layer.iter_keys(section)) |
|
538 | .flat_map(|layer| layer.iter_keys(section)) | |
501 | .collect() |
|
539 | .collect() | |
502 | } |
|
540 | } | |
503 |
|
541 | |||
504 | /// Returns whether any key is defined in the given section |
|
542 | /// Returns whether any key is defined in the given section | |
505 | pub fn has_non_empty_section(&self, section: &[u8]) -> bool { |
|
543 | pub fn has_non_empty_section(&self, section: &[u8]) -> bool { | |
506 | self.layers |
|
544 | self.layers | |
507 | .iter() |
|
545 | .iter() | |
508 | .any(|layer| layer.has_non_empty_section(section)) |
|
546 | .any(|layer| layer.has_non_empty_section(section)) | |
509 | } |
|
547 | } | |
510 |
|
548 | |||
511 | /// Yields (key, value) pairs for everything in the given section |
|
549 | /// Yields (key, value) pairs for everything in the given section | |
512 | pub fn iter_section<'a>( |
|
550 | pub fn iter_section<'a>( | |
513 | &'a self, |
|
551 | &'a self, | |
514 | section: &'a [u8], |
|
552 | section: &'a [u8], | |
515 | ) -> impl Iterator<Item = (&[u8], &[u8])> + 'a { |
|
553 | ) -> impl Iterator<Item = (&[u8], &[u8])> + 'a { | |
516 | // Deduplicate keys redefined in multiple layers |
|
554 | // Deduplicate keys redefined in multiple layers | |
517 | let mut keys_already_seen = HashSet::new(); |
|
555 | let mut keys_already_seen = HashSet::new(); | |
518 | let mut key_is_new = |
|
556 | let mut key_is_new = | |
519 | move |&(key, _value): &(&'a [u8], &'a [u8])| -> bool { |
|
557 | move |&(key, _value): &(&'a [u8], &'a [u8])| -> bool { | |
520 | keys_already_seen.insert(key) |
|
558 | keys_already_seen.insert(key) | |
521 | }; |
|
559 | }; | |
522 | // This is similar to `flat_map` + `filter_map`, except with a single |
|
560 | // This is similar to `flat_map` + `filter_map`, except with a single | |
523 | // closure that owns `key_is_new` (and therefore the |
|
561 | // closure that owns `key_is_new` (and therefore the | |
524 | // `keys_already_seen` set): |
|
562 | // `keys_already_seen` set): | |
525 | let mut layer_iters = self |
|
563 | let mut layer_iters = self | |
526 | .layers |
|
564 | .layers | |
527 | .iter() |
|
565 | .iter() | |
528 | .rev() |
|
566 | .rev() | |
529 | .map(move |layer| layer.iter_section(section)) |
|
567 | .map(move |layer| layer.iter_section(section)) | |
530 | .peekable(); |
|
568 | .peekable(); | |
531 | std::iter::from_fn(move || loop { |
|
569 | std::iter::from_fn(move || loop { | |
532 | if let Some(pair) = layer_iters.peek_mut()?.find(&mut key_is_new) { |
|
570 | if let Some(pair) = layer_iters.peek_mut()?.find(&mut key_is_new) { | |
533 | return Some(pair); |
|
571 | return Some(pair); | |
534 | } else { |
|
572 | } else { | |
535 | layer_iters.next(); |
|
573 | layer_iters.next(); | |
536 | } |
|
574 | } | |
537 | }) |
|
575 | }) | |
538 | } |
|
576 | } | |
539 |
|
577 | |||
540 | /// Get raw values bytes from all layers (even untrusted ones) in order |
|
578 | /// Get raw values bytes from all layers (even untrusted ones) in order | |
541 | /// of precedence. |
|
579 | /// of precedence. | |
542 | #[cfg(test)] |
|
580 | #[cfg(test)] | |
543 | fn get_all(&self, section: &[u8], item: &[u8]) -> Vec<&[u8]> { |
|
581 | fn get_all(&self, section: &[u8], item: &[u8]) -> Vec<&[u8]> { | |
544 | let mut res = vec![]; |
|
582 | let mut res = vec![]; | |
545 | for layer in self.layers.iter().rev() { |
|
583 | for layer in self.layers.iter().rev() { | |
546 | if let Some(v) = layer.get(section, item) { |
|
584 | if let Some(v) = layer.get(section, item) { | |
547 | res.push(v.bytes.as_ref()); |
|
585 | res.push(v.bytes.as_ref()); | |
548 | } |
|
586 | } | |
549 | } |
|
587 | } | |
550 | res |
|
588 | res | |
551 | } |
|
589 | } | |
552 |
|
590 | |||
553 | // a config layer that's introduced by ui.tweakdefaults |
|
591 | // a config layer that's introduced by ui.tweakdefaults | |
554 | fn tweakdefaults_layer() -> ConfigLayer { |
|
592 | fn tweakdefaults_layer() -> ConfigLayer { | |
555 | let mut layer = ConfigLayer::new(ConfigOrigin::Tweakdefaults); |
|
593 | let mut layer = ConfigLayer::new(ConfigOrigin::Tweakdefaults); | |
556 |
|
594 | |||
557 | let mut add = |section: &[u8], item: &[u8], value: &[u8]| { |
|
595 | let mut add = |section: &[u8], item: &[u8], value: &[u8]| { | |
558 | layer.add( |
|
596 | layer.add( | |
559 | section[..].into(), |
|
597 | section[..].into(), | |
560 | item[..].into(), |
|
598 | item[..].into(), | |
561 | value[..].into(), |
|
599 | value[..].into(), | |
562 | None, |
|
600 | None, | |
563 | ); |
|
601 | ); | |
564 | }; |
|
602 | }; | |
565 | // duplication of [tweakrc] from [ui.py] |
|
603 | // duplication of [tweakrc] from [ui.py] | |
566 | add(b"ui", b"rollback", b"False"); |
|
604 | add(b"ui", b"rollback", b"False"); | |
567 | add(b"ui", b"statuscopies", b"yes"); |
|
605 | add(b"ui", b"statuscopies", b"yes"); | |
568 | add(b"ui", b"interface", b"curses"); |
|
606 | add(b"ui", b"interface", b"curses"); | |
569 | add(b"ui", b"relative-paths", b"yes"); |
|
607 | add(b"ui", b"relative-paths", b"yes"); | |
570 | add(b"commands", b"grep.all-files", b"True"); |
|
608 | add(b"commands", b"grep.all-files", b"True"); | |
571 | add(b"commands", b"update.check", b"noconflict"); |
|
609 | add(b"commands", b"update.check", b"noconflict"); | |
572 | add(b"commands", b"status.verbose", b"True"); |
|
610 | add(b"commands", b"status.verbose", b"True"); | |
573 | add(b"commands", b"resolve.explicit-re-merge", b"True"); |
|
611 | add(b"commands", b"resolve.explicit-re-merge", b"True"); | |
574 | add(b"git", b"git", b"1"); |
|
612 | add(b"git", b"git", b"1"); | |
575 | add(b"git", b"showfunc", b"1"); |
|
613 | add(b"git", b"showfunc", b"1"); | |
576 | add(b"git", b"word-diff", b"1"); |
|
614 | add(b"git", b"word-diff", b"1"); | |
577 | layer |
|
615 | layer | |
578 | } |
|
616 | } | |
579 |
|
617 | |||
580 | // introduce the tweaked defaults as implied by ui.tweakdefaults |
|
618 | // introduce the tweaked defaults as implied by ui.tweakdefaults | |
581 | pub fn tweakdefaults(&mut self) { |
|
619 | pub fn tweakdefaults(&mut self) { | |
582 | self.layers.insert(0, Config::tweakdefaults_layer()); |
|
620 | self.layers.insert(0, Config::tweakdefaults_layer()); | |
583 | } |
|
621 | } | |
584 | } |
|
622 | } | |
585 |
|
623 | |||
586 | #[cfg(test)] |
|
624 | #[cfg(test)] | |
587 | mod tests { |
|
625 | mod tests { | |
588 | use super::*; |
|
626 | use super::*; | |
589 | use pretty_assertions::assert_eq; |
|
627 | use pretty_assertions::assert_eq; | |
590 | use std::fs::File; |
|
628 | use std::fs::File; | |
591 | use std::io::Write; |
|
629 | use std::io::Write; | |
592 |
|
630 | |||
593 | #[test] |
|
631 | #[test] | |
594 | fn test_include_layer_ordering() { |
|
632 | fn test_include_layer_ordering() { | |
595 | let tmpdir = tempfile::tempdir().unwrap(); |
|
633 | let tmpdir = tempfile::tempdir().unwrap(); | |
596 | let tmpdir_path = tmpdir.path(); |
|
634 | let tmpdir_path = tmpdir.path(); | |
597 | let mut included_file = |
|
635 | let mut included_file = | |
598 | File::create(&tmpdir_path.join("included.rc")).unwrap(); |
|
636 | File::create(&tmpdir_path.join("included.rc")).unwrap(); | |
599 |
|
637 | |||
600 | included_file.write_all(b"[section]\nitem=value1").unwrap(); |
|
638 | included_file.write_all(b"[section]\nitem=value1").unwrap(); | |
601 | let base_config_path = tmpdir_path.join("base.rc"); |
|
639 | let base_config_path = tmpdir_path.join("base.rc"); | |
602 | let mut config_file = File::create(&base_config_path).unwrap(); |
|
640 | let mut config_file = File::create(&base_config_path).unwrap(); | |
603 | let data = |
|
641 | let data = | |
604 | b"[section]\nitem=value0\n%include included.rc\nitem=value2\n\ |
|
642 | b"[section]\nitem=value0\n%include included.rc\nitem=value2\n\ | |
605 | [section2]\ncount = 4\nsize = 1.5 KB\nnot-count = 1.5\nnot-size = 1 ub"; |
|
643 | [section2]\ncount = 4\nsize = 1.5 KB\nnot-count = 1.5\nnot-size = 1 ub"; | |
606 | config_file.write_all(data).unwrap(); |
|
644 | config_file.write_all(data).unwrap(); | |
607 |
|
645 | |||
608 | let sources = vec![ConfigSource::AbsPath(base_config_path)]; |
|
646 | let sources = vec![ConfigSource::AbsPath(base_config_path)]; | |
609 | let config = Config::load_from_explicit_sources(sources) |
|
647 | let config = Config::load_from_explicit_sources(sources) | |
610 | .expect("expected valid config"); |
|
648 | .expect("expected valid config"); | |
611 |
|
649 | |||
612 | let (_, value) = config.get_inner(b"section", b"item").unwrap(); |
|
650 | let (_, value) = config.get_inner(b"section", b"item").unwrap(); | |
613 | assert_eq!( |
|
651 | assert_eq!( | |
614 | value, |
|
652 | value, | |
615 | &ConfigValue { |
|
653 | &ConfigValue { | |
616 | bytes: b"value2".to_vec(), |
|
654 | bytes: b"value2".to_vec(), | |
617 | line: Some(4) |
|
655 | line: Some(4) | |
618 | } |
|
656 | } | |
619 | ); |
|
657 | ); | |
620 |
|
658 | |||
621 | let value = config.get(b"section", b"item").unwrap(); |
|
659 | let value = config.get(b"section", b"item").unwrap(); | |
622 | assert_eq!(value, b"value2",); |
|
660 | assert_eq!(value, b"value2",); | |
623 | assert_eq!( |
|
661 | assert_eq!( | |
624 | config.get_all(b"section", b"item"), |
|
662 | config.get_all(b"section", b"item"), | |
625 | [b"value2", b"value1", b"value0"] |
|
663 | [b"value2", b"value1", b"value0"] | |
626 | ); |
|
664 | ); | |
627 |
|
665 | |||
628 | assert_eq!(config.get_u32(b"section2", b"count").unwrap(), Some(4)); |
|
666 | assert_eq!(config.get_u32(b"section2", b"count").unwrap(), Some(4)); | |
629 | assert_eq!( |
|
667 | assert_eq!( | |
630 | config.get_byte_size(b"section2", b"size").unwrap(), |
|
668 | config.get_byte_size(b"section2", b"size").unwrap(), | |
631 | Some(1024 + 512) |
|
669 | Some(1024 + 512) | |
632 | ); |
|
670 | ); | |
633 | assert!(config.get_u32(b"section2", b"not-count").is_err()); |
|
671 | assert!(config.get_u32(b"section2", b"not-count").is_err()); | |
634 | assert!(config.get_byte_size(b"section2", b"not-size").is_err()); |
|
672 | assert!(config.get_byte_size(b"section2", b"not-size").is_err()); | |
635 | } |
|
673 | } | |
636 | } |
|
674 | } |
@@ -1,675 +1,689 b'' | |||||
1 | // status.rs |
|
1 | // status.rs | |
2 | // |
|
2 | // | |
3 | // Copyright 2020, Georges Racinet <georges.racinets@octobus.net> |
|
3 | // Copyright 2020, Georges Racinet <georges.racinets@octobus.net> | |
4 | // |
|
4 | // | |
5 | // This software may be used and distributed according to the terms of the |
|
5 | // This software may be used and distributed according to the terms of the | |
6 | // GNU General Public License version 2 or any later version. |
|
6 | // GNU General Public License version 2 or any later version. | |
7 |
|
7 | |||
8 | use crate::error::CommandError; |
|
8 | use crate::error::CommandError; | |
9 | use crate::ui::{ |
|
9 | use crate::ui::{ | |
10 |
format_pattern_file_warning, print_narrow_sparse_warnings, |
|
10 | format_pattern_file_warning, print_narrow_sparse_warnings, relative_paths, | |
|
11 | RelativePaths, Ui, | |||
11 | }; |
|
12 | }; | |
12 | use crate::utils::path_utils::RelativizePaths; |
|
13 | use crate::utils::path_utils::RelativizePaths; | |
13 | use clap::Arg; |
|
14 | use clap::Arg; | |
14 | use format_bytes::format_bytes; |
|
15 | use format_bytes::format_bytes; | |
15 | use hg::config::Config; |
|
16 | use hg::config::Config; | |
16 | use hg::dirstate::has_exec_bit; |
|
17 | use hg::dirstate::has_exec_bit; | |
17 | use hg::dirstate::status::StatusPath; |
|
18 | use hg::dirstate::status::StatusPath; | |
18 | use hg::dirstate::TruncatedTimestamp; |
|
19 | use hg::dirstate::TruncatedTimestamp; | |
19 | use hg::errors::{HgError, IoResultExt}; |
|
20 | use hg::errors::{HgError, IoResultExt}; | |
20 | use hg::lock::LockError; |
|
21 | use hg::lock::LockError; | |
21 | use hg::manifest::Manifest; |
|
22 | use hg::manifest::Manifest; | |
22 | use hg::matchers::{AlwaysMatcher, IntersectionMatcher}; |
|
23 | use hg::matchers::{AlwaysMatcher, IntersectionMatcher}; | |
23 | use hg::repo::Repo; |
|
24 | use hg::repo::Repo; | |
24 | use hg::utils::debug::debug_wait_for_file; |
|
25 | use hg::utils::debug::debug_wait_for_file; | |
25 | use hg::utils::files::get_bytes_from_os_string; |
|
26 | use hg::utils::files::get_bytes_from_os_string; | |
26 | use hg::utils::files::get_path_from_bytes; |
|
27 | use hg::utils::files::get_path_from_bytes; | |
27 | use hg::utils::hg_path::{hg_path_to_path_buf, HgPath}; |
|
28 | use hg::utils::hg_path::{hg_path_to_path_buf, HgPath}; | |
28 | use hg::DirstateStatus; |
|
29 | use hg::DirstateStatus; | |
29 | use hg::PatternFileWarning; |
|
30 | use hg::PatternFileWarning; | |
30 | use hg::StatusError; |
|
31 | use hg::StatusError; | |
31 | use hg::StatusOptions; |
|
32 | use hg::StatusOptions; | |
32 | use hg::{self, narrow, sparse}; |
|
33 | use hg::{self, narrow, sparse}; | |
33 | use log::info; |
|
34 | use log::info; | |
34 | use rayon::prelude::*; |
|
35 | use rayon::prelude::*; | |
35 | use std::io; |
|
36 | use std::io; | |
36 | use std::path::PathBuf; |
|
37 | use std::path::PathBuf; | |
37 |
|
38 | |||
38 | pub const HELP_TEXT: &str = " |
|
39 | pub const HELP_TEXT: &str = " | |
39 | Show changed files in the working directory |
|
40 | Show changed files in the working directory | |
40 |
|
41 | |||
41 | This is a pure Rust version of `hg status`. |
|
42 | This is a pure Rust version of `hg status`. | |
42 |
|
43 | |||
43 | Some options might be missing, check the list below. |
|
44 | Some options might be missing, check the list below. | |
44 | "; |
|
45 | "; | |
45 |
|
46 | |||
46 | pub fn args() -> clap::Command { |
|
47 | pub fn args() -> clap::Command { | |
47 | clap::command!("status") |
|
48 | clap::command!("status") | |
48 | .alias("st") |
|
49 | .alias("st") | |
49 | .about(HELP_TEXT) |
|
50 | .about(HELP_TEXT) | |
50 | .arg( |
|
51 | .arg( | |
51 | Arg::new("all") |
|
52 | Arg::new("all") | |
52 | .help("show status of all files") |
|
53 | .help("show status of all files") | |
53 | .short('A') |
|
54 | .short('A') | |
54 | .action(clap::ArgAction::SetTrue) |
|
55 | .action(clap::ArgAction::SetTrue) | |
55 | .long("all"), |
|
56 | .long("all"), | |
56 | ) |
|
57 | ) | |
57 | .arg( |
|
58 | .arg( | |
58 | Arg::new("modified") |
|
59 | Arg::new("modified") | |
59 | .help("show only modified files") |
|
60 | .help("show only modified files") | |
60 | .short('m') |
|
61 | .short('m') | |
61 | .action(clap::ArgAction::SetTrue) |
|
62 | .action(clap::ArgAction::SetTrue) | |
62 | .long("modified"), |
|
63 | .long("modified"), | |
63 | ) |
|
64 | ) | |
64 | .arg( |
|
65 | .arg( | |
65 | Arg::new("added") |
|
66 | Arg::new("added") | |
66 | .help("show only added files") |
|
67 | .help("show only added files") | |
67 | .short('a') |
|
68 | .short('a') | |
68 | .action(clap::ArgAction::SetTrue) |
|
69 | .action(clap::ArgAction::SetTrue) | |
69 | .long("added"), |
|
70 | .long("added"), | |
70 | ) |
|
71 | ) | |
71 | .arg( |
|
72 | .arg( | |
72 | Arg::new("removed") |
|
73 | Arg::new("removed") | |
73 | .help("show only removed files") |
|
74 | .help("show only removed files") | |
74 | .short('r') |
|
75 | .short('r') | |
75 | .action(clap::ArgAction::SetTrue) |
|
76 | .action(clap::ArgAction::SetTrue) | |
76 | .long("removed"), |
|
77 | .long("removed"), | |
77 | ) |
|
78 | ) | |
78 | .arg( |
|
79 | .arg( | |
79 | Arg::new("clean") |
|
80 | Arg::new("clean") | |
80 | .help("show only clean files") |
|
81 | .help("show only clean files") | |
81 | .short('c') |
|
82 | .short('c') | |
82 | .action(clap::ArgAction::SetTrue) |
|
83 | .action(clap::ArgAction::SetTrue) | |
83 | .long("clean"), |
|
84 | .long("clean"), | |
84 | ) |
|
85 | ) | |
85 | .arg( |
|
86 | .arg( | |
86 | Arg::new("deleted") |
|
87 | Arg::new("deleted") | |
87 | .help("show only deleted files") |
|
88 | .help("show only deleted files") | |
88 | .short('d') |
|
89 | .short('d') | |
89 | .action(clap::ArgAction::SetTrue) |
|
90 | .action(clap::ArgAction::SetTrue) | |
90 | .long("deleted"), |
|
91 | .long("deleted"), | |
91 | ) |
|
92 | ) | |
92 | .arg( |
|
93 | .arg( | |
93 | Arg::new("unknown") |
|
94 | Arg::new("unknown") | |
94 | .help("show only unknown (not tracked) files") |
|
95 | .help("show only unknown (not tracked) files") | |
95 | .short('u') |
|
96 | .short('u') | |
96 | .action(clap::ArgAction::SetTrue) |
|
97 | .action(clap::ArgAction::SetTrue) | |
97 | .long("unknown"), |
|
98 | .long("unknown"), | |
98 | ) |
|
99 | ) | |
99 | .arg( |
|
100 | .arg( | |
100 | Arg::new("ignored") |
|
101 | Arg::new("ignored") | |
101 | .help("show only ignored files") |
|
102 | .help("show only ignored files") | |
102 | .short('i') |
|
103 | .short('i') | |
103 | .action(clap::ArgAction::SetTrue) |
|
104 | .action(clap::ArgAction::SetTrue) | |
104 | .long("ignored"), |
|
105 | .long("ignored"), | |
105 | ) |
|
106 | ) | |
106 | .arg( |
|
107 | .arg( | |
107 | Arg::new("copies") |
|
108 | Arg::new("copies") | |
108 | .help("show source of copied files (DEFAULT: ui.statuscopies)") |
|
109 | .help("show source of copied files (DEFAULT: ui.statuscopies)") | |
109 | .short('C') |
|
110 | .short('C') | |
110 | .action(clap::ArgAction::SetTrue) |
|
111 | .action(clap::ArgAction::SetTrue) | |
111 | .long("copies"), |
|
112 | .long("copies"), | |
112 | ) |
|
113 | ) | |
113 | .arg( |
|
114 | .arg( | |
114 | Arg::new("print0") |
|
115 | Arg::new("print0") | |
115 | .help("end filenames with NUL, for use with xargs") |
|
116 | .help("end filenames with NUL, for use with xargs") | |
116 | .short('0') |
|
117 | .short('0') | |
117 | .action(clap::ArgAction::SetTrue) |
|
118 | .action(clap::ArgAction::SetTrue) | |
118 | .long("print0"), |
|
119 | .long("print0"), | |
119 | ) |
|
120 | ) | |
120 | .arg( |
|
121 | .arg( | |
121 | Arg::new("no-status") |
|
122 | Arg::new("no-status") | |
122 | .help("hide status prefix") |
|
123 | .help("hide status prefix") | |
123 | .short('n') |
|
124 | .short('n') | |
124 | .action(clap::ArgAction::SetTrue) |
|
125 | .action(clap::ArgAction::SetTrue) | |
125 | .long("no-status"), |
|
126 | .long("no-status"), | |
126 | ) |
|
127 | ) | |
127 | .arg( |
|
128 | .arg( | |
128 | Arg::new("verbose") |
|
129 | Arg::new("verbose") | |
129 | .help("enable additional output") |
|
130 | .help("enable additional output") | |
130 | .short('v') |
|
131 | .short('v') | |
131 | .action(clap::ArgAction::SetTrue) |
|
132 | .action(clap::ArgAction::SetTrue) | |
132 | .long("verbose"), |
|
133 | .long("verbose"), | |
133 | ) |
|
134 | ) | |
134 | } |
|
135 | } | |
135 |
|
136 | |||
136 | /// Pure data type allowing the caller to specify file states to display |
|
137 | /// Pure data type allowing the caller to specify file states to display | |
137 | #[derive(Copy, Clone, Debug)] |
|
138 | #[derive(Copy, Clone, Debug)] | |
138 | pub struct DisplayStates { |
|
139 | pub struct DisplayStates { | |
139 | pub modified: bool, |
|
140 | pub modified: bool, | |
140 | pub added: bool, |
|
141 | pub added: bool, | |
141 | pub removed: bool, |
|
142 | pub removed: bool, | |
142 | pub clean: bool, |
|
143 | pub clean: bool, | |
143 | pub deleted: bool, |
|
144 | pub deleted: bool, | |
144 | pub unknown: bool, |
|
145 | pub unknown: bool, | |
145 | pub ignored: bool, |
|
146 | pub ignored: bool, | |
146 | } |
|
147 | } | |
147 |
|
148 | |||
148 | pub const DEFAULT_DISPLAY_STATES: DisplayStates = DisplayStates { |
|
149 | pub const DEFAULT_DISPLAY_STATES: DisplayStates = DisplayStates { | |
149 | modified: true, |
|
150 | modified: true, | |
150 | added: true, |
|
151 | added: true, | |
151 | removed: true, |
|
152 | removed: true, | |
152 | clean: false, |
|
153 | clean: false, | |
153 | deleted: true, |
|
154 | deleted: true, | |
154 | unknown: true, |
|
155 | unknown: true, | |
155 | ignored: false, |
|
156 | ignored: false, | |
156 | }; |
|
157 | }; | |
157 |
|
158 | |||
158 | pub const ALL_DISPLAY_STATES: DisplayStates = DisplayStates { |
|
159 | pub const ALL_DISPLAY_STATES: DisplayStates = DisplayStates { | |
159 | modified: true, |
|
160 | modified: true, | |
160 | added: true, |
|
161 | added: true, | |
161 | removed: true, |
|
162 | removed: true, | |
162 | clean: true, |
|
163 | clean: true, | |
163 | deleted: true, |
|
164 | deleted: true, | |
164 | unknown: true, |
|
165 | unknown: true, | |
165 | ignored: true, |
|
166 | ignored: true, | |
166 | }; |
|
167 | }; | |
167 |
|
168 | |||
168 | impl DisplayStates { |
|
169 | impl DisplayStates { | |
169 | pub fn is_empty(&self) -> bool { |
|
170 | pub fn is_empty(&self) -> bool { | |
170 | !(self.modified |
|
171 | !(self.modified | |
171 | || self.added |
|
172 | || self.added | |
172 | || self.removed |
|
173 | || self.removed | |
173 | || self.clean |
|
174 | || self.clean | |
174 | || self.deleted |
|
175 | || self.deleted | |
175 | || self.unknown |
|
176 | || self.unknown | |
176 | || self.ignored) |
|
177 | || self.ignored) | |
177 | } |
|
178 | } | |
178 | } |
|
179 | } | |
179 |
|
180 | |||
180 | fn has_unfinished_merge(repo: &Repo) -> Result<bool, CommandError> { |
|
181 | fn has_unfinished_merge(repo: &Repo) -> Result<bool, CommandError> { | |
181 | Ok(repo.dirstate_parents()?.is_merge()) |
|
182 | Ok(repo.dirstate_parents()?.is_merge()) | |
182 | } |
|
183 | } | |
183 |
|
184 | |||
184 | fn has_unfinished_state(repo: &Repo) -> Result<bool, CommandError> { |
|
185 | fn has_unfinished_state(repo: &Repo) -> Result<bool, CommandError> { | |
185 | // These are all the known values for the [fname] argument of |
|
186 | // These are all the known values for the [fname] argument of | |
186 | // [addunfinished] function in [state.py] |
|
187 | // [addunfinished] function in [state.py] | |
187 | let known_state_files: &[&str] = &[ |
|
188 | let known_state_files: &[&str] = &[ | |
188 | "bisect.state", |
|
189 | "bisect.state", | |
189 | "graftstate", |
|
190 | "graftstate", | |
190 | "histedit-state", |
|
191 | "histedit-state", | |
191 | "rebasestate", |
|
192 | "rebasestate", | |
192 | "shelvedstate", |
|
193 | "shelvedstate", | |
193 | "transplant/journal", |
|
194 | "transplant/journal", | |
194 | "updatestate", |
|
195 | "updatestate", | |
195 | ]; |
|
196 | ]; | |
196 | if has_unfinished_merge(repo)? { |
|
197 | if has_unfinished_merge(repo)? { | |
197 | return Ok(true); |
|
198 | return Ok(true); | |
198 | }; |
|
199 | }; | |
199 | for f in known_state_files { |
|
200 | for f in known_state_files { | |
200 | if repo.hg_vfs().join(f).exists() { |
|
201 | if repo.hg_vfs().join(f).exists() { | |
201 | return Ok(true); |
|
202 | return Ok(true); | |
202 | } |
|
203 | } | |
203 | } |
|
204 | } | |
204 | Ok(false) |
|
205 | Ok(false) | |
205 | } |
|
206 | } | |
206 |
|
207 | |||
207 | pub fn run(invocation: &crate::CliInvocation) -> Result<(), CommandError> { |
|
208 | pub fn run(invocation: &crate::CliInvocation) -> Result<(), CommandError> { | |
208 | // TODO: lift these limitations |
|
209 | // TODO: lift these limitations | |
209 | if invocation |
|
210 | if invocation | |
210 | .config |
|
211 | .config | |
211 | .get(b"commands", b"status.terse") |
|
212 | .get(b"commands", b"status.terse") | |
212 | .is_some() |
|
213 | .is_some() | |
213 | { |
|
214 | { | |
214 | return Err(CommandError::unsupported( |
|
215 | return Err(CommandError::unsupported( | |
215 | "status.terse is not yet supported with rhg status", |
|
216 | "status.terse is not yet supported with rhg status", | |
216 | )); |
|
217 | )); | |
217 | } |
|
218 | } | |
218 |
|
219 | |||
219 | let ui = invocation.ui; |
|
220 | let ui = invocation.ui; | |
220 | let config = invocation.config; |
|
221 | let config = invocation.config; | |
221 | let args = invocation.subcommand_args; |
|
222 | let args = invocation.subcommand_args; | |
222 |
|
223 | |||
223 | let print0 = args.get_flag("print0"); |
|
224 | let print0 = args.get_flag("print0"); | |
224 | let verbose = args.get_flag("verbose") |
|
225 | let verbose = args.get_flag("verbose") | |
225 | || config.get_bool(b"ui", b"verbose")? |
|
226 | || config.get_bool(b"ui", b"verbose")? | |
226 | || config.get_bool(b"commands", b"status.verbose")?; |
|
227 | || config.get_bool(b"commands", b"status.verbose")?; | |
227 | let verbose = verbose && !print0; |
|
228 | let verbose = verbose && !print0; | |
228 |
|
229 | |||
229 | let all = args.get_flag("all"); |
|
230 | let all = args.get_flag("all"); | |
230 | let display_states = if all { |
|
231 | let display_states = if all { | |
231 | // TODO when implementing `--quiet`: it excludes clean files |
|
232 | // TODO when implementing `--quiet`: it excludes clean files | |
232 | // from `--all` |
|
233 | // from `--all` | |
233 | ALL_DISPLAY_STATES |
|
234 | ALL_DISPLAY_STATES | |
234 | } else { |
|
235 | } else { | |
235 | let requested = DisplayStates { |
|
236 | let requested = DisplayStates { | |
236 | modified: args.get_flag("modified"), |
|
237 | modified: args.get_flag("modified"), | |
237 | added: args.get_flag("added"), |
|
238 | added: args.get_flag("added"), | |
238 | removed: args.get_flag("removed"), |
|
239 | removed: args.get_flag("removed"), | |
239 | clean: args.get_flag("clean"), |
|
240 | clean: args.get_flag("clean"), | |
240 | deleted: args.get_flag("deleted"), |
|
241 | deleted: args.get_flag("deleted"), | |
241 | unknown: args.get_flag("unknown"), |
|
242 | unknown: args.get_flag("unknown"), | |
242 | ignored: args.get_flag("ignored"), |
|
243 | ignored: args.get_flag("ignored"), | |
243 | }; |
|
244 | }; | |
244 | if requested.is_empty() { |
|
245 | if requested.is_empty() { | |
245 | DEFAULT_DISPLAY_STATES |
|
246 | DEFAULT_DISPLAY_STATES | |
246 | } else { |
|
247 | } else { | |
247 | requested |
|
248 | requested | |
248 | } |
|
249 | } | |
249 | }; |
|
250 | }; | |
250 | let no_status = args.get_flag("no-status"); |
|
251 | let no_status = args.get_flag("no-status"); | |
251 | let list_copies = all |
|
252 | let list_copies = all | |
252 | || args.get_flag("copies") |
|
253 | || args.get_flag("copies") | |
253 | || config.get_bool(b"ui", b"statuscopies")?; |
|
254 | || config.get_bool(b"ui", b"statuscopies")?; | |
254 |
|
255 | |||
255 | let repo = invocation.repo?; |
|
256 | let repo = invocation.repo?; | |
256 |
|
257 | |||
257 | if verbose && has_unfinished_state(repo)? { |
|
258 | if verbose && has_unfinished_state(repo)? { | |
258 | return Err(CommandError::unsupported( |
|
259 | return Err(CommandError::unsupported( | |
259 | "verbose status output is not supported by rhg (and is needed because we're in an unfinished operation)", |
|
260 | "verbose status output is not supported by rhg (and is needed because we're in an unfinished operation)", | |
260 | )); |
|
261 | )); | |
261 | } |
|
262 | } | |
262 |
|
263 | |||
263 | let mut dmap = repo.dirstate_map_mut()?; |
|
264 | let mut dmap = repo.dirstate_map_mut()?; | |
264 |
|
265 | |||
265 | let check_exec = hg::checkexec::check_exec(repo.working_directory_path()); |
|
266 | let check_exec = hg::checkexec::check_exec(repo.working_directory_path()); | |
266 |
|
267 | |||
267 | let options = StatusOptions { |
|
268 | let options = StatusOptions { | |
268 | check_exec, |
|
269 | check_exec, | |
269 | list_clean: display_states.clean, |
|
270 | list_clean: display_states.clean, | |
270 | list_unknown: display_states.unknown, |
|
271 | list_unknown: display_states.unknown, | |
271 | list_ignored: display_states.ignored, |
|
272 | list_ignored: display_states.ignored, | |
272 | list_copies, |
|
273 | list_copies, | |
273 | collect_traversed_dirs: false, |
|
274 | collect_traversed_dirs: false, | |
274 | }; |
|
275 | }; | |
275 |
|
276 | |||
276 | type StatusResult<'a> = |
|
277 | type StatusResult<'a> = | |
277 | Result<(DirstateStatus<'a>, Vec<PatternFileWarning>), StatusError>; |
|
278 | Result<(DirstateStatus<'a>, Vec<PatternFileWarning>), StatusError>; | |
278 |
|
279 | |||
279 | let after_status = |res: StatusResult| -> Result<_, CommandError> { |
|
280 | let after_status = |res: StatusResult| -> Result<_, CommandError> { | |
280 | let (mut ds_status, pattern_warnings) = res?; |
|
281 | let (mut ds_status, pattern_warnings) = res?; | |
281 | for warning in pattern_warnings { |
|
282 | for warning in pattern_warnings { | |
282 | ui.write_stderr(&format_pattern_file_warning(&warning, repo))?; |
|
283 | ui.write_stderr(&format_pattern_file_warning(&warning, repo))?; | |
283 | } |
|
284 | } | |
284 |
|
285 | |||
285 | for (path, error) in ds_status.bad { |
|
286 | for (path, error) in ds_status.bad { | |
286 | let error = match error { |
|
287 | let error = match error { | |
287 | hg::BadMatch::OsError(code) => { |
|
288 | hg::BadMatch::OsError(code) => { | |
288 | std::io::Error::from_raw_os_error(code).to_string() |
|
289 | std::io::Error::from_raw_os_error(code).to_string() | |
289 | } |
|
290 | } | |
290 | hg::BadMatch::BadType(ty) => { |
|
291 | hg::BadMatch::BadType(ty) => { | |
291 | format!("unsupported file type (type is {})", ty) |
|
292 | format!("unsupported file type (type is {})", ty) | |
292 | } |
|
293 | } | |
293 | }; |
|
294 | }; | |
294 | ui.write_stderr(&format_bytes!( |
|
295 | ui.write_stderr(&format_bytes!( | |
295 | b"{}: {}\n", |
|
296 | b"{}: {}\n", | |
296 | path.as_bytes(), |
|
297 | path.as_bytes(), | |
297 | error.as_bytes() |
|
298 | error.as_bytes() | |
298 | ))? |
|
299 | ))? | |
299 | } |
|
300 | } | |
300 | if !ds_status.unsure.is_empty() { |
|
301 | if !ds_status.unsure.is_empty() { | |
301 | info!( |
|
302 | info!( | |
302 | "Files to be rechecked by retrieval from filelog: {:?}", |
|
303 | "Files to be rechecked by retrieval from filelog: {:?}", | |
303 | ds_status.unsure.iter().map(|s| &s.path).collect::<Vec<_>>() |
|
304 | ds_status.unsure.iter().map(|s| &s.path).collect::<Vec<_>>() | |
304 | ); |
|
305 | ); | |
305 | } |
|
306 | } | |
306 | let mut fixup = Vec::new(); |
|
307 | let mut fixup = Vec::new(); | |
307 | if !ds_status.unsure.is_empty() |
|
308 | if !ds_status.unsure.is_empty() | |
308 | && (display_states.modified || display_states.clean) |
|
309 | && (display_states.modified || display_states.clean) | |
309 | { |
|
310 | { | |
310 | let p1 = repo.dirstate_parents()?.p1; |
|
311 | let p1 = repo.dirstate_parents()?.p1; | |
311 | let manifest = repo.manifest_for_node(p1).map_err(|e| { |
|
312 | let manifest = repo.manifest_for_node(p1).map_err(|e| { | |
312 | CommandError::from((e, &*format!("{:x}", p1.short()))) |
|
313 | CommandError::from((e, &*format!("{:x}", p1.short()))) | |
313 | })?; |
|
314 | })?; | |
314 | let working_directory_vfs = repo.working_directory_vfs(); |
|
315 | let working_directory_vfs = repo.working_directory_vfs(); | |
315 | let store_vfs = repo.store_vfs(); |
|
316 | let store_vfs = repo.store_vfs(); | |
316 | let res: Vec<_> = ds_status |
|
317 | let res: Vec<_> = ds_status | |
317 | .unsure |
|
318 | .unsure | |
318 | .into_par_iter() |
|
319 | .into_par_iter() | |
319 | .map(|to_check| { |
|
320 | .map(|to_check| { | |
320 | // The compiler seems to get a bit confused with complex |
|
321 | // The compiler seems to get a bit confused with complex | |
321 | // inference when using a parallel iterator + map |
|
322 | // inference when using a parallel iterator + map | |
322 | // + map_err + collect, so let's just inline some of the |
|
323 | // + map_err + collect, so let's just inline some of the | |
323 | // logic. |
|
324 | // logic. | |
324 | match unsure_is_modified( |
|
325 | match unsure_is_modified( | |
325 | working_directory_vfs, |
|
326 | working_directory_vfs, | |
326 | store_vfs, |
|
327 | store_vfs, | |
327 | check_exec, |
|
328 | check_exec, | |
328 | &manifest, |
|
329 | &manifest, | |
329 | &to_check.path, |
|
330 | &to_check.path, | |
330 | ) { |
|
331 | ) { | |
331 | Err(HgError::IoError { .. }) => { |
|
332 | Err(HgError::IoError { .. }) => { | |
332 | // IO errors most likely stem from the file being |
|
333 | // IO errors most likely stem from the file being | |
333 | // deleted even though we know it's in the |
|
334 | // deleted even though we know it's in the | |
334 | // dirstate. |
|
335 | // dirstate. | |
335 | Ok((to_check, UnsureOutcome::Deleted)) |
|
336 | Ok((to_check, UnsureOutcome::Deleted)) | |
336 | } |
|
337 | } | |
337 | Ok(outcome) => Ok((to_check, outcome)), |
|
338 | Ok(outcome) => Ok((to_check, outcome)), | |
338 | Err(e) => Err(e), |
|
339 | Err(e) => Err(e), | |
339 | } |
|
340 | } | |
340 | }) |
|
341 | }) | |
341 | .collect::<Result<_, _>>()?; |
|
342 | .collect::<Result<_, _>>()?; | |
342 | for (status_path, outcome) in res.into_iter() { |
|
343 | for (status_path, outcome) in res.into_iter() { | |
343 | match outcome { |
|
344 | match outcome { | |
344 | UnsureOutcome::Clean => { |
|
345 | UnsureOutcome::Clean => { | |
345 | if display_states.clean { |
|
346 | if display_states.clean { | |
346 | ds_status.clean.push(status_path.clone()); |
|
347 | ds_status.clean.push(status_path.clone()); | |
347 | } |
|
348 | } | |
348 | fixup.push(status_path.path.into_owned()) |
|
349 | fixup.push(status_path.path.into_owned()) | |
349 | } |
|
350 | } | |
350 | UnsureOutcome::Modified => { |
|
351 | UnsureOutcome::Modified => { | |
351 | if display_states.modified { |
|
352 | if display_states.modified { | |
352 | ds_status.modified.push(status_path); |
|
353 | ds_status.modified.push(status_path); | |
353 | } |
|
354 | } | |
354 | } |
|
355 | } | |
355 | UnsureOutcome::Deleted => { |
|
356 | UnsureOutcome::Deleted => { | |
356 | if display_states.deleted { |
|
357 | if display_states.deleted { | |
357 | ds_status.deleted.push(status_path); |
|
358 | ds_status.deleted.push(status_path); | |
358 | } |
|
359 | } | |
359 | } |
|
360 | } | |
360 | } |
|
361 | } | |
361 | } |
|
362 | } | |
362 | } |
|
363 | } | |
363 | let relative_paths = config |
|
364 | ||
|
365 | let relative_status = config | |||
364 | .get_option(b"commands", b"status.relative")? |
|
366 | .get_option(b"commands", b"status.relative")? | |
365 | .unwrap_or(config.get_bool(b"ui", b"relative-paths")?); |
|
367 | .expect("commands.status.relative should have a default value"); | |
|
368 | ||||
|
369 | let relativize_paths = relative_status || { | |||
|
370 | // TODO should be dependent on whether patterns are passed once | |||
|
371 | // we support those. | |||
|
372 | // See in Python code with `getuipathfn` usage in `commands.py`. | |||
|
373 | let legacy_relative_behavior = false; | |||
|
374 | match relative_paths(invocation.config)? { | |||
|
375 | RelativePaths::Legacy => legacy_relative_behavior, | |||
|
376 | RelativePaths::Bool(v) => v, | |||
|
377 | } | |||
|
378 | }; | |||
|
379 | ||||
366 | let output = DisplayStatusPaths { |
|
380 | let output = DisplayStatusPaths { | |
367 | ui, |
|
381 | ui, | |
368 | no_status, |
|
382 | no_status, | |
369 | relativize: if relative_paths { |
|
383 | relativize: if relativize_paths { | |
370 | Some(RelativizePaths::new(repo)?) |
|
384 | Some(RelativizePaths::new(repo)?) | |
371 | } else { |
|
385 | } else { | |
372 | None |
|
386 | None | |
373 | }, |
|
387 | }, | |
374 | print0, |
|
388 | print0, | |
375 | }; |
|
389 | }; | |
376 | if display_states.modified { |
|
390 | if display_states.modified { | |
377 | output.display(b"M ", "status.modified", ds_status.modified)?; |
|
391 | output.display(b"M ", "status.modified", ds_status.modified)?; | |
378 | } |
|
392 | } | |
379 | if display_states.added { |
|
393 | if display_states.added { | |
380 | output.display(b"A ", "status.added", ds_status.added)?; |
|
394 | output.display(b"A ", "status.added", ds_status.added)?; | |
381 | } |
|
395 | } | |
382 | if display_states.removed { |
|
396 | if display_states.removed { | |
383 | output.display(b"R ", "status.removed", ds_status.removed)?; |
|
397 | output.display(b"R ", "status.removed", ds_status.removed)?; | |
384 | } |
|
398 | } | |
385 | if display_states.deleted { |
|
399 | if display_states.deleted { | |
386 | output.display(b"! ", "status.deleted", ds_status.deleted)?; |
|
400 | output.display(b"! ", "status.deleted", ds_status.deleted)?; | |
387 | } |
|
401 | } | |
388 | if display_states.unknown { |
|
402 | if display_states.unknown { | |
389 | output.display(b"? ", "status.unknown", ds_status.unknown)?; |
|
403 | output.display(b"? ", "status.unknown", ds_status.unknown)?; | |
390 | } |
|
404 | } | |
391 | if display_states.ignored { |
|
405 | if display_states.ignored { | |
392 | output.display(b"I ", "status.ignored", ds_status.ignored)?; |
|
406 | output.display(b"I ", "status.ignored", ds_status.ignored)?; | |
393 | } |
|
407 | } | |
394 | if display_states.clean { |
|
408 | if display_states.clean { | |
395 | output.display(b"C ", "status.clean", ds_status.clean)?; |
|
409 | output.display(b"C ", "status.clean", ds_status.clean)?; | |
396 | } |
|
410 | } | |
397 |
|
411 | |||
398 | let dirstate_write_needed = ds_status.dirty; |
|
412 | let dirstate_write_needed = ds_status.dirty; | |
399 | let filesystem_time_at_status_start = |
|
413 | let filesystem_time_at_status_start = | |
400 | ds_status.filesystem_time_at_status_start; |
|
414 | ds_status.filesystem_time_at_status_start; | |
401 |
|
415 | |||
402 | Ok(( |
|
416 | Ok(( | |
403 | fixup, |
|
417 | fixup, | |
404 | dirstate_write_needed, |
|
418 | dirstate_write_needed, | |
405 | filesystem_time_at_status_start, |
|
419 | filesystem_time_at_status_start, | |
406 | )) |
|
420 | )) | |
407 | }; |
|
421 | }; | |
408 | let (narrow_matcher, narrow_warnings) = narrow::matcher(repo)?; |
|
422 | let (narrow_matcher, narrow_warnings) = narrow::matcher(repo)?; | |
409 | let (sparse_matcher, sparse_warnings) = sparse::matcher(repo)?; |
|
423 | let (sparse_matcher, sparse_warnings) = sparse::matcher(repo)?; | |
410 | let matcher = match (repo.has_narrow(), repo.has_sparse()) { |
|
424 | let matcher = match (repo.has_narrow(), repo.has_sparse()) { | |
411 | (true, true) => { |
|
425 | (true, true) => { | |
412 | Box::new(IntersectionMatcher::new(narrow_matcher, sparse_matcher)) |
|
426 | Box::new(IntersectionMatcher::new(narrow_matcher, sparse_matcher)) | |
413 | } |
|
427 | } | |
414 | (true, false) => narrow_matcher, |
|
428 | (true, false) => narrow_matcher, | |
415 | (false, true) => sparse_matcher, |
|
429 | (false, true) => sparse_matcher, | |
416 | (false, false) => Box::new(AlwaysMatcher), |
|
430 | (false, false) => Box::new(AlwaysMatcher), | |
417 | }; |
|
431 | }; | |
418 |
|
432 | |||
419 | print_narrow_sparse_warnings( |
|
433 | print_narrow_sparse_warnings( | |
420 | &narrow_warnings, |
|
434 | &narrow_warnings, | |
421 | &sparse_warnings, |
|
435 | &sparse_warnings, | |
422 | ui, |
|
436 | ui, | |
423 | repo, |
|
437 | repo, | |
424 | )?; |
|
438 | )?; | |
425 | let (fixup, mut dirstate_write_needed, filesystem_time_at_status_start) = |
|
439 | let (fixup, mut dirstate_write_needed, filesystem_time_at_status_start) = | |
426 | dmap.with_status( |
|
440 | dmap.with_status( | |
427 | matcher.as_ref(), |
|
441 | matcher.as_ref(), | |
428 | repo.working_directory_path().to_owned(), |
|
442 | repo.working_directory_path().to_owned(), | |
429 | ignore_files(repo, config), |
|
443 | ignore_files(repo, config), | |
430 | options, |
|
444 | options, | |
431 | after_status, |
|
445 | after_status, | |
432 | )?; |
|
446 | )?; | |
433 |
|
447 | |||
434 | // Development config option to test write races |
|
448 | // Development config option to test write races | |
435 | if let Err(e) = |
|
449 | if let Err(e) = | |
436 | debug_wait_for_file(config, "status.pre-dirstate-write-file") |
|
450 | debug_wait_for_file(config, "status.pre-dirstate-write-file") | |
437 | { |
|
451 | { | |
438 | ui.write_stderr(e.as_bytes()).ok(); |
|
452 | ui.write_stderr(e.as_bytes()).ok(); | |
439 | } |
|
453 | } | |
440 |
|
454 | |||
441 | if (fixup.is_empty() || filesystem_time_at_status_start.is_none()) |
|
455 | if (fixup.is_empty() || filesystem_time_at_status_start.is_none()) | |
442 | && !dirstate_write_needed |
|
456 | && !dirstate_write_needed | |
443 | { |
|
457 | { | |
444 | // Nothing to update |
|
458 | // Nothing to update | |
445 | return Ok(()); |
|
459 | return Ok(()); | |
446 | } |
|
460 | } | |
447 |
|
461 | |||
448 | // Update the dirstate on disk if we can |
|
462 | // Update the dirstate on disk if we can | |
449 | let with_lock_result = |
|
463 | let with_lock_result = | |
450 | repo.try_with_wlock_no_wait(|| -> Result<(), CommandError> { |
|
464 | repo.try_with_wlock_no_wait(|| -> Result<(), CommandError> { | |
451 | if let Some(mtime_boundary) = filesystem_time_at_status_start { |
|
465 | if let Some(mtime_boundary) = filesystem_time_at_status_start { | |
452 | for hg_path in fixup { |
|
466 | for hg_path in fixup { | |
453 | use std::os::unix::fs::MetadataExt; |
|
467 | use std::os::unix::fs::MetadataExt; | |
454 | let fs_path = hg_path_to_path_buf(&hg_path) |
|
468 | let fs_path = hg_path_to_path_buf(&hg_path) | |
455 | .expect("HgPath conversion"); |
|
469 | .expect("HgPath conversion"); | |
456 | // Specifically do not reuse `fs_metadata` from |
|
470 | // Specifically do not reuse `fs_metadata` from | |
457 | // `unsure_is_clean` which was needed before reading |
|
471 | // `unsure_is_clean` which was needed before reading | |
458 | // contents. Here we access metadata again after reading |
|
472 | // contents. Here we access metadata again after reading | |
459 | // content, in case it changed in the meantime. |
|
473 | // content, in case it changed in the meantime. | |
460 | let metadata_res = repo |
|
474 | let metadata_res = repo | |
461 | .working_directory_vfs() |
|
475 | .working_directory_vfs() | |
462 | .symlink_metadata(&fs_path); |
|
476 | .symlink_metadata(&fs_path); | |
463 | let fs_metadata = match metadata_res { |
|
477 | let fs_metadata = match metadata_res { | |
464 | Ok(meta) => meta, |
|
478 | Ok(meta) => meta, | |
465 | Err(err) => match err { |
|
479 | Err(err) => match err { | |
466 | HgError::IoError { .. } => { |
|
480 | HgError::IoError { .. } => { | |
467 | // The file has probably been deleted. In any |
|
481 | // The file has probably been deleted. In any | |
468 | // case, it was in the dirstate before, so |
|
482 | // case, it was in the dirstate before, so | |
469 | // let's ignore the error. |
|
483 | // let's ignore the error. | |
470 | continue; |
|
484 | continue; | |
471 | } |
|
485 | } | |
472 | _ => return Err(err.into()), |
|
486 | _ => return Err(err.into()), | |
473 | }, |
|
487 | }, | |
474 | }; |
|
488 | }; | |
475 | if let Some(mtime) = |
|
489 | if let Some(mtime) = | |
476 | TruncatedTimestamp::for_reliable_mtime_of( |
|
490 | TruncatedTimestamp::for_reliable_mtime_of( | |
477 | &fs_metadata, |
|
491 | &fs_metadata, | |
478 | &mtime_boundary, |
|
492 | &mtime_boundary, | |
479 | ) |
|
493 | ) | |
480 | .when_reading_file(&fs_path)? |
|
494 | .when_reading_file(&fs_path)? | |
481 | { |
|
495 | { | |
482 | let mode = fs_metadata.mode(); |
|
496 | let mode = fs_metadata.mode(); | |
483 | let size = fs_metadata.len(); |
|
497 | let size = fs_metadata.len(); | |
484 | dmap.set_clean(&hg_path, mode, size as u32, mtime)?; |
|
498 | dmap.set_clean(&hg_path, mode, size as u32, mtime)?; | |
485 | dirstate_write_needed = true |
|
499 | dirstate_write_needed = true | |
486 | } |
|
500 | } | |
487 | } |
|
501 | } | |
488 | } |
|
502 | } | |
489 | drop(dmap); // Avoid "already mutably borrowed" RefCell panics |
|
503 | drop(dmap); // Avoid "already mutably borrowed" RefCell panics | |
490 | if dirstate_write_needed { |
|
504 | if dirstate_write_needed { | |
491 | repo.write_dirstate()? |
|
505 | repo.write_dirstate()? | |
492 | } |
|
506 | } | |
493 | Ok(()) |
|
507 | Ok(()) | |
494 | }); |
|
508 | }); | |
495 | match with_lock_result { |
|
509 | match with_lock_result { | |
496 | Ok(closure_result) => closure_result?, |
|
510 | Ok(closure_result) => closure_result?, | |
497 | Err(LockError::AlreadyHeld) => { |
|
511 | Err(LockError::AlreadyHeld) => { | |
498 | // Not updating the dirstate is not ideal but not critical: |
|
512 | // Not updating the dirstate is not ideal but not critical: | |
499 | // don’t keep our caller waiting until some other Mercurial |
|
513 | // don’t keep our caller waiting until some other Mercurial | |
500 | // process releases the lock. |
|
514 | // process releases the lock. | |
501 | log::info!("not writing dirstate from `status`: lock is held") |
|
515 | log::info!("not writing dirstate from `status`: lock is held") | |
502 | } |
|
516 | } | |
503 | Err(LockError::Other(HgError::IoError { error, .. })) |
|
517 | Err(LockError::Other(HgError::IoError { error, .. })) | |
504 | if error.kind() == io::ErrorKind::PermissionDenied => |
|
518 | if error.kind() == io::ErrorKind::PermissionDenied => | |
505 | { |
|
519 | { | |
506 | // `hg status` on a read-only repository is fine |
|
520 | // `hg status` on a read-only repository is fine | |
507 | } |
|
521 | } | |
508 | Err(LockError::Other(error)) => { |
|
522 | Err(LockError::Other(error)) => { | |
509 | // Report other I/O errors |
|
523 | // Report other I/O errors | |
510 | Err(error)? |
|
524 | Err(error)? | |
511 | } |
|
525 | } | |
512 | } |
|
526 | } | |
513 | Ok(()) |
|
527 | Ok(()) | |
514 | } |
|
528 | } | |
515 |
|
529 | |||
516 | fn ignore_files(repo: &Repo, config: &Config) -> Vec<PathBuf> { |
|
530 | fn ignore_files(repo: &Repo, config: &Config) -> Vec<PathBuf> { | |
517 | let mut ignore_files = Vec::new(); |
|
531 | let mut ignore_files = Vec::new(); | |
518 | let repo_ignore = repo.working_directory_vfs().join(".hgignore"); |
|
532 | let repo_ignore = repo.working_directory_vfs().join(".hgignore"); | |
519 | if repo_ignore.exists() { |
|
533 | if repo_ignore.exists() { | |
520 | ignore_files.push(repo_ignore) |
|
534 | ignore_files.push(repo_ignore) | |
521 | } |
|
535 | } | |
522 | for (key, value) in config.iter_section(b"ui") { |
|
536 | for (key, value) in config.iter_section(b"ui") { | |
523 | if key == b"ignore" || key.starts_with(b"ignore.") { |
|
537 | if key == b"ignore" || key.starts_with(b"ignore.") { | |
524 | let path = get_path_from_bytes(value); |
|
538 | let path = get_path_from_bytes(value); | |
525 | // TODO: expand "~/" and environment variable here, like Python |
|
539 | // TODO: expand "~/" and environment variable here, like Python | |
526 | // does with `os.path.expanduser` and `os.path.expandvars` |
|
540 | // does with `os.path.expanduser` and `os.path.expandvars` | |
527 |
|
541 | |||
528 | let joined = repo.working_directory_path().join(path); |
|
542 | let joined = repo.working_directory_path().join(path); | |
529 | ignore_files.push(joined); |
|
543 | ignore_files.push(joined); | |
530 | } |
|
544 | } | |
531 | } |
|
545 | } | |
532 | ignore_files |
|
546 | ignore_files | |
533 | } |
|
547 | } | |
534 |
|
548 | |||
535 | struct DisplayStatusPaths<'a> { |
|
549 | struct DisplayStatusPaths<'a> { | |
536 | ui: &'a Ui, |
|
550 | ui: &'a Ui, | |
537 | no_status: bool, |
|
551 | no_status: bool, | |
538 | relativize: Option<RelativizePaths>, |
|
552 | relativize: Option<RelativizePaths>, | |
539 | print0: bool, |
|
553 | print0: bool, | |
540 | } |
|
554 | } | |
541 |
|
555 | |||
542 | impl DisplayStatusPaths<'_> { |
|
556 | impl DisplayStatusPaths<'_> { | |
543 | // Probably more elegant to use a Deref or Borrow trait rather than |
|
557 | // Probably more elegant to use a Deref or Borrow trait rather than | |
544 | // harcode HgPathBuf, but probably not really useful at this point |
|
558 | // harcode HgPathBuf, but probably not really useful at this point | |
545 | fn display( |
|
559 | fn display( | |
546 | &self, |
|
560 | &self, | |
547 | status_prefix: &[u8], |
|
561 | status_prefix: &[u8], | |
548 | label: &'static str, |
|
562 | label: &'static str, | |
549 | mut paths: Vec<StatusPath<'_>>, |
|
563 | mut paths: Vec<StatusPath<'_>>, | |
550 | ) -> Result<(), CommandError> { |
|
564 | ) -> Result<(), CommandError> { | |
551 | paths.sort_unstable(); |
|
565 | paths.sort_unstable(); | |
552 | // TODO: get the stdout lock once for the whole loop |
|
566 | // TODO: get the stdout lock once for the whole loop | |
553 | // instead of in each write |
|
567 | // instead of in each write | |
554 | for StatusPath { path, copy_source } in paths { |
|
568 | for StatusPath { path, copy_source } in paths { | |
555 | let relative_path; |
|
569 | let relative_path; | |
556 | let relative_source; |
|
570 | let relative_source; | |
557 | let (path, copy_source) = if let Some(relativize) = |
|
571 | let (path, copy_source) = if let Some(relativize) = | |
558 | &self.relativize |
|
572 | &self.relativize | |
559 | { |
|
573 | { | |
560 | relative_path = relativize.relativize(&path); |
|
574 | relative_path = relativize.relativize(&path); | |
561 | relative_source = |
|
575 | relative_source = | |
562 | copy_source.as_ref().map(|s| relativize.relativize(s)); |
|
576 | copy_source.as_ref().map(|s| relativize.relativize(s)); | |
563 | (&*relative_path, relative_source.as_deref()) |
|
577 | (&*relative_path, relative_source.as_deref()) | |
564 | } else { |
|
578 | } else { | |
565 | (path.as_bytes(), copy_source.as_ref().map(|s| s.as_bytes())) |
|
579 | (path.as_bytes(), copy_source.as_ref().map(|s| s.as_bytes())) | |
566 | }; |
|
580 | }; | |
567 | // TODO: Add a way to use `write_bytes!` instead of `format_bytes!` |
|
581 | // TODO: Add a way to use `write_bytes!` instead of `format_bytes!` | |
568 | // in order to stream to stdout instead of allocating an |
|
582 | // in order to stream to stdout instead of allocating an | |
569 | // itermediate `Vec<u8>`. |
|
583 | // itermediate `Vec<u8>`. | |
570 | if !self.no_status { |
|
584 | if !self.no_status { | |
571 | self.ui.write_stdout_labelled(status_prefix, label)? |
|
585 | self.ui.write_stdout_labelled(status_prefix, label)? | |
572 | } |
|
586 | } | |
573 | let linebreak = if self.print0 { b"\x00" } else { b"\n" }; |
|
587 | let linebreak = if self.print0 { b"\x00" } else { b"\n" }; | |
574 | self.ui.write_stdout_labelled( |
|
588 | self.ui.write_stdout_labelled( | |
575 | &format_bytes!(b"{}{}", path, linebreak), |
|
589 | &format_bytes!(b"{}{}", path, linebreak), | |
576 | label, |
|
590 | label, | |
577 | )?; |
|
591 | )?; | |
578 | if let Some(source) = copy_source.filter(|_| !self.no_status) { |
|
592 | if let Some(source) = copy_source.filter(|_| !self.no_status) { | |
579 | let label = "status.copied"; |
|
593 | let label = "status.copied"; | |
580 | self.ui.write_stdout_labelled( |
|
594 | self.ui.write_stdout_labelled( | |
581 | &format_bytes!(b" {}{}", source, linebreak), |
|
595 | &format_bytes!(b" {}{}", source, linebreak), | |
582 | label, |
|
596 | label, | |
583 | )? |
|
597 | )? | |
584 | } |
|
598 | } | |
585 | } |
|
599 | } | |
586 | Ok(()) |
|
600 | Ok(()) | |
587 | } |
|
601 | } | |
588 | } |
|
602 | } | |
589 |
|
603 | |||
590 | /// Outcome of the additional check for an ambiguous tracked file |
|
604 | /// Outcome of the additional check for an ambiguous tracked file | |
591 | enum UnsureOutcome { |
|
605 | enum UnsureOutcome { | |
592 | /// The file is actually clean |
|
606 | /// The file is actually clean | |
593 | Clean, |
|
607 | Clean, | |
594 | /// The file has been modified |
|
608 | /// The file has been modified | |
595 | Modified, |
|
609 | Modified, | |
596 | /// The file was deleted on disk (or became another type of fs entry) |
|
610 | /// The file was deleted on disk (or became another type of fs entry) | |
597 | Deleted, |
|
611 | Deleted, | |
598 | } |
|
612 | } | |
599 |
|
613 | |||
600 | /// Check if a file is modified by comparing actual repo store and file system. |
|
614 | /// Check if a file is modified by comparing actual repo store and file system. | |
601 | /// |
|
615 | /// | |
602 | /// This meant to be used for those that the dirstate cannot resolve, due |
|
616 | /// This meant to be used for those that the dirstate cannot resolve, due | |
603 | /// to time resolution limits. |
|
617 | /// to time resolution limits. | |
604 | fn unsure_is_modified( |
|
618 | fn unsure_is_modified( | |
605 | working_directory_vfs: hg::vfs::Vfs, |
|
619 | working_directory_vfs: hg::vfs::Vfs, | |
606 | store_vfs: hg::vfs::Vfs, |
|
620 | store_vfs: hg::vfs::Vfs, | |
607 | check_exec: bool, |
|
621 | check_exec: bool, | |
608 | manifest: &Manifest, |
|
622 | manifest: &Manifest, | |
609 | hg_path: &HgPath, |
|
623 | hg_path: &HgPath, | |
610 | ) -> Result<UnsureOutcome, HgError> { |
|
624 | ) -> Result<UnsureOutcome, HgError> { | |
611 | let vfs = working_directory_vfs; |
|
625 | let vfs = working_directory_vfs; | |
612 | let fs_path = hg_path_to_path_buf(hg_path).expect("HgPath conversion"); |
|
626 | let fs_path = hg_path_to_path_buf(hg_path).expect("HgPath conversion"); | |
613 | let fs_metadata = vfs.symlink_metadata(&fs_path)?; |
|
627 | let fs_metadata = vfs.symlink_metadata(&fs_path)?; | |
614 | let is_symlink = fs_metadata.file_type().is_symlink(); |
|
628 | let is_symlink = fs_metadata.file_type().is_symlink(); | |
615 |
|
629 | |||
616 | let entry = manifest |
|
630 | let entry = manifest | |
617 | .find_by_path(hg_path)? |
|
631 | .find_by_path(hg_path)? | |
618 | .expect("ambgious file not in p1"); |
|
632 | .expect("ambgious file not in p1"); | |
619 |
|
633 | |||
620 | // TODO: Also account for `FALLBACK_SYMLINK` and `FALLBACK_EXEC` from the |
|
634 | // TODO: Also account for `FALLBACK_SYMLINK` and `FALLBACK_EXEC` from the | |
621 | // dirstate |
|
635 | // dirstate | |
622 | let fs_flags = if is_symlink { |
|
636 | let fs_flags = if is_symlink { | |
623 | Some(b'l') |
|
637 | Some(b'l') | |
624 | } else if check_exec && has_exec_bit(&fs_metadata) { |
|
638 | } else if check_exec && has_exec_bit(&fs_metadata) { | |
625 | Some(b'x') |
|
639 | Some(b'x') | |
626 | } else { |
|
640 | } else { | |
627 | None |
|
641 | None | |
628 | }; |
|
642 | }; | |
629 |
|
643 | |||
630 | let entry_flags = if check_exec { |
|
644 | let entry_flags = if check_exec { | |
631 | entry.flags |
|
645 | entry.flags | |
632 | } else if entry.flags == Some(b'x') { |
|
646 | } else if entry.flags == Some(b'x') { | |
633 | None |
|
647 | None | |
634 | } else { |
|
648 | } else { | |
635 | entry.flags |
|
649 | entry.flags | |
636 | }; |
|
650 | }; | |
637 |
|
651 | |||
638 | if entry_flags != fs_flags { |
|
652 | if entry_flags != fs_flags { | |
639 | return Ok(UnsureOutcome::Modified); |
|
653 | return Ok(UnsureOutcome::Modified); | |
640 | } |
|
654 | } | |
641 | let filelog = hg::filelog::Filelog::open_vfs(&store_vfs, hg_path)?; |
|
655 | let filelog = hg::filelog::Filelog::open_vfs(&store_vfs, hg_path)?; | |
642 | let fs_len = fs_metadata.len(); |
|
656 | let fs_len = fs_metadata.len(); | |
643 | let file_node = entry.node_id()?; |
|
657 | let file_node = entry.node_id()?; | |
644 | let filelog_entry = filelog.entry_for_node(file_node).map_err(|_| { |
|
658 | let filelog_entry = filelog.entry_for_node(file_node).map_err(|_| { | |
645 | HgError::corrupted(format!( |
|
659 | HgError::corrupted(format!( | |
646 | "filelog {:?} missing node {:?} from manifest", |
|
660 | "filelog {:?} missing node {:?} from manifest", | |
647 | hg_path, file_node |
|
661 | hg_path, file_node | |
648 | )) |
|
662 | )) | |
649 | })?; |
|
663 | })?; | |
650 | if filelog_entry.file_data_len_not_equal_to(fs_len) { |
|
664 | if filelog_entry.file_data_len_not_equal_to(fs_len) { | |
651 | // No need to read file contents: |
|
665 | // No need to read file contents: | |
652 | // it cannot be equal if it has a different length. |
|
666 | // it cannot be equal if it has a different length. | |
653 | return Ok(UnsureOutcome::Modified); |
|
667 | return Ok(UnsureOutcome::Modified); | |
654 | } |
|
668 | } | |
655 |
|
669 | |||
656 | let p1_filelog_data = filelog_entry.data()?; |
|
670 | let p1_filelog_data = filelog_entry.data()?; | |
657 | let p1_contents = p1_filelog_data.file_data()?; |
|
671 | let p1_contents = p1_filelog_data.file_data()?; | |
658 | if p1_contents.len() as u64 != fs_len { |
|
672 | if p1_contents.len() as u64 != fs_len { | |
659 | // No need to read file contents: |
|
673 | // No need to read file contents: | |
660 | // it cannot be equal if it has a different length. |
|
674 | // it cannot be equal if it has a different length. | |
661 | return Ok(UnsureOutcome::Modified); |
|
675 | return Ok(UnsureOutcome::Modified); | |
662 | } |
|
676 | } | |
663 |
|
677 | |||
664 | let fs_contents = if is_symlink { |
|
678 | let fs_contents = if is_symlink { | |
665 | get_bytes_from_os_string(vfs.read_link(fs_path)?.into_os_string()) |
|
679 | get_bytes_from_os_string(vfs.read_link(fs_path)?.into_os_string()) | |
666 | } else { |
|
680 | } else { | |
667 | vfs.read(fs_path)? |
|
681 | vfs.read(fs_path)? | |
668 | }; |
|
682 | }; | |
669 |
|
683 | |||
670 | Ok(if p1_contents != &*fs_contents { |
|
684 | Ok(if p1_contents != &*fs_contents { | |
671 | UnsureOutcome::Modified |
|
685 | UnsureOutcome::Modified | |
672 | } else { |
|
686 | } else { | |
673 | UnsureOutcome::Clean |
|
687 | UnsureOutcome::Clean | |
674 | }) |
|
688 | }) | |
675 | } |
|
689 | } |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now