Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Feature to submit packages from proxy #281

Merged
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
2 changes: 2 additions & 0 deletions src/Composer/PacketonRepositoryFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Composer\IO\IOInterface;
use Doctrine\Persistence\ManagerRegistry;
use Packeton\Composer\Repository\ArtifactRepository;
use Packeton\Composer\Repository\ComposerProxyRepository;
use Packeton\Composer\Repository\CustomJsonRepository;
use Packeton\Composer\Repository\PacketonRepositoryInterface;
use Packeton\Composer\Repository\VcsRepository;
Expand Down Expand Up @@ -42,6 +43,7 @@ public function create(array $repoConfig, IOInterface $io, Config $config, ?stri
return match ($type) {
RepTypes::ARTIFACT => new ArtifactRepository($repoConfig, $this->zipballStorage, $this->registry, $io, $config, $httpDownloader),
RepTypes::CUSTOM, RepTypes::VIRTUAL => new CustomJsonRepository($repoConfig, $this->registry, $io, $config, $httpDownloader),
RepTypes::PROXY => new ComposerProxyRepository($repoConfig, $io, $config, $httpDownloader),
default => new VcsRepository($repoConfig, $io, $config, $httpDownloader, $this->driverFactory, null, $process),
};
}
Expand Down
46 changes: 46 additions & 0 deletions src/Composer/Repository/ComposerProxyRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

declare(strict_types=1);

namespace Packeton\Composer\Repository;

use Composer\Config;
use Composer\IO\IOInterface;
use Composer\Repository\ComposerRepository;
use Composer\Util\HttpDownloader;
use Composer\Util\ProcessExecutor;

class ComposerProxyRepository extends ComposerRepository implements PacketonRepositoryInterface
{
public function __construct(
protected array $repoConfig,
protected IOInterface $io,
protected Config $config,
protected HttpDownloader $httpDownloader,
protected ?ProcessExecutor $process = null
) {
parent::__construct($repoConfig, $io, $config, $httpDownloader);

$this->process ??= new ProcessExecutor($this->io);
}

public function getHttpDownloader(): HttpDownloader
{
return $this->httpDownloader;
}

public function getProcessExecutor(): ProcessExecutor
{
return $this->process;
}

public function getConfig(): Config
{
return $this->config;
}

public function getIO(): IOInterface
{
return $this->io;
}
}
25 changes: 25 additions & 0 deletions src/Filter/VersionFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Packeton\Filter;

use Composer\Package\PackageInterface;

class VersionFilter
{
/**
* @param PackageInterface[] $versions
* @return PackageInterface[]
*/
public function filterVersionsForOnlyMatchingRepoName(string $repoName, array $versions): array
{
$result = [];
foreach ($versions as $version) {
if ($version->getName() === $repoName) {
$result[] = $version;
}
}
return $result;
}
}
1 change: 1 addition & 0 deletions src/Form/Type/Package/BasePackageType.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
'MonoRepos (only GIT)' => RepTypes::MONO_REPO,
'Artifacts' => RepTypes::ARTIFACT,
'Custom (JSON)' => RepTypes::CUSTOM,
'Proxy Repo' => RepTypes::PROXY,
'Virtual (only JSON metadata)' => RepTypes::VIRTUAL,
'Satis / Packagist.com / VCS Import' => 'import', // only redirect
];
Expand Down
93 changes: 93 additions & 0 deletions src/Form/Type/Package/ProxyPackageType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

declare(strict_types=1);

namespace Packeton\Form\Type\Package;

use Packeton\Entity\Package;
use Packeton\Form\Type\CredentialType;
use Packeton\Model\PackageManager;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\NotBlank;

class ProxyPackageType extends AbstractType
{
/**
* @var PackageManager
*/
protected $packageManager;

/**
* @param PackageManager $packageManager
*/
public function __construct(PackageManager $packageManager)
{
$this->packageManager = $packageManager;
}

/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('credentials', CredentialType::class)
->add('name', TextType::class, [
'required' => true,
'constraints' => [new NotBlank()],
'attr' => ['class' => 'package-repo-info', 'placeholder' => 'acme/package-name'],
'disabled' => false === $options['is_created'],
])
->add('repository', TextType::class, [
'label' => 'Packages.json',
'attr' => [
'class' => 'package-repo-info',
'placeholder' => 'e.g.: https://repo.magento.com/packages.json',
],
]);

$builder->addEventListener(FormEvents::POST_SUBMIT, [$this, 'updateRepository'], 255);
}

