
                        
   d Z ddlmZ ddlmZ ddlmZ ddlmZ ddlZ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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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  dd
l!m"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* ddl'm+Z+ ddl'm,Z, ddl'm-Z- ddl'm.Z. ddl'm/Z/ ddl'm0Z0 ddl'm1Z1 ddl'm2Z2 ddl'm3Z3 ddl4m5Z5 ddl6m7Z7 ddl6m8Z8 ddl6m9Z9 ddl6m:Z: ddl6m;Z; ddl6m<Z< ddl=m>Z> dd l?m@Z@ dd!lAmBZB dd"lAmCZC dd#lAmDZD dd$lEmFZF dd%lGmHZH dd&lGmIZI dd'lGmJZJ dd(lGmKZK dd)lGmLZL dd*lMmNZN dd+lMmOZO dd,lPmQZQ dd-l&mRZR dd.lSmTZT dd/lSmUZU dd0lSmVZV dd1lSmWZW dd2lXmYZZ dd3l[m\Z\ dd4l[m]Z] dd5l^m_Z_ dd6l^m`Z` dd7l^maZa dd8l^mbZb dd9l^mcZc dd:l^mdZd dd;l^meZe dd<l^mfZf dd=l^mgZg dd>l^mhZh dd?l^miZi dd@l^mjZj ddAlkmlZl ddBlkmmZm ddClkmnZn ddDlkmoZo ddElpmqZq ddFlpmrZr ddGlpmsZs ddHlpmtZt ddIlpmuZu ddJlvmwZw ddKlvmxZx ddLlymzZz ddMlym{Z{ ddNlym|Z| ddOl}m~Z~ ddPl}mZ ddQl}mZ ddRl}mZ ddSlmZ ddTlmZ ddUlmZ ddVlmZ ddWlmZ ddXlmZ ddYlmZ ddZlmZ dd[lmZ dd\lmZ dd]lmZ dd^lmZ dd_lmZ dd`lmZ ddalmZ ddblmZ ddclmZ dddlmZ ddelmZ ddflmZ ddglmZ ddhlmZ ddilmZ ddjlmZ ddklmZ ddllmZ ddmlmZ ddnlmZ ddolmZ ddplmZ ddqlmZ ddrlmZ ddslmZ ddtlmZ ddulmZ ddvlmZ ddwlmZ ej^                  reZerddlZ e e       jf                  reljh                  ndx      a eljl                         adyZdzZd{Zd|Zg d}Z ed~d      Z edd      Z edd      ZdZdZeZdZdZ e e       jf                  reljh                  ndx      a eljl                         adddZ G d deȫ      Zd Zd ZddZ edg d      Z	 	 	 	 	 	 	 	 	 	 	 ddZd Zd Zd Zd Zd Zd Z	 ddZd Zd Zd Z	 ddZd Zd Z	 	 ddZd Z	 ddZ	 ddZ	 	 ddZd Zd Zd Zd Z	 ddZd Z	 ddZ	 	 ddZ	 	 	 ddZd Zd Z	 	 	 	 ddZd Zd ZddZd Z G d de      Z	 ddZ	 	 ddZ	 	 	 	 ddZ	 ddZ	 	 	 	 	 ddZ	 	 	 ddZddZd Z	 ddZ	 	 	 	 ddZdez  dez  dez  dĜZdń ZdƄ ZdǄ Z 	 	 	 	 	 	 	 	 	 ddȄZ G dɄ de      Z G d˄ deȫ      Z G d̈́ deȫ      Z G dτ dАe      Zdф Zd҄ Zdӄ ZddԄZ	dՄ Z
y)z(Helper functions for copy functionality.    )absolute_import)print_function)division)unicode_literalsN)
namedtuple)
attrgetter)range)	protojson)config)AccessDeniedException)ArgumentException)CloudApi)EncryptionException)NotFoundException)PreconditionException)Preconditions)ResumableDownloadException)ResumableUploadAbortException)ResumableUploadException)!ResumableUploadStartOverException)ServiceException)MAX_COMPOSE_ARITY)0DEFAULT_PARALLEL_COMPOSITE_UPLOAD_COMPONENT_SIZE)+DEFAULT_PARALLEL_COMPOSITE_UPLOAD_THRESHOLD)-DEFAULT_SLICED_OBJECT_DOWNLOAD_COMPONENT_SIZE)-DEFAULT_SLICED_OBJECT_DOWNLOAD_MAX_COMPONENTS)(DEFAULT_SLICED_OBJECT_DOWNLOAD_THRESHOLD)DEFAULT_GZIP_COMPRESSION_LEVEL)ApiSelector)DaisyChainWrapper)CommandException)HashMismatchException)InvalidUrlError)FilePart)GenerateComponentObjectPrefix)ReadParallelUploadTrackerFile)$ValidateParallelCompositeTrackerData))WriteComponentToParallelUploadTrackerFile)WriteParallelUploadTrackerFile)FileProgressCallbackHandler)ProgressCallbackWithTimeout)#ResumableStreamingJsonUploadWrapper)storage_url)ContainsWildcard)GenerationFromUrlAndString)IsCloudSubdirPlaceholder)StorageUrlFromString)storage_v1_messages)FileMessage)RetryableErrorMessage)DeleteDownloadTrackerFiles)DeleteTrackerFile)ENCRYPTION_UPLOAD_TRACKER_ENTRY)GetDownloadStartByte)GetTrackerFilePath)GetUploadTrackerData)#RaiseUnwritableTrackerFileException)ReadOrCreateDownloadTrackerFile)"SERIALIZATION_UPLOAD_TRACKER_ENTRY)TrackerFileType)!WriteDownloadComponentTrackerFile)WriteJsonDataToTrackerFile)parallelism_framework_util)	stet_util)temporary_file_util)	text_util)GetJsonResumableChunkSize)GetMaxRetryDelay)GetNumRetries)ResumableThreshold)UsingCrcmodExtension)GetCloudApiInstance)GetDownloadSerializationData)DEFAULT_FILE_BUFFER_SIZE)MIN_SIZE_COMPUTE_LOGGING)UTF8)CryptoKeyType)CryptoKeyWrapperFromKey)FindMatchingCSEKInBotoConfig)GetEncryptionKeyWrapper)Base64EncodeHash)"CalculateB64EncodedMd5FromContents)CalculateHashesFromContents)CHECK_HASH_IF_FAST_ELSE_FAIL)CHECK_HASH_NEVER)ConcatCrc32c)GetDownloadHashAlgs)GetMd5)GetUploadHashAlgs)HashingFileUploadWrapper)ObjectIsGzipEncoded)
AtomicDict)$CheckMultiprocessingAvailableAndInit)PutToQueueWithTimeout)
ATIME_ATTR)ConvertDatetimeToPOSIX)GID_ATTR)	MODE_ATTR)
MTIME_ATTR)ParseAndSetPOSIXAttributes)UID_ATTR)CheckFreeSpace)GetFileSize)GetStreamFromFileUrl)
IS_WINDOWS)AddS3MarkerAclToObjectMetadata)CopyObjectMetadata)DEFAULT_CONTENT_TYPE)ObjectMetadataFromHeaders)PreconditionsFromHeaders)S3MarkerAclFromObjectMetadata)DivideAndCeil)HumanReadableToBytes)MakeHumanReadable)SECONDS_PER_DAY)TEN_MIB)CreateWildcardIterator)managerF_corruptzF/gsutil/tmp/parallel_composite_uploads/for_details_see/gsutil_help_cp/ad  
PARALLEL_UPLOAD_SALT_TO_PREVENT_COLLISIONS.
The theory is that no user will have prepended this to the front of
one of their object names and then done an MD5 hash of the name, and
then prepended PARALLEL_UPLOAD_TEMP_NAMESPACE to the front of their object
name. Note that there will be no problems with object name length since we
hash the original name.
)crc32ccustomerEncryptionetag
generationmd5Hashsize%PerformParallelUploadFileToObjectArgszfilename file_start file_length src_url dst_url canned_acl content_type storage_class tracker_file tracker_file_lock encryption_key_sha256 gzip_encoded%PerformSlicedDownloadObjectToFileArgszicomponent_num src_url src_obj_metadata_json dst_url download_file_name start_byte end_byte decryption_key!PerformSlicedDownloadReturnValueszKcomponent_num crc32c bytes_transferred component_total_size server_encodingi    GZIP_ALL_FILESi  `	l        ztext/markdownzapplication/gzip)mdtgzc                       e Zd ZdZy)FileConcurrencySkipErrorz@Raised when skipping a file due to a concurrent, duplicate copy.N__name__
__module____qualname____doc__     *platform/gsutil/gslib/utils/copy_helper.pyr   r   +  s    Hr   r   c                 L    | j                   j                  t        |             y)9Simple exception handler to allow post-completion status.N)loggererrorstrclses     r   _RmExceptionHandlerr   /  s    **3q6r   c                     | j                   j                  t        |             | xj                  dz  c_        | j                   j	                  dt        j                                y)r      z*

Encountered exception while copying:
%s
N)r   r   r   op_failure_countdebug	traceback
format_excr   s     r   _ParallelCopyExceptionHandlerr   4  sJ    **3q6!**C'')+r   c                 8   t        |j                  |j                  |j                        }t	        | |      }|5  d}t        j                  |j                  j                  |j                  j                  |j                  |j                        }|j                  }	 t        j                  rt        j                   |_        t#        |j$                  ||j                  |j                  |||| j&                  | t(        ddd|j*                        }t        j                  r||_        	 ddd       d   }	t-        |j.                  |j0                  |	| j&                  |j2                         |S # t        j                  r||_        w w xY w# 1 sw Y   exY w)	aO  Function argument to Apply for performing parallel composite uploads.

  Args:
    cls: Calling Command class.
    args: PerformParallelUploadFileToObjectArgs tuple describing the target.
    thread_state: gsutil Cloud API instance to use for the operation.

  Returns:
    StorageUrl representing a successfully uploaded component.
  thread_stateN)namebucketcontentTypestorageClassFT)	gzip_extsallow_splittingis_componentgzip_encoded   encryption_key_sha256)r$   filename
file_startfile_lengthrJ   apitools_messagesObjectdst_urlobject_namebucket_namecontent_typestorage_class
prefer_apiglobal_copy_helper_opts
canned_aclr   XML_UploadFileToObjectsrc_urlr   r   r   r(   tracker_filetracker_file_lockr   )
r   argsr   fp
gsutil_apipreconditionsdst_object_metadataorig_prefer_apiret	components
             r   "_PerformParallelUploadFileToObjectr   <  sf    t0@0@A""3\B*	 M ,22\\%%||''%%''	) !++O0	 	+	+ !,
 " $ 0 0 $ 3 - * #

 # =*.05-1-1->->@c 
!	+	+ /
G 
J !f)+

	jj 668 
* 
!	+	+ /
 
,E 
rs%   A$F A4E3F3FFFCopyHelperOpts
perform_mv
no_clobberdaisy_chainread_args_from_stdin	print_veruse_manifestpreserve_aclr   skip_unsupported_objectstest_callback_filedest_storage_classc                 :    t        | |||||||||	|
      at        S )z9Creates CopyHelperOpts for passing options to CopyHelper.r   )r   r   r   s              r   CreateCopyHelperOptsr     s8     +/7++- 
! r   c                      t         S )z.Returns namedtuple holding CopyHelper options.)r   r   r   r   GetCopyHelperOptsr     s
     
! r   c                 p   d}| j                         r`| j                  t        j                  k(  rd}	 t        j                  | j                        j
                  }t	        j                  |      rd}|rt        j                  j                  S t        j                  j                  S # t        $ r Y Aw xY w)zGet download strategy based on the destination object.

  Args:
    dst_url: Destination StorageUrl.

  Returns:
    gsutil Cloud API DownloadStrategy.
  FT)	IsFileUrlr   osdevnullstatst_modeS_ISCHROSErrorr   DownloadStrategyONE_SHOT	RESUMABLE)r   dst_is_specialmodes      r   _SelectDownloadStrategyr     s     .bjj(nWWW(()11d	d	 $$---$$...  
s   A B) )	B54B5c                     | j                         r| j                         r"| j                         r"| j                         r|st	        d|z        yyy)a  Ensures the destination URL names a container.

  Acceptable containers include directory, bucket, bucket
  subdir, and non-existent bucket subdir.

  Args:
    exp_dst_url: Wildcard-expanded destination StorageUrl.
    have_existing_dst_container: bool indicator of whether exp_dst_url
      names a container (directory, bucket, or existing bucket subdir).
    command_name: Name of command making call. May not be the same as the
        calling class's self.command_name in the case of commands implemented
        atop other commands (like mv command).

  Raises:
    CommandException: if the URL being checked does not name a container.
  zuDestination URL must name a directory, bucket, or bucket
subdirectory for the multiple source form of the %s command.N)r   IsDirectory
IsCloudUrlIsBucketr!   )exp_dst_urlhave_existing_dst_containercommand_names      r   InsistDstUrlNamesContainerr     s_    $ {'>'>'@K$8$8$:&
 <>JK L L ' %;r   c                 >    |ry|j                         r
| xs |xr |S y)a"  Checks whether dst_url should be treated as a bucket "sub-directory".

  The decision about whether something constitutes a bucket "sub-directory"
  depends on whether there are multiple sources in this request and whether
  there is an existing bucket subdirectory. For example, when running the
  command:
    gsutil cp file gs://bucket/abc
  if there's no existing gs://bucket/abc bucket subdirectory we should copy
  file to the object gs://bucket/abc. In contrast, if
  there's an existing gs://bucket/abc bucket subdirectory we should copy
  file to gs://bucket/abc/file. And regardless of whether gs://bucket/abc
  exists, when running the command:
    gsutil cp file1 file2 gs://bucket/abc
  we should copy file1 to gs://bucket/abc/file1 (and similarly for file2).
  Finally, for recursive copies, if the source is a container then we should
  copy to a container as the target.  For example, when running the command:
    gsutil cp -r dir1 gs://bucket/dir2
  we should copy the subtree of dir1 to gs://bucket/dir2.

  Note that we don't disallow naming a bucket "sub-directory" where there's
  already an object at that URL. For example it's legitimate (albeit
  confusing) to have an object called gs://bucket/dir and
  then run the command
  gsutil cp file1 file2 gs://bucket/dir
  Doing so will end up with objects gs://bucket/dir, gs://bucket/dir/file1,
  and gs://bucket/dir/file2.

  Args:
    have_multiple_srcs: Bool indicator of whether this is a multi-source
        operation.
    dst_url: StorageUrl to check.
    have_existing_dest_subdir: bool indicator whether dest is an existing
      subdirectory.
    src_url_names_container: bool indicator of whether the source URL
      is a container.
    recursion_requested: True if a recursive operation has been requested.

  Returns:
    bool indicator.
  TN)r   )have_multiple_srcsr   have_existing_dest_subdirsrc_url_names_containerrecursion_requesteds        r    _ShouldTreatDstUrlAsBucketSubDirr     s2    X  >$<)<? r   c                     |r| ry|j                         r|j                          S | xr | xr |j                         S )av  Checks that dst_url names a single file/object after wildcard expansion.

  It is possible that an object path might name a bucket sub-directory.

  Args:
    src_url_names_container: Bool indicator of whether the source for the
        operation is a container (bucket, bucket subdir, or directory).
    have_multiple_srcs: Bool indicator of whether this is a multi-source
        operation.
    have_existing_dest_subdir: bool indicator whether dest is an existing
      subdirectory.
    dst_url: StorageUrl to check.
    recursion_requested: True if a recursive operation has been requested.

  Returns:
    bool indicator.
  F)r   r   IsObject)r   r   r   r   r   s        r   _ShouldTreatDstUrlAsSingletonr     sR    ( 4""$$$"" +D'D  r   c                 >   | j                         sy| j                  j                  | j                        }|j	                  | j                        \  }}}|t
        j                  vxr0 |t
        j                  D cg c]  }| j                  dz   |z    c}vS c c}w )ac  Returns True if not FileUrl ending in  relative path symbols.

  A URL is invalid if it is a FileUrl and the parent directory of the file is a
  relative path symbol. Unix will not allow a file itself to be named with a
  relative path symbol, but one can be the parent. Notably, "../obj" can lead
  to unexpected behavior at the copy destination. We examine the pre-recursion
  "url", which might point to "..", to see if the parent is valid.

  If the user does a recursive copy from a URL, it may not end up
  the final parent of the copied object. For example, see: "dir/nested_dir/obj".

  If you ran "cp -r dir gs://bucket" from the parent of "dir", then the "url"
  arg would be "dir", but "nested_dir" would be the parent of "obj".
  This actually doesn't matter since recursion won't add relative path symbols
  to the path. However, we still return if "url" is valid because
  there are cases where we need to copy every parent directory up to
  "dir" to prevent file name conflicts.

  Args:
    url: StorageUrl before recursion.

  Returns:
    Boolean indicating if the "url" is valid as a parent directory.
  Tz://)r   versionless_url_stringrstripdelim
