Skip to content

Commit

Permalink
Merge pull request #281 from jg-development/feature/280_add_submit_pr…
Browse files Browse the repository at this point in the history
…oxy_package

Add Feature to submit packages from proxy
  • Loading branch information
vtsykun authored Nov 2, 2024
2 parents a45a742 + 86c37ab commit 7441203
Show file tree
Hide file tree
Showing 10 changed files with 271 additions and 8 deletions.
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

0 comments on commit 7441203

Please sign in to comment.