Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit f9cc15d

Browse files
committedApr 15, 2022
Support additional format search paths
via the NIXOS_GENERATORS_FORMAT_SEARCH_PATH environment variable and --format-search-path CLI option. Additionally, introduce the --show-format-search-path option, which causes nixos-generate to print the list of paths it will search for format files.
1 parent adeb359 commit f9cc15d

File tree

2 files changed

+136
-10
lines changed

2 files changed

+136
-10
lines changed
 

‎README.md

+40-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ you can use the `--system` option to create images for other architectures.
111111
`nixos-generators` can be included as a `Flake` input and provides
112112
a `nixos-generate` function for building images as `Flake` outputs. This
113113
approach pins all dependencies and allows for conveniently defining multiple
114-
output types based on one config.
114+
output types based on one config.
115115

116116
An example `flake.nix` demonstrating this approach is below. `vmware` or
117117
`virtualbox` images can be built from the same `configuration.nix` by running
@@ -145,6 +145,45 @@ An example `flake.nix` demonstrating this approach is below. `vmware` or
145145
}
146146
```
147147

148+
## Using custom formats
149+
150+
You can choose a format by telling `nixos-generate` its full path:
151+
152+
```console
153+
nixos-generate --format-path ./path/to/my-format.nix
154+
```
155+
156+
Additionally, you can tell `nixos-generate` where to search for format files by
157+
158+
* Adding `:`-separated paths to the `NIXOS_GENERATORS_FORMAT_SEARCH_PATH`
159+
environment variable, or
160+
* Calling `nixos-generate` with one or more `--format-search-path <path>`
161+
options.
162+
163+
Example:
164+
165+
```console
166+
NIXOS_GENERATORS_FORMAT_SEARCH_PATH=/path/a:/path/b nixos-generate --format-search-path /path/c --format-search-path /path/d -f my-format
167+
```
168+
169+
The above command searches for the file `my-format.nix` in the order:
170+
171+
1. `/path/d`
172+
2. `/path/c`
173+
3. `/path/a`
174+
4. `/path/b`
175+
5. The builtin `nixos-generate` format directory
176+
177+
Note that:
178+
179+
* `nixos-generate` does not recognize a mechanism for escaping `:` characters
180+
in paths specified in `NIXOS_GENERATORS_FORMAT_SEARCH_PATH`; if you have
181+
custom formats that live in a path that contains `:`, specify the path with
182+
`--format-search-path ./path/that/contains/a:or/two:`.
183+
* `nixos-generate` ignores empty strings in the list of format search paths
184+
(`nixos-generate --format-search-path ''`).
185+
* Format names cannot be empty and cannot contain `/` elements.
186+
148187
### License
149188

150189
This project is licensed under the [MIT License](LICENSE).

‎nixos-generate

+96-9
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,27 @@ set -euo pipefail
44
## Configuration
55

66
readonly libexec_dir="${0%/*}"
7-
readonly format_dir=$libexec_dir/formats
87

98
configuration=${NIXOS_CONFIG:-$libexec_dir/configuration.nix}
109
flake_uri=
1110
flake_attr=
11+
format=
1212
format_path=
1313
target_system=
1414
cores=
1515
run=
16+
list_formats=false
17+
show_format_search_path=false
1618
nix_args=(
1719
"$libexec_dir/nixos-generate.nix"
1820
)
1921
has_outlink=false
2022
nix_build_args=()
2123

24+
# `printf' rather than `<<<' to avoid introducing a spurious trailing newline
25+
mapfile -t -d : format_dirs < <(printf -- '%s' "${NIXOS_GENERATORS_FORMAT_SEARCH_PATH:-}")
26+
format_dirs+=("$libexec_dir/formats")
27+
2228
## Functions
2329

