rust/rhg/src/error.rs
changeset 49487 9f14126cfc4c
parent 49485 ffd4b1f1c9cb
child 49488 7c93e38a0bbd
equal deleted inserted replaced
49486:e8481625c582 49487:9f14126cfc4c
    18 pub enum CommandError {
    18 pub enum CommandError {
    19     /// Exit with an error message and "standard" failure exit code.
    19     /// Exit with an error message and "standard" failure exit code.
    20     Abort {
    20     Abort {
    21         message: Vec<u8>,
    21         message: Vec<u8>,
    22         detailed_exit_code: exit_codes::ExitCode,
    22         detailed_exit_code: exit_codes::ExitCode,
       
    23         hint: Option<Vec<u8>>,
    23     },
    24     },
    24 
    25 
    25     /// Exit with a failure exit code but no message.
    26     /// Exit with a failure exit code but no message.
    26     Unsuccessful,
    27     Unsuccessful,
    27 
    28 
    48             // TODO: bytes-based (instead of Unicode-based) formatting
    49             // TODO: bytes-based (instead of Unicode-based) formatting
    49             // of error messages to handle non-UTF-8 filenames etc:
    50             // of error messages to handle non-UTF-8 filenames etc:
    50             // https://www.mercurial-scm.org/wiki/EncodingStrategy#Mixing_output
    51             // https://www.mercurial-scm.org/wiki/EncodingStrategy#Mixing_output
    51             message: utf8_to_local(message.as_ref()).into(),
    52             message: utf8_to_local(message.as_ref()).into(),
    52             detailed_exit_code: detailed_exit_code,
    53             detailed_exit_code: detailed_exit_code,
       
    54             hint: None,
       
    55         }
       
    56     }
       
    57 
       
    58     pub fn abort_with_exit_code_and_hint(
       
    59         message: impl AsRef<str>,
       
    60         detailed_exit_code: exit_codes::ExitCode,
       
    61         hint: Option<impl AsRef<str>>,
       
    62     ) -> Self {
       
    63         CommandError::Abort {
       
    64             message: utf8_to_local(message.as_ref()).into(),
       
    65             detailed_exit_code,
       
    66             hint: hint.map(|h| utf8_to_local(h.as_ref()).into()),
    53         }
    67         }
    54     }
    68     }
    55 
    69 
    56     pub fn abort_with_exit_code_bytes(
    70     pub fn abort_with_exit_code_bytes(
    57         message: impl AsRef<[u8]>,
    71         message: impl AsRef<[u8]>,
    60         // TODO: use this everywhere it makes sense instead of the string
    74         // TODO: use this everywhere it makes sense instead of the string
    61         // version.
    75         // version.
    62         CommandError::Abort {
    76         CommandError::Abort {
    63             message: message.as_ref().into(),
    77             message: message.as_ref().into(),
    64             detailed_exit_code,
    78             detailed_exit_code,
       
    79             hint: None,
    65         }
    80         }
    66     }
    81     }
    67 
    82 
    68     pub fn unsupported(message: impl AsRef<str>) -> Self {
    83     pub fn unsupported(message: impl AsRef<str>) -> Self {
    69         CommandError::UnsupportedFeature {
    84         CommandError::UnsupportedFeature {
    90                 CommandError::unsupported("Encountered a censored node")
   105                 CommandError::unsupported("Encountered a censored node")
    91             }
   106             }
    92             HgError::Abort {
   107             HgError::Abort {
    93                 message,
   108                 message,
    94                 detailed_exit_code,
   109                 detailed_exit_code,
    95             } => {
   110                 hint,
    96                 CommandError::abort_with_exit_code(message, detailed_exit_code)
   111             } => CommandError::abort_with_exit_code_and_hint(
    97             }
   112                 message,
       
   113                 detailed_exit_code,
       
   114                 hint,
       
   115             ),
    98             _ => CommandError::abort(error.to_string()),
   116             _ => CommandError::abort(error.to_string()),
    99         }
   117         }
   100     }
   118     }
   101 }
   119 }
   102 
   120 
   119 }
   137 }
   120 
   138 
   121 impl From<RepoError> for CommandError {
   139 impl From<RepoError> for CommandError {
   122     fn from(error: RepoError) -> Self {
   140     fn from(error: RepoError) -> Self {
   123         match error {
   141         match error {
   124             RepoError::NotFound { at } => CommandError::Abort {
   142             RepoError::NotFound { at } => {
   125                 message: format_bytes!(
   143                 CommandError::abort_with_exit_code_bytes(
   126                     b"abort: repository {} not found",
   144                     format_bytes!(
   127                     get_bytes_from_path(at)
   145                         b"abort: repository {} not found",
   128                 ),
   146                         get_bytes_from_path(at)
   129                 detailed_exit_code: exit_codes::ABORT,
   147                     ),
   130             },
   148                     exit_codes::ABORT,
       
   149                 )
       
   150             }
   131             RepoError::ConfigParseError(error) => error.into(),
   151             RepoError::ConfigParseError(error) => error.into(),
   132             RepoError::Other(error) => error.into(),
   152             RepoError::Other(error) => error.into(),
   133         }
   153         }
   134     }
   154     }
   135 }
   155 }
   136 
   156 
   137 impl<'a> From<&'a NoRepoInCwdError> for CommandError {
   157 impl<'a> From<&'a NoRepoInCwdError> for CommandError {
   138     fn from(error: &'a NoRepoInCwdError) -> Self {
   158     fn from(error: &'a NoRepoInCwdError) -> Self {
   139         let NoRepoInCwdError { cwd } = error;
   159         let NoRepoInCwdError { cwd } = error;
   140         CommandError::Abort {
   160         CommandError::abort_with_exit_code_bytes(
   141             message: format_bytes!(
   161             format_bytes!(
   142                 b"abort: no repository found in '{}' (.hg not found)!",
   162                 b"abort: no repository found in '{}' (.hg not found)!",
   143                 get_bytes_from_path(cwd)
   163                 get_bytes_from_path(cwd)
   144             ),
   164             ),
   145             detailed_exit_code: exit_codes::ABORT,
   165             exit_codes::ABORT,
   146         }
   166         )
   147     }
   167     }
   148 }
   168 }
   149 
   169 
   150 impl From<ConfigError> for CommandError {
   170 impl From<ConfigError> for CommandError {
   151     fn from(error: ConfigError) -> Self {
   171     fn from(error: ConfigError) -> Self {
   166         let line_message = if let Some(line_number) = line {
   186         let line_message = if let Some(line_number) = line {
   167             format_bytes!(b":{}", line_number.to_string().into_bytes())
   187             format_bytes!(b":{}", line_number.to_string().into_bytes())
   168         } else {
   188         } else {
   169             Vec::new()
   189             Vec::new()
   170         };
   190         };
   171         CommandError::Abort {
   191         CommandError::abort_with_exit_code_bytes(
   172             message: format_bytes!(
   192             format_bytes!(
   173                 b"config error at {}{}: {}",
   193                 b"config error at {}{}: {}",
   174                 origin,
   194                 origin,
   175                 line_message,
   195                 line_message,
   176                 message
   196                 message
   177             ),
   197             ),
   178             detailed_exit_code: exit_codes::CONFIG_ERROR_ABORT,
   198             exit_codes::CONFIG_ERROR_ABORT,
   179         }
   199         )
   180     }
   200     }
   181 }
   201 }
   182 
   202 
   183 impl From<(RevlogError, &str)> for CommandError {
   203 impl From<(RevlogError, &str)> for CommandError {
   184     fn from((err, rev): (RevlogError, &str)) -> CommandError {
   204     fn from((err, rev): (RevlogError, &str)) -> CommandError {