generate_changelog/rpmautospec/changelog.py
Nils Philippsen 059d133564 Wrap overly long lines
Signed-off-by: Nils Philippsen <nils@redhat.com>
2020-02-26 10:13:56 +01:00

121 lines
4 KiB
Python

#!/usr/bin/python3
import collections
import datetime
import logging
import os
import subprocess
import textwrap
import pygit2
_log = logging.getLogger(__name__)
def register_subcommand(subparsers):
subcmd_name = "generate-changelog"
gen_changelog_parser = subparsers.add_parser(
subcmd_name, help="Generate changelog entries from git commit logs",
)
gen_changelog_parser.add_argument("worktree_path", help="Path to the dist-git worktree")
return subcmd_name
def run_command(command, cwd=None):
""" Run the specified command in a specific working directory if one
is specified.
"""
output = None
try:
output = subprocess.check_output(command, cwd=cwd, stderr=subprocess.PIPE)
except subprocess.CalledProcessError as e:
_log.error("Command `{}` return code: `{}`".format(" ".join(command), e.returncode))
_log.error("stdout:\n-------\n{}".format(e.stdout))
_log.error("stderr:\n-------\n{}".format(e.stderr))
raise Exception("Command failed to run")
return output
def main(args):
""" Main method. """
repopath = args.worktree_path
repo_obj = pygit2.Repository(repopath)
name = os.path.basename(repopath)
branch = repo_obj.lookup_branch(repo_obj.head.shorthand)
commit = branch.peel(pygit2.Commit)
data = collections.defaultdict(list)
for commit in repo_obj.walk(commit.hex, pygit2.GIT_SORT_TIME):
if len(commit.parents) > 1:
# Ignore merge commits
continue
commit_dt = datetime.datetime.utcfromtimestamp(commit.commit_time)
if commit_dt < (datetime.datetime.utcnow() - datetime.timedelta(days=730)):
# Ignore all commits older than 2 years
break
repo_obj.checkout_tree(
commit, strategy=pygit2.GIT_CHECKOUT_FORCE | pygit2.GIT_CHECKOUT_RECREATE_MISSING,
)
if os.path.exists(os.path.join(repopath, f"{name}.spec")):
try:
output = run_command(
[
"rpm",
"--qf",
"%{name} %{version} %{release}\n",
"--specfile",
f"{name}.spec",
],
cwd=repopath,
)
except Exception:
continue
output = tuple(
output.decode("utf-8").strip().split("\n")[0].rsplit(".", 1)[0].split(" ")
)
nvr = "-".join(output)
if commit.parents:
diff = repo_obj.diff(commit.parents[0], commit)
else:
# First commit in the repo
diff = commit.tree.diff_to_tree(swap=True)
if diff.stats.files_changed:
files_changed = [d.new_file.path for d in diff.deltas]
ignore = True
for filename in files_changed:
if filename.endswith((".spec", ".patch")):
ignore = False
if not ignore:
data[output].append(commit)
else:
print("No more spec file, bailing")
break
for nvr, commits in data.items():
for idx, commit in enumerate(reversed(commits)):
last_commit = idx + 1 == len(commits)
commit_dt = datetime.datetime.utcfromtimestamp(commit.commit_time)
wrapper = textwrap.TextWrapper(width=75, subsequent_indent=" ")
message = wrapper.fill(commit.message.split("\n")[0].strip("- "))
if last_commit:
print(
f"* {commit_dt.strftime('%a %b %d %Y')} {commit.author.name}"
f" <{commit.author.email}> - {nvr[1]}-{nvr[2]}"
)
else:
print(
f"* {commit_dt.strftime('%a %b %d %Y')} {commit.author.name}"
f" <{commit.author.email}>"
)
print("- %s" % message)
print()