5
5
#![ allow( warnings) ]
6
6
7
7
use std:: collections:: HashMap ;
8
- use std:: ffi:: OsStr ;
8
+ use std:: ffi:: { OsStr , OsString } ;
9
9
use std:: fmt:: { Debug , Formatter } ;
10
10
use std:: hash:: { Hash , Hasher } ;
11
11
use std:: path:: Path ;
@@ -55,6 +55,14 @@ impl OutputMode {
55
55
}
56
56
}
57
57
58
+ #[ derive( Clone , Debug , PartialEq , Eq , Hash , Default ) ]
59
+ pub struct CommandCacheKey {
60
+ program : OsString ,
61
+ args : Vec < OsString > ,
62
+ envs : Vec < ( OsString , OsString ) > ,
63
+ cwd : Option < PathBuf > ,
64
+ }
65
+
58
66
/// Wrapper around `std::process::Command`.
59
67
///
60
68
/// By default, the command will exit bootstrap if it fails.
@@ -69,33 +77,39 @@ impl OutputMode {
69
77
/// [allow_failure]: BootstrapCommand::allow_failure
70
78
/// [delay_failure]: BootstrapCommand::delay_failure
71
79
pub struct BootstrapCommand {
72
- program : String ,
73
- args : Vec < String > ,
74
- envs : Vec < ( String , String ) > ,
75
- cwd : Option < PathBuf > ,
76
-
80
+ cache_key : CommandCacheKey ,
77
81
command : Command ,
78
82
pub failure_behavior : BehaviorOnFailure ,
79
83
// Run the command even during dry run
80
84
pub run_in_dry_run : bool ,
81
85
// This field makes sure that each command is executed (or disarmed) before it is dropped,
82
86
// to avoid forgetting to execute a command.
83
87
drop_bomb : DropBomb ,
88
+ should_cache : bool ,
84
89
}
85
90
86
91
impl < ' a > BootstrapCommand {
87
92
#[ track_caller]
88
93
pub fn new < S : AsRef < OsStr > > ( program : S ) -> Self {
89
- Command :: new ( program) . into ( )
94
+ Self {
95
+ should_cache : true ,
96
+ cache_key : CommandCacheKey {
97
+ program : program. as_ref ( ) . to_os_string ( ) ,
98
+ ..CommandCacheKey :: default ( )
99
+ } ,
100
+ ..Command :: new ( program) . into ( )
101
+ }
90
102
}
91
-
92
103
pub fn arg < S : AsRef < OsStr > > ( & mut self , arg : S ) -> & mut Self {
93
- let arg_str = arg. as_ref ( ) . to_string_lossy ( ) . into_owned ( ) ;
94
- self . args . push ( arg_str. clone ( ) ) ;
104
+ self . cache_key . args . push ( arg. as_ref ( ) . to_os_string ( ) ) ;
95
105
self . command . arg ( arg. as_ref ( ) ) ;
96
106
self
97
107
}
98
108
109
+ pub fn should_cache ( & self ) -> bool {
110
+ self . should_cache
111
+ }
112
+
99
113
pub fn args < I , S > ( & mut self , args : I ) -> & mut Self
100
114
where
101
115
I : IntoIterator < Item = S > ,
@@ -112,9 +126,7 @@ impl<'a> BootstrapCommand {
112
126
K : AsRef < OsStr > ,
113
127
V : AsRef < OsStr > ,
114
128
{
115
- let key_str = key. as_ref ( ) . to_string_lossy ( ) . into_owned ( ) ;
116
- let val_str = val. as_ref ( ) . to_string_lossy ( ) . into_owned ( ) ;
117
- self . envs . push ( ( key_str. clone ( ) , val_str. clone ( ) ) ) ;
129
+ self . cache_key . envs . push ( ( key. as_ref ( ) . to_os_string ( ) , val. as_ref ( ) . to_os_string ( ) ) ) ;
118
130
self . command . env ( key, val) ;
119
131
self
120
132
}
@@ -133,7 +145,7 @@ impl<'a> BootstrapCommand {
133
145
}
134
146
135
147
pub fn current_dir < P : AsRef < Path > > ( & mut self , dir : P ) -> & mut Self {
136
- self . cwd = Some ( dir. as_ref ( ) . to_path_buf ( ) ) ;
148
+ self . cache_key . cwd = Some ( dir. as_ref ( ) . to_path_buf ( ) ) ;
137
149
self . command . current_dir ( dir) ;
138
150
self
139
151
}
@@ -205,6 +217,7 @@ impl<'a> BootstrapCommand {
205
217
// We don't know what will happen with the returned command, so we need to mark this
206
218
// command as executed proactively.
207
219
self . mark_as_executed ( ) ;
220
+ self . should_cache = false ;
208
221
& mut self . command
209
222
}
210
223
@@ -230,6 +243,10 @@ impl<'a> BootstrapCommand {
230
243
self . env ( "TERM" , "xterm" ) . args ( [ "--color" , "always" ] ) ;
231
244
}
232
245
}
246
+
247
+ pub fn cache_key ( & self ) -> CommandCacheKey {
248
+ self . cache_key . clone ( )
249
+ }
233
250
}
234
251
235
252
impl Debug for BootstrapCommand {
@@ -245,10 +262,8 @@ impl From<Command> for BootstrapCommand {
245
262
let program = command. get_program ( ) . to_owned ( ) ;
246
263
247
264
Self {
248
- program : program. clone ( ) . into_string ( ) . unwrap ( ) ,
249
- args : Vec :: new ( ) ,
250
- envs : Vec :: new ( ) ,
251
- cwd : None ,
265
+ cache_key : CommandCacheKey :: default ( ) ,
266
+ should_cache : false ,
252
267
command,
253
268
failure_behavior : BehaviorOnFailure :: Exit ,
254
269
run_in_dry_run : false ,
0 commit comments