comparison rust/hg-core/src/config/mod.rs @ 50803:8ff187fbbfea

rust-config: add config getters that don't fall back to defaults This is useful in cases where we access config items that are more... lenient with their types than a fresh new system would allow. For now there is only a single use of this, but we might get more later.
author Rapha?l Gom?s <rgomes@octobus.net>
date Mon, 13 Feb 2023 18:11:48 +0100
parents f8412da86d05
children 7f8f6fe13fa9
comparison
equal deleted inserted replaced
50802:f8412da86d05 50803:8ff187fbbfea
358 358
359 pub fn apply_plain(&mut self, plain: PlainInfo) { 359 pub fn apply_plain(&mut self, plain: PlainInfo) {
360 self.plain = plain; 360 self.plain = plain;
361 } 361 }
362 362
363 /// Returns the default value for the given config item, if any. 363 /// Returns the default value for the given config item, if any.
364 pub fn get_default( 364 pub fn get_default(
365 &self, 365 &self,
366 section: &[u8], 366 section: &[u8],
367 item: &[u8], 367 item: &[u8],
368 ) -> Result<Option<&DefaultConfigItem>, HgError> { 368 ) -> Result<Option<&DefaultConfigItem>, HgError> {
369 let default_config = DEFAULT_CONFIG.as_ref().map_err(|e| { 369 let default_config = DEFAULT_CONFIG.as_ref().map_err(|e| {
370 HgError::abort( 370 HgError::abort(
371 e.to_string(), 371 e.to_string(),
372 crate::exit_codes::ABORT, 372 crate::exit_codes::ABORT,
373 Some("`mercurial/configitems.toml` is not valid".into()), 373 Some("`mercurial/configitems.toml` is not valid".into()),
374 ) 374 )
375 })?; 375 })?;
376 Ok(default_config.get(section, item)) 376 Ok(default_config.get(section, item))
377 } 377 }
378 378
379 fn get_parse<'config, T: 'config>( 379 fn get_parse<'config, T: 'config>(
380 &'config self, 380 &'config self,
381 section: &[u8], 381 section: &[u8],
382 item: &[u8], 382 item: &[u8],
383 expected_type: &'static str, 383 expected_type: &'static str,
384 parse: impl Fn(&'config [u8]) -> Option<T>, 384 parse: impl Fn(&'config [u8]) -> Option<T>,
385 fallback_to_default: bool,
385 ) -> Result<Option<T>, HgError> 386 ) -> Result<Option<T>, HgError>
386 where 387 where
387 Option<T>: TryFrom<&'config DefaultConfigItem, Error = HgError>, 388 Option<T>: TryFrom<&'config DefaultConfigItem, Error = HgError>,
388 { 389 {
389 match self.get_inner(section, item) { 390 match self.get_inner(section, item) {
397 item: item.to_owned(), 398 item: item.to_owned(),
398 expected_type, 399 expected_type,
399 }) 400 })
400 .into()), 401 .into()),
401 }, 402 },
402 None => match self.get_default(section, item)? { 403 None => {
403 Some(default) => Ok(default.try_into()?), 404 if !fallback_to_default {
404 None => { 405 return Ok(None);
405 Ok(None)
406 } 406 }
407 }, 407 match self.get_default(section, item)? {
408 Some(default) => Ok(default.try_into()?),
409 None => Ok(None),
410 }
411 }
408 } 412 }
409 } 413 }
410 414
411 /// Returns an `Err` if the first value found is not a valid UTF-8 string. 415 /// Returns an `Err` if the first value found is not a valid UTF-8 string.
412 /// Otherwise, returns an `Ok(value)` if found, or `None`. 416 /// Otherwise, returns an `Ok(value)` if found, or `None`.
413 pub fn get_str( 417 pub fn get_str(
414 &self, 418 &self,
415 section: &[u8], 419 section: &[u8],
416 item: &[u8], 420 item: &[u8],
417 ) -> Result<Option<&str>, HgError> { 421 ) -> Result<Option<&str>, HgError> {
418 self.get_parse(section, item, "ASCII or UTF-8 string", |value| { 422 self.get_parse(
419 str::from_utf8(value).ok() 423 section,
420 }) 424 item,
425 "ASCII or UTF-8 string",
426 |value| str::from_utf8(value).ok(),
427 true,
428 )
429 }
430
431 /// Same as `get_str`, but doesn't fall back to the default `configitem`
432 /// if not defined in the user config.
433 pub fn get_str_no_default(
434 &self,
435 section: &[u8],
436 item: &[u8],
437 ) -> Result<Option<&str>, HgError> {
438 self.get_parse(
439 section,
440 item,
441 "ASCII or UTF-8 string",
442 |value| str::from_utf8(value).ok(),
443 false,
444 )
421 } 445 }
422 446
423 /// Returns an `Err` if the first value found is not a valid unsigned 447 /// Returns an `Err` if the first value found is not a valid unsigned
424 /// integer. Otherwise, returns an `Ok(value)` if found, or `None`. 448 /// integer. Otherwise, returns an `Ok(value)` if found, or `None`.
425 pub fn get_u32( 449 pub fn get_u32(
426 &self, 450 &self,
427 section: &[u8], 451 section: &[u8],
428 item: &[u8], 452 item: &[u8],
429 ) -> Result<Option<u32>, HgError> { 453 ) -> Result<Option<u32>, HgError> {
430 self.get_parse(section, item, "valid integer", |value| { 454 self.get_parse(
431 str::from_utf8(value).ok()?.parse().ok() 455 section,
432 }) 456 item,
457 "valid integer",
458 |value| str::from_utf8(value).ok()?.parse().ok(),
459 true,
460 )
433 } 461 }
434 462
435 /// Returns an `Err` if the first value found is not a valid file size 463 /// Returns an `Err` if the first value found is not a valid file size
436 /// value such as `30` (default unit is bytes), `7 MB`, or `42.5 kb`. 464 /// value such as `30` (default unit is bytes), `7 MB`, or `42.5 kb`.
437 /// Otherwise, returns an `Ok(value_in_bytes)` if found, or `None`. 465 /// Otherwise, returns an `Ok(value_in_bytes)` if found, or `None`.
438 pub fn get_byte_size( 466 pub fn get_byte_size(
439 &self, 467 &self,
440 section: &[u8], 468 section: &[u8],
441 item: &[u8], 469 item: &[u8],
442 ) -> Result<Option<u64>, HgError> { 470 ) -> Result<Option<u64>, HgError> {
443 self.get_parse(section, item, "byte quantity", values::parse_byte_size) 471 self.get_parse(
472 section,
473 item,
474 "byte quantity",
475 values::parse_byte_size,
476 true,
477 )
444 } 478 }
445 479
446 /// Returns an `Err` if the first value found is not a valid boolean. 480 /// Returns an `Err` if the first value found is not a valid boolean.
447 /// Otherwise, returns an `Ok(option)`, where `option` is the boolean if 481 /// Otherwise, returns an `Ok(option)`, where `option` is the boolean if
448 /// found, or `None`. 482 /// found, or `None`.
449 pub fn get_option( 483 pub fn get_option(
450 &self, 484 &self,
451 section: &[u8], 485 section: &[u8],
452 item: &[u8], 486 item: &[u8],
453 ) -> Result<Option<bool>, HgError> { 487 ) -> Result<Option<bool>, HgError> {
454 self.get_parse(section, item, "boolean", values::parse_bool) 488 self.get_parse(section, item, "boolean", values::parse_bool, true)
489 }
490
491 /// Same as `get_option`, but doesn't fall back to the default `configitem`
492 /// if not defined in the user config.
493 pub fn get_option_no_default(
494 &self,
495 section: &[u8],
496 item: &[u8],
497 ) -> Result<Option<bool>, HgError> {
498 self.get_parse(section, item, "boolean", values::parse_bool, false)
455 } 499 }
456 500
457 /// Returns the corresponding boolean in the config. Returns `Ok(false)` 501 /// Returns the corresponding boolean in the config. Returns `Ok(false)`
458 /// if the value is not found, an `Err` if it's not a valid boolean. 502 /// if the value is not found, an `Err` if it's not a valid boolean.
459 pub fn get_bool( 503 pub fn get_bool(
460 &self, 504 &self,
461 section: &[u8], 505 section: &[u8],
462 item: &[u8], 506 item: &[u8],
463 ) -> Result<bool, HgError> { 507 ) -> Result<bool, HgError> {
464 Ok(self.get_option(section, item)?.unwrap_or(false)) 508 Ok(self.get_option(section, item)?.unwrap_or(false))
509 }
510
511 /// Same as `get_bool`, but doesn't fall back to the default `configitem`
512 /// if not defined in the user config.
513 pub fn get_bool_no_default(
514 &self,
515 section: &[u8],
516 item: &[u8],
517 ) -> Result<bool, HgError> {
518 Ok(self.get_option_no_default(section, item)?.unwrap_or(false))
465 } 519 }
466 520
467 /// Returns `true` if the extension is enabled, `false` otherwise 521 /// Returns `true` if the extension is enabled, `false` otherwise
468 pub fn is_extension_enabled(&self, extension: &[u8]) -> bool { 522 pub fn is_extension_enabled(&self, extension: &[u8]) -> bool {
469 let value = self.get(b"extensions", extension); 523 let value = self.get(b"extensions", extension);