contrib/phabricator.py
author Augie Fackler <augie@google.com>
Sat, 14 Apr 2018 11:20:38 -0400
changeset 37715 1859b9a7ddef
parent 37120 a8a902d7176e
child 37800 6cf5f5b4eb57
permissions -rw-r--r--
cleanup: polyfill assertRaisesRegex so we can avoid assertRaisesRegexp The latter is deprecated on Python 3.7 and causes our tests to fail due to the warning. Differential Revision: https://phab.mercurial-scm.org/D3375
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
     1
# phabricator.py - simple Phabricator integration
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
     2
#
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
     3
# Copyright 2017 Facebook, Inc.
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
     4
#
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms of the
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
     6
# GNU General Public License version 2 or any later version.
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
     7
"""simple Phabricator integration
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
     8
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
     9
This extension provides a ``phabsend`` command which sends a stack of
33975
07ffff841863 phabsend: make --amend the default
Jun Wu <quark@fb.com>
parents: 33974
diff changeset
    10
changesets to Phabricator, and a ``phabread`` command which prints a stack of
07ffff841863 phabsend: make --amend the default
Jun Wu <quark@fb.com>
parents: 33974
diff changeset
    11
revisions in a format suitable for :hg:`import`, and a ``phabupdate`` command
07ffff841863 phabsend: make --amend the default
Jun Wu <quark@fb.com>
parents: 33974
diff changeset
    12
to update statuses in batch.
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
    13
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
    14
By default, Phabricator requires ``Test Plan`` which might prevent some
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
    15
changeset from being sent. The requirement could be disabled by changing
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
    16
``differential.require-test-plan-field`` config server side.
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
    17
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    18
Config::
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    19
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    20
    [phabricator]
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    21
    # Phabricator URL
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    22
    url = https://phab.example.com/
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    23
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    24
    # API token. Get it from https://$HOST/conduit/login/
36818
f8b65ff02e3e phabricator: update doc string for deprecated token argument
Joerg Sonnenberger <joerg@bec.de>
parents: 36817
diff changeset
    25
    # Deprecated: see [phabricator.auth] below
f8b65ff02e3e phabricator: update doc string for deprecated token argument
Joerg Sonnenberger <joerg@bec.de>
parents: 36817
diff changeset
    26
    #token = cli-xxxxxxxxxxxxxxxxxxxxxxxxxxxx
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
    27
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
    28
    # Repo callsign. If a repo has a URL https://$HOST/diffusion/FOO, then its
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
    29
    # callsign is "FOO".
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
    30
    callsign = FOO
33200
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
    31
34064
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34063
diff changeset
    32
    # curl command to use. If not set (default), use builtin HTTP library to
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34063
diff changeset
    33
    # communicate. If set, use the specified curl command. This could be useful
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34063
diff changeset
    34
    # if you need to specify advanced options that is not easily supported by
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34063
diff changeset
    35
    # the internal library.
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34063
diff changeset
    36
    curlcmd = curl --connect-timeout 2 --retry 3 --silent
36787
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
    37
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
    38
    [phabricator.auth]
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
    39
    example.url = https://phab.example.com/
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
    40
    # API token. Get it from https://$HOST/conduit/login/
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
    41
    example.token = cli-xxxxxxxxxxxxxxxxxxxxxxxxxxxx
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    42
"""
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    43
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    44
from __future__ import absolute_import
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    45
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
    46
import itertools
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    47
import json
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
    48
import operator
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
    49
import re
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    50
33443
e48082e0a8d5 phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents: 33442
diff changeset
    51
from mercurial.node import bin, nullid
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    52
from mercurial.i18n import _
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    53
from mercurial import (
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
    54
    cmdutil,
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
    55
    context,
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
    56
    encoding,
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    57
    error,
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
    58
    mdiff,
33735
e6d8ee3c9ec3 obsutil: rename allprecursors into allpredecessors
Boris Feld <boris.feld@octobus.net>
parents: 33692
diff changeset
    59
    obsutil,
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
    60
    parser,
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
    61
    patch,
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    62
    registrar,
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
    63
    scmutil,
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
    64
    smartset,
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
    65
    tags,
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    66
    url as urlmod,
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    67
    util,
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    68
)
37120
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36818
diff changeset
    69
from mercurial.utils import (
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36818
diff changeset
    70
    procutil,
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36818
diff changeset
    71
)
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    72
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    73
cmdtable = {}
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    74
command = registrar.command(cmdtable)
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    75
34063
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
    76
colortable = {
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
    77
    'phabricator.action.created': 'green',
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
    78
    'phabricator.action.skipped': 'magenta',
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
    79
    'phabricator.action.updated': 'magenta',
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
    80
    'phabricator.desc': '',
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
    81
    'phabricator.drev': 'bold',
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
    82
    'phabricator.node': '',
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
    83
}
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
    84
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    85
def urlencodenested(params):
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    86
    """like urlencode, but works with nested parameters.
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    87
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    88
    For example, if params is {'a': ['b', 'c'], 'd': {'e': 'f'}}, it will be
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    89
    flattened to {'a[0]': 'b', 'a[1]': 'c', 'd[e]': 'f'} and then passed to
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    90
    urlencode. Note: the encoding is consistent with PHP's http_build_query.
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    91
    """
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    92
    flatparams = util.sortdict()
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    93
    def process(prefix, obj):
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    94
        items = {list: enumerate, dict: lambda x: x.items()}.get(type(obj))
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    95
        if items is None:
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    96
            flatparams[prefix] = obj
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    97
        else:
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    98
            for k, v in items(obj):
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    99
                if prefix:
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   100
                    process('%s[%s]' % (prefix, k), v)
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   101
                else:
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   102
                    process(k, v)
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   103
    process('', params)
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   104
    return util.urlreq.urlencode(flatparams)
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   105
36817
98cbfbbe33bb phabricator: print deprecation warning only once
Joerg Sonnenberger <joerg@bec.de>
parents: 36788
diff changeset
   106
printed_token_warning = False
98cbfbbe33bb phabricator: print deprecation warning only once
Joerg Sonnenberger <joerg@bec.de>
parents: 36788
diff changeset
   107
36788
b434965f984e phabricator: follow-up phab auth improvements with backwards compat mode
Augie Fackler <augie@google.com>
parents: 36787
diff changeset
   108
def readlegacytoken(repo):
b434965f984e phabricator: follow-up phab auth improvements with backwards compat mode
Augie Fackler <augie@google.com>
parents: 36787
diff changeset
   109
    """Transitional support for old phabricator tokens.
b434965f984e phabricator: follow-up phab auth improvements with backwards compat mode
Augie Fackler <augie@google.com>
parents: 36787
diff changeset
   110
b434965f984e phabricator: follow-up phab auth improvements with backwards compat mode
Augie Fackler <augie@google.com>
parents: 36787
diff changeset
   111
    Remove before the 4.6 release.
b434965f984e phabricator: follow-up phab auth improvements with backwards compat mode
Augie Fackler <augie@google.com>
parents: 36787
diff changeset
   112
    """
36817
98cbfbbe33bb phabricator: print deprecation warning only once
Joerg Sonnenberger <joerg@bec.de>
parents: 36788
diff changeset
   113
    global printed_token_warning
