Skip to content

Instantly share code, notes, and snippets.

@andmatand
Last active September 23, 2016 18:53
Show Gist options
  • Save andmatand/7ea6766fe9784354fe9f to your computer and use it in GitHub Desktop.
Save andmatand/7ea6766fe9784354fe9f to your computer and use it in GitHub Desktop.
#!/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!')
@atmartins
Copy link

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!!!!!

@andmatand
Copy link
Author

boom i did it

@atmartins
Copy link

yes! thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment