use metadata for command cache key spawning directly from command

This commit is contained in:
bit-aloo 2025-06-24 19:46:30 +05:30
parent 42875e1a3b
commit 08d7b29719
No known key found for this signature in database
2 changed files with 25 additions and 20 deletions

View file

@ -77,7 +77,6 @@ pub struct CommandCacheKey {
/// [allow_failure]: BootstrapCommand::allow_failure
/// [delay_failure]: BootstrapCommand::delay_failure
pub struct BootstrapCommand {
cache_key: CommandCacheKey,
command: Command,
pub failure_behavior: BehaviorOnFailure,
// Run the command even during dry run
@ -91,17 +90,9 @@ pub struct BootstrapCommand {
impl<'a> BootstrapCommand {
#[track_caller]
pub fn new<S: AsRef<OsStr>>(program: S) -> Self {
Self {
should_cache: true,
cache_key: CommandCacheKey {
program: program.as_ref().to_os_string(),
..CommandCacheKey::default()
},
..Command::new(program).into()
}
Self { should_cache: true, ..Command::new(program).into() }
}
pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Self {
self.cache_key.args.push(arg.as_ref().to_os_string());
self.command.arg(arg.as_ref());
self
}
@ -126,7 +117,6 @@ impl<'a> BootstrapCommand {
K: AsRef<OsStr>,
V: AsRef<OsStr>,
{
self.cache_key.envs.push((key.as_ref().to_os_string(), val.as_ref().to_os_string()));
self.command.env(key, val);
self
}
@ -145,7 +135,6 @@ impl<'a> BootstrapCommand {
}
pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Self {
self.cache_key.cwd = Some(dir.as_ref().to_path_buf());
self.command.current_dir(dir);
self
}
@ -244,8 +233,8 @@ impl<'a> BootstrapCommand {
}
}
pub fn cache_key(&self) -> CommandCacheKey {
self.cache_key.clone()
pub fn cache_key(&self) -> Option<CommandCacheKey> {
(!self.should_cache).then(|| self.into())
}
}
@ -260,9 +249,7 @@ impl From<Command> for BootstrapCommand {
#[track_caller]
fn from(command: Command) -> Self {
let program = command.get_program().to_owned();
Self {
cache_key: CommandCacheKey::default(),
should_cache: false,
command,
failure_behavior: BehaviorOnFailure::Exit,
@ -272,6 +259,21 @@ impl From<Command> for BootstrapCommand {
}
}
impl From<&BootstrapCommand> for CommandCacheKey {
fn from(value: &BootstrapCommand) -> Self {
let command = &value.command;
CommandCacheKey {
program: command.get_program().into(),
args: command.get_args().map(OsStr::to_os_string).collect(),
envs: command
.get_envs()
.filter_map(|(k, v_opt)| v_opt.map(|v| (k.to_owned(), v.to_owned())))
.collect(),
cwd: command.get_current_dir().map(Path::to_path_buf),
}
}
}
/// Represents the current status of `BootstrapCommand`.
#[derive(Clone, PartialEq)]
enum CommandStatus {

View file

@ -148,21 +148,24 @@ impl ExecutionContext {
) -> CommandOutput {
let cache_key = command.cache_key();
if command.should_cache()
&& let Some(cached_output) = self.command_cache.get(&cache_key)
if let Some(cached_output) = cache_key.as_ref().and_then(|key| self.command_cache.get(key))
{
command.mark_as_executed();
if self.dry_run() && !command.run_always {
return CommandOutput::default();
}
self.verbose(|| println!("Cache hit: {:?}", command));
return cached_output;
}
let output = self.start(command, stdout, stderr).wait_for_output(self);
if !self.dry_run() || command.run_always && command.should_cache() {
self.command_cache.insert(cache_key, output.clone());
if !self.dry_run() || command.run_always {
if let Some(cache_key) = cache_key {
self.command_cache.insert(cache_key, output.clone());
}
}
output