Package: gitver
|PyPi version| |PyPi downloads| |Project Stats| |Flattr this git repo|What is it?-----------A very simple, lightweight, tag-based version string manager for git,written in Python.It generates version strings by using Python-based formatting rulescoupled with repository information, augmented by user-defined data.It supports up to four different version number operands and optionalpre-release version information, in the format``[v]MAJOR.MINOR.PATCH[.REVISION][-PRE-RELEASE-METADATA]``, making toadopt versioning schemes such as `SemanticVersioning <https://semver.org>`__ a breeze.Optionally, it also keeps your project's version information blobsautomagically updated via custom templates.Sample output (this repository):::Most recent tag: v0.3.0-RC1(NEXT defined as: 0.3.0)Using pre-release metadata: RC1Current build ID: 1d170e7f42817d0f277c52ad686b24ac69b353d4Current version: v0.3.0-RC1.47+1d170e7 => v0.3.0Installation------------Please read the simple *Installation instructions* in the`INSTALL.md <https://github.com/manuelbua/gitver/blob/master/INSTALL.md>`__file, you can install either via ``pip`` or by cloning this repository.*NOTE the **badges** present at the top of these pages (version anddownloads) refers to the latest stable packages uploaded to PyPI:cloning this repository will checkout the version i'm currently workingon and may not reflect the same version.*Helps in version string management----------------------------------Coupled with `githooks <http://git-scm.com/book/en/Customizing-Git-Git-Hooks>`__,``gitver`` version blob templates helps to keep your own project updatedwith its version information, performing simple template-basedsubstitution automatically at *post-commit* time, for example.Why?----I'm working on a project that requires precise version string trackingand synchronization between a server and its different clients, so anautomatic mechanism is needed.Furthermore, i want the version string and/or other useful informationto be **embedded** in the application code automatically, "compiled-in"so to speak, without me having to remember to do it manually each time.Repository pre-requisites-------------------------``gitver`` expects your tags to be **annotated** and be in this format:::[v]MAJOR.MINOR.PATCH[.REVISION][-PRE-RELEASE-METADATA]Text in ``[`` square brackets ``]`` is optional, so these example tagsare all valid for use with ``gitver``:::v0.0.10.0.1-RC0v0.0.1-RC2Note that, at this time, ``gitver`` will **not** skip unsupported tagsduring its processing, so whenever it encounter such malformed tags(i.e. "this-is-my-tag") it will just error out something like this:::ERROR: Couldn't retrieve version information from tag "my-other-tag".gitver expects tags to be in the format [v]X.Y.Z[.REVISION][-PRE-RELEASE-METADATA]However, since ``gitver`` will only search for annotated tags, you couldsafely use *unannotated tags* for any other need.Workflow--------Your workflow shouldn't change much from what you are used to, butbefore using it, please review the "Repository pre-requisites" sectionabove and ensure your tags are not already being used for some otherpurpose.*Note that ``gitver`` will **never** tag, commit or interact inwrite-mode with your repository in any way, ever!*The following is a workflow exemplification of using *gitver* to manageversion strings for your project, given it has already been setup:-  you are working on your repository, now you are ready to promote thecurrent version to the next release-  create a release tag, ``git tag -a v0.0.2 -m 'Bump version'``-  defines your NEXT version, the one you are going to work *towards* toby running ``gitver next 0.0.3``-  run ``gitver`` and check everything is fine-  **OPTIONAL** preview or update your project's version informationtemplates by running ``gitver preview <template name>`` or``gitver update <template name>``, then rebuild the project toreflect version changes-  any other manual house-keeping in-between releases can be performednow-  now you are working towards the NEXT release, repeat when releasetime has came againHow does it work?-----------------By reading your last reachable **annotated** tag, it will generatecustomly-formatted version strings, distinguishing automatically between*stable* and *development* builds, depending on the number of commitsfrom that last tag (the *commit count*).It will also apply tag-based or configuration file-based pre-releasemetadata in development builds, giving you fine-grained control on howthe final version string will be composed.Config file-----------``gitver`` uses a per-repository, JSON-based configuration file.The default configuration file gets created automatically in``.gitver/config`` and it contains the following tweakable settings:::{# automatically generated configuration file## These defaults implement Semantic Versioning as described in the latest# available documentation at http://semver.org/spec/v2.0.0.html# by default, terminal output is NOT colorized for compatibility with older# terminal emulators: you may enable this if you like a more modern look"use_terminal_colors": false,# prevent gitver from storing any information in its configuration directory# if the .gitignore file doesn't exclude it from the repository"safe_mode": true,# default pre-release metadata when commit count > 0 AND# no NEXT has been defined"default_meta_pr_in_next_no_next": "NEXT",# default pre-release metadata when commit count > 0"default_meta_pr_in_next": "SNAPSHOT",# default pre-release metadata prefix"meta_pr_prefix": "-",# default commit count prefix"commit_count_prefix": ".",# Python-based format string variable names are:#     maj, min, patch, rev, rev_prefix, meta_pr_prefix, meta_pr,#     commit_count_prefix, commit_count, build_id, build_id_full## Note that prefixes will be empty strings if their valued counterpart# doesn't have a meaningful value (i.e., 0 for commit count, no meta# pre-release, ..)# format string used to build the current version string when the# commit count is 0"format": "%(maj)s.%(min)s.%(patch)s%(rev_prefix)s%(rev)s%(meta_pr_prefix)s%(meta_pr)s",# format string used to build the current version string when the# commit count is > 0"format_next": "%(maj)s.%(min)s.%(patch)s%(rev_prefix)s%(rev)s%(meta_pr_prefix)s%(meta_pr)s%(commit_count_prefix)s%(commit_count)s+%(build_id)s"}This file gets created automatically in your ``.gitver`` directory whenyou initialize it with the ``gitver init`` command: should you need toregenerate it, for example after updating to a ``gitver`` release thatadds more configuration options (this will be noted in the ChangeLog orby other means), you just need to move/delete the old configuration andtrigger regeneration by re-issuing the init command.Basic usage-----------::$ gitver --helpusage: gitver [-h] [--ignore-gitignore] [--colors {config,yes,no}] [--quiet][--quiet-errors]{version,init,check,info,current,list-templates,list-next,update,preview,next,clean,clean-all}...optional arguments:-h, --help            show this help message and exit--ignore-gitignore    Ignore the .gitignore warning and continue running asnormal (specify this flag before any other command, atYOUR own risk)--colors {config,yes,no}Enable or disable colorized terminal output: 'config'(default) reads the setting from your configurationfile, 'yes' will force-enable it, 'no' will force-disable it.--quiet               Disable any stdout message.--quiet-errors        Disable any stderr message.Valid commands:{version,init,check,info,current,list-templates,list-next,update,preview,next,clean,clean-all}version             Shows gitver versioninit                Creates gitver's configuration directory and createsthe default configuration file, if it doesn't exist.check               Checks your .gitignore file for gitver's configurationdirectory inclusion.info                Prints full version information and tag-based metadatafor this repository. [default]current             Prints the current version information only, withoutany formatting applied.list-templates      Enumerates available templates.list-next           Enumerates user-defined next stable versions.update              Performs simple keyword substitution on the specifiedtemplate file(s) and place it to the path described bythe first line in the template. This is usuallyperformed *AFTER* a release has been tagged already.preview             Same as "update", but the output is written to thestdout instead (same rules apply).next                Defines the next stable version for the most recentand reachable tag.clean               Removes the user-defined next stable version for themost recent and reachable tag or the specified tag.clean-all           Removes ALL user-defined next stable versions.Introduction~~~~~~~~~~~~The following is an easy-to-follow, step-by-step mini tutorial that willwalk you through the features of ``gitver``: we are going to create abrand new repository at ``/tmp/test`` for this.Step-by-step mini tutorial~~~~~~~~~~~~~~~~~~~~~~~~~~Building some repository history''''''''''''''''''''''''''''''''Let's create a new repository in your ``/tmp`` folder:::cd /tmp && mkdir test && cd test && git initNow populate it with some activity:::echo "some data" > some && git add some && git commit -m 'initial commit' && echo "more data" > more && echo "another one" > another && git add more && git commit -m 'one more' && git add another && git commit -m 'even more'Your repository should now look like this:::* b01e958  (HEAD, master) (Thu Jan 16 17:08:54 2014) even more (Manuel Bua)* 8f5862b  (Thu Jan 16 17:08:54 2014) one more (Manuel Bua)* fac3511  (Thu Jan 16 17:08:54 2014) initial commit (Manuel Bua)Let's initialize ``gitver`` at this point:::$ gitver initgitver has been initialized and configured.``gitver`` just created its own ``.gitver`` configuration directory andgenerated the default configuration file ``config`` right there. At thispoint it's recommended, but not mandatory, to **exclude** gitver'sconfiguration directory from the repository by adding it to your``.gitignore`` file: this is to prevent losing your ``gitver``'sconfiguration whenever you checkout old revisions of your project.Anyway, the tool is quite smart in that and it will *not* proceed if itdetects potential problems with the command you issued, in case your``.gitignore`` file isn't properly setup, so let's run a check at thispoint to see that warning message:::$ gitver checkYour .gitignore file doesn't define any rule for the .gitverconfiguration directory: it's recommended to exclude it fromthe repository, unless you know what you are doing. If you are notsure, add this line to your .gitignore file:.gitverSo let's create your ignore file, add that line, then run ``gitver``:::$ echo ".gitver" >> .gitignore$ gitverERROR: Couldn't retrieve the latest tagRight, we have no tags at this point, so let's create ``v0.0.0`` at thefirst commit with this command (replace the commit hash with your ownwhere needed):::git tag -a v0.0.0 -m 'Initial version' fac3511This is how your repository should look like:::* b01e958  (HEAD, master) (Thu Jan 16 17:08:54 2014) even more (Manuel Bua)* 8f5862b  (Thu Jan 16 17:08:54 2014) one more (Manuel Bua)* fac3511  (tag: v0.0.0) (Thu Jan 16 17:08:54 2014) initial commit (Manuel Bua)Now ``gitver`` output should be somewhat more informative:::Most recent tag: v0.0.0Using NEXT defined as: none, defaulting to -NEXT suffix(Pre-release metadata: none)Current build ID: b01e95831e8c240415510be16e93e10f68fb964aCurrent version: v0.0.0-NEXT.2+b01e958Time to decide what the NEXT version numbers will be, so let's set thisand run ``gitver`` again:::$ gitver next 0.0.1Set NEXT version string to 0.0.1 for the current tag v0.0.0$ gitverMost recent tag: v0.0.0Using NEXT defined as: 0.0.1(Pre-release metadata: none)Current build ID: b01e95831e8c240415510be16e93e10f68fb964aCurrent version: v0.0.1-SNAPSHOT.2+b01e958 => v0.0.1Notice how the build id stayed the same but the version string changed:both strings describes the same point in development, they are*equivalent*, but given the same descriptive intentions, i find thelatter to be much more clear.Now lookup your ``.gitver/config`` file and look at the ``format_next``definition:::"format_next": "%(maj)s.%(min)s.%(patch)s%(rev_prefix)s%(rev)s%(meta_pr_prefix)s%(meta_pr)s%(commit_count_prefix)s%(commit_count)s+%(build_id)s"This defines the format of the version string being generated at thispoint of development: since the *commit count* from the most recentvalid tag is greater than ``0``, this denotes a *development* build, andthe ``format_next`` variation is used: the ``%(meta_pr)s`` placeholderwill be replaced by the pre-release metadata if your tag defines one,else the configuration defaults will be used, but this will only happenin development builds, there is no point in exposing *pre-release*metadata in a *stable* release.The ``%(meta_pr_prefix)s`` counterpart, instead, will be filled with thevalue of ``meta_pr_prefix`` *only* if pre-release metadata is used, elseit will be set to an empty string as well.The same reasoning applies to the *commit count*: whenever it's equal to``0`` both ``%(commit_count)s`` and ``%(commit_count_prefix)s`` will beset to an empty string.This permit to adapt and change version string formats by letting youdefines concatenations more easily.Tagging a release'''''''''''''''''Let's add that ``.gitignore`` file we didn't add before, then declarethe version stable by just tagging it as that:::$ git add .gitignore && git commit -m 'Add .gitignore file'$ git tag -a 'v0.0.1' -m 'Bump version'Your repository should now look like this:::* 3a3cf5f  (HEAD, tag: v0.0.1, master) (Thu Jan 16 17:29:00 2014) Add .gitignore file (Manuel Bua)* b01e958  (Thu Jan 16 17:08:54 2014) even more (Manuel Bua)* 8f5862b  (Thu Jan 16 17:08:54 2014) one more (Manuel Bua)* fac3511  (tag: v0.0.0) (Thu Jan 16 17:08:54 2014) initial commit (Manuel Bua)So let's have ``gitver`` take a look at the repository now:::$ gitverMost recent tag: v0.0.1Current build ID: 3a3cf5ffe0a6a2f6051420ac730554c92bf9bdf2Current version: v0.0.1As you can see, ``gitver`` now uses the *other* string format from theconfiguration file:::"format": "%(maj)s.%(min)s.%(patch)s%(rev_prefix)s%(rev)s%(meta_pr_prefix)s%(meta_pr)s"This is being used when the commit count from the most recent tag isequal to ``0`` since this denotes a *stable* build, rather than adevelopment one.Depending on your project, format strings can change slightly between*stable* and *development* versions: ``gitver`` gives you full controlover what format to use in each case.For completeness, let's use the ``format_next`` format for the stablebuild as well and edit that portion of your configuration file to looklike this:::"format": "%(maj)s.%(min)s.%(patch)s%(meta_pr_prefix)s%(meta_pr)s%(commit_count_prefix)s%(commit_count)s+%(build_id)s"Done that? Now look at ``gitver``'s output now:::$ gitverMost recent tag: v0.0.1Current build ID: 94b2ef2ed92844377f1e8b1160a014bae0273792Current version: v0.0.1+94b2ef2As expected, there is no sign of prefixes, nor default metadata orcommit count in the stable build.Template-based version information blobs----------------------------------------One of the main reasons for this tool to exists is to be able to alsoautomatically update your project own's version information *blob* (e.g.``VersionInfo.java``, ``version.py``, ...) or some other external filewith the project's version information.Template format---------------The only **required** bit of information *gitver* needs is where theoutput of the template should be placed, so the first line shall onlycontain the path to the output file in a Bash-style comment (spaces aretrimmed):::# /path/to/project/file.extensionThe rest of the file is obviously up to you, an example is available atthe "Template example" section.*Why is the format starting with a Bash-style comment, you say?* Theinitial version of *gitver* was a Bash script, so it was a naturalchoice to adopt that: i then realized i didn't like how things were andrewrote all it in Python, but the template format stayed the samebecause it was *simple*.Template variables------------------Given these basic assumptions:-  the latest tag is ``v0.4.9``-  the NEXT version numbers have been defined to be ``0.4.10``-  the actual commit count is ``2``Here is the list of variables, with their values, available for use intemplates:::${CURRENT_VERSION}     = 0.4.10-SNAPSHOT-2/a3a73a58${BUILD_ID}            = a3a73a58${FULL_BUILD_ID}       = a3a73a5861e5721055f3a12545201e265ba0c097${MAJOR}               = 0${MINOR}               = 4${PATCH}               = 10${REV}                 = (empty string, or a revision number if present)${REV_PREFIX}          = (empty string, or a '.' if a revision number is present)${COMMIT_COUNT}        = 2 (or 0 if commit count is 0)${COMMIT_COUNT_STR}    = '2' (or an empty string if commit count is 0)${COMMIT_COUNT_PREFIX} = either the 'commit_count_prefix' specified in the config file or an empty string, if the commit count is 0${META_PR}             = either the pre-release metadata from the last reachable tag, the 'default_meta_pr_in_next' (from config file), the 'default_meta_pr_in_next_no_next' (from config file) or an empty string, depending on the state of the repository${META_PR_PREFIX}      = either the 'meta_pr_prefix' specified in the config file or an empty string, if no pre-release metadata is available for useThe list could later be expanded and improved, to cover much moreinformation, such as date, time, let me know your suggestion!Previewing and compiling templates----------------------------------You can preview the result of the template substitution by using the``preview``\ command, followed by one or more template names (multipletemplate names should be quoted):::$ gitver preview my_templateor$ gitver preview "template1 template2 templateN"This will process the template and print the output to the stdoutinstead of writing it to a file: this can be useful for scriptingpurposes, where you can filter out information messages while onlycapturing the "real meat":::$ gitver preview my_template 2>/dev/nullThe ``update`` command works similarly, it will just write the output tothe specified file, rather than stdout:::$ gitver update my_templateor$ gitver update "template1 template2 templateN"It's possible to define any number of templates, just put them in the``.gitver/templates`` directory: to have ``gitver`` enumerate all theavailable templates, use the ``list-templates`` command:::$ gitver list-templatesAvailable templates:version (/home/manuel/dev/gitver/.gitver/templates/version)test (/home/manuel/dev/gitver/.gitver/templates/test)Template example----------------Let's take a look at ``gitver``'s own`template <hub.com/manuelbua/gitver/blob/master/.gitver/templates/version>`__:::# gitver/_version.py#!/usr/bin/env python2# coding=utf-8# DO NOT TOUCH, AUTOMATICALLY UPDATED!gitver_version = '${CURRENT_VERSION}'gitver_buildid = '${FULL_BUILD_ID}'gitver_pypi = '${MAJOR}.${MINOR}.${PATCH}${META_PR_PREFIX}${META_PR}${COMMIT_COUNT_PREFIX}${COMMIT_COUNT_STR}'Now let's compile it:::$ gitver update versionProcessing template "version" for /home/manuel/dev/gitver/gitver/_version.py...Done, 207 bytes written.This will produce the following file at``/home/manuel/dev/gitver/gitver/_version.py``, **overwriting** theprevious file, if any:::#!/usr/bin/env python2# coding=utf-8# DO NOT TOUCH, AUTOMATICALLY UPDATED!gitver_version = '0.3.0-RC1.47+1d170e7'gitver_buildid = '1d170e7f42817d0f277c52ad686b24ac69b353d4'gitver_pypi = '0.3.0-RC1.47'Templates + git hooks---------------------At this point is very simple to automatize even more, instead ofmanually updating version information after each commit, let's create agit hook to take care of this:::$ cat .git/hooks/post-commit#!/bin/bash# gitver should be in your path to work!gitver update versionThere you have it!Bugs----.. figure:: http://media.giphy.com/media/10EdqIfzllpg6A/giphy.gif:alt: bugsbugsNOPE!! MY CODE HAS NO BUGS!11Just joking, probably quite a few, please report them`here <https://github.com/manuelbua/gitver/issues>`__, thanks!.. |PyPi version| image:: https://pypip.in/v/gitver/badge.png:target: https://crate.io/packages/gitver/.. |PyPi downloads| image:: https://pypip.in/d/gitver/badge.png:target: https://crate.io/packages/gitver/.. |Project Stats| image:: https://ohloh.net/p/gitver/widgets/project_thin_badge.gif:target: https://ohloh.net/projects/gitver.. |Flattr this git repo| image:: http://api.flattr.com/button/flattr-badge-large.png:target: https://flattr.com/submit/auto?user_id=manuelbua&url=https://github.com/manuelbua/gitver&title=gitver&language=&tags=github&category=software