1
0
Fork 0

Warn when require ends up auto-selecting a feature branch, fixes #11264 (#11270)

pull/11283/head
Jordi Boggiano 2023-01-19 21:42:09 +01:00 committed by GitHub
parent c7f32820d7
commit 0d96fd8149
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 3 deletions

View File

@ -338,7 +338,7 @@ EOT
try { try {
$result = $this->doUpdate($input, $output, $io, $requirements, $requireKey, $removeKey); $result = $this->doUpdate($input, $output, $io, $requirements, $requireKey, $removeKey);
if ($result === 0 && count($requirementsToGuess) > 0) { if ($result === 0 && count($requirementsToGuess) > 0) {
$this->updateRequirementsAfterResolution($requirementsToGuess, $requireKey, $removeKey, $sortPackages, $input->getOption('dry-run')); $result = $this->updateRequirementsAfterResolution($requirementsToGuess, $requireKey, $removeKey, $sortPackages, $input->getOption('dry-run'));
} }
return $result; return $result;
@ -506,7 +506,7 @@ EOT
/** /**
* @param list<string> $requirementsToUpdate * @param list<string> $requirementsToUpdate
*/ */
private function updateRequirementsAfterResolution(array $requirementsToUpdate, string $requireKey, string $removeKey, bool $sortPackages, bool $dryRun): void private function updateRequirementsAfterResolution(array $requirementsToUpdate, string $requireKey, string $removeKey, bool $sortPackages, bool $dryRun): int
{ {
$composer = $this->requireComposer(); $composer = $this->requireComposer();
$locker = $composer->getLocker(); $locker = $composer->getLocker();
@ -529,6 +529,15 @@ EOT
$requirements[$packageName], $requirements[$packageName],
$packageName $packageName
)); ));
if (Preg::isMatch('{^dev-(?!main$|master$|trunk$|latest$)}', $requirements[$packageName])) {
$this->getIO()->warning('Version '.$requirements[$packageName].' looks like it may be a feature branch which is unlikely to keep working in the long run and may be in an unstable state');
if ($this->getIO()->isInteractive() && !$this->getIO()->askConfirmation('Are you sure you want to use this constraint (<comment>Y</comment>) or would you rather abort (<comment>n</comment>) the whole operation [<comment>Y,n</comment>]? ')) {
$this->revertComposerFile();
return 1;
}
}
} }
if (!$dryRun) { if (!$dryRun) {
@ -544,6 +553,8 @@ EOT
$lock->write($lockData); $lock->write($lockData);
} }
} }
return 0;
} }
/** /**

View File

@ -147,7 +147,7 @@ class Application extends BaseApplication
$this->disableScriptsByDefault = $input->hasParameterOption('--no-scripts'); $this->disableScriptsByDefault = $input->hasParameterOption('--no-scripts');
$stdin = defined('STDIN') ? STDIN : fopen('php://stdin', 'r'); $stdin = defined('STDIN') ? STDIN : fopen('php://stdin', 'r');
if (Platform::getEnv('COMPOSER_NO_INTERACTION') || $stdin === false || !Platform::isTty($stdin)) { if (Platform::getEnv('COMPOSER_TESTS_ARE_RUNNING') !== '1' && (Platform::getEnv('COMPOSER_NO_INTERACTION') || $stdin === false || !Platform::isTty($stdin))) {
$input->setInteractive(false); $input->setInteractive(false);
} }

View File

@ -40,6 +40,48 @@ class RequireCommandTest extends TestCase
$appTester->run(['command' => 'require', '--dry-run' => true, '--no-audit' => true, 'packages' => ['required/pkg']]); $appTester->run(['command' => 'require', '--dry-run' => true, '--no-audit' => true, 'packages' => ['required/pkg']]);
} }
public function testRequireWarnsIfResolvedToFeatureBranch(): void
{
$this->initTempComposer([
'repositories' => [
'packages' => [
'type' => 'package',
'package' => [
['name' => 'required/pkg', 'version' => '2.0.0', 'require' => ['common/dep' => '^1']],
['name' => 'required/pkg', 'version' => 'dev-foo-bar', 'require' => ['common/dep' => '^2']],
['name' => 'common/dep', 'version' => '2.0.0'],
],
],
],
'require' => [
'common/dep' => '^2.0',
],
'minimum-stability' => 'dev',
'prefer-stable' => true,
]);
$appTester = $this->getApplicationTester();
$appTester->setInputs(['n']);
$appTester->run(['command' => 'require', '--dry-run' => true, '--no-audit' => true, 'packages' => ['required/pkg']], ['interactive' => true]);
self::assertSame(
'./composer.json has been updated
Running composer update required/pkg
Loading composer repositories with package information
Updating dependencies
Lock file operations: 2 installs, 0 updates, 0 removals
- Locking common/dep (2.0.0)
- Locking required/pkg (dev-foo-bar)
Installing dependencies from lock file (including require-dev)
Package operations: 2 installs, 0 updates, 0 removals
- Installing common/dep (2.0.0)
- Installing required/pkg (dev-foo-bar)
Using version dev-foo-bar for required/pkg
<warning>Version dev-foo-bar looks like it may be a feature branch which is unlikely to keep working in the long run and may be in an unstable state</warning>
Are you sure you want to use this constraint (Y) or would you rather abort (n) the whole operation [Y,n]? '.'
Installation failed, reverting ./composer.json to its original content.
', $appTester->getDisplay(true));
}
/** /**
* @dataProvider provideRequire * @dataProvider provideRequire
* @param array<mixed> $composerJson * @param array<mixed> $composerJson