@@ -37,7 +37,7 @@ use log::debug;
3737use serde:: ser;
3838use std:: fmt;
3939
40- pub use crate :: util:: errors:: Internal ;
40+ pub use crate :: util:: errors:: { InternalError , VerboseError } ;
4141pub use crate :: util:: { CargoResult , CliError , CliResult , Config } ;
4242
4343pub const CARGO_ENV : & str = "CARGO" ;
@@ -106,64 +106,60 @@ pub fn exit_with_error(err: CliError, shell: &mut Shell) -> ! {
106106 }
107107 }
108108
109- let CliError {
110- error,
111- exit_code,
112- unknown,
113- } = err;
114- // `exit_code` of 0 means non-fatal error (e.g., docopt version info).
115- let fatal = exit_code != 0 ;
116-
117- let hide = unknown && shell. verbosity ( ) != Verbose ;
118-
109+ let CliError { error, exit_code } = err;
119110 if let Some ( error) = error {
120- if hide {
121- drop ( shell. error ( "An unknown error occurred" ) )
122- } else if fatal {
123- drop ( shell. error ( & error) )
124- } else {
125- println ! ( "{}" , error) ;
126- }
127-
128- if !handle_cause ( & error, shell) || hide {
129- drop ( writeln ! (
130- shell. err( ) ,
131- "\n To learn more, run the command again \
132- with --verbose."
133- ) ) ;
134- }
111+ display_error ( & error, shell) ;
135112 }
136113
137114 std:: process:: exit ( exit_code)
138115}
139116
140- pub fn handle_error ( err : & Error , shell : & mut Shell ) {
141- debug ! ( "handle_error; err={:?}" , err) ;
142-
143- let _ignored_result = shell. error ( err) ;
144- handle_cause ( err, shell) ;
117+ /// Displays an error, and all its causes, to stderr.
118+ pub fn display_error ( err : & Error , shell : & mut Shell ) {
119+ debug ! ( "display_error; err={:?}" , err) ;
120+ let has_verbose = _display_error ( err, shell) ;
121+ if has_verbose {
122+ drop ( writeln ! (
123+ shell. err( ) ,
124+ "\n To learn more, run the command again with --verbose."
125+ ) ) ;
126+ }
127+ if err
128+ . chain ( )
129+ . any ( |e| e. downcast_ref :: < InternalError > ( ) . is_some ( ) )
130+ {
131+ drop ( shell. note ( "this is an unexpected cargo internal error" ) ) ;
132+ drop (
133+ shell. note (
134+ "we would appreciate a bug report: https://github.com/rust-lang/cargo/issues/" ,
135+ ) ,
136+ ) ;
137+ drop ( shell. note ( format ! ( "{}" , version( ) ) ) ) ;
138+ // Once backtraces are stabilized, this should print out a backtrace
139+ // if it is available.
140+ }
145141}
146142
147- fn handle_cause ( cargo_err : & Error , shell : & mut Shell ) -> bool {
148- fn print ( error : & str , shell : & mut Shell ) {
149- drop ( writeln ! ( shell. err( ) , "\n Caused by:" ) ) ;
150- drop ( writeln ! ( shell. err( ) , " {}" , error) ) ;
143+ fn _display_error ( err : & Error , shell : & mut Shell ) -> bool {
144+ let verbosity = shell. verbosity ( ) ;
145+ let is_verbose = |e : & ( dyn std:: error:: Error + ' static ) | -> bool {
146+ verbosity != Verbose && e. downcast_ref :: < VerboseError > ( ) . is_some ( )
147+ } ;
148+ // Generally the top error shouldn't be verbose, but check it anyways.
149+ if is_verbose ( err. as_ref ( ) ) {
150+ return true ;
151151 }
152-
153- let verbose = shell. verbosity ( ) ;
154-
155- // The first error has already been printed to the shell.
156- for err in cargo_err. chain ( ) . skip ( 1 ) {
152+ drop ( shell. error ( & err) ) ;
153+ for cause in err. chain ( ) . skip ( 1 ) {
157154 // If we're not in verbose mode then print remaining errors until one
158- // marked as `Internal ` appears.
159- if verbose != Verbose && err . downcast_ref :: < Internal > ( ) . is_some ( ) {
160- return false ;
155+ // marked as `VerboseError ` appears.
156+ if is_verbose ( cause ) {
157+ return true ;
161158 }
162-
163- print ( & err . to_string ( ) , shell ) ;
159+ drop ( writeln ! ( shell . err ( ) , " \n Caused by:" ) ) ;
160+ drop ( writeln ! ( shell . err ( ) , " {}" , cause ) ) ;
164161 }
165-
166- true
162+ false
167163}
168164
169165pub fn version ( ) -> VersionInfo {
0 commit comments