Cross package maker. DEB/RPM generation or conversion. Derived from jordansissel/fpm.

⌈⌋ branch:  cross package maker


Check-in [40a7170c71]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix default attributes filtering. Rework map_phar() classmap building to avoid chdir().
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 40a7170c71195eaabe91bfc68049ba17df5a950b
User & Date: mario 2015-01-21 21:55:13
Context
2015-01-21
21:58
Reinstate RPM support. Fix lesser than dependency versions. Consolidate package_typ() for prior use (::filter abbrv). Keep @in_bundle again. Use RPM "php-composer(vnd/pkg)" dependencies now for :rpm, together with a self-provides "php-composer(@in_bundle) = @version". Alternatives for literal package names not supported by RPMbuild (4.11). check-in: f28593b104 user: mario tags: trunk
21:55
Fix default attributes filtering. Rework map_phar() classmap building to avoid chdir(). check-in: 40a7170c71 user: mario tags: trunk
13:10
Implement classmap builder directly in -t phar plugin. (Original implementation and tokenizer alternative in Canonic_Autoloader.) check-in: 5c62338e56 user: mario tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to lib/fpm/package/phar.rb.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

# api: fpm
# title: PHP Phar target
# description: Chains to PHP for creating a .phar (native/tar/zip) archive
# type: package
# category: target
# version: 0.2
# 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.






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 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.
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

89
90
91
92
93
94
95
96
      :srcdir => staging_path,
      #:nocase => attributes[:phar_nocase],
      :stub   => attributes[:phar_stub_given?] ? staging_path + "/" + attributes[:phar_stub] : "",
      :sign   => attributes[:phar_sign],
    }
    
    # Retain package meta information, either from fpm attributes, or collected :attr hash (src module, formerly :meta)
    p[:meta] = attrs.merge({
      "id" => @name,
      "version" => @version.to_s,
      "epoch" => @epoch.to_s,
      "iteration" => @iteration.to_s,
      "architecture" => @architecture,
      "category" => @category == "none" ? nil : @category,
      "author" => @maintainer,
      "url" => @url,
      "license" => @license,

    }).delete_if{ |k,v| v.nil? || v==""}
    
    # 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







|





|



>
|







72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
      :srcdir => staging_path,
      #:nocase => attributes[:phar_nocase],
      :stub   => attributes[:phar_stub_given?] ? staging_path + "/" + 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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
    }
    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_reporing=~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)
    File.unlink(p[:tmpf]) if File.exists?(p[:tmpf])
  end

end # class FPM::Package::Phar







|







115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
    }
    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)
    File.unlink(p[:tmpf]) if File.exists?(p[:tmpf])
  end

end # class FPM::Package::Phar

Changes to templates/phar.php.

1
2
3
4
5

6
7
8
9
10
11
12
<?php
/**
 * api: php
 * title: Phar generation
 * description: PHP script template to get Phar assembled

 *
 * Used as template php script for -t phar building.
 * Extracts passed Ruby variables as PHP strings, so some
 * need constant(), strlen() or boolean interpretation.
 *
 */






>







1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
/**
 * api: php
 * title: Phar generation
 * description: PHP script template to get Phar assembled
 * version: 0.3
 *
 * Used as template php script for -t phar building.
 * Extracts passed Ruby variables as PHP strings, so some
 * need constant(), strlen() or boolean interpretation.
 *
 */

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
 * Phar meta data
 *  · Use injected JSON blob.
 *  · Contains at least fpm package infos,
 *  · May contain additional fields - attrs{} from `-s src` or `composer` module
 *  · Also build and include a class `map` structure.
 */
if ($meta) {
   map_phar($p, $meta, $srcdir);
   $p->setMetadata($meta);
}


/**
 * Complete packaging
 *  · Set per-file compression







|







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
 * Phar meta data
 *  · Use injected JSON blob.
 *  · Contains at least fpm package infos,
 *  · May contain additional fields - attrs{} from `-s src` or `composer` module
 *  · Also build and include a class `map` structure.
 */
if ($meta) {
   $meta["map"] = map_phar($p, $srcdir);
   $p->setMetadata($meta);
}


/**
 * Complete packaging
 *  · Set per-file compression
78
79
80
81
82
83
84
85
86
87
88
89
90
91


92
93

94






95


96
97
98
99
100
101
102




103
104
105
106
107
108
109
}




/**
 * Traverse Phar entries and augment Phar meta class/function/const `map`,
 * which lists identifiers as: ns\vnd\name => internal-filename.php simply.
 *
 * Needs to manually reread the directory and files, because freshly-built
 * Phars` RecursiveDirectoryIterator + offsetGet() won't function.
 *
 */
function map_phar($p, &$meta, $dir) {


   $meta["map"] = array("class"=>array(), "function"=>array(), "const"=>array());
   chdir($dir);

   foreach (new RegexIterator(new RecursiveIteratorIterator(new RecursiveDirectoryIterator(".")), "~^(?!.*tests?/).+\.php$~") as $fn) {






      $fn = substr($fn, 2);


      $def = new RegexPhpIdentifierDeclarations(file_get_contents($fn));
      foreach ($def->identifiers() as $type=>$list) {
         foreach ($list as $id) {
            $meta["map"][$type][strtolower($id)] = $fn;
         }
      }
   }




}



/**
 * @source  shared.phar
 * @license Public Domain







|


|


|
>
>
|
|
>
|
>
>
>
>
>
>
|
>
>


|
<
|
|
|
>
>
>
>







79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110

111
112
113
114
115
116
117
118
119
120
121
122
123
124
}




/**
 * Traverse Phar entries and augment Phar meta class/function/const `map`,
 * which lists identifiers as "vnd\pkg\class" => "internal-filename.php".
 *
 * Needs to manually reread the directory and files, because freshly-built
 * Phars` RecursiveDirectoryIterator + offsetGet() return zilch.
 *
 */
function map_phar($p, $dir) {

   // prepare empty map
   $map = array("class"=>array(), "function"=>array(), "const"=>array());
   
   // switch to staging dir, but keep old path as reference
   $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
   $it = new RegexIterator($it, "~^(?!.*tests?/).+\.php$~");
   
   // only read .php files
   foreach ($it as $fn) {

      // cut off $dir prefix      
      $int_fn = ltrim(substr($fn, strlen($dir)), "/");

      // collect identifiers
      $def = new RegexPhpIdentifierDeclarations(file_get_contents($fn));
      foreach ($def->identifiers() as $type=>$list) {
         $map[$type] = array_merge($map[$type], array_fill_keys($list, $int_fn));

      }
   }

   // prepare for PHP compliant case-insensitive lookups
   $map["class"] = array_change_key_case($map["class"]);
   $map["function"] = array_change_key_case($map["function"]);
   return $map;
}



/**
 * @source  shared.phar
 * @license Public Domain