Show More
@@ -7,7 +7,9 b'' | |||
|
7 | 7 | """simple Phabricator integration |
|
8 | 8 | |
|
9 | 9 | This extension provides a ``phabsend`` command which sends a stack of |
|
10 |
changesets to Phabricator without amending commit messages |
|
|
10 | changesets to Phabricator without amending commit messages, and a ``phabread`` | |
|
11 | command which prints a stack of revisions in a format suitable | |
|
12 | for :hg:`import`. | |
|
11 | 13 | |
|
12 | 14 | By default, Phabricator requires ``Test Plan`` which might prevent some |
|
13 | 15 | changeset from being sent. The requirement could be disabled by changing |
@@ -25,6 +27,7 b' Config::' | |||
|
25 | 27 | # Repo callsign. If a repo has a URL https://$HOST/diffusion/FOO, then its |
|
26 | 28 | # callsign is "FOO". |
|
27 | 29 | callsign = FOO |
|
30 | ||
|
28 | 31 | """ |
|
29 | 32 | |
|
30 | 33 | from __future__ import absolute_import |
@@ -273,3 +276,65 b' def phabsend(ui, repo, *revs, **opts):' | |||
|
273 | 276 | ui.write(_('D%s: %s - %s: %s\n') % (newrevid, action, ctx, |
|
274 | 277 | ctx.description().split('\n')[0])) |
|
275 | 278 | lastrevid = newrevid |
|
279 | ||
|
280 | _summaryre = re.compile('^Summary:\s*', re.M) | |
|
281 | ||
|
282 | def readpatch(repo, params, recursive=False): | |
|
283 | """generate plain-text patch readable by 'hg import' | |
|
284 | ||
|
285 | params is passed to "differential.query". If recursive is True, also return | |
|
286 | dependent patches. | |
|
287 | """ | |
|
288 | # Differential Revisions | |
|
289 | drevs = callconduit(repo, 'differential.query', params) | |
|
290 | if len(drevs) == 1: | |
|
291 | drev = drevs[0] | |
|
292 | else: | |
|
293 | raise error.Abort(_('cannot get Differential Revision %r') % params) | |
|
294 | ||
|
295 | repo.ui.note(_('reading D%s\n') % drev[r'id']) | |
|
296 | ||
|
297 | diffid = max(int(v) for v in drev[r'diffs']) | |
|
298 | body = callconduit(repo, 'differential.getrawdiff', {'diffID': diffid}) | |
|
299 | desc = callconduit(repo, 'differential.getcommitmessage', | |
|
300 | {'revision_id': drev[r'id']}) | |
|
301 | header = '# HG changeset patch\n' | |
|
302 | ||
|
303 | # Remove potential empty "Summary:" | |
|
304 | desc = _summaryre.sub('', desc) | |
|
305 | ||
|
306 | # Try to preserve metadata (user, date) from hg:meta property | |
|
307 | diffs = callconduit(repo, 'differential.querydiffs', {'ids': [diffid]}) | |
|
308 | props = diffs[str(diffid)][r'properties'] # could be empty list or dict | |
|
309 | if props and r'hg:meta' in props: | |
|
310 | meta = props[r'hg:meta'] | |
|
311 | for k, v in meta.items(): | |
|
312 | header += '# %s %s\n' % (k.capitalize(), v) | |
|
313 | ||
|
314 | patch = ('%s%s\n%s') % (header, desc, body) | |
|
315 | ||
|
316 | # Check dependencies | |
|
317 | if recursive: | |
|
318 | auxiliary = drev.get(r'auxiliary', {}) | |
|
319 | depends = auxiliary.get(r'phabricator:depends-on', []) | |
|
320 | for phid in depends: | |
|
321 | patch = readpatch(repo, {'phids': [phid]}, recursive=True) + patch | |
|
322 | return patch | |
|
323 | ||
|
324 | @command('phabread', | |
|
325 | [('', 'stack', False, _('read dependencies'))], | |
|
326 | _('REVID [OPTIONS]')) | |
|
327 | def phabread(ui, repo, revid, **opts): | |
|
328 | """print patches from Phabricator suitable for importing | |
|
329 | ||
|
330 | REVID could be a Differential Revision identity, like ``D123``, or just the | |
|
331 | number ``123``, or a full URL like ``https://phab.example.com/D123``. | |
|
332 | ||
|
333 | If --stack is given, follow dependencies information and read all patches. | |
|
334 | """ | |
|
335 | try: | |
|
336 | revid = int(revid.split('/')[-1].replace('D', '')) | |
|
337 | except ValueError: | |
|
338 | raise error.Abort(_('invalid Revision ID: %s') % revid) | |
|
339 | patch = readpatch(repo, {'ids': [revid]}, recursive=opts.get('stack')) | |
|
340 | ui.write(patch) |
General Comments 0
You need to be logged in to leave comments.
Login now