mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-02 02:53:56 +08:00
🌴 Sync 2026-03-05 23:51:42
This commit is contained in:
1 parent
0d155c70be
commit
32600acc60
14258 files changed
+3954570
No files matched your search
@@ -0,0 +1,9 @@
|
||||
|
||||
config packagesync 'config'
|
||||
option download_url 'https://downloads.openwrt.org'
|
||||
option rsync_url 'rsync://rsync.openwrt.org/downloads'
|
||||
option home_url 'packagesync'
|
||||
option auto_exec '0'
|
||||
option cron_expression '0 0 * * *'
|
||||
option proxy_enabled '0'
|
||||
|
||||
+316
@@ -0,0 +1,316 @@
|
||||
#!/bin/bash /etc/rc.common
|
||||
# Copyright (C) 2023-2024 muink
|
||||
|
||||
. "${IPKG_INSTROOT}/lib/functions.sh"
|
||||
. "${IPKG_INSTROOT}/usr/share/libubox/jshn.sh"
|
||||
|
||||
START=99
|
||||
USE_PROCD=1
|
||||
|
||||
EXTRA_COMMANDS="getinfo checkln symln setcron cleanup"
|
||||
EXTRA_HELP=\
|
||||
" getinfo Get releases/targets/archs list
|
||||
checkln Check home path
|
||||
symln [home_url] Make symlink to mount porint
|
||||
setcron [cron] Add cron expression to crontabs
|
||||
cleanup [autorm] Clean up invalid versions"
|
||||
|
||||
CONFIG_NAME='packagesync'
|
||||
SCONFIG='config'
|
||||
RELEASE='release'
|
||||
|
||||
MNTPKGS='/mnt/packagesync'
|
||||
CRONTABS='/etc/crontabs/root'
|
||||
SYNCEXE='/usr/libexec/packagesync/sync'
|
||||
PIDFILE='/var/run/packagesync.pid'
|
||||
DEF_HOMEURL="packagesync"
|
||||
DEF_HOMEPATH="/www/$DEF_HOMEURL"
|
||||
RELEASES_LIST="/var/packagesync/releaseslist"
|
||||
TARGETS_LIST="/var/packagesync/targetslist"
|
||||
PKGARCHS_LIST="/var/packagesync/pkgarchslist"
|
||||
RESULTPATH='/var/packagesync/results'
|
||||
# url path
|
||||
DOWNLOAD_URL="https://downloads.openwrt.org"
|
||||
URLHREF_RELEASES='releases'
|
||||
URLHREF_SNAPSHOTS='snapshots'
|
||||
URLHREF_PACKAGES_PREFIX='packages-' # packages-22.03
|
||||
URLHREF_VERS_PACKAGES='packages'
|
||||
URLHREF_VERS_TARGETS='targets'
|
||||
|
||||
config_load $CONFIG_NAME
|
||||
|
||||
|
||||
|
||||
# define global var: GLOBAL_*
|
||||
define_global() {
|
||||
[ "$2" == "0" ] || { >&2 echo "$(basename $0): section $1 validation failed"; return 1; }
|
||||
|
||||
local error=0
|
||||
local v ucivv="download_url rsync_url home_url bwlimit proxy_enabled proxy_protocol proxy_server"
|
||||
for v in $ucivv; do
|
||||
[ -z "$(config_get $1 $v)" ] && grep -qEv "^(download_url|rsync_url|proxy_protocol|proxy_server)$" <<< "$v" && {
|
||||
>&2 echo "$(basename $0): section $1 option $v cannot be empty"
|
||||
let error++
|
||||
}
|
||||
config_get GLOBAL_$v $1 $v
|
||||
done
|
||||
|
||||
[ "$error" -gt 0 ] && return 1 || return 0
|
||||
}
|
||||
|
||||
validate_section_config() {
|
||||
uci_load_validate "$CONFIG_NAME" "$SCONFIG" "$1" "$2" \
|
||||
'download_url:string' \
|
||||
'rsync_url:string' \
|
||||
'home_url:string' \
|
||||
'bwlimit:uinteger:8000' \
|
||||
'auto_exec:bool:1' \
|
||||
'cron_expression:string' \
|
||||
'proxy_enabled:bool:0' \
|
||||
'proxy_protocol:string:socks5' \
|
||||
'proxy_server:string'
|
||||
}
|
||||
|
||||
validate_section_release() {
|
||||
uci_load_validate $CONFIG_NAME $RELEASE "$1" "$2" \
|
||||
'enabled:bool:0' \
|
||||
'name:uciname' \
|
||||
'version:string' \
|
||||
'target:string' \
|
||||
'pkgarch:string' \
|
||||
'model:string' \
|
||||
'extra:bool:0'
|
||||
}
|
||||
|
||||
gen_order() {
|
||||
[ "$2" == "0" ] || { >&2 echo "section $1 validation failed"; return 1; }
|
||||
[ "$enabled" == "0" ] && return 0
|
||||
|
||||
json_init
|
||||
json_load "$orders"
|
||||
json_select orders
|
||||
json_add_object
|
||||
json_add_string name "$name"
|
||||
json_add_string version "$version"
|
||||
json_add_string target "$target"
|
||||
json_add_string arch "$pkgarch"
|
||||
json_add_string model "$model"
|
||||
json_add_boolean extra "$extra"
|
||||
json_close_object
|
||||
orders="$(json_dump)"
|
||||
}
|
||||
|
||||
sync_instance() {
|
||||
[ -z "$1" ] && return 1
|
||||
|
||||
procd_open_instance 'sync'
|
||||
procd_set_param command "$SYNCEXE" -o "$1"
|
||||
procd_append_param command -l "$bwlimit" -d "$homepath" ${ALL_PROXY:+-x $ALL_PROXY} \
|
||||
${GLOBAL_rsync_url:+--rsyncurl "$GLOBAL_rsync_url"}
|
||||
#procd_set_param respawn
|
||||
#procd_set_param stdout 1
|
||||
procd_set_param stderr 1
|
||||
procd_set_param user root
|
||||
procd_set_param pidfile "$PIDFILE"
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
start_service() {
|
||||
# locked file check
|
||||
[ -n "$(cat "$PIDFILE" 2>/dev/null)" -a -n "$(ps|grep -E "^\s*$(cat "$PIDFILE" 2>/dev/null)")" ] && return 1
|
||||
# mount point check
|
||||
[ -n "$(df -hT|grep "$MNTPKGS")" ] || return 1
|
||||
|
||||
validate_section_config "$SCONFIG" define_global || return $?
|
||||
local homepath bwlimit
|
||||
[ -n "$GLOBAL_home_url" ] && homepath="/www/$GLOBAL_home_url" || homepath="$DEF_HOMEPATH"
|
||||
[ -d "$homepath" ] || { >&2 echo -e "$CONFIG_NAME: The Home Path '$homepath' is invalid. please check the 'home_url'"; return 1; }
|
||||
bwlimit="$GLOBAL_bwlimit"
|
||||
[ "$GLOBAL_proxy_enabled" = "1" ] && {
|
||||
export ALL_PROXY=$GLOBAL_proxy_protocol://$GLOBAL_proxy_server
|
||||
}
|
||||
|
||||
local orders='{ "orders": [] }'
|
||||
config_foreach validate_section_release $RELEASE gen_order
|
||||
|
||||
sync_instance "$(jsonfilter -q -s "$orders" -e @.orders)"
|
||||
#$SYNCEXE -l|--bwlimit "$bwlimit" -d|--homedir "$homepath" -n|--name "x64_21_02_5" -s|--version "21.02.5" -t|--target "x86/64" -k|--arch "x86_64";
|
||||
#$SYNCEXE -l|--bwlimit "$bwlimit" -d|--homedir "$homepath" -n|--name "x64_22_03_2" -s|--version "22.03.2" -t|--target "x86/64" -k|--arch "x86_64";
|
||||
#$SYNCEXE -l|--bwlimit "$bwlimit" -d|--homedir "$homepath" -n|--name "ath79_21_02_5" -s|--version "21.02.5" -t|--target "ath79/nand" -k|--arch "mips_24kc";
|
||||
#$SYNCEXE -l|--bwlimit "$bwlimit" -d|--homedir "$homepath" -n|--name "ath79_22_03_2" -s|--version "22.03.2" -t|--target "ath79/nand" -k|--arch "mips_24kc";
|
||||
#
|
||||
#$SYNCEXE -l|--bwlimit "$bwlimit" -o|--orders '[ {"homedir": "$homepath", "name": "x64_21_02_5", "version": "21.02.5", "target": "x86/64", "arch": "x86_64"}, \
|
||||
# {"homedir": "$homepath", "name": "x64_22_03_2", "version": "22.03.2", "target": "x86/64", "arch": "x86_64"}, \
|
||||
# {"homedir": "$homepath", "name": "ath79_21_02_5", "version": "21.02.5", "target": "ath79/nand", "arch": "mips_24kc"}, \
|
||||
# {"homedir": "$homepath", "name": "ath79_22_03_2", "version": "22.03.2", "target": "ath79/nand", "arch": "mips_24kc"} ]'
|
||||
#
|
||||
#$SYNCEXE -l|--bwlimit "$bwlimit" -d|--homedir "$homepath" -o|--orders '[ {"name": "x64_21_02_5", "version": "21.02.5", "target": "x86/64", "arch": "x86_64"}, \
|
||||
# {"name": "x64_22_03_2", "version": "22.03.2", "target": "x86/64", "arch": "x86_64"}, \
|
||||
# {"name": "ath79_21_02_5", "version": "21.02.5", "target": "ath79/nand", "arch": "mips_24kc"}, \
|
||||
# {"name": "ath79_22_03_2", "version": "22.03.2", "target": "ath79/nand", "arch": "mips_24kc"} ]'
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
getinfo() {
|
||||
validate_section_config "$SCONFIG" define_global
|
||||
local rawhtml stables releases targets pkgarchs download_url="${GLOBAL_download_url:-$DOWNLOAD_URL}"
|
||||
|
||||
# Versions
|
||||
rawhtml="$(curl --connect-timeout 10 --retry 3 -sSL "$download_url/")"
|
||||
stables="$( \
|
||||
echo "$rawhtml" | sed -n '/Stable Release/,/Development Snapshots/p' \
|
||||
| sed -n '/<ul>/,/<\/ul>/p' | grep 'OpenWrt' \
|
||||
| sed -E "s|.+\breleases/([^/]+)/.+|\1|g" \
|
||||
)"
|
||||
releases="$( \
|
||||
echo "$rawhtml" | sed -n '/Release Archive/,/\$/p' \
|
||||
| sed -n '/<ul>/,/<\/ul>/p' | grep 'OpenWrt' \
|
||||
| sed -E "s|.+\breleases/([^/]+)/.+|\1|g" \
|
||||
)"
|
||||
mkdir -p "${RELEASES_LIST%/*}" 2>/dev/null
|
||||
echo -e "Releases:"
|
||||
echo -e "$stables\n$releases"
|
||||
echo -e "$stables\n$releases" > "$RELEASES_LIST"
|
||||
|
||||
# Targets
|
||||
for stable in $stables; do
|
||||
rawhtml="$(curl --connect-timeout 10 --retry 3 -sSL "$download_url/$URLHREF_RELEASES/$stable/$URLHREF_VERS_TARGETS/")"
|
||||
targets="$( \
|
||||
echo "$rawhtml" \
|
||||
| grep -E '<a href=.+\d+:\d+' \
|
||||
| sed -E "s|.+\bhref=\"([^/]+)/.+|\1|g" \
|
||||
)"
|
||||
## subTargets
|
||||
fulltargets="$( \
|
||||
for target in $targets; do
|
||||
subtargets="$(curl -sL "$download_url/$URLHREF_RELEASES/$stable/$URLHREF_VERS_TARGETS/$target/" \
|
||||
| grep -E '<a href=.+\d+:\d+' \
|
||||
| sed -E "s|.+\bhref=\"([^/]+)/.+|\1|g" \
|
||||
)"
|
||||
for subtarget in $subtargets; do sed "s|^|$target/|" <<< "$subtarget"; done
|
||||
done \
|
||||
)"
|
||||
fulltargetss="$(echo -e "$fulltargetss\n$fulltargets" | sort -u | grep -v '^$')"
|
||||
done
|
||||
mkdir -p "${TARGETS_LIST%/*}" 2>/dev/null
|
||||
echo "Targets:"
|
||||
echo "$fulltargetss"
|
||||
echo "$fulltargetss" > "$TARGETS_LIST"
|
||||
|
||||
# Archs
|
||||
for stable in $stables; do
|
||||
rawhtml="$(curl --connect-timeout 10 --retry 3 -sSL "$download_url/$URLHREF_RELEASES/$stable/$URLHREF_VERS_PACKAGES/")"
|
||||
pkgarchs="$( \
|
||||
echo "$rawhtml" \
|
||||
| grep -E '<a href=.+\d+:\d+' \
|
||||
| sed -E "s|.+\bhref=\"([^/]+)/.+|\1|g" \
|
||||
)"
|
||||
pkgarchss="$(echo -e "$pkgarchss\n$pkgarchs" | sort -u | grep -v '^$')"
|
||||
done
|
||||
mkdir -p "${PKGARCHS_LIST%/*}" 2>/dev/null
|
||||
echo "PKGArchs:"
|
||||
echo "$pkgarchss"
|
||||
echo "$pkgarchss" > "$PKGARCHS_LIST"
|
||||
}
|
||||
|
||||
gethome() {
|
||||
home_url="${1:-$(uci -q get $CONFIG_NAME.$SCONFIG.home_url)}"
|
||||
home_url="${home_url:-$DEF_HOMEURL}"
|
||||
home_path="/www/$home_url"
|
||||
}
|
||||
|
||||
checkln() {
|
||||
gethome
|
||||
|
||||
# clean up old symlink
|
||||
ls -l /www | grep "\-> $MNTPKGS" | grep -v " $home_url -> $MNTPKGS" | sed -En "s,.+ ('.+'|\S+) -> ${MNTPKGS}$,'/www/\1',p" | xargs rm -f
|
||||
# show occupied
|
||||
find /www/* ! -type l -maxdepth 0 | sed "s|.*/||g"
|
||||
}
|
||||
|
||||
symln() {
|
||||
gethome "$1"
|
||||
|
||||
# make mount dir
|
||||
[ -e "$home_path" ] || { ln -s "$MNTPKGS" "$home_path" 2>/dev/null; ln -s "$RESULTPATH" "$home_path/results" 2>/dev/null; return 0; }
|
||||
[ -L "$home_path" ] || { >&2 echo "The Name $home_url is already used, please use another name"; return 1; }
|
||||
[ -n "$(ls -l "$home_path" | grep " $home_path -> $MNTPKGS")" ] || { >&2 echo "The Name $home_url is already used, please use another name"; return 1; }
|
||||
return 0
|
||||
}
|
||||
|
||||
setcron() {
|
||||
local cron="$1" exist=$(cat "$CRONTABS" | sed -n "/\/etc\/init.d\/packagesync start/=")
|
||||
|
||||
if [ -n "$cron" ]; then
|
||||
[ -n "$exist" ] && sed -i "/\/etc\/init.d\/packagesync start/d" "$CRONTABS"
|
||||
sed -i "\$a$cron /etc/init.d/packagesync start" "$CRONTABS"
|
||||
else
|
||||
[ -n "$exist" ] && sed -i "/\/etc\/init.d\/packagesync start/d" "$CRONTABS"
|
||||
fi
|
||||
}
|
||||
|
||||
cleanup_regex() {
|
||||
[ "$2" == "0" ] || { >&2 echo "section $1 validation failed"; return 1; }
|
||||
targets="${targets:+$targets|}/$version/$URLHREF_VERS_TARGETS/$target\b"
|
||||
packages="${packages:+$packages|}/$version/$URLHREF_VERS_PACKAGES\b"
|
||||
pkgarchs="${pkgarchs:+$pkgarchs|}/$URLHREF_PACKAGES_PREFIX${version%\.*}/$pkgarch\b"
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
local autorm="$1"
|
||||
gethome
|
||||
|
||||
local count targets packages pkgarchs
|
||||
[ -d "$home_path/$URLHREF_RELEASES" ] || return 1
|
||||
|
||||
config_foreach validate_section_release $RELEASE cleanup_regex || return $?
|
||||
|
||||
#count=$(uci -q show $CONFIG_NAME|grep "=$RELEASE"|sed -E "s|.+@$RELEASE\[(\d+)\].+|\1|"|tail -n1)
|
||||
#
|
||||
#local ucivv="version target pkgarch"
|
||||
#for i in $(seq 0 $count); do
|
||||
# for _var in $ucivv; do
|
||||
# eval "local $_var=\$(uci -q get $CONFIG_NAME.@$RELEASE[$i].$_var)"
|
||||
# done
|
||||
# targets="${targets:+$targets|}/$version/$URLHREF_VERS_TARGETS/$target\b"
|
||||
# packages="${packages:+$packages|}/$version/$URLHREF_VERS_PACKAGES\b"
|
||||
# pkgarchs="${pkgarchs:+$pkgarchs|}/$URLHREF_PACKAGES_PREFIX${version%\.*}/$pkgarch\b"
|
||||
#done
|
||||
#echo "$targets"
|
||||
#echo "$packages"
|
||||
#echo "$pkgarchs"
|
||||
|
||||
local rm_path="$( \
|
||||
find $home_path/$URLHREF_RELEASES/* -type d -o -type l -maxdepth 3 | grep -Ev "$targets" | grep -Ev "$packages" | grep -Ev "$pkgarchs" \
|
||||
| grep -E "(/\d+\.\d+[^/]*/($URLHREF_VERS_PACKAGES|$URLHREF_VERS_TARGETS/[^/]+/[^/]+)\$|/${URLHREF_PACKAGES_PREFIX}\d+\.\d+/[^/]+\$)" \
|
||||
)"
|
||||
sed "s|^/|rm -rf '/|g;s|$|'|g" <<< "$rm_path"
|
||||
[ -z "$autorm" ] && return 0 || echo "$rm_path" | xargs rm -rf
|
||||
|
||||
}
|
||||
|
||||
restart() {
|
||||
start
|
||||
}
|
||||
|
||||
boot() {
|
||||
mkdir -p "$RESULTPATH" 2>/dev/null
|
||||
gethome
|
||||
if [ -e "$home_path" ]; then
|
||||
if [ -L "$home_path" -a "$(readlink "$home_path")" = "$MNTPKGS" ]; then
|
||||
sleep 0
|
||||
else
|
||||
uci set $CONFIG_NAME.$SCONFIG.home_url="$DEF_HOMEURL"
|
||||
uci commit $CONFIG_NAME
|
||||
ln -s "$MNTPKGS" "$DEF_HOMEPATH"
|
||||
fi
|
||||
else
|
||||
ln -s "$MNTPKGS" "$home_path"
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger "$CONFIG_NAME"
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ -n "$(uci -q get packagesync.config)" ] || sed -i "s|^config packagesync|config packagesync 'config'|" /etc/config/packagesync
|
||||
|
||||
download_url="$(uci -q get packagesync.config.download_url)"
|
||||
rsync_url="$(uci -q get packagesync.config.rsync_url)"
|
||||
[ -n "$download_url" ] || uci set packagesync.config.download_url='https://downloads.openwrt.org'
|
||||
[ -n "$rsync_url" ] || uci set packagesync.config.rsync_url='rsync://rsync.openwrt.org/downloads'
|
||||
|
||||
# merging option target & option subtarget
|
||||
for sid in $(uci -q show packagesync | sed -n 's|^.*\.\(@release[[0-9]*]\).subtarget=.*|\1|p'); do
|
||||
uci set packagesync.$sid.target="$(uci -q get packagesync.$sid.target)/$(uci -q get packagesync.$sid.subtarget)"
|
||||
uci delete packagesync.$sid.subtarget
|
||||
done
|
||||
|
||||
[ -z "$(uci changes packagesync)" ] || uci commit packagesync
|
||||
+403
@@ -0,0 +1,403 @@
|
||||
#!/bin/bash
|
||||
# depends: curl getopt jsonfilter rsync ncat-full
|
||||
#
|
||||
# Author: muink
|
||||
# Github: https://github.com/muink/luci-app-packagesync
|
||||
#
|
||||
|
||||
# Info
|
||||
PKGNAME='packagesync'
|
||||
RELEASE='release'
|
||||
VERSION="20240804"
|
||||
#
|
||||
HOMEPATH=''
|
||||
JSON=''
|
||||
RESULTPATH='/var/packagesync/results'
|
||||
PIDFILE='/var/run/packagesync.pid'
|
||||
# url path
|
||||
RSYNC_URL="rsync://rsync.openwrt.org/downloads"
|
||||
URLHREF_RELEASES='releases'
|
||||
#URLHREF_SNAPSHOTS='snapshots'
|
||||
#URLHREF_PACKAGES_PREFIX='packages-' # packages-22.03
|
||||
URLHREF_VERS_PACKAGES='packages'
|
||||
URLHREF_VERS_TARGETS='targets'
|
||||
# rsync default options
|
||||
ARCHIVE='-rlpt' # or '-a' (root)
|
||||
INFO='hi'
|
||||
COMPAC='--compress'
|
||||
PRUNE='--delete'
|
||||
#PROGR='--progress'
|
||||
BWLIMIT='8000'
|
||||
|
||||
|
||||
# Get parameters
|
||||
GETOPT=$(getopt -n $(basename $0) -o d:n:s:t:k:m:e:o:l:x:V -l homedir:,name:,version:,target:,arch:,model:,extra:,orders:,bwlimit:,proxy:,rsyncurl:,Version,help -- "$@")
|
||||
[ $? -ne 0 ] && >&2 echo -e "\tUse the --help option get help" && exit 1
|
||||
eval set -- "$GETOPT"
|
||||
OPTIONS=$(sed -E "s|'[^']*'||g; s| --( .*)?$||" <<< "$GETOPT")
|
||||
|
||||
# Duplicate options
|
||||
for ru in --help\|--help -V\|--Version -x\|--proxy -l\|--bwlimit -d\|--homedir -n\|--name -s\|--version -t\|--target -k\|--arch -o\|--orders; do
|
||||
eval "grep -qE \" ${ru%|*}[ .+]* ($ru)| ${ru#*|}[ .+]* ($ru)\" <<< \"\$OPTIONS\" && >&2 echo \"\$(basename \$0): Option '\$ru' option is repeated\" && exit 1"
|
||||
done
|
||||
# Independent options
|
||||
for ru in --help\|--help -V\|--Version; do
|
||||
eval "grep -qE \"^ ($ru) .+|.+ ($ru) .+|.+ ($ru) *\$\" <<< \"\$OPTIONS\" && >&2 echo \"\$(basename \$0): Option '\$(sed -E \"s,^.*($ru).*\$,\\1,\" <<< \"\$OPTIONS\")' cannot be used with other options\" && exit 1"
|
||||
done
|
||||
# Conflicting options
|
||||
echo "$OPTIONS" | grep -E " (-o|--orders)\b" | grep -E " (-n|--name)\b" >/dev/null && >&2 echo "$(basename $0): Option '-o|--orders' cannot be used with option '-n|--name'" && exit 1
|
||||
echo "$OPTIONS" | grep -E " (-o|--orders)\b" | grep -E " (-s|--version)\b" >/dev/null && >&2 echo "$(basename $0): Option '-o|--orders' cannot be used with option '-s|--version'" && exit 1
|
||||
echo "$OPTIONS" | grep -E " (-o|--orders)\b" | grep -E " (-t|--target)\b" >/dev/null && >&2 echo "$(basename $0): Option '-o|--orders' cannot be used with option '-t|--target'" && exit 1
|
||||
echo "$OPTIONS" | grep -E " (-o|--orders)\b" | grep -E " (-k|--arch)\b" >/dev/null && >&2 echo "$(basename $0): Option '-o|--orders' cannot be used with option '-k|--arch'" && exit 1
|
||||
echo "$OPTIONS" | grep -E " (-o|--orders)\b" | grep -E " (-m|--model)\b" >/dev/null && >&2 echo "$(basename $0): Option '-o|--orders' cannot be used with option '-m|--model'" && exit 1
|
||||
echo "$OPTIONS" | grep -E " (-o|--orders)\b" | grep -E " (-e|--extra)\b" >/dev/null && >&2 echo "$(basename $0): Option '-o|--orders' cannot be used with option '-e|--extra'" && exit 1
|
||||
# Required options
|
||||
[ -n "$(echo "$OPTIONS" | grep -E " (-d|--homedir)\b" | grep -E " (-s|--version)\b" | grep -E " (-t|--target)\b" | grep -E " (-k|--arch)\b")" \
|
||||
-o -n "$(echo "$OPTIONS" | grep -E " (-o|--orders)\b")" \
|
||||
-o -n "$(echo "$OPTIONS" | grep -E " (--help|-V|--Version)\b")" ] \
|
||||
|| { >&2 echo -e "$(basename $0): Missing required options\n\tUse the --help option get help"; exit 1; }
|
||||
|
||||
|
||||
|
||||
# Sub function
|
||||
_help() {
|
||||
printf "\n\
|
||||
Usage: sync [OPTION]... \n\
|
||||
\n\
|
||||
e.g. sync -d /www/sync -n x64_21_02_5 -s 21.02.5 -t 'x86/64' -k x86_64\n\
|
||||
e.g. sync -l 500K -d /www/sync -o \"[ {'homedir': '/www/sync', 'version': '21.02.5', 'target': 'x86/64', 'arch': 'x86_64'}, \ \n\
|
||||
{'homedir': '/www/sync', 'version': '22.03.2', 'target': 'x86/64', 'arch': 'x86_64'}, \ \n\
|
||||
{'homedir': '/www/sync', 'version': '21.02.5', 'target': 'ath79/nand', 'arch': 'mips_24kc'}, \ \n\
|
||||
{'homedir': '/www/sync', 'version': '22.03.2', 'target': 'ath79/nand', 'arch': 'mips_24kc'} ]\" \n\
|
||||
\n\
|
||||
Options:\n\
|
||||
-d, --homedir <homedir> -- Sync folder. Is not essential, if it has been specified in orders\n\
|
||||
-n, --name <nick name> -- Identifying name. Only used when UCI/procd calls\n\
|
||||
-s, --version <version> -- Required option. OpenWRT version\n\
|
||||
-t, --target <target/subtarget> -- Required option. Device target and subtarget\n\
|
||||
-k, --arch <pkgarch> -- Required option. Device architecture\n\
|
||||
-m, --model <model> -- Optional option. Product model keyword\n\
|
||||
-e, --extra <true|false> -- Optional option. Sync target supplementary. Default is false\n\
|
||||
-o, --orders <orders> -- Required option. Sync multi-versions at once\n\
|
||||
-l, --bwlimit <n>[(K|M|G)] -- Bandwidth limit\n\
|
||||
-x, --proxy <protocol://ip:port> -- Connect using proxy\n\
|
||||
--rsyncurl <url> -- Optional option. Rsync url\n\
|
||||
-V, --Version -- Returns version\n\
|
||||
--help -- Returns help info\n\
|
||||
\n\
|
||||
OrdersFormat:\n\
|
||||
[ {'homedir': '??', 'name': '??', 'version': '??', 'target': '??', 'arch': '??'}, \ \n\
|
||||
{'homedir': '??', 'name': '??', 'version': '??', 'target': '??', 'arch': '??'} ] \n\
|
||||
'homedir' and 'name' is optional.\n\
|
||||
\n"
|
||||
}
|
||||
|
||||
_version() {
|
||||
echo "$(basename $0) version: v$VERSION"
|
||||
}
|
||||
|
||||
#verify_path <absolute path>
|
||||
verify_path() {
|
||||
[ -n "$1" ] || return 1
|
||||
[ -d "$1" -a -n "$(grep '^/' <<< "$1")" ] || return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
#verify_order <openwrt version> <target/subtarget> <package arch>
|
||||
verify_order() {
|
||||
local version="$1" target="$2" arch="$3"
|
||||
|
||||
local ERRORCODE ERROR=0
|
||||
rsync --quiet --list-only "$RSYNC_URL/$URLHREF_RELEASES/${version:-null}/$URLHREF_VERS_TARGETS/${target:-null}" 2>/dev/null || { ERRORCODE=$?;
|
||||
>&2 echo -e "$(basename $0): Get '$RSYNC_URL/$URLHREF_RELEASES/${version:-<null>}/$URLHREF_VERS_TARGETS/${target:-<null>}' failed. Code '$ERRORCODE'"; ((ERROR++)); }
|
||||
rsync --quiet --list-only "$RSYNC_URL/$URLHREF_RELEASES/${version:-null}/$URLHREF_VERS_PACKAGES/${arch:-null}" 2>/dev/null || { ERRORCODE=$?;
|
||||
>&2 echo -e "$(basename $0): Get '$RSYNC_URL/$URLHREF_RELEASES/${version:-<null>}/$URLHREF_VERS_PACKAGES/${arch:-<null>}' failed. Code '$ERRORCODE'"; ((ERROR++)); }
|
||||
|
||||
[ "$ERROR" -gt 0 ] && return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
#parse_json <JSON>
|
||||
parse_json() {
|
||||
local array="$1"
|
||||
[ -z "$(jsonfilter -q -s "$array" -e '$')" ] && >&2 echo -e "$(basename $0): The format of <orders> is incorrect" && return 1
|
||||
|
||||
local count=$(jsonfilter -q -s "$array" -e '$[*]'|sed -n '$=')
|
||||
[ -z "$count" ] && >&2 echo -e "$(basename $0): The <orders> has no content" && return 1
|
||||
|
||||
for i in $(seq 0 $[ $count -1 ]); do
|
||||
local order="$(eval "jsonfilter -q -s \"\$array\" -e '\$[$i]'")"
|
||||
local ucivv="homedir version target arch model extra name"
|
||||
for _var in $ucivv; do
|
||||
eval "local $_var=\"\$(jsonfilter -q -s \"\$order\" -e '\$.$_var')\""
|
||||
done
|
||||
|
||||
mkdir -p "$RESULTPATH" 2>/dev/null
|
||||
if [ -n "$name" ]; then
|
||||
cat /dev/null > "$RESULTPATH/${name}.log"
|
||||
{ mirror "$homedir" "$version" "$target" "$arch" "$model" "$extra" 2>&1 1>&3 | tee "$RESULTPATH/${name}.log"; } 3>&1 1>&2 # in bash
|
||||
#mirror "$homedir" "$version" "$target" "$arch" 2> >(tee "$RESULTPATH/${name}.log" >&2) # in POSIX shell
|
||||
else
|
||||
mirror "$homedir" "$version" "$target" "$arch" "$model" "$extra"
|
||||
fi
|
||||
local ERROR="$?"
|
||||
|
||||
if [ -n "$name" ]; then
|
||||
local num=$(uci -q show $PKGNAME|sed -En "s|.+@$RELEASE\[(\d+)\]\.name='$name'|\1|p")
|
||||
if [ -n "$num" ]; then
|
||||
if [ "$ERROR" -eq 0 ]; then
|
||||
uci set $PKGNAME.@$RELEASE[$num].return="Success $(date +"%FT%TZ%z")"
|
||||
else
|
||||
uci set $PKGNAME.@$RELEASE[$num].return="Error $(date +"%FT%TZ%z")"
|
||||
#uci set $PKGNAME.@$RELEASE[$num].return="$(cat "$RESULTPATH/$name"|awk BEGIN{RS=EOF}'{gsub(/\n/,"\\\\n");print}'|sed 's|\\\\n|\\n|g')"
|
||||
## |sed ':a;N;s/\n/\\\\n/;ta;'|sed 's|\\\\n|\\n|g'
|
||||
fi
|
||||
uci commit $PKGNAME
|
||||
fi
|
||||
fi
|
||||
done
|
||||
return $ERROR
|
||||
}
|
||||
|
||||
#mirror <local mirror root path> <openwrt version> <target/subtarget> <package arch> <model> <extra>
|
||||
mirror() {
|
||||
local homedir version target arch model extra ERROR=0
|
||||
homedir="${1:-$HOMEPATH}" && shift
|
||||
version="$1" && shift
|
||||
target="$1" && shift
|
||||
arch="$1" && shift
|
||||
model="$1" && shift
|
||||
extra="$1" && shift
|
||||
|
||||
verify_path "$homedir" || { >&2 echo -e "$(basename $0): No valid <homedir> specified\n\tUse the --help option get help"; ((ERROR++)); }
|
||||
verify_order "$version" "$target" "$arch" || { >&2 echo -e "$(basename $0): Order '$version' '$target' '$arch' seems invalid.\n\tPlease check for network or typos"; ((ERROR++)); }
|
||||
[ "$ERROR" -gt 0 ] && return 1
|
||||
|
||||
#start sync
|
||||
echo -e "$(basename $0): '$version' '$arch' package syncing..."
|
||||
sync_package "${homedir}" "${version}" "${arch}" || ((ERROR++))
|
||||
echo -e "$(basename $0): '$version' '$target'${kversion:+ 'k${kversion}'} target syncing..."
|
||||
sync_target "${homedir}" "${version}" "${target}" "${kversion}" || ((ERROR++))
|
||||
[ "$extra" == "true" ] && {
|
||||
echo -e "$(basename $0): '$version' '$target' supplementary syncing..."
|
||||
sync_extra "${homedir}" "${version}" "${target}" || ((ERROR++))
|
||||
}
|
||||
[ -n "$model" ] && {
|
||||
echo -e "$(basename $0): '$version' '$target' '$model' model syncing..."
|
||||
sync_model "${homedir}" "${version}" "${target}" "${model}" || ((ERROR++))
|
||||
}
|
||||
|
||||
return $ERROR
|
||||
}
|
||||
|
||||
#sync_package <local mirror root path> <openwrt version> <package arch>
|
||||
sync_package() {
|
||||
local home="${1%/}" && shift
|
||||
local ver="$1" && shift
|
||||
local arch="$1" && shift
|
||||
|
||||
local ERROR=0
|
||||
|
||||
local VER="$URLHREF_RELEASES/$ver"
|
||||
mkdir -p "$home/${VER}" 2>/dev/null
|
||||
|
||||
rsync $ARCHIVE$INFO $COMPAC $PRUNE $PROGR --bwlimit=$BWLIMIT --include "$URLHREF_VERS_PACKAGES" --exclude='*' "$RSYNC_URL/${VER}/" "$home/${VER}/" || ((ERROR++))
|
||||
sleep 5
|
||||
mkdir -p "$home/${VER}/$(ls -l "$home/${VER}/$URLHREF_VERS_PACKAGES" | sed "s|.*->[ ]*\(.*\)[ ]*$|\1|")" 2>/dev/null
|
||||
rsync $ARCHIVE$INFO $COMPAC $PRUNE $PROGR --bwlimit=$BWLIMIT "$RSYNC_URL/${VER}/$URLHREF_VERS_PACKAGES/$arch" "$home/${VER}/$URLHREF_VERS_PACKAGES/" || ((ERROR++))
|
||||
|
||||
return $ERROR
|
||||
}
|
||||
|
||||
#sync_target <local mirror root path> <openwrt version> <target/subtarget> [Kernel version]
|
||||
sync_target() {
|
||||
local home="${1%/}" && shift
|
||||
local ver="$1" && shift
|
||||
local target="$1" && shift
|
||||
[ "$#" -ge 1 ] && local kver="$1" && shift
|
||||
|
||||
local ERROR=0
|
||||
|
||||
local VER="$URLHREF_RELEASES/$ver"
|
||||
mkdir -p "$home/${VER}" 2>/dev/null
|
||||
|
||||
mkdir -p "$home/${VER}/$URLHREF_VERS_TARGETS/$target" 2>/dev/null
|
||||
rsync $ARCHIVE$INFO $COMPAC $PRUNE $PROGR --bwlimit=$BWLIMIT --include '*/' --exclude='*' "$RSYNC_URL/${VER}/$URLHREF_VERS_TARGETS/$target/" "$home/${VER}/$URLHREF_VERS_TARGETS/$target/" || ((ERROR++))
|
||||
#kmods
|
||||
rsync $ARCHIVE$INFO $COMPAC $PRUNE $PROGR --bwlimit=$BWLIMIT "$RSYNC_URL/${VER}/$URLHREF_VERS_TARGETS/$target/kmods/$kver" "$home/${VER}/$URLHREF_VERS_TARGETS/$target/kmods/" || ((ERROR++))
|
||||
#packages
|
||||
rsync $ARCHIVE$INFO $COMPAC $PRUNE $PROGR --bwlimit=$BWLIMIT "$RSYNC_URL/${VER}/$URLHREF_VERS_TARGETS/$target/packages" "$home/${VER}/$URLHREF_VERS_TARGETS/$target/" || ((ERROR++))
|
||||
|
||||
return $ERROR
|
||||
}
|
||||
|
||||
#sync_extra <local mirror root path> <openwrt version> <target/subtarget>
|
||||
sync_extra() {
|
||||
local home="${1%/}" && shift
|
||||
local ver="$1" && shift
|
||||
local target="$1" && shift
|
||||
|
||||
local ERROR=0
|
||||
|
||||
local VER="$URLHREF_RELEASES/$ver"
|
||||
mkdir -p "$home/${VER}" 2>/dev/null
|
||||
|
||||
mkdir -p "$home/${VER}/$URLHREF_VERS_TARGETS/$target" 2>/dev/null
|
||||
#supplementary
|
||||
local table="$(rsync --list-only "$RSYNC_URL/${VER}/$URLHREF_VERS_TARGETS/$target/" | awk '{print $NF}' \
|
||||
| grep -Ev '^\.{0,2}/?$' \
|
||||
| grep -Ev '^(kmods|packages)/?$' \
|
||||
| grep -Ev "^.*-${ver}-${target/\//-}-.*$" \
|
||||
)"
|
||||
if [ -n "$table" ]; then
|
||||
local expr="{$(echo "$table" | sed "s|^|'|;s|$|'|" | tr '\n' ',' | sed 's|,$||')}"
|
||||
eval "rsync \$ARCHIVE\$INFO \$COMPAC \$PRUNE \$PROGR --bwlimit=\$BWLIMIT --include=$expr --exclude='*' \"\$RSYNC_URL/\${VER}/\$URLHREF_VERS_TARGETS/\$target/\" \"\$home/\${VER}/\$URLHREF_VERS_TARGETS/\$target/\"" || ((ERROR++))
|
||||
#for v in $(echo "$table" | sed "s|^|'|;s|$|'|"); do
|
||||
# rsync $ARCHIVE$INFO $COMPAC $PRUNE $PROGR --bwlimit=$BWLIMIT "$RSYNC_URL/${VER}/$URLHREF_VERS_TARGETS/$target/${v:1:-1}" "$home/${VER}/$URLHREF_VERS_TARGETS/$target/" || ((ERROR++))
|
||||
#done
|
||||
else
|
||||
>&2 echo -e "$(basename $0): Sync '${VER}/$URLHREF_VERS_TARGETS/$target' error. Get Supplementary Files failed.\n\tPlease check for network"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return $ERROR
|
||||
}
|
||||
|
||||
#sync_model <local mirror root path> <openwrt version> <target/subtarget> <model>
|
||||
sync_model() {
|
||||
local home="${1%/}" && shift
|
||||
local ver="$1" && shift
|
||||
local target="$1" && shift
|
||||
local model="$1" && shift
|
||||
|
||||
local ERROR=0
|
||||
|
||||
#Predefined
|
||||
[ -z "$model" ] && {
|
||||
case "$target" in
|
||||
x86/64)
|
||||
model="x86-64"
|
||||
;;
|
||||
*)
|
||||
model="${target/\//-}"
|
||||
#return 1
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
local VER="$URLHREF_RELEASES/$ver"
|
||||
mkdir -p "$home/${VER}" 2>/dev/null
|
||||
|
||||
rsync $ARCHIVE$INFO $COMPAC $PRUNE $PROGR --bwlimit=$BWLIMIT --include="*${model}-*" --exclude='*' "$RSYNC_URL/${VER}/$URLHREF_VERS_TARGETS/$target/" "$home/${VER}/$URLHREF_VERS_TARGETS/$target/" || ((ERROR++))
|
||||
|
||||
return $ERROR
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Main
|
||||
# Get options
|
||||
while [ -n "$1" ]; do
|
||||
case "$1" in
|
||||
--help)
|
||||
_help
|
||||
exit
|
||||
;;
|
||||
-V|--Version)
|
||||
_version
|
||||
exit
|
||||
;;
|
||||
-x|--proxy)
|
||||
tmp=$(echo "${2,,}"|sed -En "\
|
||||
/^(http|https|socks5|socks5h):\/\/\
|
||||
(\
|
||||
((25[0-5]|(2[0-4]|1{0,1}\d){0,1}\d)\.){3}(25[0-5]|(2[0-4]|1{0,1}\d){0,1}\d)\
|
||||
|\[(\
|
||||
([[:xdigit:]]{1,4}:){7}[[:xdigit:]]{1,4}|\
|
||||
([[:xdigit:]]{1,4}:){1,7}:|\
|
||||
([[:xdigit:]]{1,4}:){1,6}:[[:xdigit:]]{1,4}|\
|
||||
([[:xdigit:]]{1,4}:){1,5}(:[[:xdigit:]]{1,4}){1,2}|\
|
||||
([[:xdigit:]]{1,4}:){1,4}(:[[:xdigit:]]{1,4}){1,3}|\
|
||||
([[:xdigit:]]{1,4}:){1,3}(:[[:xdigit:]]{1,4}){1,4}|\
|
||||
([[:xdigit:]]{1,4}:){1,2}(:[[:xdigit:]]{1,4}){1,5}|\
|
||||
[[:xdigit:]]{1,4}:(:[[:xdigit:]]{1,4}){1,6}|\
|
||||
:((:[[:xdigit:]]{1,4}){1,7}|:)|\
|
||||
fe80:(:[[:xdigit:]]{0,4}){0,4}%\w+|\
|
||||
::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}\d){0,1}\d)\.){3}(25[0-5]|(2[0-4]|1{0,1}\d){0,1}\d)|\
|
||||
([[:xdigit:]]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}\d){0,1}\d)\.){3}(25[0-5]|(2[0-4]|1{0,1}\d){0,1}\d)\
|
||||
)\]\
|
||||
)\
|
||||
:(6553[0-5]|(655[0-2]|65[0-4]\d|6[0-4]\d{2}|[1-5]{0,1}\d{1,3}){0,1}\d)$/p")
|
||||
if [ -n "$tmp" ]; then
|
||||
export ALL_PROXY="$2"
|
||||
[ -n "$(echo "${2,,}"|sed -En '/^https?:/p')" ] && export RSYNC_PROXY="$(echo "$2"|sed -En 's|^.+://||p')"
|
||||
#[ -n "$(echo "${2,,}"|sed -En '/^socks5:/p')" ] && export RSYNC_CONNECT_PROG="ncat --proxy-type socks5 --proxy-dns local --proxy $(echo "$2"|sed -En 's|^.+://||p') %H 873"
|
||||
#[ -n "$(echo "${2,,}"|sed -En '/^socks5h:/p')" ] && export RSYNC_CONNECT_PROG="ncat --proxy-type socks5 --proxy-dns remote --proxy $(echo "$2"|sed -En 's|^.+://||p') %H 873"
|
||||
[ -n "$(echo "${2,,}"|sed -En '/^socks5h?:/p')" ] && export RSYNC_CONNECT_PROG="ncat --proxy-type socks5 --proxy-dns both --proxy $(echo "$2"|sed -En 's|^.+://||p') %H 873"
|
||||
else
|
||||
>&2 echo -e "$(basename $0): Option '$1' requires a valid argument\n\tUse the --help option get help"
|
||||
exit 1
|
||||
fi
|
||||
shift
|
||||
;;
|
||||
-l|--bwlimit)
|
||||
[ -n "$(echo "${2^^}"|sed -En '/^(\d|[1-9]\d*(K|M|G)?)$/p')" ] && BWLIMIT="${2^^}" || { >&2 echo -e "$(basename $0): Option '$1' requires a valid argument\n\tUse the --help option get help"; exit 1; }
|
||||
#[ -n "$(echo "$2"|sed -En '/^(\d|[1-9]\d*(K|M|G)?)$/lp')" ]
|
||||
shift
|
||||
;;
|
||||
--rsyncurl)
|
||||
RSYNC_URL="$2"
|
||||
shift
|
||||
;;
|
||||
-d|--homedir)
|
||||
verify_path "$2" && HOMEPATH="$2" || { >&2 echo -e "$(basename $0): Option '$1' requires a valid argument\n\tUse the --help option get help"; exit 1; }
|
||||
shift
|
||||
;;
|
||||
-n|--name)
|
||||
name="$2"
|
||||
shift
|
||||
;;
|
||||
-s|--version)
|
||||
version="$2"
|
||||
shift
|
||||
;;
|
||||
-t|--target)
|
||||
target="$2"
|
||||
shift
|
||||
;;
|
||||
-k|--arch)
|
||||
arch="$2"
|
||||
shift
|
||||
;;
|
||||
-m|--model)
|
||||
model="$2"
|
||||
shift
|
||||
;;
|
||||
-e|--extra)
|
||||
extra="$2"
|
||||
shift
|
||||
;;
|
||||
-o|--orders)
|
||||
JSON="$2"
|
||||
shift
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
>&2 echo -e "$(basename $0): '$1' is not a valid option\n\tUse the --help option get help"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
# Get parameters
|
||||
# ...
|
||||
|
||||
# Execute
|
||||
parse_json "${JSON:=[{'name':'$name','version':'$version','target':'$target','arch':'$arch','model':'${model}','extra':${extra:-false}\}]}" #|| { >&2 echo -e "$(basename $0): Required options requires valid argument\n\tUse the --help option get help"; exit 1; }
|
||||
exitcode=$?
|
||||
rm -f "$PIDFILE" 2>/dev/null
|
||||
exit $exitcode
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"admin/system/packagesync": {
|
||||
"title": "Local software source",
|
||||
"order": 32,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "packagesync"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-app-packagesync" ],
|
||||
"uci": { "packagesync": true }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"luci-app-packagesync": {
|
||||
"description": "Grant access to packagesync procedures",
|
||||
"read": {
|
||||
"file": {
|
||||
"/etc/init.d/packagesync": [ "exec" ],
|
||||
"/bin/df -hT": [ "exec" ],
|
||||
"/var/packagesync/releaseslist": [ "read" ],
|
||||
"/var/packagesync/targetslist": [ "read" ],
|
||||
"/var/packagesync/pkgarchslist": [ "read" ],
|
||||
"/var/run/packagesync.pid": [ "read" ]
|
||||
},
|
||||
"ubus": {
|
||||
"service": [ "list" ]
|
||||
},
|
||||
"uci": [ "packagesync" ]
|
||||
},
|
||||
"write": {
|
||||
"uci": [ "packagesync" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"config": "packagesync",
|
||||
"init": "packagesync"
|
||||
}
|
||||
Reference in new issue
Block a user