22// returning predefined outputs, to ease code testing.
33
44use std:: {
5- collections:: HashMap ,
6- future:: Future ,
7- io:: { self } ,
8- os:: unix:: process:: ExitStatusExt ,
9- pin:: Pin ,
10- process:: ExitStatus ,
11- rc:: Rc ,
5+ collections:: HashMap , future:: Future , io:: { self } , os:: unix:: process:: ExitStatusExt , pin:: Pin , process:: ExitStatus , rc:: Rc
126} ;
137
14- use crate :: distrobox:: Command ;
8+ use crate :: distrobox:: { Command , OutputTracker } ;
159use async_process:: { Command as AsyncCommand , Output } ;
1610use futures:: {
1711 io:: { AsyncRead , AsyncWrite , Cursor } ,
@@ -20,7 +14,100 @@ use futures::{
2014
2115use super :: wrap_flatpak_cmd;
2216
23- pub trait CommandRunner {
17+
18+ #[ derive( Debug , Clone ) ]
19+ pub enum CommandRunnerEvent {
20+ Spawned ( usize , Command ) ,
21+ /// Started command that will return the output
22+ Started ( usize , Command ) ,
23+ Output ( usize , Result < ( ) , ( ) > ) ,
24+ }
25+
26+ impl CommandRunnerEvent {
27+ pub fn event_id ( & self ) -> usize {
28+ match self {
29+ CommandRunnerEvent :: Spawned ( id, _) => * id,
30+ CommandRunnerEvent :: Started ( id, _) => * id,
31+ CommandRunnerEvent :: Output ( id, _) => * id,
32+ }
33+ }
34+ pub fn command ( & self ) -> Option < & Command > {
35+ match self {
36+ CommandRunnerEvent :: Spawned ( _, cmd) => Some ( cmd) ,
37+ CommandRunnerEvent :: Started ( _, cmd) => Some ( cmd) ,
38+ CommandRunnerEvent :: Output ( _, _) => None ,
39+ }
40+ }
41+ }
42+
43+ #[ derive( Clone ) ]
44+ pub struct CommandRunner {
45+ pub inner : Rc < dyn InnerCommandRunner > ,
46+ pub output_tracker : OutputTracker < CommandRunnerEvent > ,
47+ }
48+
49+ impl CommandRunner {
50+ pub fn new ( inner : Rc < dyn InnerCommandRunner > ) -> Self {
51+ CommandRunner {
52+ inner,
53+ output_tracker : OutputTracker :: new ( ) ,
54+ }
55+ }
56+ pub fn new_null ( ) -> Self {
57+ CommandRunner :: new ( Rc :: new ( NullCommandRunner :: default ( ) ) )
58+ }
59+ pub fn new_real ( ) -> Self {
60+ CommandRunner :: new ( Rc :: new ( RealCommandRunner { } ) )
61+ }
62+ pub fn new_flatpak_real ( ) -> Self {
63+ CommandRunner :: new ( Rc :: new ( FlatpakCommandRunner :: new (
64+ Rc :: new ( RealCommandRunner { } ) ,
65+ ) ) )
66+ }
67+
68+ pub fn output_tracker ( & self ) -> OutputTracker < CommandRunnerEvent > {
69+ self . output_tracker . enable ( ) ;
70+ self . output_tracker . clone ( )
71+ }
72+
73+ fn event_id ( & self ) -> usize {
74+ self . output_tracker . len ( )
75+ }
76+
77+ pub fn spawn ( & self , command : Command ) -> io:: Result < Box < dyn Child + Send > > {
78+ self . output_tracker . push ( CommandRunnerEvent :: Spawned ( self . event_id ( ) , command. clone ( ) ) ) ;
79+ self . inner . spawn ( command)
80+ }
81+
82+ pub fn output (
83+ & self ,
84+ command : Command ,
85+ ) -> Pin < Box < dyn Future < Output = io:: Result < std:: process:: Output > > > > {
86+ let event_id = self . event_id ( ) ;
87+ self . output_tracker . push ( CommandRunnerEvent :: Started ( event_id, command. clone ( ) ) ) ;
88+ let fut = self . inner . output ( command) ;
89+ let this = self . clone ( ) ;
90+ fut. map ( move |result| {
91+ let res_summary = match & result {
92+ Ok ( _output) => {
93+ Ok ( ( ) )
94+ }
95+ Err ( _e) => Err ( ( ) ) ,
96+ } ;
97+ this. output_tracker . push ( CommandRunnerEvent :: Output ( event_id, res_summary) ) ;
98+ result
99+ } )
100+ . boxed_local ( )
101+ }
102+ }
103+
104+ impl Default for CommandRunner {
105+ fn default ( ) -> Self {
106+ CommandRunner :: new_null ( )
107+ }
108+ }
109+
110+ pub trait InnerCommandRunner {
24111 fn spawn ( & self , command : Command ) -> io:: Result < Box < dyn Child + Send > > ;
25112 fn output (
26113 & self ,
@@ -31,7 +118,7 @@ pub trait CommandRunner {
31118#[ derive( Clone , Debug ) ]
32119pub struct RealCommandRunner { }
33120
34- impl CommandRunner for RealCommandRunner {
121+ impl InnerCommandRunner for RealCommandRunner {
35122 fn spawn ( & self , command : Command ) -> io:: Result < Box < dyn Child + Send > > {
36123 let mut command: AsyncCommand = command. into ( ) ;
37124 Ok ( Box :: new ( command. spawn ( ) ?) )
@@ -47,15 +134,15 @@ impl CommandRunner for RealCommandRunner {
47134
48135#[ derive( Clone ) ]
49136pub struct FlatpakCommandRunner {
50- pub command_runner : Rc < dyn CommandRunner > ,
137+ pub command_runner : Rc < dyn InnerCommandRunner > ,
51138}
52139impl FlatpakCommandRunner {
53- pub fn new ( command_runner : Rc < dyn CommandRunner > ) -> Self {
140+ pub fn new ( command_runner : Rc < dyn InnerCommandRunner > ) -> Self {
54141 FlatpakCommandRunner { command_runner }
55142 }
56143}
57144
58- impl CommandRunner for FlatpakCommandRunner {
145+ impl InnerCommandRunner for FlatpakCommandRunner {
59146 fn spawn ( & self , command : Command ) -> io:: Result < Box < dyn Child + Send > > {
60147 self . command_runner . spawn ( wrap_flatpak_cmd ( command) )
61148 }
@@ -98,11 +185,12 @@ impl NullCommandRunnerBuilder {
98185 self . fallback_exit_status = status;
99186 self
100187 }
101- pub fn build ( & self ) -> NullCommandRunner {
102- NullCommandRunner {
188+ pub fn build ( & self ) -> CommandRunner {
189+ let inner = Rc :: new ( NullCommandRunner {
103190 responses : self . responses . clone ( ) ,
104191 fallback_exit_status : self . fallback_exit_status ,
105- }
192+ } ) ;
193+ CommandRunner :: new ( inner)
106194 }
107195}
108196
@@ -124,7 +212,7 @@ impl NullCommandRunner {
124212 }
125213}
126214
127- impl CommandRunner for NullCommandRunner {
215+ impl InnerCommandRunner for NullCommandRunner {
128216 fn spawn ( & self , command : Command ) -> io:: Result < Box < dyn Child + Send > > {
129217 let key = Self :: key_for_cmd ( & command) ;
130218 let response = self
0 commit comments