Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into refactor/check-sett…
Browse files Browse the repository at this point in the history
…ings
  • Loading branch information
theofidry committed Nov 21, 2023
2 parents 8cb05b5 + 1cd9751 commit d0f12cf
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 45 deletions.
52 changes: 52 additions & 0 deletions src/ExecutableFinder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

/*
* This file is part of the box project.
*
* (c) Kevin Herrera <[email protected]>
* Théo Fidry <[email protected]>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace KevinGH\Box;

use RuntimeException;
use Symfony\Component\Process\PhpExecutableFinder as SymfonyPhpExecutableFinder;

final class ExecutableFinder
{
private static string $boxExecutable;
private static string $phpExecutable;

public static function findBoxExecutable(): string
{
if (isset(self::$boxExecutable)) {
return self::$boxExecutable;
}

self::$boxExecutable = getenv(Constants::BIN) ?: $_SERVER['SCRIPT_NAME'];

return self::$boxExecutable;
}

public static function findPhpExecutable(): string
{
if (isset(self::$phpExecutable)) {
return self::$phpExecutable;
}

$phpExecutable = (new SymfonyPhpExecutableFinder())->find();

if (false === $phpExecutable) {
throw new RuntimeException('Could not find a PHP executable.');
}

self::$phpExecutable = $phpExecutable;

return self::$phpExecutable;
}
}
31 changes: 3 additions & 28 deletions src/Phar/PharInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,16 @@

use Fidry\FileSystem\FS;
use KevinGH\Box\Console\Command\Extract;
use KevinGH\Box\Constants;
use KevinGH\Box\ExecutableFinder;
use OutOfBoundsException;
use Phar;
use RuntimeException;
use Symfony\Component\Filesystem\Path;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Finder\SplFileInfo;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\PhpExecutableFinder;
use Symfony\Component\Process\Process;
use function bin2hex;
use function file_exists;
use function getenv;
use function is_readable;
use function iter\mapKeys;
use function iter\toArrayWithKeys;
Expand Down Expand Up @@ -288,8 +285,8 @@ private static function initStubFileName(): void
private static function dumpPhar(string $file, string $tmp): void
{
$extractPharProcess = new Process([
self::getPhpExecutable(),
self::getBoxBin(),
ExecutableFinder::findPhpExecutable(),
ExecutableFinder::findBoxExecutable(),
'extract',
$file,
$tmp,
Expand Down Expand Up @@ -329,28 +326,6 @@ private static function loadDumpedPharFiles(string $tmp): array
return [$meta, $dumpedFiles];
}

private static function getPhpExecutable(): string
{
if (isset(self::$phpExecutable)) {
return self::$phpExecutable;
}

$phpExecutable = (new PhpExecutableFinder())->find();

if (false === $phpExecutable) {
throw new RuntimeException('Could not find a PHP executable.');
}

self::$phpExecutable = $phpExecutable;

return self::$phpExecutable;
}

private static function getBoxBin(): string
{
return getenv(Constants::BIN) ?: $_SERVER['SCRIPT_NAME'];
}

/**
* @param array<string, array{'compression': CompressionAlgorithm, compressedSize: int}> $filesMeta
*/
Expand Down
101 changes: 84 additions & 17 deletions src/PharInfo/PharInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@

namespace KevinGH\Box\PharInfo;

use KevinGH\Box\Phar\PharInfo as NewPharInfo;
use KevinGH\Box\Phar\CompressionAlgorithm;
use Phar;
use PharData;
use PharFileInfo;
use RecursiveIteratorIterator;
use UnexpectedValueException;
use function KevinGH\Box\unique_id;
use function realpath;
Expand All @@ -27,35 +29,56 @@
*/
final class PharInfo
{
private NewPharInfo $decoratedPharInfo;
private static array $ALGORITHMS;

private PharData|Phar $phar;

public function __construct(private readonly string $pharFile)
private ?array $compressionCount = null;
private ?string $hash = null;

public function __construct(string $pharFile)
{
self::initAlgorithms();

try {
$this->phar = new Phar($pharFile);
} catch (UnexpectedValueException) {
$this->phar = new PharData($pharFile);
}
}

private static function initAlgorithms(): void
{
$this->decoratedPharInfo = new NewPharInfo($pharFile);
if (!isset(self::$ALGORITHMS)) {
self::$ALGORITHMS = [];

foreach (CompressionAlgorithm::cases() as $compressionAlgorithm) {
self::$ALGORITHMS[$compressionAlgorithm->value] = $compressionAlgorithm->name;
}
}
}

public function equals(self $pharInfo): bool
{
return $this->decoratedPharInfo->equals($pharInfo->decoratedPharInfo);
return
$pharInfo->getCompressionCount() === $this->getCompressionCount()
&& $pharInfo->getNormalizedMetadata() === $this->getNormalizedMetadata();
}

public function getCompressionCount(): array
{
return $this->decoratedPharInfo->getFilesCompressionCount();
if (null === $this->compressionCount || $this->hash !== $this->getPharHash()) {
$this->compressionCount = $this->calculateCompressionCount();
$this->compressionCount['None'] = $this->compressionCount[CompressionAlgorithm::NONE->name];
unset($this->compressionCount[CompressionAlgorithm::NONE->name]);
$this->hash = $this->getPharHash();
}

return $this->compressionCount;
}

public function getPhar(): Phar|PharData
{
if (!isset($this->phar)) {
try {
$this->phar = new Phar($this->pharFile);
} catch (UnexpectedValueException) {
$this->phar = new PharData($this->pharFile);
}
}

return $this->phar;
}

Expand All @@ -67,16 +90,60 @@ public function getRoot(): string

public function getVersion(): string
{
return $this->decoratedPharInfo->getVersion();
// Do not cache the result
return '' !== $this->phar->getVersion() ? $this->phar->getVersion() : 'No information found';
}

public function getNormalizedMetadata(): ?string
{
return $this->decoratedPharInfo->getNormalizedMetadata();
// Do not cache the result
$metadata = var_export($this->phar->getMetadata(), true);

return 'NULL' === $metadata ? null : $metadata;
}

private function getPharHash(): string
{
return $this->decoratedPharInfo->getSignature()['hash'] ?? unique_id('');
// If no signature is available (e.g. a tar.gz file), we generate a random hash to ensure
// it will always be invalidated
return $this->phar->getSignature()['hash'] ?? unique_id('');
}

private function calculateCompressionCount(): array
{
$count = array_fill_keys(
self::$ALGORITHMS,
0,
);

if ($this->phar instanceof PharData) {
$count[self::$ALGORITHMS[$this->phar->isCompressed()]] = 1;

return $count;
}

$countFile = static function (array $count, PharFileInfo $file): array {
if (false === $file->isCompressed()) {
++$count[CompressionAlgorithm::NONE->name];

return $count;
}

foreach (self::$ALGORITHMS as $compressionAlgorithmCode => $compressionAlgorithmName) {
if ($file->isCompressed($compressionAlgorithmCode)) {
++$count[$compressionAlgorithmName];

return $count;
}
}

return $count;
};

return array_reduce(
iterator_to_array(new RecursiveIteratorIterator($this->phar), true),
$countFile,
$count,
);
}
}

0 comments on commit d0f12cf

Please sign in to comment.