2430
showUsage() {
@@ -34,7 +40,11 @@ Options:
3440
selects the nixos configuration to build, using flake uri like "~/dotfiles#my-config"
3541
* -f, --format NAME: select one of the pre-determined formats
3642
* --format-path PATH: pass a custom format
43+
* --format-search-path DIR:
44+
prepend a directory to the list of directories ${0##*/} searches for format definitions
3745
* --list: list the available built-in formats
46+
* --show-format-search-path:
47+
list the directories ${0##*/} searches for format files
3848
* --run: runs the configuration in a VM
3949
only works for the "vm" and "vm-nogui" formats
4050
* --show-trace: show more detailed nix evaluation location information
@@ -47,11 +57,70 @@ USAGE
4757
}
4858

4959
listFormats() {
50-
for format in "$format_dir"/*.nix; do
51-
basename "$format" ".nix"
60+
local -A formats
61+
local format_dir format_file format
62+
63+
for format_dir in "${format_dirs[@]}"; do
64+
if [[ -n $format_dir ]]; then
65+
for format_file in "$format_dir"/*.nix; do
66+
if [[ -f "$format_file" ]]; then
67+
format=$(basename "$format_file" ".nix")
68+
formats["$format"]=1
69+
fi
70+
done
71+
fi
72+
done
73+
74+
for format in "${!formats[@]}"; do
75+
printf -- '%s\n' "$format"
76+
done | sort
77+
}
78+
79+
showFormatSearchPath() {
80+
local -i pos=1
81+
local format_dir
82+
83+
for format_dir in "${format_dirs[@]}"; do
84+
if [[ -n $format_dir ]]; then
85+
printf -- '%d. "%q"\n' "$(( pos++ ))" "$format_dir"
86+
fi
5287
done
5388
}
5489

90+
validateFormat() {
91+
case "${1:-}" in
92+
*/* | '')
93+
abort "not a valid format name: ${1:-<empty>}"
94+
return 1
95+
;;
96+
esac
97+
}
98+
99+
findFormat() {
100+
local format="${1?}"
101+
shift
102+
103+
validateFormat "$format" || return
104+
105+
local -n ref_var="${1:-format_file}"
106+
shift
107+
108+
local format_dir maybe_format_file
109+
110+
for format_dir in "${format_dirs[@]}"; do
111+
if [[ -n $format_dir ]]; then
112+
maybe_format_file="${format_dir}/${format}.nix"
113+
114+
if [[ -f "$maybe_format_file" ]]; then
115+
ref_var="$maybe_format_file"
116+
return
117+
fi
118+
fi
119+
done
120+
121+
abort "unable to locate file for format: $format"
122+
}
123+
55124
abort() {
56125
echo "aborted: $*" >&2
57126
exit 1
@@ -84,27 +153,33 @@ while [[ $# -gt 0 ]]; do
84153
shift 2
85154
;;
86155
-f | --format)
87-
format_path=$format_dir/$2.nix
156+
format="$2"
88157
shift
89158
;;
90159
--format-path)
91160
format_path=$2
92161
shift
93162
;;
163+
--format-search-path)
164+
format_dirs=("$2" "${format_dirs[@]}")
165+
shift
166+
;;
94167
--help)
95168
showUsage
96169
exit
97170
;;
98171
--list)
99-
listFormats
100-
exit
172+
list_formats=true
173+
show_format_search_path=false
174+
;;
175+
--show-format-search-path)
176+
list_formats=false
177+
show_format_search_path=true
101178
;;
102179
--run)
103180
run=1
104181
# default to the VM format
105-
if [[ -z $format_path ]]; then
106-
format_path=$format_dir/vm.nix
107-
fi
182+
format="${format:-vm}"
108183
;;
109184
--show-trace)
110185
nix_args+=(--show-trace)
@@ -129,11 +204,23 @@ while [[ $# -gt 0 ]]; do
129204
shift
130205
done
131206

207+
if $list_formats; then
208+
listFormats
209+
exit
210+
elif $show_format_search_path; then
211+
showFormatSearchPath
212+
exit
213+
fi
214+
132215
if ! $has_outlink; then
133216
nix_build_args+=(--no-out-link)
134217
fi
135218

136219
if [[ -z $format_path ]]; then
220+
if [[ -n $format ]] ;then
221+
findFormat "$format" format_path
222+
fi
223+
137224
abort "missing format. use --help for more details"
138225
fi
139226

0 commit comments

Comments
 (0)
Please sign in to comment.