about summary refs log tree commit diff
path: root/pkgs/games/build-support
diff options
context:
space:
mode:
authoraszlig <aszlig@nix.build>2018-07-31 01:48:13 +0200
committeraszlig <aszlig@nix.build>2018-07-31 01:48:13 +0200
commite5afeaad30a27e44a18c9acf78d35bc59ff98046 (patch)
tree16c9df61873944ad61514b04553a4611bf29587c /pkgs/games/build-support
parente9bb11e89fb728fe2127f5ac24a15df7b3c393ad (diff)
games: Add a new gogUnpackHook
This should make all the extra unpackCmd attributes for the GOG games
superfluous and make the expression way less convoluted, especially the
games based on Unity3D.

Right now however, the gogUnpackHook is added to buildGame, which is
used for all games, not only for the GOG ones. While it doesn't really
hurt or affect non-GOG games, it's still part of the build closure so we
might want to apply this to GOG only at some day.

For that, we need to restructure our whole packaging layout, because we
want to have a way to override buildGame only for a certain namespace
but without introducing too much churn or duplicating things.

Signed-off-by: aszlig <aszlig@nix.build>
Cc: @layus
Diffstat (limited to 'pkgs/games/build-support')
-rw-r--r--pkgs/games/build-support/build-game.nix6
-rw-r--r--pkgs/games/build-support/default.nix4
-rw-r--r--pkgs/games/build-support/setup-hooks/default.nix7
-rw-r--r--pkgs/games/build-support/setup-hooks/gog-unpack.sh71
4 files changed, 85 insertions, 3 deletions
diff --git a/pkgs/games/build-support/build-game.nix b/pkgs/games/build-support/build-game.nix
index 5c1f1ef4..459fca75 100644
--- a/pkgs/games/build-support/build-game.nix
+++ b/pkgs/games/build-support/build-game.nix
@@ -1,4 +1,4 @@
-{ stdenv, lib, file, unzip, buildSandbox, autoPatchelfHook
+{ stdenv, lib, file, unzip, buildSandbox, autoPatchelfHook, gogUnpackHook
 
 , withPulseAudio ? true, libpulseaudio ? null
 , alsaLib
@@ -18,7 +18,9 @@ assert withPulseAudio -> libpulseaudio != null;
 buildSandbox (stdenv.mkDerivation ({
   buildInputs = [ stdenv.cc.cc ] ++ buildInputs;
 
-  nativeBuildInputs = [ unzip autoPatchelfHook ] ++ nativeBuildInputs;
+  nativeBuildInputs = [
+    unzip autoPatchelfHook gogUnpackHook
+  ] ++ nativeBuildInputs;
 
   preUnpack = preUnpack + ''
     mkdir "$name"
diff --git a/pkgs/games/build-support/default.nix b/pkgs/games/build-support/default.nix
index 1832f987..0e7574ec 100644
--- a/pkgs/games/build-support/default.nix
+++ b/pkgs/games/build-support/default.nix
@@ -1,4 +1,4 @@
-{ config, callPackage, ... }:
+{ config, callPackage, callPackages, ... }:
 
 {
   buildGame = callPackage ./build-game.nix {
@@ -6,4 +6,6 @@
   };
   buildUnity = callPackage ./build-unity.nix {};
   monogamePatcher = callPackage ./monogame-patcher {};
+
+  inherit (callPackages ./setup-hooks {}) gogUnpackHook;
 }
diff --git a/pkgs/games/build-support/setup-hooks/default.nix b/pkgs/games/build-support/setup-hooks/default.nix
new file mode 100644
index 00000000..9f35dad7
--- /dev/null
+++ b/pkgs/games/build-support/setup-hooks/default.nix
@@ -0,0 +1,7 @@
+{ makeSetupHook, libarchive, innoextract }:
+
+{
+  gogUnpackHook = makeSetupHook {
+    deps = [ libarchive innoextract ];
+  } ./gog-unpack.sh;
+}
diff --git a/pkgs/games/build-support/setup-hooks/gog-unpack.sh b/pkgs/games/build-support/setup-hooks/gog-unpack.sh
new file mode 100644
index 00000000..8b70803c
--- /dev/null
+++ b/pkgs/games/build-support/setup-hooks/gog-unpack.sh
@@ -0,0 +1,71 @@
+unpackCmdHooks+=(_tryUnpackGogMakeSelf _tryUnpackGogInnoSetup)
+
+_tryUnpackGogMakeSelf() {
+  # Make sure it's really a Makeself installer with GOG.com modifications.
+  sed -n -e '1,/^\([^#]\| *\)$/ {
+    /This script.*Makeself/ {
+      n; /GOG\.com/q
+    }
+    200q1 # This is getting too long, so quit immediately.
+    b
+  }
+  q1' "$curSrc" || return 1
+
+  # The file consists of a shell script at the top, followed by a tarball with
+  # the installer and after that tarball, the actual ZIP file with the game
+  # data follows. So we need to calculate the offsets accordingly, which
+  # luckily are dumped using --dumpconf (we only get the sizes, but we can
+  # infer the starting offset for the ZIP file using those).
+  local zipfileOffset="$(
+    eval "$($SHELL "$curSrc" --dumpconf)"
+    declare -i offset=1
+    offset+="$(head -n $(($OLDSKIP - 1)) "$curSrc" | wc -c)"
+    for fs in $filesizes; do
+      offset+="$fs"
+    done
+    echo "$offset"
+  )"
+
+  # Unfortunately bsdtar exits with failure if one of the patterns specified
+  # using the --include flag doesn't match. However, if the desktop icon is
+  # missing it's not the end of the world, so we need to find another way to
+  # make it happen without bsdtar returning a failure.
+  #
+  # Let's introduce -s, which is used to substitute the paths. While it may
+  # sound eligible to be used in conjunction --include, it's only really useful
+  # for our case if the inclusion patterns would be matched _after_ the
+  # substitiotions. Unfortunately, they're matched before the substitions.
+  #
+  # So what we do instead is rewrite *everything* that we want to include into
+  # a special path "/_/game" and rewrite everything that doesn't begin with /
+  # into "skip". We're (ab)using the fact here that files coming from the
+  # archive never start with "/", but during the substitutions the leading
+  # slash isn't stripped.
+  #
+  # In the end the resulting paths are normalized, so "/..." will be turned
+  # into "./...", so all we need to do in the end is to strip 2 components from
+  # the resulting path. This discards every path that has been renamed to
+  # "skip".
+  tail -c"+$zipfileOffset" "$curSrc" | bsdtar -xf - \
+    -s '!^data/noarch/game/\(.*\)$!/_/game/\1!' \
+    -s '!^data/noarch/support/icon\.png$!/_/game/xdg-icon.png!' \
+    -s '!^[^/].*!skip!' --strip-components=2
+}
+
+_tryUnpackGogInnoSetup() {
+  innoextract -i "$curSrc" &> /dev/null || return 1
+
+  local -a unpackArgs=()
+  if [ -n "$innoExtractOnly" ]; then
+    local i
+    for i in $innoExtractOnly; do
+      unpackArgs+=("--include" "$i")
+    done
+  fi
+
+  if [ -z "$innoExtractKeepCase" ]; then
+    unpackArgs+=("-L")
+  fi
+
+  innoextract -s "${unpackArgs[@]}" -m "$curSrc"
+}