comparison rust/hg-core/src/errors.rs @ 46637:bc08c2331f99

rust: Add a `ConfigValueParseError` variant to common errors Configuration files are parsed into sections of key/value pairs when they are read, but at that point values are still arbitrary bytes. Only when a value is accessed by various parts of the code do we know its expected type and syntax, so values are parsed at that point. Let?s make a new error type for this latter kind of parsing error, and add a variant to the common `HgError` so that most code can propagate it without much boilerplate. Differential Revision: https://phab.mercurial-scm.org/D10009
author Simon Sapin <simon.sapin@octobus.net>
date Tue, 16 Feb 2021 15:22:20 +0100
parents f031fe1c6ede
children 1f55cd5b292f
comparison
equal deleted inserted replaced
46636:305d74c262de 46637:bc08c2331f99
1 use crate::config::ConfigValueParseError;
1 use std::fmt; 2 use std::fmt;
2 3
3 /// Common error cases that can happen in many different APIs 4 /// Common error cases that can happen in many different APIs
4 #[derive(Debug)] 5 #[derive(Debug, derive_more::From)]
5 pub enum HgError { 6 pub enum HgError {
6 IoError { 7 IoError {
7 error: std::io::Error, 8 error: std::io::Error,
8 context: IoErrorContext, 9 context: IoErrorContext,
9 }, 10 },
27 /// Operation cannot proceed for some other reason. 28 /// Operation cannot proceed for some other reason.
28 /// 29 ///
29 /// The given string is a short explanation for users, not intended to be 30 /// The given string is a short explanation for users, not intended to be
30 /// machine-readable. 31 /// machine-readable.
31 Abort(String), 32 Abort(String),
33
34 /// A configuration value is not in the expected syntax.
35 ///
36 /// These errors can happen in many places in the code because values are
37 /// parsed lazily as the file-level parser does not know the expected type
38 /// and syntax of each value.
39 #[from]
40 ConfigValueParseError(ConfigValueParseError),
32 } 41 }
33 42
34 /// Details about where an I/O error happened 43 /// Details about where an I/O error happened
35 #[derive(Debug, derive_more::From)] 44 #[derive(Debug, derive_more::From)]
36 pub enum IoErrorContext { 45 pub enum IoErrorContext {
61 70
62 // TODO: use `DisplayBytes` instead to show non-Unicode filenames losslessly? 71 // TODO: use `DisplayBytes` instead to show non-Unicode filenames losslessly?
63 impl fmt::Display for HgError { 72 impl fmt::Display for HgError {
64 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 73 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
65 match self { 74 match self {
75 HgError::Abort(explanation) => write!(f, "{}", explanation),
66 HgError::IoError { error, context } => { 76 HgError::IoError { error, context } => {
67 write!(f, "{}: {}", error, context) 77 write!(f, "{}: {}", error, context)
68 } 78 }
69 HgError::CorruptedRepository(explanation) => { 79 HgError::CorruptedRepository(explanation) => {
70 write!(f, "corrupted repository: {}", explanation) 80 write!(f, "corrupted repository: {}", explanation)
71 } 81 }
72 HgError::UnsupportedFeature(explanation) => { 82 HgError::UnsupportedFeature(explanation) => {
73 write!(f, "unsupported feature: {}", explanation) 83 write!(f, "unsupported feature: {}", explanation)
74 } 84 }
75 HgError::Abort(explanation) => explanation.fmt(f), 85 HgError::ConfigValueParseError(ConfigValueParseError {
86 origin: _,
87 line: _,
88 section,
89 item,
90 value,
91 expected_type,
92 }) => {
93 // TODO: add origin and line number information, here and in
94 // corresponding python code
95 write!(
96 f,
97 "config error: {}.{} is not a {} ('{}')",
98 String::from_utf8_lossy(section),
99 String::from_utf8_lossy(item),
100 expected_type,
101 String::from_utf8_lossy(value)
102 )
103 }
76 } 104 }
77 } 105 }
78 } 106 }
79 107
80 // TODO: use `DisplayBytes` instead to show non-Unicode filenames losslessly? 108 // TODO: use `DisplayBytes` instead to show non-Unicode filenames losslessly?