Repository navigation
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·109 lines (96 loc) · 3.43 KB
/
Copy pathinstall.sh
File metadata and controls
executable file
·109 lines (96 loc) · 3.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#!/bin/bash
if [ "$#" -eq 0 ]; then
echo "Usage: $0 <module> [module ...]"
echo "Examples: $0 omarchy | $0 home | $0 home macos"
exit 1
fi
targets=("$@")
stow_options=(-v -t "$HOME" --no-folding --ignore='\.append$')
cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null || exit 1
echo "dotSetting at: $(pwd)"
echo ""
echo "Installing symlinks via stow:"
echo " stow -v -t ~ --no-folding --ignore='\.append$' ${targets[*]}"
echo ""
echo "About stow: https://www.gnu.org/software/stow/"
echo "Conflicting files can be moved to .bak after individual confirmation."
backup_conflicts() {
local output line relative path backup index
local unowned='^ \* existing target is not owned by stow: (.+)$'
local existing='^ \* cannot stow .+ over existing target (.+) since neither a link nor a directory and --adopt not specified$'
local directory='^ \* cannot stow non-directory .+ over existing directory target (.+)$'
local -a conflicts
local -A seen
while ! output=$(LC_ALL=C stow --simulate "${stow_options[@]}" "${targets[@]}" 2>&1); do
conflicts=()
seen=()
while IFS= read -r line; do
if [[ "$line" =~ $unowned || "$line" =~ $existing || "$line" =~ $directory ]]; then
relative=${BASH_REMATCH[1]}
path="$HOME/$relative"
if [[ "$relative" == /* || "/$relative/" == */../* || ! -e "$path" && ! -L "$path" ]]; then
echo "$output" >&2
echo "This conflict cannot be resolved by backing up an existing target." >&2
return 1
fi
if [[ ! ${seen[$relative]+exists} ]]; then
conflicts+=("$path")
seen[$relative]=1
fi
elif [[ "$line" == " * "* ]]; then
echo "$output" >&2
echo "Stow reported a conflict that requires manual resolution." >&2
return 1
fi
done <<< "$output"
if [ "${#conflicts[@]}" -eq 0 ]; then
echo "$output" >&2
return 1
fi
for path in "${conflicts[@]}"; do
backup="$path.bak"
index=1
while [[ -e "$backup" || -L "$backup" ]]; do
backup="$path.bak.$index"
((index++))
done
echo ""
printf 'Conflict: %s\n' "$path"
printf 'Move to: %s\n' "$backup"
if ! read -r -p "Back up this conflict? [y/N] " || [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Installation stopped; conflict left in place."
return 1
fi
mv -- "$path" "$backup" || return 1
done
done
}
backup_conflicts || exit 1
stow "${stow_options[@]}" "${targets[@]}" || exit "$?"
echo "stow done"
append_snippets() (
shopt -s dotglob globstar nullglob
for target in "${targets[@]}"; do
for snippet in "$target"/**/*.append; do
[[ -f "$snippet" ]] || continue
relative=${snippet#"$target"/}
path="$HOME/${relative%.append}"
content=$(<"$snippet")
[[ -n "$content" ]] || continue
# Match a literal, complete block of lines, even in a larger file.
if [[ -f "$path" ]]; then
existing=$'\n'"$(<"$path")"$'\n'
[[ "$existing" == *$'\n'"$content"$'\n'* ]] && continue
fi
printf '\nAppend %s to %s:\n%s\n' "$snippet" "$path" "$content"
if read -r -p "Append this snippet? [y/N] " && [[ $REPLY =~ ^[Yy]$ ]]; then
mkdir -p -- "$(dirname -- "$path")" || return 1
printf '\n%s\n' "$content" >> "$path" || return 1
printf '%s appended\n' "$path"
else
printf '%s skipped\n' "$path"
fi
done
done
)
append_snippets || exit "$?"