Last active
June 24, 2024 15:50
-
-
Save awerlang/b792a3f908206a90ad58ba559c5400bb to your computer and use it in GitHub Desktop.
A zypper wrapper that maximizes network throughput
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
zypper-download | |
=============== | |
Downloads packages using any amount of available openSUSE mirrors. | |
Installation | |
------------ | |
Copy both files to the following locations: | |
$HOME/.config/aria2/aria2.conf | |
$HOME/bin/zypper-download | |
Make sure the program is executable: | |
chmod +x $HOME/bin/zypper-download | |
This tool leverages aria2 to be awesome, so make sure it is installed (use zypper one last time): | |
zypper in aria2 | |
Usage | |
----- | |
It works best with repositories set to an official download redirector e.g. http://download.opensuse.org, since it relies on generated metalinks. So update your repositories URLs as needed. | |
Refer to instructions: | |
$ zypper-download -h | |
Known issues | |
------------ | |
* Only supports HTTP/HTTPS/FTP protocols for repositories | |
* Cannot be passed an individual .rpm URL directly (use aria2c instead) | |
* Minor: Some third-party repositories (e.g. Visual Studio Code) follow a different directory structure which results in those packages being skipped |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
check-integrity=true | |
console-log-level=error | |
file-allocation=falloc | |
max-concurrent-downloads=40 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
##################################################################################################### | |
## | |
### NAME | |
## zypper-download - Downloads packages using any amount of available openSUSE mirrors. | |
## | |
### SYNOPSIS | |
## Usage: zypper-download [options] command [command-args]... | |
## | |
## Options: | |
## | |
## -d <dir> Package cache directory. It can be an absolute path or relative to the | |
## current directory, or start with the environment variable ${HOME}. | |
## Default: $PKG_CACHE_DIR | |
## -z Run zypper once packages are ready in cache. | |
## -c Display default configuration. | |
## -h Display this message and exit. | |
## -v Display version information and exit. | |
## | |
## Commands: | |
## | |
## dup, dist-upgrade | |
## in, install package-name... | |
## inr, install-new-recommends | |
## | |
### CONFIGURATION | |
## PKG_CACHE_DIR = ${HOME}/.cache/zypp/packages | |
## RUN_ZYPPER = no | |
## | |
### LICENSE | |
## zypper-download v0.3.3 | |
## | |
## Copyright (C) 2020-2022 André Werlang | |
## | |
## License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>. | |
## This is free software: you are free to change and redistribute it. | |
## There is NO WARRANTY, to the extent permitted by law. | |
## | |
##################################################################################################### | |
set -o errexit -o nounset -o noclobber -o pipefail | |
shopt -s nullglob | |
export LC_ALL=C | |
main() { | |
parse_opts "$@" | |
set_default_config | |
run | |
} | |
error() { | |
echo "$0: $*" | |
} 1>&2 | |
parse_opts() { | |
local OPTIND OPTARG flag | |
while getopts hvczd: flag | |
do | |
case "$flag" in | |
(h) help; exit 0;; | |
(v) version; exit 0;; | |
(c) configuration | about; exit 0;; | |
(d) readonly PKG_CACHE_DIR="$OPTARG";; | |
(z) readonly RUN_ZYPPER="yes";; | |
(*) usage; exit 1;; | |
esac | |
done | |
shift $((OPTIND-1)) | |
if [ $# -eq 0 ]; then | |
error "expected required argument -- command" | |
usage; | |
exit 1; | |
fi | |
readonly SUB_COMMAND=("$@") | |
} | |
read_default_config() { | |
configuration | awk '/[[:alnum:]_ *= *.*]/{ print "[[ -v " $1 " ]] || readonly " $1 $2 "\x27" $3 "\x27" }' | |
} | |
set_default_config() { | |
local vars | |
vars=$(read_default_config) | |
eval "$vars" | |
} | |
subst_vars() { | |
export PKG_CACHE_DIR | |
envsubst '$HOME $PKG_CACHE_DIR' | |
} | |
about() { | |
set_default_config | |
subst_vars | |
} | |
usage() { | |
sed '/^### SYNOPSIS$/,/^###/!d;//d;s/^## \{0,6\}//' "$0" | about | |
} | |
version() { | |
sed '/^### LICENSE$/,/^###/!d;//d;s/^## \{0,6\}//' "$0" | about | |
} | |
help() { | |
sed '/^##$/,/^####/!d;//d;s/^##.\{0,2\}//' "$0" | about | |
} | |
configuration() { | |
sed '/^### CONFIGURATION$/,/^###/!d;//d;s/^## \{0,6\}//' "$0" | |
} | |
package_dir() { | |
echo "$PKG_CACHE_DIR" | subst_vars | |
} | |
run() { | |
call_zypper "${SUB_COMMAND[@]}" \ | |
| create_download_spec \ | |
| tee ./zypper-download.log \ | |
| download_all | |
check_rpm || { error "Package signature failed"; exit 1; } | |
if [[ "$RUN_ZYPPER" == yes ]]; then | |
local dir | |
dir=$(package_dir) | |
sudo zypper --pkg-cache-dir "$dir" "${SUB_COMMAND[@]}" | |
fi | |
} | |
call_zypper() { | |
local command="$1" | |
local command_args=("${@:2}") | |
sudo zypper --quiet \ | |
--terse \ | |
--non-interactive \ | |
"$command" --details \ | |
--dry-run \ | |
"${command_args[@]}" | |
} | |
create_download_spec() { | |
local repo_arrays | |
repo_arrays=$(zypper repos --uri | awk -F "|" ' | |
function trim(s) { | |
gsub(/^ +| +$/, "", s); | |
return s; | |
} | |
BEGIN { | |
print "BEGIN {"; | |
} | |
/:\/\// { | |
alias=trim($2); | |
name=trim($3); | |
uri=trim($NF); | |
print " uri[\"" name "\"]=\"" uri "\";"; | |
print " alias[\"" name "\"]=\"" alias "\";"; | |
} | |
END { | |
print "}"; | |
} | |
' | |
) | |
awk -v PKG_CACHE_DIR="$PKG_CACHE_DIR" "$repo_arrays"' | |
function trim(s) { | |
gsub(/^ +| +$/, "", s); | |
return s; | |
} | |
NF==0 { | |
pkg=0; | |
next; | |
} | |
/ packages? (is|are) going to (be installed|be reinstalled|be upgraded|be downgraded|change architecture):$/ { | |
pkg=1; | |
next; | |
} | |
pkg==1 { | |
name=$1; getline; | |
version=$NF; getline; | |
arch=$1; getline; | |
repo=trim($0); getline; | |
host=uri[repo]; | |
print host "/" arch "/" name "-" version "." arch ".rpm"; | |
print " dir=" PKG_CACHE_DIR "/" alias[repo] "/" arch; | |
} | |
' - | |
} | |
download_all() { | |
aria2c --input-file=- \ | |
--max-connection-per-server=6 \ | |
--split=16 \ | |
--min-split-size=1M \ | |
--check-integrity=true \ | |
--allow-overwrite=true \ | |
--auto-file-renaming=false \ | |
--continue=true | |
} | |
check_rpm() { | |
local dir output | |
dir=$(package_dir) | |
output=$(find "$dir" -type f -name "*.rpm" -execdir rpm --checksig "{}" +) | |
local result=$? | |
if (( result != 0 )); then | |
grep " NOT OK$" <<< "$output" | |
fi | |
return $result | |
} 1>&2 | |
main "$@" |
Has there been any updates to this? I pretty much require packman and vscode so this is of limited utility without understanding how to workaround those limitations. I don't understand how to "add a separate repo file for each part of packman"
@TonyApuzzo see https://en.opensuse.org/Additional_package_repositories#Packman how to use separate packman repos. I updated the known issues to mention that it's not a big deal, it just skips packages (e.g. vs code)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@awerlang I ended up adding a separate repo file for each section of Packman that I use. This allowed the script to find the packages.
I originally installed those packages using opi which only added the main repo. Zypper was able to update the applications for some reason, just not this script.