-
Notifications
You must be signed in to change notification settings - Fork 813
/
Copy pathchangelog.py
150 lines (103 loc) · 3.19 KB
/
changelog.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# Requires python3 to work since, python 3< does not implement %z.
import sys
sys.path += ["/Users/diasbruno/.local/lib/python3.7/site-packages"]
from datetime import datetime
from subprocess import Popen, PIPE
import semver
import functools
# 1: version, 2: date, 3: dashes, 4: entries
LOG_ENTRY = """{}
{}
{}
"""
head_version = "HEAD"
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 log_entry(entry):
log = entry.split(' ')
hash = log[0]
log = ' '.join(log[1:])
return "- [%s](../../commit/%s) %s" % (hash, hash, log)
def get_tags_date(tag):
args = [tag, "-1", '--format="%ad"']
date_time = git_log(args).split('\n')[0]
if date_time != '':
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')
return dt
def log_in_between_versions(t):
(a, b, logs) = t
v = b and to_version(b) or head_version
dt = get_tags_date(v)
header = "{} - {} UTC".format(b or head_version, dt)
dashes = ("-" * len(header))
def write_log(acc, log):
if log[8:8+7] == 'Release' or log[8:8+7] == 'release':
return acc
acc.append(log_entry(log))
return acc
actual_log = list(functools.reduce(write_log,
logs.splitlines(),
[]))
if len(actual_log) == 0:
entries = '-\n\n'
else:
entries = "\n".join(actual_log)
return LOG_ENTRY.format(header, dashes, entries)
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 to_version(tag):
if not tag:
return "HEAD"
if tag.prerelease:
return str(tag)
return "v{}".format(tag)
def logs_between(base, b):
to = to_version(b)
between = "{}..{}".format(to_version(base), to)
logs = git_log([between, "--format='%h %s'"])
return (base, b, logs)
def parse_version(version):
if version == 'HEAD':
return version
if version[0] == 'v':
version = version[1:]
return semver.parse_version_info(version)
def get_all_tags():
lines = git_exec(["tag", "-l"])
versions = map(parse_version, lines.splitlines())
return sorted(versions)
def generate_current():
versions = get_all_tags()
base = versions[-1]
logs = logs_between(base, None)
return [log_in_between_versions(logs)]
def generate_all():
versions = get_all_tags()
log_versions = adjacents(versions, logs_between, [])
vs = map(log_in_between_versions, log_versions)
return list(vs)
if __name__ == "__main__":
argc = len(sys.argv)
if sys.argv[1] == '-a': # all
head_version = sys.argv[2] if argc > 2 else "HEAD"
log = generate_all()
log.reverse()
elif sys.argv[1] == '-c': # current
head_version = sys.argv[2]
log = generate_current()
print("\n".join(log))