diff --git a/doc/03-cli.md b/doc/03-cli.md index bda06ddfcca9..892f7d042bf7 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -926,6 +926,10 @@ performance. Deletes all content from Composer's cache directories. +### Options + +* **--gc:** Only run garbage collection, not a full cache clear + ## licenses Lists the name, version and license of every package installed. Use diff --git a/src/Composer/Cache.php b/src/Composer/Cache.php index b7d74da9010a..ccf990fca1f6 100644 --- a/src/Composer/Cache.php +++ b/src/Composer/Cache.php @@ -342,6 +342,25 @@ public function gc(int $ttl, int $maxSize) return false; } + public function gcVcsCache(int $ttl): bool + { + if ($this->isEnabled()) { + $expire = new \DateTime(); + $expire->modify('-'.$ttl.' seconds'); + + $finder = Finder::create()->in($this->root)->directories()->depth(0)->date('until '.$expire->format('Y-m-d H:i:s')); + foreach ($finder as $file) { + $this->filesystem->removeDirectory($file->getPathname()); + } + + self::$cacheCollected = true; + + return true; + } + + return false; + } + /** * @param string $file * diff --git a/src/Composer/Command/ClearCacheCommand.php b/src/Composer/Command/ClearCacheCommand.php index e2ba384d38b3..4f3c2f4280dd 100644 --- a/src/Composer/Command/ClearCacheCommand.php +++ b/src/Composer/Command/ClearCacheCommand.php @@ -15,6 +15,7 @@ use Composer\Cache; use Composer\Factory; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** @@ -31,6 +32,9 @@ protected function configure(): void ->setName('clear-cache') ->setAliases(array('clearcache', 'cc')) ->setDescription('Clears composer\'s internal package cache.') + ->setDefinition(array( + new InputOption('gc', null, InputOption::VALUE_NONE, 'Only run garbage collection, not a full cache clear'), + )) ->setHelp( <<clear-cache deletes all cached packages from composer's @@ -55,6 +59,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int ); foreach ($cachePaths as $key => $cachePath) { + // only individual dirs get garbage collected + if ($key === 'cache-dir' && $input->getOption('gc')) { + continue; + } + $cachePath = realpath($cachePath); if (!$cachePath) { $io->writeError("Cache directory does not exist ($key): $cachePath"); @@ -69,11 +78,26 @@ protected function execute(InputInterface $input, OutputInterface $output): int continue; } - $io->writeError("Clearing cache ($key): $cachePath"); - $cache->clear(); + if ($input->getOption('gc')) { + $io->writeError("Garbage-collecting cache ($key): $cachePath"); + if ($key === 'cache-files-dir') { + $cache->gc($config->get('cache-files-ttl'), $config->get('cache-files-maxsize')); + } elseif ($key === 'cache-repo-dir') { + $cache->gc($config->get('cache-ttl'), 1024*1024*1024 /* 1GB, this should almost never clear anything that is not outdated */); + } elseif ($key === 'cache-vcs-dir') { + $cache->gcVcsCache($config->get('cache-ttl')); + } + } else { + $io->writeError("Clearing cache ($key): $cachePath"); + $cache->clear(); + } } - $io->writeError('All caches cleared.'); + if ($input->getOption('gc')) { + $io->writeError('All caches garbage-collected.'); + } else { + $io->writeError('All caches cleared.'); + } return 0; }