diff options
| author | Craig Jennings <c@cjennings.net> | 2026-07-23 23:57:58 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-07-23 23:57:58 -0500 |
| commit | a053e9d1ecbf583b4a6f054c34f64ad1f359365e (patch) | |
| tree | 27d60e5b02df6fdfad8094886c08952c82d5c70f /.ai/scripts/inbox-send.py | |
| parent | 0f91a8e0cd0a4b5b351efe407987bb8bb6ab125e (diff) | |
| download | rulesets-a053e9d1ecbf583b4a6f054c34f64ad1f359365e.tar.gz rulesets-a053e9d1ecbf583b4a6f054c34f64ad1f359365e.zip | |
fix(inbox-send): clean error on an unreadable source, dedupe overlapping roots
main caught ValueError and FileNotFoundError around the send, so an unreadable source raised a PermissionError as a raw traceback instead of the clean "inbox-send: <message>" every other failure produces. Widening the catch to OSError covers the unreadable source, the missing source, and any atomic-write failure alike.
discover_projects appended without deduping, so a roots config naming both a parent directory and one of its children listed the same project at two indices. It now dedupes on the resolved path, first-seen order preserved.
Diffstat (limited to '.ai/scripts/inbox-send.py')
| -rwxr-xr-x | .ai/scripts/inbox-send.py | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/.ai/scripts/inbox-send.py b/.ai/scripts/inbox-send.py index 5787a84..663efcb 100755 --- a/.ai/scripts/inbox-send.py +++ b/.ai/scripts/inbox-send.py @@ -70,17 +70,28 @@ def discover_projects(roots: list[Path]) -> list[Path]: a specific project root (included directly if it qualifies). """ projects: list[Path] = [] + seen: set[Path] = set() + + def _add(p: Path) -> None: + # Dedupe on the resolved path: a roots config naming both a parent and + # one of its children would otherwise list the child project twice, at + # two different indices. + key = p.resolve() + if key not in seen: + seen.add(key) + projects.append(p) + for root in roots: if not root.is_dir(): continue if _is_project(root): - projects.append(root) + _add(root) continue for child in sorted(root.iterdir()): if not child.is_dir(): continue if _is_project(child): - projects.append(child) + _add(child) return projects @@ -345,7 +356,10 @@ def main() -> int: else: assert args.file is not None dest = send_file(target_inbox, args.file, source_name, args.name, now) - except (ValueError, FileNotFoundError) as exc: + except (ValueError, OSError) as exc: + # OSError covers FileNotFoundError (missing source), PermissionError + # (unreadable source), and any atomic-write failure — all should + # surface as the clean "inbox-send: <message>" error, never a traceback. print(f"inbox-send: {exc}", file=sys.stderr) return 1 |
