{ config, lib, ... }: with config.krebs.lib; let 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 deprecate krebs.build.user options.krebs.build.user = mkOption { type = types.user; }; options.krebs.build.source = mkOption { type = with types; attrsOf (either str (submodule { options = { url = str; rev = str; }; })); default = {}; }; options.krebs.build.populate = mkOption { type = types.str; default = let target-user = maybeEnv "target_user" "root"; target-host = maybeEnv "target_host" config.krebs.build.host.name; target-port = maybeEnv "target_port" "22"; target-path = maybeEnv "target_path" "/var/src"; out = '' #! /bin/sh set -eu ssh=''${ssh-ssh} verbose() { printf '%s%s\n' "$PS5$(printf ' %q' "$@")" >&2 "$@" } { printf 'PS5=%q%q\n' @ "$PS5" echo ${shell.escape git-script} } | verbose $ssh -p ${shell.escape target-port} \ ${shell.escape "${target-user}@${target-host}"} -T unset tmpdir trap ' rm -f "$tmpdir"/* rmdir "$tmpdir" trap - EXIT INT QUIT ' EXIT INT QUIT tmpdir=$(mktemp -dt stockholm.XXXXXXXX) chmod 0755 "$tmpdir" ${concatStringsSep "\n" (mapAttrsToList (name: symlink: '' verbose ln -s ${shell.escape symlink.target} \ "$tmpdir"/${shell.escape name} '') source-by-method.symlink)} verbose proot \ -b "$tmpdir":${shell.escape target-path} \ ${concatStringsSep " \\\n " (mapAttrsToList (name: file: "-b ${shell.escape "${file.path}:${target-path}/${name}"}" ) source-by-method.file)} \ rsync \ -f ${shell.escape "P /*"} \ ${concatMapStringsSep " \\\n " (name: "-f ${shell.escape "R /${name}"}" ) (attrNames source-by-method.file)} \ --delete \ -vFrlptD \ -e "$ssh -p ${shell.escape target-port}" \ ${shell.escape target-path}/ \ ${shell.escape "${target-user}@${target-host}:${target-path}"} ''; git-script = '' #! /bin/sh set -efu export SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt verbose() { printf '%s%s\n' "$PS5$(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 -f "$hash" fi git clean -dxf )} ${concatStringsSep "\n" (mapAttrsToList (name: git: '' verbose fetch_git ${concatMapStringsSep " " shell.escape [ "${target-path}/${name}" git.url git.rev ]} '') source-by-method.git)} ''; in out; }; }; source-by-method = let known-methods = ["git" "file" "symlink"]; in genAttrs known-methods (const {}) // recursiveUpdate source-by-scheme { git = source-by-scheme.http or {} // source-by-scheme.https or {}; }; source-by-scheme = foldl' (out: { k, v }: recursiveUpdate out { ${v.scheme}.${k} = v; }) {} (mapAttrsToList (k: v: { inherit k v; }) normalized-source); normalized-source = mapAttrs (name: let f = x: getAttr (typeOf x) { path = f (toString x); string = f { url = if substring 0 1 x == "/" then "file://${x}" else x; }; set = let scheme = head (splitString ":" x.url); in recursiveUpdate x { inherit scheme; } // { symlink.target = removePrefix "symlink:" x.url; file.path = # TODO file://host/... assert hasPrefix "file:///" x.url; removePrefix "file://" x.url; }.${scheme} or {}; }; in f) config.krebs.build.source; in out