@@ -7,11 +7,11 @@ use clap_complete::generate;
77use dsc_lib:: { progress:: ProgressFormat , util:: DSC_IGNORE_SETTINGS_FILE } ;
88use server:: start_server;
99use rust_i18n:: { i18n, t} ;
10- use std:: { env:: set_var, io, process:: exit } ;
10+ use std:: { env:: set_var, io, process:: ExitCode } ;
1111use sysinfo:: { Process , RefreshKind , System , get_current_pid, ProcessRefreshKind } ;
1212use tracing:: { error, info, warn, debug} ;
1313
14- use crate :: util:: { EXIT_INVALID_INPUT , get_input} ;
14+ use crate :: util:: get_input;
1515
1616#[ cfg( debug_assertions) ]
1717use crossterm:: event;
@@ -28,7 +28,7 @@ pub mod util;
2828
2929i18n ! ( "locales" , fallback = "en-us" ) ;
3030
31- fn main ( ) {
31+ fn main ( ) -> ExitCode {
3232 #[ cfg( windows) ]
3333 {
3434 let handle = match std:: thread:: Builder :: new ( )
@@ -39,27 +39,38 @@ fn main() {
3939 Ok ( handle) => handle,
4040 Err ( err) => {
4141 error ! ( "{}" , t!( "main.failedToSpawnMain" , error = err) ) ;
42- exit ( util:: EXIT_DSC_ERROR ) ;
42+ return ExitCode :: from ( util:: EXIT_DSC_ERROR ) ;
4343 }
4444 } ;
4545
46- if let Err ( err) = handle. join ( ) {
47- error ! ( "{}" , t!( "main.failedToJoinMain" , error = err : { : ?} ) ) ;
48- exit ( util:: EXIT_DSC_ERROR ) ;
46+ match handle. join ( ) {
47+ Ok ( result) => {
48+ if let Err ( code) = result {
49+ return code;
50+ }
51+ } ,
52+ Err ( err) => {
53+ error ! ( "{}" , t!( "main.failedToJoinMain" , error = err : { : ?} ) ) ;
54+ return ExitCode :: from ( util:: EXIT_DSC_ERROR ) ;
55+ }
4956 }
57+ ExitCode :: from ( util:: EXIT_SUCCESS )
5058 }
5159 #[ cfg( not( windows) ) ]
5260 {
53- dsc_main ( ) ;
61+ match dsc_main ( ) {
62+ Ok ( _) => ExitCode :: from ( util:: EXIT_SUCCESS ) ,
63+ Err ( code) => code,
64+ }
5465 }
5566}
5667
57- fn dsc_main ( ) {
68+ fn dsc_main ( ) -> Result < ( ) , ExitCode > {
5869 #[ cfg( debug_assertions) ]
5970 check_debug ( ) ;
6071
6172 #[ cfg( windows) ]
62- check_store ( ) ;
73+ check_store ( ) ? ;
6374
6475 if ctrlc:: set_handler ( ctrlc_handler) . is_err ( ) {
6576 error ! ( "{}" , t!( "main.failedCtrlCHandler" ) ) ;
@@ -87,7 +98,9 @@ fn dsc_main() {
8798 generate ( shell, & mut cmd, "dsc" , & mut io:: stdout ( ) ) ;
8899 } ,
89100 SubCommand :: Config { subcommand, parameters, parameters_file, system_root, as_group, as_assert, as_include } => {
90- let params = get_input ( None , parameters_file. as_ref ( ) ) ;
101+ let Ok ( params) = get_input ( None , parameters_file. as_ref ( ) ) else {
102+ return Err ( ExitCode :: from ( util:: EXIT_INVALID_INPUT ) ) ;
103+ } ;
91104 let file_params = if params. is_empty ( ) {
92105 None
93106 } else {
@@ -101,7 +114,7 @@ fn dsc_main() {
101114 Ok ( merged) => Some ( merged) ,
102115 Err ( err) => {
103116 error ! ( "{}: {err}" , t!( "main.failedMergingParameters" ) ) ;
104- exit ( EXIT_INVALID_INPUT ) ;
117+ return Err ( ExitCode :: from ( util :: EXIT_INVALID_INPUT ) ) ;
105118 }
106119 }
107120 } ,
@@ -110,58 +123,59 @@ fn dsc_main() {
110123 ( None , None ) => None ,
111124 } ;
112125
113- subcommand:: config ( & subcommand, & merged_parameters, system_root. as_ref ( ) , & as_group, & as_assert, & as_include, progress_format) ;
126+ subcommand:: config ( & subcommand, & merged_parameters, system_root. as_ref ( ) , & as_group, & as_assert, & as_include, progress_format) ? ;
114127 } ,
115128 SubCommand :: Extension { subcommand } => {
116- subcommand:: extension ( & subcommand, progress_format) ;
129+ subcommand:: extension ( & subcommand, progress_format) ? ;
117130 } ,
118131 SubCommand :: Function { subcommand } => {
119- subcommand:: function ( & subcommand) ;
132+ subcommand:: function ( & subcommand) ? ;
120133 } ,
121134 SubCommand :: Server => {
122135 if let Err ( err) = start_server ( ) {
123136 error ! ( "{}" , t!( "main.failedToStartServer" , error = err) ) ;
124- exit ( util:: EXIT_SERVER_FAILED ) ;
137+ return Err ( ExitCode :: from ( util:: EXIT_SERVER_FAILED ) ) ;
125138 }
126- exit ( util :: EXIT_SUCCESS ) ;
139+ return Ok ( ( ) ) ;
127140 }
128141 SubCommand :: Resource { subcommand } => {
129- subcommand:: resource ( & subcommand, progress_format) ;
142+ subcommand:: resource ( & subcommand, progress_format) ? ;
130143 } ,
131144 SubCommand :: Schema { dsc_type , output_format } => {
132145 let schema = util:: get_schema ( dsc_type) ;
133146 let json = match serde_json:: to_string ( & schema) {
134147 Ok ( json) => json,
135148 Err ( err) => {
136149 error ! ( "JSON: {err}" ) ;
137- exit ( util:: EXIT_JSON_ERROR ) ;
150+ return Err ( ExitCode :: from ( util:: EXIT_JSON_ERROR ) ) ;
138151 }
139152 } ;
140- util:: write_object ( & json, output_format. as_ref ( ) , false ) ;
153+ util:: write_object ( & json, output_format. as_ref ( ) , false ) ? ;
141154 } ,
142155 }
143156
144- exit ( util :: EXIT_SUCCESS ) ;
157+ Ok ( ( ) )
145158}
146159
147160fn ctrlc_handler ( ) {
161+ use std:: process:: exit;
148162 warn ! ( "{}" , t!( "main.ctrlCReceived" ) ) ;
149163
150164 // get process tree for current process and terminate all processes
151165 let sys = System :: new_with_specifics ( RefreshKind :: nothing ( ) . with_processes ( ProcessRefreshKind :: everything ( ) ) ) ;
152166 info ! ( "{}: {}" , t!( "main.foundProcesses" ) , sys. processes( ) . len( ) ) ;
153167 let Ok ( current_pid) = get_current_pid ( ) else {
154168 error ! ( "{}" , t!( "main.failedToGetPid" ) ) ;
155- exit ( util:: EXIT_CTRL_C ) ;
169+ exit ( i32 :: from ( util:: EXIT_CTRL_C ) ) ;
156170 } ;
157171 info ! ( "{}: {}" , t!( "main.currentPid" ) , current_pid) ;
158172 let Some ( current_process) = sys. process ( current_pid) else {
159173 error ! ( "{}" , t!( "main.failedToGetProcess" ) ) ;
160- exit ( util:: EXIT_CTRL_C ) ;
174+ exit ( i32 :: from ( util:: EXIT_CTRL_C ) ) ;
161175 } ;
162176
163177 terminate_subprocesses ( & sys, current_process) ;
164- exit ( util:: EXIT_CTRL_C ) ;
178+ exit ( i32 :: from ( util:: EXIT_CTRL_C ) ) ;
165179}
166180
167181fn terminate_subprocesses ( sys : & System , process : & Process ) {
@@ -200,32 +214,34 @@ fn check_debug() {
200214
201215// Check if the dsc binary parent process is WinStore.App or Explorer.exe
202216#[ cfg( windows) ]
203- fn check_store ( ) {
217+ fn check_store ( ) -> Result < ( ) , ExitCode > {
204218 use std:: io:: Read ;
205219
206220 let sys = System :: new_with_specifics ( RefreshKind :: nothing ( ) . with_processes ( ProcessRefreshKind :: everything ( ) ) ) ;
207221 // get current process
208222 let Ok ( current_pid) = get_current_pid ( ) else {
209- return ;
223+ return Ok ( ( ) ) ;
210224 } ;
211225
212226 // get parent process
213227 let Some ( current_process) = sys. process ( current_pid) else {
214- return ;
228+ return Ok ( ( ) ) ;
215229 } ;
216230 let Some ( parent_process_pid) = current_process. parent ( ) else {
217- return ;
231+ return Ok ( ( ) ) ;
218232 } ;
219233 let Some ( parent_process) = sys. process ( parent_process_pid) else {
220- return ;
234+ return Ok ( ( ) ) ;
221235 } ;
222236
223237 // MS Store runs app using `sihost.exe`
224238 if parent_process. name ( ) . eq_ignore_ascii_case ( "sihost.exe" ) || parent_process. name ( ) . eq_ignore_ascii_case ( "explorer.exe" ) {
225239 eprintln ! ( "{}" , t!( "main.storeMessage" ) ) ;
226240 // wait for keypress
227241 let _ = io:: stdin ( ) . read ( & mut [ 0u8 ] ) . unwrap ( ) ;
228- exit ( util:: EXIT_INVALID_ARGS ) ;
242+ return Err ( ExitCode :: from ( util:: EXIT_INVALID_ARGS ) ) ;
229243 }
244+
245+ Ok ( ( ) )
230246}
231247
0 commit comments