B
    l‚z]:<  ã               @   sÖ  d dl mZmZmZmZ d dlmZ d dlZd dlm	Z	m
Z
mZ d dlZd dlmZ d dlZd dlmZmZmZ d dlZd dlZd dlmZ d dlZd dlZdd	lmZ dd
lmZ ddlm Z m!Z! ddl"m#Z# ddl$m%Z% ddl&m'Z'm(Z(m)Z)m*Z* ddl+m,Z, ddl-m.Z. ddl/m0Z0m1Z1 ddl2m3Z3 ddl4m5Z5 ddl6m7Z7m8Z8 ddl9m:Z: e ;e<¡Z=G dd„ de>ƒZ?dd„ Z@dd„ ZAdd„ ZBdd„ ZCG d d!„ d!eDƒZEe<d"krÒd d#lFmFZF eEejGƒZHeFeH I¡ ƒ eJeH K¡ ƒ dS )$é    )Úabsolute_importÚdivisionÚprint_functionÚunicode_literals)Úliteral_evalN)ÚEACCESÚEPERMÚEROFS)Ú
itemgetter)ÚisdirÚisfileÚjoin)Údedenté   )Ú__version__)Údals)ÚgroupbyÚtake)ÚDEFAULTS_CHANNEL_NAME)Úcontext)Úensure_text_typeÚ	iteritemsÚopenÚ	text_type)Úpaths_equal)Ú
PrefixData)ÚCondaHistoryErrorÚNotWritableError)Útouch)Údist_str_to_quad)ÚVersionOrderÚversion_relation_re)Ú	MatchSpecc               @   s   e Zd ZdS )ÚCondaHistoryWarningN)Ú__name__Ú
__module__Ú__qualname__© r'   r'   ú,lib/python3.7/site-packages/conda/history.pyr#   $   s   r#   c          
   C   sX   |   dt d¡ ¡ |   dd dd„ tjD ƒ¡ ¡ |   dd td	t d¡ƒ¡ ¡ d S )
Nz==> %s <==
z%Y-%m-%d %H:%M:%Sz
# cmd: %s
ú c             s   s   | ]}t |ƒV  qd S )N)r   )Ú.0Úsr'   r'   r(   ú	<genexpr>*   s    zwrite_head.<locals>.<genexpr>z# conda version: %s
Ú.é   )	ÚwriteÚtimeZstrftimer   ÚsysÚargvr   ÚCONDA_VERSIONÚsplit)Úfor'   r'   r(   Ú
write_head(   s     r6   c             C   s   t dd„ | D ƒƒS )Nc             s   s   | ]}|  d ¡V  qdS ))ú-ú+N)Ú
startswith)r*   r+   r'   r'   r(   r,   /   s    zis_diff.<locals>.<genexpr>)Úany)Úcontentr'   r'   r(   Úis_diff.   s    r<   c       
      c   s
  i }i }xj| D ]b}|dd … }t |ƒ\}}}}|tkrB|d| 7 }| d¡rZ||| ¡ < q| d¡r||| ¡ < qW t|ƒt|ƒ@ }	x(t|	ƒD ]}d||| || f V  qŽW x*tt|ƒ|	 ƒD ]}d||| f V  qÀW x*tt|ƒ|	 ƒD ]}d||| f V  qìW d S )Nr   z (%s)r7   r8   z %s  {%s -> %s}z-%s-%sz+%s-%s)r   r   r9   ÚlowerÚsetÚsorted)
