Skip to content

Commit

Permalink
writableDirWrapper: init
Browse files Browse the repository at this point in the history
  • Loading branch information
pluiedev committed Dec 2, 2024
1 parent d13c9db commit 0363cb2
Showing 1 changed file with 178 additions and 0 deletions.
178 changes: 178 additions & 0 deletions pkgs/by-name/wr/writableDirWrapper/package.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
{
lib,
writeShellApplication,
xorg,
}:
/**
A wrapper for programs that require a writable directory to function, typically
games or proprietary software that expect read-only resources to be placed alongside
config files and state files (e.g. logs).
# Inputs
*`options`* (Attribute set)
: Set of options for the wrapper.
`name` (String)
: File name of the wrapper.
`version` (String, _optional_)
: Version of the underlying program. When set, version checks will be enabled and existing links will be recreated if they belong to a different version.
`path` (String)
: Path of the directory that would hold the linked data.
`links` (List of attrsets, _optional_)
: List of links from a source directory to a directory relative to the output path.
`src` (String)
: Source directory of the link, usually from the Nix store.
`dst` (String, _optional_)
: Destination directory of the link.
: _Default:_ the output path.
`runtimeInputs` (List of strings or derivations, _optional_)
: Paths containing executables that should be added to the script's `$PATH` variable, making them usable inside the script at runtime.
`runtimeEnv` (Attribute sets of strings, _optional_)
: Environment variables to be set at runtime.
`postLink` (String, _optional_)
: Command to run after (re-)linking. Since links are first created in a temporary directory, `postLink` can be used to remove or add files that will be copied to the output path (for example, when some files need to be excluded from the linked result).
`exec` (String)
: Command to run.
# Type
```
writableDirWrapper ::
{
name :: String;
version? :: String;
path :: String;
links? :: [{ src :: String; dst? :: String }];
runtimeInputs? :: [String|Derivation];
runtimeEnv? :: { ... :: String };
postLink? :: String;
exec :: String
} -> Derivation
```
# Examples
:::{.example}
## `pkgs.writableDirWrapper` usage example
```nix
{
writableDirWrapper,
hello,
}:
writableDirWrapper {
name = "writable-hello";
links = [
{
src = hello;
dst = "hello";
}
];
postLink = ''
echo "Hello world!" | base64 > hello.txt
'';
exec = ''
./hello/bin/hello --greeting=$(<"hello.txt")
'';
}
```
When built and run, this should output:
```console
SGVsbG8gd29ybGQhCg==
```
:::
*/
{
name,
version ? null,
path,
links ? [ ],
runtimeInputs ? [ ],
runtimeEnv ? { },
postLink ? "",
exec,
}:
let
unlinkCommand = link: ''find "${path}/${link.dst or ""}" -type l -lname "${link.src}" -delete'';
linkCommand = link: ''lndir -silent ${link.src} "./${link.dst or ""}"'';
in
writeShellApplication {
inherit name runtimeEnv;

runtimeInputs = runtimeInputs ++ [ xorg.lndir ];

text =
''
relink=false
for arg in "$@"; do
case "$arg" in
--relink-files) relink=true ;;
# Passthrough all other args
*) args+=("$arg") ;;
esac
done
versionFile="${path}/.${name}.version"
if [[ "$relink" = "true" ]]; then
echo "Manually relinking files"
elif [[ ! -d "${path}" ]]; then
echo "Directory ${path} not found. Linking files..."
relink=true
''
+ lib.optionalString (version != null) ''
elif [[ ! -e "$versionFile" ]]; then
echo "Version file not found. Relinking files just to be safe..."
relink=true
elif [[ "${version}" != "$(<"$versionFile")" ]]; then
echo "Current version is not the same as the newest version (${version}). Relinking files"
relink=true
''
+ ''
fi
if [[ "$relink" = "true" ]]; then
mkdir -p "${path}"
if [[ -d "${path}" ]]; then
echo "Removing existing file links"
${lib.concatMapStringsSep "\n" unlinkCommand links}
fi
echo "Linking files"
${lib.optionalString (version != null) ''echo "${version}" > "$versionFile"''}
# In case that postLink needs to remove some links to avoid conflict,
# we first link everything into a temporary directory then move over
pushd "$(mktemp -d)"
${lib.concatMapStringsSep "\n" linkCommand links}
${postLink}
cp -r ./* -t "${path}"
popd
fi
${exec} "''${args[@]}"
'';
}

0 comments on commit 0363cb2

Please sign in to comment.