
Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­
<!DOCTYPE html>
<html>
3
ôn»j&  ã               @   sl  d dl 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 ejdƒZdZedƒZed	ƒZedƒZd?dd„Zd@dd„Zdd„ ZdAdd„ZdBdd„Zdd„ ZdCdd„Zdedfdd„Zd d!„ Zd"d#„ Zd$d%„ Zd&d'„ Zd(d)„ Z d*d+„ Z!ed,d-„ ƒZ"d.d/„ Z#dDd0d1„Z$dEd2d3„Z%d4d5„ Z&dFd7d8„Z'd9d:„ Z(d;d<„ Z)de*fdfd=d>„Z+dS )Gé    )Úprint_functionN)Údatetimeé   )Ú	constantsz^(\d+[.]\d+[-]\d+)é   Ú ó    FÚwé¤  c       
      C   sì   t jj| ƒ}|r(t jj|ƒ r(t j|ƒ yt j| ƒj}W n tk
rP   |}Y nX tj	||t jj
| ƒd dd��<}t j|jƒ |ƒ |j|ƒ |jƒ  t j|jƒ ƒ |j}W d Q R X t j|t jƒ}	zt j|	ƒ W d t j|	ƒ X t j|| ƒ d S )NÚ.F)ÚmodeÚdirÚprefixÚdelete)ÚosÚpathÚdirnameÚexistsÚmakedirsÚstatÚst_modeÚ	ExceptionÚtempfileÚNamedTemporaryFileÚbasenameÚfchmodÚfilenoÚwriteÚflushÚfsyncÚnameÚopenÚO_RDONLYÚcloseÚrename)
ÚfnameÚcontentÚ
ensure_dirr   Zcreate_modeZdnamer   ÚfZ	tmp_fnameZ	folder_fd© r)   ú+/usr/libexec/kcare/python/kcarectl/utils.pyÚatomic_write"   s$    

 
r+   úutf-8Ústrictc             C   s8   t | ƒtkr| S t | ƒtkr(| j||ƒS | j||ƒS d S )N)ÚtypeÚntypeÚbtypeÚdecodeÚencode)ÚdataÚencodingÚerrorsr)   r)   r*   Únstr>   s
    r6   c             C   s&   t | dƒ�}t|jƒ dd�S Q R X dS )a  Read ``path`` as UTF-8 text, independent of the locale codec.

    Under a C/POSIX locale Python 3 opens text files with an ASCII codec,
    so a non-ASCII byte in the file (e.g. an em-dash in a patch-info skip
    reason) makes a plain text read raise UnicodeDecodeError. Reading the
    bytes and decoding them as UTF-8 matches how the same data is decoded
    when fetched over HTTP. A byte that is not valid UTF-8 is replaced
    rather than raising, so a malformed file degrades output instead of
    aborting the command.
    ÚrbÚreplace)r5   N)r!   r6   Úread)r   r(   r)   r)   r*   Úread_text_fileH   s    r:   Úlatin1c             C   s   t | ƒtkr| j|ƒ} | S )N)r.   Úutyper2   )r3   r4   r)   r)   r*   ÚbstrX   s    
r=   c             C   s   t | ƒtkr| j|ƒ} | S )N)r.   r0   r1   )r3   r4   r)   r)   r*   Úustr_   s    
r>   c                s4   i ‰ t jˆƒ‡ ‡fdd„ƒ}ˆ |_ˆ j|_ˆ|_|S )Nc                 sH   | t t|jƒ ƒƒf}yˆ | S  tk
r0   Y nX ˆ| |Ž }ˆ |< |S )N)ÚtupleÚsortedÚitemsÚKeyError)ÚargsÚkwargsZ	cache_keyÚresult)ÚcacheÚfnr)   r*   Úinnerj   s    zcached.<locals>.inner)Ú	functoolsÚwrapsrF   ÚclearÚorig)rG   rH   r)   )rF   rG   r*   Úcachedf   s    
rM   c                sF   ˆd krt j‰ˆd krt j‰ˆ d kr*t j‰ i ‰‡ ‡‡‡‡fdd„}|S )Nc                s   ‡‡‡‡‡ ‡fdd„}|S )Nc                 s²   ˆ}xlt ˆƒD ]`}y
ˆ| |ŽS  tk
rJ } zˆ|ˆƒs:‚ W Y d d }~X nX tj|ƒ t|tjdˆ ƒ tjƒ}qW y
ˆ| |ŽS  tk
r¬ } zt	|dˆƒ ‚ W Y d d }~X nX d S )Nr   Úattempts)
Úranger   ÚtimeÚsleepÚminÚrandomÚuniformr   ÚRETRY_MAX_DELAYÚsetattr)rC   rD   ZldelayÚ_ÚexZfinal_ex)ÚbackoffÚcheck_retryÚcountÚdelayrG   Ústater)   r*   rH   †   s    



z'retry.<locals>.decorator.<locals>.innerr)   )rG   rH   )rY   rZ   r[   r\   r]   )rG   r*   Ú	decorator…   s    zretry.<locals>.decorator)r   ÚRETRY_DELAYÚRETRY_COUNTÚRETRY_BACKOFF)rZ   r[   r\   rY   r^   r)   )rY   rZ   r[   r\   r]   r*   Úretryz   s    rb   c       
      C   sÄ   t jj| ƒsd S g }t j| ƒ}|d k	r2tj||ƒ}xD|D ]<}t jj| |ƒ}||krh|jt j|ƒj	|fƒ |j
dd� q8W xF||d … D ]6\}}	t jj|	ƒs¦t jj|	ƒr²t j|	ƒ q†tj|	ƒ q†W d S )NT)Úreverse)r   r   r   ÚlistdirÚfnmatchÚfilterÚjoinÚappendr   Úst_mtimeÚsortÚisfileÚislinkÚremoveÚshutilÚrmtree)
Z	directoryÚexclude_pathÚkeep_nÚpatternr3   rA   ÚitemÚ	full_pathrW   Úentryr)   r)   r*   Úclean_directoryž   s    

rv   c               C   sN   t tjjtjdƒdd� t tjjtjdƒdd� tjjtjƒrJtjtjƒ d S )NÚmodulesr   )rq   Úpatches)	rv   r   r   rg   r   ÚPATCH_CACHEr   ÚCACHE_KEY_DUMP_PATHÚunlinkr)   r)   r)   r*   Úclear_all_cache²   s    r|   c          
   C   s^   t jj|ƒ}t jj|ƒs"t j|ƒ t|dƒ�(}tj| |ƒ |jƒ  t j	|j
ƒ ƒ W d Q R X d S )NÚwb)r   r   r   r   r   r!   rn   Úcopyfileobjr   r   r   )ÚresponseÚdstZ
parent_dirr(   r)   r)   r*   Úsave_to_fileº   s    
r�   c             C   s   t j| ƒ}|r|jdƒp| S )Nr   )Ú
VERSION_REÚmatchÚgroup)Úversionrƒ   r)   r)   r*   Ústrip_version_timestampÅ   s    
r†   c             C   s0   | j dƒ\}}}|s$| j dƒ\}}}tj|dƒS )NÚTú z%Y-%m-%d)Ú	partitionr   Ústrptime)Zstr_rawZstr_dateÚseprW   r)   r)   r*   Úparse_response_dateË   s    rŒ   c              G   s0   ddl m} djdd„ td |jƒ f|  ƒD ƒƒS )Nr   )Úipv6_supportú/c             s   s   | ]}|j d ƒV  qdS )rŽ   N)Ústrip)Ú.0Úitr)   r)   r*   ú	<genexpr>Ù   s    z'get_patch_server_url.<locals>.<genexpr>)r   r�   rg   rf   Úget_patch_server)Úpartsr�   r)   r)   r*   Úget_patch_server_urlÕ   s    r•   c          	   C   s0   t jj| ƒsd S t| ƒ�}|jƒ jƒ S Q R X d S )N)r   r   r   r!   r9   r�   )Úfilenamer(   r)   r)   r*   Útry_to_readÜ   s    
r—   c               C   s
   t tjƒS )N)r—   r   rz   r)   r)   r)   r*   Úget_cache_keyå   s    r˜   c          	   C   s.   t jj| ƒs|S t| |ƒ�
}|jƒ S Q R X d S )N)r   r   r   r!   r9   )r%   r   Údefaultr(   r)   r)   r*   Ú
_read_fileë   s    rš   c             C   s   t | d|ƒ}|S )NÚr)rš   )r%   r™   rE   r)   r)   r*   Ú	read_fileó   s    rœ   c             C   s   t | d|ƒ}|S )Nr7   )rš   )r%   r™   rE   r)   r)   r*   Úread_file_binù   s    r�   c             C   sB   i }| j ƒ }x0|D ](}|r|jdƒ\}}}|r|jƒ ||< qW |S )Nú:)Ú
splitlinesr‰   r�   )r3   rE   Z
data_linesÚlineÚkeyÚ	delimiterÚvaluer)   r)   r*   Údata_as_dictÿ   s    
r¤   Úcvec             C   s0   t ƒ }x$| D ]}|j|ƒ}|r|j|ƒ qW |S )a  
    Extract unique CVEs from a list of patches.

    Args:
        patches: List of patch dictionaries
        cve_field: Field name to extract CVE from (default 'cve' for userspace, 'kpatch-cve' for kernel)

    Returns:
        Set of unique CVE strings
    )ÚsetÚgetÚadd)rx   Ú	cve_fieldZunique_cvesÚpatchr¥   r)   r)   r*   Úextract_unique_cves  s    

r«   c               C   s   t ttjƒ ƒƒS )N)ÚstrÚintrP   r)   r)   r)   r*   Útimestamp_str  s    r®   c              G   s   t | Ž  dS )za workaround to fix T201N)Úprint)Úvaluesr)   r)   r*   Úprint_wrapper$  s    r±   c                s   ‡ ‡‡fdd„}|S )Nc                s    t jˆ ƒ‡‡‡ ‡fdd„ƒ}|S )Nc                 sn   y
ˆ| |ŽS  ˆk
rh } zBˆrZdd„ | D ƒdd„ |j ƒ D ƒ }ˆdjˆjdj|ƒ|ƒƒ ˆ S d }~X nX d S )Nc             S   s   g | ]}t |ƒ‘qS r)   )r¬   )r�   Úar)   r)   r*   ú
<listcomp>6  s    zBcatch_errors.<locals>.decorator.<locals>.inner.<locals>.<listcomp>c             S   s   g | ]\}}d j ||ƒ‘qS )z{0}={1})Úformat)r�   ÚkÚvr)   r)   r*   r³   6  s    z{0}({1}) failed: {2}z, )rA   r´   Ú__name__rg   )rC   rD   ÚeÚarg_list)Údefault_returnr5   rG   Úloggerr)   r*   rH   /  s    
 z.catch_errors.<locals>.decorator.<locals>.inner)rI   rJ   )rG   rH   )rº   r5   r»   )rG   r*   r^   -  s    zcatch_errors.<locals>.decoratorr)   )r»   r5   rº   r^   r)   )rº   r5   r»   r*   Úcatch_errors*  s    r¼   )Fr	   r
   )r,   r-   )r;   )r;   )NNN)N)N)r¥   ),Ú
__future__r   re   rI   r   rS   Úrern   r   rP   r   r   r   Úcompiler‚   ZCACHE_ENTRIESr.   r/   r0   r<   r+   r6   r:   r=   r>   rM   rb   rv   r|   r�   r†   rŒ   r•   r—   r˜   rš   rœ   r�   r¤   r«   r®   r±   r   r¼   r)   r)   r)   r*   Ú<module>   sL   






$
	


