Modified versioneer to allow specification of manual versions based on branches
You can now define a lookup file explicitely mapping virtual version tags to branches via regular expressions and a reference commit from which the commit distance will be calculated.
Format of the file is
<branch-regex> <tag> <reference commit>
The file is processed from top to bottom, the first matching line wins. If <tag> or <reference commit> are left out, the lookup table does not apply to the matched branches and the regular versioneer resolution (via git describe) takes place.
Current configuration makes "master", "staging" and any branch starting with "fix/" make use the default behaviour, all other branches (so basically all development branches) are defined as "1.2.0-dev"
(cherry picked from commit 212f40c)
This commit is contained in:
parent
18952c57ff
commit
e51d9439c5
4 changed files with 303 additions and 23 deletions
18
.versioneer-lookup
Normal file
18
.versioneer-lookup
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# Configuration file for the versioneer lookup, manually mapping tags based on branches
|
||||
#
|
||||
# Format is
|
||||
#
|
||||
# <branch-regex> <tag> <reference commit>
|
||||
#
|
||||
# The file is processed from top to bottom, the first matching line wins. If <tag> or <reference commit> are left out,
|
||||
# the lookup table does not apply to the matched branches
|
||||
|
||||
# master and staging shall not use the lookup table
|
||||
master
|
||||
staging
|
||||
|
||||
# fix/ branches are fixes for master, so we don't handle those either
|
||||
fix/.*
|
||||
|
||||
# every other branch is a development branch and thus gets resolved to 1.2.0-dev for now
|
||||
.* 1.2.0-dev 50cf776e70b9
|
||||
1
setup.py
1
setup.py
|
|
@ -7,6 +7,7 @@ versioneer.versionfile_source = 'src/octoprint/_version.py'
|
|||
versioneer.versionfile_build = 'octoprint/_version.py'
|
||||
versioneer.tag_prefix = ''
|
||||
versioneer.parentdir_prefix = ''
|
||||
versioneer.lookupfile = '.versioneer-lookup'
|
||||
|
||||
from setuptools import setup, find_packages, Command
|
||||
import os
|
||||
|
|
|
|||
|
|
@ -54,6 +54,18 @@ import sys
|
|||
import re
|
||||
import os.path
|
||||
|
||||
def get_gits(root, verbose=False):
|
||||
if not os.path.exists(os.path.join(root, ".git")):
|
||||
if verbose:
|
||||
print("no .git in %s" % root)
|
||||
return None
|
||||
|
||||
GITS = ["git"]
|
||||
if sys.platform == "win32":
|
||||
GITS = ["git.cmd", "git.exe"]
|
||||
return GITS
|
||||
|
||||
|
||||
def get_expanded_variables(versionfile_abs):
|
||||
# the code embedded in _version.py can just fetch the value of these
|
||||
# variables. When used from setup.py, we don't want to import
|
||||
|
|
@ -114,20 +126,60 @@ def versions_from_expanded_variables(variables, tag_prefix, verbose=False):
|
|||
return { "version": variables["full"].strip(),
|
||||
"full": variables["full"].strip() }
|
||||
|
||||
def versions_from_lookup(lookup, root, verbose=False):
|
||||
GITS = get_gits(root, verbose=verbose)
|
||||
if GITS is None:
|
||||
return {}
|
||||
|
||||
stdout = run_command(GITS, ["rev-parse", "--abbrev-ref", "HEAD"],
|
||||
cwd=root)
|
||||
if stdout is None:
|
||||
return {}
|
||||
|
||||
current_branch = stdout.strip()
|
||||
for matcher, tag, ref_commit in lookup:
|
||||
if matcher.match(current_branch):
|
||||
if tag is None or ref_commit is None:
|
||||
return {}
|
||||
|
||||
stdout = run_command(GITS, ["rev-list", "%s..HEAD" % ref_commit, "--count"], cwd=root)
|
||||
if stdout is None:
|
||||
return {}
|
||||
num_commits = stdout.strip()
|
||||
|
||||
stdout =run_command(GITS, ["rev-parse", "--short", "HEAD"], cwd=root)
|
||||
if stdout is None:
|
||||
return {}
|
||||
short_hash = stdout.strip()
|
||||
|
||||
stdout = run_command(GITS, ["describe", "--tags", "--dirty", "--always"], cwd=root)
|
||||
if stdout is None:
|
||||
return {}
|
||||
dirty = stdout.strip().endswith("-dirty")
|
||||
|
||||
stdout = run_command(GITS, ["rev-parse", "HEAD"], cwd=root)
|
||||
if stdout is None:
|
||||
return {}
|
||||
full = stdout.strip()
|
||||
|
||||
version = "%s-%s-g%s" % (tag, num_commits, short_hash)
|
||||
if dirty:
|
||||
version += "-dirty"
|
||||
full += "-dirty"
|
||||
return {"version": version, "full": full}
|
||||
|
||||
return {}
|
||||
|
||||
def versions_from_vcs(tag_prefix, root, verbose=False):
|
||||
# this runs 'git' from the root of 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.
|
||||
|
||||
if not os.path.exists(os.path.join(root, ".git")):
|
||||
if verbose:
|
||||
print("no .git in %s" % root)
|
||||
GITS = get_gits(root, verbose=verbose)
|
||||
if GITS is None:
|
||||
return {}
|
||||
|
||||
GITS = ["git"]
|
||||
if sys.platform == "win32":
|
||||
GITS = ["git.cmd", "git.exe"]
|
||||
stdout = run_command(GITS, ["describe", "--tags", "--dirty", "--always"],
|
||||
cwd=root)
|
||||
if stdout is None:
|
||||
|
|
@ -158,10 +210,39 @@ def versions_from_parentdir(parentdir_prefix, root, verbose=False):
|
|||
return {"version": dirname[len(parentdir_prefix):], "full": ""}
|
||||
|
||||
tag_prefix = ""
|
||||
parentdir_prefix = "octoprint-"
|
||||
parentdir_prefix = ""
|
||||
versionfile_source = "src/octoprint/_version.py"
|
||||
lookupfile = ".versioneer-lookup"
|
||||
|
||||
def get_versions(default={"version": "unknown", "full": ""}, verbose=False):
|
||||
def parse_lookup_file(root, lookup_path=None):
|
||||
if not lookup_path:
|
||||
lookup_path = lookupfile
|
||||
if not lookup_path:
|
||||
return []
|
||||
|
||||
path = os.path.join(root, lookup_path)
|
||||
if not os.path.exists(path):
|
||||
return []
|
||||
|
||||
import re
|
||||
lookup = []
|
||||
with open(os.path.join(root, lookup_path), "r") as f:
|
||||
for line in f:
|
||||
if '#' in line:
|
||||
line = line[:line.rindex('#')]
|
||||
line = line.strip()
|
||||
try:
|
||||
split_line = line.split()
|
||||
if len(split_line) == 3:
|
||||
pattern, tag, ref_commit = split_line
|
||||
lookup.append([re.compile(pattern), tag, ref_commit])
|
||||
elif len(split_line) >= 1:
|
||||
lookup.append([re.compile(split_line[0]), None, None])
|
||||
except:
|
||||
break
|
||||
return lookup
|
||||
|
||||
def get_versions(default={"version": "unknown", "full": ""}, lookup_path=None, verbose=False):
|
||||
# I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have
|
||||
# __file__, we can work backwards from there to the root. Some
|
||||
# py2exe/bbfreeze/non-CPython implementations don't do __file__, in which
|
||||
|
|
@ -182,7 +263,9 @@ def get_versions(default={"version": "unknown", "full": ""}, verbose=False):
|
|||
except NameError:
|
||||
return default
|
||||
|
||||
return (versions_from_vcs(tag_prefix, root, verbose)
|
||||
lookup = parse_lookup_file(root, lookup_path=lookup_path)
|
||||
return (versions_from_lookup(lookup, root, verbose)
|
||||
or versions_from_vcs(tag_prefix, root, verbose)
|
||||
or versions_from_parentdir(parentdir_prefix, root, verbose)
|
||||
or default)
|
||||
|
||||
|
|
|
|||
206
versioneer.py
206
versioneer.py
|
|
@ -252,6 +252,7 @@ versionfile_source = None
|
|||
versionfile_build = None
|
||||
tag_prefix = None
|
||||
parentdir_prefix = None
|
||||
lookupfile = None
|
||||
|
||||
VCS = "git"
|
||||
|
||||
|
|
@ -312,6 +313,18 @@ import sys
|
|||
import re
|
||||
import os.path
|
||||
|
||||
def get_gits(root, verbose=False):
|
||||
if not os.path.exists(os.path.join(root, ".git")):
|
||||
if verbose:
|
||||
print("no .git in %%s" %% root)
|
||||
return None
|
||||
|
||||
GITS = ["git"]
|
||||
if sys.platform == "win32":
|
||||
GITS = ["git.cmd", "git.exe"]
|
||||
return GITS
|
||||
|
||||
|
||||
def get_expanded_variables(versionfile_abs):
|
||||
# the code embedded in _version.py can just fetch the value of these
|
||||
# variables. When used from setup.py, we don't want to import
|
||||
|
|
@ -372,20 +385,60 @@ def versions_from_expanded_variables(variables, tag_prefix, verbose=False):
|
|||
return { "version": variables["full"].strip(),
|
||||
"full": variables["full"].strip() }
|
||||
|
||||
def versions_from_lookup(lookup, root, verbose=False):
|
||||
GITS = get_gits(root, verbose=verbose)
|
||||
if GITS is None:
|
||||
return {}
|
||||
|
||||
stdout = run_command(GITS, ["rev-parse", "--abbrev-ref", "HEAD"],
|
||||
cwd=root)
|
||||
if stdout is None:
|
||||
return {}
|
||||
|
||||
current_branch = stdout.strip()
|
||||
for matcher, tag, ref_commit in lookup:
|
||||
if matcher.match(current_branch):
|
||||
if tag is None or ref_commit is None:
|
||||
return {}
|
||||
|
||||
stdout = run_command(GITS, ["rev-list", "%%s..HEAD" %% ref_commit, "--count"], cwd=root)
|
||||
if stdout is None:
|
||||
return {}
|
||||
num_commits = stdout.strip()
|
||||
|
||||
stdout =run_command(GITS, ["rev-parse", "--short", "HEAD"], cwd=root)
|
||||
if stdout is None:
|
||||
return {}
|
||||
short_hash = stdout.strip()
|
||||
|
||||
stdout = run_command(GITS, ["describe", "--tags", "--dirty", "--always"], cwd=root)
|
||||
if stdout is None:
|
||||
return {}
|
||||
dirty = stdout.strip().endswith("-dirty")
|
||||
|
||||
stdout = run_command(GITS, ["rev-parse", "HEAD"], cwd=root)
|
||||
if stdout is None:
|
||||
return {}
|
||||
full = stdout.strip()
|
||||
|
||||
version = "%%s-%%s-g%%s" %% (tag, num_commits, short_hash)
|
||||
if dirty:
|
||||
version += "-dirty"
|
||||
full += "-dirty"
|
||||
return {"version": version, "full": full}
|
||||
|
||||
return {}
|
||||
|
||||
def versions_from_vcs(tag_prefix, root, verbose=False):
|
||||
# this runs 'git' from the root of 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.
|
||||
|
||||
if not os.path.exists(os.path.join(root, ".git")):
|
||||
if verbose:
|
||||
print("no .git in %%s" %% root)
|
||||
GITS = get_gits(root, verbose=verbose)
|
||||
if GITS is None:
|
||||
return {}
|
||||
|
||||
GITS = ["git"]
|
||||
if sys.platform == "win32":
|
||||
GITS = ["git.cmd", "git.exe"]
|
||||
stdout = run_command(GITS, ["describe", "--tags", "--dirty", "--always"],
|
||||
cwd=root)
|
||||
if stdout is None:
|
||||
|
|
@ -418,8 +471,37 @@ def versions_from_parentdir(parentdir_prefix, root, verbose=False):
|
|||
tag_prefix = "%(TAG_PREFIX)s"
|
||||
parentdir_prefix = "%(PARENTDIR_PREFIX)s"
|
||||
versionfile_source = "%(VERSIONFILE_SOURCE)s"
|
||||
lookupfile = %(LOOKUPFILE)s
|
||||
|
||||
def get_versions(default={"version": "unknown", "full": ""}, verbose=False):
|
||||
def parse_lookup_file(root, lookup_path=None):
|
||||
if not lookup_path:
|
||||
lookup_path = lookupfile
|
||||
if not lookup_path:
|
||||
return []
|
||||
|
||||
path = os.path.join(root, lookup_path)
|
||||
if not os.path.exists(path):
|
||||
return []
|
||||
|
||||
import re
|
||||
lookup = []
|
||||
with open(os.path.join(root, lookup_path), "r") as f:
|
||||
for line in f:
|
||||
if '#' in line:
|
||||
line = line[:line.rindex('#')]
|
||||
line = line.strip()
|
||||
try:
|
||||
split_line = line.split()
|
||||
if len(split_line) == 3:
|
||||
pattern, tag, ref_commit = split_line
|
||||
lookup.append([re.compile(pattern), tag, ref_commit])
|
||||
elif len(split_line) >= 1:
|
||||
lookup.append([re.compile(split_line[0]), None, None])
|
||||
except:
|
||||
break
|
||||
return lookup
|
||||
|
||||
def get_versions(default={"version": "unknown", "full": ""}, lookup_path=None, verbose=False):
|
||||
# I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have
|
||||
# __file__, we can work backwards from there to the root. Some
|
||||
# py2exe/bbfreeze/non-CPython implementations don't do __file__, in which
|
||||
|
|
@ -440,7 +522,9 @@ def get_versions(default={"version": "unknown", "full": ""}, verbose=False):
|
|||
except NameError:
|
||||
return default
|
||||
|
||||
return (versions_from_vcs(tag_prefix, root, verbose)
|
||||
lookup = parse_lookup_file(root, lookup_path=lookup_path)
|
||||
return (versions_from_lookup(lookup, root, verbose)
|
||||
or versions_from_vcs(tag_prefix, root, verbose)
|
||||
or versions_from_parentdir(parentdir_prefix, root, verbose)
|
||||
or default)
|
||||
|
||||
|
|
@ -488,6 +572,18 @@ import sys
|
|||
import re
|
||||
import os.path
|
||||
|
||||
def get_gits(root, verbose=False):
|
||||
if not os.path.exists(os.path.join(root, ".git")):
|
||||
if verbose:
|
||||
print("no .git in %s" % root)
|
||||
return None
|
||||
|
||||
GITS = ["git"]
|
||||
if sys.platform == "win32":
|
||||
GITS = ["git.cmd", "git.exe"]
|
||||
return GITS
|
||||
|
||||
|
||||
def get_expanded_variables(versionfile_abs):
|
||||
# the code embedded in _version.py can just fetch the value of these
|
||||
# variables. When used from setup.py, we don't want to import
|
||||
|
|
@ -548,20 +644,62 @@ def versions_from_expanded_variables(variables, tag_prefix, verbose=False):
|
|||
return { "version": variables["full"].strip(),
|
||||
"full": variables["full"].strip() }
|
||||
|
||||
|
||||
def versions_from_lookup(lookup, root, verbose=False):
|
||||
GITS = get_gits(root, verbose=verbose)
|
||||
if GITS is None:
|
||||
return {}
|
||||
|
||||
stdout = run_command(GITS, ["rev-parse", "--abbrev-ref", "HEAD"],
|
||||
cwd=root)
|
||||
if stdout is None:
|
||||
return {}
|
||||
|
||||
current_branch = stdout.strip()
|
||||
for matcher, tag, ref_commit in lookup:
|
||||
if matcher.match(current_branch):
|
||||
if tag is None or ref_commit is None:
|
||||
return {}
|
||||
|
||||
stdout = run_command(GITS, ["rev-list", "%s..HEAD" % ref_commit, "--count"], cwd=root)
|
||||
if stdout is None:
|
||||
return {}
|
||||
num_commits = stdout.strip()
|
||||
|
||||
stdout =run_command(GITS, ["rev-parse", "--short", "HEAD"], cwd=root)
|
||||
if stdout is None:
|
||||
return {}
|
||||
short_hash = stdout.strip()
|
||||
|
||||
stdout = run_command(GITS, ["describe", "--tags", "--dirty", "--always"], cwd=root)
|
||||
if stdout is None:
|
||||
return {}
|
||||
dirty = stdout.strip().endswith("-dirty")
|
||||
|
||||
stdout = run_command(GITS, ["rev-parse", "HEAD"], cwd=root)
|
||||
if stdout is None:
|
||||
return {}
|
||||
full = stdout.strip()
|
||||
|
||||
version = "%s-%s-g%s" % (tag, num_commits, short_hash)
|
||||
if dirty:
|
||||
version += "-dirty"
|
||||
full += "-dirty"
|
||||
return {"version": version, "full": full}
|
||||
|
||||
return {}
|
||||
|
||||
|
||||
def versions_from_vcs(tag_prefix, root, verbose=False):
|
||||
# this runs 'git' from the root of 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.
|
||||
|
||||
if not os.path.exists(os.path.join(root, ".git")):
|
||||
if verbose:
|
||||
print("no .git in %s" % root)
|
||||
GITS = get_gits(root, verbose=verbose)
|
||||
if GITS is None:
|
||||
return {}
|
||||
|
||||
GITS = ["git"]
|
||||
if sys.platform == "win32":
|
||||
GITS = ["git.cmd", "git.exe"]
|
||||
stdout = run_command(GITS, ["describe", "--tags", "--dirty", "--always"],
|
||||
cwd=root)
|
||||
if stdout is None:
|
||||
|
|
@ -684,11 +822,38 @@ def get_root():
|
|||
except NameError:
|
||||
return os.path.dirname(os.path.abspath(sys.argv[0]))
|
||||
|
||||
def parse_lookup_file(root, lookup_path=None):
|
||||
if not lookup_path:
|
||||
lookup_path = lookupfile
|
||||
|
||||
path = os.path.join(root, lookup_path)
|
||||
if not os.path.exists(path):
|
||||
return []
|
||||
|
||||
import re
|
||||
lookup = []
|
||||
with open(os.path.join(root, lookup_path), "r") as f:
|
||||
for line in f:
|
||||
if '#' in line:
|
||||
line = line[:line.rindex("#")]
|
||||
line = line.strip()
|
||||
try:
|
||||
split_line = line.split()
|
||||
if len(split_line) == 3:
|
||||
pattern, tag, ref_commit = split_line
|
||||
lookup.append([re.compile(pattern), tag, ref_commit])
|
||||
elif len(split_line) >= 1:
|
||||
lookup.append([re.compile(split_line[0]), None, None])
|
||||
except:
|
||||
break
|
||||
return lookup
|
||||
|
||||
def get_versions(default=DEFAULT, verbose=False):
|
||||
# returns dict with two keys: 'version' and 'full'
|
||||
assert versionfile_source is not None, "please set versioneer.versionfile_source"
|
||||
assert tag_prefix is not None, "please set versioneer.tag_prefix"
|
||||
assert parentdir_prefix is not None, "please set versioneer.parentdir_prefix"
|
||||
|
||||
# I am in versioneer.py, which must live at the top of the source tree,
|
||||
# which we use to compute the root directory. py2exe/bbfreeze/non-CPython
|
||||
# don't have __file__, in which case we fall back to sys.argv[0] (which
|
||||
|
|
@ -697,6 +862,11 @@ def get_versions(default=DEFAULT, verbose=False):
|
|||
root = get_root()
|
||||
versionfile_abs = os.path.join(root, versionfile_source)
|
||||
|
||||
if lookupfile:
|
||||
lookup = parse_lookup_file(root, lookup_path = lookupfile)
|
||||
else:
|
||||
lookup = None
|
||||
|
||||
# extract version from first of _version.py, 'git describe', parentdir.
|
||||
# This is meant to work for developers using a source checkout, for users
|
||||
# of a tarball created by 'setup.py sdist', and for users of a
|
||||
|
|
@ -715,6 +885,12 @@ def get_versions(default=DEFAULT, verbose=False):
|
|||
if verbose: print("got version from file %s %s" % (versionfile_abs,ver))
|
||||
return ver
|
||||
|
||||
if lookup:
|
||||
ver = versions_from_lookup(lookup, root, verbose=verbose)
|
||||
if ver:
|
||||
if verbose: print("got version from lookup %s" % ver)
|
||||
return ver
|
||||
|
||||
ver = versions_from_vcs(tag_prefix, root, verbose)
|
||||
if ver:
|
||||
if verbose: print("got version from git %s" % ver)
|
||||
|
|
@ -792,6 +968,7 @@ if 'cx_Freeze' in sys.modules: # cx_freeze enabled?
|
|||
"TAG_PREFIX": tag_prefix,
|
||||
"PARENTDIR_PREFIX": parentdir_prefix,
|
||||
"VERSIONFILE_SOURCE": versionfile_source,
|
||||
"LOOKUPFILE": '"%s"' % lookupfile if lookupfile is not None else "None",
|
||||
})
|
||||
f.close()
|
||||
|
||||
|
|
@ -835,6 +1012,7 @@ class cmd_update_files(Command):
|
|||
"TAG_PREFIX": tag_prefix,
|
||||
"PARENTDIR_PREFIX": parentdir_prefix,
|
||||
"VERSIONFILE_SOURCE": versionfile_source,
|
||||
"LOOKUPFILE": '"%s"' % lookupfile if lookupfile is not None else "None",
|
||||
})
|
||||
f.close()
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue