# api: fpm
# title: PHP Phar target
# description: Chains to PHP for creating a .phar (native/tar/zip) archive
# type: package
# category: target
# version: 0.3
# state: very alpha
# license: MITL
# author: mario#include-once:org
#
# This packaging target generates simple PHP Phar assemblies. With its
# default stub assuming `__init__.php` for CLI applications, and `index.php`
# as web router. A custom --phar-stub can be set of course.
#
# It honors the output filename, but alternatively allows `--phar-format`
# overriding the packaging format. It flexibly recognizes any concatenation
# of βpharΒ·zipΒ·tarβ with βgzΒ·bz2β, case-insensitively.
#
# βββββββββββββββ¬ββββββββββββββ¬ββββββββββββββ¬ββββββββββββββ¬ββββββββββββββββ
# β Extension β Archive β Compression β Envelope β Use β
# β / Specifier β Format β Per File β Compression β Cases β
# βββββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββββ€
# β phar β Phar β - β - β β
# βββββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββββ€
# β phar.gz β Phar β gzip β - β general β
# βββββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββββ€
# β pharΒ·bz2 β Phar β bzip2 β - β β
# βββββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββββ€
# β phaZ β Phar β - β gzip β β
# βββββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββββ€
# β phaZ.gz β Phar β gzip β gzip β (eschew) β
# βββββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββββ€
# β zip β Zip β - β - β β
# βββββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββββ€
# β zip.gz β Zip β gzip β - β distribution β
# βββββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββββ€
# β zipβ¦bz2 β Zip β bzip2 β - β β
# βββββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββββ€
# β tar β Pax β - β - β β
# βββββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββββ€
# β tgz β Pax β - β gzip β β
# βββββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββββ€
# β tar+bz2 β Pax β - β bzip2 β data bundles β
# βββββββββββββββ΄ββββββββββββββ΄ββββββββββββββ΄ββββββββββββββ΄ββββββββββββββββ
#
# ZIPs and TARs can be read by other languages, but contain PHP/phar-specific
# additions (.phar/stub and a signature).
#
require "fpm/package"
require "fpm/util"
require "fileutils"
require "tempfile"
require "json"
# Phar creation (output only)
class FPM::Package::Phar < FPM::Package
option "--format", "PHAR.gz/TGZ/ZIP", "Phar package type and compression (append .gz/.bz2 for method)", :default=>"PHAR.GZ"
option "--stub", "STUB.php", "Apply initialization/stub file", :default=>""
#option "--nocase", :flag, "Lowercase filenames / implicit `-u lcase=*`", :default=>false
option "--sign", "PEM_FILE", "Sign package with OpenSSL and key from .pem file", :default=>""
option "--x", :flag, "Set executable bit on phar package", :default=>false, :hidden=>true
# Invoke PHP for actual packaging process
def output(output_path)
output_check(output_path)
# Build flags
p = {
:name => name,
:srcdir => staging_path,
#:nocase => attributes[:phar_nocase],
:stub => attributes[:phar_stub_given?] ? attributes[:phar_stub] : "",
:sign => attributes[:phar_sign],
}
# Retain package meta information, either from fpm attributes, or collected :attr hash (src module, formerly :meta)
defaults = {
"id" => @name,
"version" => @version.to_s,
"epoch" => @epoch.to_s,
"iteration" => @iteration.to_s,
"architecture" => @architecture,
"category" => @category,
"author" => @maintainer,
"url" => @url,
"license" => @license,
}.delete_if{ |k,v| ["", nil, "default", "http://example.com/no-uri-given"].include? v }
p[:meta] = attrs.merge(defaults).delete_if{ |k,v| v.empty? }
# Match format specifier/extension onto type/settings
fmt = (attributes[:phar_format] + output_path).downcase
fmt, enc = fmt.match(/zip|phaz|tar|t[gb]z|pz/).to_s||"phar", fmt.match(/gz|bz2/).to_s
map_keys = [:stdext, :format, :filegz, :extout, :hullgz]
map = {
# fmt, enc extension format per-file-gz extns β archive-compr
["phar", "" ] => [ ".phar", "Phar::PHAR", "Phar::NONE", "", "" ],
["phar", "gz" ] => [ ".phar", "Phar::PHAR", "Phar::GZ", "", "" ],
["phar", "bz2"] => [ ".phar", "Phar::PHAR", "Phar::BZ2", "", "" ],
["zip", "" ] => [ ".phar.zip", "Phar::ZIP", "Phar::NONE", "", "" ],
["zip", "gz" ] => [ ".phar.zip", "Phar::ZIP", "Phar::GZ", "", "" ],
["zip", "bz2" ] => [ ".phar.zip", "Phar::ZIP", "Phar::BZ2", "", "" ],
["tar", "" ] => [ ".phar.tar", "Phar::TAR", "Phar::NONE", "", "" ],
["tar", "gz" ] => [ ".phar.tar", "Phar::TAR", "Phar::GZ", ".gz", "Phar::GZ" ],
["tar", "bz2" ] => [ ".phar.tar", "Phar::TAR", "Phar::BZ2", ".bz2", "Phar::BZ2"],
["phaz", "" ] => [ ".phar", "Phar::PHAR", "Phar::GZ", ".gz", "Phar::GZ" ],
["phaz", "gz" ] => [ ".phar", "Phar::PHAR", "Phar::GZ", ".gz", "Phar::GZ" ],
["phaz", "bz2"] => [ ".phar", "Phar::PHAR", "Phar::GZ", ".bz2", "Phar::BZ2"],
}
ext2map = { # map file extensions
"tgz" => ["tar", "gz"],
"tbz" => ["tar", "bz2"],
"pz" => ["phaz", ""]
}
opt = map[[fmt,enc]] || map[ext2map[fmt]] || map[["phar", ""]]
p.merge! Hash[map_keys.zip opt]
# Have PHP generate the package
p[:tmpf] = ::Dir::Tmpname.create(['_\$fpm_phar_', p[:stdext]]) {}
phargen = template_dir + "/phar.php"
safesystem("php", "-dphar.readonly=0", "-derror_reporting=~0", "-ddisplay_errors=1", phargen, JSON.generate(p))
#-- but might end up with suffix, for whole-archive ->compress()ion
FileUtils.mv(p[:tmpf] + p[:extout], output_path)
FileUtils.chmod("a+x", output_path) if attributes[:phar_x_given?]
end
end # class FPM::Package::Phar