o
    +ke!                     @   sN  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mZ d dl	m	Z	m
Z
mZ d dlmZ d dlmZ ddlmZ e 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mZ dd Zeg dZd)ddZdd Ze j edddZ!dd Z"G dd dZ#dd Z$dd Z%d)d d!Z&G d"d# d#ej'Z(d*d%d&Z)d'd( Z*dS )+    N)dequeOrderedDict)datetimetimezone	timedelta)islice)
attrgetter   )create_logger   )to_localtime)msgpack)__version__)chunker)
CH_BUZHASHCH_FIXEDc                 C   sZ   t tjt|d d }d}g }| D ]}|j|kr*|d7 }d|f||j< || q|S )Ni  )secondsr   r   Zwithin)r   nowr   utcr   tsidappend)archiveshourskept_becausetargetZkept_counterresulta r   5usr/lib/python3.10/site-packages/borg/helpers/misc.pyprune_within   s   

r    ))Zsecondlyz%Y-%m-%d %H:%M:%S)Zminutelyz%Y-%m-%d %H:%M)Zhourlyz%Y-%m-%d %H)Zdailyz%Y-%m-%d)Zweeklyz%G-%V)Zmonthlyz%Y-%m)Zyearlyz%Yc           	      C   s   d }g }t | }|d u ri }|dkr|S d }t| tdddD ]+}t|j|}||krJ|}|j|vrJ|| |t|f||j< t||krJ nq|d urjt||k rj|j|vrj|| |d t|f||j< |S )Nr   r   T)keyreversez[oldest])	PRUNING_PATTERNSsortedr   r   r   strftimer   r   len)	r   Zrulenr   lastZkeeppatternr   Zperiodr   r   r   prune_split-   s,   


r*   c               	   C   sx  t jdd } | dkrdS t }t }zt  }W n ty(   d }Y nw t	j
dr2d}nd }zddd	 tjD }W n   d
}Y ddlm}m} |rU|jnd}|r^d|j nd}	| |	 d| d}
g }|d ur{|dd| |d ur|d|  |dt||||
 |dt  t  f  |dt	j  |dt jd  |d d|S )NZBORG_SHOW_SYSINFOyesno linux)zUnknown Linuxr-   r-   .c                 s   s    | ]}t |V  qd S N)str).0vr   r   r   	<genexpr>Y   s    zsysinfo.<locals>.<genexpr>unknownr	   )llfuseBORG_FUSE_IMPLNonez %sz []zPlatform: {} zLinux: %s %s %sz,Borg: {}  Python: {} {} msgpack: {} fuse: {}zPID: %d  CWD: %szsys.argv: %rzSSH_ORIGINAL_COMMAND: %rZSSH_ORIGINAL_COMMAND
)osenvirongetlowerplatformpython_implementationpython_versionunameAttributeErrorsys
startswithjoinr   versionZ	fuse_implr6   r7   __name__r   r   formatborg_versiongetpidgetcwdargv)Zshow_sysinforA   rB   rC   Zlinux_distributionZmsgpack_versionr6   r7   Zllfuse_nameZllfuse_versionZllfuse_infoinfor   r   r   sysinfoG   sD   


rP   )levelloggerc                 G   s6   g }|D ]	}| |  q|D ]}|| | q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)rQ   rR   Zmsgslinesmsgliner   r   r   	log_multin   s   rY   c                 C   s`   t | ttfs	J t | trt| } t| dkr$t | d tr$tf|  } | d ttfv s.J | S )N   r   )
isinstancelisttupler&   intr   r   )cpr   r   r   normalize_chunker_params{   s   

r`   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_offsetchunk	exhaustedread_callback)selfrc   rg   r   r   r   __init__   s
   	
z!ChunkIteratorFileWrapper.__init__c                 C   s\   t | j| j }|s,zt| j}t|| _W n ty#   d| _Y dS w d| _t | j}|S )NTr   )r&   re   rd   nextrc   
memoryviewStopIterationrf   )rh   	remainingre   r   r   r   _refill   s   

z ChunkIteratorFileWrapper._refillc                 C   s>   |sdS |   }t||}|  j|7  _| j| j| | j S Nrb   )rn   minrd   re   )rh   nbytesrm   Z	will_readr   r   r   _read   s   
zChunkIteratorFileWrapper._readc                 C   sR   g }|r$| j s$| |}|t|8 }|| | jr| | |r$| j rd|S ro   )rf   rr   r&   r   rg   rG   )rh   rq   partsZ	read_datar   r   r   read   s   





zChunkIteratorFileWrapper.readr0   )rI   
__module____qualname____doc__ri   rn   rr   rt   r   r   r   r   ra      s    
ra   c                 C   s    | j dd |jD }t|S )z8Return file-like object for archived item (with chunks).c                 S   s   g | ]}|j qS r   )r   )r2   cr   r   r   
<listcomp>   s    zopen_item.<locals>.<listcomp>)ZpipelineZ
fetch_manychunksra   )archiveitemrc   r   r   r   	open_item   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 r0   )r\   r   r   iterablesizer   r   <lambda>   s    zchunkit.<locals>.<lambda>)iter)itr   r   r~   r   chunkit   s   r   c                 C   s.   |du rt | dd dS tt| ||d dS )zCAdvance the iterator n-steps ahead. If n is none, consume entirely.Nr   )maxlen)r   rj   r   )iteratorr'   r   r   r   consume   s   r   c                       s(   e Zd Z fddZ fddZ  ZS )ErrorIgnoringTextIOWrapperc                    sR   | j s'zt |W S  ty&   z	t   W Y dS  ty%   Y Y dS w w dS )Nr-   )closedsuperrt   BrokenPipeErrorcloseOSError)rh   r'   	__class__r   r   rt      s   zErrorIgnoringTextIOWrapper.readc                    sb   | j s-zt |W S  ty,   zt   W n	 ty!   Y nw Y t|S Y t|S w t|S r0   )r   r   writer   r   r   r&   )rh   sr   r   r   r      s   z ErrorIgnoringTextIOWrapper.write)rI   ru   rv   rt   r   __classcell__r   r   r   r   r      s    r      c           	      c   s    |  |}t|t}|rdnd}|p|rdnd}t|dkrA||^}}|| g|R ^ }}|E dH  |  |}t|dkst|dkrL|V  dS dS )zHIter over chunks of open file ``fd`` delimited by ``sep``. Doesn't trim.r-   rb   r;      
r   N)rt   r[   r1   r&   split)	fdsepZ	read_sizebufZis_strpartZpart2itemsfullr   r   r   iter_separated   s   




r   c                 C   s   |  dr|r	dnd}n2|  dr|rdnd}n&|  dr$|r!dnd	}n|  d
r0|r-dnd}n|  dr<|r9dnd}nd }td| |S )N)z.tar.gzz.tgzzgzip -dgzip)z.tar.bz2z.tbzzbzip2 -dbzip2)z.tar.xzz.txzzxz -dxz)z.tar.lz4zlz4 -dlz4)z	.tar.zstdz.tar.zstzzstd -dzstdz'Automatically determined tar filter: %s)endswithrR   debug)fname
decompressfilterr   r   r   get_tar_filter   s   




r   r0   )Nr   )+loggingior<   os.pathr@   rE   collectionsr   r   r   r   r   	itertoolsr   operatorr   rR   r
   timer   r-   r   r   rK   r   	constantsr   r   r    r#   r*   rP   INFOrY   r`   ra   r}   r   r   TextIOWrapperr   r   r   r   r   r   r   <module>   s<    
'2

