1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
# Makefile for archsetup dotfiles
# GNU Stow operations for managing dotfiles
STOW := stow --target=$(HOME) --no-folding
DOTFILES := $(shell pwd)/dotfiles
# Extract DE from command line (e.g., 'make stow dwm' -> DE=dwm)
DE := $(filter dwm hyprland,$(MAKECMDGOALS))
# Extract DEST from command line for import (e.g., 'make import common' -> DEST=common)
DEST := $(filter common dwm hyprland,$(MAKECMDGOALS))
.PHONY: help deps stow restow reset unstow import test common dwm hyprland
# Default target - show help
help:
@echo "Dotfiles Management (GNU Stow)"
@echo ""
@echo "Usage: make <target> <de|dest>"
@echo ""
@echo "Desktop Environments / Destinations:"
@echo " common Shared configs (all setups)"
@echo " dwm X11/DWM specific"
@echo " hyprland Wayland/Hyprland specific"
@echo ""
@echo "Targets:"
@echo " deps Install dependencies for this project"
@echo " stow Create symlinks (fresh install) - requires DE"
@echo " restow Refresh symlinks (unlink + relink) - requires DE"
@echo " reset Resolve conflicts, keep repo version - requires DE"
@echo " unstow Remove all symlinks - requires DE"
@echo " import Import new app configs into repo (fzf) - requires dest"
@echo " test Run full VM test suite and report results"
@echo ""
@echo "Examples:"
@echo " make stow dwm # Fresh DWM install (common + dwm)"
@echo " make stow hyprland # Fresh Hyprland install (common + hyprland)"
@echo " make restow dwm # Refresh DWM links after git pull"
@echo " make reset hyprland # Resolve conflicts, keep repo version"
@echo " make import common # Import configs to common/"
@echo " make import hyprland # Import configs to hyprland/"
@echo " make test # Run full VM integration test"
@echo ""
# Install project dependencies
deps:
@echo "Installing project dependencies..."
@echo ""
@echo "=== Makefile targets (stow, import) ==="
sudo pacman -S --needed stow fzf
@echo ""
@echo "=== VM testing (make test) ==="
sudo pacman -S --needed qemu-full virt-manager virt-viewer libguestfs \
bridge-utils dnsmasq archiso sshpass socat
@echo ""
@echo "Done. For VM testing, also ensure libvirtd is running:"
@echo " sudo systemctl enable --now libvirtd"
# Prevent 'common', 'dwm' and 'hyprland' from being treated as file targets
common dwm hyprland:
@:
# Validate DE was provided (for stow/restow/reset/unstow)
check-de:
ifeq ($(DE),)
@echo "Error: Desktop environment required (dwm or hyprland)."
@echo ""
@$(MAKE) --no-print-directory help
@exit 1
endif
# Validate DEST was provided (for import)
check-dest:
ifeq ($(DEST),)
@echo "Error: Destination required (common, dwm, or hyprland)."
@echo ""
@$(MAKE) --no-print-directory help
@exit 1
endif
# Stow - create symlinks
stow: check-de
@echo "Stowing common + $(DE)..."
@cd $(DOTFILES) && $(STOW) common
@cd $(DOTFILES) && $(STOW) $(DE)
@echo "Done."
# Restow - refresh symlinks (unlink + relink)
restow: check-de
@echo "Restowing common + $(DE)..."
@cd $(DOTFILES) && $(STOW) --restow common
@cd $(DOTFILES) && $(STOW) --restow $(DE)
@echo "Done."
# Reset - resolve conflicts by adopting then reverting to repo version
reset: check-de
@echo "Resetting common + $(DE)..."
@cd $(DOTFILES) && $(STOW) --adopt common
@cd $(DOTFILES) && $(STOW) --adopt $(DE)
@echo "Reverting adopted files to repo version..."
@git checkout -- dotfiles/
@echo "Done. Symlinks created, repo unchanged."
# Unstow - remove symlinks
unstow: check-de
@echo "Unstowing common + $(DE)..."
@cd $(DOTFILES) && $(STOW) --delete common
@cd $(DOTFILES) && $(STOW) --delete $(DE)
@echo "Done."
# Import - select and import new app configs into repo
import: check-dest
@echo "Select directories to import (Tab to multi-select, Enter to confirm):"
@echo ""
@selections=$$({ \
find $(HOME) -maxdepth 1 -mindepth 1 -name '.*' -type d 2>/dev/null | grep -v '\.cache\|\.local\|\.config' | sed 's|$(HOME)/||'; \
find $(HOME)/.config -maxdepth 1 -mindepth 1 -type d 2>/dev/null | sed 's|$(HOME)/||'; \
find $(HOME)/.local -maxdepth 2 -mindepth 1 -type d 2>/dev/null | sed 's|$(HOME)/||'; \
} | sort -u | fzf --multi --prompt="Import to $(DEST)> " --header="Select configs to import into dotfiles/$(DEST)/"); \
if [ -z "$$selections" ]; then \
echo "No selections made."; \
exit 0; \
fi; \
echo ""; \
for dir in $$selections; do \
src="$(HOME)/$$dir"; \
dest="$(DOTFILES)/$(DEST)/$$dir"; \
if [ -d "$$dest" ]; then \
echo "Skipping $$dir (already exists in dotfiles/$(DEST))"; \
else \
echo "Importing $$dir to $(DEST)..."; \
mkdir -p "$$(dirname $$dest)"; \
mv "$$src" "$$dest"; \
fi; \
done; \
echo ""; \
echo "Restowing $(DEST)..."; \
cd $(DOTFILES) && $(STOW) --restow $(DEST); \
echo ""; \
echo "Done. Don't forget to: git add -A && git commit"
# Test - run full VM integration test suite
test:
@bash scripts/testing/run-test.sh
|