hgext/phabricator.py
author Gregory Szorc <gregory.szorc@gmail.com>
Mon, 04 Feb 2019 08:54:30 -0800
changeset 41532 bd3f03d8cc9f
parent 41365 876494fd967d
child 41705 570e62f1dcf2
permissions -rw-r--r--
global: use raw strings for regular expressions with escapes Escape sequences like \w, \s, and \d are technically invalid in str/bytes. This became a deprecation warning in Python 3.6 (https://bugs.python.org/issue27364). Python 3.8 bumps it to a SyntaxWarning (https://bugs.python.org/issue32912), which is non-silent by default. This commit changes a number of regular expressions to use br'' so regular expression special sequences don't need \\ literals. This fixes roughly half of the SyntaxWarning we see in the code base with Python 3.8. Differential Revision: https://phab.mercurial-scm.org/D5815
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.
39655
87539f615b87 phabricator: mark extension as experimental for now
Augie Fackler <raf@durin42.com>
parents: 39654
diff changeset
     7
"""simple Phabricator integration (EXPERIMENTAL)
33198
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
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
    24
    # 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
    25
    # callsign is "FOO".
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
    26
    callsign = FOO
33200
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
    27
34064
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34063
diff changeset
    28
    # 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
    29
    # 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
    30
    # 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
    31
    # the internal library.
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34063
diff changeset
    32
    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
    33
37996
0fa050bc68cb phabricator: migrate [phabricator.auth] to [auth]
Matt Harbison <matt_harbison@yahoo.com>
parents: 37976
diff changeset
    34
    [auth]
37997
71cf20d47f25 phabricator: split auth.url into the standard auth.schemes and auth.prefix
Matt Harbison <matt_harbison@yahoo.com>
parents: 37996
diff changeset
    35
    example.schemes = https
71cf20d47f25 phabricator: split auth.url into the standard auth.schemes and auth.prefix
Matt Harbison <matt_harbison@yahoo.com>
parents: 37996
diff changeset
    36
    example.prefix = phab.example.com
71cf20d47f25 phabricator: split auth.url into the standard auth.schemes and auth.prefix
Matt Harbison <matt_harbison@yahoo.com>
parents: 37996
diff changeset
    37
36787
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
    38
    # API token. Get it from https://$HOST/conduit/login/
37996
0fa050bc68cb phabricator: migrate [phabricator.auth] to [auth]
Matt Harbison <matt_harbison@yahoo.com>
parents: 37976
diff changeset
    39
    example.phabtoken = cli-xxxxxxxxxxxxxxxxxxxxxxxxxxxx
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    40
"""
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    41
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    42
from __future__ import absolute_import
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    43
41080
9d35ae3d9999 phabricator: ensure that the return of urlopener.open() is closed
Matt Harbison <matt_harbison@yahoo.com>
parents: 41078
diff changeset
    44
import contextlib
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
    45
import itertools
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    46
import json
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
    47
import operator
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
    48
import re
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    49
33443
e48082e0a8d5 phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents: 33442
diff changeset
    50
from mercurial.node import bin, nullid
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    51
from mercurial.i18n import _
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    52
from mercurial import (
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
    53
    cmdutil,
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
    54
    context,
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
    55
    encoding,
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    56
    error,
37997
71cf20d47f25 phabricator: split auth.url into the standard auth.schemes and auth.prefix
Matt Harbison <matt_harbison@yahoo.com>
parents: 37996
diff changeset
    57
    httpconnection as httpconnectionmod,
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,
41163
0101a35deae2 phabricator: warn if unable to amend, instead of aborting after posting
Matt Harbison <matt_harbison@yahoo.com>
parents: 41080
diff changeset
    62
    phases,
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    63
    registrar,
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
    64
    scmutil,
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
    65
    smartset,
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
    66
    tags,
39654
4057e38bba76 phabricator: fix templating bug by using hybriddict
Augie Fackler <raf@durin42.com>
parents: 39652
diff changeset
    67
    templateutil,
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    68
    url as urlmod,
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    69
    util,
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    70
)
37120
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36818
diff changeset
    71
from mercurial.utils import (
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36818
diff changeset
    72
    procutil,
37800
6cf5f5b4eb57 phabricator: specify some metadata compatibly with arc
Tom Prince <mozilla@hocat.ca>
parents: 37120
diff changeset
    73
    stringutil,
37120
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36818
diff changeset
    74
)
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    75
39735
c0c703861b60 phabricator: add testedwith boilerplate
Yuya Nishihara <yuya@tcha.org>
parents: 39655
diff changeset
    76
# Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
c0c703861b60 phabricator: add testedwith boilerplate
Yuya Nishihara <yuya@tcha.org>
parents: 39655
diff changeset
    77
# extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
c0c703861b60 phabricator: add testedwith boilerplate
Yuya Nishihara <yuya@tcha.org>
parents: 39655
diff changeset
    78
# be specifying the version(s) of Mercurial they are tested with, or
c0c703861b60 phabricator: add testedwith boilerplate
Yuya Nishihara <yuya@tcha.org>
parents: 39655
diff changeset
    79
# leave the attribute unspecified.
c0c703861b60 phabricator: add testedwith boilerplate
Yuya Nishihara <yuya@tcha.org>
parents: 39655
diff changeset
    80
testedwith = 'ships-with-hg-core'
c0c703861b60 phabricator: add testedwith boilerplate
Yuya Nishihara <yuya@tcha.org>
parents: 39655
diff changeset
    81
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    82
cmdtable = {}
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    83
command = registrar.command(cmdtable)
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    84
38042
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 37997
diff changeset
    85
configtable = {}
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 37997
diff changeset
    86
configitem = registrar.configitem(configtable)
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 37997
diff changeset
    87
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 37997
diff changeset
    88
# developer config: phabricator.batchsize
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
    89
configitem(b'phabricator', b'batchsize',
38042
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 37997
diff changeset
    90
    default=12,
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 37997
diff changeset
    91
)
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
    92
configitem(b'phabricator', b'callsign',
38042
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 37997
diff changeset
    93
    default=None,
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 37997
diff changeset
    94
)
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
    95
configitem(b'phabricator', b'curlcmd',
38042
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 37997
diff changeset
    96
    default=None,
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 37997
diff changeset
    97
)
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 37997
diff changeset
    98
# developer config: phabricator.repophid
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
    99
configitem(b'phabricator', b'repophid',
38042
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 37997
diff changeset
   100
    default=None,
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 37997
diff changeset
   101
)
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   102
configitem(b'phabricator', b'url',
38042
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 37997
diff changeset
   103
    default=None,
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 37997
diff changeset
   104
)
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   105
configitem(b'phabsend', b'confirm',
38042
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 37997
diff changeset
   106
    default=False,
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 37997
diff changeset
   107
)
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 37997
diff changeset
   108
34063
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
   109
colortable = {
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   110
    b'phabricator.action.created': b'green',
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   111
    b'phabricator.action.skipped': b'magenta',
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   112
    b'phabricator.action.updated': b'magenta',
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   113
    b'phabricator.desc': b'',
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   114
    b'phabricator.drev': b'bold',
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   115
    b'phabricator.node': b'',
34063
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
   116
}
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
   117
39650
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38945
diff changeset
   118
_VCR_FLAGS = [
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38945
diff changeset
   119
    (b'', b'test-vcr', b'',
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38945
diff changeset
   120
     _(b'Path to a vcr file. If nonexistent, will record a new vcr transcript'
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38945
diff changeset
   121
       b', otherwise will mock all http requests using the specified vcr file.'
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38945
diff changeset
   122
       b' (ADVANCED)'
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38945
diff changeset
   123
     )),
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38945
diff changeset
   124
]
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38945
diff changeset
   125
41073
536beb130f3c phabricator: assign commands to help categories
Matt Harbison <matt_harbison@yahoo.com>
parents: 40546
diff changeset
   126
def vcrcommand(name, flags, spec, helpcategory=None):
39650
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38945
diff changeset
   127
    fullflags = flags + _VCR_FLAGS
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38945
diff changeset
   128
    def decorate(fn):
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38945
diff changeset
   129
        def inner(*args, **kwargs):
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38945
diff changeset
   130
            cassette = kwargs.pop(r'test_vcr', None)
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38945
diff changeset
   131
            if cassette:
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38945
diff changeset
   132
                import hgdemandimport
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38945
diff changeset
   133
                with hgdemandimport.deactivated():
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38945
diff changeset
   134
                    import vcr as vcrmod
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38945
diff changeset
   135
                    import vcr.stubs as stubs
40378
b015f30a91fb phabricator: do more of the VCR work in demandimport.deactivated()
Augie Fackler <augie@google.com>
parents: 40151
diff changeset
   136
                    vcr = vcrmod.VCR(
b015f30a91fb phabricator: do more of the VCR work in demandimport.deactivated()
Augie Fackler <augie@google.com>
parents: 40151
diff changeset
   137
                        serializer=r'json',
b015f30a91fb phabricator: do more of the VCR work in demandimport.deactivated()
Augie Fackler <augie@google.com>
parents: 40151
diff changeset
   138
                        custom_patches=[
b015f30a91fb phabricator: do more of the VCR work in demandimport.deactivated()
Augie Fackler <augie@google.com>
parents: 40151
diff changeset
   139
                            (urlmod, 'httpconnection', stubs.VCRHTTPConnection),
b015f30a91fb phabricator: do more of the VCR work in demandimport.deactivated()
Augie Fackler <augie@google.com>
parents: 40151
diff changeset
   140
                            (urlmod, 'httpsconnection',
b015f30a91fb phabricator: do more of the VCR work in demandimport.deactivated()
Augie Fackler <augie@google.com>
parents: 40151
diff changeset
   141
                             stubs.VCRHTTPSConnection),
b015f30a91fb phabricator: do more of the VCR work in demandimport.deactivated()
Augie Fackler <augie@google.com>
parents: 40151
diff changeset
   142
                        ])
b015f30a91fb phabricator: do more of the VCR work in demandimport.deactivated()
Augie Fackler <augie@google.com>
parents: 40151
diff changeset
   143
                    with vcr.use_cassette(cassette):
b015f30a91fb phabricator: do more of the VCR work in demandimport.deactivated()
Augie Fackler <augie@google.com>
parents: 40151
diff changeset
   144
                        return fn(*args, **kwargs)
39650
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38945
diff changeset
   145
            return fn(*args, **kwargs)
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38945
diff changeset
   146
        inner.__name__ = fn.__name__
40546
7e2c58b08e74 phabricator: ensure the command summaries are available in extension help
Matt Harbison <matt_harbison@yahoo.com>
parents: 40378
diff changeset
   147
        inner.__doc__ = fn.__doc__
41073
536beb130f3c phabricator: assign commands to help categories
Matt Harbison <matt_harbison@yahoo.com>
parents: 40546
diff changeset
   148
        return command(name, fullflags, spec, helpcategory=helpcategory)(inner)
39650
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38945
diff changeset
   149
    return decorate
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38945
diff changeset
   150
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   151
def urlencodenested(params):
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   152
    """like urlencode, but works with nested parameters.
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   153
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   154
    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
   155
    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
   156
    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
   157
    """
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   158
    flatparams = util.sortdict()
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   159
    def process(prefix, obj):
41017
d7d3164e6a31 phabricator: properly encode boolean types in the request body
Matt Harbison <matt_harbison@yahoo.com>
parents: 40546
diff changeset
   160
        if isinstance(obj, bool):
d7d3164e6a31 phabricator: properly encode boolean types in the request body
Matt Harbison <matt_harbison@yahoo.com>
parents: 40546
diff changeset
   161
            obj = {True: b'true', False: b'false'}[obj]  # Python -> PHP form
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   162
        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
   163
        if items is None:
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   164
            flatparams[prefix] = obj
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   165
        else:
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   166
            for k, v in items(obj):
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   167
                if prefix:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   168
                    process(b'%s[%s]' % (prefix, k), v)
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   169
                else:
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   170
                    process(k, v)
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   171
    process(b'', params)
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   172
    return util.urlreq.urlencode(flatparams)
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   173
37996
0fa050bc68cb phabricator: migrate [phabricator.auth] to [auth]
Matt Harbison <matt_harbison@yahoo.com>
parents: 37976
diff changeset
   174
def readurltoken(repo):
0fa050bc68cb phabricator: migrate [phabricator.auth] to [auth]
Matt Harbison <matt_harbison@yahoo.com>
parents: 37976
diff changeset
   175
    """return conduit url, token and make sure they exist
0fa050bc68cb phabricator: migrate [phabricator.auth] to [auth]
Matt Harbison <matt_harbison@yahoo.com>
parents: 37976
diff changeset
   176
37997
71cf20d47f25 phabricator: split auth.url into the standard auth.schemes and auth.prefix
Matt Harbison <matt_harbison@yahoo.com>
parents: 37996
diff changeset
   177
    Currently read from [auth] config section. In the future, it might
37996
0fa050bc68cb phabricator: migrate [phabricator.auth] to [auth]
Matt Harbison <matt_harbison@yahoo.com>
parents: 37976
diff changeset
   178
    make sense to read from .arcconfig and .arcrc as well.
0fa050bc68cb phabricator: migrate [phabricator.auth] to [auth]
Matt Harbison <matt_harbison@yahoo.com>
parents: 37976
diff changeset
   179
    """
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   180
    url = repo.ui.config(b'phabricator', b'url')
37996
0fa050bc68cb phabricator: migrate [phabricator.auth] to [auth]
Matt Harbison <matt_harbison@yahoo.com>
parents: 37976
diff changeset
   181
    if not url:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   182
        raise error.Abort(_(b'config %s.%s is required')
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   183
                          % (b'phabricator', b'url'))
37996
0fa050bc68cb phabricator: migrate [phabricator.auth] to [auth]
Matt Harbison <matt_harbison@yahoo.com>
parents: 37976
diff changeset
   184
37997
71cf20d47f25 phabricator: split auth.url into the standard auth.schemes and auth.prefix
Matt Harbison <matt_harbison@yahoo.com>
parents: 37996
diff changeset
   185
    res = httpconnectionmod.readauthforuri(repo.ui, url, util.url(url).user)
71cf20d47f25 phabricator: split auth.url into the standard auth.schemes and auth.prefix
Matt Harbison <matt_harbison@yahoo.com>
parents: 37996
diff changeset
   186
    token = None
37996
0fa050bc68cb phabricator: migrate [phabricator.auth] to [auth]
Matt Harbison <matt_harbison@yahoo.com>
parents: 37976
diff changeset
   187
37997
71cf20d47f25 phabricator: split auth.url into the standard auth.schemes and auth.prefix
Matt Harbison <matt_harbison@yahoo.com>
parents: 37996
diff changeset
   188
    if res:
71cf20d47f25 phabricator: split auth.url into the standard auth.schemes and auth.prefix
Matt Harbison <matt_harbison@yahoo.com>
parents: 37996
diff changeset
   189
        group, auth = res
71cf20d47f25 phabricator: split auth.url into the standard auth.schemes and auth.prefix
Matt Harbison <matt_harbison@yahoo.com>
parents: 37996
diff changeset
   190
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   191
        repo.ui.debug(b"using auth.%s.* for authentication\n" % group)
37997
71cf20d47f25 phabricator: split auth.url into the standard auth.schemes and auth.prefix
Matt Harbison <matt_harbison@yahoo.com>
parents: 37996
diff changeset
   192
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   193
        token = auth.get(b'phabtoken')
37996
0fa050bc68cb phabricator: migrate [phabricator.auth] to [auth]
Matt Harbison <matt_harbison@yahoo.com>
parents: 37976
diff changeset
   194
36787
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   195
    if not token:
40151
38ac525b44c9 phabricator: drop support for the legacy phabricator.auth.token config (BC)
Matt Harbison <matt_harbison@yahoo.com>
parents: 39735
diff changeset
   196
        raise error.Abort(_(b'Can\'t find conduit token associated to %s')
38ac525b44c9 phabricator: drop support for the legacy phabricator.auth.token config (BC)
Matt Harbison <matt_harbison@yahoo.com>
parents: 39735
diff changeset
   197
                            % (url,))
36787
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   198
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36514
diff changeset
   199
    return url, token
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   200
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   201
def callconduit(repo, name, params):
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   202
    """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
   203
    host, token = readurltoken(repo)
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   204
    url, authinfo = util.url(b'/'.join([host, b'api', name])).authinfo()
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   205
    repo.ui.debug(b'Conduit Call: %s %s\n' % (url, params))
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   206
    params = params.copy()
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   207
    params[b'api.token'] = token
34064
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34063
diff changeset
   208
    data = urlencodenested(params)
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   209
    curlcmd = repo.ui.config(b'phabricator', b'curlcmd')
34064
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34063
diff changeset
   210
    if curlcmd:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   211
        sin, sout = procutil.popen2(b'%s -d @- %s'
37120
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36818
diff changeset
   212
                                    % (curlcmd, procutil.shellquote(url)))
34064
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34063
diff changeset
   213
        sin.write(data)
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34063
diff changeset
   214
        sin.close()
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34063
diff changeset
   215
        body = sout.read()
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34063
diff changeset
   216
    else:
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34063
diff changeset
   217
        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
   218
        request = util.urlreq.request(url, data=data)
41080
9d35ae3d9999 phabricator: ensure that the return of urlopener.open() is closed
Matt Harbison <matt_harbison@yahoo.com>
parents: 41078
diff changeset
   219
        with contextlib.closing(urlopener.open(request)) as rsp:
9d35ae3d9999 phabricator: ensure that the return of urlopener.open() is closed
Matt Harbison <matt_harbison@yahoo.com>
parents: 41078
diff changeset
   220
            body = rsp.read()
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   221
    repo.ui.debug(b'Conduit Response: %s\n' % body)
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   222
    parsed = json.loads(body)
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   223
    if parsed.get(r'error_code'):
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   224
        msg = (_(b'Conduit Error (%s): %s')
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   225
               % (parsed[r'error_code'], parsed[r'error_info']))
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   226
        raise error.Abort(msg)
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   227
    return parsed[r'result']
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   228
39650
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38945
diff changeset
   229
@vcrcommand(b'debugcallconduit', [], _(b'METHOD'))
33198
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   230
def debugcallconduit(ui, repo, name):
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   231
    """call Conduit API
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   232
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   233
    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
   234
    to stdout as a JSON blob.
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   235
    """
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   236
    params = json.loads(ui.fin.read())
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   237
    result = callconduit(repo, name, params)
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   238
    s = json.dumps(result, sort_keys=True, indent=2, separators=(b',', b': '))
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   239
    ui.write(b'%s\n' % s)
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   240
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   241
def getrepophid(repo):
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   242
    """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
   243
    # developer config: phabricator.repophid
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   244
    repophid = repo.ui.config(b'phabricator', b'repophid')
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   245
    if repophid:
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   246
        return repophid
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   247
    callsign = repo.ui.config(b'phabricator', b'callsign')
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   248
    if not callsign:
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   249
        return None
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   250
    query = callconduit(repo, b'diffusion.repository.search',
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   251
                        {b'constraints': {b'callsigns': [callsign]}})
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   252
    if len(query[r'data']) == 0:
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   253
        return None
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   254
    repophid = encoding.strtolocal(query[r'data'][0][r'phid'])
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   255
    repo.ui.setconfig(b'phabricator', b'repophid', repophid)
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   256
    return repophid
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   257
41532
bd3f03d8cc9f global: use raw strings for regular expressions with escapes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41365
diff changeset
   258
_differentialrevisiontagre = re.compile(br'\AD([1-9][0-9]*)\Z')
33263
ed61189763ef phabricator: check associated Differential Revision from commit message
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   259
_differentialrevisiondescre = re.compile(
41532
bd3f03d8cc9f global: use raw strings for regular expressions with escapes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41365
diff changeset
   260
    br'^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
   261
33442
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   262
def getoldnodedrevmap(repo, nodelist):
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   263
    """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
   264
33691
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   265
    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
   266
    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
   267
    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
   268
    be ``None``.
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   269
33691
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   270
    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
   271
    association information.
33263
ed61189763ef phabricator: check associated Differential Revision from commit message
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   272
33691
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   273
    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
   274
    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
   275
    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
   276
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   277
    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
   278
    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
   279
    """
33442
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   280
    unfi = repo.unfiltered()
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   281
    nodemap = unfi.changelog.nodemap
33263
ed61189763ef phabricator: check associated Differential Revision from commit message
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   282
33691
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   283
    result = {} # {node: (oldnode?, lastdiff?, drev)}
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   284
    toconfirm = {} # {node: (force, {precnode}, drev)}
33442
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   285
    for node in nodelist:
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   286
        ctx = unfi[node]
33443
e48082e0a8d5 phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents: 33442
diff changeset
   287
        # 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
   288
        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
   289
        for n in precnodes:
33442
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   290
            if n in nodemap:
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   291
                for tag in unfi.nodetags(n):
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   292
                    m = _differentialrevisiontagre.match(tag)
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   293
                    if m:
33691
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   294
                        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
   295
                        continue
33263
ed61189763ef phabricator: check associated Differential Revision from commit message
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   296
33691
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   297
        # Check commit message
33442
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   298
        m = _differentialrevisiondescre.search(ctx.description())
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   299
        if m:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   300
            toconfirm[node] = (1, set(precnodes), int(m.group(b'id')))
33263
ed61189763ef phabricator: check associated Differential Revision from commit message
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   301
33443
e48082e0a8d5 phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents: 33442
diff changeset
   302
    # 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
   303
    # Phabricator, and expect precursors overlap with it.
e48082e0a8d5 phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents: 33442
diff changeset
   304
    if toconfirm:
33691
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   305
        drevs = [drev for force, precs, drev in toconfirm.values()]
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   306
        alldiffs = callconduit(unfi, b'differential.querydiffs',
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   307
                               {b'revisionIDs': drevs})
33691
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   308
        getnode = lambda d: bin(encoding.unitolocal(
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   309
            getdiffmeta(d).get(r'node', b''))) or None
33691
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   310
        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
   311
            diffs = [d for d in alldiffs.values()
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   312
                     if int(d[r'revisionID']) == drev]
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   313
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   314
            # "precursors" as known by Phabricator
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   315
            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
   316
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   317
            # 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
   318
            # 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
   319
            if not force and not bool(phprecset & precset):
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   320
                tagname = b'D%d' % drev
33443
e48082e0a8d5 phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents: 33442
diff changeset
   321
                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
   322
                         date=None, local=True)
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   323
                unfi.ui.warn(_(b'D%s: local tag removed - does not match '
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   324
                               b'Differential history\n') % drev)
33691
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   325
                continue
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   326
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   327
            # 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
   328
            # exists in the repo
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   329
            oldnode = lastdiff = None
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   330
            if diffs:
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   331
                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
   332
                oldnode = getnode(lastdiff)
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   333
                if oldnode and oldnode not in nodemap:
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   334
                    oldnode = None
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   335
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   336
            result[newnode] = (oldnode, lastdiff, drev)
33443
e48082e0a8d5 phabricator: verify local tags before trusting them
Jun Wu <quark@fb.com>
parents: 33442
diff changeset
   337
33442
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   338
    return result
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   339
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   340
def getdiff(ctx, diffopts):
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   341
    """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
   342
    output = util.stringio()
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   343
    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
   344
                                      None, opts=diffopts):
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   345
        output.write(chunk)
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   346
    return output.getvalue()
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   347
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   348
def creatediff(ctx):
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   349
    """create a Differential Diff"""
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   350
    repo = ctx.repo()
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   351
    repophid = getrepophid(repo)
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   352
    # Create a "Differential Diff" via "differential.createrawdiff" API
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   353
    params = {b'diff': getdiff(ctx, mdiff.diffopts(git=True, context=32767))}
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   354
    if repophid:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   355
        params[b'repositoryPHID'] = repophid
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   356
    diff = callconduit(repo, b'differential.createrawdiff', params)
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   357
    if not diff:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   358
        raise error.Abort(_(b'cannot create diff for %s') % ctx)
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   359
    return diff
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   360
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   361
def writediffproperties(ctx, diff):
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   362
    """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
   363
    params = {
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   364
        b'diff_id': diff[r'id'],
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   365
        b'name': b'hg:meta',
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   366
        b'data': json.dumps({
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   367
            b'user': ctx.user(),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   368
            b'date': b'%d %d' % ctx.date(),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   369
            b'node': ctx.hex(),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   370
            b'parent': ctx.p1().hex(),
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   371
        }),
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   372
    }
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   373
    callconduit(ctx.repo(), b'differential.setdiffproperty', params)
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   374
37800
6cf5f5b4eb57 phabricator: specify some metadata compatibly with arc
Tom Prince <mozilla@hocat.ca>
parents: 37120
diff changeset
   375
    params = {
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   376
        b'diff_id': diff[r'id'],
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   377
        b'name': b'local:commits',
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   378
        b'data': json.dumps({
37800
6cf5f5b4eb57 phabricator: specify some metadata compatibly with arc
Tom Prince <mozilla@hocat.ca>
parents: 37120
diff changeset
   379
            ctx.hex(): {
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   380
                b'author': stringutil.person(ctx.user()),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   381
                b'authorEmail': stringutil.email(ctx.user()),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   382
                b'time': ctx.date()[0],
37800
6cf5f5b4eb57 phabricator: specify some metadata compatibly with arc
Tom Prince <mozilla@hocat.ca>
parents: 37120
diff changeset
   383
            },
6cf5f5b4eb57 phabricator: specify some metadata compatibly with arc
Tom Prince <mozilla@hocat.ca>
parents: 37120
diff changeset
   384
        }),
6cf5f5b4eb57 phabricator: specify some metadata compatibly with arc
Tom Prince <mozilla@hocat.ca>
parents: 37120
diff changeset
   385
    }
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   386
    callconduit(ctx.repo(), b'differential.setdiffproperty', params)
37800
6cf5f5b4eb57 phabricator: specify some metadata compatibly with arc
Tom Prince <mozilla@hocat.ca>
parents: 37120
diff changeset
   387
33498
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   388
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
   389
                               olddiff=None, actions=None):
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   390
    """create or update a Differential Revision
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   391
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   392
    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
   393
    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
   394
95f658b558a3 phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents: 33264
diff changeset
   395
    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
   396
    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
   397
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   398
    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
   399
    """
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   400
    repo = ctx.repo()