rpartitionr-   RELATIVE_PATH_SYMBOLSscheme)url#url_string_minus_trailing_delimiter_after_last_delimitersymbols        r   _IsUrlValidParentDirr  3  s    2 
(+(B(B(I(I	ii)% C N N	ii!!Q 
[%F%F	F 
	#99#9f **u
v
%9# 	#s   =Bc	                    |j                         r|j                         r|rt        d      t        |||||      r|S |j                         rF|j                         s|j	                         r&|r"|j                         rdnd}	t        d|	z        |S |sh|sf|j
                  j                  | j                        d   }
t        |j                  j                  |j                        |j                  |
      S |s"|s |j                         rX|j                         rH|j                  j                  |j                        s#t        |j                  |j                        }t        |       }|s|rt        dj                  |             d| j                   vxr
 |xr |xs |}|s"|r~|j#                         s|j                         r^t%        | |      }|j                   t'        |      d j)                  | j                        }|sG|j+                  | j                        d   }n(|j
                  j                  | j                        d   }|j                         st-        |||||      r|j
                  r[|j
                  j                  |j                        r6|j
                  j                  |j                        |j                  |}n0|j
                  r|j                  nd	}|j
                  xs d	||}|j/                         }|j1                  | j                  |j                        |_        |S )
aQ  Constructs the destination URL for a given exp_src_url/exp_dst_url pair.

  Uses context-dependent naming rules that mimic Linux cp and mv behavior.

  Args:
    src_url: Source StorageUrl to be copied.
    exp_src_url: Single StorageUrl from wildcard expansion of src_url.
    src_url_names_container: True if src_url names a container (including the
        case of a wildcard-named bucket subdir (like gs://bucket/abc,
        where gs://bucket/abc/* matched some objects).
    have_multiple_srcs: True if this is a multi-source request. This can be
        true if src_url wildcard-expanded to multiple URLs or if there were
        multiple source URLs in the request.
    has_multiple_top_level_srcs: Same as have_multiple_srcs but measured
        before recursion.
    exp_dst_url: the expanded StorageUrl requested for the cp destination.
        Final written path is constructed from this plus a context-dependent
        variant of src_url.
    have_existing_dest_subdir: bool indicator whether dest is an existing
      subdirectory.
    recursion_requested: True if a recursive operation has been requested.
    preserve_posix: True if preservation of posix attributes has been requested.

  Returns:
    StorageUrl to use for copy.

  Raises:
    CommandException if destination object name not specified for
    source and source is a stream.
  z/Cannot preserve POSIX attributes with a stream.stream
named pipez2Destination object name needed when source is a %szmPresence of multiple top-level sources and invalid expanded URL make file name conflicts possible for URL: {}z**N )r   IsStreamr!   r   IsFifor   r   r   r1   
url_stringr   r   endswithr  r#   formatr   r   GetPathBeforeFinalDirlenlstrip	partitionr   Clonereplace)r   exp_src_urlr   r   has_multiple_top_level_srcsr   r   r   preserve_posix	type_textsrc_final_compsrc_url_is_valid_parentpreserve_src_top_level_dirssrc_url_path_sans_final_dirdst_key_namer   new_exp_dst_urls                    r   ConstructDstUrlr  [  s>   N +"6"6"8^
L
MM"#:<N#<k#68 +"6"6"8"-"4"4"6 )224(,i .09: ; ;	%7 !,,77FrJNK,B,B,I,I-'--~!? @ @ 4K$;$;$=

 
 
)
)+*;*;
<&((+*;*;<>K 19	 %@ 	99?J JR "&W-K-K!K "=!8"="= #<";  !%<&1&<&<&>&1&=&=&? #8"M55'()++16'--+@  '!++GMM:2>l **55gmmDRHL!A+'@2"4 ;#:#:#C#C$!,!8!8!?!?


")//?l $/#:#:ke!,!8!8 "$!#"$%*L:l  %%'/ , 4 4W]]5@5F5F!H/	r   c                     i }| rN| D ]I  }t        j                  | |   j                               j                  d      j	                  d      ||<   K |S )N   
ascii)base64	b64encodedigestr   decode)	digestersdigestsalgs      r   _CreateDigestsFromDigestersr*    sS    '%%
C.


!##)6%= cl  
.r   c                    i }d|v rt               |d<   d|v r"t        j                  j                  d      |d<   t	        |d      5 }t        ||t        |j                  t        | |d      j                               ddd       i }t        j                  |      D ]!  \  }}	t        |	j                               ||<   # |S # 1 sw Y   FxY w)	a  Creates a base64 CRC32C and/or MD5 digest from file_name.

  Args:
    status_queue: Queue for posting progress messages for UI/Analytics.
    algs: List of algorithms to compute.
    file_name: File to digest.
    src_url: StorageUrl for local object. Used to track progress.
    src_obj_metadata: Metadata of source object.

  Returns:
    Dict of algorithm name : base 64 encoded digest
  md5rz   zcrc-32crbHashing)r   operation_name)callback_processorN)rZ   crcmod
predefinedCrcopenrU   r+   r   r*   callsix	iteritemsrS   	hexdigest)
status_queuealgs	file_namer   src_obj_metadata	hash_dictr   r(  alg_namer%  s
             r   _CreateDigestsFromLocalFiler?    s     )
d]xIe ++//	:IhIt )3N$4$9$9$?(4077@%B CG$4HI  '--	2h()9)9);<GH 3	. s   9CCc                    t        j                  ddt              }|t        k(  ryd}i }i }|j                  r$t        j                  |j                        }	|	|d<   |j                  r$t        j                  |j                        }
|
|d<   |j                  r$t        j                  |j                        }||d<   |j                  r$t        j                  |j                        }||d<   t        j                  |      D ]s  \  }}||vr||   }t
        j                  r!t        |t              r|j                  d      }| j                  d||||       ||k7  rt        |d	|d
|d|d      d}u |s| j                  d||       yy)a  Validates integrity of two cloud objects copied via daisy-chain.

  Args:
    logger: for outputting log messages.
    src_url: CloudUrl for source cloud object.
    dst_url: CloudUrl for destination cloud object.
    src_obj_metadata: Cloud Object metadata for object being downloaded from.
    dst_obj_metadata: Cloud Object metadata for object being uploaded to.

  Raises:
    CommandException: if cloud digests don't match local digests.
  GSUtilcheck_hashesNFr,  rz   r"  z;Comparing source vs destination %s-checksum for %s. (%s/%s)z signature for source object (z+) doesn't match destination object digest (z). Object () will be deleted.Tz~WARNING: Found no hashes to validate object downloaded from %s and uploaded to %s. Integrity cannot be assured without hashes.)r   getrV   rW   r~   r6  ensure_binaryrz   r7  PY3
isinstancer   encoder   r"   warn)r   r   r   r<  dst_obj_metadatacheck_hashes_configchecked_onedownload_hashesupload_hashessrc_md5hashsrc_crc32c_hashdst_md5hashdst_crc32c_hashr)  upload_b64_digestdownload_b64_digests                   r   _CheckCloudHashesrU  .  s   & 

8^#?A,,
+/-##$4$<$<=K(OE''(8(?(?@O /OH##$4$<$<=K&M%''(8(?(?@O-M( #m <c
/!)#.
ww:137/66w?
LLNg24EG//! #%6AB B K != 
 KK	FGN 
r   c                 .   |}i }|j                   r3t        j                  |j                         }|j                  d      |d<   |j                  r3t        j                  |j                        }	|	j                  d      |d<   d}
|D ]b  }||vrt        j                  ||         }||   }| j                  d||||       ||k7  r"t        |d|d|d|rd	nd
d|r|n|d
      d}
d |
s(|r| j                  d|       y| j                  d|       yy)a  Validates integrity by comparing cloud digest to local digest.

  Args:
    logger: for outputting log messages.
    obj_url: CloudUrl for cloud object.
    obj_metadata: Cloud Object being downloaded from or uploaded to.
    file_name: Local file name on disk being downloaded to or uploaded from
               (used only for logging).
    digests: Computed Digests for the object.
    is_upload: If true, comparing for an uploaded object (controls logging).

  Raises:
    CommandException: if cloud digests don't match local digests.
  r!  r,  rz   Fz4Comparing local vs cloud %s-checksum for %s. (%s/%s)z$ signature computed for local file (z') doesn't match cloud-supplied digest (z). zCloud objectz
Local filez (rC  TzgWARNING: Found no hashes to validate object uploaded to %s. Integrity cannot be assured without hashes.ziWARNING: Found no hashes to validate object downloaded to %s. Integrity cannot be assured without hashes.N)r~   r6  rE  r   rz   r   r"   rI  )r   obj_urlobj_metadatar;  r(  	is_uploadlocal_hashescloud_hashesmd5_b64_digestcrc32c_b64_hashrL  r)  local_b64_digestcloud_b64_digests                 r   _CheckHashesr`  n  sP   : ,,&&|';';<N(//6L''(;(;<O,33E:L+c
,((c):;#C(
LLG,.>@++!  "2 5C)5*6?7Y+NPQ Q
 K  
kk89@B kk89BD 
r   c                 f    t        | t              xs  t        | t              xr d| j                  v S )aR  Checks to see if the server attempted to clobber a file.

  In this case we specified via a precondition that we didn't want the file
  clobbered.

  Args:
    e: The Exception that was generated by a failed copy operation

  Returns:
    bool indicator - True indicates that the server did attempt to clobber
        an existing file.
  412)rG  r   r   message)r   s    r   IsNoClobberServerExceptionrd    s4     a./ Ka12Iu		7ILr   c                 h   |j                         ry|j                  }t        j                  j	                  |      }t        j                  j                  |      rt        d| j                  d|d      t        j                  j                  |      rt        d| j                  d|d      y)a  Checks whether copying exp_src_url into dst_url is not possible.

     This happens if a directory exists in local file system where a file
     needs to go or vice versa. In that case we print an error message and
     exits. Example: if the file "./x" exists and you try to do:
       gsutil cp gs://mybucket/x/y .
     the request can't succeed because it requires a directory where
     the file x exists.

     Note that we don't enforce any corresponding restrictions for buckets,
     because the flat namespace semantics for buckets doesn't prohibit such
     cases the way hierarchical file systems do. For example, if a bucket
     contains an object called gs://bucket/dir and then you run the command:
       gsutil cp file1 file2 gs://bucket/dir
     you'll end up with objects gs://bucket/dir, gs://bucket/dir/file1, and
     gs://bucket/dir/file2.

  Args:
    exp_src_url: Expanded source StorageUrl.
    dst_url: Destination StorageUrl.

  Raises:
    CommandException: if errors encountered.
  NzCannot retrieve z> because a file exists where a directory needs to be created (z).z because a directory exists (z%) where the file needs to be created.)	r   r   r   pathdirnameisfiler!   r  isdir)r  r   dst_path	final_dirs       r   CheckForDirFileConflictrl    s    2 
  (ggooh')WW^^I
'22I? @ @ WW]]8
'22H> ? ? r   c                 F   t        t        j                  ddt                    }t	        |t
        |      \  }}i }g }t        |      D ]  }t        j                  t        |j                  z         }t               }|j                  |       |j                         }|t        z   |z   dz   t        |      z   }|j!                         }||_        ||dz
  k  r|}n||dz
  |z  z
  }||z  }t%        |j                  ||||| ||||	|
|      }|j'                  |       |||<    |S )a  Partitions a file into FilePart objects to be uploaded and later composed.

  These objects, when composed, will match the original file. This entails
  splitting the file into parts, naming and forming a destination URL for each
  part, and also providing the PerformParallelUploadFileToObjectArgs
  corresponding to each part.

  Args:
    canned_acl: The user-provided canned_acl, if applicable.
    content_type: content type for the component and final objects.
    dst_bucket_url: CloudUrl for the destination bucket.
    file_size: The size of fp, in bytes.
    fp: The file object to be partitioned.
    random_prefix: The randomly-generated prefix used to prevent collisions
                   among the temporary component names.
    src_url: Source FileUrl from the original command.
    storage_class: storage class for the component and final objects.
    tracker_file: The path to the parallel composite upload tracker file.
    tracker_file_lock: The lock protecting access to the tracker file.
    encryption_key_sha256: Encryption key SHA256 for use in this upload, if any.
    gzip_encoded: Whether to use gzip transport encoding for the upload.

  Returns:
    dst_args: The destination URIs for the temporary component objects.
  rA  (parallel_composite_upload_component_sizer  r   )rs   r   rD  r   _GetPartitionInfor   r	   r6  rE  PARALLEL_UPLOAD_STATIC_SALTr   rZ   updater8  PARALLEL_UPLOAD_TEMP_NAMESPACEr   r  r   r   append)r   r   dst_bucket_url	file_sizer   random_prefixr   r   r   r   r   r   rn  num_componentscomponent_sizedst_args
file_namesiencoded_namecontent_md5r%  temp_file_nametmp_dst_urlfile_part_lengthoffset	func_argss                             r   _PartitionFiler    sV   J .BjjEAC.D* &7"$L&N">> (* a $$%@277%JKL(K|$""$F#&DDvMF#N &&(K,KNQ' $(:n'LMF5
)7Km\3D|-I n%(H^7 !: 
/r   c                 j    t        | j                  | j                  j                  d      dz   d       S )zGets component number from component CloudUrl.

  Used during parallel composite upload.

  Args:
    component: CloudUrl representing component.

  Returns:
    component number
  r  r   N)intr   rfind)r   s    r   _GetComponentNumberr  7  s3     
Y""9#8#8#>#>s#Ca#G#HI	JJr   c                    t        j                          }t        |j                        }|j                  |j                        }t        t              }|r|j                  nd}t        |t        j                  ||      }t        ||
      \  }}}t        ||||||||
