Simple tool to snapshot the current directory to the package file or into subrelease archive.
I have used a packing script since around 2000. First, it was a few lines of shell script, later a big one with html generator, and now small again. I still use it today, even alongside git.
The inspiration came when somebody told me that compressing a file once or ten times is the same.
The hit-enter usage is: subrelease
, subrelease
, subrelease
, increment version,
subrelease
, subrelease
...
This is a sequence of several 'small' subreleases which are handled automatically, then a 'big' release, then the next round of subreleases, etc. If it is git, it would be a sequence of commits, then tag (plus release), and the next round of commits. When subrelease is used over the git repository, subreleases are completely independent of the git.
Subrelease itself does:
- identifies package name, version, subversion, and location of archive files (automatically),
- identifies whether now it should be a subrelease or release (automatically),
- saves package snapshot into an archive or a release file (automatically),
- increments subrelease variable value if needed (automatically).
Subrelease saves two types of files:
release files: .tlz
files containing just the package itself (saved after the version increment),
archive files: .xlz
files containing subrelease snapshots of a package between version increments.
The .tlz
and .xlz
are shortcuts for .tar.lz
and can be extracted with
standard tar. Optionally, subrelease can save .tar.gz
, .tbz2
, .tar.zst
,
etc. All these files are saved into the parent directory, or the ../tgz
directory
if it exists.
Typical subrelease history and saved files would be:
Subrelease can archive variants of a package, for instance, the "beta" variant,
or David's variant "david" etc. To create a beta variant of the package, just set
the flag VARIANT
to "beta" (when you increment a version). Later when you
decide to turn off beta status, just remove the flag and call the subrelease.
You will have beta release and main release packages, and a common archive for
beta and main subreleases:
Variant flags can be used to create temporary experimental variants of the package to be eventually merged back later. In the following example, we copy the subversion b of the package to a different directory and set a variant flag on it. Then on the next subrelease call, we got the local initial release of the variant "david", and on the second call, a subversion archive is created and initiated with a new subrelease c. This subrelease c and the main package subrelease c are different. Archives are different as well, although having the same name.
Archive names do not contain a variant string, to allow to freely change the variant string from subversion to subversion.
To use the same version name by the subrelease and by the application, subrelease has to understand variable definition in particular programming language, and we have to reserve a few variable names, like this for C:
# define PACKAGE "package-name"
# define VERSION "1.13"
# define PROJECT "project-name"
# define AUTHORS "(c) Author1, Author2, 2023 GPLv3"
or for Perl:
$PACKAGE="package-name";
$VERSION="1.13";
$PROJECT="project-name"; # comment
$COPYLEFT="(c) The.Author 1999, GPL";
Accompanying script getversion
can inspect these reserved variables. It
checks VERSION.h
or CONFIG.h
files, or VERSION.pl
, VERSION.py
, etc. for
other languages. See getversion -h
for a description of
the syntax for other languages.
For multi-language applications, the Makefile
can be used to hold variables,
which when changed will write them to temporary files for every used language,
like .version.pl
, .version.py
, etc.
Reserved variable names are (plus a few more for config files):
PACKAGE
package name,
VERSION
its version,
SUBVERS
SUBVERSION
subversion,
PROJECT
project name,
AUTHORS
AUTHOR
COPYLEFT
COPYRIGHT
authors list, and notes,
CAPTION
any package notes, message, definition,
VARIANT
BRANCH
variant/branch name.
The SUBVERSION
variable is automatically incremented always when the subversion
creates a new subrelease, thus the application can know which subversion it is.
Stealth operation without introducing any new variable definitions to the
source tree is possible by keeping them instead in the config file
.subrelease
in the current or any parent directory (than you will not add
anything into the source tree).
Config files also recognize a few more variables. To preserve the namespace of
application code these are config-files only, visible only in .subrelease
or
VERSION
files:
SUFFIX
the archive suffix, see subrelease -h
for the list of suffixes,
TGZDIR
target directory, instead of the default ../tgz
or ..
,
EXCLUDE
exclude specified files from being archived,
ALWAYS
the script/command to be fired at the and of every subrelease
run,
ONREL
ONRELEASE
script only fired at full release,
ONSUB
ONSUBRELEASE
only fired at the subrelease, not at release.
Scripts can be used to automatically:
- to sync data to mirror,
- to submit a summary to a webpage,
- to run code metrics scripts,
- etc.
The EXCLUDE
can be used to avoid .git
subdirs in all project directories by
placing the .subrelease
file in the top-level projects directory with a line:
EXCLUDE: .git
The .subrelease
can be placed in the home directory, current directory, or any
parent directory. The order of variables overriding is:
~/.subrelease
from the home directory,./.subrelease
or../.subrelease
or higher, variables here override these from 1.,- CLI arguments, like
-v
option override config values, step 4. depends on its value, ./VERSION.c
or./VERSION.pl
etc., these are main variables definitions, override 1. to 3.,- CLI arguments, finally CLI again overrides everything.
Some variables can be defined in the .subrelease
file and some in the VERSION.c
file etc. at the same time, to control their visibility.
Files subrelease
and getversion
are standalone perl scripts, which can be
copied to any /bin
directory for a system-wide installation. For user-only
installation the make install
routine is provided.
Subrelease is written in perl but is compiled from source files to the final executable script by preprocessor. The reason for such an approach is to have a singlefile script as a result, and at the same time allow source code to be structured to several files. Perl provides the best expressive power and great stability, which is (most) important for the maintenance of script in the long term. And for compactness of the executed application script.
Over time I had different requirements for the script. Sometimes conflicting. Today my subrelease design summary will be:
- content-only approach without script's private metadata/database/indexes:
- primary knowledge source - filenames in the archive,
- secondary knowledge source - variables in the application source code (and configs),
- data access with standard tools -
subrelease
is not needed to extract or inspect the archive, - autodetection first - autodetect everything possible to autodetect,
- any-functionality = single-command:
subrelease
to archive,getversion
to inspect,
- can be used either as a standalone release tool or alongside git/github etc.