eobuilder/eobuilder/changelog.py

121 lines
3.5 KiB
Python

import codecs
import datetime
import textwrap
import os
import re
import sys
import pytz
import git
from git.exc import GitCommandError
from git.objects.commit import Commit
from . import cmdline
def get_commit_from_tag(repo, tag_ref):
ref = repo.tags[tag_ref]
while ref.object.type == 'tag':
ref = ref.object
assert ref.object.type == 'commit'
return ref.object
def is_pep0440_project(path):
if not os.path.exists(os.path.join(path, 'setup.py')):
return False
curdir = os.getcwd()
try:
os.chdir(path)
output = cmdline.setup_py('--version')
if '+' in output:
return True
finally:
os.chdir(curdir)
return False
def changelog_from_git(
project,
version_suffix,
path,
repository='eobuilder',
maintainer_name='eobuilder',
maintainer_email='eobuilder@entrouvert.com',
epoch='',
):
repo = git.repo.Repo(path)
is_pep0440 = is_pep0440_project(path)
versions = []
try:
last_tag = repo.git.describe(abbrev=0)
except GitCommandError:
# no tag version is 0.0.<number of commits>
versions.append(('0.0.%d' % repo.head.commit.count(), repo.head.commit))
else:
if get_commit_from_tag(repo, last_tag) != repo.head.commit:
versions.append((repo.git.describe(), repo.head.commit))
versions.append((last_tag, get_commit_from_tag(repo, last_tag)))
while True:
try:
last_tag = repo.git.describe(last_tag + '~', abbrev=0)
except GitCommandError:
break
else:
versions.append((last_tag, get_commit_from_tag(repo, last_tag)))
n = len(versions)
for i in range(n):
name, commit = versions[i]
if i == n - 1:
logs = [commit] + list(commit.iter_parents())
else:
def encode_hex(value):
return codecs.encode(value, 'hex').decode('ascii')
reflog = '%s..%s' % (encode_hex(versions[i + 1][1].binsha), encode_hex(commit.binsha))
logs = list(Commit.iter_items(repo, reflog))
if not logs:
continue
version = name.lstrip('v').replace('-', '.')
if is_pep0440:
# use .postX+g form
version = re.sub('\.(\d+)\.g', r'.post\1+g', version)
if i == 0:
version += version_suffix
if epoch:
version = '%s:%s' % (epoch, version)
yield '%s (%s) %s; urgency=low' % (project, str(version), repository)
yield ''
for l in logs:
try:
t = '(%s) %s' % (l.hexsha[:6], l.summary)
except LookupError as e:
t = '(%s) %s' % (l.hexsha[:6], e)
lines = textwrap.wrap(t, 80)
for prefix, suffix in zip([' * '] + [' '] * (len(lines) - 1), lines):
yield (prefix + suffix)
paris = pytz.timezone('Europe/Paris')
date = (
datetime.datetime.fromtimestamp(logs[0].committed_date + logs[0].committer_tz_offset)
.replace(tzinfo=pytz.UTC)
.astimezone(paris)
.strftime('%a, %d %b %Y %H:%M:%S %z')
)
yield ''
yield ' -- %s <%s> %s' % (maintainer_name, maintainer_email, date)
yield ''
if __name__ == '__main__':
project = sys.argv[1]
version_suffix = sys.argv[2]
if len(sys.argv) > 3:
path = sys.argv[3]
else:
path = os.getcwd()
print('\n'.join(changelog_from_git(project, version_suffix, path)))