This repository was archived by the owner on Feb 25, 2020. It is now read-only.
mirrored from https://leap.se/git/leap_platform.git
-
Notifications
You must be signed in to change notification settings - Fork 24
Expand file tree
/
Copy pathapt-fast
More file actions
366 lines (316 loc) · 11.4 KB
/
apt-fast
File metadata and controls
366 lines (316 loc) · 11.4 KB
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
#!/bin/bash
#
# apt-fast v1.8
# Use this just like aptitude or apt-get for faster package downloading.
#
# Copyright: 2008-2012 Matt Parnell, http://www.mattparnell.com
# Improvements, maintenance, revisions - 2012 Dominique Lasserre
#
# You may distribute this file under the terms of the GNU General
# Public License as published by the Free Software Foundation; either
# version 3 of the License, or (at your option) any later version.
#
[ -n "$DEBUG" ] && set -xv
# Print colored messages.
# Usage: msg "message text" "message type" "optional: err"
# Message types are 'normal', 'hint' or 'warning'. Warnings and messages with a
# third argument are piped to stderr.
msg(){
case "$2" in
normal) beginColor="$cGreen";;
hint) beginColor="$cBlue";;
warning) beginColor="$cRed";;
esac
if [ -z "$3" ] && [ "$2" != "warning" ]; then
echo -e "${aptfast_prefix} ${beginColor}$1${endColor}";
else
echo -e "${aptfast_prefix} ${beginColor}$1${endColor}"; >&2
fi
}
# Search for known options and decide if root privileges are needed.
root=1 # default value: we need root privileges
option=
for arguments in $@; do
if [ "$arguments" == "upgrade" ] ||
[ "$arguments" == "install" ] ||
[ "$arguments" == "dist-upgrade" ] ||
[ "$arguments" == "build-dep" ]; then
option="install"
break
elif [ "$arguments" == "clean" ] ||
[ "$arguments" == "autoclean" ]; then
option="clean"
break
elif [ "$arguments" == "download" ]; then
option="download"
root=0
break
elif [ "$arguments" == "source" ]; then
option="source"
root=0
break
elif [ "$arguments" == "changelog" ]; then
root=0
break
fi
done
# To handle priority of options correctly (environment over config file vars)
# we need to preserve all interesting env variables. As this wouldn't be
# difficult enough we have to preserve complete env vars (especially if value
# ist set (even empty) or not) when changing context (sudo)...
# Set a 'random' string to all unset variables.
TMP_RANDOM="13979853562951413"
TMP_LCK_FILE="${LCK_FILE-${TMP_RANDOM}}"
TMP_DOWNLOADBEFORE="${DOWNLOADBEFORE-${TMP_RANDOM}}"
TMP__APTMGR="${_APTMGR-${TMP_RANDOM}}"
TMP_APTCACHE="${APTCACHE-${TMP_RANDOM}}"
TMP_DLDIR="${DLDIR-${TMP_RANDOM}}"
TMP_DLLIST="${DLLIST-${TMP_RANDOM}}"
TMP_LISTDIR="${LISTDIR-${TMP_RANDOM}}"
TMP__MAXNUM="${MAXNUM-${TMP_RANDOM}}"
TMP_aptfast_prefix="${aptfast_prefix-${TMP_RANDOM}}"
TMP_APT_FAST_TIMEOUT="${APT_FAST_TIMEOUT-${TMP_RANDOM}}"
# Check for proper privileges.
# Call explicitly with environment variables to get them into root conext.
if [ "$root" = 1 -a "$UID" != 0 ]; then
exec sudo DEBUG="$DEBUG" \
LCK_FILE="$TMP_LCK_FILE" \
DOWNLOADBEFORE="$TMP_DOWNLOADBEFORE" \
_APTMGR="$TMP__APTMGR" \
APTCACHE="$TMP_APTCACHE" \
DLDIR="$TMP_DLDIR" \
DLLIST="$TMP_DLLIST" \
LISTDIR="$TMP_LISTDIR" \
_MAXNUM="$TMP_MAXNUM" \
aptfast_prefix="$TMP_aptfast_prefix" \
APT_FAST_TIMEOUT="$TMP_APT_FAST_TIMEOUT" "$0" "$@"
fi
# Define lockfile.
# Use /tmp as directory because everybody (not only root) has to have write
# permissions.
# We need lock for non-root commands too, because we only have one download
# list file.
LCK_FILE="/tmp/apt-fast"
LCK_FD=99
# Set default package manager, APT cache, temporary download dir,
# temporary download list file, and maximal parallel downloads
_APTMGR=apt-get
eval $(apt-config shell APTCACHE Dir::Cache::archives/d)
# Check if APT config option Dir::Cache::archives::apt-fast-partial is set.
eval $(apt-config shell apt_fast_partial Dir::Cache::archives::apt-fast-partial/d)
if [ -z "$apt_fast_partial" ]; then
eval $(apt-config -o Dir::Cache::archives::apt-fast-partial=apt-fast shell DLDIR Dir::Cache::archives::apt-fast-partial/d)
else
eval $(apt-config shell DLDIR Dir::Cache::archives::apt-fast-partial/d)
fi
# Currently not needed.
eval $(apt-config shell LISTDIR Dir::State::lists/d)
DLLIST="/tmp/apt-fast.list"
_MAXNUM=5
# Prefix in front of apt-fast output:
aptfast_prefix=
# Set color variables.
cGreen='\e[0;32m'
cRed='\e[0;31m'
cBlue='\e[0;34m'
endColor='\e[0m'
# Set timout value for apt-fast download confirmation dialog.
# Value is in seconds.
APT_FAST_TIMEOUT=60
# Download command.
_DOWNLOADER='aria2c -c -j ${_MAXNUM} -x ${_MAXNUM} -s ${_MAXNUM} -i ${DLLIST} --min-split-size=1M --connect-timeout=600 --timeout=600 -m0'
# Load config file.
CONFFILE="/etc/apt-fast.conf"
if [ -e "$CONFFILE" ]; then
source "$CONFFILE"
fi
# Now overwrite with preserved values if values were set before (compare with
# 'random' string).
[ "$TMP_LCK_FILE" = "$TMP_RANDOM" ] || LCK_FILE="$TMP_LCK_FILE"
[ "$TMP_DOWNLOADBEFORE" = "$TMP_RANDOM" ] || DOWNLOADBEFORE="$TMP_DOWNLOADBEFORE"
[ "$TMP__APTMGR" = "$TMP_RANDOM" ] || _APTMGR="$TMP__APTMGR"
[ "$TMP_APTCACHE" = "$TMP_RANDOM" ] || APTCACHE="$TMP_APTCACHE"
[ "$TMP_DLDIR" = "$TMP_RANDOM" ] || DLDIR="$TMP_DLDIR"
[ "$TMP_DLLIST" = "$TMP_RANDOM" ] || DLLIST="$TMP_DLLIST"
[ "$TMP_LISTDIR" = "$TMP_RANDOM" ] || LISTDIR="$TMP_LISTDIR"
[ "$TMP__MAXNUM" = "$TMP_RANDOM" ] || _MAXNUM="$TMP__MAXNUM"
[ "$TMP_aptfast_prefix" = "$TMP_RANDOM" ] || aptfast_prefix="$TMP_aptfast_prefix"
[ "$TMP_APT_FAST_TIMEOUT" = "$TMP_RANDOM" ] || APT_FAST_TIMEOUT="$TMP_APT_FAST_TIMEOUT"
# Disable colors if not executed in terminal.
if [ ! -t 1 ]; then
cGreen=
cRed=
cBlue=
endColor=
#FIXME: Time not updated.
[ -z "$aptfast_prefix" ] && aptfast_prefix="[apt-fast $(date +"%T")]"
fi
msg_already_running()
{
msg "apt-fast already running!" "warning"
msg "Verify that all apt-fast processes are finished then remove $LCK_FILE.lock and try again." "hint"
}
# Check if a lock file exists.
if [ -f "$LCK_FILE.lock" ]; then
msg_already_running
exit 1
fi
# create the lock file and lock it, die on failure
_create_lock()
{
eval "exec $LCK_FD>\"$LCK_FILE.lock\""
trap "_remove_lock; exit" EXIT
trap "_remove_lock; exit 1;" INT KILL TERM
flock -n $LCK_FD || { msg_already_running; exit 1; }
}
# unlock and remove the lock file
_remove_lock()
{
flock -u "$LCK_FD" 2>/dev/null
rm -f "$LCK_FILE.lock"
}
# Check if mirrors are available. And if so add all mirrors to download list.
get_mirrors(){
# Check all mirror lists.
for mirrorstr in ${MIRRORS[@]}; do
# Build mirrors array from comma separated string.
mirrors=( $(echo "$mirrorstr" | sed "s/\([^,]\+\)\s*,\s*/\1 /g") )
# This does not the \s*,\s* trick, so we use sed instead to make it more
# robust.
#mirrors=( ${mirrorstr//,/ } )
# Check for all mirrors if URI of $1 is from mirror. If so add all other
# mirrors to (resmirror) list and break all loops.
for mirror in ${mirrors[@]}; do
# Real expension.
if [[ "$1" == "$mirror"* ]]; then
filepath=${1#${mirror}}
# Build list for aria download list.
list="${mirrors[@]}"
echo -e "${list// /${filepath}\t}$filepath\n"
return 0
fi
done
done
# No other mirrors found.
echo "$1"
}
# Get the package URLs.
get_uris(){
# Add header to overwrite file.
echo "# apt-fast mirror list: $(date)" > "$DLLIST"
#NOTE: aptitude doesn't have this functionality, so we use apt-get to get
# package URIs.
for urimd5 in $(apt-get -y --print-uris "$@" | egrep "^'(http(s|)|(s|)ftp)://[^']+'.+ MD5Sum:\S+\s*$" |
sed "s/^'\(.\+\)'.*MD5Sum:\(\S\+\)\s*$/\1::MD5Sum:\2/"); do
#for urimd5 in $(cat foo | egrep "^'(http(s|)|(s|)ftp)://[^']+'.+ MD5Sum:\S+\s*$" |
# sed "s/^'\(.\+\)'.*MD5Sum:\(\S\+\)\s*$/\1::MD5Sum:\2/"); do
uri="${urimd5%::MD5Sum:*}"
checksum="${urimd5#*::MD5Sum:}"
echo "$(get_mirrors "$uri")" >> "$DLLIST"
#echo " dir=$DLDIR" >> "$DLLIST"
echo " checksum=md5=$checksum" >> "$DLLIST"
echo " out=$(basename $uri)" >> "$DLLIST"
done
#cat "$DLLIST"
#LCK_RM
#exit
}
# Create and insert a PID number to lockfile.
_create_lock
# Make sure aria2c (in general first parameter from _DOWNLOADER) is available.
CMD="$(echo "$_DOWNLOADER" | sed 's/^\s*\([^ ]\+\).*$/\1/')"
if [ ! $(command -v "$CMD") ]; then
msg "Command not found: $CMD" "normal" "err"
msg "You must configure $CONFFILE to use aria2c or another supported download manager" "normal" "err"
exit 1
fi
# Make sure package manager is available.
if [ ! $(command -v "$_APTMGR") ]; then
msg "\`$_APTMGR\` command not available." "warning"
msg "You must configure $CONFFILE to use either apt-get or aptitude." "normal" "err"
exit 1
fi
# Run actions.
if [ "$option" == "install" ]; then
msg "\n Working... this may take a while." "normal"
get_uris "$@"
# Check if "assume yes" switch is enabled and if yes enable $DOWNLOADBEFORE.
#TODO: Get real value over APT items APT::Get::Assume-Yes and
# APT::Get::Assume-No .
#FIXME: Composed short options e.g. "-yV" are not recognised - we should use
# getopts for proper option passing.
for option in $@; do
if [ "$option" == "-y" ] ||
[ "$option" == "--yes" ] ||
[ "$option" == "--assume-yes" ]; then
DOWNLOADBEFORE=true
elif [ "$option" == "--assume-no" ]; then
DOWNLOADBEFORE=
fi
done
# Test /tmp/apt-fast.list file exists AND not zero bytes.
# Then download all files from the list.
if [ $(cat "$DLLIST" | wc -l) -gt 0 ] && [ ! "$DOWNLOADBEFORE" ]; then
cat "$DLLIST"
echo -ne "${cRed} If you want to download the packages on your system press Y else n to abort. [Y/n]: ${endColor}"
while ((!updsys)); do
read -sn1 -t "$APT_FAST_TIMEOUT" answer || { msg "\n Timed out." "warning"; exit 1; }
case "$answer" in
[JjYy]) result=1; updsys=1 ;;
[Nn]) result=0; updsys=1 ;;
"") result=1; updsys=1 ;;
*) updsys=0 ;;
esac
done
else
result=1
fi
echo
# Continue if answer was right or DOWNLOADBEFORE is enabled.
if ((result)); then
if [ -s "$DLLIST" ]; then
# Test if apt-fast directory is present where we put packages.
if [ ! -d "$DLDIR" ]; then
mkdir -p -- "$DLDIR"
fi
cd "$DLDIR" &>/dev/null || exit 1
eval "${_DOWNLOADER}" # execute downloadhelper command
if [ $(find "$DLDIR" -printf . | wc -c) -gt 1 ]; then
# Move all packages to the apt install directory by force to ensure
# already existing debs which may be incomplete are replaced
find -type f -name "*.deb" -execdir mv -ft "$APTCACHE" {} \+
fi
cd - &>/dev/null
fi
else
exit 1
fi
"${_APTMGR}" "$@"
elif [ "$option" == "clean" ]; then
"${_APTMGR}" "$@" && {
find "$DLDIR" -maxdepth 1 -type f -delete
[ -f "$DLLIST" ] && rm -f -- "$DLLIST"*
}
elif [ "$option" == "download" ]; then
get_uris "$@"
eval "${_DOWNLOADER}"
elif [ "$option" == "source" ]; then
msg "\n Working... this may take a while.\n" "normal"
get_uris "$@"
eval "${_DOWNLOADER}"
# We use APT manager here to provide more verbose output. This method is
# slightly slower then extractiong packages manually after download but also
# more hardened (e.g. some options like --compile are available).
"${_APTMGR}" "$@"
# Uncomment following snippet to extract source directly and comment
# both lines before.
#while read srcfile; do
# # extract only .dsc files
# echo "$srcfile" | grep -q '\.dsc$' || continue
# dpkg-source -x "$(basename "$srcfile")"
#done < "$DLLIST"
# Execute package manager directly if unknown options are passed.
else
"${_APTMGR}" "$@"
fi
# After error or all done remove our lockfile