Skip to content

Commit 4af9ef0

Browse files
committed
Adds a refresh command
1 parent ccbb2c8 commit 4af9ef0

7 files changed

Lines changed: 403 additions & 20 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
99

1010
### Added
1111
- New `Homebrew` formula and usage documentation. Closes [#45](https://github.com/raphaelstolt/lean-package-validator/issues/45).
12+
- New `refresh` command to update a present `.lpv` file with the latest preset glob patterns.
13+
Closes [#63](https://github.com/raphaelstolt/lean-package-validator/issues/63).
1214

1315
## [v5.3.3] - 2026-01-28
1416

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,24 @@ The `--preset` option allows choosing from a predefined set of glob pattern. Ava
234234

235235
The `--dry-run` option will show the content of the `.lpv` file that would be created.
236236

237+
#### Refresh command
238+
239+
The `refresh` command updates an existing `.lpv` file by adding missing preset patterns while keeping any manual
240+
modifications already present in the file.
241+
242+
``` bash
243+
lean-package-validator refresh [<directory>]
244+
```
245+
246+
The command expects a present `.lpv` file in the target directory and will fail if none existent.
247+
248+
The `--preset` option allows choosing from a predefined set of glob pattern. Available presets are `PHP`, `Python`, `Rust`,
249+
`JavaScript`, and `Go`. With `PHP` being the default.
250+
251+
The `--dry-run` option shows the refreshed `.lpv` content without writing any changes to disk.
252+
253+
Existing lines are __preserved__, so custom entries remain untouched while missing preset entries are appended.
254+
237255
#### Tree command
238256

239257
The `tree` command of the lean package validator allows you to inspect the __flat__ `source` and `dist package` structure

bin/lean-package-validator

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ if (false === $autoloaded) {
2626

2727
use Stolt\LeanPackage\Commands\CreateCommand;
2828
use Stolt\LeanPackage\Commands\InitCommand;
29+
use Stolt\LeanPackage\Commands\RefreshCommand;
2930
use Stolt\LeanPackage\Commands\TreeCommand;
3031
use Stolt\LeanPackage\Commands\UpdateCommand;
3132
use Stolt\LeanPackage\Commands\ValidateCommand;
@@ -46,6 +47,11 @@ $analyser = new Analyser($finder);
4647
$initCommand = new InitCommand(
4748
$analyser
4849
);
50+
51+
$refreshCommand = new RefreshCommand(
52+
$analyser
53+
);
54+
4955
$validateCommand = new ValidateCommand(
5056
$analyser,
5157
new Validator($archive),
@@ -57,6 +63,6 @@ $treeCommand = new TreeCommand(new Tree(new Archive(WORKING_DIRECTORY,'tree-temp
5763

5864
$application = new Application('Lean package validator', VERSION);
5965
$application->addCommands(
60-
[$initCommand, $validateCommand, $createCommand, $updateCommand, $treeCommand]
66+
[$initCommand, $refreshCommand, $validateCommand, $createCommand, $updateCommand, $treeCommand]
6167
);
6268
$application->run();

src/Commands/InitCommand.php

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Stolt\LeanPackage\Analyser;
88
use Stolt\LeanPackage\Exceptions\PresetNotAvailable;
9+
use Stolt\LeanPackage\Presets\CommonPreset;
910
use Stolt\LeanPackage\Presets\Finder;
1011
use Symfony\Component\Console\Command\Command;
1112
use Symfony\Component\Console\Input\InputArgument;
@@ -53,7 +54,7 @@ protected function configure(): void
5354
. 'project/micro-package repository';
5455
$this->setDescription($description);
5556

56-
$availablePresets = $this->formatAvailablePresetDefinitionsForDescription(
57+
$availablePresets = (new CommonPreset())->formatAvailablePresetDefinitionsForDescription(
5758
$this->finder->getAvailablePresets()
5859
);
5960

@@ -83,24 +84,6 @@ protected function configure(): void
8384
));
8485
}
8586

86-
/**
87-
* @param array $presets
88-
* @return string
89-
*/
90-
private function formatAvailablePresetDefinitionsForDescription(array $presets): string
91-
{
92-
$presets = \array_map(function ($preset) {
93-
return '<comment>' . $preset . '</comment>';
94-
}, $presets);
95-
96-
if (\count($presets) > 2) {
97-
$lastPreset = \array_pop($presets);
98-
return \implode(', ', $presets) . ', and ' . $lastPreset;
99-
}
100-
101-
return $presets[0] . ' and ' . $presets[1];
102-
}
103-
10487
/**
10588
* Execute command.
10689
*

src/Commands/RefreshCommand.php

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Stolt\LeanPackage\Commands;
6+
7+
use Stolt\LeanPackage\Analyser;
8+
use Stolt\LeanPackage\Exceptions\PresetNotAvailable;
9+
use Stolt\LeanPackage\Presets\CommonPreset;
10+
use Stolt\LeanPackage\Presets\Finder;
11+
use Symfony\Component\Console\Command\Command;
12+
use Symfony\Component\Console\Input\InputArgument;
13+
use Symfony\Component\Console\Input\InputInterface;
14+
use Symfony\Component\Console\Input\InputOption;
15+
use Symfony\Component\Console\Output\OutputInterface;
16+
17+
class RefreshCommand extends Command
18+
{
19+
private const DEFAULT_PRESET = 'PHP';
20+
21+
/**
22+
* Package analyser.
23+
*
24+
* @var Analyser
25+
*/
26+
protected Analyser $analyser;
27+
28+
/**
29+
* @var Finder
30+
*/
31+
private Finder $finder;
32+
33+
/**
34+
* @param Analyser $analyser
35+
*/
36+
public function __construct(Analyser $analyser)
37+
{
38+
$this->analyser = $analyser;
39+
$this->finder = $analyser->getFinder();
40+
41+
parent::__construct();
42+
}
43+
44+
/**
45+
* Command configuration.
46+
*
47+
* @return void
48+
*/
49+
protected function configure(): void
50+
{
51+
$this->analyser->setDirectory(WORKING_DIRECTORY);
52+
53+
$this
54+
->setName('refresh')
55+
->setDescription('Refresh a present .lpv file');
56+
57+
$availablePresets = (new CommonPreset())->formatAvailablePresetDefinitionsForDescription(
58+
$this->finder->getAvailablePresets()
59+
);
60+
61+
$directoryDescription = 'The directory of a project/micro-package repository';
62+
$presetDescription = 'The preset to use for the .lpv file. Available ones are ' . $availablePresets . '.';
63+
64+
$this->addArgument(
65+
'directory',
66+
InputArgument::OPTIONAL,
67+
$directoryDescription,
68+
$this->analyser->getDirectory()
69+
);
70+
71+
$this->addOption(
72+
'preset',
73+
null,
74+
InputOption::VALUE_REQUIRED,
75+
$presetDescription,
76+
self::DEFAULT_PRESET
77+
);
78+
$this->getDefinition()->addOption(new InputOption(
79+
'dry-run',
80+
null,
81+
InputOption::VALUE_NONE,
82+
'Do not write any files. Output the content that would be written'
83+
));
84+
}
85+
86+
/**
87+
* Execute command.
88+
*
89+
* @param InputInterface $input
90+
* @param OutputInterface $output
91+
*
92+
* @throws PresetNotAvailable
93+
* @return integer
94+
*/
95+
protected function execute(InputInterface $input, OutputInterface $output): int
96+
{
97+
$directory = (string) $input->getArgument('directory');
98+
$chosenPreset = (string) $input->getOption('preset');
99+
$dryRun = (bool) $input->getOption('dry-run');
100+
101+
if ($directory !== '' && $directory !== WORKING_DIRECTORY) {
102+
try {
103+
$this->analyser->setDirectory($directory);
104+
} catch (\RuntimeException $e) {
105+
$warning = "Warning: The provided directory "
106+
. "'$directory' does not exist or is not a directory.";
107+
$output->writeln('<error>' . $warning . '</error>');
108+
$output->writeln($e->getMessage(), OutputInterface::VERBOSITY_DEBUG);
109+
110+
return Command::FAILURE;
111+
}
112+
}
113+
114+
$defaultLpvFile = WORKING_DIRECTORY . DIRECTORY_SEPARATOR . '.lpv';
115+
116+
if (!\file_exists($defaultLpvFile) && $dryRun !== true) {
117+
$output->writeln('<error>Warning: No default .lpv file exists to refresh.</error>');
118+
119+
return Command::FAILURE;
120+
}
121+
122+
if ($chosenPreset === '' || !\in_array(\strtolower($chosenPreset), \array_map('strtolower', $this->finder->getAvailablePresets()), true)) {
123+
$warning = 'Warning: Chosen preset ' . $chosenPreset . ' is not available. Maybe contribute it?.';
124+
$output->writeln('<error>' . $warning . '</error>');
125+
126+
return Command::FAILURE;
127+
}
128+
129+
$expectedGlobPattern = $this->finder->getPresetGlobByLanguageName($chosenPreset);
130+
$expectedContent = \implode("\n", $expectedGlobPattern);
131+
132+
$existingContent = '';
133+
if (\file_exists($defaultLpvFile)) {
134+
$existingContent = (string) \file_get_contents($defaultLpvFile);
135+
}
136+
137+
$existingLines = \array_values(\array_filter(
138+
\preg_split('/\r\n|\r|\n/', $existingContent) ?: [],
139+
static fn (string $line): bool => \trim($line) !== ''
140+
));
141+
142+
$mergedLines = $existingLines;
143+
foreach (\preg_split('/\r\n|\r|\n/', $expectedContent) ?: [] as $line) {
144+
$line = \trim((string) $line);
145+
if ($line === '') {
146+
continue;
147+
}
148+
149+
if (!\in_array($line, $mergedLines, true)) {
150+
$mergedLines[] = $line;
151+
}
152+
}
153+
154+
$refreshedContent = \implode("\n", $mergedLines);
155+
156+
if ($dryRun === true) {
157+
$output->writeln($refreshedContent);
158+
159+
return Command::SUCCESS;
160+
}
161+
162+
$bytesWritten = file_put_contents($defaultLpvFile, $refreshedContent);
163+
164+
if ($bytesWritten === false) {
165+
$output->writeln('<error>Warning: The refresh of the default .lpv file failed.</error>');
166+
167+
return Command::FAILURE;
168+
}
169+
170+
$output->writeln('Refreshed default \'' . $defaultLpvFile . '\' file.');
171+
172+
return Command::SUCCESS;
173+
}
174+
}

src/Presets/CommonPreset.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,22 @@ protected function getCommonGlob(): array
3434
'*.{png,gif,jpeg,jpg,webp}',
3535
];
3636
}
37+
38+
/**
39+
* @param array $presets
40+
* @return string
41+
*/
42+
public function formatAvailablePresetDefinitionsForDescription(array $presets): string
43+
{
44+
$presets = \array_map(function ($preset) {
45+
return '<comment>' . $preset . '</comment>';
46+
}, $presets);
47+
48+
if (\count($presets) > 2) {
49+
$lastPreset = \array_pop($presets);
50+
return \implode(', ', $presets) . ', and ' . $lastPreset;
51+
}
52+
53+
return $presets[0] . ' and ' . $presets[1];
54+
}
3755
}

0 commit comments

Comments
 (0)