rust/hg-core/src/errors.rs
author Pierre-Yves David <pierre-yves.david@octobus.net>
Fri, 14 Jan 2022 17:57:49 +0100
changeset 48596 739f2ca3aa3f
parent 48418 abeae090ce67
child 49174 3f86ee422095
permissions -rw-r--r--
stream-clone: factor computation of new clone requirement out This gather code duplicated in multiple place and will make it easier to modify it safely in the future. Differential Revision: https://phab.mercurial-scm.org/D12027
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,
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
    36
    },
46598
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    37
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    38
    /// 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
    39
    ///
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    40
    /// 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
    41
    /// 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
    42
    /// and syntax of each value.
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    43
    #[from]
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    44
    ConfigValueParseError(ConfigValueParseError),
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    45
}
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    46
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    47
/// 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
    48
#[derive(Debug)]
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    49
pub enum IoErrorContext {
47780
cf5f8da2244c rhg: Propagate permission errors when finding a repository
Simon Sapin <simon.sapin@octobus.net>
parents: 47407
diff changeset
    50
    /// `std::fs::metadata`
cf5f8da2244c rhg: Propagate permission errors when finding a repository
Simon Sapin <simon.sapin@octobus.net>
parents: 47407
diff changeset
    51
    ReadingMetadata(std::path::PathBuf),
46599
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
    52
    ReadingFile(std::path::PathBuf),
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
    53
    WritingFile(std::path::PathBuf),
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
    54
    RemovingFile(std::path::PathBuf),
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
    55
    RenamingFile {
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
    56
        from: std::path::PathBuf,
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
    57
        to: std::path::PathBuf,
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
    58
    },
46740
97ac588b6d9e rhg: Don’t make repository path absolute too early
Simon Sapin <simon.sapin@octobus.net>
parents: 46735
diff changeset
    59
    /// `std::fs::canonicalize`
97ac588b6d9e rhg: Don’t make repository path absolute too early
Simon Sapin <simon.sapin@octobus.net>
parents: 46735
diff changeset
    60
    CanonicalizingPath(std::path::PathBuf),
46483
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46462
diff changeset
    61
    /// `std::env::current_dir`
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    62
    CurrentDir,
46483
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46462
diff changeset
    63
    /// `std::env::current_exe`
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46462
diff changeset
    64
    CurrentExe,
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    65
}
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    66
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    67
impl HgError {
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    68
    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
    69
        // 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
    70
        // to aid debugging?
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46438
diff changeset
    71
        // 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
    72
        HgError::CorruptedRepository(explanation.into())
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    73
    }
46462
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46443
diff changeset
    74
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46443
diff changeset
    75
    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
    76
        HgError::UnsupportedFeature(explanation.into())
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46443
diff changeset
    77
    }
47407
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
    78
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
    79
    pub fn abort(
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
    80
        explanation: impl Into<String>,
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
    81
        exit_code: exit_codes::ExitCode,
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
    82
    ) -> Self {
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
    83
        HgError::Abort {
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
    84
            message: explanation.into(),
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
    85
            detailed_exit_code: exit_code,
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
    86
        }
46485
f031fe1c6ede rhg: Abort based on config on share-safe mismatch
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
    87
    }
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    88
}
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    89
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    90
// 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
    91
impl fmt::Display for HgError {
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    92
    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
    93
        match self {
47407
6e49769b7f97 rhg: add exit code to HgError::Abort()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46797
diff changeset
    94
            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
    95
            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
    96
                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
    97
            }
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    98
            HgError::CorruptedRepository(explanation) => {
46735
12d59eec7f1d rhg: Align with Python on some more error messages
Simon Sapin <simon.sapin@octobus.net>
parents: 46731
diff changeset
    99
                write!(f, "abort: {}", explanation)
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   100
            }
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   101
            HgError::UnsupportedFeature(explanation) => {
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   102
                write!(f, "unsupported feature: {}", explanation)
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   103
            }
46797
bcdcb4423ae3 rhg: Add more conversions between error types
Simon Sapin <simon.sapin@octobus.net>
parents: 46740
diff changeset
   104
            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
   105
        }
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
}
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   108
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   109
// 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
   110
