···11{ fetchFromGitHub, sourceData }:
2233-# Using fetchFromGitHub from their mirror because it's a lot faster than their git server
44-# If you want you could fetchgit from "https://git.FreeBSD.org/src.git" instead.
33+# Using fetchFromGitHub from their mirror because we cannot use git during bootstrap
44+# If you want you could fetchurl from "https://cgit.FreeBSD.org/src" instead.
55# The update script still pulls directly from git.freebsd.org
66+# Note that hashes with `forceFetchGit = true` may be different due to `export-ignore`
77+# directives in gitattributes files.
68fetchFromGitHub {
79 owner = "freebsd";
810 repo = "freebsd-src";
911 inherit (sourceData) rev hash;
1010-1111- # The GitHub export excludes some files in the git source
1212- # that were marked `export-ignore`.
1313- # A normal git checkout will keep those files,
1414- # matching the update script
1515- forceFetchGit = true;
1612}
+28-33
pkgs/os-specific/bsd/freebsd/update.py
···1111import re
1212import subprocess
1313import sys
1414+import tarfile
1415import tempfile
1516import typing
1617import urllib.request
17181819_QUERY_VERSION_PATTERN = re.compile('^([A-Z]+)="(.+)"$')
1919-_RELEASE_PATCH_PATTERN = re.compile('^RELEASE-p([0-9]+)$')
2020+_RELEASE_PATCH_PATTERN = re.compile("^RELEASE-p([0-9]+)$")
2021BASE_DIR = os.path.dirname(os.path.abspath(__file__))
2122MIN_VERSION = packaging.version.Version("13.0.0")
2223MAIN_BRANCH = "main"
···32333334def request_supported_refs() -> list[str]:
3435 # Looks pretty shady but I think this should work with every version of the page in the last 20 years
3535- r = re.compile("^h\d$", re.IGNORECASE)
3636+ r = re.compile(r"^h\d$", re.IGNORECASE)
3637 soup = bs4.BeautifulSoup(
3738 urllib.request.urlopen("https://www.freebsd.org/security"), features="lxml"
3839 )
···4546 return list(df["Branch"])
464747484848-def query_version(repo: git.Repo) -> dict[str, typing.Any]:
4949+def query_version(work_dir: str) -> dict[str, typing.Any]:
4950 # This only works on FreeBSD 13 and later
5051 text = (
5152 subprocess.check_output(
5252- ["bash", os.path.join(repo.working_dir, "sys", "conf", "newvers.sh"), "-v"]
5353+ ["bash", os.path.join(work_dir, "sys", "conf", "newvers.sh"), "-v"]
5354 )
5455 .decode("utf-8")
5556 .strip()
···8687 print(f"{ref_name}: revision still {rev.hexsha}, skipping")
8788 return old_versions[ref_name]
88898989- repo.git.checkout(rev)
9090- print(f"{ref_name}: checked out {rev.hexsha}")
9090+ tar_content = io.BytesIO()
9191+ repo.archive(tar_content, rev, format="tar")
9292+ tar_content.seek(0)
9393+9494+ with tempfile.TemporaryDirectory(dir="/tmp") as work_dir:
9595+ file = tarfile.TarFile(fileobj=tar_content)
9696+ file.extractall(path=work_dir, filter="data")
91979292- full_hash = (
9393- subprocess.check_output(["nix", "hash", "path", "--sri", repo.working_dir])
9494- .decode("utf-8")
9595- .strip()
9696- )
9797- print(f"{ref_name}: hash is {full_hash}")
9898+ full_hash = (
9999+ subprocess.check_output(["nix", "hash", "path", "--sri", work_dir])
100100+ .decode("utf-8")
101101+ .strip()
102102+ )
103103+ print(f"{ref_name}: hash is {full_hash}")
981049999- version = query_version(repo)
100100- print(f"{ref_name}: version is {version['version']}")
105105+ version = query_version(work_dir)
106106+ print(f"{ref_name}: version is {version['version']}")
101107102108 return {
103109 "rev": rev.hexsha,
···115121 print(f"Selected temporary directory {temp_dir.name}")
116122117123 if len(sys.argv) >= 2:
118118- orig_repo = git.Repo(sys.argv[1])
119119- print(f"Fetching updates on {orig_repo.git_dir}")
120120- orig_repo.remote("origin").fetch()
124124+ repo = git.Repo(sys.argv[1])
125125+ print(f"Fetching updates on {repo.git_dir}")
126126+ repo.remote("origin").fetch()
121127 else:
122128 print("Cloning source repo")
123123- orig_repo = git.Repo.clone_from(
124124- "https://git.FreeBSD.org/src.git", to_path=os.path.join(temp_dir.name, "orig")
129129+ repo = git.Repo.clone_from(
130130+ "https://git.FreeBSD.org/src.git", to_path=temp_dir.name
125131 )
126132127133 supported_refs = request_supported_refs()
128134 print(f"Supported refs are: {' '.join(supported_refs)}")
129135130130- print("Doing git crimes, do not run `git worktree prune` until after script finishes!")
131131- workdir = os.path.join(temp_dir.name, "work")
132132- git.cmd.Git(orig_repo.git_dir).worktree("add", "--orphan", workdir)
133133-134134- # Have to create object before removing .git otherwise it will complain
135135- repo = git.Repo(workdir)
136136- repo.git.set_persistent_git_options(git_dir=repo.git_dir)
137137- # Remove so that nix hash doesn't see the file
138138- os.remove(os.path.join(workdir, ".git"))
139139-140140- print(f"Working in directory {repo.working_dir} with git directory {repo.git_dir}")
141141-136136+ print(f"git directory {repo.git_dir}")
142137143138 try:
144139 with open(os.path.join(BASE_DIR, "versions.json"), "r") as f:
···191186 )
192187 versions[fullname] = result
193188194194-195189 with open(os.path.join(BASE_DIR, "versions.json"), "w") as out:
196190 json.dump(versions, out, sort_keys=True, indent=2)
197191 out.write("\n")
198192199199-if __name__ == '__main__':
193193+194194+if __name__ == "__main__":
200195 main()