@@ -5,6 +5,7 @@ use std::path::Path;
55use std:: time:: Duration ;
66
77use bytesize:: ByteSize ;
8+ use chrono:: TimeDelta ;
89use humantime:: format_duration;
910use indicatif:: { ProgressBar , ProgressStyle } ;
1011use rustix:: io:: ioctl_fionread;
@@ -172,26 +173,22 @@ impl CommandContext for Cli {
172173
173174 // Job management
174175
175- fn job_started ( & mut self , job : & SignedJob ) -> Result < ( ) , CommandError > {
176+ fn job_started ( & mut self , job : & SignedJob ) {
176177 if let Some ( session) = self . session . as_mut ( ) {
177178 session. job_started ( job. to_owned ( ) ) ;
178- Ok ( ( ) )
179- } else {
180- Err ( CommandError :: MissingSession )
181179 }
182180 }
183181
184- fn job_stopped ( & mut self , job_id : & JobId ) -> Result < ( ) , CommandError > {
182+ fn job_stopped ( & mut self , job_id : & JobId ) {
185183 match self . get_output_format ( ) {
186184 OutputFormat :: Json => println ! ( "{}" , json!( job_id) ) ,
187185 OutputFormat :: Text => println ! ( "✅ Stopped job `{job_id}`" ) ,
188186 }
189- Ok ( ( ) )
190187 }
191188
192- fn job_error ( & mut self , error : CommandError ) -> Result < ( ) , CommandError > {
189+ fn job_error ( & mut self , error : CommandError ) -> CommandError {
193190 eprintln ! ( "{error}" ) ;
194- Ok ( ( ) )
191+ error
195192 }
196193
197194 fn job_output (
@@ -200,30 +197,29 @@ impl CommandContext for Cli {
200197 stream : JobOutputStream ,
201198 output : & [ u8 ] ,
202199 binary : bool ,
203- ) -> Result < ( ) , CommandError > {
200+ ) {
204201 match self . get_output_format ( ) {
205202 OutputFormat :: Json if binary => println ! ( "{}" , json!( output) ) ,
206- OutputFormat :: Json => println ! ( "{}" , json!( String :: from_utf8 ( output. to_vec ( ) ) ? ) ) ,
203+ OutputFormat :: Json => println ! ( "{}" , json!( String :: from_utf8_lossy ( output) ) ) ,
207204 OutputFormat :: Text if binary => {
208- stdout ( )
209- . write ( output )
210- . map_err ( |error| CommandError :: io ( "stdout" , error ) ) ? ;
205+ if let Err ( err ) = stdout ( ) . write_all ( output ) {
206+ eprintln ! ( "{err}" ) ;
207+ }
211208 }
212209 OutputFormat :: Text if output. is_empty ( ) => ( ) ,
213210 OutputFormat :: Text => {
214211 match stream {
215212 JobOutputStream :: Stdout => println ! ( "✅ Job stdout:" ) ,
216213 JobOutputStream :: Stderr => println ! ( "✅ Job stderr:" ) ,
217214 } ;
218- let output = String :: from_utf8 ( output. to_vec ( ) ) ? ;
215+ let output = String :: from_utf8_lossy ( output) ;
219216 if output. ends_with ( '\n' ) {
220217 print ! ( "{output}" ) ;
221218 } else {
222219 println ! ( "{output}" ) ;
223220 }
224221 }
225222 }
226- Ok ( ( ) )
227223 }
228224
229225 fn job_output_started (
@@ -232,7 +228,7 @@ impl CommandContext for Cli {
232228 stream : JobOutputStream ,
233229 stage : & str ,
234230 total_length : u64 ,
235- ) -> Result < ( ) , CommandError > {
231+ ) {
236232 if matches ! ( self . get_output_format( ) , OutputFormat :: Text ) && self . progress . is_none ( ) {
237233 let bar = ProgressBar :: new ( total_length) ;
238234 bar. set_prefix ( format ! ( "{stage} {stream}" ) ) ;
@@ -248,27 +244,20 @@ impl CommandContext for Cli {
248244 ) ;
249245 self . progress = Some ( bar) ;
250246 }
251- Ok ( ( ) )
252247 }
253248
254- fn job_output_update (
255- & mut self ,
256- _id : & JobId ,
257- _stream : JobOutputStream ,
258- length : u64 ,
259- ) -> Result < ( ) , CommandError > {
249+ fn job_output_update ( & mut self , _id : & JobId , _stream : JobOutputStream , length : u64 ) {
260250 if let Some ( progress) = & mut self . progress {
261251 progress. inc ( length) ;
262252 }
263- Ok ( ( ) )
264253 }
265254
266255 fn job_output_finished (
267256 & mut self ,
268257 _job_id : & JobId ,
269258 stream : JobOutputStream ,
270259 stage : Option < & str > ,
271- ) -> Result < ( ) , CommandError > {
260+ ) {
272261 if let Some ( progress) = self . progress . take ( ) {
273262 progress. finish_and_clear ( ) ;
274263 if let Some ( stage) = stage {
@@ -282,14 +271,9 @@ impl CommandContext for Cli {
282271 ) ;
283272 }
284273 }
285- Ok ( ( ) )
286274 }
287275
288- fn job_polling_started (
289- & mut self ,
290- job_id : & JobId ,
291- elapsed : Duration ,
292- ) -> Result < ( ) , CommandError > {
276+ fn job_polling_started ( & mut self , job_id : & JobId , elapsed : Duration ) {
293277 if matches ! ( self . get_output_format( ) , OutputFormat :: Text ) && self . progress . is_none ( ) {
294278 let bar = ProgressBar :: new_spinner ( ) ;
295279 bar. set_elapsed ( elapsed) ;
@@ -305,14 +289,9 @@ impl CommandContext for Cli {
305289 ) ;
306290 self . progress = Some ( bar) ;
307291 }
308- Ok ( ( ) )
309292 }
310293
311- fn job_polling_update (
312- & mut self ,
313- _job_id : & JobId ,
314- status : & JobStatus ,
315- ) -> Result < ( ) , CommandError > {
294+ fn job_polling_update ( & mut self , _job_id : & JobId , status : & JobStatus ) {
316295 if let Some ( progress) = & mut self . progress {
317296 if let JobStatus :: Started {
318297 stdout_len,
@@ -331,33 +310,29 @@ impl CommandContext for Cli {
331310 }
332311 progress. tick ( ) ;
333312 }
334- Ok ( ( ) )
335313 }
336314
337- fn job_polling_finished ( & mut self , _job_id : & JobId ) -> Result < ( ) , CommandError > {
315+ fn job_polling_finished ( & mut self , _job_id : & JobId ) {
338316 if let Some ( progress) = self . progress . take ( ) {
339317 progress. finish_and_clear ( ) ;
340318 }
341- Ok ( ( ) )
342319 }
343320
344- fn job_session_connected ( & mut self , job_id : & JobId ) -> Result < ( ) , CommandError > {
321+ fn job_session_connected ( & mut self , job_id : & JobId ) {
345322 match self . get_output_format ( ) {
346323 OutputFormat :: Json => println ! ( "{}" , json!( { "connected" : job_id} ) ) ,
347324 OutputFormat :: Text => println ! ( "✅ Connected to interactive job `{job_id}`" ) ,
348325 }
349- Ok ( ( ) )
350326 }
351327
352- fn job_session_disconnected ( & mut self , job_id : & JobId ) -> Result < ( ) , CommandError > {
328+ fn job_session_disconnected ( & mut self , job_id : & JobId ) {
353329 match self . get_output_format ( ) {
354330 OutputFormat :: Json => println ! ( "{}" , json!( { "disconnected" : job_id} ) ) ,
355331 OutputFormat :: Text => println ! ( "\r ✅ Disconnected interactive job `{job_id}`" ) ,
356332 }
357- Ok ( ( ) )
358333 }
359334
360- fn job_signing_started ( & mut self , job_id : & JobId ) -> Result < ( ) , CommandError > {
335+ fn job_signing_started ( & mut self , job_id : & JobId ) {
361336 if matches ! ( self . get_output_format( ) , OutputFormat :: Text ) && self . progress . is_none ( ) {
362337 let bar = ProgressBar :: new_spinner ( ) ;
363338 bar. set_prefix ( format ! ( "Waiting for signature on `{job_id}`" ) ) ;
@@ -373,37 +348,52 @@ impl CommandContext for Cli {
373348 bar. enable_steady_tick ( Duration :: from_millis ( 100 ) ) ;
374349 self . progress = Some ( bar) ;
375350 }
376- Ok ( ( ) )
377351 }
378352
379- fn job_signing_update ( & mut self , _job_id : & JobId ) -> Result < ( ) , CommandError > {
353+ fn job_signing_update ( & mut self , _job_id : & JobId ) {
380354 if let Some ( progress) = & mut self . progress {
381355 progress. tick ( ) ;
382356 }
383- Ok ( ( ) )
384357 }
385358
386- fn job_signing_finished ( & mut self , job_id : & JobId ) -> Result < ( ) , CommandError > {
359+ fn job_signing_finished ( & mut self , job_id : & JobId ) {
387360 if let Some ( progress) = self . progress . take ( ) {
388361 progress. finish_and_clear ( ) ;
389362 }
390363 if matches ! ( self . get_output_format( ) , OutputFormat :: Text ) {
391364 println ! ( "✅ Signed request for job `{job_id}`" ) ;
392365 }
393- Ok ( ( ) )
394366 }
395367
396- fn job_signed ( & mut self , job : & SignedJob , show : bool ) -> Result < ( ) , CommandError > {
368+ fn job_signed ( & mut self , job : & SignedJob , show : bool ) {
397369 if show {
398370 match self . get_output_format ( ) {
399- OutputFormat :: Json => println ! ( "{}" , to_json_string( & job) ?) ,
400- OutputFormat :: Text => println ! ( "{}" , to_json_string_pretty( & job) ?) ,
371+ OutputFormat :: Json => println ! (
372+ "{}" ,
373+ to_json_string( & job) . expect( "job should be JSON-serializable" )
374+ ) ,
375+ OutputFormat :: Text => println ! (
376+ "{}" ,
377+ to_json_string_pretty( & job) . expect( "job should be JSON-serializable" )
378+ ) ,
401379 }
402380 }
403- Ok ( ( ) )
404381 }
405382
406- fn job_status ( & mut self , job_id : & JobId , status : & JobStatus ) -> Result < ( ) , CommandError > {
383+ fn job_status ( & mut self , job_id : & JobId , status : & JobStatus ) {
384+ fn format_elapsed_duration ( duration : Option < TimeDelta > ) -> String {
385+ match duration {
386+ None => String :: from ( "empty duration" ) ,
387+ Some ( duration) => {
388+ if let Ok ( duration) = duration. to_std ( ) {
389+ format_duration ( duration) . to_string ( )
390+ } else {
391+ String :: from ( "negative duration, times may be unreliable" )
392+ }
393+ }
394+ }
395+ }
396+
407397 match self . get_output_format ( ) {
408398 OutputFormat :: Json => println ! ( "{}" , json!( status) ) ,
409399 OutputFormat :: Text => match status {
@@ -444,7 +434,7 @@ impl CommandContext for Cli {
444434 stderr_hash,
445435 } => {
446436 let command = job. command ( ) ;
447- let duration = format_duration ( status. time_elapsed ( ) . unwrap ( ) . to_std ( ) ? ) ;
437+ let duration = format_elapsed_duration ( status. time_elapsed ( ) ) ;
448438 let stdout_len = byte_size ( * stdout_len) ;
449439 let stderr_len = byte_size ( * stderr_len) ;
450440 println ! (
@@ -473,7 +463,7 @@ impl CommandContext for Cli {
473463 stderr_hash,
474464 } => {
475465 let command = job. command ( ) ;
476- let duration = format_duration ( status. time_elapsed ( ) . unwrap ( ) . to_std ( ) ? ) ;
466+ let duration = format_elapsed_duration ( status. time_elapsed ( ) ) ;
477467 let stdout_len = byte_size ( * stdout_len) ;
478468 let stderr_len = byte_size ( * stderr_len) ;
479469 println ! (
@@ -491,7 +481,6 @@ impl CommandContext for Cli {
491481 }
492482 } ,
493483 }
494- Ok ( ( ) )
495484 }
496485
497486 fn read_signed_job ( & mut self ) -> Result < SignedJob , CommandError > {
0 commit comments