diff --git a/src/Installer.php b/src/Installer.php
index 385d9ef..a42cdab 100644
--- a/src/Installer.php
+++ b/src/Installer.php
@@ -401,6 +401,10 @@ public function install(InstalledRepositoryInterface $repo, PackageInterface $pa
if ($this->isPathRepository($package)) {
$this->io->write(" - Skipping install for path repository: {$package->getPrettyName()}");
+ if (! $repo->hasPackage($package)) {
+ $repo->addPackage(clone $package);
+ }
+
return \React\Promise\resolve(null);
}
@@ -480,6 +484,14 @@ public function update(InstalledRepositoryInterface $repo, PackageInterface $ini
if ($this->isPathRepository($target)) {
$this->io->write(" - Skipping update for path repository: {$target->getPrettyName()}");
+ if ($repo->hasPackage($initial)) {
+ $repo->removePackage($initial);
+ }
+
+ if (! $repo->hasPackage($target)) {
+ $repo->addPackage(clone $target);
+ }
+
return \React\Promise\resolve(null);
}
diff --git a/tests/ModuleInstallerTest.php b/tests/ModuleInstallerTest.php
index ef4bfde..8f6723b 100644
--- a/tests/ModuleInstallerTest.php
+++ b/tests/ModuleInstallerTest.php
@@ -599,6 +599,38 @@ public function test_install_logs_skip_message_and_returns_promise_for_path_repo
$this->assertNotNull($promise);
}
+ public function test_install_registers_package_in_repo_when_not_already_present_for_path_repo(): void
+ {
+ $io = $this->createStub(IOInterface::class);
+
+ $pkg = $this->createStub(PackageInterface::class);
+ $pkg->method('getDistType')->willReturn('path');
+ $pkg->method('getPrettyName')->willReturn('saucebase/test');
+
+ $repo = $this->createMock(InstalledRepositoryInterface::class);
+ $repo->method('hasPackage')->willReturn(false);
+ $repo->expects($this->once())->method('addPackage');
+
+ $installer = new TestableInstaller($io, null);
+ $installer->install($repo, $pkg);
+ }
+
+ public function test_install_does_not_register_package_in_repo_when_already_present_for_path_repo(): void
+ {
+ $io = $this->createStub(IOInterface::class);
+
+ $pkg = $this->createStub(PackageInterface::class);
+ $pkg->method('getDistType')->willReturn('path');
+ $pkg->method('getPrettyName')->willReturn('saucebase/test');
+
+ $repo = $this->createMock(InstalledRepositoryInterface::class);
+ $repo->method('hasPackage')->willReturn(true);
+ $repo->expects($this->never())->method('addPackage');
+
+ $installer = new TestableInstaller($io, null);
+ $installer->install($repo, $pkg);
+ }
+
// -------------------------------------------------------------------------
// update() path-repository guard
// -------------------------------------------------------------------------
@@ -624,6 +656,64 @@ public function test_update_logs_skip_message_and_returns_promise_for_path_repo(
$this->assertNotNull($promise);
}
+ public function test_update_registers_package_in_repo_when_not_already_present_for_path_repo(): void
+ {
+ $io = $this->createStub(IOInterface::class);
+
+ $initial = $this->createStub(PackageInterface::class);
+
+ $target = $this->createStub(PackageInterface::class);
+ $target->method('getDistType')->willReturn('path');
+ $target->method('getPrettyName')->willReturn('saucebase/test');
+
+ $repo = $this->createMock(InstalledRepositoryInterface::class);
+ $repo->method('hasPackage')->willReturn(false);
+ $repo->expects($this->never())->method('removePackage');
+ $repo->expects($this->once())->method('addPackage');
+
+ $installer = new TestableInstaller($io, null);
+ $installer->update($repo, $initial, $target);
+ }
+
+ public function test_update_replaces_initial_with_target_in_repo_for_path_repo(): void
+ {
+ $io = $this->createStub(IOInterface::class);
+
+ $initial = $this->createStub(PackageInterface::class);
+
+ $target = $this->createStub(PackageInterface::class);
+ $target->method('getDistType')->willReturn('path');
+ $target->method('getPrettyName')->willReturn('saucebase/test');
+
+ $repo = $this->createMock(InstalledRepositoryInterface::class);
+ $repo->method('hasPackage')
+ ->willReturnCallback(fn (PackageInterface $pkg) => $pkg === $initial);
+ $repo->expects($this->once())->method('removePackage')->with($initial);
+ $repo->expects($this->once())->method('addPackage');
+
+ $installer = new TestableInstaller($io, null);
+ $installer->update($repo, $initial, $target);
+ }
+
+ public function test_update_does_not_register_package_in_repo_when_already_present_for_path_repo(): void
+ {
+ $io = $this->createStub(IOInterface::class);
+
+ $initial = $this->createStub(PackageInterface::class);
+
+ $target = $this->createStub(PackageInterface::class);
+ $target->method('getDistType')->willReturn('path');
+ $target->method('getPrettyName')->willReturn('saucebase/test');
+
+ $repo = $this->createMock(InstalledRepositoryInterface::class);
+ $repo->method('hasPackage')->willReturn(true);
+ $repo->expects($this->once())->method('removePackage')->with($initial);
+ $repo->expects($this->never())->method('addPackage');
+
+ $installer = new TestableInstaller($io, null);
+ $installer->update($repo, $initial, $target);
+ }
+
// -------------------------------------------------------------------------
// uninstall() path-repository guard
// -------------------------------------------------------------------------