t        t        
      \  }}||j                  d      nd}||nt!        |      }t#        ||||       t%        j&                         }i }t)        ||j*                  ||| |||j,                  ||||      }t/        ||||      \  }}}|D ]  }t0        j2                  |j4                  f||j6                  j8                  <   t;        |j<                  t1        |j>                  |j6                  t        j                          |j4                  dtA        |j6                        t0        j2                                |D ]  }|d   jB                  }t0        jD                  |d	   f||<   t;        |j<                  t1        ||d   t        j                          d|d	   tA        |d         t0        jD                  
              |D ]F  }t;        |j<                  t1        ||t        j                          dt0        jF                               H |jI                  tJ        ||	dtL        jN                  jP                  |jR                  jT                  d      }g }|D ]  }|jW                  |d           ||D  cg c]  } | d   	 c} z   }!tY        |!      tY        |      k(  rt[        |!t@              }!g }"|!D ]g  }#t\        j^                  ja                  |#jb                        }$|#je                         rtg        |#jh                        |$_4        |"jW                  |$       i |jk                  |"|||j                  g d|      }%	 |!|z   }&|jI                  t        |&t        tL        jN                  jP                  |jR                  jT                         |!D ]\  }|jB                  }	 t;        |j<                  t1        ||t        j                          dtA        |      ||   d	   ||   d                ^ |D ]F  }t;        |j<                  t1        ||t        j                          dt0        jF                               H 	 |5  tu        |       ddd       ntw        d      t        j                          |z
  }'|'|%fS c c} w #  t;        |j<                  t1        ||t        j                          d             Y 'xY w# tl        $ r4 |
jo                  ddjq                  |js                               z          Y w xY w# 1 sw Y   xY w# |5  tu        |       ddd       w # 1 sw Y   w xY wxY w)a  Uploads a local file to a cloud object using parallel composite upload.

  The file is partitioned into parts, and then the parts are uploaded in
  parallel, composed to form the original destination object, and deleted.

  Args:
    fp: The file object to be uploaded.
    src_url: FileUrl representing the local file.
    dst_url: CloudUrl representing the destination file.
    dst_obj_metadata: apitools Object describing the destination object.
    canned_acl: The canned acl to apply to the object, if any.
    file_size: The size of the source file in bytes.
    preconditions: Cloud API Preconditions for the final object.
    gsutil_api: gsutil Cloud API instance to use.
    command_obj: Command object (for calling Apply).
    copy_exception_handler: Copy exception handler (for use in Apply).
    logger: logging.Logger for outputting log messages.
    gzip_encoded: Whether to use gzip transport encoding for the upload.

  Returns:
    Elapsed upload time, uploaded Object with generation, crc32c, and size
    fields populated.
  providerNr"  r   )r   r   Fr   finishedcomponent_nummessage_typer   r   )r  r   r  r  )r  r  )r   total_bytes_transferredTarg_checkerparallel_operations_overrideshould_return_resultsr   key)r   )rz   r}   r   )r   r  fieldsencryption_tuple)r  r  )r  r  r   r  )r  z:Failed to delete some of the following temporary objects:

zSSome temporary components were not uploaded successfully. Please retry this upload.)<timer1   bucket_url_stringGetApiSelectorr   rR   r   crypto_key_sha256r9   r>   PARALLEL_UPLOADr&   r'   _DeleteTempComponentObjectFnr   r&  r%   r)   rA   
CreateLockr  r   r   FilterExistingComponentsr3   COMPONENT_TO_UPLOADr   r   r  r`   r9  r   r  r   EXISTING_COMPONENTEXISTING_OBJECT_TO_DELETEApplyr   gslibcommandDummyArgCheckerParallelOverrideReasonSLICErs  r  sortedr   ComposeRequestSourceObjectsValueListEntryr   HasGenerationlongr}   ComposeObject	ExceptionrI  joinkeysr6   r!   )(r   r   r   rJ  r   ru  r   r   command_objcopy_exception_handlerr   r   
start_timert  api_selectorencryption_keywrapperr   tracker_file_nameexisting_enc_key_sha256existing_prefixexisting_componentsrv  r   components_infory  components_to_uploadexisting_objects_to_deleter   component_str
cp_resultsuploaded_components	cp_resultr{  
componentsrequest_componentscomponent_urlr<  composed_objectobjects_to_deleteelapsed_times(                                           r   _DoParallelCompositeUploadr  E  s   F yy{*'(A(AB.**GNN*C,1&93 1BB9= 
 ))8)H)H)5w@
 9&"O
 ,P0/0.+*,?,A(?' 4? 177@EI &5&A?0-BD 
 !!2!.!47LN 1;;= /J,88*%)#,99--2G)57( #;$nj#B, (i'')>)>5@OI%%001I%%%%IIK"..""5i6G6G"H!,!@!@	BC ( 'iaL77M&1&D&D&/l&4OM"GaLIIK""1"5il"C!,!?!?	AB	 ' .iGIIK"!,!F!F		HI .   (M--//#.#E#E#K#K  ! "* iy|, "4G%H4Gqad4G%HH*_H% 
(;<J#

*
*
F
F ,, G .  
	$	$	&&*=+C+C&D# 01 $ !..#/. / 0O0- %'AA
&

mm33'2'I'I'O'O  Q ")!88	K
%%'#))+#'(;I(F.}=a@'6}'Ea'HJK "" 2)##!		!%%0%J%J	L	M 2  +, 
 	$% % z),		&&c &Id	K
%%'9diikDIK  & kk
G
))HMMO
$%&	& +, so   #T(/A U* AT-AU* *V6 -V*-7U'$U* *:V'$V6 &V''V6 *V36W9W	WWWc                    t        t        j                  ddt                    }|xr: |j	                          xr' |j                          xr |j                  dk(  xr | }|rq|dk(  rl|t        k\  rct        5  t        j                  d      s?| j                  dj                  t        j                  d            dz          dt        d<   d	d	d	       |xr |dkD  xr ||k\  S # 1 sw Y   xY w)
a  Determines whether parallel composite upload strategy should be used.

  Args:
    logger: for outputting log messages.
    allow_splitting: If false, then this function returns false.
    src_url: FileUrl corresponding to a local file.
    dst_url: CloudUrl corresponding to destination cloud object.
    file_size: The size of the source file, in bytes.
    gsutil_api: CloudApi that may be used to check if the destination bucket
        has any metadata attributes set that would discourage us from using
        parallel composite uploads.
    canned_acl: Canned ACL to apply to destination object, if any.

  Returns:
    True iff a parallel upload should be performed on the source file.
  rA  #parallel_composite_upload_thresholdgsr   	suggestedr  a  ==> NOTE: You are uploading one or more large file(s), which would run significantly faster if you enable parallel composite uploads. This feature can be enabled by editing the "parallel_composite_upload_threshold" value in your .boto configuration file. However, note that if you do this large files will be uploaded as `composite objects <https://cloud.google.com/storage/docs/composite-objects>`_,which means that any user who downloads such objects will need to have a compiled crcmod installed (see "gsutil help crcmod"). This is because without a compiled crcmod, computing checksums on composite objects is so slow that gsutil disables downloads of composite objects.TN)rs   r   rD  r   r
  r  r   'PARALLEL_COMPOSITE_SUGGESTION_THRESHOLDsuggested_sliced_transfers_locksuggested_sliced_transfersinfor  textwrapwrap)	r   r   r   r   ru  r   r   r  all_factors_but_sizes	            r    _ShouldDoParallelCompositeUploadr  (  s   2 )=jj@<>)?%
   
 nn
 ..D
  .  BaG::	('++K8DIIMM%&' *.. 	/ 37";/! 
)$  ;#F#J ;
:
:<% 
)	(s   9AC&&C/c                    |xs t        j                         }t        |       r_t        t	        | |||            }t        |      dk7  rt        d| z        |d   }t        |j                        |j                          fS t        |       } |j                         r| |j                         fS  |j                         r|dfS t        |      r|dfS |j                  j                  d      }|j!                  |j"                  |d|j$                  ddg	      }	|	D ]  }
|
j&                  t(        j*                  j,                  k(  r|
j.                  |dz   k(  r|dfc S |
j&                  t(        j*                  j0                  k(  r,|
j.                  j2                  |j                  d
z   k(  r|dfc S |
j&                  t(        j*                  j0                  k(  s|
j.                  j2                  |j                  k(  s|dfc S  ||fS )a-  Expands wildcard if present in url_str.

  Args:
    url_str: String representation of requested url.
    gsutil_api: gsutil Cloud API instance to use.
    project_id: project ID to use (for iterators).
    treat_nonexistent_object_as_subdir: indicates if should treat a non-existent
        object as a subdir.
    logger: logging.Logger instance to use for output. If None, the root Logger
        will be used.

  Returns:
      (exp_url, have_existing_dst_container)
      where exp_url is a StorageUrl
      and have_existing_dst_container is a bool indicating whether
      exp_url names an existing directory, bucket, or bucket subdirectory.
      In the case where we match a subdirectory AND an object, the
      object is returned.

  Raises:
    CommandException: if url_str matched more than 1 URL.
  )
project_idr   r   z)Destination (%s) must match exactly 1 URLr   T/prefixesz
items/name)prefix	delimiterr  r  z	_$folder$F)loggingLoggerr.   listrw   r  r!   r1   r  r   r   r   r   r0   r   r   ListObjectsr   r   datatyper   CsObjectOrPrefixTypePREFIXdataOBJECTr   )url_strr   r  "treat_nonexistent_object_as_subdirr   blr_expansionblrr-   r  list_iteratorobj_or_prefixs              r   ExpandUrlToSingleBlrr  h  s   6 %W^^%&gw)*4&,	./M
 =QH$% & &

C !0clln2DEE$W-+ [000233 [ k* ""))#.& (()@)@06362=2D2D1;\0J	 ) L-
 %m 	("?"?"F"FFfsl*4  

 
 H$A$A$H$H
H



!
![%<%<{%J
J 4  

 
 H$A$A$H$H
H



!
![%<%<
<5!!5 %< 9	::r   c                 X   t        j                  ddd      sy| j                         syt        | j                        ry|dk(  ry	 |j                  | j                  dg| j                         y# t        $ r/}t        |t        j                  j                        r Y d}~yd}~ww xY w)al  Makes a request to the destination API provider to trigger reauth.

  Addresses https://github.com/GoogleCloudPlatform/gsutil/issues/1639.

  If an API call occurs in a child process, the library that handles
  reauth will fail. We need to make at least one API call in the main
  process to allow a user to reauthorize.

  For cloud source URLs this already happens because the plurality of
  the source name expansion iterator is checked in the main thread. For
  cloud destination URLs, only some situations result in a similar API
  call. In these situations, this function exits without performing an
  API call. In others, this function performs an API call to trigger
  reauth.

  Args:
    destination_url (StorageUrl): The destination of the transfer.
    gsutil_api (CloudApiDelegator): API to use for the GetBucket call.
    worker_count (int): If greater than 1, assume that parallel execution
      is used. Technically, reauth challenges can be answered in the main
      process, but they may be triggered multiple times if multithreading
      is used.

  Returns:
    None, but performs an API call if necessary.
  rA  0trigger_reauth_challenge_for_parallel_operationsFNr   location)r  r  )r   getboolr   r.   r  	GetBucketr   r   r  rG  pyu2ferrorsPluginError)destination_urlr   worker_countr   s       r   .TriggerReauthForDestinationProviderIfNecessaryr    s    : 
BE
K
 
	#	#	%
 o001
 Q
##| ''  ) 
 !U\\--. /s   )A1 1	B):%B$$B)c                     | j                         rK| j                  dk(  r<|j                         r,t        j                  dd|j
                        }t        |      }|S )a  Translates Windows pathnames to cloud pathnames.

  Rewrites the destination URL built by ConstructDstUrl().

  Args:
    src_url: Source StorageUrl to be copied.
    dst_url: The destination StorageUrl built by ConstructDstUrl().

  Returns:
    StorageUrl to use for copy.
  \z\\r  )r   r   r   resubr  r1   )r   r   trans_url_strs      r   FixWindowsNamingr    sM     gmmt38J8J8LFF5#w'9'9:M"=1G	.r   c                 X   | j                         rg|j                         rWt        j                  j                  | j                        }t        j                  j                  |j                        }||k(  S | j
                  |j
                  k(  xr | j                  |j                  k(  S )zChecks if src_url and dst_url represent the same object or file.

  We don't handle anything about hard or symbolic links.

  Args:
    src_url: Source StorageUrl.
    dst_url: Destination StorageUrl.

  Returns:
    Bool indicator.
  )r   r   rf  normpathr   r  r}   )r   r   new_src_pathnew_dst_paths       r   
SrcDstSamer    s     W..077##G$7$78L77##G$7$78L<'''"4"44 5'"4"446r   c                 N   |j                         r|r|j                  rd|j                  z  }nd}|j                         rH|j                         s|j	                         r(|j                         rdnd}| j                  d||       y| j                  d|j                  |       y)a*  Logs copy operation, including Content-Type if appropriate.

  Args:
    logger: logger instance to use for output.
    src_url: Source StorageUrl.
    dst_url: Destination StorageUrl.
    dst_obj_metadata: Object-specific metadata that should be overidden during
                      the copy.
  z [Content-Type=%s]r	  z<STDIN>r  zCopying from %s%s...zCopying %s%s...N)r   r   r   r
  r  r  r  )r   r   r   rJ  content_type_msgsrc_texts         r   _LogCopyOperationr  5  s     /""+.>.J.JJg..0GNN4D#,,.yLH
KK&2BC
KK!7#5#57GHr   c                 0   t        |      }t        t              }t        j                         }	t	        |j
                  | |d      j                  }
t        j                  rPt        t        j                  d      5 }t        j                  |j                               j                  }
ddd       |j                  ||| j                  t        j                  ||
|j                   t"        ||
      }t        j                         }|j%                         }t'        ||j                        |_        t)        |j
                  t+        | ||t*        j,                  |j.                  d             ||	z
  |j.                  ||j0                  fS # 1 sw Y   xY w)a  Performs copy-in-the cloud from specified src to dest object.

  Args:
    src_url: Source CloudUrl.
    src_obj_metadata: Metadata for source object; must include etag and size.
    dst_url: Destination CloudUrl.
    dst_obj_metadata: Object-specific metadata that should be overidden during
                      the copy.
    preconditions: Preconditions to use for the copy.
    gsutil_api: gsutil Cloud API instance to use for the copy.
    decryption_key: Base64-encoded decryption key for the source object, if any.

  Returns:
    (elapsed_time, bytes_transferred, dst_url with generation,
    md5 hash of destination) excluding overhead like initial GET.

  Raises:
    CommandException: if errors encountered.
  Copyingr   r   r/  r-  N)src_generationr   r   progress_callbackr  r  decryption_tupler  Tr  r   r  )rP   rR   r   r  r*   r9  r5  r   r   r4  pickleloadsread
