
    dCA                        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mZmZ d dlmZmZmZmZ d dlmZ d dlmZmZmZmZmZmZmZmZmZmZ d dl m!Z!m"Z"m#Z#m$Z$m%Z% d dl&m'Z'm(Z(m)Z)m*Z* d dl+m,Z,m-Z- ej.        d	k    Z/ ej0        e1          Z2d
Z3d Z4d Z5 G d de          Z6d Z7d Z8d(dZ9d Z:d Z;d Z<d)dZ=e=xZ>xZ?Z@d ZAd ZB G d d          ZCe jD        d             ZEd ZF	 d*dZGd ZHd+d!ZId" ZJd# ZKd,d%ZLd,d&ZMd' ZNdS )-    N)ExecutorProcessPoolExecutorThreadPoolExecutor)EACCESENOENTEPERMEROFS)chain)
abspathbasenamedirnameisdirisfileislinkjoinlexistsnormpathsplit)S_IEXECS_IMODES_ISDIRS_ISREGS_IWRITE)STDOUTCalledProcessErrorcheck_outputlist2cmdline)NamedTemporaryFilemkdtempwin32z.c~c                 $    ddl m}  ||           S )Nr   )find_executable)distutils.spawnr"   )
executabler"   s     <lib/python3.11/site-packages/conda_package_handling/utils.pywhichr&   "   s$    //////?:&&&    c                    	 t          j        |           j        }t          |          r3t          j        | t          |          t          z  t          z             ndt          |          st          |           r+t          j        | t          |          t          z             nt                              d|            dS # t          $ r}t          |dd           }|t          fv rt                              d|             |t          t           t"          fv r"t                              d| |           Y d }~dS t                              d| |            d }~ww xY w)Nz path cannot be made writable: %sTerrnoz,tried to make writable, but didn't exist: %sz%tried make writable but failed: %s
%rFz!Error making path writable: %s
%r)oslstatst_moder   chmodr   r   r   r   r   logdebug	Exceptiongetattrr   r   r   r	   warn)pathmodeeenos       r%   make_writabler7   (   sG   x~~%4== 	@HT74==83g=>>>>T]] 	@fTll 	@HT74==834444II8$???t 
 
 
a$''6)IIDdKKKVUE***II>aHHH55555HH94CCC
s   B?C 
EA)E<EEc                       e Zd Zd ZdS )DummyExecutorc              '   8   K   |D ]}|D ]} ||          V  d S N )selffunc	iterablesiterablethings        r%   mapzDummyExecutor.map@   sJ      ! 	" 	"H! " "d5kk!!!!"	" 	"r'   N)__name__
__module____qualname__rB   r<   r'   r%   r9   r9   ?   s#        " " " " "r'   r9   c                 J    | dk    rt                      nt          |           S )N   max_workers)r9   r   )	processess    r%   get_executorrK   F   s%    '1nn=???2ER[2\2\2\\r'   c                 
   t          |           r[t          j        |           D ]D\  }}}t          j        ||f          D ]'} 	 t          t          ||                      !#  Y %xY wEd S 	 t          |            d S #  Y d S xY wr;   )r   r*   walkr
   from_iterabler7   r   )r3   rootdirsfiless       r%   recursive_make_writablerR   J   s     T{{ !# 	 	D$+UDM::  !$tT"2"23333D		 		$	DDs   A!!A%,A= =Bc                    |st           rdnd}|dk    rt          |           S g }| D ]Kdv rd}n'dv rd}n t          fddD                       sd}nd}|                    |z   |z              Ld                    |          S )	Ncmd.exebash"'c              3       K   | ]}|v V  	d S r;   r<   ).0_args     r%   	<genexpr>z"quote_for_shell.<locals>.<genexpr>n   s'      77ac777777r'   ) 
 r]   )on_winr   anyappendr   )	argumentsshellquotedquoter[   s       @r%   quote_for_shellrg   \   s     0#/			I&&&   		/ 		/Cczz7777;77777 MM%#+-....xxr'   c           
         t          |           } t          r	 t          d|  ddt                    }nC#  	 d }t	          dd          5 }|                    dt          | g           d	           |                    d
           |                    dt          | g           d	           |                    d           |j        }d d d            n# 1 swxY w Y   t          |          5 }|	                                }| |v sJ 	 d d d            n# 1 swxY w Y   t          j        d         }d}	t          |dd|gdd d d |	          }n`# t          $ rS}
