summaryrefslogtreecommitdiffstats
path: root/default.nix
diff options
context:
space:
mode:
authortv <tv@shackspace.de>2015-07-07 05:55:28 +0200
committertv <tv@shackspace.de>2015-07-07 05:55:28 +0200
commit366373e9c6d20501e0756a7e97cced2cb96d447d (patch)
tree94d4afccec8b669ea7564fed069513807fd4ff8b /default.nix
parent9c2bc5b4d0c6a87d5902eea3c3838d28dfe89a85 (diff)
deploy: refactor to use modified/*/paths.nix
Diffstat (limited to 'default.nix')
-rw-r--r--default.nix151
1 files changed, 151 insertions, 0 deletions
diff --git a/default.nix b/default.nix
new file mode 100644
index 00000000..84153482
--- /dev/null
+++ b/default.nix
@@ -0,0 +1,151 @@
+{ system-name
+, rsync-target ? null
+, deploy-target ? null
+}:
+
+# TODO assert that only one of rsync-target or deploy-target is not null
+
+with builtins;
+assert (typeOf system-name == "string");
+with import <nixpkgs/lib>;
+let
+ paths-file = toPath "${dirOf __curPos.file}/modules/${system-name}/paths.nix";
+
+ paths = import paths-file;
+
+ prefetch.file = ''
+ echo "$prefetch_in_url"
+ '';
+
+ prefetch.git = ''
+ ${concatMapStringsSep "\n" (attr-name: ''
+ case ''${prefetch_in_${escapeShellArg attr-name}-?} in \?)
+ printf '%s: %s: missing attribute: %s' \
+ ${escapeShellArg paths-file} \
+ "$prefetch_name" \
+ ${escapeShellArg attr-name} \
+ >&2
+ return 1
+ esac
+ '') [ "rev" "url" "cache" ]}
+
+ git_rev=$prefetch_in_rev
+ git_url=$prefetch_in_url
+
+ # cache_dir points to a (maybe non-existent) directory, where a shared cache of
+ # the repository should be maintained. The shared cache is used to create
+ # multiple working trees of the repository.
+ cache_dir=$prefetch_in_cache/$(echo "$git_url" | urlencode)
+ cache_git() {
+ git --git-dir="$cache_dir" "$@"
+ }
+
+ # work_dir points to a (maybe non-existent) directory, where a specific
+ # revision of the repository is checked out.
+ # XXX this is probably a bad idea if git_rev is not a commit
+ work_dir=$cache_dir-$(cache_git rev-parse --verify "$git_rev" | urlencode)
+ work_git() {
+ git -C "$work_dir" "$@"
+ }
+
+ is_up_to_date() {
+ test -d "$cache_dir" &&
+ test -d "$work_dir" &&
+ test "$(cache_git rev-parse --verify "$git_rev")" = "$git_rev" &&
+ test "$(work_git rev-parse --verify HEAD)" = "$git_rev"
+ }
+
+ # Notice how the remote name "origin" has been chosen arbitrarily, but must be
+ # kept in sync with the default value of nixpkgs.rev.
+ if ! is_up_to_date; then
+ if ! test -d "$cache_dir"; then
+ mkdir -p "$cache_dir"
+ cache_git init --bare
+ fi
+ if ! cache_git_url=$(cache_git config remote.origin.url); then
+ cache_git remote add origin "$git_url"
+ elif test "$cache_git_url" != "$git_url"; then
+ cache_git remote set-url origin "$git_url"
+ fi
+ cache_git fetch origin
+ if ! test -d "$work_dir"; then
+ git clone -n --shared "$cache_dir" "$work_dir"
+ fi
+ commit_name=$(cache_git rev-parse --verify "$git_rev")
+ work_git checkout "$commit_name" -- "$(readlink -f "$work_dir")"
+ work_git checkout -q "$commit_name"
+ work_git submodule init
+ work_git submodule update
+ fi
+ work_git clean -dxf
+
+ echo "$work_dir"
+ '';
+
+
+ f = pkg-name: pkg-spec:
+ let
+ types = attrNames pkg-spec;
+ type = elemAt types 0;
+ in
+ assert (length types == 1); # there can be only one source type
+ ''
+ out=$(${concatStringsSep " \\\n" (mapAttrsToList (k: v:
+ "prefetch_in_${escapeShellArg k}=${escapeShellArg (toString v)}") pkg-spec.${type})} \
+ prefetch_name=${escapeShellArg pkg-name} \
+ __prefetch_${escapeShellArg type})
+ printf '%s=%s\n' \
+ ${escapeShellArg pkg-name} \
+ "$out"
+ '';
+in
+''
+#! /bin/sh
+set -euf
+
+PATH=${toString ./.}/bin:$PATH
+export PATH
+
+__prefetch_file() {
+${prefetch.file}
+}
+__prefetch_git() {
+${prefetch.git}
+}
+
+# TODO make sure x contains only sane chars
+x=$(${concatStrings (mapAttrsToList f paths)})
+
+${optionalString (rsync-target != null) ''
+ proot $(echo "$x" | sed -n 's@^\([^=]\+\)=\(.*\)@-b \2:/shitment/\1@p') \
+ rsync --delete --delete-excluded \
+ --filter='- /*/.git' \
+ --rsync-path='mkdir -p -m 0700 /shitment/ && rsync' \
+ -vaz \
+ --no-owner \
+ --no-group \
+ '/shitment/' \
+ ${escapeShellArg rsync-target}
+''}
+
+
+${optionalString (deploy-target != null) ''
+ system_path=$(proot $(echo "$x" | sed -n 's@^\([^=]\+\)=\(.*\)@-b \2:/shitment/\1@p') \
+ env \
+ NIX_PATH=/shitment \
+ NIXOS_CONFIG=/shitment/modules/${escapeShellArg system-name} \
+ nix-build -A system --no-out-link '<nixpkgs/nixos>')
+
+ system_name=${escapeShellArg system-name}
+ target=${escapeShellArg deploy-target}
+
+ nix-copy-closure --gzip --to "$target" "$system_path"
+
+ secrets_root=${toString ./.}/secrets \
+ config_root=${toString ./.} \
+ copy-secrets "$system_name" "$target"
+
+ ssh ''${NIX_SSHOPTS-} "$target" "$system_path/bin/switch-to-configuration" switch
+''}
+
+''