Skip to content

Commit 0fd61d6

Browse files
committed
Implement full support for fp=True in iter_annexworktree()
Previously, it would only open annex objects. Now regular files (tracked or untracked) and symlink targets (via the symlink) are also opened, if they actually exist. The corresponding test is extended appropriately.
1 parent 9148814 commit 0fd61d6

File tree

2 files changed

+43
-15
lines changed

2 files changed

+43
-15
lines changed

datalad_next/iter_collections/annexworktree.py

+26-13
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
GitWorktreeFileSystemItem,
3232
iter_gitworktree
3333
)
34+
from .utils import FileSystemItemType
3435

3536

3637
lgr = logging.getLogger('datalad.ext.next.iter_collections.annexworktree')
@@ -83,7 +84,7 @@ def iter_annexworktree(
8384
8485
The basic semantics of all arguments are identical to
8586
:func:`~datalad_next.iter_collections.gitworktree.iter_gitworktree`.
86-
Importantly, with ``fp=True``, the annex object is opened directly,
87+
Importantly, with ``fp=True``, an annex object is opened directly,
8788
if available. If not available, no attempt is made to open the associated
8889
symlink or pointer file.
8990
@@ -240,19 +241,31 @@ def iter_annexworktree(
240241
path = Path(path)
241242
for res in results:
242243
item = _get_worktree_item(path, get_fs_info=True, **res)
243-
annexobjpath = res.get('annexobjpath')
244-
if not annexobjpath:
245-
# this is not an annexed file
246-
yield item
247-
continue
248-
full_annexobjpath = path / annexobjpath
249-
if not full_annexobjpath.exists():
250-
# annexed object is not present
251-
yield item
252-
continue
253-
with (full_annexobjpath).open('rb') as active_fp:
254-
item.fp = active_fp
244+
# determine would file we would open
245+
fp_src = None
246+
if item.annexobjpath is not None:
247+
# this is an annexed file
248+
fp_src = item.annexobjpath
249+
elif item.type == FileSystemItemType.file \
250+
and item.annexkey is None:
251+
# regular file (untracked or tracked)
252+
fp_src = item.name
253+
elif item.type == FileSystemItemType.symlink \
254+
and item.annexkey is None:
255+
# regular symlink
256+
fp_src = item.name
257+
if fp_src is None:
258+
# nothing to open
255259
yield item
260+
else:
261+
fp_src_fullpath = path / fp_src
262+
if not fp_src_fullpath.exists():
263+
# nothing there to open (would resolve through a symlink)
264+
yield item
265+
else:
266+
with fp_src_fullpath.open('rb') as active_fp:
267+
item.fp = active_fp
268+
yield item
256269

257270

258271
def _get_worktree_item(

datalad_next/iter_collections/tests/test_iterannexworktree.py

+17-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from datalad import cfg as dlcfg
66

77
from datalad_next.datasets import Dataset
8+
from datalad_next.utils import check_symlink_capability
89

910
from ..annexworktree import (
1011
iter_annexworktree,
@@ -98,9 +99,21 @@ def test_iter_annexworktree_basic_fp(existing_dataset, no_result_rendering):
9899
for i in ('untracked', 'ingit'):
99100
(ds.pathobj / f'file_{i}').write_text(content_tmpl.format(i))
100101
ds.save('file_ingit', to_git=True)
102+
# and add symlinks (untracked and in git)
103+
if check_symlink_capability(
104+
ds.pathobj / '_dummy', ds.pathobj / '_dummy_target'
105+
):
106+
for i in ('symlinkuntracked', 'symlinkingit'):
107+
tpath = ds.pathobj / f'target_{i}'
108+
lpath = ds.pathobj / f'file_{i}'
109+
tpath.write_text(content_tmpl.format(i))
110+
lpath.symlink_to(tpath)
111+
ds.save('file_symlinkingit', to_git=True)
101112

102113
# we expect to process an exact number of files below
103-
fcount = 5
114+
# 3 annexed files, 1 untracked, 1 in git, 1 symlink in git,
115+
# 1 symlink untracked
116+
fcount = 7
104117
for ai in filter(
105118
lambda i: str(i.name.name).startswith('file_'),
106119
iter_annexworktree(ds.pathobj, fp=True)
@@ -110,5 +123,7 @@ def test_iter_annexworktree_basic_fp(existing_dataset, no_result_rendering):
110123
assert content_tmpl.format(
111124
ai.name.name[5:]) == ai.fp.read().decode()
112125
else:
113-
assert (ds.pathobj / ai.annexobjpath).exists() is False
126+
assert (ai.annexobjpath and (
127+
ds.pathobj / ai.annexobjpath).exists() is False) or (
128+
ai.name.exists() is False)
114129
assert not fcount

0 commit comments

Comments
 (0)