B
    `y]                 @   s   d dl mZmZmZ e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 d dlmZmZmZ d dlmZ d dlmZ d dlmZ dddZdd ZG dd deZ dS )    )absolute_importdivisionprint_functionN)	constants)AnsibleErrorAnsibleFileNotFound)to_bytes	to_nativeto_text)boolean)
ActionBase)checksumTFc                s   g g g dd fdd	 d}|r4|| }n|  tjj}|dkrN| }|s^tj|}| |rpt|}|r||s|d7 }n| tjjs|d7 }tj| r̈st| tj	| dd	< S t
| }	t|	j|	jff}
 | ||
|d
 S )ah	  
    Walk a filesystem tree returning enough information to copy the files.
    This is similar to the _walk_dirs function in ``copy.py`` but returns
    a dict instead of a tuple for each entry and includes the checksum of
    a local file if wanted.

    :arg topdir: The directory that the filesystem tree is rooted at
    :arg loader: The self._loader object from ActionBase
    :kwarg decrypt: Whether to decrypt a file encrypted with ansible-vault
    :kwarg base_path: The initial directory structure to strip off of the
        files for the destination directory.  If this is None (the default),
        the base_path is set to ``top_dir``.
    :kwarg local_follow: Whether to follow symlinks on the source.  When set
        to False, no symlinks are dereferenced.  When set to True (the
        default), the code will dereference most symlinks.  However, symlinks
        can still be present if needed to break a circular link.
    :kwarg trailing_slash_detector: Function to determine if a path has
        a trailing directory separator. Only needed when dealing with paths on
        a remote machine (in which case, pass in a function that is aware of the
        directory separator conventions on the remote machine).
    :kawrg whether to get the checksum of the local file and add to the dict
    :returns: dictionary of dictionaries. All of the path elements in the structure are text string.
            This separates all the files, directories, and symlinks along with
            import information about each::

                {
                    'files'; [{
                        src: '/absolute/path/to/copy/from',
                        dest: 'relative/path/to/copy/to',
                        checksum: 'b54ba7f5621240d403f06815f7246006ef8c7d43'
                    }, ...],
                    'directories'; [{
                        src: '/absolute/path/to/copy/from',
                        dest: 'relative/path/to/copy/to'
                    }, ...],
                    'symlinks'; [{
                        src: '/symlink/target/path',
                        dest: 'relative/path/to/copy/to'
                    }, ...],

                }

        The ``symlinks`` field is only populated if ``local_follow`` is set to False
        *or* a circular symlink cannot be dereferenced. The ``checksum`` entry is set
        to None if checksum_check=False.

    )filesdirectoriessymlinks Fc          
      s  x~t | D ]n\}}}x|D ]}t j||}	t j||	|d }
t j|	rjt j|	d}rt j|rd ||
t	||d qވd t 
|	|
d q j|	d}d ||
t	||d q W x|D ]}t j||}t j|||d }t j|}t |}t j|rfrJ|j|jf|krld t 
||d nt }t j|t jj}xXtt|ddD ]D}t d	|d| }|j|jf|krP ||j|jf qW |j|jf|krd t 
||d n8d
 ||d t|d } ||||||d nd t 
||d qd
 ||d qW qW dS )a  
        This is a closure (function utilizing variables from it's parent
        function's scope) so that we only need one copy of all the containers.
        Note that this function uses side effects (See the Variables used from
        outer scope).

        :arg topdir: The directory we are walking for files
        :arg rel_offset: Integer defining how many characters to strip off of
            the beginning of a path
        :arg parent_dirs: Directories that we're copying that this directory is in.
        :kwarg rel_base: String to prepend to the path after ``rel_offset`` is
            applied to form the relative path.

        Variables used from the outer scope
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        :r_files: Dictionary of files in the hierarchy.  See the return value
            for :func:`walk` for the structure of this dictionary.
        :local_follow: Read-only inside of :func:`_recurse`. Whether to follow symlinks
        N)decryptr   )srcdestr   r   )r   r   r   /r      )rel_basechecksum_check)oswalkpathjoinislinkget_real_filerealpathisfileappend_get_local_checksumreadlinkstatst_devst_inosetdirnamesplitseprangelenaddunion)topdirZ
rel_offsetZparent_dirsr   r   	base_pathZsub_foldersr   filenamefilepathZdest_filepathZ	real_filer)   dirpathZdest_dirpathZreal_dir	dir_statsZnew_parentsZparent_dir_listparentZparent_statoffset)_recurser   loaderlocal_followr_files j/home/dcms/DCMS/lib/python3.7/site-packages/ansible_collections/ansible/windows/plugins/action/win_copy.pyr8   O   sT    


z_walk_dirs.<locals>._recurseNr   )r   r   r   )r   )r   F)endswithr   r   r+   r)   
startswithr-   r   r$   basenamer%   	frozensetr&   r'   )r0   r9   r   r1   r:   trailing_slash_detectorr   Zsource_trailing_slashr7   r5   parentsr<   )r8   r   r9   r:   r;   r=   
_walk_dirs   s.    2b



rD   c             C   s   | rt |S d S d S )N)r   )Zget_checksumZ
local_pathr<   r<   r=   r#      s    r#   c                   sJ   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zd fdd	Z	  Z
S )ActionModule\c          
   C   s~   t jtjd\}}t|d}t|}zHy|| W n4 tk
rj } zt	| t|W dd}~X Y nX W d|
  X |S )z. Create a tempfile containing defined content )dirwbN)tempfilemkstempCDEFAULT_LOCAL_TMPr   fdopenr   write	Exceptionremoveclose)selfcontentfdcontent_tempfileferrr<   r<   r=   _create_content_tempfile   s    

z%ActionModule._create_content_tempfilec             C   s   t jtjd}tj|d}t|dtj	d}xN|D ]F}t
|d dd}t
|d dd}tt|dd}	|||	tj q4W xN|D ]F}
t
|
d dd}t
|
d dd}tt|dd}	|||	tj qW |S )	N)rG   zwin_copy.zipwTr   surrogate_or_strict)errorsr   )rI   mkdtemprK   rL   r   r   r   zipfileZipFile
ZIP_STOREDr   r
   base64	b64encoderN   ZIP_DEFLATED)rR   r   r   tmpdirZzip_file_pathzip_file	directoryZdirectory_patharchive_pathZencoded_pathfile	file_pathr<   r<   r=   _create_zip_tempfile   s    

z!ActionModule._create_zip_tempfilec             C   s   |d k	rt | d S )N)r   rP   )rR   rS   rU   r<   r<   r=   #_remove_tempfile_if_content_defined  s    z0ActionModule._remove_tempfile_if_content_definedc          	   C   sv   | j jrtdd}|S | jj|d}	| ||	 | jj	 }
|

t||	|d|d |
dd  | jd|
|d}|S )	NT)changedsourceZsingle)r   r   Z_original_basename
_copy_modebackuprS   zansible.windows.win_copy)module_namemodule_args	task_vars)_play_context
check_modedict_connection_shell	join_path_transfer_file_taskargscopyupdatepop_execute_module)rR   
local_filer   Z
source_relZdest_relrq   tmprn   module_returntmp_src	copy_argsZcopy_resultr<   r<   r=   _copy_single_file  s$    

zActionModule._copy_single_filec          
   C   s   | j jrtdd}|S y| ||}W n> tk
rd }	 z tdddt|	 t d}|S d }	~	X Y nX | j	|}
| j
j|d}| |
| | jj }|t||d|d |d	d  | jd
||d}ttj|
 |S )NT)rk   Fz!failed to create tmp zip file: %s)rk   failedmsg	exceptionz
source.zipZexplode)r   r   rm   rn   rS   zansible.windows.win_copy)ro   rp   rq   )rr   rs   rt   ri   rO   r
   	traceback
format_exc_loaderr   ru   rv   rw   rx   ry   rz   r{   r|   r}   r~   shutilrmtreer   r   r)   )rR   r   r   r   rq   r   rn   r   rd   ezip_pathr   r   r<   r<   r=   _copy_zip_file"  s8    


zActionModule._copy_zip_fileNc                sN  |dkrt  }tt| ||}~| jjdd}| jjdd}| jjdd}t| jjdddd}t| jjdddd}t| jjd	d
dd}	t| jjdd
dd}
t| jjdddd}||d< ||d< d
|d< |dkr|dks|dkrd|d< n`|dk	r$|dk	r$d|d< nB|dk	r`|dk	r`|t	j
jsV|| jr`d|d< n|d= |drv|S d}|dk	r y<t|t st|tr| t|}n
| |}|}W n< tk
r } zd
|d< dt| |d< |S d}~X Y nX n|rP| jj }|t d|||	|d |dd || jd||d |S |t	j
j}y| d|}W nD tk
r } z$d
|d< t||d< t |d< |S d}~X Y nX ||t	j
jkr|d t	j
jkr|dd }n|t	j
j }g g g d}d}t	j
t|ddrdd|d< t|| j |
|| j!j"j#|	d}| j!j"#|s\d || jf }|}nd!|d< y| j j$||
d"}W n@ t%k
r } z d
|d< d#|t|f |d< |S d}~X Y nX t	j
&|}||d$< | j!j"#|r|}|}| j!j"'|||d< n*|(| jt	j
j}t	j
&|}t	j
)|}t*|	|}|d +t |||d% ||d&< t	j
,t|dd|d'< | jj }|t d(||	|d |d) |d* d+ |dd |dd | jd||d}|dd
kr|| |S t-|d d,kst-|d) d,kr*| j!j"j.dkr*| / | j!j"_.t-|d d-krt-|d) d,kr|d d, d }|d d, d }|pv|}|| 0|||||| j!j"j.| |dd
krd.||d f |d< d
|d/< nft-|d d,kst-|d) d,kr|| 1||d |d) || j!j"j.| d
|d/< nd|d< d|d/< | 2|| | 3| j!j"j. |S )0z& handler for file transfer operations Nr   rS   r   
remote_srcF)strictr:   forceTr   rn   r   z&src (or content) and dest are requiredr   z&src and content are mutually exclusivez)dest must be a file if content is definedz$could not write content tmp file: %sremote)rm   r   r   r   rn   zansible.windows.win_copy)ro   rp   rq   r   r   r   )r   r   r   rZ   )r[   Zfolder_copyZ	operation)r   r:   rB   r   z%s%sZ	file_copy)r   zcould not find src=%s, %soriginal_basename)r   r   r   r   sizequeryr   r   )rm   r   r   r   r   r   r   r   zfailed to copy file %s: %srk   )4rt   superrE   runry   rz   getr   r>   r   r   r+   WIN_PATH_SEPARATOR
isinstancelistrX   jsondumpsrO   r	   r{   r|   r}   r~   Z_find_needler   r
   r   r   isdirr   rD   r   ru   rv   Zpath_has_trailing_slashr   r   r@   rw   replacer)   r#   r"   getsizer-   rc   Z_make_tmp_pathr   r   rj   Z_remove_tmp_path)rR   r   rq   resultrl   rS   r   r   r:   r   r   rn   rU   rW   Znew_module_argsZtrailing_slashr   Zsource_filesr   Z
check_destZsource_fullr2   Z	unix_pathZfile_checksumZ
query_argsZquery_returnZfile_srcZ	file_destr@   )	__class__r<   r=   r   L  s   










4$

$
zActionModule.run)NN)__name__
__module____qualname__r   rX   ri   rj   r   r   r   __classcell__r<   r<   )r   r=   rE      s   *rE   )TNFNF)!
__future__r   r   r   type__metaclass__r`   r   r   os.pathr   rI   r   r]   Zansibler   rK   Zansible.errorsr   r   Zansible.module_utils._textr   r	   r
   Z)ansible.module_utils.parsing.convert_boolr   Zansible.plugins.actionr   Zansible.utils.hashingr   rD   r#   rE   r<   r<   r<   r=   <module>   s&   
 8