HEX
Server: Apache
System: Linux p102.lithium.hosting 4.18.0-553.141.1.el8_10.x86_64 #1 SMP Fri Jul 10 17:48:02 UTC 2026 x86_64
User: bvzmoamr (9955)
PHP: 8.1.34
Disabled: syslog
Upload Files
File: //proc/thread-self/root/lib64/python2.7/site-packages/hgext/phabricator.pyc
�
1�3\c@@sdZddlmZddlZddlZddlZddlZddlmZm	Z	ddl
mZddlm
Z
mZmZmZmZmZmZmZmZmZmZmZmZmZmZmZddlm Z m!Z!dZ"iZ#ej$e#�Z$iZ%ej&e%�Z&e&d	d
dd�e&d	d
dd�e&d	ddd�e&d	ddd�e&d	ddd�e&ddde(�idd6dd6dd6dd6dd6dd6Z)ddded�fgZ*d�Z+d �Z,d!�Z-d"�Z.e+d#ged$��d%��Z/d&�Z0ej1d'�Z2ej1d(ej3�Z4d)�Z5d*�Z6d+�Z7d,�Z8dddddd-�Z9d.�Z:e+dd/d0ged1�ed2�fdd3e;ed4�fdd5ged6�fddded7�fged8��d9��Z<ej=dxdydzd{g�Z>dB�Z?dCdDdEdFdGhZ@dH�ZAiddd|ddfdL6dMdd}ddfdO6dPddd~dfdR6dSddddfdU6dSddd�dfdW6d�dK6d�dX6d�dY6ZBdZ�ZCd[�ZDd\�ZEd]�ZFd^�ZGd_�ZHd`�ZIda�ZJe+dbddce(edd�fgede��df��ZKe+dgddhe(edi�fddje(edk�fddle(edm�fddne(edo�fdpdqdedr�fgede��ds��ZLejM�ZMeMdtdudvh�dw��ZNdS(�s�simple Phabricator integration (EXPERIMENTAL)

This extension provides a ``phabsend`` command which sends a stack of
changesets to Phabricator, and a ``phabread`` command which prints a stack of
revisions in a format suitable for :hg:`import`, and a ``phabupdate`` command
to update statuses in batch.

By default, Phabricator requires ``Test Plan`` which might prevent some
changeset from being sent. The requirement could be disabled by changing
``differential.require-test-plan-field`` config server side.

Config::

    [phabricator]
    # Phabricator URL
    url = https://phab.example.com/

    # Repo callsign. If a repo has a URL https://$HOST/diffusion/FOO, then its
    # callsign is "FOO".
    callsign = FOO

    # curl command to use. If not set (default), use builtin HTTP library to
    # communicate. If set, use the specified curl command. This could be useful
    # if you need to specify advanced options that is not easily supported by
    # the internal library.
    curlcmd = curl --connect-timeout 2 --retry 3 --silent

    [auth]
    example.schemes = https
    example.prefix = phab.example.com

    # API token. Get it from https://$HOST/conduit/login/
    example.phabtoken = cli-xxxxxxxxxxxxxxxxxxxxxxxxxxxx
