From da88a6da599c8bc598abfc00c6802d08be67be39 Mon Sep 17 00:00:00 2001 From: Austin Scola Date: Tue, 21 Jun 2022 08:40:09 -0400 Subject: [PATCH 1/9] Fix blob filter types Fix the types and type annotations of some of the blob filter code. --- git/index/typ.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/git/index/typ.py b/git/index/typ.py index 6371953bb..d9040e10f 100644 --- a/git/index/typ.py +++ b/git/index/typ.py @@ -4,6 +4,7 @@ from .util import pack, unpack from git.objects import Blob +from git.index.base import StageType # typing ---------------------------------------------------------------------- @@ -48,10 +49,10 @@ def __init__(self, paths: Sequence[PathLike]) -> None: """ self.paths = paths - def __call__(self, stage_blob: Blob) -> bool: - path = stage_blob[1].path + def __call__(self, stage_blob: Tuple[StageType, Blob]) -> bool: + path: str = str(stage_blob[1].path) for p in self.paths: - if path.startswith(p): + if path.startswith(str(p)): return True # END for each path in filter paths return False From a6ce118d6e4ade2bc01182b743f87c43a7ee8fa7 Mon Sep 17 00:00:00 2001 From: Austin Scola Date: Tue, 21 Jun 2022 08:46:54 -0400 Subject: [PATCH 2/9] Add stage type to all --- git/index/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git/index/base.py b/git/index/base.py index 1c56a219b..fb2088a70 100644 --- a/git/index/base.py +++ b/git/index/base.py @@ -89,7 +89,7 @@ # ------------------------------------------------------------------------------------ -__all__ = ("IndexFile", "CheckoutError") +__all__ = ("IndexFile", "CheckoutError", "StageType") class IndexFile(LazyMixin, git_diff.Diffable, Serializable): From d17136574ef23050fe3271e51a8b811f96544b17 Mon Sep 17 00:00:00 2001 From: Austin Scola Date: Tue, 21 Jun 2022 09:19:54 -0400 Subject: [PATCH 3/9] Move stage type def --- git/index/base.py | 2 +- git/index/typ.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/git/index/base.py b/git/index/base.py index fb2088a70..10f8b8b25 100644 --- a/git/index/base.py +++ b/git/index/base.py @@ -52,6 +52,7 @@ from .typ import ( BaseIndexEntry, IndexEntry, + StageType, ) from .util import TemporaryFileSwap, post_clear_cache, default_index, git_working_dir @@ -83,7 +84,6 @@ from git.util import Actor -StageType = int Treeish = Union[Tree, Commit, str, bytes] # ------------------------------------------------------------------------------------ diff --git a/git/index/typ.py b/git/index/typ.py index d9040e10f..5264f370f 100644 --- a/git/index/typ.py +++ b/git/index/typ.py @@ -4,7 +4,6 @@ from .util import pack, unpack from git.objects import Blob -from git.index.base import StageType # typing ---------------------------------------------------------------------- @@ -16,9 +15,11 @@ if TYPE_CHECKING: from git.repo import Repo +StageType = int + # --------------------------------------------------------------------------------- -__all__ = ("BlobFilter", "BaseIndexEntry", "IndexEntry") +__all__ = ("BlobFilter", "BaseIndexEntry", "IndexEntry", "StageType") # { Invariants CE_NAMEMASK = 0x0FFF From 1314d6356d598d53175b62351d732f5e1fbf8665 Mon Sep 17 00:00:00 2001 From: Austin Scola Date: Sun, 26 Jun 2022 16:45:22 -0400 Subject: [PATCH 4/9] Change to not stringify paths --- git/index/typ.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/git/index/typ.py b/git/index/typ.py index 5264f370f..ad1a69738 100644 --- a/git/index/typ.py +++ b/git/index/typ.py @@ -1,6 +1,7 @@ """Module with additional types used by the index""" from binascii import b2a_hex +from pathlib import Path from .util import pack, unpack from git.objects import Blob @@ -51,11 +52,12 @@ def __init__(self, paths: Sequence[PathLike]) -> None: self.paths = paths def __call__(self, stage_blob: Tuple[StageType, Blob]) -> bool: - path: str = str(stage_blob[1].path) - for p in self.paths: - if path.startswith(str(p)): + blob_pathlike: Pathlike = stage_blob[1].path + blob_path: Path = blob_pathlike if isinstance(blob_pathlike, Path) else Path(blob_pathlike) + for pathlike in self.paths: + path: Path = pathlike if isinstance(pathlike, Path) else Path(pathlike) + if path.is_relative_to(blob_path): return True - # END for each path in filter paths return False From c6a018bdf802326f89e8c93ccac79fae78d94974 Mon Sep 17 00:00:00 2001 From: Austin Scola Date: Sun, 26 Jun 2022 16:47:41 -0400 Subject: [PATCH 5/9] Fix pathlike type annotation typo --- git/index/typ.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git/index/typ.py b/git/index/typ.py index ad1a69738..7f5dcc102 100644 --- a/git/index/typ.py +++ b/git/index/typ.py @@ -52,7 +52,7 @@ def __init__(self, paths: Sequence[PathLike]) -> None: self.paths = paths def __call__(self, stage_blob: Tuple[StageType, Blob]) -> bool: - blob_pathlike: Pathlike = stage_blob[1].path + blob_pathlike: PathLike = stage_blob[1].path blob_path: Path = blob_pathlike if isinstance(blob_pathlike, Path) else Path(blob_pathlike) for pathlike in self.paths: path: Path = pathlike if isinstance(pathlike, Path) else Path(pathlike) From cc80e6bbb0b98d71f44846d66a8e9439b60efa42 Mon Sep 17 00:00:00 2001 From: Austin Scola Date: Sun, 26 Jun 2022 17:01:32 -0400 Subject: [PATCH 6/9] Remove usage of `PosixPath.is_relative_to` Remove usage of `PosixPath.is_relative_to` because it was added in Python 3.9 and earlier versions of Python are supported by `GitPython`. --- git/index/typ.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/git/index/typ.py b/git/index/typ.py index 7f5dcc102..11077454c 100644 --- a/git/index/typ.py +++ b/git/index/typ.py @@ -56,7 +56,8 @@ def __call__(self, stage_blob: Tuple[StageType, Blob]) -> bool: blob_path: Path = blob_pathlike if isinstance(blob_pathlike, Path) else Path(blob_pathlike) for pathlike in self.paths: path: Path = pathlike if isinstance(pathlike, Path) else Path(pathlike) - if path.is_relative_to(blob_path): + # TODO: Change to use `PosixPath.is_relative_to` once Python 3.8 is no longer supported. + if all(map(lambda t: t[0] == t[1], zip(path.parts, blob_path.parts))): return True return False From 420d2afa0ebfa976a07dc0ff902c75547ab228c6 Mon Sep 17 00:00:00 2001 From: Austin Scola Date: Sun, 26 Jun 2022 17:04:34 -0400 Subject: [PATCH 7/9] Use generator instead of map --- git/index/typ.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git/index/typ.py b/git/index/typ.py index 11077454c..ec7699e2b 100644 --- a/git/index/typ.py +++ b/git/index/typ.py @@ -57,7 +57,7 @@ def __call__(self, stage_blob: Tuple[StageType, Blob]) -> bool: for pathlike in self.paths: path: Path = pathlike if isinstance(pathlike, Path) else Path(pathlike) # TODO: Change to use `PosixPath.is_relative_to` once Python 3.8 is no longer supported. - if all(map(lambda t: t[0] == t[1], zip(path.parts, blob_path.parts))): + if all(i == j for i, j in zip(path.parts, blob_path.parts)): return True return False From ed45d5b3c3d4e2d4520221037b40288dc85e428c Mon Sep 17 00:00:00 2001 From: Austin Scola Date: Tue, 28 Jun 2022 08:59:26 -0400 Subject: [PATCH 8/9] Fix blob filter path shorter than filter path --- git/index/typ.py | 8 ++++++-- test/test_blob_filter.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 test/test_blob_filter.py diff --git a/git/index/typ.py b/git/index/typ.py index ec7699e2b..b2c6c371b 100644 --- a/git/index/typ.py +++ b/git/index/typ.py @@ -9,7 +9,7 @@ # typing ---------------------------------------------------------------------- -from typing import NamedTuple, Sequence, TYPE_CHECKING, Tuple, Union, cast +from typing import NamedTuple, Sequence, TYPE_CHECKING, Tuple, Union, cast, List from git.types import PathLike @@ -57,7 +57,11 @@ def __call__(self, stage_blob: Tuple[StageType, Blob]) -> bool: for pathlike in self.paths: path: Path = pathlike if isinstance(pathlike, Path) else Path(pathlike) # TODO: Change to use `PosixPath.is_relative_to` once Python 3.8 is no longer supported. - if all(i == j for i, j in zip(path.parts, blob_path.parts)): + filter_parts: List[str] = path.parts + blob_parts: List[str] = blob_path.parts + if len(filter_parts) > len(blob_parts): + continue + if all(i == j for i, j in zip(filter_parts, blob_parts)): return True return False diff --git a/test/test_blob_filter.py b/test/test_blob_filter.py new file mode 100644 index 000000000..a8cd0c9c1 --- /dev/null +++ b/test/test_blob_filter.py @@ -0,0 +1,31 @@ +"""Test the blob filter.""" +from pathlib import Path +from typing import Sequence, Tuple +from unittest.mock import MagicMock + +import pytest + +from git.index.typ import BlobFilter, StageType +from git.objects import Blob +from git.types import PathLike + + +# fmt: off +@pytest.mark.parametrize('paths, stage_type, path, expected_result', [ + ((Path("foo"),), 0, Path("foo"), True), + ((Path("foo"),), 0, Path("foo/bar"), True), + ((Path("foo/bar"),), 0, Path("foo"), False), + ((Path("foo"), Path("bar")), 0, Path("foo"), True), +]) +# fmt: on +def test_blob_filter(paths: Sequence[PathLike], stage_type: StageType, path: PathLike, expected_result: bool) -> None: + """Test the blob filter.""" + blob_filter = BlobFilter(paths) + + binsha = MagicMock(__len__=lambda self: 20) + blob: Blob = Blob(repo=MagicMock(), binsha=binsha, path=path) + stage_blob: Tuple[StageType, Blob] = (stage_type, blob) + + result = blob_filter(stage_blob) + + assert result == expected_result From da59d7481668a7133eebcd12b4d5ecfb655296a6 Mon Sep 17 00:00:00 2001 From: Austin Scola Date: Fri, 1 Jul 2022 08:19:07 -0400 Subject: [PATCH 9/9] Remove stage type as parameter from blob filter test --- test/test_blob_filter.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/test/test_blob_filter.py b/test/test_blob_filter.py index a8cd0c9c1..cbaa30b8b 100644 --- a/test/test_blob_filter.py +++ b/test/test_blob_filter.py @@ -11,18 +11,19 @@ # fmt: off -@pytest.mark.parametrize('paths, stage_type, path, expected_result', [ - ((Path("foo"),), 0, Path("foo"), True), - ((Path("foo"),), 0, Path("foo/bar"), True), - ((Path("foo/bar"),), 0, Path("foo"), False), - ((Path("foo"), Path("bar")), 0, Path("foo"), True), +@pytest.mark.parametrize('paths, path, expected_result', [ + ((Path("foo"),), Path("foo"), True), + ((Path("foo"),), Path("foo/bar"), True), + ((Path("foo/bar"),), Path("foo"), False), + ((Path("foo"), Path("bar")), Path("foo"), True), ]) # fmt: on -def test_blob_filter(paths: Sequence[PathLike], stage_type: StageType, path: PathLike, expected_result: bool) -> None: +def test_blob_filter(paths: Sequence[PathLike], path: PathLike, expected_result: bool) -> None: """Test the blob filter.""" blob_filter = BlobFilter(paths) binsha = MagicMock(__len__=lambda self: 20) + stage_type: StageType = 0 blob: Blob = Blob(repo=MagicMock(), binsha=binsha, path=path) stage_blob: Tuple[StageType, Blob] = (stage_type, blob)