ZdiffÚaddedÚremovedr+   ÚfnÚnameÚversionÚ_ÚchannelÚchangedr'   r'   r(   Úpretty_diff2   s$    


rH   c             C   s    t | ƒrt| ƒS tt| ƒƒS d S )N)r<   rH   Úiterr?   )r;   r'   r'   r(   Úpretty_contentG   s    rJ   c               @   s¾   e Zd Ze d¡Ze d¡Ze d¡Zdd„ Zdd„ Z	dd	„ Z
d
d„ Zdd„ Zdd„ Zdd„ Zedd„ ƒZedd„ ƒZdd„ Zdd„ Zdd„ Zd)dd„Zdd „ Zd!d"„ Zd#d$„ Zd*d&d'„Zd(S )+ÚHistoryz#\s*cmd:\s*(.+)z#\s*(\w+)\s*specs:\s*(.+)?z#\s*conda version:\s*(.+)c             C   s$   || _ t|dƒ| _t| jdƒ| _d S )Nz
conda-metaÚhistory)Úprefixr   Úmeta_dirÚpath)ÚselfrM   r'   r'   r(   Ú__init__T   s    zHistory.__init__c             C   s   |   ¡  | S )N)Úinit_log_file)rP   r'   r'   r(   Ú	__enter__Y   s    zHistory.__enter__c             C   s   |   ¡  d S )N)Úupdate)rP   Úexc_typeÚ	exc_valueÚ	tracebackr'   r'   r(   Ú__exit__]   s    zHistory.__exit__c             C   s   t | jdƒ d S )NT)r   rO   )rP   r'   r'   r(   rR   `   s    zHistory.init_log_filec             C   s   t  | j¡jdkS )Nr   )ÚosÚstatrO   Úst_size)rP   r'   r'   r(   Úfile_is_emptyc   s    zHistory.file_is_emptyc          
   C   sÄ   yzyt |  ¡ ƒ}W n8 tk
rJ } zt d| j|f t¡ dS d}~X Y nX t| jƒ}t dd„ | 	¡ D ƒƒ}|  
||¡ W nD tk
r¾ } z&|jtttfkr¬t| j|jƒ‚n‚ W dd}~X Y nX dS )zK
        update the history file (creating a new one if necessary)
        zError in %s: %sNc             s   s   | ]}|  ¡ V  qd S )N)Zdist_str)r*   Z
prefix_recr'   r'   r(   r,   r   s    z!History.update.<locals>.<genexpr>)r>   Ú	get_stater   ÚwarningsÚwarnrO   r#   r   rM   Úiter_recordsÚwrite_changesÚEnvironmentErrorÚerrnor   r   r	   r   )rP   ZlastÚeZpdZcurrr'   r'   r(   rT   f   s    
zHistory.updatec          	   C   sÂ   g }t | jƒs|S t d¡}t| jƒ}| ¡  ¡ }W dQ R X x~|D ]v}| ¡ }|sVqD| |¡}|r~| 	| 
d¡tƒ g f¡ qD| d¡rœ|d d  	|¡ qDt|ƒdkrD|d d  |¡ qDW |S )z„
        parse the history file and return a list of
        tuples(datetime strings, set of distributions/diffs, comments)
        z==>\s*(.+?)\s*<==Nr   ú#éÿÿÿÿé   r   )r   rO   ÚreÚcompiler   ÚreadÚ
splitlinesÚstripÚmatchÚappendÚgroupr>   r9   ÚlenÚadd)rP   ÚresZsep_patÚfÚlinesÚlineÚmr'   r'   r(   Úparsez   s$    




zHistory.parsec             C   sL   g }xB|   d¡D ]4}t |¡r:|r:d |d |g¡|d< q| |¡ qW |S )zÖ
        Parse specifications string that use conda<4.5 syntax.

        Examples
        --------
          - "param >=1.5.1,<2.0'"
          - "python>=3.5.1,jupyter >=1.0.0,<2.0,matplotlib >=1.5.1,<2.0"
        ú,rf   )r4   r!   rm   r   rn   )Úspecs_stringÚspecsÚspecr'   r'   r(   Ú_parse_old_format_specs_string’   s    
z&History._parse_old_format_specs_stringc             C   s   i }| j  |¡}|r@| d¡ ¡ }|d  d¡r8d|d< ||d< | j |¡}|r^| d¡|d< | j |¡}|r| ¡ \}}|p‚d}||d< | d¡r t	|ƒ}nd|kr²t
 |¡}d	d
„ |D ƒ}|rÞ|dkrÞ| |d< |d< n>|rü|dkrü| |d< |d< n |r|dkr| |d< |d< |S )aH  
        Parse comment lines in the history file.

        These lines can be of command type or action type.

        Examples
        --------
          - "# cmd: /scratch/mc3/bin/conda install -c conda-forge param>=1.5.1,<2.0"
          - "# install specs: python>=3.5.1,jupyter >=1.0.0,<2.0,matplotlib >=1.5.1,<2.0"
        r   r   ZcondaÚcmdÚconda_versionÚ Úactionú[c             S   s   g | ]}|r|  d ¡s|‘qS )ú@)Úendswith)r*   r{   r'   r'   r(   ú
<listcomp>É   s    z/History._parse_comment_line.<locals>.<listcomp>)rT   ÚinstallZcreateÚupdate_specsrz   )ÚremoveZ	uninstallÚremove_specs)ZneuteredÚneutered_specs)Úcom_patrm   ro   r4   rƒ   Úconda_v_patÚspec_patÚgroupsr9   r   rK   r|   )Úclsru   Úitemrv   r2   r€   ry   rz   r'   r'   r(   Ú_parse_comment_line¦   s6    


zHistory._parse_comment_linec             C   sB  g }x€|   ¡ D ]t\}}}d|i}x |D ]}|  |¡}| |¡ q&W d|krT| |¡ ttdƒ|ƒ}| dd¡|d< | dd¡|d< qW td	d
„ |D ƒƒ}	|	r>tj	s>t
|	tdd }
d td|
 d¡ƒ¡}d tdt d¡ƒ¡}t|ƒt|ƒk r>tdƒ| jt|dœ }t| jtjƒs2|tdƒtj|dœ 7 }|tdƒ7 }|S )a4  
        return a list of user requested items.  Each item is a dict with the
        following keys:
        'date': the date and time running the command
        'cmd': a list of argv of the actual command which was run
        'action': install/remove/update
        'specs': the specs being used
        Údater}   r   r7   r'   Zunlink_distsr8   Z
link_distsc             s   s   | ]}d |kr|d  V  qdS )r~   Nr'   )r*   Úxr'   r'   r(   r,   ë   s    z,History.get_user_requests.<locals>.<genexpr>)Úkeyrf   r-   rg   a†  
                This environment has previously been operated on by a conda version that's newer
                than the conda currently being used. A newer version of conda is required.
                  target environment location: %(target_prefix)s
                  current conda version: %(conda_version)s
                  minimum conda version: %(minimum_version)s
                )Ztarget_prefixr~   Úminimum_versionzŸ
                    Update conda and try again.
                        $ conda install -p "%(base_prefix)s" "conda>=%(minimum_version)s"
                    )Úbase_prefixr”   z­
                To work around this restriction, one can also set the config parameter
                'allow_conda_downgrades' to False at their own risk.
                )rw   r   rT   rn   r   r
   ÚgetÚtupler   Zallow_conda_downgradesr?   r    r   r   r4   r3   r   rM   r   Zroot_prefixr   )rP   rr   ÚdtZunused_contZcommentsr   ru   Zcomment_itemsZdistsZconda_versions_from_historyZminimum_conda_versionZminimum_major_minorZcurrent_major_minorÚmessager'   r'   r(   Úget_user_requestsÔ   s<    	



zHistory.get_user_requestsc                sÒ   i }x–|   ¡ D ]Š}dd„ | dd¡D ƒ}x|D ]}| |jd ¡ q.W dd„ | dd¡D ƒ}| dd„ |D ƒ¡ dd„ | d	d¡D ƒ}| d
d„ |D ƒ¡ qW tdd„ t| jƒ ¡ D ƒƒ‰ t	‡ fdd„t
|ƒD ƒƒS )Nc             s   s   | ]}t |ƒV  qd S )N)r"   )r*   r{   r'   r'   r(   r,     s    z2History.get_requested_specs_map.<locals>.<genexpr>rˆ   r'   c             s   s   | ]}t |ƒV  qd S )N)r"   )r*   r{   r'   r'   r(   r,     s    r†   c             s   s   | ]}|j |fV  qd S )N)rC   )r*   r+   r'   r'   r(   r,     s    c             s   s   | ]}t |ƒV  qd S )N)r"   )r*   r{   r'   r'   r(   r,     s    r‰   c             s   s   | ]}|j |fV  qd S )N)rC   )r*   r+   r'   r'   r(   r,     s    c             s   s   | ]}|j V  qd S )N)rC   )r*   rE   r'   r'   r(   r,   !  s    c             3   s"   | ]\}}|ˆ kr||fV  qd S )Nr'   )r*   rC   r{   )Úprefix_recsr'   r(   r,   "  s    )rš   r–   ÚpoprC   rT   r>   r   rM   r`   Údictr   )rP   Zspec_mapZrequestrˆ   r{   r†   r‰   r'   )r›   r(   Úget_requested_specs_map  s    
zHistory.get_requested_specs_mapc             C   sž   g }t g ƒ}xŒ|  ¡ D ]€\}}}t|ƒs.|}nVxT|D ]L}| d¡rV| |dd… ¡ q4| d¡rt| |dd… ¡ q4td| ƒ‚q4W | || ¡ f¡ qW |S )zQ
        return a list of tuples(datetime strings, set of distributions)
        r7   r   Nr8   zDid not expect: %s)	r>   rw   r<   r9   Údiscardrq   r   rn   Úcopy)rP   rr   Zcurr˜   ZcontÚ
unused_comr+   r'   r'   r(   Úconstruct_states$  s    


zHistory.construct_statesrf   c             C   s(   |   ¡ }|stg ƒS t|Ž \}}|| S )zé
        return the state, i.e. the set of distributions, for a given revision,
        defaults to latest (which is the same as the current state when
        the log file is up-to-date)

        Returns a list of dist_strs
        )r¢   r>   Úzip)rP   ÚrevZstatesÚtimesZpkgsr'   r'   r(   r]   8  s
    zHistory.get_statec             C   sZ   xTt |  ¡ ƒD ]D\}\}}}td||f ƒ xt|ƒD ]}td| ƒ q6W tdƒ qW d S )Nz%s  (rev %d)z    %sr   )Ú	enumeraterw   ÚprintrJ   )rP   Úir‘   r;   r¡   ru   r'   r'   r(   Ú	print_logF  s
    zHistory.print_logc          	   C   sÎ  g }xÂt |  ¡ ƒD ]°\}\}}}||g g g g dœ}i }i }t|ƒršx^|D ]V}	t|	dd … ƒ\}
}}}|	 d¡rˆ|||f||
 ¡ < qN|	 d¡rN|||f||
 ¡ < qNW t|ƒt|ƒ@ }xjt|ƒD ]^}
||
 }||
 }d |
f| ¡d |
f| ¡dœ}||kr|d  	|¡ qÂ|d  	|¡ qÂW x8tt|ƒ| ƒD ]$}
|d  	d |
f||
  ¡¡ q6W x\tt|ƒ| ƒD ]$}
|d	  	d |
f||
  ¡¡ qpW n"x t|ƒD ]}	|d	  	|	¡ q¤W | 	|¡ qW |S )
N)r‘   r¤   r…   r‡   ÚupgradeÚ	downgrader   r8   r7   )ÚoldÚnewrª   r«   r‡   r…   )
r¦   rw   r<   r   r9   r=   r>   r?   r   rn   )rP   Úresultr¨   r‘   r;   r¡   Zeventr@   rA   ÚpkgrC   rD   ZbuildrF   rG   r¬   r­   Zdetailsr'   r'   r(   Ú
object_logM  sD     




$&zHistory.object_logc          	   C   sˆ   t | jƒst | j¡ tj| jdddV}t|ƒ x"t|| ƒD ]}| 	d| ¡ q@W x"t|| ƒD ]}| 	d| ¡ qdW W d Q R X d S )NÚabzutf-8)ÚmodeÚencodingz-%s
z+%s
)
r   rN   rY   ÚmakedirsÚcodecsr   rO   r6   r?   r/   )rP   Z
last_stateZcurrent_stater5   rB   r'   r'   r(   ra   }  s    
zHistory.write_changesr'   c          	   C   s   dd„ |D ƒ}dd„ |D ƒ}dd„ |D ƒ}t |||fƒrŒtj| jddd<}|r^| d| ¡ |rp| d	| ¡ |r‚| d
| ¡ W d Q R X d S )Nc             S   s   g | ]}t t|ƒƒ‘qS r'   )r   r"   )r*   r+   r'   r'   r(   r„   ˆ  s    z'History.write_specs.<locals>.<listcomp>c             S   s   g | ]}t t|ƒƒ‘qS r'   )r   r"   )r*   r+   r'   r'   r(   r„   ‰  s    c             S   s   g | ]}t t|ƒƒ‘qS r'   )r   r"   )r*   r+   r'   r'   r(   r„   Š  s    r±   zutf-8)r²   r³   z# remove specs: %s
z# update specs: %s
z# neutered specs: %s
)r:   rµ   r   rO   r/   )rP   rˆ   r†   r‰   Zfhr'   r'   r(   Úwrite_specs‡  s    zHistory.write_specsN)rf   )r'   r'   r'   )r$   r%   r&   rh   ri   rŠ   rŒ   r‹   rQ   rS   rX   rR   r\   rT   rw   Ústaticmethodr|   Úclassmethodr   rš   rž   r¢   r]   r©   r°   ra   r¶   r'   r'   r'   r(   rK   N   s(   


.=
0
rK   Ú__main__)Úpprint)LZ
__future__r   r   r   r   Zastr   rµ   rc   r   r   r	   ZloggingÚoperatorr
   rY   Úos.pathr   r   r   rh   r1   Útextwrapr   r0   r^   r   r   r3   Z_vendor.auxlib.ishr   Z_vendor.toolzr   r   Zbase.constantsr   Zbase.contextr   Zcommon.compatr   r   r   r   Zcommon.pathr   Zcore.prefix_datar   Ú
exceptionsr   r   Zgateways.disk.updater   Zmodels.distr   Zmodels.versionr    r!   Zmodels.match_specr"   Z	getLoggerr$   ÚlogÚWarningr#   r6   r<   rH   rJ   ÚobjectrK   rº   rM   Úhrš   r§   rž   r'   r'   r'   r(   Ú<module>   sN   
  I