33265
95f658b558a3 phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents: 33264
diff changeset
   401
    if oldnode:
33976
27ff2a87d8c0 phabsend: detect patch change with larger context
Jun Wu <quark@fb.com>
parents: 33975
diff changeset
   402
        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
   403
        oldctx = repo.unfiltered()[oldnode]
95f658b558a3 phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents: 33264
diff changeset
   404
        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
   405
    else:
95f658b558a3 phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents: 33264
diff changeset
   406
        neednewdiff = True
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   407
33265
95f658b558a3 phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents: 33264
diff changeset
   408
    transactions = []
95f658b558a3 phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents: 33264
diff changeset
   409
    if neednewdiff:
95f658b558a3 phabricator: do not upload new diff if nothing changes
Jun Wu <quark@fb.com>
parents: 33264
diff changeset
   410
        diff = creatediff(ctx)
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   411
        transactions.append({b'type': b'update', b'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
   412
    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
   413
        # 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
   414
        # 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
   415
        # 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
   416
        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
   417
        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
   418
    writediffproperties(ctx, diff)
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   419
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   420
    # 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
   421
    # 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
   422
    # 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
   423
    # 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
   424
    if parentrevid and revid is None:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   425
        summary = b'Depends on D%s' % parentrevid
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   426
        transactions += [{b'type': b'summary', b'value': summary},
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   427
                         {b'type': b'summary', b'value': b' '}]
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   428
33498
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   429
    if actions:
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   430
        transactions += actions
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   431
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   432
    # 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
   433
    desc = ctx.description()
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   434
    info = callconduit(repo, b'differential.parsecommitmessage',
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   435
                       {b'corpus': desc})
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   436
    for k, v in info[r'fields'].items():
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   437
        if k in [b'title', b'summary', b'testPlan']:
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   438
            transactions.append({b'type': k, b'value': v})
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   439
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   440
    params = {b'transactions': transactions}
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   441
    if revid is not None:
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   442
        # Update an existing Differential Revision
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   443
        params[b'objectIdentifier'] = revid
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   444
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   445
    revision = callconduit(repo, b'differential.revision.edit', params)
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   446
    if not revision:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   447
        raise error.Abort(_(b'cannot create revision for %s') % ctx)
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   448
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   449
    return revision, diff
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   450
33498
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   451
def userphids(repo, names):
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   452
    """convert user names to PHIDs"""
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   453
    query = {b'constraints': {b'usernames': names}}
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   454
    result = callconduit(repo, b'user.search', query)
33498
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   455
    # 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
   456
    # some names here.
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   457
    data = result[r'data']
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   458
    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
   459
    unresolved = set(names) - resolved
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   460
    if unresolved:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   461
        raise error.Abort(_(b'unknown username: %s')
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   462
                          % b' '.join(sorted(unresolved)))
33498
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   463
    return [entry[r'phid'] for entry in data]
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   464
39650
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38945
diff changeset
   465
@vcrcommand(b'phabsend',
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   466
         [(b'r', b'rev', [], _(b'revisions to send'), _(b'REV')),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   467
          (b'', b'amend', True, _(b'update commit messages')),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   468
          (b'', b'reviewer', [], _(b'specify reviewers')),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   469
          (b'', b'confirm', None, _(b'ask for confirmation before sending'))],
41073
536beb130f3c phabricator: assign commands to help categories
Matt Harbison <matt_harbison@yahoo.com>
parents: 40546
diff changeset
   470
         _(b'REV [OPTIONS]'),
536beb130f3c phabricator: assign commands to help categories
Matt Harbison <matt_harbison@yahoo.com>
parents: 40546
diff changeset
   471
         helpcategory=command.CATEGORY_IMPORT_EXPORT)
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   472
def phabsend(ui, repo, *revs, **opts):
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   473
    """upload changesets to Phabricator
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
    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
   476
    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
   477
    revset.
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   478
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   479
    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
   480
    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
   481
    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
   482
    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
   483
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   484
    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
   485
    ``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
   486
    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
   487
    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
   488
33690
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   489
    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
   490
    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
   491
    behaviour::
33690
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   492
33974
45a8cd74de4e phabsend: polish the docstring a bit
Jun Wu <quark@fb.com>
parents: 33834
diff changeset
   493
        [phabsend]
45a8cd74de4e phabsend: polish the docstring a bit
Jun Wu <quark@fb.com>
parents: 33834
diff changeset
   494
        confirm = true
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   495
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   496
    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
   497
    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
   498
    """
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   499
    revs = list(revs) + opts.get(b'rev', [])
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   500
    revs = scmutil.revrange(repo, revs)
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   501
33266
5b2391b46906 phabricator: abort if phabsend gets empty revs
Jun Wu <quark@fb.com>
parents: 33265
diff changeset
   502
    if not revs:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   503
        raise error.Abort(_(b'phabsend requires at least one changeset'))
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   504
    if opts.get(b'amend'):
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   505
        cmdutil.checkunfinished(repo)
33266
5b2391b46906 phabricator: abort if phabsend gets empty revs
Jun Wu <quark@fb.com>
parents: 33265
diff changeset
   506
33978
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33977
diff changeset
   507
    # {newnode: (oldnode, olddiff, olddrev}
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33977
diff changeset
   508
    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
   509
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   510
    confirm = ui.configbool(b'phabsend', b'confirm')
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   511
    confirm |= bool(opts.get(b'confirm'))
33690
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   512
    if confirm:
33978
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33977
diff changeset
   513
        confirmed = _confirmbeforesend(repo, revs, oldmap)
33690
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   514
        if not confirmed:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   515
            raise error.Abort(_(b'phabsend cancelled'))
33690
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   516
33498
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   517
    actions = []
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   518
    reviewers = opts.get(b'reviewer', [])
33498
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   519
    if reviewers:
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   520
        phids = userphids(repo, reviewers)
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   521
        actions.append({b'type': b'reviewers.add', b'value': phids})
33498
b7a75b9a3386 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com>
parents: 33443
diff changeset
   522
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   523
    drevids = [] # [int]
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   524
    diffmap = {} # {newnode: diff}
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   525
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   526
    # 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
   527
    # can provide dependency relationship
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   528
    lastrevid = None
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   529
    for rev in revs:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   530
        ui.debug(b'sending rev %d\n' % rev)
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   531
        ctx = repo[rev]
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   532
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   533
        # Get Differential Revision ID
33691
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33690
diff changeset
   534
        oldnode, olddiff, revid = oldmap.get(ctx.node(), (None, None, None))
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   535
        if oldnode != ctx.node() or opts.get(b'amend'):
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   536
            # Create or update Differential Revision
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   537
            revision, diff = createdifferentialrevision(
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   538
                ctx, revid, lastrevid, oldnode, olddiff, actions)
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   539
            diffmap[ctx.node()] = diff
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   540
            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
   541
            if revid:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   542
                action = b'updated'
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   543
            else:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   544
                action = b'created'
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   545
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   546
            # 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
   547
            # does not have it already
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   548
            m = _differentialrevisiondescre.search(ctx.description())
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   549
            if not m or int(m.group(b'id')) != newrevid:
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   550
                tagname = b'D%d' % newrevid
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   551
                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
   552
                         date=None, local=True)
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   553
        else:
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   554
            # 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
   555
            # could depend on this one.
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   556
            newrevid = revid
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   557
            action = b'skipped'
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   558
34063
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33978
diff changeset
   559
        actiondesc = ui.label(
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   560
            {b'created': _(b'created'),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   561
             b'skipped': _(b'skipped'),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   562
             b'updated': _(b'updated')}[action],
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   563
            b'phabricator.action.%s' % action)
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   564
        drevdesc = ui.label(b'D%s' % newrevid, b'phabricator.drev')
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   565
        nodedesc = ui.label(bytes(ctx), b'phabricator.node')
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   566
        desc = ui.label(ctx.description().split(b'\n')[0], b'phabricator.desc')
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   567
        ui.write(_(b'%s - %s - %s: %s\n') % (drevdesc, actiondesc, nodedesc,
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   568
                                             desc))
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   569
        drevids.append(newrevid)
33199
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33198
diff changeset
   570
        lastrevid = newrevid
33200
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
   571
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   572
    # Update commit messages and remove tags
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   573
    if opts.get(b'amend'):
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   574
        unfi = repo.unfiltered()
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   575
        drevs = callconduit(repo, b'differential.query', {b'ids': drevids})
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   576
        with repo.wlock(), repo.lock(), repo.transaction(b'phabsend'):
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   577
            wnode = unfi[b'.'].node()
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   578
            mapping = {} # {oldnode: [newnode]}
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   579
            for i, rev in enumerate(revs):
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   580
                old = unfi[rev]
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   581
                drevid = drevids[i]
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   582
                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
   583
                newdesc = getdescfromdrev(drev)
38945
0dce1297dd01 phabricator: convert description into local
Cédric Krier <ced@b2ck.com>
parents: 38423
diff changeset
   584
                newdesc = encoding.unitolocal(newdesc)
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   585
                # Make sure commit message contain "Differential Revision"
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   586
                if old.description() != newdesc:
41163
0101a35deae2 phabricator: warn if unable to amend, instead of aborting after posting
Matt Harbison <matt_harbison@yahoo.com>
parents: 41080
diff changeset
   587
                    if old.phase() == phases.public:
0101a35deae2 phabricator: warn if unable to amend, instead of aborting after posting
Matt Harbison <matt_harbison@yahoo.com>
parents: 41080
diff changeset
   588
                        ui.warn(_("warning: not updating public commit %s\n")
0101a35deae2 phabricator: warn if unable to amend, instead of aborting after posting
Matt Harbison <matt_harbison@yahoo.com>
parents: 41080
diff changeset
   589
                                % scmutil.formatchangeid(old))
0101a35deae2 phabricator: warn if unable to amend, instead of aborting after posting
Matt Harbison <matt_harbison@yahoo.com>
parents: 41080
diff changeset
   590
                        continue
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   591
                    parents = [
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   592
                        mapping.get(old.p1().node(), (old.p1(),))[0],
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   593
                        mapping.get(old.p2().node(), (old.p2(),))[0],
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   594
                    ]
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   595
                    new = context.metadataonlyctx(
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   596
                        repo, old, parents=parents, text=newdesc,
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   597
                        user=old.user(), date=old.date(), extra=old.extra())
38336
bb7e3c6ef592 phabricator: preserve the phase when amending in the Differential fields
Matt Harbison <matt_harbison@yahoo.com>
parents: 38042
diff changeset
   598
38423
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38392
diff changeset
   599
                    newnode = new.commit()
38336
bb7e3c6ef592 phabricator: preserve the phase when amending in the Differential fields
Matt Harbison <matt_harbison@yahoo.com>
parents: 38042
diff changeset
   600
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   601
                    mapping[old.node()] = [newnode]
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   602
                    # Update diff property
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   603
                    writediffproperties(unfi[newnode], diffmap[old.node()])
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   604
                # Remove local tags since it's no longer necessary
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   605
                tagname = b'D%d' % drevid
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   606
                if tagname in repo.tags():
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   607
                    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
   608
                             date=None, local=True)
