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]