diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-06-20 19:39:32 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-06-20 19:40:17 +0900 |
| commit | a5ebca8f7001351aa26443a4a02a71c96190eccb (patch) | |
| tree | e1b701456243925e5c898d9ca5073292a8b23905 /crates/shirabe/src/command/clear_cache_command.rs | |
| parent | 5488b18fd0387d655192350011f331dfda03ebba (diff) | |
| download | php-shirabe-a5ebca8f7001351aa26443a4a02a71c96190eccb.tar.gz php-shirabe-a5ebca8f7001351aa26443a4a02a71c96190eccb.tar.zst php-shirabe-a5ebca8f7001351aa26443a4a02a71c96190eccb.zip | |
feat(clear-cache): implement ClearCacheCommand::execute
Port the command body: resolve Config from tryComposer()'s composer or
Factory::createConfig(), then clear or garbage-collect each cache-* path
via Cache. try_composer is already implemented, so the prior blocker
comment is stale.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/src/command/clear_cache_command.rs')
| -rw-r--r-- | crates/shirabe/src/command/clear_cache_command.rs | 133 |
1 files changed, 115 insertions, 18 deletions
diff --git a/crates/shirabe/src/command/clear_cache_command.rs b/crates/shirabe/src/command/clear_cache_command.rs index a414c11..ece594d 100644 --- a/crates/shirabe/src/command/clear_cache_command.rs +++ b/crates/shirabe/src/command/clear_cache_command.rs @@ -1,25 +1,22 @@ //! ref: composer/src/Composer/Command/ClearCacheCommand.php use anyhow::Result; -use indexmap::IndexMap; use shirabe_external_packages::symfony::console::command::command::Command; use shirabe_external_packages::symfony::console::input::InputInterface; use shirabe_external_packages::symfony::console::output::OutputInterface; -use shirabe_php_shim::PhpMixed; +use shirabe_php_shim::realpath; use std::cell::RefCell; use std::rc::Rc; -use crate::advisory::AuditConfig; +use crate::cache::Cache; use crate::command::BaseCommand; use crate::command::BaseCommandData; use crate::command::base_command::base_command_initialize; -use crate::composer; -use crate::composer::PartialComposerHandle; use crate::config::Config; use crate::console::input::InputOption; use crate::factory::Factory; -use crate::filter::platform_requirement_filter::PlatformRequirementFilterInterface; use crate::io::IOInterface; +use crate::io::IOInterfaceImmutable; #[derive(Debug)] pub struct ClearCacheCommand { @@ -68,20 +65,120 @@ impl Command for ClearCacheCommand { fn execute( &mut self, - _input: Rc<RefCell<dyn InputInterface>>, + input: Rc<RefCell<dyn InputInterface>>, _output: Rc<RefCell<dyn OutputInterface>>, ) -> anyhow::Result<i64> { - // PHP: $config = $this->tryComposer()?->getConfig() ?? Factory::createConfig(); then - // iterate the cache-* paths and clear/gc each via Cache. - // TODO(phase-c): two blockers. (1) The first statement calls self.try_composer(), which is - // a deferred todo!() (it needs get_application() -> the Symfony command registry). (2) The - // two config sources differ in ownership — composer.get_config() is Rc<RefCell<Config>> - // while Factory::create_config() returns an owned Config — so a shared Config model is - // needed before the per-path Cache logic can read both uniformly. - let _ = composer::VERSION; - let _: IndexMap<String, String> = IndexMap::new(); - let _ = Factory::create_config(None, None); - todo!("ClearCacheCommand::execute pending try_composer + Config sharing model") + let composer = self.try_composer(None, None); + // composer.getConfig() yields an Rc<RefCell<Config>>; Factory::createConfig() an owned + // Config. Keep whichever applies alive in a local and read both through a shared &Config. + let config_rc = composer.as_ref().map(|c| c.borrow_partial().get_config()); + let created_config = if config_rc.is_none() { + Some(Factory::create_config(None, None)?) + } else { + None + }; + let config_guard = config_rc.as_ref().map(|rc| rc.borrow()); + let config: &Config = match (config_guard.as_deref(), created_config.as_ref()) { + (Some(config), _) => config, + (None, Some(config)) => config, + (None, None) => unreachable!(), + }; + + let io = self.get_io(); + + let gc = input.borrow().get_option("gc")?.as_bool().unwrap_or(false); + + let cache_paths: [(&str, String); 4] = [ + ( + "cache-vcs-dir", + config + .get("cache-vcs-dir") + .as_string() + .unwrap_or("") + .to_string(), + ), + ( + "cache-repo-dir", + config + .get("cache-repo-dir") + .as_string() + .unwrap_or("") + .to_string(), + ), + ( + "cache-files-dir", + config + .get("cache-files-dir") + .as_string() + .unwrap_or("") + .to_string(), + ), + ( + "cache-dir", + config + .get("cache-dir") + .as_string() + .unwrap_or("") + .to_string(), + ), + ]; + + for (key, cache_path) in cache_paths { + // only individual dirs get garbage collected + if key == "cache-dir" && gc { + continue; + } + + let cache_path = match realpath(&cache_path) { + Some(path) => path, + None => { + io.write_error(&format!( + "<info>Cache directory does not exist ({key}): {cache_path}</info>" + )); + continue; + } + }; + let mut cache = Cache::new(io.clone(), &cache_path, None, None, false); + cache.set_read_only(config.get("cache-read-only").as_bool().unwrap_or(false)); + if !cache.is_enabled() { + io.write_error(&format!( + "<info>Cache is not enabled ({key}): {cache_path}</info>" + )); + continue; + } + + if gc { + io.write_error(&format!( + "<info>Garbage-collecting cache ({key}): {cache_path}</info>" + )); + if key == "cache-files-dir" { + cache.gc( + config.get("cache-files-ttl").as_int().unwrap_or(0), + config.get("cache-files-maxsize").as_int().unwrap_or(0), + ); + } else if key == "cache-repo-dir" { + cache.gc( + config.get("cache-ttl").as_int().unwrap_or(0), + 1024 * 1024 * 1024, // 1GB, this should almost never clear anything that is not outdated + ); + } else if key == "cache-vcs-dir" { + cache.gc_vcs_cache(config.get("cache-ttl").as_int().unwrap_or(0)); + } + } else { + io.write_error(&format!( + "<info>Clearing cache ({key}): {cache_path}</info>" + )); + cache.clear(); + } + } + + if gc { + io.write_error("<info>All caches garbage-collected.</info>"); + } else { + io.write_error("<info>All caches cleared.</info>"); + } + + Ok(0) } fn initialize( |
