Mercurial > hg
comparison hgext/phabricator.py @ 42434:f163e2b2594c
phabricator: pass ui instead of repo to callconduit
This will help us make `hg debugcallconduit` work outside a hg repo as next
patch will mark that command as no repo.
Differential Revision: https://phab.mercurial-scm.org/D6498
author | Pulkit Goyal <pulkit@yandex-team.ru> |
---|---|
date | Sat, 08 Jun 2019 18:41:15 +0300 |
parents | 500b64c5d991 |
children | 16312ea45a8b |
comparison
equal
deleted
inserted
replaced
42433:500b64c5d991 | 42434:f163e2b2594c |
---|---|
208 raise error.Abort(_(b'Can\'t find conduit token associated to %s') | 208 raise error.Abort(_(b'Can\'t find conduit token associated to %s') |
209 % (url,)) | 209 % (url,)) |
210 | 210 |
211 return url, token | 211 return url, token |
212 | 212 |
213 def callconduit(repo, name, params): | 213 def callconduit(ui, name, params): |
214 """call Conduit API, params is a dict. return json.loads result, or None""" | 214 """call Conduit API, params is a dict. return json.loads result, or None""" |
215 host, token = readurltoken(repo.ui) | 215 host, token = readurltoken(ui) |
216 url, authinfo = util.url(b'/'.join([host, b'api', name])).authinfo() | 216 url, authinfo = util.url(b'/'.join([host, b'api', name])).authinfo() |
217 repo.ui.debug(b'Conduit Call: %s %s\n' % (url, pycompat.byterepr(params))) | 217 ui.debug(b'Conduit Call: %s %s\n' % (url, pycompat.byterepr(params))) |
218 params = params.copy() | 218 params = params.copy() |
219 params[b'api.token'] = token | 219 params[b'api.token'] = token |
220 data = urlencodenested(params) | 220 data = urlencodenested(params) |
221 curlcmd = repo.ui.config(b'phabricator', b'curlcmd') | 221 curlcmd = ui.config(b'phabricator', b'curlcmd') |
222 if curlcmd: | 222 if curlcmd: |
223 sin, sout = procutil.popen2(b'%s -d @- %s' | 223 sin, sout = procutil.popen2(b'%s -d @- %s' |
224 % (curlcmd, procutil.shellquote(url))) | 224 % (curlcmd, procutil.shellquote(url))) |
225 sin.write(data) | 225 sin.write(data) |
226 sin.close() | 226 sin.close() |
227 body = sout.read() | 227 body = sout.read() |
228 else: | 228 else: |
229 urlopener = urlmod.opener(repo.ui, authinfo) | 229 urlopener = urlmod.opener(ui, authinfo) |
230 request = util.urlreq.request(pycompat.strurl(url), data=data) | 230 request = util.urlreq.request(pycompat.strurl(url), data=data) |
231 with contextlib.closing(urlopener.open(request)) as rsp: | 231 with contextlib.closing(urlopener.open(request)) as rsp: |
232 body = rsp.read() | 232 body = rsp.read() |
233 repo.ui.debug(b'Conduit Response: %s\n' % body) | 233 ui.debug(b'Conduit Response: %s\n' % body) |
234 parsed = pycompat.rapply( | 234 parsed = pycompat.rapply( |
235 lambda x: encoding.unitolocal(x) if isinstance(x, pycompat.unicode) | 235 lambda x: encoding.unitolocal(x) if isinstance(x, pycompat.unicode) |
236 else x, | 236 else x, |
237 json.loads(body) | 237 json.loads(body) |
238 ) | 238 ) |
257 json.loads(rawparams) | 257 json.loads(rawparams) |
258 ) | 258 ) |
259 # json.dumps only accepts unicode strings | 259 # json.dumps only accepts unicode strings |
260 result = pycompat.rapply(lambda x: | 260 result = pycompat.rapply(lambda x: |
261 encoding.unifromlocal(x) if isinstance(x, bytes) else x, | 261 encoding.unifromlocal(x) if isinstance(x, bytes) else x, |
262 callconduit(repo, name, params) | 262 callconduit(ui, name, params) |
263 ) | 263 ) |
264 s = json.dumps(result, sort_keys=True, indent=2, separators=(u',', u': ')) | 264 s = json.dumps(result, sort_keys=True, indent=2, separators=(u',', u': ')) |
265 ui.write(b'%s\n' % encoding.unitolocal(s)) | 265 ui.write(b'%s\n' % encoding.unitolocal(s)) |
266 | 266 |
267 def getrepophid(repo): | 267 def getrepophid(repo): |
271 if repophid: | 271 if repophid: |
272 return repophid | 272 return repophid |
273 callsign = repo.ui.config(b'phabricator', b'callsign') | 273 callsign = repo.ui.config(b'phabricator', b'callsign') |
274 if not callsign: | 274 if not callsign: |
275 return None | 275 return None |
276 query = callconduit(repo, b'diffusion.repository.search', | 276 query = callconduit(repo.ui, b'diffusion.repository.search', |
277 {b'constraints': {b'callsigns': [callsign]}}) | 277 {b'constraints': {b'callsigns': [callsign]}}) |
278 if len(query[b'data']) == 0: | 278 if len(query[b'data']) == 0: |
279 return None | 279 return None |
280 repophid = query[b'data'][0][b'phid'] | 280 repophid = query[b'data'][0][b'phid'] |
281 repo.ui.setconfig(b'phabricator', b'repophid', repophid) | 281 repo.ui.setconfig(b'phabricator', b'repophid', repophid) |
327 | 327 |
328 # Double check if tags are genuine by collecting all old nodes from | 328 # Double check if tags are genuine by collecting all old nodes from |
329 # Phabricator, and expect precursors overlap with it. | 329 # Phabricator, and expect precursors overlap with it. |
330 if toconfirm: | 330 if toconfirm: |
331 drevs = [drev for force, precs, drev in toconfirm.values()] | 331 drevs = [drev for force, precs, drev in toconfirm.values()] |
332 alldiffs = callconduit(unfi, b'differential.querydiffs', | 332 alldiffs = callconduit(unfi.ui, b'differential.querydiffs', |
333 {b'revisionIDs': drevs}) | 333 {b'revisionIDs': drevs}) |
334 getnode = lambda d: bin( | 334 getnode = lambda d: bin( |
335 getdiffmeta(d).get(b'node', b'')) or None | 335 getdiffmeta(d).get(b'node', b'')) or None |
336 for newnode, (force, precset, drev) in toconfirm.items(): | 336 for newnode, (force, precset, drev) in toconfirm.items(): |
337 diffs = [d for d in alldiffs.values() | 337 diffs = [d for d in alldiffs.values() |
377 repophid = getrepophid(repo) | 377 repophid = getrepophid(repo) |
378 # Create a "Differential Diff" via "differential.createrawdiff" API | 378 # Create a "Differential Diff" via "differential.createrawdiff" API |
379 params = {b'diff': getdiff(ctx, mdiff.diffopts(git=True, context=32767))} | 379 params = {b'diff': getdiff(ctx, mdiff.diffopts(git=True, context=32767))} |
380 if repophid: | 380 if repophid: |
381 params[b'repositoryPHID'] = repophid | 381 params[b'repositoryPHID'] = repophid |
382 diff = callconduit(repo, b'differential.createrawdiff', params) | 382 diff = callconduit(repo.ui, b'differential.createrawdiff', params) |
383 if not diff: | 383 if not diff: |
384 raise error.Abort(_(b'cannot create diff for %s') % ctx) | 384 raise error.Abort(_(b'cannot create diff for %s') % ctx) |
385 return diff | 385 return diff |
386 | 386 |
387 def writediffproperties(ctx, diff): | 387 def writediffproperties(ctx, diff): |
395 b'branch': ctx.branch(), | 395 b'branch': ctx.branch(), |
396 b'node': ctx.hex(), | 396 b'node': ctx.hex(), |
397 b'parent': ctx.p1().hex(), | 397 b'parent': ctx.p1().hex(), |
398 }), | 398 }), |
399 } | 399 } |
400 callconduit(ctx.repo(), b'differential.setdiffproperty', params) | 400 callconduit(ctx.repo().ui, b'differential.setdiffproperty', params) |
401 | 401 |
402 params = { | 402 params = { |
403 b'diff_id': diff[b'id'], | 403 b'diff_id': diff[b'id'], |
404 b'name': b'local:commits', | 404 b'name': b'local:commits', |
405 b'data': templatefilters.json({ | 405 b'data': templatefilters.json({ |
411 b'parents': [ctx.p1().hex()], | 411 b'parents': [ctx.p1().hex()], |
412 b'branch': ctx.branch(), | 412 b'branch': ctx.branch(), |
413 }, | 413 }, |
414 }), | 414 }), |
415 } | 415 } |
416 callconduit(ctx.repo(), b'differential.setdiffproperty', params) | 416 callconduit(ctx.repo().ui, b'differential.setdiffproperty', params) |
417 | 417 |
418 def createdifferentialrevision(ctx, revid=None, parentrevid=None, oldnode=None, | 418 def createdifferentialrevision(ctx, revid=None, parentrevid=None, oldnode=None, |
419 olddiff=None, actions=None, comment=None): | 419 olddiff=None, actions=None, comment=None): |
420 """create or update a Differential Revision | 420 """create or update a Differential Revision |
421 | 421 |
461 if actions: | 461 if actions: |
462 transactions += actions | 462 transactions += actions |
463 | 463 |
464 # Parse commit message and update related fields. | 464 # Parse commit message and update related fields. |
465 desc = ctx.description() | 465 desc = ctx.description() |
466 info = callconduit(repo, b'differential.parsecommitmessage', | 466 info = callconduit(repo.ui, b'differential.parsecommitmessage', |
467 {b'corpus': desc}) | 467 {b'corpus': desc}) |
468 for k, v in info[b'fields'].items(): | 468 for k, v in info[b'fields'].items(): |
469 if k in [b'title', b'summary', b'testPlan']: | 469 if k in [b'title', b'summary', b'testPlan']: |
470 transactions.append({b'type': k, b'value': v}) | 470 transactions.append({b'type': k, b'value': v}) |
471 | 471 |
472 params = {b'transactions': transactions} | 472 params = {b'transactions': transactions} |
473 if revid is not None: | 473 if revid is not None: |
474 # Update an existing Differential Revision | 474 # Update an existing Differential Revision |
475 params[b'objectIdentifier'] = revid | 475 params[b'objectIdentifier'] = revid |
476 | 476 |
477 revision = callconduit(repo, b'differential.revision.edit', params) | 477 revision = callconduit(repo.ui, b'differential.revision.edit', params) |
478 if not revision: | 478 if not revision: |
479 raise error.Abort(_(b'cannot create revision for %s') % ctx) | 479 raise error.Abort(_(b'cannot create revision for %s') % ctx) |
480 | 480 |
481 return revision, diff | 481 return revision, diff |
482 | 482 |
483 def userphids(repo, names): | 483 def userphids(repo, names): |
484 """convert user names to PHIDs""" | 484 """convert user names to PHIDs""" |
485 names = [name.lower() for name in names] | 485 names = [name.lower() for name in names] |
486 query = {b'constraints': {b'usernames': names}} | 486 query = {b'constraints': {b'usernames': names}} |
487 result = callconduit(repo, b'user.search', query) | 487 result = callconduit(repo.ui, b'user.search', query) |
488 # username not found is not an error of the API. So check if we have missed | 488 # username not found is not an error of the API. So check if we have missed |
489 # some names here. | 489 # some names here. |
490 data = result[b'data'] | 490 data = result[b'data'] |
491 resolved = set(entry[b'fields'][b'username'].lower() for entry in data) | 491 resolved = set(entry[b'fields'][b'username'].lower() for entry in data) |
492 unresolved = set(names) - resolved | 492 unresolved = set(names) - resolved |
607 lastrevid = newrevid | 607 lastrevid = newrevid |
608 | 608 |
609 # Update commit messages and remove tags | 609 # Update commit messages and remove tags |
610 if opts.get(b'amend'): | 610 if opts.get(b'amend'): |
611 unfi = repo.unfiltered() | 611 unfi = repo.unfiltered() |
612 drevs = callconduit(repo, b'differential.query', {b'ids': drevids}) | 612 drevs = callconduit(ui, b'differential.query', {b'ids': drevids}) |
613 with repo.wlock(), repo.lock(), repo.transaction(b'phabsend'): | 613 with repo.wlock(), repo.lock(), repo.transaction(b'phabsend'): |
614 wnode = unfi[b'.'].node() | 614 wnode = unfi[b'.'].node() |
615 mapping = {} # {oldnode: [newnode]} | 615 mapping = {} # {oldnode: [newnode]} |
616 for i, rev in enumerate(revs): | 616 for i, rev in enumerate(revs): |
617 old = unfi[rev] | 617 old = unfi[rev] |
793 def fetch(params): | 793 def fetch(params): |
794 """params -> single drev or None""" | 794 """params -> single drev or None""" |
795 key = (params.get(b'ids') or params.get(b'phids') or [None])[0] | 795 key = (params.get(b'ids') or params.get(b'phids') or [None])[0] |
796 if key in prefetched: | 796 if key in prefetched: |
797 return prefetched[key] | 797 return prefetched[key] |
798 drevs = callconduit(repo, b'differential.query', params) | 798 drevs = callconduit(repo.ui, b'differential.query', params) |
799 # Fill prefetched with the result | 799 # Fill prefetched with the result |
800 for drev in drevs: | 800 for drev in drevs: |
801 prefetched[drev[b'phid']] = drev | 801 prefetched[drev[b'phid']] = drev |
802 prefetched[int(drev[b'id'])] = drev | 802 prefetched[int(drev[b'id'])] = drev |
803 if key not in prefetched: | 803 if key not in prefetched: |
951 write is usually ui.write. drevs is what "querydrev" returns, results of | 951 write is usually ui.write. drevs is what "querydrev" returns, results of |
952 "differential.query". | 952 "differential.query". |
953 """ | 953 """ |
954 # Prefetch hg:meta property for all diffs | 954 # Prefetch hg:meta property for all diffs |
955 diffids = sorted(set(max(int(v) for v in drev[b'diffs']) for drev in drevs)) | 955 diffids = sorted(set(max(int(v) for v in drev[b'diffs']) for drev in drevs)) |
956 diffs = callconduit(repo, b'differential.querydiffs', {b'ids': diffids}) | 956 diffs = callconduit(repo.ui, b'differential.querydiffs', {b'ids': diffids}) |
957 | 957 |
958 # Generate patch for each drev | 958 # Generate patch for each drev |
959 for drev in drevs: | 959 for drev in drevs: |
960 repo.ui.note(_(b'reading D%s\n') % drev[b'id']) | 960 repo.ui.note(_(b'reading D%s\n') % drev[b'id']) |
961 | 961 |
962 diffid = max(int(v) for v in drev[b'diffs']) | 962 diffid = max(int(v) for v in drev[b'diffs']) |
963 body = callconduit(repo, b'differential.getrawdiff', | 963 body = callconduit(repo.ui, b'differential.getrawdiff', |
964 {b'diffID': diffid}) | 964 {b'diffID': diffid}) |
965 desc = getdescfromdrev(drev) | 965 desc = getdescfromdrev(drev) |
966 header = b'# HG changeset patch\n' | 966 header = b'# HG changeset patch\n' |
967 | 967 |
968 # Try to preserve metadata from hg:meta property. Write hg patch | 968 # Try to preserve metadata from hg:meta property. Write hg patch |
1032 if i + 1 == len(drevs) and opts.get(b'comment'): | 1032 if i + 1 == len(drevs) and opts.get(b'comment'): |
1033 actions.append({b'type': b'comment', b'value': opts[b'comment']}) | 1033 actions.append({b'type': b'comment', b'value': opts[b'comment']}) |
1034 if actions: | 1034 if actions: |
1035 params = {b'objectIdentifier': drev[b'phid'], | 1035 params = {b'objectIdentifier': drev[b'phid'], |
1036 b'transactions': actions} | 1036 b'transactions': actions} |
1037 callconduit(repo, b'differential.revision.edit', params) | 1037 callconduit(ui, b'differential.revision.edit', params) |
1038 | 1038 |
1039 templatekeyword = registrar.templatekeyword() | 1039 templatekeyword = registrar.templatekeyword() |
1040 | 1040 |
1041 @templatekeyword(b'phabreview', requires={b'ctx'}) | 1041 @templatekeyword(b'phabreview', requires={b'ctx'}) |
1042 def template_review(context, mapping): | 1042 def template_review(context, mapping): |