
    -              	          d Z ddlZddlZddlmZmZmZmZm	Z	m
Z
mZ e	rddlmZ ddlmZmZ dedefdZd	edefd
Zdedee   fdZddedededefdZ G d de      Z G d de      Z G d de      ZdedefdZ G d de      Zy)zhParsing of gitignore files.

For details for the matching rules, see https://git-scm.com/docs/gitignore
    N)BinaryIOIterableListOptionalTYPE_CHECKINGDictUnion)Repo)get_xdg_config_home_pathConfigsegmentreturnc                 ,   | dk(  ryd}dt        |       }}||k  r| ||dz    }|dz   }|dk(  r|dz  }n|dk(  r|dz  }n|d	k(  r|}||k  r| ||dz    d
k(  r|dz   }||k  r| ||dz    dk(  r|dz   }||k  r!| ||dz    dk7  r|dz   }||k  r| ||dz    dk7  r||k\  r|dz  }nn| || j                  dd      }|dz   }|j                  d
      r	d|dd  z   }n|j                  d      rd|z   }|d	|z   dz   z  }n|t        j                  |      z  }||k  r|S )N   *s   [^/]+    r      s   [^/]*   ?s   [^/]   [   !   ]s   \[   \s   \\   ^)lenreplace
startswithreescape)r   resincjstuffs          !lib/third_party/dulwich/ignore.py_translate_segmentr%   +   s   $
Cc'lqA
a%AAE98OC$Y7NC$YA1uQU+t3E1uQU+t3Ea%GAA.$6E a%GAA.$6Avv!,,UG<E##D) 59,E%%d+!EMEte|d**299Q<C5 a%6 Jr   patc                 f   d}d| dd vr|dz  }| j                  d      r
| dd } |dz  }| j                  d      r| dd } t        | j                  d            D ];  \  }}|d	k(  r|d
z  }||dkD  rt        j                  d      ndt        |      z   z  }= | j                  d      s|dz  }|dz   S )zTranslate a shell PATTERN to a regular expression.

    There is no way to quote meta-characters.

    Originally copied from fnmatch in Python 2.7, but modified for Dulwich
    to cope with features in Git ignore patterns.
    s   (?ms)   /Ns   (.*/)?s   **/   r   s   **s   (/.*)?r   r   s   /?s   \Z)r   	enumeratesplitr   r   r%   endswith)r&   r   r   r   s       r$   	translater.   N   s     C3s8y
~~f!"gy
~~d!"g		$0
7e9Cq1uBIIdO#9KG9TTTC 1 <<u<r   fc              #   &  K   | D ]  }|j                  d      }|s|j                  d      r)|j                  d      r9|j                  d      s(|dd }|j                  d      r|j                  d      s(|j                  dd      }|  yw)zlRead a git ignore file.

    Args:
      f: File-like object to read from
    Returns: List of patterns
    s   
   #    s   \ Nr)   )rstripr   r-   r   )r/   lines     r$   read_ignore_patternsr5   r   s      {{7# ??4  mmD!$--*?9D mmD!$--*?||FD)
! s   A5B8Bpathpattern
ignorecasec                 8    t        ||      j                  |       S )zMatch a gitignore-style pattern against a path.

    Args:
      path: Path to match
      pattern: Pattern to match
      ignorecase: Whether to do case-sensitive matching
    Returns:
      bool indicating whether the pattern matched
    )Patternmatch)r6   r7   r8   s      r$   match_patternr<      s     7J'--d33r   c                   f    e Zd ZdZddedefdZdefdZdefdZ	de
defd	Zdefd
ZdedefdZy)r:   zA single ignore pattern.r7   r8   c                     || _         || _        |dd dk(  rd| _        |dd  }n|dd dk(  r|dd  }d| _        d}| j                  rt        j                  }t        j
                  t        |      |      | _        y )Nr   r   r   Fr   T)r7   r8   
