blob: 8415348246bbf6c623e9d9c34550af949947c846 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
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
''}
''
|