i(tabsolute_importN(tbintnullid(t_(tcmdutiltcontexttencodingterrorthttpconnectiontmdifftobsutiltparsertpatcht	registrartscmutiltsmartsetttagsttemplateutilturltutil(tprocutilt
stringutilsships-with-hg-coretphabricatort	batchsizetdefaultitcallsigntcurlcmdtrepophidRtphabsendtconfirmtgreensphabricator.action.createdtmagentasphabricator.action.skippedsphabricator.action.updatedtsphabricator.desctboldsphabricator.drevsphabricator.nodestest-vcrs�Path to a vcr file. If nonexistent, will record a new vcr transcript, otherwise will mock all http requests using the specified vcr file. (ADVANCED)c@s#|t����fd�}|S(Nc@s=�fd�}�j|_�j|_t����|�S(Nc@s�|jdd�}|r�ddl}|j��yddl}ddlj}|jdddtd|j	ftd|j
fg�}|j|���||�SWdQXWdQXn�||�S(Nttest_vcrit
serializertjsontcustom_patchesRthttpsconnection(tpoptNonethgdemandimporttdeactivatedtvcrt	vcr.stubststubstVCRturlmodtVCRHTTPConnectiontVCRHTTPSConnectiontuse_cassette(targstkwargstcassetteR)tvcrmodR-R+(tfn(s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pytinners
	(t__name__t__doc__tcommand(R7R8(t	fullflagstnametspec(R7s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pytdecorate~s(t
_VCR_FLAGS(R=tflagsR>R?((R<R=R>s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyt
vcrcommand|s
c@s;tj����fd���d|�tjj��S(slike urlencode, but works with nested parameters.

    For example, if params is {'a': ['b', 'c'], 'd': {'e': 'f'}}, it will be
    flattened to {'a[0]': 'b', 'a[1]': 'c', 'd[e]': 'f'} and then passed to
    urlencode. Note: the encoding is consistent with PHP's http_build_query.
    c@s�t|t�r*idt6dt6|}nitt6d�t6jt|��}|dkri|�|<nJxG||�D]9\}}|r��d||f|�qv�||�qvWdS(NttruetfalsecS@s
|j�S(N(titems(tx((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyt<lambda>�R s%s[%s](
t
isinstancetbooltTruetFalset	enumeratetlisttdicttgetttypeR((tprefixtobjREtktv(t
flatparamstprocess(s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyRV�s&
R (Rtsortdictturlreqt	urlencode(tparams((RURVs7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyturlencodenested�s
cC@s�|jjdd�}|s7tjtd�d��ntj|j|tj|�j	�}d}|r�|\}}|jjd|�|jd�}n|s�tjtd�|f��n||fS(	s�return conduit url, token and make sure they exist

    Currently read from [auth] config section. In the future, it might
    make sense to read from .arcconfig and .arcrc as well.
    RRsconfig %s.%s is requireds#using auth.%s.* for authentication
t	phabtokens)Can't find conduit token associated to %s(RRN(
tuitconfigRtAbortRthttpconnectionmodtreadauthforuriRRtuserR(tdebugRO(trepoRtresttokentgrouptauth((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pytreadurltoken�s
$cC@s�t|�\}}tjdj|d|g��j�\}}|jjd||f�|j�}||d<t|�}|jj	dd�}|r�t
jd|t
j|�f�\}	}
|	j
|�|	j�|
j�}nBtj|j|�}tjj|d|�}
|j|
�j�}|jjd	|�tj|�}|jd
�r�td�|d
|df}tj|��n|d
S(sEcall Conduit API, params is a dict. return json.loads result, or Nonet/tapisConduit Call: %s %s
s	api.tokenRRs%s -d @- %stdatasConduit Response: %s
t
error_codesConduit Error (%s): %st
error_infotresult(RiRRtjointauthinfoR]RctcopyR[R^Rtpopen2t
shellquotetwritetclosetreadR/topenerRXtrequesttopenR$tloadsRORRR_(RdR=RZthostRfRRqRlRtsintsouttbodyt	urlopenerRytparsedtmsg((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pytcallconduit�s.-
	

	tdebugcallconduittMETHODc	C@s`tj|jj��}t|||�}tj|dtdddd	�}|jd|�dS(
s�call Conduit API

    Call parameters are read from stdin as a JSON blob. Result will be written
    to stdout as a JSON blob.
    t	sort_keystindentit
separatorst,s: s%s
N(R�s: (R$R{tfinRwR�tdumpsRJRu(R]RdR=RZRots((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyR��s!cC@s�|jjdd�}|r|S|jjdd�}|s>d
St|dii|gd6d6�}t|d�dkr{d
Stj|ddd	�}|jjdd|�|S(s.given callsign, return repository PHID or NoneRRRsdiffusion.repository.searcht	callsignstconstraintsRlitphidN(R]R^R(R�tlenRt
strtolocalt	setconfig(RdRRtquery((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pytgetrepophid�s	s\AD([1-9][0-9]*)\Zs>^Differential Revision:\s*(?P<url>(?:.*)D(?P<id>[1-9][0-9]*))$c
@s�t|�\}}|j�}|jj}i}i}x�|D]�}||}	ttj|j|g��}
xz|
D]r}||krrx]|j|�D]I}t	j
|�}
|
r�dt|
�t|
j
d��f||<q�q�q�WqrqrWtj|	j��}
|
r=dt|
�t|
j
d��f||<q=q=W|r�g|j�D]\}}}|^qE}t|di|d6�}d��xF|j�D]5\}\}}}g|j�D]"}t|d�|kr�|^q�}t�fd�|D��}|rbt||@�rbd	|}tj||td
dddddd
t�|jjtd�|�q�nd}}|r�t|dd��}�|�}|r�||kr�d}q�n|||f||<q�Wn|S(s�find previous nodes that has been sent to Phabricator

    return {node: (oldnode, Differential diff, Differential Revision ID)}
    for node in nodelist with known previous sent versions, or associated
    Differential Revision IDs. ``oldnode`` and ``Differential diff`` could
    be ``None``.

    Examines commit messages like "Differential Revision:" to get the
    association information.

    If such commit message line is not found, examines all precursors and their
    tags. Tags with format like "D1234" are considered a match and the node
    with that tag, and the number after "D" (ex. 1234) will be returned.

    The ``old node``, if not None, is guaranteed to be the last diff of
    corresponding Differential Revision, and exist in the repo.
    iitidsdifferential.querydiffstrevisionIDscS@s+ttjt|�jdd���p*dS(NtnodeR (RRt
unitolocaltgetdiffmetaROR((td((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyRG2s	t
revisionIDc3@s|]}�|�VqdS(N((t.0R�(tgetnode(s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pys	<genexpr>9ssD%dtmessageRbtdatetlocals=D%s: local tag removed - does not match Differential history
tkeycS@st|d�S(NR�(tint(R�((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyRGIR N(Rit
unfilteredt	changelogtnodemapRMR
tallpredecessorstobsstoretnodetagst_differentialrevisiontagretmatchtsetR�Rgt_differentialrevisiondescretsearchtdescriptiontvaluesR�RERIRttagRR(RJR]twarnRtmax(RdtnodelistRRftunfiR�Rot	toconfirmR�tctxt	precnodestnR�tmtforcetprecstdrevtdrevstalldiffstnewnodetprecsetR�tdiffst	phprecsetttagnametoldnodetlastdiff((R�s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pytgetoldnodedrevmapsT


(/(		""


cC@sjtj�}xQtj|j�|j�j�|j�dd|�D]\}}|j|�qCW|j	�S(s:plain-text diff without header (user, commit message, etc)toptsN(
RtstringioRtdiffuiRdtp1R�R(Rutgetvalue(R�tdiffoptstoutputtchunkt_label((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pytgetdiffRs
*cC@s�|j�}t|�}it|tjdtdd��d6}|rS||d<nt|d|�}|s�tjt	d�|��n|S(screate a Differential DifftgitRi�tdifftrepositoryPHIDsdifferential.createrawdiffscannot create diff for %s(
RdR�R�R	R�RJR�RR_R(R�RdRRZR�((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyt
creatediffZs(
cC@si|dd6dd6tji|j�d6d|j�d6|j�d6|j�j�d	6�d
6}t|j�d|�i|dd6dd6tjiitj	|j��d
6tj
|j��d6|j�dd6|j�6�d
6}t|j�d|�dS(s=write metadata to diff so patches could be applied losslesslyR�tdiff_idshg:metaR=Rbs%d %dR�R�tparentRlsdifferential.setdiffpropertys
local:commitstauthortauthorEmailittimeN(R$R�RbR�thexR�R�RdRtpersontemail(R�R�RZ((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pytwritediffpropertiesgs$	

	%cC@s�|j�}|r[tjdtdd�}|j�|}t||�t||�k}	nt}	g}
|	r�t|�}|
jidd6|dd6�n|s�t�|}t	||�|r|dkrd|}|
id	d6|d6id	d6d
d6g7}
n|r|
|7}
n|j�}
t|di|
d6�}xH|d
j
�D]6\}}|dkrN|
ji|d6|d6�qNqNWi|
d6}|dk	r�||d<nt|d|�}|s�tjtd�|��n||fS(s�create or update a Differential Revision

    If revid is None, create a new Differential Revision, otherwise update
    revid. If parentrevid is not None, set it as a dependency.

    If oldnode is not None, check if the patch content (without commit message
    and metadata) has changed before creating another diff.

    If actions is not None, they will be appended to the transaction.
    R�Ri�tupdateRPR�tvaluesDepends on D%stsummaryt sdifferential.parsecommitmessagetcorpustfieldsttitlettestPlanttransactionstobjectIdentifiersdifferential.revision.editscannot create revision for %sN(R�R�R�(RdR	R�RJR�R�R�tappendtAssertionErrorR�R(R�R�RERR_R(R�trevidtparentrevidR�tolddifftactionsRdR�toldctxtneednewdiffR�R�R�tdesctinfoRSRTRZtrevision((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pytcreatedifferentialrevision�s@!"


	"

cC@s�ii|d6d6}t|d|�}|d}td�|D��}t|�|}|r�tjtd�djt|����ng|D]}|d^q�S(	sconvert user names to PHIDst	usernamesR�suser.searchRlcs@s|]}|ddVqdS(R�tusernameN((R�tentry((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pys	<genexpr>�ssunknown username: %sR�R�(R�R�RR_RRptsorted(RdtnamesR�RoRltresolvedt
unresolvedR�((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyt	userphids�s
trtrevsrevisions to sendtREVtamendsupdate commit messagestreviewersspecify reviewerss#ask for confirmation before sendings
REV [OPTIONS]c*O@s�t|�|jdg�}tj||�}|sLtjtd���n|jd�rktj|�nt	|g|D]}||j
�^qx�}|jdd�}|t|jd��O}|r�t
|||�}|s�tjtd���q�ng}|jdg�}	|	rFt||	�}
|jidd	6|
d
6�ng}i}d%}
x|D]}|jd|�||}|j|j
�d&�\}}}||j
�ks�|jd�r�t|||
|||�\}}|||j
�<t|dd
�}|rd}nd}tj|j��}|sSt|jd
��|kr�d|}tj|||j
�dd%dd%dd%dt�q�n|}d}|jitd�d6td�d6td�d6|d|�}|jd|d�}|jt|�d�}|j|j�jd�dd�}|jtd�||||f�|j|�|}
q_W|jd�r�|j�}t |di|d6�}|j!��1|j"��|j#d��|d j
�}i} x�t$|�D]�\}!}||}"||!}#g|D]"}$t|$d
�|#kr|$^qd}%t%|%�}&t&j'|&�}&|"j�|&krD| j|"j(�j
�|"j(�f�d| j|"j)�j
�|"j)�f�dg}'t*j+||"d!|'d"|&d|"j,�d|"j-�d#|"j.��}(|(j/�})|)g| |"j
�<t0||)||"j
��nd|#}||j�kr�tj||t1dd%dd%dd%dt�q�q�Wtj2|| dd$t�|| kr�|j3| |d�nWd%QXWd%QXWd%QXnd%S('srupload changesets to Phabricator

    If there are multiple revisions specified, they will be send as a stack
    with a linear dependencies relationship using the order specified by the
    revset.

    For the first time uploading changesets, local tags will be created to
    maintain the association. After the first time, phabsend will check
    obsstore and tags information so it can figure out whether to update an
    existing Differential Revision, or create a new one.

    If --amend is set, update commit messages so they have the
    ``Differential Revision`` URL, remove related tags. This is similar to what
    arcanist will do, and is more desired in author-push workflows. Otherwise,
    use local tags to record the ``Differential Revision`` association.

    The --confirm option lets you confirm changesets before sending them. You
    can also add following to your configuration file to make it default
    behaviour::

        [phabsend]
        confirm = true

    phabsend will check obsstore and the above association to decide whether to
    update an existing Differential Revision, or create a new one.
    R�s(phabsend requires at least one changesetR�RRsphabsend cancelledRs
reviewers.addRPR�ssending rev %d
tobjectR�tupdatedtcreatedsD%dR�RbR�R�tskippedsphabricator.action.%ssD%ssphabricator.drevsphabricator.nodes
isphabricator.descs%s - %s - %s: %s
sdifferential.querytidst.tparentsttexttextratfixphaseN(NNN(4RMRORtrevrangeRR_RRtcheckunfinishedR�R�t
configboolRIt_confirmbeforesendR�R�R(RcR�R�R�R�R�RgRR�RJtlabeltbytestsplitRuR�R�twlocktlockttransactionRLtgetdescfromdrevRR�R�tp2RtmetadataonlyctxRbR�R	tcommitR�Rtcleanupnodest
setparents(*R]RdtrevsR�R�toldmapRt	confirmedR�t	reviewerstphidstdrevidstdiffmapt	lastrevidR�R�R�R�R�R�R�tnewrevidtactionR�R�t
actiondesctdrevdesctnodedescR�R�R�twnodetmappingtitoldtdrevidR�R�tnewdescRtnewR�((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyR�s�!,

!!	"
$

%





3(.'
RbtUserR�tDateR�sNode IDR�sParent c
C@st|�\}}|j}x�|D]�}||}|j�j�d}|j|j�d	�\}	}
}|r�|jd|d�}n|jtd�d�}|j	td�||jt
|�d�|j|d�f�q"W|jtd�|�r�tSt
S(
NisD%ssphabricator.drevtNEWs%s - %s: %s
sphabricator.nodesphabricator.descs0Send the above changes to %s (yn)?$$ &Yes $$ &No(NNN(RiR]R�t
splitlinesROR�R(RRRuRtpromptchoiceRKRJ(
RdRRRRfR]R�R�R�R�R�R,R&((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyRcs"	

!
tacceptedtneedsreviewt
needsrevisiontclosedt	abandonedcC@s|djdd�j�S(s7get normalized status name from a Differential Revisiont
statusNameR�R (treplacetlower(R�((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyt_getstatusname}sRgit)t(it	ancestorst:itand_t&itaddt+tsubt-tsymboltendc#@s�t|�}d�d}t|�}x�||kr�djtj�fd�||��}|r�d||fV|t|�7}q'||dkr�||d|fVn|d7}q'Wdd|fVdS(	Ns():+-& iR c@s
|�kS(N((tch(tspecial(s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyRG�R RGR�iRH(t
memoryviewR�Rpt	itertoolst	takewhileR((RtviewtpostlengthRG((RJs7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyt	_tokenize�scC@sOtjt�jt|��\}}|t|�krKtjd|��n|S(Ns
invalid token(Rt	_elementstparseRQR�Rt
ParseError(RttreeRO((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyt_parse�s$cC@sG|jd�r-|dj�r-t|d�S|j�rCt|�SdS(s<str -> int or None, ex. 'D45' -> 45; '12' -> 12; 'x' -> NonetDiN(t
startswithtisdigitR�(RG((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyt
_parsedrev�scC@s�t�}t�}|d}|dkrQt|d�}|r�|j|�q�n�|dkr�t|d�\}}|j|�|j|�|j|�nAx>|dD]2}t|�\}}|j|�|j|�q�W||fS(s9return ({single-drev-id}, {ancestor-drev-id}) to prefetchiRGiR?(R�RZRCt_prefetchdrevsR�(RUR�t
ancestordrevstopR�tatt((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyR[�s"		



c@s��fd���fd��i�t|�}t|�\}}�jjdd�}t|�}x5|D]-}|jttd||�|d��qmW|r��it|�d6�nt	t�t|���t|�B������fd��g�|�D]}�|^qS(s�return a list of "Differential Revision" dicts

    spec is a string using a simple query language, see docstring in phabread
    for details.

    A "Differential Revision dict" looks like:

        {
            "id": "2",
            "phid": "PHID-DREV-672qvysjcczopag46qty",
            "title": "example",
            "uri": "https://phab.example.com/D2",
            "dateCreated": "1499181406",
            "dateModified": "1499182103",
            "authorPHID": "PHID-USER-tv3ohwc4v4jeu34otlye",
            "status": "0",
            "statusName": "Needs Review",
            "properties": [],
            "branch": null,
            "summary": "",
            "testPlan": "",
            "lineCount": "2",
            "activeDiffPHID": "PHID-DIFF-xoqnjkobbm6k4dk6hi72",
            "diffs": [
              "3",
              "4",
            ],
            "commits": [],
            "reviewers": [],
            "ccs": [],
            "hashes": [],
            "auxiliary": {
              "phabricator:projects": [],
              "phabricator:depends-on": [
                "PHID-DREV-gbapp366kutjebt7agcd"
              ]
            },
            "repositoryPHID": "PHID-REPO-hub2hx62ieuqeheznasv",
            "sourcePath": null
        }
    c@s�|jd�p$|jd�p$dgd}|�kr?�|St�d|�}x0|D](}|�|d<|�t|d�<qXW|�kr�tjtd�|��n�|S(	sparams -> single drev or NoneRRisdifferential.queryR�R�s#cannot get Differential Revision %rN(ROR(R�R�RR_R(RZR�R�R�(t
prefetchedRd(s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pytfetch�s+

c
@s�t�}g}g|D]}i|gd6^q}x�|r�|j�}�|�}|d|kriq5n|j|d�|jt|d��|jdi�}|jdg�}x%|D]}	|ji|	gd6�q�Wq5W|j�tj|�S(s6given a top, get a stack from the bottom, [id] -> [id]RR�t	auxiliarysphabricator:depends-onR(	R�R'RCR�R�ROtreverseRtbaseset(
t
topdrevidstvisitedRoR*tqueueRZR�RbtdependsR�(Ra(s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pytgetstack�s 	#	

RRiRc@sT|d}|dkr�t|d�}|r<tj|g�S|dtkr�g�D]&}t�|�|dkrS|^qS}tj|�Stjtd�|d��n�|dddhkrt|�dks�t	�t
t|��|d��|d	��S|d
kr�|d�S|dkr=��|d��Stjd|��dS(
NiRGisunknown symbol: %sRARCREiiRgR?sillegal tree: %r(
RZRRdt_knownstatusnamesR<RR_RR�R�tgetattrtoperatortProgrammingError(RUR]R�R�R�(RiR`tvalididstwalk(s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyRo!s$

&
 *(
RVR[R]t	configintR�R�trangeR�RMR�(RdR>RUR�R\RttofetchR�((RaRiR`RdRnRos7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyt	querydrev�s*
+(cC@sm|d}|dj�}|dj�}|r=d|}nd|d}djtd||||g��S(	s�get description (commit message) from "Differential Revision"

    This is similar to differential.getcommitmessage API. But we only care
    about limited fields: title, summary, test plan, and URL.
    R�R�R�s
Test Plan:
%ssDifferential Revision: %sturis

N(trstripRptfilterR((R�R�R�ttestplanRt((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyR9s

cC@s�|jd�pi}|jd�}|r�|jd�r�t|dj��d}id|dd6|dd	6d
|d|dfd
6}t|jdd��dkr�|dd|d<q�n|p�iS(s�get commit metadata (date, node, user, p1) from a diff object

    The metadata could be "hg:meta", sent by phabsend, like:

        "properties": {
          "hg:meta": {
            "date": "1499571514 25200",
            "node": "98c08acae292b2faf60a279b4189beb6cff1414d",
            "user": "Foo Bar <foo@example.com>",
            "parent": "6d0abad76b30e4724a37ab8721d630394070fe16"
          }
        }

    Or converted from "local:commits", sent by "arc", like:

        "properties": {
          "local:commits": {
            "98c08acae292b2faf60a279b4189beb6cff1414d": {
              "author": "Foo Bar",
              "time": 1499546314,
              "branch": "default",
              "tag": "",
              "commit": "98c08acae292b2faf60a279b4189beb6cff1414d",
              "rev": "98c08acae292b2faf60a279b4189beb6cff1414d",
              "local": "1000",
              "parents": ["6d0abad76b30e4724a37ab8721d630394070fe16"],
              "summary": "...",
              "message": "...",
              "authorEmail": "foo@example.com"
            }
          }
        }

    Note: metadata extracted from "local:commits" will lose time zone
    information.
    t
propertiesshg:metas
local:commitsis%d 0R�R�R�R�s%s <%s>R�R�RbRiR�((ROR�R�R�(R�tpropstmetaR((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyR�Gs%c
C@s+ttd�|D���}t|di|d6�}x�|D]�}|jjtd�|d�td�|dD��}t|di|d	6�}t|�}d
}	t|t	|��}
x?t
j�D]1}||
kr�|	dt
||
|f7}	q�q�Wd|	||f}|tj
|��q<Wd
S(s�generate plain-text patch readable by 'hg import'

    write is usually ui.write. drevs is what "querydrev" returns, results of
    "differential.query".
    cs@s)|]}td�|dD��VqdS(cs@s|]}t|�VqdS(N(R�(R�RT((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pys	<genexpr>�sR�N(R�(R�R�((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pys	<genexpr>�ssdifferential.querydiffsRsreading D%s
R�cs@s|]}t|�VqdS(N(R�(R�RT((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pys	<genexpr>�sR�sdifferential.getrawdifftdiffIDs# HG changeset patch
s# %s %s
s%s%s
%sN(R�R�R�R]tnoteRR�RR�tstrt_metanamemaptkeysRR�(
RdR�RutdiffidsR�R�tdiffidRR�theaderRzRStcontent((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyt	readpatchys
	#tphabreadtstacksread dependenciessDREVSPEC [OPTIONS]cK@sB|jd�rd|}nt||�}t|||j�dS(sPprint patches from Phabricator suitable for importing

    DREVSPEC could be a Differential Revision identity, like ``D123``, or just
    the number ``123``. It could also have common operators like ``+``, ``-``,
    ``&``, ``(``, ``)`` for complex queries. Prefix ``:`` could be used to
    select a stack.

    ``abandoned``, ``accepted``, ``closed``, ``needsreview``, ``needsrevision``
    could be used to filter patches by status. For performance reason, they
    only represent a subset of non-status selections and cannot be used alone.

    For example, ``:D6+8-(2+D4)`` selects a stack up to D6, plus D8 and exclude
    D2 and D4. ``:D9 & needsreview`` selects "Needs Review" revisions in a
    stack up to D9.

    If --stack is given, follow dependencies information and read all patches.
    It is equivalent to the ``:`` operator.
    R�s:(%s)N(RORsR�Ru(R]RdR>R�R�((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyR��s
t
phabupdatetacceptsaccept revisionstrejectsreject revisionstabandonsabandon revisionstreclaimsreclaim revisionsR�tcommentscomment on the last revisioncK@s?gdj�D]}|j|�r
|^q
}t|�dkretjtd�dj|���ng}x)|D]!}|ji|d6dd6�qrWt||�}x�t	|�D]�\}	}
|	dt|�kr|jd�r|jidd6|dd6�n|r�i|
d	d
6|d6}t
|d|�q�q�Wd
S(srupdate Differential Revision in batch

    DREVSPEC selects revisions. See :hg:`help phabread` for its usage.
    saccept reject abandon reclaimis%s cannot be used togethers, RPRCR�R�R�R�R�sdifferential.revision.editN(RROR�RR_RRpR�RsRLR�(R]RdR>R�R�RAR�tfR�R*R�RZ((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyR��s.%
%"
t
phabreviewtrequiresR�cC@sg|j|d�}tj|j��}|rctji|jd�d6dj|jd��d6�SdS(se:phabreview: Object describing the review for this changeset.
    Has attributes `url` and `id`.
    R�RsD{}R�N(tresourceR�R�R�Rt
hybriddictRgtformat(RR)R�R�((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyttemplate_review�s	(RbR/(R�R0(R�sNode ID(R�sParent (RgiR=(R?i(RAi(RCi(REi(iNNNN(iRGNNN(iNNNN(OR:t
__future__RRLR$Rltretmercurial.nodeRRtmercurial.i18nRt	mercurialRRRRRR`R	R
RRR
RRRRRR/Rtmercurial.utilsRRt
testedwithtcmdtableR;tconfigtablet
configitemR(RKt
colortableR@RBR[RiR�R�R�tcompileR�tMR�R�R�R�R�R�R�RJRRWR~RRjR<RRRQRVRZR[RsRR�R�R�R�ttemplatekeywordR�(((s7/usr/lib64/python2.7/site-packages/hgext/phabricator.pyt<module>(s�j	
					!		O		
		>	�			
					v		2