forked from Botspot/pi-apps
-
Notifications
You must be signed in to change notification settings - Fork 0
/
updater
executable file
·305 lines (257 loc) · 11.1 KB
/
updater
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
#!/bin/bash
{ #this curly brace at start and end of script prevents issues when this script edits itself. See: https://stackoverflow.com/a/19430939
DIRECTORY="$(readlink -f "$(dirname "$0")")"
function error {
echo -e "\e[91m$1\e[39m"
exit 1
}
#for the will_reinstall() and list_intersect() functions
source "${DIRECTORY}/api" || error "failed to source ${DIRECTORY}/api"
#NOTE TO SELF BOTSPOT: REMOVE THE FASTMODE VARIABLE SETTING!!!
#fastmode=1
{ # Determine if checking for updates today
lastupdatecheck="$(cat "${DIRECTORY}/data/last-update-check")"
if [ -z $lastupdatecheck ];then
echo "Warning: ${DIRECTORY}/data/last-update-check does not exist!"
lastupdatecheck=0
fi
updateinterval="$(cat "${DIRECTORY}/data/settings/Check for updates")"
nocheck=0
#allowed values: Always, Daily, Weekly, Never
if [ "$updateinterval" == 'Never' ];then
nocheck=1
echo ''
elif [ "$updateinterval" == 'Daily' ];then
#if updates checked today, don't check
if [ "$(date +%j)" == "$lastupdatecheck" ];then
nocheck=1
fi
elif [ "$updateinterval" == 'Weekly' ];then
#if updates checked less than 7 days ago, don't check
if [ "$(date +%j)" -le "$((lastupdatecheck + 7))" ];then
nocheck=1
fi
elif [ "$updateinterval" == 'Always' ];then
echo "Checking for updates now..."
elif [ -z "$updateinterval" ];then
echo "Something isn"\'" right. Does ${DIRECTORY}/data/settings/Check for updates exist?"
else
echo "Warning: Unrecognized update interval!"
fi
#fix for new years day
if [ "$lastupdatecheck" -gt "$(date +%j)" ];then
nocheck=0
fi
#forcibly check if fastmode variable is 1
if [ "$fastmode" == 1 ];then
nocheck=0
fi
#hidden flag: if $1 is 'onboot', then check for updates only for those apps that are installed.
onboot="$1"
if [ "$onboot" == 'onboot' ] || [ "$onboot" == 'installedonly' ];then
onboot='onboot'
#make sure user installed some apps first. If none installed, then Pi-Apps may be unwanted/unused.
if [ "$(ls "${DIRECTORY}/data/status" | wc -l)" == 0 ];then
echo "No apps have been installed yet, so exiting now."
exit 0
fi
sleep 10 #wait 10 seconds, this is so the system will have booted all the way for an internet connection
fi
if [ $nocheck == 1 ];then
echo "Won"\'"t check for updates today, because of the update interval is set to $updateinterval in Settings.
To forcibly check for updates now, press any key within the next 20 seconds."
read -n 1 -t 20 || exit 0
echo ''
fi
#write today's date to file. Format is "number of days since jan 1"
echo "$(date +%j)" > "${DIRECTORY}/data/last-update-check"
}
#if fastmode is 1, then rely on previously gathered updatable app information. This information is located in data/update-status.
if [ "$fastmode" == 1 ];then
updatable="$("${DIRECTORY}/manage" check-all nogenerate 2>/dev/null)"
else
#otherwise, re-download apps to update folder and hash them all to determine which apps can be updated
updatable="$("${DIRECTORY}/manage" check-all)"
fi
[ $? -ne 0 ] && error "check-all failed! Full output: $updatable"
#shorten to last line
if [ "$updatable" == '.' ];then
updatable=''
fi
echo "updatable: $updatable"
#if check-all succeeded to download the repo to the update folder
if [ ! -d "${DIRECTORY}/update" ];then
error "${DIRECTORY}/update does not exist. Most likely there is no Internet connection."
fi
#mainfiles="$(echo -e "$(ls -Rp "${DIRECTORY}/update/pi-apps")\n$(ls -Rp "${DIRECTORY}")" | grep -v '/' | sort | uniq | tr '\n' '|')"
#list all files in update folder
cd "${DIRECTORY}/update/pi-apps" || error "Failed to enter update directory!"
updatefiles="$(find . -type f | cut -c 3- | grep -v '.git/' | grep -v 'apps/' | grep -v 'data/')"
#list all files in main folder
cd "${DIRECTORY}"
localfiles="$(find . -type f | cut -c 3- | grep -v '.git/' | grep -v 'apps/' | grep -v 'data/' | grep -v 'logs/' | grep -v 'xlunch/')"
mergedfiles="$(echo -e "${localfiles}\n${updatefiles}" | sort | uniq)"
#exclude files mentioned in data/update-exclusion file
IFS=$'\n' #exclude commented lines
for file in $(cat "${DIRECTORY}/data/update-exclusion" | grep "^[^#;]")
do
mergedfiles="$(echo "$mergedfiles" | grep -v "$file")"
echo "Excluding '$file' from the mergedlist."
done
mergedfiles="$(echo "$mergedfiles")"
for file in $mergedfiles
do
newhash=$(cat "${DIRECTORY}/update/pi-apps/${file}" 2>/dev/null | sha1sum | awk '{print $1}' | sha1sum | awk '{print $1}')
oldhash=$(cat "${DIRECTORY}/${file}" 2>/dev/null | sha1sum | awk '{print $1}' | sha1sum | awk '{print $1}')
#echo -e "newhash: $newhash\noldhash: $oldhash"
if [ "$newhash" == "$oldhash" ];then
true
#echo -e "${file} is identical\e[90m to the online version. Nothing to do!\e[39m"
else
if [ ! -f "${DIRECTORY}/${file}" ];then
echo -e "\e[97m${file} does not exist locally.\e[39m Adding to updatable list."
#in this case, add to updatable list
mainupdate="${mainupdate}
${file}"
elif [ ! -f "${DIRECTORY}/update/pi-apps/${file}" ];then
echo -e "\e[97m${file} only exists locally.\e[39m Will not add to updatable list."
#in this case, do not add to updatable list
else
echo -e "\e[97m${file} exists in both locations, but files do not match.\e[39m Adding to updatable list."
#in this case, add to updatable list
mainupdate="${mainupdate}
${file}"
fi
fi
done
IFS="$PREIFS"
#remove initial newline character
mainupdate="${mainupdate:1}"
LIST=''
PREIFS="$IFS"
IFS=$'\n'
for app in $updatable #repeat for every updatable app
do
LIST="${LIST}TRUE
${DIRECTORY}/update/pi-apps/apps/${app}/icon-24.png
$app "\("$([ "$(cat "${DIRECTORY}/data/update-status/${app}")" == 'new' ] && echo 'new ')app$(will_reinstall "$app" && echo ', <b>will be reinstalled</b>')"\)"
$app
"
done
for file in $mainupdate #repeat for every updatable file
do
#determine mimetype of updatable file to display an informative icon in the list
if [ "$(file -b --mime-type "${DIRECTORY}/${file}")" == 'text/x-shellscript' ];then
#if updatable file in question is a shell script, then display shellscript icon.
mimeicon="${DIRECTORY}/icons/shellscript.png"
mimetype='script'
elif [[ "${DIRECTORY}/${file}" == *.png ]];then
mimeicon="${DIRECTORY}/icons/image.png"
mimetype='image'
else
#otherwise display txt icon.
mimeicon="${DIRECTORY}/icons/txt.png"
mimetype='file'
fi
LIST="${LIST}TRUE
${mimeicon}
$file "\("$mimetype"\)"
${file}
"
done
IFS="$PREIFS"
if [ -z "$LIST" ];then
echo -e '\e[92mNothing to update. Nothing to do!\e[39m'
exit 0
fi
LIST="${LIST::-1}" #remove last newline
#echo "List: ${LIST}EOL"
screen_width="$(xrandr | grep "HDMI-1" | awk '{print $4}' | tr 'x+' ' ' | awk '{print $1}')"
screen_height="$(xrandr | grep "HDMI-1" | awk '{print $4}' | tr 'x+' ' ' | awk '{print $2}')"
#display notification in lower-right, only if fastmode variable is not 1
if [ "$fastmode" != 1 ];then
output="$(yad --form --text='Pi-Apps updates available.' --separator='\n' \
--on-top --skip-taskbar --undecorated --close-on-unfocus \
--geometry=260+$((screen_width-262))+$((screen_height-150)) \
--image="${DIRECTORY}/icons/logo-64.png" \
--field='Never show again':CHK FALSE \
--button="Details!${DIRECTORY}/icons/info.png":0 --button="Close!${DIRECTORY}/icons/exit.png":2)"
button=$?
if [ $button != 0 ];then
if [ "$(echo "$output" | grep . )" == TRUE ];then
#User checked the 'Never show again' box, so ask to change update interval
curval="$(cat "${DIRECTORY}/data/settings/Check for updates")"
[ -z "$curval" ] && curval="$(cat "${DIRECTORY}/etc/setting-params/Check for updates" | grep -v '#' | head -n1)"
params="$(cat "${DIRECTORY}/etc/setting-params/Check for updates" | grep -v '#')"
params="$(echo "$params" | grep -x "$curval" | tr '\n' '!')!$(echo "$params" | grep -vx "$curval" | tr '\n' '!')"
params="$(echo -e "$params" | sed 's/!!/!/g' | sed 's/!$//g' | sed 's/^!//g')"
echo "Params: '$params'"
output="$(yad --center --title='Change Pi-Apps update interval' --width=440 \
--form --separator='\n' --window-icon="${DIRECTORY}/icons/logo.png" \
--text="You just requested for Pi-Apps to <i>never check for updates again</i>."$'\n'"Are you sure? If so, change the update interval to "\""<b>Never</b>"\"" below." \
--field='Update interval: ':CB "$params" \
--button=Cancel!"${DIRECTORY}/icons/exit.png":1 \
--button=Save!"${DIRECTORY}/icons/check.png":0)"
button=$?
output="$(echo "$output" | grep .)"
if [ $button == 0 ];then #save button clicked
echo "$output" > "${DIRECTORY}/data/settings/Check for updates"
fi
fi
#since Details was not clicked, exit now
exit 0
fi
fi
#If user clicks 'Details', then display a list of everything updatable
output="$(echo -e "$LIST" | yad --center --title='Pi-Apps' \
--window-icon="${DIRECTORY}/icons/logo.png" --width=310 --height=300 \
--list --checklist --separator='\n' --print-column=4 --no-headers \
--text="Updates available:"$'\n'"Uncheck an item to skip updating it." \
--column=:CHK --column=:IMG --column=Name --column=ID:HD \
--button='Later'!"${DIRECTORY}/icons/exit.png"!"Remind me later":1 \
--button='Update now'!"${DIRECTORY}/icons/download.png":0)" || exit 0
PREIFS="$IFS"
IFS=$'\n'
#remove empty newlines from output
output="$(echo "$output" | grep .)"
#limit list of update files to those selected by user.
#Edge case: if a file and app are named the same, they will appear in both lists if either one was selected.
updatable="$(echo "$updatable" | list_intersect "$output")"
#echo -e "\nWill update these apps:\n$updatable EOAPPS"
mainupdate="$(echo "$mainupdate" | list_intersect "$output")"
#echo "Will update these files:\n$mainupdate EOFILES"
for file in $mainupdate
do
mkdir -p "$(dirname "${DIRECTORY}/${file}")"
#copy new version to apps/
cp -f "${DIRECTORY}/update/pi-apps/${file}" "${DIRECTORY}/${file}" || echo -e "\e[91mFailed to copy ${DIRECTORY}/update/pi-apps/${file}\e[39m!"
echo -e "\e[92m${file} file was copied successfully.\e[39m"
done
IFS="$PREIFS"
if [ ! -z "$updatable" ];then
"${DIRECTORY}/etc/terminal-run" '
DIRECTORY="'"$DIRECTORY"'"
updatable="'"$updatable"'"
trap "sleep 10" EXIT
PREIFS="$IFS"
IFS=$'\''\n'\''
for i in $updatable
do
"${DIRECTORY}/manage" update "$i" nofetch
done
IFS="$PREIFS"
echo -e "\e[92mAll updates complete. Closing in 10 seconds.\e[39m"
' "Updating $(echo "$updatable" | wc -l) app$([ $(echo "$updatable" | wc -l) != 1 ] && echo s)..."
fi
#.git folder
#delete .git folder, then copy the new one
rm -rf "${DIRECTORY}/.git"
cp -rf "${DIRECTORY}/update/pi-apps/.git" "${DIRECTORY}/.git" || error "Failed to copy new .git folder!"
echo -e "\e[92mPi-Apps updates complete.\e[39m"
yad --form --text='Pi-Apps updates complete.' \
--on-top --skip-taskbar --undecorated --close-on-unfocus \
--geometry=260+$((screen_width-262))+$((screen_height-150)) \
--image="${DIRECTORY}/icons/logo-64.png" \
--button="Close!${DIRECTORY}/icons/exit.png":1
exit 0
} #this curly brace at start and end of script prevents issues when this script updates itself. See: https://stackoverflow.com/a/19430939