rust/hg-core/src/errors.rs
author Manuel Jacob <me@manueljacob.de>
Thu, 15 Sep 2022 01:48:38 +0200
changeset 49494 c96ed4029fda
parent 49487 9f14126cfc4c
child 50239 491f3dd080eb
permissions -rw-r--r--
templates: add filter to reverse list The filter supports only lists because for lists, it’s straightforward to implement. Reversing text doesn’t seem very useful and is hard to implement. Reversing the bytes would break multi-bytes encodings. Reversing the code points would break characters consisting of multiple code points. Reversing graphemes is non-trivial without using a library not included in the standard library.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
46598
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
     1
use crate::config::ConfigValueParseError;
47407
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
     2
use crate::exit_codes;
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     3
use std::fmt;
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     4
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     5
/// Common error cases that can happen in many different APIs
46598
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
     6
#[derive(Debug, derive_more::From)]
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     7
pub enum HgError {
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     8
    IoError {
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     9
        error: std::io::Error,
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    10
        context: IoErrorContext,
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    11
    },
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    12
46485
f031fe1c6ede rhg: Abort based on config on share-safe mismatch
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
    13
    /// A file under `.hg/` normally only written by Mercurial is not in the
f031fe1c6ede rhg: Abort based on config on share-safe mismatch
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
    14
    /// expected format. This indicates a bug in Mercurial, filesystem
f031fe1c6ede rhg: Abort based on config on share-safe mismatch
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
    15
    /// corruption, or hardware failure.
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    16
    ///
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    17
    /// The given string is a short explanation for users, not intended to be
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    18
    /// machine-readable.
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    19
    CorruptedRepository(String),
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    20
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    21
    /// The respository or requested operation involves a feature not
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    22
    /// supported by the Rust implementation. Falling back to the Python
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    23
    /// implementation may or may not work.
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    24
    ///
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    25
    /// The given string is a short explanation for users, not intended to be
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    26
    /// machine-readable.
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    27
    UnsupportedFeature(String),
46485
f031fe1c6ede rhg: Abort based on config on share-safe mismatch
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
    28
f031fe1c6ede rhg: Abort based on config on share-safe mismatch
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
    29
    /// Operation cannot proceed for some other reason.
f031fe1c6ede rhg: Abort based on config on share-safe mismatch
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
    30
    ///
47407
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
    31
    /// The message is a short explanation for users, not intended to be
46485
f031fe1c6ede rhg: Abort based on config on share-safe mismatch
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
    32
    /// machine-readable.
47407
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
    33
    Abort {
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
    34
        message: String,
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
    35
        detailed_exit_code: exit_codes::ExitCode,
49487
9f14126cfc4c rust: add support for hints in error messages
Raphaël Gomès <rgomes@octobus.net>
parents: 49174
diff changeset
    36
        hint: Option<String>,
47407
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
    37
    },
46598
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    38
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    39
    /// A configuration value is not in the expected syntax.
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    40
    ///
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    41
    /// These errors can happen in many places in the code because values are
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    42
    /// parsed lazily as the file-level parser does not know the expected type
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    43
    /// and syntax of each value.
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    44
    #[from]
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    45
    ConfigValueParseError(ConfigValueParseError),
49174
3f86ee422095 censor: make rhg fall back to python when encountering a censored node
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48418
diff changeset
    46
3f86ee422095 censor: make rhg fall back to python when encountering a censored node
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48418
diff changeset
    47
    /// Censored revision data.
3f86ee422095 censor: make rhg fall back to python when encountering a censored node
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48418
diff changeset
    48
    CensoredNodeError,
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    49
}
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    50
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    51
/// Details about where an I/O error happened
46599
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
    52
