From 81a1bb1cd780b90a4e3b0db2f8062a2d0bf186cb Mon Sep 17 00:00:00 2001 From: purian23 Date: Mon, 18 May 2026 16:51:25 -0400 Subject: [PATCH] fix(Hyprland): Respect legacy conf configs before migrating to lua --- core/internal/config/deployer_test.go | 40 +++++++++++++++++++++++++++ core/internal/config/hyprland_lua.go | 11 ++++++-- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/core/internal/config/deployer_test.go b/core/internal/config/deployer_test.go index d3645b95..20a51ab2 100644 --- a/core/internal/config/deployer_test.go +++ b/core/internal/config/deployer_test.go @@ -11,6 +11,46 @@ import ( "github.com/stretchr/testify/require" ) +func TestCleanupStrayHyprlandConfFile(t *testing.T) { + if os.Getenv("HYPRLAND_INSTANCE_SIGNATURE") == "" { + t.Setenv("HYPRLAND_INSTANCE_SIGNATURE", "test-signature") + } + + t.Run("leaves conf alone when no hyprland.lua present", func(t *testing.T) { + td := t.TempDir() + t.Setenv("HOME", td) + configDir := filepath.Join(td, ".config", "hypr") + require.NoError(t, os.MkdirAll(configDir, 0o755)) + confPath := filepath.Join(configDir, "hyprland.conf") + require.NoError(t, os.WriteFile(confPath, []byte("# legacy user config\n"), 0o644)) + + CleanupStrayHyprlandConfFile(nil) + + assert.FileExists(t, confPath, "must not touch hyprland.conf when user has not migrated") + assert.NoDirExists(t, filepath.Join(configDir, hyprlandBackupDirName)) + }) + + t.Run("moves stray conf into backup when hyprland.lua exists", func(t *testing.T) { + td := t.TempDir() + t.Setenv("HOME", td) + configDir := filepath.Join(td, ".config", "hypr") + require.NoError(t, os.MkdirAll(configDir, 0o755)) + luaPath := filepath.Join(configDir, "hyprland.lua") + require.NoError(t, os.WriteFile(luaPath, []byte("-- dms managed\n"), 0o644)) + confPath := filepath.Join(configDir, "hyprland.conf") + require.NoError(t, os.WriteFile(confPath, []byte("# autogen\n"), 0o644)) + + CleanupStrayHyprlandConfFile(nil) + + assert.NoFileExists(t, confPath) + assert.FileExists(t, luaPath) + entries, err := os.ReadDir(filepath.Join(configDir, hyprlandBackupDirName)) + require.NoError(t, err) + require.Len(t, entries, 1) + assert.FileExists(t, filepath.Join(configDir, hyprlandBackupDirName, entries[0].Name(), "hyprland.conf")) + }) +} + func TestMergeNiriOutputSections(t *testing.T) { cd := &ConfigDeployer{} diff --git a/core/internal/config/hyprland_lua.go b/core/internal/config/hyprland_lua.go index 52281965..30d5e24c 100644 --- a/core/internal/config/hyprland_lua.go +++ b/core/internal/config/hyprland_lua.go @@ -139,9 +139,10 @@ func readExistingHyprlandConfig(configDir string) (data string, sourcePath strin } // CleanupStrayHyprlandConfFile moves a stray ~/.config/hypr/hyprland.conf -// into .dms-backups// when running under Hyprland. Hyprland 0.55 -// auto-generates hyprland.conf when launched without -c, so this is invoked -// from dms run startup to keep the active config tree single-file. +// into .dms-backups// only when hyprland.lua also exists, which +// proves Lua is the live config and the .conf is an autogen Hyprland 0.55 +// produced when launched without -c. If only hyprland.conf exists, the user +// has not migrated and we must leave their config alone. func CleanupStrayHyprlandConfFile(logFn func(format string, v ...any)) { if os.Getenv("HYPRLAND_INSTANCE_SIGNATURE") == "" { return @@ -151,6 +152,10 @@ func CleanupStrayHyprlandConfFile(logFn func(format string, v ...any)) { return } configDir := filepath.Join(home, ".config", "hypr") + luaPath := filepath.Join(configDir, "hyprland.lua") + if _, err := os.Stat(luaPath); err != nil { + return + } confPath := filepath.Join(configDir, "hyprland.conf") if _, err := os.Stat(confPath); err != nil { return