From 4f33394c77ab250fcfd0b50e19fdc9c7f4c2aeba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ste=CC=81phane=20Goetz?= Date: Tue, 14 Jul 2015 23:35:47 +0200 Subject: [PATCH] Compile archive to phar --- bin/compile | 17 +++ composer.json | 3 +- composer.lock | 51 ++++++++- libs/Compiler.php | 166 ++++++++++++++++++++++++++++++ libs/Daux.php | 12 ++- vendor/composer/autoload_psr4.php | 1 + vendor/composer/installed.json | 51 +++++++++ 7 files changed, 295 insertions(+), 6 deletions(-) create mode 100755 bin/compile create mode 100644 libs/Compiler.php diff --git a/bin/compile b/bin/compile new file mode 100755 index 0000000..832aed5 --- /dev/null +++ b/bin/compile @@ -0,0 +1,17 @@ +#!/usr/bin/env php +compile(); +} catch (\Exception $e) { + echo 'Failed to compile phar: ['.get_class($e).'] '.$e->getMessage().' at '.$e->getFile().':'.$e->getLine(); + exit(1); +} diff --git a/composer.json b/composer.json index 41ad4b9..1ddc56d 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,8 @@ "league/plates": "~3.1", "guzzlehttp/guzzle": "~5.3", "league/commonmark": "0.8.*", - "symfony/console": "~2.7" + "symfony/console": "~2.7", + "symfony/finder": "~2.7" }, "autoload": { "psr-4": {"Todaymade\\Daux\\": "libs/"} diff --git a/composer.lock b/composer.lock index ceffecc..bd3d968 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "eda78cf80f9699aa99725c4330a8830a", + "hash": "da1775dfe76954e5e731cba81179b910", "packages": [ { "name": "guzzlehttp/guzzle", @@ -378,6 +378,55 @@ "description": "Symfony Console Component", "homepage": "https://symfony.com", "time": "2015-07-09 16:07:40" + }, + { + "name": "symfony/finder", + "version": "v2.7.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/Finder.git", + "reference": "ae0f363277485094edc04c9f3cbe595b183b78e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Finder/zipball/ae0f363277485094edc04c9f3cbe595b183b78e4", + "reference": "ae0f363277485094edc04c9f3cbe595b183b78e4", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com", + "time": "2015-07-09 16:07:40" } ], "packages-dev": [], diff --git a/libs/Compiler.php b/libs/Compiler.php new file mode 100644 index 0000000..b088a23 --- /dev/null +++ b/libs/Compiler.php @@ -0,0 +1,166 @@ + + * @author Jordi Boggiano + * @author Stéphane Goetz + */ +class Compiler +{ + /** + * Compiles composer into a single phar file + * + * @throws \RuntimeException + * @param string $pharFile The full path to the file to create + */ + public function compile($pharFile = 'daux.phar') + { + if (file_exists($pharFile)) { + unlink($pharFile); + } + + $phar = new \Phar($pharFile, 0, 'daux.phar'); + $phar->setSignatureAlgorithm(\Phar::SHA1); + + $phar->startBuffering(); + + // Daux + $finder = new Finder(); + $finder->files() + ->ignoreVCS(true) + ->name('*.php') + ->notName('Compiler.php') + ->in(__DIR__ . '/../templates') + ->in(__DIR__); + + foreach ($finder as $file) { + $this->addFile($phar, $file); + } + + // Composer libraries + $finder = new Finder(); + $finder->files() + ->ignoreVCS(true) + ->exclude('Tests') + ->in(__DIR__ . '/../vendor/symfony/console') + ->in(__DIR__ . '/../vendor/guzzlehttp/guzzle/src/') + ->in(__DIR__ . '/../vendor/guzzlehttp/ringphp/src/') + ->in(__DIR__ . '/../vendor/guzzlehttp/streams/src/') + ->in(__DIR__ . '/../vendor/league/commonmark/src/') + ->in(__DIR__ . '/../vendor/league/plates/src/') + ->in(__DIR__ . '/../vendor/react/promise/src/'); + + foreach ($finder as $file) { + $this->addFile($phar, $file); + } + + // Composer autoload + $this->addFile($phar, new \SplFileInfo(__DIR__ . '/../vendor/autoload.php')); + $this->addFile($phar, new \SplFileInfo(__DIR__ . '/../vendor/composer/autoload_classmap.php')); + $this->addFile($phar, new \SplFileInfo(__DIR__ . '/../vendor/composer/autoload_files.php')); + $this->addFile($phar, new \SplFileInfo(__DIR__ . '/../vendor/composer/autoload_namespaces.php')); + $this->addFile($phar, new \SplFileInfo(__DIR__ . '/../vendor/composer/autoload_psr4.php')); + $this->addFile($phar, new \SplFileInfo(__DIR__ . '/../vendor/composer/autoload_real.php')); + $this->addFile($phar, new \SplFileInfo(__DIR__ . '/../vendor/composer/ClassLoader.php')); + $this->addBinary($phar); + + // Stubs + $phar->setStub($this->getStub()); + + $phar->stopBuffering(); + + $this->addFile($phar, new \SplFileInfo(__DIR__ . '/../LICENSE'), false); + + unset($phar); + } + + private function addFile($phar, $file, $strip = true) + { + $path = strtr(str_replace(dirname(__DIR__) . DIRECTORY_SEPARATOR, '', $file->getRealPath()), '\\', '/'); + + $content = file_get_contents($file); + if ($strip) { + $content = $this->stripWhitespace($content); + } elseif ('LICENSE' === basename($file)) { + $content = "\n" . $content . "\n"; + } + + $phar->addFromString($path, $content); + } + + private function addBinary($phar) + { + $content = file_get_contents(__DIR__ . '/../generate.php'); + //$content = preg_replace('{^#!/usr/bin/env php\s*}', '', $content); + $phar->addFromString('generate.php', $content); + } + + /** + * Removes whitespace from a PHP source string while preserving line numbers. + * + * @param string $source A PHP string + * @return string The PHP string with the whitespace removed + */ + private function stripWhitespace($source) + { + if (!function_exists('token_get_all')) { + return $source; + } + + $output = ''; + foreach (token_get_all($source) as $token) { + if (is_string($token)) { + $output .= $token; + } elseif (in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) { + $output .= str_repeat("\n", substr_count($token[1], "\n")); + } elseif (T_WHITESPACE === $token[0]) { + // reduce wide spaces + $whitespace = preg_replace('{[ \t]+}', ' ', $token[1]); + // normalize newlines to \n + $whitespace = preg_replace('{(?:\r\n|\r|\n)}', "\n", $whitespace); + // trim leading spaces + $whitespace = preg_replace('{\n +}', "\n", $whitespace); + $output .= $whitespace; + } else { + $output .= $token[1]; + } + } + + return $output; + } + + private function getStub() + { + return <<<'EOF' +#!/usr/bin/env php + + * + * For the full copyright and license information, please view + * the license that is located at the bottom of this file. + */ + +define('PHAR_DIR', dirname(__FILE__)); + +Phar::mapPhar('daux.phar'); + +require 'phar://daux.phar/generate.php'; + +__HALT_COMPILER(); +EOF; + } +} diff --git a/libs/Daux.php b/libs/Daux.php index 02ca792..bdb65b3 100644 --- a/libs/Daux.php +++ b/libs/Daux.php @@ -9,6 +9,7 @@ class Daux public static $VALID_MARKDOWN_EXTENSIONS; public $local_base; + public $internal_base; private $docs_path; /** @@ -25,7 +26,11 @@ class Daux { $this->mode = $mode; - $this->local_base = dirname(__DIR__); + $this->local_base = $this->internal_base = dirname(__DIR__); + + if (defined('PHAR_DIR')) { + $this->local_base = PHAR_DIR; + } } public static function initConstants() @@ -113,8 +118,7 @@ class Daux } /** - * @todo make it an object - * @return array + * @return Config */ public function getParams() { @@ -127,7 +131,7 @@ class Daux 'mode' => $this->mode, 'local_base' => $this->local_base, 'docs_path' => $this->docs_path, - 'templates' => $this->local_base . DS . 'templates', + 'templates' => $this->internal_base . DS . 'templates', ]; $this->options->conservativeMerge($default); diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 34988f8..1a9e77b 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -7,6 +7,7 @@ $baseDir = dirname($vendorDir); return array( 'Todaymade\\Daux\\' => array($baseDir . '/libs'), + 'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'), 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'), 'React\\Promise\\' => array($vendorDir . '/react/promise/src'), 'League\\Plates\\' => array($vendorDir . '/league/plates/src'), diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 065a379..5ec31ca 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -152,5 +152,56 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com" + }, + { + "name": "symfony/finder", + "version": "v2.7.2", + "version_normalized": "2.7.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/Finder.git", + "reference": "ae0f363277485094edc04c9f3cbe595b183b78e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Finder/zipball/ae0f363277485094edc04c9f3cbe595b183b78e4", + "reference": "ae0f363277485094edc04c9f3cbe595b183b78e4", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7" + }, + "time": "2015-07-09 16:07:40", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com" } ]