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-release.git
The following commit(s) were added to refs/heads/main by this push:
new bbd0db0 Ensure that permissions of directories are consistent
bbd0db0 is described below
commit bbd0db0317935cac842f0369c71259aaad929fb9
Author: Sean B. Palmer <[email protected]>
AuthorDate: Wed May 28 15:29:27 2025 +0100
Ensure that permissions of directories are consistent
---
atr/revision.py | 3 +
atr/routes/announce.py | 7 ++-
atr/routes/finish.py | 1 -
atr/templates/finish-selected.html | 116 ++++++++++++++++++-------------------
atr/util.py | 8 +++
5 files changed, 72 insertions(+), 63 deletions(-)
diff --git a/atr/revision.py b/atr/revision.py
index 5c0e08f..eb849fb 100644
--- a/atr/revision.py
+++ b/atr/revision.py
@@ -85,6 +85,9 @@ async def create_and_manage(
await aioshutil.rmtree(temp_dir) # type: ignore[call-arg]
raise
+ # Ensure that the permissions of every directory are 755
+ await asyncio.to_thread(util.chmod_directories, temp_dir_path)
+
# Create a revision row, holding the write lock
async with db.session() as data:
# This is the only place where models.Revision is constructed
diff --git a/atr/routes/announce.py b/atr/routes/announce.py
index fae5ced..404985d 100644
--- a/atr/routes/announce.py
+++ b/atr/routes/announce.py
@@ -15,6 +15,7 @@
# specific language governing permissions and limitations
# under the License.
+import asyncio
import datetime
import logging
from typing import TYPE_CHECKING, Any, Protocol
@@ -193,10 +194,14 @@ async def selected_post(
# Do not put it in the data block after data.commit()
# Otherwise util.release_directory() will not work
release = await
data.release(name=release.name).demand(RuntimeError(f"Release {release.name}
does not exist"))
- target = str(util.release_directory(release))
+ target_path = util.release_directory(release)
+ target = str(target_path)
if await aiofiles.os.path.exists(target):
raise routes.FlashError("Release already exists")
+ # Ensure that the permissions of every directory are 755
+ await asyncio.to_thread(util.chmod_directories, target_path)
+
try:
await aioshutil.move(source, target)
if source_base:
diff --git a/atr/routes/finish.py b/atr/routes/finish.py
index 889e515..979a745 100644
--- a/atr/routes/finish.py
+++ b/atr/routes/finish.py
@@ -145,7 +145,6 @@ async def selected(
source_files=sorted(source_files_rel),
form=move_form,
delete_dir_form=delete_dir_form,
- can_move=can_move,
user_ssh_keys=user_ssh_keys,
target_dirs=sorted(list(target_dirs)),
max_files_to_show=10,
diff --git a/atr/templates/finish-selected.html
b/atr/templates/finish-selected.html
index aadabe0..60c1255 100644
--- a/atr/templates/finish-selected.html
+++ b/atr/templates/finish-selected.html
@@ -107,75 +107,69 @@
</p>
</div>
- {% if can_move %}
- <h2>Move items to a different directory</h2>
- <p>
- Note that files with associated metadata (e.g. <code>.asc</code> or
<code>.sha512</code> files) are treated as a single unit and will be moved
together if any one of them is selected for movement.
- </p>
- <div id="move-error-alert"
- class="alert alert-danger d-none"
- role="alert"
- aria-live="assertive"></div>
- <form class="atr-canary">
- <div class="row">
- <div class="col-lg-6">
- <div class="card mb-4">
- <div class="card-header bg-light">
- <h3 class="mb-0">Select items to move</h3>
- </div>
- <div class="card-body">
- <input type="text"
- id="file-filter"
- class="form-control mb-2"
- placeholder="Search for an item to move..." />
- <table class="table table-sm table-striped border mt-3">
- <tbody id="file-list-table-body">
- </tbody>
- </table>
- <div id="file-list-more-info" class="text-muted small
mt-1"></div>
- </div>
+ <h2>Move items to a different directory</h2>
+ <p>
+ Note that files with associated metadata (e.g. <code>.asc</code> or
<code>.sha512</code> files) are treated as a single unit and will be moved
together if any one of them is selected for movement.
+ </p>
+ <div id="move-error-alert"
+ class="alert alert-danger d-none"
+ role="alert"
+ aria-live="assertive"></div>
+ <form class="atr-canary">
+ <div class="row">
+ <div class="col-lg-6">
+ <div class="card mb-4">
+ <div class="card-header bg-light">
+ <h3 class="mb-0">Select items to move</h3>
+ </div>
+ <div class="card-body">
+ <input type="text"
+ id="file-filter"
+ class="form-control mb-2"
+ placeholder="Search for an item to move..." />
+ <table class="table table-sm table-striped border mt-3">
+ <tbody id="file-list-table-body">
+ </tbody>
+ </table>
+ <div id="file-list-more-info" class="text-muted small mt-1"></div>
</div>
</div>
- <div class="col-lg-6">
- <div class="card mb-4">
- <div class="card-header bg-light">
- <h3 class="mb-0">
- <span id="selected-file-name-title">Select a destination for
the file</span>
- </h3>
- </div>
- <div class="card-body">
- <input type="text"
- id="dir-filter-input"
- class="form-control mb-2"
- placeholder="Search for a directory to move to..." />
- <table class="table table-sm table-striped border mt-3">
- <tbody id="dir-list-table-body">
- </tbody>
- </table>
- <div id="dir-list-more-info" class="text-muted small mt-1"></div>
- </div>
+ </div>
+ <div class="col-lg-6">
+ <div class="card mb-4">
+ <div class="card-header bg-light">
+ <h3 class="mb-0">
+ <span id="selected-file-name-title">Select a destination for the
file</span>
+ </h3>
+ </div>
+ <div class="card-body">
+ <input type="text"
+ id="dir-filter-input"
+ class="form-control mb-2"
+ placeholder="Search for a directory to move to..." />
+ <table class="table table-sm table-striped border mt-3">
+ <tbody id="dir-list-table-body">
+ </tbody>
+ </table>
+ <div id="dir-list-more-info" class="text-muted small mt-1"></div>
</div>
</div>
</div>
+ </div>
- <div>
- <div class="mb-3">
- <label for="maxFilesInput" class="form-label">Items to show per
list:</label>
- <input type="number"
- class="form-control form-control-sm w-25"
- id="max-files-input"
- value="{{ max_files_to_show }}"
- min="1" />
- </div>
- <div id="current-move-selection-info" class="text-muted">Please select
a file and a destination.</div>
- <button type="button" id="confirm-move-button" class="btn btn-success
mt-2">Move to selected directory</button>
+ <div>
+ <div class="mb-3">
+ <label for="maxFilesInput" class="form-label">Items to show per
list:</label>
+ <input type="number"
+ class="form-control form-control-sm w-25"
+ id="max-files-input"
+ value="{{ max_files_to_show }}"
+ min="1" />
</div>
- </form>
- {% else %}
- <div class="alert alert-info" role="alert">
- File moving is disabled as all files are currently in the same directory
or the revision is empty.
+ <div id="current-move-selection-info" class="text-muted">Please select a
file and a destination.</div>
+ <button type="button" id="confirm-move-button" class="btn btn-success
mt-2">Move to selected directory</button>
</div>
- {% endif %}
+ </form>
{% if delete_dir_form.directory_to_delete.choices %}
<h2>Delete an empty directory</h2>
<form method="post" class="mb-4">
diff --git a/atr/util.py b/atr/util.py
index a427210..a97b49f 100644
--- a/atr/util.py
+++ b/atr/util.py
@@ -22,6 +22,7 @@ import dataclasses
import datetime
import hashlib
import logging
+import os
import pathlib
import re
import tarfile
@@ -160,6 +161,13 @@ async def compute_sha512(file_path: pathlib.Path) -> str:
return sha512.hexdigest()
+def chmod_directories(path: pathlib.Path, permissions: int = 0o755) -> None:
+ os.chmod(path, permissions)
+ for dir_path in path.rglob("*"):
+ if dir_path.is_dir():
+ os.chmod(dir_path, permissions)
+
+
async def content_list(
phase_subdir: pathlib.Path, project_name: str, version_name: str,
revision_name: str | None = None
) -> AsyncGenerator[FileStat]:
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]