160 lines
3.7 KiB
Python
160 lines
3.7 KiB
Python
# Requires python3 to work since, python 3< does not implement %z.
|
|
|
|
import sys
|
|
import os
|
|
import json
|
|
from datetime import datetime
|
|
import pytz
|
|
from subprocess import Popen, PIPE, STDOUT
|
|
|
|
|
|
class Version(object):
|
|
def __init__(self, version):
|
|
v = version
|
|
if v.startswith('v'):
|
|
v = v[1:].split('\n')[0]
|
|
fix = v.split('.')
|
|
self.major = int(fix[0])
|
|
self.minor = int(fix[1])
|
|
self.patch = int(fix[2])
|
|
self.build = None
|
|
self.tip = False
|
|
|
|
def __str__(self):
|
|
return self.__repr__()
|
|
|
|
def __repr__(self):
|
|
return "v" + str(self.major) + "." + str(self.minor) + "." + str(self.patch)
|
|
|
|
|
|
class Changelog(object):
|
|
def __init__(self, info):
|
|
a, b, log = info
|
|
self.log = log
|
|
self.a = a
|
|
self.b = b
|
|
|
|
def log_in_between_versions(self):
|
|
hash = self.log.split(' ')[0]
|
|
|
|
if zeroversion(self.a):
|
|
return ""
|
|
|
|
date_time = git_log([str(self.a), "-1", '--format="%ad"']).split('\n')[0]
|
|
|
|
if date_time is not '':
|
|
dt = datetime.strptime(date_time, '%a %b %d %H:%M:%S %Y %z')
|
|
else:
|
|
dt = datetime.now()
|
|
dt = dt.strftime('%a, %d %b %Y %H:%M:%S')
|
|
|
|
log = str(self.a) + " - " + dt + " UTC\n"
|
|
log = log + ("-" * (len(log) - 1)) + "\n\n"
|
|
|
|
actual_log = self.log.splitlines()
|
|
|
|
if len(actual_log) == 1:
|
|
entries = "-\n\n"
|
|
else:
|
|
entries = "\n".join(map(url_entry, actual_log[1:])) + "\n\n"
|
|
|
|
log = log + entries
|
|
|
|
return log
|
|
|
|
def __str__(self):
|
|
return self.__repr__(self)
|
|
|
|
def __repr__(self):
|
|
return "Changelog: " + self.log
|
|
|
|
|
|
def url_entry(entry):
|
|
log = entry.split(' ')
|
|
hash = log[0]
|
|
log = ' '.join(log[1:])
|
|
|
|
return "- [%s](../../commit/%s) %s" % (hash, hash, log)
|
|
|
|
def zeroversion(v):
|
|
return v.major == 0 and v.minor == 0 and v.patch == 0
|
|
|
|
class compareversions(object):
|
|
def __init__(self, obj, *args):
|
|
self.obj = obj
|
|
|
|
def __lt__(self, other):
|
|
if self.obj.major < other.obj.major:
|
|
return True
|
|
if self.obj.minor < other.obj.minor:
|
|
return True
|
|
if self.obj.patch < other.obj.patch:
|
|
return True
|
|
return False
|
|
|
|
def git_exec(args):
|
|
p = Popen(" ".join(["git"] + args), shell=True, stdout=PIPE, stderr=PIPE)
|
|
out, err = p.communicate()
|
|
return out.decode('utf-8')
|
|
|
|
def git_log(args):
|
|
return git_exec(["log"] + args)
|
|
|
|
def adjacents(ls, f, res):
|
|
if len(ls) == 0:
|
|
return res
|
|
|
|
first = ls[0]
|
|
if len(ls) == 1:
|
|
next = None
|
|
else:
|
|
next = ls[1]
|
|
|
|
res.append(f(first, next))
|
|
return adjacents(ls[1:], f, res)
|
|
|
|
def logs_between(a, b):
|
|
v = a
|
|
if b is None:
|
|
_ = str(a)
|
|
else:
|
|
if a.tip:
|
|
a = "HEAD"
|
|
else:
|
|
a = str(a)
|
|
_ = str(b) + ".." + a
|
|
return (v, b, git_log(["--format='%h %s'", _]))
|
|
|
|
def changelog(with_versions):
|
|
process = with_versions
|
|
versions = []
|
|
|
|
generate_all = len(with_versions) == 0
|
|
|
|
if generate_all:
|
|
lines = git_exec(["tag", "-l"])
|
|
process = lines.splitlines()
|
|
|
|
for item in process:
|
|
versions.append(Version(item))
|
|
|
|
versions = sorted(versions, key=compareversions, reverse=True)
|
|
|
|
if generate_all:
|
|
vs = map(Changelog, adjacents(versions, logs_between, []))
|
|
else:
|
|
versions[0].tip = True
|
|
vs = map(Changelog, [logs_between(versions[0], versions[1])])
|
|
|
|
return [v.log_in_between_versions() for v in vs]
|
|
|
|
|
|
if __name__ == "__main__":
|
|
args = sys.argv[1:]
|
|
for_version=[]
|
|
|
|
if len(args) > 0:
|
|
for_version = list(args)
|
|
|
|
print("\n".join(changelog(for_version)))
|