36788
b434965f984e phabricator: follow-up phab auth improvements with backwards compat mode
Augie Fackler <augie@google.com>
parents: 36787
diff changeset
   114
    token = repo.ui.config('phabricator', 'token')
36817
98cbfbbe33bb phabricator: print deprecation warning only once
Joerg Sonnenberger <joerg@bec.de>
parents: 36788
diff changeset
   115
    if token and not printed_token_warning:
98cbfbbe33bb phabricator: print deprecation warning only once
Joerg Sonnenberger <joerg@bec.de>
parents: 36788
diff changeset
   116
        printed_token_warning = True
36788
b434965f984e phabricator: follow-up phab auth improvements with backwards compat mode
Augie Fackler <augie@google.com>
parents: 36787
diff changeset
   117
        repo.ui.warn(_('phabricator.token is deprecated - please '
b434965f984e phabricator: follow-up phab auth improvements with backwards compat mode
Augie Fackler <augie@google.com>
parents: 36787
diff changeset
   118
                       'migrate to the phabricator.auth section.\n'))
b434965f984e phabricator: follow-up phab auth improvements with backwards compat mode
Augie Fackler <augie@google.com>
parents: 36787
diff changeset
   119
    return token
b434965f984e phabricator: follow-up phab auth improvements with backwards compat mode
Augie Fackler <augie@google.com>
parents: 36787
diff changeset
   120
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   121
def readurltoken(repo):
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   122
    """return conduit url, token and make sure they exist
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   123
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   124
    Currently read from [phabricator] config section. In the future, it might
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   125
    make sense to read from .arcconfig and .arcrc as well.
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   126
    """
36787
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   127
    url = repo.ui.config('phabricator', 'url')
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   128
    if not url:
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   129
        raise error.Abort(_('config %s.%s is required')
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   130
                          % ('phabricator', 'url'))
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   131
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   132
    groups = {}
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   133
    for key, val in repo.ui.configitems('phabricator.auth'):
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   134
        if '.' not in key:
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   135
            repo.ui.warn(_("ignoring invalid [phabricator.auth] key '%s'\n")
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   136
                         % key)
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   137
            continue
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   138
        group, setting = key.rsplit('.', 1)
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   139
        groups.setdefault(group, {})[setting] = val
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   140
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   141
    token = None
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   142
    for group, auth in groups.iteritems():
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   143
        if url != auth.get('url'):
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   144
            continue
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   145
        token = auth.get('token')
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   146
        if token:
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   147
            break
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   148
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   149
    if not token:
36788
b434965f984e phabricator: follow-up phab auth improvements with backwards compat mode
Augie Fackler <augie@google.com>
parents: 36787
diff changeset
   150
        token = readlegacytoken(repo)
b434965f984e phabricator: follow-up phab auth improvements with backwards compat mode
Augie Fackler <augie@google.com>
parents: 36787
diff changeset
   151
        if not token:
b434965f984e phabricator: follow-up phab auth improvements with backwards compat mode
Augie Fackler <augie@google.com>
parents: 36787
diff changeset
   152
            raise error.Abort(_('Can\'t find conduit token associated to %s')
b434965f984e phabricator: follow-up phab auth improvements with backwards compat mode
Augie Fackler <augie@google.com>
parents: 36787
diff changeset
   153
                              % (url,))
36787
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   154
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   155
    return url, token
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   156
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   157
def callconduit(repo, name, params):
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   158
    """call Conduit API, params is a dict. return json.loads result, or None"""
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   159
    host, token = readurltoken(repo)
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   160
    url, authinfo = util.url('/'.join([host, 'api', name])).authinfo()
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   161
    repo.ui.debug('Conduit Call: %s %s\n' % (url, params))
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   162
    params = params.copy()
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   163
    params['api.token'] = token
34064
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34063
diff changeset
   164
    data = urlencodenested(params)
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34063
diff changeset
   165
    curlcmd = repo.ui.config('phabricator', 'curlcmd')
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34063
diff changeset
   166
    if curlcmd:
37120
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36818
diff changeset
   167
        sin, sout = procutil.popen2('%s -d @- %s'
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36818
diff changeset
   168
                                    % (curlcmd, procutil.shellquote(url)))
34064
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34063
diff changeset
   169
        sin.write(data)
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34063
diff changeset
   170
        sin.close()
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34063
diff changeset
   171
        body = sout.read()
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34063
diff changeset
   172
    else:
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34063
diff changeset
   173
        urlopener = urlmod.opener(repo.ui, authinfo)
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34063
diff changeset
   174
        request = util.urlreq.request(url, data=data)
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34063
diff changeset
   175
        body = urlopener.open(request).read()
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   176
    repo.ui.debug('Conduit Response: %s\n' % body)
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   177
    parsed = json.loads(body)
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   178
    if parsed.get(r'error_code'):
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   179
        msg = (_('Conduit Error (%s): %s')
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   180
               % (parsed[r'error_code'], parsed[r'error_info']))
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   181
        raise error.Abort(msg)
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   182
    return parsed[r'result']
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   183
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   184
@command('debugcallconduit', [], _('METHOD'))
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   185
def debugcallconduit(ui, repo, name):
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   186
    """call Conduit API
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   187
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   188
    Call parameters are read from stdin as a JSON blob. Result will be written
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   189
    to stdout as a JSON blob.
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   190
    """
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   191
    params = json.loads(ui.fin.read())
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   192
    result = callconduit(repo, name, params)
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   193
    s = json.dumps(result, sort_keys=True, indent=2, separators=(',', ': '))
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   194
    ui.write('%s\n' % s)
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   195
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   196
def getrepophid(repo):
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   197
    """given callsign, return repository PHID or None"""
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   198
    # developer config: phabricator.repophid
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   199
    repophid = repo.ui.config('phabricator', 'repophid')
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   200
    if repophid:
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   201
        return repophid
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   202
    callsign = repo.ui.config('phabricator', 'callsign')
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   203
    if not callsign:
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   204
        return None
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   205
    query = callconduit(repo, 'diffusion.repository.search',
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   206
                        {'constraints': {'callsigns': [callsign]}})
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   207
    if len(query[r'data']) == 0:
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   208
        return None
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   209
    repophid = encoding.strtolocal(query[r'data'][0][r'phid'])
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   210
    repo.ui.setconfig('phabricator', 'repophid', repophid)
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   211
    return repophid
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   212
33263
ed61189763ef phabricator: check associated Differential Revision from commit message
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   213
_differentialrevisiontagre = re.compile('\AD([1-9][0-9]*)\Z')
ed61189763ef phabricator: check associated Differential Revision from commit message
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   214
_differentialrevisiondescre = re.compile(
35626
a0d33f4ddff9 phabricator: use named group for parsing differential reviews lines
Tom Prince <mozilla@hocat.ca>
parents: 34064
diff changeset
   215
    '^Differential Revision:\s*(?P<url>(?:.*)D(?P<id>[1-9][0-9]*))$', re.M)
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   216
33442
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   217
def getoldnodedrevmap(repo, nodelist):
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   218
    """find previous nodes that has been sent to Phabricator
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   219
33691
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   220
    return {node: (oldnode, Differential diff, Differential Revision ID)}
33442
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   221
    for node in nodelist with known previous sent versions, or associated
33691
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   222
    Differential Revision IDs. ``oldnode`` and ``Differential diff`` could
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   223
    be ``None``.
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   224
33691
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   225
    Examines commit messages like "Differential Revision:" to get the
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   226
    association information.
33263
ed61189763ef phabricator: check associated Differential Revision from commit message
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   227
33691
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   228
    If such commit message line is not found, examines all precursors and their
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   229
    tags. Tags with format like "D1234" are considered a match and the node
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   230
    with that tag, and the number after "D" (ex. 1234) will be returned.
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   231
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   232
    The ``old node``, if not None, is guaranteed to be the last diff of
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   233
    corresponding Differential Revision, and exist in the repo.
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   234
    """
