about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSandro <sandro.jaeckel@gmail.com>2024-03-11 14:00:16 +0100
committerGitHub <noreply@github.com>2024-03-11 14:00:16 +0100
commitd3563eab3b02a62902d8244e02b4c55c507e3b00 (patch)
treeb437f7b448767cd9213a3c1817227928df98d370
parent921495ab81e57e5ee315c37abd0a4e9235236d12 (diff)
parentef321a0ed68ccc8b0babaca977303ff5528e8fa5 (diff)
downloadnixlib-d3563eab3b02a62902d8244e02b4c55c507e3b00.tar
nixlib-d3563eab3b02a62902d8244e02b4c55c507e3b00.tar.gz
nixlib-d3563eab3b02a62902d8244e02b4c55c507e3b00.tar.bz2
nixlib-d3563eab3b02a62902d8244e02b4c55c507e3b00.tar.lz
nixlib-d3563eab3b02a62902d8244e02b4c55c507e3b00.tar.xz
nixlib-d3563eab3b02a62902d8244e02b4c55c507e3b00.tar.zst
nixlib-d3563eab3b02a62902d8244e02b4c55c507e3b00.zip
Merge pull request #276292 from MayNiklas/papermc-multi-version
-rw-r--r--pkgs/games/papermc/default.nix63
-rw-r--r--pkgs/games/papermc/derivation.nix50
-rwxr-xr-xpkgs/games/papermc/update.py145
-rw-r--r--pkgs/games/papermc/versions.json50
-rw-r--r--pkgs/top-level/all-packages.nix4
5 files changed, 262 insertions, 50 deletions
diff --git a/pkgs/games/papermc/default.nix b/pkgs/games/papermc/default.nix
index aa16e51a7ac8..29d5c6b85203 100644
--- a/pkgs/games/papermc/default.nix
+++ b/pkgs/games/papermc/default.nix
@@ -1,50 +1,15 @@
-{
-  lib,
-  stdenvNoCC,
-  fetchurl,
-  jre,
-  makeBinaryWrapper,
-}:
-stdenvNoCC.mkDerivation (finalAttrs: {
-  pname = "papermc";
-  version = "1.20.4.435";
-
-  src =
-    let
-      mcVersion = lib.versions.pad 3 finalAttrs.version;
-      buildNum = builtins.elemAt (lib.splitVersion finalAttrs.version) 3;
-    in
-    fetchurl {
-      url = "https://papermc.io/api/v2/projects/paper/versions/${mcVersion}/builds/${buildNum}/downloads/paper-${mcVersion}-${buildNum}.jar";
-      hash = "sha256-NrIsYLoAAWORw/S26NDFjYBVwpNITJxuWGZow3696wM=";
-    };
-
-  installPhase = ''
-    runHook preInstall
-
-    install -D $src $out/share/papermc/papermc.jar
-
-    makeWrapper ${lib.getExe jre} "$out/bin/minecraft-server" \
-      --append-flags "-jar $out/share/papermc/papermc.jar nogui"
-
-    runHook postInstall
-  '';
-
-  nativeBuildInputs = [
-    makeBinaryWrapper
-  ];
-
-  dontUnpack = true;
-  preferLocalBuild = true;
-  allowSubstitutes = false;
-
-  meta = {
-    description = "High-performance Minecraft Server";
-    homepage = "https://papermc.io/";
-    sourceProvenance = with lib.sourceTypes; [ binaryBytecode ];
-    license = lib.licenses.gpl3Only;
-    platforms = lib.platforms.unix;
-    maintainers = with lib.maintainers; [ aaronjanse neonfuz ];
-    mainProgram = "minecraft-server";
-  };
+{ callPackage, lib, ... }:
+let
+  versions = lib.importJSON ./versions.json;
+  latestVersion = lib.last (builtins.sort lib.versionOlder (builtins.attrNames versions));
+  escapeVersion = builtins.replaceStrings [ "." ] [ "_" ];
+  packages = lib.mapAttrs'
+    (version: value: {
+      name = "papermc-${escapeVersion version}";
+      value = callPackage ./derivation.nix { inherit (value) version hash; };
+    })
+    versions;
+in
+lib.recurseIntoAttrs (packages // {
+  papermc = builtins.getAttr "papermc-${escapeVersion latestVersion}" packages;
 })
diff --git a/pkgs/games/papermc/derivation.nix b/pkgs/games/papermc/derivation.nix
new file mode 100644
index 000000000000..f244031f0590
--- /dev/null
+++ b/pkgs/games/papermc/derivation.nix
@@ -0,0 +1,50 @@
+{ lib, stdenvNoCC, fetchurl, makeBinaryWrapper, jre, version, hash }:
+
+stdenvNoCC.mkDerivation {
+  pname = "papermc";
+  inherit version;
+
+  src =
+    let
+      version-split = lib.strings.splitString "-" version;
+      mcVersion = builtins.elemAt version-split 0;
+      buildNum = builtins.elemAt version-split 1;
+    in
+    fetchurl {
+      url = "https://papermc.io/api/v2/projects/paper/versions/${mcVersion}/builds/${buildNum}/downloads/paper-${version}.jar";
+      inherit hash;
+    };
+
+  installPhase = ''
+    runHook preInstall
+
+    install -D $src $out/share/papermc/papermc.jar
+
+    makeWrapper ${lib.getExe jre} "$out/bin/minecraft-server" \
+      --append-flags "-jar $out/share/papermc/papermc.jar nogui"
+
+    runHook postInstall
+  '';
+
+  nativeBuildInputs = [
+    makeBinaryWrapper
+  ];
+
+  dontUnpack = true;
+  preferLocalBuild = true;
+  allowSubstitutes = false;
+
+  passthru = {
+    updateScript = ./update.py;
+  };
+
+  meta = {
+    description = "High-performance Minecraft Server";
+    homepage = "https://papermc.io/";
+    sourceProvenance = with lib.sourceTypes; [ binaryBytecode ];
+    license = lib.licenses.gpl3Only;
+    platforms = lib.platforms.unix;
+    maintainers = with lib.maintainers; [ aaronjanse neonfuz MayNiklas ];
+    mainProgram = "minecraft-server";
+  };
+}
diff --git a/pkgs/games/papermc/update.py b/pkgs/games/papermc/update.py
new file mode 100755
index 000000000000..6e2d0ec9274e
--- /dev/null
+++ b/pkgs/games/papermc/update.py
@@ -0,0 +1,145 @@
+#!/usr/bin/env nix-shell
+#! nix-shell -i python -p "python3.withPackages (ps: with ps; [ps.requests ])"
+
+import hashlib
+import base64
+import json
+
+import requests
+
+
+class Version:
+    def __init__(self, name: str):
+        self.name: str = name
+        self.hash: str | None = None
+        self.build_number: int | None = None
+
+    @property
+    def full_name(self):
+        v_name = f"{self.name}-{self.build_number}"
+
+        # this will probably never happen because the download of a build with NoneType in URL would fail
+        if not self.name or not self.build_number:
+            print(f"Warning: version '{v_name}' contains NoneType!")
+
+        return v_name
+
+
+class VersionManager:
+    def __init__(self, base_url: str = "https://api.papermc.io/v2/projects/paper"):
+        self.versions: list[Version] = []
+        self.base_url: str = base_url
+
+    def fetch_versions(self, not_before_minor_version: int = 18):
+        """
+        Fetch all versions after given minor release
+        """
+
+        response = requests.get(self.base_url)
+
+        try:
+            response.raise_for_status()
+
+        except requests.exceptions.HTTPError as e:
+            print(e)
+            return
+
+        # we only want versions that are no pre-releases
+        release_versions = filter(
+            lambda v_name: 'pre' not in v_name, response.json()["versions"])
+
+        for version_name in release_versions:
+
+            # split version string, convert to list ot int
+            version_split = version_name.split(".")
+            version_split = list(map(int, version_split))
+
+            # check if version is higher than 1.<not_before_sub_version>
+            if (version_split[0] > 1) or (version_split[0] == 1 and version_split[1] >= not_before_minor_version):
+                self.versions.append(Version(version_name))
+
+    def fetch_latest_version_builds(self):
+        """
+        Set latest build number to each version
+        """
+
+        for version in self.versions:
+            url = f"{self.base_url}/versions/{version.name}"
+            response = requests.get(url)
+
+            # check that we've got a good response
+            try:
+                response.raise_for_status()
+
+            except requests.exceptions.HTTPError as e:
+                print(e)
+                return
+
+            # the highest build in response.json()['builds']:
+            latest_build = response.json()['builds'][-1]
+            version.build_number = latest_build
+
+    def generate_version_hashes(self):
+        """
+        Generate and set the hashes for all registered versions (versions will are downloaded to memory)
+        """
+
+        for version in self.versions:
+            url = f"{self.base_url}/versions/{version.name}/builds/{version.build_number}/downloads/paper-{version.full_name}.jar"
+            version.hash = self.download_and_generate_sha256_hash(url)
+
+    def versions_to_json(self):
+        return json.dumps(
+            {version.name: {'hash': version.hash, 'version': version.full_name}
+                for version in self.versions},
+            indent=4
+        )
+
+    def write_versions(self, file_name: str):
+        """ write all processed versions to json """
+        # save json to versions.json
+        with open(file_name, 'w') as f:
+            f.write(self.versions_to_json() + "\n")
+
+    @staticmethod
+    def download_and_generate_sha256_hash(url: str) -> str | None:
+        """
+        Fetch the tarball from the given URL.
+        Then generate a sha256 hash of the tarball.
+        """
+
+        try:
+            # Download the file from the URL
+            response = requests.get(url)
+            response.raise_for_status()
+
+        except requests.exceptions.RequestException as e:
+            print(f"Error: {e}")
+            return None
+
+        # Create a new SHA-256 hash object
+        sha256_hash = hashlib.sha256()
+
+        # Update the hash object with chunks of the downloaded content
+        for byte_block in response.iter_content(4096):
+            sha256_hash.update(byte_block)
+
+        # Get the hexadecimal representation of the hash
+        hash_value = sha256_hash.digest()
+
+        # Encode the hash value in base64
+        base64_hash = base64.b64encode(hash_value).decode('utf-8')
+
+        # Format it as "sha256-{base64_hash}"
+        sri_representation = f"sha256-{base64_hash}"
+
+        return sri_representation
+
+
+if __name__ == '__main__':
+    version_manager = VersionManager()
+
+    version_manager.fetch_versions()
+    version_manager.fetch_latest_version_builds()
+    version_manager.generate_version_hashes()
+    version_manager.write_versions(file_name="versions.json")
diff --git a/pkgs/games/papermc/versions.json b/pkgs/games/papermc/versions.json
new file mode 100644
index 000000000000..0fa4bad8ba04
--- /dev/null
+++ b/pkgs/games/papermc/versions.json
@@ -0,0 +1,50 @@
+{
+    "1.18": {
+        "hash": "sha256-PJlfINrk5OIdVVT6yVegqKXIW9W/NJFfrEtPFuDvEBs=",
+        "version": "1.18-66"
+    },
+    "1.18.1": {
+        "hash": "sha256-qUkXpEcsLLyZB6FcZmu7eE+V7Ne1PHe8CP5xED5Uh/U=",
+        "version": "1.18.1-216"
+    },
+    "1.18.2": {
+        "hash": "sha256-BXjxj01jK0lLRo7FaztBS1tW/qCH7n05z23N9MnQHwU=",
+        "version": "1.18.2-388"
+    },
+    "1.19": {
+        "hash": "sha256-DTnKzFGneysHHhzoYvy/C0pL1mjMfosxNZjYT6Cfq6w=",
+        "version": "1.19-81"
+    },
+    "1.19.1": {
+        "hash": "sha256-Wv4jofreksVHEk+odLx9kI+mdvSfCYefqHYiS2Lp1Rs=",
+        "version": "1.19.1-111"
+    },
+    "1.19.2": {
+        "hash": "sha256-LrXHRZ7JS83Fl+1xHVSaOrSw/aE+QSoHkqGgabWQOGQ=",
+        "version": "1.19.2-307"
+    },
+    "1.19.3": {
+        "hash": "sha256-MAfyxjjV8E7TK2raozBT/jY0zPp0NFyD0+pJgtONtdw=",
+        "version": "1.19.3-448"
+    },
+    "1.19.4": {
+        "hash": "sha256-5YfXjLo+me+MS8JM8gzDvbvonjOwtXIHBEavTra+XM8=",
+        "version": "1.19.4-550"
+    },
+    "1.20": {
+        "hash": "sha256-HkzPwFmfSR7m/uRFXTciMyrF14WE/M1Vy7O1HhFQRQU=",
+        "version": "1.20-17"
+    },
+    "1.20.1": {
+        "hash": "sha256-I0qbMgmBAMb8EWZk1k42zNtYtbZJrw+AvMywiwJV6uo=",
+        "version": "1.20.1-196"
+    },
+    "1.20.2": {
+        "hash": "sha256-ujQKg1rEC4Vjqn7aHNZHmhGnYjQJyJosNc2ddJDtF6c=",
+        "version": "1.20.2-318"
+    },
+    "1.20.4": {
+        "hash": "sha256-NrIsYLoAAWORw/S26NDFjYBVwpNITJxuWGZow3696wM=",
+        "version": "1.20.4-435"
+    }
+}
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index c1677d7ddb24..5e03fbae6b72 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -37702,7 +37702,9 @@ with pkgs;
 
   pacvim = callPackage ../games/pacvim { };
 
-  papermc = callPackage ../games/papermc { };
+  papermcServers = callPackages ../games/papermc { };
+
+  papermc = papermcServers.papermc;
 
   path-of-building = qt6Packages.callPackage ../games/path-of-building {};