at master 2.8 kB view raw
1import argparse 2from functools import partial 3import json 4from multiprocessing import Pool 5import os 6from pathlib import Path 7import subprocess 8 9 10def dropPrefix(path, nixPrefix): 11 return path[len(nixPrefix + "/") :] 12 13 14def processItem( 15 item, nixPrefix, outDir, compression, compressionCommand, compressionExtension 16): 17 narInfoHash = dropPrefix(item["path"], nixPrefix).split("-")[0] 18 19 narFile = outDir / "nar" / f"{narInfoHash}.nar{compressionExtension}" 20 with open(narFile, "wb") as f: 21 subprocess.run( 22 f"nix-store --dump {item['path']} {compressionCommand}", 23 stdout=f, 24 shell=True, 25 check=True, 26 ) 27 28 fileHash = ( 29 subprocess.run( 30 ["nix-hash", "--base32", "--type", "sha256", "--flat", narFile], 31 capture_output=True, 32 check=True, 33 ) 34 .stdout.decode() 35 .strip() 36 ) 37 fileSize = os.path.getsize(narFile) 38 39 finalNarFileName = Path("nar") / f"{fileHash}.nar{compressionExtension}" 40 os.rename(narFile, outDir / finalNarFileName) 41 42 with open(outDir / f"{narInfoHash}.narinfo", "wt") as f: 43 f.write(f"StorePath: {item['path']}\n") 44 f.write(f"URL: {finalNarFileName}\n") 45 f.write(f"Compression: {compression}\n") 46 f.write(f"FileHash: sha256:{fileHash}\n") 47 f.write(f"FileSize: {fileSize}\n") 48 f.write(f"NarHash: {item['narHash']}\n") 49 f.write(f"NarSize: {item['narSize']}\n") 50 f.write( 51 f"References: {' '.join(dropPrefix(ref, nixPrefix) for ref in item['references'])}\n" 52 ) 53 54 55def main(): 56 parser = argparse.ArgumentParser() 57 parser.add_argument("--compression", choices=["none", "xz", "zstd"]) 58 args = parser.parse_args() 59 60 compressionCommand = { 61 "none": "", 62 "xz": "| xz -c", 63 "zstd": "| zstd", 64 }[args.compression] 65 66 compressionExtension = { 67 "none": "", 68 "xz": ".xz", 69 "zstd": ".zst", 70 }[args.compression] 71 72 outDir = Path(os.environ["out"]) 73 nixPrefix = os.environ["NIX_STORE"] 74 numWorkers = int(os.environ.get("NIX_BUILD_CORES", "4")) 75 76 with open(os.environ["NIX_ATTRS_JSON_FILE"], "r") as f: 77 closures = json.load(f)["closure"] 78 79 os.makedirs(outDir / "nar", exist_ok=True) 80 81 with open(outDir / "nix-cache-info", "w") as f: 82 f.write(f"StoreDir: {nixPrefix}\n") 83 84 with Pool(processes=numWorkers) as pool: 85 worker = partial( 86 processItem, 87 nixPrefix=nixPrefix, 88 outDir=outDir, 89 compression=args.compression, 90 compressionCommand=compressionCommand, 91 compressionExtension=compressionExtension, 92 ) 93 pool.map(worker, closures) 94 95 96if __name__ == "__main__": 97 main()