"""Write the short hash of the commit this build came from to BUILD_STAMP. Python rather than bash, and standard library only. Stock Windows has no bash and none of the coreutils the shell version reached for, so a shell entry point made the plugin uninstallable there -- for adopters who are not on this Mac, that is the whole install, not a rough edge. Why a stamp and not the manifest version: Cowork caches an uploaded plugin, and plugin.json's version does not change between milestones, so a stale build would echo the right number and every answer after it would be about some other build (risk H11). The short hash moves on every commit, which is exactly the property the check needs. The stamp is a build artefact and is gitignored. It is regenerated by scripts/package_plugin.py before every archive; a committed stamp would be false the instant the next commit moved HEAD. Usage: python3 scripts/build_stamp.py # write /BUILD_STAMP python3 scripts/build_stamp.py --ut # write somewhere else On Windows the interpreter is normally called `python`, not `python3`. """ import os import subprocess import sys SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) REPO_ROOT = os.path.dirname(SCRIPT_DIR) def parse_args(argv): """Return the output path, or exit the way the shell version exited. Kept as a function so the argument handling is reachable from a test without starting a subprocess for every case. """ ut = os.path.join(REPO_ROOT, "BUILD_STAMP") i = 0 while i < len(argv): arg = argv[i] if arg == "--ut": if i + 1 >= len(argv): sys.stderr.write("build_stamp: --ut needs a path\n") raise SystemExit(2) ut = argv[i + 1] i += 2 elif arg in ("-h", "--help"): sys.stdout.write(__doc__) raise SystemExit(0) else: sys.stderr.write("build_stamp: unknown argument: %s\n" % arg) raise SystemExit(2) return ut def git(repo, *args): """Run git in ``repo`` and return (returncode, stdout).""" kjort = subprocess.run( ["git", "-C", repo] + list(args), stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, ) return kjort.returncode, kjort.stdout.strip() def main(argv): ut = parse_args(argv) kode, _ = git(REPO_ROOT, "rev-parse", "--git-dir") if kode != 0: sys.stderr.write("build_stamp: %s is not a git working tree.\n" % REPO_ROOT) sys.stderr.write( "build_stamp: the stamp is the commit this build came from; " "there is nothing to stamp.\n" ) return 1 kode, stempel = git(REPO_ROOT, "rev-parse", "--short", "HEAD") if kode != 0: sys.stderr.write("build_stamp: git rev-parse --short HEAD failed.\n") return 1 # Newline and nothing else: the skills read this file and echo it. with open(ut, "w", encoding="utf-8", newline="\n") as handle: handle.write(stempel + "\n") sys.stdout.write("build_stamp: %s -> %s\n" % (stempel, ut)) return 0 if __name__ == "__main__": sys.exit(main(sys.argv[1:]))