/**
* {@inheritdoc}
*/
public function getParent(): string
{
return BasePackageType::class;
}

/**
* @param FormEvent $event
*/
public function updateRepository(FormEvent $event): void
{
$package = $event->getData();
if ($package instanceof Package) {
$this->packageManager->updatePackageUrl($package);
}
}

/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Package::class,
]);
}

/**
* {@inheritdoc}
*/
public function getBlockPrefix(): string
{
return 'proxy';
}
}
58 changes: 58 additions & 0 deletions src/Model/ComposerProxyPackageManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

declare(strict_types=1);

namespace Packeton\Model;

use League\Flysystem\FilesystemOperator;
use Packeton\Composer\Repository\PacketonRepositoryInterface;
use Packeton\Entity\Package;
use Packeton\Service\DistConfig;

class ComposerProxyPackageManager
{
public function __construct(
private readonly DistConfig $config,
private readonly FilesystemOperator $baseStorage,
) {
}

public function buildArchive(Package $package, PacketonRepositoryInterface $repository, ?string $reference = null): ?string
{
$version = $package->getVersionByReference($reference) ?: $package->getVersions()->first();
if (null === $version) {
throw new \RuntimeException("Not found any versions for reference '$reference' of package '{$package->getName()}'");
}

$keyName = $this->config->buildName($package->getName(), $version->getReference(), $version->getVersion());
$cachedName = $this->config->resolvePath($keyName);
if (file_exists($cachedName)) {
return $cachedName;
}

$selected = [];
$serialized = $package->getCustomVersions();
foreach ($serialized as $data) {
$verName = $data['version'] ?? null;
if ($verName === $version->getVersion() || $verName === $version->getNormalizedVersion()) {
$selected = $data['definition'] ?? [];
$selected['version'] = $version->getVersion();
}
}

$selected['name'] = $package->getName();
$dir = dirname($cachedName);
if (!is_dir($dir)) {
@mkdir($dir, 0777, true);
}

$url = $package->getVersionByReference($reference)->getDist()['proxy_url'];
$response = $repository->getHttpDownloader()->get($url);
$body = (string) $response->getBody();

$this->baseStorage->write($keyName, $body);

return $cachedName;
}

}
7 changes: 6 additions & 1 deletion src/Package/RepTypes.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Packeton\Form\Type\Package\IntegrationPackageType;
use Packeton\Form\Type\Package\MonoRepoPackageType;
use Packeton\Form\Type\Package\PackageType;
use Packeton\Form\Type\Package\ProxyPackageType;

