Skip to content

Commit 59b2469

Browse files
committed
Add FilterList, Repository.load_filter_list
1 parent d610f77 commit 59b2469

File tree

6 files changed

+95
-1
lines changed

6 files changed

+95
-1
lines changed

pygit2/_run.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
'net.h',
7878
'refspec.h',
7979
'repository.h',
80+
'filter.h',
8081
'commit.h',
8182
'revert.h',
8283
'stash.h',

pygit2/decl/filter.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
typedef enum {
2+
GIT_FILTER_TO_WORKTREE = ...,
3+
GIT_FILTER_TO_ODB = ...,
4+
} git_filter_mode_t;
5+
6+
typedef enum {
7+
GIT_FILTER_DEFAULT = ...,
8+
GIT_FILTER_ALLOW_UNSAFE = ...,
9+
GIT_FILTER_NO_SYSTEM_ATTRIBUTES = ...,
10+
GIT_FILTER_ATTRIBUTES_FROM_HEAD = ...,
11+
GIT_FILTER_ATTRIBUTES_FROM_COMMIT = ...,
12+
} git_filter_flag_t;
13+
14+
int git_filter_list_load(
15+
git_filter_list **filters,
16+
git_repository *repo,
17+
git_blob *blob,
18+
const char *path,
19+
git_filter_mode_t mode,
20+
uint32_t flags);
21+
22+
int git_filter_list_contains(
23+
git_filter_list *filters,
24+
const char *name);
25+
26+
void git_filter_list_free(git_filter_list *filters);

pygit2/decl/types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
typedef struct git_blob git_blob;
12
typedef struct git_commit git_commit;
23
typedef struct git_annotated_commit git_annotated_commit;
34
typedef struct git_config git_config;
5+
typedef struct git_filter_list git_filter_list;
46
typedef struct git_index git_index;
57
typedef struct git_index_conflict_iterator git_index_conflict_iterator;
68
typedef struct git_object git_object;

pygit2/filter.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@
2525

2626
from collections.abc import Callable
2727

28-
from ._pygit2 import FilterSource
28+
from ._pygit2 import FilterSource, Repository
29+
from .errors import check_error
30+
from .ffi import C, ffi
31+
from .utils import to_bytes
2932

3033

3134
class Filter:
@@ -107,3 +110,23 @@ def close(self, write_next: Callable[[bytes], None]) -> None:
107110
Any remaining filtered output data must be written to
108111
`write_next` before returning.
109112
"""
113+
114+
115+
class FilterList:
116+
@classmethod
117+
def _from_c(cls, ptr):
118+
if ptr == ffi.NULL:
119+
return None
120+
fl = cls.__new__(cls)
121+
fl._pointer = ptr
122+
return fl
123+
124+
def __contains__(self, name: str) -> bool:
125+
if not isinstance(name, str):
126+
raise TypeError('argument must be str')
127+
c_name = to_bytes(name)
128+
result = C.git_filter_list_contains(self._pointer, c_name)
129+
return bool(result)
130+
131+
def __del__(self):
132+
C.git_filter_list_free(self._pointer)

pygit2/repository.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
DescribeStrategy,
6565
DiffOption,
6666
FileMode,
67+
FilterMode,
6768
MergeFavor,
6869
MergeFileFlag,
6970
MergeFlag,
@@ -73,6 +74,7 @@
7374
)
7475
from .errors import check_error
7576
from .ffi import C, ffi
77+
from .filter import FilterList
7678
from .index import Index, IndexEntry, MergeFileResult
7779
from .packbuilder import PackBuilder
7880
from .references import References
@@ -235,6 +237,30 @@ def hashfile(
235237
oid = Oid(raw=bytes(ffi.buffer(c_oid.id)[:]))
236238
return oid
237239

240+
def load_filter_list(
241+
self, path: str, mode: FilterMode = FilterMode.TO_ODB
242+
) -> FilterList | None:
243+
"""
244+
Load the filter list for a given path.
245+
246+
Parameters:
247+
248+
path
249+
Relative path of the file to be filtered
250+
251+
mode
252+
Filtering direction: ODB to worktree (SMUDGE), or worktree to ODB
253+
(CLEAN).
254+
"""
255+
c_filters = ffi.new('git_filter_list **')
256+
c_path = to_bytes(path)
257+
c_mode = int(mode)
258+
259+
err = C.git_filter_list_load(c_filters, self._repo, ffi.NULL, c_path, c_mode, 0)
260+
check_error(err)
261+
fl = FilterList._from_c(c_filters[0])
262+
return fl
263+
238264
def __iter__(self) -> Iterator[Oid]:
239265
return iter(self.odb)
240266

test/test_filter.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,19 @@ def test_filter_cleanup(dirtyrepo: Repository, rot13_filter: Filter) -> None:
136136
# Indirectly test that pygit2_filter_cleanup has the GIL
137137
# before calling pygit2_filter_payload_free.
138138
dirtyrepo.diff()
139+
140+
141+
def test_filterlist_none(testrepo: Repository) -> None:
142+
fl = testrepo.load_filter_list('hello.txt')
143+
assert fl is None
144+
145+
146+
def test_filterlist_crlf(testrepo: Repository) -> None:
147+
testrepo.config['core.autocrlf'] = True
148+
149+
fl = testrepo.load_filter_list('hello.txt')
150+
assert fl is not None
151+
assert 'crlf' in fl
152+
153+
with pytest.raises(TypeError):
154+
1234 in fl

0 commit comments

Comments
 (0)