Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lib: add collectFiles and collectFilesAt #43

Merged
merged 1 commit into from
Dec 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 43 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,57 +146,82 @@ in
symlinks = {
"mods" = "${modpack}/mods";
};
files = {
"config" = "${modpack}/config";
"config/mod1.yml" = "${modpack}/config/mod1.yml";
"config/mod2.conf" = "${modpack}/config/mod2.conf";
# You can add files not on the modpack, of course
"config/server-specific.conf".value = {
example = "foo-bar";
};
};
};
}
```

This will symlink the modpack's final `mods` directory into the server's `mods` directory. You can also do this for `config`, or any files in the modpack you're interested in, in a granular way.
This will symlink the modpack's final `mods` directory into the server's `mods` directory, and copy the specified config files into `config`. You can also do this for any files in the modpack you're interested in, in a granular way.

**Note**: Be sure to use a stable URL (e.g. a git tag/commit) to the manifest, as it changing will cause the derivation to generate a different hash, breaking the build until you change it.

The built modpack also exports a `manifest` attribute, that allows you to get any information from its `pack.toml` file, such as the MC or Modloader version. You can, this way, always sync the server's version with the one the modpack recommends:
Adding config files one by-one is boring. Trying to include an additional mod will also fail, as `mods` is read-only and symlinked as is. To solve these issues, this flake provides a `collectFilesAt` function, that recursively collects every file on the given directory (e.g. `config`), and returns an attribute set in the format `symlinks`/`files` expects. For example:

```nix
{ inputs, ... }:
let
inherit (inputs.nix-minecraft.lib) collectFilesAt;
modpack = pkgs.fetchPackwizModpack {
url = "https://github.com/Misterio77/Modpack/raw/0.2.9/pack.toml";
packHash = "sha256-L5RiSktqtSQBDecVfGj1iDaXV+E90zrNEcf4jtsg+wk=";
};
mcVersion = modpack.manifest.versions.minecraft;
fabricVersion = modpack.manifest.versions.fabric;
serverVersion = lib.replaceStrings [ "." ] [ "_" ] "fabric-${mcVersion}";
in
{
services.minecraft-servers.servers.cool-modpack = {
enable = true;
package = pkgs.fabricServers.${serverVersion}.override { loaderVersion = fabricVersion; };
symlinks = {
"mods" = "${modpack}/mods";
package = pkgs.fabricServers.fabric-1_18_2-0_14_9;
symlinks = collectFilesAt modpack "mods" // {
"mods/FabricProxy-lite.jar" = pkgs.fetchurl rec {
pname = "FabricProxy-Lite";
version = "1.1.6";
url = "https://cdn.modrinth.com/data/8dI2tmqs/versions/v${version}/${pname}-${version}.jar";
hash = "sha256-U+nXvILXlYdx0vgomVDkKxj0dGCtw60qW22EK4FhAJk=";
};
};
files = collectFilesAt modpack "config" // {
"config/server-specific.conf".value = {
example = "foo-bar";
};
};
};
}
```

**Note**: Using `manifest`, by default, will cause [IFD](https://nixos.wiki/wiki/Import_From_Derivation). If you want to avoid IFD while still having access to `manifest`, simply pass a `manifestHash` to the `fetchPackwizModpack` function, it will then fetch the manifest through `builtins.fetchurl`.
**Note**: Calling `collectFilesAt` on a derivation (e.g. the modpack) will cause [IFD](https://nixos.wiki/wiki/Import_From_Derivation).

Additionally, you can override/add files (e.g. server-specific mods) on the pack through `addFiles`. For example:
The built modpack also exports a `manifest` attribute, that allows you to get any information from its `pack.toml` file, such as the MC or Modloader version. You can, this way, always sync the server's version with the one the modpack recommends:

```nix
let
modpack = (pkgs.fetchPackwizModpack {
modpack = pkgs.fetchPackwizModpack {
url = "https://github.com/Misterio77/Modpack/raw/0.2.9/pack.toml";
packHash = "sha256-L5RiSktqtSQBDecVfGj1iDaXV+E90zrNEcf4jtsg+wk=";
}).addFiles {
"mods/FabricProxy-lite.jar" = pkgs.fetchurl rec {
pname = "FabricProxy-Lite";
version = "1.1.6";
url = "https://cdn.modrinth.com/data/8dI2tmqs/versions/v${version}/${pname}-${version}.jar";
hash = "sha256-U+nXvILXlYdx0vgomVDkKxj0dGCtw60qW22EK4FhAJk=";
};
};
mcVersion = modpack.manifest.versions.minecraft;
fabricVersion = modpack.manifest.versions.fabric;
serverVersion = lib.replaceStrings [ "." ] [ "_" ] "fabric-${mcVersion}";
in
{
services.minecraft-servers.servers.cool-modpack = {
enable = true;
package = pkgs.fabricServers.${serverVersion}.override { loaderVersion = fabricVersion; };
symlinks = {
"mods" = "${modpack}/mods";
};
};
}
```

**Note**: Using `manifest`, by default, will cause [IFD](https://nixos.wiki/wiki/Import_From_Derivation). If you want to avoid IFD while still having access to `manifest`, simply pass a `manifestHash` to the `fetchPackwizModpack` function, it will then fetch the manifest through `builtins.fetchurl`.

### Others

All of these packages are also available under `packages`, not just `legacyPackages`.
Expand Down
15 changes: 15 additions & 0 deletions lib/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ let
stringToCharacters
take
versionOlder
nameValuePair
;
inherit (builtins)
match
Expand Down Expand Up @@ -76,4 +77,18 @@ rec {
files = filterAttrs seive (readDir dirPath);
in
filterAttrs (n: v: v != { }) (mapAttrs' collect files);

# Same as collectFiles, but only gathers files from a specific subdirectory
# (e.g. "config")
collectFilesAt = path: subdir: mapAttrs' (n: nameValuePair ("${subdir}/${n}")) (collectFiles "${path}/${subdir}");

# Get all files from a path (e.g. a modpack derivation) and return them in the
# format expected by the files/symlinks module options.
collectFiles = let
mapListToAttrs = fn: fv: list:
lib.listToAttrs (map (x: nameValuePair (fn x) (fv x)) list);
in path:
mapListToAttrs
(x: builtins.unsafeDiscardStringContext (lib.removePrefix "${path}/" x))
(lib.id) (lib.filesystem.listFilesRecursive "${path}");
})