2016-03-22 20:45:57 +03:00
|
|
|
# arcdiff.py - extension adding an option to the diff command to show changes
|
|
|
|
# since the last arcanist diff
|
|
|
|
#
|
|
|
|
# Copyright 2016 Facebook, Inc.
|
|
|
|
#
|
|
|
|
# This software may be used and distributed according to the terms of the
|
|
|
|
# GNU General Public License version 2 or any later version.
|
|
|
|
|
2017-01-20 11:24:45 +03:00
|
|
|
import os
|
|
|
|
|
2016-11-25 03:23:21 +03:00
|
|
|
from mercurial import commands, error, extensions
|
2016-03-22 20:45:57 +03:00
|
|
|
from mercurial.i18n import _
|
|
|
|
|
2018-01-24 23:30:25 +03:00
|
|
|
from .extlib.phabricator import (
|
2016-04-27 19:50:13 +03:00
|
|
|
arcconfig,
|
2017-12-14 21:28:30 +03:00
|
|
|
graphql,
|
2016-04-27 19:50:13 +03:00
|
|
|
diffprops,
|
|
|
|
)
|
2016-04-27 19:27:56 +03:00
|
|
|
|
2016-03-22 20:45:57 +03:00
|
|
|
def extsetup(ui):
|
|
|
|
entry = extensions.wrapcommand(commands.table, 'diff', _diff)
|
|
|
|
options = entry[1]
|
|
|
|
options.append(('', 'since-last-arc-diff', None,
|
2017-12-14 21:28:30 +03:00
|
|
|
_('show changes since last `arc diff`')))
|
2016-03-22 20:45:57 +03:00
|
|
|
|
2016-05-12 23:11:08 +03:00
|
|
|
def _differentialhash(ui, repo, phabrev):
|
2017-11-09 19:43:57 +03:00
|
|
|
timeout = repo.ui.configint('ssl', 'timeout', 5)
|
|
|
|
ca_certs = repo.ui.configpath('web', 'cacerts')
|
2016-03-22 20:45:57 +03:00
|
|
|
try:
|
2017-12-14 21:28:30 +03:00
|
|
|
client = graphql.Client(
|
|
|
|
repodir=repo.root, ca_bundle=ca_certs, repo=repo)
|
|
|
|
info = client.getrevisioninfo(timeout, [phabrev]).get(str(phabrev))
|
|
|
|
if not info:
|
2016-05-12 23:11:08 +03:00
|
|
|
return None
|
2017-12-14 21:28:30 +03:00
|
|
|
return info
|
2016-05-12 23:11:08 +03:00
|
|
|
|
2017-12-14 21:28:30 +03:00
|
|
|
except graphql.ClientError as e:
|
|
|
|
ui.warn(_('Error calling graphql: %s\n') % str(e))
|
2016-03-22 20:45:57 +03:00
|
|
|
return None
|
2016-04-27 19:27:56 +03:00
|
|
|
except arcconfig.ArcConfigError as e:
|
|
|
|
raise error.Abort(str(e))
|
2016-03-22 20:45:57 +03:00
|
|
|
|
|
|
|
def _diff(orig, ui, repo, *pats, **opts):
|
|
|
|
if not opts.get('since_last_arc_diff'):
|
|
|
|
return orig(ui, repo, *pats, **opts)
|
|
|
|
|
2018-02-23 20:36:39 +03:00
|
|
|
if len(opts['rev']) > 1:
|
|
|
|
mess = _('cannot specify --since-last-arc-diff with multiple revisions')
|
|
|
|
raise error.Abort(mess)
|
|
|
|
try:
|
|
|
|
targetrev = opts['rev'][0]
|
|
|
|
except IndexError:
|
|
|
|
targetrev = '.'
|
|
|
|
ctx = repo[targetrev]
|
2016-04-27 19:50:13 +03:00
|
|
|
phabrev = diffprops.parserevfromcommitmsg(ctx.description())
|
2016-03-22 20:45:57 +03:00
|
|
|
|
2016-04-27 19:50:13 +03:00
|
|
|
if phabrev is None:
|
2016-09-21 17:45:25 +03:00
|
|
|
mess = _('local changeset is not associated with a differential '
|
|
|
|
'revision')
|
2016-03-22 20:45:57 +03:00
|
|
|
raise error.Abort(mess)
|
|
|
|
|
2016-05-12 23:11:08 +03:00
|
|
|
rev = _differentialhash(ui, repo, phabrev)
|
2017-12-14 21:28:30 +03:00
|
|
|
|
|
|
|
if rev is None or not isinstance(rev, dict) or "hash" not in rev:
|
2016-09-21 17:45:25 +03:00
|
|
|
mess = _('unable to determine previous changeset hash')
|
2016-03-22 20:45:57 +03:00
|
|
|
raise error.Abort(mess)
|
|
|
|
|
2017-12-14 21:28:30 +03:00
|
|
|
rev = str(rev['hash'])
|
2018-02-23 20:36:39 +03:00
|
|
|
opts['rev'] = [rev, targetrev]
|
2016-03-22 20:45:57 +03:00
|
|
|
|
|
|
|
# if patterns aren't provided, restrict diff to files in both changesets
|
|
|
|
# this prevents performing a diff on rebased changes
|
|
|
|
if len(pats) == 0:
|
|
|
|
prev = set(repo.unfiltered()[rev].files())
|
2018-02-23 20:36:39 +03:00
|
|
|
curr = set(repo[targetrev].files())
|
2017-01-20 11:24:45 +03:00
|
|
|
pats = tuple(os.path.join(repo.root, p) for p in prev | curr)
|
2016-03-22 20:45:57 +03:00
|
|
|
|
|
|
|
return orig(ui, repo, *pats, **opts)
|