This is an automated email from the ASF dual-hosted git repository.

sbp pushed a commit to branch sbp
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-releases.git


The following commit(s) were added to refs/heads/sbp by this push:
     new 881a3ee  Add a function to construct a mapping of paths to inodes, and 
tests
881a3ee is described below

commit 881a3eee440663022cf31994dbdc41d309ad76b2
Author: Sean B. Palmer <[email protected]>
AuthorDate: Tue Feb 10 18:45:07 2026 +0000

    Add a function to construct a mapping of paths to inodes, and tests
---
 atr/util.py                  | 15 +++++++++++
 tests/unit/test_stat_tree.py | 61 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 76 insertions(+)

diff --git a/atr/util.py b/atr/util.py
index 8d19a6b..9c58a7f 100644
--- a/atr/util.py
+++ b/atr/util.py
@@ -785,6 +785,21 @@ async def paths_recursive_all(base_path: pathlib.Path) -> 
AsyncGenerator[pathlib
                     queue.append(entry_abs_path)
 
 
+def paths_to_inodes(directory: pathlib.Path) -> dict[str, int]:
+    result: dict[str, int] = {}
+    stack: list[pathlib.Path] = [directory]
+    while stack:
+        current = stack.pop()
+        with os.scandir(current) as entries:
+            for entry in entries:
+                if entry.is_file(follow_symlinks=False):
+                    rel_path = 
str(pathlib.Path(entry.path).relative_to(directory))
+                    result[rel_path] = entry.stat(follow_symlinks=False).st_ino
+                elif entry.is_dir(follow_symlinks=False):
+                    stack.append(pathlib.Path(entry.path))
+    return result
+
+
 def permitted_announce_recipients(asf_uid: str) -> list[str]:
     return [
         # f"dev@{committee.name}.apache.org",
diff --git a/tests/unit/test_stat_tree.py b/tests/unit/test_stat_tree.py
new file mode 100644
index 0000000..4d6f7c5
--- /dev/null
+++ b/tests/unit/test_stat_tree.py
@@ -0,0 +1,61 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import os
+import pathlib
+
+import atr.util as util
+
+
+def test_paths_to_inodes_empty_directory(tmp_path: pathlib.Path):
+    result = util.paths_to_inodes(tmp_path)
+    assert result == {}
+
+
+def test_paths_to_inodes_hard_links_share_inode(tmp_path: pathlib.Path):
+    original = tmp_path / "original.txt"
+    original.write_text("shared content")
+    linked = tmp_path / "linked.txt"
+    os.link(original, linked)
+
+    result = util.paths_to_inodes(tmp_path)
+
+    assert result["original.txt"] == result["linked.txt"]
+
+
+def test_paths_to_inodes_nested_directories_excluded(tmp_path: pathlib.Path):
+    (tmp_path / "apple").mkdir()
+    (tmp_path / "apple" / "banana").mkdir()
+    (tmp_path / "cherry.txt").write_text("cherry")
+    (tmp_path / "apple" / "date.txt").write_text("date")
+    (tmp_path / "apple" / "banana" / "elderberry.txt").write_text("elderberry")
+
+    result = util.paths_to_inodes(tmp_path)
+
+    assert set(result.keys()) == {"cherry.txt", "apple/date.txt", 
"apple/banana/elderberry.txt"}
+
+
+def test_paths_to_inodes_returns_correct_paths_and_inodes(tmp_path: 
pathlib.Path):
+    (tmp_path / "a.txt").write_text("alpha")
+    (tmp_path / "b.txt").write_text("bravo")
+
+    result = util.paths_to_inodes(tmp_path)
+
+    assert set(result.keys()) == {"a.txt", "b.txt"}
+    assert result["a.txt"] == (tmp_path / "a.txt").stat().st_ino
+    assert result["b.txt"] == (tmp_path / "b.txt").stat().st_ino
+    assert result["a.txt"] != result["b.txt"]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to