forked from Botspot/pi-apps
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmanage
executable file
·348 lines (308 loc) · 12.9 KB
/
manage
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
#!/bin/bash
#$1 is an action, like install
#$2 is app name, like Arduino
DIRECTORY="$(readlink -f "$(dirname "$0")")"
function error {
echo -e "\e[91m$1\e[39m"
exit 1
}
if [ -z "$1" ];then
error "You need to specify an operation, and in most cases, which app to operate on."
fi
mkdir -p "${DIRECTORY}/data/status" "${DIRECTORY}/data/update-status"
#determine if host system is 64 bit arm64 or 32 bit armhf
if [ ! -z "$(file "$(readlink -f "/sbin/init")" | grep 64)" ];then
arch=64
elif [ ! -z "$(file "$(readlink -f "/sbin/init")" | grep 32)" ];then
arch=32
else
error "Failed to detect OS CPU architecture! Something is very wrong."
fi
dirhash() {
#find "${DIRECTORY}/update/pi-apps/apps/${2}" -type f -print0
#echo "Hashing this dir: $1" 1>&2
#------ hash every file in the folder ---------------- and add to it the filesystem list ------ hash it again
hash="$(echo -e "$(find "$1" -type f -print0 | xargs -0 sha1sum | awk '{print $1}')$(find "$1" -type f -exec basename {} \;)" | sha1sum | awk '{print $1}')"
echo "$hash"
}
if [ "$1" == 'multi-install' ];then
failed=0
PREIFS="$IFS"
IFS=$'\n'
for app in $2
do
"${DIRECTORY}/manage" install "$app"
if [ $? != 0 ];then
failed=1
fi
done
IFS="$PREIFS"
if [ $failed == 1 ];then
exit 1
#disable donate box
elif false && [ "$(ls "${DIRECTORY}/data/status" | wc -l)" -ge 5 ] && [ "$(($(date --utc --date '' +%s)/86400-30))" -ge "$(cat "${DIRECTORY}/data/last-donate-ask" 2>/dev/null || echo "0")" ];then
donatebox() {
TEXT="$(wget -qO- https://raw.githubusercontent.com/Botspot/pi-apps-announcements/main/donate_message)"
if [ -z "$TEXT" ];then
TEXT=" <b>Pi-Apps depends on you!</b>
I (Botspot) have spent <b>over 300 hours</b> programming Pi-Apps.
Without financial support, I can't continue developing Pi-Apps as much as I have been. :(
If every Pi-Apps user pitched in a mere <i>25 cents</i>, I could work on open-source development full-time.
If Pi-Apps has saved you time & effort, please consider donating. Any amount helps.
"
fi
yad --title="Donations, anyone?" --center \
--window-icon="${DIRECTORY}/icons/logo.png" \
--text="$(echo -e "$TEXT")" \
--button='Support Pi-Apps'!"${DIRECTORY}/icons/paypal.png":0 \
--button='No thanks'!"${DIRECTORY}/icons/exit.png"!"I respect your decision.
Pi-Apps will always be free, but if everyone clicks this button, it won"\'"t be maintained forever.":1
button=$?
if [ $button == 0 ];then
#open donation page if button 0 clicked
#x-www-browser 'https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=V6W8WM4GN8AJ2&item_name=Pi-Apps+development¤cy_code=USD'
x-www-browser 'https://paypal.me/josephmarchand'
fi
#don't ask again for 30 days, no matter what button clicked
echo "$(($(date --utc --date '' +%s)/86400))" > "${DIRECTORY}/data/last-donate-ask"
}
export -f donatebox
export DIRECTORY
setsid bash -c donatebox
fi
elif [ "$1" == 'multi-uninstall' ];then
failed=0
PREIFS="$IFS"
IFS=$'\n'
for app in $2
do
"${DIRECTORY}/manage" uninstall "$app"
if [ $? != 0 ];then
failed=1
fi
done
IFS="$PREIFS"
if [ $failed == 1 ];then
exit 1
fi
elif [ "$1" == 'install-if-not-installed' ];then
#if not installed
if [ ! -f "${DIRECTORY}/data/status/$2" ] || [ "$(cat "${DIRECTORY}/data/status/$2")" != installed ];then
#install it
"${DIRECTORY}/manage" install "$2" || exit 1
fi
elif [ "$1" == 'install' ];then
#INSTALL
#for this operation, a program name must be specified.
app="$2"
if [ -z "$app" ];then
error "For this operation, you must specify which app to operate on."
elif [ ! -d "${DIRECTORY}/apps/$app" ];then
error "${DIRECTORY}/apps/$app does not exist!"
fi
#if already installed then ask for confirmation
if [ "$(cat "${DIRECTORY}/data/status/${app}" 2>/dev/null)" == 'installed' ];then
yad --text="$app is already installed. Are you sure you want to install it again?" \
--text-align=center --center --title='Quick question' --window-icon="${DIRECTORY}/icons/logo.png" \
--button=No!"${DIRECTORY}/icons/exit.png":1 --button=Yes!"${DIRECTORY}/icons/check.png":0 || exit 0
fi
#analytics
"${DIRECTORY}/etc/bitlylink" "$app" install
#determine which script to run
if [ -f "${DIRECTORY}/apps/${app}/install-32" ] && [ $arch == 32 ];then
installscript="${DIRECTORY}/apps/${app}/install-32"
scriptname='install-32'
elif [ -f "${DIRECTORY}/apps/${app}/install-64" ] && [ $arch == 64 ];then
installscript="${DIRECTORY}/apps/${app}/install-64"
scriptname='install-64'
elif [ -f "${DIRECTORY}/apps/${app}/install" ];then
installscript="${DIRECTORY}/apps/${app}/install"
scriptname='install'
else
error "It appears $app does not have an install-${arch} script suitable for your ${arch}-bit OS."
fi
echo -e "\e[96mInstalling $app with $scriptname script\e[39m"
cd $HOME
echo 'corrupted' > "${DIRECTORY}/data/status/${app}"
if nice "$installscript" ; then
echo 'installed' > "${DIRECTORY}/data/status/${app}"
echo -e "\n\e[42m\e[30mInstalled ${app} successfully.\e[39m\e[49m"
exit 0
else
echo -e "\n\e[41m\e[30mFailed to install ${app} with $scriptname script!\e[39m\e[49m"
exit 1
fi
elif [ "$1" == 'uninstall' ];then
#UNINSTALL
#for this operation, a program name must be specified.
app="$2"
if [ -z "$app" ];then
error "For this operation, you must specify which app to operate on."
elif [ ! -d "${DIRECTORY}/apps/$app" ];then
error "${DIRECTORY}/apps/$app does not exist!"
fi
#if already uninstalled then ask for confirmation
if [ "$(cat "${DIRECTORY}/data/status/${app}" 2>/dev/null)" == 'uninstalled' ];then
yad --text="$app is already uninstalled. Are you sure you want to uninstall it again?" \
--text-align=center --center --title='Quick question' --window-icon="${DIRECTORY}/icons/logo.png" \
--button=No!"${DIRECTORY}/icons/exit.png":1 --button=Yes!"${DIRECTORY}/icons/check.png":0 || exit 0
fi
#analytics
"${DIRECTORY}/etc/bitlylink" "$app" uninstall
echo -e "\e[96mUninstalling $app\e[39m"
cd $HOME
echo 'corrupted' > "${DIRECTORY}/data/status/${app}"
if "${DIRECTORY}/apps/${app}/uninstall" ; then
echo 'uninstalled' > "${DIRECTORY}/data/status/${app}"
echo -e "\n\e[42m\e[30mUninstalled ${app} successfully.\e[39m\e[49m"
exit 0
else
echo -e "\n\e[41m\e[30mFailed to uninstall ${app}!\e[39m\e[49m"
exit 1
fi
elif [ "$1" == 'update' ];then
#UPDATE
#for this operation, a program name must be specified.
app="$2"
if [ -z "$app" ];then
error "For this operation, you must specify which app to operate on."
fi
#HIDDEN FEATURE - if $3 equals nofetch, then don't download github repo. Useful for updating multiple apps at maximum speed
if [ "$3" == 'nofetch' ] && [ -d "${DIRECTORY}/update" ];then
true
else
rm -rf "${DIRECTORY}/update" && mkdir "${DIRECTORY}/update" && cd "${DIRECTORY}/update" || error "failed to enter the update directory!"
git clone --depth=1 "$(cat "${DIRECTORY}/etc/git_url")" || error "failed to clone repository!"
fi
newhash="$(dirhash "${DIRECTORY}/update/pi-apps/apps/${app}")"
oldhash="$(dirhash "${DIRECTORY}/apps/${app}")"
#detect which installation script exists and get the hash for that one
if [ -f "${DIRECTORY}/update/pi-apps/apps/${app}/install-32" ];then
scriptname='install-32'
elif [ -f "${DIRECTORY}/update/pi-apps/apps/${app}/install-64" ];then
scriptname='install-64'
elif [ -f "${DIRECTORY}/update/pi-apps/apps/${app}/install" ];then
scriptname='install'
else
error "No install script found for the $app app! Please report this to Botspot."
fi
newinstallhash=$(sha1sum "${DIRECTORY}/update/pi-apps/apps/${app}/${scriptname}" | awk '{print $1}')
oldinstallhash=$(sha1sum "${DIRECTORY}/apps/${app}/${scriptname}" | awk '{print $1}')
#echo -e "newinstallhash: $newinstallhash\noldinstallhash: $oldinstallhash"
#echo -e "newhash: $newhash\noldhash: $oldhash"
if [ "$newhash" == "$oldhash" ];then
echo "$app is identical to the online version. Nothing to do!"
exit 0
else
echo "$app is not identical to the online version."
fi
#else
installback=no
#if install was changed #if installed already
if [ "$newinstallhash" != "$oldinstallhash" ] && [ "$(cat "${DIRECTORY}/data/status/${app}" 2>/dev/null)" == 'installed' ];then
installback=yes
echo "$app's install script has been updated. Reinstalling $app..."
#uninstall it using a recursive script instance
"${DIRECTORY}/manage" uninstall "$app"
fi
#move old program to trash
gio trash "${DIRECTORY}/apps/${app}" 2>/dev/null
#failsafe
[ -d "${DIRECTORY}/apps/${app}" ] && error "${DIRECTORY}/apps/${app} still exists, despite trying to delete it!"
#copy new version to apps/
cp -rf "${DIRECTORY}/update/pi-apps/apps/${app}" "${DIRECTORY}/apps/${app}"
if [ "$installback" == 'yes' ] && [ "$(cat "${DIRECTORY}/data/settings/Reinstall after update")" != 'No' ];then
echo "$app was originally installed before updating. Reinstalling the new version now."
#install it using a recursive script instance
"${DIRECTORY}/manage" install "$app"
fi
echo -e "\e[92m${app} was updated successfully.\e[39m"
elif [ "$1" == 'check-all' ];then
#CHECK-ALL
#for this operation, a program name cannot be specified.
#hidden flag: if $2 is 'installedonly', then only check for updates for those apps that are installed
if [ "$2" == 'installedonly' ];then
installedonly=1
else
installedonly=0
fi
rm -rf "${DIRECTORY}/update" && mkdir "${DIRECTORY}/update" && cd "${DIRECTORY}/update" || error "failed to enter the update directory!"
git clone --depth=1 "$(cat "${DIRECTORY}/etc/git_url")" || error "failed to clone repository!"
#generate entire app list, combine local apps and online apps to one list
applist="$(echo -e "$(ls "${DIRECTORY}/update/pi-apps/apps")\n$(ls "${DIRECTORY}/apps")" | sort | uniq)"
#installedonly flag enabled. Remove apps that are uninstalled
if [ $installedonly == 1 ];then
echo "installedonly flag set to 1" 1>&2
PREIFS="$IFS"
IFS=$'\n'
for app in $applist
do
if [ ! -f "${DIRECTORY}/data/status/${app}" ] || [ "$(cat "${DIRECTORY}/data/status/${app}" 2>/dev/null)" == 'uninstalled' ];then
#if app is uninstalled, then remove it from the list.
applist="$(echo "$applist" | grep -vx "$app")"
echo "Removing ${app} from list because it is uninstalled." 1>&2
fi
done
IFS="$PREIFS"
fi
applist="$(echo "$applist" | tr '\n' '|')"
#echo "App list: $applist" 1>&2
updatable=''
PREIFS="$IFS"
IFS="|"
for app in $applist
do
#echo "app: $app"
newhash="$(dirhash "${DIRECTORY}/update/pi-apps/apps/${app}")"
oldhash="$(dirhash "${DIRECTORY}/apps/${app}")"
#echo -e "newhash: $newhash\noldhash: $oldhash" 1>&2
if [ "$newhash" == "$oldhash" ];then
echo -e "${app} is identical\e[90m to the online version. Nothing to do!\e[39m" 1>&2
echo 'latest' > "${DIRECTORY}/data/update-status/${app}"
else
if [ ! -d "${DIRECTORY}/apps/${app}" ];then
echo -e "\e[97m${app} does not exist locally.\e[39m Adding to updatable list." 1>&2
echo 'new' > "${DIRECTORY}/data/update-status/${app}"
#in this case, add to updatable list
updatable="${updatable}|${app}"
elif [ ! -d "${DIRECTORY}/update/pi-apps/apps/${app}" ];then
echo -e "\e[97m${app} only exists locally.\e[39m Will not add to updatable list." 1>&2
echo 'local' > "${DIRECTORY}/data/update-status/${app}"
#in this case, do not add to updatable list
else
echo -e "\e[97m${app} exists in both locations, but online version is newer\e[39m. Adding to updatable list." 1>&2
echo 'updatable' > "${DIRECTORY}/data/update-status/${app}"
#in this case, add to updatable list
updatable="${updatable}|${app}"
fi
fi
done
IFS="$PREIFS"
#remove initial '|' character
updatable="${updatable:1}"
if [ -z "$updatable" ];then
updatable='.'
fi
echo -e "\e[97mThese apps can be updated:\n${updatable}"
elif [ "$1" == 'update-all' ];then
#UPDATE-ALL
#for this operation, a program name cannot be specified.
PREIFS="$IFS"
IFS='|'
updatable="$("${DIRECTORY}/manage" check-all | tail -1)"
if [ "$updatable" == '.' ];then
updatable=''
fi
echo "Updatable: ${updatable}EOU"
for updateapp in $updatable
do
echo "updating $updateapp"
#update it using a recursive script instance
echo "${DIRECTORY}/manage update $updateapp"
"${DIRECTORY}/manage" update "$updateapp" || exit 1
done
IFS="$PREIFS"
echo -e '\e[92mOperation completed successfully!\e[39m'
else
error "Did not understand $1. Allowed values: 'install', 'install-if-not-installed', 'multi-install', 'multi-uninstall', 'update', 'check-all', or 'update-all'."
fi