From e5afeaad30a27e44a18c9acf78d35bc59ff98046 Mon Sep 17 00:00:00 2001 From: aszlig Date: Tue, 31 Jul 2018 01:48:13 +0200 Subject: 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 Cc: @layus --- pkgs/games/build-support/build-game.nix | 6 +- pkgs/games/build-support/default.nix | 4 +- pkgs/games/build-support/setup-hooks/default.nix | 7 +++ pkgs/games/build-support/setup-hooks/gog-unpack.sh | 71 ++++++++++++++++++++++ 4 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 pkgs/games/build-support/setup-hooks/default.nix create mode 100644 pkgs/games/build-support/setup-hooks/gog-unpack.sh (limited to 'pkgs/games/build-support') 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" +} -- cgit 1.4.1