33442
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   235
    url, token = readurltoken(repo)
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   236
    unfi = repo.unfiltered()
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   237
    nodemap = unfi.changelog.nodemap
33263
ed61189763ef phabricator: check associated Differential Revision from commit message
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   238
33691
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   239
    result = {} # {node: (oldnode?, lastdiff?, drev)}
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   240
    toconfirm = {} # {node: (force, {precnode}, drev)}
33442
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   241
    for node in nodelist:
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   242
        ctx = unfi[node]
33443
e48082e0a8d5 phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents: 33442
diff changeset
   243
        # For tags like "D123", put them into "toconfirm" to verify later
33735
e6d8ee3c9ec3 obsutil: rename allprecursors into allpredecessors
Boris Feld <boris.feld@octobus.net>
parents: 33692
diff changeset
   244
        precnodes = list(obsutil.allpredecessors(unfi.obsstore, [node]))
33443
e48082e0a8d5 phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents: 33442
diff changeset
   245
        for n in precnodes:
33442
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   246
            if n in nodemap:
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   247
                for tag in unfi.nodetags(n):
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   248
                    m = _differentialrevisiontagre.match(tag)
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   249
                    if m:
33691
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   250
                        toconfirm[node] = (0, set(precnodes), int(m.group(1)))
33442
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   251
                        continue
33263
ed61189763ef phabricator: check associated Differential Revision from commit message
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   252
33691
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   253
        # Check commit message
33442
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   254
        m = _differentialrevisiondescre.search(ctx.description())
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   255
        if m:
35626
a0d33f4ddff9 phabricator: use named group for parsing differential reviews lines
Tom Prince <mozilla@hocat.ca>
parents: 34064
diff changeset
   256
            toconfirm[node] = (1, set(precnodes), int(m.group('id')))
33263
ed61189763ef phabricator: check associated Differential Revision from commit message
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   257
33443
e48082e0a8d5 phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents: 33442
diff changeset
   258
    # Double check if tags are genuine by collecting all old nodes from
e48082e0a8d5 phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents: 33442
diff changeset
   259
    # Phabricator, and expect precursors overlap with it.
e48082e0a8d5 phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents: 33442
diff changeset
   260
    if toconfirm:
33691
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   261
        drevs = [drev for force, precs, drev in toconfirm.values()]
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   262
        alldiffs = callconduit(unfi, 'differential.querydiffs',
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   263
                               {'revisionIDs': drevs})
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   264
        getnode = lambda d: bin(encoding.unitolocal(
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   265
            getdiffmeta(d).get(r'node', ''))) or None
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   266
        for newnode, (force, precset, drev) in toconfirm.items():
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   267
            diffs = [d for d in alldiffs.values()
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   268
                     if int(d[r'revisionID']) == drev]
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   269
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   270
            # "precursors" as known by Phabricator
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   271
            phprecset = set(getnode(d) for d in diffs)
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   272
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   273
            # Ignore if precursors (Phabricator and local repo) do not overlap,
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   274
            # and force is not set (when commit message says nothing)
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   275
            if not force and not bool(phprecset & precset):
33443
e48082e0a8d5 phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents: 33442
diff changeset
   276
                tagname = 'D%d' % drev
e48082e0a8d5 phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents: 33442
diff changeset
   277
                tags.tag(repo, tagname, nullid, message=None, user=None,
e48082e0a8d5 phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents: 33442
diff changeset
   278
                         date=None, local=True)
e48082e0a8d5 phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents: 33442
diff changeset
   279
                unfi.ui.warn(_('D%s: local tag removed - does not match '
e48082e0a8d5 phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents: 33442
diff changeset
   280
                               'Differential history\n') % drev)
33691
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   281
                continue
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   282
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   283
            # Find the last node using Phabricator metadata, and make sure it
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   284
            # exists in the repo
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   285
            oldnode = lastdiff = None
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   286
            if diffs:
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   287
                lastdiff = max(diffs, key=lambda d: int(d[r'id']))
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   288
                oldnode = getnode(lastdiff)
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   289
                if oldnode and oldnode not in nodemap:
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   290
                    oldnode = None
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   291
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   292
            result[newnode] = (oldnode, lastdiff, drev)
33443
e48082e0a8d5 phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents: 33442
diff changeset
   293
33442
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   294
    return result
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   295
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   296
def getdiff(ctx, diffopts):
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   297
    """plain-text diff without header (user, commit message, etc)"""
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   298
    output = util.stringio()
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   299
    for chunk, _label in patch.diffui(ctx.repo(), ctx.p1().node(), ctx.node(),
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   300
                                      None, opts=diffopts):
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   301
        output.write(chunk)
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   302
    return output.getvalue()
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   303
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   304
def creatediff(ctx):
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   305
    """create a Differential Diff"""
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   306
    repo = ctx.repo()
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   307
    repophid = getrepophid(repo)
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   308
    # Create a "Differential Diff" via "differential.createrawdiff" API
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   309
    params = {'diff': getdiff(ctx, mdiff.diffopts(git=True, context=32767))}
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   310
    if repophid:
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   311
        params['repositoryPHID'] = repophid
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   312
    diff = callconduit(repo, 'differential.createrawdiff', params)
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   313
    if not diff:
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   314
        raise error.Abort(_('cannot create diff for %s') % ctx)
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   315
    return diff
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   316
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   317
def writediffproperties(ctx, diff):
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   318
    """write metadata to diff so patches could be applied losslessly"""
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   319
    params = {
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   320
        'diff_id': diff[r'id'],
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   321
        'name': 'hg:meta',
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   322
        'data': json.dumps({
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   323
            'user': ctx.user(),
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   324
            'date': '%d %d' % ctx.date(),
33264
266321579c68 phabricator: add node and p1 to hg:meta property
Jun Wu <quark@fb.com>
parents: 33263
diff changeset
   325
            'node': ctx.hex(),
266321579c68 phabricator: add node and p1 to hg:meta property
Jun Wu <quark@fb.com>
parents: 33263
diff changeset
   326
            'parent': ctx.p1().hex(),
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   327
        }),
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   328
    }
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   329
    callconduit(ctx.repo(), 'differential.setdiffproperty', params)
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   330
33498
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   331
def createdifferentialrevision(ctx, revid=None, parentrevid=None, oldnode=None,
33692
f100354cce52 phabricator: update diff property even if we choose not to create a new diff
Jun Wu <quark@fb.com>
parents: 33691
diff changeset
   332
                               olddiff=None, actions=None):
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   333
    """create or update a Differential Revision
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   334
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   335
    If revid is None, create a new Differential Revision, otherwise update
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   336
    revid. If parentrevid is not None, set it as a dependency.
33265
95f658b558a3 phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents: 33264
diff changeset
   337
95f658b558a3 phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents: 33264
diff changeset
   338
    If oldnode is not None, check if the patch content (without commit message
95f658b558a3 phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents: 33264
diff changeset
   339
    and metadata) has changed before creating another diff.
33498
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   340
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   341
    If actions is not None, they will be appended to the transaction.
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   342
    """
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   343
    repo = ctx.repo()
