@@ -4,20 +4,70 @@ use rustc_serialize::json;
44use std:: fs;
55use std:: env;
66use std:: io;
7+ use std:: fmt;
78use std:: path:: Path ;
9+ use std:: cell:: RefCell ;
810
911use std:: io:: { Write , Read } ;
1012
1113use std:: default:: Default ;
1214
1315#[ derive( Debug ) ]
14- pub enum ArgumentError {
15- ConfigurationDirectoryInaccessible ( ( String , io:: Error ) ) ,
16- ConfigurationDirectoryUnset ,
17- UsernameExpansionFailed ( String ) ,
16+ pub enum ApplicationSecretError {
17+ DecoderError ( ( String , json:: DecoderError ) ) ,
18+ FormatError ( String ) ,
19+ }
20+
21+ impl fmt:: Display for ApplicationSecretError {
22+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> Result < ( ) , fmt:: Error > {
23+ match * self {
24+ ApplicationSecretError :: DecoderError ( ( ref path, ref err) )
25+ => writeln ! ( f, "Could not decode file at '{}' with error: {}"
26+ , path, err) ,
27+ ApplicationSecretError :: FormatError ( ref path)
28+ => writeln ! ( f, "'installed' field is unset in secret file at '{}'"
29+ , path) ,
30+ }
31+ }
32+ }
33+
34+ #[ derive( Debug ) ]
35+ pub enum ConfigurationError {
36+ DirectoryCreationFailed ( ( String , io:: Error ) ) ,
37+ DirectoryUnset ,
38+ HomeExpansionFailed ( String ) ,
39+ Secret ( ApplicationSecretError ) ,
1840 IOError ( ( String , io:: Error ) ) ,
19- SecretDecoderError ( ( String , json:: DecoderError ) ) ,
20- SecretFormatError ( String ) ,
41+ }
42+
43+ impl fmt:: Display for ConfigurationError {
44+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> Result < ( ) , fmt:: Error > {
45+ match * self {
46+ ConfigurationError :: DirectoryCreationFailed ( ( ref dir, ref err) )
47+ => writeln ! ( f, "Directory '{}' could not be created with error: {}" , dir, err) ,
48+ ConfigurationError :: DirectoryUnset
49+ => writeln ! ( f, "--config-dir was unset or empty" ) ,
50+ ConfigurationError :: HomeExpansionFailed ( ref dir)
51+ => writeln ! ( f, "Couldn't find HOME directory of current user, failed to expand '{}'" , dir) ,
52+ ConfigurationError :: Secret ( ref err)
53+ => writeln ! ( f, "Secret -> {}" , err) ,
54+ ConfigurationError :: IOError ( ( ref path, ref err) )
55+ => writeln ! ( f, "IO operation failed on path '{}' with error: {}" , path, err) ,
56+ }
57+ }
58+ }
59+
60+ #[ derive( Debug ) ]
61+ pub enum ArgumentError {
62+ Configuration ( ConfigurationError ) ,
63+ }
64+
65+ impl fmt:: Display for ArgumentError {
66+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> Result < ( ) , fmt:: Error > {
67+ match * self {
68+ ArgumentError :: Configuration ( ref err) => writeln ! ( f, "Configuration -> {}" , err)
69+ }
70+ }
2171}
2272
2373#[ derive( Debug ) ]
@@ -26,6 +76,15 @@ pub struct InvalidOptionsError {
2676 pub exit_code : i32 ,
2777}
2878
79+ impl fmt:: Display for InvalidOptionsError {
80+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> Result < ( ) , fmt:: Error > {
81+ for issue in & self . issues {
82+ try!( issue. fmt ( f) ) ;
83+ }
84+ Ok ( ( ) )
85+ }
86+ }
87+
2988impl InvalidOptionsError {
3089 pub fn single ( err : ArgumentError , exit_code : i32 ) -> InvalidOptionsError {
3190 InvalidOptionsError {
@@ -38,13 +97,13 @@ impl InvalidOptionsError {
3897pub fn assure_config_dir_exists ( dir : & str ) -> Result < String , ArgumentError > {
3998 let trdir = dir. trim ( ) ;
4099 if trdir. len ( ) == 0 {
41- return Err ( ArgumentError :: ConfigurationDirectoryUnset )
100+ return Err ( ArgumentError :: Configuration ( ConfigurationError :: DirectoryUnset ) )
42101 }
43102
44103 let expanded_config_dir =
45104 if trdir. as_bytes ( ) [ 0 ] == b'~' {
46105 match env:: var ( "HOME" ) . ok ( ) . or ( env:: var ( "UserProfile" ) . ok ( ) ) {
47- None => return Err ( ArgumentError :: UsernameExpansionFailed ( trdir. to_string ( ) ) ) ,
106+ None => return Err ( ArgumentError :: Configuration ( ConfigurationError :: HomeExpansionFailed ( trdir. to_string ( ) ) ) ) ,
48107 Some ( mut user) => {
49108 user. push_str ( & trdir[ 1 ..] ) ;
50109 user
@@ -56,7 +115,8 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, ArgumentError> {
56115
57116 if let Err ( err) = fs:: create_dir ( & expanded_config_dir) {
58117 if err. kind ( ) != io:: ErrorKind :: AlreadyExists {
59- return Err ( ArgumentError :: ConfigurationDirectoryInaccessible ( ( expanded_config_dir, err) ) )
118+ return Err ( ArgumentError :: Configuration (
119+ ConfigurationError :: DirectoryCreationFailed ( ( expanded_config_dir, err) ) ) )
60120 }
61121 }
62122
@@ -67,15 +127,15 @@ pub fn application_secret_from_directory(dir: &str, secret_basename: &str) -> Re
67127 let secret_path = Path :: new ( dir) . join ( secret_basename) ;
68128 let secret_str = || secret_path. as_path ( ) . to_str ( ) . unwrap ( ) . to_string ( ) ;
69129 let secret_io_error = |io_err : io:: Error | {
70- Err ( ArgumentError :: IOError (
130+ Err ( ArgumentError :: Configuration ( ConfigurationError :: IOError (
71131 ( secret_str ( ) , io_err)
72- ) )
132+ ) ) )
73133 } ;
74134
75135 for _ in 0 ..2 {
76136 match fs:: File :: open ( & secret_path) {
77- Err ( mut e ) => {
78- if e . kind ( ) == io:: ErrorKind :: NotFound {
137+ Err ( mut err ) => {
138+ if err . kind ( ) == io:: ErrorKind :: NotFound {
79139 // Write our built-in one - user may adjust the written file at will
80140 let secret = ApplicationSecret {
81141 client_id : "14070749909-vgip2f1okm7bkvajhi9jugan6126io9v.apps.googleusercontent.com" . to_string ( ) ,
@@ -94,7 +154,7 @@ pub fn application_secret_from_directory(dir: &str, secret_basename: &str) -> Re
94154 } ;
95155
96156 let json_enocded_secret = json:: encode ( & app_secret) . unwrap ( ) ;
97- e = match fs:: OpenOptions :: new ( ) . create ( true ) . write ( true ) . open ( & secret_path) {
157+ err = match fs:: OpenOptions :: new ( ) . create ( true ) . write ( true ) . open ( & secret_path) {
98158 Err ( cfe) => cfe,
99159 Ok ( mut f) => {
100160 match f. write ( json_enocded_secret. as_bytes ( ) ) {
@@ -105,20 +165,25 @@ pub fn application_secret_from_directory(dir: &str, secret_basename: &str) -> Re
105165 } ;
106166 // fall through to IO error handling
107167 }
108- return secret_io_error ( e )
168+ return secret_io_error ( err )
109169 } ,
110170 Ok ( mut f) => {
111171 let mut json_encoded_secret = String :: new ( ) ;
112172 if let Err ( io_err) = f. read_to_string ( & mut json_encoded_secret) {
113173 return secret_io_error ( io_err)
114174 }
115175 match json:: decode :: < ConsoleApplicationSecret > ( & json_encoded_secret) {
116- Err ( json_decode_error) => return Err ( ArgumentError :: SecretDecoderError (
176+ Err ( json_decode_error) => return Err ( ArgumentError :: Configuration (
177+ ConfigurationError :: Secret ( ApplicationSecretError :: DecoderError (
117178 ( secret_str ( ) , json_decode_error)
118- ) ) ,
179+ ) ) ) ) ,
119180 Ok ( console_secret) => match console_secret. installed {
120181 Some ( secret) => return Ok ( secret) ,
121- None => return Err ( ArgumentError :: SecretFormatError ( secret_str ( ) ) )
182+ None => return Err (
183+ ArgumentError :: Configuration (
184+ ConfigurationError :: Secret (
185+ ApplicationSecretError :: FormatError ( secret_str ( ) )
186+ ) ) )
122187 } ,
123188 }
124189 }
0 commit comments