Ajout des vendor
This commit is contained in:
45
vendor/symfony/flex/src/Update/DiffHelper.php
vendored
Normal file
45
vendor/symfony/flex/src/Update/DiffHelper.php
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
<?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 Symfony\Flex\Update;
|
||||
|
||||
class DiffHelper
|
||||
{
|
||||
public static function removeFilesFromPatch(string $patch, array $files, array &$removedPatches): string
|
||||
{
|
||||
foreach ($files as $filename) {
|
||||
$start = strpos($patch, sprintf('diff --git a/%s b/%s', $filename, $filename));
|
||||
if (false === $start) {
|
||||
throw new \LogicException(sprintf('Could not find file "%s" in the patch.', $filename));
|
||||
}
|
||||
|
||||
$end = strpos($patch, 'diff --git a/', $start + 1);
|
||||
$contentBefore = substr($patch, 0, $start);
|
||||
if (false === $end) {
|
||||
// last patch in the file
|
||||
$removedPatches[$filename] = rtrim(substr($patch, $start), "\n");
|
||||
$patch = rtrim($contentBefore, "\n");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$removedPatches[$filename] = rtrim(substr($patch, $start, $end - $start), "\n");
|
||||
$patch = $contentBefore.substr($patch, $end);
|
||||
}
|
||||
|
||||
// valid patches end with a blank line
|
||||
if ($patch && "\n" !== substr($patch, \strlen($patch) - 1, 1)) {
|
||||
$patch = $patch."\n";
|
||||
}
|
||||
|
||||
return $patch;
|
||||
}
|
||||
}
|
45
vendor/symfony/flex/src/Update/RecipePatch.php
vendored
Normal file
45
vendor/symfony/flex/src/Update/RecipePatch.php
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
<?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 Symfony\Flex\Update;
|
||||
|
||||
class RecipePatch
|
||||
{
|
||||
private $patch;
|
||||
private $blobs;
|
||||
private $removedPatches;
|
||||
|
||||
public function __construct(string $patch, array $blobs, array $removedPatches = [])
|
||||
{
|
||||
$this->patch = $patch;
|
||||
$this->blobs = $blobs;
|
||||
$this->removedPatches = $removedPatches;
|
||||
}
|
||||
|
||||
public function getPatch(): string
|
||||
{
|
||||
return $this->patch;
|
||||
}
|
||||
|
||||
public function getBlobs(): array
|
||||
{
|
||||
return $this->blobs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Patches for modified files that were removed because the file
|
||||
* has been deleted in the user's project.
|
||||
*/
|
||||
public function getRemovedPatches(): array
|
||||
{
|
||||
return $this->removedPatches;
|
||||
}
|
||||
}
|
226
vendor/symfony/flex/src/Update/RecipePatcher.php
vendored
Normal file
226
vendor/symfony/flex/src/Update/RecipePatcher.php
vendored
Normal file
@ -0,0 +1,226 @@
|
||||
<?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 Symfony\Flex\Update;
|
||||
|
||||
use Composer\IO\IOInterface;
|
||||
use Composer\Util\ProcessExecutor;
|
||||
use Symfony\Component\Filesystem\Exception\IOException;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
|
||||
class RecipePatcher
|
||||
{
|
||||
private $rootDir;
|
||||
private $filesystem;
|
||||
private $io;
|
||||
private $processExecutor;
|
||||
|
||||
public function __construct(string $rootDir, IOInterface $io)
|
||||
{
|
||||
$this->rootDir = $rootDir;
|
||||
$this->filesystem = new Filesystem();
|
||||
$this->io = $io;
|
||||
$this->processExecutor = new ProcessExecutor($io);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the patch. If it fails unexpectedly, an exception will be thrown.
|
||||
*
|
||||
* @return bool returns true if fully successful, false if conflicts were encountered
|
||||
*/
|
||||
public function applyPatch(RecipePatch $patch): bool
|
||||
{
|
||||
if (!$patch->getPatch()) {
|
||||
// nothing to do!
|
||||
return true;
|
||||
}
|
||||
|
||||
$addedBlobs = $this->addMissingBlobs($patch->getBlobs());
|
||||
|
||||
$patchPath = $this->rootDir.'/_flex_recipe_update.patch';
|
||||
file_put_contents($patchPath, $patch->getPatch());
|
||||
|
||||
try {
|
||||
$this->execute('git update-index --refresh', $this->rootDir);
|
||||
|
||||
$output = '';
|
||||
$statusCode = $this->processExecutor->execute('git apply "_flex_recipe_update.patch" -3', $output, $this->rootDir);
|
||||
|
||||
if (0 === $statusCode) {
|
||||
// successful with no conflicts
|
||||
return true;
|
||||
}
|
||||
|
||||
if (false !== strpos($this->processExecutor->getErrorOutput(), 'with conflicts')) {
|
||||
// successful with conflicts
|
||||
return false;
|
||||
}
|
||||
|
||||
throw new \LogicException('Error applying the patch: '.$this->processExecutor->getErrorOutput());
|
||||
} finally {
|
||||
unlink($patchPath);
|
||||
// clean up any temporary blobs
|
||||
foreach ($addedBlobs as $filename) {
|
||||
unlink($filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function generatePatch(array $originalFiles, array $newFiles): RecipePatch
|
||||
{
|
||||
// null implies "file does not exist"
|
||||
$originalFiles = array_filter($originalFiles, function ($file) {
|
||||
return null !== $file;
|
||||
});
|
||||
$newFiles = array_filter($newFiles, function ($file) {
|
||||
return null !== $file;
|
||||
});
|
||||
|
||||
// find removed files and add them so they will be deleted
|
||||
foreach ($originalFiles as $file => $contents) {
|
||||
if (!isset($newFiles[$file])) {
|
||||
$newFiles[$file] = null;
|
||||
}
|
||||
}
|
||||
|
||||
// If a file is being modified, but does not exist in the current project,
|
||||
// it cannot be patched. We generate the diff for these, but then remove
|
||||
// it from the patch (and optionally report this diff to the user).
|
||||
$modifiedFiles = array_intersect_key(array_keys($originalFiles), array_keys($newFiles));
|
||||
$deletedModifiedFiles = [];
|
||||
foreach ($modifiedFiles as $modifiedFile) {
|
||||
if (!file_exists($this->rootDir.'/'.$modifiedFile) && $originalFiles[$modifiedFile] !== $newFiles[$modifiedFile]) {
|
||||
$deletedModifiedFiles[] = $modifiedFile;
|
||||
}
|
||||
}
|
||||
|
||||
$tmpPath = sys_get_temp_dir().'/_flex_recipe_update'.uniqid(mt_rand(), true);
|
||||
$this->filesystem->mkdir($tmpPath);
|
||||
|
||||
try {
|
||||
$this->execute('git init', $tmpPath);
|
||||
$this->execute('git config commit.gpgsign false', $tmpPath);
|
||||
$this->execute('git config user.name "Flex Updater"', $tmpPath);
|
||||
$this->execute('git config user.email ""', $tmpPath);
|
||||
|
||||
$blobs = [];
|
||||
if (\count($originalFiles) > 0) {
|
||||
$this->writeFiles($originalFiles, $tmpPath);
|
||||
$this->execute('git add -A', $tmpPath);
|
||||
$this->execute('git commit -m "original files"', $tmpPath);
|
||||
|
||||
$blobs = $this->generateBlobs($originalFiles, $tmpPath);
|
||||
}
|
||||
|
||||
$this->writeFiles($newFiles, $tmpPath);
|
||||
$this->execute('git add -A', $tmpPath);
|
||||
|
||||
$patchString = $this->execute('git diff --cached', $tmpPath);
|
||||
$removedPatches = [];
|
||||
$patchString = DiffHelper::removeFilesFromPatch($patchString, $deletedModifiedFiles, $removedPatches);
|
||||
|
||||
return new RecipePatch(
|
||||
$patchString,
|
||||
$blobs,
|
||||
$removedPatches
|
||||
);
|
||||
} finally {
|
||||
try {
|
||||
$this->filesystem->remove($tmpPath);
|
||||
} catch (IOException $e) {
|
||||
// this can sometimes fail due to git file permissions
|
||||
// if that happens, just leave it: we're in the temp directory anyways
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function writeFiles(array $files, string $directory): void
|
||||
{
|
||||
foreach ($files as $filename => $contents) {
|
||||
$path = $directory.'/'.$filename;
|
||||
if (null === $contents) {
|
||||
if (file_exists($path)) {
|
||||
unlink($path);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!file_exists(\dirname($path))) {
|
||||
$this->filesystem->mkdir(\dirname($path));
|
||||
}
|
||||
file_put_contents($path, $contents);
|
||||
}
|
||||
}
|
||||
|
||||
private function execute(string $command, string $cwd): string
|
||||
{
|
||||
$output = '';
|
||||
$statusCode = $this->processExecutor->execute($command, $output, $cwd);
|
||||
|
||||
if (0 !== $statusCode) {
|
||||
throw new \LogicException(sprintf('Command "%s" failed: "%s". Output: "%s".', $command, $this->processExecutor->getErrorOutput(), $output));
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds git blobs for each original file.
|
||||
*
|
||||
* For patching to work, each original file & contents needs to be
|
||||
* available to git as a blob. This is because the patch contains
|
||||
* the ref to the original blob, and git uses that to find the
|
||||
* original file (which is needed for the 3-way merge).
|
||||
*/
|
||||
private function addMissingBlobs(array $blobs): array
|
||||
{
|
||||
$addedBlobs = [];
|
||||
foreach ($blobs as $hash => $contents) {
|
||||
$blobPath = $this->rootDir.'/'.$this->getBlobPath($hash);
|
||||
if (file_exists($blobPath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$addedBlobs[] = $blobPath;
|
||||
if (!file_exists(\dirname($blobPath))) {
|
||||
$this->filesystem->mkdir(\dirname($blobPath));
|
||||
}
|
||||
file_put_contents($blobPath, $contents);
|
||||
}
|
||||
|
||||
return $addedBlobs;
|
||||
}
|
||||
|
||||
private function generateBlobs(array $originalFiles, string $originalFilesRoot): array
|
||||
{
|
||||
$addedBlobs = [];
|
||||
foreach ($originalFiles as $filename => $contents) {
|
||||
// if the file didn't originally exist, no blob needed
|
||||
if (!file_exists($originalFilesRoot.'/'.$filename)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$hash = trim($this->execute('git hash-object '.ProcessExecutor::escape($filename), $originalFilesRoot));
|
||||
$addedBlobs[$hash] = file_get_contents($originalFilesRoot.'/'.$this->getBlobPath($hash));
|
||||
}
|
||||
|
||||
return $addedBlobs;
|
||||
}
|
||||
|
||||
private function getBlobPath(string $hash): string
|
||||
{
|
||||
$hashStart = substr($hash, 0, 2);
|
||||
$hashEnd = substr($hash, 2);
|
||||
|
||||
return '.git/objects/'.$hashStart.'/'.$hashEnd;
|
||||
}
|
||||
}
|
114
vendor/symfony/flex/src/Update/RecipeUpdate.php
vendored
Normal file
114
vendor/symfony/flex/src/Update/RecipeUpdate.php
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
<?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 Symfony\Flex\Update;
|
||||
|
||||
use Symfony\Flex\Lock;
|
||||
use Symfony\Flex\Recipe;
|
||||
|
||||
class RecipeUpdate
|
||||
{
|
||||
private $originalRecipe;
|
||||
private $newRecipe;
|
||||
private $lock;
|
||||
private $rootDir;
|
||||
|
||||
/** @var string[] */
|
||||
private $originalRecipeFiles = [];
|
||||
/** @var string[] */
|
||||
private $newRecipeFiles = [];
|
||||
private $copyFromPackagePaths = [];
|
||||
|
||||
public function __construct(Recipe $originalRecipe, Recipe $newRecipe, Lock $lock, string $rootDir)
|
||||
{
|
||||
$this->originalRecipe = $originalRecipe;
|
||||
$this->newRecipe = $newRecipe;
|
||||
$this->lock = $lock;
|
||||
$this->rootDir = $rootDir;
|
||||
}
|
||||
|
||||
public function getOriginalRecipe(): Recipe
|
||||
{
|
||||
return $this->originalRecipe;
|
||||
}
|
||||
|
||||
public function getNewRecipe(): Recipe
|
||||
{
|
||||
return $this->newRecipe;
|
||||
}
|
||||
|
||||
public function getLock(): Lock
|
||||
{
|
||||
return $this->lock;
|
||||
}
|
||||
|
||||
public function getRootDir(): string
|
||||
{
|
||||
return $this->rootDir;
|
||||
}
|
||||
|
||||
public function getPackageName(): string
|
||||
{
|
||||
return $this->originalRecipe->getName();
|
||||
}
|
||||
|
||||
public function setOriginalFile(string $filename, ?string $contents): void
|
||||
{
|
||||
$this->originalRecipeFiles[$filename] = $contents;
|
||||
}
|
||||
|
||||
public function setNewFile(string $filename, ?string $contents): void
|
||||
{
|
||||
$this->newRecipeFiles[$filename] = $contents;
|
||||
}
|
||||
|
||||
public function addOriginalFiles(array $files)
|
||||
{
|
||||
foreach ($files as $file => $contents) {
|
||||
if (null === $contents) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->setOriginalFile($file, $contents);
|
||||
}
|
||||
}
|
||||
|
||||
public function addNewFiles(array $files)
|
||||
{
|
||||
foreach ($files as $file => $contents) {
|
||||
if (null === $contents) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->setNewFile($file, $contents);
|
||||
}
|
||||
}
|
||||
|
||||
public function getOriginalFiles(): array
|
||||
{
|
||||
return $this->originalRecipeFiles;
|
||||
}
|
||||
|
||||
public function getNewFiles(): array
|
||||
{
|
||||
return $this->newRecipeFiles;
|
||||
}
|
||||
|
||||
public function getCopyFromPackagePaths(): array
|
||||
{
|
||||
return $this->copyFromPackagePaths;
|
||||
}
|
||||
|
||||
public function addCopyFromPackagePath(string $source, string $target)
|
||||
{
|
||||
$this->copyFromPackagePaths[$source] = $target;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user