From ed684181e2627257f26e0c941553a9af810dc3f4 Mon Sep 17 00:00:00 2001 From: "tien.xuan.vo" Date: Fri, 17 May 2024 00:05:01 +0700 Subject: [PATCH] fix: Allow update extra file without manually deletion --- src/Composer/Installer/AbstractInstaller.php | 8 +- .../Repository/ExtraDownloadsRepository.php | 8 +- .../ExtraDownloadsRepositoryInterface.php | 11 ++ .../Installer/AbstractInstallerTestCase.php | 136 +++++++++++------- .../ExtraDownloadsRepositoryTest.php | 26 ++-- 5 files changed, 126 insertions(+), 63 deletions(-) create mode 100644 src/Composer/Repository/ExtraDownloadsRepositoryInterface.php diff --git a/src/Composer/Installer/AbstractInstaller.php b/src/Composer/Installer/AbstractInstaller.php index 380ffe1..2149417 100644 --- a/src/Composer/Installer/AbstractInstaller.php +++ b/src/Composer/Installer/AbstractInstaller.php @@ -8,6 +8,7 @@ use Composer\Package\PackageInterface; use Composer\Repository\InstalledRepositoryInterface; use LastCall\DownloadsPlugin\Composer\Package\ExtraDownloadInterface; +use LastCall\DownloadsPlugin\Composer\Repository\ExtraDownloadsRepositoryInterface; use LastCall\DownloadsPlugin\Exception\ExtraDownloadHashMismatchException; use LastCall\DownloadsPlugin\Installer\ExecutableInstaller; use LastCall\DownloadsPlugin\Installer\ExecutableInstallerInterface; @@ -27,14 +28,13 @@ public function __construct( public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package): bool { - if (!$package instanceof ExtraDownloadInterface) { + if (!$package instanceof ExtraDownloadInterface || !$repo instanceof ExtraDownloadsRepositoryInterface) { return false; } - $hasPackage = $repo->hasPackage($package); $fileExists = file_exists($package->getInstallPath()); - if (!$hasPackage && $fileExists) { + if ($fileExists && !$repo->isTracked($package)) { $this->io->write( sprintf( 'Extra file %s has been locally overriden in %s. To reset it, delete and reinstall.', @@ -47,7 +47,7 @@ public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface return true; } - if ($hasPackage && $fileExists) { + if ($fileExists && $repo->hasPackage($package)) { $this->io->write( sprintf('Skip extra file %s', $package->getName()), true, diff --git a/src/Composer/Repository/ExtraDownloadsRepository.php b/src/Composer/Repository/ExtraDownloadsRepository.php index b642ced..0093c8e 100644 --- a/src/Composer/Repository/ExtraDownloadsRepository.php +++ b/src/Composer/Repository/ExtraDownloadsRepository.php @@ -5,11 +5,10 @@ use Composer\Installer\InstallationManager; use Composer\Json\JsonFile; use Composer\Package\PackageInterface; -use Composer\Repository\InstalledRepositoryInterface; use Composer\Repository\InvalidRepositoryException; use LastCall\DownloadsPlugin\Composer\Package\ExtraDownloadInterface; -class ExtraDownloadsRepository implements InstalledRepositoryInterface +class ExtraDownloadsRepository implements ExtraDownloadsRepositoryInterface { private array $extraDownloads; @@ -45,6 +44,11 @@ public function hasPackage(PackageInterface $package): bool return $this->extraDownloads[$name] === $package->getTrackingChecksum(); } + public function isTracked(ExtraDownloadInterface $package): bool + { + return isset($this->extraDownloads[$package->getName()]); + } + protected function initialize(): void { $this->extraDownloads = []; diff --git a/src/Composer/Repository/ExtraDownloadsRepositoryInterface.php b/src/Composer/Repository/ExtraDownloadsRepositoryInterface.php new file mode 100644 index 0000000..7321f50 --- /dev/null +++ b/src/Composer/Repository/ExtraDownloadsRepositoryInterface.php @@ -0,0 +1,11 @@ +io = $this->createMock(IOInterface::class); $this->downloadManager = $this->createMock(DownloadManager::class); $this->executableInstaller = $this->createMock(ExecutableInstallerInterface::class); - $this->repository = $this->createMock(InstalledRepositoryInterface::class); + $this->repository = $this->createMock(ExtraDownloadsRepositoryInterface::class); $this->extraDownload = $this->createMock(ExtraDownloadInterface::class); $this->package = $this->createMock(PackageInterface::class); $this->installer = $this->createInstaller(); @@ -50,31 +51,103 @@ protected function tearDown(): void $this->fs = null; } - public function testIsInstalledPackage(): void + public function testIsInstalledNotSupportedPackage(): void { $this->assertFalse($this->installer->isInstalled($this->repository, $this->package)); } - public function getIsInstalledExtraDownloadTests(): array + public function testIsInstalledNotSupportedRepository(): void { - return [ - [true, true, true], - [false, true, true], - [true, false, false], - [false, false, false], - ]; + $this->assertFalse($this->installer->isInstalled(new InstalledArrayRepository(), $this->package)); + } + + public function testIsInstalledSkip(): void + { + $this->repository + ->expects($this->once()) + ->method('hasPackage') + ->with($this->extraDownload) + ->willReturn(true); + $this->repository + ->expects($this->once()) + ->method('isTracked') + ->with($this->extraDownload) + ->willReturn(true); + $this->extraDownload + ->expects($this->once()) + ->method('getInstallPath') + ->willReturn($this->fs->path($this->installPath)); + $this->fs->createDirectory(\dirname($this->installPath), true); + $this->fs->createFile($this->installPath, 'downloaded file'); + $this->extraDownload + ->expects($this->once()) + ->method('getName') + ->willReturn($this->name); + $this->io + ->expects($this->once()) + ->method('write') + ->with( + sprintf('Skip extra file %s', $this->name), + true, + IOInterface::VERY_VERBOSE + ); + $this->assertTrue($this->installer->isInstalled($this->repository, $this->extraDownload)); + } + + public function testIsInstalledLocalyOverriden(): void + { + $this->repository + ->expects($this->once()) + ->method('isTracked') + ->with($this->extraDownload) + ->willReturn(false); + $this->extraDownload + ->expects($this->once()) + ->method('getInstallPath') + ->willReturn($this->fs->path($this->installPath)); + $this->fs->createDirectory(\dirname($this->installPath), true); + $this->fs->createFile($this->installPath, 'downloaded file'); + $this->extraDownload + ->expects($this->once()) + ->method('getName') + ->willReturn($this->name); + $this->extraDownload + ->expects($this->once()) + ->method('getTargetDir') + ->willReturn($this->targetDir); + $this->io + ->expects($this->once()) + ->method('write') + ->with( + sprintf( + 'Extra file %s has been locally overriden in %s. To reset it, delete and reinstall.', + $this->name, + $this->targetDir, + ), + true + ); + $this->assertTrue($this->installer->isInstalled($this->repository, $this->extraDownload)); } /** - * @dataProvider getIsInstalledExtraDownloadTests + * @testWith [false, true, true] + * [true, true, false] + * [true, false, false] + * [false, true, false] + * [false, false, false] */ - public function testIsInstalledExtraDownload(bool $hasPackage, bool $fileExists, bool $isInstalled): void + public function testIsNotInstalled(bool $hasPackage, bool $isTracked, bool $fileExists): void { $this->repository - ->expects($this->once()) + ->expects($this->any()) ->method('hasPackage') ->with($this->extraDownload) ->willReturn($hasPackage); + $this->repository + ->expects($this->any()) + ->method('isTracked') + ->with($this->extraDownload) + ->willReturn($isTracked); $this->extraDownload ->expects($this->once()) ->method('getInstallPath') @@ -83,40 +156,7 @@ public function testIsInstalledExtraDownload(bool $hasPackage, bool $fileExists, $this->fs->createDirectory(\dirname($this->installPath), true); $this->fs->createFile($this->installPath, 'downloaded file'); } - if ($fileExists) { - $this->extraDownload - ->expects($this->once()) - ->method('getName') - ->willReturn($this->name); - } - if (!$hasPackage && $fileExists) { - $this->extraDownload - ->expects($this->once()) - ->method('getTargetDir') - ->willReturn($this->targetDir); - $this->io - ->expects($this->once()) - ->method('write') - ->with( - sprintf( - 'Extra file %s has been locally overriden in %s. To reset it, delete and reinstall.', - $this->name, - $this->targetDir, - ), - true - ); - } - if ($hasPackage && $fileExists) { - $this->io - ->expects($this->once()) - ->method('write') - ->with( - sprintf('Skip extra file %s', $this->name), - true, - IOInterface::VERY_VERBOSE - ); - } - $this->assertSame($isInstalled, $this->installer->isInstalled($this->repository, $this->extraDownload)); + $this->assertFalse($this->installer->isInstalled($this->repository, $this->extraDownload)); } public function testDownloadPackage(): void diff --git a/tests/Unit/Composer/Repository/ExtraDownloadsRepositoryTest.php b/tests/Unit/Composer/Repository/ExtraDownloadsRepositoryTest.php index 15dc994..6038197 100644 --- a/tests/Unit/Composer/Repository/ExtraDownloadsRepositoryTest.php +++ b/tests/Unit/Composer/Repository/ExtraDownloadsRepositoryTest.php @@ -87,16 +87,9 @@ public function testHasPackage(): void $this->assertFalse($this->repository->hasPackage($this->package)); } - public function getHasExtraDownloadTests(): array - { - return [ - [false], - [true], - ]; - } - /** - * @dataProvider getHasExtraDownloadTests + * @testWith [true] + * [false] */ public function testHasExtraDownload(bool $sameTrackingChecksum): void { @@ -114,6 +107,21 @@ public function testHasExtraDownload(bool $sameTrackingChecksum): void $this->assertSame($sameTrackingChecksum, $this->repository->hasPackage($this->extraDownload)); } + public function testIsTracked(): void + { + $this->extraDownload + ->expects($this->exactly(3)) + ->method('getName') + ->willReturn($this->name); + $this->extraDownload + ->expects($this->once()) + ->method('getTrackingChecksum') + ->willReturn($this->trackingChecksum); + $this->assertFalse($this->repository->isTracked($this->extraDownload)); + $this->repository->addPackage($this->extraDownload); + $this->assertTrue($this->repository->isTracked($this->extraDownload)); + } + public function testReloadFromInvalidFile(): void { $this->fs->createDirectory(\dirname($this->path), true);