Mercurial > public > mercurial-scm > hg-stable
comparison rust/hg-core/src/errors.rs @ 46638:1f55cd5b292f
rust: Add a log file rotation utility
This is ported to Rust from `mercurial/loggingutil.py`.
The "builder" pattern is used to make it visible at call sites what the two
numeric parameters mean. In Python they might simply by keyword arguments.
Differential Revision: https://phab.mercurial-scm.org/D10010
author | Simon Sapin <simon.sapin@octobus.net> |
---|---|
date | Thu, 11 Feb 2021 15:51:11 +0100 |
parents | bc08c2331f99 |
children | 3d692e724d06 |
comparison
equal
deleted
inserted
replaced
46637:bc08c2331f99 | 46638:1f55cd5b292f |
---|---|
39 #[from] | 39 #[from] |
40 ConfigValueParseError(ConfigValueParseError), | 40 ConfigValueParseError(ConfigValueParseError), |
41 } | 41 } |
42 | 42 |
43 /// Details about where an I/O error happened | 43 /// Details about where an I/O error happened |
44 #[derive(Debug, derive_more::From)] | 44 #[derive(Debug)] |
45 pub enum IoErrorContext { | 45 pub enum IoErrorContext { |
46 /// A filesystem operation for the given file | 46 ReadingFile(std::path::PathBuf), |
47 #[from] | 47 WritingFile(std::path::PathBuf), |
48 File(std::path::PathBuf), | 48 RemovingFile(std::path::PathBuf), |
49 RenamingFile { | |
50 from: std::path::PathBuf, | |
51 to: std::path::PathBuf, | |
52 }, | |
49 /// `std::env::current_dir` | 53 /// `std::env::current_dir` |
50 CurrentDir, | 54 CurrentDir, |
51 /// `std::env::current_exe` | 55 /// `std::env::current_exe` |
52 CurrentExe, | 56 CurrentExe, |
53 } | 57 } |
107 | 111 |
108 // TODO: use `DisplayBytes` instead to show non-Unicode filenames losslessly? | 112 // TODO: use `DisplayBytes` instead to show non-Unicode filenames losslessly? |
109 impl fmt::Display for IoErrorContext { | 113 impl fmt::Display for IoErrorContext { |
110 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | 114 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
111 match self { | 115 match self { |
112 IoErrorContext::File(path) => path.display().fmt(f), | 116 IoErrorContext::ReadingFile(path) => { |
113 IoErrorContext::CurrentDir => f.write_str("current directory"), | 117 write!(f, "when reading {}", path.display()) |
114 IoErrorContext::CurrentExe => f.write_str("current executable"), | 118 } |
119 IoErrorContext::WritingFile(path) => { | |
120 write!(f, "when writing {}", path.display()) | |
121 } | |
122 IoErrorContext::RemovingFile(path) => { | |
123 write!(f, "when removing {}", path.display()) | |
124 } | |
125 IoErrorContext::RenamingFile { from, to } => write!( | |
126 f, | |
127 "when renaming {} to {}", | |
128 from.display(), | |
129 to.display() | |
130 ), | |
131 IoErrorContext::CurrentDir => write!(f, "current directory"), | |
132 IoErrorContext::CurrentExe => write!(f, "current executable"), | |
115 } | 133 } |
116 } | 134 } |
117 } | 135 } |
118 | 136 |
119 pub trait IoResultExt<T> { | 137 pub trait IoResultExt<T> { |
120 /// Annotate a possible I/O error as related to a file at the given path. | 138 /// Annotate a possible I/O error as related to a reading a file at the |
139 /// given path. | |
121 /// | 140 /// |
122 /// This allows printing something like “File not found: example.txt” | 141 /// This allows printing something like “File not found when reading |
123 /// instead of just “File not found”. | 142 /// example.txt” instead of just “File not found”. |
124 /// | 143 /// |
125 /// Converts a `Result` with `std::io::Error` into one with `HgError`. | 144 /// Converts a `Result` with `std::io::Error` into one with `HgError`. |
126 fn for_file(self, path: &std::path::Path) -> Result<T, HgError>; | 145 fn when_reading_file(self, path: &std::path::Path) -> Result<T, HgError>; |
146 | |
147 fn with_context( | |
148 self, | |
149 context: impl FnOnce() -> IoErrorContext, | |
150 ) -> Result<T, HgError>; | |
127 } | 151 } |
128 | 152 |
129 impl<T> IoResultExt<T> for std::io::Result<T> { | 153 impl<T> IoResultExt<T> for std::io::Result<T> { |
130 fn for_file(self, path: &std::path::Path) -> Result<T, HgError> { | 154 fn when_reading_file(self, path: &std::path::Path) -> Result<T, HgError> { |
155 self.with_context(|| IoErrorContext::ReadingFile(path.to_owned())) | |
156 } | |
157 | |
158 fn with_context( | |
159 self, | |
160 context: impl FnOnce() -> IoErrorContext, | |
161 ) -> Result<T, HgError> { | |
131 self.map_err(|error| HgError::IoError { | 162 self.map_err(|error| HgError::IoError { |
132 error, | 163 error, |
133 context: IoErrorContext::File(path.to_owned()), | 164 context: context(), |
134 }) | 165 }) |
135 } | 166 } |
136 } | 167 } |
137 | 168 |
138 pub trait HgResultExt<T> { | 169 pub trait HgResultExt<T> { |