Source

perl/cpan_make_release / sample-version_hook.py

# -*- coding: utf-8 -*-

"""
Updating version number in files automatically whenever "hg tag" is
issued.

To use:

1. Save as version_hook.py in the package directory

2. Edit UPDATED_FILES below

3. Add in .hg/hgrc

       [hooks]
       pre-tag=python:version_hook.py:version_update

  Note: pre-tag, not pretag! Hook should run before changeset being
  tagged is selected.

With such config, simple

  hg tag 0.27

sets 0.27 as version number and commits this change before the tag
is actually set.

Hook scans configured files for constructs like::

   our $VERSION = 'something';

and::

   Version 1.2342.

In case other construct is needed, check version_regexps below.
"""

# Will be updated automatically
VERSION = "0.2001"

# List of files to scan and update
UPDATED_FILES = [
    "lib/Passwd/Keyring/KDEWallet.pm",
    ]

def _patch_perl_files(ui, new_version_no):
    """
    Patches all perl files to new version number, returns modified files.
    """
    import os, re
    version_regexps = [
        re.compile(r"^(?P<pfx>our +\$VERSION *= *').*?(?P<sfx>'.*)$"),
        re.compile(r"^(?P<pfx>Version +)\d+\.\d+(\.\d+)?(?P<sfx>\.? *)$"),
        ]

    location = os.path.dirname(__file__)
    updated_files = []
    for candidate in UPDATED_FILES:
        full_name = os.path.join(location, candidate)
        changes = 0
        file_lines = []
        ui.note("Checking file %s\n" % candidate)
        with open(full_name, "r") as input:
            for line in input.readlines():
                m = None
                for rgxp in version_regexps:
                    m = rgxp.search(line)
                    if m:
                        ui.note("Patching line %s" % line)
                        break
                if m:
                    file_lines.append(
                        m.group('pfx') + new_version_no + m.group('sfx') + "\n")
                    changes += 1
                else:
                    file_lines.append(line)
        if changes:
            ui.status("Version updater: Replacing old version number with {0:>s} in {1}\n".format(new_version_no, full_name))
            with open(full_name, "w") as output:
                output.writelines(file_lines)
            updated_files.append(full_name)
    return updated_files
    
def version_update(repo, ui, hooktype, pats, opts, **kwargs):
    """
    Method used in mercurial version-update hook. Don't call directly.
    """
    import re
    import mercurial.commands

    # Regexps for handled version number syntaxes
    tag_regexps = [
        # something_1-2, something-1.2 and similar
        re.compile(r"[^-_0-9][-_](?P<major>[0-9]+)[-_\.](?P<minor>[0-9]+)$"),
        # 1.2, 1-2, 1_2
        re.compile(r"^(?P<major>[0-9]+)[-_\.](?P<minor>[0-9]+)$"),
        ]

    if opts.get('local'):
        ui.note("Version updater: ignoring local tag\n")
        return
    if opts.get('remove'):
        ui.note("Version updater: ignoring tag removal\n")
        return
    if opts.get('rev'):
        ui.note("Version updater: ignoring tag placed by rev\n")
        return

    if len(pats) != 1:
        ui.warn("Version updater: unexpected arguments, pats=%s\n" % pats)
        return True # means fail

    tag_name = pats[0]

    version_no = None
    for tag_regexp in tag_regexps:
        m = tag_regexp.search(tag_name)
        if m:
            version_no = "{major:>s}.{minor:>s}".format(**m.groupdict())
            break
    if not version_no:
        ui.warn("Version updater: Given tag does not seem to be versioned. Please make proper tags (1.2, xxxx_1-2, xaear-aera-1.2 or similar\n")
        return True # means fail

    if version_no == VERSION:
        ui.note("Version updater: version number {0:>s} is already correct\n".format(version_no))
        return False # means OK

    # Regexp for VERSION= line
    py_version_regexp = re.compile(r"^VERSION *= *")

    my_name = __file__
    if my_name.endswith(".pyc") or my_name.endswith(".pyo"):
        my_name = my_name[:-1]

    ui.status("Version updater: Replacing old version number {0:>s} with {1:>s} in {2}\n".format(
        VERSION, version_no, my_name))

    file_lines = []
    changes = 0
    with open(my_name, "r") as input:
        for line in input.readlines():
            if py_version_regexp.search(line):
                file_lines.append('VERSION = "%s"\n' % version_no)
                changes += 1
            else:
                file_lines.append(line)
    if not changes:
        ui.warn("Version updater: Line starting with VERSION= not found in {0:>s}.\nPlease correct this file and retry\n".format(my_name))
        return True #means fail
    with open(my_name, "w") as output:
        output.writelines(file_lines)

    updated_perl_files = _patch_perl_files(ui, version_no)

    ui.note("Commiting updated version number\n")
    mercurial.commands.commit(
        ui, repo,
        my_name,
        *updated_perl_files,
        message="Version number set to %s" % version_no)
    return False #means ok
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.