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 @# link files to their destination $(FIND) ./public -not \( -path ./public/.git -prune \) -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 \) -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