fix avahi
This commit is contained in:
472
scripts/update.py
Normal file
472
scripts/update.py
Normal file
@@ -0,0 +1,472 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
version.json CLI updater.
|
||||
|
||||
Usage examples:
|
||||
# Update a GitHub source to its latest release tag, then recompute hash
|
||||
scripts/update.py --file packages/edk2/version.json --github-latest-release --prefetch
|
||||
|
||||
# Update a specific component to the latest commit
|
||||
scripts/update.py --file packages/edk2/version.json --component edk2 --github-latest-commit --prefetch
|
||||
|
||||
# Update all URL-based sources in a file (recompute hash only)
|
||||
scripts/update.py --file packages/uboot/version.json --url-prefetch
|
||||
|
||||
# Update a variant's variables
|
||||
scripts/update.py --file packages/proton-cachyos/version.json --variant cachyos-v4 \\
|
||||
--set variables.base=10.0 --set variables.release=20260301
|
||||
|
||||
# Filter tags with a regex (e.g. only stable_* tags)
|
||||
scripts/update.py --file packages/raspberrypi/linux-rpi/version.json \\
|
||||
--component stable --github-latest-tag --tag-regex '^stable_\\d{8}$' --prefetch
|
||||
|
||||
# Update a fetchgit source to HEAD
|
||||
scripts/update.py --file packages/linux-cachyos/version.json --component zfs --git-latest --prefetch
|
||||
|
||||
# Dry run (show what would change, don't write)
|
||||
scripts/update.py --file packages/edk2/version.json --github-latest-release --prefetch --dry-run
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import List, Optional
|
||||
|
||||
# Ensure scripts/ is on the path so we can import lib and hooks
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
||||
|
||||
import lib
|
||||
import hooks # noqa: F401 — registers hooks as a side effect
|
||||
|
||||
|
||||
def _apply_set_pairs(target: lib.Json, pairs: List[str]) -> bool:
|
||||
changed = False
|
||||
for pair in pairs:
|
||||
if "=" not in pair:
|
||||
lib.eprint(f"--set: expected KEY=VALUE, got: {pair!r}")
|
||||
continue
|
||||
key, val = pair.split("=", 1)
|
||||
path = [p for p in key.strip().split(".") if p]
|
||||
lib.deep_set(target, path, val)
|
||||
lib.eprint(f" set {'.'.join(path)} = {val!r}")
|
||||
changed = True
|
||||
return changed
|
||||
|
||||
|
||||
def update_components(
|
||||
spec: lib.Json,
|
||||
variant: Optional[str],
|
||||
components: Optional[List[str]],
|
||||
args: argparse.Namespace,
|
||||
) -> bool:
|
||||
changed = False
|
||||
merged_vars, merged_srcs, target_dict = lib.merged_view(spec, variant)
|
||||
target_sources: lib.Json = target_dict.setdefault("sources", {})
|
||||
|
||||
names = (
|
||||
list(merged_srcs.keys())
|
||||
if not components
|
||||
else [c for c in components if c in merged_srcs]
|
||||
)
|
||||
if components:
|
||||
missing = [c for c in components if c not in merged_srcs]
|
||||
for m in missing:
|
||||
lib.eprint(f" [warn] component '{m}' not found in merged sources")
|
||||
|
||||
for name in names:
|
||||
view_comp = merged_srcs[name]
|
||||
fetcher = view_comp.get("fetcher", "none")
|
||||
comp = target_sources.setdefault(name, {})
|
||||
|
||||
if fetcher == "github":
|
||||
owner = view_comp.get("owner") or ""
|
||||
repo = view_comp.get("repo") or ""
|
||||
if not (owner and repo):
|
||||
lib.eprint(f" [{name}] missing owner/repo, skipping")
|
||||
continue
|
||||
|
||||
# --set-branch: update branch field and fetch HEAD of that branch
|
||||
if args.set_branch is not None:
|
||||
new_branch = args.set_branch or None # empty string → clear branch
|
||||
if new_branch:
|
||||
comp["branch"] = new_branch
|
||||
lib.eprint(f" [{name}] branch -> {new_branch!r}")
|
||||
else:
|
||||
comp.pop("branch", None)
|
||||
lib.eprint(f" [{name}] branch cleared")
|
||||
changed = True
|
||||
rev = lib.gh_head_commit(owner, repo, new_branch)
|
||||
if rev:
|
||||
comp["rev"] = rev
|
||||
comp.pop("tag", None)
|
||||
lib.eprint(f" [{name}] rev -> {rev}")
|
||||
changed = True
|
||||
if args.prefetch:
|
||||
sri = lib.prefetch_github(
|
||||
owner,
|
||||
repo,
|
||||
rev,
|
||||
submodules=bool(view_comp.get("submodules", False)),
|
||||
)
|
||||
if sri:
|
||||
comp["hash"] = sri
|
||||
lib.eprint(f" [{name}] hash -> {sri}")
|
||||
changed = True
|
||||
else:
|
||||
lib.eprint(
|
||||
f" [{name}] could not resolve HEAD for branch {new_branch!r}"
|
||||
)
|
||||
continue # skip the normal ref-update logic for this component
|
||||
|
||||
new_ref: Optional[str] = None
|
||||
ref_kind = ""
|
||||
|
||||
if args.github_latest_release:
|
||||
tag = lib.gh_latest_release(owner, repo)
|
||||
if tag:
|
||||
new_ref, ref_kind = tag, "tag"
|
||||
elif args.github_latest_tag:
|
||||
tag = lib.gh_latest_tag(owner, repo, tag_regex=args.tag_regex)
|
||||
if tag:
|
||||
new_ref, ref_kind = tag, "tag"
|
||||
elif args.github_latest_commit:
|
||||
rev = lib.gh_head_commit(owner, repo)
|
||||
if rev:
|
||||
new_ref, ref_kind = rev, "rev"
|
||||
|
||||
if new_ref:
|
||||
if ref_kind == "tag":
|
||||
comp["tag"] = new_ref
|
||||
comp.pop("rev", None)
|
||||
else:
|
||||
comp["rev"] = new_ref
|
||||
comp.pop("tag", None)
|
||||
lib.eprint(f" [{name}] {ref_kind} -> {new_ref}")
|
||||
changed = True
|
||||
|
||||
if args.prefetch and (new_ref or args.url_prefetch):
|
||||
# Use merged view with the updated ref for prefetching
|
||||
merged_vars2, merged_srcs2, _ = lib.merged_view(spec, variant)
|
||||
view2 = lib.render(merged_srcs2.get(name, view_comp), merged_vars2)
|
||||
sri = lib.prefetch_github(
|
||||
owner,
|
||||
repo,
|
||||
view2.get("tag") or view2.get("rev") or new_ref or "",
|
||||
submodules=bool(view_comp.get("submodules", False)),
|
||||
)
|
||||
if sri:
|
||||
comp["hash"] = sri
|
||||
lib.eprint(f" [{name}] hash -> {sri}")
|
||||
changed = True
|
||||
|
||||
elif fetcher == "git":
|
||||
url = view_comp.get("url") or ""
|
||||
if not url:
|
||||
lib.eprint(f" [{name}] missing url for git fetcher, skipping")
|
||||
continue
|
||||
|
||||
# --set-branch: update branch field and fetch HEAD of that branch
|
||||
if args.set_branch is not None:
|
||||
new_branch = args.set_branch or None
|
||||
if new_branch:
|
||||
comp["branch"] = new_branch
|
||||
lib.eprint(f" [{name}] branch -> {new_branch!r}")
|
||||
else:
|
||||
comp.pop("branch", None)
|
||||
lib.eprint(f" [{name}] branch cleared")
|
||||
changed = True
|
||||
rev = lib.git_branch_commit(url, new_branch)
|
||||
if rev:
|
||||
comp["rev"] = rev
|
||||
lib.eprint(f" [{name}] rev -> {rev}")
|
||||
changed = True
|
||||
if args.prefetch:
|
||||
sri = lib.prefetch_git(url, rev)
|
||||
if sri:
|
||||
comp["hash"] = sri
|
||||
lib.eprint(f" [{name}] hash -> {sri}")
|
||||
changed = True
|
||||
else:
|
||||
lib.eprint(
|
||||
f" [{name}] could not resolve HEAD for branch {new_branch!r}"
|
||||
)
|
||||
continue
|
||||
|
||||
if args.git_latest:
|
||||
rev = lib.git_branch_commit(url, view_comp.get("branch"))
|
||||
if rev:
|
||||
comp["rev"] = rev
|
||||
lib.eprint(f" [{name}] rev -> {rev}")
|
||||
changed = True
|
||||
if args.prefetch:
|
||||
sri = lib.prefetch_git(url, rev)
|
||||
if sri:
|
||||
comp["hash"] = sri
|
||||
lib.eprint(f" [{name}] hash -> {sri}")
|
||||
changed = True
|
||||
|
||||
elif fetcher == "url":
|
||||
if args.latest_version:
|
||||
url_info = lib._url_source_info(view_comp, merged_vars)
|
||||
kind = url_info.get("kind", "plain")
|
||||
version_var = url_info.get("version_var") or "version"
|
||||
new_ver: Optional[str] = None
|
||||
|
||||
if kind == "github":
|
||||
owner = url_info.get("owner", "")
|
||||
repo = url_info.get("repo", "")
|
||||
tags = lib.gh_release_tags(owner, repo) if owner and repo else []
|
||||
prefix = str(merged_vars.get("releasePrefix") or "")
|
||||
suffix = str(merged_vars.get("releaseSuffix") or "")
|
||||
if prefix or suffix:
|
||||
tag = next(
|
||||
(
|
||||
t
|
||||
for t in tags
|
||||
if t.startswith(prefix) and t.endswith(suffix)
|
||||
),
|
||||
None,
|
||||
)
|
||||
else:
|
||||
tag = tags[0] if tags else None
|
||||
if tag:
|
||||
# Proton-cachyos style: extract base+release from tag
|
||||
mid = tag
|
||||
if prefix and mid.startswith(prefix):
|
||||
mid = mid[len(prefix) :]
|
||||
if suffix and mid.endswith(suffix):
|
||||
mid = mid[: -len(suffix)]
|
||||
parts = mid.split("-")
|
||||
if (
|
||||
len(parts) >= 2
|
||||
and "base" in merged_vars
|
||||
and "release" in merged_vars
|
||||
):
|
||||
lib.eprint(
|
||||
f" [{name}] latest tag: {tag} (base={parts[0]}, release={parts[-1]})"
|
||||
)
|
||||
vs = target_dict.setdefault("variables", {})
|
||||
vs["base"] = parts[0]
|
||||
vs["release"] = parts[-1]
|
||||
changed = True
|
||||
merged_vars2, merged_srcs2, _ = lib.merged_view(
|
||||
spec, variant
|
||||
)
|
||||
view2 = merged_srcs2.get(name, view_comp)
|
||||
sri = lib.prefetch_source(view2, merged_vars2)
|
||||
if sri:
|
||||
comp["hash"] = sri
|
||||
lib.eprint(f" [{name}] hash -> {sri}")
|
||||
changed = True
|
||||
else:
|
||||
new_ver = tag
|
||||
tag = None # avoid fall-through
|
||||
|
||||
elif kind == "openvsx":
|
||||
publisher = url_info.get("publisher", "")
|
||||
ext_name = url_info.get("ext_name", "")
|
||||
new_ver = lib.openvsx_latest_version(publisher, ext_name)
|
||||
|
||||
elif kind == "plain":
|
||||
lib.eprint(
|
||||
f" [{name}] url (plain): cannot auto-detect version; use --set"
|
||||
)
|
||||
|
||||
if new_ver:
|
||||
lib.eprint(f" [{name}] latest version: {new_ver}")
|
||||
vs = target_dict.setdefault("variables", {})
|
||||
vs[version_var] = new_ver
|
||||
changed = True
|
||||
if args.prefetch:
|
||||
# Re-render with updated variable
|
||||
merged_vars2, merged_srcs2, _ = lib.merged_view(spec, variant)
|
||||
view2 = merged_srcs2.get(name, view_comp)
|
||||
sri = lib.prefetch_source(view2, merged_vars2)
|
||||
if sri:
|
||||
comp["hash"] = sri
|
||||
lib.eprint(f" [{name}] hash -> {sri}")
|
||||
changed = True
|
||||
|
||||
elif args.url_prefetch or args.prefetch:
|
||||
rendered = lib.render(view_comp, merged_vars)
|
||||
url = rendered.get("url") or rendered.get("urlTemplate") or ""
|
||||
if not url:
|
||||
lib.eprint(f" [{name}] no url/urlTemplate for url fetcher")
|
||||
else:
|
||||
sri = lib.prefetch_source(view_comp, merged_vars)
|
||||
if sri:
|
||||
comp["hash"] = sri
|
||||
lib.eprint(f" [{name}] hash -> {sri}")
|
||||
changed = True
|
||||
|
||||
elif fetcher == "pypi":
|
||||
if args.latest_version:
|
||||
pkg_name = view_comp.get("name") or str(merged_vars.get("name") or name)
|
||||
new_ver = lib.pypi_latest_version(pkg_name)
|
||||
if new_ver:
|
||||
version_var = (
|
||||
lib._url_source_info(view_comp, merged_vars).get("version_var")
|
||||
or "version"
|
||||
)
|
||||
cur_ver = str(merged_vars.get(version_var) or "")
|
||||
if new_ver == cur_ver:
|
||||
lib.eprint(f" [{name}] pypi: already at {new_ver}")
|
||||
else:
|
||||
lib.eprint(f" [{name}] pypi: {cur_ver} -> {new_ver}")
|
||||
vs = target_dict.setdefault("variables", {})
|
||||
vs[version_var] = new_ver
|
||||
changed = True
|
||||
if args.prefetch:
|
||||
sri = lib.pypi_hash(pkg_name, new_ver)
|
||||
if sri:
|
||||
comp["hash"] = sri
|
||||
lib.eprint(f" [{name}] hash -> {sri}")
|
||||
changed = True
|
||||
else:
|
||||
lib.eprint(f" [{name}] pypi hash prefetch failed")
|
||||
else:
|
||||
lib.eprint(
|
||||
f" [{name}] pypi: could not fetch latest version for {pkg_name!r}"
|
||||
)
|
||||
elif args.url_prefetch or args.prefetch:
|
||||
lib.eprint(
|
||||
f" [{name}] pypi: use --latest-version --prefetch to update hash"
|
||||
)
|
||||
|
||||
return changed
|
||||
|
||||
|
||||
def main() -> int:
|
||||
ap = argparse.ArgumentParser(
|
||||
description="Update version.json files",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog=__doc__.split("\n", 2)[2], # show the usage block as epilog
|
||||
)
|
||||
ap.add_argument(
|
||||
"--file", required=True, metavar="PATH", help="Path to version.json"
|
||||
)
|
||||
ap.add_argument(
|
||||
"--variant", metavar="NAME", help="Variant to target (default: base)"
|
||||
)
|
||||
ap.add_argument(
|
||||
"--component",
|
||||
dest="components",
|
||||
action="append",
|
||||
metavar="NAME",
|
||||
help="Limit to specific component(s); can be repeated",
|
||||
)
|
||||
ap.add_argument(
|
||||
"--github-latest-release",
|
||||
action="store_true",
|
||||
help="Update GitHub sources to latest release tag",
|
||||
)
|
||||
ap.add_argument(
|
||||
"--github-latest-tag",
|
||||
action="store_true",
|
||||
help="Update GitHub sources to latest tag",
|
||||
)
|
||||
ap.add_argument(
|
||||
"--github-latest-commit",
|
||||
action="store_true",
|
||||
help="Update GitHub sources to HEAD commit",
|
||||
)
|
||||
ap.add_argument(
|
||||
"--tag-regex",
|
||||
metavar="REGEX",
|
||||
help="Filter tags (used with --github-latest-tag)",
|
||||
)
|
||||
ap.add_argument(
|
||||
"--set-branch",
|
||||
metavar="BRANCH",
|
||||
default=None,
|
||||
help=(
|
||||
"Set the branch field on github/git sources, resolve its HEAD commit, "
|
||||
"and (with --prefetch) recompute the hash. "
|
||||
"Pass an empty string ('') to clear the branch and switch back to tag/release tracking."
|
||||
),
|
||||
)
|
||||
ap.add_argument(
|
||||
"--git-latest",
|
||||
action="store_true",
|
||||
help="Update fetchgit sources to latest HEAD commit",
|
||||
)
|
||||
ap.add_argument(
|
||||
"--latest-version",
|
||||
action="store_true",
|
||||
help=(
|
||||
"Fetch the latest version from upstream (PyPI, Open VSX, GitHub releases) "
|
||||
"and update the version variable. Use with --prefetch to also recompute the hash."
|
||||
),
|
||||
)
|
||||
ap.add_argument(
|
||||
"--url-prefetch",
|
||||
action="store_true",
|
||||
help="Recompute hash for url/urlTemplate sources",
|
||||
)
|
||||
ap.add_argument(
|
||||
"--prefetch",
|
||||
action="store_true",
|
||||
help="After updating ref, also recompute hash",
|
||||
)
|
||||
ap.add_argument(
|
||||
"--set",
|
||||
dest="sets",
|
||||
action="append",
|
||||
default=[],
|
||||
metavar="KEY=VALUE",
|
||||
help="Set a field (dot-path relative to base or --variant). Can be repeated.",
|
||||
)
|
||||
ap.add_argument(
|
||||
"--dry-run", action="store_true", help="Show changes without writing"
|
||||
)
|
||||
ap.add_argument(
|
||||
"--print",
|
||||
dest="do_print",
|
||||
action="store_true",
|
||||
help="Print resulting JSON to stdout",
|
||||
)
|
||||
args = ap.parse_args()
|
||||
|
||||
path = Path(args.file)
|
||||
if not path.exists():
|
||||
lib.eprint(f"File not found: {path}")
|
||||
return 1
|
||||
|
||||
spec = lib.load_json(path)
|
||||
lib.eprint(f"Loaded: {path}")
|
||||
|
||||
# Apply --set mutations
|
||||
target = spec
|
||||
if args.variant:
|
||||
target = spec.setdefault("variants", {}).setdefault(args.variant, {})
|
||||
changed = _apply_set_pairs(target, args.sets)
|
||||
|
||||
# Update refs/hashes
|
||||
if update_components(spec, args.variant, args.components, args):
|
||||
changed = True
|
||||
|
||||
if changed:
|
||||
if args.dry_run:
|
||||
lib.eprint("Dry run: no changes written.")
|
||||
else:
|
||||
lib.save_json(path, spec)
|
||||
lib.eprint(f"Saved: {path}")
|
||||
else:
|
||||
lib.eprint("No changes.")
|
||||
|
||||
if args.do_print:
|
||||
import json
|
||||
|
||||
print(json.dumps(spec, indent=2, ensure_ascii=False))
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
sys.exit(main())
|
||||
except KeyboardInterrupt:
|
||||
sys.exit(130)
|
||||
Reference in New Issue
Block a user