Skip to content

Commit

Permalink
Merge pull request #176 from asgrim/use-repo-commands
Browse files Browse the repository at this point in the history
Add repository management commands
  • Loading branch information
asgrim authored Jan 27, 2025
2 parents 286930c + 7106f69 commit e41e560
Show file tree
Hide file tree
Showing 19 changed files with 979 additions and 32 deletions.
2 changes: 1 addition & 1 deletion .github/docs/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM ghcr.io/roave/docbooktool:1.16.0 AS builder
FROM ghcr.io/roave/docbooktool:1.19.0 AS builder

COPY ./.github/docs/templates /docs-src/templates
COPY ./docs /docs-src/book
Expand Down
43 changes: 43 additions & 0 deletions .github/docs/templates/online.twig
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>PIE Documentation</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
<link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.22.0/themes/prism.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/css/all.min.css" rel="stylesheet" />
<style>
.selected {
background-color: #7A86B8;
Expand All @@ -15,6 +17,41 @@
.hidden {
display: none;
}
.markdown-alert {
border-left: 0.25em solid black;
padding: 1em 1em 0.25em;
background-color: #f7f7f7;
}
.markdown-alert-note {
border-left-color: #0d68d5;
}
.markdown-alert-note .markdown-alert-title {
color: #0d68d5;
}
.markdown-alert-tip {
border-left-color: #188337;
}
.markdown-alert-tip .markdown-alert-title {
color: #188337;
}
.markdown-alert-important {
border-left-color: #7844d6;
}
.markdown-alert-important .markdown-alert-title {
color: #7844d6;
}
.markdown-alert-warning {
border-left-color: #a67003;
}
.markdown-alert-warning .markdown-alert-title {
color: #a67003;
}
.markdown-alert-caution {
border-left-color: #d61c28;
}
.markdown-alert-caution .markdown-alert-title {
color: #d61c28;
}
</style>
</head>
<body>
Expand Down Expand Up @@ -47,6 +84,10 @@
* @param {string} title
*/
function loadDocBookNavigation(title) {
document.querySelectorAll('table').forEach((table) => {
table.classList.add("table");
})
/**
* @param {NodeListOf<HTMLElement>} unselectedListElements
* @param {HTMLElement} selectedListElement
Expand Down Expand Up @@ -184,5 +225,7 @@
loadDocBookNavigation("PIE Documentation");
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/autoloader/prism-autoloader.js"></script>
</body>
</html>
6 changes: 6 additions & 0 deletions bin/pie
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ use Php\Pie\Command\BuildCommand;
use Php\Pie\Command\DownloadCommand;
use Php\Pie\Command\InfoCommand;
use Php\Pie\Command\InstallCommand;
use Php\Pie\Command\RepositoryAddCommand;
use Php\Pie\Command\RepositoryListCommand;
use Php\Pie\Command\RepositoryRemoveCommand;
use Php\Pie\Command\ShowCommand;
use Php\Pie\Util\PieVersion;
use Symfony\Component\Console\Application;
Expand All @@ -31,6 +34,9 @@ $application->setCommandLoader(new ContainerCommandLoader(
'install' => InstallCommand::class,
'info' => InfoCommand::class,
'show' => ShowCommand::class,
'repository:list' => RepositoryListCommand::class,
'repository:add' => RepositoryAddCommand::class,
'repository:remove' => RepositoryRemoveCommand::class,
]
));

Expand Down
2 changes: 1 addition & 1 deletion docs/extension-maintainers.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ specify a default value in the `configure-options` definition.
The `build-path` setting may be used if your source code is not in the root
of your repository. For example, if your repository structure is like:

```
```text
/
docs/
src/
Expand Down
49 changes: 44 additions & 5 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ COPY --from=ghcr.io/php/pie:bin /pie /usr/bin/pie

Instead of `bin` tag (which represents latest binary-only image) you can also use explicit version (in `x.y.z-bin` format). Use [GitHub registry](https://ghcr.io/php/pie) to find available tags.

> [!IMPORTANT]
> [!IMPORTANT]
> Binary-only images don't include PHP runtime so you can't use them for _running_ PIE. This is just an alternative way of distributing PHAR file, you still need to satisfy PIE's runtime requirements on your own.
#### Example of PIE working in a Dockerfile
Expand Down Expand Up @@ -197,7 +197,7 @@ functionality, or to provide paths to libraries not automatically detected.
In order to determine what configure options are available for an extension,
you may use `pie info <vendor>/<package>` which will return a list, such as:

```
```text
Configure options:
--enable-some-functionality (whether to enable some additional functionality provided)
--with-some-library-name=? (Path for some-library)
Expand All @@ -215,6 +215,45 @@ pie install example/some-extension --with-some-library-name=/path/to/the/lib --e

### Configuring the INI file

At the moment, PIE does not configure the INI file, although this improvement
is planned soon. In the meantime, you must enable the extension after installing
by adding a line such as `extension=foo` to your `php.ini`.
PIE will automatically try to enable the extension by adding `extension=...` or
`zend_extension=...` in the appropriate INI file. If you want to disable this
behaviour, pass the `--skip-enable-extension` flag to your `pie install`
command. The following techniques are used to attempt to enable the extension:

* `phpenmod`, if using the deb.sury.org distribution
* `docker-php-ext-enable` if using Docker's PHP image
* Add a new file to the "additional .ini file" path, if configured
* Append to the standard php.ini, if configured

If none of these techniques work, or you used the `--skip-enable-extension`
flag, PIE will warn you that the extension was not enabled, and will note that
you must enable the extension yourself.

### Adding non-Packagist.org repositories

Sometimes you may want to install an extension from a package repository other
than Packagist.org (such as [Private Packagist](https://packagist.com/)), or
from a local directory. Since PIE is based heavily on Composer, it is possible
to use some other repository types:

* `pie repository:add [--with-php-config=...] path /path/to/your/local/extension`
* `pie repository:add [--with-php-config=...] vcs https://github.com/youruser/yourextension`
* `pie repository:add [--with-php-config=...] composer https://repo.packagist.com/your-private-packagist/`
* `pie repository:add [--with-php-config=...] composer packagist.org`

The `repository:*` commands all support the optional `--with-php-config` flag
to allow you to specify which PHP installation to use (for example, if you have
multiple PHP installations on one machine). The above added repositories can be
removed too, using the inverse `repository:remove` commands:

* `pie repository:remove [--with-php-config=...] /path/to/your/local/extension`
* `pie repository:remove [--with-php-config=...] https://github.com/youruser/yourextension`
* `pie repository:remove [--with-php-config=...] https://repo.packagist.com/your-private-packagist/`
* `pie repository:remove [--with-php-config=...] packagist.org`

Note you do not need to specify the repository type in `repository:remove`,
just the URL.

You can list the repositories for the target PHP installation with:

* `pie repository:list [--with-php-config=...]`
2 changes: 1 addition & 1 deletion features/install-extensions.feature
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Feature: Extensions can be installed with Behat
Feature: Extensions can be installed with PIE

Example: The latest version of an extension can be downloaded
When I run a command to download the latest version of an extension
Expand Down
11 changes: 11 additions & 0 deletions features/manage-repositories.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Feature: Package repositories can be managed with PIE

Example: A package repository can be added
Given no repositories have previously been added
When I add a package repository
Then I should see the package repository can be used by PIE

Example: A package repository can be removed
Given I have previously added a package repository
When I remove the package repository
Then I should see the package repository is not used by PIE
44 changes: 44 additions & 0 deletions src/Command/CommandHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@

namespace Php\Pie\Command;

use Composer\Composer;
use Composer\Package\Version\VersionParser;
use Composer\Repository\ComposerRepository;
use Composer\Repository\PathRepository;
use Composer\Repository\VcsRepository;
use Composer\Util\Platform;
use InvalidArgumentException;
use Php\Pie\DependencyResolver\Package;
Expand Down Expand Up @@ -263,4 +267,44 @@ public static function processConfigureOptionsFromInput(Package $package, InputI

return $configureOptionsValues;
}

public static function listRepositories(Composer $composer, OutputInterface $output): void
{
$output->writeln('The following repositories are in use for this Target PHP:');

foreach ($composer->getRepositoryManager()->getRepositories() as $repo) {
if ($repo instanceof ComposerRepository) {
$repoConfig = $repo->getRepoConfig();

$repoUrl = array_key_exists('url', $repoConfig) && is_string($repoConfig['url']) && $repoConfig['url'] !== '' ? $repoConfig['url'] : null;

if ($repoUrl === 'https://repo.packagist.org') {
$output->writeln(' - Packagist');
continue;
}

$output->writeln(sprintf(' - Composer (%s)', $repoUrl ?? 'no url?'));
continue;
}

if ($repo instanceof VcsRepository) {
/** @psalm-suppress InternalMethod */
$output->writeln(sprintf(
' - VCS Repository (%s)',
$repo->getDriver()?->getUrl() ?? 'no url?',
));
continue;
}

if (! $repo instanceof PathRepository) {
continue;
}

$repoConfig = $repo->getRepoConfig();
$output->writeln(sprintf(
' - Path Repository (%s)',
array_key_exists('url', $repoConfig) && is_string($repoConfig['url']) && $repoConfig['url'] !== '' ? $repoConfig['url'] : 'no path?',
));
}
}
}
97 changes: 97 additions & 0 deletions src/Command/RepositoryAddCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php