38423
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38392
diff changeset
   609
            scmutil.cleanupnodes(repo, mapping, b'phabsend', fixphase=True)
33787
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   610
            if wnode in mapping:
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   611
                unfi.setparents(mapping[wnode][0])
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33785
diff changeset
   612
33264
266321579c68 phabricator: add node and p1 to hg:meta property
Jun Wu <quark@fb.com>
parents: 33263
diff changeset
   613
# 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
   614
# consistent with "hg export" output.
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   615
_metanamemap = util.sortdict([(r'user', b'User'), (r'date', b'Date'),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   616
                              (r'node', b'Node ID'), (r'parent', b'Parent ')])
33264
266321579c68 phabricator: add node and p1 to hg:meta property
Jun Wu <quark@fb.com>
parents: 33263
diff changeset
   617
33978
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33977
diff changeset
   618
def _confirmbeforesend(repo, revs, oldmap):
33977
edeb8f28c031 phabsend: print the actual URL with --confirm
Jun Wu <quark@fb.com>
parents: 33976
diff changeset
   619
    url, token = readurltoken(repo)
33690
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   620
    ui = repo.ui
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   621
    for rev in revs:
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   622
        ctx = repo[rev]
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   623
        desc = ctx.description().splitlines()[0]
33978
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33977
diff changeset
   624
        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
   625
        if drevid:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   626
            drevdesc = ui.label(b'D%s' % drevid, b'phabricator.drev')
