(
manifest: pathlib.Path, objects_dir: pathlib.Path
)
| 246 | |
| 247 | |
| 248 | def load_candidates( |
| 249 | manifest: pathlib.Path, objects_dir: pathlib.Path |
| 250 | ) -> tuple[list[dict[str, str]], dict[str, pathlib.Path]]: |
| 251 | metadata, rows = parse_tsv( |
| 252 | manifest, |
| 253 | marker="cbm-release-candidates-v1", |
| 254 | fields=CANDIDATE_FIELDS, |
| 255 | ) |
| 256 | if metadata != {"targets": str(len(TARGETS)), "candidates": str(len(TARGETS) * len(VARIANTS))}: |
| 257 | raise ContractError("candidate metadata does not bind the exact canonical matrix") |
| 258 | expected_pairs = [(target, variant) for target in TARGETS for variant in VARIANTS] |
| 259 | if [(row["target"], row["variant"]) for row in rows] != expected_pairs: |
| 260 | raise ContractError("candidate rows are not the exact canonical target/variant matrix") |
| 261 | |
| 262 | try: |
| 263 | objects_status = objects_dir.lstat() |
| 264 | except FileNotFoundError as error: |
| 265 | raise ContractError(f"candidate object directory is missing: {objects_dir}") from error |
| 266 | if not stat.S_ISDIR(objects_status.st_mode): |
| 267 | raise ContractError(f"candidate object path is not a regular directory: {objects_dir}") |
| 268 | |
| 269 | object_paths: dict[str, pathlib.Path] = {} |
| 270 | seen_hashes: set[str] = set() |
| 271 | for row, (target, variant) in zip(rows, expected_pairs): |
| 272 | validate_candidate_row(row, target=target, variant=variant) |
| 273 | if row["sha256"] in seen_hashes: |
| 274 | raise ContractError("candidate object hashes are not unique") |
| 275 | seen_hashes.add(row["sha256"]) |
| 276 | path = objects_dir / pathlib.PurePosixPath(row["scan_path"]).name |
| 277 | actual_sha256 = sha256_file(path, expected_size=int(row["size"])) |
| 278 | if actual_sha256 != row["sha256"]: |
| 279 | raise ContractError(f"candidate object hash changed: {row['scan_path']}") |
| 280 | object_paths[row["scan_path"]] = path |
| 281 | |
| 282 | actual_names: set[str] = set() |
| 283 | for path in objects_dir.iterdir(): |
| 284 | if path.is_symlink() or not path.is_file(): |
| 285 | raise ContractError(f"unexpected non-regular candidate object: {path}") |
| 286 | actual_names.add(path.name) |
| 287 | expected_names = {path.name for path in object_paths.values()} |
| 288 | if actual_names != expected_names or len(actual_names) != len(rows): |
| 289 | raise ContractError("candidate object directory is missing objects or contains surplus entries") |
| 290 | for target in TARGETS: |
| 291 | pair = [row for row in rows if row["target"] == target] |
| 292 | if len({row["source_sha256"] for row in pair}) != 1: |
| 293 | raise ContractError(f"candidate siblings do not share source provenance: {target}") |
| 294 | if pair[0]["pre_sign_sha256"] != pair[0]["source_sha256"]: |
| 295 | raise ContractError( |
| 296 | f"unstripped pre-sign bytes do not match source provenance: {target}" |
| 297 | ) |
| 298 | if not target.startswith("darwin-") and any( |
| 299 | row["pre_sign_sha256"] != row["sha256"] for row in pair |
| 300 | ): |
| 301 | raise ContractError( |
| 302 | f"non-Darwin candidate changed between pre-sign and final bytes: {target}" |
| 303 | ) |
| 304 | if pair[0]["sha256"] == pair[1]["sha256"]: |
| 305 | raise ContractError(f"candidate siblings are not byte-distinct: {target}") |
no test coverage detected