diff --git a/build-phar.php b/build-phar.php
new file mode 100644
index 000000000..68c4dd8c5
--- /dev/null
+++ b/build-phar.php
@@ -0,0 +1,10 @@
+addFile('composer.json');
+$phar->addFile('composer.lock');
+$phar->compressFiles(Phar::BZ2);
+
+$x = new PharFileInfo('phar://demo.phar/composer.lock');
+$x->compress(Phar::GZ);
diff --git a/src/Console/Command/Diff.php b/src/Console/Command/Diff.php
index a77a21f0d..2229e53f2 100644
--- a/src/Console/Command/Diff.php
+++ b/src/Console/Command/Diff.php
@@ -29,6 +29,8 @@
use Throwable;
use Webmozart\Assert\Assert;
use function array_map;
+use function array_search;
+use function array_sum;
use function count;
// TODO: migrate to Safe API
use function is_string;
@@ -122,10 +124,13 @@ public function execute(IO $io): int
return ExitCode::FAILURE;
}
- $result1 = $this->compareArchives($diff, $io);
- $result2 = $this->compareContents($diff, $io);
+ $results = [
+ $this->compareCheckSums($diff, $io),
+ $this->compareArchives($diff, $io),
+ $this->compareContents($diff, $io),
+ ];
- return $result1 + $result2;
+ return array_sum($results);
}
/**
@@ -146,6 +151,37 @@ private static function getPaths(IO $io): array
);
}
+ private function compareCheckSums(PharDiff $diff, IO $io): int
+ {
+ $io->comment('Comparing the two archives... (do not check the signatures)');
+
+ $pharInfoA = $diff->getPharA()->getPharInfo();
+ $pharInfoB = $diff->getPharB()->getPharInfo();
+
+ if ($pharInfoA->equals($pharInfoB)) {
+ $io->success('The two archives are identical');
+
+ return ExitCode::SUCCESS;
+ }
+
+ self::renderArchive(
+ $diff->getPharA()->getFileName(),
+ $pharInfoA,
+ $io,
+ );
+
+ $io->newLine();
+
+ self::renderArchive(
+ $diff->getPharB()->getFileName(),
+ $pharInfoB,
+ $io,
+ );
+
+ return ExitCode::FAILURE;
+ }
+
+
private function compareArchives(PharDiff $diff, IO $io): int
{
$io->comment('Comparing the two archives... (do not check the signatures)');
diff --git a/src/Pharaoh/Pharaoh.php b/src/Pharaoh/Pharaoh.php
index bc3c2e191..3a12f8e38 100644
--- a/src/Pharaoh/Pharaoh.php
+++ b/src/Pharaoh/Pharaoh.php
@@ -51,6 +51,7 @@
use function file_exists;
use function file_put_contents;
use function KevinGH\Box\FileSystem\copy;
+use function KevinGH\Box\FileSystem\dump_file;
use function KevinGH\Box\FileSystem\mkdir;
use function KevinGH\Box\FileSystem\remove;
use function KevinGH\Box\FileSystem\tempnam;
@@ -58,55 +59,33 @@
use function sys_get_temp_dir;
use const DIRECTORY_SEPARATOR;
+/**
+ * Pharaoh is a wrapper around Phar
+ */
final class Pharaoh
{
- public Phar $phar;
-
- public string $tmp;
-
- public static string $stubfile;
+ private static string $stubfile;
+ private Phar $phar;
+ private string $tmp;
private string $fileName;
private ?PharInfo $pharInfo = null;
private ?string $path = null;
- public function __construct(string $file, ?string $alias = null)
+ public function __construct(string $file)
{
Assert::readable($file);
- Assert::true(
+ Assert::false(
PharPhpSettings::isReadonly(),
'Pharaoh cannot be used if phar.readonly is enabled in php.ini',
);
- // Set the static variable here
- if (!isset(self::$stubfile)) {
- self::$stubfile = Hex::encode(random_bytes(12)).'.pharstub';
- }
-
- // We have to give every one a different alias, or it pukes.
- $alias ??= (Hex::encode(random_bytes(16)).'.phar');
-
- $tmpFile = sys_get_temp_dir().DIRECTORY_SEPARATOR.$alias;
- copy($file, $tmpFile);
-
- $phar = new Phar($tmpFile);
- $phar->setAlias($alias);
-
- // Make a random folder in /tmp
- /** @var string|bool $tmp */
- $tmp = tempnam(sys_get_temp_dir(), 'phr_');
+ self::initStubFileName();
- Assert::false(file_exists($tmp));
- mkdir($tmp, 0o755);
-
- // Let's extract to our temporary directory
- $phar->extractTo($tmp);
+ $tmp = self::createTmpDir();
+ $phar = self::createTmpPhar($file);
- // Also extract the stub
- file_put_contents(
- $tmp.'/'.self::$stubfile,
- $phar->getStub()
- );
+ self::extractPhar($phar, $tmp);
$this->tmp = $tmp;
$this->phar = $phar;
@@ -139,4 +118,48 @@ public function getPharInfo(): PharInfo
return $this->pharInfo;
}
+
+ private static function initStubFileName(): void
+ {
+ if (!isset(self::$stubfile)) {
+ self::$stubfile = Hex::encode(random_bytes(12)).'.pharstub';
+ }
+ }
+
+ private static function createTmpPhar(string $file): Phar
+ {
+ // We have to give every one a different alias, or it pukes.
+ $alias = Hex::encode(random_bytes(16)).'.phar';
+
+ $tmpFile = sys_get_temp_dir().DIRECTORY_SEPARATOR.$alias;
+ copy($file, $tmpFile);
+
+ $phar = new Phar($tmpFile);
+ $phar->setAlias($alias);
+
+ return $phar;
+ }
+
+ private static function createTmpDir(): string
+ {
+ $tmp = tempnam(sys_get_temp_dir(), 'box_');
+
+ remove($tmp);
+ mkdir($tmp, 0o755);
+
+ return $tmp;
+ }
+
+ private static function extractPhar(Phar $phar, string $tmp): void
+ {
+ // Extract the PHAR content
+ $phar->extractTo($tmp);
+
+ // Extract the stub; Phar::extractTo() does not do it since it
+ // is internal to the PHAR.
+ dump_file(
+ $tmp.DIRECTORY_SEPARATOR.self::$stubfile,
+ $phar->getStub(),
+ );
+ }
}