CopyObjectr}   r   r   UPLOAD_RETURN_FIELDSr  r/   r`   r3   FILE_CLOUD_COPYr   r~   )r   r<  r   rJ  r   r   decryption_keydecryption_keywrapperr  r  r
  test_fpdst_objend_time
result_urls                  r   _CopyObjToObjInTheCloudr  L  si   4 2.A1&9yy{*1*2I2I:A:AAJL MQD  //	%88$	?7 ,,w||~6;; 
@!!"2"2181C1C-D-O-O0=4E+2>>)=3H3H " 	J' YY[(}}*4Z5<5G5GI* '*::',,!" Z
!1!6!6

//
 9 
@	?s   <.FFc                    |j                   | j                         r| j                         s| j                         sq| j                  }d}|dk7  rMt
        j                  j                  |      }t        j                  ddd      rt        s	 t        j                  ddd|gt        j                  t        j                  	      }|j                         \  }}|j                  j!                          |j"                  j!                          |j$                  d
k7  s|rt'        d||j$                  |fz        |j)                         }t+        j,                  |      }n?|j1                  d      \  }	}	}
|
t2        v r
t2        |
   }nt5        j6                  |      \  }}	|st8        }||_         yyyyy# t.        $ r}t'        d|d|      d}~ww xY w)zDetects and sets Content-Type if src_url names a local file.

  Args:
    src_url: Source StorageUrl.
    dst_obj_metadata: Object-specific metadata that should be overidden during
                     the copy.
  N-rA  use_magicfileFfilez-bz--mime)stdoutstderrr   zAEncountered error running "file -b --mime %s" (returncode=%d).
%sz,Encountered OSError running "file -b --mime z"
.)r   r   r
  r  r   r   rf  realpathr   r  rk   
subprocessPopenPIPEcommunicater  closer  
returncoder!   r   r6  
ensure_strr   r   COMMON_EXTENSION_RULES	mimetypes
guess_typern   )r   rJ  r   r   real_file_pathpoutputr   r   r  	extensions              r   _SetContentTypeFromFiler0    s    ""*w/@/@/B



W^^%5 %%KL cww''4n	/5	9*	#hG&0oo&0oo7! --/-&%
((..

((..
\\Q%"'*8!,,)NOP P  ,5, )33C81i../	:,%00@/,)l#/ K &6
 0C*4  	# q"# #	#s   CF6 6	G?GGc                    t        |j                  | |d      j                  }t        j                  rPt        t        j                  d      5 }	t        j                  |	j                               j                  }ddd       t        j                         }
t        t              }| j                         s| j                         r7|j                  ||t        j                  ||||j                   t"        |	      }n7|j%                  ||t        j                  |||||j                   t"        |
      }t        j                         }||
z
  }||fS # 1 sw Y   xY w)a  Uploads the file using a non-resumable strategy.

  This function does not support component transfers.

  Args:
    src_url: Source StorageUrl to upload.
    src_obj_filestream: File pointer to uploadable bytes.
    src_obj_size (int or None): Size of the source object.
    dst_url: Destination StorageUrl for the upload.
    dst_obj_metadata: Metadata for the target object.
    preconditions: Preconditions for the upload, if any.
    gsutil_api: gsutil Cloud API instance to use for the upload.
    gzip_encoded: Whether to use gzip transport encoding for the upload.

  Returns:
    Elapsed upload time, uploaded Object with generation, md5, and size fields
    populated.
  	Uploadingr  r-  N)object_metadatar   r   r
  r  r  r  r   )	r3  r   r   r   r
  r  r  r  r   )r*   r9  r5  r   r   r4  r  r  r  r  rR   r   r
  r  UploadObjectStreamingr   r   r  UploadObject)r   src_obj_filestreamsrc_obj_sizer   rJ  r   r   r   r
  r  r  r  uploaded_objectr  r  s                  r   _UploadFileToObjectNonResumabler9    s:   4 2 	" #'$	  //	%88$	?7 ,,w||~6;; 
@yy{*1&97>>+ 66(*55#+.#! 7 	#O !--(*55#+.#! . 
#O YY[(J&,		&&C 
@	?s   .EEc
                    t        |t        j                  |j                  |j                              t        t              }
|
r'|
j                  r|
j                  j                  d      ndfd}t        |      }|r|j                  d| j                         d}|rt        |      nd}t        |j                  | ||d	      j                  }t         j"                  rPt%        t         j"                  d
      5 }t'        j(                  |j+                               j                  }ddd       t-        j,                         }d}|rM	 |j/                  ||t         j0                  ||j                  |||
t2        |||	      }d}|stA               	 |rMt-        j,                         }||z
  }|fS # 1 sw Y   xY w# t4        $ r}|j                  d| j                  z         |dz  }|t7               k  }|s 	 |j                  d|j8                  z         |j;                  |j8                  |j                         n# t<        $ r Y nt>        $ r  w xY wtA               |j                  dd| j                  d       n2# tA               |j                  dd| j                  d       w xY w|j                  d| j                  ||fz         d}|jC                  d       |rt        |      nd}t        |j                  | ||d	      j                  }tE        |j                  tG        |t-        j,                         |             t-        jH                  tK        tM        jL                         d|z  z  tO                            Y d}~d}~wtP        $ r d} w xY w# |stA               w w xY w)a  Uploads the file using a resumable strategy.

  Args:
    src_url: Source FileUrl to upload.  Must not be a stream.
    src_obj_filestream: File pointer to uploadable bytes.
    src_obj_size (int or None): Size of the source object.
    dst_url: Destination StorageUrl for the upload.
    dst_obj_metadata: Metadata for the target object.
    preconditions: Preconditions for the upload, if any.
    gsutil_api: gsutil Cloud API instance to use for the upload.
    logger: for outputting log messages.
    is_component: indicates whether this is a single component or whole file.
    gzip_encoded: Whether to use gzip transport encoding for the upload.

  Returns:
    Elapsed upload time, uploaded Object with generation, md5, and size fields
    populated.
  r  r"  Nc                 L    t         t        t        |       i}t        |       y)a  Creates a new tracker file for starting an upload from scratch.

    This function is called by the gsutil Cloud API implementation and the
    the serialization data is implementation-specific.

    Args:
      serialization_data: Serialization data used in resuming the upload.
    N)r7   r=   r   r@   )serialization_datar  r   r  s     r   _UploadTrackerCallbackz<_UploadFileToObjectResumable.<locals>._UploadTrackerCallback/  s*     	()>*C0B,CD 0$7r   r   zResuming upload for %sTr2  )r   r  r   r/  r-  r   )r3  r   r   r  r   r<  r  r  tracker_callbackr
  r   Fz:Caught ResumableUploadStartOverException for upload of %s.r   z8Checking that bucket %s exists before retrying upload...zDeleted tracker file z for resumable upload of z before retrying.zRestarting upload of %s from scratch (retry #%d) after exception indicating we need to start over with a new resumable upload ID: %s)num_retriesr   ))r9   r>   UPLOADr  r   rR   r   r  r&  r:   r  r  r  r*   r9  r5  r   r   r4  r  r  r  r  UploadObjectResumabler   r  r   rG   r   r  r   r   r6   seekr`   r4   sleepminrandomrF   r   )r   r6  r7  r   rJ  r   r   r   r   r   r  r=  tracker_data	retryabler  r
  r  r  num_startover_attemptsr8  r   r  r  r   r  s                          @@r   _UploadFileToObjectResumablerI  	  s   8 )%%8: 2&9 
#8#J#J --44W=
 
8" &7LN,
KK('*<*<=)2>%g.D-1! "
 #'$  //	%88$	?7 ,,w||~6;; 
@ yy{* 	H-"88
*,77%>>)0%1-# 9 %o ir +,S 	V YY[(J&,
	((u 
@	?8 - 3#kkN$$% &
 !)MO;iKN$++, 	--44w~~N"  	  	+,#4g6H6HJ 	K 	+,#4g6H6HJ 	K kkP!7;<= la 6B)'2m5

!
!%$&
 '+d  

!
!
 $		,BDE
 jj
fmmo$:!:; "# # ) i +, sn   .F;;G ;G
N33N#AI
J	I J
I  J#.N#/K  CN#N6 #N33N6 6Oc                     d}d}| j                  d      }|r|rd}||fS |t        k(  s|rt        |      dkD  r|d   |v r| }|}||fS )a  Selects how an upload should be compressed.

  This is a helper function for _UploadFileToObject.

  Args:
    object_name: The object name of the source FileUrl.
    is_component: indicates whether this is a single component or whole file.
    gzip_exts: List of file extensions to gzip prior to upload, if any.
               If gzip_exts is GZIP_ALL_FILES, gzip all files.
    gzip_encoded: Whether to use gzip transport encoding for the upload. Used
        in conjunction with gzip_exts for selecting which files will be
        encoded. Streaming files compressed is only supported on the JSON GCS
        API.

  Returns:
    A tuple: (If the file should be gzipped locally, if the file should be gzip
    transport encoded).
  Fr   Tr   r  )splitr   r  )r   r   r   r   zipped_filegzip_encoded_filefname_partss          r    _SelectUploadCompressionStrategyrO    sx    , +!!#&+
 l 
'	'' 	^#	s;'!+B90L""K$	'	''r   c                 X   ||t         k\  r|j                  d|        t        j                         \  }}d}	 | j	                         s| j                         rt        d      |(t        |      dt        |      z  k  rt        d| z        t        j                  ddt              }t        j                  |d|	      }|j                  t              }|r)|j!                  |       |j                  t              }|r)|r|j#                          t%        j"                  |       |j#                          t$        j&                  j)                  |      }	t        |d
      }
t+        |      |
|	fS # |r|j#                          t%        j"                  |       |j#                          w xY w)a  Compresses a to-be-uploaded local file to save bandwidth.

  This is a helper function for _UploadFileToObject.

  Args:
    src_url: Source FileUrl.
    src_obj_filestream: Read stream of the source file - will be consumed
      and closed.
    src_obj_size (int or None): Size of the source file.
    logger: for outputting log messages.

  Returns:
    StorageUrl path to compressed file, read stream of the compressed file,
    compressed file size.
  NzCompressing %s (to tmp)...zgzip compression is not currently supported on streaming uploads. Remove the compression flag or save the streamed output temporarily to a file before uploading.r   z|Inadequate temp space available to compress %s. See the CHANGING TEMP DIRECTORIES section of "gsutil help cp" for more info.rA  gzip_compression_levelwb)compresslevelr-  )rM   r  tempfilemkstempr
  r  r!   rh   r  r   getintr   gzipr4  r  GZIP_CHUNK_SIZEwriter&  r   rf  getsizer1   )r   r6  r7  r   gzip_fh	gzip_pathgzip_fpcompression_levelr  	gzip_sizecompressed_filestreams              r   _ApplyZippedUploadCompressionra    s   $ ,2J"J
KK,g6!))+7I' W^^- 45 5 ^I%>'(3|+<'<&= BDKL M M h0H&DFii	47HIG""?3D
mmD$$_5d  mmoHHWggooi()y$/	i	(*?	JJ mmoHHWs   CE0 09F)c                 2   d}d}	 |r0|s.t         j                  j                  5   |        \  }}ddd       n
 |        \  }}|j                          |r$	 t	        j
                  |j                         ||fS ||fS # 1 sw Y   CxY w# t        $ r" |j                  d|j                         Y ||fS w xY w# |j                          |rL	 t	        j
                  |j                         w # t        $ r |j                  d|j                         Y w w xY ww xY w)a  Handles setup and tear down logic for uploads.

  This is a helper function for _UploadFileToObject.

  Args:
    upload_delegate: Function that handles uploading the file.
    upload_url: StorageURL path to the file.
    upload_stream: Read stream of the file being uploaded. This will be closed
      after the upload.
    zipped_file: Flag for if the file is locally compressed prior to calling
      this function. If true, the local temporary file is deleted after the
      upload.
    gzip_encoded_file: Flag for if the file will be uploaded with the gzip
      transport encoding. If true, a lock is used to limit resource usage.
    parallel_composite_upload: Set to true if this upload represents a
      top-level parallel composite upload (not an upload of a component). If
      true, resource locking is skipped.
    logger: For outputting log messages.

  Returns:
    The elapsed upload time, the uploaded object.
  NzZCould not delete %s. This can occur in Windows because the temporary file is still locked.)	r  r  !concurrent_compressed_upload_lockr&  r   unlinkr   r  warning)	upload_delegate
upload_urlupload_streamrL  rM  parallel_composite_uploadr   r  r8  s	            r   _DelegateUploadFileToObjectrj    s-   2 ,/G !:==::(7(9%o ;: '6&7#lO G
		*(() 
	&&	&&) ;:   G./9/E/E	G 
	&&	G G
		*(()  G./9/E/E	GG sW   B6 A<B6 B <BB6 %B32B36D
C*)D*%DDDDc                   	 !" rj                   st        j                  dd      }|r|_         | !| |t        | j                  |
|      \  }rsj                  d|        n`|r^t        | ||      \  ! d_        j                  sd_        n1dj                  j                         vrxj                  dz  c_        sEt        j                  t        !t        j                         t        j                  d             d	}d	}t               t!        fd
xs i D              }t#        |!|t$        j&                        }dnt)               k  xs" | j+                         xs | j-                         }| j+                         s| j-                         rCj/                  j0                        t2        j4                  k(  r }t7        |t9                      |st;              rt=         |!      "n "	 !fd}!"fd}!"f
d}|r|}n|r|}n|}t?        |! ||      \  }}|s'	 tA        |      }tC        || j                  |d       j]                         }|jZ                  |_-        t_        ||jZ                        |_-        sEt        j                  t        !t        j                         t        j                  d             ||j`                  ||jb                  fS # tD        $ r tF        rltI        jJ                  jL                  jN                  |jP                        }j                  tR        z   _&        jU                  |j0                         jW                  jX                  j                  |jZ                  j0                          w xY w)a|  Uploads a local file to an object.

  Args:
    src_url: Source FileUrl.
    src_obj_filestream: Read stream of the source file to be read and closed.
    src_obj_size (int or None): Size of the source file.
    dst_url: Destination CloudUrl.
    dst_obj_metadata: Metadata to be applied to the destination object.
    preconditions: Preconditions to use for the copy.
    gsutil_api: gsutil Cloud API to use for the copy.
    logger: for outputting log messages.
    command_obj: command object for use in Apply in parallel composite uploads.
    copy_exception_handler: For handling copy exceptions during Apply.
    gzip_exts: List of file extensions to gzip prior to upload, if any.
               If gzip_exts is GZIP_ALL_FILES, gzip all files.
    allow_splitting: Whether to allow the file to be split into component
                     pieces for an parallel composite upload.
    is_component: indicates whether this is a single component or whole file.
    gzip_encoded: Whether to use gzip transport encoding for the upload. Used
        in conjunction with gzip_exts for selecting which files will be
        encoded. Streaming files compressed is only supported on the JSON GCS
        API.

  Returns:
    (elapsed_time, bytes_transferred, dst_url with generation,
    md5 hash of destination) excluding overhead like initial GET.

  Raises:
    CommandException: if errors encountered.
  rA  content_languagez+Using compressed transport encoding for %s.rW  zno-transformz,no-transformFr  Nc              3   6   K   | ]  }| |          f  y wNr   .0r)  	hash_algss     r   	<genexpr>z&_UploadFileToObject.<locals>.<genexpr>        FosC3)*o   )r   r   r  c                  N    t        	
t        j                         S N)r   )r  r   r   )r  r  rJ  r   r   rM  r   r   upload_sizerh  rg  s   r   CallParallelCompositeUploadz8_UploadFileToObject.<locals>.CallParallelCompositeUpload  s;    %m&0&-&6&=&H&H&1&3&0&1&<&,3DF Fr   c            
      *    t               S rv  )r9  )rJ  r   r   rM  r   rw  rg  wrapped_filestreams   r   CallNonResumableUploadz3_UploadFileToObject.<locals>.CallNonResumableUpload  s)    *:+=+6+2+;+8+58IK Kr   c                  .   
 t        	 
      S )N)r   r   )rI  )