33978
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33977
diff changeset
   627
        else:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   628
            drevdesc = ui.label(_(b'NEW'), b'phabricator.drev')
33978
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33977
diff changeset
   629
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   630
        ui.write(_(b'%s - %s: %s\n')
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   631
                 % (drevdesc,
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   632
                    ui.label(bytes(ctx), b'phabricator.node'),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   633
                    ui.label(desc, b'phabricator.desc')))
33690
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   634
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   635
    if ui.promptchoice(_(b'Send the above changes to %s (yn)?'
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   636
                         b'$$ &Yes $$ &No') % url):
33690
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   637
        return False
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   638
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   639
    return True
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   640
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   641
_knownstatusnames = {b'accepted', b'needsreview', b'needsrevision', b'closed',
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   642
                     b'abandoned'}
33833
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   643
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   644
def _getstatusname(drev):
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   645
    """get normalized status name from a Differential Revision"""
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   646
    return drev[r'statusName'].replace(b' ', b'').lower()
33833
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   647
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   648
# 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
   649
# +, and -.
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   650
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   651
_elements = {
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   652
    # token-type: binding-strength, primary, prefix, infix, suffix
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   653
    b'(':      (12, None, (b'group', 1, b')'), None, None),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   654
    b':':      (8, None, (b'ancestors', 8), None, None),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   655
    b'&':      (5,  None, None, (b'and_', 5), None),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   656
    b'+':      (4,  None, None, (b'add', 4), None),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   657
    b'-':      (4,  None, None, (b'sub', 4), None),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   658
    b')':      (0,  None, None, None, None),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   659
    b'symbol': (0, b'symbol', None, None, None),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   660
    b'end':    (0, None, None, None, None),
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   661
}
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   662
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   663
def _tokenize(text):
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   664
    view = memoryview(text) # zero-copy slice
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   665
    special = b'():+-& '
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   666
    pos = 0
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   667
    length = len(text)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   668
    while pos < length:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   669
        symbol = b''.join(itertools.takewhile(lambda ch: ch not in special,
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   670
                                              view[pos:]))
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   671
        if symbol:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   672
            yield (b'symbol', symbol, pos)
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   673
            pos += len(symbol)
