Repository: datalad/datalad-next

Issue:
`FileSystemItem.from_path()` ignores `link_target=False` parameter
It will call `readlink` unconditionally for any symlink.

The following patch should fix it. A corresponding test is TODO.

```diff
diff --git a/datalad_next/iter_collections/utils.py b/datalad_next/iter_collections/utils.py
index 0f00a2e..91fcdc4 100644
--- a/datalad_next/iter_collections/utils.py
+++ b/datalad_next/iter_collections/utils.py
@@ -96,7 +96,7 @@ class FileSystemItem(PathBasedItem, TypedItem):
             uid=cstat.st_uid,
             gid=cstat.st_gid,
         )
-        if ctype == FileSystemItemType.symlink:
+        if link_target and ctype == FileSystemItemType.symlink:
             # could be p.readlink() from PY3.9+
             item.link_target = PurePath(os.readlink(path))
         return item
```

Discussion:

Patch:
diff --git a/changelog.d/20231003_111547_michael.hanke_bf_462.md b/changelog.d/20231003_111547_michael.hanke_bf_462.md
new file mode 100644
index 0000000..b03c6af
--- /dev/null
+++ b/changelog.d/20231003_111547_michael.hanke_bf_462.md
@@ -0,0 +1,7 @@
+### 🐛 Bug Fixes
+
+- `FileSystemItem.from_path()` now honors its `link_target` parameter, and
+  resolves a target for any symlink item conditional on this setting.
+  Previously, a symlink target was always resolved.
+  Fixes https://github.com/datalad/datalad-next/issues/462 via
+  https://github.com/datalad/datalad-next/pull/464 (by @mih)
diff --git a/datalad_next/iter_collections/utils.py b/datalad_next/iter_collections/utils.py
index 0f00a2e..91fcdc4 100644
--- a/datalad_next/iter_collections/utils.py
+++ b/datalad_next/iter_collections/utils.py
@@ -96,7 +96,7 @@ class FileSystemItem(PathBasedItem, TypedItem):
             uid=cstat.st_uid,
             gid=cstat.st_gid,
         )
-        if ctype == FileSystemItemType.symlink:
+        if link_target and ctype == FileSystemItemType.symlink:
             # could be p.readlink() from PY3.9+
             item.link_target = PurePath(os.readlink(path))
         return item


Test patch:
diff --git a/datalad_next/iter_collections/tests/test_utils.py b/datalad_next/iter_collections/tests/test_utils.py
new file mode 100644
index 0000000..1393431
--- /dev/null
+++ b/datalad_next/iter_collections/tests/test_utils.py
@@ -0,0 +1,32 @@
+from datalad_next.tests.utils import skip_wo_symlink_capability
+
+from ..utils import FileSystemItem
+
+
+def test_FileSystemItem(tmp_path):
+    testfile = tmp_path / 'file1.txt'
+    testfile_content = 'content'
+    testfile.write_text(testfile_content)
+
+    item = FileSystemItem.from_path(testfile)
+    assert item.size == len(testfile_content)
+    assert item.link_target is None
+
+
+@skip_wo_symlink_capability
+def test_FileSystemItem_linktarget(tmp_path):
+    testfile = tmp_path / 'file1.txt'
+    testfile_content = 'short'
+    testfile.write_text(testfile_content)
+    testlink = tmp_path / 'link'
+    testlink.symlink_to(testfile)
+
+    item = FileSystemItem.from_path(testlink)
+    assert testfile.samefile(item.link_target)
+    # size of the link file does not anyhow propagate the size of the
+    # link target
+    assert item.size != len(testfile_content)
+
+    # we can disable link resolution
+    item = FileSystemItem.from_path(testlink, link_target=False)
+    assert item.link_target is None