Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ mise.local.toml
architecture/plans

# Claude
.claude/settings.local.json.claude/worktrees/
.claude/settings.local.json
.claude/worktrees/
rfc.md
.worktrees
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 7 additions & 3 deletions crates/openshell-driver-podman/src/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,7 @@ mod tests {
let (stream, _) = listener.accept().await.expect("test stub should accept");
let log = log_for_task.clone();
let queue = queue_for_task.clone();
http1::Builder::new()
let result = http1::Builder::new()
.serve_connection(
TokioIo::new(stream),
service_fn(move |req| {
Expand Down Expand Up @@ -690,8 +690,12 @@ mod tests {
}
}),
)
.await
.expect("test stub should serve request");
.await;
// The one-shot test client can close the Unix socket after the
// response, which Hyper reports as a shutdown error. Let the
// request log assertions below decide whether the stub served
// the expected API calls.
let _ = result;
}
let _ = std::fs::remove_file(&socket_path_for_task);
});
Expand Down
10 changes: 7 additions & 3 deletions crates/openshell-driver-podman/src/grpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ mod tests {
let (stream, _) = listener.accept().await.expect("test stub should accept");
let log = log_for_task.clone();
let queue = queue_for_task.clone();
http1::Builder::new()
let result = http1::Builder::new()
.serve_connection(
TokioIo::new(stream),
service_fn(move |req| {
Expand Down Expand Up @@ -282,8 +282,12 @@ mod tests {
}
}),
)
.await
.expect("test stub should serve request");
.await;
// The one-shot test client can close the Unix socket after the
// response, which Hyper reports as a shutdown error. Let the
// request log assertions below decide whether the stub served
// the expected API calls.
let _ = result;
}
let _ = std::fs::remove_file(&socket_path_for_task);
});
Expand Down
74 changes: 62 additions & 12 deletions scripts/update_license_headers.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import argparse
import os
import subprocess
import sys
from pathlib import Path

Expand Down Expand Up @@ -113,11 +114,48 @@ def is_excluded(rel: Path) -> bool:
return True

# Prefix exclusions (CI config, editor config).
for prefix in EXCLUDE_DIR_PREFIXES:
if rel_str.startswith(prefix):
return True

return False
return any(rel_str.startswith(prefix) for prefix in EXCLUDE_DIR_PREFIXES)


def git_candidate_files(root: Path) -> list[Path] | None:
"""Return Git-tracked and unignored files, or None if Git is unavailable."""
try:
result = subprocess.run(
[
"git",
"-C",
str(root),
"ls-files",
"-z",
"--cached",
"--others",
"--exclude-standard",
],
check=True,
capture_output=True,
)
except (OSError, subprocess.CalledProcessError):
return None

files = []
for raw_path in result.stdout.split(b"\0"):
if raw_path:
files.append(Path(os.fsdecode(raw_path)))
return files


def is_git_ignored(root: Path, rel: Path) -> bool:
"""Return True if Git ignore rules exclude a path."""
try:
result = subprocess.run(
["git", "-C", str(root), "check-ignore", "-q", "--", str(rel)],
check=False,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
except OSError:
return False
return result.returncode == 0


def is_dockerfile(path: Path) -> bool:
Expand All @@ -135,6 +173,19 @@ def get_comment_style(path: Path) -> str | None:
def discover_files(root: Path) -> list[Path]:
"""Walk the repo and return all files that should have headers."""
results = []

git_files = git_candidate_files(root)
if git_files is not None:
for rel in git_files:
path = root / rel
if not path.is_file():
continue
if is_excluded(rel):
continue
if get_comment_style(rel) is not None:
results.append(path)
return sorted(results)

for dirpath, dirnames, filenames in os.walk(root):
rel_dir = Path(dirpath).relative_to(root)

Expand All @@ -161,10 +212,7 @@ def discover_files(root: Path) -> list[Path]:

def has_header(lines: list[str]) -> bool:
"""Check if the SPDX header is present in the first 10 lines."""
for line in lines[:10]:
if SPDX_MARKER in line:
return True
return False
return any(SPDX_MARKER in line for line in lines[:10])


def find_insertion_point(lines: list[str], path: Path) -> int:
Expand Down Expand Up @@ -276,8 +324,11 @@ def main() -> int:
p = p.resolve()
if not p.is_file():
continue
rel = p.relative_to(root)
if is_excluded(rel):
try:
rel = p.relative_to(root)
except ValueError:
continue
if is_excluded(rel) or is_git_ignored(root, rel):
continue
if get_comment_style(rel) is not None:
files.append(p)
Expand All @@ -301,7 +352,6 @@ def main() -> int:
print("All files have SPDX headers.")
return 0

added = len(missing) # In non-check mode, missing list is empty; count via verbose
print("Done.")
return 0

Expand Down
Loading