class RepTypes
{
Expand All @@ -18,6 +19,7 @@ class RepTypes
public const INTEGRATION = 'integration';
public const CUSTOM = 'custom';
public const VIRTUAL = 'virtual';
public const PROXY = 'proxy';

private static $types = [
self::ARTIFACT,
Expand All @@ -26,6 +28,7 @@ class RepTypes
self::VCS,
self::CUSTOM,
self::VIRTUAL,
self::PROXY,
];

public static function getFormType(?string $type): string
Expand All @@ -35,6 +38,7 @@ public static function getFormType(?string $type): string
self::ARTIFACT => ArtifactPackageType::class,
self::INTEGRATION => IntegrationPackageType::class,
self::CUSTOM, self::VIRTUAL => CustomPackageType::class,
self::PROXY => ProxyPackageType::class,
default => PackageType::class,
};
}
Expand All @@ -47,7 +51,7 @@ public static function isNotAutoCrawled(): array
public static function isBuildInDist(?string $type): bool
{
return match ($type) {
self::ARTIFACT, self::CUSTOM, self::VIRTUAL => true,
self::ARTIFACT, self::CUSTOM, self::VIRTUAL => true, self::PROXY => true,
default => false,
};
}
Expand All @@ -69,6 +73,7 @@ public static function normalizeType(?string $type): string
self::INTEGRATION => self::INTEGRATION,
self::CUSTOM => self::CUSTOM,
self::VIRTUAL => self::VIRTUAL,
self::PROXY => self::PROXY,
default => self::VCS,
};
}
Expand Down
32 changes: 27 additions & 5 deletions src/Package/Updater.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ManagerRegistry;
use Packeton\Composer\PackagistFactory;
use Packeton\Composer\Repository\ComposerProxyRepository;
use Packeton\Composer\Repository\PacketonRepositoryInterface;
use Packeton\Entity\Author;
use Packeton\Entity\Package;
Expand All @@ -41,6 +42,7 @@
use Packeton\Entity\SuggestLink;
use Packeton\Event\SecurityAdvisoryEvent;
use Packeton\Event\UpdaterEvent;
use Packeton\Mirror\Service\ProxyHttpDownloader;
use Packeton\Model\ProviderManager;
use Packeton\Repository\VersionRepository;
use Packeton\Service\DistConfig;
Expand Down Expand Up @@ -95,6 +97,7 @@ public function __construct(
protected ProviderManager $providerManager,
protected EventDispatcherInterface $dispatcher,
protected DistManager $distManager,
protected ProxyHttpDownloader $downloader,
) {
ErrorHandler::register();
}
Expand All @@ -109,7 +112,7 @@ public function setSerializerCachePath(?string $serializerCachePath): void
*/
public static function supportRepoTypes(): iterable
{
return [RepTypes::VCS, RepTypes::ARTIFACT, RepTypes::INTEGRATION, RepTypes::CUSTOM, RepTypes::VIRTUAL];
return [RepTypes::VCS, RepTypes::ARTIFACT, RepTypes::INTEGRATION, RepTypes::CUSTOM, RepTypes::VIRTUAL, RepTypes::PROXY];
}

/**
Expand All @@ -134,7 +137,12 @@ public function update(IOInterface $io, Config $config, Package $package, Reposi
$flags |= $addFlags;
}

$versions = PacketonUtils::sort($repository->getPackages());
if ($repository instanceof ComposerProxyRepository) {
$versions = PacketonUtils::sort($repository->findPackages($package->getName()));
} else {
$versions = PacketonUtils::sort($repository->getPackages());
}

/** @var VersionRepository $versionRepository */
$versionRepository = $this->doctrine->getRepository(Version::class);
if (null === $rootIdentifier && ($probe = end($versions))) {
Expand Down Expand Up @@ -563,7 +571,7 @@ private function updateArchive(PackageInterface $data, Package $package): ?array
// Process local path repos
if (is_string($distUrl = $data->getDistUrl())
&& (str_starts_with($distUrl, '/') || $distUrl === DistConfig::HOSTNAME_PLACEHOLDER)
&& (empty($data->getSourceUrl()) || in_array($package->getRepoType(), [RepTypes::CUSTOM, RepTypes::VIRTUAL], true))
&& (empty($data->getSourceUrl()) || in_array($package->getRepoType(), [RepTypes::CUSTOM, RepTypes::VIRTUAL, RepTypes::PROXY], true))
) {
return [
'url' => $this->distConfig->generateRoute($data->getName(), $data->getDistReference(), $data->getDistType()),
Expand Down Expand Up @@ -609,8 +617,22 @@ private function updateArchive(PackageInterface $data, Package $package): ?array
}

$dist['type'] = $this->distConfig->getArchiveFormat();
$dist['url'] = $this->distConfig->generateRoute($data->getName(), $data->getSourceReference());
$dist['reference'] = $data->getSourceReference();

$url = $data->getSourceReference();
if (null === $url) {
$url = $data->getDistReference();
}

if (null === $url) {
$url = sha1($data->getVersion());
}

$dist['url'] = $this->distConfig->generateRoute($data->getName(), $url);
$dist['reference'] = $url;

if ($package->getRepoType() === RepTypes::PROXY) {
$dist['proxy_url'] = $data->getDistUrl();
}

return $dist;
}
Expand Down
Loading