Added support for phar metadata
This commit is contained in:
		
							
								
								
									
										24
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								README.md
									
									
									
									
									
								
							@@ -83,6 +83,28 @@ You can follow the same approach when excluding files with the `exclude` block:
 | 
			
		||||
The `dir` rules match against `*/<dirname>/*` while the `file` rule will match
 | 
			
		||||
against `*/<filename>`.
 | 
			
		||||
 | 
			
		||||
## Metadata
 | 
			
		||||
 | 
			
		||||
As PHAR archives support metadata, you can insert your own custom data using
 | 
			
		||||
the `metadata` block:
 | 
			
		||||
 | 
			
		||||
    library; // build a library (plugin)
 | 
			
		||||
    metadata {
 | 
			
		||||
      plugin_type "myapp.plugin";
 | 
			
		||||
      plugin_name "myapp.plugin.awesomeplugin";
 | 
			
		||||
      plugin_version "1.0.0";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
You can also map props to metadata. The advantage to this is that you can scan
 | 
			
		||||
the metadata before including the .phar letting you pick the most recent versions
 | 
			
		||||
etc.
 | 
			
		||||
 | 
			
		||||
    metadata {
 | 
			
		||||
      plugin_version prop="MYPLUGIN_VERSION";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
The order is important! Make sure you have defined the props you want to reference
 | 
			
		||||
before referencing them!
 | 
			
		||||
 | 
			
		||||
## Props
 | 
			
		||||
 | 
			
		||||
@@ -142,6 +164,8 @@ If set, no minification will take place. Generally, the minification should not
 | 
			
		||||
cause any problems but lead to a file that can be up to half a megabyte smaller
 | 
			
		||||
as whitespace and comments are removed.
 | 
			
		||||
 | 
			
		||||
It is also possible to mark specific directories or files as verbatim on the
 | 
			
		||||
`dir` and `file` tags in an `include` block.
 | 
			
		||||
 | 
			
		||||
### compress (bool)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,8 @@
 | 
			
		||||
    ],
 | 
			
		||||
    "require": {
 | 
			
		||||
        "noccylabs/sdl": "^2.0",
 | 
			
		||||
        "symfony/finder": "^3.2"
 | 
			
		||||
        "symfony/finder": "^3.2",
 | 
			
		||||
        "noccylabs/tinyphar": "^0.1.1"
 | 
			
		||||
    },
 | 
			
		||||
    "autoload": {
 | 
			
		||||
        "files": [ "src/global.php" ],
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								makephar.sdl
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								makephar.sdl
									
									
									
									
									
								
							@@ -4,14 +4,22 @@ phar "makephar.phar" {
 | 
			
		||||
    // Set stub
 | 
			
		||||
    stub "src/bootstrap.php";
 | 
			
		||||
 | 
			
		||||
    props exec="props.php";
 | 
			
		||||
 | 
			
		||||
    metadata {
 | 
			
		||||
        package_name "makephar.application";
 | 
			
		||||
        package_version prop="APP_VERSION";
 | 
			
		||||
        update_channel "https://packages.noccylabs.info/channel/makephar/testing.json";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Select files/dirs to include
 | 
			
		||||
    include {
 | 
			
		||||
        dir "vendor";
 | 
			
		||||
        dir "src";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    exclude {
 | 
			
		||||
        dir ".git";
 | 
			
		||||
        dir "Tests";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -10,10 +10,17 @@ phar "output.phar" {
 | 
			
		||||
    // Define the stub called when the phar is executed
 | 
			
		||||
    stub "src/bootstrap.php";
 | 
			
		||||
 | 
			
		||||
    // Phar metadata
 | 
			
		||||
    metadata {
 | 
			
		||||
        generator "MakePhar/2.0";
 | 
			
		||||
        channel_stable "http://dist.noccylabs.info/channels/makephar/stable.json";
 | 
			
		||||
        channel_beta "http://dist.noccylabs.info/channels/makephar/beta.json";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Select files/dirs to include
 | 
			
		||||
    include {
 | 
			
		||||
        dir "vendor";
 | 
			
		||||
        dir "src";
 | 
			
		||||
        dir "src" verbatim=true; /* directories and files can be marked verbatim */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Patterns to exclude
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								props.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								props.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
function app_version() {
 | 
			
		||||
    $ver = exec("git describe --tags");
 | 
			
		||||
    $ver = explode("-",$ver);
 | 
			
		||||
    if (count($ver)>1) {
 | 
			
		||||
        $ver = array_slice($ver,0,2);
 | 
			
		||||
    }
 | 
			
		||||
    return join(".",$ver);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
printf("%s=%s\n", "APP_VERSION", app_version());
 | 
			
		||||
@@ -9,7 +9,7 @@ class Application
 | 
			
		||||
 | 
			
		||||
    private function parseCommandLine()
 | 
			
		||||
    {
 | 
			
		||||
        $opts = "hn";
 | 
			
		||||
        $opts = "hnq";
 | 
			
		||||
        $long = [ 'help', 'new' ];
 | 
			
		||||
 | 
			
		||||
        $parsed = getopt($opts, $long);
 | 
			
		||||
@@ -19,6 +19,7 @@ class Application
 | 
			
		||||
            'manifest' => getcwd()."/makephar.sdl",
 | 
			
		||||
            'output' => null,
 | 
			
		||||
            'compress' => false,
 | 
			
		||||
            'quiet' => false,
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        foreach ($parsed as $k=>$v) switch ($k) {
 | 
			
		||||
@@ -30,6 +31,9 @@ class Application
 | 
			
		||||
            case 'new':
 | 
			
		||||
                $config['init'] = true;
 | 
			
		||||
                break;
 | 
			
		||||
            case 'q':
 | 
			
		||||
                $config['quiet'] = true;
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $this->config = (object)$config;
 | 
			
		||||
@@ -40,19 +44,22 @@ class Application
 | 
			
		||||
        printf("Usage:    makephar [opts]\n");
 | 
			
		||||
        printf("Options:  -h,--help     Show this help\n");
 | 
			
		||||
        printf("          -n,--new      Create a new configuration file\n");
 | 
			
		||||
        printf("          -q            Quiet operation\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function run()
 | 
			
		||||
    {
 | 
			
		||||
        $this->parseCommandLine();
 | 
			
		||||
        
 | 
			
		||||
        if ($this->config->quiet) {
 | 
			
		||||
            define("QUIET",true);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        if ($this->config->help) {
 | 
			
		||||
            $this->printHelp();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        log_info("MakePhar 2.0 - (c) 2016-2017, NoccyLabs");
 | 
			
		||||
 | 
			
		||||
        if ($this->config->init) {
 | 
			
		||||
            if (!file_exists("composer.json")) {
 | 
			
		||||
                error_log("No composer.json in current directory");
 | 
			
		||||
@@ -62,6 +69,9 @@ class Application
 | 
			
		||||
            $proj_name = basename(getcwd()).".phar";
 | 
			
		||||
            $proj_files = [];
 | 
			
		||||
            $proj_dirs = [];
 | 
			
		||||
            printf("// makephar.sdl generated for %s\n", basename(getcwd()));
 | 
			
		||||
            printf("phar \"%s\" {\n", $proj_name);
 | 
			
		||||
            printf("  include {\n");
 | 
			
		||||
            if (!empty($proj->autoload)) {
 | 
			
		||||
                foreach ((array)$proj->autoload as $type=>$loaders) {
 | 
			
		||||
                    if ($type == 'files') {
 | 
			
		||||
@@ -75,20 +85,22 @@ class Application
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                printf("phar \"%s\" {\n", $proj_name);
 | 
			
		||||
                printf("  include {\n");
 | 
			
		||||
                foreach ($proj_files as $file)
 | 
			
		||||
                    printf("    file \"%s\";\n", $file);
 | 
			
		||||
                foreach ($proj_dirs as $dir)
 | 
			
		||||
                    printf("    dir \"%s\";\n", $dir);
 | 
			
		||||
                printf("    dir \"vendor\";\n");
 | 
			
		||||
                printf("  }\n");
 | 
			
		||||
                printf("  // stub \"src/path-to-stub.php\";\n");
 | 
			
		||||
                printf("}\n");
 | 
			
		||||
            } else {
 | 
			
		||||
                printf("    // file \"filename.php\" src=\"path/file.php\";\n");
 | 
			
		||||
                printf("    // dir \"path\";\n");
 | 
			
		||||
            }
 | 
			
		||||
            printf("  }\n");
 | 
			
		||||
            printf("  // stub \"src/path-to-stub.php\";\n");
 | 
			
		||||
            printf("}\n");
 | 
			
		||||
            
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        log_info("MakePhar 2.0 - (c) 2016-2017, NoccyLabs");
 | 
			
		||||
 | 
			
		||||
        $this->buildManifest();
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,8 @@ class Manifest
 | 
			
		||||
    protected $props = [];
 | 
			
		||||
    /** @var array Patterns to exclude */
 | 
			
		||||
    protected $excludes = [];
 | 
			
		||||
    /** @var array Phar metadata */
 | 
			
		||||
    protected $metadata = [];
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Read manifests from a makephar.sdl file and return all the build targets
 | 
			
		||||
@@ -94,6 +96,21 @@ class Manifest
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case 'metadata':
 | 
			
		||||
                foreach ($child->getChildren() as $meta) {
 | 
			
		||||
                    if (($prop = $meta->getAttribute("prop"))) {
 | 
			
		||||
                        if (array_key_exists($prop,$mf->props)) {
 | 
			
		||||
                            $value = $mf->props[$prop];
 | 
			
		||||
                        } else {
 | 
			
		||||
                            log_warn("Property %s is not defined", $prop);
 | 
			
		||||
                        }
 | 
			
		||||
                    } else {
 | 
			
		||||
                        $value = $meta->getValue();
 | 
			
		||||
                    }
 | 
			
		||||
                    $mf->setMetadata($meta->getTagName(), $value);
 | 
			
		||||
                    
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case 'props':
 | 
			
		||||
                $props = [];
 | 
			
		||||
                if ($src = (string)$child->getValue()) {
 | 
			
		||||
@@ -166,6 +183,20 @@ class Manifest
 | 
			
		||||
        return $this->stub;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setMetadata($key,$value)
 | 
			
		||||
    {
 | 
			
		||||
        $this->metadata[$key] = $value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getMetadata($key=null)
 | 
			
		||||
    {
 | 
			
		||||
        if ($key===null)
 | 
			
		||||
            return $this->metadata;
 | 
			
		||||
        if (!array_key_exists($key, $this->metadata))
 | 
			
		||||
            return null;
 | 
			
		||||
        return $this->metadata[$key];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setCompression($value)
 | 
			
		||||
    {
 | 
			
		||||
        $this->compress = $value;
 | 
			
		||||
@@ -207,14 +238,19 @@ class Manifest
 | 
			
		||||
    {
 | 
			
		||||
        $items = [];
 | 
			
		||||
        foreach ($this->sources as $source) {
 | 
			
		||||
            if (@isset($source->opts->verbatim)) {
 | 
			
		||||
                $verbatim = $source->opts->verbatim;
 | 
			
		||||
            } else {
 | 
			
		||||
                $verbatim = $this->getVerbatim();
 | 
			
		||||
            }
 | 
			
		||||
            if ($source->type == 'dir') {
 | 
			
		||||
                $it = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source->path));
 | 
			
		||||
                foreach ($it as $item) {
 | 
			
		||||
                    if ($item->isDir()) continue;
 | 
			
		||||
                    $items[] = (object)['src'=>realpath($item->getPathname()),'dest'=>$item->getPathname()];
 | 
			
		||||
                    $items[] = (object)['src'=>realpath($item->getPathname()),'dest'=>$item->getPathname(),'verbatim'=>$verbatim];
 | 
			
		||||
                }
 | 
			
		||||
            } elseif ($source->type == 'file') {
 | 
			
		||||
                $items[] = (object)['src'=>realpath($source->path),'dest'=>$item->getPathname()];
 | 
			
		||||
                $items[] = (object)['src'=>realpath($source->path),'dest'=>$source->path,'verbatim'=>$verbatim];
 | 
			
		||||
            } else {
 | 
			
		||||
                log_warn("Unsupported source type: %s", $source->type);
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -59,7 +59,7 @@ class PharBuilder
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            $size_tot += filesize($file->src);
 | 
			
		||||
            if (fnmatch("*.php",$file->src) && (!$verbatim)) {
 | 
			
		||||
            if (fnmatch("*.php",$file->src) && (!$file->verbatim)) {
 | 
			
		||||
                $min = php_strip_whitespace($file->src);
 | 
			
		||||
                $size_min += strlen($min);
 | 
			
		||||
                $phar->addFromString($file->dest?:$file->src, $min);
 | 
			
		||||
@@ -92,7 +92,7 @@ class PharBuilder
 | 
			
		||||
            log_debug("Creating library stub...");
 | 
			
		||||
            // Create library stub
 | 
			
		||||
            $stub = '<?php ';
 | 
			
		||||
            $stub.= 'require_once __DIR__."/vendor/autoload.php";';
 | 
			
		||||
            $stub.= 'file_exists(__DIR__."/vendor/autoload.php") && require_once __DIR__."/vendor/autoload.php";';
 | 
			
		||||
            foreach ($this->manifest->getProps() as $k=>$v) {
 | 
			
		||||
                $stub.= sprintf('define(%s,%s);', var_export($k,true), var_export($v,true));
 | 
			
		||||
            }
 | 
			
		||||
@@ -119,6 +119,13 @@ class PharBuilder
 | 
			
		||||
            $phar->setStub($mainstub);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Write metadata
 | 
			
		||||
        log_debug("Writing metadata...");
 | 
			
		||||
        $md = $this->manifest->getMetadata();
 | 
			
		||||
        foreach ($md as $key=>$value)
 | 
			
		||||
            log_debug("  meta[{$key}] = {$value}");
 | 
			
		||||
        $phar->setMetadata($md);
 | 
			
		||||
 | 
			
		||||
        // Close the phar
 | 
			
		||||
        $phar = null;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,6 @@ if (@empty(STDOUT) || (!posix_isatty(STDOUT))) {
 | 
			
		||||
    define("IS_TTY", true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function log_info($fmt,...$arg) { printf(LF_INFO."[info] {$fmt}".LF_RESET."\n", ...$arg); }
 | 
			
		||||
function log_debug($fmt,...$arg) { printf(LF_DEBUG."[debg] {$fmt}".LF_RESET."\n", ...$arg); }
 | 
			
		||||
function log_warn($fmt,...$arg) { printf(LF_WARN."[warn] {$fmt}".LF_RESET."\n", ...$arg); }
 | 
			
		||||
function log_info($fmt,...$arg) { defined("QUIET") || printf(LF_INFO."[info] {$fmt}".LF_RESET."\n", ...$arg); }
 | 
			
		||||
function log_debug($fmt,...$arg) { defined("QUIET") || printf(LF_DEBUG."[debg] {$fmt}".LF_RESET."\n", ...$arg); }
 | 
			
		||||
function log_warn($fmt,...$arg) { defined("QUIET") || printf(LF_WARN."[warn] {$fmt}".LF_RESET."\n", ...$arg); }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user