a
    &0_֕                 
   @   sZ  d dl mZmZ d dlZd dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
Z
ddlmZ ddlmZmZ ddlmZ ddlmZmZmZmZmZmZmZmZmZmZmZmZmZ ddl m!Z!m"Z"m#Z#m$Z$ ej%Z%e&d	Z'e&d
Z(e&dZ)ej*Z*dd Z+g dZ,ej-dd Z.dd Z/G dd de0Z1dd Z2G dd de0Z3G dd de0Z4G dd de4Z5G dd de5Z6G dd  d e0Z7G d!d" d"e4Z8e&d#Z9e&d$Z:g d%Z;G d&d' d'e0Z<G d(d) d)e0Z=G d*d+ d+e0Z>d,d- Z?d}d.d/Z@G d0d1 d1e0ZAG d2d3 d3e0ZBd4d5 ZCd6d7 ZDd~d8d9ZEd:d; ZFd<d= ZGd>d? ZHd@dA ZIdBdC ZJdDdE ZKddHdIZLdJdK ZMddLdMZNdNdO ZOddPdQZPddRdSZQddTdUZRddVdWZSddXdYZTG dZd[ d[eUZVejWZXejWZWejYZYdd\d]ZZdd^d_Z[d`da Z\dbdc Z]ddde Z^dfdg Z_dhdi Z`djdk ZadldmdndoZbdpdq Zcdrds Zddtdu Zedvdw ZfddydzZgd{d| ZhdS )    )absolute_importprint_functionN   _)hexshort)open)copies
diffhelperdiffutilencodingerrormailmdiffpathutilpycompatscmutilsimilarutilvfs)dateutilhashutilprocutil
stringutils   diff --git a/(.*) b/(.*)s   (\t+|[^\t]+)s9   (\t+| +|[a-zA-Z0-9_\x80-\xff]+|[^ \ta-zA-Z0-9_\x80-\xff])c                    s  dd dd   fdd} fdd} fd	d
} fdd} fdd}G dd dt }d}g }dg}	t| ds|| } | D ]}
||
 |
dr|| |  S |
dr|| |  S |
|rd}|
ddd  |	v r|| |  S q|
dr|r|| |  S q||S )z6return an iterator of individual patches from a streamc                 S   sD   |r|  drdS |  dr dS | dd}t|dkoBd|d	 vS )
N)       	T)r      -   +F   : r      r   r   )
startswithsplitlen)lineinheaderl r'   1/usr/lib/python3/dist-packages/mercurial/patch.pyisheader@   s    
zsplit.<locals>.isheaderc                 S   s   t d| S N    )stringiojoin)linesr'   r'   r(   chunkJ   s    zsplit.<locals>.chunkc                 3   sV   d}| D ]:}|  sd}|s8|dr8 |V  g }d}|| q|rR |V  d S )NTF   # HG changeset patch)stripr!   appendstreamcurr%   r$   r/   r'   r(   hgsplitM   s    
zsplit.<locals>.hgsplitc                 3   sj   | D ]<}| dr6t |dd  D ]
}|V  q&g }|| q|rft |dd  D ]
}|V  qZd S )N   From r   )r!   r"   r2   )r4   r5   r$   cr6   r'   r(   	mboxsplit]   s    
zsplit.<locals>.mboxsplitc           	      3   st   dd }| D ]}| | q |}t|}| sB||V  n.d}| D ] }| }||vrdqN||V  qNd S )Nc                 S   s,   t  }tj|dd}||  |d |S )NF)Zmangle_from_r   )r,   r   	GeneratorZflattenseek)mfpgr'   r'   r(   msgfpk   s
    

z'split.<locals>.mimesplit.<locals>.msgfp
   text/plains   text/x-diffs   text/x-patch)r2   r   parseZis_multipartwalkget_content_type)	r4   r5   r@   r$   r9   r=   ok_typespartZctr6   r'   r(   	mimesplitj   s    
zsplit.<locals>.mimesplitc                 3   s\   d}| D ]@}|s,||r, |V  g }d}|r>||s>d}| | q|rX |V  d S NFTr2   r3   r/   r)   r'   r(   headersplit   s    
zsplit.<locals>.headersplitc                 3   s    | V  d S Nr'   )r5   r6   r'   r(   	remainder   s    zsplit.<locals>.remainderc                   @   s(   e Zd Zdd Zdd Zdd ZeZdS )zsplit.<locals>.fiterc                 S   s
   || _ d S rM   )r>   selfr>   r'   r'   r(   __init__   s    zsplit.<locals>.fiter.__init__c                 S   s   | S rM   r'   rP   r'   r'   r(   __iter__   s    zsplit.<locals>.fiter.__iter__c                 S   s   | j  }|st|S rM   )r>   readlineStopIterationrP   r&   r'   r'   r(   next   s    
zsplit.<locals>.fiter.nextN)__name__
__module____qualname__rQ   rS   rW   __next__r'   r'   r'   r(   fiter   s   r\   Fs   content-types   nextr0   r8   T   :r   r      --- )objectr   safehasattrr2   r!   r"   lower)r4   r7   r:   rH   rL   rN   r\   r%   r5   Zmimeheadersr$   r'   rK   r(   r"   =   s4    




r"   ))s   Dates   date)s   Branchs   branch)s   Node ID   nodeidc              	   c   s\   t jdd\}}t|d}z&t| |||V  W |  t| n|  t| 0 dS )a  extract patch from data read from fileobj.

    patch can be a normal patch or contained in an email message.

    return a dictionary. Standard keys are:
      - filename,
      - message,
      - user,
      - date,
      - branch,
      - node,
      - p1,
      - p2.
    Any item can be missing from the dictionary. If filename is missing,
    fileobj did not contain a patch. Caller must unlink filename when done.	   hg-patch-prefixwbN)r   mkstemposfdopen_extractcloseunlink)uifileobjfdtmpnametmpfpr'   r'   r(   extract   s    rr   c              	   C   s  t dt jt jB }i }t|}|d o6t|d }|d oLt|d |d< |sz|d szddd | D d }g }|d }	|	rt|	 |d	< }	| 	d
|	  |r|
dr|d}
|
dkr||
d d   }t dd|}| 	d|  |d r| 	d|d   d}d}d}| D ]}t| }| 	d|  ||vrZq*|jdd}||}|rd}d}d}| 	d|d  |d7 }t }|d |d  D ],}|
dr|s| 	d d}d}|d |  d }n|r|
dr2|dd  |d< | 	d|d   n|
drV||dd    n`|
d rtD ]H\}}d!| }|
|rf|t|d  ||< | 	d"||| f  qfnd}n|d#krd}|s|s|| |d q| }|r<|| |ds<|d n"|s*|r*|d$kr*|d| 7 }q*|r^|
|s^d%||f }||d&< |  |r| d|d'< |r| d|d(< |r||d)< |S )*Ns}   ^(?:Index:[ \t]|diff[ \t]-|RCS file: |retrieving revision [0-9]+(\.[0-9]+)*$|---[ \t].*?^\+\+\+[ \t]|\*\*\*[ \t].*?^---[ \t])ZSubjectZFroms   user   
c                 s   s    | ]}d  ttj|V  qdS )r   N)r-   mapr   Z
strtolocal.0hr'   r'   r(   	<genexpr>   s   z_extract.<locals>.<genexpr>zX-Mercurial-Noderb   s   Node ID: %s
s   [PATCH   ]r   r   s   \n[ \t]+r   s   Subject: %s
s	   From: %s
rA   r+   s   Content-Type: %s
T)decodeFs   found patch at byte %d
r0   s   patch generated by hg export
s   # User    s	   # Parent 	      # s   # %s s   %s: %s
   ---rB   s   %s
%ss   messages   p1s   p2s   filename)!recompile	MULTILINEDOTALLr   rC   Z
headdecoder-   itemsdebugr!   findlstripsubrD   r   bytestrrE   Zget_payloadsearchstartr,   
splitlinesr<   truncater2   patchheadermapr#   writegetvalueendswithrk   pop)rm   rn   rp   rq   diffredatamsgZsubjectparentsZnodeidZpendZ
diffs_seenrF   messagerG   Zcontent_typeZpayloadr=   ZhgpatchZhgpatchheaderZ
ignoretextZcfpr$   headerkeyre   r'   r'   r(   rj      s    












rj   c                   @   sH   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dS )	patchmetaa  Patched file metadata

    'op' is the performed operation within ADD, DELETE, RENAME, MODIFY
    or COPY.  'path' is patched file path. 'oldpath' is set to the
    origin file when 'op' is either COPY or RENAME, None otherwise. If
    file mode is changed, 'mode' is a tuple (islink, isexec) where
    'islink' is True if the file is a symlink and 'isexec' is True if
    the file is executable. Otherwise, 'mode' is None.
    c                 C   s"   || _ d | _d | _d| _d| _d S )Ns   MODIFYF)patholdpathmodeopbinary)rP   r   r'   r'   r(   rQ   `  s
    zpatchmeta.__init__c                 C   s   |d@ }|d@ }||f| _ d S )Ni    @   )r   )rP   r   islinkisexecr'   r'   r(   setmodeg  s    zpatchmeta.setmodec                 C   s.   t | j}| j|_| j|_| j|_| j|_|S rM   )r   r   r   r   r   r   )rP   otherr'   r'   r(   copyl  s    
zpatchmeta.copyc                 C   s&   |dkr| j dkS |d| jp | j kS )N	   /dev/null   ADD   a/)r   r   r   )rP   afiler'   r'   r(   _ispatchingat  s    
zpatchmeta._ispatchingac                 C   s    |dkr| j dkS |d| j kS )Nr      DELETE   b/r   r   )rP   bfiler'   r'   r(   _ispatchingby  s    
zpatchmeta._ispatchingbc                 C   s   |  |o| |S rM   )r   r   )rP   r   r   r'   r'   r(   
ispatching~  s    zpatchmeta.ispatchingc                 C   s   d| j | jf S )Nz<patchmeta %s %r>r   rR   r'   r'   r(   __repr__  s    zpatchmeta.__repr__N)rX   rY   rZ   __doc__rQ   r   r   r   r   r   r   r'   r'   r'   r(   r   U  s   
r   c                 C   sr  d}g }| D ]N}| d}|drVt|}|rT|rB|| |d}t|}q|r|drt|| d}q|drd|_|dd |_q|d	r|d
d |_	q|drd|_|d
d |_q|dr|dd |_	q|drd|_q|dr&d|_|
t|dd d q|drL|
t|dd d q|drd|_q|rn|| |S )z9extract git-style metadata about patches from <patchname>N    
   diff --git a/r    r^   s   rename from    RENAME   s
   rename to 
   s
   copy from    COPYs   copy to    s   deleted filer   s   new file mode r   is	   new mode    GIT binary patchT)rstripr!   gitrematchr2   groupr   r   r   r   r   intr   )lrgp