rJ  r   r   rM  r   r   r   rw  rg  rz  s
   r   CallResumableUploadz0_UploadFileToObject.<locals>.CallResumableUpload  s/    '
(:(3(/(8(5(2(.5A5F	H 	Hr   T)rY  r   r   r|   r}   r  )2contentLanguager   	get_valuerO  r   r   ra  contentEncodingcacheControllowerr`   r9  r3   r  FILE_UPLOADr[   dictr  r   r   rH   r
  r  r  r   r   JSONr,   rE   r  r\   rj  r*  r`  r"   _RENAME_ON_HASH_MISMATCHr   r   r   r   r|   _RENAME_ON_HASH_MISMATCH_SUFFIXr  DeleteObjectr   r}   r  r/   r   r~   )#r   r6  r7  r   rJ  r   r   r   r  r  r   r   r   r   rl  rL  r  r8  r'  ri  non_resumable_uploadorig_streamrx  r{  r}  delegater(  corrupted_obj_metadatar  rM  rq  rw  rh  rg  rz  s#      ```````  `                @@@@@@r   r   r   E  s   X 
!1!A!A''2DE)9&*$-+#C<L$B +  |
LL>H-J#\6.;*J{'-$ ((&4#	/<<BBD	D##6#	JIIK!,!8!8$"	$% ,/!)Fio2oFF)>(335 !, 31.01 +4;4D4D4F+!..*  W^^-8K<L<LLK7.02M 
#s9~ 2-2;ZQ 'F FK K
H 
H *H%H"H"=
M;8I#), 
#+I6g6"&&!#0 }}*)44*4Z5D5O5OQ* 
JIIK!,!8!8$!	#$ ,,j

!
!
# #E ! 	!!2!9!9!&&#** %%"' ")!4!4!@"A4.'.~~ 	 	7 g11%11)8)C)C'.~~  7 !s   $&L' 'B:O!c                    t         j                  j                  | j                        }|r5t         j                  j	                  |      s	 t        j
                  |       d}t        |      r*d}t        j                  |       }|j                  d|       nt        j                  |       }t         j                  j	                  | j                        rt        j                  | j                         t         j                  j	                  |      st        |d      }|j!                          ||fS # t        $ r(}|j                  t        j                  k7  r Y d}~d}~ww xY w)a  Creates a new download file, and deletes the file that will be replaced.

  Names and creates a temporary file for this download. Also, if there is an
  existing file at the path where this file will be placed after the download
  is completed, that file will be deleted.

  Args:
    dst_url: Destination FileUrl.
    src_obj_metadata: Metadata from the source object.
    logger: for outputting log messages.

  Returns:
    (download_file_name, need_to_unzip)
    download_file_name: The name of the temporary file to which the object will
                        be downloaded.
    need_to_unzip: If true, a temporary zip file was used and must be
                   uncompressed as part of validation.
  NFTz$Downloading to temp gzip filename %sw)r   rf  rg  r   existsmakedirsr   errnoEEXISTr]   rC   GetTempZipFileNamer  GetTempFileNamerd  r4  r&  )r   r<  r   dir_namer   need_to_unzipdownload_file_namer   s           r   _GetDownloadFiler  	  s   & WW__W001(bggnnX.kk(
 - )*M,??H
KK68JK,<<WE
 WW^^G''(IIg!!" 
*	+	 #	&BHHJ	]	**;  	
ELL	  
!s   D4 4	E%=E  E%c                    t        t        j                  ddt                    }t        j                  ddt
              }t        j                  ddt              }|j                  xr
 t               }|xs	 |t        k(  }|xr? | t        j                  j                  uxr! |dkD  xr |xr |dkD  xr |j                  |k\  }	|	s|j                  t        k\  rxt               sn|t        k7  ret        5  t         j                  d      s?|j#                  dj%                  t'        j(                  d	            dz          d
t         d<   ddd       |	S |	S # 1 sw Y   |	S xY w)a|  Determines whether the sliced download strategy should be used.

  Args:
    download_strategy: CloudApi download strategy.
    src_obj_metadata: Metadata from the source object.
    allow_splitting: If false, then this function returns false.
    logger: logging.Logger for log message output.

  Returns:
    True iff a sliced download should be performed on the source file.
  rA   sliced_object_download_threshold%sliced_object_download_max_componentsrB  r   r   r  r  z==> NOTE: You are downloading one or more large file(s), which would run significantly faster if you enabled sliced object downloads. This feature is enabled by default but requires that compiled crcmod be installed (see "gsutil help crcmod").TN)rs   r   rD  r   rV  r   rV   rz   rI   rW   r   r   r   r   r  r  r  r  r  r  r  )
download_strategyr<  r   r   r  max_componentsrK  parallel_hashinghashing_okay	use_slices
             r   _ShouldDoSlicedDownloadr  R	  sq    &:jj=9;&<" ==!H!NP. 

8^#?A%,,G1E1G!L%8<L%L, I (A(A(J(JJI!I&2I 0!3I  $$(HH	  FF

 %8<L%L	('++K8DIIMMKLM  	 37";/ 
) 
 
) 
s   1AEEc                 N  	 t        | |      }t        j                  t        j                  |j
                        }t        | j                  |j                        	t        	fd	xs i D              }t        |j                  ||j                  |j                  || j                  ||j                  |j                  |j                   |j"                        \  }}d}d|v r|d   j$                  }t'        |j                  |||j                   |j                  z
  dz   |      S )a"  Function argument to Apply for performing sliced downloads.

  Args:
    cls: Calling Command class.
    args: PerformSlicedDownloadObjectToFileArgs tuple describing the target.
    thread_state: gsutil Cloud API instance to use for the operation.

  Returns:
    PerformSlicedDownloadReturnValues named-tuple filled with:
    component_num: The component number for this download.
    crc32c: CRC32C hash value (integer) of the downloaded bytes.
    bytes_transferred: The number of bytes transferred, potentially less
                       than the component size if the download was resumed.
    component_total_size: The number of bytes corresponding to the whole
                       component size, potentially more than bytes_transferred
                       if the download was resumed.
  r   )consider_crc32cc              3   6   K   | ]  }| |          f  y wrn  r   ro  s     r   rr  z5_PerformSlicedDownloadObjectToFile.<locals>.<genexpr>	  rs  rt  )r  
start_byteend_byter  Nrz   r   )rJ   r
   decode_messager   r   src_obj_metadata_jsonrY   r   rz   r  _DownloadObjectToFileResumabler   r   r  r  r  r  r  crcValuer   )
r   r   r   r   r<  r'  bytes_transferredserver_encoding
crc32c_valrq  s
            @r   "_PerformSlicedDownloadObjectToFiler  	  s   $ #3\B*--.?.F.F.2.H.HJ!#**2B2I2IK)Fio2oFF)*H
ll
ll
	jj&&}}((+*&o *8$--J	*4+=+=z+<+/==4??+JQ+N+:
< <r   c           	         | j                   sJ d}| j                  t               k  ryt        |t        j
                  |      }d}	 t        |d      }t        |      }	|	| j                  k(  rt        |d      }t        j                  |      }
|
d   | j                   k(  rA|
d   | j                  k(  r/|
d   |k(  r'	 |r|j                          |r|j                          yy|j                          |j                  d|j                  z         |r|j                          |r|j                          	 t)        ||       	 t        |d      5 }| j                   | j                  |d}
|j+                  t        j,                  |
             ddd       y# t        t        f$ rX}t!        |t              s|j"                  t"        j$                  k7  r!|j                  d|d	t'        |      d
       Y d}~d}~ww xY w# |r|j                          |r|j                          w w xY w# 1 sw Y   yxY w# t        $ r }t/        ||j0                         Y d}~yd}~ww xY w)a  Maintains sliced download tracker files in order to permit resumability.

  Reads or creates a sliced download tracker file representing this object
  download. Upon an attempt at cross-process resumption, the contents of the
  sliced download tracker file are verified to make sure a resumption is
  possible and appropriate. In the case that a resumption should not be
  attempted, existing component tracker files are deleted (to prevent child
  processes from attempting resumption), and a new sliced download tracker
  file is created.

  Args:
    src_obj_metadata: Metadata from the source object. Must include etag and
                      generation.
    dst_url: Destination FileUrl.
    download_file_name: Temporary file name to be used for the download.
    logger: for outputting log messages.
    api_selector: The Cloud API implementation used.
    num_components: The number of components to perform this download with.
  Nr-  rr|   r}   rw  z`Sliced download tracker file doesn't match for download of %s. Restarting download from scratch.z,Couldn't read sliced download tracker file (z): z#. Restarting download from scratch.r  )r|   r}   rw  )r|   r   rH   r9   r>   SLICED_DOWNLOADr4  ri   jsonloadr}   r&  rI  r   IOError
ValueErrorrG  r  ENOENTr   r5   rY  dumpsr;   strerror)r<  r   r  r   r  rw  r   r  r   existing_file_sizetracker_file_datar   s               r   #_MaintainSlicedDownloadTrackerFilesr  	  s:   , 
			, /11
()8)H)H)57 "	 $	'B$R -222+S1l))L1
F
#'7'<'<
<
L
)-=-H-H
H
,
-
? 
hhj  	 H''( 	) 
hhj Wl3	G		%"''(33*
 $567 
&	%% :	 / !Z AGGu||$;kk$c!f. /	/ 
hhj  
&	% 
 G'(91::FFGsh   A3F !.F H5 ?H)H5 G<$AG72G? 7G<<G? ?'H&)H2.H5 2H5 5	I>IIc                   \    e Zd ZdZd Zed        Zd Zej                  fdZ
d Zd Zd Zy	)
SlicedDownloadFileWrappera  Wraps a file object to be used in GetObjectMedia for sliced downloads.

  In order to allow resumability, the file object used by each thread in a
  sliced object download should be wrapped using SlicedDownloadFileWrapper.
  Passing a SlicedDownloadFileWrapper object to GetObjectMedia will allow the
  download component tracker file for this component to be updated periodically,
  while the downloaded bytes are normally written to file.
  c                 X    || _         || _        || _        d| _        || _        || _        y)a;  Initializes the SlicedDownloadFileWrapper.

    Args:
      fp: The already-open file object to be used for writing in
          GetObjectMedia. Data will be written to file starting at the current
          seek position.
      tracker_file_name: The name of the tracker file for this component.
      src_obj_metadata: Metadata from the source object. Must include etag and
                        generation.
      start_byte: The first byte to be downloaded for this parallel component.
      end_byte: The last byte to be downloaded for this parallel component.
    N)_orig_fp_tracker_file_name_src_obj_metadata_last_tracker_file_byte_start_byte	_end_byte)selfr   r  r<  r  r  s         r   __init__z"SlicedDownloadFileWrapper.__init__
  s2     DM/D-D#'D !DDNr   c                 0    t        | j                  dd      S )z<Returns the mode of the underlying file descriptor, or None.r   N)getattrr  r  s    r   r   zSlicedDownloadFileWrapper.mode'
  s     4==&$//r   c                    | j                   j                         }| j                  |k  r|t        |      z   | j                  dz   k  sJ t        j                  | j                   |       | j                   j                         }t        }| j                  $|| j                  z
  |kD  s|| j                  dz   k(  r)t        | j                  | j                  |       || _        y y Nr   )r  tellr  r  r  rD   write_to_fdTRACKERFILE_UPDATE_THRESHOLDr  r?   r  r  )r  r  current_file_pos	thresholds       r   rY  zSlicedDownloadFileWrapper.write,
  s    }}))+ 00s4y(DNNQ,>>@ ? $--.}}))+,I$$,4777)CDNNQ..'(?(?(,(>(>(8: &6d"	 	/r   c                 8   |t         j                  k(  r,| j                  j                  || j                  z   dz          n| j                  j                  ||       | j
                  | j                  j                         cxk  r| j                  dz   k  sJ  J y r  )r   SEEK_ENDr  rB  r  r  r  )r  r  whences      r   rB  zSlicedDownloadFileWrapper.seek=
  sw    
mm$..0145
mm(t}}113It~~7IIIIIIr   c                 6    | j                   j                         S rn  )r  r  r  s    r   r  zSlicedDownloadFileWrapper.tellD
  s    ==r   c                 8    | j                   j                          y rn  )r  flushr  s    r   r  zSlicedDownloadFileWrapper.flushG
  s    MMr   c                 R    | j                   r| j                   j                          y y rn  )r  r&  r  s    r   r&  zSlicedDownloadFileWrapper.closeJ
  s    }}
mm r   N)r   r   r   r   r  propertyr   rY  r   SEEK_SETrB  r  r  r&  r   r   r   r  r  
  sC    * 0 06" !# J r   r  c                    t        t        j                  ddt                    }t        j                  ddt
              }t        |j                  ||      \  }}g }	g }
t        |      D ]v  }||z  }t        |dz   |z  dz
  |j                  dz
        }|
j                  ||z
  dz          t        j                  |      }|	j                  t        || ||||||             x |	|
fS )a  Partitions an object into components to be downloaded.

  Each component is a byte range of the object. The byte ranges
  of the returned components are mutually exclusive and collectively
  exhaustive. The byte ranges are inclusive at both end points.

  Args:
    src_url: Source CloudUrl.
    src_obj_metadata: Metadata from the source object with non-pickleable
        fields removed.
    dst_url: Destination FileUrl.
    download_file_name: Temporary file name to be used for the download.
    decryption_key: Base64-encoded decryption key for the source object, if any.

  Returns:
    components_to_download: A list of PerformSlicedDownloadObjectToFileArgs
                            to be used in Apply for the sliced download.
  rA  %sliced_object_download_component_sizer  r   )rs   r   rD  r   rV  r   ro  r   r	   rD  rs  r
   encode_messager   )r   r<  r   r  r  sliced_download_component_sizer  rw  rx  components_to_downloadcomponent_lengthsr{  r  r  r  s                  r   _PartitionObjectr  O
  s   . $8jjB>@$A  ==!H!NP. $5^-K$M ..  a^#JAEn-13C3H3H13LMHX
2Q67 &445EF!!-a:O.57I.8(.<	>? ! 
 !2	22r   c
                 (   d|_         t        | ||||      \  }
}t        |
      }t        ||||||       t	        |d      5 }|j                  |j                         ddd       t        |
      D ]  \  }}|j                  |j                  z
  dz   }t        ||||j                  ||      }||j                  z
  }t        |	t        | |t        j                         |d|t        j                  |              |j                  t         |
|t"        j$                  j&                  |j(                  j*                  d      }t        |      |k  rt-        d|j.                  z        t1        |t3        d	      
      }|d   j4                  }|.t7        d|      D ]  }t9        |||   j4                  ||         }! d}t;        |      }|D ]  }t        |	t        | |t        j                         |j<                  d|j>                  t        j                               ||j@                  z  }|jB                  xr) |jB                  jE                         jG                  d      }|s|rt-        d|j.                  z         ||fS # 1 sw Y   ,xY w)a  Downloads a cloud object to a local file using sliced download.

  Byte ranges are decided for each thread/process, and then the parts are
  downloaded in parallel.

  Args:
    src_url: Source CloudUrl.
    src_obj_metadata: Metadata from the source object.
    dst_url: Destination FileUrl.
    download_file_name: Temporary file name to be used for download.
    command_obj: command object for use in Apply in parallel composite uploads.
    logger: for outputting log messages.
    copy_exception_handler: For handling copy exceptions during Apply.
    api_selector: The Cloud API implementation used.
    decryption_key: Base64-encoded decryption key for the source object, if any.
    status_queue: Queue for posting file messages for UI/Analytics.

  Returns:
    (bytes_transferred, crc32c)
    bytes_transferred: Number of bytes transferred from server this call.
    crc32c: a crc32c hash value (integer) for the downloaded bytes, or None if
            crc32c hashing wasn't performed.
  Nr+br   F)r   r  r  r  bytes_already_downloadedTr  zSSome components of %s were not downloaded successfully. Please retry this download.r  r  r   r  rW  zTDownload of %s failed because the server sent back data with an unexpected encoding.)$r{   r  r  r  r4  truncater   	enumerater  r  r8   r`   r3   r  COMPONENT_TO_DOWNLOADr  r  r  r  r  r  r  r!   r   r  r   rz   r	   rX   r]   component_total_sizer  r  r  r  r  )r   r<  r   r  r  r   r  r  r  r9  r  r  rw  r   r{  r   r   download_start_byter  r  rz   r  expect_gzipr  server_gzips                            r   _DoSlicedDownloadr  
  s   H )-%.>*<n/N++ -..%&6&8&,&46
 &"KK %%& ' ""89nq)	 4 44q8D./?/;/8/C/CT1N  3Y5I5IIGIIK""#!,!B!B-E	G	H :$   (--//#.#E#E#K#K  ! "* 	_~%
	&(/(;(;	<= =
 jj&AB*a=&1n%FJqM$8$8:KA:NOf & #$45+iGIIK"77!"+"9"9!,!B!B	DE 444,, F,,224==fE  ;!#*#6#678 8# * 
F	""C '&s   JJc                 B   |	|j                   dz
  }	|	|z
  dz   }|du}|j                  | j                        }d}|j                  }|r|d|z  z  }d}	 t	        |d      }|j                  |       |j                  | j                        }t        |      }t        |||||||      \  }}||k  s||	dz   kD  rt        |       t        d|z        |||z   k(  }||k7  xr | }|r|j                  d|       n|r|j                  d|       t        |||j                  	      }|s|rd
}||z
  }t        |t        |j                  || |d      j                         }||k  rt#        t$        ||z
        }|j'                  |      }||z  }|D ])  }||   j)                  t+        j,                  |             + |j/                  t1        |             ||k  rwn|s|j3                  d
       d
}t        |j                  ||| ||d      j                   }t4        j6                  rPt	        t4        j6                  d      5 }t9        j:                  |j'                               j                   }ddd       |r&|j                   t=               k\  rt?        |||||	      }tA        |      }|s|j                  |       |jC                  | jD                  | j                  |||	|| jF                  |j                   tH        jJ                  jL                  | j                  |||tO        |
            }|r|jW                          	 |	|z
  dz   }!|!|fS # 1 sw Y   xY w# tP        $ r#} |jS                  d| jT                  |        d} ~ ww xY w# |r|jW                          w w xY w)a]  Downloads an object to a local file using the resumable strategy.

  Args:
    src_url: Source CloudUrl.
    src_obj_metadata: Metadata from the source object.
    dst_url: Destination FileUrl.
    download_file_name: Temporary file name to be used for download.
    gsutil_api: gsutil Cloud API instance to use for the download.
    logger: for outputting log messages.
    digesters: Digesters corresponding to the hash algorithms that will be used
               for validation.
    component_num: Which component of a sliced download this call is for, or
                   None if this is not a sliced download.
    start_byte: The first byte of a byte range for a sliced download.
    end_byte: The last byte of a byte range for a sliced download.
    decryption_key: Base64-encoded decryption key for the source object, if any.

  Returns:
    (bytes_transferred, server_encoding)
    bytes_transferred: Number of bytes transferred from server this call.
    server_encoding: Content-encoding string if it was detected that the server
                     sent encoded bytes during transfer, None otherwise.
  Nr   r  z component %dr  zResumable download start point for %s is not in the correct byte range. Deleting tracker file, so if you re-try this download it will start from scratchzResuming download for %szRDownload already complete for %s, skipping download but will run integrity checks.)progressuser_projectr   r.  )r  r   r   r/  Downloading)r  override_total_sizer   r   r  r/  r-  )r  r  compressed_encodingr}   object_sizer  r  r<  r'  r
  r  z:Caught ResumableDownloadException (%s) for download of %s.),r   r  r   r   r4  rB  ri   r<   r6   r!   r  rK   r  r+   r*   r9  r5  rD  rL   r  rq  r6  rE  Progressr  r  r   r   r  r  rH   r  r]   GetObjectMediar   r}   r   r   r   rP   r   re  reasonr&  )"r   r<  r   r  r   r   r'  r  r  r  r  download_size	is_slicedr  r  download_namer   r  r  r  download_completeresumingr<  bytes_digestedtotal_bytes_to_digesthash_callbackbytes_to_readr  r>  r
  r  r  r   r  s"                                     r   r  r  
  s   D $$q(HZ'!+-4')**GNN*C,/ %%-_}44M"s	 %	(BGGJ,,gnn,EL$R-L.** Z'+>A+M)*$&345 5
 -
]0JJ#z1L;L7LHkk,m<	kk'(57 6$,,.
 $n1J>1

