109 lines
3.4 KiB
Python
109 lines
3.4 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)))
|