Package: mercurial_update_version
No more manual version number editing.Whenever you issuehg tag, this extension scans your repository
for files containing various kinds ofVERSION =lines, updates
those constants appropriately, commits the change, and only then tags
the release.Functionality can be enabled per-repository or (via~/.hgrc) for
many repositories at once (so you don’t need to remember about
activating it on every created, or cloned repository).1Enabling the extension1.1Enabling per-repository1.2Enabling for many repositories at once1.3Enabling for use in TortoiseHg2Using3Predefined languages3.1Python (language=python)3.2Perl (language=perl)3.3JavaScript (language=javascript)3.4JSON (language=json)3.5YAML (language=yaml)3.6Logstash (language=logstash)3.7C++ (language=c++)4Predefined tag formats4.1Dot-separated numbers (tagfmt=dotted)4.2Dash-separated numbers (tagfmt=dashed)4.3Dotted with text prefix (tagfmt=pfx-dotted)4.4Dashed with text prefix (tagfmt=pfx-dashed)5Keyword expansion6Custom languages7Custom tag formats8Commands8.1hg tag8.2hg tag_version_test9Installation9.1Linux/Unix (from PyPI)9.2Linux/Unix (from source)9.3Windows10History11Repository, bug reports, enhancement suggestions12Additional notes1Enabling the extensionInstall the extension as described below. Then either enable it
per-repository, or enable for many repositories at once.1.1Enabling per-repositoryIn repository.hg/hgrcwrite:[update_version]
active = true
language = python
tagfmt = dotted(of course using appropriate settings). Here:languageimplies version constants syntax, and sometimes
restricts list of files scanned,tagfmtdescribes expected tag syntax (and how to extract
actual version number from the tag).For example,language = pythonmeans looking forsetup.py,__init__.pyandversion.pyfiles anywhere inside the
repository, and updating lines looking likeVERSION = "1.2.3",
whiletagfmt = dottedmeans simple dotted numbers are used as
tags (hg tag 1.0.9).Both languages and tag formats are configurable, extension brings
some sane defaults but they can be overridden, and new styles
can be defined. See below.It is also possible to enable more than one language. For example,
to update numbers in both python, and javascript files,
one can write in.hg/hgrc:[update_version]
py.active = true
py.language = python
py.tagfmt = dotted
js.active = true
js.language = javascript
js.tagfmt = dottedName prefixes (pyandjsin the sample above) are used only
to group the settings and are not important (use any name you like).
Thetagfmtsetting should usually be the same in all entries.1.2Enabling for many repositories at onceIn~/.hgrcwrite something like:[update_version]
pydev.active_on = ~/sources/pymodules, ~/work/python
pydev.language = python
pydev.tagfmt = dotted
myperl.active_on = ~/scripts, ~/work/scripts
myperl.language = perl
myperl.tagfmt = dashed
excvs.active_on = ~/legacy
excvs.expand_keywords = 1Name prefixes (pydevandmyperl) are used only to group
three settings together (use any names you like).In both cases:.active_onlists directory trees to which given rule can be applied
(absolute paths,~and~userare allowed),.languageand.tagfmtdefine which language settings and which tag
format to use for those directories..expand_keywordsenables CVS keyword expansion (replacement of$Name$and similar constructs). Note that it works differently than keyword extension, replacements are commited (so will always be present in the checked out code).In case multiple directives match the same repo, all are processed, for example with:[update_version]
pydev.active_on = ~/sources
pydev.language = python
pydev.tagfmt = dotted
jsdev.active_on = ~/sources
jsdev.language = javascript
jsdev.tagfmt = dottedin repo~/sources/mywebboth python, and javascript files, will be processed.1.3Enabling for use in TortoiseHgThe setup above is not sufficient for tags created from TortoiseHg GUI
(viathg tagor tagging dialog of main TortoiseHg window). To get
those working, you must manually enable the update version hook. Add
to your~/.hgrc:[hooks]
pre-tag.update_version = python:mercurial_update_version.pre_tag_hookPlease, use exactly that name and value (it will be used by extension
to detect that you enabled the hook, so it need not be enabled again
under bare Mercurial).The rest of the configuration remains the same.NoteTechnical details:mercurial_update_versionusually enables
that hook by itself. Unfortunately under TortoiseHg dynamic hook
activation does not work (THG has it’s own command processing chain
different from Mercurial core, and hook list is effectively frozen
before extensions are able to impact it).2UsingAfter enabling the extension:ensure your code have some initial version variables
(put sth. likeVERSION = "0.0.0"in appropriate place(s))simplyhg tag«appropriate-tag».and your version constants will be updated, the change commited, and
only the resulting changeset tagged.Version numbers are not updated when tag is placed by revision (hg tag-r«version-no»«tag»), unless specified revision matches
currently checked out revision.Tags not matching the expected pattern are ignored, just like local
tags (rarely used Mercurial feature).The extension notifies you whether and what it does, for example:$ hg tag 2.0
update_version: Version number in src/version.py set to 2.0. List of changes:
    Line 2
    < VERSION = "1.0"
    > VERSION = "2.0"or:$ hg tag -r 2 0.5.0
