contrib/phabricator.py
changeset 33498 b7a75b9a3386
parent 33443 e48082e0a8d5
child 33564 91e3dcefc9b7
equal deleted inserted replaced
33497:80e1331a7fe9 33498:b7a75b9a3386
   234             'parent': ctx.p1().hex(),
   234             'parent': ctx.p1().hex(),
   235         }),
   235         }),
   236     }
   236     }
   237     callconduit(ctx.repo(), 'differential.setdiffproperty', params)
   237     callconduit(ctx.repo(), 'differential.setdiffproperty', params)
   238 
   238 
   239 def createdifferentialrevision(ctx, revid=None, parentrevid=None, oldnode=None):
   239 def createdifferentialrevision(ctx, revid=None, parentrevid=None, oldnode=None,
       
   240                                actions=None):
   240     """create or update a Differential Revision
   241     """create or update a Differential Revision
   241 
   242 
   242     If revid is None, create a new Differential Revision, otherwise update
   243     If revid is None, create a new Differential Revision, otherwise update
   243     revid. If parentrevid is not None, set it as a dependency.
   244     revid. If parentrevid is not None, set it as a dependency.
   244 
   245 
   245     If oldnode is not None, check if the patch content (without commit message
   246     If oldnode is not None, check if the patch content (without commit message
   246     and metadata) has changed before creating another diff.
   247     and metadata) has changed before creating another diff.
       
   248 
       
   249     If actions is not None, they will be appended to the transaction.
   247     """
   250     """
   248     repo = ctx.repo()
   251     repo = ctx.repo()
   249     if oldnode:
   252     if oldnode:
   250         diffopts = mdiff.diffopts(git=True, context=1)
   253         diffopts = mdiff.diffopts(git=True, context=1)
   251         oldctx = repo.unfiltered()[oldnode]
   254         oldctx = repo.unfiltered()[oldnode]
   266     if parentrevid and revid is None:
   269     if parentrevid and revid is None:
   267         summary = 'Depends on D%s' % parentrevid
   270         summary = 'Depends on D%s' % parentrevid
   268         transactions += [{'type': 'summary', 'value': summary},
   271         transactions += [{'type': 'summary', 'value': summary},
   269                          {'type': 'summary', 'value': ' '}]
   272                          {'type': 'summary', 'value': ' '}]
   270 
   273 
       
   274     if actions:
       
   275         transactions += actions
       
   276 
   271     # Parse commit message and update related fields.
   277     # Parse commit message and update related fields.
   272     desc = ctx.description()
   278     desc = ctx.description()
   273     info = callconduit(repo, 'differential.parsecommitmessage',
   279     info = callconduit(repo, 'differential.parsecommitmessage',
   274                        {'corpus': desc})
   280                        {'corpus': desc})
   275     for k, v in info[r'fields'].items():
   281     for k, v in info[r'fields'].items():
   285     if not revision:
   291     if not revision:
   286         raise error.Abort(_('cannot create revision for %s') % ctx)
   292         raise error.Abort(_('cannot create revision for %s') % ctx)
   287 
   293 
   288     return revision
   294     return revision
   289 
   295 
       
   296 def userphids(repo, names):
       
   297     """convert user names to PHIDs"""
       
   298     query = {'constraints': {'usernames': names}}
       
   299     result = callconduit(repo, 'user.search', query)
       
   300     # username not found is not an error of the API. So check if we have missed
       
   301     # some names here.
       
   302     data = result[r'data']
       
   303     resolved = set(entry[r'fields'][r'username'] for entry in data)
       
   304     unresolved = set(names) - resolved
       
   305     if unresolved:
       
   306         raise error.Abort(_('unknown username: %s')
       
   307                           % ' '.join(sorted(unresolved)))
       
   308     return [entry[r'phid'] for entry in data]
       
   309 
   290 @command('phabsend',
   310 @command('phabsend',
   291          [('r', 'rev', [], _('revisions to send'), _('REV'))],
   311          [('r', 'rev', [], _('revisions to send'), _('REV')),
       
   312           ('', 'reviewer', [], _('specify reviewers'))],
   292          _('REV [OPTIONS]'))
   313          _('REV [OPTIONS]'))
   293 def phabsend(ui, repo, *revs, **opts):
   314 def phabsend(ui, repo, *revs, **opts):
   294     """upload changesets to Phabricator
   315     """upload changesets to Phabricator
   295 
   316 
   296     If there are multiple revisions specified, they will be send as a stack
   317     If there are multiple revisions specified, they will be send as a stack
   305     revs = list(revs) + opts.get('rev', [])
   326     revs = list(revs) + opts.get('rev', [])
   306     revs = scmutil.revrange(repo, revs)
   327     revs = scmutil.revrange(repo, revs)
   307 
   328 
   308     if not revs:
   329     if not revs:
   309         raise error.Abort(_('phabsend requires at least one changeset'))
   330         raise error.Abort(_('phabsend requires at least one changeset'))
       
   331 
       
   332     actions = []
       
   333     reviewers = opts.get('reviewer', [])
       
   334     if reviewers:
       
   335         phids = userphids(repo, reviewers)
       
   336         actions.append({'type': 'reviewers.add', 'value': phids})
   310 
   337 
   311     oldnodedrev = getoldnodedrevmap(repo, [repo[r].node() for r in revs])
   338     oldnodedrev = getoldnodedrevmap(repo, [repo[r].node() for r in revs])
   312 
   339 
   313     # Send patches one by one so we know their Differential Revision IDs and
   340     # Send patches one by one so we know their Differential Revision IDs and
   314     # can provide dependency relationship
   341     # can provide dependency relationship
   320         # Get Differential Revision ID
   347         # Get Differential Revision ID
   321         oldnode, revid = oldnodedrev.get(ctx.node(), (None, None))
   348         oldnode, revid = oldnodedrev.get(ctx.node(), (None, None))
   322         if oldnode != ctx.node():
   349         if oldnode != ctx.node():
   323             # Create or update Differential Revision
   350             # Create or update Differential Revision
   324             revision = createdifferentialrevision(ctx, revid, lastrevid,
   351             revision = createdifferentialrevision(ctx, revid, lastrevid,
   325                                                   oldnode)
   352                                                   oldnode, actions)
   326             newrevid = int(revision[r'object'][r'id'])
   353             newrevid = int(revision[r'object'][r'id'])
   327             if revid:
   354             if revid:
   328                 action = _('updated')
   355                 action = _('updated')
   329             else:
   356             else:
   330                 action = _('created')
   357                 action = _('created')