Skip to content

Commit

Permalink
up: optimize phar package build speed
Browse files Browse the repository at this point in the history
  • Loading branch information
inhere committed Dec 1, 2019
1 parent 159b51c commit 1055fff
Showing 1 changed file with 104 additions and 74 deletions.
178 changes: 104 additions & 74 deletions src/console/src/Advanced/PharCompiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use RuntimeException;
use Seld\PharUtils\Timestamps;
use SplFileInfo;
use SplQueue;
use Swoft\Stdlib\Helper\Dir;
use Swoft\Stdlib\Helper\FSHelper;
use Swoft\Stdlib\Helper\Sys;
Expand All @@ -33,8 +34,6 @@
use function is_file;
use function is_string;
use function ltrim;
use function openssl_pkey_export;
use function openssl_pkey_get_details;
use function preg_replace;
use function realpath;
use function str_replace;
Expand Down Expand Up @@ -62,6 +61,9 @@ class PharCompiler
public const ON_SKIP = 'skip';
public const ON_ERROR = 'error';

public const ON_MESSAGE = 'message';
public const ON_COLLECTED = 'collected';

/** @var array */
private static $supportedSignatureTypes = [
Phar::SHA512 => 1,
Expand Down Expand Up @@ -172,6 +174,8 @@ class PharCompiler
*/
private $versionFile = '';

private $versionFileContent = '';

// -------------------- internal properties --------------------

/** @var int */
Expand All @@ -197,6 +201,11 @@ class PharCompiler
*/
private $modifies;

/**
* @var SplQueue
*/
private $fileQueue;

/**
* @param string $pharFile
* @param string $extractTo
Expand Down Expand Up @@ -240,7 +249,8 @@ public function __construct(string $basePath)
{
self::checkEnv();

$this->basePath = realpath($basePath);
$this->basePath = realpath($basePath);
$this->fileQueue = new SplQueue();

if (!is_dir($this->basePath)) {
throw new RuntimeException("The inputted path is not exists. PATH: {$this->basePath}");
Expand Down Expand Up @@ -399,7 +409,7 @@ public function setModifies($modifies): self
* @throws InvalidArgumentException
* @throws Exception
*/
public function pack(string $pharFile, $refresh = true): string
public function pack(string $pharFile, bool $refresh = true): string
{
if (!$this->directories) {
throw new RuntimeException("Please setting the 'directories' want building directories by 'in()'");
Expand Down Expand Up @@ -430,36 +440,25 @@ public function pack(string $pharFile, $refresh = true): string
$phar->setSignatureAlgorithm($this->selectSignatureType());
}

$basePath = $this->basePath;
$phar->startBuffering();
// Collect files
$this->collectFiles($exists, $refresh);

// Only build modifies
if (!$refresh && $exists && $this->modifies) {
foreach ($this->modifies as $file) {
if ('/' === $file[0] || is_file($file = $basePath . '/' . $file)) {
$this->packFile($phar, new SplFileInfo($file));
}
}
} else {
// Collect files in there are dirs.
foreach ($this->directories as $directory) {
foreach ($this->findFiles($directory) as $file) {
$this->packFile($phar, $file);
}
}
}
// Begin packing
$this->fire(self::ON_COLLECTED, $this->counter);
$phar->startBuffering();

// Add special files
foreach ($this->files as $filename) {
if ('/' === $filename[0] || is_file($filename = $basePath . '/' . $filename)) {
$this->packFile($phar, new SplFileInfo($filename));
}
}
$this->fire(self::ON_MESSAGE, 'Files collect complete, begin add file to Phar');
$phar->buildFromIterator($this->fileQueue, $this->basePath);

// Add index files
$this->packIndexFile($phar);

// Stubs
// Add version file
if ($content = $this->versionFileContent) {
$phar->addFromString($this->versionFile, $content);
}

// Add Stubs
// $phar->setDefaultStub($this->cliIndex, $this->webIndex));
$phar->setStub($this->createStub());

Expand All @@ -477,6 +476,7 @@ public function pack(string $pharFile, $refresh = true): string
// 'Date' => date('Y-m-d')
// );
// $phar->setMetadata($metaData);
$this->fire(self::ON_MESSAGE, 'Write requests to the Phar archive, save changes to disk');
$phar->stopBuffering();
unset($phar);

Expand All @@ -490,6 +490,68 @@ public function pack(string $pharFile, $refresh = true): string
return $pharFile;
}

/**
* @param bool $exists
* @param bool $refresh
*/
protected function collectFiles(bool $exists, bool $refresh): void
{
$basePath = $this->basePath;

// Only build modifies
if (!$refresh && $exists && $this->modifies) {
foreach ($this->modifies as $file) {
if ('/' === $file[0] || is_file($file = $basePath . '/' . $file)) {
$this->collectFileInfo(new SplFileInfo($file));
}
}
} else {
// Collect files in there are dirs.
foreach ($this->directories as $directory) {
foreach ($this->findFiles($directory) as $fileInfo) {
$this->collectFileInfo($fileInfo);
}
}
}

// Add special files
foreach ($this->files as $filename) {
if ('/' === $filename[0] || is_file($filename = $basePath . '/' . $filename)) {
// $this->packFile($phar, new SplFileInfo($filename));
$this->collectFileInfo(new SplFileInfo($filename));
}
}
}

/**
* @param SplFileInfo $file
*/
protected function collectFileInfo(SplFileInfo $file): void
{
$filePath = $file->getPathname();

// Skip not exist file
if (!file_exists($filePath)) {
$this->fire(self::ON_ERROR, "File $filePath is not exists!");
return;
}

$this->counter++;
$relativePath = $this->getRelativeFilePath($file);

$this->fire(self::ON_ADD, $relativePath, $this->counter);

// have version file
if ($relativePath === $this->versionFile) {
$content = file_get_contents($filePath);
// save content
$this->versionFileContent = $this->addVersionInfo($content);
return;
}

$this->fileQueue->push($file);
}

/**
* find changed or new created files by git status.
* @throws RuntimeException
Expand Down Expand Up @@ -537,56 +599,16 @@ protected function findFiles(string $directory)
}

/**
* Add a file to the Phar.
* @param Phar $phar
* @param SplFileInfo $file
* @param string $content
*
* @return string
*/
private function packFile(Phar $phar, SplFileInfo $file): void
private function addVersionInfo(string $content): string
{
$filePath = $file->getPathname();

// skip error
if (!file_exists($filePath)) {
$this->fire(self::ON_ERROR, "File $filePath is not exists!");
return;
}

$strip = $this->stripComments;
$path = $this->getRelativeFilePath($file);

$this->counter++;
$this->fire(self::ON_ADD, $path, $this->counter);

// clear php file comments
if ($strip && strpos($path, '.php')) {
$filter = $this->stripFilter;

if (!$filter || $filter($file)) {
$content = $this->stripWhitespace(file_get_contents($filePath));

// add content to phar
$phar->addFromString(
$path,
$this->addVersionInfo($content) . "\n// added by phar pack"
);
return;
}
}

// have versionFile
if ($path === $this->versionFile) {
$content = file_get_contents($filePath);

$phar->addFromString($path, $this->addVersionInfo($content));
return;
if (!$this->collectVersionInfo) {
return $content;
}

// add file to phar
$phar->addFile($filePath, $path);
}

private function addVersionInfo(string $content): string
{
return str_replace([
'{@package_last_commit}',
'{@package_last_version}',
Expand Down Expand Up @@ -1008,4 +1030,12 @@ public function getPharFile(): string
{
return $this->pharFile;
}

/**
* @return int
*/
public function getFileCount(): int
{
return $this->fileQueue->count();
}
}

0 comments on commit 1055fff

Please sign in to comment.