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