Skip to content

Instantly share code, notes, and snippets.

@stephenmcd
Created July 12, 2010 22:03
Show Gist options
  • Save stephenmcd/473147 to your computer and use it in GitHub Desktop.
Save stephenmcd/473147 to your computer and use it in GitHub Desktop.
Extract a RST changelog from a HG repo
#!/usr/bin/env python
"""
Use a mercurial repository to generate a reStructuredText changelog.
"""
from datetime import datetime
from mercurial import ui, hg
from django.utils.datastructures import SortedDict
path_to_repo = "/path/to/repo/"
repo = hg.repository(ui.ui(), path_to_repo)
version_file = os.path.join(path_to_repo, "__init__.py")
version_var = "__version__"
changelog_filename = "CHANGELOG"
changelog_file = os.path.join(path_to_repo, changelog_filename)
versions = SortedDict()
for changeset in reversed(list(repo.changelog)):
# Check if the file with the version number is in this changeset and if
# it is, pull it out and assign it as a variable.
context = repo.changectx(changeset)
files = context.files()
new_version = False
if version_file in files:
for line in context[version_file].data().split("\n"):
if line.startswith(version_var):
exec line
version_info = {"changes": [], "date":
datetime.fromtimestamp(context.date()[0]
).strftime("%b %d, %Y")}
versions[globals()[version_var]] = version_info
new_version = len(files) == 1
# Ignore changesets that are merges, bumped the version or regenerated
# the changelog itself
merge = len(context.parents()) > 1
changelog_update = changelog_filename in files and len(files) == 1
if merge or new_version or changelog_update:
continue
# Ensure we have a current version and if so, add this changeset's
# description to it.
try:
version = globals()[version_var]
except KeyError:
continue
else:
description = context.description().rstrip(".")
user = context.user().split()[0]
entry = "%s - %s" % (description, user)
if entry not in versions[version]["changes"]:
versions[version]["changes"].insert(0, entry)
# Write out the changelog.
with open(changelog_file, "w") as f:
for version, version_info in versions.items():
version_header = "Version %s (%s)" % (version, version_info["date"])
f.write("%s\n" % version_header)
f.write("%s\n" % ("-" * len(version_header)))
f.write("\n")
if version_info["changes"]:
for change in version_info["changes"]:
f.write(" * %s\n" % change)
else:
f.write(" * No changes listed.\n")
f.write("\n")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment