hgext/phabricator.py
author Pulkit Goyal <pulkit@yandex-team.ru>
Mon, 24 Dec 2018 15:01:47 +0300
changeset 41147 eb172f9c208c
parent 41083 9d35ae3d9999
child 41163 0101a35deae2
permissions -rw-r--r--
tests: add tests for narrow clone when both sparse and narrow are enabled This patch adds tests for doing a narrow clone when client has both sparse and narrow enabled. As shown by this patch, we can see that the narrow clone has sparse enabled which we does not want here. Upcoming patch will fix this. Also while writing tests, I realized we don't have a flag to list the current sparse profile. Differential Revision: https://phab.mercurial-scm.org/D5478
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
33200
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.
39671
87539f615b87 phabricator: mark extension as experimental for now
Augie Fackler <raf@durin42.com>
parents: 39670
diff changeset
     7
"""simple Phabricator integration (EXPERIMENTAL)
33200
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
     8
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
     9
This extension provides a ``phabsend`` command which sends a stack of
33993
07ffff841863 phabsend: make --amend the default
Jun Wu <quark@fb.com>
parents: 33992
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: 33992
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: 33992
diff changeset
    12
to update statuses in batch.
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
    13
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
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: 33200
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: 33200
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: 33200
diff changeset
    17
33200
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
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
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: 33200
diff changeset
    25
    # callsign is "FOO".
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
    26
    callsign = FOO
33202
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33201
diff changeset
    27
34081
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34080
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: 34080
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: 34080
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: 34080
diff changeset
    31
    # the internal library.
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34080
diff changeset
    32
    curlcmd = curl --connect-timeout 2 --retry 3 --silent
36795
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36543
diff changeset
    33
38039
0fa050bc68cb phabricator: migrate [phabricator.auth] to [auth]
Matt Harbison <matt_harbison@yahoo.com>
parents: 38020
diff changeset
    34
    [auth]
38040
71cf20d47f25 phabricator: split auth.url into the standard auth.schemes and auth.prefix
Matt Harbison <matt_harbison@yahoo.com>
parents: 38039
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: 38039
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: 38039
diff changeset
    37
36795
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36543
diff changeset
    38
    # API token. Get it from https://$HOST/conduit/login/
38039
0fa050bc68cb phabricator: migrate [phabricator.auth] to [auth]
Matt Harbison <matt_harbison@yahoo.com>
parents: 38020
diff changeset
    39
    example.phabtoken = cli-xxxxxxxxxxxxxxxxxxxxxxxxxxxx
33200
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
41083
9d35ae3d9999 phabricator: ensure that the return of urlopener.open() is closed
Matt Harbison <matt_harbison@yahoo.com>
parents: 41081
diff changeset
    44
import contextlib
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
    45
import itertools
33200
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    46
import json
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
    47
import operator
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
    48
import re
33200
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
33200
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 (
33808
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
    53
    cmdutil,
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
    54
    context,
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
    55
    encoding,
33200
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    56
    error,
38040
71cf20d47f25 phabricator: split auth.url into the standard auth.schemes and auth.prefix
Matt Harbison <matt_harbison@yahoo.com>
parents: 38039
diff changeset
    57
    httpconnection as httpconnectionmod,
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
    58
    mdiff,
33761
e6d8ee3c9ec3 obsutil: rename allprecursors into allpredecessors
Boris Feld <boris.feld@octobus.net>
parents: 33718
diff changeset
    59
    obsutil,
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
    60
    parser,
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
    61
    patch,
33200
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    62
    registrar,
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
    63
    scmutil,
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
    64
    smartset,
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
    65
    tags,
39670
4057e38bba76 phabricator: fix templating bug by using hybriddict
Augie Fackler <raf@durin42.com>
parents: 39668
diff changeset
    66
    templateutil,
33200
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    67
    url as urlmod,
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    68
    util,
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    69
)
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36826
diff changeset
    70
from mercurial.utils import (
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36826
diff changeset
    71
    procutil,
37800
6cf5f5b4eb57 phabricator: specify some metadata compatibly with arc
Tom Prince <mozilla@hocat.ca>
parents: 37123
diff changeset
    72
    stringutil,
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36826
diff changeset
    73
)
33200
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    74
39751
c0c703861b60 phabricator: add testedwith boilerplate
Yuya Nishihara <yuya@tcha.org>
parents: 39671
diff changeset
    75
# Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
c0c703861b60 phabricator: add testedwith boilerplate
Yuya Nishihara <yuya@tcha.org>
parents: 39671
diff changeset
    76
# extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
c0c703861b60 phabricator: add testedwith boilerplate
Yuya Nishihara <yuya@tcha.org>
parents: 39671
diff changeset
    77
# be specifying the version(s) of Mercurial they are tested with, or
c0c703861b60 phabricator: add testedwith boilerplate
Yuya Nishihara <yuya@tcha.org>
parents: 39671
diff changeset
    78
# leave the attribute unspecified.
c0c703861b60 phabricator: add testedwith boilerplate
Yuya Nishihara <yuya@tcha.org>
parents: 39671
diff changeset
    79
testedwith = 'ships-with-hg-core'
c0c703861b60 phabricator: add testedwith boilerplate
Yuya Nishihara <yuya@tcha.org>
parents: 39671
diff changeset
    80
33200
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    81
cmdtable = {}
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    82
command = registrar.command(cmdtable)
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
    83
38075
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 38040
diff changeset
    84
configtable = {}
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 38040
diff changeset
    85
configitem = registrar.configitem(configtable)
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 38040
diff changeset
    86
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 38040
diff changeset
    87
# developer config: phabricator.batchsize
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
    88
configitem(b'phabricator', b'batchsize',
38075
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 38040
diff changeset
    89
    default=12,
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 38040
diff changeset
    90
)
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
    91
configitem(b'phabricator', b'callsign',
38075
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 38040
diff changeset
    92
    default=None,
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 38040
diff changeset
    93
)
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
    94
configitem(b'phabricator', b'curlcmd',
38075
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 38040
diff changeset
    95
    default=None,
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 38040
diff changeset
    96
)
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 38040
diff changeset
    97
# developer config: phabricator.repophid
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
    98
configitem(b'phabricator', b'repophid',
38075
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 38040
diff changeset
    99
    default=None,
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 38040
diff changeset
   100
)
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   101
configitem(b'phabricator', b'url',
38075
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 38040
diff changeset
   102
    default=None,
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 38040
diff changeset
   103
)
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   104
configitem(b'phabsend', b'confirm',
38075
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 38040
diff changeset
   105
    default=False,
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 38040
diff changeset
   106
)
5a7cf42ba6ef phabricator: register config settings
Matt Harbison <matt_harbison@yahoo.com>
parents: 38040
diff changeset
   107
34080
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33996
diff changeset
   108
colortable = {
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   109
    b'phabricator.action.created': b'green',
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   110
    b'phabricator.action.skipped': b'magenta',
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   111
    b'phabricator.action.updated': b'magenta',
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   112
    b'phabricator.desc': b'',
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   113
    b'phabricator.drev': b'bold',
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   114
    b'phabricator.node': b'',
34080
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33996
diff changeset
   115
}
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33996
diff changeset
   116
39666
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38983
diff changeset
   117
_VCR_FLAGS = [
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38983
diff changeset
   118
    (b'', b'test-vcr', b'',
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38983
diff changeset
   119
     _(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: 38983
diff changeset
   120
       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: 38983
diff changeset
   121
       b' (ADVANCED)'
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38983
diff changeset
   122
     )),
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38983
diff changeset
   123
]
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38983
diff changeset
   124
41076
536beb130f3c phabricator: assign commands to help categories
Matt Harbison <matt_harbison@yahoo.com>
parents: 40435
diff changeset
   125
def vcrcommand(name, flags, spec, helpcategory=None):
39666
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38983
diff changeset
   126
    fullflags = flags + _VCR_FLAGS
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38983
diff changeset
   127
    def decorate(fn):
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38983
diff changeset
   128
        def inner(*args, **kwargs):
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38983
diff changeset
   129
            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: 38983
diff changeset
   130
            if cassette:
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38983
diff changeset
   131
                import hgdemandimport
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38983
diff changeset
   132
                with hgdemandimport.deactivated():
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38983
diff changeset
   133
                    import vcr as vcrmod
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38983
diff changeset
   134
                    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
   135
                    vcr = vcrmod.VCR(
b015f30a91fb phabricator: do more of the VCR work in demandimport.deactivated()
Augie Fackler <augie@google.com>
parents: 40151
diff changeset
   136
                        serializer=r'json',
b015f30a91fb phabricator: do more of the VCR work in demandimport.deactivated()
Augie Fackler <augie@google.com>
parents: 40151
diff changeset
   137
                        custom_patches=[
b015f30a91fb phabricator: do more of the VCR work in demandimport.deactivated()
Augie Fackler <augie@google.com>
parents: 40151
diff changeset
   138
                            (urlmod, 'httpconnection', stubs.VCRHTTPConnection),
b015f30a91fb phabricator: do more of the VCR work in demandimport.deactivated()
Augie Fackler <augie@google.com>
parents: 40151
diff changeset
   139
                            (urlmod, 'httpsconnection',
b015f30a91fb phabricator: do more of the VCR work in demandimport.deactivated()
Augie Fackler <augie@google.com>
parents: 40151
diff changeset
   140
                             stubs.VCRHTTPSConnection),
b015f30a91fb phabricator: do more of the VCR work in demandimport.deactivated()
Augie Fackler <augie@google.com>
parents: 40151
diff changeset
   141
                        ])
b015f30a91fb phabricator: do more of the VCR work in demandimport.deactivated()
Augie Fackler <augie@google.com>
parents: 40151
diff changeset
   142
                    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
   143
                        return fn(*args, **kwargs)
39666
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38983
diff changeset
   144
            return fn(*args, **kwargs)
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38983
diff changeset
   145
        inner.__name__ = fn.__name__
40435
7e2c58b08e74 phabricator: ensure the command summaries are available in extension help
Matt Harbison <matt_harbison@yahoo.com>
parents: 40378
diff changeset
   146
        inner.__doc__ = fn.__doc__
41076
536beb130f3c phabricator: assign commands to help categories
Matt Harbison <matt_harbison@yahoo.com>
parents: 40435
diff changeset
   147
        return command(name, fullflags, spec, helpcategory=helpcategory)(inner)
39666
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38983
diff changeset
   148
    return decorate
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38983
diff changeset
   149
33200
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   150
def urlencodenested(params):
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   151
    """like urlencode, but works with nested parameters.
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   152
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   153
    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
   154
    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
   155
    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
   156
    """
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   157
    flatparams = util.sortdict()
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   158
    def process(prefix, obj):
40473
d7d3164e6a31 phabricator: properly encode boolean types in the request body
Matt Harbison <matt_harbison@yahoo.com>
parents: 40435
diff changeset
   159
        if isinstance(obj, bool):
d7d3164e6a31 phabricator: properly encode boolean types in the request body
Matt Harbison <matt_harbison@yahoo.com>
parents: 40435
diff changeset
   160
            obj = {True: b'true', False: b'false'}[obj]  # Python -> PHP form
33200
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   161
        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
   162
        if items is None:
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   163
            flatparams[prefix] = obj
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   164
        else:
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   165
            for k, v in items(obj):
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   166
                if prefix:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   167
                    process(b'%s[%s]' % (prefix, k), v)
33200
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   168
                else:
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   169
                    process(k, v)
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   170
    process(b'', params)
33200
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   171
    return util.urlreq.urlencode(flatparams)
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   172
38039
0fa050bc68cb phabricator: migrate [phabricator.auth] to [auth]
Matt Harbison <matt_harbison@yahoo.com>
parents: 38020
diff changeset
   173
def readurltoken(repo):
0fa050bc68cb phabricator: migrate [phabricator.auth] to [auth]
Matt Harbison <matt_harbison@yahoo.com>
parents: 38020
diff changeset
   174
    """return conduit url, token and make sure they exist
0fa050bc68cb phabricator: migrate [phabricator.auth] to [auth]
Matt Harbison <matt_harbison@yahoo.com>
parents: 38020
diff changeset
   175
38040
71cf20d47f25 phabricator: split auth.url into the standard auth.schemes and auth.prefix
Matt Harbison <matt_harbison@yahoo.com>
parents: 38039
diff changeset
   176
    Currently read from [auth] config section. In the future, it might
38039
0fa050bc68cb phabricator: migrate [phabricator.auth] to [auth]
Matt Harbison <matt_harbison@yahoo.com>
parents: 38020
diff changeset
   177
    make sense to read from .arcconfig and .arcrc as well.
0fa050bc68cb phabricator: migrate [phabricator.auth] to [auth]
Matt Harbison <matt_harbison@yahoo.com>
parents: 38020
diff changeset
   178
    """
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   179
    url = repo.ui.config(b'phabricator', b'url')
38039
0fa050bc68cb phabricator: migrate [phabricator.auth] to [auth]
Matt Harbison <matt_harbison@yahoo.com>
parents: 38020
diff changeset
   180
    if not url:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   181
        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: 38342
diff changeset
   182
                          % (b'phabricator', b'url'))
38039
0fa050bc68cb phabricator: migrate [phabricator.auth] to [auth]
Matt Harbison <matt_harbison@yahoo.com>
parents: 38020
diff changeset
   183
38040
71cf20d47f25 phabricator: split auth.url into the standard auth.schemes and auth.prefix
Matt Harbison <matt_harbison@yahoo.com>
parents: 38039
diff changeset
   184
    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: 38039
diff changeset
   185
    token = None
38039
0fa050bc68cb phabricator: migrate [phabricator.auth] to [auth]
Matt Harbison <matt_harbison@yahoo.com>
parents: 38020
diff changeset
   186
38040
71cf20d47f25 phabricator: split auth.url into the standard auth.schemes and auth.prefix
Matt Harbison <matt_harbison@yahoo.com>
parents: 38039
diff changeset
   187
    if res:
71cf20d47f25 phabricator: split auth.url into the standard auth.schemes and auth.prefix
Matt Harbison <matt_harbison@yahoo.com>
parents: 38039
diff changeset
   188
        group, auth = res
71cf20d47f25 phabricator: split auth.url into the standard auth.schemes and auth.prefix
Matt Harbison <matt_harbison@yahoo.com>
parents: 38039
diff changeset
   189
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   190
        repo.ui.debug(b"using auth.%s.* for authentication\n" % group)
38040
71cf20d47f25 phabricator: split auth.url into the standard auth.schemes and auth.prefix
Matt Harbison <matt_harbison@yahoo.com>
parents: 38039
diff changeset
   191
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   192
        token = auth.get(b'phabtoken')
38039
0fa050bc68cb phabricator: migrate [phabricator.auth] to [auth]
Matt Harbison <matt_harbison@yahoo.com>
parents: 38020
diff changeset
   193
36795
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36543
diff changeset
   194
    if not token:
40151
38ac525b44c9 phabricator: drop support for the legacy phabricator.auth.token config (BC)
Matt Harbison <matt_harbison@yahoo.com>
parents: 39751
diff changeset
   195
        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: 39751
diff changeset
   196
                            % (url,))
36795
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36543
diff changeset
   197
4397909f82d3 phabricator: specify API tokens per host, rather than per repo
Tom Prince <mozilla@hocat.ca>
parents: 36543
diff changeset
   198
    return url, token
33200
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   199
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   200
def callconduit(repo, name, params):
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   201
    """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
   202
    host, token = readurltoken(repo)
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   203
    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: 38342
diff changeset
   204
    repo.ui.debug(b'Conduit Call: %s %s\n' % (url, params))
33200
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   205
    params = params.copy()
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   206
    params[b'api.token'] = token
34081
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34080
diff changeset
   207
    data = urlencodenested(params)
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   208
    curlcmd = repo.ui.config(b'phabricator', b'curlcmd')
34081
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34080
diff changeset
   209
    if curlcmd:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   210
        sin, sout = procutil.popen2(b'%s -d @- %s'
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36826
diff changeset
   211
                                    % (curlcmd, procutil.shellquote(url)))
34081
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34080
diff changeset
   212
        sin.write(data)
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34080
diff changeset
   213
        sin.close()
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34080
diff changeset
   214
        body = sout.read()
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34080
diff changeset
   215
    else:
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34080
diff changeset
   216
        urlopener = urlmod.opener(repo.ui, authinfo)
8b659b7388c0 phabricator: add a config to use curl for communication
Jun Wu <quark@fb.com>
parents: 34080
diff changeset
   217
        request = util.urlreq.request(url, data=data)
41083
9d35ae3d9999 phabricator: ensure that the return of urlopener.open() is closed
Matt Harbison <matt_harbison@yahoo.com>
parents: 41081
diff changeset
   218
        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: 41081
diff changeset
   219
            body = rsp.read()
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   220
    repo.ui.debug(b'Conduit Response: %s\n' % body)
33200
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   221
    parsed = json.loads(body)
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   222
    if parsed.get(r'error_code'):
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   223
        msg = (_(b'Conduit Error (%s): %s')
33200
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   224
               % (parsed[r'error_code'], parsed[r'error_info']))
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   225
        raise error.Abort(msg)
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   226
    return parsed[r'result']
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   227
39666
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38983
diff changeset
   228
@vcrcommand(b'debugcallconduit', [], _(b'METHOD'))
33200
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   229
def debugcallconduit(ui, repo, name):
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   230
    """call Conduit API
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   231
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   232
    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
   233
    to stdout as a JSON blob.
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   234
    """
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   235
    params = json.loads(ui.fin.read())
36b3febd739f phabricator: add a contrib script
Jun Wu <quark@fb.com>
parents:
diff changeset
   236
    result = callconduit(repo, name, params)
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   237
    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: 38342
diff changeset
   238
    ui.write(b'%s\n' % s)
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   239
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   240
def getrepophid(repo):
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   241
    """given callsign, return repository PHID or None"""
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   242
    # developer config: phabricator.repophid
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   243
    repophid = repo.ui.config(b'phabricator', b'repophid')
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   244
    if repophid:
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   245
        return repophid
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   246
    callsign = repo.ui.config(b'phabricator', b'callsign')
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   247
    if not callsign:
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   248
        return None
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   249
    query = callconduit(repo, b'diffusion.repository.search',
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   250
                        {b'constraints': {b'callsigns': [callsign]}})
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   251
    if len(query[r'data']) == 0:
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   252
        return None
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   253
    repophid = encoding.strtolocal(query[r'data'][0][r'phid'])
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   254
    repo.ui.setconfig(b'phabricator', b'repophid', repophid)
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   255
    return repophid
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   256
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   257
_differentialrevisiontagre = re.compile(b'\AD([1-9][0-9]*)\Z')
33263
ed61189763ef phabricator: check associated Differential Revision from commit message
Jun Wu <quark@fb.com>
parents: 33202
diff changeset
   258
_differentialrevisiondescre = re.compile(
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   259
    b'^Differential Revision:\s*(?P<url>(?:.*)D(?P<id>[1-9][0-9]*))$', re.M)
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   260
33442
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   261
def getoldnodedrevmap(repo, nodelist):
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   262
    """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
   263
33717
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
diff changeset
   264
    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
   265
    for node in nodelist with known previous sent versions, or associated
33717
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
diff changeset
   266
    Differential Revision IDs. ``oldnode`` and ``Differential diff`` could
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
diff changeset
   267
    be ``None``.
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   268
33717
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
diff changeset
   269
    Examines commit messages like "Differential Revision:" to get the
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
diff changeset
   270
    association information.
33263
ed61189763ef phabricator: check associated Differential Revision from commit message
Jun Wu <quark@fb.com>
parents: 33202
diff changeset
   271
33717
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
diff changeset
   272
    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: 33716
diff changeset
   273
    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: 33716
diff changeset
   274
    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: 33716
diff changeset
   275
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
diff changeset
   276
    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: 33716
diff changeset
   277
    corresponding Differential Revision, and exist in the repo.
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   278
    """
33442
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   279
    url, token = readurltoken(repo)
3ab0d5767b54 phabricator: finding old nodes in batch
Jun Wu <quark@fb.com>
parents: 33441
diff changeset
   280
    unfi = repo.unfiltered()
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   281
    nodemap = unfi.changelog.nodemap
33263
ed61189763ef phabricator: check associated Differential Revision from commit message
Jun Wu <quark@fb.com>
parents: 33202
diff changeset
   282
33717
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
diff changeset
   283
    result = {} # {node: (oldnode?, lastdiff?, drev)}
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
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
33761
e6d8ee3c9ec3 obsutil: rename allprecursors into allpredecessors
Boris Feld <boris.feld@octobus.net>
parents: 33718
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:
33717
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
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: 33202
diff changeset
   296
33717
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
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:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
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: 33202
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:
33717
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
diff changeset
   305
        drevs = [drev for force, precs, drev in toconfirm.values()]
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
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: 38342
diff changeset
   307
                               {b'revisionIDs': drevs})
33717
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
diff changeset
   308
        getnode = lambda d: bin(encoding.unitolocal(
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   309
            getdiffmeta(d).get(r'node', b''))) or None
33717
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
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: 33716
diff changeset
   311
            diffs = [d for d in alldiffs.values()
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
diff changeset
   312
                     if int(d[r'revisionID']) == drev]
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
diff changeset
   313
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
diff changeset
   314
            # "precursors" as known by Phabricator
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
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: 33716
diff changeset
   316
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
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: 33716
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: 33716
diff changeset
   319
            if not force and not bool(phprecset & precset):
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
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)
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
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: 38342
diff changeset
   324
                               b'Differential history\n') % drev)
33717
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
diff changeset
   325
                continue
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
diff changeset
   326
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
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: 33716
diff changeset
   328
            # exists in the repo
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
diff changeset
   329
            oldnode = lastdiff = None
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
diff changeset
   330
            if diffs:
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
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: 33716
diff changeset
   332
                oldnode = getnode(lastdiff)
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
diff changeset
   333
                if oldnode and oldnode not in nodemap:
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
diff changeset
   334
                    oldnode = None
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
diff changeset
   335
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
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
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   339
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   340
def getdiff(ctx, diffopts):
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
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: 33200
diff changeset
   342
    output = util.stringio()
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
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: 33200
diff changeset
   344
                                      None, opts=diffopts):
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   345
        output.write(chunk)
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   346
    return output.getvalue()
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   347
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   348
def creatediff(ctx):
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   349
    """create a Differential Diff"""
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   350
    repo = ctx.repo()
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   351
    repophid = getrepophid(repo)
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   352
    # Create a "Differential Diff" via "differential.createrawdiff" API
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   353
    params = {b'diff': getdiff(ctx, mdiff.diffopts(git=True, context=32767))}
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   354
    if repophid:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   355
        params[b'repositoryPHID'] = repophid
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   356
    diff = callconduit(repo, b'differential.createrawdiff', params)
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   357
    if not diff:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   358
        raise error.Abort(_(b'cannot create diff for %s') % ctx)
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   359
    return diff
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   360
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   361
def writediffproperties(ctx, diff):
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
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: 33200
diff changeset
   363
    params = {
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
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: 38342
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: 38342
diff changeset
   366
        b'data': json.dumps({
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   367
            b'user': ctx.user(),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
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: 38342
diff changeset
   369
            b'node': ctx.hex(),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   370
            b'parent': ctx.p1().hex(),
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   371
        }),
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   372
    }
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   373
    callconduit(ctx.repo(), b'differential.setdiffproperty', params)
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   374
37800
6cf5f5b4eb57 phabricator: specify some metadata compatibly with arc
Tom Prince <mozilla@hocat.ca>
parents: 37123
diff changeset
   375
    params = {
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
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: 38342
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: 38342
diff changeset
   378
        b'data': json.dumps({
37800
6cf5f5b4eb57 phabricator: specify some metadata compatibly with arc
Tom Prince <mozilla@hocat.ca>
parents: 37123
diff changeset
   379
            ctx.hex(): {
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
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: 38342
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: 38342
diff changeset
   382
                b'time': ctx.date()[0],
37800
6cf5f5b4eb57 phabricator: specify some metadata compatibly with arc
Tom Prince <mozilla@hocat.ca>
parents: 37123
diff changeset
   383
            },
6cf5f5b4eb57 phabricator: specify some metadata compatibly with arc
Tom Prince <mozilla@hocat.ca>
parents: 37123
diff changeset
   384
        }),
6cf5f5b4eb57 phabricator: specify some metadata compatibly with arc
Tom Prince <mozilla@hocat.ca>
parents: 37123
diff changeset
   385
    }
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
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: 37123
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,
33718
f100354cce52 phabricator: update diff property even if we choose not to create a new diff
Jun Wu <quark@fb.com>
parents: 33717
diff changeset
   389
                               olddiff=None, actions=None):
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   390
    """create or update a Differential Revision
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   391
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
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: 33200
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.
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   399
    """
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
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:
33994
27ff2a87d8c0 phabsend: detect patch change with larger context
Jun Wu <quark@fb.com>
parents: 33993
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
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
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)
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   411
        transactions.append({b'type': b'update', b'value': diff[r'phid']})
33718
f100354cce52 phabricator: update diff property even if we choose not to create a new diff
Jun Wu <quark@fb.com>
parents: 33717
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: 33717
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: 33717
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: 33717
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: 33717
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: 33717
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: 33717
diff changeset
   418
    writediffproperties(ctx, diff)
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   419
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
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: 33200
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: 33200
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: 33200
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: 33200
diff changeset
   424
    if parentrevid and revid is None:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
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: 38342
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: 38342
diff changeset
   427
                         {b'type': b'summary', b'value': b' '}]
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
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
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
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: 33200
diff changeset
   433
    desc = ctx.description()
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
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: 38342
diff changeset
   435
                       {b'corpus': desc})
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   436
    for k, v in info[r'fields'].items():
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
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: 38342
diff changeset
   438
            transactions.append({b'type': k, b'value': v})
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   439
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   440
    params = {b'transactions': transactions}
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   441
    if revid is not None:
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   442
        # Update an existing Differential Revision
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   443
        params[b'objectIdentifier'] = revid
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   444
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   445
    revision = callconduit(repo, b'differential.revision.edit', params)
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   446
    if not revision:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   447
        raise error.Abort(_(b'cannot create revision for %s') % ctx)
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   448
33808
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   449
    return revision, diff
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
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"""
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
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: 38342
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:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
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: 38342
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
39666
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38983
diff changeset
   465
@vcrcommand(b'phabsend',
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
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: 38342
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: 38342
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: 38342
diff changeset
   469
          (b'', b'confirm', None, _(b'ask for confirmation before sending'))],
41076
536beb130f3c phabricator: assign commands to help categories
Matt Harbison <matt_harbison@yahoo.com>
parents: 40435
diff changeset
   470
         _(b'REV [OPTIONS]'),
536beb130f3c phabricator: assign commands to help categories
Matt Harbison <matt_harbison@yahoo.com>
parents: 40435
diff changeset
   471
         helpcategory=command.CATEGORY_IMPORT_EXPORT)
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   472
def phabsend(ui, repo, *revs, **opts):
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   473
    """upload changesets to Phabricator
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   474
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
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: 33200
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: 33200
diff changeset
   477
    revset.
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   478
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
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: 33200
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: 33200
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: 33200
diff changeset
   482
    existing Differential Revision, or create a new one.
33716
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   483
33808
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
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: 33806
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: 33806
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: 33806
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: 33806
diff changeset
   488
33716
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
33992
45a8cd74de4e phabsend: polish the docstring a bit
Jun Wu <quark@fb.com>
parents: 33855
diff changeset
   491
    behaviour::
33716
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   492
33992
45a8cd74de4e phabsend: polish the docstring a bit
Jun Wu <quark@fb.com>
parents: 33855
diff changeset
   493
        [phabsend]
45a8cd74de4e phabsend: polish the docstring a bit
Jun Wu <quark@fb.com>
parents: 33855
diff changeset
   494
        confirm = true
33808
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   495
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
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: 33806
diff changeset
   497
    update an existing Differential Revision, or create a new one.
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   498
    """
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   499
    revs = list(revs) + opts.get(b'rev', [])
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   500
    revs = scmutil.revrange(repo, revs)
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
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:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
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: 38342
diff changeset
   504
    if opts.get(b'amend'):
33808
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
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
33996
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33995
diff changeset
   507
    # {newnode: (oldnode, olddiff, olddrev}
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33995
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: 33995
diff changeset
   509
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
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: 38342
diff changeset
   511
    confirm |= bool(opts.get(b'confirm'))
33716
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   512
    if confirm:
33996
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33995
diff changeset
   513
        confirmed = _confirmbeforesend(repo, revs, oldmap)
33716
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   514
        if not confirmed:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   515
            raise error.Abort(_(b'phabsend cancelled'))
33716
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 = []
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
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)
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
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
33808
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   523
    drevids = [] # [int]
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   524
    diffmap = {} # {newnode: diff}
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   525
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
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: 33200
diff changeset
   527
    # can provide dependency relationship
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   528
    lastrevid = None
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   529
    for rev in revs:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   530
        ui.debug(b'sending rev %d\n' % rev)
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   531
        ctx = repo[rev]
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   532
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   533
        # Get Differential Revision ID
33717
1664406a44d9 phabricator: use Phabricator's last node information
Jun Wu <quark@fb.com>
parents: 33716
diff changeset
   534
        oldnode, olddiff, revid = oldmap.get(ctx.node(), (None, None, None))
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   535
        if oldnode != ctx.node() or opts.get(b'amend'):
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   536
            # Create or update Differential Revision
33808
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   537
            revision, diff = createdifferentialrevision(
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   538
                ctx, revid, lastrevid, oldnode, olddiff, actions)
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   539
            diffmap[ctx.node()] = diff
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
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: 33200
diff changeset
   541
            if revid:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   542
                action = b'updated'
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   543
            else:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   544
                action = b'created'
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   545
33808
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
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: 33806
diff changeset
   547
            # does not have it already
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   548
            m = _differentialrevisiondescre.search(ctx.description())
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
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: 38342
diff changeset
   550
                tagname = b'D%d' % newrevid
33808
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
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: 33806
diff changeset
   552
                         date=None, local=True)
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   553
        else:
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
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: 33200
diff changeset
   555
            # could depend on this one.
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   556
            newrevid = revid
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   557
            action = b'skipped'
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   558
34080
941c33cfde81 phabricator: standardize colors
Jun Wu <quark@fb.com>
parents: 33996
diff changeset
   559
        actiondesc = ui.label(
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   560
            {b'created': _(b'created'),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   561
             b'skipped': _(b'skipped'),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
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: 38342
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: 38342
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: 38342
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: 38342
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: 38342
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: 38342
diff changeset
   568
                                             desc))
33808
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   569
        drevids.append(newrevid)
33201
228ad1e58a85 phabricator: add phabsend command to send a stack
Jun Wu <quark@fb.com>
parents: 33200
diff changeset
   570
        lastrevid = newrevid
33202
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33201
diff changeset
   571
33808
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   572
    # Update commit messages and remove tags
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   573
    if opts.get(b'amend'):
33808
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   574
        unfi = repo.unfiltered()
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
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: 38342
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: 38342
diff changeset
   577
            wnode = unfi[b'.'].node()
33808
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   578
            mapping = {} # {oldnode: [newnode]}
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   579
            for i, rev in enumerate(revs):
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   580
                old = unfi[rev]
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   581
                drevid = drevids[i]
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
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: 33806
diff changeset
   583
                newdesc = getdescfromdrev(drev)
38983
0dce1297dd01 phabricator: convert description into local
Cédric Krier <ced@b2ck.com>
parents: 38429
diff changeset
   584
                newdesc = encoding.unitolocal(newdesc)
33808
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   585
                # Make sure commit message contain "Differential Revision"
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   586
                if old.description() != newdesc:
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   587
                    parents = [
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   588
                        mapping.get(old.p1().node(), (old.p1(),))[0],
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   589
                        mapping.get(old.p2().node(), (old.p2(),))[0],
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   590
                    ]
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   591
                    new = context.metadataonlyctx(
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   592
                        repo, old, parents=parents, text=newdesc,
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   593
                        user=old.user(), date=old.date(), extra=old.extra())
38342
bb7e3c6ef592 phabricator: preserve the phase when amending in the Differential fields
Matt Harbison <matt_harbison@yahoo.com>
parents: 38075
diff changeset
   594
38429
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38398
diff changeset
   595
                    newnode = new.commit()
38342
bb7e3c6ef592 phabricator: preserve the phase when amending in the Differential fields
Matt Harbison <matt_harbison@yahoo.com>
parents: 38075
diff changeset
   596
33808
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   597
                    mapping[old.node()] = [newnode]
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   598
                    # Update diff property
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   599
                    writediffproperties(unfi[newnode], diffmap[old.node()])
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   600
                # Remove local tags since it's no longer necessary
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   601
                tagname = b'D%d' % drevid
33808
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   602
                if tagname in repo.tags():
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   603
                    tags.tag(repo, tagname, nullid, message=None, user=None,
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   604
                             date=None, local=True)
38429
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38398
diff changeset
   605
            scmutil.cleanupnodes(repo, mapping, b'phabsend', fixphase=True)
33808
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   606
            if wnode in mapping:
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   607
                unfi.setparents(mapping[wnode][0])
fa3aa6c98bb7 phabricator: add --amend option to phabsend
Jun Wu <quark@fb.com>
parents: 33806
diff changeset
   608
33264
266321579c68 phabricator: add node and p1 to hg:meta property
Jun Wu <quark@fb.com>
parents: 33263
diff changeset
   609
# 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
   610
# consistent with "hg export" output.
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   611
_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: 38342
diff changeset
   612
                              (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
   613
33996
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33995
diff changeset
   614
def _confirmbeforesend(repo, revs, oldmap):
33995
edeb8f28c031 phabsend: print the actual URL with --confirm
Jun Wu <quark@fb.com>
parents: 33994
diff changeset
   615
    url, token = readurltoken(repo)
33716
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   616
    ui = repo.ui
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   617
    for rev in revs:
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   618
        ctx = repo[rev]
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   619
        desc = ctx.description().splitlines()[0]
33996
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33995
diff changeset
   620
        oldnode, olddiff, drevid = oldmap.get(ctx.node(), (None, None, None))
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33995
diff changeset
   621
        if drevid:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   622
            drevdesc = ui.label(b'D%s' % drevid, b'phabricator.drev')
33996
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33995
diff changeset
   623
        else:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   624
            drevdesc = ui.label(_(b'NEW'), b'phabricator.drev')
33996
088598153aa2 phabsend: show associated Differential Revisions with --confirm
Jun Wu <quark@fb.com>
parents: 33995
diff changeset
   625
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   626
        ui.write(_(b'%s - %s: %s\n')
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   627
                 % (drevdesc,
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   628
                    ui.label(bytes(ctx), b'phabricator.node'),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   629
                    ui.label(desc, b'phabricator.desc')))
33716
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   630
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   631
    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: 38342
diff changeset
   632
                         b'$$ &Yes $$ &No') % url):
33716
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   633
        return False
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   634
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   635
    return True
40cfe3197bc1 phabricator: add --confirm option to phabsend command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33601
diff changeset
   636
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   637
_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: 38342
diff changeset
   638
                     b'abandoned'}
33854
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33853
diff changeset
   639
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33853
diff changeset
   640
def _getstatusname(drev):
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33853
diff changeset
   641
    """get normalized status name from a Differential Revision"""
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   642
    return drev[r'statusName'].replace(b' ', b'').lower()
33854
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33853
diff changeset
   643
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   644
# 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: 33852
diff changeset
   645
# +, and -.
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   646
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   647
_elements = {
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   648
    # token-type: binding-strength, primary, prefix, infix, suffix
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   649
    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: 38342
diff changeset
   650
    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: 38342
diff changeset
   651
    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: 38342
diff changeset
   652
    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: 38342
diff changeset
   653
    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: 38342
diff changeset
   654
    b')':      (0,  None, None, None, None),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   655
    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: 38342
diff changeset
   656
    b'end':    (0, None, None, None, None),
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   657
}
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   658
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   659
def _tokenize(text):
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   660
    view = memoryview(text) # zero-copy slice
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   661
    special = b'():+-& '
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   662
    pos = 0
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   663
    length = len(text)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   664
    while pos < length:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   665
        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: 38342
diff changeset
   666
                                              view[pos:]))
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   667
        if symbol:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   668
            yield (b'symbol', symbol, pos)
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   669
            pos += len(symbol)
33854
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33853
diff changeset
   670
        else: # special char, ignore space
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   671
            if text[pos] != b' ':
33854
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33853
diff changeset
   672
                yield (text[pos], None, pos)
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   673
            pos += 1
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   674
    yield (b'end', None, pos)
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   675
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   676
def _parse(text):
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   677
    tree, pos = parser.parser(_elements).parse(_tokenize(text))
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   678
    if pos != len(text):
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   679
        raise error.ParseError(b'invalid token', pos)
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   680
    return tree
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   681
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   682
def _parsedrev(symbol):
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   683
    """str -> int or None, ex. 'D45' -> 45; '12' -> 12; 'x' -> None"""
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   684
    if symbol.startswith(b'D') and symbol[1:].isdigit():
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   685
        return int(symbol[1:])
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   686
    if symbol.isdigit():
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   687
        return int(symbol)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   688
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   689
def _prefetchdrevs(tree):
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   690
    """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: 33852
diff changeset
   691
    drevs = set()
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   692
    ancestordrevs = set()
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   693
    op = tree[0]
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   694
    if op == b'symbol':
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   695
        r = _parsedrev(tree[1])
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   696
        if r:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   697
            drevs.add(r)
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   698
    elif op == b'ancestors':
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   699
        r, a = _prefetchdrevs(tree[1])
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   700
        drevs.update(r)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   701
        ancestordrevs.update(r)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   702
        ancestordrevs.update(a)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   703
    else:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   704
        for t in tree[1:]:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   705
            r, a = _prefetchdrevs(t)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   706
            drevs.update(r)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   707
            ancestordrevs.update(a)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   708
    return drevs, ancestordrevs
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   709
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   710
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
   711
    """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
   712
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   713
    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: 33852
diff changeset
   714
    for details.
33267
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   715
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   716
    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
   717
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   718
        {
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   719
            "id": "2",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   720
            "phid": "PHID-DREV-672qvysjcczopag46qty",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   721
            "title": "example",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   722
            "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
   723
            "dateCreated": "1499181406",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   724
            "dateModified": "1499182103",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   725
            "authorPHID": "PHID-USER-tv3ohwc4v4jeu34otlye",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   726
            "status": "0",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   727
            "statusName": "Needs Review",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   728
            "properties": [],
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   729
            "branch": null,
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   730
            "summary": "",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   731
            "testPlan": "",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   732
            "lineCount": "2",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   733
            "activeDiffPHID": "PHID-DIFF-xoqnjkobbm6k4dk6hi72",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   734
            "diffs": [
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   735
              "3",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   736
              "4",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   737
            ],
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   738
            "commits": [],
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   739
            "reviewers": [],
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   740
            "ccs": [],
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   741
            "hashes": [],
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   742
            "auxiliary": {
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   743
              "phabricator:projects": [],
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   744
              "phabricator:depends-on": [
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   745
                "PHID-DREV-gbapp366kutjebt7agcd"
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   746
              ]
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   747
            },
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   748
            "repositoryPHID": "PHID-REPO-hub2hx62ieuqeheznasv",
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   749
            "sourcePath": null
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
    """
33269
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   752
    def fetch(params):
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   753
        """params -> single drev or None"""
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   754
        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
   755
        if key in prefetched:
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   756
            return prefetched[key]
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   757
        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
   758
        # Fill prefetched with the result
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   759
        for drev in drevs:
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   760
            prefetched[drev[r'phid']] = drev
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   761
            prefetched[int(drev[r'id'])] = drev
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   762
        if key not in prefetched:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   763
            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: 38342
diff changeset
   764
                              % params)
33269
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   765
        return prefetched[key]
ead6749354e1 phabricator: try to fetch differential revisions in batch
Jun Wu <quark@fb.com>
parents: 33268
diff changeset
   766
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   767
    def getstack(topdrevids):
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   768
        """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: 33852
diff changeset
   769
        visited = set()
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   770
        result = []
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   771
        queue = [{r'ids': [i]} for i in topdrevids]
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   772
        while queue:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   773
            params = queue.pop()
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   774
            drev = fetch(params)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   775
            if drev[r'id'] in visited:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   776
                continue
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   777
            visited.add(drev[r'id'])
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   778
            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
   779
            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
   780
            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
   781
            for phid in depends:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   782
                queue.append({b'phids': [phid]})
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   783
        result.reverse()
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   784
        return smartset.baseset(result)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   785
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   786
    # Initialize prefetch cache
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   787
    prefetched = {} # {id or phid: drev}
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   788
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   789
    tree = _parse(spec)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   790
    drevs, ancestordrevs = _prefetchdrevs(tree)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   791
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   792
    # developer config: phabricator.batchsize
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   793
    batchsize = repo.ui.configint(b'phabricator', b'batchsize')
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   794
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   795
    # Prefetch Differential Revisions in batch
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   796
    tofetch = set(drevs)
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   797
    for r in ancestordrevs:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   798
        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: 33852
diff changeset
   799
    if drevs:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   800
        fetch({r'ids': list(tofetch)})
33854
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33853
diff changeset
   801
    validids = sorted(set(getstack(list(ancestordrevs))) | set(drevs))
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   802
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   803
    # Walk through the tree, return smartsets
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   804
    def walk(tree):
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   805
        op = tree[0]
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   806
        if op == b'symbol':
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   807
            drev = _parsedrev(tree[1])
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   808
            if drev:
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   809
                return smartset.baseset([drev])
33854
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33853
diff changeset
   810
            elif tree[1] in _knownstatusnames:
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33853
diff changeset
   811
                drevs = [r for r in validids
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33853
diff changeset
   812
                         if _getstatusname(prefetched[r]) == tree[1]]
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33853
diff changeset
   813
                return smartset.baseset(drevs)
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   814
            else:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   815
                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: 38342
diff changeset
   816
        elif op in {b'and_', b'add', b'sub'}:
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   817
            assert len(tree) == 3
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   818
            return getattr(operator, op)(walk(tree[1]), walk(tree[2]))
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   819
        elif op == b'group':
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   820
            return walk(tree[1])
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   821
        elif op == b'ancestors':
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   822
            return getstack(walk(tree[1]))
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   823
        else:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   824
            raise error.ProgrammingError(b'illegal tree: %r' % tree)
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   825
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   826
    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
   827
33268
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   828
def getdescfromdrev(drev):
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   829
    """get description (commit message) from "Differential Revision"
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   830
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   831
    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
   832
    about limited fields: title, summary, test plan, and URL.
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   833
    """
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   834
    title = drev[r'title']
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   835
    summary = drev[r'summary'].rstrip()
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   836
    testplan = drev[r'testPlan'].rstrip()
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   837
    if testplan:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   838
        testplan = b'Test Plan:\n%s' % testplan
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   839
    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: 38342
diff changeset
   840
    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
   841
33441
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   842
def getdiffmeta(diff):
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   843
    """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
   844
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   845
    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
   846
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   847
        "properties": {
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   848
          "hg:meta": {
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   849
            "date": "1499571514 25200",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   850
            "node": "98c08acae292b2faf60a279b4189beb6cff1414d",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   851
            "user": "Foo Bar <foo@example.com>",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   852
            "parent": "6d0abad76b30e4724a37ab8721d630394070fe16"
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   853
          }
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   854
        }
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   855
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   856
    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
   857
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   858
        "properties": {
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   859
          "local:commits": {
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   860
            "98c08acae292b2faf60a279b4189beb6cff1414d": {
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   861
              "author": "Foo Bar",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   862
              "time": 1499546314,
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   863
              "branch": "default",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   864
              "tag": "",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   865
              "commit": "98c08acae292b2faf60a279b4189beb6cff1414d",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   866
              "rev": "98c08acae292b2faf60a279b4189beb6cff1414d",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   867
              "local": "1000",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   868
              "parents": ["6d0abad76b30e4724a37ab8721d630394070fe16"],
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   869
              "summary": "...",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   870
              "message": "...",
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   871
              "authorEmail": "foo@example.com"
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   872
            }
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   873
          }
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   874
        }
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   875
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   876
    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
   877
    information.
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
    props = diff.get(r'properties') or {}
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   880
    meta = props.get(r'hg:meta')
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   881
    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
   882
        commit = sorted(props[r'local:commits'].values())[0]
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   883
        meta = {
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   884
            r'date': r'%d 0' % commit[r'time'],
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   885
            r'node': commit[r'rev'],
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   886
            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
   887
        }
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   888
        if len(commit.get(r'parents', ())) >= 1:
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   889
            meta[r'parent'] = commit[r'parents'][0]
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   890
    return meta or {}
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   891
33852
75fdaf851e83 phabricator: change "readpatch" to be more flexible
Jun Wu <quark@fb.com>
parents: 33808
diff changeset
   892
def readpatch(repo, drevs, write):
33202
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33201
diff changeset
   893
    """generate plain-text patch readable by 'hg import'
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33201
diff changeset
   894
33852
75fdaf851e83 phabricator: change "readpatch" to be more flexible
Jun Wu <quark@fb.com>
parents: 33808
diff changeset
   895
    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: 33808
diff changeset
   896
    "differential.query".
33202
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33201
diff changeset
   897
    """
33267
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   898
    # 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
   899
    diffids = sorted(set(max(int(v) for v in drev[r'diffs']) for drev in drevs))
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   900
    diffs = callconduit(repo, b'differential.querydiffs', {b'ids': diffids})
33202
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33201
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
    # 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
   903
    for drev in drevs:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   904
        repo.ui.note(_(b'reading D%s\n') % drev[r'id'])
33202
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33201
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
        diffid = max(int(v) for v in drev[r'diffs'])
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   907
        body = callconduit(repo, b'differential.getrawdiff',
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   908
                           {b'diffID': diffid})
33268
85391b95961d phabricator: avoid calling differential.getcommitmessage
Jun Wu <quark@fb.com>
parents: 33267
diff changeset
   909
        desc = getdescfromdrev(drev)
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   910
        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
   911
