summaryrefslogtreecommitdiff
path: root/Makefile
blob: 95f3a528e678f7c81cd9ce60c5b64b7bc1b772a2 (plain) (blame)
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
SHELL := /bin/bash -eufo pipefail
PREFIX ?= $(HOME)
FIND ?= gfind

.PHONY: all
all: clean merge stow after_stow

.PHONY: after_stow
after_stow:
	ln -nfs "$(PREFIX)/.nvim" "$(PREFIX)/.config/nvim"
	ln -nfs "$(PREFIX)/.zls.json" "$(PREFIX)/Library/Application Support/zls.json"

.PHONY: stow
stow:
	@# stow doesn't support __stowing?__ directories with symlinks, see:
	@# https://github.com/aspiers/stow/issues/51
	@# what i do here is a stow-like glue
	@# - loop through all top level directories in merged
	@# - for each file or directory in the top level
	@# - create a symlink in $HOME pointing to merged
	@# this has one important limitation: it doesn't support shared
	@# nested directories as stow does. for example, if you have a directory
	@# like: merged/nvim/.config/nvim, $HOME/.config would end up as a link,
	@# which is not ideal since it contains other configs too!
	@#
	@# the solution is to never use shared directories and setup links after
	@# this target with the after_stow target.
	$(FIND) ./merged -mindepth 1 -maxdepth 1 -type d -print0 |\
		xargs -0 -S 600 -I{} $(SHELL) -c '\
			export package={}; \
			echo "stowing - $${package#./merged/}"; \
			$(FIND) "$${package}" -mindepth 1 -maxdepth 1 -print0 |\
				xargs -0 -I{} $(SHELL) -c '\''\
					target={}; \
					echo "linking - $${target#./merged/}"; \
					ln -nfs "$(PWD)/$${target#./}" \
						"$(PREFIX)/$${target#.\/merged\/$${package#./merged/}\/}"; \
				'\''; \
		'

.PHONY: merge
merge: merge_check_dups
	@# create directory structure
	rsync -a --include '*/' --exclude '*' "private/" "merged"
	rsync -a --include '*/' --exclude '*' "public/" "merged"
	rm -rf merged/.git merged/.git-crypt
	@# link files to their destination
	$(FIND) ./public -type f -print0 |\
		xargs -0 -S 600 -I '{}' $(SHELL) -c '\
			file={}; \
			ln -s "$$(realpath $$file)" "./merged/$${file#./public/}"; \
		'
	$(FIND) ./private \
		-not \( -path ./private/.git -prune \) \
		-not \( -path ./private/.git-crypt -prune \) \
		-not \( -path ./private/.gitattributes -prune \) \
		-type f -print0 | xargs -0 -S 600 -I '{}' $(SHELL) -c '\
			file={}; \
			ln -s "$$(realpath $$file)" "./merged/$${file#./private/}"; \
		'

.PHONY: merge_check_dups
merge_check_dups:
	DUPES=$$({ \
		$(FIND) ./private -type f -printf '%P\n'; \
		$(FIND) ./public -type f -printf '%P\n'; \
	} | sort | uniq -d); \
	if [ "$$(echo -n "$$DUPES" | wc -c)" -gt 0 ]; then \
		echo "ERROR: Duplicate files found in private and public"; \
		echo "$$DUPES"; \
		exit 1; \
	fi

.PHONY: clean
clean:
	rm -rf merged