33833
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   674
        else: # special char, ignore space
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   675
            if text[pos] != b' ':
33833
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   676
                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
   677
            pos += 1
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   678
    yield (b'end', None, pos)
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   679
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   680
def _parse(text):
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   681
    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
   682
    if pos != len(text):
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   683
        raise error.ParseError(b'invalid token', pos)
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   684
    return tree
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   685
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   686
def _parsedrev(symbol):
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   687
    """str -> int or None, ex. 'D45' -> 45; '12' -> 12; 'x' -> None"""
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   688
    if symbol.startswith(b'D') and symbol[1:].isdigit():
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   689
        return int(symbol[1:])
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   690
    if symbol.isdigit():
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   691
        return int(symbol)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   692
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   693
def _prefetchdrevs(tree):
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   694
    """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
   695
    drevs = set()
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   696
    ancestordrevs = set()
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   697
    op = tree[0]
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   698
    if op == b'symbol':
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   699
        r = _parsedrev(tree[1])
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   700
        if r:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   701
            drevs.add(r)
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   702
    elif op == b'ancestors':
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   703
        r, a = _prefetchdrevs(tree[1])
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   704
        drevs.update(r)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   705
        ancestordrevs.update(r)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   706
        ancestordrevs.update(a)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   707
    else:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   708
        for t in tree[1:]:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   709
            r, a = _prefetchdrevs(t)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   710
            drevs.update(r)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   711
            ancestordrevs.update(a)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   712
    return drevs, ancestordrevs
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   713
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   714
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
   715
    """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
   716
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   717
    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
   718
    for details.
33267
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   719
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   720
    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
   721
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   722
        {
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   723
            "id": "2",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   724
            "phid": "PHID-DREV-672qvysjcczopag46qty",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   725
            "title": "example",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   726
            "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
   727
            "dateCreated": "1499181406",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   728
            "dateModified": "1499182103",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   729
            "authorPHID": "PHID-USER-tv3ohwc4v4jeu34otlye",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   730
            "status": "0",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   731
            "statusName": "Needs Review",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   732
            "properties": [],
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   733
            "branch": null,
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   734
            "summary": "",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   735
            "testPlan": "",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   736
            "lineCount": "2",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   737
            "activeDiffPHID": "PHID-DIFF-xoqnjkobbm6k4dk6hi72",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   738
            "diffs": [
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   739
              "3",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   740
              "4",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   741
            ],
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   742
            "commits": [],
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   743
            "reviewers": [],
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   744
            "ccs": [],
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   745
            "hashes": [],
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   746
            "auxiliary": {
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   747
              "phabricator:projects": [],
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   748
              "phabricator:depends-on": [
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   749
                "PHID-DREV-gbapp366kutjebt7agcd"
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   750
              ]
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   751
            },
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   752
            "repositoryPHID": "PHID-REPO-hub2hx62ieuqeheznasv",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   753
            "sourcePath": null
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   754
        }
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   755
    """
33269
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   756
    def fetch(params):
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   757
        """params -> single drev or None"""
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   758
        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
   759
        if key in prefetched:
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   760
            return prefetched[key]
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   761
        drevs = callconduit(repo, b'differential.query', params)
33269
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   762
        # Fill prefetched with the result
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   763
        for drev in drevs:
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   764
            prefetched[drev[r'phid']] = drev
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   765
            prefetched[int(drev[r'id'])] = drev
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   766
        if key not in prefetched:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   767
            raise error.Abort(_(b'cannot get Differential Revision %r')
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   768
                              % params)
33269
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   769
        return prefetched[key]
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   770
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   771
    def getstack(topdrevids):
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   772
        """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
   773
        visited = set()
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   774
        result = []
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   775
        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
   776
        while queue:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   777
            params = queue.pop()
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   778
            drev = fetch(params)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   779
            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
   780
                continue
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   781
            visited.add(drev[r'id'])
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   782
            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
   783
            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
   784
            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
   785
            for phid in depends:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   786
                queue.append({b'phids': [phid]})
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   787
        result.reverse()
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   788
        return smartset.baseset(result)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   789
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   790
    # Initialize prefetch cache
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   791
    prefetched = {} # {id or phid: drev}
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   792
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   793
    tree = _parse(spec)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   794
    drevs, ancestordrevs = _prefetchdrevs(tree)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   795
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   796
    # developer config: phabricator.batchsize
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   797
    batchsize = repo.ui.configint(b'phabricator', b'batchsize')
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   798
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   799
    # Prefetch Differential Revisions in batch
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   800
    tofetch = set(drevs)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   801
    for r in ancestordrevs:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   802
        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
   803
    if drevs:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   804
        fetch({r'ids': list(tofetch)})
33833
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   805
    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
   806
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   807
    # 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
   808
    def walk(tree):
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   809
        op = tree[0]
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   810
        if op == b'symbol':
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   811
            drev = _parsedrev(tree[1])
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   812
            if drev:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   813
                return smartset.baseset([drev])
33833
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   814
            elif tree[1] in _knownstatusnames:
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   815
                drevs = [r for r in validids
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   816
                         if _getstatusname(prefetched[r]) == tree[1]]
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   817
                return smartset.baseset(drevs)
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   818
            else:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   819
                raise error.Abort(_(b'unknown symbol: %s') % tree[1])
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   820
        elif op in {b'and_', b'add', b'sub'}:
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   821
            assert len(tree) == 3
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   822
            return getattr(operator, op)(walk(tree[1]), walk(tree[2]))
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   823
        elif op == b'group':
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   824
            return walk(tree[1])
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   825
        elif op == b'ancestors':
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   826
            return getstack(walk(tree[1]))
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   827
        else:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   828
            raise error.ProgrammingError(b'illegal tree: %r' % tree)
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   829
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   830
    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
   831
33268
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   832
def getdescfromdrev(drev):
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   833
    """get description (commit message) from "Differential Revision"
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   834
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   835
    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
   836
    about limited fields: title, summary, test plan, and URL.
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   837
    """
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   838
    title = drev[r'title']
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   839
    summary = drev[r'summary'].rstrip()
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   840
    testplan = drev[r'testPlan'].rstrip()
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   841
    if testplan:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   842
        testplan = b'Test Plan:\n%s' % testplan
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   843
    uri = b'Differential Revision: %s' % drev[r'uri']
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   844
    return b'\n\n'.join(filter(None, [title, summary, testplan, uri]))
33268
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   845
33441
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   846
def getdiffmeta(diff):
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   847
    """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
   848
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   849
    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
   850
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   851
        "properties": {
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   852
          "hg:meta": {
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   853
            "date": "1499571514 25200",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   854
            "node": "98c08acae292b2faf60a279b4189beb6cff1414d",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   855
            "user": "Foo Bar <foo@example.com>",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   856
            "parent": "6d0abad76b30e4724a37ab8721d630394070fe16"
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   857
          }
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   858
        }
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   859
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   860
    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
   861
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   862
        "properties": {
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   863
          "local:commits": {
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   864
            "98c08acae292b2faf60a279b4189beb6cff1414d": {
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   865
              "author": "Foo Bar",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   866
              "time": 1499546314,
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   867
              "branch": "default",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   868
              "tag": "",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   869
              "commit": "98c08acae292b2faf60a279b4189beb6cff1414d",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   870
              "rev": "98c08acae292b2faf60a279b4189beb6cff1414d",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   871
              "local": "1000",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   872
              "parents": ["6d0abad76b30e4724a37ab8721d630394070fe16"],
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   873
              "summary": "...",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   874
              "message": "...",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   875
              "authorEmail": "foo@example.com"
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   876
            }
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   877
          }
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   878
        }
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   879
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   880
    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
   881
    information.
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   882
    """
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   883
    props = diff.get(r'properties') or {}
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   884
    meta = props.get(r'hg:meta')
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   885
    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
   886
        commit = sorted(props[r'local:commits'].values())[0]
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   887
        meta = {
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   888
            r'date': r'%d 0' % commit[r'time'],
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   889
            r'node': commit[r'rev'],
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   890
            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
   891
        }
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   892
        if len(commit.get(r'parents', ())) >= 1:
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   893
            meta[r'parent'] = commit[r'parents'][0]
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   894
    return meta or {}
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   895
33831
75fdaf851e83 phabricator: change "readpatch" to be more flexible
Jun Wu <quark@fb.com>
parents: 33787
diff changeset
   896
def readpatch(repo, drevs, write):
33200
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
   897
    """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
   898
33831
75fdaf851e83 phabricator: change "readpatch" to be more flexible
Jun Wu <quark@fb.com>
parents: 33787
diff changeset
   899
    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
   900
    "differential.query".
33200
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
   901
    """
33267
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   902
    # 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
   903
    diffids = sorted(set(max(int(v) for v in drev[r'diffs']) for drev in drevs))
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   904
    diffs = callconduit(repo, b'differential.querydiffs', {b'ids': diffids})
33200
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
   905