is_excluder   
IGNORECASEcompiler.   _re)selfr7   r8   flagss       r$   __init__zPattern.__init__   s|    $1Q<4#DOabkGq|u$!!"+"DO??MME::i0%8r   r   c                     | j                   S N)r7   rC   s    r$   	__bytes__zPattern.__bytes__   s    ||r   c                 @    t        j                  | j                        S rG   )osfsdecoder7   rH   s    r$   __str__zPattern.__str__   s    {{4<<((r   otherc                     t        |t        |             xr4 | j                  |j                  k(  xr | j                  |j                  k(  S rG   )
isinstancetyper7   r8   )rC   rN   s     r$   __eq__zPattern.__eq__   sA    ud4j) 4-45#3#33	
r   c                 f    t        |       j                  d| j                  d| j                  dS N(z, ))rQ   __name__r7   r8   rH   s    r$   __repr__zPattern.__repr__   s'    JLLOO
 	
r   r6   c                 J    t        | j                  j                  |            S )zTry to match a path against this ignore pattern.

        Args:
          path: Path to match (relative to ignore location)
        Returns: boolean
        )boolrB   r;   rC   r6   s     r$   r;   zPattern.match   s     DHHNN4())r   NF)rW   
__module____qualname____doc__bytesrZ   rE   rI   strrM   objectrR   rX   r;    r   r$   r:   r:      sb    "9 94 95 ) )
F 
t 

# 
*% *D *r   r:   c                       e Zd Zddee   defdZdeddfdZdeee	f   dee
   fd	Zdedee   fd
Zeddedd fd       Zde	fdZy)IgnoreFilterNpatternsr8   c                 ^    g | _         || _        || _        |D ]  }| j                  |        y rG   )	_patterns_ignorecase_pathappend_pattern)rC   rf   r8   r6   r7   s        r$   rE   zIgnoreFilter.__init__   s0    %
G(  r   r7   r   c                 b    | j                   j                  t        || j                               y)zAdd a pattern to the set.N)rh   appendr:   ri   )rC   r7   s     r$   rk   zIgnoreFilter.append_pattern   s!    ggt/?/?@Ar   r6   c              #      K   t        |t              st        j                  |      }| j                  D ]  }|j                  |      s|  yw)zYield all matching patterns for path.

        Args:
          path: Path to match
        Returns:
          Iterator over iterators
        N)rP   r`   rK   fsencoderh   r;   )rC   r6   r7   s      r$   find_matchingzIgnoreFilter.find_matching   s?      $&;;t$D~~G}}T" &s   AA	Ac                 N    d}| j                  |      D ]  }|j                  } |S )zCheck whether a path is ignored.

        For directories, include a trailing slash.

        Returns: status is None if file is not mentioned, True if it is
            included, False if it is explicitly excluded.
        N)rp   r?   )rC   r6   statusr7   s       r$   
is_ignoredzIgnoreFilter.is_ignored   s.     ))$/G''F 0r   c                 n    t        |d      5 } | t        |      ||      cd d d        S # 1 sw Y   y xY w)Nrb)r6   )openr5   )clsr6   r8   r/   s       r$   	from_pathzIgnoreFilter.from_path   s,    $+A.
F s   +4c                     t        | dd       }|t        |       j                  d|dS dt        |       j                  z  S )Nrj   z.from_path(rV   z<%s>)getattrrQ   rW   r[   s     r$   rX   zIgnoreFilter.__repr__   s@    tWd+)-d)<)<dCCT$Z0011r   )FNr\   )rW   r]   r^   r   r`   rZ   rE   rk   r	   ra   r:   rp   r   rs   classmethodrx   rX   rc   r   r$   re   re      s    )% )d )Be B B%s
"3 8I u $  G G. G G2# 2r   re   c                   ,    e Zd ZdZd Zdedee   fdZy)IgnoreFilterStackz,Check for ignore status in multiple filters.c                     || _         y rG   )_filters)rC   filterss     r$   rE   zIgnoreFilterStack.__init__  s	    r   r6   r   c                 Z    d}| j                   D ]  }|j                  |      }||c S  |S )Check whether a path is explicitly included or excluded in ignores.

        Args:
          path: Path to check
        Returns:
          None if the file is not mentioned, True if it is included,
          False if it is explicitly excluded.
        N)r   rs   )rC   r6   rr   filters       r$   rs   zIgnoreFilterStack.is_ignored  s9     mmF&&t,F! $ r   N)	rW   r]   r^   r_   rE   ra   r   rZ   rs   rc   r   r$   r}   r}      s!    6 s x~ r   r}   configc                 ^    	 | j                  dd      S # t        $ r Y nw xY wt        dd      S )zReturn default user ignore filter path.

    Args:
      config: A Config object
    Returns:
      Path to a global ignore file
    )   cores   excludesFilegitignore)getKeyErrorr   )r   s    r$   default_user_ignore_filter_pathr     s9    zz*o66  $E844s    	  c                       e Zd ZdZdedee   defdZdefdZ	dede
