2026-02-06 09:59:29 +08:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
|
|
namespace StaticPHP\Command;
|
|
|
|
|
|
2026-06-16 15:17:51 +08:00
|
|
|
use StaticPHP\Exception\SPCInternalException;
|
2026-04-08 11:08:05 +08:00
|
|
|
use StaticPHP\Runtime\Shell\Shell;
|
2026-02-06 09:59:29 +08:00
|
|
|
use StaticPHP\Util\FileSystem;
|
|
|
|
|
use StaticPHP\Util\InteractiveTerm;
|
|
|
|
|
use Symfony\Component\Console\Attribute\AsCommand;
|
2026-06-16 15:17:51 +08:00
|
|
|
use Symfony\Component\Console\Helper\QuestionHelper;
|
2026-02-06 09:59:29 +08:00
|
|
|
use Symfony\Component\Console\Input\InputOption;
|
2026-06-16 15:11:48 +08:00
|
|
|
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
2026-02-06 09:59:29 +08:00
|
|
|
|
|
|
|
|
#[AsCommand('reset')]
|
|
|
|
|
class ResetCommand extends BaseCommand
|
|
|
|
|
{
|
|
|
|
|
public function configure(): void
|
|
|
|
|
{
|
|
|
|
|
$this->setDescription('Reset and clean build directories')
|
|
|
|
|
->addOption('with-pkgroot', null, InputOption::VALUE_NONE, 'Also remove pkgroot directory')
|
|
|
|
|
->addOption('with-download', null, InputOption::VALUE_NONE, 'Also remove downloads directory')
|
|
|
|
|
->addOption('yes', 'y', InputOption::VALUE_NONE, 'Skip confirmation prompt');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function handle(): int
|
|
|
|
|
{
|
|
|
|
|
$dirs_to_remove = [
|
|
|
|
|
'buildroot' => BUILD_ROOT_PATH,
|
|
|
|
|
'source' => SOURCE_PATH,
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
if ($this->input->getOption('with-pkgroot')) {
|
|
|
|
|
$dirs_to_remove['pkgroot'] = PKG_ROOT_PATH;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($this->input->getOption('with-download')) {
|
|
|
|
|
$dirs_to_remove['downloads'] = DOWNLOAD_PATH;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Show warning
|
|
|
|
|
InteractiveTerm::notice('You are doing some operations that are not recoverable:');
|
|
|
|
|
foreach ($dirs_to_remove as $name => $path) {
|
|
|
|
|
InteractiveTerm::notice("- Removing directory: {$path}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Confirm with user unless --yes is specified
|
|
|
|
|
if (!$this->input->getOption('yes')) {
|
2026-06-16 15:11:48 +08:00
|
|
|
$helper = $this->getHelper('question');
|
2026-06-16 15:17:51 +08:00
|
|
|
if (!$helper instanceof QuestionHelper) {
|
|
|
|
|
throw new SPCInternalException('Question helper not provided');
|
|
|
|
|
}
|
2026-06-16 15:11:48 +08:00
|
|
|
if (!$helper->ask($this->input, $this->output, new ConfirmationQuestion('Are you sure you want to continue? [y/N] ', false))) {
|
2026-02-06 09:59:29 +08:00
|
|
|
InteractiveTerm::error(message: 'Reset operation cancelled.');
|
|
|
|
|
return static::SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Remove directories
|
|
|
|
|
foreach ($dirs_to_remove as $name => $path) {
|
|
|
|
|
if (!is_dir($path)) {
|
|
|
|
|
InteractiveTerm::notice("Directory {$name} does not exist, skipping: {$path}");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
InteractiveTerm::indicateProgress("Removing: {$path}");
|
|
|
|
|
|
|
|
|
|
if (PHP_OS_FAMILY === 'Windows') {
|
2026-04-12 01:11:59 +08:00
|
|
|
Shell::passthruCallback(fn () => InteractiveTerm::advance());
|
2026-02-06 09:59:29 +08:00
|
|
|
// Force delete on Windows to handle git directories
|
|
|
|
|
$this->removeDirectoryWindows($path);
|
2026-04-12 01:11:59 +08:00
|
|
|
Shell::passthruCallback(null);
|
2026-02-06 09:59:29 +08:00
|
|
|
} else {
|
|
|
|
|
// Use FileSystem::removeDir for Unix systems
|
|
|
|
|
FileSystem::removeDir($path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
InteractiveTerm::finish("Removed: {$path}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
InteractiveTerm::notice('Reset completed.');
|
|
|
|
|
return static::SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Force remove directory on Windows
|
|
|
|
|
* Uses PowerShell to handle git directories and other problematic files
|
|
|
|
|
*
|
|
|
|
|
* @param string $path Directory path to remove
|
|
|
|
|
*/
|
|
|
|
|
private function removeDirectoryWindows(string $path): void
|
|
|
|
|
{
|
|
|
|
|
$path = FileSystem::convertPath($path);
|
|
|
|
|
|
|
|
|
|
// Try using PowerShell for force deletion
|
|
|
|
|
$escaped_path = escapeshellarg($path);
|
|
|
|
|
|
|
|
|
|
// Use PowerShell Remove-Item with -Force and -Recurse
|
2026-04-08 11:08:05 +08:00
|
|
|
$result = cmd()->execWithResult("powershell -Command \"Remove-Item -Path {$escaped_path} -Recurse -Force -ErrorAction SilentlyContinue\"", false);
|
|
|
|
|
$ret_code = $result[0];
|
2026-02-06 09:59:29 +08:00
|
|
|
// If PowerShell fails or directory still exists, try cmd rmdir
|
|
|
|
|
if ($ret_code !== 0 || is_dir($path)) {
|
|
|
|
|
$cmd_command = "rmdir /s /q {$escaped_path}";
|
2026-04-08 11:08:05 +08:00
|
|
|
$result = cmd()->execWithResult($cmd_command, false);
|
|
|
|
|
if ($result[0] === 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2026-02-06 09:59:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Final fallback: use FileSystem::removeDir
|
|
|
|
|
if (is_dir($path)) {
|
|
|
|
|
FileSystem::removeDir($path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|