#!/bin/bash ENVS="$HOME/envs" ANSIBLE="$ENVS/ansible/bin/ansible-playbook" read -d '' HELP << EOF dot - a (mostly) one script dotfiles manager 1. Install this file on your path 2. Clone your (or my) 'dotfiles' repository to ~/dotfiles 3. Run 'dot help' to get started. Copyright 2026 Edward Delaporte V Licensed under AGPLv3 and later. dot setup install ansible CLI to $ANSIBLE dot link FILE updates ~/dot.HOSTNAME.yaml to include a symlink from ~/dotfiles/files/FILE to ~/.FILE dot install SCRIPT updates ~/dot.HOSTNAME.yaml to run ~/dotfiles/SCRIPT.sh if it has not yet been run creates ~/dot/SCRIPT.installed after SCRIPT has been run dot check check setup against ~/dot.HOSTNAME.yaml dot apply apply config in ~/dot.HOSTNAME.yaml EOF if [ ! -n "$1" ] || [ "$1" == "help" ]; then echo "$HELP" fi # set -v TASKFILE="$HOME/backup/dot.$HOSTNAME.yaml" LINKFILES="$HOME/dotfiles/files" INSTALLS="$HOME/dotfiles/install" DOT="$HOME/.dot" read -d '' EMPTY_TASKFILE << EOF --- - name: Set up dotfiles on $HOSTNAME gather_facts: no hosts: localhost connection: local tasks: - name: Check on $TASKFILE ansible.builtin.stat: path: $TASKFILE EOF if [[ ! -f "$TASKFILE" ]]; then echo "Creating empty $TASKFILE" mkdir -p "$HOME/backup" echo "$EMPTY_TASKFILE" >> $TASKFILE fi if [ "$1" == "setup" ]; then if [[ ! -f "$ANSIBLE" ]]; then mkdir -p "$ENVS" echo "Setting up Ansible in ~/envs/ansible" cd $HOME/envs; python3 -m venv ansible $HOME/envs/ansible/bin/pip install ansible jinja2 fi if [[ -f "$ANSIBLE" ]]; then echo "[ ok ]: Ansible setup at $ANSIBLE" fi if [[ -f "$TASKFILE" ]]; then echo "[ ok ]: dot config at $TASKFILE" fi fi if [ "$1" == "reset" ]; then read -n1 -p "Reset $TASKFILE? [y,N]" input if [[ ! $input == "Y" && ! $input == "y" ]]; then echo "Aborted by user" exit 1 fi echo "$EMPTY_TASKFILE" > $TASKFILE echo "" fi if [ "$1" == "check" ]; then $ANSIBLE $TASKFILE --check --diff fi if [ "$1" == "link" ]; then if [ ! -n "$2" ]; then echo "Can symlink: (from $LINKFILES)" cd $LINKFILES ls -p | grep -v / exit 1 fi read -d '' LINK_THIS_FILE << EOF - name: symlink $2 ansible.builtin.file: src: "$LINKFILES/$2" dest: "$HOME/.$2" state: "link" EOF echo " $LINK_THIS_FILE" >> $TASKFILE echo "$2 added to symlinks in $TASKFILE" echo "Run 'dot apply' to create all configured symlinks" fi if [ "$1" == "apply" ]; then if [[ ! -f "$TASKFILE" ]]; then echo "$TASKFILE is missing. Run 'dot setup'" exit 1 fi $ANSIBLE $TASKFILE fi if [ "$1" == "install" ]; then if [ ! -n "$2" ]; then echo "Can install: (.sh scripts in $INSTALLS)" cd $INSTALLS ls -p | grep -v / | grep .sh exit 1 fi if [[ ! -f "$INSTALLS/$2.sh" ]]; then echo "No such install script $INSTALLS/$2.sh" echo "Run dot install with no params to list scripts." exit 1 fi mkdir -p $DOT read -d '' RUN_INSTALL << EOF - name: check $2 stat: path: "$DOT/$2.installed" register: $2_installed - name: install $2 ansible.builtin.shell: | "$INSTALLS/$2.sh" touch "$DOT/$2.installed" when: not $2_installed.stat.exists - name: verify $2 is installed ansible.builtin.debug: msg: "$2 is installed." when: $2_installed.stat.exists EOF echo " $RUN_INSTALL" >> $TASKFILE echo "Run 'dot apply' to run the install" fi