diff --git a/pkgs/applications/networking/instant-messengers/discord/darwin.nix b/pkgs/applications/networking/instant-messengers/discord/darwin.nix index aabb23a155a1..b8ff915a0ff0 100644 --- a/pkgs/applications/networking/instant-messengers/discord/darwin.nix +++ b/pkgs/applications/networking/instant-messengers/discord/darwin.nix @@ -8,9 +8,10 @@ self, lib, fetchurl, - undmg, makeWrapper, writeScript, + writeShellScript, + brotli, python3, runCommand, branch, @@ -34,7 +35,45 @@ let enabledDiscordModsCount = builtins.length (lib.filter (x: x) discordMods); inherit (source) version; - src = fetchurl { inherit (source) url hash; }; + + src = fetchurl { inherit (source.distro) url hash; }; + + moduleSrcs = lib.mapAttrs (_: mod: fetchurl { inherit (mod) url hash; }) source.modules; + + moduleVersions = lib.mapAttrs (_: mod: mod.version) source.modules; + + configDirName = lib.replaceStrings [ " " ] [ "" ] (lib.toLower binaryName); + + fixDistroSymlinks = writeScript "discord-fix-distro-symlinks.py" '' + #!${python3.interpreter} + import pathlib + import sys + import tarfile + + with tarfile.open(sys.argv[1]) as tar: + for member in tar: + if not member.issym(): + continue + parts = pathlib.PurePosixPath(member.name).parts[1:] + if not parts: + continue + path = pathlib.Path(sys.argv[2], *parts) + path.unlink(missing_ok=True) + path.symlink_to(member.linkname) + ''; + + stageModules = writeShellScript "discord-stage-modules" '' + store_modules="$1" + modules_dir="$HOME/Library/Application Support/${configDirName}/${version}/modules" + if [ ! -f "$modules_dir/installed.json" ]; then + mkdir -p "$modules_dir" + for m in ${lib.concatStringsSep " " (lib.attrNames moduleSrcs)}; do + ln -sfn "$store_modules/$m" "$modules_dir/$m" + done + echo '${builtins.toJSON (lib.mapAttrs (_: mod: { installedVersion = mod; }) moduleVersions)}' \ + > "$modules_dir/installed.json" + fi + ''; disableBreakingUpdates = runCommand "disable-breaking-updates.py" @@ -62,22 +101,47 @@ stdenv.mkDerivation { ; nativeBuildInputs = [ - undmg + brotli makeWrapper ]; sourceRoot = "."; + dontUnpack = true; + installPhase = '' runHook preInstall mkdir -p $out/Applications - cp -r "${desktopName}.app" $out/Applications + + extractDistro() { + local src="$1" + local dest="$2" + local tarball + tarball=$(mktemp) + brotli -d < "$src" > "$tarball" + tar xf "$tarball" --strip-components=1 -C "$dest" + + # Discord's distro tarballs store symlinks with mode 000, which makes + # them unreadable on Darwin. Recreate them with normal permissions. + ${fixDistroSymlinks} "$tarball" "$dest" + rm "$tarball" + } + + extractDistro "$src" "$out/Applications" + + ${lib.concatStringsSep "\n" ( + lib.mapAttrsToList (name: src: '' + mkdir -p "$out/Applications/${desktopName}.app/Contents/Resources/modules/${name}" + extractDistro ${src} "$out/Applications/${desktopName}.app/Contents/Resources/modules/${name}" + '') moduleSrcs + )} # wrap executable to $out/bin mkdir -p $out/bin makeWrapper "$out/Applications/${desktopName}.app/Contents/MacOS/${binaryName}" "$out/bin/${binaryName}" \ --run ${lib.getExe disableBreakingUpdates} \ + --run "${stageModules} $out/Applications/${desktopName}.app/Contents/Resources/modules" \ --add-flags ${lib.escapeShellArg commandLineArgs} runHook postInstall