%j&=&=4A.5.55>	@ AEFm 2241NBDww}%-'!H
H

$
$S%6%6t%<
= "s4y) 22 kk!n3)#$& '+d  11'::DAW"LL8== B %**.@.BB$R):<L%/;b ..>? gg!""11






(1''&++$55??>>/-2>B 2 Do* 
hhj!44q8	O	++U BAB 
$ 

NNO88],	

 
hhj 
sE   FM A&M .M/C M MM 	N#NNN	 	Nc                    d}	 t        |d      }t        |d|j                        }t        |j                  | |d      j
                  }	t        j                  rPt        t        j                  d      5 }
t        j                  |
j                               j
                  }	ddd       |j                  | j                  | j                  || j                  |j                  t         j"                  j$                  | j&                  |||	t)        |            }|r|j+                          	 |j                  |fS # 1 sw Y   xY w# |r|j+                          w w xY w)	a^  Downloads an object to a local file using the non-resumable strategy.

  This function does not support component transfers.
  Args:
    src_url: Source CloudUrl.
    src_obj_metadata: Metadata from the source object.
    dst_url: Destination FileUrl.
    download_file_name: Temporary file name to be used for download.
    gsutil_api: gsutil Cloud API instance to use for the download.
    digesters: Digesters corresponding to the hash algorithms that will be used
               for validation.
    decryption_key: Base64-encoded decryption key for the source object, if any.

  Returns:
    (bytes_transferred, server_encoding)
    bytes_transferred: Number of bytes transferred from server this call.
    server_encoding: Content-encoding string if it was detected that the server
                     sent encoded bytes during transfer, None otherwise.
  Nr  r   )r  r  r  r-  )r}   r  r  r  r<  r'  r
  r  )r4  rK   r  r*   r9  r5  r   r   r  r  r  r  r   r   r}   r   r   r   r   r   rP   r&  )r   r<  r   r  r   r'  r  r   r<  r
  r  r  s               r   !_DownloadObjectToFileNonResumabler    s@   4 " 	 #	&B 6!**A*AC 4$	& '+d	  11'::DAW"LL8== B !//
%%$))"33<<-+0@ 0 BO 
hhj				//' BA  
hhj 
s%   A1E 5.D;#A7E ;E E Ec                    |j                   j                  |j                        rX|j                  dj	                  t        j                  d|j                   z                     t        d|j                   z        |j                  | j                        }t        |      }t        ||||      }t        |||      \  }}t        5  t        j                  |d      rt         dt        |<   ddd       |j"                  xr | }t%        |||j&                        t)        fd	xs i D              }d}|j*                  d
k(  }d
}t-        j,                         }|s|r1t/        | |||||||||j0                  
      \  }}d|v r||d   _        nv|t4        j6                  j8                  u rt;        | ||||||      \  }}nD|t4        j6                  j<                  u rt?        | |||||||      \  }}ntA        d|d|      t-        j,                         }|xr |jC                         j                  d      }tE        || ||||||||||	|
|      }t        5  t        jG                  |       ddd       tI        |j0                  tK        | ||tJ        jL                  |j*                  d             ||z
  |||fS # 1 sw Y   xY w# 1 sw Y   \xY w)a  Downloads an object to a local file.

  Args:
    src_url: Source CloudUrl.
    src_obj_metadata: Metadata from the source object.
    dst_url: Destination FileUrl.
    gsutil_api: gsutil Cloud API instance to use for the download.
    logger: for outputting log messages.
    command_obj: command object for use in Apply in sliced downloads.
    copy_exception_handler: For handling copy exceptions during Apply.
    allow_splitting: Whether or not to allow sliced download.
    decryption_key: Base64-encoded decryption key for the source object, if any.
    is_rsync: Whether or not the caller is the rsync command.
    preserve_posix: Whether or not to preserve POSIX attributes.
    use_stet: Decrypt downloaded file with STET binary if available on system.

  Returns:
    (elapsed_time, bytes_transferred, dst_url, md5), where time elapsed
    excludes initial GET.

  Raises:
    FileConcurrencySkipError: if this download is already in progress.
    CommandException: if other errors encountered.
  r  zSkipping attempt to download to filename ending with slash (%s). This typically happens when using gsutil to download from a subdirectory created by the Cloud Console (https://cloud.google.com/console)zInvalid destination path: %sr  FTN)consider_md5r  c              3   6   K   | ]  }| |          f  y wrn  r   ro  s     r   rr  z(_DownloadObjectToFile.<locals>.<genexpr>#  rs  rt  r   )r  r9  rz   r  zInvalid download strategy z chosen forfile rW  )is_rsyncr  use_stet)message_timer  r   r  )'r   r  r   rI  r  r  r  r#   r  r   r   r  r  open_files_lockopen_files_maprD  r   r~   rY   rz   r  r   r  r  r9  r  r   r   r   r  r   r  r!   r  _ValidateAndCompleteDownloaddeleter`   r3   FILE_DOWNLOAD)r   r<  r   r   r   r  r  r   r  r  r  r  r  r  sliced_downloadr  r  r  r'  r  r  r  r  rz   r  r  	local_md5rq  s                              @r   _DownloadObjectToFiler    s    J !!'--0
KK		N  	!" # 87;N;NN
OO**GNN*C,-g6+,=?O,;VE/ '7w7G'Q#m ,e4$$)-N%&  "))A/.A,!&/;2B2I2IK) Fio2oFF) /',,1yy{*	#G$4$+$6$/$*$:$03A1;1H1H	J 
Y	'-	($	h77@@	@+L





',( 
h77AA	A+I






'	,( /1CE F F YY[(LO$9$9$;$D$DV$L+*6+2+;+2+8+6+4+4+=+7+<+54<:H4<>)  ,-  ''*88',,!" Z
!2GY	GGs Z s   
&K"KKKc                    |j                   }d}|D ]  }||   r	d} n |rt        |      }nt        |j                  ||||      }d}d}	 t	        | ||||       t        ||	       |s|s|}nt        j                   |      }|
t"        kD  r| j%                  d|       d}	 t'        j(                  |d      }t)        |d      5 }|j+                  t,              }|r)|j/                  |       |j+                  t,              }|r)ddd       |r|j5                          	 t        j                  |       |s5	 t        |j                  ||||      }t	        | ||||       t        ||	       |rt7        j8                  ||||        t        j                  ||       t;        ||||
       d|v r|d   S y# t        $ r}|r| j                  d       d}no|	t        j                  k(  r| j                  d       |}d}nFt        ||	       t        rt        j                  ||t        z           t        j                  |        Y d}~d}~ww xY w# 1 sw Y   NxY w# t0        $ r}d	t3        |      v r|r|Y d}~qd}~ww xY w# |r|j5                          w w xY w# t        $ rG t        ||	       t        rt        j                  ||t        z           t        j                  |        w xY w)a  Validates and performs necessary operations on a downloaded file.

  Validates the integrity of the downloaded file using hash_algs. If the file
  was compressed (temporarily), the file will be decompressed. Then, if the
  integrity of the file was successfully validated, the file will be moved
  from its temporary download location to its permanent location on disk.

  Args:
    logger: For outputting log messages.
    src_url: StorageUrl for the source object.
    src_obj_metadata: Metadata for the source object, potentially containing
                      hash values.
    dst_url: StorageUrl describing the destination file.
    need_to_unzip: If true, a temporary zip file was used and must be
                   uncompressed as part of validation.
    server_gzip: If true, the server gzipped the bytes (regardless of whether
                 the object metadata claimed it was gzipped).
    digesters: dict of {string, hash digester} that contains up-to-date digests
               computed during the download. If a digester for a particular
               algorithm is None, an up-to-date digest is not available and the
               hash must be recomputed from the local file.
    hash_algs: dict of {string, hash algorithm} that can be used if digesters
               don't have up-to-date digests.
    temporary_file_name: Temporary file name that was used for download.
    api_selector: The Cloud API implementation used (used tracker file naming).
    bytes_transferred: Number of bytes downloaded (used for logging).
    gsutil_api: Cloud API to use for service and status.
    is_rsync: Whether or not the caller is the rsync function. Used to determine
              if timeCreated should be used.
    preserve_posix: Whether or not to preserve the posix attributes.
    use_stet: If True, attempt to decrypt downloaded files with the STET
              binary if it's present on the system.

  Returns:
    An MD5 of the local file, if one was calculated as part of the integrity
    check.
  TFNzDHash did not match but server gzipped the content, will recalculate.zMHash did not match but server may have gzipped the content, will recalculate.z/Uncompressing temporarily gzipped file to %s...r-  rR  zNot a gzipped filer  r  r,  )r   r*  r?  r9  r`  r5   r"   r   r   r   r  r   renamer  rd  rC   r  rv   r  rW  r4  r  rX  rY  r  r   r&  rB   decrypt_downloadrf   )r   r   r<  r   r  r  r'  rq  temporary_file_namer  r  r   r  r  r  final_file_namedigesters_succeededr)  rZ  digest_verifiedhash_invalid_exceptionr   unzipped_temporary_file_namer]  f_outr  s                             r   r  r  u  s   h ''/c S>!  .y9L.z/F/F/8:M/68HJL /"2Ow52 ;#6  $7#F#Fw#O  7"kkC!# G 		-t4g,d3u||O,
++d
o.$  4 
II!"	01H1H1:1M18:JLl 67$4o! ,7 w1M%' ))(/:_-&.,:<
 l u 
  ll " #o		(ll  !o ,7	!
		%!$CC	E  			%&-R 43
  % 
Q	',B %$% 
 
 !  ,7	!
		((+JJ	L
  			./si   F3  "I A II 64J 3	I<BIIII 	J%I<6J <JJ JAK,c                    t        |       }t        j                  j                  |j                        }|r	 t        j
                  |       t        |j                  d      5 }t        j                         }t        j                  ||       ddd       | j                         s|j                          t        j                         }	t        |t!        | ||	t         j"                  |r|j$                  ndd             |	z
  t        j                  j'                  |j                        |dfS # t        $ r)}|j                  t        j                  k7  r Y d}~d}~ww xY w# 1 sw Y   xY w)a  Copies a local file to a local file.

  Args:
    src_url: Source FileUrl.
    dst_url: Destination FileUrl.
    status_queue: Queue for posting file messages for UI/Analytics.
    src_obj_metadata: An apitools Object that may contain file size, or None.

  Returns:
    (elapsed_time, bytes_transferred, dst_url, md5=None).

  Raises:
    CommandException: if errors encountered.
  NrR  Tr  )rj   r   rf  rg  r   r  r   r  r  r4  r  shutilcopyfileobjr
  r&  r`   r3   FILE_LOCAL_COPYr   rZ  )
