mod_hg.py

Sat, 11 Apr 2015 21:02:54 +0300

author
Teemu Piippo <crimsondusk64@gmail.com>
date
Sat, 11 Apr 2015 21:02:54 +0300
changeset 122
f899af683bbe
parent 121
ac07779f788d
child 123
aeb0d0788869
permissions
-rw-r--r--

- fixed a derp in commitsdb

from hgapi import hgapi, Repo
from datetime import datetime
import hgpoll as HgPoll
import re
import bt as Bt
from configfile import Config
from modulecore import command_error

ModuleData = {
	'commands':
	[
		{
			'name': 'checkhg',
			'description': 'Polls the zandronum repositories for updates',
			'args': None,
			'level': 'admin',
		},

		{
			'name': 'cset',
			'description': 'Yields changeset information (use a hash or date as key)',
			'args': '<key>',
			'level': 'normal',
		},

		{
			'name': 'hg',
			'description': 'Executes a hg command',
			'args': '<repo> <command...>',
			'level': 'admin',
		},

		{
			'name': 'resolves',
			'description': 'Manually cause a ticket to be resolved by a changeset',
			'args': '<ticket> <changeset>',
			'level': 'admin', # TODO
		},
	]
}

def plural (a):
	return '' if a == 1 else 's'

def cmd_checkhg (bot, **rest):
	HgPoll.force_poll()

def is_dateversion (key):
	try:
		datetime.strptime (key, '%y%m%d-%H%M')
		return True
	except ValueError:
		return False

def resolve_node (node):
	reponame = None

	if '/' in node:
		reponame, node = node.split ('/')[0:2]
		
		if reponame not in HgPoll.all_repo_names():
			command_error ('''unknown repository %s''' % reponame)

	# Possibly we're passed a date version instead. Try find the node for this.
	if is_dateversion (node):
		node = HgPoll.g_CommitsDb.find_commit_by_dateversion (node)

		if node == None:
			command_error ('''couldn't find changeset for date %s''' % node)
			return

		node = node[0:7]

	noderepos = HgPoll.g_CommitsDb.get_commit_repos (node)

	if reponame == None:
		if not noderepos:
			command_error ('''couldn't find changeset %s''' % node)

		reponame = noderepos[0]

	return (node, reponame)

def cmd_cset (bot, args, reply, **rest):
	data = ""
	node, reponame = resolve_node (args['key'])
	repourl = HgPoll.get_repo_info (reponame).get_value ('url')
	repo = Repo (reponame)
	delim = '@@@@@@@@@@@@'

	try:
		data = repo.hg_command ("log", "-l1", "-r", node, "--template",
			delim.join (["{node|short}",
			"{desc}",
			"{author}",
			"{diffstat}",
			"{date|hgdate}",
			"{bookmarks}",
			"{latesttagdistance}",
			"{latesttag}"])).split (delim)
	except hgapi.HgException:
		command_error ('''couldn't find changeset %s in %s''' % (node, reponame))
		return

	try:
		node = data[0]
		message = data[1]
		author = data[2]
		diffstat = data[3]
		date = datetime.utcfromtimestamp (int (data[4].split (' ')[0]))
		bookmarks = data[5]
		latesttagdistance = int (data[6])
		latesttag = data[7]
		delta = datetime.utcnow() - date
		datestring = ''

		if bookmarks:
			bookmarks = HgPoll.prettify_bookmarks (bookmarks)

		# Find out the Zandronum version of this changeset
		repo.hg_command ('revert', '-r', node, 'src/version.h')
		zanversion = '<unknown version>'

		try:
			with open (reponame + '/src/version.h') as version_file:
				regexps = [ \
					re.compile (r'#define\s+GAMEVER_STRING\s+"([^"]+)"'), \
					re.compile (r'#define\s+DOTVERSIONSTR_NOREV\s+"([^"]+)"'), \
					re.compile (r'#define\s+DOTVERSIONSTR\s+"([^"]+)"')]

				for line in version_file:
					for rex in regexps:
						match = rex.match (line)
						if match != None:
							zanversion = match.group (1)
							break

					if match != None:
						break
		except IOError:
			pass


		repo.hg_command ('revert', '--all')

		# Remove the email address from the author if possible
		match = re.compile (r'^(.+) <([^>]+)>$.*').match (author)
		if match:
			author = match.group (1)
			email = match.group (2)

		username = Config.find_developer_by_email (email)

		if username != '':
			author = username

		# Try prettify the diffstat
		rex = re.compile (r'^([0-9]+): \+([0-9]+)/-([0-9]+)$')
		match = rex.match (diffstat)

		if match:
			diffstat = "%s\003:\0033 +%s\003/\0034-%s\003" % (match.group (1), match.group (2), match.group (3))

		if delta.days < 4:
			if delta.days == 0:
				if delta.seconds < 60:
					datestring = 'just now'
				elif delta.seconds < 3600:
					minutes = delta.seconds / 60
					datestring = '%d minute%s ago' % (minutes, plural (minutes))
				else:
					hours = delta.seconds / 3600
					datestring = '%d hour%s ago' % (hours, plural (hours))
			else:
				datestring = '%d day%s ago' % (delta.days, plural (delta.days))
		else:
			datestring = 'on %s' % (str (date))

		versionstring = ""
		if latesttagdistance != 0:
			versionstring = '%s %s, %d hops from %s' % (zanversion, date.strftime ('%y%m%d-%H%M'), latesttagdistance, latesttag)
		else:
			versionstring = latesttag

		reply ('changeset\0035 %s%s\003 (%s)\003: committed by\0032 %s\003 %s,\0032 %s' % \
			(node, bookmarks, versionstring, author, datestring, diffstat))

		for line in message.split ('\n'):
			reply ('    ' + line)

		reply ('url: %s/commits/%s' % (repourl, node))
	except hgapi.HgException as e:
		result = HgPoll.decipher_hgapi_error (e)

		if result[0]:
			command_error (result[1])
		else:
			command_error (`e`)

def cmd_hg (bot, args, reply, **rest):
	try:
		repo = hgapi.Repo (args['repo'])
		result = repo.hg_command (*args['command'])
		reply (result)
	except hgapi.hgapi.HgException as e:
		result = HgPoll.decipher_hgapi_error (e)

		if result[0]:
			command_error (result[1])
		else:
			command_error (`e`)

def cmd_resolves (bot, args, **rest):
	try:
		HgPoll.announce_ticket_resolved (args['ticket'], args['changeset'])
	except Exception as e:
		command_error (str (e))

mercurial