
    A                     |    S r SSKrSSKrSSKrSrSr " S S\5      r " S S\5      rS	 r	S
 r
S r " S S\5      rg)a  Library for ignoring files for upload.

This library very closely mimics the semantics of Git's gitignore file:
https://git-scm.com/docs/gitignore

See `gcloud topic gcloudignore` for details.

A typical use would be:

  file_chooser = gcloudignore.GetFileChooserForDir(upload_directory)
  for f in file_chooser.GetIncludedFiles('some/path'):
    print 'uploading {}'.format(f)
    # actually do the upload, too
    N/z(?<!\\)\\(\\\\)*$c                       \ rS rSrSrSrg)InternalParserError'   z*An internal error in gcloudignore parsing. N__name__
__module____qualname____firstlineno____doc____static_attributes__r       +lib/googlecloudsdk/command_lib/util/glob.pyr   r   '   s    2r   r   c                       \ rS rSrSrSrg)InvalidLineError+   z<Error indicating that a line of the ignore file was invalid.r   Nr   r   r   r   r   r   +   s    Dr   r   c                 *    S nS nU" U" U 5      5      $ )zHandles spaces in a line.

In particular, deals with trailing spaces (which are stripped unless
escaped) and escaped spaces throughout the line (which are unescaped).

Args:
  line: str, the line

Returns:
  str, the line with spaces handled
c                    / nSnU[        U 5      :  at  X   nUS:X  aC  US-   [        U 5      :  a  UR                  U5        OFUR                  X0US-      -   5        US-  nOUR                  U5        US-  nU[        U 5      :  a  Mt  / nSn[        U5       H%  nU(       a  US:X  a  M  SnUR                  U5        M'     SR                  [        U5      5      $ )	z!Strips unescaped trailing spaces.r   \      T F )lenappendreversedjoin)linetokensicurrresonly_seen_spacess         r   _Rstrip_HandleSpaces.<locals>._Rstrip;   s     F	A
c$i-Wd	q5CI
--

d!A#Y&'	Qd	Q c$i- C 	dck	jj	 ! 778C=!!r   c                 &    U R                  SS5      $ )zUnescapes all spaces in a line.z\ r   )replacer   s    r   _UnescapeSpaces&_HandleSpaces.<locals>._UnescapeSpacesX   s    <<s##r   r   )r   r%   r*   s      r   _HandleSpacesr,   /   s    ":$ 
	''r   c                 R    [         R                  " SSU 5      R                  SS5      $ )zUnescapes a line.

The escape character is '\'. An escaped backslash turns into one backslash;
any other escaped character is ignored.

Args:
  line: str, the line to unescape

Returns:
  str, the unescaped line

z	\\([^\\])z\1z\\r   )resubr(   r)   s    r   	_Unescaper0   _   s$     
eT	*	2	264	@@r   c                     U /nSnU (       aJ  U(       aC  [         R                  R                  U 5      u  pUR                  SU 5        U (       a	  U(       a  MC  U$ )zReturns all prefixes for the given path, inclusive.

That is, for 'foo/bar/baz', returns ['', 'foo', 'foo/bar', 'foo/bar/baz'].

Args:
  path: str, the path for which to get prefixes.

Returns:
  list of str, the prefixes.
Tr   )ospathsplitinsert)r3   path_prefixespath_reminders      r   GetPathPrefixesr8   o   sM     &-- 	''---DD! 	 
r   c                   B    \ rS rSrSrS	S jrS rS	S jr\S 5       r	Sr
g)
Glob   zA file-matching glob pattern.

See https://git-scm.com/docs/gitignore for full syntax specification.

Attributes:
  pattern: str, a globbing pattern.
  must_be_dir: bool, true if only dirs match.
c                     Xl         X l        g N)patternmust_be_dir)selfr>   r?   s      r   __init__Glob.__init__   s    L"r   c                   ^ ^ U(       d  gUc  gUS   nUSS mU(       a  [         R                  R                  U5      n[         R                  R                  U5      u  pEU(       d  SnUS:X  aC  [	        U5      nT(       a	  TS   S:X  d  TR                  SS5        [        UU 4S jU 5       5      $ US	:X  a  T(       d  U(       a  [        U5      S
:  a  g[        R                  " XS5      (       d  gT R                  TU5      $ )a2  Determines whether the given pattern matches the given path.

Args:
  pattern_parts: list of str, the list of pattern parts that must all match
    the path.
  path: str, the path to match.

Returns:
  bool, whether the patch matches the pattern_parts (Matches() will convert
    this into a Match value).
TNFz**r   r   c              3   H   >#    U  H  nTR                  TU5      v   M     g 7fr=   )_MatchesHelper).0prefixremaining_patternr@   s     r   	<genexpr>&Glob._MatchesHelper.<locals>.<genexpr>   s+      #! EK$$%6??!s   "*r   )
r2   r3   normpathr4   r8   r5   anyr   fnmatchrF   )r@   pattern_partsr3   pattern_partremaining_path	path_partr6   rI   s   `      @r   rF   Glob._MatchesHelper   s     |  $L%cr*WWd#d "d 3Nnt &d+m  $5a$8B$>  B' #!# # # s#4
 
C/!3??933 0.AAr   c                     U R                   (       a  U(       d  gU R                  U R                  R                  S5      U5      (       a  gg)z4Returns a Match for this pattern and the given path.Fr   T)r?   rF   r>   r4   )r@   r3   is_dirs      r   MatchesGlob.Matches   s8    4<<--c2D99r   c                 0   UR                  S5      (       a  USS nSnOSn[        U5      n[        R                  " [        U5      (       a  [        SR                  U5      5      e[        U5      nU(       d  [        SR                  U5      5      eU " XS9$ )	a  Creates a pattern for an individual line of an ignore file.

Windows-style newlines must be removed.

Args:
  line: str, The line to parse.

Returns:
  Pattern.

Raises:
  InvalidLineError: if the line was invalid (comment, blank, contains
    invalid consecutive stars).
r   NrD   TFz(Line [{}] ends in an odd number of [\]s.zLine [{}] is blank.)r?   )endswithr,   r.   search_ENDS_IN_ODD_NUMBER_SLASHES_REr   formatr0   )clsr   r?   s      r   
FromStringGlob.FromString   s      }}S#2YdkkD	yy/66
5
<
<T
BD DT?D299$?@@t--r   )r?   r>   N)F)r	   r
   r   r   r   rA   rF   rW   classmethodr_   r   r   r   r   r:   r:      s-    #ABF . .r   r:   )r   rO   r2   r.   _GCLOUDIGNORE_PATH_SEPr\   	Exceptionr   r   r,   r0   r8   objectr:   r   r   r   <module>re      s[      	 	 !5 3) 3E* E-(`A *v.6 v.r   