import argparse import json import pathlib import subprocess GET_INPUTS_CMD = [ "nix-instantiate", "--eval", "--json", # This parser is stupid, better provide it with pre-eaten stuff "--expr", "builtins.fromJSON (builtins.toJSON (import ./flake.nix).inputs)", ] def process_flake(flake_uri: pathlib.Path) -> None: # get full path flake_file = flake_uri / "flake.nix" if not flake_file.is_file(): msg = f"Flake not found: {flake_uri}" raise FileNotFoundError(msg) # import dependencies p = subprocess.run( GET_INPUTS_CMD, cwd=flake_uri, stdout=subprocess.PIPE, check=True ) deps = json.loads(p.stdout) # for each dependency for dep_name, dep in deps.items(): dep_url = dep["url"] # if not local path, continue if not dep_url.startswith(("path:", "git+file:")): continue if dep.get("flake", True): # get flake file corresponding dep_path = pathlib.Path(flake_uri, dep_url.split(":")[1]) process_flake(dep_path) # update lockfile cmd = [ "nix", "--extra-experimental-features", "nix-command", "--extra-experimental-features", "flakes", "flake", "update", dep_name, ] p = subprocess.run(cmd, cwd=flake_uri, check=True) if __name__ == "__main__": parser = argparse.ArgumentParser( description="Recursively update lockfiles " "of flakes located on the system" ) parser.add_argument("flake", help="Starting flake", type=pathlib.Path) args = parser.parse_args() process_flake(args.flake)