Initial commit of new codebase
This commit is contained in:
commit
00ebb6ff95
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
vendor
|
||||||
|
composer.lock
|
||||||
|
makephar.phar
|
4
bin/makephar
Executable file
4
bin/makephar
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__."/../src/bootstrap.php";
|
22
composer.json
Normal file
22
composer.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"name": "noccylabs/makephar",
|
||||||
|
"description": "Build portable phar executables and libraries",
|
||||||
|
"type": "application",
|
||||||
|
"license": "GPL-3.0",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Christopher Vagnetoft",
|
||||||
|
"email": "cvagnetoft@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"noccylabs/sdl": "^2.0",
|
||||||
|
"symfony/finder": "^3.2"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [ "src/global.php" ],
|
||||||
|
"psr-0":{
|
||||||
|
"": "src/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
makephar.sdl
Normal file
19
makephar.sdl
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
phar "makephar.phar" {
|
||||||
|
|
||||||
|
// Set to true to build a library-only phar
|
||||||
|
library false;
|
||||||
|
|
||||||
|
// Set to 1, 2 or 3 to compress, doesn't work for libraries
|
||||||
|
compress false;
|
||||||
|
|
||||||
|
// Set stub
|
||||||
|
stub "src/bootstrap.php";
|
||||||
|
|
||||||
|
// Select files/dirs to include
|
||||||
|
include {
|
||||||
|
dir "vendor";
|
||||||
|
dir "src";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
65
src/MakePhar/Application.php
Normal file
65
src/MakePhar/Application.php
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MakePhar;
|
||||||
|
|
||||||
|
class Application
|
||||||
|
{
|
||||||
|
|
||||||
|
protected $config;
|
||||||
|
|
||||||
|
private function parseCommandLine()
|
||||||
|
{
|
||||||
|
$opts = "h";
|
||||||
|
$long = [ 'help' ];
|
||||||
|
|
||||||
|
$parsed = getopt($opts, $long);
|
||||||
|
$config = [
|
||||||
|
'help' => false,
|
||||||
|
'manifest' => getcwd()."/makephar.sdl",
|
||||||
|
'output' => null,
|
||||||
|
'compress' => false,
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($parsed as $k=>$v) switch ($k) {
|
||||||
|
case 'h':
|
||||||
|
case 'help':
|
||||||
|
$config['help'] = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->config = (object)$config;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function printHelp()
|
||||||
|
{
|
||||||
|
printf("Usage: makephar [opts]\n");
|
||||||
|
printf("Options: -h,--help Show this help\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
$this->parseCommandLine();
|
||||||
|
|
||||||
|
if ($this->config->help) {
|
||||||
|
$this->printHelp();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->buildManifest();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function buildManifest()
|
||||||
|
{
|
||||||
|
$manifests = Manifest::createFromFile($this->config->manifest);
|
||||||
|
|
||||||
|
foreach ($manifests as $manifest) {
|
||||||
|
log_info("Building %s", $manifest->getOutput());
|
||||||
|
$builder = new PharBuilder($manifest);
|
||||||
|
$builder->prepare();
|
||||||
|
$builder->build();
|
||||||
|
$builder->finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
154
src/MakePhar/Manifest.php
Normal file
154
src/MakePhar/Manifest.php
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MakePhar;
|
||||||
|
|
||||||
|
use Sdl\Parser\SdlParser;
|
||||||
|
use Sdl\SdlTag;
|
||||||
|
|
||||||
|
class Manifest
|
||||||
|
{
|
||||||
|
/** @var string Output filename */
|
||||||
|
protected $output = null;
|
||||||
|
/** @var int|null Mode to set on output filename */
|
||||||
|
protected $chmod = null;
|
||||||
|
/** @var string[] Included files and directories */
|
||||||
|
protected $sources = [];
|
||||||
|
/** @var bool If true, build a library instead of executable */
|
||||||
|
protected $library = false;
|
||||||
|
/** @var string|null The stub to call on */
|
||||||
|
protected $stub = null;
|
||||||
|
/** @var bool If true, the archive will be compressed */
|
||||||
|
protected $compress = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read manifests from a makephar.sdl file and return all the build targets
|
||||||
|
* defined in it.
|
||||||
|
*
|
||||||
|
* @return Manifest[] The parsed manifests
|
||||||
|
*/
|
||||||
|
public static function createFromFile($filename)
|
||||||
|
{
|
||||||
|
$root = SdlParser::parseFile($filename);
|
||||||
|
$ret = [];
|
||||||
|
foreach ($root->getChildren() as $child) {
|
||||||
|
$mf = self::createFromSdlTag($child);
|
||||||
|
$ret[] = $mf;
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a manifest from a SdlTag
|
||||||
|
*
|
||||||
|
* @return Manifest The manifest
|
||||||
|
*/
|
||||||
|
public static function createFromSdlTag(SdlTag $tag)
|
||||||
|
{
|
||||||
|
$mf = new Manifest();
|
||||||
|
|
||||||
|
// Output
|
||||||
|
$mf->setOutput($tag->getValue());
|
||||||
|
|
||||||
|
foreach ($tag->getChildren() as $child) switch ($child->getTagName()) {
|
||||||
|
case 'library':
|
||||||
|
$mf->setIsLibrary($child->getValue());
|
||||||
|
break;
|
||||||
|
case 'compress':
|
||||||
|
$mf->setCompression($child->getValue());
|
||||||
|
break;
|
||||||
|
case 'stub':
|
||||||
|
$mf->setStubFile($child->getValue());
|
||||||
|
break;
|
||||||
|
case 'include':
|
||||||
|
foreach ($child->getChildren() as $inc) switch ($inc->getTagName()) {
|
||||||
|
case 'dir':
|
||||||
|
case 'file':
|
||||||
|
$mf->addSource($inc->getTagName(),$inc->getValue(),$inc->getAttributeStrings());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $mf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function setOutput($output)
|
||||||
|
{
|
||||||
|
$this->output = $output;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOutput()
|
||||||
|
{
|
||||||
|
return $this->output;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setIsLibrary($value)
|
||||||
|
{
|
||||||
|
$this->library = (bool)$value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIsLibrary()
|
||||||
|
{
|
||||||
|
return $this->library;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setStubFile($file)
|
||||||
|
{
|
||||||
|
$this->stub = $file;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStubFile()
|
||||||
|
{
|
||||||
|
return $this->stub;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setCompression($value)
|
||||||
|
{
|
||||||
|
$this->compress = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCompression()
|
||||||
|
{
|
||||||
|
return $this->compress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addSource($type, $path, array $opts)
|
||||||
|
{
|
||||||
|
$this->sources[] = (object)[
|
||||||
|
'type' => $type,
|
||||||
|
'path' => $path,
|
||||||
|
'opts' => (object)$opts,
|
||||||
|
];
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSources()
|
||||||
|
{
|
||||||
|
return $this->sources;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findSourceFiles()
|
||||||
|
{
|
||||||
|
$items = [];
|
||||||
|
foreach ($this->sources as $source) {
|
||||||
|
if ($source->type == 'dir') {
|
||||||
|
$it = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source->path));
|
||||||
|
foreach ($it as $item) {
|
||||||
|
if ($item->isDir()) continue;
|
||||||
|
$items[] = (object)['src'=>$item->getPathname(),'dest'=>null];
|
||||||
|
}
|
||||||
|
} elseif ($source->type == 'file') {
|
||||||
|
$items[] = (object)['src'=>$source->path,'dest'=>null];
|
||||||
|
} else {
|
||||||
|
log_warn("Unsupported source type: %s", $source->type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $items;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
77
src/MakePhar/PharBuilder.php
Normal file
77
src/MakePhar/PharBuilder.php
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MakePhar;
|
||||||
|
|
||||||
|
class PharBuilder
|
||||||
|
{
|
||||||
|
|
||||||
|
protected $manifest;
|
||||||
|
|
||||||
|
protected $files = [];
|
||||||
|
|
||||||
|
protected $phar;
|
||||||
|
|
||||||
|
public function __construct(Manifest $manifest)
|
||||||
|
{
|
||||||
|
$this->manifest = $manifest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function prepare()
|
||||||
|
{
|
||||||
|
log_debug("Finding files to add...");
|
||||||
|
$this->files = $this->manifest->findSourceFiles();
|
||||||
|
log_debug("Found %d files", count($this->files));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function build()
|
||||||
|
{
|
||||||
|
// Create the phar
|
||||||
|
$phar = new \Phar("/tmp/output.phar");
|
||||||
|
|
||||||
|
// Add files
|
||||||
|
log_debug("Adding files to phar archive...");
|
||||||
|
foreach ($this->files as $file) {
|
||||||
|
$phar->addFile($file->dest?:$file->src, $file->src);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create stub
|
||||||
|
if ($this->manifest->getIsLibrary()) {
|
||||||
|
log_debug("Creating library stub...");
|
||||||
|
// Create library stub
|
||||||
|
$stub = '<?php ';
|
||||||
|
$stub.= 'if (basename(__FILE__)==basename($_SERVER["SCRIPT_FILENAME"])) { echo "Error: This is a library and can not be executed\n"; exit(1); }';
|
||||||
|
$stub.= 'require_once __DIR__."/vendor/autoload.php";';
|
||||||
|
$phar->addFromString("index.php", $stub);
|
||||||
|
} else {
|
||||||
|
log_debug("Creating application stub...");
|
||||||
|
// Write application stub
|
||||||
|
$stubfile = $this->manifest->getStubFile();
|
||||||
|
$stub = '<?php require_once __DIR__."/'.ltrim($stubfile,'/').'";';
|
||||||
|
$phar->addFromString("index.php", $stub);
|
||||||
|
// Make the phar stub executable
|
||||||
|
$mainstub = $phar->createDefaultStub("index.php");
|
||||||
|
$mainstub = "#!/usr/bin/env php\n{$mainstub}";
|
||||||
|
$phar->setStub($mainstub);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the phar
|
||||||
|
$phar = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function finalize()
|
||||||
|
{
|
||||||
|
$output = $this->manifest->getOutput();
|
||||||
|
|
||||||
|
if (file_exists($output)) {
|
||||||
|
unlink($output);
|
||||||
|
}
|
||||||
|
log_debug("Writing %s", $output);
|
||||||
|
rename("/tmp/output.phar", $output);
|
||||||
|
|
||||||
|
if (!$this->manifest->getIsLibrary()) {
|
||||||
|
chmod($output, 0777);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
6
src/bootstrap.php
Normal file
6
src/bootstrap.php
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__."/../vendor/autoload.php";
|
||||||
|
|
||||||
|
$app = new MakePhar\Application();
|
||||||
|
$app->run();
|
11
src/global.php
Normal file
11
src/global.php
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class LogFuncs {
|
||||||
|
public static function bind() {
|
||||||
|
static $bound;
|
||||||
|
if ($bound++) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function log_info($fmt,...$arg) { printf("[info] {$fmt}\n", ...$arg); }
|
||||||
|
function log_debug($fmt,...$arg) { printf("[debg] {$fmt}\n", ...$arg); }
|
||||||
|
function log_warn($fmt,...$arg) { printf("[warn] {$fmt}\n", ...$arg); }
|
Loading…
Reference in New Issue
Block a user