Change:
with open("dub.selections.json") as f: selectionsJson = json.load(f) <del> versionDict: dict[str, str] = selectionsJson["versions"] </del> <ins> depsDict: dict = selectionsJson["versions"] # For each dependency expand non-expanded version into a dict with a "version" key depsDict = {pname: (versionOrDepDict if isinstance(versionOrDepDict, dict) else {"version": versionOrDepDict}) for (pname, versionOrDepDict) in depsDict.items()} # Don't process path-type selections depsDict = {pname: depDict for (pname, depDict) in depsDict.items() if "path" not in depDict} </ins> <del> for pname in versionDict: version = versionDict[pname] </del> <ins> # Pre-validate selections before trying to fetch for pname in depsDict: depDict = depsDict[pname] version = depDict["version"] </ins> if version.startswith("~"): <del> eprint(f'Package "{pname}" has a branch-type version "{version}", which doesn't point to a fixed version') eprint("You can resolve it by manually changing the required version to a fixed one inside `dub.selections.json`") eprint("When packaging, you might need to create a patch for `dub.sdl` or `dub.json` to accept the changed version") </del> <ins> eprint(f'Expected version of "{pname}" to be non-branch type') eprint(f'Found: "{version}"') eprint("Please specify a non-branch version inside `dub.selections.json`") eprint("When packaging, you might also need to patch the version value in the appropriate places (`dub.selections.json`, dub.sdl`, `dub.json`)") </ins> sys.exit(1) <ins> if "repository" in depDict: repository = depDict["repository"] if not repository.startswith("git+"): eprint(f'Expected repository field of "{pname}" to begin with "git+"') eprint(f'Found: "{repository}"') sys.exit(1) if (len(version) < 7 or len(version) > 40 or not all(c in string.hexdigits for c in version)): eprint(f'Expected version field of "{pname}" to begin be a valid git revision') eprint(f'Found: "{version}"') sys.exit(1) </ins> <del> lockedDependenciesDict: dict[str, dict[str, str]] = {} </del> <ins> lockedDepsDict: dict[str, dict[str, str]] = {} </ins> <del> for pname in versionDict: version = versionDict[pname] eprint(f"Fetching {pname}@{version}") url = f"https://code.dlang.org/packages/{pname}/{version}.zip" command = ["nix-prefetch-url", "--type", "sha256", url] sha256 = subprocess.run(command, check=True, text=True, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout.rstrip() lockedDependenciesDict[pname] = {"version": version, "sha256": sha256} </del> <ins> for pname in depsDict: depDict = depsDict[pname] version = depDict["version"] if "repository" in depDict: repository = depDict["repository"] strippedRepo = repository[4:] eprint(f"Fetching {pname}@{version} ({strippedRepo})") command = ["nix-prefetch-git", strippedRepo, version] rawRes = subprocess.run(command, check=True, text=True, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout sha256 = json.loads(rawRes)["sha256"] lockedDepsDict[pname] = {"version": version, "repository": repository, "sha256": sha256} else: eprint(f"Fetching {pname}@{version}") url = f"https://code.dlang.org/packages/{pname}/{version}.zip" command = ["nix-prefetch-url", "--type", "sha256", url] sha256 = subprocess.run(command, check=True, text=True, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout.rstrip() lockedDepsDict[pname] = {"version": version, "sha256": sha256} </ins> <del> print(json.dumps({"dependencies": lockedDependenciesDict}, indent=2)) </del> <ins> print(json.dumps({"dependencies": lockedDepsDict}, indent=2)) </ins>

Discussion:
fails to build a lockfile with dependencies in the format (). Here's the error: any repository whose contains a dependency that fetches from Git, e.g. , e.g. . a few moments, then see error. A generated lockfile containing the Git dependency. If applicable, add screenshots to help explain your problem. Add any other context about the problem here. Please run and paste the result. Add a :+1: [reaction] to [issues you find important]. [reaction]: [issues you find important]:
Thanks for reporting this bug, I'll try to extend the lockfile logic later today, (the current one is pretty primitive, as you might have seen)