Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Command/BuildCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ public function execute(InputInterface $input, OutputInterface $output): int
PieOperation::Build,
$configureOptionsValues,
false, // setting up INI not needed for build
suppressedDownloadUrlMethods: CommandHelper::determineSuppressedDownloadUrlMethods($input),
),
);

Expand Down
41 changes: 41 additions & 0 deletions src/Command/CommandHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use Php\Pie\DependencyResolver\RequestedPackageAndVersion;
use Php\Pie\DependencyResolver\ResolvedPackageRequest;
use Php\Pie\DependencyResolver\UnableToResolveRequirement;
use Php\Pie\Downloading\DownloadUrlMethod;
use Php\Pie\ExtensionName;
use Php\Pie\Installing\InstallForPhpProject\FindMatchingPackages;
use Php\Pie\Platform as PiePlatform;
Expand All @@ -36,6 +37,7 @@
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Throwable;
use ValueError;
use Webmozart\Assert\Assert;

use function array_key_exists;
Expand All @@ -44,6 +46,7 @@
use function assert;
use function count;
use function explode;
use function implode;
use function is_array;
use function is_dir;
use function is_string;
Expand Down Expand Up @@ -75,6 +78,7 @@ final class CommandHelper
private const OPTION_MAKE_PARALLEL_JOBS = 'make-parallel-jobs';
private const OPTION_SKIP_ENABLE_EXTENSION = 'skip-enable-extension';
private const OPTION_FORCE = 'force';
private const OPTION_SUPPRESS_DOWNLOAD_URL_METHOD = 'suppress-download-url-method';
private const OPTION_NO_CACHE = 'no-cache';
private const OPTION_AUTO_INSTALL_BUILD_TOOLS = 'auto-install-build-tools';
private const OPTION_SUPPRESS_BUILD_TOOLS_CHECK = 'no-build-tools-check';
Expand Down Expand Up @@ -152,6 +156,14 @@ public static function configureDownloadBuildInstallOptions(Command $command, bo
'To attempt to install a version that doesn\'t match the version constraints from the meta-data, for instance to install an older version than recommended, or when the signature is not available.',
);

$command->addOption(
self::OPTION_SUPPRESS_DOWNLOAD_URL_METHOD,
null,
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'Do not use the specified download URL methods if they are supported by the extension. May be specified multiple times. Valid values: '
. implode(', ', array_map(static fn (DownloadUrlMethod $downloadUrlMethod): string => $downloadUrlMethod->value, DownloadUrlMethod::cases())),
);

$command->addOption(
self::OPTION_WORKING_DIRECTORY,
'd',
Expand Down Expand Up @@ -293,6 +305,35 @@ public static function determineForceInstallingPackageVersion(InputInterface $in
return $input->hasOption(self::OPTION_FORCE) && $input->getOption(self::OPTION_FORCE);
}

/** @return list<DownloadUrlMethod> */
public static function determineSuppressedDownloadUrlMethods(InputInterface $input): array
{
if (! $input->hasOption(self::OPTION_SUPPRESS_DOWNLOAD_URL_METHOD)) {
return [];
}

$suppressedDownloadUrlMethods = $input->getOption(self::OPTION_SUPPRESS_DOWNLOAD_URL_METHOD);
assert(is_array($suppressedDownloadUrlMethods));

return array_values(array_map(
static function (mixed $suppressedDownloadUrlMethod): DownloadUrlMethod {
assert(is_string($suppressedDownloadUrlMethod) && $suppressedDownloadUrlMethod !== '');

try {
return DownloadUrlMethod::from($suppressedDownloadUrlMethod);
} catch (ValueError) {
throw new InvalidArgumentException(sprintf(
'Invalid value "%s" for --%s; valid values are: %s',
$suppressedDownloadUrlMethod,
self::OPTION_SUPPRESS_DOWNLOAD_URL_METHOD,
implode(', ', array_map(static fn (DownloadUrlMethod $downloadUrlMethod): string => $downloadUrlMethod->value, DownloadUrlMethod::cases())),
));
}
},
$suppressedDownloadUrlMethods,
));
}

public static function autoInstallBuildTools(InputInterface $input): bool
{
return $input->hasOption(self::OPTION_AUTO_INSTALL_BUILD_TOOLS)
Expand Down
1 change: 1 addition & 0 deletions src/Command/DownloadCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ public function execute(InputInterface $input, OutputInterface $output): int
PieOperation::Download,
[], // Configure options are not needed for download only
false, // setting up INI not needed for download
suppressedDownloadUrlMethods: CommandHelper::determineSuppressedDownloadUrlMethods($input),
),
);

Expand Down
1 change: 1 addition & 0 deletions src/Command/InstallCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ public function execute(InputInterface $input, OutputInterface $output): int
$configureOptionsValues,
CommandHelper::determineAttemptToSetupIniFile($input),
installAllPackages: $installFromLock,
suppressedDownloadUrlMethods: CommandHelper::determineSuppressedDownloadUrlMethods($input),
),
);

Expand Down
1 change: 1 addition & 0 deletions src/Command/UpgradeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ public function execute(InputInterface $input, OutputInterface $output): int
$configureOptions,
CommandHelper::determineAttemptToSetupIniFile($input),
installAllPackages: true,
suppressedDownloadUrlMethods: CommandHelper::determineSuppressedDownloadUrlMethods($input),
),
);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace Php\Pie\ComposerIntegration\Listeners;

use Php\Pie\DependencyResolver\Package;
use RuntimeException;

use function sprintf;

