refactor: move state migration to pre-flight, fix XDG hardcoding, and prevent Nix store bloat

This commit is contained in:
Bernardo Magri
2026-04-06 21:37:24 +01:00
parent 0194569a42
commit db6bdd8495
5 changed files with 114 additions and 90 deletions

View File

@@ -0,0 +1,83 @@
#!/usr/bin/env bash
# Nomarchy Pre-flight State Migration
# Migrates legacy state files into the unified state.json before Nix evaluation
STATE_DIR="$HOME/.config/home-manager"
OLD_TOGGLES_DIR="$HOME/.local/state/nomarchy/toggles"
IDLE_STATE_FILE="$STATE_DIR/idle-state.json"
NIGHTLIGHT_STATE_FILE="$STATE_DIR/hyprsunset-state.json"
HYPRLAND_STATE_FILE="$STATE_DIR/hyprland-state.json"
THEME_STATE_FILE="$STATE_DIR/theme-state.nix"
WALLPAPER_STATE_FILE="$STATE_DIR/wallpaper-state.nix"
FONT_STATE_FILE="$STATE_DIR/font-state.nix"
NEW_STATE_FILE="$STATE_DIR/state.json"
# We expect jq to be in PATH (it's a dependency of nomarchy-scripts)
JQ="jq"
mkdir -p "$(dirname "$NEW_STATE_FILE")"
[[ ! -f $NEW_STATE_FILE ]] && echo "{}" > "$NEW_STATE_FILE"
# 1. Migrate .local/state/nomarchy/toggles
if [[ -d $OLD_TOGGLES_DIR ]]; then
for file in "$OLD_TOGGLES_DIR"/*; do
[[ -e "$file" ]] || continue
filename=$(basename "$file")
case "$filename" in
suspend-off)
$JQ '.suspend = false' "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
;;
screensaver-off)
$JQ '.screensaver = false' "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
;;
skip-vscode-theme-changes)
$JQ '.skipVsCodeTheme = true' "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
;;
esac
rm "$file"
done
rmdir "$OLD_TOGGLES_DIR" 2>/dev/null || true
fi
# 2. Migrate existing JSON state files
if [[ -f $IDLE_STATE_FILE ]]; then
ENABLED=$($JQ '.enabled' "$IDLE_STATE_FILE")
if [[ "$ENABLED" == "true" || "$ENABLED" == "false" ]]; then
$JQ ".idle = $ENABLED" "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
fi
rm "$IDLE_STATE_FILE"
fi
if [[ -f $NIGHTLIGHT_STATE_FILE ]]; then
ENABLED=$($JQ '.enabled' "$NIGHTLIGHT_STATE_FILE")
TEMP=$($JQ '.temperature' "$NIGHTLIGHT_STATE_FILE")
$JQ ".nightlight = $ENABLED | .nightlightTemperature = $TEMP" "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
rm "$NIGHTLIGHT_STATE_FILE"
fi
if [[ -f $HYPRLAND_STATE_FILE ]]; then
GAPS_OUT=$($JQ '.gaps_out' "$HYPRLAND_STATE_FILE")
GAPS_IN=$($JQ '.gaps_in' "$HYPRLAND_STATE_FILE")
BORDER_SIZE=$($JQ '.border_size' "$HYPRLAND_STATE_FILE")
$JQ ".hyprland = {\"gaps_out\": $GAPS_OUT, \"gaps_in\": $GAPS_IN, \"border_size\": $BORDER_SIZE}" "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
rm "$HYPRLAND_STATE_FILE"
fi
# 3. Migrate plaintext string state files
if [[ -f $THEME_STATE_FILE ]]; then
THEME=$(cat "$THEME_STATE_FILE" | tr -d '\n')
$JQ ".theme = \"$THEME\"" "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
rm "$THEME_STATE_FILE"
fi
if [[ -f $WALLPAPER_STATE_FILE ]]; then
WALLPAPER=$(cat "$WALLPAPER_STATE_FILE" | tr -d '\n')
$JQ ".wallpaper = \"$WALLPAPER\"" "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
rm "$WALLPAPER_STATE_FILE"
fi
if [[ -f $FONT_STATE_FILE ]]; then
FONT=$(cat "$FONT_STATE_FILE" | tr -d '\n')
$JQ ".font = \"$FONT\"" "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
rm "$FONT_STATE_FILE"
fi

View File

@@ -32,9 +32,9 @@ in
./swayosd.nix
];
colorScheme = palettes.${config.nomarchy.theme} or palettes.nord;
colorScheme = lib.mkDefault (palettes.${config.nomarchy.theme} or palettes.nord);
home.packages = with pkgs; [
home.packages = lib.mkDefault (with pkgs; [
firefox
xfce.thunar
imv
@@ -55,10 +55,10 @@ in
nerd-fonts.roboto-mono
nerd-fonts.fira-code
nerd-fonts.ubuntu-mono
] ++ userPackages;
] ++ userPackages);
home.shellAliases = {
home.shellAliases = lib.mkDefault {
sys-update = "sudo nixos-rebuild switch --flake /etc/nixos#default --impure";
env-update = "home-manager switch --flake /etc/nixos#default --impure";
env-update = "nomarchy-preflight-migration && home-manager switch --flake /etc/nixos#default --impure";
};
}

View File

@@ -22,83 +22,6 @@ let
in
{
config = {
home.activation.migrateNomarchyState = lib.hm.dag.entryAfter ["writeBoundary"] ''
OLD_TOGGLES_DIR="${config.home.homeDirectory}/.local/state/nomarchy/toggles"
IDLE_STATE_FILE="${stateDir}/idle-state.json"
NIGHTLIGHT_STATE_FILE="${stateDir}/hyprsunset-state.json"
HYPRLAND_STATE_FILE="${stateDir}/hyprland-state.json"
THEME_STATE_FILE="${stateDir}/theme-state.nix"
WALLPAPER_STATE_FILE="${stateDir}/wallpaper-state.nix"
FONT_STATE_FILE="${stateDir}/font-state.nix"
NEW_STATE_FILE="${stateDir}/state.json"
JQ="${pkgs.jq}/bin/jq"
mkdir -p "$(dirname "$NEW_STATE_FILE")"
[[ ! -f $NEW_STATE_FILE ]] && echo "{}" > "$NEW_STATE_FILE"
# 1. Migrate .local/state/nomarchy/toggles (empty 'off' flag files)
if [[ -d $OLD_TOGGLES_DIR ]]; then
for file in "$OLD_TOGGLES_DIR"/*; do
[[ -e "$file" ]] || continue
filename=$(basename "$file")
case "$filename" in
suspend-off)
$JQ '.suspend = false' "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
;;
screensaver-off)
$JQ '.screensaver = false' "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
;;
skip-vscode-theme-changes)
$JQ '.skipVsCodeTheme = true' "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
;;
esac
rm "$file"
done
rmdir "$OLD_TOGGLES_DIR" 2>/dev/null || true
fi
# 2. Migrate existing JSON state files
if [[ -f $IDLE_STATE_FILE ]]; then
ENABLED=$($JQ '.enabled' "$IDLE_STATE_FILE")
$JQ ".idle = $ENABLED" "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
rm "$IDLE_STATE_FILE"
fi
if [[ -f $NIGHTLIGHT_STATE_FILE ]]; then
ENABLED=$($JQ '.enabled' "$NIGHTLIGHT_STATE_FILE")
TEMP=$($JQ '.temperature' "$NIGHTLIGHT_STATE_FILE")
$JQ ".nightlight = $ENABLED | .nightlightTemperature = $TEMP" "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
rm "$NIGHTLIGHT_STATE_FILE"
fi
if [[ -f $HYPRLAND_STATE_FILE ]]; then
GAPS_OUT=$($JQ '.gaps_out' "$HYPRLAND_STATE_FILE")
GAPS_IN=$($JQ '.gaps_in' "$HYPRLAND_STATE_FILE")
BORDER_SIZE=$($JQ '.border_size' "$HYPRLAND_STATE_FILE")
$JQ ".hyprland = {\"gaps_out\": $GAPS_OUT, \"gaps_in\": $GAPS_IN, \"border_size\": $BORDER_SIZE}" "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
rm "$HYPRLAND_STATE_FILE"
fi
# 3. Migrate plaintext string state files
if [[ -f $THEME_STATE_FILE ]]; then
THEME=$(cat "$THEME_STATE_FILE" | tr -d '\n')
$JQ ".theme = \"$THEME\"" "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
rm "$THEME_STATE_FILE"
fi
if [[ -f $WALLPAPER_STATE_FILE ]]; then
WALLPAPER=$(cat "$WALLPAPER_STATE_FILE" | tr -d '\n')
$JQ ".wallpaper = \"$WALLPAPER\"" "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
rm "$WALLPAPER_STATE_FILE"
fi
if [[ -f $FONT_STATE_FILE ]]; then
FONT=$(cat "$FONT_STATE_FILE" | tr -d '\n')
$JQ ".font = \"$FONT\"" "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
rm "$FONT_STATE_FILE"
fi
'';
nomarchy = {
toggles = {
suspend = togglesState.suspend or true;

View File

@@ -1,4 +1,4 @@
{ config, ... }:
{ config, lib, ... }:
{
xdg.configFile."nomarchy/current/theme" = {
@@ -16,7 +16,20 @@
xdg.configFile."nomarchy/branding/icon.txt".source = ../../assets/branding/icon.txt;
# Expose all themes to the system via local share for script accessibility
xdg.dataFile."nomarchy/themes".source = ../../assets/themes;
# We filter out images to prevent Nix Store bloat
xdg.dataFile."nomarchy/themes".source = builtins.path {
name = "nomarchy-themes-no-images";
path = ../../assets/themes;
filter = path: type:
let
baseName = baseNameOf path;
in
! (type == "regular" && (
lib.hasSuffix ".jpg" baseName ||
lib.hasSuffix ".png" baseName ||
lib.hasSuffix ".jpeg" baseName
));
};
# Nautilus python extensions
xdg.dataFile."nautilus-python/extensions/localsend.py".source = ../../assets/nautilus-python/extensions/localsend.py;

View File

@@ -13,7 +13,7 @@ let
fi
'';
nomarchy-font-selector = pkgs.writeShellScriptBin "nomarchy-font-selector" ''
STATE_DIR="$HOME/.config/home-manager"
STATE_DIR="${config.home.homeDirectory}/.config/home-manager"
STATE_FILE="$STATE_DIR/state.json"
mkdir -p "$STATE_DIR"
@@ -30,18 +30,23 @@ let
fi
'';
nomarchy-wallpaper-selector = pkgs.writeShellScriptBin "nomarchy-wallpaper-selector" ''
STATE_DIR="$HOME/.config/home-manager"
STATE_DIR="${config.home.homeDirectory}/.config/home-manager"
STATE_FILE="$STATE_DIR/state.json"
THEMES_DIR="$HOME/.local/share/nomarchy/themes"
THEMES_DIR="${config.xdg.dataHome}/nomarchy/themes"
mkdir -p "$STATE_DIR"
[[ ! -f $STATE_FILE ]] && echo "{}" > "$STATE_FILE"
# List all images in all themes backgrounds
WALLPAPERS=$(find "$THEMES_DIR" -type f \( -name "*.jpg" -o -name "*.png" \))
# We search in the system-wide flake source for distro wallpapers to avoid Nix Store bloat
WALLPAPERS=$(find "${config.xdg.dataHome}/nomarchy/themes" -type f \( -name "*.jpg" -o -name "*.png" \) 2>/dev/null)
DISTRO_THEMES="/etc/nixos/nomarchy/assets/themes"
if [ -d "$DISTRO_THEMES" ]; then
WALLPAPERS="$WALLPAPERS\n$(find "$DISTRO_THEMES" -type f \( -name "*.jpg" -o -name "*.png" \))"
fi
# Include user themes if they exist
if [ -d "$HOME/.config/nomarchy/themes" ]; then
WALLPAPERS="$WALLPAPERS\n$(find "$HOME/.config/nomarchy/themes" -type f \( -name "*.jpg" -o -name "*.png" \))"
if [ -d "${config.home.homeDirectory}/.config/nomarchy/themes" ]; then
WALLPAPERS="$WALLPAPERS\n$(find "${config.home.homeDirectory}/.config/nomarchy/themes" -type f \( -name "*.jpg" -o -name "*.png" \))"
fi
SELECTED_WP=$(echo -e "$WALLPAPERS" | walker --dmenu)