declare(strict_types=1);

namespace Php\Pie\Command;

use Php\Pie\ComposerIntegration\PieComposerFactory;
use Php\Pie\ComposerIntegration\PieComposerRequest;
use Php\Pie\ComposerIntegration\PieJsonEditor;
use Psr\Container\ContainerInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Webmozart\Assert\Assert;

use function realpath;
use function str_contains;

#[AsCommand(
name: 'repository:add',
description: 'Add a new repository for packages that PIE can use.',
)]
final class RepositoryAddCommand extends Command
{
private const ARG_TYPE = 'type';
private const ARG_URL = 'url';

private const ALLOWED_TYPES = ['vcs', 'path', 'composer'];

public function __construct(
private readonly ContainerInterface $container,
) {
parent::__construct();
}

public function configure(): void
{
parent::configure();

CommandHelper::configurePhpConfigOptions($this);

$this->addArgument(
self::ARG_TYPE,
InputArgument::REQUIRED,
'Specify the type of the repository, e.g. vcs, path, composer',
);
$this->addArgument(
self::ARG_URL,
InputArgument::REQUIRED,
'Specify the URL of the repository, e.g. a Github/Gitlab URL, a filesystem path, or Private Packagist URL',
);
}

public function execute(InputInterface $input, OutputInterface $output): int
{
$targetPlatform = CommandHelper::determineTargetPlatformFromInputs($input, $output);
$pieJsonEditor = PieJsonEditor::fromTargetPlatform($targetPlatform);

$type = (string) $input->getArgument(self::ARG_TYPE);
/** @psalm-var 'vcs'|'path'|'composer' $type */
Assert::inArray($type, self::ALLOWED_TYPES);

$url = $originalUrl = (string) $input->getArgument(self::ARG_URL);

if ($type === 'path') {
$url = realpath($originalUrl);
}

if ($type === 'composer' && str_contains($url, 'packagist.org')) {
// "adding packagist" is really just removing an exclusion
$pieJsonEditor
->ensureExists()
->removeRepository('packagist.org');
} else {
Assert::stringNotEmpty($url, 'Could not resolve ' . $originalUrl . ' to a real path');

$pieJsonEditor
->ensureExists()
->addRepository($type, $url);
}

CommandHelper::listRepositories(
PieComposerFactory::createPieComposer(
$this->container,
PieComposerRequest::noOperation(
$output,
$targetPlatform,
),
),
$output,
);

return 0;
}
}
49 changes: 49 additions & 0 deletions src/Command/RepositoryListCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

declare(strict_types=1);

namespace Php\Pie\Command;

use Php\Pie\ComposerIntegration\PieComposerFactory;
use Php\Pie\ComposerIntegration\PieComposerRequest;
use Psr\Container\ContainerInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

#[AsCommand(
name: 'repository:list',
description: 'List the package repositories that PIE uses.',
)]
final class RepositoryListCommand extends Command
{
public function __construct(
private readonly ContainerInterface $container,
) {
parent::__construct();
}

public function configure(): void
{
parent::configure();

CommandHelper::configurePhpConfigOptions($this);
}

public function execute(InputInterface $input, OutputInterface $output): int
{
CommandHelper::listRepositories(
PieComposerFactory::createPieComposer(
$this->container,
PieComposerRequest::noOperation(
$output,
CommandHelper::determineTargetPlatformFromInputs($input, $output),
),
),
$output,
);

return 0;
}
}
Loading

0 comments on commit e41e560

Please sign in to comment.