From 6e5b2d9e8014b5572e3367937a329e7053458d34 Mon Sep 17 00:00:00 2001 From: DDoSolitary Date: Thu, 12 Dec 2024 05:13:27 +0800 Subject: [PATCH] home-manager: support username with special chars (#5609) The home manager script fails when $USER contains special characters. For example, my work PC is managed by company's LDAP and username is \). When running home-manager switch I get the following error: ``` error: flake 'path:/home///.config/home-manager' does not provide attribute 'packages.x86_64-linux.homeConfigurations."\".activationPackage', 'legacyPackages.x86_64-linux.homeConfigurations."\".activationPackage' or 'homeConfigurations."\".activationPackage' Did you mean ? ``` There are two types of strings that need escaping: strings in Nix expressions (e.g. home.nix generated by home-manager init) they need backslashes before special chars flake URI (passed to nix build) they need URI's percent encoding, luckily jq supports that --- home-manager/home-manager | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/home-manager/home-manager b/home-manager/home-manager index 712954476..300d44e49 100644 --- a/home-manager/home-manager +++ b/home-manager/home-manager @@ -52,6 +52,11 @@ function hasFlakeSupport() { | grep -q nix-command } +# Escape string for use in Nix files. +function escapeForNix() { + printf %s "$1" | sed 's/["$\\]/\\\0/g' +} + # Attempts to set the HOME_MANAGER_CONFIG global variable. # # If no configuration file can be found then this function will print @@ -201,7 +206,7 @@ function setFlakeAttribute() { # Check FQDN, long, and short hostnames; long first to preserve # pre-existing behaviour in case both happen to be defined. for n in "$USER@$(hostname -f)" "$USER@$(hostname)" "$USER@$(hostname -s)"; do - if [[ "$(nix eval "$flake#homeConfigurations" --apply "x: x ? \"$n\"")" == "true" ]]; then + if [[ "$(nix eval "$flake#homeConfigurations" --apply "x: x ? \"$(escapeForNix "$n")\"")" == "true" ]]; then name="$n" if [[ -v VERBOSE ]]; then echo "Using flake homeConfiguration for $name" @@ -210,7 +215,7 @@ function setFlakeAttribute() { done ;; esac - export FLAKE_CONFIG_URI="$flake#homeConfigurations.\"$name\"" + export FLAKE_CONFIG_URI="$flake#homeConfigurations.\"$(printf %s "$name" | jq -sRr @uri)\"" fi } @@ -349,8 +354,8 @@ function doInit() { { # Home Manager needs a bit of information about you and the paths it should # manage. - home.username = "$USER"; - home.homeDirectory = "$HOME"; + home.username = "$(escapeForNix "$USER")"; + home.homeDirectory = "$(escapeForNix "$HOME")"; $xdgVars # This value determines the Home Manager release that your configuration is # compatible with. This helps avoid breakage when a new Home Manager release @@ -439,7 +444,7 @@ EOF mkdir -p "$confDir" cat > "$flakeFile" < "$HOME_MANAGER_CONFIG" <