Skip to content

Commit ffd3865

Browse files
committed
nix: avoid IFD
1 parent 8f84c96 commit ffd3865

1 file changed

Lines changed: 87 additions & 45 deletions

File tree

nix/shell-plugins.nix

Lines changed: 87 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
1-
{ pkgs, lib, config, is-home-manager, ... }:
1+
{
2+
pkgs,
3+
lib,
4+
config,
5+
is-home-manager,
6+
...
7+
}:
28
with lib;
39
let
410
cfg = config.programs._1password-shell-plugins;
511

6-
supported_plugins = splitString "\n" (
7-
lib.readFile "${
8-
# get the list of supported plugin executable names
9-
pkgs.runCommand "op-plugin-list" { }
10-
# 1Password CLI tries to create the config directory automatically, so set a temp XDG_CONFIG_HOME
11-
# since we don't actually need it for this
12-
"mkdir $out && XDG_CONFIG_HOME=$out ${
13-
if cfg.package != null then cfg.package else pkgs._1password-cli
14-
}/bin/op plugin list | cut -d ' ' -f1 | tail -n +2 > $out/plugins.txt"
15-
}/plugins.txt"
16-
);
12+
opPkg = if cfg.package != null then cfg.package else pkgs._1password-cli;
13+
1714
getExeName =
1815
package:
1916
# NOTE: SAFETY: This is okay because the `packages` list is also referred
@@ -22,6 +19,62 @@ let
2219
# compute the dependency tree, even though we're discarding string context here,
2320
# since the packages are still referred to below without discarding string context.
2421
strings.unsafeDiscardStringContext (baseNameOf (getExe package));
22+
23+
mkPluginSupportCheck =
24+
pluginExeNames:
25+
let
26+
configuredFile = pkgs.writeText "op-configured-plugins.txt" (
27+
# ensure trailing newline
28+
lib.concatStringsSep "\n" pluginExeNames + "\n"
29+
);
30+
in
31+
pkgs.runCommand "op-shell-plugins-support-check"
32+
{
33+
nativeBuildInputs = [
34+
pkgs.coreutils
35+
pkgs.gnugrep
36+
pkgs.gawk
37+
pkgs.gnused
38+
];
39+
}
40+
''
41+
set -euo pipefail
42+
43+
export XDG_CONFIG_HOME="$TMPDIR/xdg-config"
44+
mkdir -p "$XDG_CONFIG_HOME"
45+
46+
"${opPkg}/bin/op" plugin list \
47+
| awk 'NR>1 { print $1 }' \
48+
| sed '/^$/d' \
49+
| sort -u > supported.txt
50+
51+
if [ ! -s supported.txt ]; then
52+
echo "ERROR: \`op plugin list\` produced no supported plugins (unexpected output or CLI failure)." >&2
53+
echo "Raw output was:" >&2
54+
"${opPkg}/bin/op" plugin list >&2 || true
55+
exit 1
56+
fi
57+
58+
missing=0
59+
while IFS= read -r plugin; do
60+
[ -z "$plugin" ] && continue
61+
if ! grep -Fxq "$plugin" supported.txt; then
62+
echo "ERROR: Configured plugin '$plugin' is not supported by this op binary (\`${opPkg.name or "op"}\`)." >&2
63+
missing=1
64+
fi
65+
done < "${configuredFile}"
66+
67+
if [ "$missing" -ne 0 ]; then
68+
echo "" >&2
69+
echo "Supported plugins according to \`op plugin list\`:" >&2
70+
cat supported.txt >&2
71+
exit 1
72+
fi
73+
mkdir -p "$out"
74+
echo "Plugin support check passed." > "$out/check.txt"
75+
76+
'';
77+
2578
in
2679
{
2780
options = {
@@ -39,28 +92,17 @@ in
3992
]
4093
'';
4194
description = "CLI Packages to enable 1Password Shell Plugins for; ensure that a Shell Plugin exists by checking the docs: https://developer.1password.com/docs/cli/shell-plugins/";
42-
# this is a bit of a hack to do option validation;
43-
# ensure that the list of packages include only packages
44-
# for which the executable has a supported 1Password Shell Plugin
45-
apply =
46-
package_list:
47-
map
48-
(
49-
package:
50-
if (elem (getExeName package) supported_plugins) then
51-
package
52-
else
53-
abort "${getExeName package} is not a valid 1Password Shell Plugin. A list of supported plugins can be found by running `op plugin list` or at: https://developer.1password.com/docs/cli/shell-plugins/"
54-
)
55-
package_list;
95+
5696
};
5797
};
5898
};
5999

60100
config =
61101
let
102+
62103
# executable names as strings, e.g. `pkgs.gh` => `"gh"`, `pkgs.awscli2` => `"aws"`
63104
pkg-exe-names = map getExeName cfg.plugins;
105+
plugin-support-check = mkPluginSupportCheck pkg-exe-names;
64106
# Explanation:
65107
# Map over `cfg.plugins` (the value of the `plugins` option provided by the user)
66108
# and for each package specified, get the executable name, then create a shell function
@@ -80,20 +122,16 @@ in
80122
# end
81123
# ```
82124
# where `{pkg}` is the executable name of the package
83-
posixFunctions = map
84-
(package: ''
85-
${package}() {
86-
op plugin run -- ${package} "$@";
87-
}
88-
'')
89-
pkg-exe-names;
90-
fishFunctions = map
91-
(package: ''
92-
function ${package} --wraps "${package}" --description "1Password Shell Plugin for ${package}"
93-
op plugin run -- ${package} $argv
94-
end
95-
'')
96-
pkg-exe-names;
125+
posixFunctions = map (package: ''
126+
${package}() {
127+
op plugin run -- ${package} "$@";
128+
}
129+
'') pkg-exe-names;
130+
fishFunctions = map (package: ''
131+
function ${package} --wraps "${package}" --description "1Password Shell Plugin for ${package}"
132+
op plugin run -- ${package} $argv
133+
end
134+
'') pkg-exe-names;
97135
packages = lib.optional (cfg.package != null) cfg.package ++ cfg.plugins;
98136
initExtraPosix = strings.concatStringsSep "\n" posixFunctions;
99137
in
@@ -102,6 +140,7 @@ in
102140
programs.fish.interactiveShellInit = strings.concatStringsSep "\n" fishFunctions;
103141
}
104142
(optionalAttrs is-home-manager {
143+
home.checks = [ plugin-support-check ];
105144
programs = {
106145
# for the Bash and Zsh home-manager modules,
107146
# the initExtra/initContent option is equivalent to Fish's interactiveShellInit
@@ -110,20 +149,23 @@ in
110149
};
111150
home = {
112151
inherit packages;
113-
sessionVariables = { OP_PLUGINS_SOURCED = "1"; };
152+
sessionVariables = {
153+
OP_PLUGINS_SOURCED = "1";
154+
};
114155
};
115156
})
116157
(optionalAttrs (!is-home-manager) {
158+
system.checks = [ plugin-support-check ];
117159
programs = {
118-
bash.interactiveShellInit =
119-
strings.concatStringsSep "\n" posixFunctions;
160+
bash.interactiveShellInit = strings.concatStringsSep "\n" posixFunctions;
120161
zsh.interactiveShellInit = strings.concatStringsSep "\n" posixFunctions;
121162
};
122163
environment = {
123164
systemPackages = packages;
124-
variables = { OP_PLUGINS_SOURCED = "1"; };
165+
variables = {
166+
OP_PLUGINS_SOURCED = "1";
167+
};
125168
};
126169
})
127170
]);
128171
}
129-

0 commit comments

Comments
 (0)