diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2020-02-07 11:53:08 +0100 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2020-02-07 11:58:31 +0100 |
commit | 507ae64c3e886b82435cbc963594ed5e2af3458f (patch) | |
tree | 873b009acbc94db6fd34c291fcb62603c709285a | |
parent | 06031d3add92479fce6b02971a23ad5931ee26dd (diff) | |
download | slackupgrade-507ae64c3e886b82435cbc963594ed5e2af3458f.tar.gz slackupgrade-507ae64c3e886b82435cbc963594ed5e2af3458f.tar.bz2 |
Implement the "safe upgrade" mode
In safe upgrade mode, all the necessary package tarballs are first
downloaded to the spool directory. Once downloaded, the program
starts upgrading using these tarballs. Each tarball is removed after
being processed.
The old ("incremental") mode is used if there is not enough disk space
for full download.
-rw-r--r-- | slackupgrade | 288 | ||||
-rw-r--r-- | slackupgrade.8 | 158 |
2 files changed, 353 insertions, 93 deletions
diff --git a/slackupgrade b/slackupgrade index 662b325..ff4d46f 100644 --- a/slackupgrade +++ b/slackupgrade | |||
@@ -2,6 +2,6 @@ | |||
2 | # slackupgrade - full upgrade of a Slackware installation | 2 | # slackupgrade - full upgrade of a Slackware installation |
3 | # Copyright (C) 2019 Sergey Poznyakoff. | 3 | # Copyright (C) 2019-2020 Sergey Poznyakoff. |
4 | # | 4 | # |
5 | # Slackware-upgrade-system is free software; you can redistribute it and/or | 5 | # Slackware-upgrade-system is free software; you can redistribute it and/or |
6 | # modify it under the terms of the GNU General Public License as published | 6 | # modify it under the terms of the GNU General Public License as published |
7 | # by the Free Software Foundation; either version 3, or (at your option) | 7 | # by the Free Software Foundation; either version 3, or (at your option) |
@@ -22,2 +22,3 @@ set -e | |||
22 | : ${SLACKUPGRADE_CONFDIR:=/etc/slackupgrade} | 22 | : ${SLACKUPGRADE_CONFDIR:=/etc/slackupgrade} |
23 | : ${SLACKUPGRADE_PKGDIR:=/var/slackupgrade} | ||
23 | # Slackware root directory | 24 | # Slackware root directory |
@@ -43,2 +44,16 @@ keep_file= | |||
43 | max_backup=4 | 44 | max_backup=4 |
45 | # Display progress bar when downloading | ||
46 | progressbar=1 | ||
47 | # Operating mode. Possible values: | ||
48 | # INCR Incremental mode. Archive for each package is downloaded prior | ||
49 | # to its nstallation and removed immediately afterwards. This | ||
50 | # ensures minimal disk space requirements. | ||
51 | # SAFE Safe mode. All archives are first downloaded to | ||
52 | # SLACKUPGRADE_PKGDIR and then installed. Each archive is removed | ||
53 | # immediately after installing from it. This requires some 2.5G | ||
54 | # of disk space at the beginning, which will be freed by the end | ||
55 | # of upgrade. | ||
56 | # AUTO Select incremental mode if there is enough disk space. If not, | ||
57 | # ask the user if it is OK to proceed in incremental mode. | ||
58 | opmode=AUTO | ||
44 | 59 | ||
@@ -47,2 +62,3 @@ remote= | |||
47 | tempdir=${TMP:-/tmp}/slackupg.$$ | 62 | tempdir=${TMP:-/tmp}/slackupg.$$ |
63 | strip_series=0 | ||
48 | installed_list=$tempdir/installed.list | 64 | installed_list=$tempdir/installed.list |
@@ -134,2 +150,4 @@ function error() { | |||
134 | 150 | ||
151 | # Abnormal termination: print error message, remove temporary directory | ||
152 | # and terminate with status 1. | ||
135 | function abend() { | 153 | function abend() { |
@@ -145,10 +163,8 @@ function package_file_name() { | |||
145 | else | 163 | else |
146 | echo $pkg | 164 | echo $pkg |
147 | fi | 165 | fi |
148 | } | ||
149 | |||
150 | function package_name_md5sum() { | ||
151 | pkg=$(awk -vname=$1 '$1==name { print $3 }' $avail_index) | ||
152 | } | 166 | } |
153 | 167 | ||
168 | # check_package_md5sum PKG ARCHIVE | ||
169 | # Verifies the MD5 sum of the ARCHIVE file for Slackware package PKG | ||
154 | function check_package_md5sum() { | 170 | function check_package_md5sum() { |
@@ -161,2 +177,4 @@ function check_package_md5sum() { | |||
161 | 177 | ||
178 | # all_package_names | ||
179 | # Lists all packages from the Slackware distribution. | ||
162 | function all_package_names() { | 180 | function all_package_names() { |
@@ -165,2 +183,4 @@ function all_package_names() { | |||
165 | 183 | ||
184 | # series_package_names S | ||
185 | # Lists the names of packages in Slackware series S. | ||
166 | function series_package_names() { | 186 | function series_package_names() { |
@@ -173,2 +193,4 @@ function catfile() { | |||
173 | 193 | ||
194 | # download_curl FILE URL | ||
195 | # Downloads file from URL to FILE using curl. | ||
174 | function download_curl { | 196 | function download_curl { |
@@ -177,2 +199,4 @@ function download_curl { | |||
177 | 199 | ||
200 | # download_wget LOCAL URL | ||
201 | # Downloads file from URL to FILE using wget. | ||
178 | function download_wget { | 202 | function download_wget { |
@@ -184,2 +208,4 @@ function download_wget { | |||
184 | 208 | ||
209 | # dnfunc_init | ||
210 | # Initializes the downloader function to wget or curl. | ||
185 | function dnfunc_init() { | 211 | function dnfunc_init() { |
@@ -196,7 +222,10 @@ function dnfunc_init() { | |||
196 | 222 | ||
223 | # download FILE | ||
224 | # Downloads package FILE from the remote server. On success, returns the | ||
225 | # full pathname of the downloaded copy. | ||
197 | function download() { | 226 | function download() { |
198 | local name=$(basename $1) | 227 | local name=$SLACKUPGRADE_PKGDIR/$(basename $1) |
199 | local url=$(catfile $1) | 228 | local url=$(catfile $1) |
200 | if $dnfunc $name $url; then | 229 | if $dnfunc $name $url; then |
201 | echo $name | 230 | echo $name |
202 | fi | 231 | fi |
@@ -204,22 +233,30 @@ function download() { | |||
204 | 233 | ||
234 | # getfile PKG [GPG] | ||
235 | # Retrieves the package archive file for the package PKG. If second argument | ||
236 | # is non-empty, verifies the GPG signature of the file. | ||
237 | # If checksums file is available, verifies also the MD5 checksum of the file. | ||
238 | # | ||
239 | # Returns full pathname of the retrieved file. | ||
205 | function getfile() { | 240 | function getfile() { |
206 | local name=$(if [ -n "$remote" ]; then | 241 | local name=$(if [ -n "$remote" ]; then |
207 | download $1 | 242 | download $1 |
208 | else | 243 | elif [ $strip_series -eq 1 ]; then |
209 | catfile $1 | 244 | catfile $(basename $1) |
210 | fi) | 245 | else |
211 | 246 | catfile $1 | |
247 | fi) | ||
248 | |||
212 | if [ -n "$2" ]; then | 249 | if [ -n "$2" ]; then |
213 | ascname=$(if [ -n "$remote" ]; then | 250 | ascname=$(if [ -n "$remote" ]; then |
214 | download $1.asc | 251 | download $1.asc |
215 | else | 252 | else |
216 | catfile $1.asc | 253 | catfile $1.asc |
217 | fi) | 254 | fi) |
218 | if [ -n "$ascname" ] \ | 255 | if [ -n "$ascname" ] \ |
219 | && ${GPG:-gpg} --verify $ascname $name 2>/dev/null; then | 256 | && ${GPG:-gpg} --verify $ascname $name 2>/dev/null; then |
220 | : | 257 | : |
221 | else | 258 | else |
222 | error "gpg verification failed for $name" | 259 | error "gpg verification failed for $name" |
223 | return | 260 | return |
224 | fi | 261 | fi |
225 | fi | 262 | fi |
@@ -233,8 +270,13 @@ function getfile() { | |||
233 | 270 | ||
271 | # dropfile FILE | ||
272 | # Removes FILE, if it has been downloaded from the remote repository, | ||
234 | function dropfile() { | 273 | function dropfile() { |
235 | if [ -n "$remote" ]; then | 274 | if [ -n "$remote" ] || [ $strip_series -eq 1 ]; then |
236 | rm $1 | 275 | rm $1 |
237 | fi | 276 | fi |
238 | } | 277 | } |
239 | 278 | ||
279 | # upgrade_package [OPTIONS] FILE | ||
280 | # Runs upgradepkg with the supplied arguments and captures its output to | ||
281 | # the log file. In verbose mode, filters parts of it to the stdout. | ||
240 | function upgrade_local() { | 282 | function upgrade_local() { |
@@ -251,2 +293,4 @@ function upgrade_local() { | |||
251 | 293 | ||
294 | # upgrade_package NAME [OPTIONS] | ||
295 | # Upgrades the package NAME. OPTIONS will be passed to upgradepkg verbatim. | ||
252 | function upgrade_package() { | 296 | function upgrade_package() { |
@@ -265,2 +309,4 @@ function upgrade_package() { | |||
265 | 309 | ||
310 | # version_gt A B | ||
311 | # Returns true if version A is greater than B. | ||
266 | function version_gt() { | 312 | function version_gt() { |
@@ -292,10 +338,10 @@ function backup() { | |||
292 | do | 338 | do |
293 | if [ -n "$max_backup" ] && [ $n -ge $max_backup ]; then | 339 | if [ -n "$max_backup" ] && [ $n -ge $max_backup ]; then |
294 | $p rm $dir/${stem}~$n | 340 | $p rm $dir/${stem}~$n |
295 | else | 341 | else |
296 | $p mv $dir/${stem}~$n $dir/${stem}~$((n + 1)) | 342 | $p mv $dir/${stem}~$n $dir/${stem}~$((n + 1)) |
297 | fi | 343 | fi |
298 | done | 344 | done |
299 | $p mv "$1~" "$1~1" | 345 | $p mv "$1~" "$1~1" |
300 | fi | 346 | fi |
301 | $p mv "$1" "$1~" | 347 | $p mv "$1" "$1~" |
@@ -304,2 +350,54 @@ function backup() { | |||
304 | 350 | ||
351 | # disk_avail_size DIR | ||
352 | # Returns the available disk size (in kilobytes) on the device where | ||
353 | # DIR is located | ||
354 | function disk_avail_size() { | ||
355 | df -k --output=target,avail | \ | ||
356 | sed 1d | \ | ||
357 | awk -vdir=$1 \ | ||
358 | 'BEGIN { dirlen=length(dir) } | ||
359 | { len = length($1) | ||
360 | if (len <= dirlen && substr(dir, 1, len) == $1) { | ||
361 | if (mp_len < len) { | ||
362 | mp_len = len | ||
363 | mp_avail = $2 | ||
364 | } | ||
365 | } | ||
366 | } | ||
367 | END { print mp_avail }' | ||
368 | } | ||
369 | |||
370 | # Downloads all selected packages to the spool directory. | ||
371 | function download_all() { | ||
372 | info "downloading packages" | ||
373 | if [ ${COLUMNS:-0} -lt 10 ]; then | ||
374 | progressbar=0 | ||
375 | fi | ||
376 | if [ $progressbar -eq 1 ]; then | ||
377 | total=$(wc -l candidates | cut -d ' ' -f 1) | ||
378 | width=$(( $COLUMNS - 7 )) | ||
379 | fi | ||
380 | i=0 | ||
381 | cat candidates | | ||
382 | while read pkg | ||
383 | do | ||
384 | if [ $progressbar -eq 1 ]; then | ||
385 | n=$(( $i * $width / $total )) | ||
386 | s=$(printf "%${n}s" ' '|sed 's/./=/g') | ||
387 | printf "\r% 3d%% %s>" $(( $i * 100 / $total)) $s | ||
388 | fi | ||
389 | if [ -z "$dry_run" ]; then | ||
390 | file=$(getfile $(package_file_name $pkg)) | ||
391 | if [ -z "$file" ]; then | ||
392 | abend "failed to download $pkg" | ||
393 | fi | ||
394 | fi | ||
395 | i=$(( $i + 1 )) | ||
396 | done || exit $? | ||
397 | if [ $p |