Mercurial > hg
annotate contrib/phabricator.py @ 33443:e48082e0a8d5
phabricator: verify local tags before trusting them
Previously we trust local tags blindly and that could cause wrong
Differential Revision to be updated, when people switch between Phabricator
instances.
This patch adds verification logic to detect such issue and remove
problematic tags. For example, a tag "D19" was on node "X", the code will
fetch all diffs attached to D19, and check if nodes server-side overlaps
with nodes in precursors. If they do not overlap, create a new Differential
Revision.
Test Plan:
Use a test Phabricator instance, send patches using `hg phabsend`, then
change the local tag manually to a wrong Differential Revision number.
Amend the patch and send again. Make sure the tag gets ignored and deleted.
Differential Revision: https://phab.mercurial-scm.org/D36
author | Jun Wu <quark@fb.com> |
---|---|
date | Tue, 11 Jul 2017 08:17:29 -0700 |
parents | 3ab0d5767b54 |
children | b7a75b9a3386 |
rev | line source |
---|---|
33198 | 1 # phabricator.py - simple Phabricator integration |
2 # | |
3 # Copyright 2017 Facebook, Inc. | |
4 # | |
5 # This software may be used and distributed according to the terms of the | |
6 # GNU General Public License version 2 or any later version. | |
7 """simple Phabricator integration | |
8 | |
33199
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
9 This extension provides a ``phabsend`` command which sends a stack of |
33200
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
10 changesets to Phabricator without amending commit messages, and a ``phabread`` |
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
11 command which prints a stack of revisions in a format suitable |
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
12 for :hg:`import`. |
33199
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
13 |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
14 By default, Phabricator requires ``Test Plan`` which might prevent some |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
15 changeset from being sent. The requirement could be disabled by changing |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
16 ``differential.require-test-plan-field`` config server side. |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
17 |
33198 | 18 Config:: |
19 | |
20 [phabricator] | |
21 # Phabricator URL | |
22 url = https://phab.example.com/ | |
23 | |
24 # API token. Get it from https://$HOST/conduit/login/ | |
25 token = cli-xxxxxxxxxxxxxxxxxxxxxxxxxxxx | |
33199
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
26 |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
27 # Repo callsign. If a repo has a URL https://$HOST/diffusion/FOO, then its |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
28 # callsign is "FOO". |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
29 callsign = FOO |
33200
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
30 |
33198 | 31 """ |
32 | |
33 from __future__ import absolute_import | |
34 | |
35 import json | |
33199
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
36 import re |
33198 | 37 |
33443
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
38 from mercurial.node import bin, nullid |
33198 | 39 from mercurial.i18n import _ |
40 from mercurial import ( | |
33199
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
41 encoding, |
33198 | 42 error, |
33199
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
43 mdiff, |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
44 obsolete, |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
45 patch, |
33198 | 46 registrar, |
33199
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
47 scmutil, |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
48 tags, |
33198 | 49 url as urlmod, |
50 util, | |
51 ) | |
52 | |
53 cmdtable = {} | |
54 command = registrar.command(cmdtable) | |
55 | |
56 def urlencodenested(params): | |
57 """like urlencode, but works with nested parameters. | |
58 | |
59 For example, if params is {'a': ['b', 'c'], 'd': {'e': 'f'}}, it will be | |
60 flattened to {'a[0]': 'b', 'a[1]': 'c', 'd[e]': 'f'} and then passed to | |
61 urlencode. Note: the encoding is consistent with PHP's http_build_query. | |
62 """ | |
63 flatparams = util.sortdict() | |
64 def process(prefix, obj): | |
65 items = {list: enumerate, dict: lambda x: x.items()}.get(type(obj)) | |
66 if items is None: | |
67 flatparams[prefix] = obj | |
68 else: | |
69 for k, v in items(obj): | |
70 if prefix: | |
71 process('%s[%s]' % (prefix, k), v) | |
72 else: | |
73 process(k, v) | |
74 process('', params) | |
75 return util.urlreq.urlencode(flatparams) | |
76 | |
77 def readurltoken(repo): | |
78 """return conduit url, token and make sure they exist | |
79 | |
80 Currently read from [phabricator] config section. In the future, it might | |
81 make sense to read from .arcconfig and .arcrc as well. | |
82 """ | |
83 values = [] | |
84 section = 'phabricator' | |
85 for name in ['url', 'token']: | |
86 value = repo.ui.config(section, name) | |
87 if not value: | |
88 raise error.Abort(_('config %s.%s is required') % (section, name)) | |
89 values.append(value) | |
90 return values | |
91 | |
92 def callconduit(repo, name, params): | |
93 """call Conduit API, params is a dict. return json.loads result, or None""" | |
94 host, token = readurltoken(repo) | |
95 url, authinfo = util.url('/'.join([host, 'api', name])).authinfo() | |
96 urlopener = urlmod.opener(repo.ui, authinfo) | |
97 repo.ui.debug('Conduit Call: %s %s\n' % (url, params)) | |
98 params = params.copy() | |
99 params['api.token'] = token | |
100 request = util.urlreq.request(url, data=urlencodenested(params)) | |
101 body = urlopener.open(request).read() | |
102 repo.ui.debug('Conduit Response: %s\n' % body) | |
103 parsed = json.loads(body) | |
104 if parsed.get(r'error_code'): | |
105 msg = (_('Conduit Error (%s): %s') | |
106 % (parsed[r'error_code'], parsed[r'error_info'])) | |
107 raise error.Abort(msg) | |
108 return parsed[r'result'] | |
109 | |
110 @command('debugcallconduit', [], _('METHOD')) | |
111 def debugcallconduit(ui, repo, name): | |
112 """call Conduit API | |
113 | |
114 Call parameters are read from stdin as a JSON blob. Result will be written | |
115 to stdout as a JSON blob. | |
116 """ | |
117 params = json.loads(ui.fin.read()) | |
118 result = callconduit(repo, name, params) | |
119 s = json.dumps(result, sort_keys=True, indent=2, separators=(',', ': ')) | |
120 ui.write('%s\n' % s) | |
33199
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
121 |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
122 def getrepophid(repo): |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
123 """given callsign, return repository PHID or None""" |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
124 # developer config: phabricator.repophid |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
125 repophid = repo.ui.config('phabricator', 'repophid') |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
126 if repophid: |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
127 return repophid |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
128 callsign = repo.ui.config('phabricator', 'callsign') |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
129 if not callsign: |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
130 return None |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
131 query = callconduit(repo, 'diffusion.repository.search', |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
132 {'constraints': {'callsigns': [callsign]}}) |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
133 if len(query[r'data']) == 0: |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
134 return None |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
135 repophid = encoding.strtolocal(query[r'data'][0][r'phid']) |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
136 repo.ui.setconfig('phabricator', 'repophid', repophid) |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
137 return repophid |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
138 |
33263
ed61189763ef
phabricator: check associated Differential Revision from commit message
Jun Wu <quark@fb.com>
parents:
33200
diff
changeset
|
139 _differentialrevisiontagre = re.compile('\AD([1-9][0-9]*)\Z') |
ed61189763ef
phabricator: check associated Differential Revision from commit message
Jun Wu <quark@fb.com>
parents:
33200
diff
changeset
|
140 _differentialrevisiondescre = re.compile( |
ed61189763ef
phabricator: check associated Differential Revision from commit message
Jun Wu <quark@fb.com>
parents:
33200
diff
changeset
|
141 '^Differential Revision:.*D([1-9][0-9]*)$', re.M) |
33199
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
142 |
33442
3ab0d5767b54
phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents:
33441
diff
changeset
|
143 def getoldnodedrevmap(repo, nodelist): |
3ab0d5767b54
phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents:
33441
diff
changeset
|
144 """find previous nodes that has been sent to Phabricator |
3ab0d5767b54
phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents:
33441
diff
changeset
|
145 |
3ab0d5767b54
phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents:
33441
diff
changeset
|
146 return {node: (oldnode or None, Differential Revision ID)} |
3ab0d5767b54
phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents:
33441
diff
changeset
|
147 for node in nodelist with known previous sent versions, or associated |
3ab0d5767b54
phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents:
33441
diff
changeset
|
148 Differential Revision IDs. |
33199
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
149 |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
150 Examines all precursors and their tags. Tags with format like "D1234" are |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
151 considered a match and the node with that tag, and the number after "D" |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
152 (ex. 1234) will be returned. |
33263
ed61189763ef
phabricator: check associated Differential Revision from commit message
Jun Wu <quark@fb.com>
parents:
33200
diff
changeset
|
153 |
ed61189763ef
phabricator: check associated Differential Revision from commit message
Jun Wu <quark@fb.com>
parents:
33200
diff
changeset
|
154 If tags are not found, examine commit message. The "Differential Revision:" |
ed61189763ef
phabricator: check associated Differential Revision from commit message
Jun Wu <quark@fb.com>
parents:
33200
diff
changeset
|
155 line could associate this changeset to a Differential Revision. |
33199
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
156 """ |
33442
3ab0d5767b54
phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents:
33441
diff
changeset
|
157 url, token = readurltoken(repo) |
3ab0d5767b54
phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents:
33441
diff
changeset
|
158 unfi = repo.unfiltered() |
33199
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
159 nodemap = unfi.changelog.nodemap |
33263
ed61189763ef
phabricator: check associated Differential Revision from commit message
Jun Wu <quark@fb.com>
parents:
33200
diff
changeset
|
160 |
33442
3ab0d5767b54
phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents:
33441
diff
changeset
|
161 result = {} # {node: (oldnode or None, drev)} |
33443
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
162 toconfirm = {} # {node: (oldnode, {precnode}, drev)} |
33442
3ab0d5767b54
phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents:
33441
diff
changeset
|
163 for node in nodelist: |
3ab0d5767b54
phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents:
33441
diff
changeset
|
164 ctx = unfi[node] |
33443
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
165 # For tags like "D123", put them into "toconfirm" to verify later |
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
166 precnodes = list(obsolete.allprecursors(unfi.obsstore, [node])) |
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
167 for n in precnodes: |
33442
3ab0d5767b54
phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents:
33441
diff
changeset
|
168 if n in nodemap: |
3ab0d5767b54
phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents:
33441
diff
changeset
|
169 for tag in unfi.nodetags(n): |
3ab0d5767b54
phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents:
33441
diff
changeset
|
170 m = _differentialrevisiontagre.match(tag) |
3ab0d5767b54
phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents:
33441
diff
changeset
|
171 if m: |
33443
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
172 toconfirm[node] = (n, set(precnodes), int(m.group(1))) |
33442
3ab0d5767b54
phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents:
33441
diff
changeset
|
173 continue |
33263
ed61189763ef
phabricator: check associated Differential Revision from commit message
Jun Wu <quark@fb.com>
parents:
33200
diff
changeset
|
174 |
33442
3ab0d5767b54
phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents:
33441
diff
changeset
|
175 # Check commit message |
3ab0d5767b54
phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents:
33441
diff
changeset
|
176 m = _differentialrevisiondescre.search(ctx.description()) |
3ab0d5767b54
phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents:
33441
diff
changeset
|
177 if m: |
3ab0d5767b54
phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents:
33441
diff
changeset
|
178 result[node] = (None, int(m.group(1))) |
33263
ed61189763ef
phabricator: check associated Differential Revision from commit message
Jun Wu <quark@fb.com>
parents:
33200
diff
changeset
|
179 |
33443
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
180 # Double check if tags are genuine by collecting all old nodes from |
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
181 # Phabricator, and expect precursors overlap with it. |
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
182 if toconfirm: |
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
183 confirmed = {} # {drev: {oldnode}} |
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
184 drevs = [drev for n, precs, drev in toconfirm.values()] |
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
185 diffs = callconduit(unfi, 'differential.querydiffs', |
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
186 {'revisionIDs': drevs}) |
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
187 for diff in diffs.values(): |
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
188 drev = int(diff[r'revisionID']) |
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
189 oldnode = bin(encoding.unitolocal(getdiffmeta(diff).get(r'node'))) |
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
190 if node: |
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
191 confirmed.setdefault(drev, set()).add(oldnode) |
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
192 for newnode, (oldnode, precset, drev) in toconfirm.items(): |
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
193 if bool(precset & confirmed.get(drev, set())): |
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
194 result[newnode] = (oldnode, drev) |
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
195 else: |
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
196 tagname = 'D%d' % drev |
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
197 tags.tag(repo, tagname, nullid, message=None, user=None, |
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
198 date=None, local=True) |
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
199 unfi.ui.warn(_('D%s: local tag removed - does not match ' |
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
200 'Differential history\n') % drev) |
e48082e0a8d5
phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents:
33442
diff
changeset
|
201 |
33442
3ab0d5767b54
phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents:
33441
diff
changeset
|
202 return result |
33199
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
203 |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
204 def getdiff(ctx, diffopts): |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
205 """plain-text diff without header (user, commit message, etc)""" |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
206 output = util.stringio() |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
207 for chunk, _label in patch.diffui(ctx.repo(), ctx.p1().node(), ctx.node(), |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
208 None, opts=diffopts): |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
209 output.write(chunk) |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
210 return output.getvalue() |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
211 |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
212 def creatediff(ctx): |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
213 """create a Differential Diff""" |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
214 repo = ctx.repo() |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
215 repophid = getrepophid(repo) |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
216 # Create a "Differential Diff" via "differential.createrawdiff" API |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
217 params = {'diff': getdiff(ctx, mdiff.diffopts(git=True, context=32767))} |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
218 if repophid: |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
219 params['repositoryPHID'] = repophid |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
220 diff = callconduit(repo, 'differential.createrawdiff', params) |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
221 if not diff: |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
222 raise error.Abort(_('cannot create diff for %s') % ctx) |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
223 return diff |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
224 |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
225 def writediffproperties(ctx, diff): |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
226 """write metadata to diff so patches could be applied losslessly""" |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
227 params = { |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
228 'diff_id': diff[r'id'], |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
229 'name': 'hg:meta', |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
230 'data': json.dumps({ |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
231 'user': ctx.user(), |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
232 'date': '%d %d' % ctx.date(), |
33264
266321579c68
phabricator: add node and p1 to hg:meta property
Jun Wu <quark@fb.com>
parents:
33263
diff
changeset
|
233 'node': ctx.hex(), |
266321579c68
phabricator: add node and p1 to hg:meta property
Jun Wu <quark@fb.com>
parents:
33263
diff
changeset
|
234 'parent': ctx.p1().hex(), |
33199
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
235 }), |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
236 } |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
237 callconduit(ctx.repo(), 'differential.setdiffproperty', params) |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
238 |
33265
95f658b558a3
phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents:
33264
diff
changeset
|
239 def createdifferentialrevision(ctx, revid=None, parentrevid=None, oldnode=None): |
33199
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
240 """create or update a Differential Revision |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
241 |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
242 If revid is None, create a new Differential Revision, otherwise update |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
243 revid. If parentrevid is not None, set it as a dependency. |
33265
95f658b558a3
phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents:
33264
diff
changeset
|
244 |
95f658b558a3
phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents:
33264
diff
changeset
|
245 If oldnode is not None, check if the patch content (without commit message |
95f658b558a3
phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents:
33264
diff
changeset
|
246 and metadata) has changed before creating another diff. |
33199
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
247 """ |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
248 repo = ctx.repo() |
33265
95f658b558a3
phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents:
33264
diff
changeset
|
249 if oldnode: |
95f658b558a3
phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents:
33264
diff
changeset
|
250 diffopts = mdiff.diffopts(git=True, context=1) |
95f658b558a3
phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents:
33264
diff
changeset
|
251 oldctx = repo.unfiltered()[oldnode] |
95f658b558a3
phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents:
33264
diff
changeset
|
252 neednewdiff = (getdiff(ctx, diffopts) != getdiff(oldctx, diffopts)) |
95f658b558a3
phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents:
33264
diff
changeset
|
253 else: |
95f658b558a3
phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents:
33264
diff
changeset
|
254 neednewdiff = True |
33199
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
255 |
33265
95f658b558a3
phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents:
33264
diff
changeset
|
256 transactions = [] |
95f658b558a3
phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents:
33264
diff
changeset
|
257 if neednewdiff: |
95f658b558a3
phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents:
33264
diff
changeset
|
258 diff = creatediff(ctx) |
95f658b558a3
phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents:
33264
diff
changeset
|
259 writediffproperties(ctx, diff) |
95f658b558a3
phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents:
33264
diff
changeset
|
260 transactions.append({'type': 'update', 'value': diff[r'phid']}) |
33199
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
261 |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
262 # Use a temporary summary to set dependency. There might be better ways but |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
263 # I cannot find them for now. But do not do that if we are updating an |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
264 # existing revision (revid is not None) since that introduces visible |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
265 # churns (someone edited "Summary" twice) on the web page. |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
266 if parentrevid and revid is None: |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
267 summary = 'Depends on D%s' % parentrevid |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
268 transactions += [{'type': 'summary', 'value': summary}, |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
269 {'type': 'summary', 'value': ' '}] |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
270 |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
271 # Parse commit message and update related fields. |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
272 desc = ctx.description() |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
273 info = callconduit(repo, 'differential.parsecommitmessage', |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
274 {'corpus': desc}) |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
275 for k, v in info[r'fields'].items(): |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
276 if k in ['title', 'summary', 'testPlan']: |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
277 transactions.append({'type': k, 'value': v}) |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
278 |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
279 params = {'transactions': transactions} |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
280 if revid is not None: |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
281 # Update an existing Differential Revision |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
282 params['objectIdentifier'] = revid |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
283 |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
284 revision = callconduit(repo, 'differential.revision.edit', params) |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
285 if not revision: |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
286 raise error.Abort(_('cannot create revision for %s') % ctx) |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
287 |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
288 return revision |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
289 |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
290 @command('phabsend', |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
291 [('r', 'rev', [], _('revisions to send'), _('REV'))], |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
292 _('REV [OPTIONS]')) |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
293 def phabsend(ui, repo, *revs, **opts): |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
294 """upload changesets to Phabricator |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
295 |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
296 If there are multiple revisions specified, they will be send as a stack |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
297 with a linear dependencies relationship using the order specified by the |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
298 revset. |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
299 |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
300 For the first time uploading changesets, local tags will be created to |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
301 maintain the association. After the first time, phabsend will check |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
302 obsstore and tags information so it can figure out whether to update an |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
303 existing Differential Revision, or create a new one. |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
304 """ |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
305 revs = list(revs) + opts.get('rev', []) |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
306 revs = scmutil.revrange(repo, revs) |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
307 |
33266
5b2391b46906
phabricator: abort if phabsend gets empty revs
Jun Wu <quark@fb.com>
parents:
33265
diff
changeset
|
308 if not revs: |
5b2391b46906
phabricator: abort if phabsend gets empty revs
Jun Wu <quark@fb.com>
parents:
33265
diff
changeset
|
309 raise error.Abort(_('phabsend requires at least one changeset')) |
5b2391b46906
phabricator: abort if phabsend gets empty revs
Jun Wu <quark@fb.com>
parents:
33265
diff
changeset
|
310 |
33442
3ab0d5767b54
phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents:
33441
diff
changeset
|
311 oldnodedrev = getoldnodedrevmap(repo, [repo[r].node() for r in revs]) |
3ab0d5767b54
phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents:
33441
diff
changeset
|
312 |
33199
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
313 # Send patches one by one so we know their Differential Revision IDs and |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
314 # can provide dependency relationship |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
315 lastrevid = None |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
316 for rev in revs: |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
317 ui.debug('sending rev %d\n' % rev) |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
318 ctx = repo[rev] |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
319 |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
320 # Get Differential Revision ID |
33442
3ab0d5767b54
phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents:
33441
diff
changeset
|
321 oldnode, revid = oldnodedrev.get(ctx.node(), (None, None)) |
33199
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
322 if oldnode != ctx.node(): |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
323 # Create or update Differential Revision |
33265
95f658b558a3
phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents:
33264
diff
changeset
|
324 revision = createdifferentialrevision(ctx, revid, lastrevid, |
95f658b558a3
phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents:
33264
diff
changeset
|
325 oldnode) |
33199
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
326 newrevid = int(revision[r'object'][r'id']) |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
327 if revid: |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
328 action = _('updated') |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
329 else: |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
330 action = _('created') |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
331 |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
332 # Create a local tag to note the association |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
333 tagname = 'D%d' % newrevid |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
334 tags.tag(repo, tagname, ctx.node(), message=None, user=None, |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
335 date=None, local=True) |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
336 else: |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
337 # Nothing changed. But still set "newrevid" so the next revision |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
338 # could depend on this one. |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
339 newrevid = revid |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
340 action = _('skipped') |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
341 |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
342 ui.write(_('D%s: %s - %s: %s\n') % (newrevid, action, ctx, |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
343 ctx.description().split('\n')[0])) |
228ad1e58a85
phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents:
33198
diff
changeset
|
344 lastrevid = newrevid |
33200
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
345 |
33264
266321579c68
phabricator: add node and p1 to hg:meta property
Jun Wu <quark@fb.com>
parents:
33263
diff
changeset
|
346 # Map from "hg:meta" keys to header understood by "hg import". The order is |
266321579c68
phabricator: add node and p1 to hg:meta property
Jun Wu <quark@fb.com>
parents:
33263
diff
changeset
|
347 # consistent with "hg export" output. |
266321579c68
phabricator: add node and p1 to hg:meta property
Jun Wu <quark@fb.com>
parents:
33263
diff
changeset
|
348 _metanamemap = util.sortdict([(r'user', 'User'), (r'date', 'Date'), |
266321579c68
phabricator: add node and p1 to hg:meta property
Jun Wu <quark@fb.com>
parents:
33263
diff
changeset
|
349 (r'node', 'Node ID'), (r'parent', 'Parent ')]) |
266321579c68
phabricator: add node and p1 to hg:meta property
Jun Wu <quark@fb.com>
parents:
33263
diff
changeset
|
350 |
33267
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
351 def querydrev(repo, params, stack=False): |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
352 """return a list of "Differential Revision" dicts |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
353 |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
354 params is the input of "differential.query" API, and is expected to match |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
355 just a single Differential Revision. |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
356 |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
357 A "Differential Revision dict" looks like: |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
358 |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
359 { |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
360 "id": "2", |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
361 "phid": "PHID-DREV-672qvysjcczopag46qty", |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
362 "title": "example", |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
363 "uri": "https://phab.example.com/D2", |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
364 "dateCreated": "1499181406", |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
365 "dateModified": "1499182103", |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
366 "authorPHID": "PHID-USER-tv3ohwc4v4jeu34otlye", |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
367 "status": "0", |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
368 "statusName": "Needs Review", |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
369 "properties": [], |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
370 "branch": null, |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
371 "summary": "", |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
372 "testPlan": "", |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
373 "lineCount": "2", |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
374 "activeDiffPHID": "PHID-DIFF-xoqnjkobbm6k4dk6hi72", |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
375 "diffs": [ |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
376 "3", |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
377 "4", |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
378 ], |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
379 "commits": [], |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
380 "reviewers": [], |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
381 "ccs": [], |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
382 "hashes": [], |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
383 "auxiliary": { |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
384 "phabricator:projects": [], |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
385 "phabricator:depends-on": [ |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
386 "PHID-DREV-gbapp366kutjebt7agcd" |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
387 ] |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
388 }, |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
389 "repositoryPHID": "PHID-REPO-hub2hx62ieuqeheznasv", |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
390 "sourcePath": null |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
391 } |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
392 |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
393 If stack is True, return a list of "Differential Revision dict"s in an |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
394 order that the latter ones depend on the former ones. Otherwise, return a |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
395 list of a unique "Differential Revision dict". |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
396 """ |
33269
ead6749354e1
phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents:
33268
diff
changeset
|
397 prefetched = {} # {id or phid: drev} |
ead6749354e1
phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents:
33268
diff
changeset
|
398 def fetch(params): |
ead6749354e1
phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents:
33268
diff
changeset
|
399 """params -> single drev or None""" |
ead6749354e1
phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents:
33268
diff
changeset
|
400 key = (params.get(r'ids') or params.get(r'phids') or [None])[0] |
ead6749354e1
phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents:
33268
diff
changeset
|
401 if key in prefetched: |
ead6749354e1
phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents:
33268
diff
changeset
|
402 return prefetched[key] |
ead6749354e1
phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents:
33268
diff
changeset
|
403 # Otherwise, send the request. If we're fetching a stack, be smarter |
ead6749354e1
phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents:
33268
diff
changeset
|
404 # and fetch more ids in one batch, even if it could be unnecessary. |
ead6749354e1
phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents:
33268
diff
changeset
|
405 batchparams = params |
ead6749354e1
phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents:
33268
diff
changeset
|
406 if stack and len(params.get(r'ids', [])) == 1: |
ead6749354e1
phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents:
33268
diff
changeset
|
407 i = int(params[r'ids'][0]) |
ead6749354e1
phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents:
33268
diff
changeset
|
408 # developer config: phabricator.batchsize |
ead6749354e1
phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents:
33268
diff
changeset
|
409 batchsize = repo.ui.configint('phabricator', 'batchsize', 12) |
ead6749354e1
phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents:
33268
diff
changeset
|
410 batchparams = {'ids': range(max(1, i - batchsize), i + 1)} |
ead6749354e1
phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents:
33268
diff
changeset
|
411 drevs = callconduit(repo, 'differential.query', batchparams) |
ead6749354e1
phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents:
33268
diff
changeset
|
412 # Fill prefetched with the result |
ead6749354e1
phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents:
33268
diff
changeset
|
413 for drev in drevs: |
ead6749354e1
phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents:
33268
diff
changeset
|
414 prefetched[drev[r'phid']] = drev |
ead6749354e1
phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents:
33268
diff
changeset
|
415 prefetched[int(drev[r'id'])] = drev |
ead6749354e1
phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents:
33268
diff
changeset
|
416 if key not in prefetched: |
ead6749354e1
phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents:
33268
diff
changeset
|
417 raise error.Abort(_('cannot get Differential Revision %r') % params) |
ead6749354e1
phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents:
33268
diff
changeset
|
418 return prefetched[key] |
ead6749354e1
phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents:
33268
diff
changeset
|
419 |
33271
02299a28ba34
phabricator: do not read a same revision twice
Jun Wu <quark@fb.com>
parents:
33269
diff
changeset
|
420 visited = set() |
33267
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
421 result = [] |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
422 queue = [params] |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
423 while queue: |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
424 params = queue.pop() |
33269
ead6749354e1
phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents:
33268
diff
changeset
|
425 drev = fetch(params) |
33271
02299a28ba34
phabricator: do not read a same revision twice
Jun Wu <quark@fb.com>
parents:
33269
diff
changeset
|
426 if drev[r'id'] in visited: |
02299a28ba34
phabricator: do not read a same revision twice
Jun Wu <quark@fb.com>
parents:
33269
diff
changeset
|
427 continue |
02299a28ba34
phabricator: do not read a same revision twice
Jun Wu <quark@fb.com>
parents:
33269
diff
changeset
|
428 visited.add(drev[r'id']) |
33267
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
429 result.append(drev) |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
430 if stack: |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
431 auxiliary = drev.get(r'auxiliary', {}) |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
432 depends = auxiliary.get(r'phabricator:depends-on', []) |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
433 for phid in depends: |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
434 queue.append({'phids': [phid]}) |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
435 result.reverse() |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
436 return result |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
437 |
33268
85391b95961d
phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents:
33267
diff
changeset
|
438 def getdescfromdrev(drev): |
85391b95961d
phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents:
33267
diff
changeset
|
439 """get description (commit message) from "Differential Revision" |
85391b95961d
phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents:
33267
diff
changeset
|
440 |
85391b95961d
phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents:
33267
diff
changeset
|
441 This is similar to differential.getcommitmessage API. But we only care |
85391b95961d
phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents:
33267
diff
changeset
|
442 about limited fields: title, summary, test plan, and URL. |
85391b95961d
phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents:
33267
diff
changeset
|
443 """ |
85391b95961d
phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents:
33267
diff
changeset
|
444 title = drev[r'title'] |
85391b95961d
phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents:
33267
diff
changeset
|
445 summary = drev[r'summary'].rstrip() |
85391b95961d
phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents:
33267
diff
changeset
|
446 testplan = drev[r'testPlan'].rstrip() |
85391b95961d
phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents:
33267
diff
changeset
|
447 if testplan: |
85391b95961d
phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents:
33267
diff
changeset
|
448 testplan = 'Test Plan:\n%s' % testplan |
85391b95961d
phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents:
33267
diff
changeset
|
449 uri = 'Differential Revision: %s' % drev[r'uri'] |
85391b95961d
phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents:
33267
diff
changeset
|
450 return '\n\n'.join(filter(None, [title, summary, testplan, uri])) |
85391b95961d
phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents:
33267
diff
changeset
|
451 |
33441
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
452 def getdiffmeta(diff): |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
453 """get commit metadata (date, node, user, p1) from a diff object |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
454 |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
455 The metadata could be "hg:meta", sent by phabsend, like: |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
456 |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
457 "properties": { |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
458 "hg:meta": { |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
459 "date": "1499571514 25200", |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
460 "node": "98c08acae292b2faf60a279b4189beb6cff1414d", |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
461 "user": "Foo Bar <foo@example.com>", |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
462 "parent": "6d0abad76b30e4724a37ab8721d630394070fe16" |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
463 } |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
464 } |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
465 |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
466 Or converted from "local:commits", sent by "arc", like: |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
467 |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
468 "properties": { |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
469 "local:commits": { |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
470 "98c08acae292b2faf60a279b4189beb6cff1414d": { |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
471 "author": "Foo Bar", |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
472 "time": 1499546314, |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
473 "branch": "default", |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
474 "tag": "", |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
475 "commit": "98c08acae292b2faf60a279b4189beb6cff1414d", |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
476 "rev": "98c08acae292b2faf60a279b4189beb6cff1414d", |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
477 "local": "1000", |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
478 "parents": ["6d0abad76b30e4724a37ab8721d630394070fe16"], |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
479 "summary": "...", |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
480 "message": "...", |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
481 "authorEmail": "foo@example.com" |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
482 } |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
483 } |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
484 } |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
485 |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
486 Note: metadata extracted from "local:commits" will lose time zone |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
487 information. |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
488 """ |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
489 props = diff.get(r'properties') or {} |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
490 meta = props.get(r'hg:meta') |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
491 if not meta and props.get(r'local:commits'): |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
492 commit = sorted(props[r'local:commits'].values())[0] |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
493 meta = { |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
494 r'date': r'%d 0' % commit[r'time'], |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
495 r'node': commit[r'rev'], |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
496 r'user': r'%s <%s>' % (commit[r'author'], commit[r'authorEmail']), |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
497 } |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
498 if len(commit.get(r'parents', ())) >= 1: |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
499 meta[r'parent'] = commit[r'parents'][0] |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
500 return meta or {} |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
501 |
33267
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
502 def readpatch(repo, params, write, stack=False): |
33200
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
503 """generate plain-text patch readable by 'hg import' |
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
504 |
33267
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
505 write is usually ui.write. params is passed to "differential.query". If |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
506 stack is True, also write dependent patches. |
33200
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
507 """ |
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
508 # Differential Revisions |
33267
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
509 drevs = querydrev(repo, params, stack) |
33200
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
510 |
33267
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
511 # Prefetch hg:meta property for all diffs |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
512 diffids = sorted(set(max(int(v) for v in drev[r'diffs']) for drev in drevs)) |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
513 diffs = callconduit(repo, 'differential.querydiffs', {'ids': diffids}) |
33200
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
514 |
33267
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
515 # Generate patch for each drev |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
516 for drev in drevs: |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
517 repo.ui.note(_('reading D%s\n') % drev[r'id']) |
33200
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
518 |
33267
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
519 diffid = max(int(v) for v in drev[r'diffs']) |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
520 body = callconduit(repo, 'differential.getrawdiff', {'diffID': diffid}) |
33268
85391b95961d
phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents:
33267
diff
changeset
|
521 desc = getdescfromdrev(drev) |
33267
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
522 header = '# HG changeset patch\n' |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
523 |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
524 # Try to preserve metadata from hg:meta property. Write hg patch |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
525 # headers that can be read by the "import" command. See patchheadermap |
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
526 # and extract in mercurial/patch.py for supported headers. |
33441
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
527 meta = getdiffmeta(diffs[str(diffid)]) |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
528 for k in _metanamemap.keys(): |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
529 if k in meta: |
de7c6ec27d99
phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents:
33271
diff
changeset
|
530 header += '# %s %s\n' % (_metanamemap[k], meta[k]) |
33200
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
531 |
33267
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
532 write(('%s%s\n%s') % (header, desc, body)) |
33200
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
533 |
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
534 @command('phabread', |
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
535 [('', 'stack', False, _('read dependencies'))], |
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
536 _('REVID [OPTIONS]')) |
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
537 def phabread(ui, repo, revid, **opts): |
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
538 """print patches from Phabricator suitable for importing |
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
539 |
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
540 REVID could be a Differential Revision identity, like ``D123``, or just the |
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
541 number ``123``, or a full URL like ``https://phab.example.com/D123``. |
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
542 |
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
543 If --stack is given, follow dependencies information and read all patches. |
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
544 """ |
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
545 try: |
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
546 revid = int(revid.split('/')[-1].replace('D', '')) |
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
547 except ValueError: |
04cf9927f350
phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents:
33199
diff
changeset
|
548 raise error.Abort(_('invalid Revision ID: %s') % revid) |
33267
dba9f88659a3
phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents:
33266
diff
changeset
|
549 readpatch(repo, {'ids': [revid]}, ui.write, opts.get('stack')) |