|
j        dk    r!t                              d|  d|             t                              d|            Y d }
~
nd }
~
ww xY wY nxY w	 t          j        d           n#  Y nxY wt%          d          }|rt'          d          r	 t          |dddt)          t          j                    d          dz   | dz   gt                    }n-# t          $ r  t                              d|            Y nw xY wt-          j        d           t-          j        |            d S )Nz
RD /S /Q "z" > NUL 2> NULT)rd   stderr.batF)suffixdeletezRD /S r^   zchcp 65001
zEXIT 0
COMSPECi   z/dz/c)rd   stdoutri   stdincreationflags   zRemoving folder z# the fast way failed.  Output was: z8removing dir contents the fast way failed.  Output was: z.emptyrsyncz-az--forcez--delete/ri   )r   r`   r   r   r   writerg   nameopenreadr*   environr   
returncoder.   errorr/   makedirsr&   r   r   getcwdshutilrmtree)r3   argskwargsoutrv   
batch_filecontentscontentcomspecCREATE_NO_WINDOWr5   rr   s               r%   r   r   v   s   D>>D H$.	` @D@@@U[\\\CC#	`"`'veDDD +
$$%Iotf.E.E%I%I%IJJJ$$^444$$%Iotf.E.E%I%I%IJJJ$$Z000%?D+ + + + + + + + + + + + + + + $ZZ +8&mmooG7?????+ + + + + + + + + + + + + + + *Y/#-  #dD$/"2   & ` ` `<1$$II___Z]__```II^Y\^^________`	K!!!!	D g 	$U8__ 	$\"!"RY[[(33c9s
 "
 
 
 & \ \ \		ZUXZZ[[[[[\M(###
M$s   6 F5EB CEC	EC	 E2DED	E!D	"0EF5
F0A	F+&F5+F00F59G G6AH8 8'I"!I"c                    	 t          |            t          j        |            dS # t          $ r 	 t          j        | | dz              Y dS # t          $ r t
          rIt          d          5 }t          |d          5 }|                    d           |                    d           |                    d           ddd           n# 1 swxY w Y   t          |           \  }}| dz   }d	}t          |          r'|j        d
         d| z   }|d	z  }t          |          'd}	 t          dd|||t          |          gt                    }n># t          $ r1 t                               d                    | |                     Y nw xY wddd           n# 1 swxY w Y   t                               d                    |                      Y Y dS w xY ww xY w)zIf files are in use, especially on windows, we can't remove them.
    The fallback path is to rename them (but keep their folder the same),
    which maintains the file handle validity.  See comments at:
    https://serverfault.com/a/503769
    z.conda_trashrj   )rk   wz@pushd "%1"
z@REM Rename src to destz@ren "%2" "%3" > NUL 2> NUL")NrG   r   z.conda_trash_z	< empty >rT   z/Crt   z6renaming file path {} to trash failed.  Output was: {}znCould not remove or rename {}.  Please remove this file manually (you may need to reboot to free file handles))r7   r*   unlinkOSErrorrenamer`   r   rw   ru   r   r   splitextr   r   r   r   r.   r2   format)r3   trash_scriptf_dirname_fndest_fncounterr   s           r%   unlink_or_rename_to_trashr      s   -d
	$ * * *)	IdD>1222222 '	 '	 '	 ! (v666 ,lC00 AA000 9::: ?@@@A A A A A A A A A A A A A A A
 %*$KKMHc"^3GG // %")"21"58Q8Q8Q"Q1 !// % &C* ) $ , ( # ( 1 1 $*
 
 
 .   T[[ $c     3              @ HH;;A6$<<      I'	*s   #' G A#G1FA C	FCFCAF+)EF8F	FF	FGF##G&F#'0GG GG c                     t          |           }t          |          rWt          j        |          sGt	          |           t          |          }t          |          rt          j        |          Ad S d S d S d S r;   )r   r   r*   listdirrmdir)r3   parent_paths     r%   remove_empty_parent_pathsr      s    $--K


 +RZ%<%< +kk** 

 +RZ%<%< + + + + + + + + +r'   Fc                 2   t          |            	 t          |           } t          |           rt          |           st	          |            n:t          |           rt          |            nt                              d|            t          |           rt          	                    d|            dS n3# t          |           rt          	                    d|             Y dS w xY wt          |           rt          |            |rt          |            dS )z
    Completely delete path
    max_retries is the number of times to retry on failure. The default is 5. This only applies
    to deleting a directory.
    If removing path fails and trash is True, files will be moved to the trash directory.
    z0rm_rf failed. Not a link, file, or directory: %szrm_rf failed for %sFT)rR   r   r   r   r   r   r   r.   r/   infodelete_trashr   )r3   clean_empty_parentsr   kws       r%   rm_rfr     s    D!!!t}};; 	Pvd|| 	P$KKKKT]] 	P%d++++IIH$OOO4== 	HH*D1115	74== 	HH*D1115555555T{{ T (!$'''4s   A7B5 5,C%$C%c           	         | st           j        } dht          j        | d          D ]\  }}}fd|D             |d d <   |D ]}t	          j        |d          st	          j        |dt
          z             rnt          ||          }	 t          j        |           t          |           i# t          $ r,}t                              d||j        |           Y d }~d }~ww xY wd S )NenvsTtopdownc                     g | ]}|v|	S r<   r<   )rY   dexcludes     r%   
<listcomp>z delete_trash.<locals>.<listcomp>'  s#    777aw&6&61&6&6&6r'   z*.conda_trash**z%r errno %d
Cannot unlink %s.)sysprefixr*   rM   fnmatchCONDA_TEMP_EXTENSIONr   r   r   r   r.   r/   r)   )r   rO   rP   rQ   fnfilenamer5   r   s          @r%   r   r   "  sB    hGWVT::: V VdE7777d777QQQ 		V 		VBr#344 VC..9 9 V  b>>VIh'''-h7777 V V VII>17HUUUUUUUUVV		VV Vs   	#B--
C#7"CC#c                     t          |           sd S 	 t          |            n#  Y nxY wt          j        | d          D ](\  }}}|D ]}t	          t          ||                      )d S )NFr   )r   r   r*   rM   r   r   )dirpathrO   rP   rQ   r   s        r%   r   r   4  s    >> wWWe<<< 5 5dE 	5 	5A%d4mm4444	55 5s   # 'c                   f    e Zd ZdZdZdZdd ej                    fdZd Z	d Z
defd	Zd
 Zd ZdS )TemporaryDirectorya+  Create and return a temporary directory.  This has the same
    behavior as mkdtemp but can be used as a context manager.  For
    example:

        with TemporaryDirectory() as tmpdir:
            ...

    Upon exiting the context, the directory and everything contained
    in it are removed.
    NFr_   z.cph_tmpc                 2    t          |||          | _        d S r;   )r   rv   )r=   rk   r   dirs       r%   __init__zTemporaryDirectory.__init__T  s    FFC00			r'   c                 2    d| j         j         d| j        dS )N<r]   >)	__class__rC   rv   r=   s    r%   __repr__zTemporaryDirectory.__repr__W  s"    ;4>*;;TY;;;;r'   c                     | j         S r;   )rv   r   s    r%   	__enter__zTemporaryDirectory.__enter__Z  s
    yr'   c                     | j         rg| j        sb	 t          | j                    n#   |j        d| j         z             Y nxY wd| _        |r&|j        r! |j        d| |j                   d S d S d S d S d S )NzConda-package-handling says: "I tried to clean up, but I could not.  There is a mess in %s that you might want to clean up yourself.  Sorry..."TzImplicitly cleaning up )rv   _closedr   r2   ResourceWarning)r=   _warn	_warningss      r%   cleanupzTemporaryDirectory.cleanup]  s    9 	T\ 	di    	<>BiH    
  DL  	6d66-    	 	 	 	   s	   % Ac                 .    |                                   d S r;   r   )r=   excvaluetbs       r%   __exit__zTemporaryDirectory.__exit__n  s    r'   c                 2    |                      d           d S )NT)r   r   r   s    r%   __del__zTemporaryDirectory.__del__q  s    4     r'   )rC   rD   rE   __doc__rv   r   r*   r}   r   r   r   r   r   r   r   r<   r'   r%   r   r   D  s        	 	 DG  1 1 1 1< < <   "Y    "  ! ! ! ! !r'   r   c              #      K   t          j                    }	 t          j        |            d V  t          j        |           d S # t          j        |           w xY wr;   )r*   r}   chdir)destcurdirs     r%   	tmp_chdirr   v  sX      Y[[F

s   A Ac                 `    t          | t                    st          | d          s| | g} ng } | S )N__iter__)
isinstancestrhasattr)r[   s    r%   ensure_listr     s=    #s 73
#;#; ?%CCCJr'   z(.*[\\\\/])?\.git[\\\\/].*z(.*[\\\\/])?\.git$z(.*)?\.DS_Store.*z.*\.la$zconda-meta.*c                     |D ]H}t          j        |          }t          |           t          t          |j        |                     z
  } Ifd| D             S )zIRemove things like the .git directory from the list of files to be copiedc                    g | ]~}t           j                            t           j                            |                    s=t           j                            t           j                            |                    ||S r<   )r*   r3   r   r   r   )rY   r   r   s     r%   r   z filter_files.<locals>.<listcomp>  sy        	rw||FA..//
 8:w}}RW\\RXZ[E\E\7]7]	  r'   )recompilesetfiltermatch)
files_listr   filter_patternspatternrs    `   r%   filter_filesr     sv     # H HJw__s6!':+F+F'G'GG

      r'   c                 &    t          | |d          S )N)zinfo[\\/]index\.jsonzinfo[\\/]fileszinfo[\\/]paths\.jsonzinfo[\\/]about\.jsonzinfo[\\/]has_prefixzinfo[\\/]hash_input_fileszinfo[\\/]hash_input\.jsonzinfo[\\/]run_exports\.yamlzinfo[\\/]run_exports\.jsonzinfo[\\/]gitzinfo[\\/]recipe[\\/].*zinfo[\\/]recipe_log.jsonzinfo[\\/]recipe.tarzinfo[\\/]test[\\/].*zinfo[\\/]LICENSE.*zinfo[\\/]requireszinfo[\\/]metazinfo[\\/]platformzinfo[\\/]no_linkzinfo[\\/]link\.jsonzinfo[\\/]icon\.png)r   )r   )r   r   s     r%   filter_info_filesr     s$    
   r'      c                      t          t          |          }|st          d|            |            }t           fdd          D ]}|                    |           |                                S )NzUnrecognized hash algorithm: c                  .                                    S r;   )rx   )
buffersizefds   r%   <lambda>z_checksum.<locals>.<lambda>  s    bggj11 r'   r'   )r1   hashlib
ValueErroriterupdate	hexdigest)r   	algorithmr   	hash_implblocks   ` `  r%   	_checksumr     s    ++I  DDDEEEIKK	11111377       r'   c                 "    t          | d          S )Nsha256r   r   s    r%   sha256_checksumr     s    R"""r'   c                 "    t          | d          S )Nmd5r   r   s    r%   md5_checksumr     s    Rr'      c                 x    t          | d          5 }t          |||          cddd           S # 1 swxY w Y   dS )zA
    Calculate a checksum for a filename (not an open file).
    rbN)rw   r   )r   r   r   r   s       r%   checksumr    s     
b$ 42Y
334 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4s   /33c                      t          t          |                    5  fd|D             }ddd           n# 1 swxY w Y   d |D             S )zB
    Calculate multiple checksums for a filename in parallel.
    rH   c                 J    g | ]}                     t          |           S r<   )submitr  )rY   r   r   r5   r   s     r%   r   zchecksums.<locals>.<listcomp>  s+    ]]]Y188Hb)Z@@]]]r'   Nc                 6    g | ]}|                                 S r<   )result)rY   r  s     r%   r   zchecksums.<locals>.<listcomp>  s     222FMMOO222r'   )r   len)r   
algorithmsr   resultsr5   s   ` ` @r%   	checksumsr    s     
J	8	8	8 ^A]]]]]]R\]]]^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 32'2222s   >AAc                 >    d| _         d| _        d| _        d| _        | S )z,
    Remove user id, name from tarinfo.
    r   r_   )uidunamegidgname)tarinfos    r%   anonymize_tarinfor    s%    
 GKGMGKGMNr'   r;   )F)r   )r   )r   )O
contextlibr   r   loggingr*   r   r~   r   warningsr   concurrent.futuresr   r   r   r)   r   r   r   r	   	itertoolsr
   os.pathr   r   r   r   r   r   r   r   r   r   statr   r   r   r   r   
subprocessr   r   r   r   tempfiler   r   platformr`   	getLogger__file__r.   r   r&   r7   r9   rK   rR   rg   r   r   r   r   try_rmdir_all_emptymove_to_trashmove_path_to_trashr   r   r   contextmanagerr   r   r   r   r   r   r   r  r  r  r<   r'   r%   <module>r#     s          				 				  



     P P P P P P P P P P . . . . . . . . . . . .                              > = = = = = = = = = = = = = M M M M M M M M M M M M 0 0 0 0 0 0 0 0		 g!! ' ' '  ." " " " "H " " "] ] ]  $       4L L L^3 3 3l+ + +   8 <A @  @m&8V V V$5 5 5 /! /! /! /! /! /! /! /!d        0  <! ! ! !# # #     4 4 4 43 3 3 3	 	 	 	 	r'   