33267
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   906
    # 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
   907
    for drev in drevs:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   908
        repo.ui.note(_(b'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
   909
33267
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   910
        diffid = max(int(v) for v in drev[r'diffs'])
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   911
        body = callconduit(repo, b'differential.getrawdiff',
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   912
                           {b'diffID': diffid})
33268
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   913
        desc = getdescfromdrev(drev)
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   914
        header = b'# HG changeset patch\n'
33267
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   915
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   916
        # 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
   917
        # 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
   918
        # 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
   919
        meta = getdiffmeta(diffs[str(diffid)])
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   920
        for k in _metanamemap.keys():
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   921
            if k in meta:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   922
                header += b'# %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
   923
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   924
        content = b'%s%s\n%s' % (header, desc, body)
33601
850d2ec2cf6a phabricator: convert unicode to binary when writing patches
Jun Wu <quark@fb.com>
parents: 33564
diff changeset
   925
        write(encoding.unitolocal(content))
33200
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
   926
39650
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38945
diff changeset
   927
@vcrcommand(b'phabread',
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   928
         [(b'', b'stack', False, _(b'read dependencies'))],
41073
536beb130f3c phabricator: assign commands to help categories
Matt Harbison <matt_harbison@yahoo.com>
parents: 40546
diff changeset
   929
         _(b'DREVSPEC [OPTIONS]'),
536beb130f3c phabricator: assign commands to help categories
Matt Harbison <matt_harbison@yahoo.com>
parents: 40546
diff changeset
   930
         helpcategory=command.CATEGORY_IMPORT_EXPORT)
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   931
def phabread(ui, repo, spec, **opts):
33200
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
   932
    """print patches from Phabricator suitable for importing
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
   933
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   934
    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
   935
    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
   936
    ``&``, ``(``, ``)`` 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
   937
    select a stack.
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   938
33833
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   939
    ``abandoned``, ``accepted``, ``closed``, ``needsreview``, ``needsrevision``
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33832
diff changeset
   940
    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
   941
    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
   942
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   943
    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
   944
    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
   945
    stack up to D9.
33200
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
   946
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
   947
    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
   948
    It is equivalent to the ``:`` operator.
33200
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33199
diff changeset
   949
    """
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   950
    if opts.get(b'stack'):
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   951
        spec = b':(%s)' % spec
33832
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33831
diff changeset
   952
    drevs = querydrev(repo, spec)
33831
75fdaf851e83 phabricator: change "readpatch" to be more flexible
Jun Wu <quark@fb.com>
parents: 33787
diff changeset
   953
    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
   954
39650
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38945
diff changeset
   955
@vcrcommand(b'phabupdate',
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   956
         [(b'', b'accept', False, _(b'accept revisions')),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   957
          (b'', b'reject', False, _(b'reject revisions')),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   958
          (b'', b'abandon', False, _(b'abandon revisions')),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   959
          (b'', b'reclaim', False, _(b'reclaim revisions')),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   960
          (b'm', b'comment', b'', _(b'comment on the last revision')),
41073
536beb130f3c phabricator: assign commands to help categories
Matt Harbison <matt_harbison@yahoo.com>
parents: 40546
diff changeset
   961
          ], _(b'DREVSPEC [OPTIONS]'),
536beb130f3c phabricator: assign commands to help categories
Matt Harbison <matt_harbison@yahoo.com>
parents: 40546
diff changeset
   962
          helpcategory=command.CATEGORY_IMPORT_EXPORT)
33834
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   963
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
   964
    """update Differential Revision in batch
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   965
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   966
    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
   967
    """
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   968
    flags = [n for n in b'accept reject abandon reclaim'.split() if opts.get(n)]
33834
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   969
    if len(flags) > 1:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   970
        raise error.Abort(_(b'%s cannot be used together') % b', '.join(flags))
33834
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   971
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   972
    actions = []
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   973
    for f in flags:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   974
        actions.append({b'type': f, b'value': b'true'})
33834
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   975
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   976
    drevs = querydrev(repo, spec)
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   977
    for i, drev in enumerate(drevs):
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   978
        if i + 1 == len(drevs) and opts.get(b'comment'):
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   979
            actions.append({b'type': b'comment', b'value': opts[b'comment']})
33834
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33833
diff changeset
   980
        if actions:
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   981
            params = {b'objectIdentifier': drev[r'phid'],
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   982
                      b'transactions': actions}
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   983
            callconduit(repo, b'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
   984
f18ba40d792f phabricator: add a template item for linking to a differential review
Tom Prince <mozilla@hocat.ca>
parents: 35626
diff changeset
   985
templatekeyword = registrar.templatekeyword()
f18ba40d792f phabricator: add a template item for linking to a differential review
Tom Prince <mozilla@hocat.ca>
parents: 35626
diff changeset
   986
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   987
@templatekeyword(b'phabreview', requires={b'ctx'})
36514
7b74afec6772 templatekw: switch non-showlist template keywords to new API
Yuya Nishihara <yuya@tcha.org>
parents: 35722
diff changeset
   988
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
   989
    """: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
   990
    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
   991
    """
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   992
    ctx = context.resource(mapping, b'ctx')
35722
f18ba40d792f phabricator: add a template item for linking to a differential review
Tom Prince <mozilla@hocat.ca>
parents: 35626
diff changeset
   993
    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
   994
    if m:
39654
4057e38bba76 phabricator: fix templating bug by using hybriddict
Augie Fackler <raf@durin42.com>
parents: 39652
diff changeset
   995
        return templateutil.hybriddict({
38392
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   996
            b'url': m.group(b'url'),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38336
diff changeset
   997
            b'id': b"D{}".format(m.group(b'id')),
39654
4057e38bba76 phabricator: fix templating bug by using hybriddict
Augie Fackler <raf@durin42.com>
parents: 39652
diff changeset
   998
        })
41164
43fd1947301d phabricator: teach {phabreview} to work without --amend
Matt Harbison <matt_harbison@yahoo.com>
parents: 41163
diff changeset
   999
    else:
43fd1947301d phabricator: teach {phabreview} to work without --amend
Matt Harbison <matt_harbison@yahoo.com>
parents: 41163
diff changeset
  1000
        tags = ctx.repo().nodetags(ctx.node())
43fd1947301d phabricator: teach {phabreview} to work without --amend
Matt Harbison <matt_harbison@yahoo.com>
parents: 41163
diff changeset
  1001
        for t in tags:
43fd1947301d phabricator: teach {phabreview} to work without --amend
Matt Harbison <matt_harbison@yahoo.com>
parents: 41163
diff changeset
  1002
            if _differentialrevisiontagre.match(t):
43fd1947301d phabricator: teach {phabreview} to work without --amend
Matt Harbison <matt_harbison@yahoo.com>
parents: 41163
diff changeset
  1003
                url = ctx.repo().ui.config(b'phabricator', b'url')
43fd1947301d phabricator: teach {phabreview} to work without --amend
Matt Harbison <matt_harbison@yahoo.com>
parents: 41163
diff changeset
  1004
                if not url.endswith(b'/'):
43fd1947301d phabricator: teach {phabreview} to work without --amend
Matt Harbison <matt_harbison@yahoo.com>
parents: 41163
diff changeset
  1005
                    url += b'/'
43fd1947301d phabricator: teach {phabreview} to work without --amend
Matt Harbison <matt_harbison@yahoo.com>
parents: 41163
diff changeset
  1006
                url += t
43fd1947301d phabricator: teach {phabreview} to work without --amend
Matt Harbison <matt_harbison@yahoo.com>
parents: 41163
diff changeset
  1007
43fd1947301d phabricator: teach {phabreview} to work without --amend
Matt Harbison <matt_harbison@yahoo.com>
parents: 41163
diff changeset
  1008
                return templateutil.hybriddict({
43fd1947301d phabricator: teach {phabreview} to work without --amend
Matt Harbison <matt_harbison@yahoo.com>
parents: 41163
diff changeset
  1009
                    b'url': url,
43fd1947301d phabricator: teach {phabreview} to work without --amend
Matt Harbison <matt_harbison@yahoo.com>
parents: 41163
diff changeset
  1010
                    b'id': t,
43fd1947301d phabricator: teach {phabreview} to work without --amend
Matt Harbison <matt_harbison@yahoo.com>
parents: 41163
diff changeset
  1011
                })
43fd1947301d phabricator: teach {phabreview} to work without --amend
Matt Harbison <matt_harbison@yahoo.com>
parents: 41163
diff changeset
  1012
    return None