##// END OF EJS Templates
rhg: fix `clippy` warnings...
Antoine Cezar -
r46010:fbc373b7 default
parent child Browse files
Show More
@@ -1,110 +1,110
1 use crate::exitcode;
1 use crate::exitcode;
2 use crate::ui::UiError;
2 use crate::ui::UiError;
3 use hg::operations::{FindRootError, FindRootErrorKind};
3 use hg::operations::{FindRootError, FindRootErrorKind};
4 use hg::utils::files::get_bytes_from_path;
4 use hg::utils::files::get_bytes_from_path;
5 use std::convert::From;
5 use std::convert::From;
6 use std::path::PathBuf;
6 use std::path::PathBuf;
7
7
8 /// The kind of command error
8 /// The kind of command error
9 #[derive(Debug)]
9 #[derive(Debug)]
10 pub enum CommandErrorKind {
10 pub enum CommandErrorKind {
11 /// The root of the repository cannot be found
11 /// The root of the repository cannot be found
12 RootNotFound(PathBuf),
12 RootNotFound(PathBuf),
13 /// The current directory cannot be found
13 /// The current directory cannot be found
14 CurrentDirNotFound(std::io::Error),
14 CurrentDirNotFound(std::io::Error),
15 /// The standard output stream cannot be written to
15 /// The standard output stream cannot be written to
16 StdoutError,
16 StdoutError,
17 /// The standard error stream cannot be written to
17 /// The standard error stream cannot be written to
18 StderrError,
18 StderrError,
19 /// The command aborted
19 /// The command aborted
20 Abort(Option<Vec<u8>>),
20 Abort(Option<Vec<u8>>),
21 }
21 }
22
22
23 impl CommandErrorKind {
23 impl CommandErrorKind {
24 pub fn get_exit_code(&self) -> exitcode::ExitCode {
24 pub fn get_exit_code(&self) -> exitcode::ExitCode {
25 match self {
25 match self {
26 CommandErrorKind::RootNotFound(_) => exitcode::ABORT,
26 CommandErrorKind::RootNotFound(_) => exitcode::ABORT,
27 CommandErrorKind::CurrentDirNotFound(_) => exitcode::ABORT,
27 CommandErrorKind::CurrentDirNotFound(_) => exitcode::ABORT,
28 CommandErrorKind::StdoutError => exitcode::ABORT,
28 CommandErrorKind::StdoutError => exitcode::ABORT,
29 CommandErrorKind::StderrError => exitcode::ABORT,
29 CommandErrorKind::StderrError => exitcode::ABORT,
30 CommandErrorKind::Abort(_) => exitcode::ABORT,
30 CommandErrorKind::Abort(_) => exitcode::ABORT,
31 }
31 }
32 }
32 }
33
33
34 /// Return the message corresponding to the error kind if any
34 /// Return the message corresponding to the error kind if any
35 pub fn get_error_message_bytes(&self) -> Option<Vec<u8>> {
35 pub fn get_error_message_bytes(&self) -> Option<Vec<u8>> {
36 match self {
36 match self {
37 // TODO use formating macro
37 // TODO use formating macro
38 CommandErrorKind::RootNotFound(path) => {
38 CommandErrorKind::RootNotFound(path) => {
39 let bytes = get_bytes_from_path(path);
39 let bytes = get_bytes_from_path(path);
40 Some(
40 Some(
41 [
41 [
42 b"abort: no repository found in '",
42 b"abort: no repository found in '",
43 bytes.as_slice(),
43 bytes.as_slice(),
44 b"' (.hg not found)!\n",
44 b"' (.hg not found)!\n",
45 ]
45 ]
46 .concat(),
46 .concat(),
47 )
47 )
48 }
48 }
49 // TODO use formating macro
49 // TODO use formating macro
50 CommandErrorKind::CurrentDirNotFound(e) => Some(
50 CommandErrorKind::CurrentDirNotFound(e) => Some(
51 [
51 [
52 b"abort: error getting current working directory: ",
52 b"abort: error getting current working directory: ",
53 e.to_string().as_bytes(),
53 e.to_string().as_bytes(),
54 b"\n",
54 b"\n",
55 ]
55 ]
56 .concat(),
56 .concat(),
57 ),
57 ),
58 CommandErrorKind::Abort(message) => message.to_owned(),
58 CommandErrorKind::Abort(message) => message.to_owned(),
59 _ => None,
59 _ => None,
60 }
60 }
61 }
61 }
62 }
62 }
63
63
64 /// The error type for the Command trait
64 /// The error type for the Command trait
65 #[derive(Debug)]
65 #[derive(Debug)]
66 pub struct CommandError {
66 pub struct CommandError {
67 pub kind: CommandErrorKind,
67 pub kind: CommandErrorKind,
68 }
68 }
69
69
70 impl CommandError {
70 impl CommandError {
71 /// Exist the process with the corresponding exit code.
71 /// Exist the process with the corresponding exit code.
72 pub fn exit(&self) -> () {
72 pub fn exit(&self) {
73 std::process::exit(self.kind.get_exit_code())
73 std::process::exit(self.kind.get_exit_code())
74 }
74 }
75
75
76 /// Return the message corresponding to the command error if any
76 /// Return the message corresponding to the command error if any
77 pub fn get_error_message_bytes(&self) -> Option<Vec<u8>> {
77 pub fn get_error_message_bytes(&self) -> Option<Vec<u8>> {
78 self.kind.get_error_message_bytes()
78 self.kind.get_error_message_bytes()
79 }
79 }
80 }
80 }
81
81
82 impl From<CommandErrorKind> for CommandError {
82 impl From<CommandErrorKind> for CommandError {
83 fn from(kind: CommandErrorKind) -> Self {
83 fn from(kind: CommandErrorKind) -> Self {
84 CommandError { kind }
84 CommandError { kind }
85 }
85 }
86 }
86 }
87
87
88 impl From<UiError> for CommandError {
88 impl From<UiError> for CommandError {
89 fn from(error: UiError) -> Self {
89 fn from(error: UiError) -> Self {
90 CommandError {
90 CommandError {
91 kind: match error {
91 kind: match error {
92 UiError::StdoutError(_) => CommandErrorKind::StdoutError,
92 UiError::StdoutError(_) => CommandErrorKind::StdoutError,
93 UiError::StderrError(_) => CommandErrorKind::StderrError,
93 UiError::StderrError(_) => CommandErrorKind::StderrError,
94 },
94 },
95 }
95 }
96 }
96 }
97 }
97 }
98
98
99 impl From<FindRootError> for CommandError {
99 impl From<FindRootError> for CommandError {
100 fn from(err: FindRootError) -> Self {
100 fn from(err: FindRootError) -> Self {
101 match err.kind {
101 match err.kind {
102 FindRootErrorKind::RootNotFound(path) => CommandError {
102 FindRootErrorKind::RootNotFound(path) => CommandError {
103 kind: CommandErrorKind::RootNotFound(path),
103 kind: CommandErrorKind::RootNotFound(path),
104 },
104 },
105 FindRootErrorKind::GetCurrentDirError(e) => CommandError {
105 FindRootErrorKind::GetCurrentDirError(e) => CommandError {
106 kind: CommandErrorKind::CurrentDirNotFound(e),
106 kind: CommandErrorKind::CurrentDirNotFound(e),
107 },
107 },
108 }
108 }
109 }
109 }
110 }
110 }
@@ -1,106 +1,100
1 use std::io;
1 use std::io;
2 use std::io::{ErrorKind, Write};
2 use std::io::{ErrorKind, Write};
3
3
4 #[derive(Debug)]
4 #[derive(Debug)]
5 pub struct Ui {
5 pub struct Ui {
6 stdout: std::io::Stdout,
6 stdout: std::io::Stdout,
7 stderr: std::io::Stderr,
7 stderr: std::io::Stderr,
8 }
8 }
9
9
10 /// The kind of user interface error
10 /// The kind of user interface error
11 pub enum UiError {
11 pub enum UiError {
12 /// The standard output stream cannot be written to
12 /// The standard output stream cannot be written to
13 StdoutError(io::Error),
13 StdoutError(io::Error),
14 /// The standard error stream cannot be written to
14 /// The standard error stream cannot be written to
15 StderrError(io::Error),
15 StderrError(io::Error),
16 }
16 }
17
17
18 /// The commandline user interface
18 /// The commandline user interface
19 impl Ui {
19 impl Ui {
20 pub fn new() -> Self {
20 pub fn new() -> Self {
21 Ui {
21 Ui {
22 stdout: std::io::stdout(),
22 stdout: std::io::stdout(),
23 stderr: std::io::stderr(),
23 stderr: std::io::stderr(),
24 }
24 }
25 }
25 }
26
26
27 /// Returns a buffered handle on stdout for faster batch printing
27 /// Returns a buffered handle on stdout for faster batch printing
28 /// operations.
28 /// operations.
29 pub fn stdout_buffer(&self) -> StdoutBuffer<std::io::StdoutLock> {
29 pub fn stdout_buffer(&self) -> StdoutBuffer<std::io::StdoutLock> {
30 StdoutBuffer::new(self.stdout.lock())
30 StdoutBuffer::new(self.stdout.lock())
31 }
31 }
32
32
33 /// Write bytes to stdout
33 /// Write bytes to stdout
34 pub fn write_stdout(&self, bytes: &[u8]) -> Result<(), UiError> {
34 pub fn write_stdout(&self, bytes: &[u8]) -> Result<(), UiError> {
35 let mut stdout = self.stdout.lock();
35 let mut stdout = self.stdout.lock();
36
36
37 stdout
37 stdout.write_all(bytes).or_else(handle_stdout_error)?;
38 .write_all(bytes)
39 .or_else(|e| handle_stdout_error(e))?;
40
38
41 stdout.flush().or_else(|e| handle_stdout_error(e))
39 stdout.flush().or_else(handle_stdout_error)
42 }
40 }
43
41
44 /// Write bytes to stderr
42 /// Write bytes to stderr
45 pub fn write_stderr(&self, bytes: &[u8]) -> Result<(), UiError> {
43 pub fn write_stderr(&self, bytes: &[u8]) -> Result<(), UiError> {
46 let mut stderr = self.stderr.lock();
44 let mut stderr = self.stderr.lock();
47
45
48 stderr
46 stderr.write_all(bytes).or_else(handle_stderr_error)?;
49 .write_all(bytes)
50 .or_else(|e| handle_stderr_error(e))?;
51
47
52 stderr.flush().or_else(|e| handle_stderr_error(e))
48 stderr.flush().or_else(handle_stderr_error)
53 }
49 }
54 }
50 }
55
51
56 /// A buffered stdout writer for faster batch printing operations.
52 /// A buffered stdout writer for faster batch printing operations.
57 pub struct StdoutBuffer<W: Write> {
53 pub struct StdoutBuffer<W: Write> {
58 buf: io::BufWriter<W>,
54 buf: io::BufWriter<W>,
59 }
55 }
60
56
61 impl<W: Write> StdoutBuffer<W> {
57 impl<W: Write> StdoutBuffer<W> {
62 pub fn new(writer: W) -> Self {
58 pub fn new(writer: W) -> Self {
63 let buf = io::BufWriter::new(writer);
59 let buf = io::BufWriter::new(writer);
64 Self { buf }
60 Self { buf }
65 }
61 }
66
62
67 /// Write bytes to stdout buffer
63 /// Write bytes to stdout buffer
68 pub fn write_all(&mut self, bytes: &[u8]) -> Result<(), UiError> {
64 pub fn write_all(&mut self, bytes: &[u8]) -> Result<(), UiError> {
69 self.buf
65 self.buf.write_all(bytes).or_else(handle_stdout_error)
70 .write_all(bytes)
71 .or_else(|e| handle_stdout_error(e))
72 }
66 }
73
67
74 /// Flush bytes to stdout
68 /// Flush bytes to stdout
75 pub fn flush(&mut self) -> Result<(), UiError> {
69 pub fn flush(&mut self) -> Result<(), UiError> {
76 self.buf.flush().or_else(|e| handle_stdout_error(e))
70 self.buf.flush().or_else(handle_stdout_error)
77 }
71 }
78 }
72 }
79
73
80 /// Sometimes writing to stdout is not possible, try writing to stderr to
74 /// Sometimes writing to stdout is not possible, try writing to stderr to
81 /// signal that failure, otherwise just bail.
75 /// signal that failure, otherwise just bail.
82 fn handle_stdout_error(error: io::Error) -> Result<(), UiError> {
76 fn handle_stdout_error(error: io::Error) -> Result<(), UiError> {
83 if let ErrorKind::BrokenPipe = error.kind() {
77 if let ErrorKind::BrokenPipe = error.kind() {
84 // This makes `| head` work for example
78 // This makes `| head` work for example
85 return Ok(());
79 return Ok(());
86 }
80 }
87 let mut stderr = io::stderr();
81 let mut stderr = io::stderr();
88
82
89 stderr
83 stderr
90 .write_all(&[b"abort: ", error.to_string().as_bytes(), b"\n"].concat())
84 .write_all(&[b"abort: ", error.to_string().as_bytes(), b"\n"].concat())
91 .map_err(|e| UiError::StderrError(e))?;
85 .map_err(UiError::StderrError)?;
92
86
93 stderr.flush().map_err(|e| UiError::StderrError(e))?;
87 stderr.flush().map_err(UiError::StderrError)?;
94
88
95 Err(UiError::StdoutError(error))
89 Err(UiError::StdoutError(error))
96 }
90 }
97
91
98 /// Sometimes writing to stderr is not possible.
92 /// Sometimes writing to stderr is not possible.
99 fn handle_stderr_error(error: io::Error) -> Result<(), UiError> {
93 fn handle_stderr_error(error: io::Error) -> Result<(), UiError> {
100 // A broken pipe should not result in a error
94 // A broken pipe should not result in a error
101 // like with `| head` for example
95 // like with `| head` for example
102 if let ErrorKind::BrokenPipe = error.kind() {
96 if let ErrorKind::BrokenPipe = error.kind() {
103 return Ok(());
97 return Ok(());
104 }
98 }
105 Err(UiError::StdoutError(error))
99 Err(UiError::StdoutError(error))
106 }
100 }
General Comments 0
You need to be logged in to leave comments. Login now