Skip to content

Commit

Permalink
Draft: rework Pharaoh
Browse files Browse the repository at this point in the history
  • Loading branch information
theofidry committed Mar 19, 2023
1 parent 57c1508 commit 8e7a4a7
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 37 deletions.
10 changes: 10 additions & 0 deletions build-phar.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

@unlink('demo.phar');
$phar = new Phar('demo.phar');
$phar->addFile('composer.json');
$phar->addFile('composer.lock');
$phar->compressFiles(Phar::BZ2);

$x = new PharFileInfo('phar://demo.phar/composer.lock');
$x->compress(Phar::GZ);
42 changes: 39 additions & 3 deletions src/Console/Command/Diff.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}

/**
Expand All @@ -146,6 +151,37 @@ private static function getPaths(IO $io): array
);
}

private function compareCheckSums(PharDiff $diff, IO $io): int
{
$io->comment('<info>Comparing the two archives... (do not check the signatures)</info>');

$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('<info>Comparing the two archives... (do not check the signatures)</info>');
Expand Down
91 changes: 57 additions & 34 deletions src/Pharaoh/Pharaoh.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,62 +51,41 @@
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;
use function random_bytes;
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;
Expand Down Expand Up @@ -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(),
);
}
}

0 comments on commit 8e7a4a7

Please sign in to comment.