1
1
use crate :: Build ;
2
+ use build_helper:: drop_bomb:: DropBomb ;
2
3
use std:: ffi:: OsStr ;
3
4
use std:: path:: Path ;
4
5
use std:: process:: { Command , CommandArgs , CommandEnvs , ExitStatus , Output , Stdio } ;
@@ -61,9 +62,13 @@ pub struct BootstrapCommand {
61
62
pub stderr : OutputMode ,
62
63
// Run the command even during dry run
63
64
pub run_always : bool ,
65
+ // This field makes sure that each command is executed (or disarmed) before it is dropped,
66
+ // to avoid forgetting to execute a command.
67
+ drop_bomb : DropBomb ,
64
68
}
65
69
66
70
impl BootstrapCommand {
71
+ #[ track_caller]
67
72
pub fn new < S : AsRef < OsStr > > ( program : S ) -> Self {
68
73
Command :: new ( program) . into ( )
69
74
}
@@ -149,18 +154,30 @@ impl BootstrapCommand {
149
154
/// Provides access to the stdlib Command inside.
150
155
/// All usages of this function should be eventually removed from bootstrap.
151
156
pub fn as_command_mut ( & mut self ) -> & mut Command {
157
+ // We don't know what will happen with the returned command, so we need to mark this
158
+ // command as executed proactively.
159
+ self . mark_as_executed ( ) ;
152
160
& mut self . command
153
161
}
162
+
163
+ /// Mark the command as being executd, disarming the drop bomb.
164
+ /// If this method is not called before the command is dropped, its drop will panic.
165
+ pub fn mark_as_executed ( & mut self ) {
166
+ self . drop_bomb . defuse ( ) ;
167
+ }
154
168
}
155
169
156
170
impl From < Command > for BootstrapCommand {
171
+ #[ track_caller]
157
172
fn from ( command : Command ) -> Self {
173
+ let program = command. get_program ( ) . to_owned ( ) ;
158
174
Self {
159
175
command,
160
176
failure_behavior : BehaviorOnFailure :: Exit ,
161
177
stdout : OutputMode :: Print ,
162
178
stderr : OutputMode :: Print ,
163
179
run_always : false ,
180
+ drop_bomb : DropBomb :: arm ( program) ,
164
181
}
165
182
}
166
183
}
@@ -175,6 +192,7 @@ enum CommandStatus {
175
192
176
193
/// Create a new BootstrapCommand. This is a helper function to make command creation
177
194
/// shorter than `BootstrapCommand::new`.
195
+ #[ track_caller]
178
196
#[ must_use]
179
197
pub fn command < S : AsRef < OsStr > > ( program : S ) -> BootstrapCommand {
180
198
BootstrapCommand :: new ( program)
0 commit comments