33265
95f658b558a3 phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents: 33264
diff changeset
   344
    if oldnode:
33976
27ff2a87d8c0 phabsend: detect patch change with larger context
Jun Wu <quark@fb.com>
parents: 33975
diff changeset
   345
        diffopts = mdiff.diffopts(git=True, context=32767)
33265
95f658b558a3 phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents: 33264
diff changeset
   346
        oldctx = repo.unfiltered()[oldnode]
95f658b558a3 phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents: 33264
diff changeset
   347
        neednewdiff = (getdiff(ctx, diffopts) != getdiff(oldctx, diffopts))
95f658b558a3 phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents: 33264
diff changeset
   348
    else:
95f658b558a3 phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents: 33264
diff changeset
   349
        neednewdiff = True
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   350
33265
95f658b558a3 phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents: 33264
diff changeset
   351
    transactions = []
95f658b558a3 phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents: 33264
diff changeset
   352
    if neednewdiff:
95f658b558a3 phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents: 33264
diff changeset
   353
        diff = creatediff(ctx)
95f658b558a3 phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents: 33264
diff changeset
   354
        transactions.append({'type': 'update', 'value': diff[r'phid']})
33692
f100354cce52 phabricator: update diff property even if we choose not to create a new diff
Jun Wu <quark@fb.com>
parents: 33691
diff changeset
   355
    else:
f100354cce52 phabricator: update diff property even if we choose not to create a new diff
Jun Wu <quark@fb.com>
parents: 33691
diff changeset
   356
        # Even if we don't need to upload a new diff because the patch content
f100354cce52 phabricator: update diff property even if we choose not to create a new diff
Jun Wu <quark@fb.com>
parents: 33691
diff changeset
   357
        # does not change. We might still need to update its metadata so
f100354cce52 phabricator: update diff property even if we choose not to create a new diff
Jun Wu <quark@fb.com>
parents: 33691
diff changeset
   358
        # pushers could know the correct node metadata.
f100354cce52 phabricator: update diff property even if we choose not to create a new diff
Jun Wu <quark@fb.com>
parents: 33691
diff changeset
   359
        assert olddiff
f100354cce52 phabricator: update diff property even if we choose not to create a new diff
Jun Wu <quark@fb.com>
parents: 33691
diff changeset
   360
        diff = olddiff
f100354cce52 phabricator: update diff property even if we choose not to create a new diff
Jun Wu <quark@fb.com>
parents: 33691
diff changeset
   361
    writediffproperties(ctx, diff)
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   362
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   363
    # Use a temporary summary to set dependency. There might be better ways but
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   364
    # I cannot find them for now. But do not do that if we are updating an
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   365
    # existing revision (revid is not None) since that introduces visible
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   366
    # churns (someone edited "Summary" twice) on the web page.
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   367
    if parentrevid and revid is None:
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   368
        summary = 'Depends on D%s' % parentrevid
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   369
        transactions += [{'type': 'summary', 'value': summary},
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   370
                         {'type': 'summary', 'value': ' '}]
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   371
33498
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   372
    if actions:
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   373
        transactions += actions
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   374
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   375
    # Parse commit message and update related fields.
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   376
    desc = ctx.description()
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   377
    info = callconduit(repo, 'differential.parsecommitmessage',
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   378
                       {'corpus': desc})
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   379
    for k, v in info[r'fields'].items():
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   380
        if k in ['title', 'summary', 'testPlan']:
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   381
            transactions.append({'type': k, 'value': v})
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   382
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   383
    params = {'transactions': transactions}
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   384
    if revid is not None:
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   385
        # Update an existing Differential Revision
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   386
        params['objectIdentifier'] = revid
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   387
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   388
    revision = callconduit(repo, 'differential.revision.edit', params)
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   389
    if not revision:
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   390
        raise error.Abort(_('cannot create revision for %s') % ctx)
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   391
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   392
    return revision, diff
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   393
33498
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   394
def userphids(repo, names):
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   395
    """convert user names to PHIDs"""
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   396
    query = {'constraints': {'usernames': names}}
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   397
    result = callconduit(repo, 'user.search', query)
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   398
    # username not found is not an error of the API. So check if we have missed
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   399
    # some names here.
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   400
    data = result[r'data']
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   401
    resolved = set(entry[r'fields'][r'username'] for entry in data)
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   402
    unresolved = set(names) - resolved
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   403
    if unresolved:
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   404
        raise error.Abort(_('unknown username: %s')
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   405
                          % ' '.join(sorted(unresolved)))
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   406
    return [entry[r'phid'] for entry in data]
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   407
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   408
@command('phabsend',
33498
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   409
         [('r', 'rev', [], _('revisions to send'), _('REV')),
33975
07ffff841863 phabsend: make --amend the default
Jun Wu <quark@fb.com>
parents: 33974
diff changeset
   410
          ('', 'amend', True, _('update commit messages')),
33690
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   411
          ('', 'reviewer', [], _('specify reviewers')),
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   412
          ('', 'confirm', None, _('ask for confirmation before sending'))],
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   413
         _('REV [OPTIONS]'))
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   414
def phabsend(ui, repo, *revs, **opts):
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   415
    """upload changesets to Phabricator
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   416
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   417
    If there are multiple revisions specified, they will be send as a stack
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   418
    with a linear dependencies relationship using the order specified by the
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   419
    revset.
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   420
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   421
    For the first time uploading changesets, local tags will be created to
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   422
    maintain the association. After the first time, phabsend will check
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   423
    obsstore and tags information so it can figure out whether to update an
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   424
    existing Differential Revision, or create a new one.
33690
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   425
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   426
    If --amend is set, update commit messages so they have the
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   427
    ``Differential Revision`` URL, remove related tags. This is similar to what
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   428
    arcanist will do, and is more desired in author-push workflows. Otherwise,
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   429
    use local tags to record the ``Differential Revision`` association.
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   430
33690
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   431
    The --confirm option lets you confirm changesets before sending them. You
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   432
    can also add following to your configuration file to make it default
33974
45a8cd74de4e phabsend: polish the docstring a bit
Jun Wu <quark@fb.com>
parents: 33834
diff changeset
   433
    behaviour::
33690
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   434
33974
45a8cd74de4e phabsend: polish the docstring a bit
Jun Wu <quark@fb.com>
parents: 33834
diff changeset
   435
        [phabsend]
45a8cd74de4e phabsend: polish the docstring a bit
Jun Wu <quark@fb.com>
parents: 33834
diff changeset
   436
        confirm = true
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   437
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   438
    phabsend will check obsstore and the above association to decide whether to
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   439
    update an existing Differential Revision, or create a new one.
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   440
    """
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   441
    revs = list(revs) + opts.get('rev', [])
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   442
    revs = scmutil.revrange(repo, revs)
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   443
33266
5b2391b46906 phabricator: abort if phabsend gets empty revs
Jun Wu <quark@fb.com>
parents: 33265
diff changeset
   444
    if not revs:
