dwarf-fortress: purge minor versions and add autoupdate

Since DF saves are compatible within the same major version, we can
simply keep the latest of each major version.

From Dwarf Therapist 42.1.7 onward, dfhack-generated memory maps work
in place of Therapist's builtin memory maps. Allow this to happen.
This commit is contained in:
Morgan Jones 2024-10-13 18:35:59 -07:00
parent c8d862c2d0
commit f5df5eaba6
No known key found for this signature in database
GPG Key ID: 5C3EB94D198F1491
18 changed files with 928 additions and 407 deletions

View File

@ -207,6 +207,8 @@
- `pnpm` was updated to version 10. If your project is incompatible, you can install the previous version from the package attribute `pnpm_9`.
- `dwarf-fortress-packages` now only contains one minor version for each major version since version 0.44. Saves should still be compatible, but you may have to change which minor version you were using if it was one other than the newest.
- `zig_0_9` and `zig_0_10` have been removed, you should upgrade to `zig_0_13` (also available as just `zig`), `zig_0_12` or `zig_0_11` instead.
- `webpack-cli` was updated to major version 6, which has breaking changes from the previous version 5.1.4. See the [upstream release notes](https://github.com/webpack/webpack-cli/releases/tag/webpack-cli%406.0.0) for details on these changes.

View File

@ -0,0 +1,9 @@
# dwarf-fortress
Maintainers, please read me!
The policy for updates is currently keeping one major version of DF around since 0.44.
See [Save Compatibility](https://dwarffortresswiki.org/index.php/Save_compatibility)
on the DF wiki. Note that saves are backwards compatible, but not forwards-compatible.
This policy has been in effect since Nixpkgs 25.05.

View File

@ -61,12 +61,14 @@ let
# out, ensure that (unfuck|dfhack|twbt) are all up to date before changing
# this. Note that unfuck and twbt are not required for 50.
latestVersion =
self.dfVersions.game.latest.${
if stdenv.hostPlatform.isLinux then
"50.13"
"linux"
else if stdenv.hostPlatform.isDarwin then
"0.47.05"
"darwin"
else
throw "Unsupported system";
throw "Unsupported system"
};
# Converts a version to a package name.
versionToName = version: "dwarf-fortress_${replaceStrings [ "." ] [ "_" ] version}";
@ -96,18 +98,15 @@ let
stdenv = gccStdenv;
};
dwarf-therapist = libsForQt5.callPackage ./dwarf-therapist/wrapper.nix {
inherit dwarf-fortress;
dwarf-therapist = (libsForQt5.callPackage ./dwarf-therapist { }).override (
optionalAttrs (!isAtLeast50) {
# 41.2.5 is the last version to support Dwarf Fortress 0.47.
version = "41.2.5";
hash = "sha256-xfYBtnO1n6OcliVt07GsQ9alDJIfWdVhtuyWwuvXSZs=";
}
);
};
in
callPackage ./wrapper {
mkDfWrapper =
{
dwarf-fortress,
dfhack,
dwarf-therapist ? null,
...
}@args:
callPackage ./wrapper (
{
inherit (self) themes;
inherit
dwarf-fortress
@ -117,12 +116,32 @@ let
;
jdk = jdk8; # TODO: remove override https://github.com/NixOS/nixpkgs/pull/89731
}
// args
);
dwarf-therapist = libsForQt5.callPackage ./dwarf-therapist/wrapper.nix {
inherit dwarf-fortress dfhack mkDfWrapper;
dwarf-therapist =
(libsForQt5.callPackage ./dwarf-therapist {
inherit (self) dfVersions;
}).override
(
optionalAttrs (!isAtLeast50) {
# 41.2.5 is the last version to support Dwarf Fortress 0.47.
version = "41.2.5";
maxDfVersion = "0.47.05";
hash = "sha256-xfYBtnO1n6OcliVt07GsQ9alDJIfWdVhtuyWwuvXSZs=";
}
);
};
}) (attrNames self.df-hashes)
in
mkDfWrapper { inherit dwarf-fortress dfhack dwarf-therapist; };
}) (attrNames self.dfVersions.game.versions)
);
self = rec {
df-hashes = importJSON ./game.json;
dfVersions = importJSON ./df.lock.json;
# Aliases for the latest Dwarf Fortress and the selected Therapist install
dwarf-fortress = getAttr (versionToName latestVersion) df-games;
@ -135,9 +154,7 @@ let
soundSense = callPackage ./soundsense.nix { };
legends-browser = callPackage ./legends-browser {
jre = jre8; # TODO: remove override https://github.com/NixOS/nixpkgs/pull/89731
};
legends-browser = callPackage ./legends-browser { };
themes = recurseIntoAttrs (
callPackage ./themes {

View File

@ -0,0 +1,107 @@
{
"game": {
"latest": {
"linux": "51.10",
"darwin": "0.47.05"
},
"versions": {
"51.10": {
"df": {
"version": "51.10",
"urls": {
"linux": {
"url": "https://www.bay12games.com/dwarves/df_51_10_linux.tar.bz2",
"outputHash": "sha256-r4dadc/nch2smNHt4Ixa2FG2Sc1NFmY88iSnFFeMcz0="
}
}
},
"hack": {
"version": "51.10-r1",
"git": {
"url": "https://github.com/DFHack/dfhack.git",
"revision": "51.10-r1",
"outputHash": "sha256-TsgafCiLX/IZXgBdqQaRt7hmATwKz80x2xclCwdE3fM="
},
"xmlRev": "ec3ab067aef716817d9c5b84a6fb85bc22516caa"
}
},
"50.15": {
"df": {
"version": "50.15",
"urls": {
"linux": {
"url": "https://www.bay12games.com/dwarves/df_50_15_linux.tar.bz2",
"outputHash": "sha256-KkKcXfXjD7dUjQDfKtXiaKfoieRN8wJSYxyN6liBwU4="
}
}
},
"hack": {
"version": "50.15-r2",
"git": {
"url": "https://github.com/DFHack/dfhack.git",
"revision": "50.15-r2",
"outputHash": "sha256-6T1RXdBJdo/tvHXwYATS8emLIfDg7/0cGL4i982iHdY="
},
"xmlRev": "c6c8f15afec05d457813c003a869509901993af4"
}
},
"0.47.05": {
"df": {
"version": "0.47.05",
"urls": {
"linux": {
"url": "https://www.bay12games.com/dwarves/df_47_05_linux.tar.bz2",
"outputHash": "sha256-rHSm27fX2WIfQwQFCAMiq1DDX2YyNS/y6pI/bcWv/KM="
},
"darwin": {
"url": "https://www.bay12games.com/dwarves/df_47_05_osx.tar.bz2",
"outputHash": "sha256-vHmpKtuWSX1ZVGN46MmrLvZ8oiq/vZdjYW3pwuAOXyQ="
}
}
},
"hack": {
"version": "0.47.05-r8",
"git": {
"url": "https://github.com/DFHack/dfhack.git",
"revision": "0.47.05-r8",
"outputHash": "sha256-y5XluaNU0ewUg2uAd77+h80CYDwNr1rsxB8IslZWip8="
},
"xmlRev": "afe7e908e9e7e863412e8983f9feb2b999fae498"
}
},
"0.44.12": {
"df": {
"version": "0.44.12",
"urls": {
"linux": {
"url": "https://www.bay12games.com/dwarves/df_44_12_linux.tar.bz2",
"outputHash": "sha256-Wi0Vcw0htBpo2gnOPDtww+Km/RW5XGy/toV47S0tuXk="
},
"darwin": {
"url": "https://www.bay12games.com/dwarves/df_44_12_osx.tar.bz2",
"outputHash": "sha256-IY1TGZ9+ufWMA146XUTYgvG2ngfvY/mKZZDWGm/IptU="
}
}
},
"hack": {
"version": "0.44.12-r3",
"git": {
"url": "https://github.com/DFHack/dfhack.git",
"revision": "0.44.12-r3",
"outputHash": "sha256-8ChD4P7SpSNlhhOsrbIxoJ/T/CWobwvOY7QswxP0KK0="
},
"xmlRev": "4053321b202a29f667d64d824ba8339ec1b1df4f"
}
}
}
},
"therapist": {
"version": "42.1.12",
"maxDfVersion": "51.10",
"git": {
"url": "https://github.com/Dwarf-Therapist/Dwarf-Therapist.git",
"revision": "v42.1.12",
"outputHash": "sha256-/6tiFjfrAziw7XeEzPoNFgrsXk8Z7ea2PGjCvJlRt+A="
}
}
}

View File

@ -24,6 +24,7 @@
binutils,
gnused,
dfVersion,
dfVersions,
}:
let
@ -40,77 +41,20 @@ let
versionAtLeast
;
dfhack-releases = {
"0.44.10" = {
dfHackRelease = "0.44.10-r2";
hash = "sha256-0RikMwFv/eJk26Hptnam6J97flekapQhjWvw3+HTfaU=";
xmlRev = "321bd48b10c4c3f694cc801a7dee6be392c09b7b";
};
"0.44.11" = {
dfHackRelease = "0.44.11-beta2.1";
hash = "sha256-Yi/8BdoluickbcQQRbmuhcfrvrl02vf12MuHmh5m/Mk=";
xmlRev = "f27ebae6aa8fb12c46217adec5a812cd49a905c8";
prerelease = true;
};
"0.44.12" = {
dfHackRelease = "0.44.12-r1";
hash = "sha256-3j83wgRXbfcrwPRrJVHFGcLD+tXy1M3MR2dwIw2mA0g=";
xmlRev = "23500e4e9bd1885365d0a2ef1746c321c1dd5094";
};
"0.47.02" = {
dfHackRelease = "0.47.02-alpha0";
hash = "sha256-ScrFcfyiimuLgEaFjN5DKKRaFuKfdJjaTlGDit/0j6Y=";
xmlRev = "23500e4e9bd1885365d0a2ef1746c321c1dd509a";
prerelease = true;
};
"0.47.04" = {
dfHackRelease = "0.47.04-r5";
hash = "sha256-0s+/LKbqsS/mrxKPDeniqykE5+Gy3ZzCa8yEDzMyssY=";
xmlRev = "be0444cc165a1abff053d5893dc1f780f06526b7";
};
"0.47.05" = {
dfHackRelease = "0.47.05-r7";
hash = "sha256-vBKUTSjfCnalkBzfjaIKcxUuqsGGOTtoJC1RHJIDlNc=";
xmlRev = "f5019a5c6f19ef05a28bd974c3e8668b78e6e2a4";
};
"50.10" = {
dfHackRelease = "50.10-r1.1";
hash = "sha256-k2j8G4kJ/RYE8W0YDOxcsRb5qjjn4El+rigf0v3AqZU=";
xmlRev = "041493b221e0799c106abeac1f86df4535ab80d3";
needsPatches = true;
};
"50.11" = {
dfHackRelease = "50.11-r7";
hash = "sha256-3KsFc0i4XkzoeRvcl5GUlx/fJB1HyqfZm+xL6T4oT/A=";
xmlRev = "cca87907c1cbfcf4af957b0bea3a961a345b1581";
needsPatches = true;
};
"50.12" = {
dfHackRelease = "50.12-r3";
hash = "sha256-2mO8DpNmZRCV7IRY0arf3SMvlO4Pxs61Kxfh3q3k3HU=";
xmlRev = "980b1af13acc31660dce632f913c968f52e2b275";
};
"50.13" = {
dfHackRelease = "50.13-r3";
hash = "sha256-WbkJ8HmLT5GdZgDmcuFh+1uzhloKM9um0b9YO//uR7Y=";
xmlRev = "f0530a22149606596e97e3e17d941df3aafe29b9";
};
};
release =
if isAttrs dfVersion then
dfVersion
else if hasAttr dfVersion dfhack-releases then
getAttr dfVersion dfhack-releases
else if hasAttr dfVersion dfVersions.game.versions then
(getAttr dfVersion dfVersions.game.versions).hack
else
throw "[DFHack] Unsupported Dwarf Fortress version: ${dfVersion}";
version = release.dfHackRelease;
inherit (release) version;
isAtLeast50 = versionAtLeast version "50.0";
needs50Patches = isAtLeast50 && (release.needsPatches or false);
# revision of library/xml submodule
xmlRev = release.xmlRev;
inherit (release) xmlRev;
arch =
if stdenv.hostPlatform.system == "x86_64-linux" then
@ -149,8 +93,8 @@ stdenv.mkDerivation {
src = fetchFromGitHub {
owner = "DFHack";
repo = "dfhack";
rev = release.dfHackRelease;
inherit (release) hash;
tag = release.git.revision;
hash = release.git.outputHash;
fetchSubmodules = true;
};

View File

@ -6,8 +6,12 @@
qtdeclarative,
cmake,
ninja,
version ? "42.1.6",
hash ? "sha256-VjCXT4sl3HsFILrqTc3JJSeRedZaOXUbf4KvSzTo0uc=",
dfVersions,
# see: https://github.com/Dwarf-Therapist/Dwarf-Therapist/releases
version ? dfVersions.therapist.version,
maxDfVersion ? dfVersions.therapist.maxDfVersion,
hash ? dfVersions.therapist.git.outputHash,
}:
stdenv.mkDerivation rec {
@ -18,7 +22,7 @@ stdenv.mkDerivation rec {
src = fetchFromGitHub {
owner = "Dwarf-Therapist";
repo = "Dwarf-Therapist";
rev = "v${version}";
tag = "v${version}";
inherit hash;
};
@ -46,6 +50,10 @@ stdenv.mkDerivation rec {
dontWrapQtApps = true;
passthru = {
inherit maxDfVersion;
};
meta = with lib; {
mainProgram = "dwarftherapist";
description = "Tool to manage dwarves in a running game of Dwarf Fortress";

View File

@ -1,10 +1,16 @@
{
lib,
stdenv,
writeText,
dwarf-therapist,
dwarf-fortress,
dfhack,
mkDfWrapper,
replaceVars,
coreutils,
wrapQtAppsHook,
expect,
xvfb-run,
}:
let
@ -15,12 +21,26 @@ let
in
prefix + base;
inifile = "linux/v0.${builtins.toString dwarf-fortress.baseVersion}.${dwarf-fortress.patchVersion}${platformSlug}.ini";
unsupportedVersion = lib.versionOlder dwarf-therapist.maxDfVersion dwarf-fortress.dfVersion;
# Used to run dfhack to produce a Therapist ini file for the current memory map.
# See: http://www.bay12forums.com/smf/index.php?topic=168411.msg8532557#msg8532557
dfHackExpectScript = writeText "dfhack.exp" ''
spawn xvfb-run dfhack +devel/export-dt-ini
expect "DFHack is ready. Have a nice day!"
send "die\r"
'';
dfHackWrapper = mkDfWrapper {
inherit dwarf-fortress dfhack;
enableDFHack = true;
};
in
stdenv.mkDerivation {
pname = "dwarf-therapist";
inherit (dwarf-therapist) version meta;
inherit (dwarf-therapist) version meta maxDfVersion;
inherit (dwarf-fortress) dfVersion;
wrapper = replaceVars ./dwarf-therapist.in {
stdenv_shell = "${stdenv.shell}";
@ -36,11 +56,47 @@ stdenv.mkDerivation {
paths = [ dwarf-therapist ];
nativeBuildInputs = [ wrapQtAppsHook ];
nativeBuildInputs =
[ wrapQtAppsHook ]
++ lib.optionals unsupportedVersion [
expect
xvfb-run
dfHackWrapper
];
passthru = { inherit dwarf-fortress dwarf-therapist; };
buildCommand = ''
buildCommand =
lib.optionalString unsupportedVersion ''
fixupMemoryMaps() (
local output="$1"
local orig_md5="$2"
local patched_md5="$3"
echo "It doesn't support DF $dfVersion out of the box, so we're doing it the hard way."
export NIXPKGS_DF_HOME="$(mktemp -dt dfhack.XXXXXX)"
expect ${dfHackExpectScript}
local ini="$NIXPKGS_DF_HOME/therapist.ini"
if [ -f "$ini" ]; then
if grep -q "$patched_md5" "$ini"; then
cp -v "$ini" "$output"
else
echo "Couldn't find MD5 ($patched_md5) in $ini"
exit 1
fi
else
echo "Couldn't find $ini!"
exit 1
fi
)
''
+ lib.optionalString (!unsupportedVersion) ''
fixupMemoryMaps() {
echo "It should support DF $dfVersion, but we couldn't find any memory maps."
echo "This is a nixpkgs bug, please report it!"
exit 1
}
''
+ ''
mkdir -p $out/bin
install -Dm755 $wrapper $out/bin/dwarftherapist
@ -51,14 +107,15 @@ stdenv.mkDerivation {
wrapQtApp $out/bin/dwarftherapist
# Fix up memory layouts
ini_path="$out/share/dwarftherapist/memory_layouts/${inifile}"
rm -f "$ini_path"
mkdir -p "$(dirname -- "$ini_path")"
orig_md5=$(cat "${dwarf-fortress}/hash.md5.orig" | cut -c1-8)
patched_md5=$(cat "${dwarf-fortress}/hash.md5" | cut -c1-8)
input_file="${dwarf-therapist}/share/dwarftherapist/memory_layouts/${inifile}"
output_file="$out/share/dwarftherapist/memory_layouts/${inifile}"
rm -f "$output_file"
mkdir -p "$(dirname -- "$output_file")"
orig_md5=$(cat "${dwarf-fortress}/hash.md5.orig" | cut -c1-8)
patched_md5=$(cat "${dwarf-fortress}/hash.md5" | cut -c1-8)
if [ -f "$input_file" ]; then
echo "[Dwarf Therapist Wrapper] Fixing Dwarf Fortress MD5 prefix:"
echo " Input: $input_file"
echo " Search: $orig_md5"
@ -66,6 +123,11 @@ stdenv.mkDerivation {
echo " Replace: $patched_md5"
substitute "$input_file" "$output_file" --replace-fail "$orig_md5" "$patched_md5"
else
echo "[Dwarf Therapist Wrapper] OH NO! No memory maps found!"
echo "This version of Therapist ($dfVersion) has max DF version $maxDfVersion."
fixupMemoryMaps "$output_file" "$orig_md5" "$patched_md5"
fi
'';
preferLocalBuild = true;

View File

@ -1,151 +0,0 @@
{
"0.43.05": {
"linux": "1r0b96yrdf24m9476k5x7rmp3faxr0kfwwdf35agpvlb1qbi6v45",
"linux32": "16l1lydpkbnl3zhz4i2snmjk7pps8vmw3zv0bjgr8dncbsrycd03",
"osx": "1j2zdkjnmxy8yn599pm0qmbi4zjp1m8h4ggqjxhyzp135h0lqqf9",
"osx32": "09ym4mflp5z78pk5mvj7b44xihnsvrxmh0b5kix6h1m6z3cc90l4",
"win": "0m337wh4c47ij1f3zrimvy7baff7nzrmgjbmrwdy89d0z90xpnx8",
"win_s": "0bjk5m1qkn3ldhqiwbq24y2m9fz9r574d54ngdb8b4ri2xfl1fbp",
"win32": "162rl9ygpj66pis87bqc5bwc0mk75hxv6ianhn87pbl4rh7g8ax8",
"win32_s": "0gv1jyw5fdskjjs27pr41grbmkk7ipqn0ry615f5g79k3mhl200i",
"legacy": "09lvbmg1gq257qchlbmq7hxc5nl9r39jpf73zhmwb5xfbpprn0zs",
"legacy_s": "023a5b27fm65w7gmzjssyyci70fdjk2zbv965y4n0f23kc4rj9gl",
"legacy32": "1m75arxj1q82l2dkk8qcargm3xczxlqi8krwvg3iimddky34gipq",
"legacy32_s": "1hgzsk66isfr5vcraxwgl7cvycl14kwf8w9kzxr8jyp5z7k24q29"
},
"0.44.05": {
"linux": "18bjyhjp5458bfbizm8vq4s00pqpfs097qp6pv76m84kgbc4ghg3",
"linux32": "1b9i4kf4c8s6bhqwn8jx100mg7fqp8nmswrai5w8dsma01py4amr",
"osx": "1ssc8vq3ad38x9c04j8gg96kxv0g2npi3jwcg40676byx5nrx7b6",
"osx32": "12i7x8idcbvp5h62jyc7b7j98jf4lrisnwglvnrms6jclj0b3g0q",
"win": "1kaifarjx0akg7s5a2ngfw0vm0vyr4jnax5rrbv96dliqn5knddz",
"win_s": "1a1xikrjdv4b0yfgnp5s8d6xn0njylynsqd8zixdc01vccl5kqm6",
"win32": "1j3cq0h7jdvxbsbpfxa7bli45smvy9m4fji0j6849kj7x0vcpwq4",
"win32_s": "10cw1n48ffkrv9ms07ka5b5370d9k2fm051cnnq03lkcvlwrq145",
"legacy": "0y7xpgmwn4nshhc7apyf8mj5ycl0q5vckdaviwzz6w1x31s3dp6n",
"legacy_s": "0j8rbw9ww1avmh8zhyzljjj6in87q4qffpffdl394fsi74n8px0d",
"legacy32": "0d3l4jvx53a01fjf1lf20ar9lfyykfhk05dlrfwz3w4k7vj4vvlf",
"legacy32_s": "1c5x9x44bblz7anhmk4y9a7p1b39b9k7gzvj4pi55jzfq0k60kl7"
},
"0.44.09": {
"linux": "1haikynkg1pqyrzzqk1qxm19p36ww58qp8brh3fjxssp4x71rcdy",
"linux32": "0lmbrdf7wjdwj5yx0khnq871yxvhfwqxjjyfkqcdy5ik18lvlkj8",
"osx": "01dss8g9lmi8majp6lxcfw166ydz4himkz6am5pi29gixaf4vfqs",
"osx32": "1iwlvmz1ir9k0kzn6726frmkznvsg9a99bbqnxvwcnq3nnnjxw3s",
"win": "08g5irgp59dfjgj3jxc8ixwzgnz2wghcl8cg1b1g4088dsf2x3x8",
"win_s": "1xyb4msn9wfrh7x136r8xn3sjz6z8c4zksbzifa0z0bpa3pdviap",
"win32": "0m8bs2mnyi1r4x84fwnfgd1ijdcf08xsq5zy84476svci932g5kz",
"win32_s": "0pl319qmyy96ibzlgj4wfj19dv1wzyg8ig6q11l4c7rivzc9286i",
"legacy": "0l8nrvppfzazhjsfkd5nd0bxnc6ljk8fs6yg8qh69g7q7zvzgnd3",
"legacy_s": "1c49z539a31czzq0rnhg6yrv1zbaja35sd0ssr4k7lsghjv84k1z",
"legacy32": "155xg6dpb8frlw7d9h7m1y0spw55wl4nkn7zrm70bpyp39pydlqp",
"legacy32_s": "05qkzjfx1ybrv96wya1dirdfxdkhj6a440sjpzwbqpkqgr8z57a3"
},
"0.44.10": {
"linux": "1cqm43hn3ar9d8a7y7dwq48ajp72cirn1gclh8r2fykkypprxmp2",
"linux32": "0gdb6sq8725nwdisxwha8f5b6arq570s73aj4gdrh611gxh13r6n",
"osx": "1wpa45d81q8f5mhqmaxvdkz93k6cm3pg7vpsqjjjsp5s961gd74g",
"osx32": "0rsy1n19n12gh8rddgi3db32in488f2nizq8kw25hga03hsh4r6x",
"win": "04i0ka12hmn3chsyfmk2pbknr1pdf3p8yaz7kv82ri4g6dvsjfv6",
"win_s": "01m6nqcrz4rhdc8wb31azj3vmjid8bdpqaf9wkz4g4vvjyy7xiyz",
"win32": "1nymin8wbzbh8gm2702dy7h5spdijdxnysdz71ldyl0xx4vw68d9",
"win32_s": "1skz0jpfm6j9bins04kn96f3v3k0kvjqlh25x3129r3hh8xacnd3",
"legacy": "0s84vpfr2b5y1kda9allqjrpkaxw15mkblk9dq08syhsj19vspa7",
"legacy_s": "18b7ikp7xy2y071h3ydfh5mq9hw9y303rdqyikvra5ji3n5p96cm",
"legacy32": "1yh2fl3qwpy6wrxavhn75grbjygymnfh746hxbmc60la7y5flrpy",
"legacy32_s": "0j65w2hxgpccg9qsaz14r82qvnvfd0pbl2gyx9fv8d77kxhkc4pw"
},
"0.44.11": {
"linux": "1qizfkxl2k6pn70is4vz94q4k55bc3pm13b2r6yqi6lw1cnna4sf",
"linux32": "11m39lfyrsxlw1g7f269q7fzwichg06l21fxhqzgvlvmzmxsf8q5",
"osx": "073hmcj7bm323m3xqi42605rkvmgmv83bnxz1byymgs8aqyfykkx",
"osx32": "0w5avnj86wprk8q0rb5qm9kxbigzk6dk0akqbw4m76jgg2jdmir7",
"win": "1yxyv1sycn5jc3g1y02d82154xydg3kbghis7l3xi28n3bh8387b",
"win_s": "1xzwl6c362wqgps911y9q8vndp8zyd20fc2p7pkzzmw2hrgfqi6q",
"win32": "16x2rg3gm3lh2akg7n057kkxxigb2ljz0nk685lmn4j0adq8l31p",
"win32_s": "1a2y220111d94mzj5y3jwpy062k8fw25akyp7yn3fwa17vwvn8zq",
"legacy": "0gfjmsfqj21hs4d1hm7fvppbdjspc4r2qnnp6mwcbgh67i5p5rdb",
"legacy_s": "1wr4hpzmhgl8haric3jpfd3kwqv1fi4vkb1gvaax5f7kplvfqfac",
"legacy32": "1cpzckwvqkxqn0c498mmh4papsjdi3mcvcp2vzlvj46kvdl3n0f0",
"legacy32_s": "024vzwfcrx7ms4dip0ccwd0vizzck2pwz2ryyvlz4rpjzhswj5gi"
},
"0.44.12": {
"win32": "0bxrc7zj4vgcgdwc130g6f5jnp13vgx9a2kn2l1jcc958x8a367g",
"linux32": "0fmr8diskmbh12s0bpfn5gky9lmrc7xxj6va5adjm6ahxv9jwr06",
"osx": "1md6r1pimmlhcn5gjqzg0ygbdwc2v125sfjy0f6gbfbykwcm7391",
"osx32": "1dbg7pavxw20r8iqc566fn558avgj5glsycvi6ggbvsh0rpw6n5v",
"win": "0zb5ximqi5j7vyvgjzfz7ycadh5sgb7jlyaa68x0sjlbybdr1min",
"win_s": "1ncf5zr1fggr5knf30l0wh7spp376v1jcc6m9c86zim8azcfx0y7",
"linux": "0ydr5lnysy45nsznqp5r2pysdqn3f0xkrkh9v9l1md111mriabas",
"win32_s": "1mxbjkikf010skrpng51r86jmv4nal51j5n1y9kyhv344bq6chr9",
"legacy": "11a212ynhx18p3k8hvdjx199din14wggxiwz191b4309fznzpprz",
"legacy_s": "05madj529y18ndxrih96mivbzng1vz2zbzicrcnj58i2084zm23f",
"legacy32": "0rapcydiic2nq6idjf7fg53xsxk8dxzyi1vflpz554ghdrnsmwjv",
"legacy32_s": "16fgbd3lx4r270dxqj6gr1g1iqjj8cv389h2hw1l646xx28g8d2m"
},
"0.47.01": {
"linux": "1wbybkfpgvpd2yliy8mfgddnz806ac4rv4j0lhlsqwpk8jj0mx81",
"linux32": "1fnz1mydqgybcm8kzranvjzc2x9g6bcalxv3fsjngvpv13x6izzv",
"osx": "18wdffidasbrsbhqjwds08ckbrjhcw0759aynz7zggyy5is9q8iw",
"osx32": "1b4kf3vg0zd5w5s0rdhzfz0rswkl6sq0j1f8qmimnw7qd09h43wx",
"win": "1v3v2z7g67d6926h9lxakznvbddyxyr85i1ym34y2wywnc886z7r",
"win_s": "0yahynimhz4nvdi5qp5a612vf7ikg87w2aj2r8s1lhdw6xwdkpyc",
"win32": "07mqhm64c1ddjc3vpyhf9qf14lp19xwz3pgg4c2pvcwy4yyrys22",
"win32_s": "07acbxai8g04yxg7n68nyx4jwcqqkgjn7n96q2lzxdvc988kiivz",
"legacy32_s": "1gxmc3rsl9glai3wb4wzsda3qyhdimd8s5kbr5m753n8lmzasafx"
},
"0.47.02": {
"linux": "1zbsygbfiqxxs767qxkxjp3ayywi5q0d8xlrqlbd0l8a3ccg5avw",
"linux32": "1ddc9s4n408j8gidgign51bgv2wgy5z4cy74jzx00pvnhsfp2mpy",
"osx": "1mwy88yxip1wys1kxpfsbg7wlvfrkc4lg04gqw0d266a88dj7a30",
"osx32": "08ssnzl52gqqgcqhl0ynyikbxz76825kpcg1d6yx8g7ifjndf19n",
"win": "08g7fy18y8q32l0158314bny0qg57xz37qj9fri9r4xbhci67ldk",
"win_s": "0x56s1md62yk661aqcdgnz8k0zir0zr8qwan5vrqc0q9yh069yl1",
"win32": "0ww64mymbilb235n93d7w4c9axq3ww2mxa0f7bl4x8yrxwc8k942",
"win32_s": "0r801vip807v88icf47i3s82v7lshx67q4ilzfjirqfslh1x00bs",
"legacy": "14f4d6r7swfjnlaalg4l5916ihj6wvhlsgjp7cygamzp4c2wgng8",
"legacy_s": "1jxf52kaijf4crwxj30a4f6z7rzs6xa91y6vn5s8jr0cvbr5pz64",
"legacy32": "0j7shqdv3gimacj03cil2y0fmr0j0fp57cwmdjwnxwx3m96k3xwm",
"legacy32_s": "1wc7pcp9dwz0q1na3i5pbqknya595qdkmr7hsmgh2kk8rsp3g9g2"
},
"0.47.04": {
"linux": "1ri82c5hja6n0wv538srf2nbcyb8ip49w4l201m90cmcycmqgr8x",
"linux32": "00yz8gl75sbx15d7vl22ij0a5qd325kpc9mgm1lh5g7i065vgzn8",
"osx": "0c1g655bn5n4pbzxw3v83gmy54va5y87m7ksi6iryfal0m9lshhv",
"osx32": "1knfgqbwa7v9va1w6i8yzz6xp3dj633dbs50izx6ldszm0ra42pg",
"win": "0j7ixr3rf9900zzfw3nd3vg97kdkspm530cmf9dkwhf6klmpks7s",
"win_s": "11amw5gjhi753mvf17wifcjiyikjx0qwa16787gfhj9jfp0yw764",
"win32": "1xw9f49n85c31kbzkm5zh81kccjx9msjyy3xwr0klak5w398a59l",
"win32_s": "0s26hrgfk2b5wg4dvg90wgw1mvrrvbyjhmsys9f5fl7zn1pjbxxr",
"legacy": "103bcnn8gxi2rkpjmjfgv5a5kxmh1zd7vagrsscv55sppd7fcl7n",
"legacy_s": "19ai7lvxx0y3iha9qrbl5krric547rzs6vm4ibk8x61vv97jrbd8",
"legacy32": "0lli6s1g7yj3p3h26ajgq3h619n88qn6s7amyz6z8w7hyzfi7wij",
"legacy32_s": "1wzxbzgln9pmsk2nchrl94d2yd09xdgynmjl4qwcaqzkrnf3sfqc"
},
"0.47.05": {
"linux": "18zwmz2nsgwjxbr2yd9jcrgw6l5b481hh1848cgn5nfpnzdscx5c",
"linux32": "1jbav7ghsjsxd6cdp6f2x5qn83zc8707dqan5sp73fp6mbj2jasl",
"osx": "092z1vhc5sbdc5irggdz5ai7rxifmg4yhy33aicpsjcnvcmajydw",
"osx32": "0lpbwfiagp0zp280aw3fmj8938w5fc5r9gibzk2h86jy63ps29ww",
"win": "0bbk7j3d4h2wn9hmbsbbbbr0ajf3ddlprxfaajfbnbiyv72cpn9s",
"win_s": "0nl7c9dpfx7jjpy7y52z8h3kiy4cpax1m58apbcfyy95an4jz8s4",
"win32": "08ka1lklly82h4mr770y9p0a21x9dx6jqvjgxdsxj5979f26il1v",
"win32_s": "06w844zxzx3lfykibgkk4gbg4xymnqraj1ikv4mzlv31l727a1x4",
"legacy": "042a0gbad3cp5dwhnrzg3vr9w48b8ybqgxgw5i9rk4c1i0gjjpw2",
"legacy_s": "1rb7h8lzlsjs08rvhhl3nwbrpj54zijijp4y0qdp4vyzsig6nisk",
"legacy32": "0ayw09x9smihh8qp5pdvr6vvhwkvcqz36h3lh4g1b5kzxj7g9cyf",
"legacy32_s": "10gfxlysfs9gyi1mv52idp5xk45g9h517g2jq4a8cqp2j7594v9c"
},
"50.10": {
"linux": "13s5p7205r9ha2j5n7carrwd0y7krq34bcdl08khp0kh2v4470a3"
},
"50.11": {
"linux": "0iz2d88gzvn0vjxlr99f13j4awhvh2lggjmipdwpbxhfsqih7dx0"
},
"50.12": {
"linux": "070014fzwszfgjyxjyij0k0hadah6s62lpi91ykp3vs220azya1m"
},
"50.13": {
"linux": "19wzgsdgv0vq7v2dxhypr9hayky3nm3lbra1kk9vn8ri96jdkfkw"
}
}

View File

@ -15,7 +15,7 @@
gcc,
dfVersion,
df-hashes,
dfVersions,
}:
let
@ -35,14 +35,9 @@ let
;
# Map Dwarf Fortress platform names to Nixpkgs platform names.
# Other srcs are available like 32-bit mac & win, but I have only
# included the ones most likely to be needed by Nixpkgs users.
platforms = {
x86_64-linux = "linux";
i686-linux = "linux32";
x86_64-darwin = "osx";
x86_64-cygwin = "win";
i686-cygwin = "win32";
x86_64-darwin = "darwin";
};
dfVersionTuple = splitVersion dfVersion;
@ -61,8 +56,8 @@ let
&& (dwarf-fortress-unfuck.dfVersion or null) == dfVersion;
game =
if hasAttr dfVersion df-hashes then
getAttr dfVersion df-hashes
if hasAttr dfVersion dfVersions.game.versions then
(getAttr dfVersion dfVersions.game.versions).df
else
throw "Unknown Dwarf Fortress version: ${dfVersion}";
dfPlatform =
@ -70,9 +65,9 @@ let
getAttr stdenv.hostPlatform.system platforms
else
throw "Unsupported system: ${stdenv.hostPlatform.system}";
sha256 =
if hasAttr dfPlatform game then
getAttr dfPlatform game
url =
if hasAttr dfPlatform game.urls then
getAttr dfPlatform game.urls
else
throw "Unsupported dfPlatform: ${dfPlatform}";
exe =
@ -87,8 +82,8 @@ stdenv.mkDerivation {
version = dfVersion;
src = fetchurl {
url = "https://www.bay12games.com/dwarves/df_${toString baseVersion}_${toString patchVersion}_${dfPlatform}.tar.bz2";
inherit sha256;
inherit (url) url;
hash = url.outputHash;
};
sourceRoot = ".";
@ -184,7 +179,11 @@ stdenv.mkDerivation {
dfVersion
exe
;
updateScript = ./update.sh;
updateScript = {
command = [ ./update.rb ];
attrPath = "dwarf-fortress-packages";
supportedFeatures = [ "commit" ];
};
};
meta = {

View File

@ -8,11 +8,11 @@
let
name = "legends-browser-${version}";
version = "1.17.1";
version = "1.19.2";
jar = fetchurl {
url = "https://github.com/robertjanetzko/LegendsBrowser/releases/download/${version}/legendsbrowser-${version}.jar";
sha256 = "05b4ksbl4481rh3ykfirbp6wvxhppcd5mvclhn9995gsrcaj8gx9";
hash = "sha256-jkv7InwaRn0K3VAa0LqkYpH6TnrT/tGYBtbvNGM6t98=";
};
script = writeShellScriptBin "legends-browser" ''
@ -24,7 +24,7 @@ let
echo 'Creating initial configuration for legends-browser'
echo "last=$(cd ..; pwd)" > legendsbrowser.properties
fi
${jre}/bin/java -jar ${jar}
exec ${jre}/bin/java -jar ${jar}
'';
in
@ -34,7 +34,10 @@ buildEnv {
meta = with lib; {
description = "Multi-platform, open source, java-based legends viewer for dwarf fortress";
maintainers = with maintainers; [ Baughn ];
maintainers = with maintainers; [
Baughn
numinit
];
sourceProvenance = with sourceTypes; [ binaryBytecode ];
license = licenses.mit;
platforms = platforms.all;

View File

@ -7,7 +7,6 @@ let
listToAttrs
maintainers
platforms
readFile
;
in

View File

@ -16,37 +16,16 @@ let
;
twbt-releases = {
"0.44.10" = {
twbtRelease = "6.49";
sha256 = "1qjkc7k33qhxj2g18njzasccjqsis5y8zrw5vl90h4rs3i8ld9xz";
prerelease = false;
};
"0.44.11" = {
twbtRelease = "6.51";
sha256 = "1yclqmarjd97ch054h425a12r8a5ailmflsd7b39cg4qhdr1nii5";
prerelease = true;
};
"0.44.12" = {
twbtRelease = "6.54";
sha256 = "10gfd6vv0vk4v1r5hjbz7vf1zqys06dsad695gysc7fbcik2dakh";
hash = "sha256-cKomZmTLHab9K8k0pZsB2uMf3D5/SVhy2GRusLdp7oE=";
prerelease = false;
};
"0.47.02" = {
twbtRelease = "6.61";
sha256 = "07bqy9rkd64h033sxdpigp5zq4xrr0xd36wdr1b21g649mv8j6yw";
prerelease = false;
};
"0.47.04" = {
twbtRelease = "6.xx";
dfhackRelease = "0.47.04-r5";
sha256 = "sha256-+C3g4KJShCb2VXGQ4mtkDOufXZQ1P+ebDTmUzL3tNyU=";
prerelease = true;
};
"0.47.05" = {
twbtRelease = "6.xx";
dfhackRelease = "0.47.05-r7";
sha256 = "sha256-4xMKuSP5J6pMK+hwjTAcTI0gsLJfw+Xt+vh9CopR4tk=";
prerelease = true;
dfhackRelease = "0.47.05-r8";
hash = "sha256-qiNs6iMAUNGiq0kpXqEs4u4Wcrjf6/qA/dzBe947Trc=";
prerelease = false;
};
};
@ -67,7 +46,7 @@ stdenvNoCC.mkDerivation rec {
"https://github.com/thurin/df-twbt/releases/download/${release.dfhackRelease}/twbt-${version}-linux64-${release.dfhackRelease}.zip"
else
"https://github.com/mifki/df-twbt/releases/download/v${version}/twbt-${version}-linux.zip";
sha256 = release.sha256;
inherit (release) hash;
};
sourceRoot = ".";

View File

@ -32,42 +32,10 @@ let
;
unfuck-releases = {
"0.43.05" = {
unfuckRelease = "0.43.05";
hash = "sha256-4iLVrKmlVdvBICb8NLe/U7pHtL372CGDkxt/2lf2bZw=";
};
"0.44.05" = {
unfuckRelease = "0.44.05";
hash = "sha256-iwR9st4VsPJBn7cKH/cy8YS6Tcw8J+lMJK9/9Qgl0gM=";
};
"0.44.09" = {
unfuckRelease = "0.44.09";
hash = "sha256-9W9qON0QEjfXe2XzRvseixc+YznPzDQdcId08dEGF40=";
};
"0.44.10" = {
unfuckRelease = "0.44.10";
hash = "sha256-8ldEFcf5zPRdC/yXgMByeCC0pqZprreITIetKDpOYW0=";
};
"0.44.11" = {
unfuckRelease = "0.44.11.1";
hash = "sha256-f9vDe3Q3Vl2hFLCPSzYtqyv9rLKBKEnARZTu0MKaX88=";
};
"0.44.12" = {
unfuckRelease = "0.44.12";
hash = "sha256-f9vDe3Q3Vl2hFLCPSzYtqyv9rLKBKEnARZTu0MKaX88=";
};
"0.47.01" = {
unfuckRelease = "0.47.01";
hash = "sha256-k8yrcJVHlHNlmOL2kEPTftSfx4mXO35TcS0zAvFYu4c=";
};
"0.47.02" = {
unfuckRelease = "0.47.01";
hash = "sha256-k8yrcJVHlHNlmOL2kEPTftSfx4mXO35TcS0zAvFYu4c=";
};
"0.47.04" = {
unfuckRelease = "0.47.04";
hash = "sha256-KRr0A/2zANAOSDeP8V9tYe7tVO2jBLzU+TF6vTpISfE=";
};
"0.47.05" = {
unfuckRelease = "0.47.05-final";
hash = "sha256-kBdzU6KDpODOBP9XHM7lQRIEWUGOj838vXF1FbSr0Xw=";

View File

@ -0,0 +1,626 @@
#!/usr/bin/env nix-shell
#!nix-shell -i ruby -p "ruby.withPackages (ps: with ps; [ curb nokogiri ])" nix-prefetch-git
require 'set'
require 'json'
require 'uri'
require 'shellwords'
require 'erb'
require 'rubygems'
require 'curb'
require 'nokogiri'
# Performs a GET to an arbitrary address.
# +url+:: the URL
def get url, &block
curl = Curl::Easy.new(url) do |http|
http.follow_location = false
http.headers['User-Agent'] = 'nixpkgs dwarf fortress update bot'
yield http if block_given?
end
curl.perform
curl.body_str
end
# Performs a GET on the Github API.
# +url+:: the relative URL to api.github.com
def get_gh url, &block
ret = get URI.join('https://api.github.com/', url) do |http|
http.headers['Accept'] = 'application/vnd.github+json'
http.headers['Authorization'] = "Bearer #{ENV['GH_TOKEN']}" if ENV.include?('GH_TOKEN')
http.headers['X-GitHub-Api-Version'] = '2022-11-28'
yield http if block_given?
end
JSON.parse(ret, symbolize_names: true)
end
def normalize_keys hash
Hash[hash.map {
[
_1.to_s,
_2.is_a?(Hash) ? normalize_keys(_2) : _2
]
}]
end
module Mergeable
# Merges this Mergeable with something else.
# +other+:: The other Mergeable.
def merge other
if !other
return self
end
if !other.is_a?(Mergeable) || self.members != other.members
raise "invalid right-hand operand for merge: #{other.members}"
end
hash = {}
self.members.each do |member|
if @@expensive && @@expensive.include?(member)
# Already computed
hash[member] = self[member]
elsif self[member] && self[member].is_a?(Mergeable)
# Merge it
hash[member] = self[member].merge(other[member])
elsif self[member] && self[member].is_a?(Hash)
hash[member] = Hash[other[member].map {
[_1, self[member][_1] && self[member][_1].is_a?(Mergeable) ? self[member][_1].merge(_2) : _2]
}]
else
# Compute it
hash[member] = other[member]
end
end
self.class.new(**hash)
end
# Marks some attributes as expensive.
def expensive *attrs
@@expensive ||= Set.new
attrs.each {@@expensive << _1}
self
end
end
module Versionable
# Parses the version.
def parsed_version
@version ||= Gem::Version.create(self.version.partition('-').first)
end
# Drops the last component of the version for chunking.
def major_version
@major_version ||= Gem::Version.create(self.parsed_version.canonical_segments[..-2].join('.'))
end
# Compares the major version.
def =~ other
self.major_version == other.major_version
end
# Negation of the above.
def !~ other
!(self =~ other)
end
# Compares two versions.
def <=> other
other.parsed_version <=> self.parsed_version
end
end
class DFUrl < Struct.new(:url, :output_hash, keyword_init: true)
include Mergeable
extend Mergeable
expensive :output_hash
# Converts this DFUrl to a hash.
def to_h
{
url: self.url,
outputHash: self.output_hash
}
end
# Returns or computes the output hash.
def output_hash
return super if super
self.output_hash = `nix-prefetch-url #{Shellwords.escape(self.url.to_s)} | xargs nix-hash --to-sri --type sha256`.strip
super
end
# Converts this DFUrl from a hash.
# +hash+:: The hash
def self.from_hash hash
DFUrl.new(
url: hash.fetch(:url),
output_hash: hash[:outputHash]
)
end
end
class DFGithub < Struct.new(:url, :revision, :output_hash, keyword_init: true)
include Mergeable
extend Mergeable
expensive :output_hash
# Converts this DFGithub to a hash.
def to_h
{
url: self.url,
revision: self.revision,
outputHash: self.output_hash
}
end
# Returns or computes the output hash.
def output_hash
return super if super
url = URI.parse(self.url.to_s)
if ENV['GH_TOKEN']
url.userinfo = ENV['GH_TOKEN']
end
self.output_hash = JSON.parse(`nix-prefetch-git --no-deepClone --fetch-submodules #{Shellwords.escape(url.to_s)} #{Shellwords.escape(self.revision.to_s)}`, symbolize_names: true).fetch(:hash)
super
end
# Converts a hash to a DFGithub.
# +hash+:: The hash
def self.from_hash hash
DFGithub.new(
url: hash.fetch(:url),
revision: hash.fetch(:revision),
output_hash: hash[:outputHash]
)
end
end
class DFVersion < Struct.new(:version, :urls, keyword_init: true)
include Mergeable
extend Mergeable
include Versionable
# Converts a DFVersion to a hash.
def to_h
{
version: self.version,
urls: Hash[self.urls.map {
[_1, _2.to_h]
}]
}
end
# Converts a hash to a DFVersion.
# +hash+:: The hash
def self.from_hash hash
DFVersion.new(
version: hash.fetch(:version),
urls: Hash[hash.fetch(:urls).map {
[_1, DFUrl.from_hash(_2)]
}]
)
end
# Converts an HTML node to a DFVersion.
# +base+:: The base URL for DF downloads.
# +node+:: The HTML node
def self.from_node base, node
match = node.text.match(/DF\s+(\d+\.\d+(?:\.\d+)?)/)
if match
systems = {}
node.css('a').each do |a|
case a['href']
when /osx\.tar/ then systems[:darwin] = DFUrl.new(url: URI.join(base, a['href']).to_s)
when /linux\.tar/ then systems[:linux] = DFUrl.new(url: URI.join(base, a['href']).to_s)
end
end
if systems.empty?
nil
else
DFVersion.new(version: match[1], urls: systems)
end
else
nil
end
end
# Returns all DFVersions from the download page.
# +cutoff+:: The minimum version
def self.all cutoff:
cutoff = Gem::Version.create(cutoff)
base = 'https://www.bay12games.com/dwarves/'
res = get URI.join(base, 'older_versions.html')
parsed = Nokogiri::HTML(res)
# Figure out which versions we care about.
parsed.css('p.menu').map {DFVersion.from_node(base, _1)}.select {
_1 && _1.parsed_version >= cutoff
}.sort.chunk {
_1.major_version
}.map {|*, versions|
versions.max_by {_1.parsed_version}
}.to_a
end
end
class DFHackVersion < Struct.new(:version, :git, :xml_rev, keyword_init: true)
include Mergeable
extend Mergeable
include Versionable
expensive :xml_rev
# Returns the download URL.
def git
return super if super
self.git = DFGithub.new(
url: "https://github.com/DFHack/dfhack.git",
revision: self.version
)
super
end
# Converts this DFHackVersion to a hash.
def to_h
{
version: self.version,
git: self.git.to_h,
xmlRev: self.xml_rev,
}
end
# Returns the revision number in the version. Defaults to 0.
def rev
return @rev if @rev
rev = self.version.match(/-r([\d\.]+)\z/)
@rev = rev[1].to_f if rev
@rev ||= 0
@rev
end
# Returns the XML revision, fetching it if necessary.
def xml_rev
return super if super
url = "repos/dfhack/dfhack/contents/library/xml?ref=#{URI.encode_uri_component(self.git.revision)}"
body = get_gh url
self.xml_rev = body.fetch(:sha)
super
end
# Compares two DFHack versions.
# +other+:: the other dfhack version
def <=> other
ret = super
ret = other.rev <=> self.rev if ret == 0
ret
end
# Returns a version from a hash.
# +hash+:: the hash
def self.from_hash hash
DFHackVersion.new(
version: hash.fetch(:version),
git: DFGithub.from_hash(hash.fetch(:git)),
xml_rev: hash[:xmlRev]
)
end
# Returns a release from a github object.
# +github_obj+:: The github object. Returns null for prereleases.
def self.from_github github_obj
if github_obj.fetch(:prerelease)
return nil
end
version = github_obj.fetch(:tag_name)
DFHackVersion.new(version: version)
end
# Returns all dfhack versions.
# +cutoff+:: The cutoff version.
def self.all cutoff:
cutoff = Gem::Version.create(cutoff)
ret = {}
(1..).each do |page|
url = "repos/dfhack/dfhack/releases?per_page=100&page=#{page}"
releases = get_gh url
releases.each do |release|
release = DFHackVersion.from_github(release)
if release && release.parsed_version >= cutoff
ret[release.major_version] ||= {}
ret[release.major_version][release.parsed_version] ||= []
ret[release.major_version][release.parsed_version] << release
end
end
break if releases.length < 1
end
ret.each do |_, dfhack_major_versions|
dfhack_major_versions.each do |_, dfhack_minor_versions|
dfhack_minor_versions.sort!
end
end
ret
end
end
class DFWithHackVersion < Struct.new(:df, :hack, keyword_init: true)
include Mergeable
extend Mergeable
# Converts this DFWithHackVersion to a hash.
def to_h
{
df: self.df.to_h,
hack: self.hack.to_h
}
end
# Converts a hash to a DFWithHackVersion.
# +hash+:: the hash to convert
def self.from_hash hash
DFWithHackVersion.new(
df: DFVersion.from_hash(hash.fetch(:df)),
hack: DFHackVersion.from_hash(hash.fetch(:hack))
)
end
end
class DFWithHackVersions < Struct.new(:latest, :versions, keyword_init: true)
include Mergeable
extend Mergeable
# Initializes this DFWithHackVersions.
def initialize *args, **kw
super *args, **kw
self.latest ||= {}
self.versions ||= {}
end
# Converts this DFWithHackVersions to a hash.
def to_h
{
latest: self.latest,
versions: Hash[self.versions.map {
[_1.to_s, _2.to_h]
}]
}
end
# Loads this DFWithHackVersions.
# +cutoff+:: The minimum version to load.
def load! cutoff:
df_versions = DFVersion.all(cutoff: cutoff)
dfhack_versions = DFHackVersion.all(cutoff: cutoff)
df_versions.each do |df_version|
latest_dfhack_version = nil
corresponding_dfhack_versions = dfhack_versions.dig(df_version.major_version, df_version.parsed_version)
if corresponding_dfhack_versions
latest_dfhack_version = corresponding_dfhack_versions.first
end
if latest_dfhack_version
df_version.urls.each do |platform, url|
if !self.latest[platform] || df_version.parsed_version > Gem::Version.create(self.latest[platform])
self.latest[platform] = df_version.version
end
end
self.versions[df_version.version] = DFWithHackVersion.new(df: df_version, hack: latest_dfhack_version)
end
end
end
# Converts a hash to a DFWithHackVersions.
# +hash+:: The hash
def self.from_hash hash
DFWithHackVersions.new(
latest: hash.fetch(:latest),
versions: Hash[hash.fetch(:versions).map {
[_1.to_s, DFWithHackVersion.from_hash(_2)]
}]
)
end
end
class Therapist < Struct.new(:version, :max_df_version, :git, keyword_init: true)
include Mergeable
extend Mergeable
include Versionable
expensive :max_df_version
# Converts this Therapist instance to a hash.
def to_h
{
version: self.version,
maxDfVersion: self.max_df_version,
git: self.git.to_h
}
end
# Returns the max supported DF version.
def max_df_version
return super if super
url = "repos/Dwarf-Therapist/Dwarf-Therapist/contents/share/memory_layouts/linux?ref=#{URI.encode_uri_component(self.git.revision)}"
body = get_gh url
# Figure out the max supported memory layout.
max_version = nil
max_version_str = nil
body.each do |item|
name = item[:name] || ""
match = name.match(/\Av(?:0\.)?(\d+\.\d+)-classic_linux\d*\.ini/)
if match
version = Gem::Version.create(match[1])
if !max_version || version > max_version
max_version = version
max_version_str = match[1]
end
end
end
self.max_df_version = max_version_str
super
end
# Returns a Github URL.
def git
return super if super
self.git = DFGithub.new(
url: "https://github.com/Dwarf-Therapist/Dwarf-Therapist.git",
revision: 'v' + self.version
)
super
end
# Loads this therapist instance from Github.
def load!
latest = self.class.latest
self.version = latest.version
self.max_df_version = latest.max_df_version
self.git = nil
self
end
# Loads a hash into this Therapist instance.
# +hash+: the hash
def self.from_hash hash
Therapist.new(
version: hash.fetch(:version),
max_df_version: hash[:maxDfVersion],
git: DFGithub.from_hash(hash.fetch(:git))
)
end
# Returns a release from a github object.
# +github_obj+:: The github object. Returns null for prereleases.
def self.from_github github_obj
if github_obj.fetch(:prerelease)
return nil
end
version = github_obj.fetch(:tag_name)
match = version.match(/\Av([\d\.]+)\z/)
if match
Therapist.new(version: match[1])
else
nil
end
end
# Returns the latest Therapist version.
def self.latest
url = "repos/Dwarf-Therapist/Dwarf-Therapist/releases"
releases = get_gh url
releases.each do |release|
release = Therapist.from_github(release)
if release
return release
end
end
nil
end
end
class DFLock < Struct.new(:game, :therapist, keyword_init: true)
include Mergeable
extend Mergeable
# Initializes this DFLock.
def initialize *args, **kw
super *args, **kw
self.game ||= DFWithHackVersions.new
self.therapist ||= Therapist.new
end
# Converts this DFLock to a hash.
def to_h
{
game: self.game.to_h,
therapist: self.therapist.to_h
}
end
# Returns an array containing all versions.
def all_versions
self.game.versions.keys.map {"DF #{_1}"}.to_a + ["DT #{self.therapist.version}"]
end
# Loads this DFLock.
# +cutoff+:: The minimum DF version to load.
def load! cutoff:
self.game.load! cutoff: cutoff
self.therapist.load!
end
# Converts a hash to a DFLock.
# +hash+:: The hash
def self.from_hash hash
DFLock.new(
game: DFWithHackVersions.from_hash(hash.fetch(:game)),
therapist: Therapist.from_hash(hash.fetch(:therapist))
)
end
end
# 0.43 and below has a broken dfhack.
new_df_lock = DFLock.new
new_df_lock.load! cutoff: '0.44'
df_lock_file = File.join(__dir__, 'df.lock.json')
df_lock, df_lock_json = if File.file?(df_lock_file)
json = JSON.parse(File.read(df_lock_file), symbolize_names: true)
[DFLock.from_hash(json), json]
else
[DFLock.new, {}]
end
new_df_lock_json = df_lock.merge(new_df_lock).to_h
json = JSON.pretty_generate(new_df_lock_json)
json << "\n"
STDERR.puts json
File.write(df_lock_file, json)
# See if there were any changes.
changed_paths = []
if normalize_keys(df_lock_json) != normalize_keys(new_df_lock_json)
all_old_versions = df_lock.all_versions
all_new_versions = new_df_lock.all_versions
just_old_versions = all_old_versions - all_new_versions
just_new_versions = all_new_versions - all_old_versions
changes = just_old_versions.zip(just_new_versions)
template = ERB.new(<<-EOF, trim_mode: '<>-')
dwarf-fortress-packages: <%= changes.map {|old, new| '%s -> %s' % [old, new]}.join('; ') %>
Performed the following automatic DF updates:
<% changes.each do |old, new| %>
- <%= old -%> -> <%= new -%>
<% end %>
EOF
changed_paths << {
attrPath: 'dwarf-fortress-packages',
oldVersion: just_old_versions.join('; '),
newVersion: just_new_versions.join('; '),
files: [
File.realpath(df_lock_file)
],
commitMessage: template.result(binding)
}
end
STDOUT.puts JSON.pretty_generate(changed_paths)

View File

@ -1,40 +0,0 @@
#!/usr/bin/env nix-shell
#! nix-shell -i bash -p jq nix coreutils curl
# systems to generate hashes for
systems='linux osx'
if [ $# -eq 0 ]; then
versions="$(curl http://www.bay12games.com/dwarves/ \
| grep 'DWARF FORTRESS CLASSIC ' \
| sed 's/.*DWARF FORTRESS CLASSIC \([0-9.]*\) .*/\1/')"
else
versions="$@"
fi
tmp1="$(mktemp)"
tmp2="$(mktemp)"
for version in $versions; do
for system in $systems; do
echo -n $version,$system,
ver=$(echo $version | sed -e s,^0\.,, | tr . _)
if [[ "$system" = *win* ]] || [[ "$system" = *legacy* ]]; then
ext=zip
else
ext=tar.bz2
fi
nix-prefetch-url \
http://www.bay12games.com/dwarves/df_${ver}_${system}.${ext}
done
done | jq --slurp --raw-input \
'split("\n") | .[:-1] | map(split(",")) |
map({ "version": .[0], "platform": .[1], "sha256": .[2] }) |
group_by(.version) |
map(map({"version": .version, (.platform): .sha256}) | add |
{(.version): .} | map_values(del(.version))) | add' \
> "$tmp1"
# Append $tmp1 to game.json. There should be a better way to handle
# this but all other attempts failed for me.
jq -M --slurpfile a "$tmp1" '. + $a[]' < "$(dirname "$0")/game.json" > "$tmp2"
cat "$tmp2" > "$(dirname "$0")/game.json"

View File

@ -246,28 +246,17 @@ lib.throwIf (enableTWBT' && !enableDFHack) "dwarf-fortress: TWBT requires DFHack
installCheckPhase =
let
commonExpectStatements =
fmod:
lib.optionalString isAtLeast50 ''
expect "Loading audio..."
''
+ lib.optionalString (!fmod && isAtLeast50) ''
expect "Failed to load fmod, trying SDL_mixer"
''
+ lib.optionalString isAtLeast50 ''
expect "Audio loaded successfully!"
''
+ ''
commonExpectStatements = ''
expect "Loading bindings from data/init/interface.txt"
'';
dfHackExpectScript = writeText "dfhack-test.exp" (
''
spawn env NIXPKGS_DF_OPTS=debug xvfb-run $env(out)/bin/dfhack
''
+ commonExpectStatements false
+ commonExpectStatements
+ ''
expect "DFHack is ready. Have a nice day!"
expect "DFHack version ${version}"
expect "DFHack version ${dfhack'.version}"
expect "\[DFHack\]#"
send -- "lua print(os.getenv('out'))\r"
expect "$env(out)"
@ -281,7 +270,7 @@ lib.throwIf (enableTWBT' && !enableDFHack) "dwarf-fortress: TWBT requires DFHack
''
spawn env NIXPKGS_DF_OPTS=debug,${lib.optionalString fmod "fmod"} xvfb-run $env(out)/bin/dwarf-fortress
''
+ commonExpectStatements fmod
+ commonExpectStatements
+ ''
exit 0
''

View File

@ -114,7 +114,7 @@ go() {
# If we make it past here, we want to log.
# shellcheck disable=SC2093
exec -a "$NIXPKGS_DF_EXE" "$NIXPKGS_DF_HOME/$NIXPKGS_DF_EXE"
exec -a "$NIXPKGS_DF_EXE" "$NIXPKGS_DF_HOME/$NIXPKGS_DF_EXE" "$@"
log "Execution of $NIXPKGS_DF_HOME/$NIXPKGS_DF_EXE failed!"
exit 1
}

View File

@ -32,4 +32,4 @@ else
done
fi
go
go "$@"