#[derive(Debug)]
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    53
pub enum IoErrorContext {
47780
cf5f8da2244c rhg: Propagate permission errors when finding a repository
Simon Sapin <simon.sapin@octobus.net>
parents: 47407
diff changeset
    54
    /// `std::fs::metadata`
cf5f8da2244c rhg: Propagate permission errors when finding a repository
Simon Sapin <simon.sapin@octobus.net>
parents: 47407
diff changeset
    55
    ReadingMetadata(std::path::PathBuf),
46599
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
    56
    ReadingFile(std::path::PathBuf),
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
    57
    WritingFile(std::path::PathBuf),
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
    58
    RemovingFile(std::path::PathBuf),
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
    59
    RenamingFile {
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
    60
        from: std::path::PathBuf,
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
    61
        to: std::path::PathBuf,
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
    62
    },
46740
97ac588b6d9e rhg: Don’t make repository path absolute too early
Simon Sapin <simon.sapin@octobus.net>
parents: 46735
diff changeset
    63
    /// `std::fs::canonicalize`
97ac588b6d9e rhg: Don’t make repository path absolute too early
Simon Sapin <simon.sapin@octobus.net>
parents: 46735
diff changeset
    64
    CanonicalizingPath(std::path::PathBuf),
46483
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46462
diff changeset
    65
    /// `std::env::current_dir`
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    66
    CurrentDir,
46483
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46462
diff changeset
    67
    /// `std::env::current_exe`
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46462
diff changeset
    68
    CurrentExe,
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    69
}
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    70
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    71
impl HgError {
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    72
    pub fn corrupted(explanation: impl Into<String>) -> Self {
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46438
diff changeset
    73
        // TODO: capture a backtrace here and keep it in the error value
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46438
diff changeset
    74
        // to aid debugging?
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46438
diff changeset
    75
        // https://doc.rust-lang.org/std/backtrace/struct.Backtrace.html
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    76
        HgError::CorruptedRepository(explanation.into())
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    77
    }
46462
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46443
diff changeset
    78
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46443
diff changeset
    79
    pub fn unsupported(explanation: impl Into<String>) -> Self {
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46443
diff changeset
    80
        HgError::UnsupportedFeature(explanation.into())
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46443
diff changeset
    81
    }
47407
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
    82
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
    83
    pub fn abort(
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
    84
        explanation: impl Into<String>,
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
    85
        exit_code: exit_codes::ExitCode,
49487
9f14126cfc4c rust: add support for hints in error messages
Raphaël Gomès <rgomes@octobus.net>
parents: 49174
diff changeset
    86
        hint: Option<String>,
47407
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
    87
    ) -> Self {
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
    88
        HgError::Abort {
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
    89
            message: explanation.into(),
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
    90
            detailed_exit_code: exit_code,
49487
9f14126cfc4c rust: add support for hints in error messages
Raphaël Gomès <rgomes@octobus.net>
parents: 49174
diff changeset
    91
            hint,
47407
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
    92
        }
46485
f031fe1c6ede rhg: Abort based on config on share-safe mismatch
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
    93
    }
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    94
}
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    95
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    96
// TODO: use `DisplayBytes` instead to show non-Unicode filenames losslessly?
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    97
impl fmt::Display for HgError {
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    98
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    99
        match self {
47407
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
   100
            HgError::Abort { message, .. } => write!(f, "{}", message),
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   101
            HgError::IoError { error, context } => {
46731
3d692e724d06 rhg: Align config file parse error formatting with Python
Simon Sapin <simon.sapin@octobus.net>
parents: 46599
diff changeset
   102
                write!(f, "abort: {}: {}", context, error)
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   103
            }
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   104
            HgError::CorruptedRepository(explanation) => {
46735
12d59eec7f1d rhg: Align with Python on some more error messages
Simon Sapin <simon.sapin@octobus.net>
parents: 46731
diff changeset
   105
                write!(f, "abort: {}", explanation)
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   106
            }
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   107
            HgError::UnsupportedFeature(explanation) => {
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   108
                write!(f, "unsupported feature: {}", explanation)
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   109
            }
49174
3f86ee422095 censor: make rhg fall back to python when encountering a censored node
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48418
diff changeset
   110
            HgError::CensoredNodeError => {
3f86ee422095 censor: make rhg fall back to python when encountering a censored node
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48418
diff changeset
   111
                write!(f, "encountered a censored node")
3f86ee422095 censor: make rhg fall back to python when encountering a censored node
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48418
diff changeset
   112
            }
46797
bcdcb4423ae3 rhg: Add more conversions between error types
Simon Sapin <simon.sapin@octobus.net>
parents: 46740
diff changeset
   113
            HgError::ConfigValueParseError(error) => error.fmt(f),
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   114
        }
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   115
    }
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   116
}
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   117
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   118
// TODO: use `DisplayBytes` instead to show non-Unicode filenames losslessly?
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   119
impl fmt::Display for IoErrorContext {
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   120
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   121
        match self {
47780
cf5f8da2244c rhg: Propagate permission errors when finding a repository
Simon Sapin <simon.sapin@octobus.net>
parents: 47407
diff changeset
   122
            IoErrorContext::ReadingMetadata(path) => {
cf5f8da2244c rhg: Propagate permission errors when finding a repository
Simon Sapin <simon.sapin@octobus.net>
parents: 47407
diff changeset
   123
                write!(f, "when reading metadata of {}", path.display())
cf5f8da2244c rhg: Propagate permission errors when finding a repository
Simon Sapin <simon.sapin@octobus.net>
parents: 47407
diff changeset
   124
            }
46599
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   125
            IoErrorContext::ReadingFile(path) => {
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   126
                write!(f, "when reading {}", path.display())
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   127
            }
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   128
            IoErrorContext::WritingFile(path) => {
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   129
                write!(f, "when writing {}", path.display())
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   130
            }
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   131
            IoErrorContext::RemovingFile(path) => {
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   132
                write!(f, "when removing {}", path.display())
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   133
            }
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   134
            IoErrorContext::RenamingFile { from, to } => write!(
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   135
                f,
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   136
                "when renaming {} to {}",
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   137
                from.display(),
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   138
                to.display()
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   139
            ),
46740
97ac588b6d9e rhg: Don’t make repository path absolute too early
Simon Sapin <simon.sapin@octobus.net>
parents: 46735
diff changeset
   140
            IoErrorContext::CanonicalizingPath(path) => {
97ac588b6d9e rhg: Don’t make repository path absolute too early
Simon Sapin <simon.sapin@octobus.net>
parents: 46735
diff changeset
   141
                write!(f, "when canonicalizing {}", path.display())
97ac588b6d9e rhg: Don’t make repository path absolute too early
Simon Sapin <simon.sapin@octobus.net>
parents: 46735
diff changeset
   142
            }
46731
3d692e724d06 rhg: Align config file parse error formatting with Python
Simon Sapin <simon.sapin@octobus.net>
parents: 46599
diff changeset
   143
            IoErrorContext::CurrentDir => {
3d692e724d06 rhg: Align config file parse error formatting with Python
Simon Sapin <simon.sapin@octobus.net>
parents: 46599
diff changeset
   144
                write!(f, "error getting current working directory")
3d692e724d06 rhg: Align config file parse error formatting with Python
Simon Sapin <simon.sapin@octobus.net>
parents: 46599
diff changeset
   145
            }
3d692e724d06 rhg: Align config file parse error formatting with Python
Simon Sapin <simon.sapin@octobus.net>
parents: 46599
diff changeset
   146
            IoErrorContext::CurrentExe => {
3d692e724d06 rhg: Align config file parse error formatting with Python
Simon Sapin <simon.sapin@octobus.net>
parents: 46599
diff changeset
   147
                write!(f, "error getting current executable")
3d692e724d06 rhg: Align config file parse error formatting with Python
Simon Sapin <simon.sapin@octobus.net>
parents: 46599
diff changeset
   148
            }
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   149
        }
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   150
    }
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   151
}
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   152
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   153
pub trait IoResultExt<T> {
46599
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   154
    /// Annotate a possible I/O error as related to a reading a file at the
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   155
    /// given path.
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   156
    ///
46599
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   157
    /// This allows printing something like “File not found when reading
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   158
    /// example.txt” instead of just “File not found”.
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   159
    ///
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   160
    /// Converts a `Result` with `std::io::Error` into one with `HgError`.
46599
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   161
    fn when_reading_file(self, path: &std::path::Path) -> Result<T, HgError>;
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   162
48418
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 47780
diff changeset
   163
    fn when_writing_file(self, path: &std::path::Path) -> Result<T, HgError>;
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 47780
diff changeset
   164
46599
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   165
    fn with_context(
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   166
        self,
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   167
        context: impl FnOnce() -> IoErrorContext,
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   168
    ) -> Result<T, HgError>;
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   169
}
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   170
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   171
impl<T> IoResultExt<T> for std::io::Result<T> {
46599
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   172
    fn when_reading_file(self, path: &std::path::Path) -> Result<T, HgError> {
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   173
        self.with_context(|| IoErrorContext::ReadingFile(path.to_owned()))
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   174
    }
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   175
48418
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 47780
diff changeset
   176
    fn when_writing_file(self, path: &std::path::Path) -> Result<T, HgError> {
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 47780
diff changeset
   177
        self.with_context(|| IoErrorContext::WritingFile(path.to_owned()))
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 47780
diff changeset
   178
    }
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 47780
diff changeset
   179
46599
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   180
    fn with_context(
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   181
        self,
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   182
        context: impl FnOnce() -> IoErrorContext,
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   183
    ) -> Result<T, HgError> {
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   184
        self.map_err(|error| HgError::IoError {
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   185
            error,
46599
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   186
            context: context(),
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   187
        })
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   188
    }
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   189
}
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   190
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   191
pub trait HgResultExt<T> {
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   192
    /// Handle missing files separately from other I/O error cases.
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   193
    ///
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   194
    /// Wraps the `Ok` type in an `Option`:
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   195
    ///
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   196
    /// * `Ok(x)` becomes `Ok(Some(x))`
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   197
    /// * An I/O "not found" error becomes `Ok(None)`
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   198
    /// * Other errors are unchanged
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   199
    fn io_not_found_as_none(self) -> Result<Option<T>, HgError>;
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   200
}
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   201
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   202
impl<T> HgResultExt<T> for Result<T, HgError> {
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   203
    fn io_not_found_as_none(self) -> Result<Option<T>, HgError> {
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   204
        match self {
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   205
            Ok(x) => Ok(Some(x)),
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   206
            Err(HgError::IoError { error, .. })
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   207
                if error.kind() == std::io::ErrorKind::NotFound =>
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   208
            {
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   209
                Ok(None)
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   210
            }
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   211
            Err(other_error) => Err(other_error),
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   212
        }
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   213
    }
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   214
}