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

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


The following commit(s) were added to refs/heads/main by this push:
     new 552e2d3  Add a function to change file permissions recursively
552e2d3 is described below

commit 552e2d322f863e4c81c398a729e876d2663ab5a8
Author: Sean B. Palmer <[email protected]>
AuthorDate: Tue Jan 20 16:41:40 2026 +0000

    Add a function to change file permissions recursively
---
 atr/util.py             |   7 ++++
 tests/unit/test_util.py | 104 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 111 insertions(+)

diff --git a/atr/util.py b/atr/util.py
index aa40a5c..4b83f96 100644
--- a/atr/util.py
+++ b/atr/util.py
@@ -208,6 +208,13 @@ def chmod_directories(path: pathlib.Path, permissions: int 
= 0o755) -> None:
             os.chmod(dir_path, permissions)
 
 
+def chmod_files(path: pathlib.Path, permissions: int) -> None:
+    """Set permissions on all files in a directory tree."""
+    for file_path in path.rglob("*"):
+        if file_path.is_file():
+            os.chmod(file_path, permissions)
+
+
 def committee_is_standing(committee_name: str) -> bool:
     return committee_name in registry.STANDING_COMMITTEES
 
diff --git a/tests/unit/test_util.py b/tests/unit/test_util.py
new file mode 100644
index 0000000..0a8c814
--- /dev/null
+++ b/tests/unit/test_util.py
@@ -0,0 +1,104 @@
+# 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 stat
+import tempfile
+
+import atr.util as util
+
+
+def test_chmod_files_does_not_change_directory_permissions():
+    with tempfile.TemporaryDirectory() as tmp_dir:
+        tmp_path = pathlib.Path(tmp_dir)
+        subdir = tmp_path / "subdir"
+        subdir.mkdir()
+        os.chmod(subdir, 0o700)
+        test_file = subdir / "test.txt"
+        test_file.write_text("content")
+
+        util.chmod_files(tmp_path, 0o444)
+
+        dir_mode = stat.S_IMODE(subdir.stat().st_mode)
+        assert dir_mode == 0o700
+
+
+def test_chmod_files_handles_empty_directory():
+    with tempfile.TemporaryDirectory() as tmp_dir:
+        tmp_path = pathlib.Path(tmp_dir)
+        util.chmod_files(tmp_path, 0o444)
+
+
+def test_chmod_files_handles_multiple_files():
+    with tempfile.TemporaryDirectory() as tmp_dir:
+        tmp_path = pathlib.Path(tmp_dir)
+        files = [tmp_path / f"file{i}.txt" for i in range(5)]
+        for f in files:
+            f.write_text("content")
+            os.chmod(f, 0o644)
+
+        util.chmod_files(tmp_path, 0o400)
+
+        for f in files:
+            file_mode = stat.S_IMODE(f.stat().st_mode)
+            assert file_mode == 0o400
+
+
+def test_chmod_files_handles_nested_directories():
+    with tempfile.TemporaryDirectory() as tmp_dir:
+        tmp_path = pathlib.Path(tmp_dir)
+        nested_dir = tmp_path / "subdir" / "nested"
+        nested_dir.mkdir(parents=True)
+        file1 = tmp_path / "root.txt"
+        file2 = tmp_path / "subdir" / "mid.txt"
+        file3 = nested_dir / "deep.txt"
+        for f in [file1, file2, file3]:
+            f.write_text("content")
+            os.chmod(f, 0o644)
+
+        util.chmod_files(tmp_path, 0o444)
+
+        for f in [file1, file2, file3]:
+            file_mode = stat.S_IMODE(f.stat().st_mode)
+            assert file_mode == 0o444
+
+
+def test_chmod_files_sets_custom_permissions():
+    with tempfile.TemporaryDirectory() as tmp_dir:
+        tmp_path = pathlib.Path(tmp_dir)
+        test_file = tmp_path / "test.txt"
+        test_file.write_text("content")
+        os.chmod(test_file, 0o644)
+
+        util.chmod_files(tmp_path, 0o400)
+
+        file_mode = stat.S_IMODE(test_file.stat().st_mode)
+        assert file_mode == 0o400
+
+
+def test_chmod_files_sets_default_permissions():
+    with tempfile.TemporaryDirectory() as tmp_dir:
+        tmp_path = pathlib.Path(tmp_dir)
+        test_file = tmp_path / "test.txt"
+        test_file.write_text("content")
+        os.chmod(test_file, 0o644)
+
+        util.chmod_files(tmp_path, 0o444)
+
+        file_mode = stat.S_IMODE(test_file.stat().st_mode)
+        assert file_mode == 0o444


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

Reply via email to