5b2391b46906 phabricator: abort if phabsend gets empty revs
Jun Wu <quark@fb.com>
parents: 33265
diff changeset
   445
        raise error.Abort(_('phabsend requires at least one changeset'))
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   446
    if opts.get('amend'):
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   447
        cmdutil.checkunfinished(repo)
33266
5b2391b46906 phabricator: abort if phabsend gets empty revs
Jun Wu <quark@fb.com>
parents: 33265
diff changeset
   448
33978
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33977
diff changeset
   449
    # {newnode: (oldnode, olddiff, olddrev}
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33977
diff changeset
   450
    oldmap = getoldnodedrevmap(repo, [repo[r].node() for r in revs])
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33977
diff changeset
   451
33690
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   452
    confirm = ui.configbool('phabsend', 'confirm')
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   453
    confirm |= bool(opts.get('confirm'))
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   454
    if confirm:
33978
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33977
diff changeset
   455
        confirmed = _confirmbeforesend(repo, revs, oldmap)
33690
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   456
        if not confirmed:
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   457
            raise error.Abort(_('phabsend cancelled'))
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   458
33498
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   459
    actions = []
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   460
    reviewers = opts.get('reviewer', [])
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   461
    if reviewers:
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   462
        phids = userphids(repo, reviewers)
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   463
        actions.append({'type': 'reviewers.add', 'value': phids})
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   464
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   465
    drevids = [] # [int]
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   466
    diffmap = {} # {newnode: diff}
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   467
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   468
    # Send patches one by one so we know their Differential Revision IDs and
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   469
    # can provide dependency relationship
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   470
    lastrevid = None
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   471
    for rev in revs:
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   472
        ui.debug('sending rev %d\n' % rev)
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   473
        ctx = repo[rev]
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   474
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   475
        # Get Differential Revision ID
33691
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   476
        oldnode, olddiff, revid = oldmap.get(ctx.node(), (None, None, None))
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   477
        if oldnode != ctx.node() or opts.get('amend'):
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   478
            # Create or update Differential Revision
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   479
            revision, diff = createdifferentialrevision(
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   480
                ctx, revid, lastrevid, oldnode, olddiff, actions)
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   481
            diffmap[ctx.node()] = diff
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   482
            newrevid = int(revision[r'object'][r'id'])
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   483
            if revid:
34063
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
   484
                action = 'updated'
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   485
            else:
34063
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
   486
                action = 'created'
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   487
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   488
            # Create a local tag to note the association, if commit message
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   489
            # does not have it already
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   490
            m = _differentialrevisiondescre.search(ctx.description())
35626
a0d33f4ddff9 phabricator: use named group for parsing differential reviews lines
Tom Prince <mozilla@hocat.ca>
parents: 34064
diff changeset
   491
            if not m or int(m.group('id')) != newrevid:
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   492
                tagname = 'D%d' % newrevid
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   493
                tags.tag(repo, tagname, ctx.node(), message=None, user=None,
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   494
                         date=None, local=True)
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   495
        else:
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   496
            # Nothing changed. But still set "newrevid" so the next revision
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   497
            # could depend on this one.
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   498
            newrevid = revid
34063
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
   499
            action = 'skipped'
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   500
34063
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
   501
        actiondesc = ui.label(
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
   502
            {'created': _('created'),
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
   503
             'skipped': _('skipped'),
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
   504
             'updated': _('updated')}[action],
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
   505
            'phabricator.action.%s' % action)
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
   506
        drevdesc = ui.label('D%s' % newrevid, 'phabricator.drev')
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
   507
        nodedesc = ui.label(bytes(ctx), 'phabricator.node')
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
   508
        desc = ui.label(ctx.description().split('\n')[0], 'phabricator.desc')
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
   509
        ui.write(_('%s - %s - %s: %s\n') % (drevdesc, actiondesc, nodedesc,
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
   510
                                            desc))
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   511
        drevids.append(newrevid)
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   512
        lastrevid = newrevid
33200
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
   513
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   514
    # Update commit messages and remove tags
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   515
    if opts.get('amend'):
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   516
        unfi = repo.unfiltered()
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   517
        drevs = callconduit(repo, 'differential.query', {'ids': drevids})
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   518
        with repo.wlock(), repo.lock(), repo.transaction('phabsend'):
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   519
            wnode = unfi['.'].node()
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   520
            mapping = {} # {oldnode: [newnode]}
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   521
            for i, rev in enumerate(revs):
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   522
                old = unfi[rev]
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   523
                drevid = drevids[i]
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   524
                drev = [d for d in drevs if int(d[r'id']) == drevid][0]
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   525
                newdesc = getdescfromdrev(drev)
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   526
                # Make sure commit message contain "Differential Revision"
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   527
                if old.description() != newdesc:
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   528
                    parents = [
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   529
                        mapping.get(old.p1().node(), (old.p1(),))[0],
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   530
                        mapping.get(old.p2().node(), (old.p2(),))[0],
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   531
                    ]
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   532
                    new = context.metadataonlyctx(
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   533
                        repo, old, parents=parents, text=newdesc,
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   534
                        user=old.user(), date=old.date(), extra=old.extra())
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   535
                    newnode = new.commit()
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   536
                    mapping[old.node()] = [newnode]
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   537
                    # Update diff property
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   538
                    writediffproperties(unfi[newnode], diffmap[old.node()])
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   539
                # Remove local tags since it's no longer necessary
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   540
                tagname = 'D%d' % drevid
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   541
                if tagname in repo.tags():
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   542
                    tags.tag(repo, tagname, nullid, message=None, user=None,
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   543
                             date=None, local=True)
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   544
            scmutil.cleanupnodes(repo, mapping, 'phabsend')
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   545
            if wnode in mapping:
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   546
                unfi.setparents(mapping[wnode][0])
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   547
33264
266321579c68 phabricator: add node and p1 to hg:meta property
Jun Wu <quark@fb.com>
parents: 33263
diff changeset
   548
# Map from "hg:meta" keys to header understood by "hg import". The order is
266321579c68 phabricator: add node and p1 to hg:meta property
Jun Wu <quark@fb.com>
parents: 33263
diff changeset
   549
# consistent with "hg export" output.
266321579c68 phabricator: add node and p1 to hg:meta property
Jun Wu <quark@fb.com>
parents: 33263
diff changeset
   550
