
    =                     j   d 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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mZ ddlmZ ddlZdZ G d dej6                        Z G d de      Z G d de      Z G d de      Z G d de      Z dZ!dZ"dZ#dZ$dZ%d Z&d! Z'd" Z( G d# d$e)      Z* G d% d&e)      Z+d' Z,d( Z-d) Z.dd*ej^                  j`                  ej^                  j`                  fd+Z1 G d, d-e)      Z2 G d. d/e)      Z3 G d0 d1ejh                        Z5y)2z4Utilities for interacting with Google Cloud Storage.    )absolute_import)division)unicode_literalsN)apis)gcloudignore)config)
exceptions)execution_utils)log)	resources)files)iso_duration)	platformszgs://c                       e Zd ZdZy)Errorz)Base class for exceptions in this module.N__name__
__module____qualname____doc__     2lib/googlecloudsdk/api_lib/storage/storage_util.pyr   r   +   s    1r   r   c                       e Zd ZdZy)GsutilErrorz-Exception raised when gsutil cannot be found.Nr   r   r   r   r   r   /   s    5r   r   c                   "     e Zd ZdZ fdZ xZS )InvalidNameErrorz.Error indicating that a given name is invalid.c                 R    t         t        |   dj                  ||||             y )Nz>Invalid {type} name [{name}]: {reason}

See {url} for details.)namereasontypeurl)superr   __init__format)selfr   r    	type_namer"   	__class__s        r   r$   zInvalidNameError.__init__6   s2    	
D*
"#)6tF/8c $* $CDr   )r   r   r   r   r$   __classcell__r(   s   @r   r   r   3   s    6D Dr   r   c                   *     e Zd ZdZdZdZ fdZ xZS )InvalidBucketNameErrorz5Error indicating that a given bucket name is invalid.bucketz9https://cloud.google.com/storage/docs/naming#requirementsc                 Z    t         t        |   ||| j                  | j                         y N)r#   r,   r$   TYPEURLr&   r   r    r(   s      r   r$   zInvalidBucketNameError.__init__B   $    	
 $0fdii+r   r   r   r   r   r0   r1   r$   r)   r*   s   @r   r,   r,   =   s    =	$C#+ +r   r,   c                   *     e Zd ZdZdZdZ fdZ xZS )InvalidObjectNameErrorz5Error indicating that a given object name is invalid.objectz8https://cloud.google.com/storage/docs/naming#objectnamesc                 Z    t         t        |   ||| j                  | j                         y r/   )r#   r6   r$   r0   r1   r2   s      r   r$   zInvalidObjectNameError.__init__L   r3   r   r4   r*   s   @r   r6   r6   G   s    =	$B#+ +r   r6   zeBucket names must contain only lowercase letters, numbers, dashes (-), underscores (_), and dots (.).z8Bucket names must start and end with a number or letter.zBucket names must contain 3 to 63 characters. Names containing dots can contain up to 222 characters, but each dot-separated component can be no longer than 63 characters.zjBucket names cannot be represented as an IP address in dotted-decimal notation (for example, 192.168.5.4).zmObject names can contain any sequence of valid Unicode characters, of length 1-1024 bytes when UTF-8 encoded.zFObject names must not contain Carriage Return or Line Feed characters.c                 D   | j                  d      }dt        |       cxk  rdk  rn nt        d |D              rt        | t              t        |       t        t        j                  t        j                  z   dz         z
  rt        | t              t        | d   | d   z         t        t        j                  t        j                  z         z
  rt        | t              t        |      dk(  r0d	j                  |      j                         rt        | t              y
y
)a  Validate the given bucket name according to the naming requirements.

  See https://cloud.google.com/storage/docs/naming#requirements

  Args:
    name: the name of the bucket, not including 'gs://'

  Raises:
    InvalidBucketNameError: if the given bucket name is invalid
  .      c              3   8   K   | ]  }t        |      d kD    yw)?   N)len).0cs     r   	<genexpr>z&_ValidateBucketName.<locals>.<genexpr>r   s     'HZAZs   z-_.r       N)splitr?   anyr,   VALID_BUCKET_LENGTH_MESSAGEsetstringascii_lowercasedigitsVALID_BUCKET_CHARS_MESSAGEVALID_BUCKET_START_END_MESSAGEjoinisdigit#VALID_BUCKET_DOTTED_DECIMAL_MESSAGE)r   
componentss     r   _ValidateBucketNamerS   f   s     zz#*
s4y
C
C'HZ'H$H
 'B
CCYV++fmm;eCDD
 'A
