@@ -157,22 +157,122 @@ impl CmdRun {
157157 }
158158 }
159159
160+ fn cmdrun_error_message ( message : & str , command : & str ) -> String {
161+ format ! ( "**cmdrun error**: {} in 'cmdrun {}'" , message, command)
162+ }
163+
160164 // This method is public for unit tests
161165 pub fn run_cmdrun ( command : String , working_dir : & str , inline : bool ) -> Result < String > {
166+ // unfortunately, we need to manually parse the command string for cmdrun's
167+ // exit status checking flags.
168+ // Some experimentation using clap was done; however, splitting and then re-escaping
169+ // the shellwords was found to be a large barrier to using this other tool.
170+ let ( command, correct_exit_code) : ( String , Option < i32 > ) =
171+ if let Some ( first_word) = command. split_whitespace ( ) . next ( ) {
172+ if first_word. starts_with ( '-' ) {
173+ if first_word. starts_with ( "--" ) {
174+ // double-tick long form
175+ match first_word {
176+ "--strict" => (
177+ command
178+ . split_whitespace ( )
179+ . skip ( 1 )
180+ . collect :: < Vec < & str > > ( )
181+ . join ( " " ) ,
182+ Some ( 0 ) ,
183+ ) ,
184+ "--expect-return-code" => {
185+ if let Some ( second_word) = command. split_whitespace ( ) . nth ( 1 ) {
186+ match second_word. parse :: < i32 > ( ) {
187+ Ok ( return_code) => (
188+ command
189+ . split_whitespace ( )
190+ . skip ( 2 )
191+ . collect :: < Vec < & str > > ( )
192+ . join ( " " ) ,
193+ Some ( return_code) ,
194+ ) ,
195+ Err ( _) => {
196+ return Ok ( Self :: cmdrun_error_message (
197+ "No return code after '--expect-return-code'" ,
198+ & command,
199+ ) ) ;
200+ }
201+ }
202+ } else {
203+ // no second word after return code, print error
204+ return Ok ( Self :: cmdrun_error_message (
205+ "No return code after '--expect-return-code'" ,
206+ & command,
207+ ) ) ;
208+ }
209+ }
210+ some_other_word => {
211+ // unrecognized flag, print error
212+ return Ok ( Self :: cmdrun_error_message (
213+ & format ! ( "Unrecognized cmdrun flag {}" , some_other_word) ,
214+ & command,
215+ ) ) ;
216+ }
217+ }
218+ } else {
219+ // single-tick short form
220+ let ( _, exit_code) = first_word. rsplit_once ( '-' ) . unwrap_or ( ( "" , "0" ) ) ;
221+ match exit_code. parse :: < i32 > ( ) {
222+ Ok ( return_code) => (
223+ command
224+ . split_whitespace ( )
225+ . skip ( 1 )
226+ . collect :: < Vec < & str > > ( )
227+ . join ( " " ) ,
228+ Some ( return_code) ,
229+ ) ,
230+ Err ( _) => {
231+ return Ok ( Self :: cmdrun_error_message (
232+ & format ! (
233+ "Unable to interpret short-form exit code {} as a number" ,
234+ first_word
235+ ) ,
236+ & command,
237+ ) ) ;
238+ }
239+ }
240+ }
241+ } else {
242+ ( command, None )
243+ }
244+ } else {
245+ ( command, None )
246+ } ;
247+
162248 let output = Command :: new ( LAUNCH_SHELL_COMMAND )
163249 . args ( [ LAUNCH_SHELL_FLAG , & command] )
164250 . current_dir ( working_dir)
165251 . output ( )
166252 . with_context ( || "Fail to run shell" ) ?;
167253
168254 let stdout = Self :: format_whitespace ( String :: from_utf8_lossy ( & output. stdout ) , inline) ;
169-
170- // let stderr = String::from_utf8_lossy(&output.stderr).to_string();
171-
172- // eprintln!("command: {}", command);
173- // eprintln!("stdout: {:?}", stdout);
174- // eprintln!("stderr: {:?}", stderr);
175-
176- Ok ( stdout)
255+ match ( output. status . code ( ) , correct_exit_code) {
256+ ( None , _) => Ok ( Self :: cmdrun_error_message (
257+ "Command was ended before completing" ,
258+ & command,
259+ ) ) ,
260+ ( Some ( code) , Some ( correct_code) ) => {
261+ if code != correct_code {
262+ Ok ( format ! (
263+ "**cmdrun error**: '{command}' returned exit code {code} instead of {correct_code}.\n {0}\n {1}" ,
264+ String :: from_utf8_lossy( & output. stdout) ,
265+ String :: from_utf8_lossy( & output. stderr) ) )
266+ } else {
267+ Ok ( stdout)
268+ }
269+ }
270+ ( Some ( _code) , None ) => {
271+ // no correct code specified, program exited with some code _code
272+ // could put default check requiring code to be zero here but
273+ // that would break current behavior
274+ Ok ( stdout)
275+ }
276+ }
177277 }
178278}
0 commit comments