Files
ServerSync/lib/pathspec/_backends/simple/gitignore.py
2026-03-31 00:43:39 +03:00

105 lines
2.8 KiB
Python

"""
This module provides the simple backend for :class:`~pathspec.gitignore.GitIgnoreSpec`.
WARNING: The *pathspec._backends.simple* package is not part of the public API.
Its contents and structure are likely to change.
"""
from collections.abc import (
Sequence)
from typing import (
Optional) # Replaced by `X | None` in 3.10.
from pathspec.pattern import (
RegexPattern)
from pathspec.patterns.gitignore.spec import (
_DIR_MARK)
from pathspec._typing import (
override) # Added in 3.12.
from .pathspec import (
SimplePsBackend)
class SimpleGiBackend(SimplePsBackend):
"""
The :class:`SimpleGiBackend` class is the default (or simple) implementation
used by :class:`~pathspec.gitignore.GitIgnoreSpec` for matching files.
"""
# Change type hint.
_patterns: list[tuple[int, RegexPattern]]
def __init__(
self,
patterns: Sequence[RegexPattern],
*,
no_filter: Optional[bool] = None,
no_reverse: Optional[bool] = None,
) -> None:
"""
Initialize the :class:`SimpleGiBackend` instance.
*patterns* (:class:`Sequence` of :class:`.RegexPattern`) contains the
compiled patterns.
*no_filter* (:class:`bool`) is whether to keep no-op patterns (:data:`True`),
or remove them (:data:`False`).
*no_reverse* (:class:`bool`) is whether to keep the pattern order
(:data:`True`), or reverse the order (:data:`True`).
"""
super().__init__(patterns, no_filter=no_filter, no_reverse=no_reverse)
@override
def match_file(self, file: str) -> tuple[Optional[bool], Optional[int]]:
"""
Check the file against the patterns.
*file* (:class:`str`) is the normalized file path to check.
Returns a :class:`tuple` containing whether to include *file* (:class:`bool`
or :data:`None`), and the index of the last matched pattern (:class:`int` or
:data:`None`).
"""
is_reversed = self._is_reversed
out_include: Optional[bool] = None
out_index: Optional[int] = None
out_priority = 0
for index, pattern in self._patterns:
if (
(include := pattern.include) is not None
and (match := pattern.match_file(file)) is not None
):
# Pattern matched.
# Check for directory marker.
dir_mark = match.match.groupdict().get(_DIR_MARK)
if dir_mark:
# Pattern matched by a directory pattern.
priority = 1
else:
# Pattern matched by a file pattern.
priority = 2
if is_reversed:
if priority > out_priority:
out_include = include
out_index = index
out_priority = priority
else:
# Forward.
if (include and dir_mark) or priority >= out_priority:
out_include = include
out_index = index
out_priority = priority
if is_reversed and priority == 2:
# Patterns are being checked in reverse order. The first pattern that
# matches with priority 2 takes precedence.
break
return (out_include, out_index)