#!/bin/bash read -d '' HELP << EOF dot - a (mostly) one script dotfiles manager Copyright 2026 Edward Delaporte V Licensed under AGPLv3 and later. dot setup install the necessary tools to $HOME/envs/dot dot link FILE updates ~/dot.HOSTNAME.yaml to include a symlink from ~/dotfiles/files/FILE to ~/.FILE 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 ENVS="$HOME/envs" ANSIBLE="$ENVS/ansible/bin/ansible-playbook" TASKFILE="$HOME/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 [ "$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 "Creating $TASKFILE" echo "$EMPTY_TASKFILE" >> $TASKFILE 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 "May symlink:" 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:" cd $INSTALLS ls -p | grep -v / 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