diff --git a/third_party/nixpkgs/patches/pr105296-factorio-updatescript.patch b/third_party/nixpkgs/patches/pr105296-factorio-updatescript.patch new file mode 100644 index 0000000000..f247e7c237 --- /dev/null +++ b/third_party/nixpkgs/patches/pr105296-factorio-updatescript.patch @@ -0,0 +1,449 @@ +From 2c8f7755d40dd1a77f99d766e1d23a3d4ddf67a1 Mon Sep 17 00:00:00 2001 +From: Luke Granger-Brown +Date: Sat, 28 Nov 2020 22:52:07 +0000 +Subject: [PATCH 1/2] factorio: add an updateScript + +The updateScript knows how to automatically fetch and update the version +data from the Factorio versions API (and update the hashes +appropriately), which makes it easier to update whenever experimental +does. +--- + pkgs/games/factorio/default.nix | 120 ++++++++++----------- + pkgs/games/factorio/update.py | 174 ++++++++++++++++++++++++++++++ + pkgs/games/factorio/versions.json | 58 ++++++++++ + 3 files changed, 286 insertions(+), 66 deletions(-) + create mode 100755 pkgs/games/factorio/update.py + create mode 100644 pkgs/games/factorio/versions.json + +diff --git a/pkgs/games/factorio/default.nix b/pkgs/games/factorio/default.nix +index f5f12b47dd72d..14e00380e8751 100644 +--- a/pkgs/games/factorio/default.nix ++++ b/pkgs/games/factorio/default.nix +@@ -13,6 +13,8 @@ assert releaseType == "alpha" + + let + ++ inherit (stdenv.lib) importJSON; ++ + helpMsg = '' + + ===FETCH FAILED=== +@@ -59,72 +61,54 @@ let + + # NB `experimental` directs us to take the latest build, regardless of its branch; + # hence the (stable, experimental) pairs may sometimes refer to the same distributable. +- binDists = { +- x86_64-linux = let bdist = bdistForArch { inUrl = "linux64"; inTar = "x64"; }; in { +- alpha = { +- stable = bdist { sha256 = "0zixscff0svpb0yg8nzczp2z4filqqxi1k0z0nrpzn2hhzhf1464"; version = "1.0.0"; withAuth = true; }; +- experimental = bdist { sha256 = "0cmia16d5dhy3f8mck926d7rrnavxmvb6a72ymjllxm37slsx60j"; version = "1.1.2"; withAuth = true; }; +- }; +- headless = { +- stable = bdist { sha256 = "0r0lplns8nxna2viv8qyx9mp4cckdvx6k20w2g2fwnj3jjmf3nc1"; version = "1.0.0"; }; +- experimental = bdist { sha256 = "0x3lwz11z8cczqr5i799m4yg8x3yk6h5qz48pfzw4l2ikrrwgahd"; version = "1.1.2"; }; +- }; +- demo = { +- stable = bdist { sha256 = "0h9cqbp143w47zcl4qg4skns4cngq0k40s5jwbk0wi5asjz8whqn"; version = "1.0.0"; }; +- }; +- }; +- i686-linux = let bdist = bdistForArch { inUrl = "linux32"; inTar = "i386"; }; in { +- alpha = { +- stable = bdist { sha256 = "0nnfkxxqnywx1z05xnndgh71gp4izmwdk026nnjih74m2k5j086l"; version = "0.14.23"; withAuth = true; nameMut = asGz; }; +- }; +- }; +- }; ++ versions = importJSON ./versions.json; ++ binDists = makeBinDists versions; + + actual = binDists.${stdenv.hostPlatform.system}.${releaseType}.${branch} or (throw "Factorio ${releaseType}-${branch} binaries for ${stdenv.hostPlatform.system} are not available for download."); + +- bdistForArch = arch: { version +- , sha256 +- , withAuth ? false +- , nameMut ? x: x +- }: +- let +- url = "https://factorio.com/get-download/${version}/${releaseType}/${arch.inUrl}"; +- name = nameMut "factorio_${releaseType}_${arch.inTar}-${version}.tar.xz"; +- in { +- inherit version arch; +- src = +- if withAuth then +- (stdenv.lib.overrideDerivation +- (fetchurl { +- inherit name url sha256; +- curlOpts = [ +- "--get" +- "--data-urlencode" "username@username" +- "--data-urlencode" "token@token" +- ]; +- }) +- (_: { # This preHook hides the credentials from /proc +- preHook = +- if username != "" && token != "" then '' +- echo -n "${username}" >username +- echo -n "${token}" >token +- '' else '' +- # Deliberately failing since username/token was not provided, so we can't fetch. +- # We can't use builtins.throw since we want the result to be used if the tar is in the store already. +- exit 1 +- ''; +- failureHook = '' +- cat <username ++ echo -n "${token}" >token ++ '' else '' ++ # Deliberately failing since username/token was not provided, so we can't fetch. ++ # We can't use builtins.throw since we want the result to be used if the tar is in the store already. ++ exit 1 ++ ''; ++ failureHook = '' ++ cat < str: ++ if FLAGS.out: ++ return out ++ try_paths = ["pkgs/games/factorio/versions.json", "versions.json"] ++ for path in try_paths: ++ if os.path.exists(path): ++ return path ++ raise Exception("Couldn't figure out where to write versions.json; try specifying --out") ++ ++ ++def fetch_versions() -> FactorioVersionsJSON: ++ return json.loads(requests.get("https://factorio.com/api/latest-releases").text) ++ ++ ++def generate_our_versions(factorio_versions: FactorioVersionsJSON) -> OurVersionJSON: ++ rec_dd = lambda: defaultdict(rec_dd) ++ output = rec_dd() ++ for system in SYSTEMS: ++ for release_type in RELEASE_TYPES: ++ for release_channel in RELEASE_CHANNELS: ++ version = factorio_versions[release_channel.name][release_type.name] ++ this_release = { ++ "name": f"factorio_{release_type.name}_{system.tar_name}-{version}.tar.xz", ++ "url": f"https://factorio.com/get-download/{version}/{release_type.name}/{system.url_name}", ++ "version": version, ++ "needsAuth": release_type.needs_auth, ++ "tarDirectory": system.tar_name, ++ } ++ output[system.nix_name][release_type.name][release_channel.name] = this_release ++ return output ++ ++ ++def iter_version(versions: OurVersionJSON, it: Callable[[str, str, str, Dict[str, str]], Dict[str, str]]) -> OurVersionJSON: ++ versions = copy.deepcopy(versions) ++ for system_name, system in versions.items(): ++ for release_type_name, release_type in system.items(): ++ for release_channel_name, release in release_type.items(): ++ release_type[release_channel_name] = it(system_name, release_type_name, release_channel_name, dict(release)) ++ return versions ++ ++ ++def merge_versions(old: OurVersionJSON, new: OurVersionJSON) -> OurVersionJSON: ++ """Copies already-known hashes from version.json to avoid having to re-fetch.""" ++ def _merge_version(system_name: str, release_type_name: str, release_channel_name: str, release: Dict[str, str]) -> Dict[str, str]: ++ old_system = old.get(system_name, {}) ++ old_release_type = old_system.get(release_type_name, {}) ++ old_release = old_release_type.get(release_channel_name, {}) ++ if not "sha256" in old_release: ++ logging.info("%s/%s/%s: not copying sha256 since it's missing", system_name, release_type_name, release_channel_name) ++ return release ++ if not all(old_release.get(k, None) == release[k] for k in ['name', 'version', 'url']): ++ logging.info("%s/%s/%s: not copying sha256 due to mismatch", system_name, release_type_name, release_channel_name) ++ return release ++ release["sha256"] = old_release["sha256"] ++ return release ++ return iter_version(new, _merge_version) ++ ++ ++def nix_prefetch_url(name: str, url: str, algo: str = 'sha256') -> str: ++ cmd = ['nix-prefetch-url', '--type', algo, '--name', name, url] ++ logging.info('running %s', cmd) ++ out = subprocess.check_output(cmd) ++ return out.decode('utf-8').strip() ++ ++ ++def fill_in_hash(versions: OurVersionJSON) -> OurVersionJSON: ++ """Fill in sha256 hashes for anything missing them.""" ++ urls_to_hash = {} ++ def _fill_in_hash(system_name: str, release_type_name: str, release_channel_name: str, release: Dict[str, str]) -> Dict[str, str]: ++ if "sha256" in release: ++ logging.info("%s/%s/%s: skipping fetch, sha256 already present", system_name, release_type_name, release_channel_name) ++ return release ++ url = release["url"] ++ if url in urls_to_hash: ++ logging.info("%s/%s/%s: found url %s in cache", system_name, release_type_name, release_channel_name, url) ++ release["sha256"] = urls_to_hash[url] ++ return release ++ logging.info("%s/%s/%s: fetching %s", system_name, release_type_name, release_channel_name, url) ++ if release["needsAuth"]: ++ if not FLAGS.username or not FLAGS.token: ++ raise Exception("fetching %s/%s/%s from %s requires --username and --token" % (system_name, release_type_name, release_channel_name, url)) ++ url += f"?username={FLAGS.username}&token={FLAGS.token}" ++ release["sha256"] = nix_prefetch_url(release["name"], url) ++ urls_to_hash[url] = release["sha256"] ++ return release ++ return iter_version(versions, _fill_in_hash) ++ ++ ++def main(argv): ++ factorio_versions = fetch_versions() ++ new_our_versions = generate_our_versions(factorio_versions) ++ old_our_versions = None ++ our_versions_path = find_versions_json() ++ if our_versions_path: ++ logging.info('Loading old versions.json from %s', our_versions_path) ++ with open(our_versions_path, 'r') as f: ++ old_our_versions = json.load(f) ++ if old_our_versions: ++ logging.info('Merging in old hashes') ++ new_our_versions = merge_versions(old_our_versions, new_our_versions) ++ logging.info('Fetching necessary tars to get hashes') ++ new_our_versions = fill_in_hash(new_our_versions) ++ with open(our_versions_path, 'w') as f: ++ logging.info('Writing versions.json to %s', our_versions_path) ++ json.dump(new_our_versions, f, sort_keys=True, indent=2) ++ f.write("\n") ++ ++if __name__ == '__main__': ++ app.run(main) +diff --git a/pkgs/games/factorio/versions.json b/pkgs/games/factorio/versions.json +new file mode 100644 +index 0000000000000..82ab40ec3cbe5 +--- /dev/null ++++ b/pkgs/games/factorio/versions.json +@@ -0,0 +1,58 @@ ++{ ++ "x86_64-linux": { ++ "alpha": { ++ "experimental": { ++ "name": "factorio_alpha_x64-1.1.2.tar.xz", ++ "needsAuth": true, ++ "sha256": "0cmia16d5dhy3f8mck926d7rrnavxmvb6a72ymjllxm37slsx60j", ++ "tarDirectory": "x64", ++ "url": "https://factorio.com/get-download/1.1.2/alpha/linux64", ++ "version": "1.1.2" ++ }, ++ "stable": { ++ "name": "factorio_alpha_x64-1.0.0.tar.xz", ++ "needsAuth": true, ++ "sha256": "0zixscff0svpb0yg8nzczp2z4filqqxi1k0z0nrpzn2hhzhf1464", ++ "tarDirectory": "x64", ++ "url": "https://factorio.com/get-download/1.0.0/alpha/linux64", ++ "version": "1.0.0" ++ } ++ }, ++ "demo": { ++ "experimental": { ++ "name": "factorio_demo_x64-1.0.0.tar.xz", ++ "needsAuth": false, ++ "sha256": "0h9cqbp143w47zcl4qg4skns4cngq0k40s5jwbk0wi5asjz8whqn", ++ "tarDirectory": "x64", ++ "url": "https://factorio.com/get-download/1.0.0/demo/linux64", ++ "version": "1.0.0" ++ }, ++ "stable": { ++ "name": "factorio_demo_x64-1.0.0.tar.xz", ++ "needsAuth": false, ++ "sha256": "0h9cqbp143w47zcl4qg4skns4cngq0k40s5jwbk0wi5asjz8whqn", ++ "tarDirectory": "x64", ++ "url": "https://factorio.com/get-download/1.0.0/demo/linux64", ++ "version": "1.0.0" ++ } ++ }, ++ "headless": { ++ "experimental": { ++ "name": "factorio_headless_x64-1.1.2.tar.xz", ++ "needsAuth": false, ++ "sha256": "0x3lwz11z8cczqr5i799m4yg8x3yk6h5qz48pfzw4l2ikrrwgahd", ++ "tarDirectory": "x64", ++ "url": "https://factorio.com/get-download/1.1.2/headless/linux64", ++ "version": "1.1.2" ++ }, ++ "stable": { ++ "name": "factorio_headless_x64-1.0.0.tar.xz", ++ "needsAuth": false, ++ "sha256": "0r0lplns8nxna2viv8qyx9mp4cckdvx6k20w2g2fwnj3jjmf3nc1", ++ "tarDirectory": "x64", ++ "url": "https://factorio.com/get-download/1.0.0/headless/linux64", ++ "version": "1.0.0" ++ } ++ } ++ } ++} + +From 8a63eaab52abc1ffe065f0c9f93eeedaae7a487b Mon Sep 17 00:00:00 2001 +From: Luke Granger-Brown +Date: Sat, 28 Nov 2020 22:53:22 +0000 +Subject: [PATCH 2/2] factorio: add lukegb as maintainer + +--- + pkgs/games/factorio/default.nix | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pkgs/games/factorio/default.nix b/pkgs/games/factorio/default.nix +index 14e00380e8751..4535f31f26237 100644 +--- a/pkgs/games/factorio/default.nix ++++ b/pkgs/games/factorio/default.nix +@@ -169,7 +169,7 @@ let + ''; + homepage = "https://www.factorio.com/"; + license = stdenv.lib.licenses.unfree; +- maintainers = with stdenv.lib.maintainers; [ Baughn elitak erictapen priegger ]; ++ maintainers = with stdenv.lib.maintainers; [ Baughn elitak erictapen priegger lukegb ]; + platforms = [ "x86_64-linux" ]; + }; + }; diff --git a/third_party/nixpkgs/patches/pr105471-factorio-bump-1.1.3.patch b/third_party/nixpkgs/patches/pr105471-factorio-bump-1.1.3.patch new file mode 100644 index 0000000000..3fa2099a06 --- /dev/null +++ b/third_party/nixpkgs/patches/pr105471-factorio-bump-1.1.3.patch @@ -0,0 +1,48 @@ +From e555cb3a33b778227c60587eb66c538403bf9cf9 Mon Sep 17 00:00:00 2001 +From: Luke Granger-Brown +Date: Mon, 30 Nov 2020 18:03:14 +0000 +Subject: [PATCH] factorio-experimental, factorio-headless-experimental: 1.1.2 + -> 1.1.3 + +--- + pkgs/games/factorio/versions.json | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/pkgs/games/factorio/versions.json b/pkgs/games/factorio/versions.json +index 82ab40ec3cbe5..a76f5abc14750 100644 +--- a/pkgs/games/factorio/versions.json ++++ b/pkgs/games/factorio/versions.json +@@ -2,12 +2,12 @@ + "x86_64-linux": { + "alpha": { + "experimental": { +- "name": "factorio_alpha_x64-1.1.2.tar.xz", ++ "name": "factorio_alpha_x64-1.1.3.tar.xz", + "needsAuth": true, +- "sha256": "0cmia16d5dhy3f8mck926d7rrnavxmvb6a72ymjllxm37slsx60j", ++ "sha256": "0lsgj7361bf9zhidp4hpdhb9jj7wgcw7s0q5bpqbigbnz848m3lm", + "tarDirectory": "x64", +- "url": "https://factorio.com/get-download/1.1.2/alpha/linux64", +- "version": "1.1.2" ++ "url": "https://factorio.com/get-download/1.1.3/alpha/linux64", ++ "version": "1.1.3" + }, + "stable": { + "name": "factorio_alpha_x64-1.0.0.tar.xz", +@@ -38,12 +38,12 @@ + }, + "headless": { + "experimental": { +- "name": "factorio_headless_x64-1.1.2.tar.xz", ++ "name": "factorio_headless_x64-1.1.3.tar.xz", + "needsAuth": false, +- "sha256": "0x3lwz11z8cczqr5i799m4yg8x3yk6h5qz48pfzw4l2ikrrwgahd", ++ "sha256": "1164hbbd1b33hjnvjm079czjypj837gpjp2i4f23rkd4qmjpl0dj", + "tarDirectory": "x64", +- "url": "https://factorio.com/get-download/1.1.2/headless/linux64", +- "version": "1.1.2" ++ "url": "https://factorio.com/get-download/1.1.3/headless/linux64", ++ "version": "1.1.3" + }, + "stable": { + "name": "factorio_headless_x64-1.0.0.tar.xz", diff --git a/third_party/nixpkgs/patches/series b/third_party/nixpkgs/patches/series index e313c2530e..25dc8039bf 100644 --- a/third_party/nixpkgs/patches/series +++ b/third_party/nixpkgs/patches/series @@ -2,3 +2,5 @@ pr102855-zram-allow-memorymax.patch pr103084-teamspeak3-bump-3.5.6.patch pr104891-factorio-bump-1.1.1.patch pr105231-factorio-bump-1.1.2.patch +pr105296-factorio-updatescript.patch +pr105471-factorio-bump-1.1.3.patch