BBa48	s6#9#9FMM#IJJ
 'E
FF_bggj199;
 'J
KK <r   c                     | j                  t              r| t        t              d  }n| }t        |j	                  d             y )N/)
startswithGSUTIL_BUCKET_PREFIXr?   rS   rstrip)r"   r   s     r   ValidateBucketUrlrY      s:     	^^()s'()*DDdkk#&'r   c                   f    e Zd ZdZd Zed        Zed        Zedd       Zd Z	d Z
d Zd	 Zd
 Zy)BucketReferencez=A wrapper class to make working with GCS bucket names easier.c                     || _         y)zMCreates a BucketReference.

    Args:
      bucket: str, The bucket name
    Nr-   )r&   r-   s     r   r$   zBucketReference.__init__   s     DKr   c                 &     | |j                         S )z=Create a bucket reference from a bucket message from the API.r   )clsr-   s     r   FromMessagezBucketReference.FromMessage   s     v{{r   c                 d     | t         j                  j                  |d      j                        S )z=Parse a bucket URL ('gs://' optional) into a BucketReference.zstorage.buckets)
collection)r   REGISTRYParser-   )r`   r"   s     r   FromUrlzBucketReference.FromUrl   s/     y!!''8I'J r   c                    |r*|j                  t              st        j                  d      	 t	        |       | j                  |      S # t
        $ r-}t        j                  t        j                  |            d}~ww xY w)zEValidates that the argument is a reference to a Cloud Storage bucket.zIMust be a valid Google Cloud Storage bucket of the form [gs://somebucket]N)	rV   rW   argparseArgumentTypeErrorrY   r,   six	text_typerf   )r`   valuerequire_prefixerrs       r   FromArgumentzBucketReference.FromArgument   sw     e../CD&& ; ;;u " ;&&s}}S'9::;s   A
 
	B (A;;B c                 8    dj                  | j                        S )Nzgs://{}r%   r-   r&   s    r   ToUrlzBucketReference.ToUrl   s    DKK((r   c                 8    dj                  | j                        S )Nz"https://storage.googleapis.com/{0}rq   rr   s    r   GetPublicUrlzBucketReference.GetPublicUrl   s    /66t{{CCr   c                 4    | j                   |j                   k(  S r/   r]   r&   others     r   __eq__zBucketReference.__eq__   s    ;;%,,&&r   c                 &    | j                  |       S r/   ry   rw   s     r   __ne__zBucketReference.__ne__       {{5!!!r   c                 ,    t        | j                        S r/   )hashr-   rr   s    r   __hash__zBucketReference.__hash__   s    r   N)T)r   r   r   r   r$   classmethodra   rf   ro   rs   ru   ry   r|   r   r   r   r   r[   r[      s`    E    
  )D'"r   r[   c                       e Zd ZdZdZdZd Zed        Zed        Z	e
d        Ze
d        Ze
d	        Ze
dd
       Ze