gitpatchesr$   r=   dstr'   r'   r(   readgitpatch  sL    















r   c                   @   s,   e Zd Zdd Zdd Zdd Zdd Zd	S )

linereaderc                 C   s   || _ g | _d S rM   )r>   bufrO   r'   r'   r(   rQ     s    zlinereader.__init__c                 C   s   |d ur| j | d S rM   )r   r2   rP   r$   r'   r'   r(   push  s    zlinereader.pushc                 C   s&   | j r| j d }| j d= |S | j S Nr   )r   r>   rT   rV   r'   r'   r(   rT     s
    
zlinereader.readlinec                 C   s   t | jdS r*   )iterrT   rR   r'   r'   r(   rS     s    zlinereader.__iter__N)rX   rY   rZ   rQ   r   rT   rS   r'   r'   r'   r(   r     s   r   c                   @   sD   e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd Zdd Z	dS )abstractbackendc                 C   s
   || _ d S rM   )rm   )rP   rm   r'   r'   r(   rQ     s    zabstractbackend.__init__c                 C   s   t dS )zReturn target file data and flags as a (data, (islink,
        isexec)) tuple. Data is None if file is missing/deleted.
        NNotImplementedErrorrP   fnamer'   r'   r(   getfile  s    zabstractbackend.getfilec                 C   s   t dS )a	  Write data to target file fname and set its mode. mode is a
        (islink, isexec) tuple. If data is None, the file content should
        be left unchanged. If the file is modified after being copied,
        copysource is set to the original file name.
        Nr   rP   r   r   r   
copysourcer'   r'   r(   setfile  s    zabstractbackend.setfilec                 C   s   t dS )zUnlink target file.Nr   r   r'   r'   r(   rl     s    zabstractbackend.unlinkc                 C   s   dS )zWrite rejected lines for fname. total is the number of hunks
        which failed to apply and total the total number of hunks for this
        files.
        Nr'   )rP   r   failedtotalr.   r'   r'   r(   writerej  s    zabstractbackend.writerejc                 C   s   t d S rM   r   r   r'   r'   r(   exists  s    zabstractbackend.existsc                 C   s   t d S rM   r   rR   r'   r'   r(   rk     s    zabstractbackend.closeN)
rX   rY   rZ   rQ   r   r   rl   r   r   rk   r'   r'   r'   r(   r     s   r   c                       sD   e Zd Z fddZdd Zdd Zdd Zd	d
 Zdd Z  Z	S )	fsbackendc                    s    t t| | t|| _d S rM   )superr   rQ   vfsmodr   opener)rP   rm   Zbasedir	__class__r'   r(   rQ     s    zfsbackend.__init__c              
   C   s   | j |r| j |dfS d}z| j |jd@ dk}W n2 tyl } z|jtjkrX W Y d }~n
d }~0 0 z| j |d|ffW S  t	y } z|jtjkr W Y d }~dS d }~0 0 d S )NTFFr   r   NN)
r   r   readlinklstatst_modeOSErrorerrnoZENOENTreadIOError)rP   r   r   er'   r'   r(   r     s    zfsbackend.getfilec                 C   s^   |\}}|d u r$| j ||| d S |r8| j || n"| j || |rZ| j |dd d S rI   )r   Zsetflagssymlinkr   )rP   r   r   r   r   r   r   r'   r'   r(   r      s    zfsbackend.setfilec                 C   s$   | j dd}| jj|d|d d S )Ns   experimentals   removeemptydirsT)Zignoremissingrmdir)rm   Z
configboolr   Z
unlinkpath)rP   r   r   r'   r'   r(   rl     s    zfsbackend.unlinkc                 C   sD   |d }| j td|||f  | |d}|| |  d S )Ns   .rejs7   %d out of %d hunks FAILED -- saving rejects to file %s
   w)rm   warnr   r   
writelinesrk   )rP   r   r   r   r.   r>   r'   r'   r(   r     s    
zfsbackend.writerejc                 C   s   | j |S rM   )r   lexistsr   r'   r'   r(   r     s    zfsbackend.exists)
rX   rY   rZ   rQ   r   r   rl   r   r   __classcell__r'   r'   r   r(   r     s   
r   c                       sD   e Zd Z fddZdd Z fddZ fddZd	d
 Z  ZS )workingbackendc                    s:   t t| ||j || _|| _t | _t | _g | _	d S rM   )
r   r   rQ   rootrepo
similaritysetremovedchangedcopied)rP   rm   r   r   r   r'   r(   rQ     s    zworkingbackend.__init__c                 C   s.   | j j| dkr*| |r*ttd| d S )N   ?$   cannot patch %s: file is not tracked)r   dirstater   
PatchErrorr   r   r'   r'   r(   _checkknown'  s    zworkingbackend._checkknownc                    sH   |  | tt| |||| |d ur8| j||f | j| d S rM   )r   r   r   r   r   r2   r   addr   r   r'   r(   r   +  s
    
zworkingbackend.setfilec                    s6   |  | tt| | | j| | j| d S rM   )r   r   r   rl   r   r   r   r   r   r'   r(   rl   2  s    
zworkingbackend.unlinkc                 C   s   | j d  }t| j}| jD ]\}}t| j| j ||| q| jrr|t	| j | jD ]}|| j j
vrV|| qV|rt| j || j t	| jS rM   )r   r   r   r   r   Zdirstatecopyrm   r   Zforgetsortedr   discardmarktouchedr   )rP   Zwctxr   srcr   fr'   r'   r(   rk   8  s    


zworkingbackend.close)	rX   rY   rZ   rQ   r   r   rl   rk   r   r'   r'   r   r(   r     s
   r   c                   @   s0   e Zd Zd
ddZdddZdd Zdd	 ZdS )	filestoreNc                 C   s8   d | _ i | _d| _|| _| jd u r(d| _d| _i | _d S )Nr   i  @ )r   filescreatedmaxsizesizer   )rP   r  r'   r'   r(   rQ   L  s    
zfilestore.__init__c                 C   s   | j dk st|| j | j krB|||f| j|< |  jt|7  _nX| jd u rdtjdd}t|| _d| j	 }| j
|| |  j	d7  _	|||f| j|< d S )Nr   rc   rd      %dr   )r  r#   r  r   r   r   Zmkdtempr   r   r  r   r  )rP   r   r   r   r   r   fnr'   r'   r(   r   V  s    

zfilestore.setfilec                 C   sJ   || j v r| j | S | jr$|| jvr(dS | j| \}}}| j|||fS )N)NNN)r   r   r  r   )rP   r   r  r   r   r'   r'   r(   r   d  s    

zfilestore.getfilec                 C   s   | j rt| j j d S rM   )r   shutilZrmtreebaserR   r'   r'   r(   rk   l  s    zfilestore.close)N)N)rX   rY   rZ   rQ   r   r   rk   r'   r'   r'   r(   r  K  s   


r  c                       sL   e Zd Z fddZdd Zdd Zdd Zd	d
 Zdd Zdd Z	  Z
S )repobackendc                    s<   t t| | || _|| _|| _t | _t | _i | _	d S rM   )
r   r
  rQ   r   ctxstorer   r   r   r   )rP   rm   r   r  r  r   r'   r(   rQ   r  s    zrepobackend.__init__c                 C   s   || j vrttd| d S )Nr   )r  r   r   r   r'   r'   r(   r   {  s    
zrepobackend._checkknownc                 C   sF   z| j | }W n tjy$   Y dS 0 | }| d|v d|v ffS )Nr      l   x)r  r   LookupErrorflagsr   )rP   r   fctxr  r'   r'   r(   r     s    zrepobackend.getfilec                 C   sT   |r|  | |d u r$| j|  }| j|||| | j| |rP|| j|< d S rM   )r   r  r   r  r   r   r   r   r   r'   r'   r(   r     s    
zrepobackend.setfilec                 C   s   |  | | j| d S rM   )r   r   r   r   r'   r'   r(   rl     s    
zrepobackend.unlinkc                 C   s
   || j v S rM   )r  r   r'   r'   r(   r     s    zrepobackend.existsc                 C   s   | j | jB S rM   )r   r   rR   r'   r'   r(   rk     s    zrepobackend.close)rX   rY   rZ   rQ   r   r   r   rl   r   rk   r   r'   r'   r   r(   r
  q  s   	
r
  s*   @@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@s.   (?:---|\*\*\*) (\d+)(?:,(\d+))? (?:---|\*\*\*))   strict   crlf   lf   autoc                   @   sF   e Zd ZdddZdd Zdd Zdd	 Zd
d Zdd Zdd Z	dS )	patchfiler  c           
      C   s  |j | _|| _d | _|| _|| _g | _d| _d| _|j	| _	|j
| _|jdv | _|jdk| _| jd u rv|| j\}}n|| jd d \}}|d urX| jd u p|| j| _d| _|rt|| _| j	d u r|| _	| jrx| jd drd| _n| jd drd| _|d	krxg }| jD ],}	|	drB|	d d
 d }	||	 q"|| _n | jrfd| _| j	d u rxd| _	| jr| jtd| j  | jtd i | _d| _d| _d| _g | _d| _| d d| _d S )NFT)r   r   r   r   r    r      
rs   r  )FFs!   unable to find '%s' for patching
sB   (use '--prefix' to apply patch relative to the current directory)
)r   r   eolmodeeolbackendrm   r.   r   missingr   r   r   r   createremover   r   splitnewlinesr   r2   r   r   hashdirtyoffsetskewrejfileprinted	printfilehunks)
rP   rm   r   r  r  r  r   r   nlinesr&   r'   r'   r(   rQ     sj    





zpatchfile.__init__c                 C   s   | j dkr| j}n| j dkr"d}nd}| j dkrv|rv|dkrvg }|D ],}|rf|drf|d d | }|| qD|}| j|d||| j d S )Nr  r  r  rs   r  r+   )r  r  r   r2   r  r   r-   r   )rP   r   r.   r   r  Zrawlinesr&   r'   r'   r(   r     s    

zpatchfile.writelinesc                 C   sL   | j r
d S |s| jjrd| _ td| j }|r<| j| n| j| d S )NTs   patching file %s
)r%  rm   verboser   r   r   note)rP   r   sr'   r'   r(   r&    s    zpatchfile.printfilec                    s2   | j |g }t|dkr.|j fddd |S )Nr   c                    s   t |   S rM   )abs)xlinenumr'   r(   <lambda>  r+   z%patchfile.findlines.<locals>.<lambda>)r   )r   getr#   sort)rP   r&   r0  candr'   r/  r(   	findlines  s    zpatchfile.findlinesc                 C   s   | j s
d S tj| j}d||f g}| j D ]:}|jD ].}|| |dd  dkr6|dtj  q6q,| j	
| jt| j | j| d S )Ns   --- %s
+++ %s
r)  rs   )r$  rh   r   basenamer   hunkr2   r   MISSING_NEWLINE_MARKERr  r   r#   r'  )rP   r	  r.   r.  r&   r'   r'   r(   	write_rej  s    


zpatchfile.write_rejc              
   C   s  |  s8ttd|j|jt|j|jt|j|j	f |  j
d7  _
| jr\| j| dS | jr| jr| jr| jtd| j  n| jtd| j  | j| dS t|tr| jr| j| j n2|| j}|| jd d < |  jt|7  _d| _dS |}| jdv s(| jd	kr0| jr0| }| dd
\}}}}|| j7 }|}| j!dkrt"#|| j|r| jr| j| j n6|| j||t| < |  jt|t| 7  _d| _dS i | _$t%| jD ]\}	}
| j$&|
g |	 qt'(| j)ddd D ]J}dD ]<}| ||\}}}}|| j | j! }t*|t| j}|rn| +|d dd  |}n|g}|D ]}|rt"#|| j|rx|| j||t| < |  jt|t| 7  _|| | _!d| _|| | }|rtd}| ,d | j||j|d ||f  n$td}| j-||j|d |f  |      S qxqq
| ,d | jtd|j|f  | j| dS )Ns   bad hunk #%d %s (%d %d %d %d)r   r)  s-   cannot create %s: destination already exists
s   file %s already exists
Tr   )r  r  r  F   patchs   fuzzr   s9   Hunk #%d succeeded at %d with fuzz %d (offset %d lines).
s,   Hunk #%d succeeded at %d (offset %d lines).
s   Hunk #%d FAILED at %d
).completer   r   numberdescr#   alenablenbr'  r  r$  r2   r   r  r   rm   r   r   
isinstancebinhunkr  r  rl   newr.   r"  r!  r  r  getnormalizedfuzzitr#  r   Ztesthunkr   	enumerate
setdefaultr   xrangeZ	configintminr5  r&  r+  )rP   rw   r&   ZhorigoldoldstartrD  newstartZ
orig_startr.  r,  Zfuzzlentoponlyr4  r"  r   r'   r'   r(   apply  s    "





zpatchfile.applyc                 C   s,   | j r| | j| j| j |   t| jS rM   )r!  r   r   r.   r   r9  r#   r$  rR   r'   r'   r(   rk     s    zpatchfile.closeN)r  )
rX   rY   rZ   rQ   r   r&  r5  r9  rO  rk   r'   r'   r'   r(   r    s   
<mr  c                   @   s   e Zd ZdZedZedZedZedZ	edZ
edZdd	 Zd
d Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd ZdS )r   zpatch header
    s   diff --git a/(.*) b/(.*)$s   diff -r .* (.*)$s   (?:index|deleted file) s   (?:new file|deleted file) s'   (?:index|deleted|copy|rename|new mode) s   (?:new file|copy to|rename to)c                 C   s   || _ g | _d S rM   )r   r'  )rP   r   r'   r'   r(   rQ     s    zheader.__init__c                 C   s   t dd | jD S )Nc                 s   s   | ]}| d V  qdS )   index Nr!   ru   r'   r'   r(   rx     r+   z header.binary.<locals>.<genexpr>anyr   rR   r'   r'   r(   r     s    zheader.binaryc                 C   s   | j D ]}|dr&|td  q| j|rV|| |  rR|td  q|dr|tdt| jt	dd | jD f   q|| qd S )NrP  s-   this modifies a binary file (all or nothing)
s   this is a binary file
r~   s   %d hunks, %d lines changed
c                 S   s   g | ]}t |j|jqS r'   )maxaddedr   ru   r'   r'   r(   
<listcomp>  r+   z!header.pretty.<locals>.<listcomp>)
r   r!   r   r   	pretty_rer   r   r#   r'  sum)rP   r>   rw   r'   r'   r(   pretty  s&    



zheader.prettyc                 C   s   | d| j d S r*   )r   r-   r   rO   r'   r'   r(   r     s    zheader.writec                    s   t  fdd jD S )Nc                 3   s   | ]} j |V  qd S rM   )allhunks_rer   ru   rR   r'   r(   rx     r+   z"header.allhunks.<locals>.<genexpr>rR  rR   r'   rR   r(   allhunks  s    zheader.allhunksc                 C   sR   | j | jd }|r8| \}}||kr0|gS ||gS | j| jd  S d S r   )
diffgit_rer   r   groupsdiff_re)rP   r   fromfiletofiler'   r'   r(   r    s    zheader.filesc                 C   s   |   d S )Nr)  )r  rR   r'   r'   r(   filename  s    zheader.filenamec                 C   s   dd ttj|   S )Nz<header %s> )r-   r   Zrapplyfsdecoder  rR   r'   r'   r(   r     s    zheader.__repr__c                    s   t  fdd jD S )Nc                 3   s   | ]} j |V  qd S rM   )
newfile_rer   ru   rR   r'   r(   rx     r+   z#header.isnewfile.<locals>.<genexpr>rR  rR   r'   rR   r(   	isnewfile  s    zheader.isnewfilec                    s6   t  jdk}  o|}|p4t fdd jD S )Nr    c                 3   s   | ]} j |V  qd S rM   )
special_rer   ru   rR   r'   r(   rx     s   z!header.special.<locals>.<genexpr>)r#   r   re  rS  )rP   Z	nocontentZemptynewfiler'   rR   r(   special  s
    zheader.specialN)rX   rY   rZ   r   r   r   r\  r^  rZ  rW  rf  rd  rQ   r   rY  r   r[  r  ra  r   re  rg  r'   r'   r'   r(   r     s"   






r   c                   @   s\   e Zd ZdZdddZdd Zdd Zd	d
 Zdd Zdd Z	e	Z
dd Zejdd ZdS )
recordhunkzKpatch hunk

    XXX shouldn't we merge this with the other hunk class?
    Nc	                    sl   d fdd	}	|| _ |	|d\}
| _||
 | _||
 | _|	|d\}| _|| _|| _| | j\| _| _	d S )NFc                    sH    d ur@t |   }|dkr@|r0|| |d  fS || d   fS d| fS r   r#   )r.   reversedelta
maxcontextr'   r(   trimcontext  s    z(recordhunk.__init__.<locals>.trimcontextT)F)
r   beforefromlinetolineafterprocr7  countchangesrU  r   )rP   r   rp  rq  rs  ro  r7  rr  rm  rn  ZtrimedbeforeZ_trimedafterr'   rl  r(   rQ     s    


zrecordhunk.__init__c                 C   sF   t |tsdS |j| jkoD|j| jkoD| j|jkoD| j |j kS )NF)rB  rh  r7  rs  rp  r   r  )rP   vr'   r'   r(   __eq__   s    


zrecordhunk.__eq__c                 C   s$   t t| jt| j | j| jfS rM   )r   tupler7  r   r  rp  rs  rR   r'   r'   r(   __hash__  s    zrecordhunk.__hash__c                 C   s,   t dd |D }t dd |D }||fS )zhunk -> (n+,n-)c                 S   s   g | ]}| d r|qS )r   rQ  ru   r'   r'   r(   rV    r+   z+recordhunk.countchanges.<locals>.<listcomp>c                 S   s   g | ]}| d r|qS )r   rQ  ru   r'   r'   r(   rV    r+   ri  )rP   r7  r   Zremr'   r'   r(   rt    s    zrecordhunk.countchangesc                    s@   dddd  fdd| j D }t| j| j| j| j| j|| jS )zreturn another recordhunk which is the reverse of the hunk

        If this hunk is diff(A, B), the returned hunk is diff(B, A). To do
        that, swap fromline/toline and +/- signs while keep other things
        unchanged.
        r   r      \)r   r   ry  c                    s,   g | ]$}d  |dd  |dd f qS )s   %s%sr   r   Nr'   )rv   r&   r=   r'   r(   rV  #  r+   z*recordhunk.reversehunk.<locals>.<listcomp>)r7  rh  r   rq  rp  rs  ro  rr  rP   r7  r'   rz  r(   reversehunk  s    zrecordhunk.reversehunkc              	   C   s   t | jt | j }| jr2| jd tjkr2|d8 }|| j }|| j }|d| j|| j	|| j
ofd| j
 f  |d| j| j | j  d S )Nr)  r   s   @@ -%d,%d +%d,%d @@%s
r   r+   )r#   ro  rr  r   r8  r   rU  r   rp  rq  rs  r-   r7  )rP   r>   rk  ZfromlenZtolenr'   r'   r(   r   .  s     


zrecordhunk.writec                 C   s
   | j  S rM   )r   ra  rR   r'   r'   r(   ra  B  s    zrecordhunk.filenamec                 C   s   d|   | jf S )Ns   <hunk %r@%d>)ra  rp  rR   r'   r'   r(   r   E  s    zrecordhunk.__repr__)N)rX   rY   rZ   r   rQ   rv  rx  rt  r|  r   rY  ra  r   Z	strmethodr   r'   r'   r'   r(   rh    s    

rh  c                   C   sZ   t dt dt dt ddt dt dt dt d	dt d
t dt dt dddS )Ns   apply change %d/%d to '%s'?s   discard change %d/%d to '%s'?s   keep change %d/%d to '%s'?s   record change %d/%d to '%s'?)s   applys   discards   keep   records   apply this change to '%s'?s   discard this change to '%s'?s   keep this change to '%s'?s   record this change to '%s'?s0  [Ynesfdaq?]$$ &Yes, apply this change$$ &No, skip this change$$ &Edit this change manually$$ &Skip remaining changes to this file$$ Apply remaining changes to this &file$$ &Done, skip remaining changes and files$$ Apply &all changes to all remaining files$$ &Quit, applying no changes$$ &? (display help)s8  [Ynesfdaq?]$$ &Yes, discard this change$$ &No, skip this change$$ &Edit this change manually$$ &Skip remaining changes to this file$$ Discard remaining changes to this &file$$ &Done, skip remaining changes and files$$ Discard &all changes to all remaining files$$ &Quit, discarding no changes$$ &? (display help)s-  [Ynesfdaq?]$$ &Yes, keep this change$$ &No, skip this change$$ &Edit this change manually$$ &Skip remaining changes to this file$$ Keep remaining changes to this &file$$ &Done, skip remaining changes and files$$ Keep &all changes to all remaining files$$ &Quit, keeping all changes$$ &? (display help)s4  [Ynesfdaq?]$$ &Yes, record this change$$ &No, skip this change$$ &Edit this change manually$$ &Skip remaining changes to this file$$ Record remaining changes to this &file$$ &Done, skip remaining changes and files$$ Record &all changes to all remaining files$$ &Quit, recording no changes$$ &? (display help))   multiple   single   helpr   r'   r'   r'   r(   getmessagesJ  s0    r  c                    s  t  du rdfdd}t }i }d\}}dtdd |D  }	}
|D ]}|	t|j7 }	d}d	}d
|j}||v rqP|| |du r| |	 }t
dt
ddd |D  }t fdd|D rd\}}}n||||d\}}}}|sqP|g|| < | r6||   |j7  < qPt|jD ]\}}|du rh|du rh| |
dkrd  |  }n,|	t|j | }d  ||
| f }|||||\}}}}|r|rt|}| j|7  _||  | n\|durN|D ]:}|jD ],}|r2| j|7  _||  | qqn||j|j 7 }q@qPtdd t|D g i fS )z:Interactively filter patch chunks into applied-only chunksNr}  c              	      s  d}|dur|| ||fS | dur,| | ||fS  d  } d||f }d |dkr|d D ] \}}d|t|f  qjq,n"|dkrd	}	n|dkrd
}	n|dkrL|du rވtd d q,|j rtd d q,dtd }
tj	ddd\}}d}zt
t|d}|j| || |ddd |
 D  |   }jd||f d idd}	|	dkr̈td|	  W t| ~q,t|d}t }t
|D ]&}t
|}|ds|| q|  |d t|}W t| ~nt| ~0 d
}	nh|dkr`d
 }	} nT|dkrtd	 }	} n@|d krd
 }	}n,|d!krd	 }	}n|d"krttd#|	| ||fS )$zprompt query, and process base inputs

        - y/n for the rest of file
        - y/n for the rest
        - ? (help)
        - q (quit)

        Return True/False and possibly updated skipfile and skipall.
        Nr  s   %s
(enter ? for help) %srs   r   r   s   %s - %s
r   TFr    s    cannot edit patch for whole files!   cannot edit patch for binary filer~   a  
To remove '-' lines, make them ' ' lines (context).
To remove '+' lines, delete them.
Lines starting with # will be removed from the patch.

If the patch applies cleanly, the edited hunk will immediately be
added to the record list. If it does not apply cleanly, a rejects
file will be generated: you can use that when you try again. If
all lines of the hunk are removed, then the edit is aborted and
the hunk is left unchanged.
s
   hg-editor-s   .diff)re   suffixrf   r+   c                 S   s   g | ]}d | d qS )r}   rs   r'   )rv   ir'   r'   r(   rV    r+   z/filterpatch.<locals>.prompt.<locals>.<listcomp>s   %s "%s"s   HGUSERs   filterpatch)environZ
blockedtags    editor exited with exit code %d
rb   #            r{   s	   user quit)Zpromptchoicer   Zextractchoicesr   ra   r   r   r   r   rg   r   Znativeeolwriterrh   ri   r-   r   rk   Z	geteditorsystemZusernamer   rl   r	   r,   iterfileZfromnativeeolr!   r<   
parsepatchr   Abort)skipfileskipallZqueryr/   
newpatchesZrespsrr9   tretZphelpZpatchfdZpatchfnZ	ncpatchfpr   ZeditorZpatchfpr$   )messages	operationrm   r'   r(   prompt  s    

























zfilterpatch.<locals>.promptr   r   c                 s   s   | ]}t |jV  qd S rM   )r#   r'  ru   r'   r'   r(   rx     r+   zfilterpatch.<locals>.<genexpr>r   r+   s   examine changes to %s?s    and c                 s   s   | ]}d | V  qdS )s   '%s'Nr'   rv   r   r'   r'   r(   rx     s   c                 3   s   | ]}  |V  qd S rM   )exactr  r   r'   r(   rx     r+   )TNNr  r~  c                 S   s(   g | ] }|d    s t|dkr|qS )r   r   )rg  r#   ru   r'   r'   r(   rV  8  s   zfilterpatch.<locals>.<listcomp>)r  r   rX  r#   r'  r-   r   r   rY  r  r   allra  r[  rG  r   rq  r2   r   rU  r   Z
itervalues)rm   headersr   r  r  seenZappliedr  r  posr   rw   Z	fixoffsethdrr  r   r  Znpr  r/   idxr  ZnewpatchZnewhunkr'   )r   r  r  rm   r(   filterpatch  s    j










r  c                   @   sL   e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dS )r7  c                 C   s^   || _ || _|g| _g | _g | _d  | _| _d  | _| _|d urZ|rP| 	| n
| 
| d S rM   )r<  r=  r7  r>  r@  startar?  startbrA  read_context_hunkread_unified_hunk)rP   r=  Znumr   contextr'   r'   r(   rQ   D  s    zhunk.__init__c                 C   sn   dd }t | j| jdd}| j|_| j|_| j |_ || j|_|| j|_| j|_| j|_| j|_| j|_|S )z1Return a copy with line endings normalized to LF.c                 S   s6   g }| D ](}| dr&|d d d }|| q|S )Nr  r  rs   )r   r2   )r.   r(  r$   r'   r'   r(   	normalizeU  s    
z%hunk.getnormalized.<locals>.normalizeN)	r7  r=  r<  r>  r@  r  r  r?  rA  )rP   r  Znhr'   r'   r(   rE  R  s    	zhunk.getnormalizedc              
   C   sF  t | j}|s"ttd| j | \| _| _| _	| _
| jd u rLd| _nt| j| _| j
d u rjd| _
nt| j
| _
t| j| _t| j	| _	z"t|| j| j| j
| j| j W n< tjy } z"ttd| j|f W Y d }~n
d }~0 0 t| jd dkr8| jd= | jd= | jd= |  jd8  _|  j
d8  _
q| | d S )N   bad hunk #%dr   s   bad hunk #%d: %sr)  r   )unidescr   r=  r   r   r<  r]  r  r?  r  rA  r   r   Zaddlinesr7  r>  r@  r   Z
ParseErrorr#   _fixnewline)rP   r   r=   r   r'   r'   r(   r  j  s2    

,zhunk.read_unified_hunkc                 C   s  |  | _t| j}|s,ttd| j | \| _}t	| j| _|d u rT| j}t	|| j | _
| jrx|  j
d7  _
t| j
D ]}|  }|dr||  q|dd  }|ds|drd| }n*|drd	| }nttd
| j|f | j| | j| q|  }|drZ| jd d d }|| jd< || jd< |  }t|}|s|ttd| j | \| _}t	| j| _|d u r| j}t	|| j | _| jr|  jd7  _d}	t| jD ]J}|  }|dr$| jd d d }|| jd< || j|	d < q|s:||  q*|dd  }|ds^|drhd| }nN|dr~d	| }n8t| jdkr||  q*nttd
| j|f | j| |	t| jkrd}
n
| j|	 }
|	d7 }	|
|krqn(|
drqn| j|	d | qܐqq| jsd| jD ]*}|dsT|d	r8| j| q8| js| jD ]2}|ds|d	rr| j|dd   qrd| j| j
| j| jf | _| j| jd< | | d S )Nr  r   r~   r    s   - s   ! r   s     r   s   bad hunk #%d old text line %d   \ r)  s   + r   r   r+   s   @@ -%d,%d +%d,%d @@
)rT   r=  contextdescr   r   r   r<  r]  r  r   r?  r   rI  r!   r   r>  r2   r7  r  rA  r@  r#   insertr  )rP   r   r=   Zaendr.  r&   r,  uZbendZhunkirw   r'   r'   r(   r    s    


















zhunk.read_context_hunkc                 C   s6   |  }|dr(t| j| j| j n
|| d S )Nr  )rT   r!   r   Z
fixnewliner7  r>  r@  r   )rP   r   r&   r'   r'   r(   r    s    
zhunk._fixnewlinec                 C   s    t | j| jkot | j| jkS rM   )r#   r>  r?  r@  rA  rR   r'   r'   r(   r;    s    zhunk.completec           	      C   s   t |t|}|rd}d}t| j}t|d D ]&}| j|d  drT|d7 }q2 qZq2|st|d D ]*}| j|| d  dr|d7 }ql qqlt ||}t ||}||t||  ||t||  |fS ||dfS )Nr   r   r   )rJ  r#   r7  r   rI  r!   )	rP   rK  rD  fuzzrN  topZbotZhlenr.  r'   r'   r(   _fuzzit   s$    




*zhunk._fuzzitc                 C   sf   |  | j| j||\}}}| j| }| j| }| jrD|dkrD|d8 }| jrZ|dkrZ|d8 }||||fS )Nr   r   )r  r>  r@  r  r  r?  rA  )rP   r  rN  rK  rD  r  rL  rM  r'   r'   r(   rF    s    

zhunk.fuzzitN)rX   rY   rZ   rQ   rE  r  r  r  r;  r  rF  r'   r'   r'   r(   r7  C  s   mr7  c                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )rC  zA binary patch file.c                 C   s(   d | _ d| _dg| _|| _| | d S )NFs   GIT binary patch
)textrk  r7  _fname_read)rP   r   r   r'   r'   r(   rQ   *  s
    zbinhunk.__init__c                 C   s
   | j d uS rM   )r  rR   r'   r'   r(   r;  1  s    zbinhunk.completec                 C   s"   | j rt| jd|gS | jgS r*   )rk  applybindeltar  r-   )rP   r.   r'   r'   r(   rD  4  s    zbinhunk.newc           	   
   C   s  dd }||| j }|s*ttd| j |drJt|dd   }qr|drt|dd   }d| _qrqg }||| j }t|d	krL|d
d	 }|dkr|dkrt	|t	d d	 }nt	|t	d d }z$|
t|d	d  d |  W nB ty< } z(ttd| jt|f W Y d }~n
d }~0 0 ||| j }qtd|}t||krttd| jt||f || _d S )Nc                 S   s   |   }|| |dS )Nr  )rT   r2   r   )r   r7  r&   r'   r'   r(   getline:  s    
zbinhunk._read.<locals>.getlines"   could not extract "%s" binary datas   literal r   s   delta r  Tr   r      Z   A   a   s&   could not decode "%s" binary patch: %sr+   s%   "%s" length is %d bytes, should be %d)r7  r   r   r  r!   r   r   rk  r#   ordr2   r   Z	b85decode
ValueErrorr   forcebytestrzlib
decompressr-   r  )	rP   r   r  r$   r  Zdecr&   r   r  r'   r'   r(   r  9  sJ    

$zbinhunk._readN)rX   rY   rZ   r   rQ   r;  rD  r  r'   r'   r'   r(   rC  '  s
   rC  c                 C   sF   | dd   d}|d}|dk r:|d}|dk r:|S |d | S )Nr  r  r   r   r   )r   r   )strr,  r  r'   r'   r(   parsefilenamee  s    

r  c                 C   s0   g }| D ]"}t |dr | }|| q|S )a  reverse the signs in the hunks given as argument

    This function operates on hunks coming out of patch.filterpatch, that is
    a list of the form: [header1, hunk1, hunk2, header2...]. Example usage:

    >>> rawpatch = b"""diff --git a/folder1/g b/folder1/g
    ... --- a/folder1/g
    ... +++ b/folder1/g
    ... @@ -1,7 +1,7 @@
    ... +firstline
    ...  c
    ...  1
    ...  2
    ... + 3
    ... -4
    ...  5
    ...  d
    ... +lastline"""
    >>> hunks = parsepatch([rawpatch])
    >>> hunkscomingfromfilterpatch = []
    >>> for h in hunks:
    ...     hunkscomingfromfilterpatch.append(h)
    ...     hunkscomingfromfilterpatch.extend(h.hunks)

    >>> reversedhunks = reversehunks(hunkscomingfromfilterpatch)
    >>> from . import util
    >>> fp = util.stringio()
    >>> for c in reversedhunks:
    ...      c.write(fp)
    >>> fp.seek(0) or None
    >>> reversedpatch = fp.read()
    >>> print(pycompat.sysstr(reversedpatch))
    diff --git a/folder1/g b/folder1/g
    --- a/folder1/g
    +++ b/folder1/g
    @@ -1,4 +1,3 @@
    -firstline
     c
     1
     2
    @@ -2,6 +1,6 @@
     c
     1
     2
    - 3
    +4
     5
     d
    @@ -6,3 +5,2 @@
     5
     d
    -lastline

    s   reversehunk)r   r`   r|  r2   )r'  Znewhunksr9   r'   r'   r(   reversehunksp  s    8r  c              	      s   G  fdddt }| }t }|d|  |d d}t|D ]H\}}z|j| | || W n" ty   td||f Y n0 |}qF~|	 S )aD  patch -> [] of headers -> [] of hunks

    If maxcontext is not None, trim context lines if necessary.

    >>> rawpatch = b'''diff --git a/folder1/g b/folder1/g
    ... --- a/folder1/g
    ... +++ b/folder1/g
    ... @@ -1,8 +1,10 @@
    ...  1
    ...  2
    ... -3
    ...  4
    ...  5
    ...  6
    ... +6.1
    ... +6.2
    ...  7
    ...  8
    ... +9'''
    >>> out = util.stringio()
    >>> headers = parsepatch([rawpatch], maxcontext=1)
    >>> for header in headers:
    ...     header.write(out)
    ...     for hunk in header.hunks:
    ...         hunk.write(out)
    >>> print(pycompat.sysstr(out.getvalue()))
    diff --git a/folder1/g b/folder1/g
    --- a/folder1/g
    +++ b/folder1/g
    @@ -2,3 +2,2 @@
     2
    -3
     4
    @@ -6,2 +5,4 @@
     6
    +6.1
    +6.2
     7
    @@ -8,1 +9,2 @@
     8
    +9
    c                       s   e Zd ZdZdd Zdd Z fddZdd	 Zd
d Zdd Z	dd Z
eeeedeeee	deeedeedde	idZdS )zparsepatch.<locals>.parserzpatch parsing state machinec                 S   s4   d| _ d| _d| _d | _g | _g | _g | _g | _d S )Nr   r+   )rp  rq  rs  r   r  ro  r7  r  rR   r'   r'   r(   rQ     s    z#parsepatch.<locals>.parser.__init__c                 S   s6   |  g  |\}}}}}t|| _t|| _|| _d S rM   )
addcontextr   rp  rq  rs  )rP   ZlimitsZ	fromstartZfromendZtostartZtoendrs  r'   r'   r(   addrange  s
    


z#parsepatch.<locals>.parser.addrangec              	      s   | j rvt| j| j| j| j| j| j | }| jj| |  jt	| j|j
 7  _|  jt	| j|j 7  _g | _g | _ || _d S rM   )r7  rh  r   rp  rq  rs  ro  r'  r2   r#   r   rU  r  )rP   r  rw   rl  r'   r(   r    s"    
z%parsepatch.<locals>.parser.addcontextc                 S   s.   | j r| j | _g | _ | jr$| g  || _d S rM   )r  ro  r7  r  r{  r'   r'   r(   addhunk  s    
z"parsepatch.<locals>.parser.addhunkc                 S   s(   |  g  t|}| j| || _d S rM   )r  r   r  r2   )rP   r  rw   r'   r'   r(   newfile  s    
z"parsepatch.<locals>.parser.newfilec                 S   s   d S rM   r'   r   r'   r'   r(   addother  s    z#parsepatch.<locals>.parser.addotherc                 S   s   |  g  | jS rM   )r  r  rR   r'   r'   r(   finished  s    
z#parsepatch.<locals>.parser.finished)   context   file   hunk   range)r  r  r     other)r  r  r  )r  r  r  )r  r  r  r  r  N)rX   rY   rZ   r   rQ   r  r  r  r  r  r  transitionsr'   rl  r'   r(   parser  s2   
r  r+   r   r  s   unhandled transition: %s -> %s)
r_   r,   r   r-   r<   	scanpatchr  KeyErrorr   r  )Zoriginalchunksrm  r  pr>   stateZnewstater   r'   rl  r(   r    s     ,R


r  c                 C   s   t | }d}|dkr$d||   fS |}|dkr| d|}|dkrZttd||| f |d7 }||d k r| ||d  dkr|d7 }qb|d8 }q(| d|  || |d   fS )a  turn a path from a patch into a path suitable for the repository

    prefix, if not empty, is expected to be normalized with a / at the end.

    Returns (stripped components, path in repository).

    >>> pathtransform(b'a/b/c', 0, b'')
    ('', 'a/b/c')
    >>> pathtransform(b'   a/b/c   ', 0, b'')
    ('', '   a/b/c')
    >>> pathtransform(b'   a/b/c   ', 2, b'')
    ('a/b/', 'c')
    >>> pathtransform(b'a/b/c', 0, b'd/e/')
    ('', 'd/e/a/b/c')
    >>> pathtransform(b'   a//b/c   ', 2, b'd/e/')
    ('a//b/', 'd/e/c')
    >>> pathtransform(b'a/b/c', 3, b'')
    Traceback (most recent call last):
    PatchError: unable to strip away 1 of 3 dirs from a/b/c
    r   r+      /r)  s*   unable to strip away %d of %d dirs from %sr   N)r#   r   r   r   r   r   )r   r1   re   Zpathlenr  countr'   r'   r(   pathtransform@  s$     

r  c                 C   s  |dk}|dk}|o&|j dko&|jdk}|o>|jdko>|jdk}	t|||\}
}| o^| |}t|||\}}||kr~|}n| o| |}| o| o| }|d |dd  }|d |dd  }|r||kr||r|j dkr|jdkrd}d}|
|ko||}d }|sD|r:|r:|r4|}n|}n
|rD|}|sz|sb|r\|}n|}n|sn|}ntt	dt
|}|rd|_n|	rd	|_|S )
Nr   r   r  r   TFs&   undefined source and destination filesr   r   )r  r?  r  rA  r  r   rfindr!   r   r   r   r   )r  Z
afile_origZ
bfile_origr7  r1   re   ZnullaZnullbr  r  Zabaser   ZgoodaZbbaser   Zgoodbr  ZabasedirZbbasedirZisbackupr   r   r'   r'   r(   makepatchmetai  s`    r  c           	      #   s  t d}t| fdd}tjdD ]}|dsB|drdd }|||} }|d	r| }|||g7 }n
| d
|fV  q*|drd d|| fddfV  q*|drd d|| fddfV  q*||}|rd| fV  q*d|fV  q*dS )zlike patch.iterhunks, but yield different events

    - ('file',    [header_lines + fromfile + tofile])
    - ('context', [context_lines])
    - ('hunk',    [hunk_lines])
    - ('range',   (-start,len, +start,len, proc))
    s'   @@ -(\d+),(\d+) \+(\d+),(\d+) @@\s*(.*)c                    s>   | g}t  jdD ]&}||r*|| q |  q:q|S )zscan lr while predicate holdsr+   )r   rT   r2   r   )firstr  r.   r$   )r   r'   r(   	scanwhile  s    
zscanpatch.<locals>.scanwhiler+   r   s   diff -r c                 S   s   |  d d}| p|d dvS )Nr   r   )r~      diff)r"   )r$   r,  r'   r'   r(   	notheader  s    zscanpatch.<locals>.notheaderr~   r  r   )r   ry  r  c                    s
   |   S rM   rQ  r&   csr'   r(   r1    r+   zscanpatch.<locals>.<lambda>)r   r   )r   r   ry  r  c                    s
   |   S rM   rQ  r  r  r'   r(   r1    r+   r  r  N)	r   r   r   r   rT   r!   r   r   r]  )	r>   Zlines_rer  r$   r  r   r_  r`  r=   r'   )r  r   r(   r    s.    






r  c                 C   sb   d}z| j  }| j }W n  ty8   t| j  }Y n0 t|}|| t|}|| |S )a  
    Git patches can emit:
    - rename a to b
    - change b
    - copy a to c
    - change c

    We cannot apply this sequence as-is, the renamed 'a' could not be
    found for it would have been renamed already. And we cannot copy
    from 'b' instead because 'b' would have been changed already. So
    we scan the git patch for copy and rename commands so we can
    perform the copies ahead of time.
    r   )	r>   tellr   r,   r   r   r   r   r<   )r   	firstliner  r>   Zgitlrr   r'   r'   r(   scangitpatch  s    



r  c                 c   s  d}d}d}d}d }}d}d}d}	t | }
t|
jdD ]z}||kr|	sV|dst|	durh|dst|drd}|r|d	 ||r| }|drt|
|j}n(|	du r|drd
}	t||d |
|	}|d7 }|rd}d||||r|	 pdffV  d|fV  n|drt
|d}|s6q8|du rft|
|}ddd |D fV  |  d|d }d|d }|r|d	 ||s| }dd|j d|j d|	 ffV  q|sttd|dd  d
}n|dr2|
 }|ds|
| q8d
}d}	t|}t|}nn|dr|
 }|ds^|
| q8|
 }|
| |ds|
| q8d
}d
}	t|}t|}|r8d}d
}|}d}q8|r| }dd|j d|j d|	 ffV  qdS )aD  Read a patch and yield the following events:
    - ("file", afile, bfile, firsthunk): select a new target file.
    - ("hunk", hunk): a new hunk is ready to be applied, follows a
    "file" event.
    - ("git", gitchanges): current diff is in git format, gitchanges
    maps filenames to gitpatch records. Unique event.
    r+   Nr   Fr      @s   ***************r   r)  Tr  r  r   r      gitc                 S   s   g | ]}|j d v r| qS ))r   r   )r   r   )rv   r?   r'   r'   r(   rV  #  s   ziterhunks.<locals>.<listcomp>r   r   r    s'   failed to synchronize metadata for "%s"r~      +++s   ***)r   r   rT   r!   r   r   rC  r   r7  r   r   r   r   r  rj  r   r   r   r   r  )r>   r   r   r  ZhunknumZemitfiler  r   ZBFILEr  r   r.  r   rw   r=   l2l3r'   r'   r(   	iterhunks  s    









r  c           
      C   s  dd }d}|| }| |d } || }| |d } d}|t | k rt| ||d  }|d7 }|d@ rd}d}|d@ rt| ||d  }|d7 }|d@ r|t| ||d  d	> O }|d7 }|d
@ r|t| ||d  d> O }|d7 }|d	@ r|t| ||d  d> O }|d7 }|d@ rDt| ||d  }|d7 }|d@ rr|t| ||d  d	> O }|d7 }|d@ r|t| ||d  d> O }|d7 }|dkrd}|| }	||||	 7 }q8|dkr|| }	|| ||	 7 }||7 }q8ttdq8|S )z_Apply a binary delta hunk
    The algorithm used is the algorithm from git's patch-delta.c
    c                 S   s4   d}t | D ] }|d7 }t|d@ s|  S q|S )Nr   r      )r   r   r  )binchunkr  r9   r'   r'   r(   	deltahead`  s    
z applybindelta.<locals>.deltaheadr+   Nr   r   r  r    r   r            r   i   s   unexpected delta opcode 0)r#   r  r   r   )
r  r   r  outr,  r  cmdr"  r  Z
offset_endr'   r'   r(   r  [  sX    







r  r+   r  c              
   C   s   t | |t|||||dS )aN  Reads a patch from fp and tries to apply it.

    Returns 0 for a clean patch, -1 if any rejects were found and 1 if
    there was any fuzz.

    If 'eolmode' is 'strict', the patch content and patched file are
    read in binary mode. Otherwise, line endings are ignored when
    patching then normalized according to 'eolmode'.
    r1   re   r  )
_applydiffr  )rm   r>   r  r  r1   re   r  r'   r'   r(   	applydiff  s    
r  c                 C   s,   |r(t | j|  |}|dkr(|d7 }|S )Nr+   r  )r   Z	canonpathr   getcwd)r   re   r'   r'   r(   _canonprefix  s
    r  c                    s  t |j   fdd}d}	d}
d }t|D ]<\}}|dkr^|sFq.||}|dkr\d}
q.|dkr|r||	| 7 }	d }|\}}}}|r||j|_|jr||j|_nt|||| }|jdkr|	|j |s|jdkr|	|j q.d	\}}|jd
v r:|
|jd d \}}|d u r:ttd|j |jrX|j}|jdkrXd}|sb|r.|jdv r||jrttd|j ||j|||j q.z|| ||||d}W nR ty } z8| t|d  d }|	d7 }	W Y d }~q.W Y d }~n
d }~0 0 q.|dkrZ|D ]8}||j}|
|\}}|d u rFn|||| qq.ttd| q.|r|	| 7 }	|	rdS |
S )Nc                    s   t | d  d S )Nr   )r  )r  re   r1   r'   r(   pstrip  s    z_applydiff.<locals>.pstripr   r  r   r  r   r   r   )r   r   r    s   source file '%s' does not existr   r+   )r   r   r   s,   cannot create %s: destination already exists)r  rs   r     unsupported parser state: %sr)  )r  r   r  rO  rk   r   r   r  r   rl   r   r   r   r   r   r   r   r   r  r   r  )rm   r>   patcherr  r  r1   re   r  r  ZrejectserrZcurrent_filer  valuesr  r   r   
first_hunkr   r   r   instr   r'   r  r(   r    s    





$


r  c                 C   s  d}g }|j }	|	r&|dt|	  d|d||t|f }
| d|
  t|
d}zt|D ]}|	 }| 
|d  |drt|}d}|| qh|d	d
krd}|s| |d  d}| |d  qh|dd
kr| |d  qh|dd
krh|s"| |d  d}| |d  qhW |r`t||| n|r^t||| 0 | }|rttdt| |S )ztuse <patcher> to apply <patchname> to the working directory.
    returns whether patch was applied with fuzz factor.Fs   -d %ss   %s %s -p%d < %sr   s   Using external patch tool: %s
   rbrs   s   patching file s	   with fuzzr   Ts   saving rejects to files   FAILEDs   patch command failed: %s)r   r2   r   Z
shellquoter-   r   popenr   r  r   r+  r!   Zparsepatchoutputr   r   r   r   r   rk   r   r   Zexplainexit)rm   r   r  	patchnamer1   r  r   r  argscwdr  r>   r$   ZpfZprinted_filecoder'   r'   r(   _externalpatch	  sX    

r  c           
   
   C   s   |d u rt  }|d u r"| dd}| tvr@ttd| | }t }zt|d}W n t	yr   |}Y n0 z@t
| ||||||d}	W ||kr|  ||  |  n(||kr|  ||  |  0 |	dk rttd|	dkS )Nr:  s   eols!   unsupported line endings type: %sr  r  r   s   patch failed to apply)r   configra   eolmodesr   r  r   r  r	   	TypeErrorr  rk   updater   )
rm   r  patchobjr1   re   r  r  r  r>   r  r'   r'   r(   patchbackendD	  s6    


r
  c           	      C   s    t | ||}t| ||||||S )zwuse builtin patch to apply <patchobj> to the working directory.
    returns whether patch was applied with fuzz factor.)r   r
  )	rm   r   r	  r1   re   r  r  r   r  r'   r'   r(   internalpatchb	  s    r  c	           
      C   s"   t | |||}	t| |	|||||S rM   )r
  r
  )
rm   r   r  r  r	  r1   re   r  r  r  r'   r'   r(   	patchrepor	  s    r  c           	   	   C   sH   |  dd}|du rt }|r2t| ||||||S t| |||||||S )a  Apply <patchname> to the working directory.

    'eolmode' specifies how end of lines should be handled. It can be:
    - 'strict': inputs are read in binary mode, EOLs are preserved
    - 'crlf': EOLs are ignored when patching and reset to CRLF
    - 'lf': EOLs are ignored when patching and reset to LF
    - None: get it from user settings, default to 'strict'
    'eolmode' is ignored when using an external patcher program.

    Returns whether patch was applied with fuzz factor.
    s   uir:  N)r  r   r  r  )	rm   r   r   r1   re   r  r  r   r  r'   r'   r(   patchy	  s    r  c              	   C   s  t | |j}t||}t|d}t }t|D ]\}}	|dkr|	\}
}}}|rt|j|d |d |_|jrt|j|d |d |_nt	||
||||}|
|j |jdkr|
|j q0|dvr0ttd| q0|W  d    S 1  s0    Y  d S )Nr  r  r   r   )r  r  r  )r   r   r  r	   r   r  r  r   r   r  r   r   r   r  r   )rm   r   Z	patchpathr1   re   r  r>   r   r  r  r   r   r  r   r'   r'   r(   changedfiles	  s0    

r  c                   @   s   e Zd ZdS )GitDiffRequiredN)rX   rY   rZ   r'   r'   r'   r(   r  	  s   r  c                 c   s   |s|s| j  }| | }| | }t| |||||||||	d
D ]p\}}}}|
durl|dusbJ d|
||}ddd |D }|r|st|dkrd|d V  |r>|V  q>dS )	a  yields diff of changes to files between two nodes, or node and
    working directory.

    if node1 is None, use first dirstate parent instead.
    if node2 is None, compare node1 with working directory.

    losedatafn(**kwarg) is a callable run when opts.upgrade=True and
    every time some change cannot be represented with the current
    patch format. Return False to upgrade to git patch format, True to
    accept the loss or raise an exception to abort the diff. It is
    called with the name of current file being diffed as 'fn'. If set
    to None, patches will always be upgraded to git format when
    necessary.

    prefix is a filename prefix that is prepended to all filenames on
    display (used for subrepos).

    relroot, if not empty, must be normalized with a trailing /. Any match
    patterns that fall outside it will be ignored.

    copy, if not empty, should contain mappings {dst@y: src@x} of copy
    information.

    if copysourcematch is not None, then copy sources will be filtered by this
    matcher

    hunksfilterfn, if not None, should be a function taking a filectx and
    hunks generator that may yield filtered hunks.
    )	ctx1ctx2r   changesopts
losedatafnpathfnr   copysourcematchNs-   fctx2 unexpectly None in diff hunks filteringr+   c                 s   s   | ]\}}d  |V  qdS )r+   Nr-   )rv   ZhrangeZhlinesr'   r'   r(   rx   
  r+   zdiff.<locals>.<genexpr>r   rs   )r   Zp1	diffhunksr-   r#   )r   Znode1Znode2r   r  r  r  r  r   r  Zhunksfilterfnr  r  fctx1fctx2r  r'  r  r'   r'   r(   diff	  s6    *

r  c
              
      sN  |du rt j}dd }
|
 |s.j|d}t|trL|dd \ 
n|j|j|j   
sr sr
srg S jj	rt
ntfdd  fD du ri |js|jrtj|drfdd	tD t}t }t
}D ]$}|vr|| || q
D ]}|vr,|| q,t|t| t|
t D ]\}}|vrl|= qltt||B |B } |f |fg}t|  	
f
d
d}|jr@|js@z$fdd}t||jdd|W S  ty<   ||jddd Y S 0 n
||dS dS )zYield diff of changes to files in the form of (`header`, `hunks`) tuples
    where `header` is a list of diff headers and `hunks` is an iterable of
    (`hunkrange`, `hunklines`) tuples.

    See diff() for the meaning of parameters.
    Nc                     s   i  t   fdd} | S )Nc                    sX   |j |  | d}|  vr@t dkr2  = |  | < n
|  |  |S )N)filelog   )Zfilectxr2  r#   popleftr  r  r2   )r   r  r  cacheorderr'   r(   
getfilectx"
  s    


z4diffhunks.<locals>.lrugetfilectx.<locals>.getfilectx)collectionsdeque)r"  r'   r  r(   lrugetfilectx
  s    z diffhunks.<locals>.lrugetfilectxr  r  c                    s   g | ]}|r |qS r'   r'   )rv   node)hexfuncr'   r(   rV  C
  r+   zdiffhunks.<locals>.<listcomp>c                    s   i | ]\}} |r||qS r'   r'   )rv   r   r   )r  r'   r(   
<dictcomp>M
  s   zdiffhunks.<locals>.<dictcomp>c                    s   t 	 | |S rM   )trydiff)r  losedata)
rU  r   r  r  r"  modifiedr  r   r   revsr'   r(   difffns
  s    zdiffhunks.<locals>.difffnc                    s    r | dst d S )Nr  )r  r.  )r  r'   r(   r*  
  s    zdiffhunks.<locals>.losedataF)gitT)r   ZdefaultoptsZstatusrB  listr+  rU  r   rm   Z	debugflagr   r   r&  r/  Zupgrader
   Z
pathcopiesr   Z	iteritemsr   r  r   r   r   r   Z
matchfilesrevZprefetchfilesr   r  )r   r  r  r   r  r  r  r  r   r  r%  Zmodifiedsetaddedset
removedsetr   r   r   ZprefetchmatchZ
revmatchesr-  r*  r'   )rU  r   r  r  r  r"  r'  r  r+  r  r   r   r,  r(   r  
  sr    









r  c                 c   s   | D ]}| d}|  }|dr*d}n|dr:d}ntd| t|D ]$}|drl|dfV  qR||fV  qR||kr|t|d	 d
fV  ||kr|t|d	 dfV  qd	S )z1yield tokens for a list of lines in a single hunkr  r      diff.deletedr      diff.inserted   unexpected hunk line: %sr      diff.tabN   diff.trailingwhitespacer+   )r   r!   r   ProgrammingErrortabsplitterfindallr#   )	hunklinesr$   Z	chompline	striplinelabeltokenr'   r'   r(   diffsinglehunk
  s     



r@  c                 c   s  t  }t  }| D ]V}|dd dkr6||dd 7 }q|dd dkrX||dd 7 }qtd| q|rp|st| D ]
}|V  qxdS tt|}tt|}dd |D }d	d |D }d
|}	d
|}
g }g }tj	|	|
||d}|D ]t\\}}}}}|dk}t
d
||| D ]}|||f q"t
d
||| D ]}|||f qPqdd|fdd|ffD ] \}}}d}|D ]\}}|r||fV  d}|d}|r|dd }|dr|dd }|t|d }| }|t|d }t|D ]@}d|dd kr.d}n|r>|d }n|d }||fV  q|r|rj|dfV  |d
fV  d}qq|dS )zEyield tokens for a list of lines in a single hunk, with inline colorsr   r   r   Nr   r6  c                 S   s    g | ]}|d kr|n|d  qS rs   r'   rv   r,  r'   r'   r(   rV  
  r+   z(diffsinglehunkinline.<locals>.<listcomp>c                 S   s    g | ]}|d kr|n|d  qS rA  r'   rB  r'   r'   r(   rV  
  r+   r+   )Zlines1Zlines2   !r4  r5  TFrs   r)     r   r7  s   .changeds
   .unchangedr8  )	bytearrayr   r9  r@  wordsplitterr;  bytesr-   r   Z	allblocksr  r2   r   r#   r   r:  )r<  r>  r@  r$   r  ZalZblZalnZblnZanZbnZatokensZbtokensZblocksZa1Za2Zb1Zb2Zbtyper   r?  re   r>  tokensZnextisnewlineZisendoflineZchompZ	endoflineZ	endspacesZmaybetabZcurrentlabelr'   r'   r(   diffsinglehunkinline
  sn    






rI  c                 /   s  | dr|d jrt nt g d}dg}d}g  fdd}| |i |D ]4}|d}t|}	t|D  ]\}
}|r|drd}n|r|d	sd
}d}|s|r|drd
}|}|r|}|r|}|
d |	k r|d7 }| qp| D ]
}|V  q|	 }|D ]F\}}||r||fV  ||krJ|t|d dfV   q^q|dfV  |
d |	k rpdV  qp| D ]}|V  qxqPdS )z@yields 2-tuples of (output, label) based on the output of func()r  )
)r  s   diff.diffline)   copy   diff.extended)   renamerK  )s   oldrK  )s   newrK  )s   deletedrK  )s   indexrK  )s
   similarityrK  )r~   s   diff.file_a)r  s   diff.file_b)r  s	   diff.hunkFc                  3   s(   r$ D ]
} | V  qg d d < d S rM   r'   )r?  Z
dodiffhunkZ
hunkbufferr'   r(   consumehunkbuffer  s    z$difflabel.<locals>.consumehunkbufferrs   r  )r   r   r   r  ry  T)r   r   r   Nr8  r+   rs   r+   )
r2  ZworddiffrI  r@  r"   r#   rG  r!   r2   r   )funcr  kwZheadprefixesZtextprefixesheadrN  r/   r.   Z	linecountr  r$   difflineprefixesZbufferedliner?  r=  re   r>  r'   rM  r(   	difflabel
  s^    







rU  c                  O   s   t tg| R i |S )zBlike diff(), but yields 2-tuples of (output, label) for ui.write())rU  r  )r  rQ  r'   r'   r(   diffuiC  s    rV  c                 c   s   t  }dd | D }t |t | }}t| | | D ]}	d}
|	|	 }}|	|v rd}|	|v r|jr||	 }||v r||vrd}
|| qd}
n8|	|v rd}|jr|	|v r||	 |v r|||	  |	krq:|||
fV  q:dS )a  generates tuples (f1, f2, copyop), where f1 is the name of the file
    before and f2 is the the name after. For added files, f1 will be None,
    and for removed files, f2 will be None. copyop may be set to None, 'copy'
    or 'rename' (the latter two only if opts.git is set).c                 S   s   i | ]\}}||qS r'   r'   )rv   kru  r'   r'   r(   r(  O  r+   z_filepairs.<locals>.<dictcomp>NrL  rJ  )r   r   r   r/  r   )r+  rU  r   r   r  ZgoneZcopytor2  r3  r   copyopf1f2r'   r'   r(   
_filepairsH  s4    

r[  c                 C   s4   | sd} t | }td| }||  t| S )Nr+   s   blob %d )r#   r   Zsha1r  r   Zdigest)r  r&   r,  r'   r'   r(   	_gitindexm  s    
r\  s   120000s   100755s   100644)r  r  r+   c           $      c   s2  |	j rd }}nd}d}dd }dd }t| }t| }|sPdd	 }t|||||	D ]\}}}d
}d
}d
}d
}d
}d
}|r|||}|	js|
r||}|r|||}|	js|
r||}|	jrd}ntdd ||fD }|
rX|	jsX|sJ||v sJ|s||sJ||r(|rJ|s4|sJ|rX|rX||krX|
|pT| ||pb|}||pp|}g }|	jr`|	d||||f  |s|	dt
|   n|s|	dt
|   nt
| t
|  }} || kr|	d|  |	d|   |d
urv|	jr:t|| || d }!|	d|!  |	d||f  |	d||f  n|rv|	||| |r|	jr|	jr|	jr|	js|d
urd}|d
ur|d
ur||sd}nd}n$|d
ur| }|d
ur| }||||||f}"||||||f}#t|"|#|||	V  q`d
S )zgiven input data, generate a diff and yield it in blocks

    If generating a diff would lose data like flags or binary data and
    losedatafn is not None, it will be called.

    pathfn is applied to every path in the diff output.
    r+   r   r   c                 S   s    d dd |D }d|| f S )Nr   c                 S   s   g | ]}d | qS )s   -r %sr'   )rv   r1  r'   r'   r(   rV    r+   z-trydiff.<locals>.diffline.<locals>.<listcomp>s
   diff %s %sr  )r   r,  Zrevinfor'   r'   r(   rS    s    ztrydiff.<locals>.difflinec                 S   s   | d u p|   dkS r   )r  )r  r'   r'   r(   isempty  s    ztrydiff.<locals>.isemptyc                 S   s   | S rM   r'   )r   r'   r'   r(   r1    r+   ztrydiff.<locals>.<lambda>NFc                 s   s   | ]}|d ur|  V  qd S rM   )isbinaryr  r'   r'   r(   rx     r+   ztrydiff.<locals>.<genexpr>s   diff --git %s%s %s%ss   new file mode %ss   deleted file mode %ss   old mode %ss   new mode %sd   s   similarity index %d%%s
   %s from %ss   %s to %s    s     )Znoprefixr   Zdatestrdater[  r/  r  r  rS  r2   _gitmodeZshowsimilarityr   ZscorenobinaryindexZcmpr   diffcontent)$r   r,  r  r  r+  rU  r   r   r"  r  r  r  ZaprefixZbprefixrS  r]  date1date2rY  rZ  rX  content1content2r  r  flag1flag2r   path1path2r   Zmode1Zmode2Zsimdata1data2r'   r'   r(   r)  y  s    














r)  c              
   C   s   | \}}}}}	}
|\}}}}}}|rh|j rh|jsht|	|}|rZ|dt|	t|f  d|gff}n||j r|jdkr|}|du r|}|dt|	d|j t|d|j t| f  tj|	|
||||||d\}}|	| ||||fS )aP   diffs two versions of a file.

    data1 and data2 are tuples containg:

        * ctx: changeset for the file
        * fctx: file context for that file
        * path1: name of the file
        * flag: flags of the file
        * content: full content of the file (can be null in case of binary)
        * date: date of the changeset

    header: the patch header
    binary: whether the any of the version of file is binary or not
    opts:   user passed options

    It exists as a separate function so that extensions like extdiff can wrap
    it and use the file content directly.
    s   index %s..%sNr   s   index %s..%s %s)r   r  )
r/  rc  r   Zb85diffr2   r\  rd  rb  Zunidiffextend)rn  ro  r   r   r  r  r  rl  rj  rh  rf  r  r  rm  rk  ri  rg  r  r'  flagZuheadersr'   r'   r(   re  	  sB    	


re  c           
      C   sd   d\}}}}}| D ]B\}}}}	t |t|}t ||| }||7 }||7 }|pR|	}q|||||fS )N)r   r   r   r   F)rT  r   colwidth)
statsZmaxfilemaxtotalZaddtotalZremovetotalr   r   r>  r  r@  r'   r'   r(   diffstatsumB  s    
ru  c                    s.  t d}g d\  fdd}d}| D ]}|dr|  d}d\ |d	rtt|d
n|dr||dq6|drd}q6|dr|s d7  q6|dr|sЈd7 q6|ds|drdq6|dr|dd  q6|dr6d|dd   7 q6|  S )Ns   ^diff .*-r [a-z0-9]+\s(.*)$)Nr   r   Fc                      s   r  f d S rM   rJ   r'   addsra  r^  removesZresultsr'   r(   	addresultT  s    zdiffstatdata.<locals>.addresultFr  T)r   r   Fr   r    s   diff -rr   s   @@r   r   r   s   Binary files   rename fromr   s	   rename tos    => %sr   )r   r   r!   r   r   r   )r.   r   ry  r%   r$   r'   rv  r(   diffstatdataN  s<    








rz  P   c              
      s   g }t | }t|\}}}}tt}|r:|dk r:d}|| | d   dk rVd  fdd}	|D ]b\}
}}}|r~d}nd||  }d|	| }d	|	| }|d
|
d|t|
  ||||f  qh|r|tdt|||f  d|S )Nr  r  r   c                    s&    kr| S t |    tt| S rM   )rT  r   bool)r  Z
graphwidthrt  r'   r(   scale  s    zdiffstat.<locals>.scales   Binr  r   r   s    %s%s |  %*s %s%s
r   s5    %d files changed, %d insertions(+), %d deletions(-)
r+   )	rz  ru  r#   r  r2   r   rr  r   r-   )r.   widthoutputrs  ZmaxnameZ	totaladdsZtotalremovesZ	hasbinaryZ
countwidthr~  ra  rw  rx  r^  r  ZplusesZminusesr'   r}  r(   diffstat{  sD    r  c                  o   s   t | i | D ]}|r|d dv r|dd\}}|d dfV  td|}|rd|ddfV  td	|}|r|dd
fV  n
|dfV  dV  qdS )zOlike diffstat(), but yields 2-tuples of (output, label) for
    ui.write()
    r)  s   +-r   r   r+   s   \++r   s   diffstat.inserteds   -+s   diffstat.deletedrO  N)r  r   rsplitr   r   r   )r  rQ  r$   nameZgraphr=   r'   r'   r(   
diffstatui  s    
r  )N)N)r   r+   r  )r   r+   r  )Nr  )r+   Nr  r   )Nr  )r   r+   Nr  r   )r   r+   )
NNNNNNNNNN)NNNNNNN)r{  )iZ
__future__r   r   r#  
contextlibr   r   rh   r   r  r  Zi18nr   r&  r   r   r   r	    r
   r   r   r   r   r   r   r   r   r   r   r   r   Zutilsr   r   r   r   r,   r   r   r:  rF  r   r"   r   contextmanagerrr   rj   r_   r   r   r   r   r   r   r  r
  r  r  r  r  r   rh  r  r  r7  rC  r  r  r  r  r  r  r  r  r  r  r  r  r  r
  r  r  r  r  	Exceptionr  ZdiffalloptsZdiffoptsZdifffeatureoptsr  r  r@  rI  rU  rV  r[  r\  rb  r)  re  ru  rz  r  r  r'   r'   r'   r(   <module>	   s   <

 
q0-#4-&,

 jQnC
 7 e>@
 )=3g;
	 
_2 
#    
 
     
!
          
O       
 HP%	 9-
0