Skip to content

Commit

Permalink
Fix issue on update where composer-link maintained older original pac…
Browse files Browse the repository at this point in the history
…kage version (#7)
  • Loading branch information
SanderSander authored Apr 1, 2022
1 parent 550bda2 commit 29a6aca
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 76 deletions.
62 changes: 25 additions & 37 deletions src/LinkManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,17 @@

namespace ComposerLink;

use Composer\DependencyResolver\Operation\InstallOperation;
use Composer\DependencyResolver\Operation\UninstallOperation;
use Composer\Downloader\DownloadManager;
use Composer\Installer\InstallationManager;
use Composer\Package\PackageInterface;
use Composer\Repository\InstalledRepositoryInterface;
use Composer\Util\Filesystem;
use Composer\Util\Loop;
use React\Promise\PromiseInterface;

class LinkManager
{
protected Filesystem $filesystem;

protected DownloadManager $downloadManager;

protected Loop $loop;

protected InstallationManager $installationManager;
Expand All @@ -36,13 +32,11 @@ class LinkManager

public function __construct(
Filesystem $filesystem,
DownloadManager $downloadManager,
Loop $loop,
InstallationManager $installationManager,
InstalledRepositoryInterface $installedRepository
) {
$this->filesystem = $filesystem;
$this->downloadManager = $downloadManager;
$this->loop = $loop;
$this->installationManager = $installationManager;
$this->installedRepository = $installedRepository;
Expand All @@ -65,7 +59,6 @@ public function linkPackage(LinkedPackage $linkedPackage): void
if (!is_null($linkedPackage->getOriginalPackage())) {
$this->uninstall($linkedPackage->getOriginalPackage());
}

$this->install($linkedPackage->getPackage());
}

Expand All @@ -80,48 +73,43 @@ public function unlinkPackage(LinkedPackage $linkedPackage): void
}
$this->installedRepository->addPackage($linkedPackage->getPackage());

// Uninstall the linked package
$this->uninstall($linkedPackage->getPackage());

// Reinstall the linked package
if (!is_null($linkedPackage->getOriginalPackage())) {
// Prepare (Not sure if really needed)
$this->downloadManager->prepare(
$linkedPackage->getOriginalPackage()->getType(),
$linkedPackage->getOriginalPackage(),
$linkedPackage->getInstallationPath()
);

// Download the original package
$downloadPromise = $this->downloadManager->download(
$linkedPackage->getOriginalPackage(),
$linkedPackage->getInstallationPath()
);
$this->loop->wait([$downloadPromise]);

$this->install($linkedPackage->getOriginalPackage());
}
}

protected function uninstall(PackageInterface $package): void
{
$promise = $this->installationManager->uninstall(
$this->installedRepository,
new UninstallOperation($package)
);

if (!is_null($promise)) {
$this->loop->wait([$promise]);
}
$installer = $this->installationManager->getInstaller($package->getType());
$this->wait($installer->uninstall($this->installedRepository, $package));
}

/**
* Downloads and installs the given package
* https://github.com/composer/composer/blob/2.0.0/src/Composer/Util/SyncHelper.php
*/
protected function install(PackageInterface $package): void
{
$promise = $this->installationManager->install(
$this->installedRepository,
new InstallOperation($package)
);
$installer = $this->installationManager->getInstaller($package->getType());

try {
$this->wait($installer->download($package));
$this->wait($installer->prepare('install', $package));
$this->wait($installer->install($this->installedRepository, $package));
} catch (\Exception $exception) {
$this->wait($installer->cleanup('install', $package));
throw $exception;
}

$this->wait($installer->cleanup('install', $package));
}

/**
* Waits for promise to be finished
*/
protected function wait(?PromiseInterface $promise): void
{
if (!is_null($promise)) {
$this->loop->wait([$promise]);
}
Expand Down
5 changes: 5 additions & 0 deletions src/LinkedPackage.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,9 @@ public function getInstallationPath(): string
{
return $this->installationPath;
}

public function setOriginalPackage(?PackageInterface $package): void
{
$this->originalPackage = $package;
}
}
36 changes: 29 additions & 7 deletions src/LinkedPackagesRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,34 @@ public function __construct(FilesystemOperator $filesystem, IOInterface $io)

public function store(LinkedPackage $linkedPackage): void
{
$this->io->debug("[ComposerLink]\tStoring linked repository into memory");
$this->linkedPackages[] = $linkedPackage;
$index = $this->findIndex($linkedPackage);

if (is_null($index)) {
$this->linkedPackages[] = $linkedPackage;
return;
}

$this->linkedPackages[$index] = $linkedPackage;
}

