aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/snakeoil/version.py')
-rw-r--r--src/snakeoil/version.py78
1 files changed, 44 insertions, 34 deletions
diff --git a/src/snakeoil/version.py b/src/snakeoil/version.py
index 7b9a500..0e88dbf 100644
--- a/src/snakeoil/version.py
+++ b/src/snakeoil/version.py
@@ -3,12 +3,14 @@
import errno
import os
import subprocess
+from datetime import datetime
from importlib import import_module
+from typing import NamedTuple, Optional
_ver = None
-def get_version(project, repo_file, api_version=None):
+def get_version(project, repo_file, api_version=None) -> str:
"""Determine a project's version information.
Standardized version retrieval for git-based projects. In summary, if the
@@ -40,74 +42,82 @@ def get_version(project, repo_file, api_version=None):
version_info = get_git_version(path)
if version_info is None:
- s = ''
- elif version_info['tag'] == api_version:
- s = f" -- released {version_info['date']}"
+ suffix = ''
+ elif version_info.tag == api_version:
+ suffix = f' -- released {version_info.date_rfc2822}'
else:
- rev = version_info['rev'][:7]
- date = version_info['date']
- commits = version_info.get('commits', None)
- commits = f'-{commits}' if commits is not None else ''
- s = f'{commits}-g{rev} -- {date}'
+ rev = version_info.short_revision
+ date = version_info.date_rfc2822
+ commits = f'-{version_info.commits}' if version_info.commits is not None else ''
+ suffix = f'{commits}-g{rev} -- {date}'
- _ver = f'{project} {api_version}{s}'
+ _ver = f'{project} {api_version}{suffix}'
return _ver
-def _run_git(path, cmd):
+def _run_git(path: str, *cmd: str):
env = dict(os.environ)
for key in env.copy(): # pragma: no cover
if key.startswith("LC_"):
del env[key]
env["LC_CTYPE"] = "C"
env["LC_ALL"] = "C"
+ r = subprocess.Popen(('git', ) + cmd, env=env, cwd=path,
+ stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
- r = subprocess.Popen(
- ['git'] + list(cmd), stdout=subprocess.PIPE, env=env,
- stderr=subprocess.DEVNULL, cwd=path)
-
- stdout = r.communicate()[0]
+ stdout, _ = r.communicate()
return stdout, r.returncode
-def get_git_version(path):
+class GitVersion(NamedTuple):
+ revision: str
+ date: datetime
+ tag: Optional[str] = None
+ commits: Optional[int] = None
+
+ @property
+ def date_rfc2822(self):
+ return self.date.strftime('%a, %d %b %Y %H:%M:%S %z')
+
+ @property
+ def short_revision(self):
+ return self.revision[:7]
+
+
+def get_git_version(path: str) -> Optional[GitVersion]:
"""Return git related revision data."""
path = os.path.abspath(path)
try:
- stdout, ret = _run_git(path, ["log", "--format=%H\n%aD", "HEAD^..HEAD"])
-
+ stdout, ret = _run_git(path, "log", "--format=%H\n%aI", "HEAD^..HEAD")
if ret != 0:
return None
- data = stdout.decode().splitlines()
- tag = _get_git_tag(path, data[0])
+ revision, date = stdout.decode().splitlines()
+ tag = _get_git_tag(path, revision)
# get number of commits since most recent tag
- stdout, ret = _run_git(path, ['describe', '--tags', '--abbrev=0'])
- prev_tag = None
+ stdout, ret = _run_git(path, 'describe', '--tags', '--abbrev=0')
commits = None
if ret == 0:
prev_tag = stdout.decode().strip()
- stgbdout, ret = _run_git(
- path, ['log', '--oneline', f'{prev_tag}..HEAD'])
+ stdout, ret = _run_git(
+ path, 'log', '--oneline', f'{prev_tag}..HEAD')
if ret == 0:
commits = len(stdout.decode().splitlines())
- return {
- 'rev': data[0],
- 'date': data[1],
- 'tag': tag,
- 'commits': commits,
- }
- except EnvironmentError as e:
+ return GitVersion(
+ revision=revision, date=datetime.fromisoformat(date),
+ tag=tag, commits=commits,
+ )
+ except EnvironmentError as exc:
# ENOENT is thrown when the git binary can't be found.
- if e.errno != errno.ENOENT:
+ if exc.errno != errno.ENOENT:
raise
return None
def _get_git_tag(path, rev):
- stdout, _ = _run_git(path, ['name-rev', '--tag', rev])
+ stdout, _ = _run_git(path, 'name-rev', '--tag', rev)
tag = stdout.decode().split()
if len(tag) != 2:
return None