##// END OF EJS Templates
phabricator: convert conduit response JSON unicode to bytes inside callconduit...
Ian Moody -
r42448:c340a8ac default
parent child Browse files
Show More
@@ -1,1013 +1,1017 b''
1 # phabricator.py - simple Phabricator integration
1 # phabricator.py - simple Phabricator integration
2 #
2 #
3 # Copyright 2017 Facebook, Inc.
3 # Copyright 2017 Facebook, Inc.
4 #
4 #
5 # This software may be used and distributed according to the terms of the
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.
6 # GNU General Public License version 2 or any later version.
7 """simple Phabricator integration (EXPERIMENTAL)
7 """simple Phabricator integration (EXPERIMENTAL)
8
8
9 This extension provides a ``phabsend`` command which sends a stack of
9 This extension provides a ``phabsend`` command which sends a stack of
10 changesets to Phabricator, and a ``phabread`` command which prints a stack of
10 changesets to Phabricator, and a ``phabread`` command which prints a stack of
11 revisions in a format suitable for :hg:`import`, and a ``phabupdate`` command
11 revisions in a format suitable for :hg:`import`, and a ``phabupdate`` command
12 to update statuses in batch.
12 to update statuses in batch.
13
13
14 By default, Phabricator requires ``Test Plan`` which might prevent some
14 By default, Phabricator requires ``Test Plan`` which might prevent some
15 changeset from being sent. The requirement could be disabled by changing
15 changeset from being sent. The requirement could be disabled by changing
16 ``differential.require-test-plan-field`` config server side.
16 ``differential.require-test-plan-field`` config server side.
17
17
18 Config::
18 Config::
19
19
20 [phabricator]
20 [phabricator]
21 # Phabricator URL
21 # Phabricator URL
22 url = https://phab.example.com/
22 url = https://phab.example.com/
23
23
24 # Repo callsign. If a repo has a URL https://$HOST/diffusion/FOO, then its
24 # Repo callsign. If a repo has a URL https://$HOST/diffusion/FOO, then its
25 # callsign is "FOO".
25 # callsign is "FOO".
26 callsign = FOO
26 callsign = FOO
27
27
28 # curl command to use. If not set (default), use builtin HTTP library to
28 # curl command to use. If not set (default), use builtin HTTP library to
29 # communicate. If set, use the specified curl command. This could be useful
29 # communicate. If set, use the specified curl command. This could be useful
30 # if you need to specify advanced options that is not easily supported by
30 # if you need to specify advanced options that is not easily supported by
31 # the internal library.
31 # the internal library.
32 curlcmd = curl --connect-timeout 2 --retry 3 --silent
32 curlcmd = curl --connect-timeout 2 --retry 3 --silent
33
33
34 [auth]
34 [auth]
35 example.schemes = https
35 example.schemes = https
36 example.prefix = phab.example.com
36 example.prefix = phab.example.com
37
37
38 # API token. Get it from https://$HOST/conduit/login/
38 # API token. Get it from https://$HOST/conduit/login/
39 example.phabtoken = cli-xxxxxxxxxxxxxxxxxxxxxxxxxxxx
39 example.phabtoken = cli-xxxxxxxxxxxxxxxxxxxxxxxxxxxx
40 """
40 """
41
41
42 from __future__ import absolute_import
42 from __future__ import absolute_import
43
43
44 import contextlib
44 import contextlib
45 import itertools
45 import itertools
46 import json
46 import json
47 import operator
47 import operator
48 import re
48 import re
49
49
50 from mercurial.node import bin, nullid
50 from mercurial.node import bin, nullid
51 from mercurial.i18n import _
51 from mercurial.i18n import _
52 from mercurial import (
52 from mercurial import (
53 cmdutil,
53 cmdutil,
54 context,
54 context,
55 encoding,
55 encoding,
56 error,
56 error,
57 httpconnection as httpconnectionmod,
57 httpconnection as httpconnectionmod,
58 mdiff,
58 mdiff,
59 obsutil,
59 obsutil,
60 parser,
60 parser,
61 patch,
61 patch,
62 phases,
62 phases,
63 pycompat,
63 registrar,
64 registrar,
64 scmutil,
65 scmutil,
65 smartset,
66 smartset,
66 tags,
67 tags,
67 templateutil,
68 templateutil,
68 url as urlmod,
69 url as urlmod,
69 util,
70 util,
70 )
71 )
71 from mercurial.utils import (
72 from mercurial.utils import (
72 procutil,
73 procutil,
73 stringutil,
74 stringutil,
74 )
75 )
75
76
76 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
77 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
77 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
78 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
78 # be specifying the version(s) of Mercurial they are tested with, or
79 # be specifying the version(s) of Mercurial they are tested with, or
79 # leave the attribute unspecified.
80 # leave the attribute unspecified.
80 testedwith = 'ships-with-hg-core'
81 testedwith = 'ships-with-hg-core'
81
82
82 cmdtable = {}
83 cmdtable = {}
83 command = registrar.command(cmdtable)
84 command = registrar.command(cmdtable)
84
85
85 configtable = {}
86 configtable = {}
86 configitem = registrar.configitem(configtable)
87 configitem = registrar.configitem(configtable)
87
88
88 # developer config: phabricator.batchsize
89 # developer config: phabricator.batchsize
89 configitem(b'phabricator', b'batchsize',
90 configitem(b'phabricator', b'batchsize',
90 default=12,
91 default=12,
91 )
92 )
92 configitem(b'phabricator', b'callsign',
93 configitem(b'phabricator', b'callsign',
93 default=None,
94 default=None,
94 )
95 )
95 configitem(b'phabricator', b'curlcmd',
96 configitem(b'phabricator', b'curlcmd',
96 default=None,
97 default=None,
97 )
98 )
98 # developer config: phabricator.repophid
99 # developer config: phabricator.repophid
99 configitem(b'phabricator', b'repophid',
100 configitem(b'phabricator', b'repophid',
100 default=None,
101 default=None,
101 )
102 )
102 configitem(b'phabricator', b'url',
103 configitem(b'phabricator', b'url',
103 default=None,
104 default=None,
104 )
105 )
105 configitem(b'phabsend', b'confirm',
106 configitem(b'phabsend', b'confirm',
106 default=False,
107 default=False,
107 )
108 )
108
109
109 colortable = {
110 colortable = {
110 b'phabricator.action.created': b'green',
111 b'phabricator.action.created': b'green',
111 b'phabricator.action.skipped': b'magenta',
112 b'phabricator.action.skipped': b'magenta',
112 b'phabricator.action.updated': b'magenta',
113 b'phabricator.action.updated': b'magenta',
113 b'phabricator.desc': b'',
114 b'phabricator.desc': b'',
114 b'phabricator.drev': b'bold',
115 b'phabricator.drev': b'bold',
115 b'phabricator.node': b'',
116 b'phabricator.node': b'',
116 }
117 }
117
118
118 _VCR_FLAGS = [
119 _VCR_FLAGS = [
119 (b'', b'test-vcr', b'',
120 (b'', b'test-vcr', b'',
120 _(b'Path to a vcr file. If nonexistent, will record a new vcr transcript'
121 _(b'Path to a vcr file. If nonexistent, will record a new vcr transcript'
121 b', otherwise will mock all http requests using the specified vcr file.'
122 b', otherwise will mock all http requests using the specified vcr file.'
122 b' (ADVANCED)'
123 b' (ADVANCED)'
123 )),
124 )),
124 ]
125 ]
125
126
126 def vcrcommand(name, flags, spec, helpcategory=None):
127 def vcrcommand(name, flags, spec, helpcategory=None):
127 fullflags = flags + _VCR_FLAGS
128 fullflags = flags + _VCR_FLAGS
128 def decorate(fn):
129 def decorate(fn):
129 def inner(*args, **kwargs):
130 def inner(*args, **kwargs):
130 cassette = kwargs.pop(r'test_vcr', None)
131 cassette = kwargs.pop(r'test_vcr', None)
131 if cassette:
132 if cassette:
132 import hgdemandimport
133 import hgdemandimport
133 with hgdemandimport.deactivated():
134 with hgdemandimport.deactivated():
134 import vcr as vcrmod
135 import vcr as vcrmod
135 import vcr.stubs as stubs
136 import vcr.stubs as stubs
136 vcr = vcrmod.VCR(
137 vcr = vcrmod.VCR(
137 serializer=r'json',
138 serializer=r'json',
138 custom_patches=[
139 custom_patches=[
139 (urlmod, 'httpconnection', stubs.VCRHTTPConnection),
140 (urlmod, 'httpconnection', stubs.VCRHTTPConnection),
140 (urlmod, 'httpsconnection',
141 (urlmod, 'httpsconnection',
141 stubs.VCRHTTPSConnection),
142 stubs.VCRHTTPSConnection),
142 ])
143 ])
143 with vcr.use_cassette(cassette):
144 with vcr.use_cassette(cassette):
144 return fn(*args, **kwargs)
145 return fn(*args, **kwargs)
145 return fn(*args, **kwargs)
146 return fn(*args, **kwargs)
146 inner.__name__ = fn.__name__
147 inner.__name__ = fn.__name__
147 inner.__doc__ = fn.__doc__
148 inner.__doc__ = fn.__doc__
148 return command(name, fullflags, spec, helpcategory=helpcategory)(inner)
149 return command(name, fullflags, spec, helpcategory=helpcategory)(inner)
149 return decorate
150 return decorate
150
151
151 def urlencodenested(params):
152 def urlencodenested(params):
152 """like urlencode, but works with nested parameters.
153 """like urlencode, but works with nested parameters.
153
154
154 For example, if params is {'a': ['b', 'c'], 'd': {'e': 'f'}}, it will be
155 For example, if params is {'a': ['b', 'c'], 'd': {'e': 'f'}}, it will be
155 flattened to {'a[0]': 'b', 'a[1]': 'c', 'd[e]': 'f'} and then passed to
156 flattened to {'a[0]': 'b', 'a[1]': 'c', 'd[e]': 'f'} and then passed to
156 urlencode. Note: the encoding is consistent with PHP's http_build_query.
157 urlencode. Note: the encoding is consistent with PHP's http_build_query.
157 """
158 """
158 flatparams = util.sortdict()
159 flatparams = util.sortdict()
159 def process(prefix, obj):
160 def process(prefix, obj):
160 if isinstance(obj, bool):
161 if isinstance(obj, bool):
161 obj = {True: b'true', False: b'false'}[obj] # Python -> PHP form
162 obj = {True: b'true', False: b'false'}[obj] # Python -> PHP form
162 items = {list: enumerate, dict: lambda x: x.items()}.get(type(obj))
163 items = {list: enumerate, dict: lambda x: x.items()}.get(type(obj))
163 if items is None:
164 if items is None:
164 flatparams[prefix] = obj
165 flatparams[prefix] = obj
165 else:
166 else:
166 for k, v in items(obj):
167 for k, v in items(obj):
167 if prefix:
168 if prefix:
168 process(b'%s[%s]' % (prefix, k), v)
169 process(b'%s[%s]' % (prefix, k), v)
169 else:
170 else:
170 process(k, v)
171 process(k, v)
171 process(b'', params)
172 process(b'', params)
172 return util.urlreq.urlencode(flatparams)
173 return util.urlreq.urlencode(flatparams)
173
174
174 def readurltoken(repo):
175 def readurltoken(repo):
175 """return conduit url, token and make sure they exist
176 """return conduit url, token and make sure they exist
176
177
177 Currently read from [auth] config section. In the future, it might
178 Currently read from [auth] config section. In the future, it might
178 make sense to read from .arcconfig and .arcrc as well.
179 make sense to read from .arcconfig and .arcrc as well.
179 """
180 """
180 url = repo.ui.config(b'phabricator', b'url')
181 url = repo.ui.config(b'phabricator', b'url')
181 if not url:
182 if not url:
182 raise error.Abort(_(b'config %s.%s is required')
183 raise error.Abort(_(b'config %s.%s is required')
183 % (b'phabricator', b'url'))
184 % (b'phabricator', b'url'))
184
185
185 res = httpconnectionmod.readauthforuri(repo.ui, url, util.url(url).user)
186 res = httpconnectionmod.readauthforuri(repo.ui, url, util.url(url).user)
186 token = None
187 token = None
187
188
188 if res:
189 if res:
189 group, auth = res
190 group, auth = res
190
191
191 repo.ui.debug(b"using auth.%s.* for authentication\n" % group)
192 repo.ui.debug(b"using auth.%s.* for authentication\n" % group)
192
193
193 token = auth.get(b'phabtoken')
194 token = auth.get(b'phabtoken')
194
195
195 if not token:
196 if not token:
196 raise error.Abort(_(b'Can\'t find conduit token associated to %s')
197 raise error.Abort(_(b'Can\'t find conduit token associated to %s')
197 % (url,))
198 % (url,))
198
199
199 return url, token
200 return url, token
200
201
201 def callconduit(repo, name, params):
202 def callconduit(repo, name, params):
202 """call Conduit API, params is a dict. return json.loads result, or None"""
203 """call Conduit API, params is a dict. return json.loads result, or None"""
203 host, token = readurltoken(repo)
204 host, token = readurltoken(repo)
204 url, authinfo = util.url(b'/'.join([host, b'api', name])).authinfo()
205 url, authinfo = util.url(b'/'.join([host, b'api', name])).authinfo()
205 repo.ui.debug(b'Conduit Call: %s %s\n' % (url, params))
206 repo.ui.debug(b'Conduit Call: %s %s\n' % (url, params))
206 params = params.copy()
207 params = params.copy()
207 params[b'api.token'] = token
208 params[b'api.token'] = token
208 data = urlencodenested(params)
209 data = urlencodenested(params)
209 curlcmd = repo.ui.config(b'phabricator', b'curlcmd')
210 curlcmd = repo.ui.config(b'phabricator', b'curlcmd')
210 if curlcmd:
211 if curlcmd:
211 sin, sout = procutil.popen2(b'%s -d @- %s'
212 sin, sout = procutil.popen2(b'%s -d @- %s'
212 % (curlcmd, procutil.shellquote(url)))
213 % (curlcmd, procutil.shellquote(url)))
213 sin.write(data)
214 sin.write(data)
214 sin.close()
215 sin.close()
215 body = sout.read()
216 body = sout.read()
216 else:
217 else:
217 urlopener = urlmod.opener(repo.ui, authinfo)
218 urlopener = urlmod.opener(repo.ui, authinfo)
218 request = util.urlreq.request(url, data=data)
219 request = util.urlreq.request(url, data=data)
219 with contextlib.closing(urlopener.open(request)) as rsp:
220 with contextlib.closing(urlopener.open(request)) as rsp:
220 body = rsp.read()
221 body = rsp.read()
221 repo.ui.debug(b'Conduit Response: %s\n' % body)
222 repo.ui.debug(b'Conduit Response: %s\n' % body)
222 parsed = json.loads(body)
223 parsed = pycompat.rapply(
223 if parsed.get(r'error_code'):
224 lambda x: encoding.unitolocal(x) if isinstance(x, pycompat.unicode)
225 else x,
226 json.loads(body)
227 )
228 if parsed.get(b'error_code'):
224 msg = (_(b'Conduit Error (%s): %s')
229 msg = (_(b'Conduit Error (%s): %s')
225 % (parsed[r'error_code'], parsed[r'error_info']))
230 % (parsed[b'error_code'], parsed[b'error_info']))
226 raise error.Abort(msg)
231 raise error.Abort(msg)
227 return parsed[r'result']
232 return parsed[b'result']
228
233
229 @vcrcommand(b'debugcallconduit', [], _(b'METHOD'))
234 @vcrcommand(b'debugcallconduit', [], _(b'METHOD'))
230 def debugcallconduit(ui, repo, name):
235 def debugcallconduit(ui, repo, name):
231 """call Conduit API
236 """call Conduit API
232
237
233 Call parameters are read from stdin as a JSON blob. Result will be written
238 Call parameters are read from stdin as a JSON blob. Result will be written
234 to stdout as a JSON blob.
239 to stdout as a JSON blob.
235 """
240 """
236 params = json.loads(ui.fin.read())
241 params = json.loads(ui.fin.read())
237 result = callconduit(repo, name, params)
242 result = callconduit(repo, name, params)
238 s = json.dumps(result, sort_keys=True, indent=2, separators=(b',', b': '))
243 s = json.dumps(result, sort_keys=True, indent=2, separators=(b',', b': '))
239 ui.write(b'%s\n' % s)
244 ui.write(b'%s\n' % s)
240
245
241 def getrepophid(repo):
246 def getrepophid(repo):
242 """given callsign, return repository PHID or None"""
247 """given callsign, return repository PHID or None"""
243 # developer config: phabricator.repophid
248 # developer config: phabricator.repophid
244 repophid = repo.ui.config(b'phabricator', b'repophid')
249 repophid = repo.ui.config(b'phabricator', b'repophid')
245 if repophid:
250 if repophid:
246 return repophid
251 return repophid
247 callsign = repo.ui.config(b'phabricator', b'callsign')
252 callsign = repo.ui.config(b'phabricator', b'callsign')
248 if not callsign:
253 if not callsign:
249 return None
254 return None
250 query = callconduit(repo, b'diffusion.repository.search',
255 query = callconduit(repo, b'diffusion.repository.search',
251 {b'constraints': {b'callsigns': [callsign]}})
256 {b'constraints': {b'callsigns': [callsign]}})
252 if len(query[r'data']) == 0:
257 if len(query[b'data']) == 0:
253 return None
258 return None
254 repophid = encoding.strtolocal(query[r'data'][0][r'phid'])
259 repophid = query[b'data'][0][b'phid']
255 repo.ui.setconfig(b'phabricator', b'repophid', repophid)
260 repo.ui.setconfig(b'phabricator', b'repophid', repophid)
256 return repophid
261 return repophid
257
262
258 _differentialrevisiontagre = re.compile(br'\AD([1-9][0-9]*)\Z')
263 _differentialrevisiontagre = re.compile(br'\AD([1-9][0-9]*)\Z')
259 _differentialrevisiondescre = re.compile(
264 _differentialrevisiondescre = re.compile(
260 br'^Differential Revision:\s*(?P<url>(?:.*)D(?P<id>[1-9][0-9]*))$', re.M)
265 br'^Differential Revision:\s*(?P<url>(?:.*)D(?P<id>[1-9][0-9]*))$', re.M)
261
266
262 def getoldnodedrevmap(repo, nodelist):
267 def getoldnodedrevmap(repo, nodelist):
263 """find previous nodes that has been sent to Phabricator
268 """find previous nodes that has been sent to Phabricator
264
269
265 return {node: (oldnode, Differential diff, Differential Revision ID)}
270 return {node: (oldnode, Differential diff, Differential Revision ID)}
266 for node in nodelist with known previous sent versions, or associated
271 for node in nodelist with known previous sent versions, or associated
267 Differential Revision IDs. ``oldnode`` and ``Differential diff`` could
272 Differential Revision IDs. ``oldnode`` and ``Differential diff`` could
268 be ``None``.
273 be ``None``.
269
274
270 Examines commit messages like "Differential Revision:" to get the
275 Examines commit messages like "Differential Revision:" to get the
271 association information.
276 association information.
272
277
273 If such commit message line is not found, examines all precursors and their
278 If such commit message line is not found, examines all precursors and their
274 tags. Tags with format like "D1234" are considered a match and the node
279 tags. Tags with format like "D1234" are considered a match and the node
275 with that tag, and the number after "D" (ex. 1234) will be returned.
280 with that tag, and the number after "D" (ex. 1234) will be returned.
276
281
277 The ``old node``, if not None, is guaranteed to be the last diff of
282 The ``old node``, if not None, is guaranteed to be the last diff of
278 corresponding Differential Revision, and exist in the repo.
283 corresponding Differential Revision, and exist in the repo.
279 """
284 """
280 unfi = repo.unfiltered()
285 unfi = repo.unfiltered()
281 nodemap = unfi.changelog.nodemap
286 nodemap = unfi.changelog.nodemap
282
287
283 result = {} # {node: (oldnode?, lastdiff?, drev)}
288 result = {} # {node: (oldnode?, lastdiff?, drev)}
284 toconfirm = {} # {node: (force, {precnode}, drev)}
289 toconfirm = {} # {node: (force, {precnode}, drev)}
285 for node in nodelist:
290 for node in nodelist:
286 ctx = unfi[node]
291 ctx = unfi[node]
287 # For tags like "D123", put them into "toconfirm" to verify later
292 # For tags like "D123", put them into "toconfirm" to verify later
288 precnodes = list(obsutil.allpredecessors(unfi.obsstore, [node]))
293 precnodes = list(obsutil.allpredecessors(unfi.obsstore, [node]))
289 for n in precnodes:
294 for n in precnodes:
290 if n in nodemap:
295 if n in nodemap:
291 for tag in unfi.nodetags(n):
296 for tag in unfi.nodetags(n):
292 m = _differentialrevisiontagre.match(tag)
297 m = _differentialrevisiontagre.match(tag)
293 if m:
298 if m:
294 toconfirm[node] = (0, set(precnodes), int(m.group(1)))
299 toconfirm[node] = (0, set(precnodes), int(m.group(1)))
295 continue
300 continue
296
301
297 # Check commit message
302 # Check commit message
298 m = _differentialrevisiondescre.search(ctx.description())
303 m = _differentialrevisiondescre.search(ctx.description())
299 if m:
304 if m:
300 toconfirm[node] = (1, set(precnodes), int(m.group(b'id')))
305 toconfirm[node] = (1, set(precnodes), int(m.group(b'id')))
301
306
302 # Double check if tags are genuine by collecting all old nodes from
307 # Double check if tags are genuine by collecting all old nodes from
303 # Phabricator, and expect precursors overlap with it.
308 # Phabricator, and expect precursors overlap with it.
304 if toconfirm:
309 if toconfirm:
305 drevs = [drev for force, precs, drev in toconfirm.values()]
310 drevs = [drev for force, precs, drev in toconfirm.values()]
306 alldiffs = callconduit(unfi, b'differential.querydiffs',
311 alldiffs = callconduit(unfi, b'differential.querydiffs',
307 {b'revisionIDs': drevs})
312 {b'revisionIDs': drevs})
308 getnode = lambda d: bin(encoding.unitolocal(
313 getnode = lambda d: bin(
309 getdiffmeta(d).get(r'node', b''))) or None
314 getdiffmeta(d).get(b'node', b'')) or None
310 for newnode, (force, precset, drev) in toconfirm.items():
315 for newnode, (force, precset, drev) in toconfirm.items():
311 diffs = [d for d in alldiffs.values()
316 diffs = [d for d in alldiffs.values()
312 if int(d[r'revisionID']) == drev]
317 if int(d[b'revisionID']) == drev]
313
318
314 # "precursors" as known by Phabricator
319 # "precursors" as known by Phabricator
315 phprecset = set(getnode(d) for d in diffs)
320 phprecset = set(getnode(d) for d in diffs)
316
321
317 # Ignore if precursors (Phabricator and local repo) do not overlap,
322 # Ignore if precursors (Phabricator and local repo) do not overlap,
318 # and force is not set (when commit message says nothing)
323 # and force is not set (when commit message says nothing)
319 if not force and not bool(phprecset & precset):
324 if not force and not bool(phprecset & precset):
320 tagname = b'D%d' % drev
325 tagname = b'D%d' % drev
321 tags.tag(repo, tagname, nullid, message=None, user=None,
326 tags.tag(repo, tagname, nullid, message=None, user=None,
322 date=None, local=True)
327 date=None, local=True)
323 unfi.ui.warn(_(b'D%s: local tag removed - does not match '
328 unfi.ui.warn(_(b'D%s: local tag removed - does not match '
324 b'Differential history\n') % drev)
329 b'Differential history\n') % drev)
325 continue
330 continue
326
331
327 # Find the last node using Phabricator metadata, and make sure it
332 # Find the last node using Phabricator metadata, and make sure it
328 # exists in the repo
333 # exists in the repo
329 oldnode = lastdiff = None
334 oldnode = lastdiff = None
330 if diffs:
335 if diffs:
331 lastdiff = max(diffs, key=lambda d: int(d[r'id']))
336 lastdiff = max(diffs, key=lambda d: int(d[b'id']))
332 oldnode = getnode(lastdiff)
337 oldnode = getnode(lastdiff)
333 if oldnode and oldnode not in nodemap:
338 if oldnode and oldnode not in nodemap:
334 oldnode = None
339 oldnode = None
335
340
336 result[newnode] = (oldnode, lastdiff, drev)
341 result[newnode] = (oldnode, lastdiff, drev)
337
342
338 return result
343 return result
339
344
340 def getdiff(ctx, diffopts):
345 def getdiff(ctx, diffopts):
341 """plain-text diff without header (user, commit message, etc)"""
346 """plain-text diff without header (user, commit message, etc)"""
342 output = util.stringio()
347 output = util.stringio()
343 for chunk, _label in patch.diffui(ctx.repo(), ctx.p1().node(), ctx.node(),
348 for chunk, _label in patch.diffui(ctx.repo(), ctx.p1().node(), ctx.node(),
344 None, opts=diffopts):
349 None, opts=diffopts):
345 output.write(chunk)
350 output.write(chunk)
346 return output.getvalue()
351 return output.getvalue()
347
352
348 def creatediff(ctx):
353 def creatediff(ctx):
349 """create a Differential Diff"""
354 """create a Differential Diff"""
350 repo = ctx.repo()
355 repo = ctx.repo()
351 repophid = getrepophid(repo)
356 repophid = getrepophid(repo)
352 # Create a "Differential Diff" via "differential.createrawdiff" API
357 # Create a "Differential Diff" via "differential.createrawdiff" API
353 params = {b'diff': getdiff(ctx, mdiff.diffopts(git=True, context=32767))}
358 params = {b'diff': getdiff(ctx, mdiff.diffopts(git=True, context=32767))}
354 if repophid:
359 if repophid:
355 params[b'repositoryPHID'] = repophid
360 params[b'repositoryPHID'] = repophid
356 diff = callconduit(repo, b'differential.createrawdiff', params)
361 diff = callconduit(repo, b'differential.createrawdiff', params)
357 if not diff:
362 if not diff:
358 raise error.Abort(_(b'cannot create diff for %s') % ctx)
363 raise error.Abort(_(b'cannot create diff for %s') % ctx)
359 return diff
364 return diff
360
365
361 def writediffproperties(ctx, diff):
366 def writediffproperties(ctx, diff):
362 """write metadata to diff so patches could be applied losslessly"""
367 """write metadata to diff so patches could be applied losslessly"""
363 params = {
368 params = {
364 b'diff_id': diff[r'id'],
369 b'diff_id': diff[b'id'],
365 b'name': b'hg:meta',
370 b'name': b'hg:meta',
366 b'data': json.dumps({
371 b'data': json.dumps({
367 b'user': ctx.user(),
372 b'user': ctx.user(),
368 b'date': b'%d %d' % ctx.date(),
373 b'date': b'%d %d' % ctx.date(),
369 b'node': ctx.hex(),
374 b'node': ctx.hex(),
370 b'parent': ctx.p1().hex(),
375 b'parent': ctx.p1().hex(),
371 }),
376 }),
372 }
377 }
373 callconduit(ctx.repo(), b'differential.setdiffproperty', params)
378 callconduit(ctx.repo(), b'differential.setdiffproperty', params)
374
379
375 params = {
380 params = {
376 b'diff_id': diff[r'id'],
381 b'diff_id': diff[b'id'],
377 b'name': b'local:commits',
382 b'name': b'local:commits',
378 b'data': json.dumps({
383 b'data': json.dumps({
379 ctx.hex(): {
384 ctx.hex(): {
380 b'author': stringutil.person(ctx.user()),
385 b'author': stringutil.person(ctx.user()),
381 b'authorEmail': stringutil.email(ctx.user()),
386 b'authorEmail': stringutil.email(ctx.user()),
382 b'time': ctx.date()[0],
387 b'time': ctx.date()[0],
383 },
388 },
384 }),
389 }),
385 }
390 }
386 callconduit(ctx.repo(), b'differential.setdiffproperty', params)
391 callconduit(ctx.repo(), b'differential.setdiffproperty', params)
387
392
388 def createdifferentialrevision(ctx, revid=None, parentrevid=None, oldnode=None,
393 def createdifferentialrevision(ctx, revid=None, parentrevid=None, oldnode=None,
389 olddiff=None, actions=None):
394 olddiff=None, actions=None):
390 """create or update a Differential Revision
395 """create or update a Differential Revision
391
396
392 If revid is None, create a new Differential Revision, otherwise update
397 If revid is None, create a new Differential Revision, otherwise update
393 revid. If parentrevid is not None, set it as a dependency.
398 revid. If parentrevid is not None, set it as a dependency.
394
399
395 If oldnode is not None, check if the patch content (without commit message
400 If oldnode is not None, check if the patch content (without commit message
396 and metadata) has changed before creating another diff.
401 and metadata) has changed before creating another diff.
397
402
398 If actions is not None, they will be appended to the transaction.
403 If actions is not None, they will be appended to the transaction.
399 """
404 """
400 repo = ctx.repo()
405 repo = ctx.repo()
401 if oldnode:
406 if oldnode:
402 diffopts = mdiff.diffopts(git=True, context=32767)
407 diffopts = mdiff.diffopts(git=True, context=32767)
403 oldctx = repo.unfiltered()[oldnode]
408 oldctx = repo.unfiltered()[oldnode]
404 neednewdiff = (getdiff(ctx, diffopts) != getdiff(oldctx, diffopts))
409 neednewdiff = (getdiff(ctx, diffopts) != getdiff(oldctx, diffopts))
405 else:
410 else:
406 neednewdiff = True
411 neednewdiff = True
407
412
408 transactions = []
413 transactions = []
409 if neednewdiff:
414 if neednewdiff:
410 diff = creatediff(ctx)
415 diff = creatediff(ctx)
411 transactions.append({b'type': b'update', b'value': diff[r'phid']})
416 transactions.append({b'type': b'update', b'value': diff[b'phid']})
412 else:
417 else:
413 # Even if we don't need to upload a new diff because the patch content
418 # Even if we don't need to upload a new diff because the patch content
414 # does not change. We might still need to update its metadata so
419 # does not change. We might still need to update its metadata so
415 # pushers could know the correct node metadata.
420 # pushers could know the correct node metadata.
416 assert olddiff
421 assert olddiff
417 diff = olddiff
422 diff = olddiff
418 writediffproperties(ctx, diff)
423 writediffproperties(ctx, diff)
419
424
420 # Use a temporary summary to set dependency. There might be better ways but
425 # Use a temporary summary to set dependency. There might be better ways but
421 # I cannot find them for now. But do not do that if we are updating an
426 # I cannot find them for now. But do not do that if we are updating an
422 # existing revision (revid is not None) since that introduces visible
427 # existing revision (revid is not None) since that introduces visible
423 # churns (someone edited "Summary" twice) on the web page.
428 # churns (someone edited "Summary" twice) on the web page.
424 if parentrevid and revid is None:
429 if parentrevid and revid is None:
425 summary = b'Depends on D%s' % parentrevid
430 summary = b'Depends on D%s' % parentrevid
426 transactions += [{b'type': b'summary', b'value': summary},
431 transactions += [{b'type': b'summary', b'value': summary},
427 {b'type': b'summary', b'value': b' '}]
432 {b'type': b'summary', b'value': b' '}]
428
433
429 if actions:
434 if actions:
430 transactions += actions
435 transactions += actions
431
436
432 # Parse commit message and update related fields.
437 # Parse commit message and update related fields.
433 desc = ctx.description()
438 desc = ctx.description()
434 info = callconduit(repo, b'differential.parsecommitmessage',
439 info = callconduit(repo, b'differential.parsecommitmessage',
435 {b'corpus': desc})
440 {b'corpus': desc})
436 for k, v in info[r'fields'].items():
441 for k, v in info[b'fields'].items():
437 if k in [b'title', b'summary', b'testPlan']:
442 if k in [b'title', b'summary', b'testPlan']:
438 transactions.append({b'type': k, b'value': v})
443 transactions.append({b'type': k, b'value': v})
439
444
440 params = {b'transactions': transactions}
445 params = {b'transactions': transactions}
441 if revid is not None:
446 if revid is not None:
442 # Update an existing Differential Revision
447 # Update an existing Differential Revision
443 params[b'objectIdentifier'] = revid
448 params[b'objectIdentifier'] = revid
444
449
445 revision = callconduit(repo, b'differential.revision.edit', params)
450 revision = callconduit(repo, b'differential.revision.edit', params)
446 if not revision:
451 if not revision:
447 raise error.Abort(_(b'cannot create revision for %s') % ctx)
452 raise error.Abort(_(b'cannot create revision for %s') % ctx)
448
453
449 return revision, diff
454 return revision, diff
450
455
451 def userphids(repo, names):
456 def userphids(repo, names):
452 """convert user names to PHIDs"""
457 """convert user names to PHIDs"""
453 names = [name.lower() for name in names]
458 names = [name.lower() for name in names]
454 query = {b'constraints': {b'usernames': names}}
459 query = {b'constraints': {b'usernames': names}}
455 result = callconduit(repo, b'user.search', query)
460 result = callconduit(repo, b'user.search', query)
456 # username not found is not an error of the API. So check if we have missed
461 # username not found is not an error of the API. So check if we have missed
457 # some names here.
462 # some names here.
458 data = result[r'data']
463 data = result[b'data']
459 resolved = set(entry[r'fields'][r'username'].lower() for entry in data)
464 resolved = set(entry[b'fields'][b'username'].lower() for entry in data)
460 unresolved = set(names) - resolved
465 unresolved = set(names) - resolved
461 if unresolved:
466 if unresolved:
462 raise error.Abort(_(b'unknown username: %s')
467 raise error.Abort(_(b'unknown username: %s')
463 % b' '.join(sorted(unresolved)))
468 % b' '.join(sorted(unresolved)))
464 return [entry[r'phid'] for entry in data]
469 return [entry[b'phid'] for entry in data]
465
470
466 @vcrcommand(b'phabsend',
471 @vcrcommand(b'phabsend',
467 [(b'r', b'rev', [], _(b'revisions to send'), _(b'REV')),
472 [(b'r', b'rev', [], _(b'revisions to send'), _(b'REV')),
468 (b'', b'amend', True, _(b'update commit messages')),
473 (b'', b'amend', True, _(b'update commit messages')),
469 (b'', b'reviewer', [], _(b'specify reviewers')),
474 (b'', b'reviewer', [], _(b'specify reviewers')),
470 (b'', b'confirm', None, _(b'ask for confirmation before sending'))],
475 (b'', b'confirm', None, _(b'ask for confirmation before sending'))],
471 _(b'REV [OPTIONS]'),
476 _(b'REV [OPTIONS]'),
472 helpcategory=command.CATEGORY_IMPORT_EXPORT)
477 helpcategory=command.CATEGORY_IMPORT_EXPORT)
473 def phabsend(ui, repo, *revs, **opts):
478 def phabsend(ui, repo, *revs, **opts):
474 """upload changesets to Phabricator
479 """upload changesets to Phabricator
475
480
476 If there are multiple revisions specified, they will be send as a stack
481 If there are multiple revisions specified, they will be send as a stack
477 with a linear dependencies relationship using the order specified by the
482 with a linear dependencies relationship using the order specified by the
478 revset.
483 revset.
479
484
480 For the first time uploading changesets, local tags will be created to
485 For the first time uploading changesets, local tags will be created to
481 maintain the association. After the first time, phabsend will check
486 maintain the association. After the first time, phabsend will check
482 obsstore and tags information so it can figure out whether to update an
487 obsstore and tags information so it can figure out whether to update an
483 existing Differential Revision, or create a new one.
488 existing Differential Revision, or create a new one.
484
489
485 If --amend is set, update commit messages so they have the
490 If --amend is set, update commit messages so they have the
486 ``Differential Revision`` URL, remove related tags. This is similar to what
491 ``Differential Revision`` URL, remove related tags. This is similar to what
487 arcanist will do, and is more desired in author-push workflows. Otherwise,
492 arcanist will do, and is more desired in author-push workflows. Otherwise,
488 use local tags to record the ``Differential Revision`` association.
493 use local tags to record the ``Differential Revision`` association.
489
494
490 The --confirm option lets you confirm changesets before sending them. You
495 The --confirm option lets you confirm changesets before sending them. You
491 can also add following to your configuration file to make it default
496 can also add following to your configuration file to make it default
492 behaviour::
497 behaviour::
493
498
494 [phabsend]
499 [phabsend]
495 confirm = true
500 confirm = true
496
501
497 phabsend will check obsstore and the above association to decide whether to
502 phabsend will check obsstore and the above association to decide whether to
498 update an existing Differential Revision, or create a new one.
503 update an existing Differential Revision, or create a new one.
499 """
504 """
500 revs = list(revs) + opts.get(b'rev', [])
505 revs = list(revs) + opts.get(b'rev', [])
501 revs = scmutil.revrange(repo, revs)
506 revs = scmutil.revrange(repo, revs)
502
507
503 if not revs:
508 if not revs:
504 raise error.Abort(_(b'phabsend requires at least one changeset'))
509 raise error.Abort(_(b'phabsend requires at least one changeset'))
505 if opts.get(b'amend'):
510 if opts.get(b'amend'):
506 cmdutil.checkunfinished(repo)
511 cmdutil.checkunfinished(repo)
507
512
508 # {newnode: (oldnode, olddiff, olddrev}
513 # {newnode: (oldnode, olddiff, olddrev}
509 oldmap = getoldnodedrevmap(repo, [repo[r].node() for r in revs])
514 oldmap = getoldnodedrevmap(repo, [repo[r].node() for r in revs])
510
515
511 confirm = ui.configbool(b'phabsend', b'confirm')
516 confirm = ui.configbool(b'phabsend', b'confirm')
512 confirm |= bool(opts.get(b'confirm'))
517 confirm |= bool(opts.get(b'confirm'))
513 if confirm:
518 if confirm:
514 confirmed = _confirmbeforesend(repo, revs, oldmap)
519 confirmed = _confirmbeforesend(repo, revs, oldmap)
515 if not confirmed:
520 if not confirmed:
516 raise error.Abort(_(b'phabsend cancelled'))
521 raise error.Abort(_(b'phabsend cancelled'))
517
522
518 actions = []
523 actions = []
519 reviewers = opts.get(b'reviewer', [])
524 reviewers = opts.get(b'reviewer', [])
520 if reviewers:
525 if reviewers:
521 phids = userphids(repo, reviewers)
526 phids = userphids(repo, reviewers)
522 actions.append({b'type': b'reviewers.add', b'value': phids})
527 actions.append({b'type': b'reviewers.add', b'value': phids})
523
528
524 drevids = [] # [int]
529 drevids = [] # [int]
525 diffmap = {} # {newnode: diff}
530 diffmap = {} # {newnode: diff}
526
531
527 # Send patches one by one so we know their Differential Revision IDs and
532 # Send patches one by one so we know their Differential Revision IDs and
528 # can provide dependency relationship
533 # can provide dependency relationship
529 lastrevid = None
534 lastrevid = None
530 for rev in revs:
535 for rev in revs:
531 ui.debug(b'sending rev %d\n' % rev)
536 ui.debug(b'sending rev %d\n' % rev)
532 ctx = repo[rev]
537 ctx = repo[rev]
533
538
534 # Get Differential Revision ID
539 # Get Differential Revision ID
535 oldnode, olddiff, revid = oldmap.get(ctx.node(), (None, None, None))
540 oldnode, olddiff, revid = oldmap.get(ctx.node(), (None, None, None))
536 if oldnode != ctx.node() or opts.get(b'amend'):
541 if oldnode != ctx.node() or opts.get(b'amend'):
537 # Create or update Differential Revision
542 # Create or update Differential Revision
538 revision, diff = createdifferentialrevision(
543 revision, diff = createdifferentialrevision(
539 ctx, revid, lastrevid, oldnode, olddiff, actions)
544 ctx, revid, lastrevid, oldnode, olddiff, actions)
540 diffmap[ctx.node()] = diff
545 diffmap[ctx.node()] = diff
541 newrevid = int(revision[r'object'][r'id'])
546 newrevid = int(revision[b'object'][b'id'])
542 if revid:
547 if revid:
543 action = b'updated'
548 action = b'updated'
544 else:
549 else:
545 action = b'created'
550 action = b'created'
546
551
547 # Create a local tag to note the association, if commit message
552 # Create a local tag to note the association, if commit message
548 # does not have it already
553 # does not have it already
549 m = _differentialrevisiondescre.search(ctx.description())
554 m = _differentialrevisiondescre.search(ctx.description())
550 if not m or int(m.group(b'id')) != newrevid:
555 if not m or int(m.group(b'id')) != newrevid:
551 tagname = b'D%d' % newrevid
556 tagname = b'D%d' % newrevid
552 tags.tag(repo, tagname, ctx.node(), message=None, user=None,
557 tags.tag(repo, tagname, ctx.node(), message=None, user=None,
553 date=None, local=True)
558 date=None, local=True)
554 else:
559 else:
555 # Nothing changed. But still set "newrevid" so the next revision
560 # Nothing changed. But still set "newrevid" so the next revision
556 # could depend on this one.
561 # could depend on this one.
557 newrevid = revid
562 newrevid = revid
558 action = b'skipped'
563 action = b'skipped'
559
564
560 actiondesc = ui.label(
565 actiondesc = ui.label(
561 {b'created': _(b'created'),
566 {b'created': _(b'created'),
562 b'skipped': _(b'skipped'),
567 b'skipped': _(b'skipped'),
563 b'updated': _(b'updated')}[action],
568 b'updated': _(b'updated')}[action],
564 b'phabricator.action.%s' % action)
569 b'phabricator.action.%s' % action)
565 drevdesc = ui.label(b'D%s' % newrevid, b'phabricator.drev')
570 drevdesc = ui.label(b'D%s' % newrevid, b'phabricator.drev')
566 nodedesc = ui.label(bytes(ctx), b'phabricator.node')
571 nodedesc = ui.label(bytes(ctx), b'phabricator.node')
567 desc = ui.label(ctx.description().split(b'\n')[0], b'phabricator.desc')
572 desc = ui.label(ctx.description().split(b'\n')[0], b'phabricator.desc')
568 ui.write(_(b'%s - %s - %s: %s\n') % (drevdesc, actiondesc, nodedesc,
573 ui.write(_(b'%s - %s - %s: %s\n') % (drevdesc, actiondesc, nodedesc,
569 desc))
574 desc))
570 drevids.append(newrevid)
575 drevids.append(newrevid)
571 lastrevid = newrevid
576 lastrevid = newrevid
572
577
573 # Update commit messages and remove tags
578 # Update commit messages and remove tags
574 if opts.get(b'amend'):
579 if opts.get(b'amend'):
575 unfi = repo.unfiltered()
580 unfi = repo.unfiltered()
576 drevs = callconduit(repo, b'differential.query', {b'ids': drevids})
581 drevs = callconduit(repo, b'differential.query', {b'ids': drevids})
577 with repo.wlock(), repo.lock(), repo.transaction(b'phabsend'):
582 with repo.wlock(), repo.lock(), repo.transaction(b'phabsend'):
578 wnode = unfi[b'.'].node()
583 wnode = unfi[b'.'].node()
579 mapping = {} # {oldnode: [newnode]}
584 mapping = {} # {oldnode: [newnode]}
580 for i, rev in enumerate(revs):
585 for i, rev in enumerate(revs):
581 old = unfi[rev]
586 old = unfi[rev]
582 drevid = drevids[i]
587 drevid = drevids[i]
583 drev = [d for d in drevs if int(d[r'id']) == drevid][0]
588 drev = [d for d in drevs if int(d[b'id']) == drevid][0]
584 newdesc = getdescfromdrev(drev)
589 newdesc = getdescfromdrev(drev)
585 newdesc = encoding.unitolocal(newdesc)
586 # Make sure commit message contain "Differential Revision"
590 # Make sure commit message contain "Differential Revision"
587 if old.description() != newdesc:
591 if old.description() != newdesc:
588 if old.phase() == phases.public:
592 if old.phase() == phases.public:
589 ui.warn(_("warning: not updating public commit %s\n")
593 ui.warn(_("warning: not updating public commit %s\n")
590 % scmutil.formatchangeid(old))
594 % scmutil.formatchangeid(old))
591 continue
595 continue
592 parents = [
596 parents = [
593 mapping.get(old.p1().node(), (old.p1(),))[0],
597 mapping.get(old.p1().node(), (old.p1(),))[0],
594 mapping.get(old.p2().node(), (old.p2(),))[0],
598 mapping.get(old.p2().node(), (old.p2(),))[0],
595 ]
599 ]
596 new = context.metadataonlyctx(
600 new = context.metadataonlyctx(
597 repo, old, parents=parents, text=newdesc,
601 repo, old, parents=parents, text=newdesc,
598 user=old.user(), date=old.date(), extra=old.extra())
602 user=old.user(), date=old.date(), extra=old.extra())
599
603
600 newnode = new.commit()
604 newnode = new.commit()
601
605
602 mapping[old.node()] = [newnode]
606 mapping[old.node()] = [newnode]
603 # Update diff property
607 # Update diff property
604 writediffproperties(unfi[newnode], diffmap[old.node()])
608 writediffproperties(unfi[newnode], diffmap[old.node()])
605 # Remove local tags since it's no longer necessary
609 # Remove local tags since it's no longer necessary
606 tagname = b'D%d' % drevid
610 tagname = b'D%d' % drevid
607 if tagname in repo.tags():
611 if tagname in repo.tags():
608 tags.tag(repo, tagname, nullid, message=None, user=None,
612 tags.tag(repo, tagname, nullid, message=None, user=None,
609 date=None, local=True)
613 date=None, local=True)
610 scmutil.cleanupnodes(repo, mapping, b'phabsend', fixphase=True)
614 scmutil.cleanupnodes(repo, mapping, b'phabsend', fixphase=True)
611 if wnode in mapping:
615 if wnode in mapping:
612 unfi.setparents(mapping[wnode][0])
616 unfi.setparents(mapping[wnode][0])
613
617
614 # Map from "hg:meta" keys to header understood by "hg import". The order is
618 # Map from "hg:meta" keys to header understood by "hg import". The order is
615 # consistent with "hg export" output.
619 # consistent with "hg export" output.
616 _metanamemap = util.sortdict([(r'user', b'User'), (r'date', b'Date'),
620 _metanamemap = util.sortdict([(b'user', b'User'), (b'date', b'Date'),
617 (r'node', b'Node ID'), (r'parent', b'Parent ')])
621 (b'node', b'Node ID'), (b'parent', b'Parent ')])
618
622
619 def _confirmbeforesend(repo, revs, oldmap):
623 def _confirmbeforesend(repo, revs, oldmap):
620 url, token = readurltoken(repo)
624 url, token = readurltoken(repo)
621 ui = repo.ui
625 ui = repo.ui
622 for rev in revs:
626 for rev in revs:
623 ctx = repo[rev]
627 ctx = repo[rev]
624 desc = ctx.description().splitlines()[0]
628 desc = ctx.description().splitlines()[0]
625 oldnode, olddiff, drevid = oldmap.get(ctx.node(), (None, None, None))
629 oldnode, olddiff, drevid = oldmap.get(ctx.node(), (None, None, None))
626 if drevid:
630 if drevid:
627 drevdesc = ui.label(b'D%s' % drevid, b'phabricator.drev')
631 drevdesc = ui.label(b'D%s' % drevid, b'phabricator.drev')
628 else:
632 else:
629 drevdesc = ui.label(_(b'NEW'), b'phabricator.drev')
633 drevdesc = ui.label(_(b'NEW'), b'phabricator.drev')
630
634
631 ui.write(_(b'%s - %s: %s\n')
635 ui.write(_(b'%s - %s: %s\n')
632 % (drevdesc,
636 % (drevdesc,
633 ui.label(bytes(ctx), b'phabricator.node'),
637 ui.label(bytes(ctx), b'phabricator.node'),
634 ui.label(desc, b'phabricator.desc')))
638 ui.label(desc, b'phabricator.desc')))
635
639
636 if ui.promptchoice(_(b'Send the above changes to %s (yn)?'
640 if ui.promptchoice(_(b'Send the above changes to %s (yn)?'
637 b'$$ &Yes $$ &No') % url):
641 b'$$ &Yes $$ &No') % url):
638 return False
642 return False
639
643
640 return True
644 return True
641
645
642 _knownstatusnames = {b'accepted', b'needsreview', b'needsrevision', b'closed',
646 _knownstatusnames = {b'accepted', b'needsreview', b'needsrevision', b'closed',
643 b'abandoned'}
647 b'abandoned'}
644
648
645 def _getstatusname(drev):
649 def _getstatusname(drev):
646 """get normalized status name from a Differential Revision"""
650 """get normalized status name from a Differential Revision"""
647 return drev[r'statusName'].replace(b' ', b'').lower()
651 return drev[b'statusName'].replace(b' ', b'').lower()
648
652
649 # Small language to specify differential revisions. Support symbols: (), :X,
653 # Small language to specify differential revisions. Support symbols: (), :X,
650 # +, and -.
654 # +, and -.
651
655
652 _elements = {
656 _elements = {
653 # token-type: binding-strength, primary, prefix, infix, suffix
657 # token-type: binding-strength, primary, prefix, infix, suffix
654 b'(': (12, None, (b'group', 1, b')'), None, None),
658 b'(': (12, None, (b'group', 1, b')'), None, None),
655 b':': (8, None, (b'ancestors', 8), None, None),
659 b':': (8, None, (b'ancestors', 8), None, None),
656 b'&': (5, None, None, (b'and_', 5), None),
660 b'&': (5, None, None, (b'and_', 5), None),
657 b'+': (4, None, None, (b'add', 4), None),
661 b'+': (4, None, None, (b'add', 4), None),
658 b'-': (4, None, None, (b'sub', 4), None),
662 b'-': (4, None, None, (b'sub', 4), None),
659 b')': (0, None, None, None, None),
663 b')': (0, None, None, None, None),
660 b'symbol': (0, b'symbol', None, None, None),
664 b'symbol': (0, b'symbol', None, None, None),
661 b'end': (0, None, None, None, None),
665 b'end': (0, None, None, None, None),
662 }
666 }
663
667
664 def _tokenize(text):
668 def _tokenize(text):
665 view = memoryview(text) # zero-copy slice
669 view = memoryview(text) # zero-copy slice
666 special = b'():+-& '
670 special = b'():+-& '
667 pos = 0
671 pos = 0
668 length = len(text)
672 length = len(text)
669 while pos < length:
673 while pos < length:
670 symbol = b''.join(itertools.takewhile(lambda ch: ch not in special,
674 symbol = b''.join(itertools.takewhile(lambda ch: ch not in special,
671 view[pos:]))
675 view[pos:]))
672 if symbol:
676 if symbol:
673 yield (b'symbol', symbol, pos)
677 yield (b'symbol', symbol, pos)
674 pos += len(symbol)
678 pos += len(symbol)
675 else: # special char, ignore space
679 else: # special char, ignore space
676 if text[pos] != b' ':
680 if text[pos] != b' ':
677 yield (text[pos], None, pos)
681 yield (text[pos], None, pos)
678 pos += 1
682 pos += 1
679 yield (b'end', None, pos)
683 yield (b'end', None, pos)
680
684
681 def _parse(text):
685 def _parse(text):
682 tree, pos = parser.parser(_elements).parse(_tokenize(text))
686 tree, pos = parser.parser(_elements).parse(_tokenize(text))
683 if pos != len(text):
687 if pos != len(text):
684 raise error.ParseError(b'invalid token', pos)
688 raise error.ParseError(b'invalid token', pos)
685 return tree
689 return tree
686
690
687 def _parsedrev(symbol):
691 def _parsedrev(symbol):
688 """str -> int or None, ex. 'D45' -> 45; '12' -> 12; 'x' -> None"""
692 """str -> int or None, ex. 'D45' -> 45; '12' -> 12; 'x' -> None"""
689 if symbol.startswith(b'D') and symbol[1:].isdigit():
693 if symbol.startswith(b'D') and symbol[1:].isdigit():
690 return int(symbol[1:])
694 return int(symbol[1:])
691 if symbol.isdigit():
695 if symbol.isdigit():
692 return int(symbol)
696 return int(symbol)
693
697
694 def _prefetchdrevs(tree):
698 def _prefetchdrevs(tree):
695 """return ({single-drev-id}, {ancestor-drev-id}) to prefetch"""
699 """return ({single-drev-id}, {ancestor-drev-id}) to prefetch"""
696 drevs = set()
700 drevs = set()
697 ancestordrevs = set()
701 ancestordrevs = set()
698 op = tree[0]
702 op = tree[0]
699 if op == b'symbol':
703 if op == b'symbol':
700 r = _parsedrev(tree[1])
704 r = _parsedrev(tree[1])
701 if r:
705 if r:
702 drevs.add(r)
706 drevs.add(r)
703 elif op == b'ancestors':
707 elif op == b'ancestors':
704 r, a = _prefetchdrevs(tree[1])
708 r, a = _prefetchdrevs(tree[1])
705 drevs.update(r)
709 drevs.update(r)
706 ancestordrevs.update(r)
710 ancestordrevs.update(r)
707 ancestordrevs.update(a)
711 ancestordrevs.update(a)
708 else:
712 else:
709 for t in tree[1:]:
713 for t in tree[1:]:
710 r, a = _prefetchdrevs(t)
714 r, a = _prefetchdrevs(t)
711 drevs.update(r)
715 drevs.update(r)
712 ancestordrevs.update(a)
716 ancestordrevs.update(a)
713 return drevs, ancestordrevs
717 return drevs, ancestordrevs
714
718
715 def querydrev(repo, spec):
719 def querydrev(repo, spec):
716 """return a list of "Differential Revision" dicts
720 """return a list of "Differential Revision" dicts
717
721
718 spec is a string using a simple query language, see docstring in phabread
722 spec is a string using a simple query language, see docstring in phabread
719 for details.
723 for details.
720
724
721 A "Differential Revision dict" looks like:
725 A "Differential Revision dict" looks like:
722
726
723 {
727 {
724 "id": "2",
728 "id": "2",
725 "phid": "PHID-DREV-672qvysjcczopag46qty",
729 "phid": "PHID-DREV-672qvysjcczopag46qty",
726 "title": "example",
730 "title": "example",
727 "uri": "https://phab.example.com/D2",
731 "uri": "https://phab.example.com/D2",
728 "dateCreated": "1499181406",
732 "dateCreated": "1499181406",
729 "dateModified": "1499182103",
733 "dateModified": "1499182103",
730 "authorPHID": "PHID-USER-tv3ohwc4v4jeu34otlye",
734 "authorPHID": "PHID-USER-tv3ohwc4v4jeu34otlye",
731 "status": "0",
735 "status": "0",
732 "statusName": "Needs Review",
736 "statusName": "Needs Review",
733 "properties": [],
737 "properties": [],
734 "branch": null,
738 "branch": null,
735 "summary": "",
739 "summary": "",
736 "testPlan": "",
740 "testPlan": "",
737 "lineCount": "2",
741 "lineCount": "2",
738 "activeDiffPHID": "PHID-DIFF-xoqnjkobbm6k4dk6hi72",
742 "activeDiffPHID": "PHID-DIFF-xoqnjkobbm6k4dk6hi72",
739 "diffs": [
743 "diffs": [
740 "3",
744 "3",
741 "4",
745 "4",
742 ],
746 ],
743 "commits": [],
747 "commits": [],
744 "reviewers": [],
748 "reviewers": [],
745 "ccs": [],
749 "ccs": [],
746 "hashes": [],
750 "hashes": [],
747 "auxiliary": {
751 "auxiliary": {
748 "phabricator:projects": [],
752 "phabricator:projects": [],
749 "phabricator:depends-on": [
753 "phabricator:depends-on": [
750 "PHID-DREV-gbapp366kutjebt7agcd"
754 "PHID-DREV-gbapp366kutjebt7agcd"
751 ]
755 ]
752 },
756 },
753 "repositoryPHID": "PHID-REPO-hub2hx62ieuqeheznasv",
757 "repositoryPHID": "PHID-REPO-hub2hx62ieuqeheznasv",
754 "sourcePath": null
758 "sourcePath": null
755 }
759 }
756 """
760 """
757 def fetch(params):
761 def fetch(params):
758 """params -> single drev or None"""
762 """params -> single drev or None"""
759 key = (params.get(r'ids') or params.get(r'phids') or [None])[0]
763 key = (params.get(r'ids') or params.get(r'phids') or [None])[0]
760 if key in prefetched:
764 if key in prefetched:
761 return prefetched[key]
765 return prefetched[key]
762 drevs = callconduit(repo, b'differential.query', params)
766 drevs = callconduit(repo, b'differential.query', params)
763 # Fill prefetched with the result
767 # Fill prefetched with the result
764 for drev in drevs:
768 for drev in drevs:
765 prefetched[drev[r'phid']] = drev
769 prefetched[drev[b'phid']] = drev
766 prefetched[int(drev[r'id'])] = drev
770 prefetched[int(drev[b'id'])] = drev
767 if key not in prefetched:
771 if key not in prefetched:
768 raise error.Abort(_(b'cannot get Differential Revision %r')
772 raise error.Abort(_(b'cannot get Differential Revision %r')
769 % params)
773 % params)
770 return prefetched[key]
774 return prefetched[key]
771
775
772 def getstack(topdrevids):
776 def getstack(topdrevids):
773 """given a top, get a stack from the bottom, [id] -> [id]"""
777 """given a top, get a stack from the bottom, [id] -> [id]"""
774 visited = set()
778 visited = set()
775 result = []
779 result = []
776 queue = [{r'ids': [i]} for i in topdrevids]
780 queue = [{r'ids': [i]} for i in topdrevids]
777 while queue:
781 while queue:
778 params = queue.pop()
782 params = queue.pop()
779 drev = fetch(params)
783 drev = fetch(params)
780 if drev[r'id'] in visited:
784 if drev[b'id'] in visited:
781 continue
785 continue
782 visited.add(drev[r'id'])
786 visited.add(drev[b'id'])
783 result.append(int(drev[r'id']))
787 result.append(int(drev[b'id']))
784 auxiliary = drev.get(r'auxiliary', {})
788 auxiliary = drev.get(b'auxiliary', {})
785 depends = auxiliary.get(r'phabricator:depends-on', [])
789 depends = auxiliary.get(b'phabricator:depends-on', [])
786 for phid in depends:
790 for phid in depends:
787 queue.append({b'phids': [phid]})
791 queue.append({b'phids': [phid]})
788 result.reverse()
792 result.reverse()
789 return smartset.baseset(result)
793 return smartset.baseset(result)
790
794
791 # Initialize prefetch cache
795 # Initialize prefetch cache
792 prefetched = {} # {id or phid: drev}
796 prefetched = {} # {id or phid: drev}
793
797
794 tree = _parse(spec)
798 tree = _parse(spec)
795 drevs, ancestordrevs = _prefetchdrevs(tree)
799 drevs, ancestordrevs = _prefetchdrevs(tree)
796
800
797 # developer config: phabricator.batchsize
801 # developer config: phabricator.batchsize
798 batchsize = repo.ui.configint(b'phabricator', b'batchsize')
802 batchsize = repo.ui.configint(b'phabricator', b'batchsize')
799
803
800 # Prefetch Differential Revisions in batch
804 # Prefetch Differential Revisions in batch
801 tofetch = set(drevs)
805 tofetch = set(drevs)
802 for r in ancestordrevs:
806 for r in ancestordrevs:
803 tofetch.update(range(max(1, r - batchsize), r + 1))
807 tofetch.update(range(max(1, r - batchsize), r + 1))
804 if drevs:
808 if drevs:
805 fetch({r'ids': list(tofetch)})
809 fetch({b'ids': list(tofetch)})
806 validids = sorted(set(getstack(list(ancestordrevs))) | set(drevs))
810 validids = sorted(set(getstack(list(ancestordrevs))) | set(drevs))
807
811
808 # Walk through the tree, return smartsets
812 # Walk through the tree, return smartsets
809 def walk(tree):
813 def walk(tree):
810 op = tree[0]
814 op = tree[0]
811 if op == b'symbol':
815 if op == b'symbol':
812 drev = _parsedrev(tree[1])
816 drev = _parsedrev(tree[1])
813 if drev:
817 if drev:
814 return smartset.baseset([drev])
818 return smartset.baseset([drev])
815 elif tree[1] in _knownstatusnames:
819 elif tree[1] in _knownstatusnames:
816 drevs = [r for r in validids
820 drevs = [r for r in validids
817 if _getstatusname(prefetched[r]) == tree[1]]
821 if _getstatusname(prefetched[r]) == tree[1]]
818 return smartset.baseset(drevs)
822 return smartset.baseset(drevs)
819 else:
823 else:
820 raise error.Abort(_(b'unknown symbol: %s') % tree[1])
824 raise error.Abort(_(b'unknown symbol: %s') % tree[1])
821 elif op in {b'and_', b'add', b'sub'}:
825 elif op in {b'and_', b'add', b'sub'}:
822 assert len(tree) == 3
826 assert len(tree) == 3
823 return getattr(operator, op)(walk(tree[1]), walk(tree[2]))
827 return getattr(operator, op)(walk(tree[1]), walk(tree[2]))
824 elif op == b'group':
828 elif op == b'group':
825 return walk(tree[1])
829 return walk(tree[1])
826 elif op == b'ancestors':
830 elif op == b'ancestors':
827 return getstack(walk(tree[1]))
831 return getstack(walk(tree[1]))
828 else:
832 else:
829 raise error.ProgrammingError(b'illegal tree: %r' % tree)
833 raise error.ProgrammingError(b'illegal tree: %r' % tree)
830
834
831 return [prefetched[r] for r in walk(tree)]
835 return [prefetched[r] for r in walk(tree)]
832
836
833 def getdescfromdrev(drev):
837 def getdescfromdrev(drev):
834 """get description (commit message) from "Differential Revision"
838 """get description (commit message) from "Differential Revision"
835
839
836 This is similar to differential.getcommitmessage API. But we only care
840 This is similar to differential.getcommitmessage API. But we only care
837 about limited fields: title, summary, test plan, and URL.
841 about limited fields: title, summary, test plan, and URL.
838 """
842 """
839 title = drev[r'title']
843 title = drev[b'title']
840 summary = drev[r'summary'].rstrip()
844 summary = drev[b'summary'].rstrip()
841 testplan = drev[r'testPlan'].rstrip()
845 testplan = drev[b'testPlan'].rstrip()
842 if testplan:
846 if testplan:
843 testplan = b'Test Plan:\n%s' % testplan
847 testplan = b'Test Plan:\n%s' % testplan
844 uri = b'Differential Revision: %s' % drev[r'uri']
848 uri = b'Differential Revision: %s' % drev[b'uri']
845 return b'\n\n'.join(filter(None, [title, summary, testplan, uri]))
849 return b'\n\n'.join(filter(None, [title, summary, testplan, uri]))
846
850
847 def getdiffmeta(diff):
851 def getdiffmeta(diff):
848 """get commit metadata (date, node, user, p1) from a diff object
852 """get commit metadata (date, node, user, p1) from a diff object
849
853
850 The metadata could be "hg:meta", sent by phabsend, like:
854 The metadata could be "hg:meta", sent by phabsend, like:
851
855
852 "properties": {
856 "properties": {
853 "hg:meta": {
857 "hg:meta": {
854 "date": "1499571514 25200",
858 "date": "1499571514 25200",
855 "node": "98c08acae292b2faf60a279b4189beb6cff1414d",
859 "node": "98c08acae292b2faf60a279b4189beb6cff1414d",
856 "user": "Foo Bar <foo@example.com>",
860 "user": "Foo Bar <foo@example.com>",
857 "parent": "6d0abad76b30e4724a37ab8721d630394070fe16"
861 "parent": "6d0abad76b30e4724a37ab8721d630394070fe16"
858 }
862 }
859 }
863 }
860
864
861 Or converted from "local:commits", sent by "arc", like:
865 Or converted from "local:commits", sent by "arc", like:
862
866
863 "properties": {
867 "properties": {
864 "local:commits": {
868 "local:commits": {
865 "98c08acae292b2faf60a279b4189beb6cff1414d": {
869 "98c08acae292b2faf60a279b4189beb6cff1414d": {
866 "author": "Foo Bar",
870 "author": "Foo Bar",
867 "time": 1499546314,
871 "time": 1499546314,
868 "branch": "default",
872 "branch": "default",
869 "tag": "",
873 "tag": "",
870 "commit": "98c08acae292b2faf60a279b4189beb6cff1414d",
874 "commit": "98c08acae292b2faf60a279b4189beb6cff1414d",
871 "rev": "98c08acae292b2faf60a279b4189beb6cff1414d",
875 "rev": "98c08acae292b2faf60a279b4189beb6cff1414d",
872 "local": "1000",
876 "local": "1000",
873 "parents": ["6d0abad76b30e4724a37ab8721d630394070fe16"],
877 "parents": ["6d0abad76b30e4724a37ab8721d630394070fe16"],
874 "summary": "...",
878 "summary": "...",
875 "message": "...",
879 "message": "...",
876 "authorEmail": "foo@example.com"
880 "authorEmail": "foo@example.com"
877 }
881 }
878 }
882 }
879 }
883 }
880
884
881 Note: metadata extracted from "local:commits" will lose time zone
885 Note: metadata extracted from "local:commits" will lose time zone
882 information.
886 information.
883 """
887 """
884 props = diff.get(r'properties') or {}
888 props = diff.get(b'properties') or {}
885 meta = props.get(r'hg:meta')
889 meta = props.get(b'hg:meta')
886 if not meta and props.get(r'local:commits'):
890 if not meta and props.get(b'local:commits'):
887 commit = sorted(props[r'local:commits'].values())[0]
891 commit = sorted(props[b'local:commits'].values())[0]
888 meta = {
892 meta = {
889 r'date': r'%d 0' % commit[r'time'],
893 b'date': b'%d 0' % commit[b'time'],
890 r'node': commit[r'rev'],
894 b'node': commit[b'rev'],
891 r'user': r'%s <%s>' % (commit[r'author'], commit[r'authorEmail']),
895 b'user': b'%s <%s>' % (commit[b'author'], commit[b'authorEmail']),
892 }
896 }
893 if len(commit.get(r'parents', ())) >= 1:
897 if len(commit.get(b'parents', ())) >= 1:
894 meta[r'parent'] = commit[r'parents'][0]
898 meta[b'parent'] = commit[b'parents'][0]
895 return meta or {}
899 return meta or {}
896
900
897 def readpatch(repo, drevs, write):
901 def readpatch(repo, drevs, write):
898 """generate plain-text patch readable by 'hg import'
902 """generate plain-text patch readable by 'hg import'
899
903
900 write is usually ui.write. drevs is what "querydrev" returns, results of
904 write is usually ui.write. drevs is what "querydrev" returns, results of
901 "differential.query".
905 "differential.query".
902 """
906 """
903 # Prefetch hg:meta property for all diffs
907 # Prefetch hg:meta property for all diffs
904 diffids = sorted(set(max(int(v) for v in drev[r'diffs']) for drev in drevs))
908 diffids = sorted(set(max(int(v) for v in drev[b'diffs']) for drev in drevs))
905 diffs = callconduit(repo, b'differential.querydiffs', {b'ids': diffids})
909 diffs = callconduit(repo, b'differential.querydiffs', {b'ids': diffids})
906
910
907 # Generate patch for each drev
911 # Generate patch for each drev
908 for drev in drevs:
912 for drev in drevs:
909 repo.ui.note(_(b'reading D%s\n') % drev[r'id'])
913 repo.ui.note(_(b'reading D%s\n') % drev[b'id'])
910
914
911 diffid = max(int(v) for v in drev[r'diffs'])
915 diffid = max(int(v) for v in drev[b'diffs'])
912 body = callconduit(repo, b'differential.getrawdiff',
916 body = callconduit(repo, b'differential.getrawdiff',
913 {b'diffID': diffid})
917 {b'diffID': diffid})
914 desc = getdescfromdrev(drev)
918 desc = getdescfromdrev(drev)
915 header = b'# HG changeset patch\n'
919 header = b'# HG changeset patch\n'
916
920
917 # Try to preserve metadata from hg:meta property. Write hg patch
921 # Try to preserve metadata from hg:meta property. Write hg patch
918 # headers that can be read by the "import" command. See patchheadermap
922 # headers that can be read by the "import" command. See patchheadermap
919 # and extract in mercurial/patch.py for supported headers.
923 # and extract in mercurial/patch.py for supported headers.
920 meta = getdiffmeta(diffs[str(diffid)])
924 meta = getdiffmeta(diffs[str(diffid)])
921 for k in _metanamemap.keys():
925 for k in _metanamemap.keys():
922 if k in meta:
926 if k in meta:
923 header += b'# %s %s\n' % (_metanamemap[k], meta[k])
927 header += b'# %s %s\n' % (_metanamemap[k], meta[k])
924
928
925 content = b'%s%s\n%s' % (header, desc, body)
929 content = b'%s%s\n%s' % (header, desc, body)
926 write(encoding.unitolocal(content))
930 write(content)
927
931
928 @vcrcommand(b'phabread',
932 @vcrcommand(b'phabread',
929 [(b'', b'stack', False, _(b'read dependencies'))],
933 [(b'', b'stack', False, _(b'read dependencies'))],
930 _(b'DREVSPEC [OPTIONS]'),
934 _(b'DREVSPEC [OPTIONS]'),
931 helpcategory=command.CATEGORY_IMPORT_EXPORT)
935 helpcategory=command.CATEGORY_IMPORT_EXPORT)
932 def phabread(ui, repo, spec, **opts):
936 def phabread(ui, repo, spec, **opts):
933 """print patches from Phabricator suitable for importing
937 """print patches from Phabricator suitable for importing
934
938
935 DREVSPEC could be a Differential Revision identity, like ``D123``, or just
939 DREVSPEC could be a Differential Revision identity, like ``D123``, or just
936 the number ``123``. It could also have common operators like ``+``, ``-``,
940 the number ``123``. It could also have common operators like ``+``, ``-``,
937 ``&``, ``(``, ``)`` for complex queries. Prefix ``:`` could be used to
941 ``&``, ``(``, ``)`` for complex queries. Prefix ``:`` could be used to
938 select a stack.
942 select a stack.
939
943
940 ``abandoned``, ``accepted``, ``closed``, ``needsreview``, ``needsrevision``
944 ``abandoned``, ``accepted``, ``closed``, ``needsreview``, ``needsrevision``
941 could be used to filter patches by status. For performance reason, they
945 could be used to filter patches by status. For performance reason, they
942 only represent a subset of non-status selections and cannot be used alone.
946 only represent a subset of non-status selections and cannot be used alone.
943
947
944 For example, ``:D6+8-(2+D4)`` selects a stack up to D6, plus D8 and exclude
948 For example, ``:D6+8-(2+D4)`` selects a stack up to D6, plus D8 and exclude
945 D2 and D4. ``:D9 & needsreview`` selects "Needs Review" revisions in a
949 D2 and D4. ``:D9 & needsreview`` selects "Needs Review" revisions in a
946 stack up to D9.
950 stack up to D9.
947
951
948 If --stack is given, follow dependencies information and read all patches.
952 If --stack is given, follow dependencies information and read all patches.
949 It is equivalent to the ``:`` operator.
953 It is equivalent to the ``:`` operator.
950 """
954 """
951 if opts.get(b'stack'):
955 if opts.get(b'stack'):
952 spec = b':(%s)' % spec
956 spec = b':(%s)' % spec
953 drevs = querydrev(repo, spec)
957 drevs = querydrev(repo, spec)
954 readpatch(repo, drevs, ui.write)
958 readpatch(repo, drevs, ui.write)
955
959
956 @vcrcommand(b'phabupdate',
960 @vcrcommand(b'phabupdate',
957 [(b'', b'accept', False, _(b'accept revisions')),
961 [(b'', b'accept', False, _(b'accept revisions')),
958 (b'', b'reject', False, _(b'reject revisions')),
962 (b'', b'reject', False, _(b'reject revisions')),
959 (b'', b'abandon', False, _(b'abandon revisions')),
963 (b'', b'abandon', False, _(b'abandon revisions')),
960 (b'', b'reclaim', False, _(b'reclaim revisions')),
964 (b'', b'reclaim', False, _(b'reclaim revisions')),
961 (b'm', b'comment', b'', _(b'comment on the last revision')),
965 (b'm', b'comment', b'', _(b'comment on the last revision')),
962 ], _(b'DREVSPEC [OPTIONS]'),
966 ], _(b'DREVSPEC [OPTIONS]'),
963 helpcategory=command.CATEGORY_IMPORT_EXPORT)
967 helpcategory=command.CATEGORY_IMPORT_EXPORT)
964 def phabupdate(ui, repo, spec, **opts):
968 def phabupdate(ui, repo, spec, **opts):
965 """update Differential Revision in batch
969 """update Differential Revision in batch
966
970
967 DREVSPEC selects revisions. See :hg:`help phabread` for its usage.
971 DREVSPEC selects revisions. See :hg:`help phabread` for its usage.
968 """
972 """
969 flags = [n for n in b'accept reject abandon reclaim'.split() if opts.get(n)]
973 flags = [n for n in b'accept reject abandon reclaim'.split() if opts.get(n)]
970 if len(flags) > 1:
974 if len(flags) > 1:
971 raise error.Abort(_(b'%s cannot be used together') % b', '.join(flags))
975 raise error.Abort(_(b'%s cannot be used together') % b', '.join(flags))
972
976
973 actions = []
977 actions = []
974 for f in flags:
978 for f in flags:
975 actions.append({b'type': f, b'value': b'true'})
979 actions.append({b'type': f, b'value': b'true'})
976
980
977 drevs = querydrev(repo, spec)
981 drevs = querydrev(repo, spec)
978 for i, drev in enumerate(drevs):
982 for i, drev in enumerate(drevs):
979 if i + 1 == len(drevs) and opts.get(b'comment'):
983 if i + 1 == len(drevs) and opts.get(b'comment'):
980 actions.append({b'type': b'comment', b'value': opts[b'comment']})
984 actions.append({b'type': b'comment', b'value': opts[b'comment']})
981 if actions:
985 if actions:
982 params = {b'objectIdentifier': drev[r'phid'],
986 params = {b'objectIdentifier': drev[b'phid'],
983 b'transactions': actions}
987 b'transactions': actions}
984 callconduit(repo, b'differential.revision.edit', params)
988 callconduit(repo, b'differential.revision.edit', params)
985
989
986 templatekeyword = registrar.templatekeyword()
990 templatekeyword = registrar.templatekeyword()
987
991
988 @templatekeyword(b'phabreview', requires={b'ctx'})
992 @templatekeyword(b'phabreview', requires={b'ctx'})
989 def template_review(context, mapping):
993 def template_review(context, mapping):
990 """:phabreview: Object describing the review for this changeset.
994 """:phabreview: Object describing the review for this changeset.
991 Has attributes `url` and `id`.
995 Has attributes `url` and `id`.
992 """
996 """
993 ctx = context.resource(mapping, b'ctx')
997 ctx = context.resource(mapping, b'ctx')
994 m = _differentialrevisiondescre.search(ctx.description())
998 m = _differentialrevisiondescre.search(ctx.description())
995 if m:
999 if m:
996 return templateutil.hybriddict({
1000 return templateutil.hybriddict({
997 b'url': m.group(b'url'),
1001 b'url': m.group(b'url'),
998 b'id': b"D{}".format(m.group(b'id')),
1002 b'id': b"D{}".format(m.group(b'id')),
999 })
1003 })
1000 else:
1004 else:
1001 tags = ctx.repo().nodetags(ctx.node())
1005 tags = ctx.repo().nodetags(ctx.node())
1002 for t in tags:
1006 for t in tags:
1003 if _differentialrevisiontagre.match(t):
1007 if _differentialrevisiontagre.match(t):
1004 url = ctx.repo().ui.config(b'phabricator', b'url')
1008 url = ctx.repo().ui.config(b'phabricator', b'url')
1005 if not url.endswith(b'/'):
1009 if not url.endswith(b'/'):
1006 url += b'/'
1010 url += b'/'
1007 url += t
1011 url += t
1008
1012
1009 return templateutil.hybriddict({
1013 return templateutil.hybriddict({
1010 b'url': url,
1014 b'url': url,
1011 b'id': t,
1015 b'id': t,
1012 })
1016 })
1013 return None
1017 return None
This diff has been collapsed as it changes many lines, (901 lines changed) Show them Hide them
@@ -1,590 +1,617 b''
1 {
1 {
2 "version": 1,
3 "interactions": [
2 "interactions": [
4 {
3 {
4 "request": {
5 "method": "POST",
6 "body": "constraints%5Bcallsigns%5D%5B0%5D=HG&api.token=cli-hahayouwish",
7 "uri": "https://phab.mercurial-scm.org//api/diffusion.repository.search",
8 "headers": {
9 "content-type": [
10 "application/x-www-form-urlencoded"
11 ],
12 "accept": [
13 "application/mercurial-0.1"
14 ],
15 "user-agent": [
16 "mercurial/proto-1.0 (Mercurial 4.9+477-7c86ec0ca5c5+20190303)"
17 ],
18 "host": [
19 "phab.mercurial-scm.org"
20 ],
21 "content-length": [
22 "79"
23 ]
24 }
25 },
5 "response": {
26 "response": {
6 "status": {
27 "status": {
7 "message": "OK",
28 "code": 200,
8 "code": 200
29 "message": "OK"
9 },
30 },
10 "body": {
31 "body": {
11 "string": "{\"result\":{\"data\":[{\"id\":2,\"type\":\"REPO\",\"phid\":\"PHID-REPO-bvunnehri4u2isyr7bc3\",\"fields\":{\"name\":\"Mercurial\",\"vcs\":\"hg\",\"callsign\":\"HG\",\"shortName\":null,\"status\":\"active\",\"isImporting\":false,\"spacePHID\":null,\"dateCreated\":1498761653,\"dateModified\":1500403184,\"policy\":{\"view\":\"public\",\"edit\":\"admin\",\"diffusion.push\":\"users\"}},\"attachments\":{}}],\"maps\":{},\"query\":{\"queryKey\":null},\"cursor\":{\"limit\":100,\"after\":null,\"before\":null,\"order\":null}},\"error_code\":null,\"error_info\":null}"
32 "string": "{\"result\":{\"data\":[{\"id\":2,\"type\":\"REPO\",\"phid\":\"PHID-REPO-bvunnehri4u2isyr7bc3\",\"fields\":{\"name\":\"Mercurial\",\"vcs\":\"hg\",\"callsign\":\"HG\",\"shortName\":null,\"status\":\"active\",\"isImporting\":false,\"spacePHID\":null,\"dateCreated\":1498761653,\"dateModified\":1500403184,\"policy\":{\"view\":\"public\",\"edit\":\"admin\",\"diffusion.push\":\"users\"}},\"attachments\":{}}],\"maps\":{},\"query\":{\"queryKey\":null},\"cursor\":{\"limit\":100,\"after\":null,\"before\":null,\"order\":null}},\"error_code\":null,\"error_info\":null}"
12 },
33 },
13 "headers": {
34 "headers": {
14 "x-xss-protection": [
15 "1; mode=block"
16 ],
17 "expires": [
35 "expires": [
18 "Sat, 01 Jan 2000 00:00:00 GMT"
36 "Sat, 01 Jan 2000 00:00:00 GMT"
19 ],
37 ],
20 "set-cookie": [
38 "x-xss-protection": [
21 "phsid=A%2F4wycgjx3wajuukr7ggfpqedpe7czucr7mvmaems3; expires=Thu, 14-Sep-2023 04:47:40 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
39 "1; mode=block"
22 ],
40 ],
41 "transfer-encoding": [
42 "chunked"
43 ],
44 "date": [
45 "Sun, 03 Mar 2019 00:12:23 GMT"
46 ],
23 "x-frame-options": [
47 "x-frame-options": [
24 "Deny"
48 "Deny"
25 ],
49 ],
50 "cache-control": [
51 "no-store"
52 ],
53 "content-type": [
54 "application/json"
55 ],
26 "x-content-type-options": [
56 "x-content-type-options": [
27 "nosniff"
57 "nosniff"
28 ],
58 ],
59 "server": [
60 "Apache/2.4.10 (Debian)"
61 ],
62 "set-cookie": [
63 "phsid=A%2Fpywot5xerq4gs2tjxw3gnadzdg6vomqmfcnwqddp; expires=Fri, 01-Mar-2024 00:12:23 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
64 ],
29 "strict-transport-security": [
65 "strict-transport-security": [
30 "max-age=0; includeSubdomains; preload"
66 "max-age=0; includeSubdomains; preload"
31 ],
32 "server": [
33 "Apache/2.4.10 (Debian)"
34 ],
35 "date": [
36 "Sat, 15 Sep 2018 04:47:40 GMT"
37 ],
38 "content-type": [
39 "application/json"
40 ],
41 "cache-control": [
42 "no-store"
43 ]
44 }
45 },
46 "request": {
47 "method": "POST",
48 "uri": "https://phab.mercurial-scm.org//api/diffusion.repository.search",
49 "body": "constraints%5Bcallsigns%5D%5B0%5D=HG&api.token=cli-hahayouwish",
50 "headers": {
51 "accept": [
52 "application/mercurial-0.1"
53 ],
54 "content-type": [
55 "application/x-www-form-urlencoded"
56 ],
57 "host": [
58 "phab.mercurial-scm.org"
59 ],
60 "content-length": [
61 "79"
62 ],
63 "user-agent": [
64 "mercurial/proto-1.0 (Mercurial 4.7.1+866-5f07496726a1+20180915)"
65 ]
67 ]
66 }
68 }
67 }
69 }
68 },
70 },
69 {
71 {
72 "request": {
73 "method": "POST",
74 "body": "repositoryPHID=PHID-REPO-bvunnehri4u2isyr7bc3&api.token=cli-hahayouwish&diff=diff+--git+a%2Falpha+b%2Falpha%0Anew+file+mode+100644%0A---+%2Fdev%2Fnull%0A%2B%2B%2B+b%2Falpha%0A%40%40+-0%2C0+%2B1%2C1+%40%40%0A%2Balpha%0A",
75 "uri": "https://phab.mercurial-scm.org//api/differential.createrawdiff",
76 "headers": {
77 "content-type": [
78 "application/x-www-form-urlencoded"
79 ],
80 "accept": [
81 "application/mercurial-0.1"
82 ],
83 "user-agent": [
84 "mercurial/proto-1.0 (Mercurial 4.9+477-7c86ec0ca5c5+20190303)"
85 ],
86 "host": [
87 "phab.mercurial-scm.org"
88 ],
89 "content-length": [
90 "235"
91 ]
92 }
93 },
70 "response": {
94 "response": {
71 "status": {
95 "status": {
72 "message": "OK",
96 "code": 200,
73 "code": 200
97 "message": "OK"
74 },
98 },
75 "body": {
99 "body": {
76 "string": "{\"result\":{\"id\":11072,\"phid\":\"PHID-DIFF-xm6cw76uivc6g56xiuv2\",\"uri\":\"https:\\/\\/phab.mercurial-scm.org\\/differential\\/diff\\/11072\\/\"},\"error_code\":null,\"error_info\":null}"
100 "string": "{\"result\":{\"id\":14303,\"phid\":\"PHID-DIFF-allzuauvigfjpv4z6dpi\",\"uri\":\"https:\\/\\/phab.mercurial-scm.org\\/differential\\/diff\\/14303\\/\"},\"error_code\":null,\"error_info\":null}"
77 },
101 },
78 "headers": {
102 "headers": {
103 "expires": [
104 "Sat, 01 Jan 2000 00:00:00 GMT"
105 ],
79 "x-xss-protection": [
106 "x-xss-protection": [
80 "1; mode=block"
107 "1; mode=block"
81 ],
108 ],
82 "expires": [
109 "transfer-encoding": [
83 "Sat, 01 Jan 2000 00:00:00 GMT"
110 "chunked"
84 ],
111 ],
85 "set-cookie": [
112 "date": [
86 "phsid=A%2Fll65pt562b6d7ifhjva4jwqqzxh2oopj4tuc6lfa; expires=Thu, 14-Sep-2023 04:47:40 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
113 "Sun, 03 Mar 2019 00:12:24 GMT"
87 ],
114 ],
88 "x-frame-options": [
115 "x-frame-options": [
89 "Deny"
116 "Deny"
90 ],
117 ],
118 "cache-control": [
119 "no-store"
120 ],
121 "content-type": [
122 "application/json"
123 ],
91 "x-content-type-options": [
124 "x-content-type-options": [
92 "nosniff"
125 "nosniff"
93 ],
126 ],
94 "strict-transport-security": [
95 "max-age=0; includeSubdomains; preload"
96 ],
97 "server": [
127 "server": [
98 "Apache/2.4.10 (Debian)"
128 "Apache/2.4.10 (Debian)"
99 ],
129 ],
100 "date": [
130 "set-cookie": [
101 "Sat, 15 Sep 2018 04:47:40 GMT"
131 "phsid=A%2F2n2dlkkwzljrpzfghpdsflbt4ftnrwcc446dzcy5; expires=Fri, 01-Mar-2024 00:12:24 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
102 ],
132 ],
103 "content-type": [
133 "strict-transport-security": [
104 "application/json"
134 "max-age=0; includeSubdomains; preload"
105 ],
106 "cache-control": [
107 "no-store"
108 ]
109 }
110 },
111 "request": {
112 "method": "POST",
113 "uri": "https://phab.mercurial-scm.org//api/differential.createrawdiff",
114 "body": "repositoryPHID=PHID-REPO-bvunnehri4u2isyr7bc3&diff=diff+--git+a%2Falpha+b%2Falpha%0Anew+file+mode+100644%0A---+%2Fdev%2Fnull%0A%2B%2B%2B+b%2Falpha%0A%40%40+-0%2C0+%2B1%2C1+%40%40%0A%2Balpha%0A&api.token=cli-hahayouwish",
115 "headers": {
116 "accept": [
117 "application/mercurial-0.1"
118 ],
119 "content-type": [
120 "application/x-www-form-urlencoded"
121 ],
122 "host": [
123 "phab.mercurial-scm.org"
124 ],
125 "content-length": [
126 "235"
127 ],
128 "user-agent": [
129 "mercurial/proto-1.0 (Mercurial 4.7.1+866-5f07496726a1+20180915)"
130 ]
135 ]
131 }
136 }
132 }
137 }
133 },
138 },
134 {
139 {
140 "request": {
141 "method": "POST",
142 "body": "diff_id=14303&data=%7B%22user%22%3A+%22test%22%2C+%22parent%22%3A+%220000000000000000000000000000000000000000%22%2C+%22node%22%3A+%22d386117f30e6b1282897bdbde75ac21e095163d4%22%2C+%22date%22%3A+%220+0%22%7D&api.token=cli-hahayouwish&name=hg%3Ameta",
143 "uri": "https://phab.mercurial-scm.org//api/differential.setdiffproperty",
144 "headers": {
145 "content-type": [
146 "application/x-www-form-urlencoded"
147 ],
148 "accept": [
149 "application/mercurial-0.1"
150 ],
151 "user-agent": [
152 "mercurial/proto-1.0 (Mercurial 4.9+477-7c86ec0ca5c5+20190303)"
153 ],
154 "host": [
155 "phab.mercurial-scm.org"
156 ],
157 "content-length": [
158 "264"
159 ]
160 }
161 },
135 "response": {
162 "response": {
136 "status": {
163 "status": {
137 "message": "OK",
164 "code": 200,
138 "code": 200
165 "message": "OK"
139 },
166 },
140 "body": {
167 "body": {
141 "string": "{\"result\":null,\"error_code\":null,\"error_info\":null}"
168 "string": "{\"result\":null,\"error_code\":null,\"error_info\":null}"
142 },
169 },
143 "headers": {
170 "headers": {
171 "expires": [
172 "Sat, 01 Jan 2000 00:00:00 GMT"
173 ],
144 "x-xss-protection": [
174 "x-xss-protection": [
145 "1; mode=block"
175 "1; mode=block"
146 ],
176 ],
147 "expires": [
177 "transfer-encoding": [
148 "Sat, 01 Jan 2000 00:00:00 GMT"
178 "chunked"
149 ],
179 ],
150 "set-cookie": [
180 "date": [
151 "phsid=A%2F5ivszbehkvbetlnks7omsqmbsu7r5by3p3yqw3ep; expires=Thu, 14-Sep-2023 04:47:41 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
181 "Sun, 03 Mar 2019 00:12:25 GMT"
152 ],
182 ],
153 "x-frame-options": [
183 "x-frame-options": [
154 "Deny"
184 "Deny"
155 ],
185 ],
186 "cache-control": [
187 "no-store"
188 ],
189 "content-type": [
190 "application/json"
191 ],
156 "x-content-type-options": [
192 "x-content-type-options": [
157 "nosniff"
193 "nosniff"
158 ],
194 ],
159 "strict-transport-security": [
160 "max-age=0; includeSubdomains; preload"
161 ],
162 "server": [
195 "server": [
163 "Apache/2.4.10 (Debian)"
196 "Apache/2.4.10 (Debian)"
164 ],
197 ],
165 "date": [
198 "set-cookie": [
166 "Sat, 15 Sep 2018 04:47:41 GMT"
199 "phsid=A%2F5mq3t25wu5igv7oufpwcoy32fveozo7wn5wni3gw; expires=Fri, 01-Mar-2024 00:12:25 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
167 ],
200 ],
168 "content-type": [
201 "strict-transport-security": [
169 "application/json"
202 "max-age=0; includeSubdomains; preload"
170 ],
171 "cache-control": [
172 "no-store"
173 ]
174 }
175 },
176 "request": {
177 "method": "POST",
178 "uri": "https://phab.mercurial-scm.org//api/differential.setdiffproperty",
179 "body": "data=%7B%22date%22%3A+%220+0%22%2C+%22node%22%3A+%225206a4fa1e6cd7dbc027640267c109e05a9d2341%22%2C+%22user%22%3A+%22test%22%2C+%22parent%22%3A+%220000000000000000000000000000000000000000%22%7D&name=hg%3Ameta&diff_id=11072&api.token=cli-hahayouwish",
180 "headers": {
181 "accept": [
182 "application/mercurial-0.1"
183 ],
184 "content-type": [
185 "application/x-www-form-urlencoded"
186 ],
187 "host": [
188 "phab.mercurial-scm.org"
189 ],
190 "content-length": [
191 "264"
192 ],
193 "user-agent": [
194 "mercurial/proto-1.0 (Mercurial 4.7.1+866-5f07496726a1+20180915)"
195 ]
203 ]
196 }
204 }
197 }
205 }
198 },
206 },
199 {
207 {
208 "request": {
209 "method": "POST",
210 "body": "diff_id=14303&data=%7B%22d386117f30e6b1282897bdbde75ac21e095163d4%22%3A+%7B%22author%22%3A+%22test%22%2C+%22authorEmail%22%3A+%22test%22%2C+%22time%22%3A+0.0%7D%7D&api.token=cli-hahayouwish&name=local%3Acommits",
211 "uri": "https://phab.mercurial-scm.org//api/differential.setdiffproperty",
212 "headers": {
213 "content-type": [
214 "application/x-www-form-urlencoded"
215 ],
216 "accept": [
217 "application/mercurial-0.1"
218 ],
219 "user-agent": [
220 "mercurial/proto-1.0 (Mercurial 4.9+477-7c86ec0ca5c5+20190303)"
221 ],
222 "host": [
223 "phab.mercurial-scm.org"
224 ],
225 "content-length": [
226 "227"
227 ]
228 }
229 },
200 "response": {
230 "response": {
201 "status": {
231 "status": {
202 "message": "OK",
232 "code": 200,
203 "code": 200
233 "message": "OK"
204 },
234 },
205 "body": {
235 "body": {
206 "string": "{\"result\":null,\"error_code\":null,\"error_info\":null}"
236 "string": "{\"result\":null,\"error_code\":null,\"error_info\":null}"
207 },
237 },
208 "headers": {
238 "headers": {
239 "expires": [
240 "Sat, 01 Jan 2000 00:00:00 GMT"
241 ],
209 "x-xss-protection": [
242 "x-xss-protection": [
210 "1; mode=block"
243 "1; mode=block"
211 ],
244 ],
212 "expires": [
245 "transfer-encoding": [
213 "Sat, 01 Jan 2000 00:00:00 GMT"
246 "chunked"
214 ],
247 ],
215 "set-cookie": [
248 "date": [
216 "phsid=A%2Fxvwxxrmwpjntx6dlohrstyox7yjssdbzufiwygcg; expires=Thu, 14-Sep-2023 04:47:41 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
249 "Sun, 03 Mar 2019 00:12:25 GMT"
217 ],
250 ],
218 "x-frame-options": [
251 "x-frame-options": [
219 "Deny"
252 "Deny"
220 ],
253 ],
254 "cache-control": [
255 "no-store"
256 ],
257 "content-type": [
258 "application/json"
259 ],
221 "x-content-type-options": [
260 "x-content-type-options": [
222 "nosniff"
261 "nosniff"
223 ],
262 ],
224 "strict-transport-security": [
225 "max-age=0; includeSubdomains; preload"
226 ],
227 "server": [
263 "server": [
228 "Apache/2.4.10 (Debian)"
264 "Apache/2.4.10 (Debian)"
229 ],
265 ],
230 "date": [
266 "set-cookie": [
231 "Sat, 15 Sep 2018 04:47:41 GMT"
267 "phsid=A%2F5nja6g4cnpt63ctjjwykxyceyb7kokfptrzbejoc; expires=Fri, 01-Mar-2024 00:12:25 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
232 ],
268 ],
233 "content-type": [
269 "strict-transport-security": [
234 "application/json"
270 "max-age=0; includeSubdomains; preload"
235 ],
236 "cache-control": [
237 "no-store"
238 ]
239 }
240 },
241 "request": {
242 "method": "POST",
243 "uri": "https://phab.mercurial-scm.org//api/differential.setdiffproperty",
244 "body": "data=%7B%225206a4fa1e6cd7dbc027640267c109e05a9d2341%22%3A+%7B%22time%22%3A+0.0%2C+%22author%22%3A+%22test%22%2C+%22authorEmail%22%3A+%22test%22%7D%7D&name=local%3Acommits&diff_id=11072&api.token=cli-hahayouwish",
245 "headers": {
246 "accept": [
247 "application/mercurial-0.1"
248 ],
249 "content-type": [
250 "application/x-www-form-urlencoded"
251 ],
252 "host": [
253 "phab.mercurial-scm.org"
254 ],
255 "content-length": [
256 "227"
257 ],
258 "user-agent": [
259 "mercurial/proto-1.0 (Mercurial 4.7.1+866-5f07496726a1+20180915)"
260 ]
271 ]
261 }
272 }
262 }
273 }
263 },
274 },
264 {
275 {
276 "request": {
277 "method": "POST",
278 "body": "api.token=cli-hahayouwish&corpus=create+alpha+for+phabricator+test+%E2%82%AC",
279 "uri": "https://phab.mercurial-scm.org//api/differential.parsecommitmessage",
280 "headers": {
281 "content-type": [
282 "application/x-www-form-urlencoded"
283 ],
284 "accept": [
285 "application/mercurial-0.1"
286 ],
287 "user-agent": [
288 "mercurial/proto-1.0 (Mercurial 4.9+477-7c86ec0ca5c5+20190303)"
289 ],
290 "host": [
291 "phab.mercurial-scm.org"
292 ],
293 "content-length": [
294 "93"
295 ]
296 }
297 },
265 "response": {
298 "response": {
266 "status": {
299 "status": {
267 "message": "OK",
300 "code": 200,
268 "code": 200
301 "message": "OK"
269 },
302 },
270 "body": {
303 "body": {
271 "string": "{\"result\":{\"errors\":[],\"fields\":{\"title\":\"create alpha for phabricator test\"},\"revisionIDFieldInfo\":{\"value\":null,\"validDomain\":\"https:\\/\\/phab.mercurial-scm.org\"}},\"error_code\":null,\"error_info\":null}"
304 "string": "{\"result\":{\"errors\":[],\"fields\":{\"title\":\"create alpha for phabricator test \\u20ac\"},\"revisionIDFieldInfo\":{\"value\":null,\"validDomain\":\"https:\\/\\/phab.mercurial-scm.org\"}},\"error_code\":null,\"error_info\":null}"
272 },
305 },
273 "headers": {
306 "headers": {
307 "expires": [
308 "Sat, 01 Jan 2000 00:00:00 GMT"
309 ],
274 "x-xss-protection": [
310 "x-xss-protection": [
275 "1; mode=block"
311 "1; mode=block"
276 ],
312 ],
277 "expires": [
313 "transfer-encoding": [
278 "Sat, 01 Jan 2000 00:00:00 GMT"
314 "chunked"
279 ],
315 ],
280 "set-cookie": [
316 "date": [
281 "phsid=A%2Fy3s5iysh6h2javfdo2u7myspyjypv4mvojegqr6j; expires=Thu, 14-Sep-2023 04:47:42 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
317 "Sun, 03 Mar 2019 00:12:26 GMT"
282 ],
318 ],
283 "x-frame-options": [
319 "x-frame-options": [
284 "Deny"
320 "Deny"
285 ],
321 ],
322 "cache-control": [
323 "no-store"
324 ],
325 "content-type": [
326 "application/json"
327 ],
286 "x-content-type-options": [
328 "x-content-type-options": [
287 "nosniff"
329 "nosniff"
288 ],
330 ],
289 "strict-transport-security": [
290 "max-age=0; includeSubdomains; preload"
291 ],
292 "server": [
331 "server": [
293 "Apache/2.4.10 (Debian)"
332 "Apache/2.4.10 (Debian)"
294 ],
333 ],
295 "date": [
334 "set-cookie": [
296 "Sat, 15 Sep 2018 04:47:42 GMT"
335 "phsid=A%2Fkrxawhyvcd4jhv77inuwdmzcci4f7kql6c7l3smz; expires=Fri, 01-Mar-2024 00:12:26 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
297 ],
336 ],
298 "content-type": [
337 "strict-transport-security": [
299 "application/json"
338 "max-age=0; includeSubdomains; preload"
300 ],
301 "cache-control": [
302 "no-store"
303 ]
304 }
305 },
306 "request": {
307 "method": "POST",
308 "uri": "https://phab.mercurial-scm.org//api/differential.parsecommitmessage",
309 "body": "corpus=create+alpha+for+phabricator+test&api.token=cli-hahayouwish",
310 "headers": {
311 "accept": [
312 "application/mercurial-0.1"
313 ],
314 "content-type": [
315 "application/x-www-form-urlencoded"
316 ],
317 "host": [
318 "phab.mercurial-scm.org"
319 ],
320 "content-length": [
321 "83"
322 ],
323 "user-agent": [
324 "mercurial/proto-1.0 (Mercurial 4.7.1+866-5f07496726a1+20180915)"
325 ]
339 ]
326 }
340 }
327 }
341 }
328 },
342 },
329 {
343 {
344 "request": {
345 "method": "POST",
346 "body": "transactions%5B0%5D%5Btype%5D=update&transactions%5B0%5D%5Bvalue%5D=PHID-DIFF-allzuauvigfjpv4z6dpi&transactions%5B1%5D%5Btype%5D=title&transactions%5B1%5D%5Bvalue%5D=create+alpha+for+phabricator+test+%E2%82%AC&api.token=cli-hahayouwish",
347 "uri": "https://phab.mercurial-scm.org//api/differential.revision.edit",
348 "headers": {
349 "content-type": [
350 "application/x-www-form-urlencoded"
351 ],
352 "accept": [
353 "application/mercurial-0.1"
354 ],
355 "user-agent": [
356 "mercurial/proto-1.0 (Mercurial 4.9+477-7c86ec0ca5c5+20190303)"
357 ],
358 "host": [
359 "phab.mercurial-scm.org"
360 ],
361 "content-length": [
362 "252"
363 ]
364 }
365 },
330 "response": {
366 "response": {
331 "status": {
367 "status": {
332 "message": "OK",
368 "code": 200,
333 "code": 200
369 "message": "OK"
334 },
370 },
335 "body": {
371 "body": {
336 "string": "{\"result\":{\"object\":{\"id\":4596,\"phid\":\"PHID-DREV-bntcdwe74cw3vwkzt6nq\"},\"transactions\":[{\"phid\":\"PHID-XACT-DREV-mnqxquobbhdgttd\"},{\"phid\":\"PHID-XACT-DREV-nd34pqrjamxbhop\"},{\"phid\":\"PHID-XACT-DREV-4ka4rghn6b7xooc\"},{\"phid\":\"PHID-XACT-DREV-mfuvfyiijdqwpyg\"},{\"phid\":\"PHID-XACT-DREV-ckar54h6yenx24s\"}]},\"error_code\":null,\"error_info\":null}"
372 "string": "{\"result\":{\"object\":{\"id\":6054,\"phid\":\"PHID-DREV-6pczsbtdpqjc2nskmxwy\"},\"transactions\":[{\"phid\":\"PHID-XACT-DREV-efgl4j4fesixjog\"},{\"phid\":\"PHID-XACT-DREV-xj7ksjeyfadwf5m\"},{\"phid\":\"PHID-XACT-DREV-gecx5zw42kkuffc\"},{\"phid\":\"PHID-XACT-DREV-asda7zcwgzdadoi\"},{\"phid\":\"PHID-XACT-DREV-ku26t33y6iiugjw\"}]},\"error_code\":null,\"error_info\":null}"
337 },
373 },
338 "headers": {
374 "headers": {
375 "expires": [
376 "Sat, 01 Jan 2000 00:00:00 GMT"
377 ],
339 "x-xss-protection": [
378 "x-xss-protection": [
340 "1; mode=block"
379 "1; mode=block"
341 ],
380 ],
342 "expires": [
381 "transfer-encoding": [
343 "Sat, 01 Jan 2000 00:00:00 GMT"
382 "chunked"
344 ],
383 ],
345 "set-cookie": [
384 "date": [
346 "phsid=A%2Foe7kd7hhldo25tzbegntkyfxm6wnztgdfmsfubo2; expires=Thu, 14-Sep-2023 04:47:42 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
385 "Sun, 03 Mar 2019 00:12:27 GMT"
347 ],
386 ],
348 "x-frame-options": [
387 "x-frame-options": [
349 "Deny"
388 "Deny"
350 ],
389 ],
390 "cache-control": [
391 "no-store"
392 ],
393 "content-type": [
394 "application/json"
395 ],
351 "x-content-type-options": [
396 "x-content-type-options": [
352 "nosniff"
397 "nosniff"
353 ],
398 ],
354 "strict-transport-security": [
355 "max-age=0; includeSubdomains; preload"
356 ],
357 "server": [
399 "server": [
358 "Apache/2.4.10 (Debian)"
400 "Apache/2.4.10 (Debian)"
359 ],
401 ],
360 "date": [
402 "set-cookie": [
361 "Sat, 15 Sep 2018 04:47:42 GMT"
403 "phsid=A%2Fjwgcqb5hvbltjq4jqbpauz7rmmhpuh2rb7phsdmf; expires=Fri, 01-Mar-2024 00:12:27 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
362 ],
404 ],
363 "content-type": [
405 "strict-transport-security": [
364 "application/json"
406 "max-age=0; includeSubdomains; preload"
365 ],
366 "cache-control": [
367 "no-store"
368 ]
369 }
370 },
371 "request": {
372 "method": "POST",
373 "uri": "https://phab.mercurial-scm.org//api/differential.revision.edit",
374 "body": "transactions%5B0%5D%5Bvalue%5D=PHID-DIFF-xm6cw76uivc6g56xiuv2&transactions%5B0%5D%5Btype%5D=update&transactions%5B1%5D%5Bvalue%5D=create+alpha+for+phabricator+test&transactions%5B1%5D%5Btype%5D=title&api.token=cli-hahayouwish",
375 "headers": {
376 "accept": [
377 "application/mercurial-0.1"
378 ],
379 "content-type": [
380 "application/x-www-form-urlencoded"
381 ],
382 "host": [
383 "phab.mercurial-scm.org"
384 ],
385 "content-length": [
386 "242"
387 ],
388 "user-agent": [
389 "mercurial/proto-1.0 (Mercurial 4.7.1+866-5f07496726a1+20180915)"
390 ]
407 ]
391 }
408 }
392 }
409 }
393 },
410 },
394 {
411 {
412 "request": {
413 "method": "POST",
414 "body": "api.token=cli-hahayouwish&ids%5B0%5D=6054",
415 "uri": "https://phab.mercurial-scm.org//api/differential.query",
416 "headers": {
417 "content-type": [
418 "application/x-www-form-urlencoded"
419 ],
420 "accept": [
421 "application/mercurial-0.1"
422 ],
423 "user-agent": [
424 "mercurial/proto-1.0 (Mercurial 4.9+477-7c86ec0ca5c5+20190303)"
425 ],
426 "host": [
427 "phab.mercurial-scm.org"
428 ],
429 "content-length": [
430 "58"
431 ]
432 }
433 },
395 "response": {
434 "response": {
396 "status": {
435 "status": {
397 "message": "OK",
436 "code": 200,
398 "code": 200
437 "message": "OK"
399 },
438 },
400 "body": {
439 "body": {
401 "string": "{\"result\":[{\"id\":\"4596\",\"phid\":\"PHID-DREV-bntcdwe74cw3vwkzt6nq\",\"title\":\"create alpha for phabricator test\",\"uri\":\"https:\\/\\/phab.mercurial-scm.org\\/D4596\",\"dateCreated\":\"1536986862\",\"dateModified\":\"1536986862\",\"authorPHID\":\"PHID-USER-cgcdlc6c3gpxapbmkwa2\",\"status\":\"0\",\"statusName\":\"Needs Review\",\"properties\":[],\"branch\":null,\"summary\":\"\",\"testPlan\":\"\",\"lineCount\":\"1\",\"activeDiffPHID\":\"PHID-DIFF-xm6cw76uivc6g56xiuv2\",\"diffs\":[\"11072\"],\"commits\":[],\"reviewers\":{\"PHID-PROJ-3dvcxzznrjru2xmmses3\":\"PHID-PROJ-3dvcxzznrjru2xmmses3\"},\"ccs\":[\"PHID-USER-q42dn7cc3donqriafhjx\"],\"hashes\":[],\"auxiliary\":{\"phabricator:projects\":[],\"phabricator:depends-on\":[]},\"repositoryPHID\":\"PHID-REPO-bvunnehri4u2isyr7bc3\",\"sourcePath\":null}],\"error_code\":null,\"error_info\":null}"
440 "string": "{\"result\":[{\"id\":\"6054\",\"phid\":\"PHID-DREV-6pczsbtdpqjc2nskmxwy\",\"title\":\"create alpha for phabricator test \\u20ac\",\"uri\":\"https:\\/\\/phab.mercurial-scm.org\\/D6054\",\"dateCreated\":\"1551571947\",\"dateModified\":\"1551571947\",\"authorPHID\":\"PHID-USER-5iy6mkoveguhm2zthvww\",\"status\":\"0\",\"statusName\":\"Needs Review\",\"properties\":[],\"branch\":null,\"summary\":\"\",\"testPlan\":\"\",\"lineCount\":\"1\",\"activeDiffPHID\":\"PHID-DIFF-allzuauvigfjpv4z6dpi\",\"diffs\":[\"14303\"],\"commits\":[],\"reviewers\":{\"PHID-PROJ-3dvcxzznrjru2xmmses3\":\"PHID-PROJ-3dvcxzznrjru2xmmses3\"},\"ccs\":[\"PHID-USER-q42dn7cc3donqriafhjx\"],\"hashes\":[],\"auxiliary\":{\"phabricator:projects\":[],\"phabricator:depends-on\":[]},\"repositoryPHID\":\"PHID-REPO-bvunnehri4u2isyr7bc3\",\"sourcePath\":null}],\"error_code\":null,\"error_info\":null}"
402 },
441 },
403 "headers": {
442 "headers": {
443 "expires": [
444 "Sat, 01 Jan 2000 00:00:00 GMT"
445 ],
404 "x-xss-protection": [
446 "x-xss-protection": [
405 "1; mode=block"
447 "1; mode=block"
406 ],
448 ],
407 "expires": [
449 "transfer-encoding": [
408 "Sat, 01 Jan 2000 00:00:00 GMT"
450 "chunked"
409 ],
451 ],
410 "set-cookie": [
452 "date": [
411 "phsid=A%2F5d2bgafhoqhg5thqxeu6y4fngq7lqezf5h6eo5pd; expires=Thu, 14-Sep-2023 04:47:43 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
453 "Sun, 03 Mar 2019 00:12:28 GMT"
412 ],
454 ],
413 "x-frame-options": [
455 "x-frame-options": [
414 "Deny"
456 "Deny"
415 ],
457 ],
458 "cache-control": [
459 "no-store"
460 ],
461 "content-type": [
462 "application/json"
463 ],
416 "x-content-type-options": [
464 "x-content-type-options": [
417 "nosniff"
465 "nosniff"
418 ],
466 ],
419 "strict-transport-security": [
420 "max-age=0; includeSubdomains; preload"
421 ],
422 "server": [
467 "server": [
423 "Apache/2.4.10 (Debian)"
468 "Apache/2.4.10 (Debian)"
424 ],
469 ],
425 "date": [
470 "set-cookie": [
426 "Sat, 15 Sep 2018 04:47:43 GMT"
471 "phsid=A%2F3lgkbbyaa646ng5klghjyehsbjxtaqblipnvocuz; expires=Fri, 01-Mar-2024 00:12:28 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
427 ],
472 ],
428 "content-type": [
473 "strict-transport-security": [
429 "application/json"
474 "max-age=0; includeSubdomains; preload"
430 ],
431 "cache-control": [
432 "no-store"
433 ]
434 }
435 },
436 "request": {
437 "method": "POST",
438 "uri": "https://phab.mercurial-scm.org//api/differential.query",
439 "body": "api.token=cli-hahayouwish&ids%5B0%5D=4596",
440 "headers": {
441 "accept": [
442 "application/mercurial-0.1"
443 ],
444 "content-type": [
445 "application/x-www-form-urlencoded"
446 ],
447 "host": [
448 "phab.mercurial-scm.org"
449 ],
450 "content-length": [
451 "58"
452 ],
453 "user-agent": [
454 "mercurial/proto-1.0 (Mercurial 4.7.1+866-5f07496726a1+20180915)"
455 ]
475 ]
456 }
476 }
457 }
477 }
458 },
478 },
459 {
479 {
480 "request": {
481 "method": "POST",
482 "body": "diff_id=14303&data=%7B%22user%22%3A+%22test%22%2C+%22parent%22%3A+%220000000000000000000000000000000000000000%22%2C+%22node%22%3A+%22cb03845d6dd98c72bec766c7ed08c693cc49817a%22%2C+%22date%22%3A+%220+0%22%7D&api.token=cli-hahayouwish&name=hg%3Ameta",
483 "uri": "https://phab.mercurial-scm.org//api/differential.setdiffproperty",
484 "headers": {
485 "content-type": [
486 "application/x-www-form-urlencoded"
487 ],
488 "accept": [
489 "application/mercurial-0.1"
490 ],
491 "user-agent": [
492 "mercurial/proto-1.0 (Mercurial 4.9+477-7c86ec0ca5c5+20190303)"
493 ],
494 "host": [
495 "phab.mercurial-scm.org"
496 ],
497 "content-length": [
498 "264"
499 ]
500 }
501 },
460 "response": {
502 "response": {
461 "status": {
503 "status": {
462 "message": "OK",
504 "code": 200,
463 "code": 200
505 "message": "OK"
464 },
506 },
465 "body": {
507 "body": {
466 "string": "{\"result\":null,\"error_code\":null,\"error_info\":null}"
508 "string": "{\"result\":null,\"error_code\":null,\"error_info\":null}"
467 },
509 },
468 "headers": {
510 "headers": {
511 "expires": [
512 "Sat, 01 Jan 2000 00:00:00 GMT"
513 ],
469 "x-xss-protection": [
514 "x-xss-protection": [
470 "1; mode=block"
515 "1; mode=block"
471 ],
516 ],
472 "expires": [
517 "transfer-encoding": [
473 "Sat, 01 Jan 2000 00:00:00 GMT"
518 "chunked"
474 ],
519 ],
475 "set-cookie": [
520 "date": [
476 "phsid=A%2F2cewrqifmvko6evm2sy2nvksvcvhk6hpsj36lcv2; expires=Thu, 14-Sep-2023 04:47:43 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
521 "Sun, 03 Mar 2019 00:12:28 GMT"
477 ],
522 ],
478 "x-frame-options": [
523 "x-frame-options": [
479 "Deny"
524 "Deny"
480 ],
525 ],
526 "cache-control": [
527 "no-store"
528 ],
529 "content-type": [
530 "application/json"
531 ],
481 "x-content-type-options": [
532 "x-content-type-options": [
482 "nosniff"
533 "nosniff"
483 ],
534 ],
484 "strict-transport-security": [
485 "max-age=0; includeSubdomains; preload"
486 ],
487 "server": [
535 "server": [
488 "Apache/2.4.10 (Debian)"
536 "Apache/2.4.10 (Debian)"
489 ],
537 ],
490 "date": [
538 "set-cookie": [
491 "Sat, 15 Sep 2018 04:47:43 GMT"
539 "phsid=A%2Fwjxvlsjqmqwvcljfv6oe2sbometi3gebps6vzrlw; expires=Fri, 01-Mar-2024 00:12:28 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
492 ],
540 ],
493 "content-type": [
541 "strict-transport-security": [
494 "application/json"
542 "max-age=0; includeSubdomains; preload"
495 ],
496 "cache-control": [
497 "no-store"
498 ]
499 }
500 },
501 "request": {
502 "method": "POST",
503 "uri": "https://phab.mercurial-scm.org//api/differential.setdiffproperty",
504 "body": "data=%7B%22date%22%3A+%220+0%22%2C+%22node%22%3A+%22d8f232f7d799e1064d3da179df41a2b5d04334e9%22%2C+%22user%22%3A+%22test%22%2C+%22parent%22%3A+%220000000000000000000000000000000000000000%22%7D&name=hg%3Ameta&diff_id=11072&api.token=cli-hahayouwish",
505 "headers": {
506 "accept": [
507 "application/mercurial-0.1"
508 ],
509 "content-type": [
510 "application/x-www-form-urlencoded"
511 ],
512 "host": [
513 "phab.mercurial-scm.org"
514 ],
515 "content-length": [
516 "264"
517 ],
518 "user-agent": [
519 "mercurial/proto-1.0 (Mercurial 4.7.1+866-5f07496726a1+20180915)"
520 ]
543 ]
521 }
544 }
522 }
545 }
523 },
546 },
524 {
547 {
548 "request": {
549 "method": "POST",
550 "body": "diff_id=14303&data=%7B%22cb03845d6dd98c72bec766c7ed08c693cc49817a%22%3A+%7B%22author%22%3A+%22test%22%2C+%22authorEmail%22%3A+%22test%22%2C+%22time%22%3A+0.0%7D%7D&api.token=cli-hahayouwish&name=local%3Acommits",
551 "uri": "https://phab.mercurial-scm.org//api/differential.setdiffproperty",
552 "headers": {
553 "content-type": [
554 "application/x-www-form-urlencoded"
555 ],
556 "accept": [
557 "application/mercurial-0.1"
558 ],
559 "user-agent": [
560 "mercurial/proto-1.0 (Mercurial 4.9+477-7c86ec0ca5c5+20190303)"
561 ],
562 "host": [
563 "phab.mercurial-scm.org"
564 ],
565 "content-length": [
566 "227"
567 ]
568 }
569 },
525 "response": {
570 "response": {
526 "status": {
571 "status": {
527 "message": "OK",
572 "code": 200,
528 "code": 200
573 "message": "OK"
529 },
574 },
530 "body": {
575 "body": {
531 "string": "{\"result\":null,\"error_code\":null,\"error_info\":null}"
576 "string": "{\"result\":null,\"error_code\":null,\"error_info\":null}"
532 },
577 },
533 "headers": {
578 "headers": {
579 "expires": [
580 "Sat, 01 Jan 2000 00:00:00 GMT"
581 ],
534 "x-xss-protection": [
582 "x-xss-protection": [
535 "1; mode=block"
583 "1; mode=block"
536 ],
584 ],
537 "expires": [
585 "transfer-encoding": [
538 "Sat, 01 Jan 2000 00:00:00 GMT"
586 "chunked"
539 ],
587 ],
540 "set-cookie": [
588 "date": [
541 "phsid=A%2Fped6v7jlldydnkfolkdmecyyjrkciqhkr7opvbt2; expires=Thu, 14-Sep-2023 04:47:44 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
589 "Sun, 03 Mar 2019 00:12:29 GMT"
542 ],
590 ],
543 "x-frame-options": [
591 "x-frame-options": [
544 "Deny"
592 "Deny"
545 ],
593 ],
594 "cache-control": [
595 "no-store"
596 ],
597 "content-type": [
598 "application/json"
599 ],
546 "x-content-type-options": [
600 "x-content-type-options": [
547 "nosniff"
601 "nosniff"
548 ],
602 ],
549 "strict-transport-security": [
550 "max-age=0; includeSubdomains; preload"
551 ],
552 "server": [
603 "server": [
553 "Apache/2.4.10 (Debian)"
604 "Apache/2.4.10 (Debian)"
554 ],
605 ],
555 "date": [
606 "set-cookie": [
556 "Sat, 15 Sep 2018 04:47:44 GMT"
607 "phsid=A%2Foeyncgzaanzmnhgfc7ecvmu5pq7qju7ewq6tvgrp; expires=Fri, 01-Mar-2024 00:12:29 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
557 ],
608 ],
558 "content-type": [
609 "strict-transport-security": [
559 "application/json"
610 "max-age=0; includeSubdomains; preload"
560 ],
561 "cache-control": [
562 "no-store"
563 ]
564 }
565 },
566 "request": {
567 "method": "POST",
568 "uri": "https://phab.mercurial-scm.org//api/differential.setdiffproperty",
569 "body": "data=%7B%22d8f232f7d799e1064d3da179df41a2b5d04334e9%22%3A+%7B%22time%22%3A+0.0%2C+%22author%22%3A+%22test%22%2C+%22authorEmail%22%3A+%22test%22%7D%7D&name=local%3Acommits&diff_id=11072&api.token=cli-hahayouwish",
570 "headers": {
571 "accept": [
572 "application/mercurial-0.1"
573 ],
574 "content-type": [
575 "application/x-www-form-urlencoded"
576 ],
577 "host": [
578 "phab.mercurial-scm.org"
579 ],
580 "content-length": [
581 "227"
582 ],
583 "user-agent": [
584 "mercurial/proto-1.0 (Mercurial 4.7.1+866-5f07496726a1+20180915)"
585 ]
611 ]
586 }
612 }
587 }
613 }
588 }
614 }
589 ]
615 ],
616 "version": 1
590 }
617 }
This diff has been collapsed as it changes many lines, (1432 lines changed) Show them Hide them
@@ -1,915 +1,1025 b''
1 {
1 {
2 "version": 1,
3 "interactions": [
2 "interactions": [
4 {
3 {
5 "request": {
4 "request": {
6 "body": "api.token=cli-hahayouwish&revisionIDs%5B0%5D=4596",
5 "method": "POST",
7 "uri": "https://phab.mercurial-scm.org//api/differential.querydiffs",
6 "body": "api.token=cli-hahayouwish&revisionIDs%5B0%5D=6054",
7 "uri": "https://phab.mercurial-scm.org//api/differential.querydiffs",
8 "headers": {
8 "headers": {
9 "content-length": [
10 "66"
11 ],
12 "host": [
13 "phab.mercurial-scm.org"
14 ],
15 "content-type": [
9 "content-type": [
16 "application/x-www-form-urlencoded"
10 "application/x-www-form-urlencoded"
17 ],
11 ],
18 "accept": [
12 "accept": [
19 "application/mercurial-0.1"
13 "application/mercurial-0.1"
20 ],
14 ],
21 "user-agent": [
15 "user-agent": [
22 "mercurial/proto-1.0 (Mercurial 4.7.1+867-34bcd3af7109+20180915)"
16 "mercurial/proto-1.0 (Mercurial 4.9+477-7c86ec0ca5c5+20190303)"
17 ],
18 "host": [
19 "phab.mercurial-scm.org"
20 ],
21 "content-length": [
22 "66"
23 ]
23 ]
24 },
24 }
25 "method": "POST"
25 },
26 },
27 "response": {
26 "response": {
28 "status": {
27 "status": {
29 "code": 200,
28 "code": 200,
30 "message": "OK"
29 "message": "OK"
31 },
30 },
32 "headers": {
33 "server": [
34 "Apache/2.4.10 (Debian)"
35 ],
36 "strict-transport-security": [
37 "max-age=0; includeSubdomains; preload"
38 ],
39 "x-frame-options": [
40 "Deny"
41 ],
42 "x-content-type-options": [
43 "nosniff"
44 ],
45 "expires": [
46 "Sat, 01 Jan 2000 00:00:00 GMT"
47 ],
48 "set-cookie": [
49 "phsid=A%2F5bjqjyefdbiq65cc3qepzxq7ncczgfqo2xxsybaf; expires=Thu, 14-Sep-2023 04:53:46 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
50 ],
51 "x-xss-protection": [
52 "1; mode=block"
53 ],
54 "content-type": [
55 "application/json"
56 ],
57 "cache-control": [
58 "no-store"
59 ],
60 "date": [
61 "Sat, 15 Sep 2018 04:53:46 GMT"
62 ]
63 },
64 "body": {
31 "body": {
65 "string": "{\"result\":{\"11073\":{\"id\":\"11073\",\"revisionID\":\"4596\",\"dateCreated\":\"1536986866\",\"dateModified\":\"1536986868\",\"sourceControlBaseRevision\":null,\"sourceControlPath\":null,\"sourceControlSystem\":null,\"branch\":null,\"bookmark\":null,\"creationMethod\":\"web\",\"description\":null,\"unitStatus\":\"4\",\"lintStatus\":\"4\",\"changes\":[{\"id\":\"24417\",\"metadata\":{\"line:first\":1},\"oldPath\":null,\"currentPath\":\"alpha\",\"awayPaths\":[],\"oldProperties\":[],\"newProperties\":{\"unix:filemode\":\"100644\"},\"type\":\"1\",\"fileType\":\"1\",\"commitHash\":null,\"addLines\":\"2\",\"delLines\":\"0\",\"hunks\":[{\"oldOffset\":\"0\",\"newOffset\":\"1\",\"oldLength\":\"0\",\"newLength\":\"2\",\"addLines\":null,\"delLines\":null,\"isMissingOldNewline\":null,\"isMissingNewNewline\":null,\"corpus\":\"+alpha\\n+more\\n\"}]}],\"properties\":{\"hg:meta\":{\"parent\":\"0000000000000000000000000000000000000000\",\"node\":\"f70265671c65ab4b5416e611a6bd61887c013122\",\"user\":\"test\",\"date\":\"0 0\"},\"local:commits\":{\"f70265671c65ab4b5416e611a6bd61887c013122\":{\"time\":0,\"authorEmail\":\"test\",\"author\":\"test\"}}},\"authorName\":\"test\",\"authorEmail\":\"test\"},\"11072\":{\"id\":\"11072\",\"revisionID\":\"4596\",\"dateCreated\":\"1536986860\",\"dateModified\":\"1536986862\",\"sourceControlBaseRevision\":null,\"sourceControlPath\":null,\"sourceControlSystem\":null,\"branch\":null,\"bookmark\":null,\"creationMethod\":\"web\",\"description\":null,\"unitStatus\":\"4\",\"lintStatus\":\"4\",\"changes\":[{\"id\":\"24416\",\"metadata\":{\"line:first\":1},\"oldPath\":null,\"currentPath\":\"alpha\",\"awayPaths\":[],\"oldProperties\":[],\"newProperties\":{\"unix:filemode\":\"100644\"},\"type\":\"1\",\"fileType\":\"1\",\"commitHash\":null,\"addLines\":\"1\",\"delLines\":\"0\",\"hunks\":[{\"oldOffset\":\"0\",\"newOffset\":\"1\",\"oldLength\":\"0\",\"newLength\":\"1\",\"addLines\":null,\"delLines\":null,\"isMissingOldNewline\":null,\"isMissingNewNewline\":null,\"corpus\":\"+alpha\\n\"}]}],\"properties\":{\"hg:meta\":{\"date\":\"0 0\",\"node\":\"d8f232f7d799e1064d3da179df41a2b5d04334e9\",\"user\":\"test\",\"parent\":\"0000000000000000000000000000000000000000\"},\"local:commits\":{\"d8f232f7d799e1064d3da179df41a2b5d04334e9\":{\"time\":0,\"author\":\"test\",\"authorEmail\":\"test\"}}},\"authorName\":\"test\",\"authorEmail\":\"test\"}},\"error_code\":null,\"error_info\":null}"
32 "string": "{\"result\":{\"14303\":{\"id\":\"14303\",\"revisionID\":\"6054\",\"dateCreated\":\"1551571944\",\"dateModified\":\"1551571947\",\"sourceControlBaseRevision\":null,\"sourceControlPath\":null,\"sourceControlSystem\":null,\"branch\":null,\"bookmark\":null,\"creationMethod\":\"web\",\"description\":null,\"unitStatus\":\"4\",\"lintStatus\":\"4\",\"changes\":[{\"id\":\"32287\",\"metadata\":{\"line:first\":1},\"oldPath\":null,\"currentPath\":\"alpha\",\"awayPaths\":[],\"oldProperties\":[],\"newProperties\":{\"unix:filemode\":\"100644\"},\"type\":\"1\",\"fileType\":\"1\",\"commitHash\":null,\"addLines\":\"1\",\"delLines\":\"0\",\"hunks\":[{\"oldOffset\":\"0\",\"newOffset\":\"1\",\"oldLength\":\"0\",\"newLength\":\"1\",\"addLines\":null,\"delLines\":null,\"isMissingOldNewline\":null,\"isMissingNewNewline\":null,\"corpus\":\"+alpha\\n\"}]}],\"properties\":{\"hg:meta\":{\"user\":\"test\",\"parent\":\"0000000000000000000000000000000000000000\",\"node\":\"cb03845d6dd98c72bec766c7ed08c693cc49817a\",\"date\":\"0 0\"},\"local:commits\":{\"cb03845d6dd98c72bec766c7ed08c693cc49817a\":{\"author\":\"test\",\"authorEmail\":\"test\",\"time\":0}}},\"authorName\":\"test\",\"authorEmail\":\"test\"}},\"error_code\":null,\"error_info\":null}"
66 }
33 },
67 }
68 },
69 {
70 "request": {
71 "body": "diff_id=11073&api.token=cli-hahayouwish&data=%7B%22parent%22%3A+%220000000000000000000000000000000000000000%22%2C+%22node%22%3A+%22f70265671c65ab4b5416e611a6bd61887c013122%22%2C+%22user%22%3A+%22test%22%2C+%22date%22%3A+%220+0%22%7D&name=hg%3Ameta",
72 "uri": "https://phab.mercurial-scm.org//api/differential.setdiffproperty",
73 "headers": {
34 "headers": {
74 "content-length": [
75 "264"
76 ],
77 "host": [
78 "phab.mercurial-scm.org"
79 ],
80 "content-type": [
81 "application/x-www-form-urlencoded"
82 ],
83 "accept": [
84 "application/mercurial-0.1"
85 ],
86 "user-agent": [
87 "mercurial/proto-1.0 (Mercurial 4.7.1+867-34bcd3af7109+20180915)"
88 ]
89 },
90 "method": "POST"
91 },
92 "response": {
93 "status": {
94 "code": 200,
95 "message": "OK"
96 },
97 "headers": {
98 "server": [
99 "Apache/2.4.10 (Debian)"
100 ],
101 "strict-transport-security": [
102 "max-age=0; includeSubdomains; preload"
103 ],
104 "x-frame-options": [
105 "Deny"
106 ],
107 "x-content-type-options": [
108 "nosniff"
109 ],
110 "expires": [
35 "expires": [
111 "Sat, 01 Jan 2000 00:00:00 GMT"
36 "Sat, 01 Jan 2000 00:00:00 GMT"
112 ],
37 ],
113 "set-cookie": [
114 "phsid=A%2Ff6o4ingm2wmr3ma4aht2kytfrrxvrkitj6ipkf5k; expires=Thu, 14-Sep-2023 04:53:46 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
115 ],
116 "x-xss-protection": [
38 "x-xss-protection": [
117 "1; mode=block"
39 "1; mode=block"
118 ],
40 ],
119 "content-type": [
41 "transfer-encoding": [
120 "application/json"
42 "chunked"
121 ],
43 ],
44 "date": [
45 "Sun, 03 Mar 2019 00:12:30 GMT"
46 ],
47 "x-frame-options": [
48 "Deny"
49 ],
122 "cache-control": [
50 "cache-control": [
123 "no-store"
51 "no-store"
124 ],
52 ],
125 "date": [
126 "Sat, 15 Sep 2018 04:53:46 GMT"
127 ]
128 },
129 "body": {
130 "string": "{\"result\":null,\"error_code\":null,\"error_info\":null}"
131 }
132 }
133 },
134 {
135 "request": {
136 "body": "diff_id=11073&api.token=cli-hahayouwish&data=%7B%22f70265671c65ab4b5416e611a6bd61887c013122%22%3A+%7B%22time%22%3A+0.0%2C+%22authorEmail%22%3A+%22test%22%2C+%22author%22%3A+%22test%22%7D%7D&name=local%3Acommits",
137 "uri": "https://phab.mercurial-scm.org//api/differential.setdiffproperty",
138 "headers": {
139 "content-length": [
140 "227"
141 ],
142 "host": [
143 "phab.mercurial-scm.org"
144 ],
145 "content-type": [
53 "content-type": [
146 "application/x-www-form-urlencoded"
54 "application/json"
147 ],
55 ],
148 "accept": [
56 "x-content-type-options": [
149 "application/mercurial-0.1"
57 "nosniff"
150 ],
58 ],
151 "user-agent": [
152 "mercurial/proto-1.0 (Mercurial 4.7.1+867-34bcd3af7109+20180915)"
153 ]
154 },
155 "method": "POST"
156 },
157 "response": {
158 "status": {
159 "code": 200,
160 "message": "OK"
161 },
162 "headers": {
163 "server": [
59 "server": [
164 "Apache/2.4.10 (Debian)"
60 "Apache/2.4.10 (Debian)"
165 ],
61 ],
62 "set-cookie": [
63 "phsid=A%2Fnf3xdxgvvgky277foc7s2p6xrgtsvn4bzmayrbmb; expires=Fri, 01-Mar-2024 00:12:30 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
64 ],
166 "strict-transport-security": [
65 "strict-transport-security": [
167 "max-age=0; includeSubdomains; preload"
66 "max-age=0; includeSubdomains; preload"
168 ],
169 "x-frame-options": [
170 "Deny"
171 ],
172 "x-content-type-options": [
173 "nosniff"
174 ],
175 "expires": [
176 "Sat, 01 Jan 2000 00:00:00 GMT"
177 ],
178 "set-cookie": [
179 "phsid=A%2F4fitvy4kno46zkca6hq7npvuxvnh4dxlbvscmodb; expires=Thu, 14-Sep-2023 04:53:47 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
180 ],
181 "x-xss-protection": [
182 "1; mode=block"
183 ],
184 "content-type": [
185 "application/json"
186 ],
187 "cache-control": [
188 "no-store"
189 ],
190 "date": [
191 "Sat, 15 Sep 2018 04:53:47 GMT"
192 ]
67 ]
193 },
194 "body": {
195 "string": "{\"result\":null,\"error_code\":null,\"error_info\":null}"
196 }
68 }
197 }
69 }
198 },
70 },
199 {
71 {
200 "request": {
72 "request": {
201 "body": "api.token=cli-hahayouwish&corpus=create+alpha+for+phabricator+test%0A%0ADifferential+Revision%3A+https%3A%2F%2Fphab.mercurial-scm.org%2FD4596",
73 "method": "POST",
202 "uri": "https://phab.mercurial-scm.org//api/differential.parsecommitmessage",
74 "body": "constraints%5Bcallsigns%5D%5B0%5D=HG&api.token=cli-hahayouwish",
75 "uri": "https://phab.mercurial-scm.org//api/diffusion.repository.search",
203 "headers": {
76 "headers": {
204 "content-length": [
205 "158"
206 ],
207 "host": [
208 "phab.mercurial-scm.org"
209 ],
210 "content-type": [
77 "content-type": [
211 "application/x-www-form-urlencoded"
78 "application/x-www-form-urlencoded"
212 ],
79 ],
213 "accept": [
80 "accept": [
214 "application/mercurial-0.1"
81 "application/mercurial-0.1"
215 ],
82 ],
216 "user-agent": [
83 "user-agent": [
217 "mercurial/proto-1.0 (Mercurial 4.7.1+867-34bcd3af7109+20180915)"
84 "mercurial/proto-1.0 (Mercurial 4.9+477-7c86ec0ca5c5+20190303)"
85 ],
86 "host": [
87 "phab.mercurial-scm.org"
88 ],
89 "content-length": [
90 "79"
218 ]
91 ]
219 },
92 }
220 "method": "POST"
93 },
221 },
222 "response": {
94 "response": {
223 "status": {
95 "status": {
224 "code": 200,
96 "code": 200,
225 "message": "OK"
97 "message": "OK"
226 },
98 },
99 "body": {
100 "string": "{\"result\":{\"data\":[{\"id\":2,\"type\":\"REPO\",\"phid\":\"PHID-REPO-bvunnehri4u2isyr7bc3\",\"fields\":{\"name\":\"Mercurial\",\"vcs\":\"hg\",\"callsign\":\"HG\",\"shortName\":null,\"status\":\"active\",\"isImporting\":false,\"spacePHID\":null,\"dateCreated\":1498761653,\"dateModified\":1500403184,\"policy\":{\"view\":\"public\",\"edit\":\"admin\",\"diffusion.push\":\"users\"}},\"attachments\":{}}],\"maps\":{},\"query\":{\"queryKey\":null},\"cursor\":{\"limit\":100,\"after\":null,\"before\":null,\"order\":null}},\"error_code\":null,\"error_info\":null}"
101 },
102 "headers": {
103 "expires": [
104 "Sat, 01 Jan 2000 00:00:00 GMT"
105 ],
106 "x-xss-protection": [
107 "1; mode=block"
108 ],
109 "transfer-encoding": [
110 "chunked"
111 ],
112 "date": [
113 "Sun, 03 Mar 2019 00:12:31 GMT"
114 ],
115 "x-frame-options": [
116 "Deny"
117 ],
118 "cache-control": [
119 "no-store"
120 ],
121 "content-type": [
122 "application/json"
123 ],
124 "x-content-type-options": [
125 "nosniff"
126 ],
127 "server": [
128 "Apache/2.4.10 (Debian)"
129 ],
130 "set-cookie": [
131 "phsid=A%2Fmlq7cl6pakmia2uecfcevwhdl3hyqe6rdb2y7usm; expires=Fri, 01-Mar-2024 00:12:31 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
132 ],
133 "strict-transport-security": [
134 "max-age=0; includeSubdomains; preload"
135 ]
136 }
137 }
138 },
139 {
140 "request": {
141 "method": "POST",
142 "body": "repositoryPHID=PHID-REPO-bvunnehri4u2isyr7bc3&api.token=cli-hahayouwish&diff=diff+--git+a%2Falpha+b%2Falpha%0Anew+file+mode+100644%0A---+%2Fdev%2Fnull%0A%2B%2B%2B+b%2Falpha%0A%40%40+-0%2C0+%2B1%2C2+%40%40%0A%2Balpha%0A%2Bmore%0A",
143 "uri": "https://phab.mercurial-scm.org//api/differential.createrawdiff",
227 "headers": {
144 "headers": {
145 "content-type": [
146 "application/x-www-form-urlencoded"
147 ],
148 "accept": [
149 "application/mercurial-0.1"
150 ],
151 "user-agent": [
152 "mercurial/proto-1.0 (Mercurial 4.9+477-7c86ec0ca5c5+20190303)"
153 ],
154 "host": [
155 "phab.mercurial-scm.org"
156 ],
157 "content-length": [
158 "245"
159 ]
160 }
161 },
162 "response": {
163 "status": {
164 "code": 200,
165 "message": "OK"
166 },
167 "body": {
168 "string": "{\"result\":{\"id\":14304,\"phid\":\"PHID-DIFF-3wv2fwmzp27uamb66xxg\",\"uri\":\"https:\\/\\/phab.mercurial-scm.org\\/differential\\/diff\\/14304\\/\"},\"error_code\":null,\"error_info\":null}"
169 },
170 "headers": {
171 "expires": [
172 "Sat, 01 Jan 2000 00:00:00 GMT"
173 ],
174 "x-xss-protection": [
175 "1; mode=block"
176 ],
177 "transfer-encoding": [
178 "chunked"
179 ],
180 "date": [
181 "Sun, 03 Mar 2019 00:12:32 GMT"
182 ],
183 "x-frame-options": [
184 "Deny"
185 ],
186 "cache-control": [
187 "no-store"
188 ],
189 "content-type": [
190 "application/json"
191 ],
192 "x-content-type-options": [
193 "nosniff"
194 ],
228 "server": [
195 "server": [
229 "Apache/2.4.10 (Debian)"
196 "Apache/2.4.10 (Debian)"
230 ],
197 ],
198 "set-cookie": [
199 "phsid=A%2Fptjtujvqlcwhzs4yhneogb323aqessc5axlu4rif; expires=Fri, 01-Mar-2024 00:12:32 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
200 ],
231 "strict-transport-security": [
201 "strict-transport-security": [
232 "max-age=0; includeSubdomains; preload"
202 "max-age=0; includeSubdomains; preload"
233 ],
234 "x-frame-options": [
235 "Deny"
236 ],
237 "x-content-type-options": [
238 "nosniff"
239 ],
240 "expires": [
241 "Sat, 01 Jan 2000 00:00:00 GMT"
242 ],
243 "set-cookie": [
244 "phsid=A%2F7u2j7nsrtq2dtxqws7pnsnjyaufsamwj44e45euz; expires=Thu, 14-Sep-2023 04:53:47 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
245 ],
246 "x-xss-protection": [
247 "1; mode=block"
248 ],
249 "content-type": [
250 "application/json"
251 ],
252 "cache-control": [
253 "no-store"
254 ],
255 "date": [
256 "Sat, 15 Sep 2018 04:53:47 GMT"
257 ]
203 ]
258 },
259 "body": {
260 "string": "{\"result\":{\"errors\":[],\"fields\":{\"title\":\"create alpha for phabricator test\",\"revisionID\":4596},\"revisionIDFieldInfo\":{\"value\":4596,\"validDomain\":\"https:\\/\\/phab.mercurial-scm.org\"}},\"error_code\":null,\"error_info\":null}"
261 }
204 }
262 }
205 }
263 },
206 },
264 {
207 {
265 "request": {
208 "request": {
266 "body": "api.token=cli-hahayouwish&objectIdentifier=4596&transactions%5B0%5D%5Btype%5D=title&transactions%5B0%5D%5Bvalue%5D=create+alpha+for+phabricator+test",
209 "method": "POST",
267 "uri": "https://phab.mercurial-scm.org//api/differential.revision.edit",
210 "body": "diff_id=14304&data=%7B%22user%22%3A+%22test%22%2C+%22parent%22%3A+%220000000000000000000000000000000000000000%22%2C+%22node%22%3A+%22939d862f03181a366fea64a540baf0bb33f85d92%22%2C+%22date%22%3A+%220+0%22%7D&api.token=cli-hahayouwish&name=hg%3Ameta",
211 "uri": "https://phab.mercurial-scm.org//api/differential.setdiffproperty",
268 "headers": {
212 "headers": {
269 "content-length": [
270 "165"
271 ],
272 "host": [
273 "phab.mercurial-scm.org"
274 ],
275 "content-type": [
213 "content-type": [
276 "application/x-www-form-urlencoded"
214 "application/x-www-form-urlencoded"
277 ],
215 ],
278 "accept": [
216 "accept": [
279 "application/mercurial-0.1"
217 "application/mercurial-0.1"
280 ],
218 ],
281 "user-agent": [
219 "user-agent": [
282 "mercurial/proto-1.0 (Mercurial 4.7.1+867-34bcd3af7109+20180915)"
220 "mercurial/proto-1.0 (Mercurial 4.9+477-7c86ec0ca5c5+20190303)"
221 ],
222 "host": [
223 "phab.mercurial-scm.org"
224 ],
225 "content-length": [
226 "264"
283 ]
227 ]
284 },
228 }
285 "method": "POST"
229 },
286 },
287 "response": {
230 "response": {
288 "status": {
231 "status": {
289 "code": 200,
232 "code": 200,
290 "message": "OK"
233 "message": "OK"
291 },
234 },
235 "body": {
236 "string": "{\"result\":null,\"error_code\":null,\"error_info\":null}"
237 },
292 "headers": {
238 "headers": {
293 "server": [
294 "Apache/2.4.10 (Debian)"
295 ],
296 "strict-transport-security": [
297 "max-age=0; includeSubdomains; preload"
298 ],
299 "x-frame-options": [
300 "Deny"
301 ],
302 "x-content-type-options": [
303 "nosniff"
304 ],
305 "expires": [
239 "expires": [
306 "Sat, 01 Jan 2000 00:00:00 GMT"
240 "Sat, 01 Jan 2000 00:00:00 GMT"
307 ],
241 ],
308 "set-cookie": [
309 "phsid=A%2F7ubtculubfazivfxjxbmnyt3wzjcgdxnfdn57t42; expires=Thu, 14-Sep-2023 04:53:48 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
310 ],
311 "x-xss-protection": [
242 "x-xss-protection": [
312 "1; mode=block"
243 "1; mode=block"
313 ],
244 ],
314 "content-type": [
245 "transfer-encoding": [
315 "application/json"
246 "chunked"
316 ],
247 ],
248 "date": [
249 "Sun, 03 Mar 2019 00:12:32 GMT"
250 ],
251 "x-frame-options": [
252 "Deny"
253 ],
317 "cache-control": [
254 "cache-control": [
318 "no-store"
255 "no-store"
319 ],
256 ],
320 "date": [
257 "content-type": [
321 "Sat, 15 Sep 2018 04:53:47 GMT"
258 "application/json"
259 ],
260 "x-content-type-options": [
261 "nosniff"
262 ],
263 "server": [
264 "Apache/2.4.10 (Debian)"
265 ],
266 "set-cookie": [
267 "phsid=A%2Feho2462w6mulsjeoz3e4rwgf37aekqwgpqmarn2f; expires=Fri, 01-Mar-2024 00:12:32 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
268 ],
269 "strict-transport-security": [
270 "max-age=0; includeSubdomains; preload"
322 ]
271 ]
323 },
324 "body": {
325 "string": "{\"result\":{\"object\":{\"id\":\"4596\",\"phid\":\"PHID-DREV-bntcdwe74cw3vwkzt6nq\"},\"transactions\":[]},\"error_code\":null,\"error_info\":null}"
326 }
272 }
327 }
273 }
328 },
274 },
329 {
275 {
330 "request": {
276 "request": {
331 "body": "api.token=cli-hahayouwish&constraints%5Bcallsigns%5D%5B0%5D=HG",
277 "method": "POST",
332 "uri": "https://phab.mercurial-scm.org//api/diffusion.repository.search",
278 "body": "diff_id=14304&data=%7B%22939d862f03181a366fea64a540baf0bb33f85d92%22%3A+%7B%22author%22%3A+%22test%22%2C+%22authorEmail%22%3A+%22test%22%2C+%22time%22%3A+0.0%7D%7D&api.token=cli-hahayouwish&name=local%3Acommits",
279 "uri": "https://phab.mercurial-scm.org//api/differential.setdiffproperty",
333 "headers": {
280 "headers": {
334 "content-length": [
335 "79"
336 ],
337 "host": [
338 "phab.mercurial-scm.org"
339 ],
340 "content-type": [
281 "content-type": [
341 "application/x-www-form-urlencoded"
282 "application/x-www-form-urlencoded"
342 ],
283 ],
343 "accept": [
284 "accept": [
344 "application/mercurial-0.1"
285 "application/mercurial-0.1"
345 ],
286 ],
346 "user-agent": [
287 "user-agent": [
347 "mercurial/proto-1.0 (Mercurial 4.7.1+867-34bcd3af7109+20180915)"
288 "mercurial/proto-1.0 (Mercurial 4.9+477-7c86ec0ca5c5+20190303)"
289 ],
290 "host": [
291 "phab.mercurial-scm.org"
292 ],
293 "content-length": [
294 "227"
348 ]
295 ]
349 },
296 }
350 "method": "POST"
297 },
351 },
352 "response": {
298 "response": {
353 "status": {
299 "status": {
354 "code": 200,
300 "code": 200,
355 "message": "OK"
301 "message": "OK"
356 },
302 },
303 "body": {
304 "string": "{\"result\":null,\"error_code\":null,\"error_info\":null}"
305 },
357 "headers": {
306 "headers": {
358 "server": [
307 "expires": [
359 "Apache/2.4.10 (Debian)"
308 "Sat, 01 Jan 2000 00:00:00 GMT"
360 ],
309 ],
361 "strict-transport-security": [
310 "x-xss-protection": [
362 "max-age=0; includeSubdomains; preload"
311 "1; mode=block"
363 ],
312 ],
313 "transfer-encoding": [
314 "chunked"
315 ],
316 "date": [
317 "Sun, 03 Mar 2019 00:12:33 GMT"
318 ],
364 "x-frame-options": [
319 "x-frame-options": [
365 "Deny"
320 "Deny"
366 ],
321 ],
322 "cache-control": [
323 "no-store"
324 ],
325 "content-type": [
326 "application/json"
327 ],
367 "x-content-type-options": [
328 "x-content-type-options": [
368 "nosniff"
329 "nosniff"
369 ],
330 ],
370 "expires": [
331 "server": [
371 "Sat, 01 Jan 2000 00:00:00 GMT"
332 "Apache/2.4.10 (Debian)"
372 ],
333 ],
373 "set-cookie": [
334 "set-cookie": [
374 "phsid=A%2Fdpvy3rwephm5krs7posuadvjmkh7o7wbytgdhisv; expires=Thu, 14-Sep-2023 04:53:48 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
335 "phsid=A%2F4ca3h5qhtwgn55t3zznczixyt2st4tm44t23aceg; expires=Fri, 01-Mar-2024 00:12:33 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
375 ],
336 ],
376 "x-xss-protection": [
337 "strict-transport-security": [
377 "1; mode=block"
338 "max-age=0; includeSubdomains; preload"
378 ],
379 "content-type": [
380 "application/json"
381 ],
382 "cache-control": [
383 "no-store"
384 ],
385 "date": [
386 "Sat, 15 Sep 2018 04:53:48 GMT"
387 ]
339 ]
388 },
389 "body": {
390 "string": "{\"result\":{\"data\":[{\"id\":2,\"type\":\"REPO\",\"phid\":\"PHID-REPO-bvunnehri4u2isyr7bc3\",\"fields\":{\"name\":\"Mercurial\",\"vcs\":\"hg\",\"callsign\":\"HG\",\"shortName\":null,\"status\":\"active\",\"isImporting\":false,\"spacePHID\":null,\"dateCreated\":1498761653,\"dateModified\":1500403184,\"policy\":{\"view\":\"public\",\"edit\":\"admin\",\"diffusion.push\":\"users\"}},\"attachments\":{}}],\"maps\":{},\"query\":{\"queryKey\":null},\"cursor\":{\"limit\":100,\"after\":null,\"before\":null,\"order\":null}},\"error_code\":null,\"error_info\":null}"
391 }
340 }
392 }
341 }
393 },
342 },
394 {
343 {
395 "request": {
344 "request": {
396 "body": "api.token=cli-hahayouwish&diff=diff+--git+a%2Fbeta+b%2Fbeta%0Anew+file+mode+100644%0A---+%2Fdev%2Fnull%0A%2B%2B%2B+b%2Fbeta%0A%40%40+-0%2C0+%2B1%2C1+%40%40%0A%2Bbeta%0A&repositoryPHID=PHID-REPO-bvunnehri4u2isyr7bc3",
345 "method": "POST",
397 "uri": "https://phab.mercurial-scm.org//api/differential.createrawdiff",
346 "body": "api.token=cli-hahayouwish&corpus=create+alpha+for+phabricator+test+%E2%82%AC%0A%0ADifferential+Revision%3A+https%3A%2F%2Fphab.mercurial-scm.org%2FD6054",
347 "uri": "https://phab.mercurial-scm.org//api/differential.parsecommitmessage",
398 "headers": {
348 "headers": {
399 "content-length": [
400 "231"
401 ],
402 "host": [
403 "phab.mercurial-scm.org"
404 ],
405 "content-type": [
349 "content-type": [
406 "application/x-www-form-urlencoded"
350 "application/x-www-form-urlencoded"
407 ],
351 ],
408 "accept": [
352 "accept": [
409 "application/mercurial-0.1"
353 "application/mercurial-0.1"
410 ],
354 ],
411 "user-agent": [
355 "user-agent": [
412 "mercurial/proto-1.0 (Mercurial 4.7.1+867-34bcd3af7109+20180915)"
356 "mercurial/proto-1.0 (Mercurial 4.9+477-7c86ec0ca5c5+20190303)"
357 ],
358 "host": [
359 "phab.mercurial-scm.org"
360 ],
361 "content-length": [
362 "168"
413 ]
363 ]
414 },
364 }
415 "method": "POST"
365 },
416 },
417 "response": {
366 "response": {
418 "status": {
367 "status": {
419 "code": 200,
368 "code": 200,
420 "message": "OK"
369 "message": "OK"
421 },
370 },
371 "body": {
372 "string": "{\"result\":{\"errors\":[],\"fields\":{\"title\":\"create alpha for phabricator test \\u20ac\",\"revisionID\":6054},\"revisionIDFieldInfo\":{\"value\":6054,\"validDomain\":\"https:\\/\\/phab.mercurial-scm.org\"}},\"error_code\":null,\"error_info\":null}"
373 },
422 "headers": {
374 "headers": {
375 "expires": [
376 "Sat, 01 Jan 2000 00:00:00 GMT"
377 ],
378 "x-xss-protection": [
379 "1; mode=block"
380 ],
381 "transfer-encoding": [
382 "chunked"
383 ],
384 "date": [
385 "Sun, 03 Mar 2019 00:12:34 GMT"
386 ],
387 "x-frame-options": [
388 "Deny"
389 ],
390 "cache-control": [
391 "no-store"
392 ],
393 "content-type": [
394 "application/json"
395 ],
396 "x-content-type-options": [
397 "nosniff"
398 ],
423 "server": [
399 "server": [
424 "Apache/2.4.10 (Debian)"
400 "Apache/2.4.10 (Debian)"
425 ],
401 ],
402 "set-cookie": [
403 "phsid=A%2F7pvtbpw2waiblbsbydew3vfpulqnccf4647ymipq; expires=Fri, 01-Mar-2024 00:12:34 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
404 ],
426 "strict-transport-security": [
405 "strict-transport-security": [
427 "max-age=0; includeSubdomains; preload"
406 "max-age=0; includeSubdomains; preload"
428 ],
407 ]
429 "x-frame-options": [
408 }
430 "Deny"
409 }
431 ],
410 },
432 "x-content-type-options": [
411 {
433 "nosniff"
412 "request": {
434 ],
413 "method": "POST",
414 "body": "api.token=cli-hahayouwish&transactions%5B0%5D%5Btype%5D=update&transactions%5B0%5D%5Bvalue%5D=PHID-DIFF-3wv2fwmzp27uamb66xxg&transactions%5B1%5D%5Btype%5D=title&transactions%5B1%5D%5Bvalue%5D=create+alpha+for+phabricator+test+%E2%82%AC&objectIdentifier=6054",
415 "uri": "https://phab.mercurial-scm.org//api/differential.revision.edit",
416 "headers": {
417 "content-type": [
418 "application/x-www-form-urlencoded"
419 ],
420 "accept": [
421 "application/mercurial-0.1"
422 ],
423 "user-agent": [
424 "mercurial/proto-1.0 (Mercurial 4.9+477-7c86ec0ca5c5+20190303)"
425 ],
426 "host": [
427 "phab.mercurial-scm.org"
428 ],
429 "content-length": [
430 "274"
431 ]
432 }
433 },
434 "response": {
435 "status": {
436 "code": 200,
437 "message": "OK"
438 },
439 "body": {
440 "string": "{\"result\":{\"object\":{\"id\":\"6054\",\"phid\":\"PHID-DREV-6pczsbtdpqjc2nskmxwy\"},\"transactions\":[{\"phid\":\"PHID-XACT-DREV-mc2gfyoyhkfz7dy\"}]},\"error_code\":null,\"error_info\":null}"
441 },
442 "headers": {
435 "expires": [
443 "expires": [
436 "Sat, 01 Jan 2000 00:00:00 GMT"
444 "Sat, 01 Jan 2000 00:00:00 GMT"
437 ],
445 ],
438 "set-cookie": [
439 "phsid=A%2Fafqgsnm7vbqi3vyfg5c7xgxyiv7fgi77vauw6wnv; expires=Thu, 14-Sep-2023 04:53:49 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
440 ],
441 "x-xss-protection": [
446 "x-xss-protection": [
442 "1; mode=block"
447 "1; mode=block"
443 ],
448 ],
449 "transfer-encoding": [
450 "chunked"
451 ],
452 "date": [
453 "Sun, 03 Mar 2019 00:12:34 GMT"
454 ],
455 "x-frame-options": [
456 "Deny"
457 ],
458 "cache-control": [
459 "no-store"
460 ],
444 "content-type": [
461 "content-type": [
445 "application/json"
462 "application/json"
446 ],
463 ],
447 "cache-control": [
464 "x-content-type-options": [
448 "no-store"
465 "nosniff"
449 ],
466 ],
450 "date": [
467 "server": [
451 "Sat, 15 Sep 2018 04:53:49 GMT"
468 "Apache/2.4.10 (Debian)"
469 ],
470 "set-cookie": [
471 "phsid=A%2Fhmyuw3lg6h4joaswqnfcmnzdkp6p2qxotsvahb7l; expires=Fri, 01-Mar-2024 00:12:34 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
472 ],
473 "strict-transport-security": [
474 "max-age=0; includeSubdomains; preload"
452 ]
475 ]
453 },
454 "body": {
455 "string": "{\"result\":{\"id\":11074,\"phid\":\"PHID-DIFF-sitmath22fwgsfsbdmne\",\"uri\":\"https:\\/\\/phab.mercurial-scm.org\\/differential\\/diff\\/11074\\/\"},\"error_code\":null,\"error_info\":null}"
456 }
476 }
457 }
477 }
458 },
478 },
459 {
479 {
460 "request": {
480 "request": {
461 "body": "diff_id=11074&api.token=cli-hahayouwish&data=%7B%22parent%22%3A+%22f70265671c65ab4b5416e611a6bd61887c013122%22%2C+%22node%22%3A+%221a5640df7bbfc26fc4f6ef38e4d1581d5b2a3122%22%2C+%22user%22%3A+%22test%22%2C+%22date%22%3A+%220+0%22%7D&name=hg%3Ameta",
481 "method": "POST",
462 "uri": "https://phab.mercurial-scm.org//api/differential.setdiffproperty",
482 "body": "repositoryPHID=PHID-REPO-bvunnehri4u2isyr7bc3&api.token=cli-hahayouwish&diff=diff+--git+a%2Fbeta+b%2Fbeta%0Anew+file+mode+100644%0A---+%2Fdev%2Fnull%0A%2B%2B%2B+b%2Fbeta%0A%40%40+-0%2C0+%2B1%2C1+%40%40%0A%2Bbeta%0A",
483 "uri": "https://phab.mercurial-scm.org//api/differential.createrawdiff",
463 "headers": {
484 "headers": {
464 "content-length": [
485 "content-type": [
465 "264"
486 "application/x-www-form-urlencoded"
466 ],
487 ],
488 "accept": [
489 "application/mercurial-0.1"
490 ],
491 "user-agent": [
492 "mercurial/proto-1.0 (Mercurial 4.9+477-7c86ec0ca5c5+20190303)"
493 ],
467 "host": [
494 "host": [
468 "phab.mercurial-scm.org"
495 "phab.mercurial-scm.org"
469 ],
496 ],
470 "content-type": [
497 "content-length": [
471 "application/x-www-form-urlencoded"
498 "231"
472 ],
473 "accept": [
474 "application/mercurial-0.1"
475 ],
476 "user-agent": [
477 "mercurial/proto-1.0 (Mercurial 4.7.1+867-34bcd3af7109+20180915)"
478 ]
499 ]
479 },
500 }
480 "method": "POST"
501 },
481 },
482 "response": {
502 "response": {
483 "status": {
503 "status": {
484 "code": 200,
504 "code": 200,
485 "message": "OK"
505 "message": "OK"
486 },
506 },
507 "body": {
508 "string": "{\"result\":{\"id\":14305,\"phid\":\"PHID-DIFF-pofynzhmmqm2czm33teg\",\"uri\":\"https:\\/\\/phab.mercurial-scm.org\\/differential\\/diff\\/14305\\/\"},\"error_code\":null,\"error_info\":null}"
509 },
487 "headers": {
510 "headers": {
488 "server": [
511 "expires": [
489 "Apache/2.4.10 (Debian)"
512 "Sat, 01 Jan 2000 00:00:00 GMT"
490 ],
513 ],
491 "strict-transport-security": [
514 "x-xss-protection": [
492 "max-age=0; includeSubdomains; preload"
515 "1; mode=block"
493 ],
516 ],
517 "transfer-encoding": [
518 "chunked"
519 ],
520 "date": [
521 "Sun, 03 Mar 2019 00:12:35 GMT"
522 ],
494 "x-frame-options": [
523 "x-frame-options": [
495 "Deny"
524 "Deny"
496 ],
525 ],
497 "x-content-type-options": [
526 "cache-control": [
498 "nosniff"
527 "no-store"
499 ],
528 ],
500 "expires": [
501 "Sat, 01 Jan 2000 00:00:00 GMT"
502 ],
503 "set-cookie": [
504 "phsid=A%2Frvpld6nyjmtrq3qynmldbquhgwbrhcdhythbot6r; expires=Thu, 14-Sep-2023 04:53:49 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
505 ],
506 "x-xss-protection": [
507 "1; mode=block"
508 ],
509 "content-type": [
529 "content-type": [
510 "application/json"
530 "application/json"
511 ],
531 ],
512 "cache-control": [
532 "x-content-type-options": [
513 "no-store"
533 "nosniff"
514 ],
534 ],
515 "date": [
535 "server": [
516 "Sat, 15 Sep 2018 04:53:49 GMT"
536 "Apache/2.4.10 (Debian)"
537 ],
538 "set-cookie": [
539 "phsid=A%2F2xpzt6bryn7n3gug3ll7iu2gfqyy4zss5d7nolew; expires=Fri, 01-Mar-2024 00:12:35 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
540 ],
541 "strict-transport-security": [
542 "max-age=0; includeSubdomains; preload"
517 ]
543 ]
518 },
519 "body": {
520 "string": "{\"result\":null,\"error_code\":null,\"error_info\":null}"
521 }
544 }
522 }
545 }
523 },
546 },
524 {
547 {
525 "request": {
548 "request": {
526 "body": "diff_id=11074&api.token=cli-hahayouwish&data=%7B%221a5640df7bbfc26fc4f6ef38e4d1581d5b2a3122%22%3A+%7B%22time%22%3A+0.0%2C+%22authorEmail%22%3A+%22test%22%2C+%22author%22%3A+%22test%22%7D%7D&name=local%3Acommits",
549 "method": "POST",
527 "uri": "https://phab.mercurial-scm.org//api/differential.setdiffproperty",
550 "body": "diff_id=14305&data=%7B%22user%22%3A+%22test%22%2C+%22parent%22%3A+%22939d862f03181a366fea64a540baf0bb33f85d92%22%2C+%22node%22%3A+%22f55f947ed0f8ad80a04b7e87a0bf9febda2070b1%22%2C+%22date%22%3A+%220+0%22%7D&api.token=cli-hahayouwish&name=hg%3Ameta",
551 "uri": "https://phab.mercurial-scm.org//api/differential.setdiffproperty",
528 "headers": {
552 "headers": {
529 "content-length": [
530 "227"
531 ],
532 "host": [
533 "phab.mercurial-scm.org"
534 ],
535 "content-type": [
553 "content-type": [
536 "application/x-www-form-urlencoded"
554 "application/x-www-form-urlencoded"
537 ],
555 ],
538 "accept": [
556 "accept": [
539 "application/mercurial-0.1"
557 "application/mercurial-0.1"
540 ],
558 ],
541 "user-agent": [
559 "user-agent": [
542 "mercurial/proto-1.0 (Mercurial 4.7.1+867-34bcd3af7109+20180915)"
560 "mercurial/proto-1.0 (Mercurial 4.9+477-7c86ec0ca5c5+20190303)"
561 ],
562 "host": [
563 "phab.mercurial-scm.org"
564 ],
565 "content-length": [
566 "264"
543 ]
567 ]
544 },
568 }
545 "method": "POST"
569 },
546 },
547 "response": {
570 "response": {
548 "status": {
571 "status": {
549 "code": 200,
572 "code": 200,
550 "message": "OK"
573 "message": "OK"
551 },
574 },
575 "body": {
576 "string": "{\"result\":null,\"error_code\":null,\"error_info\":null}"
577 },
552 "headers": {
578 "headers": {
553 "server": [
554 "Apache/2.4.10 (Debian)"
555 ],
556 "strict-transport-security": [
557 "max-age=0; includeSubdomains; preload"
558 ],
559 "x-frame-options": [
560 "Deny"
561 ],
562 "x-content-type-options": [
563 "nosniff"
564 ],
565 "expires": [
579 "expires": [
566 "Sat, 01 Jan 2000 00:00:00 GMT"
580 "Sat, 01 Jan 2000 00:00:00 GMT"
567 ],
581 ],
568 "set-cookie": [
569 "phsid=A%2Flpkv333zitgztqx2clpg2uibjy633myliembguf2; expires=Thu, 14-Sep-2023 04:53:50 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
570 ],
571 "x-xss-protection": [
582 "x-xss-protection": [
572 "1; mode=block"
583 "1; mode=block"
573 ],
584 ],
574 "content-type": [
585 "transfer-encoding": [
575 "application/json"
586 "chunked"
576 ],
587 ],
588 "date": [
589 "Sun, 03 Mar 2019 00:12:36 GMT"
590 ],
591 "x-frame-options": [
592 "Deny"
593 ],
577 "cache-control": [
594 "cache-control": [
578 "no-store"
595 "no-store"
579 ],
596 ],
580 "date": [
581 "Sat, 15 Sep 2018 04:53:49 GMT"
582 ]
583 },
584 "body": {
585 "string": "{\"result\":null,\"error_code\":null,\"error_info\":null}"
586 }
587 }
588 },
589 {
590 "request": {
591 "body": "api.token=cli-hahayouwish&corpus=create+beta+for+phabricator+test",
592 "uri": "https://phab.mercurial-scm.org//api/differential.parsecommitmessage",
593 "headers": {
594 "content-length": [
595 "82"
596 ],
597 "host": [
598 "phab.mercurial-scm.org"
599 ],
600 "content-type": [
597 "content-type": [
601 "application/x-www-form-urlencoded"
598 "application/json"
602 ],
599 ],
603 "accept": [
600 "x-content-type-options": [
604 "application/mercurial-0.1"
601 "nosniff"
605 ],
602 ],
606 "user-agent": [
607 "mercurial/proto-1.0 (Mercurial 4.7.1+867-34bcd3af7109+20180915)"
608 ]
609 },
610 "method": "POST"
611 },
612 "response": {
613 "status": {
614 "code": 200,
615 "message": "OK"
616 },
617 "headers": {
618 "server": [
603 "server": [
619 "Apache/2.4.10 (Debian)"
604 "Apache/2.4.10 (Debian)"
620 ],
605 ],
606 "set-cookie": [
607 "phsid=A%2Fygzbpe74xh6shrejkd3tj32t4gaqnvumy63iudrd; expires=Fri, 01-Mar-2024 00:12:36 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
608 ],
621 "strict-transport-security": [
609 "strict-transport-security": [
622 "max-age=0; includeSubdomains; preload"
610 "max-age=0; includeSubdomains; preload"
623 ],
624 "x-frame-options": [
625 "Deny"
626 ],
627 "x-content-type-options": [
628 "nosniff"
629 ],
630 "expires": [
631 "Sat, 01 Jan 2000 00:00:00 GMT"
632 ],
633 "set-cookie": [
634 "phsid=A%2Fav6ovbqxoy3dijysouoabcz7jqescejugeedwspi; expires=Thu, 14-Sep-2023 04:53:50 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
635 ],
636 "x-xss-protection": [
637 "1; mode=block"
638 ],
639 "content-type": [
640 "application/json"
641 ],
642 "cache-control": [
643 "no-store"
644 ],
645 "date": [
646 "Sat, 15 Sep 2018 04:53:50 GMT"
647 ]
611 ]
648 },
649 "body": {
650 "string": "{\"result\":{\"errors\":[],\"fields\":{\"title\":\"create beta for phabricator test\"},\"revisionIDFieldInfo\":{\"value\":null,\"validDomain\":\"https:\\/\\/phab.mercurial-scm.org\"}},\"error_code\":null,\"error_info\":null}"
651 }
612 }
652 }
613 }
653 },
614 },
654 {
615 {
655 "request": {
616 "request": {
656 "body": "api.token=cli-hahayouwish&transactions%5B0%5D%5Btype%5D=update&transactions%5B0%5D%5Bvalue%5D=PHID-DIFF-sitmath22fwgsfsbdmne&transactions%5B1%5D%5Btype%5D=summary&transactions%5B1%5D%5Bvalue%5D=Depends+on+D4596&transactions%5B2%5D%5Btype%5D=summary&transactions%5B2%5D%5Bvalue%5D=+&transactions%5B3%5D%5Btype%5D=title&transactions%5B3%5D%5Bvalue%5D=create+beta+for+phabricator+test",
617 "method": "POST",
657 "uri": "https://phab.mercurial-scm.org//api/differential.revision.edit",
618 "body": "diff_id=14305&data=%7B%22f55f947ed0f8ad80a04b7e87a0bf9febda2070b1%22%3A+%7B%22author%22%3A+%22test%22%2C+%22authorEmail%22%3A+%22test%22%2C+%22time%22%3A+0.0%7D%7D&api.token=cli-hahayouwish&name=local%3Acommits",
619 "uri": "https://phab.mercurial-scm.org//api/differential.setdiffproperty",
658 "headers": {
620 "headers": {
659 "content-length": [
660 "398"
661 ],
662 "host": [
663 "phab.mercurial-scm.org"
664 ],
665 "content-type": [
621 "content-type": [
666 "application/x-www-form-urlencoded"
622 "application/x-www-form-urlencoded"
667 ],
623 ],
668 "accept": [
624 "accept": [
669 "application/mercurial-0.1"
625 "application/mercurial-0.1"
670 ],
626 ],
671 "user-agent": [
627 "user-agent": [
672 "mercurial/proto-1.0 (Mercurial 4.7.1+867-34bcd3af7109+20180915)"
628 "mercurial/proto-1.0 (Mercurial 4.9+477-7c86ec0ca5c5+20190303)"
629 ],
630 "host": [
631 "phab.mercurial-scm.org"
632 ],
633 "content-length": [
634 "227"
673 ]
635 ]
674 },
636 }
675 "method": "POST"
637 },
676 },
677 "response": {
638 "response": {
678 "status": {
639 "status": {
679 "code": 200,
640 "code": 200,
680 "message": "OK"
641 "message": "OK"
681 },
642 },
643 "body": {
644 "string": "{\"result\":null,\"error_code\":null,\"error_info\":null}"
645 },
646 "headers": {
647 "expires": [
648 "Sat, 01 Jan 2000 00:00:00 GMT"
649 ],
650 "x-xss-protection": [
651 "1; mode=block"
652 ],
653 "transfer-encoding": [
654 "chunked"
655 ],
656 "date": [
657 "Sun, 03 Mar 2019 00:12:37 GMT"
658 ],
659 "x-frame-options": [
660 "Deny"
661 ],
662 "cache-control": [
663 "no-store"
664 ],
665 "content-type": [
666 "application/json"
667 ],
668 "x-content-type-options": [
669 "nosniff"
670 ],
671 "server": [
672 "Apache/2.4.10 (Debian)"
673 ],
674 "set-cookie": [
675 "phsid=A%2Fgw67yfcsx7vvxkymeac52ca5is4jkxjwqqkhayco; expires=Fri, 01-Mar-2024 00:12:37 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
676 ],
677 "strict-transport-security": [
678 "max-age=0; includeSubdomains; preload"
679 ]
680 }
681 }
682 },
683 {
684 "request": {
685 "method": "POST",
686 "body": "api.token=cli-hahayouwish&corpus=create+beta+for+phabricator+test",
687 "uri": "https://phab.mercurial-scm.org//api/differential.parsecommitmessage",
682 "headers": {
688 "headers": {
689 "content-type": [
690 "application/x-www-form-urlencoded"
691 ],
692 "accept": [
693 "application/mercurial-0.1"
694 ],
695 "user-agent": [
696 "mercurial/proto-1.0 (Mercurial 4.9+477-7c86ec0ca5c5+20190303)"
697 ],
698 "host": [
699 "phab.mercurial-scm.org"
700 ],
701 "content-length": [
702 "82"
703 ]
704 }
705 },
706 "response": {
707 "status": {
708 "code": 200,
709 "message": "OK"
710 },
711 "body": {
712 "string": "{\"result\":{\"errors\":[],\"fields\":{\"title\":\"create beta for phabricator test\"},\"revisionIDFieldInfo\":{\"value\":null,\"validDomain\":\"https:\\/\\/phab.mercurial-scm.org\"}},\"error_code\":null,\"error_info\":null}"
713 },
714 "headers": {
715 "expires": [
716 "Sat, 01 Jan 2000 00:00:00 GMT"
717 ],
718 "x-xss-protection": [
719 "1; mode=block"
720 ],
721 "transfer-encoding": [
722 "chunked"
723 ],
724 "date": [
725 "Sun, 03 Mar 2019 00:12:37 GMT"
726 ],
727 "x-frame-options": [
728 "Deny"
729 ],
730 "cache-control": [
731 "no-store"
732 ],
733 "content-type": [
734 "application/json"
735 ],
736 "x-content-type-options": [
737 "nosniff"
738 ],
683 "server": [
739 "server": [
684 "Apache/2.4.10 (Debian)"
740 "Apache/2.4.10 (Debian)"
685 ],
741 ],
742 "set-cookie": [
743 "phsid=A%2Fyt5ejs6pgvjdxzms7geaxup63jpqkisngu3cprk6; expires=Fri, 01-Mar-2024 00:12:37 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
744 ],
686 "strict-transport-security": [
745 "strict-transport-security": [
687 "max-age=0; includeSubdomains; preload"
746 "max-age=0; includeSubdomains; preload"
688 ],
689 "x-frame-options": [
690 "Deny"
691 ],
692 "x-content-type-options": [
693 "nosniff"
694 ],
695 "expires": [
696 "Sat, 01 Jan 2000 00:00:00 GMT"
697 ],
698 "set-cookie": [
699 "phsid=A%2Fywrdtdafcn5p267qiqfgfh7h4buaqxmnrgan6fh2; expires=Thu, 14-Sep-2023 04:53:50 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
700 ],
701 "x-xss-protection": [
702 "1; mode=block"
703 ],
704 "content-type": [
705 "application/json"
706 ],
707 "cache-control": [
708 "no-store"
709 ],
710 "date": [
711 "Sat, 15 Sep 2018 04:53:50 GMT"
712 ]
747 ]
713 },
714 "body": {
715 "string": "{\"result\":{\"object\":{\"id\":4597,\"phid\":\"PHID-DREV-as7flhipq636gqvnyrsf\"},\"transactions\":[{\"phid\":\"PHID-XACT-DREV-bwzosyyqmzlhe6g\"},{\"phid\":\"PHID-XACT-DREV-ina5ktuwp6eiwv6\"},{\"phid\":\"PHID-XACT-DREV-22bjztn3szeyicy\"},{\"phid\":\"PHID-XACT-DREV-kcv6zk2yboepbmo\"},{\"phid\":\"PHID-XACT-DREV-mnbp6f6sq54hzs2\"},{\"phid\":\"PHID-XACT-DREV-qlakltzsdzclpha\"},{\"phid\":\"PHID-XACT-DREV-a5347cobhvqnc22\"},{\"phid\":\"PHID-XACT-DREV-sciqq5cqfuqfh67\"}]},\"error_code\":null,\"error_info\":null}"
716 }
748 }
717 }
749 }
718 },
750 },
719 {
751 {
720 "request": {
752 "request": {
721 "body": "api.token=cli-hahayouwish&ids%5B0%5D=4596&ids%5B1%5D=4597",
753 "method": "POST",
722 "uri": "https://phab.mercurial-scm.org//api/differential.query",
754 "body": "transactions%5B0%5D%5Btype%5D=update&transactions%5B0%5D%5Bvalue%5D=PHID-DIFF-pofynzhmmqm2czm33teg&transactions%5B1%5D%5Btype%5D=summary&transactions%5B1%5D%5Bvalue%5D=Depends+on+D6054&transactions%5B2%5D%5Btype%5D=summary&transactions%5B2%5D%5Bvalue%5D=+&transactions%5B3%5D%5Btype%5D=title&transactions%5B3%5D%5Bvalue%5D=create+beta+for+phabricator+test&api.token=cli-hahayouwish",
755 "uri": "https://phab.mercurial-scm.org//api/differential.revision.edit",
723 "headers": {
756 "headers": {
724 "content-length": [
725 "74"
726 ],
727 "host": [
728 "phab.mercurial-scm.org"
729 ],
730 "content-type": [
757 "content-type": [
731 "application/x-www-form-urlencoded"
758 "application/x-www-form-urlencoded"
732 ],
759 ],
733 "accept": [
760 "accept": [
734 "application/mercurial-0.1"
761 "application/mercurial-0.1"
735 ],
762 ],
736 "user-agent": [
763 "user-agent": [
737 "mercurial/proto-1.0 (Mercurial 4.7.1+867-34bcd3af7109+20180915)"
764 "mercurial/proto-1.0 (Mercurial 4.9+477-7c86ec0ca5c5+20190303)"
765 ],
766 "host": [
767 "phab.mercurial-scm.org"
768 ],
769 "content-length": [
770 "398"
738 ]
771 ]
739 },
772 }
740 "method": "POST"
773 },
741 },
742 "response": {
774 "response": {
743 "status": {
775 "status": {
744 "code": 200,
776 "code": 200,
745 "message": "OK"
777 "message": "OK"
746 },
778 },
779 "body": {
780 "string": "{\"result\":{\"object\":{\"id\":6055,\"phid\":\"PHID-DREV-k2hin2iytzuvu3j5icm3\"},\"transactions\":[{\"phid\":\"PHID-XACT-DREV-3xjvwemev7dqsj3\"},{\"phid\":\"PHID-XACT-DREV-giypqlavgemr56i\"},{\"phid\":\"PHID-XACT-DREV-tcfqd4aj6rxtxzz\"},{\"phid\":\"PHID-XACT-DREV-2timgnudaxeln7a\"},{\"phid\":\"PHID-XACT-DREV-vb6564lrsxpsw4l\"},{\"phid\":\"PHID-XACT-DREV-maym4xi2tdhysvo\"},{\"phid\":\"PHID-XACT-DREV-bna5heyckxkk5ke\"},{\"phid\":\"PHID-XACT-DREV-b2eig3stbdic7k7\"}]},\"error_code\":null,\"error_info\":null}"
781 },
747 "headers": {
782 "headers": {
748 "server": [
749 "Apache/2.4.10 (Debian)"
750 ],
751 "strict-transport-security": [
752 "max-age=0; includeSubdomains; preload"
753 ],
754 "x-frame-options": [
755 "Deny"
756 ],
757 "x-content-type-options": [
758 "nosniff"
759 ],
760 "expires": [
783 "expires": [
761 "Sat, 01 Jan 2000 00:00:00 GMT"
784 "Sat, 01 Jan 2000 00:00:00 GMT"
762 ],
785 ],
763 "set-cookie": [
764 "phsid=A%2F2iio6iugurtd7ml2tnwfwv24hkrfhs62yshvmouv; expires=Thu, 14-Sep-2023 04:53:51 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
765 ],
766 "x-xss-protection": [
786 "x-xss-protection": [
767 "1; mode=block"
787 "1; mode=block"
768 ],
788 ],
769 "content-type": [
789 "transfer-encoding": [
770 "application/json"
790 "chunked"
771 ],
791 ],
792 "date": [
793 "Sun, 03 Mar 2019 00:12:38 GMT"
794 ],
795 "x-frame-options": [
796 "Deny"
797 ],
772 "cache-control": [
798 "cache-control": [
773 "no-store"
799 "no-store"
774 ],
800 ],
775 "date": [
801 "content-type": [
776 "Sat, 15 Sep 2018 04:53:51 GMT"
802 "application/json"
803 ],
804 "x-content-type-options": [
805 "nosniff"
806 ],
807 "server": [
808 "Apache/2.4.10 (Debian)"
809 ],
810 "set-cookie": [
811 "phsid=A%2Fgqyrj3op7rar26t6crqlt6rpdsxcefnrofqkw5rt; expires=Fri, 01-Mar-2024 00:12:38 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
812 ],
813 "strict-transport-security": [
814 "max-age=0; includeSubdomains; preload"
777 ]
815 ]
778 },
779 "body": {
780 "string": "{\"result\":[{\"id\":\"4597\",\"phid\":\"PHID-DREV-as7flhipq636gqvnyrsf\",\"title\":\"create beta for phabricator test\",\"uri\":\"https:\\/\\/phab.mercurial-scm.org\\/D4597\",\"dateCreated\":\"1536987231\",\"dateModified\":\"1536987231\",\"authorPHID\":\"PHID-USER-cgcdlc6c3gpxapbmkwa2\",\"status\":\"0\",\"statusName\":\"Needs Review\",\"properties\":[],\"branch\":null,\"summary\":\" \",\"testPlan\":\"\",\"lineCount\":\"1\",\"activeDiffPHID\":\"PHID-DIFF-sitmath22fwgsfsbdmne\",\"diffs\":[\"11074\"],\"commits\":[],\"reviewers\":{\"PHID-PROJ-3dvcxzznrjru2xmmses3\":\"PHID-PROJ-3dvcxzznrjru2xmmses3\"},\"ccs\":[\"PHID-USER-q42dn7cc3donqriafhjx\"],\"hashes\":[],\"auxiliary\":{\"phabricator:projects\":[],\"phabricator:depends-on\":[\"PHID-DREV-bntcdwe74cw3vwkzt6nq\"]},\"repositoryPHID\":\"PHID-REPO-bvunnehri4u2isyr7bc3\",\"sourcePath\":null},{\"id\":\"4596\",\"phid\":\"PHID-DREV-bntcdwe74cw3vwkzt6nq\",\"title\":\"create alpha for phabricator test\",\"uri\":\"https:\\/\\/phab.mercurial-scm.org\\/D4596\",\"dateCreated\":\"1536986862\",\"dateModified\":\"1536987231\",\"authorPHID\":\"PHID-USER-cgcdlc6c3gpxapbmkwa2\",\"status\":\"0\",\"statusName\":\"Needs Review\",\"properties\":[],\"branch\":null,\"summary\":\"\",\"testPlan\":\"\",\"lineCount\":\"2\",\"activeDiffPHID\":\"PHID-DIFF-vwre7kpjdq52wbt56ftl\",\"diffs\":[\"11073\",\"11072\"],\"commits\":[],\"reviewers\":{\"PHID-PROJ-3dvcxzznrjru2xmmses3\":\"PHID-PROJ-3dvcxzznrjru2xmmses3\"},\"ccs\":[\"PHID-USER-q42dn7cc3donqriafhjx\"],\"hashes\":[],\"auxiliary\":{\"phabricator:projects\":[],\"phabricator:depends-on\":[]},\"repositoryPHID\":\"PHID-REPO-bvunnehri4u2isyr7bc3\",\"sourcePath\":null}],\"error_code\":null,\"error_info\":null}"
781 }
816 }
782 }
817 }
783 },
818 },
784 {
819 {
785 "request": {
820 "request": {
786 "body": "diff_id=11074&api.token=cli-hahayouwish&data=%7B%22parent%22%3A+%22f70265671c65ab4b5416e611a6bd61887c013122%22%2C+%22node%22%3A+%22c2b605ada280b38c38031b5d31622869c72b0d8d%22%2C+%22user%22%3A+%22test%22%2C+%22date%22%3A+%220+0%22%7D&name=hg%3Ameta",
821 "method": "POST",
787 "uri": "https://phab.mercurial-scm.org//api/differential.setdiffproperty",
822 "body": "api.token=cli-hahayouwish&ids%5B0%5D=6054&ids%5B1%5D=6055",
823 "uri": "https://phab.mercurial-scm.org//api/differential.query",
788 "headers": {
824 "headers": {
789 "content-length": [
790 "264"
791 ],
792 "host": [
793 "phab.mercurial-scm.org"
794 ],
795 "content-type": [
825 "content-type": [
796 "application/x-www-form-urlencoded"
826 "application/x-www-form-urlencoded"
797 ],
827 ],
798 "accept": [
828 "accept": [
799 "application/mercurial-0.1"
829 "application/mercurial-0.1"
800 ],
830 ],
801 "user-agent": [
831 "user-agent": [
802 "mercurial/proto-1.0 (Mercurial 4.7.1+867-34bcd3af7109+20180915)"
832 "mercurial/proto-1.0 (Mercurial 4.9+477-7c86ec0ca5c5+20190303)"
833 ],
834 "host": [
835 "phab.mercurial-scm.org"
836 ],
837 "content-length": [
838 "74"
803 ]
839 ]
804 },
840 }
805 "method": "POST"
841 },
806 },
807 "response": {
842 "response": {
808 "status": {
843 "status": {
809 "code": 200,
844 "code": 200,
810 "message": "OK"
845 "message": "OK"
811 },
846 },
847 "body": {
848 "string": "{\"result\":[{\"id\":\"6055\",\"phid\":\"PHID-DREV-k2hin2iytzuvu3j5icm3\",\"title\":\"create beta for phabricator test\",\"uri\":\"https:\\/\\/phab.mercurial-scm.org\\/D6055\",\"dateCreated\":\"1551571958\",\"dateModified\":\"1551571958\",\"authorPHID\":\"PHID-USER-5iy6mkoveguhm2zthvww\",\"status\":\"0\",\"statusName\":\"Needs Review\",\"properties\":[],\"branch\":null,\"summary\":\" \",\"testPlan\":\"\",\"lineCount\":\"1\",\"activeDiffPHID\":\"PHID-DIFF-pofynzhmmqm2czm33teg\",\"diffs\":[\"14305\"],\"commits\":[],\"reviewers\":{\"PHID-PROJ-3dvcxzznrjru2xmmses3\":\"PHID-PROJ-3dvcxzznrjru2xmmses3\"},\"ccs\":[\"PHID-USER-q42dn7cc3donqriafhjx\"],\"hashes\":[],\"auxiliary\":{\"phabricator:projects\":[],\"phabricator:depends-on\":[\"PHID-DREV-6pczsbtdpqjc2nskmxwy\"]},\"repositoryPHID\":\"PHID-REPO-bvunnehri4u2isyr7bc3\",\"sourcePath\":null},{\"id\":\"6054\",\"phid\":\"PHID-DREV-6pczsbtdpqjc2nskmxwy\",\"title\":\"create alpha for phabricator test \\u20ac\",\"uri\":\"https:\\/\\/phab.mercurial-scm.org\\/D6054\",\"dateCreated\":\"1551571947\",\"dateModified\":\"1551571958\",\"authorPHID\":\"PHID-USER-5iy6mkoveguhm2zthvww\",\"status\":\"0\",\"statusName\":\"Needs Review\",\"properties\":[],\"branch\":null,\"summary\":\"\",\"testPlan\":\"\",\"lineCount\":\"2\",\"activeDiffPHID\":\"PHID-DIFF-3wv2fwmzp27uamb66xxg\",\"diffs\":[\"14304\",\"14303\"],\"commits\":[],\"reviewers\":{\"PHID-PROJ-3dvcxzznrjru2xmmses3\":\"PHID-PROJ-3dvcxzznrjru2xmmses3\"},\"ccs\":[\"PHID-USER-q42dn7cc3donqriafhjx\"],\"hashes\":[],\"auxiliary\":{\"phabricator:projects\":[],\"phabricator:depends-on\":[]},\"repositoryPHID\":\"PHID-REPO-bvunnehri4u2isyr7bc3\",\"sourcePath\":null}],\"error_code\":null,\"error_info\":null}"
849 },
812 "headers": {
850 "headers": {
813 "server": [
851 "expires": [
814 "Apache/2.4.10 (Debian)"
852 "Sat, 01 Jan 2000 00:00:00 GMT"
815 ],
853 ],
816 "strict-transport-security": [
854 "x-xss-protection": [
817 "max-age=0; includeSubdomains; preload"
855 "1; mode=block"
818 ],
856 ],
857 "transfer-encoding": [
858 "chunked"
859 ],
860 "date": [
861 "Sun, 03 Mar 2019 00:12:39 GMT"
862 ],
819 "x-frame-options": [
863 "x-frame-options": [
820 "Deny"
864 "Deny"
821 ],
865 ],
866 "cache-control": [
867 "no-store"
868 ],
869 "content-type": [
870 "application/json"
871 ],
822 "x-content-type-options": [
872 "x-content-type-options": [
823 "nosniff"
873 "nosniff"
824 ],
874 ],
825 "expires": [
875 "server": [
826 "Sat, 01 Jan 2000 00:00:00 GMT"
876 "Apache/2.4.10 (Debian)"
827 ],
877 ],
828 "set-cookie": [
878 "set-cookie": [
829 "phsid=A%2Fvwsd2gtkeg64gticvthsxnpufne42t4eqityra25; expires=Thu, 14-Sep-2023 04:53:52 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
879 "phsid=A%2F5wxg6sdf2mby5iljd5e5qpgoex6uefo5pgltav7k; expires=Fri, 01-Mar-2024 00:12:39 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
830 ],
880 ],
831 "x-xss-protection": [
881 "strict-transport-security": [
832 "1; mode=block"
882 "max-age=0; includeSubdomains; preload"
833 ],
834 "content-type": [
835 "application/json"
836 ],
837 "cache-control": [
838 "no-store"
839 ],
840 "date": [
841 "Sat, 15 Sep 2018 04:53:52 GMT"
842 ]
883 ]
843 },
844 "body": {
845 "string": "{\"result\":null,\"error_code\":null,\"error_info\":null}"
846 }
884 }
847 }
885 }
848 },
886 },
849 {
887 {
850 "request": {
888 "request": {
851 "body": "diff_id=11074&api.token=cli-hahayouwish&data=%7B%22c2b605ada280b38c38031b5d31622869c72b0d8d%22%3A+%7B%22time%22%3A+0.0%2C+%22authorEmail%22%3A+%22test%22%2C+%22author%22%3A+%22test%22%7D%7D&name=local%3Acommits",
889 "method": "POST",
852 "uri": "https://phab.mercurial-scm.org//api/differential.setdiffproperty",
890 "body": "diff_id=14305&data=%7B%22user%22%3A+%22test%22%2C+%22parent%22%3A+%22939d862f03181a366fea64a540baf0bb33f85d92%22%2C+%22node%22%3A+%229c64e1fc33e1b9a70eb60643fe96a4d5badad9dc%22%2C+%22date%22%3A+%220+0%22%7D&api.token=cli-hahayouwish&name=hg%3Ameta",
891 "uri": "https://phab.mercurial-scm.org//api/differential.setdiffproperty",
853 "headers": {
892 "headers": {
854 "content-length": [
855 "227"
856 ],
857 "host": [
858 "phab.mercurial-scm.org"
859 ],
860 "content-type": [
893 "content-type": [
861 "application/x-www-form-urlencoded"
894 "application/x-www-form-urlencoded"
862 ],
895 ],
863 "accept": [
896 "accept": [
864 "application/mercurial-0.1"
897 "application/mercurial-0.1"
865 ],
898 ],
866 "user-agent": [
899 "user-agent": [
867 "mercurial/proto-1.0 (Mercurial 4.7.1+867-34bcd3af7109+20180915)"
900 "mercurial/proto-1.0 (Mercurial 4.9+477-7c86ec0ca5c5+20190303)"
901 ],
902 "host": [
903 "phab.mercurial-scm.org"
904 ],
905 "content-length": [
906 "264"
868 ]
907 ]
869 },
908 }
870 "method": "POST"
909 },
871 },
872 "response": {
910 "response": {
873 "status": {
911 "status": {
874 "code": 200,
912 "code": 200,
875 "message": "OK"
913 "message": "OK"
876 },
914 },
915 "body": {
916 "string": "{\"result\":null,\"error_code\":null,\"error_info\":null}"
917 },
877 "headers": {
918 "headers": {
919 "expires": [
920 "Sat, 01 Jan 2000 00:00:00 GMT"
921 ],
922 "x-xss-protection": [
923 "1; mode=block"
924 ],
925 "transfer-encoding": [
926 "chunked"
927 ],
928 "date": [
929 "Sun, 03 Mar 2019 00:12:40 GMT"
930 ],
931 "x-frame-options": [
932 "Deny"
933 ],
934 "cache-control": [
935 "no-store"
936 ],
937 "content-type": [
938 "application/json"
939 ],
940 "x-content-type-options": [
941 "nosniff"
942 ],
878 "server": [
943 "server": [
879 "Apache/2.4.10 (Debian)"
944 "Apache/2.4.10 (Debian)"
880 ],
945 ],
946 "set-cookie": [
947 "phsid=A%2F4c7iamnsn57y6qpccmbesf4ooflmkqvt4m6udawl; expires=Fri, 01-Mar-2024 00:12:40 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
948 ],
881 "strict-transport-security": [
949 "strict-transport-security": [
882 "max-age=0; includeSubdomains; preload"
950 "max-age=0; includeSubdomains; preload"
883 ],
951 ]
884 "x-frame-options": [
952 }
885 "Deny"
953 }
886 ],
954 },
887 "x-content-type-options": [
955 {
888 "nosniff"
956 "request": {
889 ],
957 "method": "POST",
958 "body": "diff_id=14305&data=%7B%229c64e1fc33e1b9a70eb60643fe96a4d5badad9dc%22%3A+%7B%22author%22%3A+%22test%22%2C+%22authorEmail%22%3A+%22test%22%2C+%22time%22%3A+0.0%7D%7D&api.token=cli-hahayouwish&name=local%3Acommits",
959 "uri": "https://phab.mercurial-scm.org//api/differential.setdiffproperty",
960 "headers": {
961 "content-type": [
962 "application/x-www-form-urlencoded"
963 ],
964 "accept": [
965 "application/mercurial-0.1"
966 ],
967 "user-agent": [
968 "mercurial/proto-1.0 (Mercurial 4.9+477-7c86ec0ca5c5+20190303)"
969 ],
970 "host": [
971 "phab.mercurial-scm.org"
972 ],
973 "content-length": [
974 "227"
975 ]
976 }
977 },
978 "response": {
979 "status": {
980 "code": 200,
981 "message": "OK"
982 },
983 "body": {
984 "string": "{\"result\":null,\"error_code\":null,\"error_info\":null}"
985 },
986 "headers": {
890 "expires": [
987 "expires": [
891 "Sat, 01 Jan 2000 00:00:00 GMT"
988 "Sat, 01 Jan 2000 00:00:00 GMT"
892 ],
989 ],
893 "set-cookie": [
894 "phsid=A%2Fflxjbmx24qcq7qhggolo6b7iue7utwp7kyoazduk; expires=Thu, 14-Sep-2023 04:53:52 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
895 ],
896 "x-xss-protection": [
990 "x-xss-protection": [
897 "1; mode=block"
991 "1; mode=block"
898 ],
992 ],
993 "transfer-encoding": [
994 "chunked"
995 ],
996 "date": [
997 "Sun, 03 Mar 2019 00:12:40 GMT"
998 ],
999 "x-frame-options": [
1000 "Deny"
1001 ],
1002 "cache-control": [
1003 "no-store"
1004 ],
899 "content-type": [
1005 "content-type": [
900 "application/json"
1006 "application/json"
901 ],
1007 ],
902 "cache-control": [
1008 "x-content-type-options": [
903 "no-store"
1009 "nosniff"
904 ],
1010 ],
905 "date": [
1011 "server": [
906 "Sat, 15 Sep 2018 04:53:52 GMT"
1012 "Apache/2.4.10 (Debian)"
1013 ],
1014 "set-cookie": [
1015 "phsid=A%2Ftdudqohojcq4hyc7gl4kthzkhuq3nmcxgnunpbjm; expires=Fri, 01-Mar-2024 00:12:40 GMT; Max-Age=157680000; path=/; domain=phab.mercurial-scm.org; secure; httponly"
1016 ],
1017 "strict-transport-security": [
1018 "max-age=0; includeSubdomains; preload"
907 ]
1019 ]
908 },
909 "body": {
910 "string": "{\"result\":null,\"error_code\":null,\"error_info\":null}"
911 }
1020 }
912 }
1021 }
913 }
1022 }
914 ]
1023 ],
1024 "version": 1
915 }
1025 }
@@ -1,119 +1,121 b''
1 #require vcr
1 #require vcr
2 $ cat >> $HGRCPATH <<EOF
2 $ cat >> $HGRCPATH <<EOF
3 > [extensions]
3 > [extensions]
4 > phabricator =
4 > phabricator =
5 > EOF
5 > EOF
6 $ hg init repo
6 $ hg init repo
7 $ cd repo
7 $ cd repo
8 $ cat >> .hg/hgrc <<EOF
8 $ cat >> .hg/hgrc <<EOF
9 > [phabricator]
9 > [phabricator]
10 > url = https://phab.mercurial-scm.org/
10 > url = https://phab.mercurial-scm.org/
11 > callsign = HG
11 > callsign = HG
12 >
12 >
13 > [auth]
13 > [auth]
14 > hgphab.schemes = https
14 > hgphab.schemes = https
15 > hgphab.prefix = phab.mercurial-scm.org
15 > hgphab.prefix = phab.mercurial-scm.org
16 > # When working on the extension and making phabricator interaction
16 > # When working on the extension and making phabricator interaction
17 > # changes, edit this to be a real phabricator token. When done, edit
17 > # changes, edit this to be a real phabricator token. When done, edit
18 > # it back, and make sure to also edit your VCR transcripts to match
18 > # it back, and make sure to also edit your VCR transcripts to match
19 > # whatever value you put here.
19 > # whatever value you put here.
20 > hgphab.phabtoken = cli-hahayouwish
20 > hgphab.phabtoken = cli-hahayouwish
21 > EOF
21 > EOF
22 $ VCR="$TESTDIR/phabricator"
22 $ VCR="$TESTDIR/phabricator"
23
23
24 Error is handled reasonably. We override the phabtoken here so that
24 Error is handled reasonably. We override the phabtoken here so that
25 when you're developing changes to phabricator.py you can edit the
25 when you're developing changes to phabricator.py you can edit the
26 above config and have a real token in the test but not have to edit
26 above config and have a real token in the test but not have to edit
27 this test.
27 this test.
28 $ hg phabread --config auth.hgphab.phabtoken=cli-notavalidtoken \
28 $ hg phabread --config auth.hgphab.phabtoken=cli-notavalidtoken \
29 > --test-vcr "$VCR/phabread-conduit-error.json" D4480 | head
29 > --test-vcr "$VCR/phabread-conduit-error.json" D4480 | head
30 abort: Conduit Error (ERR-INVALID-AUTH): API token "cli-notavalidtoken" has the wrong length. API tokens should be 32 characters long.
30 abort: Conduit Error (ERR-INVALID-AUTH): API token "cli-notavalidtoken" has the wrong length. API tokens should be 32 characters long.
31
31
32 Basic phabread:
32 Basic phabread:
33 $ hg phabread --test-vcr "$VCR/phabread-4480.json" D4480 | head
33 $ hg phabread --test-vcr "$VCR/phabread-4480.json" D4480 | head
34 # HG changeset patch
34 # HG changeset patch
35 exchangev2: start to implement pull with wire protocol v2
35 exchangev2: start to implement pull with wire protocol v2
36
36
37 Wire protocol version 2 will take a substantially different
37 Wire protocol version 2 will take a substantially different
38 approach to exchange than version 1 (at least as far as pulling
38 approach to exchange than version 1 (at least as far as pulling
39 is concerned).
39 is concerned).
40
40
41 This commit establishes a new exchangev2 module for holding
41 This commit establishes a new exchangev2 module for holding
42 code related to exchange using wire protocol v2. I could have
42 code related to exchange using wire protocol v2. I could have
43 added things to the existing exchange module. But it is already
43 added things to the existing exchange module. But it is already
44
44
45 phabupdate with an accept:
45 phabupdate with an accept:
46 $ hg phabupdate --accept D4564 \
46 $ hg phabupdate --accept D4564 \
47 > -m 'I think I like where this is headed. Will read rest of series later.'\
47 > -m 'I think I like where this is headed. Will read rest of series later.'\
48 > --test-vcr "$VCR/accept-4564.json"
48 > --test-vcr "$VCR/accept-4564.json"
49
49
50 Create a differential diff:
50 Create a differential diff:
51 $ HGENCODING=utf-8; export HGENCODING
51 $ echo alpha > alpha
52 $ echo alpha > alpha
52 $ hg ci --addremove -m 'create alpha for phabricator test'
53 $ hg ci --addremove -m 'create alpha for phabricator test '
53 adding alpha
54 adding alpha
54 $ hg phabsend -r . --test-vcr "$VCR/phabsend-create-alpha.json"
55 $ hg phabsend -r . --test-vcr "$VCR/phabsend-create-alpha.json"
55 D4596 - created - 5206a4fa1e6c: create alpha for phabricator test
56 D6054 - created - d386117f30e6: create alpha for phabricator test \xe2\x82\xac (esc)
56 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/5206a4fa1e6c-dec9e777-phabsend.hg
57 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/d386117f30e6-24ffe649-phabsend.hg
57 $ echo more >> alpha
58 $ echo more >> alpha
58 $ HGEDITOR=true hg ci --amend
59 $ HGEDITOR=true hg ci --amend
59 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/d8f232f7d799-c573510a-amend.hg
60 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/cb03845d6dd9-870f61a6-amend.hg
60 $ echo beta > beta
61 $ echo beta > beta
61 $ hg ci --addremove -m 'create beta for phabricator test'
62 $ hg ci --addremove -m 'create beta for phabricator test'
62 adding beta
63 adding beta
63 $ hg phabsend -r ".^::" --test-vcr "$VCR/phabsend-update-alpha-create-beta.json"
64 $ hg phabsend -r ".^::" --test-vcr "$VCR/phabsend-update-alpha-create-beta.json"
64 D4596 - updated - f70265671c65: create alpha for phabricator test
65 D6054 - updated - 939d862f0318: create alpha for phabricator test \xe2\x82\xac (esc)
65 D4597 - created - 1a5640df7bbf: create beta for phabricator test
66 D6055 - created - f55f947ed0f8: create beta for phabricator test
66 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/1a5640df7bbf-6daf3e6e-phabsend.hg
67 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/f55f947ed0f8-0d1e502e-phabsend.hg
68 $ unset HGENCODING
67
69
68 The amend won't explode after posting a public commit. The local tag is left
70 The amend won't explode after posting a public commit. The local tag is left
69 behind to identify it.
71 behind to identify it.
70
72
71 $ echo 'public change' > beta
73 $ echo 'public change' > beta
72 $ hg ci -m 'create public change for phabricator testing'
74 $ hg ci -m 'create public change for phabricator testing'
73 $ hg phase --public .
75 $ hg phase --public .
74 $ echo 'draft change' > alpha
76 $ echo 'draft change' > alpha
75 $ hg ci -m 'create draft change for phabricator testing'
77 $ hg ci -m 'create draft change for phabricator testing'
76 $ hg phabsend --amend -r '.^::' --test-vcr "$VCR/phabsend-create-public.json"
78 $ hg phabsend --amend -r '.^::' --test-vcr "$VCR/phabsend-create-public.json"
77 D5544 - created - 540a21d3fbeb: create public change for phabricator testing
79 D5544 - created - a56e5ebd77e6: create public change for phabricator testing
78 D5545 - created - 6bca752686cd: create draft change for phabricator testing
80 D5545 - created - 6a0ade3e3ec2: create draft change for phabricator testing
79 warning: not updating public commit 2:540a21d3fbeb
81 warning: not updating public commit 2:a56e5ebd77e6
80 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/6bca752686cd-41faefb4-phabsend.hg
82 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/6a0ade3e3ec2-aca7d23c-phabsend.hg
81 $ hg tags -v
83 $ hg tags -v
82 tip 3:620a50fd6ed9
84 tip 3:90532860b5e1
83 D5544 2:540a21d3fbeb local
85 D5544 2:a56e5ebd77e6 local
84
86
85 $ hg debugcallconduit user.search --test-vcr "$VCR/phab-conduit.json" <<EOF
87 $ hg debugcallconduit user.search --test-vcr "$VCR/phab-conduit.json" <<EOF
86 > {
88 > {
87 > "constraints": {
89 > "constraints": {
88 > "isBot": true
90 > "isBot": true
89 > }
91 > }
90 > }
92 > }
91 > EOF
93 > EOF
92 {
94 {
93 "cursor": {
95 "cursor": {
94 "after": null,
96 "after": null,
95 "before": null,
97 "before": null,
96 "limit": 100,
98 "limit": 100,
97 "order": null
99 "order": null
98 },
100 },
99 "data": [],
101 "data": [],
100 "maps": {},
102 "maps": {},
101 "query": {
103 "query": {
102 "queryKey": null
104 "queryKey": null
103 }
105 }
104 }
106 }
105
107
106 Template keywords
108 Template keywords
107 $ hg log -T'{rev} {phabreview|json}\n'
109 $ hg log -T'{rev} {phabreview|json}\n'
108 3 {"id": "D5545", "url": "https://phab.mercurial-scm.org/D5545"}
110 3 {"id": "D5545", "url": "https://phab.mercurial-scm.org/D5545"}
109 2 {"id": "D5544", "url": "https://phab.mercurial-scm.org/D5544"}
111 2 {"id": "D5544", "url": "https://phab.mercurial-scm.org/D5544"}
110 1 {"id": "D4597", "url": "https://phab.mercurial-scm.org/D4597"}
112 1 {"id": "D6055", "url": "https://phab.mercurial-scm.org/D6055"}
111 0 {"id": "D4596", "url": "https://phab.mercurial-scm.org/D4596"}
113 0 {"id": "D6054", "url": "https://phab.mercurial-scm.org/D6054"}
112
114
113 $ hg log -T'{rev} {if(phabreview, "{phabreview.url} {phabreview.id}")}\n'
115 $ hg log -T'{rev} {if(phabreview, "{phabreview.url} {phabreview.id}")}\n'
114 3 https://phab.mercurial-scm.org/D5545 D5545
116 3 https://phab.mercurial-scm.org/D5545 D5545
115 2 https://phab.mercurial-scm.org/D5544 D5544
117 2 https://phab.mercurial-scm.org/D5544 D5544
116 1 https://phab.mercurial-scm.org/D4597 D4597
118 1 https://phab.mercurial-scm.org/D6055 D6055
117 0 https://phab.mercurial-scm.org/D4596 D4596
119 0 https://phab.mercurial-scm.org/D6054 D6054
118
120
119 $ cd ..
121 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now