
­­­­­­­­­­­­­­­­­­
<!DOCTYPE html>
<html>
3
i=y                @   s  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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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mZmZ d dlmZmZm Z  d dl!m"Z"m#Z# d dl$m%Z% d dl&m'Z' d dl
m(Z( d d	l)m*Z* d d
l+m,Z, dZ-y&e-rTe.d dl/j0j1Z1d dl/m2Z3 W n* e.k
r   d dl1Z1d dl1m2Z3 Y nX ddl4m5Z5 e5 Z4d dl6Z7ddl8m9Z: ddl8m;Z< ddl8m=Z= ddl8m>Z> ddl8m?Z? ddl@T eAe
jBjCddjDdZEeFaGdd ZHG dd deIZJG dd deJZKG dd deKZLG d d! d!eLZMG d"d# d#eJZNG d$d% d%eJZOG d&d' d'eJZPG d(d) d)ePZQG d*d+ d+eJZRd,d- ZSG d.d/ d/eJZTd0d1 ZUd2d3 ZVed4d5ZWG d6d7 d7ejXZYG d8d9 d9ZZd:d; Z[d<d= Z\d>d? Z]g fd@dAZ^ej_ej`B ejaB dBfdCdDZbdEdF ZcdGdH Zdd*dIdJZedKdL ZfdMdN ZgdOdP ZhejifdQdRZjdSdT ZkdUdV ZldWdX ZmdYdZ Znd[d\ Zod]d^ ZpG d_d` d`Zqdadb Zri fdcddZsesZtesZuesZvdTgeweWjx Zyeyjzde dfdg Z{dBZ|e|rd.Z}e}dl Z~nd5Z~e~dl Z}dndo Zdpdq Zdrds Zd6edtdudvZedtdwdxZdydz ZG d{d| d|Zd7d}d~ZG dd deZdd Zd8ddZd9ddZd:ddZdd ZG dd dZe#ddd;ddZe#ddd<ddZe#ddd=ddZe#ddd>ddZdd Zd?ddZd@ddZdd Zdd ZG dd dZdAddZdd ZdBddZdd ZdCddZejdZdd Zdd ZG dd deZdd Zdd Zdd Zdd ZdDZdEZdFZdddddddeeeddBddedBdfddǄZddӄ ZddՄ ZG ddׄ d׃Zddل ZG ddۄ deZG dd݄ deZG dd߄ d߃Zdd Zeje4dddZG dd dZG dd deZG dd deZG dd dZdd Zdd Zdd Zdd ZdGddZdd ZdHddZdIddZG dd dejÃZG d d deŃZG dd deƃZG dd deƃZejɐdd Zʐdd	 Zːd
d ZG dd de	j̓ZdddddZϐdd ZАdd Zѐdd ZҐdd ZӐdJeԐdddZՐdKddZ֐dd Zejfd d!Zِd"d# Zd dl
Zd dlZd dlZd d$lmZmZmZmZmZ dLd&d'ZdMd(d)ZdS (N      N)hexlify)
namedtupledequeabcCounter)datetimetimezone	timedelta)partial	lru_cache)islice)
attrgetter)scandir)	Formatter)get_terminal_sizeF)fallback   )create_logger)__version__)__version_tuple__)chunker)	hashindex)shellpattern)*ZBORG_WORKAROUNDS ,c             C   s   t t| atS )z
    Sets the exit code of the program, if an exit code higher or equal than this is set, this does nothing. This
    makes EXIT_ERROR override EXIT_WARNING, etc..

    ec: exit code to set
    )max	exit_code)Zec r   /usr/lib64/python3.6/helpers.pyset_ecc   s    
r    c                   s4   e Zd ZdZeZdZ fddZdd ZeZ	  Z
S )Errorz	Error: {}Fc                s   t  j|  || _d S )N)super__init__args)selfr$   )	__class__r   r   r#   z   s    zError.__init__c             C   s   t | jj| j S )N)type__doc__formatr$   )r%   r   r   r   get_message~   s    zError.get_message)__name__
__module____qualname__r(   Z
EXIT_ERRORr   	tracebackr#   r*   __str____classcell__r   r   )r&   r   r!   o   s   r!   c               @   s   e Zd ZdZdZdS )ErrorWithTracebackz	Error: {}TN)r+   r,   r-   r(   r.   r   r   r   r   r1      s   r1   c               @   s   e Zd ZdZdS )IntegrityErrorzData integrity error: {}N)r+   r,   r-   r(   r   r   r   r   r2      s   r2   c               @   s   e Zd ZdZdS )DecompressionErrorzDecompression error: {}N)r+   r,   r-   r(   r   r   r   r   r3      s   r3   c               @   s   e Zd ZdZdS )ExtensionModuleErrorzFThe Borg binary extension modules do not seem to be properly installedN)r+   r,   r-   r(   r   r   r   r   r4      s   r4   c               @   s   e Zd ZdZdS )NoManifestErrorzRepository has no manifest.N)r+   r,   r-   r(   r   r   r   r   r5      s   r5   c               @   s   e Zd ZdZdS )PlaceholderErrorz)Formatting Error: "{}".format({}): {}({})N)r+   r,   r-   r(   r   r   r   r   r6      s   r6   c               @   s   e Zd ZdZdS )InvalidPlaceholderz&Invalid placeholder "{}" in string: {}N)r+   r,   r-   r(   r   r   r   r   r7      s   r7   c               @   s   e Zd ZdZdS )PythonLibcTooOldzXFATAL: this Python was compiled for a too old (g)libc and misses required functionality.N)r+   r,   r-   r(   r   r   r   r   r8      s   r8   c              C   s$   t jt jt jh} t jj| s td S )N)osstatutimechownsupports_follow_symlinks
issupersetr8   )Zrequired_funcsr   r   r   check_python   s    r?   c               @   s   e Zd ZdZdS )MandatoryFeatureUnsupportedzdUnsupported repository feature(s) {}. A newer version of borg is required to access this repository.N)r+   r,   r-   r(   r   r   r   r   r@      s   r@   c              C   s|   ddl m} m}m} tjdkr"ttjdkr0t|jdkr>ttj	j
jdkrPt| j| jksf| jdkrjt|jdkrxtd S )	Nr   )platformcompressitemz1.1_07z1.1_01z1.1_06z1.1_02z1.1_04z1.1_03)r   rA   rB   rC   r   ZAPI_VERSIONr4   r   borgZcryptoZ	low_levelZOS_API_VERSION)rA   rB   rC   r   r   r   check_extension_modules   s    



rE   c          	   C   s   t ddddttt td}| dkr8|jt ddd n| dkrT|jt tdd np| d	krx|jt d
dtdtdd nL| dkr|jt d
ddtd n,| dkr|jt d
dddtdd ntdt	j
f |S )zWreturn a limited Unpacker because we should not trust msgpack data received from remoteFr      )use_listZmax_bin_lenZmax_ext_lenZmax_buffer_sizemax_str_lenZserverd   )max_array_lenmax_map_lenZclientmanifestT   surrogateescape)rG   rJ   rK   rH   object_hookZunicode_errorsarchivei'  )rG   rK   rH   rO   key
   i  z4kind must be "server", "client", "manifest" or "key")dictr   ZBUFSIZEZMAX_OBJECT_SIZEupdateZLIST_SCAN_LIMITMAX_ARCHIVES
StableDict
ValueErrormsgpackZUnpacker)Zkindr$   r   r   r   get_limited_unpacker   s@    rY   ArchiveInfoz
name id tsc               @   sp   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f ddddddZ
dd Zdd Zdd ZdS )Archivesz
    Nice wrapper around the archives dict, making sure only valid types/values get in
    and we can deal with str keys (and it internally encodes to byte keys) and either
    str timestamps or datetime timestamps.
    c             C   s
   i | _ d S )N)	_archives)r%   r   r   r   r#      s    zArchives.__init__c             C   s
   t | jS )N)lenr\   )r%   r   r   r   __len__   s    zArchives.__len__c             C   s   t dd | jD S )Nc             s   s   | ]}t |V  qd S )N)safe_decode).0namer   r   r   	<genexpr>   s    z$Archives.__iter__.<locals>.<genexpr>)iterr\   )r%   r   r   r   __iter__   s    zArchives.__iter__c             C   sR   t |tstt|}| jj|}|d kr.tt|d jd}t	||d |dS )Ns   timezutf-8s   id)ra   idts)

isinstancestrAssertionErrorsafe_encoder\   getKeyErrorparse_timestampdecoderZ   )r%   ra   _namevaluesrf   r   r   r   __getitem__   s    zArchives.__getitem__c             C   s   t |tstt|}t |ts$t|\}}t |ts:tt |trV|jd djt	}t |tsdt|j
 }||d| j|< d S )N)tzinfo)s   ids   time)rg   rh   ri   rj   tuplebytesr   replacestrftime
ISO_FORMATencoder\   )r%   ra   infore   rf   r   r   r   __setitem__  s    
zArchives.__setitem__c             C   s"   t |tstt|}| j|= d S )N)rg   rh   ri   rj   r\   )r%   ra   r   r   r   __delitem__  s    zArchives.__delitem__Nz\ZF)glob	match_endsort_byfirstlastreversec      	         s   t |ttfrtdtjtj|p$d|d  fdd| j D }x t	|D ]}|j
t|d qNW |rx|d| }n|r|tt|| dd }|r|j  |S )	aH  
        Return list of ArchiveInfo instances according to the parameters.

        First match *glob* (considering *match_end*), then *sort_by*.
        Apply *first* and *last* filters, and then possibly *reverse* the list.

        *sort_by* is a list of sort keys applied in reverse order.

        Note: for better robustness, all filtering / limiting parameters must default to
              "not limit / not filter", so a FULL archive list is produced by a simple .list().
              some callers EXPECT to iterate over all archives in a repo for correct operation.
        z!sort_by must be a sequence of strr   )r}   c                s    g | ]} j |jd k	r|qS )N)matchra   )r`   x)regexr   r   
<listcomp>(  s    z!Archives.list.<locals>.<listcomp>)rQ   Nr   )rg   rh   rt   	TypeErrorrecompiler   	translaterp   reversedsortr   r   r]   r   )	r%   r|   r}   r~   r   r   r   archivesZsortkeyr   )r   r   list  s    zArchives.listc             C   sF   |j jrtd|jdk	r&|jd |_| j|jjd|j|j|j	dS )zi
        get a list of archives, considering --first/last/prefix/glob-archives/sort cmdline args
        zaThe options --first, --last, --prefix and --glob-archives can only be used on repository targets.Nr   r   )r~   r|   r   r   )
locationrP   r!   prefixZglob_archivesr   r~   splitr   r   )r%   r$   r   r   r   list_considering3  s
    
zArchives.list_consideringc             C   sP   xJ|j  D ]>\}}t|ts tt|tr:d|kr:d|ks>t|| j|< q
W dS )z-set the dict we get from the msgpack unpackers   ids   timeN)itemsrg   rt   ri   rS   r\   )r%   dkvr   r   r   set_raw_dict=  s    zArchives.set_raw_dictc             C   s   | j S )z.get the dict we can give to the msgpack packer)r\   )r%   r   r   r   get_raw_dictD  s    zArchives.get_raw_dict)r+   r,   r-   r(   r#   r^   rd   rq   rz   r{   r   r   r   r   r   r   r   r   r[      s   	
r[   c               @   s   e Zd ZejG dd dejZe Ze	g Z
dd ZdddZedd	 Zed
d ZedddZdd Zdd Zdd ZdS )Manifestc               @   s   e Zd ZdZdZdZdZdS )zManifest.OperationreadZcheckwritedeleteN)r+   r,   r-   ZREADZCHECKZWRITEZDELETEr   r   r   r   	OperationK  s   
r           Nc             C   s@   t  | _i | _|| _|| _|d k	r*t|nt| _d| _d | _	d S )NF)
r[   r   configrQ   
repository	frozenset	ITEM_KEYS	item_keystam_verified	timestamp)r%   rQ   r   r   r   r   r   r#   i  s    zManifest.__init__c             C   s
   t | jS )N)
bin_to_hexre   )r%   r   r   r   id_strr  s    zManifest.id_strc             C   s   t | jd dS )N)rr   )rm   r   )r%   r   r   r   last_timestampv  s    zManifest.last_timestampFc             C   s  ddl m} ddlm}m}m} ddlm}	 y|j| j	}
W n |	j
k
rV   tY nX |sf|||
}| ||}|jd |
}|j||d\}|_||d}|j||_|jddkrtd	|jj|j |jd
|_|j|_ttdd |jdg D B |_|jrp|jjdd}||}|rJ| rJtjd ||}t|dj  | rp|rptjd tj|| |j| ||fS )Nr   )ManifestItem)key_factorytam_required_filetam_required)
Repository)force_tam_not_required)Zinternal_dictversion   zInvalid manifest versionr   c             s   s   | ]}|j  V  qd S )N)rn   )r`   rQ   r   r   r   rb     s    z Manifest.load.<locals>.<genexpr>r   s   tam_requiredFzPManifest is TAM verified and says TAM is required, updating security database...wzVManifest is TAM verified and says TAM is *not* required, updating security database...)r   r   ) rC   r   Z
crypto.keyr   r   r   r   r   rk   MANIFEST_IDZObjectNotFoundr5   ZdecryptZunpack_and_verify_manifestr   id_hashre   rW   r   r   r   r   r   r   r   loggerdebugopencloser9   unlinkcheck_repository_compatibility)clsr   
operationsrQ   r   r   r   r   r   r   ZcdatarL   dataZmanifest_dictmZmanifest_requiredZsecurity_requiredfiler   r   r   loadz  s@    



 


zManifest.loadc             C   s   x|D ]|}t || jst| jjdd }|d kr4d S |jj |krDq||jj  }d|krt|d | j }|rt	dd |D qW d S )Ns   feature_flagss	   mandatoryc             S   s   g | ]}|j  qS r   )rn   )r`   fr   r   r   r     s    z;Manifest.check_repository_compatibility.<locals>.<listcomp>)
rg   r   ri   r   rk   valuerx   setSUPPORTED_REPO_FEATURESr@   )r%   r   	operationfeature_flagsrequirementsZunsupportedr   r   r   r     s    
z'Manifest.check_repository_compatibilityc             C   s^   i }| j jdd }|d kr|S x:|j D ].\}}d|kr(tdd |d D ||j < q(W |S )Ns   feature_flagss	   mandatoryc             S   s   g | ]}|j  qS r   )rn   )r`   Zfeaturer   r   r   r     s    z7Manifest.get_all_mandatory_features.<locals>.<listcomp>)r   rk   r   r   rn   )r%   resultr   r   r   r   r   r   get_all_mandatory_features  s    "z#Manifest.get_all_mandatory_featuresc             C   s  ddl m} | jjrd| jd< | jd kr:tj jt	| _n0| j
}|tdd jt	}t|tj jt	| _t| jtks|ttdd | jD stt| jdkst|dt| jj | jt| jtt| jd	}d| _| jj|j }| jj|| _| jj| j| jj| d S )
Nr   )r   Ts   tam_required)Zmicrosecondsc             s   s   | ]}t |d kV  qdS )rM   N)r]   )r`   ra   r   r   r   rb     s    z!Manifest.write.<locals>.<genexpr>rI   )r   r   r   r   r   ) rC   r   rQ   r   r   r   r   utcnowrv   rw   r   r	   r   r]   r   rU   ri   allr   rV   r   rs   sortedr   Zpack_and_authenticate_metadataZas_dictr   re   r   Zputr   Zencrypt)r%   r   Zprev_tsZincrementedrL   r   r   r   r   r     s*    

zManifest.write)N)NF)r+   r,   r-   enumuniqueEnumr   rs   ZNO_OPERATION_CHECKr   r   r   r#   propertyr   r   classmethodr   r   r   r   r   r   r   r   r   I  s   

	$r   c             C   s"   t | }|dkrtjd|  |S )z#argparse type for positive integersr   z"A positive integer is required: %s)intargparseArgumentTypeError)r   Z	int_valuer   r   r   positive_int_validator  s    r   c             C   s   dddddd}| j t|j r8| dd }| d }n4dd	 t|j d
d dD }tjd| d |f yt|||  }W n tk
r   d}Y nX |dkrtjd| |S )zDConvert a string representing a valid interval to a number of hours.r            im  )Hr   r   r   yNc             S   s   g | ]\}}|qS r   r   )r`   r   r   r   r   r   r     s    zinterval.<locals>.<listcomp>c             S   s   | d S )Nr   r   )tr   r   r   <lambda>  s    zinterval.<locals>.<lambda>)rQ   z6Unexpected interval time unit "%s": expected one of %rr   zCUnexpected interval number "%s": expected an integer greater than 0   i  i8"  r   r   r   )	endswithrs   keysr   r   r   r   r   rW   )sZ
multiplierZnumbersuffixZrangeshoursr   r   r   interval  s    


r   c                s,   t jtjt|d d   fdd| D S )Ni  )Zsecondsc                s   g | ]}|j  kr|qS r   )rf   )r`   a)targetr   r   r     s    z prune_within.<locals>.<listcomp>)r   nowr   utcr	   )r   r   r   )r   r   prune_within  s    r   c             C   sp   d }g }|dkr|S xVt | tdddD ]@}t|jj|}||kr(|}||kr(|j| t||kr(P q(W |S )Nr   rf   T)rQ   r   )r   r   to_localtimerf   rv   appendr]   )r   patternnskipr   Zkeepr   Zperiodr   r   r   prune_split  s    
r   Tc             C   sP   yt j| |dd W n6 tk
rJ } z|r8tt|n W Y dd}~X nX dS )a  
    Ensures that the dir exists with the right permissions.
    1) Make sure the directory exists in a race-free operation
    2) If mode is not None and the directory has been created, give the right
    permissions to the leaf directory. The current umask value is masked out first.
    3) If pretty_deadly is True, catch exceptions, reraise them with a pretty
    message.
    Returns if the directory has been created and has the right permissions,
    An exception otherwise. If a deadly exception happened it is reraised.
    T)modeexist_okN)r9   makedirsOSErrorr!   rh   )pathr   Zpretty_deadlyer   r   r   
ensure_dir
  s    r   c              C   s:   t jjdpt jjd} | s6t jjdt jjdd } | S )zGet home directory / base directory for borg:

    - BORG_BASE_DIR, if set
    - HOME, if set
    - ~$USER, if USER is set
    - ~
    BORG_BASE_DIRHOMEz~%sZUSERr   )r9   environrk   r   
expanduser)Zbase_dirr   r   r   get_base_dir  s    r   c              C   s0   t jjd} | dkr$t jjt d} t|  | S )z,Determine where to repository keys and cacheZBORG_KEYS_DIRNr   )r9   r   rk   r   joinget_config_dirr   )Zkeys_dirr   r   r   get_keys_dir0  s
    r   c             C   sB   t jjd}|dkr$t jjt d}| r6t jj|| }t| |S )z4Determine where to store local security information.ZBORG_SECURITY_DIRNZsecurity)r9   r   rk   r   r   r   r   )Zrepository_idZsecurity_dirr   r   r   get_security_dir:  s    r   c           	   C   s   t jjt d} t jjds*t jjd| } t jjdt jj| d}t| t jj|t}t jj|st	t
jdjd }dd	lm} ||d
d}|j| W dQ R X |S )z,Determine where to repository keys and cachez.cacher   ZXDG_CACHE_HOMEZBORG_CACHE_DIRrD   z
        # This file is a cache directory tag created by Borg.
        # For information about cache directory tags, see:
        #       http://www.bford.info/cachedir/spec.html
        asciir   )SaveFileT)binaryN)r9   r   r   r   r   rk   r   CACHE_TAG_NAMEexistsCACHE_TAG_CONTENTStextwrapdedentrx   rA   r   r   )Z
cache_home	cache_dirZcache_tag_fnZcache_tag_contentsr   fdr   r   r   get_cache_dirF  s    r	  c              C   sN   t jjt d} t jjds*t jjd| } t jjdt jj| d}t| |S )z%Determine where to store whole configz.configr   ZXDG_CONFIG_HOMEZBORG_CONFIG_DIRrD   )r9   r   r   r   r   rk   r   )Zconfig_homeZ
config_dirr   r   r   r   ^  s    r   c          	   C   s,   t tj| t dddtjd j dd  S )z3Convert datetime object from UTC to local time zonei  r   )rr   N   )r   timeZ	localtimer   r   total_seconds)rf   r   r   r   r   l  s    r   c             C   s4   d| krt nt}tj| |}|dk	r0|j|d}|S )z!Parse a ISO 8601 timestamp string.N)rr   )rw   ISO_FORMAT_NO_USECSr   strptimeru   )r   rr   Zfmtdtr   r   r   rm   q  s
    rm   c             C   sz   y t tj| j}tj|tjdS  tk
rt   x:dD ]2}ytj	| |j
tjd
S  tk
rf   w6Y q6X q6W tY nX dS )z5Convert a --timestamp=s argument to a datetime object)Ztz%Y-%m-%dT%H:%M:%SZ%Y-%m-%dT%H:%M:%S+00:00%Y-%m-%dT%H:%M:%S%Y-%m-%d %H:%M:%S%Y-%m-%dT%H:%M%Y-%m-%d %H:%M%Y-%m-%d%Y-%j)rr   N)r  r  r  r  r  r  r  r  )safe_sr9   r:   st_mtimer   fromtimestampr   r   r   r  ru   rW   )r   rf   r)   r   r   r   r   z  s      r   c             C   sV   | j  j dkrtS | jd\}}}}t|dkr:tdt|t|t|t|fS )Ndefaultr      zOmax. chunk size exponent must not be more than 23 (2^23 = 8MiB max. chunk size))striplowerZCHUNKER_PARAMSr   r   rW   )r   Z	chunk_minZ	chunk_maxZ
chunk_maskZwindow_sizer   r   r   ChunkerParams  s    r   c                s   t ddddddd d}t| j jd}|t ksLtddjt   fdd|D }djt|}||krtddj| |S )Ncr   r   irr   )ctimemtimesizeinodeZrechunkZdisabledcisimscsmscrmrr   z0cache mode must be a comma-separated list of: %sc                s   h | ]} | qS r   r   )r`   entry)ENTRIES_MAPr   r   	<setcomp>  s    z!FilesCacheMode.<locals>.<setcomp>r   z#cache mode short must be one of: %s)r(  r)  r*  r+  r,  r-  r   r   )rS   r   r  r   rW   r   r   )r   ZVALID_MODESentriesZshort_entriesr   r   )r/  r   FilesCacheMode  s    r2  c             C   sh   t jj| t}y@t jj|rLt|d }|jtt}|tkrBdS W dQ R X W n t	k
rb   Y nX dS )zDetermines whether the specified path is a cache directory (and
    therefore should potentially be excluded from the backup) according to
    the CACHEDIR.TAG protocol
    (http://www.bford.info/cachedir/spec.html).
    rbTNF)
r9   r   r   r  r  r   r   r]   r  r   )r   tag_pathZtag_fileZtag_datar   r   r   dir_is_cachedir  s    r5  c             C   sb   g }|r$t | r$|jtjj| t |dk	r^x0|D ](}tjj| |}tjj|r2|j| q2W |S )a  Determines whether the specified path is excluded by being a cache
    directory or containing user-specified tag files/directories. Returns a
    list of the paths of the tag files/directories (either CACHEDIR.TAG or the
    matching user-specified files/directories).
    N)r5  r   r9   r   r   r  r  )r   Zexclude_cachesZexclude_if_presentZ	tag_pathstagr4  r   r   r   dir_is_tagged  s    
r7  c                sB   x< j  D ]0\}}tj|}tjd||f  fdd| } q
W | S )z
    Apply format.format_map(mapping) while preserving unknown keys

    Does not support attribute access, indexing and ![rsa] conversions
    z!(?<!\{)((\{%s\})|(\{%s:[^\}]*\}))c                s   | j dj S )Nr   )group
format_map)r   )mappingr   r   r     s    z partial_format.<locals>.<lambda>)r   r   escapesub)r)   r:  rQ   r   r   )r:  r   partial_format  s    


r=  c               @   s   e Zd Zdd Zdd ZdS )DatetimeWrapperc             C   s
   || _ d S )N)r  )r%   r  r   r   r   r#     s    zDatetimeWrapper.__init__c             C   s   |dkrt }| jj|S )Nr   )r  r  
__format__)r%   format_specr   r   r   r?    s    zDatetimeWrapper.__format__N)r+   r,   r-   r#   r?  r   r   r   r   r>    s   r>  c             C   s   x8t  j| D ](\}}}}|s q|s,||krt|| qW y
| j|S  tk
r| } zt| ||jjt|W Y d d }~X nX d S )N)	r   parser7   r9  	Exceptionr6   r&   r+   rh   )r)   r   _rQ   Z
conversionr   r   r   r   format_line  s    
rD  c             C   s   ddl m}m} tjtj}tj |dj	t
|jd|t|jdt|ttj tj ttj tdtdd  dtdd  dtdd	  d
|}t| |S )z/Replace placeholders in text with their values.r   )fqdnhostnamer  Nz%dz%d.%dr   z%d.%d.%drF   )pidrE  zreverse-fqdnrF  r   r   useruuid4ZborgversionZ	borgmajorZ	borgminorZ	borgpatch)rA   rE  rF  r   r   r   r   r9   getpidr   r   r   r>  
astimezoneuid2usergetuidrh   uuidrI  borg_versionborg_version_tuplerD  )text	overridesrE  rF  Zcurrent_timer   r   r   r   replace_placeholders  s     
rS  rf   c             C   s4   x&| j dD ]}|tkrtd| qW | jddS )Nr   zInvalid sort key: %sr   rf   )r   HUMAN_SORT_KEYSrW   ru   )rQ  tokenr   r   r   
SortBySpec  s    rV  r   r   0   i  i ʚ;?   c             C   s0   d|   kot kn  r| S | dk r(dS t S d S )Nr   )MAX_S)rf   r   r   r   r  .  s
    r  c             C   s0   d|   kot kn  r| S | dk r(dS t S d S )Nr   )MAX_NS)rf   r   r   r   safe_ns7  s
    r[  c             C   s   t | }tj|d S )Ng    eA)r[  r   r  )Zitem_timestamp_nsZt_nsr   r   r   safe_timestamp@  s    r\  )rf   c             C   s   | j |dkrdn|S )zG
    Convert *ts* to a human-friendly format with textual weekday.
    r   z%a, %Y-%m-%d %H:%M:%S)rv   )rf   r@  r   r   r   format_timeE  s    r]  c             C   s
   | j tS )z,
    Format *ts* according to ISO 8601.
    )rv   rw   )rf   r   r   r   isoformat_timeL  s    r^  c             C   sp   | j  }|d }t|d d }t|d d }d| }|rHd||f }|rXd||f }| jrld| j|f }|S )z0Format timedelta in a human friendly format
    <   i  r   z%.2f secondsz%d minutes %sz%d hours %sz
%d days %s)r  r   Zdays)Ztdrf   r   r   hZtxtr   r   r   format_timedeltaT  s    ra  c               @   s6   e Zd ZedddZdd Zdd Zdd	 ZeZd
S )OutputTimestamp)rf   c             C   s   |j tjkrt|}|| _d S )N)rr   r   r   r   rf   )r%   rf   r   r   r   r#   f  s    zOutputTimestamp.__init__c             C   s   t | j|dS )N)r@  )r]  rf   )r%   r@  r   r   r   r?  k  s    zOutputTimestamp.__format__c             C   s
   dj | S )Nz{})r)   )r%   r   r   r   r/   n  s    zOutputTimestamp.__str__c             C   s
   t | jS )N)r^  rf   )r%   r   r   r   	isoformatq  s    zOutputTimestamp.isoformatN)	r+   r,   r-   r   r#   r?  r/   rc  to_jsonr   r   r   r   rb  e  s
   rb  c             C   s   t | dd||dS )z2Format file size into a human friendly format
    B )r   sep	precisionsign)sizeof_fmt_decimal)r   rh  ri  r   r   r   format_file_sizew  s    rk  c               @   s   e Zd Zdd ZdS )FileSizec             C   s   t t| j|S )N)rk  r   r?  )r%   r@  r   r   r   r?  ~  s    zFileSize.__format__N)r+   r,   r-   r?  r   r   r   r   rl  }  s   rl  c             C   sv   | st | S | d	 }d}y4||d |d |d |d d| }| dd
 } W n tk
rd   d}Y nX t t| | S )z,Return int from file size (1234, 55G, 1.7T).r   i  r   rF         )KMGTPNr   r   )r   rl   float)r   r   powerZfactorr   r   r   parse_file_size  s    

rv  re  c       	      C   s   |r| dkrdnd}xb|d d D ]R}t t| ||k rht| trTdj|| |||S dj|| ||||S | t| } q"W dj|| |||d	 |S )
Nr   +r   r   z
{}{}{}{}{}z{}{:3.{}f}{}{}{}z{}{:.{}f}{}{}{}r   r   )absroundrg   r   r)   rt  )	numr   unitsru  rg  rh  ri  r   Zunitr   r   r   
sizeof_fmt  s    
r|  c             C   s(   t | ||||ddddddddd	g	d
dS )Nr   ZKiZMiZGiZTiZPiZEiZZiZYii   )r   rg  rh  ri  r{  ru  )r|  )rz  r   rg  rh  ri  r   r   r   sizeof_fmt_iec  s    r}  c             C   s(   t | ||||ddddddddd	g	d
dS )Nr   r   rp  rq  rr  rs  EZYi  )r   rg  rh  ri  r{  ru  )r|  )rz  r   rg  rh  ri  r   r   r   rj    s    rj  c             C   s    d| j tt| jt| jf S )Nz%-36s %s [%s])ra   r]  r   rf   r   re   )rP   r   r   r   format_archive  s    r  c               @   sH   e Zd ZdZG dd deeZdddZdd	 ZdddZ	dddZ
dS )Bufferz5
    managed buffer (like a resizable bytearray)
    c               @   s   e Zd ZdZdS )zBuffer.MemoryLimitExceededz2Requested buffer size {} is above the limit of {}.N)r+   r,   r-   r(   r   r   r   r   MemoryLimitExceeded  s   r     Nc             C   sF   t |std|dks(||ks(td|| _|| _| j|dd dS )z
        Initialize the buffer: use allocator(size) call to allocate a buffer.
        Optionally, set the upper <limit> for the buffer size.
        z-must give alloc(size) function as first paramNzinitial size must be <= limitT)init)callableri   	allocatorlimitresize)r%   r  r&  r  r   r   r   r#     s
    zBuffer.__init__c             C   s
   t | jS )N)r]   buffer)r%   r   r   r   r^     s    zBuffer.__len__Fc             C   sJ   t |}| jdk	r*|| jkr*tj|| j|s:t| |k rF| j|| _dS )a$  
        resize the buffer - to avoid frequent reallocation, we usually always grow (if needed).
        giving init=True it is possible to first-time initialize or shrink the buffer.
        if a buffer size beyond the limit is requested, raise Buffer.MemoryLimitExceeded (OSError).
        N)r   r  r  r  r]   r  r  )r%   r&  r  r   r   r   r    s
    zBuffer.resizec             C   s   |dk	r| j || | jS )z
        return a buffer of at least the requested size (None: any current size).
        init=True can be given to trigger shrinking of the buffer to the given size.
        N)r  r  )r%   r&  r  r   r   r   rk     s    z
Buffer.get)r  N)F)NF)r+   r,   r-   r(   r!   r   r  r#   r^   r  rk   r   r   r   r   r    s   

r  )maxsizec             C   s&   yt j| jS  tk
r    |S X d S )N)pwdgetpwuidZpw_namerl   )uidr  r   r   r   rL    s    rL  c             C   s*   y| ot j| jS  tk
r$   |S X d S )N)r  getpwnamZpw_uidrl   )rH  r  r   r   r   user2uid  s    r  c             C   s&   yt j| jS  tk
r    |S X d S )N)grpZgetgrgidZgr_namerl   )gidr  r   r   r   	gid2group  s    r  c             C   s*   y| ot j| jS  tk
r$   |S X d S )N)r  ZgetgrnamZgr_gidrl   )r8  r  r   r   r   	group2gid  s    r  c             C   sr   g }x^t | jdD ]L}|r|jd}t|dkrV|jdj|d |d |d g q|j| qW tdj|S )z9Replace the user/group field with the stored uid/gid
    
:rm  r   rF   r   )r_   r   r]   r   r   rj   )Zaclr1  r.  Zfieldsr   r   r   posix_acl_use_stored_uid_gid  s    
$r  utf-8rN   c             C   s   | dkrdS | j ||S )z8decode bytes to str, with round-tripping "invalid" bytesN)rn   )r   codingerrorsr   r   r   r_     s    r_   c             C   s   | dkrdS | j ||S )z8encode str to bytes, with round-tripping "invalid" bytesN)rx   )r   r  r  r   r   r   rj     s    rj   c             C   s   t | jdS )Nr   )r   rn   )r  r   r   r   r     s    r   c             C   s   t jd| }dd |D S )Nz *, *c             S   s   g | ]}|d kr|qS )r   r   )r`   rC   r   r   r   r   #  s    z*parse_stringified_list.<locals>.<listcomp>)r   r   )r   lr   r   r   parse_stringified_list!  s    r  c               @   s
  e Zd ZdZd Z Z Z Z ZZ	dZ
dZdZdZdZdZejd	e
 e d
 e e ejZejde e ejZejde
 e d e e ejZejde ejZdi fddZi fddZdd Zdd Zdd Zdd Zedd Zdd Zd d! Z d"d# Z!dS )$Locationz8Object representing a repository / archive location
    Nz%
        (?:(?P<user>[^@:/]+)@)?
    z
        (?!(:|//|ssh://))                                   # not starting with ":" or // or ssh://
        (?P<path>([^:]|(:(?!:)))+)                          # any chars, but no "::"
        z
        (?P<path>(([^/]*)/([^:]|(:(?!:)))+))                # start opt. servername, then /, then any chars, but no "::"
        zq
        (?P<path>(/([^:]|(:(?!:)))+))                       # start with /, then any chars, but no "::"
        z
        (?:
            ::                                              # "::" as separator
            (?P<archive>[^/]+)                              # archive name must not contain "/"
        )?$z
        (?P<host>(
            (?!\[)[^:/]+(?<!\])     # hostname or v4 addr, not containing : or / (does not match v6 addr: no brackets!)
            |
            \[[0-9a-fA-F:.]+\])     # ipv6 address in brackets
        )
    zR
        (?P<proto>ssh)://                                       # ssh://
        z                 # user@  (optional), host name or address
        (?::(?P<port>\d+))?                                     # :port (optional)
        zO
        (?P<proto>file)://                                  # file://
        z
        (
            z             # user@  (optional), host name or address
            :                                                   # : (required!)
        )?                                                      # user@host: part is optional
        a                                  # the repo part is fetched from BORG_REPO
        (?:::$)                                             # just "::" is ok (when a pos. arg is required, no archive)
        |                                                   # or
        r   c             C   s   | j ||std| j d S )NzInvalid location format: "%s")rA  rW   	processed)r%   rQ  rR  r   r   r   r#   w  s    zLocation.__init__c             C   s   || _ t|| | _}| j|}|r(dS | jj|}|s<dS tjjd}|d krTdS t||}| j|}|j	d| _
| j
s~|n|| j  | _ | j
s|nd|| j
f | _|S )NTFZ	BORG_REPOrP   z%s::%s)rawrS  r  _parseenv_rer   r9   r   rk   r8  rP   )r%   rQ  rR  Zvalidr   Zrepo_rawZrepor   r   r   rA  {  s"    


zLocation.parsec             C   s  dd }| j j|}|rz|jd| _|jd| _|jd| _|jdrTt|jdpVd | _||jd| _|jd| _	d	S | j
j|}|r|jd| _||jd| _|jd| _	d	S | jj|}|r|jd| _|jd| _||jd| _|jd| _	| jr
d
pd| _d	S dS )Nc             S   s&   | j d}tjj| } |r"d|  S | S )Nz/./z/.)
startswithr9   r   normpath)pZrelativer   r   r   normpath_special  s    
z)Location._parse.<locals>.normpath_specialprotorH  hostportr   rP   TZsshr   F)ssh_rer   r8  r  rH  _hostr   r  r   rP   file_rescp_re)r%   rQ  r  r   r   r   r   r    s2    zLocation._parsec             C   s>   d| j  d| j d| j d| j d| j d| j g}dj|S )Nzproto=%rzuser=%rzhost=%rzport=%rzpath=%rz
archive=%rz, )r  rH  r  r  r   rP   r   )r%   r   r   r   r   r/     s    zLocation.__str__c             C   s`   t jdd| jjd}| jdkr8t jdd| jd | }t|dkrP|d d }tjjt	 |S )Nz[^\w]rC  r   __rI   )
r   r<  r   r  r  r  r]   r9   r   r   )r%   ra   r   r   r   to_key_filename  s    
zLocation.to_key_filenamec             C   s   d|  S )NzLocation(%s)r   )r%   r   r   r   __repr__  s    zLocation.__repr__c             C   s    | j d k	r| j jdjdS d S )N[])r  lstriprstrip)r%   r   r   r   r    s    
zLocation.hostc             C   s   | j dkr| jS | jr.| jjdr.d| j }n&| jrN| jjd rNd| j }n| j}dj| jrjdj| jnd| j| jrdj| jnd|S d S )	Nr   ~/z/./zssh://{}{}{}{}z{}@r   z:{})r  r   r  r)   rH  r  r  )r%   r   r   r   r   canonical_path  s    
zLocation.canonical_pathc             C   s"   t | jt|jd t|ddS )N)r   r   )rR  )r  r  r>  rK  )r%   r   r   r   r   with_timestamp  s    zLocation.with_timestampc             C   s8   t | j}d |_|jjdd |_|jjdd |_|S )Nz::r   )r  r  rP   r   r  )r%   locr   r   r   omit_archive  s
    
zLocation.omit_archive)"r+   r,   r-   r(   r  rH  r  r  r   rP   Zoptional_user_reZscp_path_reZfile_path_reZabs_path_reZoptional_archive_reZhost_rer   r   VERBOSEr  r  r  r  r#   rA  r  r/   r  r  r   r  r  r  r  r   r   r   r   r  &  s4   		 r  c                s    fdd}|S )Nc                s   yt | }W n2 tk
r> } ztjt|d W Y d d }~X nX  dkr`|j r`tjd|  n dkr||jr|tjd|  d k	r|jkrdkrtjd|  ntjd|  |S )NTz"%s": No archive specifiedFz!"%s": No archive can be specifiedr   z"%s": Repository must be localz"%s": Repository must be remote)r  rW   r   r   rh   rP   r  )rQ  r  err)rP   r  r   r   	validator  s    "z%location_validator.<locals>.validatorr   )rP   r  r  r   )rP   r  r   location_validator  s    r  c              C   s   dd } | S )Nc             S   s0   t | } d| ksd| ks|  r,tjd|  | S )Nr  z::zInvalid archive name: "%s")rS  r   r   )rQ  r   r   r   r    s    z(archivename_validator.<locals>.validatorr   )r  r   r   r   archivename_validator  s    r  c             C   s6   x0|D ](}t | j|tr| | j||| |< qW | S )N)rg   rk   rt   rn   )r   r   encodingr  rQ   r   r   r   decode_dict  s    
r  c                s0   dd  fdd fdd  | S )Nc             S   s8   | j ds,y| j } | S  tk
r*   Y nX dt|  S )N   )r  rn   UnicodeDecodeErrorr   )r   r   r   r   decode_bytes  s    
z'prepare_dump_dict.<locals>.decode_bytesc                sd   g }xZ| D ]R}t |tr" |}n0t |ts6t |tr@|}nt |trR|}|j| q
W |S )N)rg   rS   rs   r   rt   r   )r   resr   )rn   r  decode_tupler   r   r    s    




z'prepare_dump_dict.<locals>.decode_tuplec                sz   t j }xl| j D ]`\}}t|tr. |}n*t|ttfrF|}nt|trX|}t|trj|j }|||< qW |S )N)	collectionsOrderedDictr   rg   rS   rs   r   rt   rn   )r   r  rQ   r   )rn   r  r  r   r   rn   '  s    




z!prepare_dump_dict.<locals>.decoder   )r   r   )rn   r  r  r   prepare_dump_dict  s    r  ru   c             C   s   | j d|jdS )z6Replace surrogates generated by fsdecode with '?'
    zutf-8)rx   rn   )r   r  r   r   r   remove_surrogates8  s    r  z^((\.\.)?/+)+c             C   s   t jd| pdS )z3Make path safe by making it relative and local
    r   r  )_safe_rer<  )r   r   r   r   make_path_safeA  s    r  c              C   s   ddl m}  |  }tj }|r(tjd tj  tj }|rFtjd tjd tjd tjd tjd tjtj	tj
}tj|d tj|d tj|d |  }||fS )zsDetach process from controlling terminal and run in background

    Returns: old and new get_process_id tuples
    r   )get_process_idr   r  r   )rA   r  r9   fork_exitsetsidchdirr   r   devnullO_RDWRdup2)r  Zold_idrG  r  Znew_idr   r   r   	daemonizeG  s&    





r  c                   s    e Zd ZdZ fddZ  ZS )rV   z,A dict subclass with stable items() orderingc                s   t t j S )N)r   r"   r   )r%   )r&   r   r   r   c  s    zStableDict.items)r+   r,   r-   r(   r   r0   r   r   )r&   r   rV   a  s   rV   c             C   s   t | trtj| dddS | S )zConvert bytearray to int
    littleT)signed)rg   rt   r   
from_bytes)r%  r   r   r   bigint_to_intg  s    
r  c             C   s,   | j  dkr(| j| j  d d dddS | S )z[Convert integers larger than 64 bits to bytearray

    Smaller integers are left alone
    rX  	      r  T)r  )
bit_lengthto_bytes)r   r   r   r   int_to_biginto  s    r  c               C   s   t jtjkS )N)rX   ZPackermsgpack_fallbackr   r   r   r   is_slow_msgpacky  s    r  c              C   s.   t jd d } d|   ko dkn  o,| dkS )NrF   r   rm  r
  rn  r   )r   rm  r
  )r   rn  r
  r   rn  r   r   rn  r   r   rn  rF   r   rn  rn  )r  r  r  r  )rX   r   )r   r   r   r   is_supported_msgpack}  s    r  NoNOnoNr   0YesYESyesr  r   1DefaultDEFAULTr  Dr   z{} (from {})c                sV  d fdd	} p| dkr&t j|
dkr6td| rH|| ddd xd}|rtjj|}|dk	r|r||j||d	|d
 |dkr|s|
S y
| }W n( tk
r   |
r|d n|d }Y nX ||	kr|r||d |
S ||k r| r||d dS ||kr|r||d dS |r,||d |s6|
S |rJ||ddd d}qLW dS )ab  Output <msg> (usually a question) and let user input an answer.
    Qualifies the answer according to falsish, truish and defaultish as True, False or <default>.
    If it didn't qualify and retry is False (no retries wanted), return the default [which
    defaults to False]. If retry is True let user retry answering until answer is qualified.

    If env_var_override is given and this var is present in the environment, do not ask
    the user, but just use the env var contents as answer as if it was typed in.
    Otherwise read input from stdin and proceed as normal.
    If EOF is received instead an input or an invalid input without retry possibility,
    return default.

    :param msg: introducing message to output on ofile, no 
 is added [None]
    :param retry_msg: retry message to output on ofile, no 
 is added [None]
    :param false_msg: message to output before returning False [None]
    :param true_msg: message to output before returning True [None]
    :param default_msg: message to output before returning a <default> [None]
    :param invalid_msg: message to output after a invalid answer was given [None]
    :param env_msg: message to output when using input from env_var_override ['{} (from {})'],
           needs to have 2 placeholders for answer and env var name
    :param falsish: sequence of answers qualifying as False
    :param truish: sequence of answers qualifying as True
    :param defaultish: sequence of answers qualifying as <default>
    :param default: default return value (defaultish answer was given or no-answer condition) [False]
    :param retry: if True and input is incorrect, retry. Otherwise return default. [True]
    :param env_var_override: environment variable name [None]
    :param ofile: output stream [sys.stderr]
    :param input: input function [input from builtins]
    :return: boolean answer value, True or False
    Fc                sj   t tjddd}|rD|jtd|  | d ttj|tj	d n"|rZt| ddd	 nt| d d S )
NrD   jsonFzquestion_%s)r'   msgidmessage)r   r   T)r   endflush)
getattrlogging	getLoggerrT   rS   printr  dumpssysstderr)msgZmsg_type	is_promptkwargsZjson_output)r  ofiler   r   output  s    
zyes.<locals>.outputNTz,invalid default value, must be True or Falseprompt)r  Z
env_answer)Zenv_varr   Zaccepted_defaultZaccepted_trueZaccepted_falseZinvalid_answerZprompt_retry)F)TF)r  r  rW   r9   r   rk   r)   EOFError)r  Z	false_msgZtrue_msgZdefault_msgZ	retry_msgZinvalid_msgenv_msgZfalsishZtruishZ
defaultishr  Zretryenv_var_overrider  inputr  r  r  Zanswerr   )r  r  r   r    sP    "






c               C   s   t ddd ddS )NZBORG_HOSTNAME_IS_UNIQUEFT)r  r  r  r  )r  r   r   r   r   hostname_is_unique  s    r  c             C   sv   ddl m} |d}|| }|dk r4dd||   S ||| k rfdt| |d | t| | d f S | d||   S )z
    shorten a long string by adding ellipsis between it and return it, example:
    this_is_a_very_long_string -------> this_is..._string
    r   )swidthz...r  rf  z%s...%sr   )rA   r	  swidth_slice)r  spacer	  Zellipsis_widthZ	msg_widthr   r   r   ellipsis_truncate  s    r  c               @   sP   e Zd ZdZdZdZdZedd ZdddZ	d	d
 Z
ddddZdd ZdS )ProgressIndicatorBasezborg.output.progressNFr   c             C   s   |  j d7  _ | j S )zYUnique number, can be used by receiving applications to distinguish different operations.r   )operation_id_counter)r   r   r   r   operation_id  s    z"ProgressIndicatorBase.operation_idc             C   s   d | _ tj| j| _| j | _|| _| jjstj	t
jd| _ | j jtj tjd}y |j}|jrfdnd}|j| _W n tk
r   d}Y nX | j j| || j _| jj| j  | jjtjkr| jjtj d| j_| jj tjk| _d S )N)streamrD   r  F)handlerr  r  LOGGERr   r  re   r  ZhandlersZStreamHandlerr  r  ZsetLevelINFO	formatterr  AttributeErrorZsetFormatter
terminatorZ
addHandlerlevelZNOTSETZWARNZ	propagateZgetEffectiveLevelemit)r%   r  r   r  r  r   r   r   r#   
  s*    


	zProgressIndicatorBase.__init__c             C   s&   | j d k	r"| jj| j  | j j  d S )N)r  r   ZremoveHandlerr   )r%   r   r   r   __del__1  s    
zProgressIndicatorBase.__del__)finishedc            K   sP   | j s
t| jsd S |jt| j| j| j|tj d t	t j
|tjdd d S )N)r   r  r'   r  r  T)r   r  )r  ri   r  rT   rS   re   r  	JSON_TYPEr  r  r  r  r  )r%   r  r   r   r   r   output_json6  s    
z!ProgressIndicatorBase.output_jsonc             C   s"   | j r| jdd n
| jd d S )NT)r  r   )r  r  r  )r%   r   r   r   finishC  s    zProgressIndicatorBase.finish)N)r+   r,   r-   r  r  r  r  r   r  r#   r  r  r  r   r   r   r   r    s   
'r  c             C   s$   t ddd }|dkr | j|S | S )Nr   )r   r   r   r   )r   r   r   )r   ljust)r  terminal_spacer   r   r   justify_to_terminal_sizeJ  s    
r!  c               @   s   e Zd ZdZdd ZdS )ProgressIndicatorMessageZprogress_messagec             C   s(   | j r| j|d n| jjt| d S )N)r  )r  r  r   ry   r!  )r%   r  r   r   r   r  U  s    zProgressIndicatorMessage.outputN)r+   r,   r-   r  r  r   r   r   r   r"  R  s   r"  c                   s@   e Zd ZdZd fdd	Zdd	d
ZdddZdddZ  ZS )ProgressIndicatorPercentZprogress_percentr   rn  %3.0f%%Nc                s0   d| _ || _|| _|| _|| _t j|d dS )a  
        Percentage-based progress indicator

        :param total: total amount of items
        :param step: step size in percent
        :param start: at which percent value to start
        :param msg: output message, must contain one %f placeholder for the percentage
        r   )r  N)countertotal
trigger_atstepr  r"   r#   )r%   r&  r(  startr  r  )r&   r   r   r#   _  s    	z!ProgressIndicatorPercent.__init__r   c             C   sN   |d k	r|| _ | j d | j }|  j |7  _ || jkrJ|  j| j7  _|S d S )NrI   )r%  r&  r'  r(  )r%   currentincreasepctr   r   r   progressp  s    
z!ProgressIndicatorPercent.progressc             C   s   | j ||}|dk	r|dk	r| jsttd
dd }|dkrt|t| jt|g|dd  dg   }t|d ||d< | j| jt|g|  d|dS | j| j| S dS )z
        Show and output the progress message

        :param current: set the current percentage [None]
        :param increase: increase the current percentage [None]
        :param info: array of strings to be formatted with msg [None]
        Nr   )r   r   r   F)justifyry   r   r   )r   r   r   r   r   r   )r-  r  r   r]   r  rs   r  r  )r%   r*  r+  ry   r,  r   r  r   r   r   showy  s    * zProgressIndicatorPercent.showTc             C   s:   | j r| j|| j| j|d n|r*t|}| jj| d S )N)r  r*  r&  ry   )r  r  r%  r&  r!  r   ry   )r%   r  r.  ry   r   r   r   r    s
    zProgressIndicatorPercent.output)r   rn  r   r$  N)Nr   )Nr   N)TN)	r+   r,   r-   r  r#   r-  r/  r  r0   r   r   )r&   r   r#  \  s
   
	
r#  c               @   s6   e Zd ZdddZdd Zdd Zd	d
 Zdd ZdS )ProgressIndicatorEndlessrR   Nc             C   s*   d| _ d| _|| _|dkr tj}|| _dS )z
        Progress indicator (long row of dots)

        :param step: every Nth call, call the func
        :param file: output file, default: sys.stderr
        r   N)r%  	triggeredr(  r  r  r   )r%   r(  r   r   r   r   r#     s    z!ProgressIndicatorEndless.__init__c             C   s4   |  j d7  _ | j | j dk}|r0|  jd7  _|S )Nr   r   )r%  r(  r1  )r%   triggerr   r   r   r-    s
    z!ProgressIndicatorEndless.progressc             C   s   | j  }|r| j| jS d S )N)r-  r  r1  )r%   r2  r   r   r   r/    s    zProgressIndicatorEndless.showc             C   s   t dd| jdd d S )Nr  r   T)r  r   r  )r  r   )r%   r1  r   r   r   r    s    zProgressIndicatorEndless.outputc             C   s   t | jd d S )N)r   )r  r   )r%   r   r   r   r    s    zProgressIndicatorEndless.finish)rR   N)r+   r,   r-   r#   r-  r/  r  r  r   r   r   r   r0    s
   
r0  c              C   sR  t jjddj } | dkrdS tj }tj }yt j }W n tk
rR   d }Y nX t	jj
drytj }W q   d}Y qX nd }ydjdd	 tjD }W n   d
}Y nX g }|d k	r|jddj|f  |d k	r|jd|  |jdt|||f  |jdt j t j f  |jdt	j  |jdt jjd  |jd dj|S )NZBORG_SHOW_SYSINFOr  r  r   linuxUnknown Linuxr  c             s   s   | ]}t |V  qd S )N)rh   )r`   r   r   r   r   rb     s    zsysinfo.<locals>.<genexpr>unknownzPlatform: %srf  zLinux: %s %s %sz#Borg: %s  Python: %s %s msgpack: %szPID: %d  CWD: %szsys.argv: %rzSSH_ORIGINAL_COMMAND: %rZSSH_ORIGINAL_COMMANDr  )r4  r   r   )r9   r   rk   r  rA   python_implementationpython_versionunamer  r  r  linux_distributionr   rX   r   r   rO  rJ  getcwdargv)Zshow_sysinfor6  r7  r8  r9  Zmsgpack_versionry   r   r   r   sysinfo  s>    


r<  )r  r   c             G   s>   g }x|D ]}|j |j  q
W x|D ]}|j| | q&W dS )z
    log multiple lines of text, each line by a separate logging call for cosmetic reasons

    each positional argument may be a single or multiple lines (separated by newlines) of text.
    N)extend
splitlineslog)r  r   Zmsgslinesr  liner   r   r   	log_multi  s
    

rB  c               @   s@   e Zd ZdddddejejdZdd Zd	d
 Zedd Z	dS )BaseFormatterr  rf  	r   )ZLFZSPACEZTABZCRZNULNEWLINENLc             C   s   t d S )N)NotImplementedError)r%   rC   r   r   r   get_item_data  s    zBaseFormatter.get_item_datac             C   s   | j j| j|S )N)r)   r9  rI  )r%   rC   r   r   r   format_item  s    zBaseFormatter.format_itemc               C   s   dS )Nz- NEWLINE: OS dependent line separator
- NL: alias of NEWLINE
- NUL: NUL character for creating print0 / xargs -0 like output, see barchive and bpath keys below
- SPACE
- TAB
- CR
- LFr   r   r   r   r   	keys_help   s    zBaseFormatter.keys_helpN)
r+   r,   r-   r9   linesep
FIXED_KEYSrI  rJ  staticmethodrK  r   r   r   r   rC    s   
rC  c               @   s   e Zd Zddddddddd	d
ddddZd8Zedd Zedd Zd d!d"d#Zd$d% Z	d&d' Z
ed(d) Zd*d+ Zd,d- Zd.d/ Zd0d1 Zd2d3 Zd4S )9ArchiveFormatterzUarchive name interpreted as text (might be missing non-text characters, see barchive)zalias of "archive"z;verbatim archive name, can contain any character except NULzXarchive comment interpreted as text (might be missing non-text characters, see bcomment)z>verbatim archive comment, can contain any character except NULz'time (start) of creation of the archivezalias of "start"z%time (end) of creation of the archivez1command line which was used to create the archivezinternal ID of the archivez2hostname of host on which this archive was createdz)username of user who created this archivez(TAM authentication state of this archive)rP   ra   barchivecommentbcommentr)  r  r  command_linere   rF  usernametamrP   ra   rP  rQ  rR  re   rU  r)  r  r  rS  rF  rT  c          	   C   sX   t ddd tdddtjd}| dd d d }g }|j|jj  |j|j|j  |S )Narchivename   r   i  r   )rr   r   )rZ   r   r   r   r=  	call_keysr   rI  )r   Zfake_archive_infor  r   r   r   r   available_keys"  s    zArchiveFormatter.available_keysc             C   s   g }| j  }x| jD ]}|j| qW x^| jD ]T}xD|D ]<}|j| d| }|| jkrj|d| j|  7 }|j| q8W |jd q.W | stt|dj|S )Nz- z: r   r  )	rY  rM  remove
KEY_GROUPSKEY_DESCRIPTIONSr   ri   rh   r   )r   helpr   rQ   r8  rQ  r   r   r   rK  +  s    


zArchiveFormatter.keys_helpF)r  c            C   s   || _ || _|| _d | _d | _d | _|| _i }|j| j t	||| _
dd t j|D | _t| jdddt| jdddt| jdddt| jddd| j| j| jd	| _t| j| j@ | _| jri | _| j| _n|| _d S )
Nc             S   s   h | ]}|d  qS )r   r   )r`   r   r   r   r   r0  H  s    z,ArchiveFormatter.__init__.<locals>.<setcomp>rF  T)rsrT  rQ  F)rF  rT  rQ  rR  r  rS  rU  )r   rL   rQ   ra   re   _archiver  rT   rM  r=  r)   r   rA  format_keysr
   get_meta
get_ts_endget_cmdlineget_tamrX  r   used_call_keys	item_dataformat_item_jsonrJ  )r%   r)   r   rL   rQ   r  static_keysr   r   r   r#   =  s.    
zArchiveFormatter.__init__c             C   s   t j| j|tdd S )N)r   r  )r  r  rI  BorgJsonEncoder)r%   rC   r   r   r   rg  Y  s    z!ArchiveFormatter.format_item_jsonc             C   s   |j | _ |j| _i }|j| j |jt|j t|j |j t|j| j|j| j|jd x| jD ]}| j	|  ||< qdW |S )N)ra   rP   rP  re   r  r)  )
ra   re   rT   rf  r  r   r]  rf   re  rX  )r%   Zarchive_inforf  rQ   r   r   r   rI  \  s    
zArchiveFormatter.get_item_datac             C   sB   | j dks| j j| jkr<ddlm} || j| j| j| j| _ | j S )z!lazy load / update loaded archiveNr   )Archive)r_  re   rP   rj  r   rQ   rL   ra   )r%   rj  r   r   r   rP   m  s    zArchiveFormatter.archivec             C   s    | j jj|d}|rt|S |S )Nr   )rP   metadatark   r  )r%   rQ   r^  r   r   r   r   ra  u  s    zArchiveFormatter.get_metac             C   s:   t t| jjjdg }| jr$t|S djt tj	|S d S )Ncmdlinerf  )
mapr  rP   rk  rk   r  r   r   shlexZquote)r%   rl  r   r   r   rc  y  s    zArchiveFormatter.get_cmdlinec             C   s   | j | jjS )N)r]  rP   Zts_end)r%   r   r   r   rb    s    zArchiveFormatter.get_ts_endc             C   s   | j jrdS dS )NZverifiedZnone)rP   r   )r%   r   r   r   rd    s    zArchiveFormatter.get_tamc             C   s   t |S )N)rb  )r%   rf   r   r   r   r]    s    zArchiveFormatter.format_timeNrP   ra   rP  rQ  rR  re   rU  r)  r  r  rS  rF  rT  )ro  rp  rq  )r+   r,   r-   r\  r[  r   rY  rK  r#   rg  rI  r   rP   ra  rc  rb  rd  r]  r   r   r   r   rO    s6     	rO  c               @   s   e Zd ZejjddhZddddddd	d
ddd
ZdHdIdJee	edKdLfZ
dMZed)d* Zed+d, Zed-d. Zd/d0d1d2Zd3d4 Zd5d6 Zd7d8 Zd9d: Zd;d< Zd=d> Zd?d@ ZdAdB ZdCdD ZdEdF ZdGS )NItemFormatterZ	shake_128Z	shake_256z9verbatim POSIX path, can contain any character except NULzJpath interpreted as text (might be missing non-text characters, see bpath)z/link target for links (identical to linktarget)zKprepends {source} with " -> " for soft links and " link to " for hard linkszcompressed sizezdeduplicated sizezdeduplicated compressed sizeznumber of chunks in this filez$number of unique chunks in this filezPeither "healthy" (file ok) or "broken" (if file has all-zero replacement chunks))
bpathr   sourceextracsizedsizedcsize
num_chunksunique_chunkshealthr'   r   r  r  rH  r8  r   rs  rt  
linktargetflagsr&  rv  rw  rx  ry  rz  r%  r$  atimeisomtimeisoctimeisoatime	archiveidrV  ru  r{  c          	   C   sf   G dd d}ddl m} |dddddddd}| |d}g }|j|jj  |j|j|j  |S )Nc               @   s   e Zd Zd ZZdS )z1ItemFormatter.available_keys.<locals>.FakeArchiver   N)r+   r,   r-   fprra   r   r   r   r   FakeArchive  s   r  r   )Itemr   r   )r   r   rH  r8  r%  r  r  )rC   r  r=  rX  r   rI  )r   r  r  Z	fake_itemr  r   r   r   r   rY    s    
zItemFormatter.available_keysc             C   s   g }| j  }x| jD ]}|j| qW x^| jD ]T}xD|D ]<}|j| d| }|| jkrj|d| j|  7 }|j| q8W |jd q.W | stt|dj|S )Nz- z: r   r  )	rY  rM  rZ  r[  r\  r   ri   rh   r   )r   r]  r   rQ   r8  rQ  r   r   r   rK    s    


zItemFormatter.keys_helpc                s,   dd t  j|D }t fdd|D S )Nc             S   s   h | ]}|d  qS )r   r   )r`   r   r   r   r   r0    s    z3ItemFormatter.format_needs_cache.<locals>.<setcomp>c             3   s   | ]}| j kV  qd S )N)KEYS_REQUIRING_CACHE)r`   rQ   )r   r   r   rb     s    z3ItemFormatter.format_needs_cache.<locals>.<genexpr>)r   rA  any)r   r)   r`  r   )r   r   format_needs_cache  s    z ItemFormatter.format_needs_cacheF)
json_linesc            C   s  || _ || _|j|jd}|j| j | jr<i | _| j| _n|| _t	||| _
dd t j|D | _| j| jt| jdd t| jdd | jt| jdd t| jdt| jd	t| jd
t| jdt| jd	t| jd
d| _x"| jD ]}| j|t| j| qW t| j| j@ | _d S )N)rV  r  c             S   s   h | ]}|d  qS )r   r   )r`   r   r   r   r   r0    s    z)ItemFormatter.__init__.<locals>.<setcomp>c             S   s   | j S )N)r&  )chunkr   r   r   r     s    z(ItemFormatter.__init__.<locals>.<lambda>c             S   s   | j S )N)rv  )r  r   r   r   r     s    c             S   s   dS )Nr   r   )r  r   r   r   r     s    r%  r$  r~  )r&  rv  rw  rx  ry  rz  r  r  r  r%  r$  r~  )rP   r  ra   r  rT   rM  rf  rg  rJ  r=  r)   r   rA  r`  calculate_sizecalculate_csizer
   sum_unique_chunks_metadatacalculate_num_chunksformat_iso_timer]  rX  hash_algorithmsadd_key	hash_itemr   re  )r%   rP   r)   r  rh  hash_functionr   r   r   r#     s4    






zItemFormatter.__init__c             C   s   t j| j|tdd S )N)r   r  )r  r  rI  ri  )r%   rC   r   r   r   rg    s    zItemFormatter.format_item_jsonc             C   s    || j |< t| j | j@ | _d S )N)rX  r   r`  re  )r%   rQ   Zcallable_with_itemr   r   r   r    s    
zItemFormatter.add_keyc             C   s>  i }|j | j tj|j}|d }|jdd}d}|rjt|}|dkrRd| }nd|dd   }d| }||d	< ||d
< |jp|j|d< |j	p|j
|d< |j|d< |j
|d< t|j|d< | jrd|k|d< n&|j|d< ||d< d|krdnd|d< ||d< ||d< |jdd|d< x"| jD ]}| j| |||< qW |S )Nr   rt  r   r  z -> %sr`  r   z link to %sr'   r   rH  r8  r  r  r   Zchunks_healthyZhealthyrs  ru  Zbrokenr{  r|  Zbsdflagsr}  )rT   rf  r:   filemoder   rk   r  rH  r  r8  r  r   r  re  rX  )r%   rC   rf  r   Z	item_typert  ru  rQ   r   r   r   rI    s<    



zItemFormatter.get_item_datac                sB   | j jj |jdg }tdd |D t fdd|D S )au  
        sum unique chunks metadata, a unique chunk is a chunk which is referenced globally as often as it is in the
        item

        item: The item to sum its unique chunks' metadata
        metadata_func: A function that takes a parameter of type ChunkIndexEntry and returns a number, used to return
                       the metadata needed from the chunk
        chunksc             s   s   | ]}|j V  qd S )N)re   )r`   r!  r   r   r   rb   !  s    z;ItemFormatter.sum_unique_chunks_metadata.<locals>.<genexpr>c             3   s,   | ]$} |j  j|j  kr|V  qd S )N)re   Zrefcount)r`   r!  )chunk_indexchunks_countermetadata_funcr   r   rb   "  s    )rP   cacher  rk   r   sum)r%   r  rC   r  r   )r  r  r  r   r    s    	
z(ItemFormatter.sum_unique_chunks_metadatac             C   s   t |jdg S )Nr  )r]   rk   )r%   rC   r   r   r   r  $  s    z"ItemFormatter.calculate_num_chunksc             C   s   |j ddS )NF)
compressed)get_size)r%   rC   r   r   r   r  '  s    zItemFormatter.calculate_sizec             C   s   |j ddS )NT)r  )r  )r%   rC   r   r   r   r  +  s    zItemFormatter.calculate_csizec             C   sZ   || j kstd|krdS tj|}x,| jjjdd |jD D ]}|j| q@W |j	 S )Nr  r   c             S   s   g | ]
}|j qS r   )re   )r`   r!  r   r   r   r   4  s    z+ItemFormatter.hash_item.<locals>.<listcomp>)
r  ri   hashlibnewrP   pipeline
fetch_manyr  rT   Z	hexdigest)r%   r  rC   hashr   r   r   r   r  /  s    
 zItemFormatter.hash_itemc             C   s   t t|j|p|jS )N)rb  r\  rk   r%  )r%   rQ   rC   r   r   r   r]  8  s    zItemFormatter.format_timec             C   s   | j ||j S )N)r]  rc  )r%   rQ   rC   r   r   r   r  ;  s    zItemFormatter.format_iso_timeN)r'   r   r  r  rH  r8  r   rs  rt  r|  r}  )r&  rv  rw  rx  ry  rz  )r%  r$  r~  r  r  r  )r  rV  ru  )r{  )rw  rx  rz  )r+   r,   r-   r  Zalgorithms_guaranteed
differencer  r\  rs   r   r[  r  r   rY  rK  r  r#   rg  r  rI  r  r  r  r  r  r]  r  r   r   r   r   rr    s@   
!#	rr  c               @   s2   e Zd ZdZdddZdd Zdd Zd	d
 ZdS )ChunkIteratorFileWrapperz%File-like wrapper for chunk iteratorsNc             C   s"   || _ d| _d| _d| _|| _dS )at  
        *chunk_iterator* should be an iterator yielding bytes. These will be buffered
        internally as necessary to satisfy .read() calls.

        *read_callback* will be called with one argument, some byte string that has
        just been read and will be subsequently returned to a caller of .read().
        It can be used to update a progress display.
        r       FN)chunk_iteratorchunk_offsetr  	exhaustedread_callback)r%   r  r  r   r   r   r#   B  s
    	z!ChunkIteratorFileWrapper.__init__c             C   s\   t | j| j }|sXyt| j}t|| _W n tk
rF   d| _dS X d| _t | j}|S )NTr   )r]   r  r  nextr  
memoryviewStopIterationr  )r%   	remainingr  r   r   r   _refillQ  s    

z ChunkIteratorFileWrapper._refillc             C   s>   |sdS | j  }t||}|  j|7  _| j| j| | j S )Nr  )r  minr  r  )r%   nbytesr  Z	will_readr   r   r   _read^  s    
zChunkIteratorFileWrapper._readc             C   sP   g }x@|rD| j  rD| j|}|t|8 }|j| | jr| j| qW dj|S )Nr  )r  r  r]   r   r  r   )r%   r  partsZ	read_datar   r   r   r   f  s    

zChunkIteratorFileWrapper.read)N)r+   r,   r-   r(   r#   r  r  r   r   r   r   r   r  ?  s
   
r  c             C   s    | j jdd |jD }t|S )z8Return file-like object for archived item (with chunks).c             S   s   g | ]
}|j qS r   )re   )r`   r!  r   r   r   r   s  s    zopen_item.<locals>.<listcomp>)r  r  r  r  )rP   rC   r  r   r   r   	open_itemq  s    r  c             C   sX   t j| rdS t j| rdS t j| r*dS t j| r8dS t j| rFdS t j| rTdS dS )NAr   br!  r   r   ?)r:   S_ISREGS_ISDIRS_ISBLKS_ISCHRS_ISLNKS_ISFIFO)r   r   r   r   file_statusw  s    





r  c             C   s(   t j| p&t j| p&t j| p&t j| S )z7return True if we support hardlinked items of this type)r:   r  r  r  r  )r   r   r   r   hardlinkable  s    r  c                s   t |  t  fddg S )z
    Chunk an iterator <it> into pieces of <size>.

    >>> list(chunker('ABCDEFG', 3))
    [['A', 'B', 'C'], ['D', 'E', 'F'], ['G']]
    c                  s   t t S )N)r   r   r   )iterabler&  r   r   r     s    zchunkit.<locals>.<lambda>)rc   )itr&  r   )r  r&  r   chunkit  s    r  c             C   s,   |dkrt | dd ntt| ||d dS )zCAdvance the iterator n-steps ahead. If n is none, consume entirely.Nr   )maxlen)r   r  r   )iteratorr   r   r   r   consume  s    r  c             C   sH   yd| j  fS  tk
rB } ztjd| j| d| jfS d }~X nX d S )Nr   z&scandir_inorder: Unable to stat %s: %sr   )r'  r   r   r   r   ra   )Zdirentr   r   r   r   scandir_keyfunc  s
    r  r  c             C   s   t t| tdS )N)rQ   )r   r   r  )r   r   r   r   scandir_inorder  s    r  c             c   sX   xR| D ]J}|dk	r|j |}|dk	r.|j|}|r:| r:q|rJ|jdrJq|V  qW dS )a  
    clean lines (usually read from a config file):

    1. strip whitespace (left and right), 2. remove empty lines, 3. remove comments.

    note: only "pure comment lines" are supported, no support for "trailing comments".

    :param lines: input line iterator (e.g. list or open text file) that gives unclean input lines
    :param lstrip: lstrip call arguments or False, if lstripping is not desired
    :param rstrip: rstrip call arguments or False, if rstripping is not desired
    :param remove_comments: remove comment lines (lines starting with "#")
    :param remove_empty: remove empty lines
    :return: yields processed lines
    F#N)r  r  r  )r@  r  r  Zremove_emptyZremove_commentsrA  r   r   r   clean_lines  s    



r  c                   s(   e Zd Z fddZ fddZ  ZS )ErrorIgnoringTextIOWrapperc                sP   | j sLyt j|S  tk
rJ   yt j  W n tk
rD   Y nX Y nX dS )Nr   )closedr"   r   BrokenPipeErrorr   r   )r%   r   )r&   r   r   r     s    zErrorIgnoringTextIOWrapper.readc                sT   | j sLyt j|S  tk
rJ   yt j  W n tk
rD   Y nX Y nX t|S )N)r  r"   r   r  r   r   r]   )r%   r   )r&   r   r   r     s    z ErrorIgnoringTextIOWrapper.write)r+   r,   r-   r   r   r0   r   r   )r&   r   r    s   r  c               @   s   e Zd ZdZdS )SignalExceptionz*base class for all signal-based exceptionsN)r+   r,   r-   r(   r   r   r   r   r    s   r  c               @   s   e Zd ZdZdS )SigHupzraised on SIGHUP signalN)r+   r,   r-   r(   r   r   r   r   r    s   r  c               @   s   e Zd ZdZdS )SigTermzraised on SIGTERM signalN)r+   r,   r-   r(   r   r   r   r   r    s   r  c             c   sP   t | trtt| d} | dk	r*tj| |}z
dV  W d| dk	rJtj| | X dS )a  
    when entering context, set up signal handler <handler> for signal <sig>.
    when leaving context, restore original signal handler.

    <sig> can bei either a str when giving a signal.SIGXXX attribute name (it
    won't crash if the attribute name does not exist as some names are platform
    specific) or a int, when giving a signal number.

    <handler> is any handler value as accepted by the signal.signal(sig, handler).
    N)rg   rh   r  signal)Zsigr  Zorig_handlerr   r   r   signal_handler  s    

r  c                s    fdd}|S )Nc                s   t j | t j  d S )N)r  SIG_IGN)Zsig_noframe)exc_clsr   r   r  
	  s    z'raising_signal_handler.<locals>.handlerr   )r  r  r   )r  r   raising_signal_handler		  s    r  c             C   st   ddl m} |dk }t|}|r(t| } d}g }x,| D ]$}|||7 }||krPP |j| q6W |rj|j  dj|S )a  
    Return a slice of *max_width* cells from *string*.

    Negative *max_width* means from the end of string.

    *max_width* is in units of character cells (or "columns").
    Latin characters are usually one cell wide, many CJK characters are two cells wide.
    r   )r	  r   r   )rA   r	  rx  r   r   r   r   )stringZ	max_widthr	  r   Zcurrent_swidthr   	characterr   r   r   r
  	  s    	
r
  c                   s   e Zd Z fddZ  ZS )ri  c                s   ddl m} ddlm} ddlm} ddlm}m} t	||sHt	||r^t
|j|jj dS t	||rp|j S t	||r|j|j dS t	||rd|j iS tt|d	d r|j S t j|S )
Nr   )r   )RemoteRepository)rj  )
LocalCache
AdHocCache)re   r   )r   statsr  rd  )r   r   Zremoter  rP   rj  r  r  r  rg   r   re   Z	_locationr  ry   r   r  r  r  rd  r"   r  )r%   or   r  rj  r  r  )r&   r   r   r  /	  s"    


zBorgJsonEncoder.default)r+   r,   r-   r  r0   r   r   )r&   r   ri  .	  s   ri  )r  ru  c            C   sv   | j }|pi }|jt j| jd|jid t| jjt	j
d|d d< |jjdrf|j |d d< |rr||d	< |S )
Nr   )r   
encryption)rr   r   Zlast_modifiedzkey filer  Zkeyfiler  )rQ   rT   ri  r  r   ZARG_NAMErb  r   ru   r   r   NAMEr  Zfind_key)rL   r  ru  rQ   r   r   r   r   basic_json_dataI	  s    r  c             C   s   t j| ddtdS )zDump using BorgJSONEncoder.Trm  )Z	sort_keysindentr   )r  r  ri  )objr   r   r   	json_dumpZ	  s    r  c             C   s   t t|  d S )N)r  r  )r  r   r   r   
json_print_	  s    r  c         
   C   sh   t | dJ}tj|j }|jdko&|sP|jtj|j |j  tj	|j  W dQ R X tj
|  dS )a  Attempt to securely erase a file by writing random data over it before deleting it.

    If avoid_collateral_damage is True, we only secure erase if the total link count is 1,
    otherwise we just do a normal "delete" (unlink) without first overwriting it with random.
    This avoids other hardlinks pointing to same inode as <path> getting damaged, but might be less secure.
    A typical scenario where this is useful are quick "hardlink copies" of bigger directories.

    If avoid_collateral_damage is False, we always secure erase.
    If there are hardlinks pointing to the same inode as <path>, they will contain random garbage afterwards.
    zr+br   N)r   r9   r:   filenost_nlinkr   urandomst_sizer  fsyncr   )r   Zavoid_collateral_damager  str   r   r   secure_erasec	  s    r  c             C   s   yt j|  W n tk
r } zp|jtjkr. t j| }|jdkrD y"t| d}|j  W dQ R X W n tk
r~   |Y nX t j|  W Y dd}~X nX dS )a  
    Safely unlink (delete) *path*.

    If we run out of space while deleting the file, we try truncating it first.
    BUT we truncate only if path is the only hardlink referring to this content.

    Use this when deleting potentially large files when recovering
    from a VFS error such as ENOSPC. It can help a full file system
    recover. Refer to the "File system interaction" section
    in repository.py for further explanations.
    r   zr+bN)	r9   r   r   errnoZENOSPCr:   r  r   truncate)r   Z
unlink_errr  r  r   r   r   safe_unlinkw	  s    


r  )cmd_linec             K   s   |j d stdytj| }|s,tdW n. tk
r\ } ztjd|| dS d}~X nX tjd|| ytj	|f|S  t
k
r   tjd||d  dS  tk
r   tjd	||d  dS X dS )
as  
    Handle typical errors raised by subprocess.Popen. Return None if an error occurred,
    otherwise return the Popen object.

    *cmd_line* is split using shlex (e.g. 'gzip -9' => ['gzip', '-9']).

    Log messages will be prefixed with *log_prefix*; if set, it should end with a space
    (e.g. log_prefix='--some-option: ').

    Does not change the exit code.
    shellz Sorry pal, shell mode is a no-noz&an empty command line is not permittedz%s%sNz%scommand line: %sz%sexecutable not found: %sr   z%spermission denied: %s)rk   ri   rn  r   rW   r   errorr   
subprocessPopenFileNotFoundErrorPermissionError)r  Z
log_prefixr   ZcommandZver   r   r   popen_with_error_handling	  s"    
r  c             C   s   t |dk	r|ntj}| rpd}|j|d }|dk	r>|||< n2|j|}|dk	rpttddrpttdrp|j| |jdd t|d< |S )	a  
    Prepare the environment for a subprocess we are going to create.

    :param system: True for preparing to invoke system-installed binaries,
                   False for stuff inside the pyinstaller environment (like borg, python).
    :param env: optionally give a environment dict here. if not given, default to os.environ.
    :return: a modified copy of the environment
    NZLD_LIBRARY_PATHZ_ORIGfrozenFZ_MEIPASSZBORG_PASSPHRASEZBORG_VERSION)	rS   r9   r   rk   r  r  hasattrpoprO  )systemenvZlp_keyZlp_origZlpr   r   r   prepare_subprocess_env	  s    	



r  c             C   sH   d|kst | dkr:d|kr"tjntj}d|kr6|jS |S t| |S d S )Nrw  -r#  r  )ri   r  stdinstdoutr  r   )r   r   r  r   r   r   	dash_open	  s
    r  c             C   s&   t | do$| j o$tjdkp$dtjkS )NisattyZwin32ZANSICON)r  r  r  rA   r9   r   )r  r   r   r   is_terminal	  s    r  c             C   sF   t dd}ytjdd| g|dS  tk
r@   tjd| g|dS X d S )NT)r  Z
fusermountz-u)r  umount)r  r  Zcallr  )Z
mountpointr  r   r   r   r   	  s
    
r   )_sanitize_params_get_candidate_namesTMP_MAX_text_openflags_bin_openflags  c             C   s   t jj| } t }|tkr&tt j|}xttD ]}t	|}t jj
| || | }	yt j|	||}
W nR tk
rz   w0Y n> tk
r   t jdkrt jj| rt j| t jrw0n Y nX |
|	fS W ttjddS )z>Code common to mkstemp, TemporaryFile, and NamedTemporaryFile.ntz#No usable temporary file name foundN)_osr   abspathr  rt   rm  fsencoderanger  r  r   r   FileExistsErrorr  ra   isdiraccessW_OK_errnoZEEXIST)dirZpreZsufr}  output_typer   namesseqra   r   r  r   r   r   _mkstemp_inner	  s"    $
r  c             C   s4   t || |\}} }}|rt}nt}t||| |||S )a  User-callable function to create and return a unique temporary
    file.  The return value is a pair (fd, name) where fd is the
    file descriptor returned by os.open, and name is the filename.
    If 'suffix' is not None, the file name will end with that suffix,
    otherwise there will be no suffix.
    If 'prefix' is not None, the file name will begin with that prefix,
    otherwise a default prefix is used.
    If 'dir' is not None, the file will be created in that directory,
    otherwise a default directory is used.
    If 'text' is specified and true, the file is opened in text
    mode.  Else (the default) the file is opened in binary mode.
    If any of 'suffix', 'prefix' and 'dir' are not None, they must be the
    same type.  If they are bytes, the returned name will be bytes; str
    otherwise.
    The file is readable and writable only by the creating user ID.
    If the operating system uses permission bits to indicate whether a
    file is executable, the file is executable by no one. The file
    descriptor is not inherited by children of this process.
    Caller is responsible for deleting the file when done with it.
    )r  r  r  r  )r   r   r  rQ  r   r  r}  r   r   r   mkstemp_mode
  s
    r  )Nl        ii  i\l            l    i  l     <Et l   :[ l   Z}K l    (TZ )r   )r   F)re  NNr   r   F)re  r   r   F)re  r   r   F)N)N)N)N)r  rN   )r  rN   )NN)r  rN   )ru   )r  r  r  r  r   r  )r  r  r  r  r   r  )r  r  r  r  r   r   )N)r  )NNTT)r   )N)r  )NNNFr  )r   
contextlibr  r   r  r  r  r  ior  r9   Zos.pathrA   r  r   rn  r  Zsocketr:   r  r  r  r  rN  Zbinasciir   r   r   r   r   r   r   r	   	functoolsr
   r   	itertoolsr   operatorr   r   r  r   Zshutilr   Zprefer_system_msgpackImportErrorZborg.algorithms.msgpackZ
algorithmsrX   r   r  r   r   Zborg.crypto.low_levelrD   r   r   rO  r   rP  r   r   r   Z	constantsrs   r   rk   r   ZworkaroundsZEXIT_SUCCESSr   r    rB  r!   r1   r2   r3   r4   r5   r6   r7   r8   r?   r@   rE   rY   rZ   MutableMappingr[   r   r   r   r   r   S_IRWXUS_IRWXGS_IRWXOr   r   r   r   r	  r   r   r   rm   r   r   r2  r5  r7  r=  r>  rD  rS  Z
PrefixSpecZGlobSpecZCommentSpecr   _fieldsrT  rZ  rV  ZSUPPORT_32BIT_PLATFORMSrY  rZ  r  r[  r\  r]  r^  ra  rb  rk  r   rl  rv  r|  r}  rj  r  r  rL  r  r  r  r  r_   rj   r   r  r  r  r  r  r  r  r   r  r  r  rS   rV   r  r  r  r  ZFALSISHZTRUISHZ
DEFAULTISHr  r  r  r  r  r!  r"  r#  r0  r<  r  rB  rC  rO  rr  r  r  r  r  r  r  r  r  r  TextIOWrapperr  BaseExceptionr  r  r  contextmanagerr  r  r
  ZJSONEncoderri  r  r  r  r  r  rh   r  r  r  r  r  r   r  _sysr  Ztempfiler  r  r  r  r  r  r  r   r   r   r   <module>   s  +
[ 
		


		, E	+

[M
<"' 62$&	
