{ config, lib, ... }: with lib; let target = config.krebs.build // { user.name = "root"; }; out = { # TODO deprecate krebs.build.host options.krebs.build.host = mkOption { type = types.host; }; # TODO make krebs.build.profile shell safe options.krebs.build.profile = mkOption { type = types.str; default = "/nix/var/nix/profiles/system"; }; # TODO make krebs.build.target.host :: host options.krebs.build.target = mkOption { type = with types; nullOr str; default = null; }; # TODO deprecate krebs.build.user options.krebs.build.user = mkOption { type = types.user; }; options.krebs.build.source = let raw = types.either types.str types.path; url = types.submodule { options = { url = mkOption { type = types.str; }; rev = mkOption { type = types.str; }; dev = mkOption { type = types.str; }; }; }; in mkOption { type = types.attrsOf (types.either types.str url); apply = let f = mapAttrs (_: value: { string = value; path = toString value; set = f value; }.${typeOf value}); in f; default = {}; }; options.krebs.build.populate = mkOption { type = types.str; default = let source = config.krebs.build.source; target-user = maybeEnv "target_user" "root"; target-host = maybeEnv "target_host" config.krebs.build.host.name; target-path = maybeEnv "target_path" "/var/src"; out = '' #! /bin/sh set -eu verbose() { printf '+%s\n' "$(printf ' %q' "$@")" >&2 "$@" } echo ${shell.escape git-script} \ | ssh ${shell.escape "${target-user}@${target-host}"} -T unset tmpdir trap ' rm "$tmpdir"/* rmdir "$tmpdir" trap - EXIT INT QUIT ' EXIT INT QUIT tmpdir=$(mktemp -dt stockholm.XXXXXXXX) chmod 0755 "$tmpdir" ${concatStringsSep "\n" (mapAttrsToList (name: spec: let dst = removePrefix "symlink:" (get-url spec); in "verbose ln -s ${shell.escape dst} $tmpdir/${shell.escape name}") symlink-specs)} verbose proot \ -b $tmpdir:${shell.escape target-path} \ ${concatStringsSep " \\\n " (mapAttrsToList (name: spec: "-b ${shell.escape "${get-url spec}:${target-path}/${name}"}") file-specs)} \ rsync \ -f ${shell.escape "P /*"} \ ${concatMapStringsSep " \\\n " (name: "-f ${shell.escape "R /${name}"}") (attrNames file-specs)} \ --delete \ -vFrlptD \ ${shell.escape target-path}/ \ ${shell.escape "${target-user}@${target-host}:${target-path}"} ''; get-schema = uri: if substring 0 1 uri == "/" then "file" else head (splitString ":" uri); has-schema = schema: uri: get-schema uri == schema; get-url = spec: { string = spec; path = toString spec; set = get-url spec.url; }.${typeOf spec}; git-specs = filterAttrs (_: spec: has-schema "https" (get-url spec)) source // filterAttrs (_: spec: has-schema "http" (get-url spec)) source // filterAttrs (_: spec: has-schema "git" (get-url spec)) source; file-specs = filterAttrs (_: spec: has-schema "file" (get-url spec)) source; symlink-specs = filterAttrs (_: spec: has-schema "symlink" (get-url spec)) source; git-script = '' #! /bin/sh set -efu verbose() { printf '+%s\n' "$(printf ' %q' "$@")" >&2 "$@" } fetch_git() {( dst_dir=$1 src_url=$2 src_ref=$3 if ! test -e "$dst_dir"; then git clone "$src_url" "$dst_dir" fi cd "$dst_dir" if ! url=$(git config remote.origin.url); then git remote add origin "$src_url" elif test "$url" != "$src_url"; then git remote set-url origin "$src_url" fi # TODO resolve src_ref to commit hash hash=$src_ref if ! test "$(git log --format=%H -1)" = "$hash"; then git fetch origin git checkout "$hash" -- "$dst_dir" git checkout "$hash" fi git clean -dxf )} ${concatStringsSep "\n" (mapAttrsToList (name: spec: toString (map shell.escape [ "verbose" "fetch_git" "${target-path}/${name}" spec.url spec.rev ])) git-specs)} ''; in out; }; }; in out