r   r   r9  r<  src_fpr  r   dst_fpr  r  s
             r   _CopyFileToFiler#    s&     (&WW__W001(kk(
 G&&J
vv& ' 
			
LLNYY[('*::0@',,d!" Z
1D1D!Ew

 '  	
ELL	  
! '&s#   D1 #+E&1	E#:EE#&E/c                      y rn  r   )r  s    r   _DummyTrackerCallbackr%  K  s    r   c                 \   t         j                  r$| j                  |j                  k7  rt        d      t         j                  sg |_        d}t         j
                  rPt        t         j
                  d      5 }	t        j                  |	j                               j                  }ddd       t        |      }
t        t              }t        j                         }t        | |j                   ||
||      }d}|j                   dk(  r@|j#                  ||t         j$                  ||j                  t&        |j                   |      }nf|j)                  ||t         j$                  ||j                  t&        |j                   t+        |j,                  | |d      j                  t.        |	
      }t        j                         }	 t1        || |||       |jO                         }tQ        ||jL                        |_&        tS        |j,                  tU        | ||tT        jV                  |j                   d             ||z
  |j                   ||jX                  fS # 1 sw Y   xY w# t2        $ r t4        ryt7        j8                  |j:                  |j<                  |j>                  
      }|j@                  tB        z   |_        tE        |      }|jG                  |||j                  ||       |jI                  |jJ                  |j@                  |jL                  |j                          w xY w)a  Copies from src_url to dst_url in "daisy chain" mode.

  See -D OPTION documentation about what daisy chain mode is.

  Args:
    src_url: Source CloudUrl
    src_obj_metadata: Metadata from source object
    dst_url: Destination CloudUrl
    dst_obj_metadata: Object-specific metadata that should be overidden during
                      the copy.
    preconditions: Preconditions to use for the copy.
    gsutil_api: gsutil Cloud API to use for the copy.
    logger: For outputting log messages.
    decryption_key: Base64-encoded decryption key for the source object, if any.

  Returns:
    (elapsed_time, bytes_transferred, dst_url with generation,
    md5 hash of destination) excluding overhead like initial GET.

  Raises:
    CommandException: if errors encountered.
  z"Cross-provider cp -p not supportedNr-  )r  r
  r  r   )r3  r   r   r  r  r   r  r2  r  )	r3  r   r   r  r  r   r
  r>  r  r~  )r  r  r  r  Tr  )-r   r   r   NotImplementedErroraclr   r4  r  r  r  r5  r]   rR   r   r  r    r   r5  r   r  rA  r*   r9  r%  rU  r"   r  r   r   r   r   r|   r   r  rP   r  r  r   r}   r  r/   r`   r3   FILE_DAISY_COPYr~   )r   r<  r   rJ  r   r   r   r  r
  r  r  r  r  	upload_fpr8  r  r  r  r  s                      r   _CopyObjToObjDaisyChainModer+  P  s   @ **nn&
B
CC	 	-	- //	%88$	?7 ,,w||~6;; 
@ ,,<=1&9yy{* 0 5 5 *4G2C/=?) /a --(*55##"". . 0O !66(*55##""5##&	( )-.. 7 0O YY[(
fgw0@%'. }}*4Z5D5O5OQ* '*::',,!" Z
!1!6!6


!
!
# #i 
@	?d 
 
077$$!((## %  '22> ?5nE2,%,^^-B-B	  D G//#//'6'A'A%,^^  5 
'
s   8.II$ I!$CL+c                    t               }| r<|j                  g d       |r|j                  dg       |s|j                  dg       nl|j                  g d       |r|j                  dt        z  dg       |r;dt        z  dt        z  dt        z  dt
        z  dt        z  g}|j                  |       |r|j                  ddg       |r|j                  dg       t        |      S )a  Determines the metadata fields needed for a copy operation.

  This function returns the fields we will need to successfully copy any
  cloud objects that might be iterated. By determining this prior to iteration,
  the cp command can request this metadata directly from the iterator's
  get/list calls, avoiding the need for a separate get metadata HTTP call for
  each iterated result. As a trade-off, filtering objects at the leaf nodes of
  the iteration (based on a remaining wildcard) is more expensive. This is
  because more metadata will be requested when object name is all that is
  required for filtering.

  The rsync command favors fast listing and comparison, and makes the opposite
  trade-off, optimizing for the low-delta case by making per-object get
  metadata HTTP call so that listing can return minimal metadata. It uses
  this function to determine what is needed for get metadata HTTP calls.

  Args:
    dst_is_cloud: if true, destination is a Cloud URL.
    skip_unsupported_objects: if true, get metadata for skipping unsupported
        object types.
    preserve_acl: if true, get object ACL.
    is_rsync: if true, the calling function is rsync. Determines if metadata is
              needed to verify download.
    preserve_posix: if true, retrieves POSIX attributes into user metadata.
    delete_source: if true, source object will be deleted after the copy
                   (mv command).
    file_size_will_change: if true, do not try to record file size.

  Returns:
    List of necessary field metadata field names.

  )r  componentCountcontentDispositionr  r  r   rz   r{   r|   r}   r~   	mediaLinkmetadatametagenerationr   timeCreatedr(  r   )	rz   r  r   r{   r|   r/  r~   r   r}   zmetadata/%sr2  r   )setrq  re   ra   rc   rd   rg   r  )	dst_is_cloudr   r   r  r  delete_sourcefile_size_will_changesrc_obj_fields_setposix_fieldss	            r   GetSourceFieldsNeededForCopyr9    s    N u   & ( )  
 
 !;] KL
*
$
*
$
(
"
)
#
(
"l - 
 ~./	 	!!r      Z   im  )nearlinecoldlinearchivec                 n   | j                   dk(  r|r|j                  r|j                  r|j                  j                         }t        j                  |d      }|rV|t        |j                        z   }t        j                         |k  r&|j                  d|| j                  |t        z         yyyyyyy)a  Warns when deleting a gs:// object could incur an early deletion charge.

  This function inspects metadata for Google Cloud Storage objects that are
  subject to early deletion charges (such as Nearline), and warns when
  performing operations like mv that would delete them.

  Args:
    src_url: CloudUrl for the source object.
    src_obj_metadata: source object metadata with necessary fields
        (per GetSourceFieldsNeededForCopy).
    logger: logging.Logger for outputting warning.
  r  NzWarning: moving %s object %s may incur an early deletion charge, because the original object is less than %s days old according to the local system time.)r   r2  r   r  EARLY_DELETION_MINIMUM_LIFETIMErD  rb   r  rI  r  ru   )r   r<  r   object_storage_classearly_deletion_cutoff_secondsminimum_delete_ages         r   "WarnIfMvEarlyDeletionChargeAppliesrD  I  s     nn!1""'7'D'D+88>>@$C$G$Gd%$!$
'
 !1!=!=
>?  
)	); !'"4"4)_<	> 
*	 %	 (E" "2r   c                 x    | j                   dk(  r+t        j                  r|j                  dk(  r
t	               yyy)a  Skips unsupported object types if requested.

  Args:
    src_url: CloudUrl for the source object.
    src_obj_metadata: source object metadata with storageClass field
        (per GetSourceFieldsNeededForCopy).

  Raises:
    SkipGlacierError: if skipping a s3 Glacier object.
  s3GLACIERN)r   r   r   r   SkipGlacierError)r   r<  s     r   MaybeSkipUnsupportedObjectrI  h  s?     nn66##y0

 1 7 r   c                     |j                   rMt        |j                   j                  t              }|s%t	        d|j                   j                  d|       |S y)a  Ensures a matching decryption key is available for the source object.

  Args:
    src_url: CloudUrl for the source object.
    src_obj_metadata: source object metadata with optional customerEncryption
        field.

  Raises:
    EncryptionException if the object is encrypted and no matching key is found.

  Returns:
    Base64-encoded decryption key string if the object is encrypted and a
    matching key is found, or None if object is not encrypted.
  z(Missing decryption key with SHA256 hash z#. No decryption key matches object N)r{   rQ   	keySha256r   r   )r   r<  r  s      r   GetDecryptionCSEKrL  y  s`     ((1++55v?N ..88'CD D  )r   c                    |r|j                         }ni }t        |      }|j                         r|j                  dk(  rt	        |      }n
t               }d}d}d}|j                         r|j                         r+|j                  |j                  k(  rt        j                  sd}t        j                  rt        |||        t        ||       t        ||      }|j                  }|j                  |_        t        j                  r|j                         r|j                  dk(  r|j                  st!        d|z        |j                  |_        |j                  dk(  rt#        |      }|rt%        ||       n|rt'        j(                  |||       }n|}	 t+        |      }|j7                         s|j9                         rd}nF|r|j                  r|s|j                  }n)t:        j<                  j?                  |j@                        }t        jB                  r|	jE                  |jF                  d|       |j                  dk(  r/|dk7  r*|(|tH        kD  rt!        d|dtK        tH              d      tL        r[|jO                         rK|j7                         r;tQ        jR                  t+        |      jU                         t:        jV                         t        jX                  r|jZ                  rt]        d      d|_-        |jO                         r3t:        j<                  j_                  |j@                        r
ta               |j                         r?	 |jc                  |jd                  |j@                  |j                        }|r
ta               |j                         r|j@                  |_4        |jd                  |_5        |j                         r#|j@                  |_4        |jd                  |_5        ntm        ||       to        tp              }|r=|jr                  tt        jv                  k(  r |j                  dk(  r|jx                  |_=        |rt}        ||d       t        j~                  rt        j~                  |_@        tq        j                  dd      t        k(  rd|_C        t        | |||       |j                         r|jO                         r\t        |j                  t        ||t        j                         t        j                  |d             t        ||||| |||||||      S |rWt        |j                  t        ||t        j                         t        j                  |d             t        |||||||      S t        |j                  t        ||t        j                         t        j                  |d             t        ||||||| |      S |j                         r;t        |||||||| |||
||      }|rt;        j                  |jh                         |S t        |j                  t        ||t        j                         t        j                  |d             t        |||j                  |      }|j7                         s)|j7                         st        |j@                  |||       |S # t,        $ rY}d|dt/        |      d	}|j0                  r+|xj2                  d
z  c_        | j5                  |       Y d}~yt!        |      d}~ww xY w# tf        $ r d}Y w xY w)a  Performs copy from src_url to dst_url, handling various special cases.

  Args:
    logger: for outputting log messages.
    src_url: Source StorageUrl.
    dst_url: Destination StorageUrl.
    gsutil_api: gsutil Cloud API instance to use for the copy.
    command_obj: command object for use in Apply in parallel composite uploads
        and sliced object downloads.
    copy_exception_handler: for handling copy exceptions during Apply.
    src_obj_metadata: If source URL is a cloud object, source object metadata
        with all necessary fields (per GetSourceFieldsNeededForCopy).
        Required for cloud source URLs. If source URL is a file, an
        apitools Object that may contain file size, or None.
    allow_splitting: Whether to allow the file to be split into component
                     pieces for an parallel composite upload or download.
    headers: optional headers to use for the copy operation.
    manifest: optional manifest for tracking copy operations.
    gzip_exts: List of file extensions to gzip, if any.
               If gzip_exts is GZIP_ALL_FILES, gzip all files.
    is_rsync: Whether or not the caller is the rsync command.
    preserve_posix: Whether or not to preserve posix attributes.
    gzip_encoded: Whether to use gzip transport encoding for the upload. Used
        in conjunction with gzip_exts. Streaming files compressed is only
        supported on the JSON GCS API.
    use_stet: If True, will perform STET encryption or decryption using
        the binary specified in the boto config or PATH.

  Returns:
    (elapsed_time, bytes_transferred, version-specific dst_url) excluding
    overhead like initial GET.

  Raises:
    ItemExistsError: if no clobber flag is specified and the destination
        object already exists.
    SkipUnsupportedObjectError: if skip_unsupported_objects flag is specified
        and the source is an unsupported type.
    CommandException: if other errors encountered.
  r  NFTzZNo OWNER permission found for object %s. OWNER permission is required for preserving ACLs.rF  zError opening file "z": r   r   r   "zV" exceeds the maximum gsutil-supported size for an S3 upload. S3 objects greater than zB in size require multipart uploads, which gsutil does not support.zASpecifying x-goog-if-generation-match is not supported with cp -nr   r  )overriderA  rB  r  )r   r  r  r  r  r  )r   r   r   )r9  r<  r  )Tcopyro   r   r   rp   r   r   r   r   rD  rI  rL  r   r   r   r(  r!   rq   rl   rB   encrypt_uploadrj   r  r   continue_on_errorr   r   r
  r  r   rf  rZ  r   r   Setr  S3_MAX_UPLOAD_SIZErt   rk   r   msvcrtsetmodefilenoO_BINARYr   	gen_matchr   r  ItemExistsErrorGetObjectMetadatar   r   r   r   r0  rR   r   crypto_typerO   CMEK
crypto_key
kmsKeyNamerm   r   r   rD  rW   r~   r  r`   r9  r3   r  r  r  r  r  r)  r+  r   rd  r   r#  rf   )r   r   r   r   r  r  r<  r   headersmanifestr   r  r  r   r  dst_obj_headersrJ  r   r6  r  copy_in_the_cloudr7  acl_textsource_stream_urlr   rc  
dst_objectr  uploaded_metadataresults                                 r   PerformCopyri    s   n llnOO
 /?gnn4,_=M!OM.7>>!A#//))(2BFKw(89&w0@AN#((L#3#?#? ++0B0B0D	4	(8(<(<,.567 	7 .11
 
4	01AB
()98
D#227GVL!	(/0AB W^^-l	.33H &**lWW__%6%B%BCl))LL##V\:nnD''
 
#$67	9: : G%%'G,<,<,>
NN'07792;;G''  9 : : !"mrww~~g.A.AB				11'2E2E292E2E;B>> 2 K

 
#//%11 &11 ' 3 3g'783F;))]-?-??$$9$D$D! ')9EJ//$;$N$N!ZZ.)-==  $FGW.>?

!
!
giik#.#<#<'$&' #7#3#*#-#)#.#93B2@,42@,46 6 


!
!
giik#.#>#>'$&' %W%5%,%5%2%/4BD D 

!
!
giik#.#>#>'$&' ))9)0)9)6)3)/8FH H  .g.@.:.5.>.;.8.4.9.D8A>M;GI 

		$))*

!
!
giik#.#>#>'$&' w&,6,C,C0@Bf
 (8(8(:"7#6#6#3,42@	B mI  (293q6Bg		&	&$$)$Ww''(z  
s1   [ 2\8 	\5A\0%\00\58]]c                   H    e Zd ZdZd Zd Zd Zd Zd Zd Z	ddZ
d	 Zd
 Zy)Manifestz2Stores the manifest items for the CpCommand class.c                     i | _         i | _        t        j                         | _        t
        j                  j                  |      | _        | j                          | j                          y rn  )itemsmanifest_filterrA   r  lockr   rf  
expandusermanifest_path_ParseManifest_CreateManifestFile)r  rf  s     r   r  zManifest.__init__  sP    DJD*557DI++D1Dr   c                    	 t         j                  j                  | j                        rt	        | j                  d      5 }d}t        j                  |      }|D ]G  }|r#	 |j                  d      }|j                  d      }d}|   }|   }|dv s9|| j                  |<   I 	 ddd       yy# t        $ r t        d| j                  z        w xY w# 1 sw Y   yxY w# t        $ r t        d	| j                  z        w xY w)
z|Load and parse a manifest file.

    This information will be used to skip any files that have a skip or OK
    status.
    r  TSourceResultz$Missing headers in manifest file: %sF)OKskipNzCould not parse %s)r   rf  r  rq  r4  csvreaderindexr  r!   rn  r  )	r  f	first_rowrz  rowsource_indexresult_indexsourcerh  s	            r   rr  zManifest._ParseManifest  s   H	**	+ $$$c*a)::a=&c;"yy2"yy2
 I&F&F' .4d""6*  +* 
,   ;&'M'+'9'9(: ; ;; +*&  H1D4F4FFGGHsG   ?C! C!"B0CC&C! 0"CCCC! C! !"Dc                     || j                   v S )z?Returns whether the specified src url was marked as successful.)rn  )r  srcs     r   WasSuccessfulzManifest.WasSuccessful  s    $&&&&r   c                 V   	 t         j                  j                  | j                        r,t        j                  | j                        j
                  dk(  rt        j                  rJt        | j                  dd      5 }t        j                  |      }|j                  g d       ddd       yt        | j                  dd      5 }t        j                  |      }|j                  g d       ddd       yy# 1 sw Y   yxY w# 1 sw Y   yxY w# t        $ r t        d	      w xY w)
z;Opens the manifest file and assigns it to the file pointer.r   r  r	  newline)
ru  DestinationStartEndMd5UploadIdzSource SizezBytes Transferredrv  DescriptionNrR  r   zCould not create manifest file.)r   rf  r  rq  r   st_sizer6  rF  r4  ry  writerwriterowr  r!   )r  r|  r  s      r   rs  zManifest._CreateManifestFile  s    #@ww~~d001774%%&..!377D&&R8AZZ]FOO   98 D&&a0AZZ]FOO   10% 4 98 10  @>??@sN   A=D ?)C;(D 1D )D1D ;D D D DD D D(c                 n    |y || j                   v r|| j                   |   |<   y ||i| j                   |<   y rn  rm  )r  r   r  values       r   rS  zManifest.Set  s;    } 
djj"djjocedjjor   c                    | j                  |d|       | j                  |d|       | j                  |dt        j                  j                  t        j                  j                        j                  d              y )N
source_uridestination_urir  tztzinfo)rS  datetimenowtimezoneutcr  )r  
source_urlr  s      r   
InitializezManifest.Initialize)  sb    HHZz2HHZ*O<HHZx'8'8'<'<@Q@Q@U@U'<'V'^'^fj'^'klr   c                 l   | j                  |d|       | j                  |d|       | j                  |d|       | j                  |dt        j                  j                  t        j                  j                        j                  d              | j                  |       | j                  |       y )Nbytesrh  descriptionr  r  r  )rS  r  r  r  r  r  _WriteRowToManifestFile_RemoveItemFromManifest)r  r  r  rh  r  s        r   	SetResultzManifest.SetResult/  s    HHZ"34HHZ6*HHZ4HHZX%6%6%:%:h>O>O>S>S%:%T%\%\dh%\%ij  ,  ,r   c                    | j                   |   }|d   |d   d|d   j                         z  d|d   j                         z  d|v r|d   ndd|v r|d   ndd	|v rt        |d	         ndd
|v rt        |d
         nd|d   |d   g
}|D cg c]  }t        j                  |       }}| j
                  5  t        r*t        j                  rt        | j                  ddd      }nt        | j                  dd      }t        j                  |      }|j                  |       |j                          ddd       yc c}w # 1 sw Y   yxY w)zBWrites a manifest entry to the manifest file for the url argument.r  r  z%sZr  r  r,  r	  	upload_idr   r  rh  r  ar   r  N)rm  	isoformatr   r6  r(  ro  rk   rF  r4  rq  ry  r  r  r&  )r  r   row_itemr  r  r|  r  s          r   r  z Manifest._WriteRowToManifestFile7  sA   zz#H"#&0022$..00 H,"!,!8b!'8!3HV")X"5HW2D 044teCNN5!tD4 
	##S!R8##S!,zz!}foodggi 
	 5 
s   
D;4A>E  E	c                     | j                   |= y rn  r  )r  r   s     r   r  z Manifest._RemoveItemFromManifestT  s     	

3r   N)r	  )r   r   r   r   r  rr  r  rs  rS  r  r  r  r  r   r   r   rk  rk    s7    :H@'%@N	%m-:r   rk  c                       e Zd ZdZy)rZ  zHException class for objects that are skipped because they already exist.Nr   r   r   r   rZ  rZ  [  s    Pr   rZ  c                   "     e Zd ZdZ fdZ xZS )SkipUnsupportedObjectErrorCException for objects skipped because they are an unsupported type.c                 8    t         t        |           d| _        y )NUnknown)superr  r  unsupported_typer  	__class__s    r   r  z#SkipUnsupportedObjectError.__init__c  s    	
$d46%Dr   r   r   r   r   r  __classcell__r  s   @r   r  r  `      K& &r   r  c                   "     e Zd ZdZ fdZ xZS )rH  r  c                 8    t         t        |           d| _        y )NrG  )r  rH  r  r  r  s    r   r  zSkipGlacierError.__init__k  s    	
D*,%Dr   r  r  s   @r   rH  rH  h  r  r   rH  c                    | j                   }| j                         rS| j                  t        d      d }|j	                  |      dk(  ryd|j                  |      j                  |      d   z  S | j                         rd| j                  z  S | j                  j                  |      j                  |      d   }t        ||      S )a?  Returns the path section before the final directory component of the URL.

  This handles cases for file system directories, bucket, and bucket
  subdirectories. Example: for gs://bucket/dir/ we'll return 'gs://bucket',
  and for file://dir we'll return file://

  Args:
    url: StorageUrl representing a filesystem directory, cloud bucket or
         bucket subdir.
    exp_src_url: StorageUrl representing the fully expanded object
        to-be-copied; used for resolving cloud wildcards.

  Returns:
    String name of above-described path, sans final path separator.
  zfile://Nr  z	file://%sr   z%s://)
