Skip to content

Commit 924d519

Browse files
committed
Adding phar compile system
1 parent da6dbf2 commit 924d519

File tree

3 files changed

+208
-0
lines changed

3 files changed

+208
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
/vendor/
22
/tests/_output
33
/var/
4+
/docs.phar

bin/compile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/usr/bin/env php
2+
<?php
3+
4+
require __DIR__.'/../vendor/autoload.php';
5+
6+
use SymfonyDocsBuilder\Phar\Compiler;
7+
8+
error_reporting(-1);
9+
ini_set('display_errors', 1);
10+
11+
try {
12+
$compiler = new Compiler();
13+
$compiler->compile();
14+
} catch (\Exception $e) {
15+
echo 'Failed to compile phar: ['.get_class($e).'] '.$e->getMessage().' at '.$e->getFile().':'.$e->getLine();
16+
exit(1);
17+
}

src/Phar/Compiler.php

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
<?php
2+
3+
namespace SymfonyDocsBuilder\Phar;
4+
5+
use Symfony\Component\Finder\Finder;
6+
use Symfony\Component\Process\Process;
7+
8+
/**
9+
* The Compiler class compiles composer into a phar.
10+
*
11+
* Originally adapted from Composer.
12+
*
13+
* @author Fabien Potencier <fabien@symfony.com>
14+
* @author Jordi Boggiano <j.boggiano@seld.be>
15+
* @author Ryan Weaver <ryan@knplabs.com>
16+
*/
17+
class Compiler
18+
{
19+
private $version;
20+
private $versionDate;
21+
22+
/**
23+
* Compiles composer into a single phar file
24+
*
25+
* @throws \RuntimeException
26+
* @param string $pharFile The full path to the file to create
27+
*/
28+
public function compile($pharFile = 'docs.phar')
29+
{
30+
if (file_exists($pharFile)) {
31+
unlink($pharFile);
32+
}
33+
34+
$process = new Process('git log --pretty="%H" -n1 HEAD', __DIR__);
35+
if ($process->run() != 0) {
36+
throw new \RuntimeException('Can\'t run git log.');
37+
}
38+
$this->version = trim($process->getOutput());
39+
40+
$process = new Process('git log -n1 --pretty=%ci HEAD', __DIR__);
41+
if ($process->run() != 0) {
42+
throw new \RuntimeException('Can\'t run git log.');
43+
}
44+
$date = new \DateTime(trim($process->getOutput()));
45+
$date->setTimezone(new \DateTimeZone('UTC'));
46+
$this->versionDate = $date->format('Y-m-d H:i:s');
47+
48+
$process = new Process('git describe --tags HEAD');
49+
if ($process->run() == 0) {
50+
$this->version = trim($process->getOutput());
51+
}
52+
53+
$phar = new \Phar($pharFile, 0, $pharFile);
54+
$phar->setSignatureAlgorithm(\Phar::SHA1);
55+
56+
$phar->startBuffering();
57+
58+
$finder = new Finder();
59+
$finder->files()
60+
->ignoreVCS(true)
61+
->name('*.php')
62+
->notName('Compiler.php')
63+
->in(__DIR__.'/..')
64+
;
65+
66+
foreach ($finder as $file) {
67+
$this->addFile($phar, $file);
68+
}
69+
70+
$finder = new Finder();
71+
$finder->files()
72+
->ignoreVCS(true)
73+
->name('*.php')
74+
->exclude('Tests')
75+
->in(__DIR__.'/../../vendor/doctrine/')
76+
->in(__DIR__.'/../../vendor/psr/')
77+
->in(__DIR__.'/../../vendor/scrivo/')
78+
->in(__DIR__.'/../../vendor/symfony/')
79+
->in(__DIR__.'/../../vendor/twig/')
80+
->in(__DIR__.'/../../vendor/guzzlehttp/')
81+
->in(__DIR__.'/../../vendor/ralouphie/')
82+
;
83+
84+
foreach ($finder as $file) {
85+
$this->addFile($phar, $file);
86+
}
87+
88+
89+
$this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/autoload.php'));
90+
$this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/autoload_namespaces.php'));
91+
$this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/autoload_psr4.php'));
92+
$this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/autoload_classmap.php'));
93+
$this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/autoload_files.php'));
94+
$this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/autoload_real.php'));
95+
$this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/autoload_static.php'));
96+
if (file_exists(__DIR__.'/../../vendor/composer/include_paths.php')) {
97+
$this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/include_paths.php'));
98+
}
99+
$this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/ClassLoader.php'));
100+
$this->addConsoleBin($phar);
101+
102+
// Stubs
103+
$phar->setStub($this->getStub());
104+
105+
$phar->stopBuffering();
106+
107+
// disabled for interoperability with systems without gzip ext
108+
// $phar->compressFiles(\Phar::GZ);
109+
110+
$this->addFile($phar, new \SplFileInfo(__DIR__.'/../../LICENSE'), false);
111+
112+
unset($phar);
113+
}
114+
115+
private function addFile($phar, $file, $strip = true)
116+
{
117+
$path = strtr(str_replace(dirname(dirname(__DIR__)).DIRECTORY_SEPARATOR, '', $file->getRealPath()), '\\', '/');
118+
119+
$content = file_get_contents($file);
120+
if ($strip) {
121+
$content = $this->stripWhitespace($content);
122+
}
123+
124+
$phar->addFromString($path, $content);
125+
}
126+
127+
private function addConsoleBin($phar)
128+
{
129+
$content = file_get_contents(__DIR__.'/../../bin/console');
130+
$content = preg_replace('{^#!/usr/bin/env php\s*}', '', $content);
131+
$phar->addFromString('bin/console', $content);
132+
}
133+
134+
/**
135+
* Removes whitespace from a PHP source string while preserving line numbers.
136+
*
137+
* @param string $source A PHP string
138+
* @return string The PHP string with the whitespace removed
139+
*/
140+
private function stripWhitespace($source)
141+
{
142+
if (!function_exists('token_get_all')) {
143+
return $source;
144+
}
145+
146+
$output = '';
147+
foreach (token_get_all($source) as $token) {
148+
if (is_string($token)) {
149+
$output .= $token;
150+
} elseif (in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) {
151+
$output .= str_repeat("\n", substr_count($token[1], "\n"));
152+
} elseif (T_WHITESPACE === $token[0]) {
153+
// reduce wide spaces
154+
$whitespace = preg_replace('{[ \t]+}', ' ', $token[1]);
155+
// normalize newlines to \n
156+
$whitespace = preg_replace('{(?:\r\n|\r|\n)}', "\n", $whitespace);
157+
// trim leading spaces
158+
$whitespace = preg_replace('{\n +}', "\n", $whitespace);
159+
$output .= $whitespace;
160+
} else {
161+
$output .= $token[1];
162+
}
163+
}
164+
165+
return $output;
166+
}
167+
168+
private function getStub()
169+
{
170+
$stub = <<<'EOF'
171+
#!/usr/bin/env php
172+
<?php
173+
/*
174+
* This file is part of the Docs Builder.
175+
*
176+
* For the full copyright and license information, please view
177+
* the license that is located at the bottom of this file.
178+
*/
179+
180+
Phar::mapPhar('docs.phar');
181+
182+
EOF;
183+
184+
return $stub . <<<'EOF'
185+
require 'phar://docs.phar/bin/console';
186+
187+
__HALT_COMPILER();
188+
EOF;
189+
}
190+
}

0 commit comments

Comments
 (0)