dba9f88659a3 phabricator: rework phabread to reduce memory usage and round-trips
Jun Wu <quark@fb.com>
parents: 33266
diff changeset
   912
        # 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
   913
        # 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
   914
        # 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
   915
        meta = getdiffmeta(diffs[str(diffid)])
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   916
        for k in _metanamemap.keys():
de7c6ec27d99 phabricator: respect metadata sent by arc
Jun Wu <quark@fb.com>
parents: 33271
diff changeset
   917
            if k in meta:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   918
                header += b'# %s %s\n' % (_metanamemap[k], meta[k])
33202
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33201
diff changeset
   919
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   920
        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
   921
        write(encoding.unitolocal(content))
33202
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33201
diff changeset
   922
39666
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38983
diff changeset
   923
@vcrcommand(b'phabread',
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   924
         [(b'', b'stack', False, _(b'read dependencies'))],
41076
536beb130f3c phabricator: assign commands to help categories
Matt Harbison <matt_harbison@yahoo.com>
parents: 40435
diff changeset
   925
         _(b'DREVSPEC [OPTIONS]'),
536beb130f3c phabricator: assign commands to help categories
Matt Harbison <matt_harbison@yahoo.com>
parents: 40435
diff changeset
   926
         helpcategory=command.CATEGORY_IMPORT_EXPORT)
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   927
def phabread(ui, repo, spec, **opts):
33202
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33201
diff changeset
   928
    """print patches from Phabricator suitable for importing
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33201
diff changeset
   929
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   930
    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: 33852
diff changeset
   931
    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: 33852
diff changeset
   932
    ``&``, ``(``, ``)`` for complex queries. Prefix ``:`` could be used to
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   933
    select a stack.
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   934
33854
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33853
diff changeset
   935
    ``abandoned``, ``accepted``, ``closed``, ``needsreview``, ``needsrevision``
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33853
diff changeset
   936
    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: 33853
diff changeset
   937
    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: 33853
diff changeset
   938
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   939
    For example, ``:D6+8-(2+D4)`` selects a stack up to D6, plus D8 and exclude
33854
fb59192b4981 phabricator: add status to revision query language
Jun Wu <quark@fb.com>
parents: 33853
diff changeset
   940
    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: 33853
diff changeset
   941
    stack up to D9.
33202
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33201
diff changeset
   942
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33201
diff changeset
   943
    If --stack is given, follow dependencies information and read all patches.
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   944
    It is equivalent to the ``:`` operator.
33202
04cf9927f350 phabricator: add phabread command to read patches
Jun Wu <quark@fb.com>
parents: 33201
diff changeset
   945
    """
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   946
    if opts.get(b'stack'):
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   947
        spec = b':(%s)' % spec
33853
539541779010 phabricator: add a small language to query Differential Revisions
Jun Wu <quark@fb.com>
parents: 33852
diff changeset
   948
    drevs = querydrev(repo, spec)
33852
75fdaf851e83 phabricator: change "readpatch" to be more flexible
Jun Wu <quark@fb.com>
parents: 33808
diff changeset
   949
    readpatch(repo, drevs, ui.write)
33855
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33854
diff changeset
   950
39666
d8f07b16abfc phabricator: add support for using the vcr library to mock interactions
Augie Fackler <raf@durin42.com>
parents: 38983
diff changeset
   951
@vcrcommand(b'phabupdate',
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   952
         [(b'', b'accept', False, _(b'accept revisions')),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   953
          (b'', b'reject', False, _(b'reject revisions')),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   954
          (b'', b'abandon', False, _(b'abandon revisions')),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   955
          (b'', b'reclaim', False, _(b'reclaim revisions')),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   956
          (b'm', b'comment', b'', _(b'comment on the last revision')),
41076
536beb130f3c phabricator: assign commands to help categories
Matt Harbison <matt_harbison@yahoo.com>
parents: 40435
diff changeset
   957
          ], _(b'DREVSPEC [OPTIONS]'),
536beb130f3c phabricator: assign commands to help categories
Matt Harbison <matt_harbison@yahoo.com>
parents: 40435
diff changeset
   958
          helpcategory=command.CATEGORY_IMPORT_EXPORT)
33855
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33854
diff changeset
   959
def phabupdate(ui, repo, spec, **opts):
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33854
diff changeset
   960
    """update Differential Revision in batch
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33854
diff changeset
   961
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33854
diff changeset
   962
    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: 33854
diff changeset
   963
    """
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   964
    flags = [n for n in b'accept reject abandon reclaim'.split() if opts.get(n)]
33855
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33854
diff changeset
   965
    if len(flags) > 1:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   966
        raise error.Abort(_(b'%s cannot be used together') % b', '.join(flags))
33855
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33854
diff changeset
   967
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33854
diff changeset
   968
    actions = []
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33854
diff changeset
   969
    for f in flags:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   970
        actions.append({b'type': f, b'value': b'true'})
33855
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33854
diff changeset
   971
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33854
diff changeset
   972
    drevs = querydrev(repo, spec)
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33854
diff changeset
   973
    for i, drev in enumerate(drevs):
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   974
        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: 38342
diff changeset
   975
            actions.append({b'type': b'comment', b'value': opts[b'comment']})
33855
6e666cd59879 phabricator: add phabupdate command to update status in batch
Jun Wu <quark@fb.com>
parents: 33854
diff changeset
   976
        if actions:
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   977
            params = {b'objectIdentifier': drev[r'phid'],
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   978
                      b'transactions': actions}
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   979
            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
   980
f18ba40d792f phabricator: add a template item for linking to a differential review
Tom Prince <mozilla@hocat.ca>
parents: 35626
diff changeset
   981
templatekeyword = registrar.templatekeyword()
f18ba40d792f phabricator: add a template item for linking to a differential review
Tom Prince <mozilla@hocat.ca>
parents: 35626
diff changeset
   982
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   983
@templatekeyword(b'phabreview', requires={b'ctx'})
36543
7b74afec6772 templatekw: switch non-showlist template keywords to new API
Yuya Nishihara <yuya@tcha.org>
parents: 35722
diff changeset
   984
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
   985
    """: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
   986
    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
   987
    """
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   988
    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
   989
    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
   990
    if m:
39670
4057e38bba76 phabricator: fix templating bug by using hybriddict
Augie Fackler <raf@durin42.com>
parents: 39668
diff changeset
   991
        return templateutil.hybriddict({
38398
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   992
            b'url': m.group(b'url'),
81a4be7099fa py3: byte-stringify literals in contrib/phabricator.py as example
Yuya Nishihara <yuya@tcha.org>
parents: 38342
diff changeset
   993
            b'id': b"D{}".format(m.group(b'id')),
39670
4057e38bba76 phabricator: fix templating bug by using hybriddict
Augie Fackler <raf@durin42.com>
parents: 39668
diff changeset
   994
        })