update_version: ignoring tag placed -r revision (tag is placed, but version number not updated)3Predefined languagesThelanguagesetting defines:which files to check and patch (by filename patterns)what is the appropriate constant format and nameThe following languages are currently supported:3.1Python (language=python)Look for files namedsetup.py,__init__.pyorversion.py(anywhere inside repository). In those files,
update lines looking like:VERSION = '1.2.3'(at least one dot - but can be more, both single and double-quotes
are supported, just like various spacing and indentation).Inserted version number is formatted in the same way (as
dot-separated list of numbers).  Tag being placed should contain
at least two-part version number to be used.3.2Perl (language=perl)Look for files named*.pl,*.pmand*.podaround
repository. If found, look for lines like:our $VERSION = '1.00';
my $VERSION = '11.72';
use constant VERSION => '21.3374';(exactly one dot expected, various spacing and indentation
allowed, double quotes allowed) and also:Version 1.23(usually met in POD sections).Also, look fordist.iniand if found, fix lines like:version = 0.02Two kinds of tags numbers are supported. If tag contains two-item
version, it is left as is (tag1.0results in version1.0,
dashed tag1-03brings1.03). If tag has three parts,
first is left before the dot while second and third each get two
digits after the dot (tag1.7.2is translated into version1.0702, tag17-0-9into17.0009). Other tags are
invalid.3.3JavaScript (language=javascript)Look for files namedversion.js,version.jsx,*_version.jsand*_version.jsx. In any of those, look for lines like:var VERSION = "1.2.3";
const VERSION = "1.2.3";
let VERSION = "1.2.3";(final semicolons being optional).Also look forpackage.jsonfile(s) and if found, update line like:"version": "1.0.0",(with or without semicolon, and with or without indentation). Note: this
is currently expected to be the sole item on the line, without other
keys.3.4JSON (language=json)Check files named*.jsonfor lines like:"version": "1.0.0",(with or without semicolon, with or without indentation, with single or double quotes,
without other keys on the same line).Contrary to most other languages, there are additional restrictions:checking is limited to first 30 lines of the file,only one (first) line of such form is modified.3.5YAML (language=yaml)Check files named*.yamlor*.ymlfor lines like:version: "1.0.0"
package_version: "1.0.0"
module_version: "1.0.0"(with or without quotes, with or without indentation).Contrary to most other languages, there are additional restrictions:checking is limited to first 20 lines of the file,only one (first) matching line is modified.3.6Logstash (language=logstash)Check files named*version*.conf(confextension and wordversionanywhere inside basename) for lines like:add_field => { "[version]" => "1.0.2" }or mayhaps:add_field => { "[some][prefix][version]" => "1.0.2" }(last - or only - part of the key must be[version], whitespace can be flexible
but whole line as such must be constructed as above).I recommend using file like01-version.conf(named so it is
processed early), with content like:filter {
    mutate {
        add_field => { "[@metadata][myapp][version]" => "1.0.2" }
    }
}and then referring to this field (copying it, using inside formatted
strings) wherever needed in filters and outputs.3.7C++ (language=c++)Look for files namedversion.hxx,version.cxx,version.hpp,version.cpp. Look for and update lines like:const string VERSION = "1.2.3";
const char* VERSION = "1.2.3";
const char VERSION[] = "1.2.3";
string VERSION = "1.2.3";Support for further languages is planned, feel free to suggest them.4Predefined tag formatsThe following tag formats are supported.4.1Dot-separated numbers (tagfmt=dotted)Tags like1.0,1.0.3,11.17.34.4.2Dash-separated numbers (tagfmt=dashed)Tags like1-0,1-0-3,11-17-34.4.3Dotted with text prefix (tagfmt=pfx-dotted)Tags likemylib-1.0orsth_11.3.17:
alphanumeric string, dash or underscore,
then actual version as indotted.4.4Dashed with text prefix (tagfmt=pfx-dashed)Tags likemylib-1-0orsth_11-3-17:
alphanumeric string, dash or underscore,
then actual version as indashed. leading
part must not end with digit.5Keyword expansionSettingexpand_keywords=1enables CVS keyword expansion.  Source
will be scanned for CVS keywords like$Name$(or$Name: mytag_0.7.0 $),$Revision$, etc, and those will be appropriately updated. This change will be commited, making those changes permanent
(until they are replaced by newer tag).This is an alternative to standard keyword extension, which updates
those keywords on update (and causes various problems with merges,
edits, extension configuration, etc). Withupdate_versionapproach, proper keyword values will be simply commited just before
tagging, so they will always be present in the checkout.Note that the replacement is somewhat simplistic: the main purpose is
to get proper$Name$, everything else ($Revision$,$Header$etc) gets populated with the data of last pre-tag changeset (calculating
true date or revision of last change per each file is possible, but would
be fairly costly).Example configuration (~/.hgrc):[update_version]
cvsconverts.active_on = ~/devel/legacy ~/devel/libs
cvsconverts.expand_keywords = 16Custom languagesNot yet supported, but planned (defining new language by configuration
settings, or overriding some default language characteristics). The
general idea is to have some reasonable defaults built-in, but allow
reconfiguration.7Custom tag formatsNot yet supported, but planned (defining new tag format by
configuration settings).8Commands8.1hg tagExtension mainly work by augmentinghg tag, as described
above.8.2hg tag_version_testThis isdry runcheck. The command:hg tag_version_test 1.0lists which files would be checked, whether version lines were found
in them, and how would they be changed, but does not change anything.9Installation9.1Linux/Unix (from PyPI)If you have workingpiporeasy_install:pip install --user mercurial_update_versionor maybe:sudo pip install mercurial_update_version(or useeasy_installinstead ofpip). Then activate by:[extensions]
mercurial_update_version =To upgrade, repeat the same command with--upgradeoption, for
example:pip install --user --upgrade mercurial_update_version9.2Linux/Unix (from source)If you don’t havepip, or wish to follow development more closely:clone both this repository andmercurial_extension_utilsand put
them in the same directory, for example:cd ~/sources
hg clone https://foss.heptapod.net/mercurial/mercurial-extension_utils/
hg clone https://foss.heptapod.net/mercurial/mercurial-update_version/update to newest tags,activate by:[extensions]
mercurial_update_version = ~/sources/mercurial-update_version/mercurial_update_version.pyTo upgrade, pull and update.Seemercurial_extension_utilsfor longer description of this kind
of installation.9.3WindowsIf you have any Python installed, you may install withpip:pip install mercurial_update_versionStill, as Mercurial (whether taken fromTortoiseHg, or own package)
uses it’s own bundled Python, you must activate by specifying the path:[extensions]
mercurial_update_version = C:/Python27/Lib/site-packages/mercurial_update_version.py
;; Or wherever pip installed it, depending on the version it can also be
;; sth like (replace john with proper username and 37 with proper version)
;; mercurial_update_version =  C:\Users\john\AppData\Local\Programs\Python\Python37\Lib\site-packages\mercurial_update_version.pyTo upgrade to new version:pip install --upgrade mercurial_update_versionIf you don’t have any Python, clone repositories:cd c:\hgplugins
hg clone https://foss.heptapod.net/mercurial/mercurial-extension_utils/
hg clone https://foss.heptapod.net/mercurial/mercurial-update_version/update to tagged versions and activate by path:[extensions]
mercurial_update_version = C:/hgplugins/mercurial-update_version/mercurial_update_version.py
;; Or wherever you clonedSeemercurial_extension_utilsdocumentation for more details on
Windows installation.10HistorySeeHISTORY.rst11Repository, bug reports, enhancement suggestionsDevelopment is tracked on HeptaPod, seehttps://foss.heptapod.net/mercurial/mercurial-update_version/Use issue tracker there for bug reports and enhancement
suggestions.Thanks toOctobusandClever Cloudfor hosting this service.12Additional notesInformation about this extension is also available
on Mercurial Wiki:http://mercurial.selenic.com/wiki/UpdateVersionExtensionCheck alsoother Mercurial extensions I wrote.