blob: b4090ec55a31247e14f892885153765a9451b520 (
plain)
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
# Functions used for interactive installation of new changes to running system
# vim: ft=sh
# Ask if given section should be installed
# First argument is name (take care not to use special characters for regulard
# expression) and second argument is a question
ask() {
local ignore_file=".ignore-$(hostname)"
[ -f "$ignore_file" ] && grep -q "^$1$" "$ignore_file" && return 1
if $FORCE; then
echo "\e[1;34m$2\e[0m"
# Fall trough with 0 exit (always yes)
else
echo -e -n "\e[1;34m$2? (Y/n) \e[0m"
local reply
read -r reply
echo "$reply" | grep -qE '^[Yy]?$'
fi
}
dodiff() {
if [ -d "$2" ]; then
# If we just copying some file to directory
OUT=$2/$(basename "$1")
else
OUT=$2
fi
if ! [ -f "$OUT" ]; then
echo -e "\e[1;33mNot installed:\e[0m $1 => $OUT"
if ask "Install?"; then
doinst "$1" "$OUT"
fi
return
fi
if cmp "$1" "$OUT" >/dev/null 2>&1; then
echo -e "\e[1;32mNo difference detected:\e[0m $OUT"
return
fi
if $FORCE; then
doinst "$1" "$OUT"
else
vimdiff "$1" "$OUT"
fi
}
# Managing two git trees with master has small inconvenience that git allows only
# single branch checkout in all work trees, so as it sets now git will execute all
# commands not on deployed tree but on tree in this repository, so we need specify
# work tree on command line every time we want target deployed work tree.
gitrepo_relink() {
local GITD="gitdir: $PWD/.git$(sed "s/^gitdir: [./]*git//" "$1")"
# We check that we are pointing to correct path just because of making message correct
if ! grep -q "$GITD" "$2"; then
echo -e "\e[1;34mPointing git repository $2 to this repository\e[0m"
echo "$GITD" > "$2"
fi
# else probably not a git repository or who knows.
}
checkdiff() {
# Iterate trough source directory but ignore any git repositories
# Note that it's design decision to not iterate trough target directory.
if [ -d "$1" ]; then
# This is check if we have correct inst command basically. If it is
# directory than it have to have trailing slash to ensure that no
# additional directory is created.
if ! echo "$1" | grep -qE '/$'; then
echo -e "\e[1;31mERROR: Directory without trailing slash detected:\e[0m $1"
exit 1
fi
# Got trough all files ignoring git repositories
for f in `find "$1" \( -type d -exec test -e '{}'/.git \; \) -prune -o -type f -print`; do
F="${f#$1}"
dodiff "$1/$F" "$2/$F"
done
# Check if we have all directories ignoring those in git repositories
for d in `find "$1" -type d -print -exec test -e '{}'/.git \; -prune`; do
D="${d#$1}"
if [ ! -d "$2/$D" ]; then
echo -e "\e[1;33mDirectory not installed:\e[0m $1/$D => $2/$D"
if ask "Install?"; then
doinst "$1/$D/" "$2/$D"
fi
fi
done
# Now checkout git repositories
for g in `find "$1" -type d -exec test -e '{}'/.git \; -print -prune`; do
G="$2/${g#$1}"
gitrepo_relink "$g/.git" "$G/.git" # Always reling .git just to be sure
PREV="$(pwd)"
cd "$G"
# Check if we have any change at all
if git --work-tree=. diff --exit-code -s; then
echo -e "\e[1;32mNo difference detected in git:\e[0m $G"
else
echo -e "\e[0;32mCheckout of git repository:\e[0m $G"
# Checkout all files to HEAD
git --work-tree=. checkout -f HEAD
# Update all submodules
git --work-tree=. submodule update --recursive
fi
cd "$PREV"
done
else
dodiff "$1" "$2"
fi
}
doinst() {
echo -e "\e[1;34mrsync -rlpt $1 $2\e[0m"
mkdir -p "$(dirname "$2")"
rsync -rlpt $1 $2
# Now edit all .git files in target directory
for g in `find "$1" -name '.git' -type f`; do
gitrepo_relink "$g" "$2/${g#$1}"
done
}
inst() {
if [ ! -e "$1" ]; then
echo "Missing file to be installed: $1" >&2
fi
if [ -e "$2" ]; then
# If output exists, execute diff instead
checkdiff $1 $2
return
fi
doinst $1 $2
}
# gpg encrypted install
ginst() {
if [ -z "$PASS" ]; then
PASS="$(gpg --batch --decrypt pass.gpg)"
fi
# TODO probably we should be sure that file will be always removed
local TMP="$(mktemp myconfigs.XXXXXXXXXX)"
gpg --batch --passphase "$PASS" --output "$TMP" --decrypt "$1"
inst "$TMP" "$2"
gpg --batch --passphase "$PASS" --output "$1" --encrypt "$TMP"
}
|