e   fd	Zdedee   fd
Zdede
e   fdZedd       Zy)IgnoreFilterManagerzIgnore file manager.top_pathglobal_filtersr8   c                 <    i | _         || _        || _        || _        y rG   )_path_filters	_top_path_global_filtersri   )rC   r   r   r8   s       r$   rE   zIgnoreFilterManager.__init__(  s#      !-%r   r   c                     t        |       j                  d| j                  d| j                  d| j                  dS rT   )rQ   rW   r   r   ri   rH   s    r$   rX   zIgnoreFilterManager.__repr__3  s2    JNN  	
 	
r   r6   c                 N   	 | j                   |   S # t        $ r Y nw xY wt        j                  j	                  | j
                  |d      }	 t        j                  || j                        | j                   |<   n# t        $ r d | j                   |<   Y nw xY w| j                   |   S )Nz
.gitignore)
r   r   rK   r6   joinr   re   rx   ri   IOError)rC   r6   ps      r$   
_load_pathzIgnoreFilterManager._load_path;  s    	%%d++ 		 GGLL|<	,'3'='=aAQAQ'RDt$ 	,'+Dt$	,!!$''s    	-A: :BBc                    t         j                  j                  |      rt        d|z        | j                  D cg c]  }d|f }}t         j                  j
                  dk7  r*|j                  t         j                  j
                  d      }|j                  d      }g }t        t        |      dz         D ]  }dj                  |d|       }|D ]I  \  }}dj                  |||       }	|t        |      k  r|	dz  }	|t        |j                  |	            z  }K | j                  |      }
|
y|j                  d||
f        t        |      S c c}w )zFind matching patterns for path.

        Args:
          path: Path to check
        Returns:
          Iterator over Pattern instances
        z%s is an absolute pathr   /r   N)rK   r6   isabs
ValueErrorr   sepr   r,   ranger   r   listrp   r   insertiter)rC   r6   r/   r   partsmatchesr   dirnamesrelpathignore_filters              r$   rp   z!IgnoreFilterManager.find_matchingH  s4    77==5<==#'#7#78#7aAq6#7877;;#<<S1D

3s5zA~&AhhuRay)G1((51:.s5z> sNG4 899   !OOG4M(q1m"45 ' G}# 9s   Ec                 Z    t        | j                  |            }|r|d   j                  S y)r   r)   N)r   rp   r?   )rC   r6   r   s      r$   rs   zIgnoreFilterManager.is_ignorede  s/     t))$/02;)))r   c                    g }t         j                  j                  |j                         dd      t	        |j                               fD ]D  }	 |j                  t        j                  t         j                  j                  |                   F |j                         }|j                  ddd      } | |j                  ||      S # t        $ r Y w xY w)zCreate a IgnoreFilterManager from a repository.

        Args:
          repo: Repository object
        Returns:
          A `IgnoreFilterManager` object
        infoexcluder   s
   ignorecaseF)rK   r6   r   
controldirr   get_config_stackrm   re   rx   
expanduserr   get_boolean)rw   repor   r   r   r8   s         r$   	from_repozIgnoreFilterManager.from_repos  s     GGLL*FI>+D,A,A,CD
A%%l&<&<RWW=O=OPQ=R&ST
 &&(''MEJ
499nj99	  s   AC			CCN)r   r
   r   r   )rW   r]   r^   r_   ra   r   re   rZ   rE   rX   r   r   r   r:   rp   rs   r{   r   rc   r   r$   r   r   %  s    	&	& \*	& 		&
# 
(s (x'= (# (7*; :s x~  : :r   r   r\   )r_   os.pathrK   r   typingr   r   r   r   r   r   r	   dulwich.repor
   dulwich.configr   r   r`   r%   r.   r5   rZ   r<   rb   r:   re   r}   ra   r   r   rc   r   r$   <module>r      s   (
  	   ! ;   %  F!5 !U !HH % 6
4 
4 
44 
4D 
4-*f -*`126 12h .5F 5s 5 b:& b:r   