_metanamemap = util.sortdict([(r'user', 'User'), (r'date', 'Date'),
266321579c68 phabricator: add node and p1 to hg:meta property
Jun Wu <quark@fb.com>
parents: 33263
diff changeset
   551
                              (r'node', 'Node ID'), (r'parent', 'Parent ')])
266321579c68 phabricator: add node and p1 to hg:meta property
Jun Wu <quark@fb.com>
parents: 33263
diff changeset
   552
33978
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33977
diff changeset
   553
def _confirmbeforesend(repo, revs, oldmap):
33977
edeb8f28c031 phabsend: print the actual URL with --confirm
Jun Wu <quark@fb.com>
parents: 33976
diff changeset
   554
    url, token = readurltoken(repo)
33690
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   555
    ui = repo.ui
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   556
    for rev in revs:
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   557
        ctx = repo[rev]
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   558
        desc = ctx.description().splitlines()[0]
33978
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33977
diff changeset
   559
        oldnode, olddiff, drevid = oldmap.get(ctx.node(), (None, None, None))
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33977
diff changeset
   560
        if drevid:
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33977
diff changeset
   561
            drevdesc = ui.label('D%s' % drevid, 'phabricator.drev')
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33977
diff changeset
   562
        else:
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33977
diff changeset
   563
            drevdesc = ui.label(_('NEW'), 'phabricator.drev')
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33977
diff changeset
   564
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33977
diff changeset
   565
        ui.write(_('%s - %s: %s\n') % (drevdesc,
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33977
diff changeset
   566
                                       ui.label(bytes(ctx), 'phabricator.node'),
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33977
diff changeset
   567
                                       ui.label(desc, 'phabricator.desc')))
33690
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   568
33977
edeb8f28c031 phabsend: print the actual URL with --confirm
Jun Wu <quark@fb.com>
parents: 33976
diff changeset
   569
    if ui.promptchoice(_('Send the above changes to %s (yn)?'
edeb8f28c031 phabsend: print the actual URL with --confirm
Jun Wu <quark@fb.com>
parents: 33976
diff changeset
   570
                         '$$ &Yes $$ &No') % url):
33690
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   571
        return False
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   572
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   573
    return True
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   574
33833
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   575
_knownstatusnames = {'accepted', 'needsreview', 'needsrevision', 'closed',
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   576
                     'abandoned'}
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   577
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   578
def _getstatusname(drev):
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   579
    """get normalized status name from a Differential Revision"""
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   580
    return drev[r'statusName'].replace(' ', '').lower()
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   581
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   582
# Small language to specify differential revisions. Support symbols: (), :X,
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   583
# +, and -.
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   584
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   585
_elements = {
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   586
    # token-type: binding-strength, primary, prefix, infix, suffix
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   587
    '(':      (12, None, ('group', 1, ')'), None, None),
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   588
    ':':      (8, None, ('ancestors', 8), None, None),
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   589
    '&':      (5,  None, None, ('and_', 5), None),
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   590
    '+':      (4,  None, None, ('add', 4), None),
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   591
    '-':      (4,  None, None, ('sub', 4), None),
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   592
    ')':      (0,  None, None, None, None),
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   593
    'symbol': (0, 'symbol', None, None, None),
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   594
    'end':    (0, None, None, None, None),
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   595
}
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   596
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   597
def _tokenize(text):
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   598
    view = memoryview(text) # zero-copy slice
33833
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   599
    special = '():+-& '
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   600
    pos = 0
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   601
    length = len(text)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   602
    while pos < length:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   603
        symbol = ''.join(itertools.takewhile(lambda ch: ch not in special,
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   604
                                             view[pos:]))
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   605
        if symbol:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   606
            yield ('symbol', symbol, pos)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   607
            pos += len(symbol)
33833
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   608
        else: # special char, ignore space
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   609
            if text[pos] != ' ':
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   610
                yield (text[pos], None, pos)
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   611
            pos += 1
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   612
    yield ('end', None, pos)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   613
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   614
def _parse(text):
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   615
    tree, pos = parser.parser(_elements).parse(_tokenize(text))
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   616
    if pos != len(text):
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   617
        raise error.ParseError('invalid token', pos)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   618
    return tree
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   619
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   620
def _parsedrev(symbol):
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   621
    """str -> int or None, ex. 'D45' -> 45; '12' -> 12; 'x' -> None"""
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   622
    if symbol.startswith('D') and symbol[1:].isdigit():
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   623
        return int(symbol[1:])
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   624
    if symbol.isdigit():
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   625
        return int(symbol)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   626
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   627
def _prefetchdrevs(tree):
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   628
    """return ({single-drev-id}, {ancestor-drev-id}) to prefetch"""
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   629
    drevs = set()
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   630
    ancestordrevs = set()
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   631
    op = tree[0]
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   632
    if op == 'symbol':
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   633
        r = _parsedrev(tree[1])
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   634
        if r:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   635
            drevs.add(r)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   636
    elif op == 'ancestors':
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   637
        r, a = _prefetchdrevs(tree[1])
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   638
        drevs.update(r)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   639
        ancestordrevs.update(r)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   640
        ancestordrevs.update(a)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   641
    else:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   642
        for t in tree[1:]:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   643
            r, a = _prefetchdrevs(t)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   644
            drevs.update(r)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   645
            ancestordrevs.update(a)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   646
    return drevs, ancestordrevs
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   647
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   648
def querydrev(repo, spec):
33267
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   649
    """return a list of "Differential Revision" dicts
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   650
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   651
    spec is a string using a simple query language, see docstring in phabread
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   652
    for details.
33267
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   653
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   654
    A "Differential Revision dict" looks like:
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   655
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   656
        {
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   657
            "id": "2",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   658
            "phid": "PHID-DREV-672qvysjcczopag46qty",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   659
            "title": "example",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   660
            "uri": "https://phab.example.com/D2",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   661
            "dateCreated": "1499181406",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   662
            "dateModified": "1499182103",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   663
            "authorPHID": "PHID-USER-tv3ohwc4v4jeu34otlye",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   664
            "status": "0",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   665
            "statusName": "Needs Review",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   666
            "properties": [],
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   667
            "branch": null,
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   668
            "summary": "",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   669
            "testPlan": "",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   670
            "lineCount": "2",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   671
            "activeDiffPHID": "PHID-DIFF-xoqnjkobbm6k4dk6hi72",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   672
            "diffs": [
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   673
              "3",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   674
              "4",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   675
            ],
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   676
            "commits": [],
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   677
            "reviewers": [],
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   678
            "ccs": [],
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   679
            "hashes": [],
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   680
            "auxiliary": {
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   681
              "phabricator:projects": [],
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   682
              "phabricator:depends-on": [
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   683
                "PHID-DREV-gbapp366kutjebt7agcd"
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   684
              ]
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   685
            },
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   686
            "repositoryPHID": "PHID-REPO-hub2hx62ieuqeheznasv",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   687
            "sourcePath": null
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   688
        }
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   689
    """
33269
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   690
    def fetch(params):
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   691
        """params -> single drev or None"""
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   692
        key = (params.get(r'ids') or params.get(r'phids') or [None])[0]
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   693
        if key in prefetched:
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   694
            return prefetched[key]
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   695
        drevs = callconduit(repo, 'differential.query', params)
