setup.py: get version from git or darcs

This replaces the setup.cfg aliases that run "darcsver" before each major
command with the new "update_version". update_version is defined in setup.py,
and tries to get a version string from either darcs or git (or leaves the
existing _version.py alone if neither VC metadata is available).

Also clean up a tiny typo in verlib.py that messed up syntax hilighting.
This commit is contained in:
Brian Warner 2011-12-04 20:40:01 -08:00
parent b73aba98de
commit 7d5ca407a1
3 changed files with 136 additions and 8 deletions

View File

@ -37,10 +37,10 @@ find_links=misc/dependencies tahoe-deps ../tahoe-deps
# (See http://tahoe-lafs.org/trac/tahoe-lafs/ticket/142 .) # (See http://tahoe-lafs.org/trac/tahoe-lafs/ticket/142 .)
[aliases] [aliases]
build = darcsver --count-all-patches develop --prefix=support make_executable build build = update_version develop --prefix=support make_executable build
test = darcsver --count-all-patches develop --prefix=support make_executable build trial test = update_version develop --prefix=support make_executable build trial
sdist = darcsver --count-all-patches sdist sdist = update_version sdist
install = darcsver --count-all-patches install install = update_version install
bdist_egg = darcsver --count-all-patches bdist_egg bdist_egg = update_version bdist_egg
trial = darcsver --count-all-patches trial trial = update_version trial
sdist_dsc = darcsver --count-all-patches sdist_dsc sdist_dsc = update_version sdist_dsc

128
setup.py
View File

@ -268,6 +268,133 @@ class MakeExecutable(Command):
raise raise
GIT_VERSION_BODY = '''
# This _version.py is generated from git metadata by the tahoe setup.py.
__pkgname__ = "%(pkgname)s"
real_version = "%(version)s"
full_version = "%(full)s"
verstr = "%(normalized)s"
try:
from pyutil.version_class import Version as pyutil_Version
__version__ = pyutil_Version(verstr)
except (ImportError, ValueError):
# Maybe there is no pyutil installed.
from distutils.version import LooseVersion as distutils_Version
__version__ = distutils_Version(verstr)
'''
def run_command(args, cwd=None, verbose=False):
try:
# remember shell=False, so use git.cmd on windows, not just git
p = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=cwd)
except EnvironmentError, e:
if verbose:
print "unable to run %s" % args[0]
print e
return None
stdout = p.communicate()[0].strip()
if p.returncode != 0:
if verbose:
print "unable to run %s (error)" % args[0]
return None
return stdout
def versions_from_git(tag_prefix, verbose=False):
# this runs 'git' from the directory that contains this file. That either
# means someone ran a setup.py command (and this code is in
# versioneer.py, thus the containing directory is the root of the source
# tree), or someone ran a project-specific entry point (and this code is
# in _version.py, thus the containing directory is somewhere deeper in
# the source tree). This only gets called if the git-archive 'subst'
# variables were *not* expanded, and _version.py hasn't already been
# rewritten with a short version string, meaning we're inside a checked
# out source tree.
# versions_from_git (as copied from python-versioneer) returns strings
# like "1.9.0-25-gb73aba9-dirty", which means we're in a tree with
# uncommited changes (-dirty), the latest checkin is revision b73aba9,
# the most recent tag was 1.9.0, and b73aba9 has 25 commits that weren't
# in 1.9.0 . The narrow-minded NormalizedVersion parser that takes our
# output (meant to enable sorting of version strings) refuses most of
# that. Tahoe uses a function named suggest_normalized_version() that can
# handle "1.9.0.post25", so dumb down our output to match.
try:
source_dir = os.path.dirname(os.path.abspath(__file__))
except NameError:
# some py2exe/bbfreeze/non-CPython implementations don't do __file__
return {} # not always correct
GIT = "git"
if sys.platform == "win32":
GIT = "git.cmd"
stdout = run_command([GIT, "describe", "--tags", "--dirty", "--always"],
cwd=source_dir)
if stdout is None:
return {}
if not stdout.startswith(tag_prefix):
if verbose:
print "tag '%s' doesn't start with prefix '%s'" % (stdout, tag_prefix)
return {}
version = stdout[len(tag_prefix):]
pieces = version.split("-")
if len(pieces) == 1:
normalized_version = pieces[0]
else:
normalized_version = "%s.post%s" % (pieces[0], pieces[1])
stdout = run_command([GIT, "rev-parse", "HEAD"], cwd=source_dir)
if stdout is None:
return {}
full = stdout.strip()
if version.endswith("-dirty"):
full += "-dirty"
return {"version": version, "normalized": normalized_version, "full": full}
class UpdateVersion(Command):
description = "update _version.py from revision-control metadata"
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
target = self.distribution.versionfiles[0]
if os.path.isdir(os.path.join(basedir, "_darcs")):
verstr = self.try_from_darcs(target)
elif os.path.isdir(os.path.join(basedir, ".git")):
verstr = self.try_from_git(target)
else:
print "no version-control data found, leaving _version.py alone"
return
if verstr:
self.distribution.metadata.version = verstr
def try_from_darcs(self, target):
from darcsver.darcsvermodule import update
(rc, verstr) = update(pkgname=self.distribution.get_name(),
verfilename=self.distribution.versionfiles,
revision_number=True)
if rc == 0:
return verstr
def try_from_git(self, target):
versions = versions_from_git("allmydata-tahoe-", verbose=True)
if versions:
for fn in self.distribution.versionfiles:
f = open(fn, "wb")
f.write(GIT_VERSION_BODY %
{ "pkgname": self.distribution.get_name(),
"version": versions["version"],
"normalized": versions["normalized"],
"full": versions["full"] })
f.close()
print "git-version: wrote '%s' into '%s'" % (versions["version"], fn)
return versions.get("normalized", None)
class MySdist(sdist.sdist): class MySdist(sdist.sdist):
""" A hook in the sdist command so that we can determine whether this the """ A hook in the sdist command so that we can determine whether this the
tarball should be 'SUMO' or not, i.e. whether or not to include the tarball should be 'SUMO' or not, i.e. whether or not to include the
@ -331,6 +458,7 @@ setup(name=APPNAME,
license='GNU GPL', # see README.txt -- there is an alternative licence license='GNU GPL', # see README.txt -- there is an alternative licence
cmdclass={"trial": Trial, cmdclass={"trial": Trial,
"make_executable": MakeExecutable, "make_executable": MakeExecutable,
"update_version": UpdateVersion,
"sdist": MySdist, "sdist": MySdist,
}, },
package_dir = {'':'src'}, package_dir = {'':'src'},

View File

@ -139,7 +139,7 @@ class NormalizedVersion(object):
pad_zeros_length=0): pad_zeros_length=0):
"""Parse 'N.N.N' sequences, return a list of ints. """Parse 'N.N.N' sequences, return a list of ints.
@param s {str} 'N.N.N..." sequence to be parsed @param s {str} 'N.N.N...' sequence to be parsed
@param full_ver_str {str} The full version string from which this @param full_ver_str {str} The full version string from which this
comes. Used for error strings. comes. Used for error strings.
@param drop_trailing_zeros {bool} Whether to drop trailing zeros @param drop_trailing_zeros {bool} Whether to drop trailing zeros