diff --git a/scripts/nix/README.md b/scripts/nix/README.md index 1836038..69d06d1 100644 --- a/scripts/nix/README.md +++ b/scripts/nix/README.md @@ -22,7 +22,7 @@ It is invoked during package installation (Arch/Debian/Fedora scriptlets) and ca The entry point sources small, focused modules from *scripts/nix/lib/*: -- *config.sh* — configuration defaults (installer URL, retry timing) +- *bootstrap_config.sh* — configuration defaults (installer URL, retry timing) - *detect.sh* — container detection helpers - *path.sh* — PATH adjustments and `nix` binary resolution helpers - *symlinks.sh* — user/global symlink helpers for stable `nix` discovery diff --git a/scripts/nix/init.sh b/scripts/nix/init.sh index 9371ff7..f2fa900 100755 --- a/scripts/nix/init.sh +++ b/scripts/nix/init.sh @@ -1,21 +1,23 @@ #!/usr/bin/env bash set -euo pipefail -# shellcheck source=lib/config.sh +# shellcheck source=lib/bootstrap_config.sh # shellcheck source=lib/detect.sh # shellcheck source=lib/path.sh # shellcheck source=lib/symlinks.sh # shellcheck source=lib/users.sh # shellcheck source=lib/install.sh +# shellcheck source=lib/nix_conf_file.sh SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -source "${SCRIPT_DIR}/lib/config.sh" +source "${SCRIPT_DIR}/lib/bootstrap_config.sh" source "${SCRIPT_DIR}/lib/detect.sh" source "${SCRIPT_DIR}/lib/path.sh" source "${SCRIPT_DIR}/lib/symlinks.sh" source "${SCRIPT_DIR}/lib/users.sh" source "${SCRIPT_DIR}/lib/install.sh" +source "${SCRIPT_DIR}/lib/nix_conf_file.sh" echo "[init-nix] Starting Nix initialization..." @@ -26,6 +28,7 @@ main() { ensure_nix_on_path if [[ "${EUID:-0}" -eq 0 ]]; then + nixconf_ensure_experimental_features ensure_global_nix_symlinks "$(resolve_nix_bin 2>/dev/null || true)" else ensure_user_nix_symlink "$(resolve_nix_bin 2>/dev/null || true)" @@ -106,6 +109,10 @@ main() { # ------------------------------------------------------------------------- ensure_nix_on_path + if [[ "${EUID:-0}" -eq 0 ]]; then + nixconf_ensure_experimental_features + fi + local nix_bin_post nix_bin_post="$(resolve_nix_bin 2>/dev/null || true)" diff --git a/scripts/nix/lib/config.sh b/scripts/nix/lib/bootstrap_config.sh similarity index 100% rename from scripts/nix/lib/config.sh rename to scripts/nix/lib/bootstrap_config.sh diff --git a/scripts/nix/lib/nix_conf_file.sh b/scripts/nix/lib/nix_conf_file.sh new file mode 100644 index 0000000..3e94b24 --- /dev/null +++ b/scripts/nix/lib/nix_conf_file.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Prevent double-sourcing +if [[ -n "${PKGMGR_NIX_CONF_FILE_SH:-}" ]]; then + return 0 +fi +PKGMGR_NIX_CONF_FILE_SH=1 + +nixconf_file_path() { + echo "/etc/nix/nix.conf" +} + +nixconf_ensure_experimental_features() { + local nix_conf want + nix_conf="$(nixconf_file_path)" + want="experimental-features = nix-command flakes" + + mkdir -p /etc/nix + + if [[ ! -f "${nix_conf}" ]]; then + echo "[nix-conf] Creating ${nix_conf} with: ${want}" + printf "%s\n" "${want}" >"${nix_conf}" + return 0 + fi + + if grep -qE '^\s*experimental-features\s*=' "${nix_conf}"; then + if grep -qE '^\s*experimental-features\s*=.*\bnix-command\b' "${nix_conf}" \ + && grep -qE '^\s*experimental-features\s*=.*\bflakes\b' "${nix_conf}"; then + echo "[nix-conf] experimental-features already correct" + return 0 + fi + + echo "[nix-conf] Extending experimental-features in ${nix_conf}" + + local current + current="$(grep -E '^\s*experimental-features\s*=' "${nix_conf}" | head -n1 | cut -d= -f2-)" + current="$(echo "${current}" | xargs)" # trim + + # Build a merged feature string without duplicates (simple token set) + local merged="nix-command flakes" + local token + for token in ${current}; do + if [[ " ${merged} " != *" ${token} "* ]]; then + merged="${merged} ${token}" + fi + done + + sed -i "s|^\s*experimental-features\s*=.*|experimental-features = ${merged}|" "${nix_conf}" + return 0 + fi + + echo "[nix-conf] Appending to ${nix_conf}: ${want}" + printf "\n%s\n" "${want}" >>"${nix_conf}" +}