33269
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   696
        # Fill prefetched with the result
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   697
        for drev in drevs:
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   698
            prefetched[drev[r'phid']] = drev
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   699
            prefetched[int(drev[r'id'])] = drev
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   700
        if key not in prefetched:
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   701
            raise error.Abort(_('cannot get Differential Revision %r') % params)
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   702
        return prefetched[key]
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   703
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   704
    def getstack(topdrevids):
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   705
        """given a top, get a stack from the bottom, [id] -> [id]"""
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   706
        visited = set()
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   707
        result = []
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   708
        queue = [{r'ids': [i]} for i in topdrevids]
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   709
        while queue:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   710
            params = queue.pop()
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   711
            drev = fetch(params)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   712
            if drev[r'id'] in visited:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   713
                continue
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   714
            visited.add(drev[r'id'])
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   715
            result.append(int(drev[r'id']))
33267
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   716
            auxiliary = drev.get(r'auxiliary', {})
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   717
            depends = auxiliary.get(r'phabricator:depends-on', [])
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   718
            for phid in depends:
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   719
                queue.append({'phids': [phid]})
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   720
        result.reverse()
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   721
        return smartset.baseset(result)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   722
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   723
    # Initialize prefetch cache
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   724
    prefetched = {} # {id or phid: drev}
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   725
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   726
    tree = _parse(spec)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   727
    drevs, ancestordrevs = _prefetchdrevs(tree)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   728
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   729
    # developer config: phabricator.batchsize
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   730
    batchsize = repo.ui.configint('phabricator', 'batchsize', 12)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   731
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   732
    # Prefetch Differential Revisions in batch
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   733
    tofetch = set(drevs)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   734
    for r in ancestordrevs:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   735
        tofetch.update(range(max(1, r - batchsize), r + 1))
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   736
    if drevs:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   737
        fetch({r'ids': list(tofetch)})
33833
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   738
    validids = sorted(set(getstack(list(ancestordrevs))) | set(drevs))
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   739
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   740
    # Walk through the tree, return smartsets
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   741
    def walk(tree):
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   742
        op = tree[0]
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   743
        if op == 'symbol':
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   744
            drev = _parsedrev(tree[1])
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   745
            if drev:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   746
                return smartset.baseset([drev])
33833
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   747
            elif tree[1] in _knownstatusnames:
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   748
                drevs = [r for r in validids
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   749
                         if _getstatusname(prefetched[r]) == tree[1]]
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   750
                return smartset.baseset(drevs)
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   751
            else:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   752
                raise error.Abort(_('unknown symbol: %s') % tree[1])
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   753
        elif op in {'and_', 'add', 'sub'}:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   754
            assert len(tree) == 3
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   755
            return getattr(operator, op)(walk(tree[1]), walk(tree[2]))
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   756
        elif op == 'group':
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   757
            return walk(tree[1])
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   758
        elif op == 'ancestors':
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   759
            return getstack(walk(tree[1]))
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   760
        else:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   761
            raise error.ProgrammingError('illegal tree: %r' % tree)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   762
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   763
    return [prefetched[r] for r in walk(tree)]
33267
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   764
33268
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   765
def getdescfromdrev(drev):
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   766
    """get description (commit message) from "Differential Revision"
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   767
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   768
    This is similar to differential.getcommitmessage API. But we only care
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   769
    about limited fields: title, summary, test plan, and URL.
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   770
    """
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   771
    title = drev[r'title']
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   772
    summary = drev[r'summary'].rstrip()
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   773
    testplan = drev[r'testPlan'].rstrip()
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   774
    if testplan:
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   775
        testplan = 'Test Plan:\n%s' % testplan
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   776
    uri = 'Differential Revision: %s' % drev[r'uri']
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   777
    return '\n\n'.join(filter(None, [title, summary, testplan, uri]))
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   778
33441
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   779
def getdiffmeta(diff):
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   780
    """get commit metadata (date, node, user, p1) from a diff object
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   781
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   782
    The metadata could be "hg:meta", sent by phabsend, like:
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   783
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   784
        "properties": {
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   785
          "hg:meta": {
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   786
            "date": "1499571514 25200",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   787
            "node": "98c08acae292b2faf60a279b4189beb6cff1414d",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   788
            "user": "Foo Bar <foo@example.com>",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   789
            "parent": "6d0abad76b30e4724a37ab8721d630394070fe16"
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   790
          }
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   791
        }
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   792
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   793
    Or converted from "local:commits", sent by "arc", like:
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   794
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   795
        "properties": {
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   796
          "local:commits": {
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   797
            "98c08acae292b2faf60a279b4189beb6cff1414d": {
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   798
              "author": "Foo Bar",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   799
              "time": 1499546314,
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   800
              "branch": "default",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   801
              "tag": "",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   802
              "commit": "98c08acae292b2faf60a279b4189beb6cff1414d",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   803
              "rev": "98c08acae292b2faf60a279b4189beb6cff1414d",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   804
              "local": "1000",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   805
              "parents": ["6d0abad76b30e4724a37ab8721d630394070fe16"],
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   806
              "summary": "...",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   807
              "message": "...",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   808
              "authorEmail": "foo@example.com"
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   809
            }
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   810
          }
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   811
        }
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   812
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   813
    Note: metadata extracted from "local:commits" will lose time zone
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   814
    information.
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   815
    """
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   816
    props = diff.get(r'properties') or {}
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   817
    meta = props.get(r'hg:meta')
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   818
    if not meta and props.get(r'local:commits'):
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   819
        commit = sorted(props[r'local:commits'].values())[0]
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   820
        meta = {
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   821
            r'date': r'%d 0' % commit[r'time'],
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   822
            r'node': commit[r'rev'],
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   823
            r'user': r'%s <%s>' % (commit[r'author'], commit[r'authorEmail']),
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   824
        }
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   825
        if len(commit.get(r'parents', ())) >= 1:
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   826
            meta[r'parent'] = commit[r'parents'][0]
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   827
    return meta or {}
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   828
33831
75fdaf851e83 phabricator: change "readpatch" to be more flexible
Jun Wu <quark@fb.com>
parents: 33787
diff changeset
   829
def readpatch(repo, drevs, write):
33200
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
   830
    """generate plain-text patch readable by 'hg import'
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
   831
33831
75fdaf851e83 phabricator: change "readpatch" to be more flexible
Jun Wu <quark@fb.com>
parents: 33787
diff changeset
   832
    write is usually ui.write. drevs is what "querydrev" returns, results of
75fdaf851e83 phabricator: change "readpatch" to be more flexible
Jun Wu <quark@fb.com>
parents: 33787
diff changeset
   833
    "differential.query".
33200
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
   834
    """
33267
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   835
    # Prefetch hg:meta property for all diffs
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   836
    diffids = sorted(set(max(int(v) for v in drev[r'diffs']) for drev in drevs))
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   837
    diffs = callconduit(repo, 'differential.querydiffs', {'ids': diffids})
33200
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
   838
33267
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   839
    # Generate patch for each drev
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   840
    for drev in drevs:
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   841
        repo.ui.note(_('reading D%s\n') % drev[r'id'])
