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

⌈⌋ ⎇ branch:  cross package maker


src

-s src input plugin

The "src" module allows packaging scripting language apps through self-referencing package infos.

It extracts package information from the first given input file. It looks for a top-level comment block with key: value fields. It's language-agnostic and understands coherent # lines or // comments and multiline /*...*/ blocks.

# title: FooBar
# description: does the stuff
# version: 0.2
# architecture: all
# license: BSDL
# pack: lib/dependency.py, ext/*.py, doc/README
# 
# Remainder of documentation block
# is used as long description ...

Field names almost literally map to fpm packaging options. Command line flags (--description, --version, etc.) still can override extracted meta fields. Extra fields may be utilized by specific target plugins (-t phar does).

Recursive pack: specifier

The src plugin mainly cares about the # pack: list, which references other file/script names to include.

  • Simple comma-separated file lists:

    • It can just enumerate file1, file2, file3.py plain files.
    • Or list files in subdirs lib/file4, ../also.txt
  • Similar to the dir source, it may also rename files:

    • With src=dest, file5=file6.txt
    • Or move them into target subdirectories file7=lib/file7
      (The target directory directory can be an absolute path, if the fpm --prefix flag isn't used.)
  • Use glob patterns:

    • Where *.py, *.txt includes matching files from the current directory.
    • And lib/*.py recurses into a subdirectory.
    • Remap directory contents with lib/*.sh=/opt/app/lib/shell/
  • Recursion: Each referenced script file is scanned for pack: specifiers of its own.

    • For example, let the main script reference lib/submodule.py. Then all file references in the pack: line of submodule.py are treated as basenames within the lib/ source directory.
    • This allows for simple file-to-file dependency chains / grouping. And submodules don't have to care themselves about their source residence, but only need to know neighboring/relative scripts.
  • Files can even exclude themselves from packaging with pack: myself.py=

It's actually rather simple in practice, and self-explanatory for each file. But see also src.rb for a more concise summary of how file relations are handled.

Use cases

For small projects a single pack: specifier in the main script/file often suffices. It just lists files to be included and general package description fields. Which then allows terse invocations like:

fpm -s src -t deb,rpm  main.sh

It's getting more interesting for modularized packages:

  • Main source file st2.py

     # pack: st2.py=bin/streamtuner2,
     #       channels/__init__.py=share/streamtuner2/channels/
    
  • And channels/__init__.py referencing the desired submodules

     # pack: a*, m*, y*, z*.png
    

From an actual example, which in reality isn't actually doing that. (Currently just packaging *.* all modules therein.)

Notes

The meta format is losely based on Generic PHP Plugins and also recognized by the versionnum copying tool. It's not yet formalized, but was very much designed with cross-language compatibility in mind.

For FPM/XPM the inset script basename also becomes the package name in absence of an id: field.

The remainder of the comment (after the meta fields) will substitute as long --description field.

So basically this scheme provides a file-embedded .fpm option and --inputs specification scheme; with just more generalized field names.

It could also be utilized for packaging binary apps. Simply craft a spec.txt file with # comment markers and key:value fields. The spec file can exclude itself with # pack: spec.txt=, bin/* for example.

With --src-only recursive pack: line lookups are disabled. Only the pack: list from the primary input file is acted on then.