-
Notifications
You must be signed in to change notification settings - Fork 0
/
mm_backup.sh
executable file
·466 lines (436 loc) · 12.7 KB
/
mm_backup.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
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
#!/bin/bash
# backup MM modules config
base=$HOME/MagicMirror
saveDir=$HOME/MM_backup
default_user=temp
user_name=$default_user
default_email=$email
logfile=$base/installers/backup.log
push=false
# is this a mac
mac=$(uname -s)
if [ $mac == 'Darwin' ]; then
cmd=greadlink
else
cmd=readlink
fi
msg_prefix='updating'
#script_dir=$(dirname $($cmd -f "$0"))
#OPTIND=1 # Reset if getopts used previously
remote=
next_tagnumber=1
beginswith() {
l=$(expr length "$2")
leading="${1:0:$l}"
case $2 in
$leading):
true
;;
*):
false
;;
esac
}
check_for_push(){
if [ $push == true ]; then
if [ "$repo." == "." ]; then
# repo not connected to git
if [ "$reponame." == "." ]; then
echo to push, we need the repo name | tee -a $logfile
echo see the help for the -r parm
exit 2
else
if [ "$user_name" != $default_user ]; then
cd $saveDir
echo adding the git repmote https://github.com/$user_name/$reponame.git | tee -a $logfile
git remote add origin https://github.com/$user_name/$reponame.git
cd -
else
echo "you requested to push the local backup repository to github, but didn't specify the username" | tee -a $logfile
exit 3
fi
fi
else
if [ "$(cd $saveDir && git config user.email)." == "." -a "$user_name" == $default_user ]; then
echo we will need the github userid | tee -a $logfile
echo see the help for the -u parm
exit 3
else
if [ "$(cd $saveDir && git config user.email)." == "." -a "$email." == $default_email ]; then
echo we will need the github user email | tee -a $logfile
echo see the help for the -e parm
exit 4
fi
fi
fi
else
# if not push, but repo specified
if [ "$repo." != "." ]; then
echo "you specified a github repository name , but didn't request push" | tee -a $logfile
read -p "do you want to save the results of this backup to github now? (Y/n)?" choice
choice="${choice:-Y}"
choice=${choice,,}
echo user selection for push now is $choice >>$logfile
if [ $choice == "y" ]; then
push=true
check_for_push
fi
fi
fi
}
process_args(){
local OPTIND
#r=${1:0:1}
#echo "$r='$r'"
#if [ "$r." != '-.' ]; then
#echo "Illegal option '$1'"
#exit 3
#fi
while getopts ":hs:b:m:r:u:e:p" opt
do
case $opt in
# help
h) echo
echo $0 takes optional parameters
echo
echo -e "\t -s MagicMirror_dir"
echo -e "\t\tdefault $base"
echo
echo -e "\t -b backup_dir "
echo -e "\t\tdefault $saveDir"
echo
echo -e "\t -m backup message "
echo -e "\t\t any message (in quotes) that you would like to attach to this change for later info"
echo -e "\t\tdefault none"
echo
echo -e "\t -p auto push to github (will need repo name, username, user password or token"
echo -e "\t\tdefault false"
echo
echo -e "\t -r github repository name (reponame)"
echo -e "\t\ttypically https://github.com/username/reponame.git"
echo -e "\t\tdefault output of git remote -v (if set)"
echo -e "\t\t -r overrides the git remote setting"
echo
echo -e "\t -u github username"
echo -e "\t\tdefault none"
echo
echo -e "\t -u github password or token"
echo -e "\t\tdefault none"
exit 1
;;
s)
# source MagicMirror folder
b=$(echo $OPTARG | xargs)
if [ -d $HOME/$b ]; then
base=$HOME/$b
else
if [ -d $b ]; then
base=$b
else
echo unable to find Source folder $OPTARG | tee -a $logfile
exit 2
fi
fi
logfile=$base/installers/backup.log
echo source MagicMirror folder is $base | tee -a $logfile
;;
b)
# backup folder
full_path=false
b=$(echo $OPTARG | xargs)
if [ "$b." != "." ]; then
if beginswith "$b" "/"; then
full_path=true
fi
if [ -d $HOME/$b -a $full_path == false ]; then
saveDir=$HOME/$b
else
echo checking for backup folder $b | tee -a $logfile
if [ -d $b ]; then
echo backup folder $b exists | tee -a $logfile
saveDir=$b
else
if [ $full_path == false ]; then
echo folder doesn\'t exist, creating backup folder $HOME/$b | tee -a $logfile
saveDir=$HOME/$b
else
echo folder doesn\'t exist, creating backup folder $b | tee -a $logfile
saveDir=$b
fi
fi
fi
echo backup folder is $saveDir | tee -a $logfile
else
echo no folder was specified for backup | tee -a $logfile
exit 4
fi
;;
m)
# message on the git tag
msg=""
mparm=${@:$OPTIND}
if [[ ${mparm:0:1} != "-" ]];then
msg=$(echo ${@:$OPTIND}| cut -d' ' -f1)
OPTIND=$((OPTIND+1))
fi
;;
r)
# github repo name or url
repo=$OPTARG
# check for fulll url specified, we only want the name
IFS='/'; repoIN=($OPTARG); unset IFS;
# if there were slashes
if [ ${#repoIN[@]} -gt 0 ]; then
# get the last element of split array
index=${#repoIN[@]}
# get the name
repot=${repoIN[$((index -1))]}
# user is one array element earlier
# get the user name from the URL
useru=${repoIN[$(($index-2))]}
# check for '.git'
IFS='.'; repoN=($repot); unset IFS;
# get just the name
reponame=${repoN[0]}
# if we already processed the -u parm
if [ $user_name != $default_user ]; then
# and the url username is not the same
if [ $useru != $user_name ]; then
echo "username specified with -u $user_name doesn't match the user in the github repo $useru, aborting" | tee -a $logfile
exit 6
fi
fi
else
reponame=$repo
fi
;;
p)
# push requested
push=true
# ignore the repo name , get the one from the save folder, if the folder exists and remote is set
if [ -d $saveDir ]; then
configured_repo=$(cd $saveDir 2>/dev/null && git remote -v 2>/dev/null| grep fetch -m1 | awk '{print $2}')
if [ "$configured_repo." != "." ]; then
repo=$configured_repo
reponame=$repo
fi
fi
;;
u)
# username
#echo username=$OPTARG
user_name=$(echo $OPTARG | tr -d [:blank:])
;;
e)
# email
email=$OPTARG
;;
\?) echo "Illegal option '-$OPTARG'" && exit 3
;;
esac
done
shift $((OPTIND-1))
}
# if this script was started directly then arg0 is 'mm_backup.sh', else it is the first argument provided (oops)
if [[ "$0" == *.sh ]]; then
process_args "$@"
else
process_args "$0 $@"
fi
date +"backup starting - %a %b %e %H:%M:%S %Z %Y" >>$logfile
if [ ! -d $saveDir ]; then
echo creating $saveDir | tee -a $logfile
mkdir $saveDir 2>./make_error
if [ $? -eq 0 ]; then
cd $saveDir
git init &>/dev/null
git symbolic-ref HEAD refs/heads/main
cd - >/dev/null
msg_prefix='creating'
else
echo unable to create $saveDir $(cat ./make_error)
rm ./make_error
exit 1
fi
else
if [ ! -d $saveDir/.git ]; then
echo using $savedir | tee -a $logfile
cd $saveDir
echo "creating local git repo" | tee -a $logfile
# create local repo
git init &>/dev/null
git symbolic-ref HEAD refs/heads/main
cd - >/dev/null
fi
fi
check_for_push
repo_list=$saveDir/module_list
echo $msg_prefix folder $saveDir | tee -a $logfile
#copy config.js
cp -p $base/config/config.js $saveDir
# copy custom.css, no error if not found
cp -p $base/css/custom.css $saveDir 2>/dev/null
if [ $mac != 'Darwin' ]; then
SAVEIFS=$IFS # Save current IFS
IFS=$'\n'
fi
# get the installed module list
# split putput on new lines, not spaces
modules=($(find $base/modules -maxdepth 1 -type d | grep -v default | xargs -J % echo "%"))
if [ $mac != 'Darwin' ]; then
IFS=$SAVEIFS
fi
# if there is a modules list, erase it, creating new
if [ ${#modules[@]} -gt 0 ]; then
if [ -e $repo_list ]; then
echo will create new $repo_list | tee -a $logfile
rm $repo_list >/dev/null
touch $repo_list
fi
# loop thru the modules discovered
for module in "${modules[@]}"
do
# if its not the base modules folder
if [ "$module" != "$base/modules" ]; then
# change to the that module folder
cd "$module"
echo Backing up for $module | tee -a $logfile
# if it has a git repo, then it was cloned
if [ -d ".git" ]; then
# get the remote repo url
repo1=$(git remote -v | git remote -v| grep fetch -m1 | awk '{ print $2}')
# just the module name, not the path
mname=$(echo $module |awk -F/ '{print $NF}')
if [[ "$repo1" == *"$mname"* ]]; then
echo -e "found module $mname \n\t installed from $repo1" | tee -a $logfile
# save it to the file
echo $repo1 >>$repo_list
cd $module
untracked=$(git ls-files --other | grep -v / | grep -v package-lock.json | grep -v package.json)
if [ "$untracked." != "." ]; then
echo untracked files for module $module = $untracked >> $logfile
# if the folder doesn't exist
if [ ! -d $saveDir/$mname ]; then
# create it.
mkdir $saveDir/$mname 2>/dev/null
fi
# copy the untracked(extra) files to the backup for this module
cp -a $untracked $saveDir/$mname
fi
cd - >/dev/null
else
echo -e "\e[91m module $repo cloned to unique folder name $mname not backed up \e[90m"
# reset the echo ansi code back to default
# could save the folder name along with the url
# and then clone to the correct folder, rename the modulename.js and use sed to change the register clause too..
tput init 2>/dev/null
echo
fi
else
echo -e "\e[91m module $module was not cloned from github, so no link can be saved, not backed up \e[90m"
tput init 2>/dev/null
echo
fi
# back to the current folder
cd - >/dev/null
fi
done
if [ -e $repo_list ]; then
savefile=temp
cat $repo_list | sort -t/ -k5 >$savefile
rm $repo_list
mv $savefile $repo_list
fi
fi
cd $saveDir
# check for local info on username email so commits work
# get the git userid , if any
if [ "$(git config user.email)." == "." ]; then
# git info not set
if [ "$user_name." == "." ]; then
# prompt for users name
git config --local user.name $user_name
else
git config --local user.name $user_name
fi
if [ "$email." == "." ]; then
# prompt for email address
git config --local user.email $email
else
git config --local user.email $email
fi
#else
# echo no user name or email set, required to save changes to git, please see the -u and -e parameters | tee -a $logfile
# exit 3
fi
# add all the changed files
git add .
# commit them to the local repo
git commit -m "updated on $(date) $msg"
# check for any new named tags
last_tag=$(git for-each-ref --sort=creatordate --format '%(refname)' | grep tags | grep -v - | awk -F/ {'print $3'} | sort -r -g | head -n1)
# if we found some then we have the highest number
if [ "$last_tag." != "." ]; then
next_tagnumber=$((last_tag+1))
fi
# lets check rename any old date named tags
if [ $mac != 'Darwin' ]; then
SAVEIFS=$IFS # Save current IFS
IFS=$'\n'
fi
# split output on new lines, not spaces
tag_list=($(git for-each-ref --sort=creatordate --format '%(refname)' | grep tags | grep - | awk -F/ {'print $3'}))
if [ $mac != 'Darwin' ]; then
IFS=$SAVEIFS
fi
if [ ${#tag_list} -gt 0 ]; then
for tag in "${tag_list[@]}"
do
git tag $next_tagnumber $tag 2>/dev/null
git tag -d $tag 2>/dev/null
next_tagnumber=$((next_tagnumber+1))
done
else
:
fi
git tag -a $next_tagnumber -m "backup on $(date) $msg"
echo backup completed, see the git repo at $saveDir| tee -a $logfile
remote=false
# should we push now?
if [ "$push." == "." ]; then
# no, tell user to do it
echo "because you didn't request push"
echo recommended you "git push --tags" from this folder \($saveDir\) to backup your repo on github | tee -a $logfile
echo see "https://github.com/new"
echo to learn how to create a repo on github and the commands to sync your local system to the github repo
else
# yes push
cd $saveDir
# did they specify the repo
if [ "$reponame." != "." ]; then
remote=true
# no, is it set already?
repo=$(git remote -v 2>/dev/null| grep fetch -m1 | awk '{ print $2}')
# no, need to prompt for repo name
if [ "$repo." == "." ]; then
# remote not set yet
# name not specified
# need to prompt
# repo
# if we had their userid, we could get the list of repos to pick from
git remote add origin "https://github.com/$user_name/$reponame.git"
git branch -M main
repo=$(git remote -v| grep fetch -m1 | awk '{ print $2}')
fi
# git remote add origin https://github.com/$user_name/$reponame.git
# git branch -M main
#fi
git push -u origin main --tags
fi
fi
echo see this link for how to fetch tags for restore
echo https://devconnected.com/how-to-list-git-tags/
echo or run the list_tags.sh command from this repo
cd - >/dev/null
date +"backup ended - %a %b %e %H:%M:%S %Z %Y" >>$logfile