r   r   r  r  findr   r   r   r   $ResolveWildcardsInPathBeforeFinalDir)r   r  seppast_schemepath_sans_final_dirs        r   r  r  p  s      			#]]_..Y1K";--c2==cB1EEE\\^SZZ--c2==cB1E	-.A;	OOr   c                 b   t        |       s| S t        |       j                  j                  d      }|j                  j                  d      }t	        t        |            D ]  }t        ||         s||   ||<    dj                  |      }|j                         }||_        |j                  S )af  Returns the path section for a bucket subdir with wildcards resolved.

  This handles cases for bucket subdirectories where the initial source URL
  contains a wildcard. In this case, src_url must be wildcard-expanded
  before calculating the final directory.

  Example:
    A bucket containing:
      gs://bucket/dir1/subdir/foo
      gs://bucket/dir2/subdir/foo

    and source URL gs://bucket/*/subdir
    and src_url_path_sans_final dir gs://bucket/*

    should yield final path gs://bucket/dir1 or gs://bucket/dir2 according to
    the expanded source URL.

  Args:
    src_url_path_sans_final_dir: URL string with wildcards representing a
        bucket subdir as computed from GetPathBeforeFinalDir.
    exp_src_url: CloudUrl representing the fully expanded object to-be-copied.

  Returns:
    String name of above-described path, sans final path separator.
  r  )	r.   r1   r   rK  r	   r  r  r  r  )r  r  wildcarded_src_obj_pathexpanded_src_obj_pathpath_segment_indexresolved_src_pathfinal_path_urls          r   r  r    s    6 
5	6&& 1!##.;uuSz %1177<!#&=">?/0BCD   2
3 01	 @ hh67$$&.0.		"	""r   c                 f    t        | |      }t        t        ||      d      }t        | |      }||fS )a  Gets info about a file partition for parallel file/object transfers.

  Args:
    file_size: The number of bytes in the file to be partitioned.
    max_components: The maximum number of components that can be composed.
    default_component_size: The size of a component, assuming that
                            max_components is infinite.
  Returns:
    The number of components in the partitioned file, and the size of each
    component (except the last, which will have a different size iff
    file_size != 0 (mod num_components)).
  r   )rr   maxrD  )ru  r  default_component_sizerw  rx  s        r   ro  ro    s?     !,BC. s>>:A>. !N;.
.	))r   c                     t        | |      }	 |j                  |j                  |j                  |j                  |j
                         y# t        $ r Y yw xY w)zGWrapper func to be used with command.Apply to delete temporary objects.r  N)rJ   r  r   r   r}   r   r   )r   url_to_deleter   r   s       r   r  r    s_    "35*
	M55)55'4'?'?%2%9%9  ; 
 	
 		s   =A 	AAc           	         g }|D cg c]  }|j                    }}| D ]  }||vs|j                  | |           g }g }	g }
|D ]  }|j                   | j                         vs|j                   |v rD|j                         }|j                   |_         |j                  |_        |	j                  |       r| |j                      }t        |j                  |j                  |j                        }t        |      }	 |j                  }|j                  |j                  |j                   |j                  |j                  g d      }|j                  }||k7  rx|j                  |       |j                  |j                          |j                  sO|j                  j                         }|j                  |_        |	j                  |       |j                  j                         }|j                  |_        |
j                  ||j                  f       |j                  |j                           |
rt!        j"                  dt%        |
             ||
|	fS c c}w # t        $ r d}Y w xY w)a]  Determines course of action for component objects.

  Given the list of all target objects based on partitioning the file and
  the list of objects that have already been uploaded successfully,
  this function determines which objects should be uploaded, which
  existing components are still valid, and which existing components should
  be deleted.

  Args:
    dst_args: The map of file_name -> PerformParallelUploadFileToObjectArgs
              calculated by partitioning the file.
    existing_components: A list of ObjectFromTracker objects that have been
                         uploaded in the past.
    bucket_url: CloudUrl of the bucket in which the components exist.
    gsutil_api: gsutil Cloud API instance to use for retrieving object metadata.

  Returns:
    components_to_upload: List of components that need to be uploaded.
    uploaded_components: List of components that have already been
                         uploaded and are still valid. Each element of the list
                         contains the dst_url for the uploaded component and
                         its size.
    existing_objects_to_delete: List of components that have already
                                been uploaded, but are no longer valid
                                and are in a versioned bucket, and
                                therefore should be deleted.
  )r{   r|   r~   )r}   r  r  Nz0Found %d existing temporary components to reuse.)r   rs  r  r  r}   r$   r   r   r   rT   r   r[  r   r   r~   r  r  r  r  )ry  r  
bucket_urlr   r  r   existing_component_namescomponent_nameobjects_already_chosenr  r  tracker_objectr   dst_arg	file_partr}  r   dst_metadata	cloud_md5!invalid_component_with_generations                       r   r  r    sj   : -@-@	i-@   !n55!!(>":; ! 
  "+n""(--/9""&<< c&22co%00cn '',~112G))7+=+= ,,.I 5Y?Kg11





''>>: 2 <l &&i K!!'*##N$>$>?		"	" -4OO,A,A,C)7E7P7P)4"))*KLOO!!#c%00cn  #w':':!;<##N$>$>?a ,d LLC()+  35O	PPIX   is   I<AI""I10I1rn  )FFFFFFFNFNN)F)NF)FN)FF)FFF)NTFF)NN)Nr   NN)TNFFF)FFFF)	NTNNNFFFF(  r   
__future__r   r   r   r   r#  collectionsr   ry  r  r  rW  r  r  r*  operatorr   r   r  r  rE  r  r  r6  r   r"  rT  r  r  r   	six.movesr	   apitools.base.protorpcliter
   botor   r1  r  gslib.cloud_apir   r   r   r   r   r   r   r   r   r   r   r   gslib.commands.composer   gslib.commands.configr   r   r   r   r   r   gslib.cs_api_mapr   gslib.daisy_chain_wrapperr    gslib.exceptionr!   r"   r#   gslib.file_partr$   gslib.parallel_tracker_filer%   r&   r'   r(   r)   gslib.progress_callbackr*   r+    gslib.resumable_streaming_uploadr,   r-   gslib.storage_urlr.   r/   r0   r1   "gslib.third_party.storage_apitoolsr2   r   gslib.thread_messager3   r4   gslib.tracker_filer5   r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   r@   gslib.utilsrA   rB   rC   rD   gslib.utils.boto_utilrE   rF   rG   rH   rI   gslib.utils.cloud_api_helperrJ   rK   gslib.utils.constantsrL   rM   rN   gslib.utils.encryption_helperrO   rP   rQ   rR   gslib.utils.hashing_helperrS   rT   rU   rV   rW   rX   rY   rZ   r[   r\   gslib.utils.metadata_utilr]   &gslib.utils.parallelism_framework_utilr^   r_   r`   gslib.utils.posix_utilra   rb   rc   rd   re   rf   rg   gslib.utils.system_utilrh   ri   rj   rk   gslib.utils.translation_helperrl   rm   rn   ro   rp   rq   gslib.utils.unit_utilrr   rs   rt   ru   rv   gslib.wildcard_iteratorrw   rF  r  r  rU  is_availabletop_level_managerr  r  r
  r  r  rr  rp  r  r   r   r   rX  r   r  r  rT  r  r  r)  r  r   r   r   r   r   r   r   r   r   r   r   r  r  r*  r?  rU  r`  rd  rl  r  r  r  r  r  r  r  r  r  r  r0  r9  rI  rO  ra  rj  r   r  r  r  r  objectr  r  r  r  r  r  r  r#  r%  r+  r9  r@  rD  rI  rL  ri  rk  rZ  r  rH  r  r  ro  r  r  r   r   r   <module>r     s    / & %  '  " 
        	    	  
       
   0    1 - $ / - 1 ) 6 9 4 = , 4 R M O O J @ ( 7 , 1 + $ E E L Q F ? ? P  . 8 6 2 W , 6 9 0 > 3 1 3 B > A . @ 9 2 ! + ! ; 2 / 4 6 < E : : & 7 A F A 7 I B C 7 3 : - 8 ? 9 = W H - 9 + , - = + 2 / 8 . I = ? D C H / 6 3 1 ) :77	$  46CC (99IMP 8,779 ! ",  M   4 )3+) % )3+))* %  %/'% !  "  ' *; ' , 
 (46CC (99IMP  #H"<"G"G"I   Iy I
+9x , /   %*$)%*.3#(&+&+$(27,0,0!@!/6L40?f :%	` $)ePD=J !@DFL"%?d *. %JZK2 -2`'R 15=<F =B $	g;T5v$6,I: ,0AH/0t 27B'\ /4.3a)J 38/427$(N4Kn7'H #'(,%*%*P#f7+t0f-<`PGfD DV %)	23z &*#'p#t 26./,026f,^ 6:=0N +/)-#().#(RHB +005*/gT)X 04#J +005/47<k"b _$_$_$# >>"D "& $$"nb	Rv Rji 
& &&1 &P<,#^*0	 bQr   