Skip to content

Commit

Permalink
Merge pull request #371 from TravisCarden/feature/fork-symfony-process
Browse files Browse the repository at this point in the history
Outright fork Symfony Process
  • Loading branch information
TravisCarden authored Jun 14, 2024
2 parents 3e4ec84 + 4655a89 commit 79817b9
Show file tree
Hide file tree
Showing 40 changed files with 1,056 additions and 78 deletions.
3 changes: 3 additions & 0 deletions infection.json5.dist
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
"source": {
"directories": [
"src"
],
"excludes": [
"Internal/SymfonyProcess"
]
},
"timeout": 30,
Expand Down
2 changes: 1 addition & 1 deletion src/Internal/Finder/Service/ExecutableFinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
use PhpTuf\ComposerStager\API\Exception\LogicException;
use PhpTuf\ComposerStager\API\Finder\Service\ExecutableFinderInterface;
use PhpTuf\ComposerStager\API\Translation\Factory\TranslatableFactoryInterface;
use PhpTuf\ComposerStager\Internal\SymfonyProcess\Service\ExecutableFinder as SymfonyExecutableFinder;
use PhpTuf\ComposerStager\Internal\Translation\Factory\TranslatableAwareTrait;
use Symfony\Component\Process\ExecutableFinder as SymfonyExecutableFinder;

/**
* @package Finder
Expand Down
4 changes: 2 additions & 2 deletions src/Internal/Process/Factory/SymfonyProcessFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
use PhpTuf\ComposerStager\API\Exception\LogicException;
use PhpTuf\ComposerStager\API\Path\Value\PathInterface;
use PhpTuf\ComposerStager\API\Translation\Factory\TranslatableFactoryInterface;
use PhpTuf\ComposerStager\Internal\SymfonyProcess\Value\FixedSymfonyProcess as SymfonyProcess;
use PhpTuf\ComposerStager\Internal\SymfonyProcess\Value\Exception\ExceptionInterface as SymfonyExceptionInterface;
use PhpTuf\ComposerStager\Internal\SymfonyProcess\Value\Process as SymfonyProcess;
use PhpTuf\ComposerStager\Internal\Translation\Factory\TranslatableAwareTrait;
use Symfony\Component\Process\Exception\ExceptionInterface as SymfonyExceptionInterface;

/**
* @package Process
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace PhpTuf\ComposerStager\Internal\Process\Factory;

use PhpTuf\ComposerStager\API\Path\Value\PathInterface;
use PhpTuf\ComposerStager\Internal\SymfonyProcess\Value\FixedSymfonyProcess as SymfonyProcess;
use PhpTuf\ComposerStager\Internal\SymfonyProcess\Value\Process as SymfonyProcess;

/**
* Creates Symfony Process objects.
Expand Down Expand Up @@ -46,7 +46,7 @@ interface SymfonyProcessFactoryInterface
* @throws \PhpTuf\ComposerStager\API\Exception\LogicException
* If the process cannot be created due to host configuration.
*
* @see \Symfony\Component\Process\Process::__construct
* @see \PhpTuf\ComposerStager\Internal\SymfonyProcess\Value\Process::__construct
*/
public function create(array $command, ?PathInterface $cwd = null, array $env = []): SymfonyProcess;
}
2 changes: 1 addition & 1 deletion src/Internal/Process/Service/OutputCallbackAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use PhpTuf\ComposerStager\API\Process\Service\OutputCallbackInterface;
use PhpTuf\ComposerStager\API\Process\Value\OutputTypeEnum;
use Symfony\Component\Process\Process as SymfonyProcess;
use PhpTuf\ComposerStager\Internal\SymfonyProcess\Value\Process as SymfonyProcess;

/**
* @package Process
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@
*/
interface OutputCallbackAdapterInterface
{
/** @see \Symfony\Component\Process\Process::readPipes */
/** @see \PhpTuf\ComposerStager\Internal\SymfonyProcess\Value\Process::readPipes */
public function __invoke(string $type, string $buffer): void;
}
2 changes: 1 addition & 1 deletion src/Internal/Process/Service/Process.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use PhpTuf\ComposerStager\API\Process\Service\ProcessInterface;
use PhpTuf\ComposerStager\API\Translation\Factory\TranslatableFactoryInterface;
use PhpTuf\ComposerStager\Internal\Process\Factory\SymfonyProcessFactoryInterface;
use PhpTuf\ComposerStager\Internal\SymfonyProcess\Value\FixedSymfonyProcess as SymfonyProcess;
use PhpTuf\ComposerStager\Internal\SymfonyProcess\Value\Process as SymfonyProcess;
use PhpTuf\ComposerStager\Internal\Translation\Factory\TranslatableAwareTrait;
use Throwable;

Expand Down
19 changes: 19 additions & 0 deletions src/Internal/SymfonyProcess/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Copyright (c) 2004-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
6 changes: 6 additions & 0 deletions src/Internal/SymfonyProcess/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Symfony Process

