|
1 from hgapi import hgapi, Repo |
|
2 from datetime import datetime |
|
3 import hgpoll as HgPoll |
|
4 import re |
|
5 import bt as Bt |
|
6 from configfile import Config |
|
7 from modulecore import command_error |
|
8 |
|
9 ModuleData = { |
|
10 'commands': |
|
11 [ |
|
12 { |
|
13 'name': 'checkhg', |
|
14 'description': 'Polls the zandronum repositories for updates', |
|
15 'args': None, |
|
16 'level': 'admin', |
|
17 }, |
|
18 { |
|
19 'name': 'cset', |
|
20 'description': 'Yields changeset information (use a hash or date as key)', |
|
21 'args': '<key>', |
|
22 'level': 'normal', |
|
23 }, |
|
24 { |
|
25 'name': 'hg', |
|
26 'description': 'Executes a hg command', |
|
27 'args': '<repo> <command...>', |
|
28 'level': 'admin', |
|
29 }, |
|
30 { |
|
31 'name': 'resolves', |
|
32 'description': 'Manually cause a ticket to be resolved by a changeset', |
|
33 'args': '<ticket> <changeset>', |
|
34 'level': 'admin', |
|
35 }, |
|
36 ] |
|
37 } |
|
38 |
|
39 def plural (a): |
|
40 return '' if a == 1 else 's' |
|
41 |
|
42 def cmd_checkhg (bot, **rest): |
|
43 HgPoll.force_poll() |
|
44 |
|
45 def cmd_cset (bot, args, reply, **rest): |
|
46 repo = Repo ('zandronum-everything') |
|
47 data = "" |
|
48 node = args['key'] |
|
49 |
|
50 # Possibly we're passed a date version instead. Try find the node for this. |
|
51 try: |
|
52 datetime.strptime (args['key'], '%y%m%d-%H%M') |
|
53 HgPoll.make_commits_txt() |
|
54 commits_txt = open ('commits.txt', 'r') |
|
55 |
|
56 for line in commits_txt: |
|
57 data = line.replace ('\n', '').split (' ') |
|
58 if data[1] == args['key']: |
|
59 node = data[0] |
|
60 break |
|
61 else: |
|
62 command_error ('couldn\'t find changeset for date %s' % args['key']) |
|
63 return |
|
64 except ValueError: |
|
65 pass |
|
66 |
|
67 # zandronum-everything contains all zandronum changesets, so look for changesets in that. |
|
68 try: |
|
69 data = repo.hg_command ("log", "-l1", "-r", node, "--template", |
|
70 "{node|short}@@@@@@@" + |
|
71 "{desc}@@@@@@@" + |
|
72 "{author}@@@@@@@" + |
|
73 "{diffstat}@@@@@@@" + |
|
74 "{date|hgdate}@@@@@@@" + |
|
75 "{bookmarks}@@@@@@@" + |
|
76 "{latesttagdistance}@@@@@@@" + |
|
77 "{latesttag}") |
|
78 except hgapi.HgException: |
|
79 command_error ('couldn\'t find changeset %s' % (node)) |
|
80 return |
|
81 |
|
82 try: |
|
83 data = data.split ('@@@@@@@') |
|
84 node = data[0] |
|
85 message = data[1] |
|
86 author = data[2] |
|
87 diffstat = data[3] |
|
88 date = datetime.utcfromtimestamp (int (data[4].split (' ')[0])) |
|
89 bookmarks = data[5] |
|
90 latesttagdistance = int (data[6]) |
|
91 latesttag = data[7] |
|
92 delta = datetime.utcnow() - date |
|
93 datestring = '' |
|
94 |
|
95 if bookmarks: |
|
96 bookmarks = HgPoll.prettify_bookmarks (bookmarks) |
|
97 |
|
98 # Find out the Zandronum version of this changeset |
|
99 repo.hg_command ('revert', '-r', node, 'src/version.h') |
|
100 zanversion = '<unknown zandronum version>' |
|
101 |
|
102 with open ('zandronum-everything/src/version.h') as version_file: |
|
103 regexps = [ \ |
|
104 re.compile (r'#define\s+GAMEVER_STRING\s+"([^"]+)"'), \ |
|
105 re.compile (r'#define\s+DOTVERSIONSTR_NOREV\s+"([^"]+)"'), \ |
|
106 re.compile (r'#define\s+DOTVERSIONSTR\s+"([^"]+)"')] |
|
107 |
|
108 for line in version_file: |
|
109 for rex in regexps: |
|
110 match = rex.match (line) |
|
111 if match != None: |
|
112 zanversion = match.group (1) |
|
113 break |
|
114 |
|
115 if match != None: |
|
116 break |
|
117 |
|
118 |
|
119 repo.hg_command ('revert', '--all') |
|
120 |
|
121 # Remove the email address from the author if possible |
|
122 match = re.compile (r'^(.+) <([^>]+)>$.*').match (author) |
|
123 if match: |
|
124 author = match.group (1) |
|
125 email = match.group (2) |
|
126 |
|
127 username = Config.find_developer_by_email (email) |
|
128 |
|
129 if username != '': |
|
130 author = username |
|
131 |
|
132 # Try prettify the diffstat |
|
133 rex = re.compile (r'^([0-9]+): \+([0-9]+)/-([0-9]+)$') |
|
134 match = rex.match (diffstat) |
|
135 |
|
136 if match: |
|
137 diffstat = "%s\003:\0033 +%s\003/\0034-%s\003" % (match.group (1), match.group (2), match.group (3)) |
|
138 |
|
139 if delta.days < 4: |
|
140 if delta.days == 0: |
|
141 if delta.seconds < 60: |
|
142 datestring = 'just now' |
|
143 elif delta.seconds < 3600: |
|
144 minutes = delta.seconds / 60 |
|
145 datestring = '%d minute%s ago' % (minutes, plural (minutes)) |
|
146 else: |
|
147 hours = delta.seconds / 3600 |
|
148 datestring = '%d hour%s ago' % (hours, plural (hours)) |
|
149 else: |
|
150 datestring = '%d day%s ago' % (delta.days, plural (delta.days)) |
|
151 else: |
|
152 datestring = 'on %s' % (str (date)) |
|
153 |
|
154 versionstring = "" |
|
155 if latesttagdistance != 0: |
|
156 versionstring = '%s %s, %d hops from %s' % (zanversion, date.strftime ('%y%m%d-%H%M'), latesttagdistance, latesttag) |
|
157 else: |
|
158 versionstring = latesttag |
|
159 |
|
160 reply ('changeset\0035 %s%s\003 (%s)\003: committed by\0032 %s\003 %s,\0032 %s' % \ |
|
161 (node, bookmarks, versionstring, author, datestring, diffstat)) |
|
162 |
|
163 for line in message.split ('\n'): |
|
164 reply (' ' + line) |
|
165 except hgapi.HgException as e: |
|
166 result = HgPoll.decipher_hgapi_error (e) |
|
167 |
|
168 if result[0]: |
|
169 command_error (result[1]) |
|
170 else: |
|
171 command_error (`e`) |
|
172 |
|
173 def cmd_hg (bot, args, **rest): |
|
174 try: |
|
175 repo = hgapi.Repo (args['repo']) |
|
176 result = repo.hg_command (*args['command']) |
|
177 reply (replyto, result) |
|
178 except hgapi.hgapi.HgException as e: |
|
179 result = HgPoll.decipher_hgapi_error (e) |
|
180 |
|
181 if result[0]: |
|
182 command_error (result[1]) |
|
183 else: |
|
184 command_error (`e`) |
|
185 |
|
186 def cmd_resolves (bot, args, replyto, **rest): |
|
187 try: |
|
188 HgPoll.announce_ticket_resolved (args['ticket'], args['changeset']) |
|
189 except Exception as e: |
|
190 command_error (str (e)) |