class AllDownloadUrlMethodsSuppressed extends RuntimeException
{
public static function forPackage(Package $piePackage): self
{
return new self(sprintf(
'Could not find a way to download %s as all possible download URL methods were suppressed',
$piePackage->name(),
));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use Throwable;

use function array_walk;
use function in_array;
use function pathinfo;

use const PATHINFO_EXTENSION;
Expand Down Expand Up @@ -75,6 +76,25 @@ function (OperationInterface $operation): void {
$targetPlatform = $this->composerRequest->targetPlatform;
$downloadUrlMethods = DownloadUrlMethod::possibleDownloadUrlMethodsForPackage($piePackage, $targetPlatform);

if ($this->composerRequest->suppressedDownloadUrlMethods !== []) {
$remainingDownloadUrlMethods = [];

foreach ($downloadUrlMethods as $downloadUrlMethod) {
if (in_array($downloadUrlMethod, $this->composerRequest->suppressedDownloadUrlMethods, true)) {
$this->io->write('Suppressing download method: ' . $downloadUrlMethod->value, verbosity: IOInterface::VERBOSE);
continue;
}

$remainingDownloadUrlMethods[] = $downloadUrlMethod;
}

if ($remainingDownloadUrlMethods === []) {
throw AllDownloadUrlMethodsSuppressed::forPackage($piePackage);
}

$downloadUrlMethods = $remainingDownloadUrlMethods;
}

$selectedDownloadUrlMethod = null;
$downloadMethodFailures = [];

Expand Down
5 changes: 4 additions & 1 deletion src/ComposerIntegration/PieComposerRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Composer\IO\IOInterface;
use Php\Pie\DependencyResolver\RequestedPackageAndVersion;
use Php\Pie\Downloading\DownloadUrlMethod;
use Php\Pie\Platform\TargetPlatform;

use function array_map;
Expand All @@ -23,7 +24,8 @@ final class PieComposerRequest

/**
* @param list<RequestedPackageAndVersion> $requestedPackages
* @param array<string, list<non-empty-string>> $configureOptions Keyed by package name
* @param array<string, list<non-empty-string>> $configureOptions Keyed by package name
* @param list<DownloadUrlMethod> $suppressedDownloadUrlMethods
*/
public function __construct(
public readonly IOInterface $pieOutput,
Expand All @@ -33,6 +35,7 @@ public function __construct(
public readonly array $configureOptions,
public readonly bool $attemptToSetupIniFile,
public readonly bool $installAllPackages = false,
public readonly array $suppressedDownloadUrlMethods = [],
) {
$this->requestedPackageNames = array_map(static fn (RequestedPackageAndVersion $request) => $request->package, $this->requestedPackages);
}
Expand Down
36 changes: 36 additions & 0 deletions test/unit/Command/CommandHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use Php\Pie\DependencyResolver\RequestedPackageAndVersion;
use Php\Pie\DependencyResolver\ResolvedPackageRequest;
use Php\Pie\DependencyResolver\UnableToResolveRequirement;
use Php\Pie\Downloading\DownloadUrlMethod;
use Php\Pie\Platform\TargetPlatform;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
Expand Down Expand Up @@ -340,6 +341,41 @@ public function testWindowsMachinesCannotUseWithPhpizePathOption(): void
CommandHelper::determineTargetPlatformFromInputs($input, $io);
}

public function testDetermineSuppressedDownloadUrlMethodsDefaultsToEmpty(): void
{
$command = new Command();
$input = new ArrayInput([]);
CommandHelper::configureDownloadBuildInstallOptions($command);
CommandHelper::validateInput($input, $command);

self::assertSame([], CommandHelper::determineSuppressedDownloadUrlMethods($input));
}

public function testDetermineSuppressedDownloadUrlMethodsParsesGivenValues(): void
{
$command = new Command();
$input = new ArrayInput(['--suppress-download-url-method' => ['composer-default', 'pre-packaged-source']]);
CommandHelper::configureDownloadBuildInstallOptions($command);
CommandHelper::validateInput($input, $command);

self::assertSame(
[DownloadUrlMethod::ComposerDefaultDownload, DownloadUrlMethod::PrePackagedSourceDownload],
CommandHelper::determineSuppressedDownloadUrlMethods($input),
);
}

public function testDetermineSuppressedDownloadUrlMethodsThrowsForInvalidValue(): void
{
$command = new Command();
$input = new ArrayInput(['--suppress-download-url-method' => ['not-a-real-method']]);
CommandHelper::configureDownloadBuildInstallOptions($command);
CommandHelper::validateInput($input, $command);

$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Invalid value "not-a-real-method" for --suppress-download-url-method; valid values are: composer-default, windows-binary, pre-packaged-source, pre-packaged-binary');
CommandHelper::determineSuppressedDownloadUrlMethods($input);
}

public function testListRepositories(): void
{
$io = new BufferIO();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace Php\PieUnitTest\ComposerIntegration\Listeners;

use Composer\Package\CompletePackageInterface;
use Php\Pie\ComposerIntegration\Listeners\AllDownloadUrlMethodsSuppressed;
use Php\Pie\DependencyResolver\Package;
use Php\Pie\ExtensionName;
use Php\Pie\ExtensionType;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\TestCase;

#[CoversClass(AllDownloadUrlMethodsSuppressed::class)]
final class AllDownloadUrlMethodsSuppressedTest extends TestCase
{
public function testForPackage(): void
{
self::assertSame(
'Could not find a way to download foo/bar as all possible download URL methods were suppressed',
AllDownloadUrlMethodsSuppressed::forPackage(new Package(
$this->createMock(CompletePackageInterface::class),
ExtensionType::PhpModule,
ExtensionName::normaliseFromString('bar'),
'foo/bar',
'1.2.3',
null,
))->getMessage(),
);
}
}
Loading
Loading