123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- #!/bin/bash
-
- shellfu import pretty
-
- #
- # Should broken links be silently overwritten?
- #
- DOTTUM__CLOBBER_BROKEN=false
-
- #
- # Should all links be silently overwritten?
- #
- DOTTUM__CLOBBER_LINKS=false
-
- #
- # List of subvalults passed on command line
- #
- # This is added to the front of list in *subvalults* file.
- #
- DOTTUM__SUBVAULTS=()
-
- #
- # Vault to process
- #
- DOTTUM__VAULT=""
-
- _dottum__slstatus() {
- #
- # Print status of slpath $1
- #
- local slpath=$1
- local tlink=0
- local texis=0
- test -L "$slpath"; tlink=$?
- test -e "$slpath"; texis=$?
- case $tlink:$texis in
- 0:0) echo symlink ;;
- 0:1) echo broken ;;
- 1:0) echo nonlink ;;
- 1:1) echo nothing ;;
- *) warn "strange resiult: tlink=$tlink texis=$texis" ;;
- esac
- }
-
- dottum__lssv() {
- #
- # List sub-vaults
- #
- # Sub-vault is a sub-path of vault directory that contains items
- # that should be linked separately, to a similar $HOME subpath,
- # rather than linking the whole sub-tree. This is typical for
- # .config directory specified by XDG standard.
- #
- # For example, imagine vault like this:
- #
- # dotfiles/
- # ├── config
- # │ ├── dunst
- # │ │ └── dunstrc
- # │ └── uzbl
- # │ ├── config
- # │ └── style.css
- # ├── i3
- # │ └── config
- # ├── i3status.conf
- # └── vimrc
- #
- # Without sub-vault, the "config" would be linked as "$HOME/.config":
- #
- # $HOME/.config -> dotfiles/.config
- # $HOME/.i3 -> dotfiles/i3
- # $HOME/.i3status.conf -> dotfiles/i3status.conf
- # $HOME/.vimrc -> dotfiles/vimrc
- #
- # This is impractical in most cases, as normally you want to select
- # applications to link--some dotfiles could be specific to some
- # hosts or even private.
- #
- # Setting 'config' as sub-vault will tell mklinks that you don't
- # want to link this item directly but rather each of its items:
- #
- # $HOME/.config/dunst -> dotfiles/config/dunst
- # $HOME/.config/uzbl -> dotfiles/config/uzbl
- # $HOME/.i3 -> dotfiles/i3
- # $HOME/.i3status.conf -> dotfiles/i3status.conf
- # $HOME/.vimrc -> dotfiles/vimrc
- #
- # This way, you can have other items under "$HOME/.config" that
- # are either purely local or linked to another vault.
- #
- # Note that the subvault can be deeper than one level, i.e.
- # subvault "local/share" also works:
- #
- # $HOME/.local/share/klavaro -> dotfiles/local/share/klavaro
- #
- local sv
- test -n "${DOTTUM__SUBVAULTS[0]}" && {
- think "using sub-vaults from command line"
- for sv in "${DOTTUM__SUBVAULTS[@]}";
- do
- echo "$sv"
- done
- return
- }
- test -f "$DOTTUM__VAULT/dotvault/subvaults" && {
- think "reading subvaults from file: $DOTTUM__VAULT/dotvault/subvaults"
- grep . "$DOTTUM__VAULT/dotvault/subvaults" \
- | grep -v "^#.*"
- return
- }
- think "using hard-coded list of subvaults"
- echo config
- }
-
- dottum__lsvault() {
- #
- # List all vaults and subvaults, depth-first
- #
- {
- echo "$DOTTUM__VAULT"
- dottum__lssv \
- | while IFS= read -r sv;
- do
- test -e "$DOTTUM__VAULT/$sv" || {
- think "ignoring non-existent sub-vault: $sv"
- continue
- }
- test -d "$DOTTUM__VAULT/$sv" || {
- warn "ignoring non-directory sub-vault: $sv"
- continue
- }
- echo "$DOTTUM__VAULT/$sv"
- done
- } \
- | LC_ALL=C sort \
- | tac
- }
-
- dottum__istarget() {
- #
- # True if item $1 is possible target
- #
- # Item is obviously not a possible target if it's
- # a (sub-)vault.
- #
- # A less obvious case is when item is an intermediate directory
- # on a path leading to a sub-vault. Such item cannot be a target!
- #
- # For example: there are sub-vaults:
- #
- # foo
- # foo/bar/baz
- #
- # and a tree:
- #
- # foo
- # ├── A
- # └── bar
- # └── baz
- # └── B
- #
- # Items A and B could both be targets, but baz could not be!
- #
- #TODO: write an explanation
- #
- local item=$1
- debug -v item
- Verbose=false dottum__lsvault | grep -qxF "$item" && return 1
- Verbose=false dottum__lsvault | grep -qx "$item/.*" && return 1
- return 0
- }
-
- dottum__pfxpath() {
- #
- # Prefix paths with $1
- #
- # Just like `sed "s/^/$1/" but works with any characters
- # in $1 excepr newline, which is not allowed in paths..
- #
- local pfx="$1"
- local path
- while IFS= read -r path;
- do
- echo "$pfx$path"
- done
- }
-
- dottum__lstarget() {
- #
- # List potential items in vault $1
- #
- local vlt=$1
- debug -v vlt
- local item
- find "$vlt" -mindepth 1 -maxdepth 1 -printf "%P\n" \
- | dottum__pfxpath "$vlt/" \
- | grep -v "$DOTTUM__VAULT/dotvault" \
- | while IFS= read -r item;
- do
- dottum__istarget "$item" && echo "$item"
- done
- }
-
-
- dottum__make_links() {
- #
- # Create all links
- #
- local slpath
- local target
- local vlt
- local slstatus
- dottum__lsvault \
- | while IFS= read -r vlt;
- do
- dottum__lstarget "$vlt" \
- | while IFS= read -r target;
- do
- slpath=$(dottum__slpath "$target")
- slstatus=$(_dottum__slstatus "$slpath")
- debug -v slpath slstatus
- case $slstatus in
- nonlink)
- warn "skipping existing non-link: $slpath"
- continue
- ;;
- broken)
- if $DOTTUM__CLOBBER_LINKS || $DOTTUM__CLOBBER_BROKEN; then
- think "removing existing broken link: $slpath"
- dottum__maybe rm "$slpath"
- else
- warn "skipping existing broken link: $slpath"
- continue
- fi
- ;;
- symlink)
- if $DOTTUM__CLOBBER_LINKS; then
- think "removing existing link: $slpath"
- dottum__maybe rm "$slpath"
- else
- warn "skipping existing slpath: $slpath"
- continue
- fi
- ;;
- esac
- dottum__maybe ln -sr "$target" "$slpath"
- done
- done
- }
-
- dottum__explore() {
- #
- # Show what would be done
- #
- local vlt
- local tgt
- local tgts
- dottum__lsvault \
- | sort \
- | while IFS= read -r vlt;
- do
- tgts=$(dottum__lstarget "$vlt")
- test -n "$tgts" || continue
- if test "$vlt" == "$DOTTUM__VAULT";
- then
- echo "VAULT:$vlt:"
- else
- echo
- echo "SUBVAULT:$vlt"
- fi
- sort <<<"$tgts" \
- | while IFS= read -r tgt;
- do
- echo "${tgt}:$(dottum__slpath "$tgt")"
- done \
- | sed -e "s|:$HOME|:=> ~|" \
- | column -ts: \
- | sed -e "s/^/ /"
- done
- }
-
- dottum__maybe() {
- #
- # Maybe do things $@, maybe not (if in debug mode)
- #
- $PRETTY_DEBUG && { debug "MAYBE:$*"; return; }
- "$@"
- }
-
- dottum__slpath() {
- #
- # Print path where to create link for target $1
- #
- local item=$1
- echo "$HOME/.${item#$DOTTUM__VAULT/}"
- }
|