o
    Uh3                     @   s|   d Z ddlZddlmZ ddlmZ G dd deZG dd	 d	eZd
d Zdd Z	dd Z
dddZdd ZdddZdS )z!Sparse checkout pattern handling.    N)fnmatch   )ensure_dir_existsc                   @      e Zd ZdZdS )SparseCheckoutConflictErrorzTRaised when local modifications would be overwritten by a sparse checkout operation.N__name__
__module____qualname____doc__ r   r   k/var/www/html/construction_image-detection-poc/venv/lib/python3.10/site-packages/dulwich/sparse_patterns.pyr          r   c                   @   r   )BlobNotFoundErrorzKRaised when a requested blob is not found in the repository's object store.Nr   r   r   r   r   r   "   r   r   c                 C   s   |rt | |S t| |S )ag  Determine which paths in the index should be included based on either
    a full-pattern match or a cone-mode approach.

    Args:
      repo: A path to the repository or a Repo object.
      lines: A list of pattern lines (strings) from sparse-checkout config.
      cone: A bool indicating cone mode.

    Returns:
      A set of included path strings.
    )compute_included_paths_conecompute_included_paths_full)repolinesconer   r   r   determine_included_paths&   s   

r   c                 C   sN   t |}|  }t }| D ]\}}|d}t||ddr$|| q|S )a  Use .gitignore-style parsing and matching to determine included paths.

    Each file path in the index is tested against the parsed sparse patterns.
    If it matches the final (most recently applied) positive pattern, it is included.

    Args:
      repo: A path to the repository or a Repo object.
      lines: A list of pattern lines (strings) from sparse-checkout config.

    Returns:
      A set of included path strings.
    utf-8F)path_is_dir)parse_sparse_patterns
open_indexsetitemsdecodematch_gitignore_patternsadd)r   r   parsedindexincluded
path_bytesentrypath_strr   r   r   r   8   s   

r   c                 C   s   d}d}t  }|D ]!}|dkrd}q	|dkrd}q	|dr*|d}|r*|| q	|  }t  }| D ].\}	}
|	d}d|vrK|rJ|| q6|ddd }|r_||v r^|| q6|| q6|S )	aA  Implement a simplified 'cone' approach for sparse-checkout.

    By default, this can include top-level files, exclude all subdirectories,
    and re-include specified directories. The logic is less comprehensive than
    Git's built-in cone mode (recursive vs parent) and is essentially an implementation
    of the recursive cone mode.

    Args:
      repo: A path to the repository or a Repo object.
      lines: A list of pattern lines (strings), typically including entries like
        "/*", "!/*/", or "/mydir/".

    Returns:
      A set of included path strings.
    F/*Tz!/*//r   r   r   )r   
startswithstripr   r   r   r   split)r   r   include_top_levelexclude_subdirsreinclude_dirspatdr    r!   r"   r#   r$   top_dirr   r   r   r   P   s8   





r   Fc              
      s    }   fdd}t| D ]\}}|d}||v r(|d n|d |||< q|  t| D ]\}}tj	j|d}|j
r}tj|r||sc|||rctd| dzt| W q< tys   Y q< ty{   Y q<w q<tj|szj|j }	W n ty   td|j d	| d
w ttj| t|d}
|
|	j W d   n1 sw   Y  q<dS )a]  Apply the sparse-checkout inclusion set to the index and working tree.

    This function updates skip-worktree bits in the index based on whether each
    path is included or not. It then adds or removes files in the working tree
    accordingly. If ``force=False``, files that have local modifications
    will cause an error instead of being removed.

    Args:
      repo: A path to the repository or a Repo object.
      included_paths: A set of paths (strings) that should remain included.
      force: Whether to forcibly remove locally modified files (default False).

    Returns:
      None
    c                    s   t j| sdS zt| d}| }W d    n1 sw   Y  W n
 ty-   Y dS w zj|j }W n
 ty@   Y dS w  	|| }||j
kS )NFrbT)ospathexistsopenreadOSErrorobject_storeshaKeyErrorcheckin_normalizedata)	full_pathindex_entryf	disk_datablob	norm_data
normalizerr   r   r   local_modifications_exist   s"   

z7apply_included_paths.<locals>.local_modifications_existr   FTzLocal modifications in zE would be overwritten by sparse checkout. Use force=True to override.zBlob z not found for .wbN)r   get_blob_normalizerlistr   r   set_skip_worktreewriter1   r2   joinskip_worktreer3   r   removeIsADirectoryErrorFileNotFoundErrorr7   r8   r9   r   r   dirnamer4   r;   )r   included_pathsforcer    rD   r"   r#   r$   r<   r@   r>   r   rB   r   apply_included_paths   sP   



rS   c                 C   s   g }| D ]@}|  }|r|drq|d}|r|dd }|d}|r,|dd }d}|dr;d}|dd }|||||f q|S )	a  Parse pattern lines from a sparse-checkout file (.git/info/sparse-checkout).

    This simplified parser:
      1. Strips comments (#...) and empty lines.
      2. Returns a list of (pattern, is_negation, is_dir_only, anchored) tuples.

    These lines are similar to .gitignore patterns but are used for sparse-checkout
    logic. This function strips comments and blank lines, identifies negation,
    anchoring, and directory-only markers, and returns data suitable for matching.

    Example:
      ``line = "/*.txt" -> ("/.txt", False, False, True)``
      ``line = "!/docs/" -> ("/docs/", True, True, True)``
      ``line = "mydir/" -> ("mydir/", False, True, False)`` not anchored, no leading "/"

    Args:
      lines: A list of raw lines (strings) from the sparse-checkout file.

    Returns:
      A list of tuples (pattern, negation, dir_only, anchored), representing
      the essential details needed to perform matching.
    #!r   Nr&   FT)r(   r'   endswithappend)r   resultsraw_linelinenegationanchoreddir_onlyr   r   r   r      s"   


r   c           
      C   s   d}|D ]l\}}}}|o| }| |kr|rqd}	nd}	|r?|	s?| |d kr)| }	nt | | dr4d}	n|s?t | d| d}	|r\|	s\|dkrHq| |krOd}	n| |d rYd}	nd}	n|	skt | |pjt | d| }	|	rp| }q|S )a  Check whether a path is included based on .gitignore-style patterns.

    This is a simplified approach that:
      1. Iterates over patterns in order.
      2. If a pattern matches, we set the "include" state depending on negation.
      3. Later matches override earlier ones.

    In a .gitignore sense, lines that do not start with '!' are "ignore" patterns,
    lines that start with '!' are "unignore" (re-include). But in sparse checkout,
    it's effectively reversed: a non-negation line is "include," negation is "exclude."
    However, many flows still rely on the same final logic: the last matching pattern
    decides "excluded" vs. "included."

    We'll interpret "include" as returning True, "exclude" as returning False.

    Each pattern can include negation (!), directory-only markers, or be anchored
    to the start of the path. The last matching pattern determines whether the
    path is ultimately included or excluded.

    Args:
      path_str: The path (string) to test.
      parsed_patterns: A list of (pattern, negation, dir_only, anchored) tuples
        as returned by parse_sparse_patterns.
      path_is_dir: Whether to treat the path as a directory (default False).

    Returns:
      True if the path is included by the last matching pattern, False otherwise.
    FTr&   r%   z*/ )r   r'   )
r$   parsed_patternsr   is_includedpatternr\   r^   r]   forbidden_pathmatchedr   r   r   r     s:    
r   )F)r   r1   r   filer   	Exceptionr   r   r   r   r   rS   r   r   r   r   r   r   <module>   s   
9L1