Skip to content

Commit 0933eba

Browse files
committed
feat: add dry-run option to copy-from-vendor command for previews
1 parent e057e78 commit 0933eba

2 files changed

Lines changed: 38 additions & 14 deletions

File tree

.github/workflows/functional-tests.yml

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -162,18 +162,11 @@ jobs:
162162
echo "Test help command:"
163163
bin/magento mageforge:theme:copy-from-vendor --help
164164
165-
echo "Test with dry-run (no actual copying):"
166-
bin/magento mageforge:theme:copy-from-vendor Magento/blank hyva-themes/magento2-default-theme::src/etc/view.xml --dry-run || echo "Expected: may fail if file doesn't exist"
167-
168-
echo "Test aliases:"
169-
bin/magento theme:copy --help
170-
171-
- name: Test Inspector Status
172-
working-directory: magento2
173-
run: |
174-
echo "=== Inspector Tests ==="
175-
bin/magento mageforge:theme:inspector status
176-
165+
echo "Test with dry-run (preview only, no actual copying):"
166+
# Use a file that actually exists in vendor (composer.json from any installed package)
167+
bin/magento mageforge:theme:copy-from-vendor vendor/composer/composer/composer.json Magento/blank --dry-run
168+
169+
echo "Test alias:"
177170
- name: Test Inspector Functionality
178171
working-directory: magento2
179172
run: |

src/Console/Command/Theme/CopyFromVendorCommand.php

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use OpenForgeProject\MageForge\Service\VendorFileMapper;
1616
use Symfony\Component\Console\Input\InputArgument;
1717
use Symfony\Component\Console\Input\InputInterface;
18+
use Symfony\Component\Console\Input\InputOption;
1819
use Symfony\Component\Console\Output\OutputInterface;
1920

2021
use function Laravel\Prompts\search;
@@ -34,15 +35,17 @@ protected function configure(): void
3435
{
3536
$this->setName('mageforge:theme:copy-from-vendor')
3637
->setDescription('Copy a file from vendor/ to a specific theme with correct path resolution')
37-
->setAliases(['m:t:cfv'])
38+
->setAliases(['theme:copy'])
3839
->addArgument('file', InputArgument::REQUIRED, 'Path to the source file (vendor/...)')
39-
->addArgument('theme', InputArgument::OPTIONAL, 'Target theme code (e.g. Magento/luma)');
40+
->addArgument('theme', InputArgument::OPTIONAL, 'Target theme code (e.g. Magento/luma)')
41+
->addOption('dry-run', null, InputOption::VALUE_NONE, 'Preview the copy operation without performing it');
4042
}
4143

4244
protected function executeCommand(InputInterface $input, OutputInterface $output): int
4345
{
4446
try {
4547
$sourceFileArg = $input->getArgument('file');
48+
$isDryRun = $input->getOption('dry-run');
4649
$absoluteSourcePath = $this->getAbsoluteSourcePath($sourceFileArg);
4750

4851
// Update sourceFileArg if it was normalized to relative path
@@ -57,6 +60,11 @@ protected function executeCommand(InputInterface $input, OutputInterface $output
5760
$destinationPath = $this->vendorFileMapper->mapToThemePath($sourceFile, $themePath);
5861
$absoluteDestPath = $this->getAbsoluteDestPath($destinationPath, $rootPath);
5962

63+
if ($isDryRun) {
64+
$this->showDryRunPreview($sourceFile, $absoluteDestPath, $rootPath);
65+
return Cli::RETURN_SUCCESS;
66+
}
67+
6068
if (!$this->confirmCopy($sourceFile, $absoluteDestPath, $rootPath)) {
6169
return Cli::RETURN_SUCCESS;
6270
}
@@ -175,6 +183,29 @@ private function performCopy(string $absoluteSourcePath, string $absoluteDestPat
175183
copy($absoluteSourcePath, $absoluteDestPath);
176184
}
177185

186+
private function showDryRunPreview(string $sourceFile, string $absoluteDestPath, string $rootPath): void
187+
{
188+
$destinationDisplay = str_starts_with($absoluteDestPath, $rootPath . '/')
189+
? substr($absoluteDestPath, strlen($rootPath) + 1)
190+
: $absoluteDestPath;
191+
192+
$this->io->section('Dry Run - Copy Preview');
193+
$this->io->text([
194+
"Source: <info>$sourceFile</info>",
195+
"Target: <info>$destinationDisplay</info>",
196+
"Absolute Target: <comment>$absoluteDestPath</comment>"
197+
]);
198+
$this->io->newLine();
199+
200+
if (file_exists($absoluteDestPath)) {
201+
$this->io->warning("File already exists at destination and would be overwritten!");
202+
} else {
203+
$this->io->info("File would be created at destination.");
204+
}
205+
206+
$this->io->note("No files were modified (dry-run mode).");
207+
}
208+
178209
private function fixPromptEnvironment(): void
179210
{
180211
if (getenv('DDEV_PROJECT')) {

0 commit comments

Comments
 (0)