-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdeploy-config-linux.sh
executable file
·248 lines (170 loc) · 6.83 KB
/
deploy-config-linux.sh
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
#!/bin/bash
# Usage function.
usage() {
echo ""
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Options:"
echo " -d, --debug Turns on debug output messages."
echo " -t, --dry-run Simulates actions without making changes."
echo " -v, --verbose Shows standards output from commands."
echo " -h, --help Show this help message and exit."
echo ""
echo "This script reads environment variables from a .env file and creates symbolic links for"
echo "configuration files based on paths specified in each subfolder's "paths.txt" file."
echo "Symbolic links allow the configurations to be used without copying files directly,"
echo "facilitating easy updates and management using Git."
echo ""
}
# Parsed from command line arguments.
while [[ $# -gt 0 ]]; do
case "$1" in
-d|--debug)
debug=true
shift
;;
-t|--dry-run)
dryRun=true
shift
;;
-v|--verbose)
verbose=true
shift
;;
-h|--help)
usage
exit 0
;;
*)
echo "Invalid option: $1" >&2
usage
exit 1
;;
esac
done
# Set external logger- and error handling script paths
# Getting absolute path as script might be called from another script
externalLogger=$(dirname "${BASH_SOURCE[0]}")"/utils/bash/logging-and-output-function.sh"
externalErrorHandler=$(dirname "${BASH_SOURCE[0]}")"/utils/bash/error-handling-function.sh"
# Source external logger and error handler (but allow execution without them)
source "${externalErrorHandler}" "Dotfiles scrip failed" || true
source "${externalLogger}" || true
# Verify if logger function exists or sett fallback
if [[ $(type -t logMessage) != function ]]; then
# Fallback minimalistic logger function
logMessage() {
local level="${2:-INFO}"
echo "[$level] $1"
}
fi
# Redirect output functions if not debug enabled
run() {
if [[ "${verbose}" == "true" ]]; then
"$@"
else
"$@" > /dev/null
fi
}
# Check if the script is running in WSL
isWsl() {
# Check /proc/version for WSL-specific terms
grep -qEi "microsoft.*(subsystem|standard)" /proc/version
}
# Set dotfiles directory and log file
dotfilesDirectory=$(dirname "${BASH_SOURCE[0]}")
# Function to expand environment variables in paths
expandPath() {
eval echo "$1"
}
# Set environment variable file path
if isWsl; then
# Set environment variable file path for WSL
envFile="${dotfilesDirectory}/.env.wsl"
else
# Set environment variable file path for Linux
envFile="${dotfilesDirectory}/.env.linux"
fi
# Load environment variables
if [ -f "${envFile}" ]; then
logMessage "Loading environment variables from file (${envFile})..." "INFO"
# Read each line from the file and export it
while IFS='=' read -r key value; do
# Skip empty lines and comments
[[ -z "$key" || "$key" =~ ^# ]] && continue
logMessage "Setting environment variable: ${key}=${value}" "DEBUG"
# Export the variable
export "$key=$value"
done < "${envFile}"
else
logMessage "Environment file (${envFile}) not found." "ERROR"
exit 1
fi
# Find and process all paths.txt files in subdirectories
find "${dotfilesDirectory}" -type f -name "paths.txt" | while IFS= read -r pathsFile; do
# Set current app directory
appPath=$(dirname "$pathsFile")
appDirectory=$(basename "$appPath")
logMessage "Processing symlink paths for '${appDirectory}'..." "INFO"
# Process only lines starting with "l "
grep '^l' "${pathsFile}" | while IFS= read -r line; do
# Extract source and target paths (remove the "l " prefix)
targetPathRaw=$(echo "$line" | awk '{print $2}')
symlinkPathRaw=$(echo "$line" | awk '{print $3}')
# Resolve/expand initial absolute and relative paths
targetPathAbsolute=$(expandPath "${targetPathRaw}")
targetPathRelative=$(expandPath "${appPath}/${targetPathRaw}")
# Verify/test target path
# Check if the target path is an existing absolute path
if [[ -e "${targetPathAbsolute}" ]]; then
targetPath="${targetPathAbsolute}"
# Check if the target path is a relative path
elif [[ ! "${targetPathRaw}" =~ ^/ && ! "${targetPathRaw}" =~ ^~ && ! "${targetPathRaw}" =~ ^\$ ]]; then
# Check if the relative path exists
if [[ -e "${targetPathRelative}" ]]; then
targetPath="${targetPathRelative}"
else
logMessage "Incorrect formatted target path (${targetPathRaw}) or relative path (${targetPathRelative}) does not exist." "ERROR"
continue
fi
else
logMessage "Incorrect formatted target path (${targetPathRaw}) or absolute path (${targetPathAbsolute}) does not exist." "ERROR"
continue
fi
# Resolve/expand symlink path
symlinkPath=$(expandPath "${symlinkPathRaw}")
# Create parent directory for symlink if necessary
if [[ "${dryRun}" != "true" ]]; then
mkdir -p "$(dirname "${symlinkPath}")"
fi
# Check if an item already exists (file, directory, or symlink, even broken symlink)
if [[ -e "${symlinkPath}" || -L "${symlinkPath}" ]]; then
# Check specifically if the item is a symlink
if [[ -L "${symlinkPath}" ]]; then
# If it's a symlink, check if it points to the correct source
currentTarget=$(readlink "${symlinkPath}")
# Check if the link target path is correct
if [[ "${currentTarget}" != "${targetPath}" ]]; then
logMessage "Symlink exists (${symlinkPath}), but points to a different target (${currentTarget}). Recreating..." "DEBUG"
# Remove the incorrect symlink
if [[ "${dryRun}" != "true" ]]; then
rm "${symlinkPath}"
fi
else
logMessage "Symlink already exists (${symlinkPath}) and points to the correct target (${targetPath})" "INFO"
continue
fi
else
logMessage "A file or directory exists in the symlink path (${symlinkPath}) and is not a symlink. Replacing..." "INFO"
# It is not a symbolic link (regular file or directory)
if [[ "${dryRun}" != "true" ]]; then
rm -rf "${symlinkPath}"
fi
fi
fi
# Create new symlink
if [[ "${dryRun}" != "true" ]]; then
ln -s "${targetPath}" "${symlinkPath}"
fi
logMessage "Creating new symlink: ${symlinkPath} -> ${targetPath}" "INFO"
done
done