dd       Ze
d        Zd Zd Zd Zd Zd Zy)ObjectReferencezGWrapper class to make working with Cloud Storage bucket/objects easier.z&^gs://(?P<bucket>[^/]+)/(?P<object>.+)z^gs://(?P<bucket>[^/]+)/?c                      || _         || _        y r/   r-   r   )r&   r-   r   s      r   r$   zObjectReference.__init__   s    DKDIr   c                     | j                   S )z:Emulates the object field on the object core/resource ref.r_   rr   s    r   r7   zObjectReference.object   s     99r   c                 ,    t        | j                        S )z9Gets a bucket reference for the bucket this object is in.)r[   r-   rr   s    r   
bucket_refzObjectReference.bucket_ref   s     4;;''r   c                 <     | |j                   |j                        S )z?Create an object reference from an object message from the API.r   )r`   objs     r   ra   zObjectReference.FromMessage   s     szz388$$r   c                     t        |       dt        |j                  d            cxk  rdk  sn t        |t              d|v sd|v rt        |t
               | ||      S )z<Create an object reference after ensuring the name is valid.r   zutf-8i   
)rS   r?   encoder6   VALID_OBJECT_LENGTH_MESSAGEVALID_OBJECT_CHARS_MESSAGE)r`   r-   r   s      r   FromNamezObjectReference.FromName   s_      DKK()1T1"4)DEEt|tt|"4)CDDvtr   c                 :    | j                  |j                  |      S )z>Create an object reference from a bucket reference and a name.)r   r-   )r`   r   r   s      r   FromBucketRefzObjectReference.FromBucketRef   s     <<
))400r   c                    t        j                  | j                  |t         j                        }|r0| j	                  |j                  d      |j                  d            S t        j                  | j                  |t         j                        }|r&|r | |j                  d      d      S t        dd      t        d      )z?Parse an object URL ('gs://' required) into an ObjectReference.r-   r7   rE   z Empty object name is not allowedz"Must be of form gs://bucket/object)	rematchGSUTIL_OBJECT_REGEXDOTALLr   groupGSUTIL_BUCKET_REGEXr6   
ValueError)r`   r"   allow_empty_objectr   s       r   rf   zObjectReference.FromUrl   s     HHS,,c299=E\\%++h/X1FGGHHS,,c299=E	5;;x("--$R)KLL
9
::r   c                     	 | j                  ||      S # t        t        f$ r-}t        j                  t        j                  |            d }~ww xY w)N)r   )rf   r6   r   rh   ri   rj   rk   )r`   r"   r   rn   s       r   ro   zObjectReference.FromArgument  sJ    ;[[1C[DD"J/ ;&&s}}S'9::;s    A(AAc                 F    	 | j                  |       y# t        $ r Y yw xY w)NFT)rf   r   )r`   paths     r   IsStorageUrlzObjectReference.IsStorageUrl  s,    	kk$   s    	  c                 N    dj                  | j                  | j                        S )Nz
gs://{}/{}r%   r-   r   rr   s    r   rs   zObjectReference.ToUrl  s    t{{DII66r   c                 N    dj                  | j                  | j                        S )Nz$https://storage.googleapis.com/{}/{}r   rr   s    r   ru   zObjectReference.GetPublicUrl  s    188diiPPr   c                 D    | j                         |j                         k(  S r/   )rs   rw   s     r   ry   zObjectReference.__eq__  s    ::<5;;=((r   c                 &    | j                  |       S r/   r{   rw   s     r   r|   zObjectReference.__ne__  r}   r   c                 4    t        | j                               S r/   )r   rs   rr   s    r   r   zObjectReference.__hash__  s    

