Last active
September 23, 2016 18:53
-
-
Save andmatand/7ea6766fe9784354fe9f to your computer and use it in GitHub Desktop.
This file contains hidden or 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
#!/usr/bin/env python3 | |
import re | |
import subprocess | |
import sys | |
from xml.etree import ElementTree | |
if len(sys.argv) == 2: | |
commitMessage = sys.argv[1] | |
else: | |
print('Usage: ' + sys.argv[0] + " 'Your commit message here'") | |
sys.exit(1) | |
def run_shell_cmd(args): | |
output = subprocess.check_output(args) | |
if output.strip(): | |
return output.decode('utf8') | |
else: | |
return None | |
def get_trunk_url(): | |
svnInfo = run_shell_cmd(['svn', 'info']) | |
match = re.search('^URL: (.*)$', svnInfo, flags=re.MULTILINE) | |
return match.group(1) | |
def get_tag_url_base(trunkUrl): | |
return re.sub('/trunk(/.*)?$', '/tags', trunkUrl) | |
def remove_malformed_tags(tags): | |
newTags = [] | |
for tag in tags: | |
match = re.search('v[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+', tag) | |
# If this tag is well-formed | |
if match: | |
# Remove everything from the tag except numbers and dots | |
tag = re.sub('[^0-9.]', '', tag) | |
newTags.append(tag) | |
return newTags | |
# Returns a dict where each item has the following structure: | |
# key: date of the commit | |
# value: tag number, e.g. v0.0.0.1 | |
def get_tags(tagUrlBase): | |
output = run_shell_cmd(['svn', 'ls', '--xml', tagUrlBase]) | |
xml = ElementTree.fromstring(output) | |
tags = {} | |
for entry in xml[0].findall('entry'): | |
name = entry.find('name').text | |
date = entry.find('commit').find('date').text | |
tags[date] = name | |
return tags | |
def get_latest_tag_by_date(tags): | |
# Return the tag with the most recent date | |
mostRecentDate = sorted(tags.keys())[-1] | |
return tags[mostRecentDate] | |
def get_latest_tag_by_number(tags): | |
tags = tags.values() | |
tags = remove_malformed_tags(tags) | |
if len(tags) == 0: | |
print('All tag numbers are malformed!') | |
sys.exit(1) | |
for slot in range(0, 4): | |
highestNumber = 0 | |
# Find the highest number in this slot | |
for tag in tags: | |
number = tag.split('.')[slot] | |
if number.strip() != '': | |
if int(number) > highestNumber: | |
highestNumber = int(number) | |
# Keep only the tags that have the high number in this slot | |
newTags = [] | |
for tag in tags: | |
number = tag.split('.')[slot] | |
if number.strip() != '': | |
if int(number) == highestNumber: | |
newTags.append(tag) | |
tags = newTags | |
return 'v' + tags[0] | |
def get_current_revision(): | |
output = run_shell_cmd(['svn', 'info', '-r', 'HEAD']) | |
match = re.search('^Revision: (.*)$', output, re.MULTILINE) | |
return match.group(1) | |
def get_new_tag(latestTag): | |
pieces = latestTag.split('.') | |
newPenultimate = str(int(pieces[2]) + 1) | |
rev = get_current_revision() | |
return pieces[0] + '.' + pieces[1] + '.' + newPenultimate + '.' + rev | |
def str_is_empty(s): | |
return not bool(s and s.strip()) | |
def check_sanity(trunkUrl, latestTag, newTag, tagUrl, commitMessage): | |
if str_is_empty(trunkUrl): | |
return False | |
if str_is_empty(latestTag): | |
return False | |
if str_is_empty(newTag): | |
return False | |
if str_is_empty(tagUrl): | |
return False | |
if str_is_empty(commitMessage): | |
return False | |
return True | |
trunkUrl = get_trunk_url() | |
tagUrlBase = get_tag_url_base(trunkUrl) | |
if '/branches/' in tagUrlBase: | |
print('It looks like you are in a branch. This program only works in trunk :(') | |
sys.exit(1) | |
tags = get_tags(tagUrlBase) | |
if len(tags) > 0: | |
latestTagByDate = get_latest_tag_by_date(tags) | |
latestTagByNumber = get_latest_tag_by_number(tags) | |
if latestTagByDate == latestTagByNumber: | |
latestTag = latestTagByDate | |
else: | |
print('ERROR: Unable to determine latest tag') | |
print('latest tag by number: ' + latestTagByNumber) | |
print(' latest tag by date: ' + latestTagByDate) | |
sys.exit(2) | |
else: | |
latestTag = 'v0.1.0.0' | |
newTag = get_new_tag(latestTag) | |
tagUrl = tagUrlBase + '/' + newTag | |
print(' trunk URL: ' + trunkUrl) | |
print(' latest tag: ' + latestTag) | |
print(' new tag: ' + newTag) | |
print('new tag URL: ' + tagUrl) | |
print(' message: ' + commitMessage) | |
answer = input('\nDo you want to make the new tag above? [Y/n] ') | |
if answer == 'y' or answer == 'Y' or answer.strip() == '': | |
if check_sanity(trunkUrl, latestTag, newTag, tagUrl, commitMessage): | |
subprocess.call([ | |
'svn', 'cp', trunkUrl, tagUrl, | |
'-m', commitMessage]) | |
else: | |
print('Sanity check failed!') | |
else: | |
print('Cancelled!') |
boom i did it
yes! thank you!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Andrew, this is awesome! One suggestion: when it prompts you if things look good, maybe a (Y/n) instead of press Enter or (implicitly) ctrl-c.
Thanks dude!!!!!