Last active
December 29, 2015 22:09
-
-
Save aquinzi/7734823 to your computer and use it in GitHub Desktop.
Create svn changelog
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Create svn changelog (Python 2.7, 3.3) | |
""" | |
Takes the svn log [options] and turns them into a changelog. | |
Basic: | |
-------- | |
2013-11-25: | |
changed arguments (better handling) | |
fix: output path with one file | |
fix: finding <h1> | |
2013-11-19: | |
fixed: now files are saved according to source dir tree | |
+ option to save files in one depth dir | |
2013-11-19: | |
+ relative links for book | |
Options: | |
--------- | |
Show author with --author, revision with --rev, time with --time. You can prefix a char with --prefix. | |
The default order is new to old, but you can reverse it with --reverse | |
Specify the date (in ISO 8601) with --date. You can include a range as date1:date2, or leave date2 empty (date1:) to include today. | |
Specify the revision with --revision, or a range as rev1:rev2 or leave rev2 empty to include HEAD revision | |
Group them | |
---------- | |
You can group the dates with --group. This will show revs in a list. If you want to group them, use --subgroup ([rev][msg]). | |
If you want to show them inline (besides grouping with date), use --inline ([rev][msg][author]) | |
""" | |
import subprocess | |
import sys | |
import argparse | |
import datetime | |
from collections import namedtuple | |
__version__ = "0.2" | |
logItemDetails = namedtuple('logItemDetails', 'rev,author,msgs') | |
groupit = {} | |
def format_strings(option, value, grouping=False): | |
""" Format the option: adds space to value or make it blank | |
if grouping, dont add the space | |
""" | |
if option: | |
if not grouping: | |
return " " + value | |
else: | |
return value | |
return "" | |
def prepare_range(option, value): | |
"""Prepares the options with range, or the ones that use them """ | |
if len(value.split(":")) == 1: | |
part1 = value | |
part2 = "" | |
else: | |
part1, part2 = value.split(":") | |
if option == 'date': | |
if part2: | |
part2 = datetime.datetime.strptime(part2, "%Y-%m-%d").date() | |
else: | |
part2 = datetime.date.today() | |
part2 = part2 + datetime.timedelta(days=1) | |
if option == 'revision': | |
if not part2: | |
try: | |
#head revision | |
svnversion = subprocess.check_output(['svnversion']).strip() | |
except subprocess.CalledProcessError: | |
sys.exit() | |
if svnversion.endswith('M') or svnversion.endswith('S') \ | |
or svnversion.endswith('P') or svnversion.endswith('MSP'): | |
if not svnversion.endswith('MSP'): | |
svnversion = svnversion[0:len(svnversion)-1] | |
else: | |
svnversion = svnversion[0:len(svnversion)-3] | |
value = part1 + ":" + svnversion | |
if option == 'date': | |
#add one day so it's really that day and not the one before it | |
# see http://svnbook.red-bean.com/en/1.5/svn.tour.revs.specifiers.html#svn.tour.revs.dates | |
part1 = datetime.datetime.strptime(part1, "%Y-%m-%d").date() | |
part1 = part1 + datetime.timedelta(days=1) | |
if part2: | |
part2 = ":{" + part2.isoformat() + '}' | |
value = '{' + part1.isoformat() + '}' + part2 | |
return value | |
def clean_svnlog_item(item): | |
"""returns necessary data (rev, author, date, time, msgs) from svn log item""" | |
item = item.splitlines() | |
item_title = item[1] | |
item_msgs = item[3:] | |
rev, author, date_all, totallines = item_title.split(" | ") | |
date, time, diftime, hdayname, hday, hmonth, hyear = date_all.split(" ") | |
time = time[0:len(time)-3] # remove seconds | |
if not OPTIONS.group: | |
rev = format_strings(OPTIONS.show_rev, rev) | |
author = format_strings(OPTIONS.show_author, author) | |
time = format_strings(OPTIONS.show_time, time) | |
else: | |
rev = format_strings(OPTIONS.show_rev, rev, True) | |
author = format_strings(OPTIONS.show_author, author, True) | |
return rev, author, date, time, item_msgs | |
parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter, description=''' Make a changelog from svn. | |
You\'re using '''+__version__+''' version''') | |
parser.add_argument("path", help="The working dir or file") | |
exclusive = parser.add_mutually_exclusive_group() | |
exclusive.add_argument("--date", help="Specify date (ISO 8601) or range (date1:date2) to show from. Can leave second date in range (date1:) empty to include today") | |
exclusive.add_argument("--revision", help="Specify revision or range (rev1:rev2) to show from. Can leave second rev in range (rev1:) to include latest") | |
parser.add_argument("--show-author", "-a", action='store_true', help="Show author") | |
parser.add_argument("--show-rev", "-r", action='store_true', help="Show revision") | |
parser.add_argument("--show-time", "-t", action='store_true', help="Show time (HH:MM)") | |
parser.add_argument("--group" , "-g", action='store_true', help="Group by date, show revs and authors in list (if enabled).") | |
parser.add_argument("--subgroup", "-s", action='store_true', help="Subgroup date grouping revs. Authors show below (if enabled)") | |
parser.add_argument("--inline", "-i", action='store_true', help="Items grouped by date: [rev][msg][author] for each message (if properties enabled)") | |
parser.add_argument("--prefix", default="", help="prefix all lines with char") | |
parser.add_argument("--reverse", action="store_false", help="old to new instead of new to old") | |
OPTIONS = parser.parse_args() | |
PREFIX = OPTIONS.prefix | |
command = ['svn', 'log', OPTIONS.path] | |
#check belonging to group and auto activate view: | |
if OPTIONS.subgroup or OPTIONS.inline: | |
OPTIONS.group = True | |
if OPTIONS.subgroup: | |
OPTIONS.rev = True | |
if OPTIONS.date or OPTIONS.revision: | |
if OPTIONS.date: | |
the_option = prepare_range('date', OPTIONS.date) | |
if OPTIONS.revision: | |
the_option = prepare_range('revision', OPTIONS.revision) | |
command += ['-r', the_option] | |
try: | |
output = subprocess.check_output(command) | |
# to show svn error | |
except subprocess.CalledProcessError: | |
sys.exit() | |
output = output.split("------------------------------------------------------------------------") | |
output = [s for s in output if s.strip()] # bye blank lines | |
ouputNice = list() | |
for line in output: | |
rev, author, date, time, msgs = clean_svnlog_item(line) | |
if not OPTIONS.group: | |
print (PREFIX + "{0}{1}{2}{3}:".format(date, time, rev, author)) | |
for msg in msgs: | |
print (PREFIX + " " + msg) | |
print (PREFIX) | |
else: | |
if not date in groupit: | |
groupit[date] = list() | |
groupit[date].append(logItemDetails(rev,author,msgs)) | |
# for group | |
for date, items in sorted(groupit.items(), reverse=OPTIONS.reverse): | |
if not OPTIONS.subgroup and not OPTIONS.inline: | |
revs = list() | |
authors = list() | |
msgs = list() | |
for log in items: | |
revs.append(log.rev) | |
authors.append(log.author) | |
msgs.append(log.msgs) | |
# remove duplicated authors | |
authors = list(set(authors)) | |
#remove blank items | |
revs = [s for s in revs if s.strip()] | |
revs = " (" + " ".join(revs) + ") " if revs else "" | |
authors = ", ".join(authors) if authors else "" | |
print ("{0}{1}{2}{3}:".format(PREFIX, date, revs, authors)) | |
for list_msgs in msgs: | |
for msg in list_msgs: | |
print (PREFIX + " " + msg) | |
else: | |
print (PREFIX+ date) | |
for log in items: | |
for msg in log.msgs: | |
printhis = "" | |
if OPTIONS.subgroup or (OPTIONS.inline and not OPTIONS.show_author): | |
printhis = PREFIX + " {0} {1}" | |
else: | |
printhis = PREFIX + " {0} {1} ({2})" | |
print (printhis.format(log.rev, msg, log.author)) | |
if OPTIONS.subgroup and OPTIONS.show_author: | |
print (PREFIX + " ------- " + log.author + "\n" + PREFIX) | |
else: | |
print (PREFIX + "") | |
print (PREFIX) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment