
    5%                     4   S r SSKJr  SSKJr  SSKJr  SSKrSSKJr  SSKJ	r	  SSKJ
r
  SS	KJr  SS
KJr   " S S\R                  5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      rg)z?Utilities for computing copy operations from command arguments.    )absolute_import)division)unicode_literalsN)storage_util)	expansion)paths)storage_parallel)
exceptionsc                       \ rS rSrSrg)Error    N__name__
__module____qualname____firstlineno____static_attributes__r       1lib/googlecloudsdk/command_lib/storage/copying.pyr   r          r   r   c                       \ rS rSrSrg)WildcardError#   r   Nr   r   r   r   r   r   #   r   r   r   c                       \ rS rSrSrg)RecursionError'   r   Nr   r   r   r   r   r   '   r   r   r   c                       \ rS rSrSrg)LocationMismatchError+   r   Nr   r   r   r   r   r   +   r   r   r   c                       \ rS rSrSrg)DestinationDirectoryExistsError/   r   Nr   r   r   r   r"   r"   /   r   r   r"   c                       \ rS rSrSrg)DestinationNotDirectoryError3   r   Nr   r   r   r   r%   r%   3   r   r   r%   c                   (   ^  \ rS rSrU 4S jrSrU =r$ )InvalidDestinationError7   c                 t   > [         [        U ]  SR                  UR                  UR                  5      5        g )Na  Cannot copy [{}] to [{}] because of "." or ".." in the path. gcloud does not support Cloud Storage paths containing these path segments and it is recommended that you do not name objects in this way. Other tooling may convert these paths to incorrect local directories.)superr(   __init__formatpath)selfsourcedest	__class__s      r   r,    InvalidDestinationError.__init__9   s.    	
!41	 $VFKK;=r   r   )r   r   r   r   r,   r   __classcell__)r2   s   @r   r(   r(   7   s    = =r   r(   c                   L    \ rS rSrSrS rS rSS jrS rS r	S r
S	 rS
 rSrg)CopyTaskGeneratorB   zFA helper to compute and generate the tasks required to perform a copy.c                 l    [         R                  " 5       U l        [         R                  " 5       U l        g )N)r   LocalPathExpander_local_expanderGCSPathExpander_gcs_expander)r/   s    r   r,   CopyTaskGenerator.__init__E   s&     %668D"224Dr   c                 T    UR                   (       a  U R                  $ U R                  $ )z/Get the correct expander for this type of path.)	is_remoter<   r:   )r/   r.   s     r   _GetExpanderCopyTaskGenerator._GetExpanderK   s!    ~~r   c                 P   UR                   n[        R                  " U R                  U5      R	                  UR
                  5      5      nU(       a  UR                  S5      n[        R                  R                  UR
                  5      (       a$  [        SR                  UR
                  5      5      eUR                  (       d6  U Vs/ s H  oUR                  (       a  M  UPM     nnU(       a  [        S5      eU R                  U5      u  pxUR                   (       d&  [        U5      [        U5      -   S:  a  [!        S5      eU(       a  U(       d  [#        S5      e/ n	U	R%                  U R'                  Xr5      5        U	R%                  U R)                  X5      5        U	$ s  snf )a  Get all the file copy tasks for the sources given to this copier.

Args:
  sources: [paths.Path], The sources (containing optional wildcards) that
    you want to copy.
  dest: paths.Path, The wildcard-free path you want to copy the sources to.
  recursive: bool, True to allow recursive copying of directories.

Raises:
  WildcardError: If dest contains a wildcard.
  LocationMismatchError: If you are trying to copy local files to local
    files.
  DestinationNotDirectoryError: If trying to copy multiple files to a single
    dest name.
  RecursionError: If any of sources are directories, but recursive is
    false.

Returns:
  [storage_parallel.Task], All the tasks that should be executed to perform
  this copy.
 z*Destination [{}] cannot contain wildcards.zCWhen destination is a local path, all sources must be remote paths.   z\When copying multiple sources, destination must be a directory (a path ending with a slash).zBSource path matches directories but --recursive was not specified.)is_dir_liker   Pathr@   AbsPathr.   Joinr   PathExpanderHasExpansionr   r-   r?   r   _ExpandFilesToCopylenr%   r   extend_GetFileCopyTasks_GetDirCopyTasks)
r/   sourcesr1   	recursivedest_is_dirslocal_sourcesfilesdirstaskss
             r   GetCopyTasksCopyTaskGenerator.GetCopyTasksQ   sU   0 ""K::d''-55dii@ADYYr]d**49955
6
=
=dii
HJ J >>")='Qq'm=	# 	 ))'2KE
e*s4y
 A	%*,- 	- I
NP P E	LL''45	LL&&t23L+ >s   
F#"F#c                    [        5       n[        5       nU HS  nU R                  U5      nUR                  UR                  5      u  pgUR	                  U5        UR	                  U5        MU     [        U5       Vs/ s H  n[        R                  " U5      PM     sn[        U5       V	s/ s H  n	[        R                  " U	5      PM     sn	4$ s  snf s  sn	f )a  Do initial expansion of all the wildcard arguments.

Args:
  sources: [paths.Path], The sources (containing optional wildcards) that
    you want to copy.

Returns:
  ([paths.Path], [paths.Path]), The file and directory paths that the
  initial set of sources expanded to.
)setr@   
ExpandPathr.   updatesortedr   rF   )
r/   rP   rU   rV   rS   expandercurrent_filescurrent_dirsfds
             r   rK   $CopyTaskGenerator._ExpandFilesToCopy   s     EE5D""1%h&.&9&9!&&&A#}ll=!
kk,	  %+5M2MqUZZ]M2$*4L1LqUZZ]L13 321s   ; C* Cc                    / nU H  nU R                  XB5      nU R                  U5      nUR                  UR                  S5      R                  5      u  px[        U5       V	s/ s H  n	[        R                  " U	5      PM     nn	[        U5       Vs/ s H  n[        R                  " U5      PM     nnUR                  U R                  Xu5      5        UR                  U R                  X5      5        M     U$ s  sn	f s  snf )a	  Get the Tasks to be executed to copy the given directories.

If dest is dir-like (ending in a slash), all dirs are copied under the
destination. If it is file-like, at most one directory can be provided and
it is copied directly to the destination name.

File copy tasks are generated recursively for the contents of all
directories.

Args:
  dirs: [paths.Path], The directories to copy.
  dest: paths.Path, The destination to copy the directories to.

Returns:
  [storage_parallel.Task], The file copy tasks to execute.
*)_GetDestinationNamer@   r\   rH   r.   r^   r   rF   rM   rN   rO   )
r/   rV   r1   rW   rc   	item_destr_   rU   sub_dirsrb   s
             r   rO   "CopyTaskGenerator._GetDirCopyTasks   s    " E**13i""1%h"--affSk.>.>?u&,Um4muzz!}me4)/)9:)9A%**Q-)9h:ll4))%;<ll4((=>  L	 5:s   # C: C?c                     U(       d  / $ / nU H4  nU R                  XB5      nUR                  U R                  XE5      5        M6     U$ )a  Get the Tasks to be executed to copy the given sources.

If dest is dir-like (ending in a slash), all sources are copied under the
destination. If it is file-like, at most one source can be provided and it
is copied directly to the destination name.

Args:
  sources: [paths.Path], The source files to copy. These must all be files
    not directories.
  dest: paths.Path, The destination to copy the files to.

Returns:
  [storage_parallel.Task], The file copy tasks to execute.
)rg   append	_MakeTask)r/   rP   r1   rW   r0   rh   s         r   rN   #CopyTaskGenerator._GetFileCopyTasks   sG     iE**68ill4>>&45  Lr   c                    U R                  U5      nUR                  (       a  UR                  [        R                  R                  UR                  R                  S5      R                  S5      5      5      nUR                  (       a  UR                  S5      nUR                  UR                  5      (       a:  [        SR                  UR                  UR                  UR                  5      5      eOUnUR                  (       a  UR                  OUR                  nU" UR                  5      (       a/  [        SR                  UR                  UR                  5      5      eU$ )z/Computes the destination name to copy item to../\rC   z4Cannot copy [{}] to [{}]: [{}] exists and is a file.zCannot copy [{}] to [{}]: The destination already exists. If you meant to copy under this destination, add a slash to the end of its path.)r@   rE   rH   osr.   basenamerstripIsFiler"   r-   ExistsIsDir)r/   itemr1   r_   rh   
check_funcs         r   rg   %CopyTaskGenerator._GetDestinationName   s     &H))
''

499++C077=
>@i			NN2&			#	#-BII		9>>49967 	7 
$
 i
 %)$4$4(..J)..!!+ 6$))Y^^,	. . r   c                    UR                  5       (       d  [        X5      eUR                  (       a  [        R                  R                  UR                  5      nUR                  (       a?  [        R                  R                  UR                  5      n[        R                  " X45      $ [        R                  " X2R                  5      $ UR                  (       aJ  [        R                  R                  UR                  5      n[        R                  " UR                  U5      $ [        SR                  UR                  UR                  5      5      e)a  Make a file copy Task for a single source.

Args:
  source: paths.Path, The source file to copy.
  dest: path.Path, The destination to copy the file to.

Raises:
  InvalidDestinationError: If this would end up copying to a path that has
    '.' or '..' as a segment.
  LocationMismatchError: If trying to copy a local file to a local file.

Returns:
  storage_parallel.Task, The copy task to execute.
z.Cannot copy local file [{}] to local file [{}])
IsPathSafer(   r?   r   ObjectReferenceFromUrlr.   r	   FileRemoteCopyTaskFileDownloadTaskFileUploadTaskr   r-   )r/   r0   r1   
source_objdest_objs        r   rm   CopyTaskGenerator._MakeTask   s     ??#F11//77Dj	//77		B22:HH..z99EE ~~--55dii@h,,V[[(CC  8??KK	$% %r   )r<   r:   N)F)r   r   r   r   __doc__r,   r@   rX   rK   rO   rN   rg   rm   r   r   r   r   r6   r6   B   s.    N5 7r3,80: %r   r6   )r   
__future__r   r   r   rr   googlecloudsdk.api_lib.storager   "googlecloudsdk.command_lib.storager   r   r	   googlecloudsdk.corer
   r   r   r   r   r"   r%   r(   objectr6   r   r   r   <module>r      s     F &  ' 	 7 8 4 ? *J E U E e 5 =e =O% O%r   