/**
* @return LinkedPackage[]
*/
public function all(): array
{
return $this->linkedPackages;
$all = [];
foreach ($this->linkedPackages as $package) {
$all[] = clone $package;
}

return $all;
}

public function findByPath(string $path): ?LinkedPackage
{
foreach ($this->linkedPackages as $linkedPackage) {
if ($linkedPackage->getPath() === $path) {
return $linkedPackage;
return clone $linkedPackage;
}
}

Expand All @@ -66,7 +77,7 @@ public function findByName(string $name): ?LinkedPackage
{
foreach ($this->linkedPackages as $linkedPackage) {
if ($linkedPackage->getName() === $name) {
return $linkedPackage;
return clone $linkedPackage;
}
}

Expand All @@ -75,9 +86,9 @@ public function findByName(string $name): ?LinkedPackage

public function remove(LinkedPackage $linkedPackage): void
{
$index = array_search($linkedPackage, $this->linkedPackages, true);
$index = $this->findIndex($linkedPackage);

if ($index === false) {
if (is_null($index)) {
throw new \RuntimeException('Linked package not found');
}

Expand All @@ -103,4 +114,15 @@ private function loadFromJsonFile(): void
// TODO use json
$this->linkedPackages = unserialize($this->filesystem->read(self::FILE_NAME));
}

private function findIndex(LinkedPackage $package): ?int
{
foreach ($this->linkedPackages as $index => $linkedPackage) {
if ($linkedPackage->getName() === $package->getName()) {
return $index;
}
}

return null;
}
}
25 changes: 18 additions & 7 deletions src/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
namespace ComposerLink;

use Composer\Composer;
use Composer\Downloader\DownloadManager;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\Installer\InstallationManager;
use Composer\IO\IOInterface;
use Composer\Plugin\Capability\CommandProvider as ComposerCommandProvider;
use Composer\Plugin\Capable;
use Composer\Plugin\PluginInterface;
use Composer\Repository\RepositoryManager;
use Composer\Script\ScriptEvents;
use Composer\Util\Filesystem as ComposerFileSystem;
use League\Flysystem\Filesystem;
Expand All @@ -32,8 +32,6 @@ class Plugin implements PluginInterface, Capable, EventSubscriberInterface

protected LinkedPackagesRepository $repository;

protected DownloadManager $downloadManager;

protected InstallationManager $installationManager;

protected ComposerFileSystem $filesystem;
Expand All @@ -42,6 +40,8 @@ class Plugin implements PluginInterface, Capable, EventSubscriberInterface

protected LinkedPackageFactory $packageFactory;

protected RepositoryManager $repositoryManager;

public function __construct(ComposerFileSystem $filesystem = null)
{
$this->filesystem = $filesystem ?: new ComposerFileSystem();
Expand All @@ -62,20 +62,19 @@ public function activate(Composer $composer, IOInterface $io)
{
$io->debug("[ComposerLink]\tPlugin is activating");
$this->io = $io;
$this->downloadManager = $composer->getDownloadManager();
$this->installationManager = $composer->getInstallationManager();
$this->repositoryManager = $composer->getRepositoryManager();

$this->packageFactory = new LinkedPackageFactory(
$this->installationManager,
$composer->getRepositoryManager()->getLocalRepository()
$this->repositoryManager->getLocalRepository()
);

$this->linkedPackagesManager = new LinkManager(
$this->filesystem,
$this->downloadManager,
$composer->getLoop(),
$composer->getInstallationManager(),
$composer->getRepositoryManager()->getLocalRepository()
$this->repositoryManager->getLocalRepository()
);

// TODO use factory pattern
Expand Down Expand Up @@ -103,9 +102,21 @@ public function linkLinkedPackages(): void
{
foreach ($this->repository->all() as $linkedPackage) {
if (!$this->linkedPackagesManager->isLinked($linkedPackage)) {
// Package is updated, so we need to link the newer original package
$oldOriginalPackage = $linkedPackage->getOriginalPackage();
if (!is_null($oldOriginalPackage)) {
$newOriginalPackage = $this->repositoryManager
->getLocalRepository()
->findPackage($oldOriginalPackage->getName(), '*');
$linkedPackage->setOriginalPackage($newOriginalPackage);
$this->repository->store($linkedPackage);
}

$this->linkedPackagesManager->linkPackage($linkedPackage);
}
}

$this->repository->persist();
}

public function getCapabilities(): array
Expand Down
Loading

0 comments on commit 29a6aca

Please sign in to comment.