This directory contains a fork of the Symfony Process component at `v6.4.8`. See these issues for details:

- [[Process] Regression: Error output-handling is affecting Drupal core development by TravisCarden · Pull Request #57317 · symfony/symfony](https://github.com/symfony/symfony/pull/57317)
- [Track upstream Symfony Process regression and remove workaround · Issue #369 · php-tuf/composer-stager](https://github.com/php-tuf/composer-stager/issues/369)
82 changes: 82 additions & 0 deletions src/Internal/SymfonyProcess/Service/ExecutableFinder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace PhpTuf\ComposerStager\Internal\SymfonyProcess\Service;

/**
* Generic executable finder.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class ExecutableFinder
{
private array $suffixes = ['.exe', '.bat', '.cmd', '.com'];

/**
* Replaces default suffixes of executable.
*
* @return void
*/
public function setSuffixes(array $suffixes)
{
$this->suffixes = $suffixes;
}

/**
* Adds new possible suffix to check for executable.
*
* @return void
*/
public function addSuffix(string $suffix)
{
$this->suffixes[] = $suffix;
}

/**
* Finds an executable by name.
*
* @param string $name The executable name (without the extension)
* @param string|null $default The default to return if no executable is found
* @param array $extraDirs Additional dirs to check into
*/
public function find(string $name, ?string $default = null, array $extraDirs = []): ?string
{
$dirs = array_merge(
explode(\PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')),
$extraDirs
);

$suffixes = [''];
if ('\\' === \DIRECTORY_SEPARATOR) {
$pathExt = getenv('PATHEXT');
$suffixes = array_merge($pathExt ? explode(\PATH_SEPARATOR, $pathExt) : $this->suffixes, $suffixes);
}
foreach ($suffixes as $suffix) {
foreach ($dirs as $dir) {
if (@is_file($file = $dir.\DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === \DIRECTORY_SEPARATOR || @is_executable($file))) {
return $file;
}

if (!@is_dir($dir) && basename($dir) === $name.$suffix && @is_executable($dir)) {
return $dir;
}
}
}

$command = '\\' === \DIRECTORY_SEPARATOR ? 'where' : 'command -v --';
if (\function_exists('exec') && ($executablePath = strtok(@exec($command.' '.escapeshellarg($name)), \PHP_EOL)) && @is_executable($executablePath)) {
return $executablePath;
}

return $default;
}
}
21 changes: 21 additions & 0 deletions src/Internal/SymfonyProcess/Value/Exception/ExceptionInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace PhpTuf\ComposerStager\Internal\SymfonyProcess\Value\Exception;

/**
* Marker Interface for the Process Component.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface ExceptionInterface extends \Throwable
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace PhpTuf\ComposerStager\Internal\SymfonyProcess\Value\Exception;

/**
* InvalidArgumentException for the Process Component.
*
* @author Romain Neutron <imprec@gmail.com>
*/
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
21 changes: 21 additions & 0 deletions src/Internal/SymfonyProcess/Value/Exception/LogicException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace PhpTuf\ComposerStager\Internal\SymfonyProcess\Value\Exception;

/**
* LogicException for the Process Component.
*
* @author Romain Neutron <imprec@gmail.com>
*/
class LogicException extends \LogicException implements ExceptionInterface
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace PhpTuf\ComposerStager\Internal\SymfonyProcess\Value\Exception;

use PhpTuf\ComposerStager\Internal\SymfonyProcess\Value\Process;

/**
* Exception for failed processes.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class ProcessFailedException extends RuntimeException
{
private Process $process;

public function __construct(Process $process)
{
if ($process->isSuccessful()) {
throw new InvalidArgumentException('Expected a failed process, but the given process was successful.');
}

$error = sprintf('The command "%s" failed.'."\n\nExit Code: %s(%s)\n\nWorking directory: %s",
$process->getCommandLine(),
$process->getExitCode(),
$process->getExitCodeText(),
$process->getWorkingDirectory()
);

if (!$process->isOutputDisabled()) {
$error .= sprintf("\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s",
$process->getOutput(),
$process->getErrorOutput()
);
}

parent::__construct($error);

$this->process = $process;
}

/**
* @return Process
*/
public function getProcess()
{
return $this->process;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace PhpTuf\ComposerStager\Internal\SymfonyProcess\Value\Exception;

use PhpTuf\ComposerStager\Internal\SymfonyProcess\Value\Process;

/**
* Exception that is thrown when a process has been signaled.
*
* @author Sullivan Senechal <soullivaneuh@gmail.com>
*/
final class ProcessSignaledException extends RuntimeException
{
private Process $process;

public function __construct(Process $process)
{
$this->process = $process;

parent::__construct(sprintf('The process has been signaled with signal "%s".', $process->getTermSignal()));
}

public function getProcess(): Process
{
return $this->process;
}

public function getSignal(): int
{
return $this->getProcess()->getTermSignal();
}
}
Loading

0 comments on commit 79817b9

Please sign in to comment.