]> apps.delaporte.us Git - dotfiles.git/blob - bin/dot
Install script for KDE
[dotfiles.git] / bin / dot
1 #!/bin/bash
2 ENVS="$HOME/envs" # Python environments - including required Ansible
3 ANSIBLE="$ENVS/ansible/bin/ansible-playbook" # Core command
4 TASKFILE="$HOME/backup/dot.$HOSTNAME.yaml" # Backup of localhost config
5 DOTFILES="$HOME/dotfiles" # Where to find dotfiles
6
7 LINKFILES="$DOTFILES/files" # Files to symlink
8 INSTALLS="$DOTFILES/install" # Install scripts
9 DOT="$HOME/.dot" # Touched files go here to track installs
10 REQS="$DOTFILES/reqs" # Python env requirements.txt files
11
12 read -d '' HELP << EOF
13 dot - a (mostly) one script dotfiles manager
14
15 Copyright 2026 Edward Delaporte V
16 Licensed under AGPLv3 and later.
17
18 dot setup
19 install ansible CLI to $ANSIBLE
20
21 dot link FILE
22 updates ~/dot.HOSTNAME.yaml
23 to include a symlink from ~/dotfiles/files/FILE to ~/.FILE
24
25 dot check
26 check setup against ~/backup/dot.HOSTNAME.yaml
27
28 dot apply
29 apply config in ~/backup/dot.HOSTNAME.yaml
30
31 dot help FEATURE
32 setup - more information on setup
33 all - additional features
34 EOF
35
36 read -d '' SETUP_HELP << EOF
37 ## Setup
38
39 1. Install this file on your path
40 2. Clone your (or my) 'dotfiles' repository to ~/dotfiles
41 3. Run 'dot help' to get started.
42
43 EOF
44
45
46 read -d '' EXTRA_HELP << EOF
47
48 dot install SCRIPT
49 updates ~/dot.HOSTNAME.yaml
50 to run ~/dotfiles/SCRIPT.sh if it has not yet been run
51 creates ~/dot/SCRIPT.installed after SCRIPT has been run
52
53 dot env ENV
54 create Python environment ~/envs/ENV based on ~/dotfiles/reqs/ENV.txt
55
56 EOF
57
58
59 if [ ! -n "$1" ] || [ "$1" == "help" ]; then
60 echo "$HELP"
61 fi
62 if [ "$1" == "help" ] && [ "$2" == "all" ]; then
63 echo ""
64 echo "$EXTRA_HELP"
65 echo ""
66 echo "$SETUP_HELP"
67 fi
68 if [ "$1" == "help" ] && [ "$2" == "setup" ]; then
69 echo ""
70 echo "$SETUP_HELP"
71 fi
72
73 # set -v
74 #
75
76
77 read -d '' EMPTY_TASKFILE << EOF
78 ---
79 - name: Set up dotfiles on $HOSTNAME
80 gather_facts: no
81 hosts: localhost
82 connection: local
83
84 tasks:
85 - name: Check on $TASKFILE
86 ansible.builtin.stat:
87 path: $TASKFILE
88 EOF
89
90 if [[ ! -f "$TASKFILE" ]]; then
91 echo "Creating empty $TASKFILE"
92 mkdir -p "$HOME/backup"
93 echo "$EMPTY_TASKFILE" >> $TASKFILE
94 fi
95
96 if [ "$1" == "setup" ]; then
97 if [[ ! -f "$ANSIBLE" ]]; then
98 mkdir -p "$ENVS"
99 echo "Setting up Ansible in ~/envs/ansible"
100 cd $HOME/envs; python3 -m venv ansible
101 $HOME/envs/ansible/bin/pip install ansible jinja2
102 fi
103 if [[ -f "$ANSIBLE" ]]; then
104 echo "[ ok ]: Ansible setup at $ANSIBLE"
105 fi
106 if [[ -f "$TASKFILE" ]]; then
107 echo "[ ok ]: dot config at $TASKFILE"
108 fi
109 fi
110
111 if [ "$1" == "reset" ]; then
112 read -n1 -p "Reset $TASKFILE? [y,N]" input
113 if [[ ! $input == "Y" && ! $input == "y" ]]; then
114 echo "Aborted by user"
115 exit 1
116 fi
117 echo "$EMPTY_TASKFILE" > $TASKFILE
118 echo ""
119 fi
120
121
122 if [ "$1" == "check" ]; then
123 $ANSIBLE $TASKFILE --check --diff
124 fi
125
126 if [ "$1" == "link" ]; then
127 if [ ! -n "$2" ]; then
128 echo "Can symlink: (from $LINKFILES)"
129 cd $LINKFILES
130 ls -p | grep -v /
131 exit 1
132 fi
133
134 read -d '' LINK_THIS_FILE << EOF
135
136 - name: symlink $2
137 ansible.builtin.file:
138 src: "$LINKFILES/$2"
139 dest: "$HOME/.$2"
140 state: "link"
141 EOF
142
143 if [[ "$2" == *"."* ]];then
144 # File already contains a dot
145 read -d '' LINK_THIS_FILE << EOF
146
147 - name: symlink $2
148 ansible.builtin.file:
149 src: "$LINKFILES/$2"
150 dest: "$HOME/$2"
151 state: "link"
152 EOF
153
154
155 fi
156
157 echo " $LINK_THIS_FILE" >> $TASKFILE
158 echo "$2 added to symlinks in $TASKFILE"
159 echo "Run 'dot apply' to create all configured symlinks"
160 fi
161
162 if [ "$1" == "apply" ]; then
163 if [[ ! -f "$TASKFILE" ]]; then
164 echo "$TASKFILE is missing. Run 'dot setup'"
165 exit 1
166 fi
167 $ANSIBLE $TASKFILE
168 fi
169
170 if [ "$1" == "install" ]; then
171 if [ ! -n "$2" ]; then
172 echo "Can install: (.sh scripts in $INSTALLS)"
173 cd $INSTALLS
174 ls -p | grep -v / | grep .sh
175 exit 1
176 fi
177 if [[ ! -f "$INSTALLS/$2.sh" ]]; then
178 echo "No such install script $INSTALLS/$2.sh"
179 echo "Run dot install with no params to list scripts."
180 exit 1
181 fi
182
183 mkdir -p $DOT
184 read -d '' RUN_INSTALL << EOF
185 - name: check $2
186 stat:
187 path: "$DOT/$2.installed"
188 register: $2_installed
189 - name: install $2
190 ansible.builtin.shell: |
191 "$INSTALLS/$2.sh"
192 touch "$DOT/$2.installed"
193 when: not $2_installed.stat.exists
194 - name: verify $2 is installed
195 ansible.builtin.debug:
196 msg: "$2 is installed."
197 when: $2_installed.stat.exists
198 EOF
199 echo " $RUN_INSTALL" >> $TASKFILE
200 echo "Run 'dot apply' to run the install"
201 fi
202
203
204 if [ "$1" == "env" ]; then
205 if [ ! -n "$2" ]; then
206 echo "Can create: (.txt files in $REQS)"
207 cd $REQS
208 ls -p | grep -v / | grep .txt
209 exit 1
210 fi
211 if [[ ! -f "$REQS/$2.txt" ]]; then
212 echo "No such requirements file script $REQS/$2.txt"
213 echo "Run dot env with no params to list files."
214 exit 1
215 fi
216
217 read -d '' ADD_ENV << EOF
218 - name: check env $2
219 stat:
220 path: "$ENVS/$2"
221 register: $2_path
222 - name: install $2
223 ansible.builtin.shell: |
224 cd $ENVS
225 python3 -m venv $2
226 $ENVS/$2/bin/python -m pip install -r $REQS/$2.txt
227 when: not $2_path.stat.exists
228 - name: verify env $2 exists
229 ansible.builtin.debug:
230 msg: "env $2 exists"
231 when: $2_path.stat.exists
232 EOF
233 echo " $ADD_ENV" >> $TASKFILE
234 echo "Run 'dot apply' to run the install"
235 fi
236