{ pkgs, lib, ... }:
rec {
mkWrapper = { basePackage, prependFlags ? [], appendFlags ? [], pathAdd ? [], environment ? {}, extraPackages ? [] }: pkgs.symlinkJoin ({
name = "wrapper-${basePackage.name}";
paths = [ basePackage ] ++ extraPackages;
nativeBuildInputs = [ pkgs.makeWrapper ];
postBuild = let
envToWrapperArg = name: config: let
optionStr = attr: lib.showOption ["env" name attr];
unsetArg =
if !config.force
then
(lib.warn ''
${optionStr "value"} is null (indicating unsetting the variable), but ${optionStr "force"} is false. This option will have no effect
'' [])
else ["--unset" config.name];
setArg = let
arg =
if config.force
then "--set"
else "--set-default";
in [arg config.name config.value];
in
if config.value == null
then unsetArg
else setArg;
envArgs = lib.mapAttrsToList envToWrapperArg environment;
# Yes, the arguments are escaped later, yes, this is intended to "double escape",
# so that they are escaped for wrapProgram and for the final binary too.
prependFlagArgs = map (args: ["--add-flags" (lib.escapeShellArg args)]) prependFlags;
appendFlagArgs = map (args: ["--append-flags" (lib.escapeShellArg args)]) appendFlags;
pathArgs = map (p: ["--prefix" "PATH" ":" "${p}/bin"]) pathAdd;
allArgs = lib.flatten (envArgs ++ prependFlagArgs ++ appendFlagArgs ++ pathArgs);
in ''
for file in $out/bin/*; do
wrapProgram \
"$file" \
${lib.escapeShellArgs allArgs}
done
${
lib.concatMapStringsSep "\n"
(p:
if lib.hasAttr "man" p
then "${pkgs.xorg.lndir}/bin/lndir -silent ${p.man} $out"
else "#")
([basePackage] ++ extraPackages)
}
'';
passthru = (basePackage.passhtru or {}) // {unwrapped = basePackage;};
});
escapeTmpFileContents = contents: builtins.replaceStrings ["\n"] ["\\n"] contents;
mkTmpFile = { type ? "f", target, mode ? "0700", user, group, contents }: "${type} \"${target}\" ${mode} ${user} ${group} - ${escapeTmpFileContents contents}";
mkRmTmpFile = { type ? "f", target }: "${if type == "d" then "R" else "r"} ${target}";
tmpFileType = lib.types.submodule ({ config, ... }: {
options = {
enable = lib.mkOption {
type = lib.types.bool;
default = true;
};
type = lib.mkOption { type = lib.types.str; default = "f"; };
mode = lib.mkOption { type = lib.types.str; default = "0400"; };
user = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; };
group = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; };
executable = lib.mkOption {
type = lib.types.bool;
default = false;
};
target = lib.mkOption {
type = lib.types.str;
};
source = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
};
text = lib.mkOption {
type = lib.types.nullOr lib.types.lines;
default = null;
};
};
});
homeFileType = (lib.types.submodule ({ config, name, ... }: {
options = {
enable = lib.mkOption {
type = lib.types.bool;
default = true;
};
type = lib.mkOption { type = lib.types.str; default = "f"; };
mode = lib.mkOption { type = lib.types.str; default = "0400"; };
user = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; };
group = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; };
executable = lib.mkOption {
type = lib.types.bool;
default = false;
};
target = lib.mkOption {
type = lib.types.str;
};
source = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
};
text = lib.mkOption {
type = lib.types.nullOr lib.types.lines;
default = null;
};
};
config = {
target = lib.mkDefault name;
source = lib.mkIf (config.text != null) (lib.mkDefault (pkgs.writeTextFile {
inherit (config) text;
executable = config.executable == true;
name = storeFileName config.target;
}));
};
}));
# Figures out a valid Nix store name for the given path.
storeFileName = path:
let
# All characters that are considered safe. Note "-" is not
# included to avoid "-" followed by digit being interpreted as a
# version.
safeChars = [ "+" "." "_" "?" "=" ] ++ lib.lowerChars ++ lib.upperChars
++ lib.stringToCharacters "0123456789";
empties = l: lib.genList (x: "") (lib.length l);
unsafeInName =
lib.stringToCharacters (lib.replaceStrings safeChars (empties safeChars) path);
safeName = lib.replaceStrings unsafeInName (empties unsafeInName) path;
in "home_" + safeName;
}