r   N)F)r   r   r   r   r   r   r$   propertyr7   r   r   ra   r   r   rf   ro   r   rs   ru   ry   r|   r   r   r   r   r   r      s    OA4   ( ( % % 	 	 1 1 ; ; ; ;  7Q)"r   r   c                  .    t        j                  dd      S )z:Import and return the appropriate storage messages module.storagev1)	core_apisGetMessagesModuler   r   r   GetMessagesr          		$	$Y	55r   c                  .    t        j                  dd      S )z1Import and return the appropriate storage client.r   r   )r   GetClientInstancer   r   r   	GetClientr   %  r   r   c                     t        j                         j                  } | sIt        j                  d      }|r't        j                  dj                  |             |S t        d      t        j                  j                  | d      S )z)Determines the path to the gsutil binary.gsutilzUsing gsutil found at [{path}])r   z]A path to the storage client `gsutil` could not be found. Please check your SDK installation.)r   Pathssdk_bin_path
file_utilsFindExecutableOnPathr   debugr%   r   osr   rO   )r   gsutil_paths     r   _GetGsutilPathr   *  st    ,,,	11(;K	ii077[7IJ E F F	lH	--r   Fc                    t               }|rd| gn| g}|||z  }t        j                  j                         t        j                  j                  k(  rt        j                  |dz   g| }nt        j                  |g| }t        j                  dj                  dj                  |                   t        j                  |d||      S )ac  Runs the specified gsutil command and returns the command's exit code.

  WARNING: This is not compatible with python 3 and should no longer be used.

  Args:
    command_name: The gsutil command to run.
    command_args: List of arguments to pass to the command.
    run_concurrent: Whether concurrent uploads should be enabled while running
      the command.
    out_func: str->None, a function to call with the stdout of the gsutil
        command.
    err_func: str->None, a function to call with the stderr of the gsutil
        command.

  Returns:
    The exit code of the call to the gsutil command.
  z-mz.cmdzRunning command: [{args}]] )argsT)no_exitout_funcerr_func)r   r   OperatingSystemCurrentWINDOWSr
   ArgsForCMDToolArgsForExecutableToolr   r   r%   rO   Exec)command_namecommand_argsrun_concurrentr   r   command_pathr   gsutil_argss           r   RunGsutilCommandr   9  s    ,  !,!/$	l^$LD&&(I,E,E,M,MM!001FNNK!77LtLK))(//SXXk5J/KL			k4'/'/
1 1r   c                       e Zd ZdZd Zy)FileMetadataa  FileMetadata contains information about a file destined for GCP upload.

  Attributes:
      root: str, The root directory for considering file metadata.
      path: str, The path of this file, relative to the root.
      size: int, The size of this file, in bytes.
  c                     || _         || _        t        j                  j                  t        j                  j	                  ||            | _        y)zCollect file metadata.

    Args:
      root: str, The root directory for considering file metadata.
      path: str, The path of this file, relative to the root.
    N)rootr   r   getsizerO   size)r&   r   r   s      r   r$   zFileMetadata.__init__h  s5     DIDIT4 89DIr   Nr   r   r   r   r$   r   r   r   r   r   _  s    	:r   r   c                       e Zd ZdZddZy)Snapshota  Snapshot is a manifest of the source in a directory.

  Attributes:
    src_dir: str, The root of the snapshot source on the local disk.
    ignore_file: optional str, an override for .gcloudignore.
    include_gitignore: bool, whether the local .gitignore shouild be included in
      the ignored files.
    files: {str: FileMetadata}, A mapping from file path (relative to the
      snapshot root) to file metadata.
    dirs: [str], The list of dirs (possibly empty) in the snapshot.
    uncompressed_size: int, The number of bytes needed to store all of the files
      in this snapshot, uncompressed.
    any_files_ignored: bool, whether any files were ignored.
  Nc                 `   || _         i | _        g | _        d| _        t	        j
                  | j                   d||      }d| _        t        j                  t        j                  | j                               D ]  \  }}}t        j                  j                  || j                         }|D ]
  }	t        j                  j                  ||	      }
t        j                  j                  |
      rDt        j                  j                  |
      s%t!        j"                  dj%                  |
             |dk7  r t        j                  j                  ||	      n|	}|j'                  |      sd| _        t)        | j                   |      }|| j                  |<   | xj                  |j*                  z  c_         |d d  D ]i  }|dk7  r t        j                  j                  ||      n|}|j'                  |d      s|j-                  |       O| j                  j/                  |       k  y )Nr   F)write_on_diskignore_fileinclude_gitignorez5Ignoring [{}] which is a symlink to non-existent pathr:   T)is_dir)src_dirr   dirsuncompressed_sizer   GetFileChooserForDirany_files_ignoredr   walkrj   rk   r   relpathrO   islinkexistsr   infor%   
IsIncludedr   r   removeappend)r&   r   r   r   file_chooserdirpathdirnames	filenamesr   fnamer   fpathfmdnamedpaths                  r   r$   zSnapshot.__init__  s   DLDJDID44+	L #D +-''#--2M*N&(I6g%ww||GU+77>>$t(<
((ELL 073We,E&&u-#'$
 
$,,.

5"'') $ A;%073We,E&&uT&:
//%
 
		 ) +Or   )NTr   r   r   r   r   r   t  s    ' r   r   c                   P    e Zd ZdZdZdZdZdZdZdZ	eez  Z
e
ez  Zeez  Zdez  Zy)	ObjectLockRetentionDurationa  Specialized object lock duration class derived from iso_duration.Duration.

  Retention period for object lock feature follows non iso standard values
  for years and months. A year is considered to be 365.25 days
  and every month is expected to have 31 days.

  This class makes the required changes so that calculations are adjusted
  accordingly when parsing the duration string.
  g     v@i@B <            N)r   r   r   r   _DAYS_PER_YEAR_MICROSECONDS_PER_SECOND_SECONDS_PER_MINUTE_MINUTES_PER_HOUR_HOURS_PER_DAY_MONTHS_PER_YEAR_SECONDS_PER_HOUR_SECONDS_PER_DAY_SECONDS_PER_YEAR_SECONDS_PER_MONTHr   r   r   r   r     sY     .$.),==&7&7,,r   r   )6r   
__future__r   r   r   rh   r   r   rJ   googlecloudsdk.api_lib.utilr   r   googlecloudsdk.command_lib.utilr   googlecloudsdk.corer   r	   r
   r   r   googlecloudsdk.core.utilr   r   r   r   rj   rW   r   r   r   r   r,   r6   rM   rN   rH   rQ   r   r   rS   rY   r7   r[   r   r   r   r   file_only_loggerr   r   r   r   Durationr   r   r   r   <module>r	     sN    ; &  '  	 	  9 8 & * / # ) 8 1 . 
  2J 26% 6Dz D+- ++- +" "< @ '( #
. J LH(2f 2jTf Tn6
6
.  #'$)!2288!2288	#1L:6 :*7 v 7 t-,"7"7 -r   