33200
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
   842
33267
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   843
        diffid = max(int(v) for v in drev[r'diffs'])
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   844
        body = callconduit(repo, 'differential.getrawdiff', {'diffID': diffid})
33268
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   845
        desc = getdescfromdrev(drev)
33267
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   846
        header = '# HG changeset patch\n'
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   847
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   848
        # Try to preserve metadata from hg:meta property. Write hg patch
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   849
        # headers that can be read by the "import" command. See patchheadermap
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   850
        # and extract in mercurial/patch.py for supported headers.
33441
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   851
        meta = getdiffmeta(diffs[str(diffid)])
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   852
        for k in _metanamemap.keys():
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   853
            if k in meta:
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   854
                header += '# %s %s\n' % (_metanamemap[k], meta[k])
33200
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
   855
33601
850d2ec2cf6a phabricator: convert unicode to binary when writing patches
Jun Wu <quark@fb.com>
parents: 33564
diff changeset
   856
        content = '%s%s\n%s' % (header, desc, body)
850d2ec2cf6a phabricator: convert unicode to binary when writing patches
Jun Wu <quark@fb.com>
parents: 33564
diff changeset
   857
        write(encoding.unitolocal(content))
33200
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
   858
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
   859
@command('phabread',
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
   860
         [('', 'stack', False, _('read dependencies'))],
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   861
         _('DREVSPEC [OPTIONS]'))
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   862
def phabread(ui, repo, spec, **opts):
33200
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
   863
    """print patches from Phabricator suitable for importing
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
   864
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   865
    DREVSPEC could be a Differential Revision identity, like ``D123``, or just
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   866
    the number ``123``. It could also have common operators like ``+``, ``-``,
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   867
    ``&``, ``(``, ``)`` for complex queries. Prefix ``:`` could be used to
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   868
    select a stack.
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   869
33833
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   870
    ``abandoned``, ``accepted``, ``closed``, ``needsreview``, ``needsrevision``
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   871
    could be used to filter patches by status. For performance reason, they
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   872
    only represent a subset of non-status selections and cannot be used alone.
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   873
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   874
    For example, ``:D6+8-(2+D4)`` selects a stack up to D6, plus D8 and exclude
33833
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   875
    D2 and D4. ``:D9 & needsreview`` selects "Needs Review" revisions in a
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   876
    stack up to D9.
33200
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
   877
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
   878
    If --stack is given, follow dependencies information and read all patches.
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   879
    It is equivalent to the ``:`` operator.
33200
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
   880
    """
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   881
    if opts.get('stack'):
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   882
        spec = ':(%s)' % spec
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   883
    drevs = querydrev(repo, spec)
33831
75fdaf851e83 phabricator: change "readpatch" to be more flexible
Jun Wu <quark@fb.com>
parents: 33787
diff changeset
   884
    readpatch(repo, drevs, ui.write)
33834
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   885
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   886
@command('phabupdate',
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   887
         [('', 'accept', False, _('accept revisions')),
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   888
          ('', 'reject', False, _('reject revisions')),
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   889
          ('', 'abandon', False, _('abandon revisions')),
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   890
          ('', 'reclaim', False, _('reclaim revisions')),
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   891
          ('m', 'comment', '', _('comment on the last revision')),
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   892
         ], _('DREVSPEC [OPTIONS]'))
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   893
def phabupdate(ui, repo, spec, **opts):
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   894
    """update Differential Revision in batch
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   895
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   896
    DREVSPEC selects revisions. See :hg:`help phabread` for its usage.
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   897
    """
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   898
    flags = [n for n in 'accept reject abandon reclaim'.split() if opts.get(n)]
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   899
    if len(flags) > 1:
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   900
        raise error.Abort(_('%s cannot be used together') % ', '.join(flags))
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   901
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   902
    actions = []
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   903
    for f in flags:
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   904
        actions.append({'type': f, 'value': 'true'})
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   905
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   906
    drevs = querydrev(repo, spec)
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   907
    for i, drev in enumerate(drevs):
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   908
        if i + 1 == len(drevs) and opts.get('comment'):
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   909
            actions.append({'type': 'comment', 'value': opts['comment']})
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   910
        if actions:
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   911
            params = {'objectIdentifier': drev[r'phid'],
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   912
                      'transactions': actions}
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   913
            callconduit(repo, 'differential.revision.edit', params)
35722
f18ba40d792f phabricator: add a template item for linking to a differential review
Tom Prince <mozilla@hocat.ca>
parents: 35626
diff changeset
   914
f18ba40d792f phabricator: add a template item for linking to a differential review
Tom Prince <mozilla@hocat.ca>
parents: 35626
diff changeset
   915
templatekeyword = registrar.templatekeyword()
f18ba40d792f phabricator: add a template item for linking to a differential review
Tom Prince <mozilla@hocat.ca>
parents: 35626
diff changeset
   916
36514
7b74afec6772 templatekw: switch non-showlist template keywords to new API
Yuya Nishihara <yuya@tcha.org>
parents: 35722
diff changeset
   917
@templatekeyword('phabreview', requires={'ctx'})
7b74afec6772 templatekw: switch non-showlist template keywords to new API
Yuya Nishihara <yuya@tcha.org>
parents: 35722
diff changeset
   918
def template_review(context, mapping):
35722
f18ba40d792f phabricator: add a template item for linking to a differential review
Tom Prince <mozilla@hocat.ca>
parents: 35626
diff changeset
   919
    """:phabreview: Object describing the review for this changeset.
f18ba40d792f phabricator: add a template item for linking to a differential review
Tom Prince <mozilla@hocat.ca>
parents: 35626
diff changeset
   920
    Has attributes `url` and `id`.
f18ba40d792f phabricator: add a template item for linking to a differential review
Tom Prince <mozilla@hocat.ca>
parents: 35626
diff changeset
   921
    """
36514
7b74afec6772 templatekw: switch non-showlist template keywords to new API
Yuya Nishihara <yuya@tcha.org>
parents: 35722
diff changeset
   922
    ctx = context.resource(mapping, 'ctx')
35722
f18ba40d792f phabricator: add a template item for linking to a differential review
Tom Prince <mozilla@hocat.ca>
parents: 35626
diff changeset
   923
    m = _differentialrevisiondescre.search(ctx.description())
f18ba40d792f phabricator: add a template item for linking to a differential review
Tom Prince <mozilla@hocat.ca>
parents: 35626
diff changeset
   924
    if m:
f18ba40d792f phabricator: add a template item for linking to a differential review
Tom Prince <mozilla@hocat.ca>
parents: 35626
diff changeset
   925
        return {
f18ba40d792f phabricator: add a template item for linking to a differential review
Tom Prince <mozilla@hocat.ca>
parents: 35626
diff changeset
   926
            'url': m.group('url'),
f18ba40d792f phabricator: add a template item for linking to a differential review
Tom Prince <mozilla@hocat.ca>
parents: 35626
diff changeset
   927
            'id': "D{}".format(m.group('id')),
f18ba40d792f phabricator: add a template item for linking to a differential review
Tom Prince <mozilla@hocat.ca>
parents: 35626
diff changeset
   928
        }