impl fmt::Display for IoErrorContext {
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   111
    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
   112
        match self {
47780
cf5f8da2244c rhg: Propagate permission errors when finding a repository
Simon Sapin <simon.sapin@octobus.net>
parents: 47407
diff changeset
   113
            IoErrorContext::ReadingMetadata(path) => {
cf5f8da2244c rhg: Propagate permission errors when finding a repository
Simon Sapin <simon.sapin@octobus.net>
parents: 47407
diff changeset
   114
                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
   115
            }
46599
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   116
            IoErrorContext::ReadingFile(path) => {
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   117
                write!(f, "when reading {}", path.display())
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   118
            }
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   119
            IoErrorContext::WritingFile(path) => {
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   120
                write!(f, "when writing {}", path.display())
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   121
            }
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   122
            IoErrorContext::RemovingFile(path) => {
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   123
                write!(f, "when removing {}", path.display())
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   124
            }
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   125
            IoErrorContext::RenamingFile { from, to } => write!(
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   126
                f,
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   127
                "when renaming {} to {}",
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   128
                from.display(),
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   129
                to.display()
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   130
            ),
46740
97ac588b6d9e rhg: Don’t make repository path absolute too early
Simon Sapin <simon.sapin@octobus.net>
parents: 46735
diff changeset
   131
            IoErrorContext::CanonicalizingPath(path) => {
97ac588b6d9e rhg: Don’t make repository path absolute too early
Simon Sapin <simon.sapin@octobus.net>
parents: 46735
diff changeset
   132
                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
   133
            }
46731
3d692e724d06 rhg: Align config file parse error formatting with Python
Simon Sapin <simon.sapin@octobus.net>
parents: 46599
diff changeset
   134
            IoErrorContext::CurrentDir => {
3d692e724d06 rhg: Align config file parse error formatting with Python
Simon Sapin <simon.sapin@octobus.net>
parents: 46599
diff changeset
   135
                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
   136
            }
3d692e724d06 rhg: Align config file parse error formatting with Python
Simon Sapin <simon.sapin@octobus.net>
parents: 46599
diff changeset
   137
            IoErrorContext::CurrentExe => {
3d692e724d06 rhg: Align config file parse error formatting with Python
Simon Sapin <simon.sapin@octobus.net>
parents: 46599
diff changeset
   138
                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
   139
            }
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   140
        }
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   141
    }
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   142
}
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   143
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   144
pub trait IoResultExt<T> {
46599
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   145
    /// 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
   146
    /// given path.
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   147
    ///
46599
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   148
    /// 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
   149
    /// 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
   150
    ///
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   151
    /// 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
   152
    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
   153
48418
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 47780
diff changeset
   154
    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
   155
46599
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   156
    fn with_context(
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   157
        self,
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   158
        context: impl FnOnce() -> IoErrorContext,
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   159
    ) -> Result<T, HgError>;
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   160
}
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   161
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   162
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
   163
    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
   164
        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
   165
    }
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   166
48418
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 47780
diff changeset
   167
    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
   168
        self.with_context(|| IoErrorContext::WritingFile(path.to_owned()))
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 47780
diff changeset
   169
    }
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 47780
diff changeset
   170
46599
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   171
    fn with_context(
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   172
        self,
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   173
        context: impl FnOnce() -> IoErrorContext,
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   174
    ) -> Result<T, HgError> {
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   175
        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
   176
            error,
46599
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   177
            context: context(),
46438
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   178
        })
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   179
    }
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   180
}
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   181
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   182
pub trait HgResultExt<T> {
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   183
    /// 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
   184
    ///
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   185
    /// 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
   186
    ///
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   187
    /// * `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
   188
    /// * 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
   189
    /// * Other errors are unchanged
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   190
    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
   191
}
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   192
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   193
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
   194
    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
   195
        match self {
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   196
            Ok(x) => Ok(Some(x)),
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   197
            Err(HgError::IoError { error, .. })
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   198
                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
   199
            {
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   200
                Ok(None)
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
            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
   203
        }
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   204
    }
39e9407820ac rust: Introduce an `HgError` enum for common error cases
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   205
}