Files
eos-pkgbuild-setup/archive-sync-to-remote

285 lines
8.0 KiB
Bash
Executable File

#!/bin/bash
printf2() { printf "$@" >&2 ; }
echo2() { echo "$@" >&2 ; }
read2() { read "$@" >&2 ; }
Indent() { sed 's|^| |' ; }
FolderTests() {
local filename_head="$1"
local testing="$2" # yes or no
if [ "$(basename "$PWD")" != "PKG_ARCHIVE" ] ; then
echo2 "You seem to be in the wrong folder, should be PKG_ARCHIVE."
return 4
fi
if [ -z "$(ls -1 ${filename_head}-*.zst 2>/dev/null)" ] ; then
[ "$testing" = "yes" ] || echo2 "You seem to be in the wrong folder, package ${filename_head}-*.zst was not found."
return 4
fi
}
FileToTag() {
local filename_head="$1"
case "$filename_head" in
welcome) tag=packages ;;
eos-pkgbuild-setup) tag=repo-testing ;;
esac
}
Tag() {
local available_tags
local known_tag
echo "Making sure we can reach the tags."
logstuff on
readarray -t available_tags < <(hub release)
for known_tag in "${available_tags[@]}" ; do
[ "$tag" = "$known_tag" ] && break
done
case "$tag" in
"$known_tag")
case "$tag" in
packages)
FolderTests welcome no || return $?
echo2 "Using tag: $tag"
return 0
;;
repo-testing)
FolderTests eos-pkgbuild-setup no || return $?
echo2 "Using tag: $tag"
return 0
;;
*)
echo2 "Detected tags: ${available_tags[*]}"
read2 -p "Use tag '$tag'? [Y/n] "
case "$REPLY" in
"" | [yY]*) ;;
*) return 1 ;;
esac
;;
esac
;;
"")
local xx
for xx in eos-pkgbuild-setup welcome ; do
if FolderTests $xx yes ; then
FileToTag $xx
printf2 "Based on existing file(s) ${xx}-*.zst using tag: $tag\n"
return 0
fi
done
echo2 "Please give a tag. Available tags:"
printf2 " %s\n" "${available_tags[@]}"
return 2
;;
*)
echo2 "Unknown tag '$tag'. Available tags:"
printf2 " %s\n" "${available_tags[@]}"
return 3
;;
esac
}
Options() {
local progname="${0##*/}"
local opts
opts="$(/usr/bin/getopt -o=hd --longoptions help,dryrun --name "$progname" -- "$@")" || {
Options -h
return 1
}
eval set -- "$opts"
while true ; do
case "$1" in
-d | --dryrun)
dryrun=yes
;;
-h | --help)
cat <<EOF >&2
Usage: $progname [options] tag
Options:
-d, --dryrun Simulate run, don't change anything permanently.
Tag: Release assets tag at github.
EOF
;;
--) shift ; break ;;
esac
shift
done
tag="$1"
}
AddsAndRemoves() {
# combine local and remote, keep 5 latest of each file version
local locals_and_remotes=$(printf "%s\n" "$locals" "$remotes" | grep -v "\.sig$" | sort -Vu)
local file fileprev=""
local pkgname pkgnameprev=""
local files=()
local files_to_keep=()
local files_to_remove=()
local -r breaker="[A-DUMMY-BREAKER]"
local count
for file in $locals_and_remotes "$breaker" ; do
[ "$file" = "$breaker" ] && break # all files checked
# [ "$file" = "$fileprev" ] && continue # remove duplicates (commented because of 'sort -Vu' above)
fileprev="$file"
pkgname=$(pkg-name-components N "$file")
[ -z "$pkgnameprev" ] && pkgnameprev="$pkgname"
case "$pkgname" in
"$pkgnameprev")
files+=("$file")
;;
*)
# pkgname changed, files full
files_to_keep+=($(printf "%s\n" "${files[@]}" | tail -n$keep))
count=${#files[@]}
if [ $count -gt $keep ] ; then
files_to_remove+=($(printf "%s\n" "${files[@]}" | head -n$((count-keep))))
fi
# prepare for the next file
pkgnameprev="$pkgname"
files=("$file")
esac
done
# now we know which files to remove from local and remote, and keep
local add_remote=()
local remove_remote=()
local add_local=()
local remove_local=()
printf2 "\n===> Managing archived files >>>>>>>>>>>>>\n\n"
# Note: handle .sig files now.
for file in "${files_to_keep[@]}" ; do
if [ -z "$(echo "$remotes" | grep "$file")" ] ; then
add_remote+=("$file" "$file.sig")
fi
if [ -z "$(echo "$locals" | grep "$file")" ] ; then
add_local+=("$file" "$file.sig")
fi
done
for file in "${files_to_remove[@]}" ; do
if [ -n "$(echo "$remotes" | grep "$file")" ] ; then
remove_remote+=("$file" "$file.sig")
fi
if [ -n "$(echo "$locals" | grep "$file")" ] ; then
remove_local+=("$file" "$file.sig")
fi
done
ShowFileInfo "additions to local" "${add_local[@]}"
ShowFileInfo "additions to remote" "${add_remote[@]}"
ShowFileInfo "removals from local" "${remove_local[@]}"
ShowFileInfo "removals from remote" "${remove_remote[@]}"
if [ "$dryrun" = no ] ; then
local arr=() remo renamed_to_remo=()
local handle_chmods=no
case "$(/bin/ls -ld .)" in
"dr-x"*) handle_chmods=yes; chmod u+w . ;;
esac
# local adds
if [ ${#add_local[@]} -gt 0 ] ; then
for remo in "${add_local[@]}" ; do
## local file name may include : or +, so convert them for github
case "$remo" in
*.sig) ;; # download-release-assets will get this too!
*)
download-release-assets "$tag" "$remo*" || return $? # remove * from $remo* ??
sleep 1
;;
esac
done
fi
# remote adds
if [ ${#add_remote[@]} -gt 0 ] ; then
# rename local name with :/+ to COLON/PLUS for remote
arr=()
for file in "${add_remote[@]}" ; do
remo=${file/:/COLON}
remo=${remo/+/PLUS}
arr+=("$remo")
if [ "$file" != "$remo" ] ; then
cp "$file" "$remo"
renamed_to_remo+=("$remo")
fi
done
add-release-assets "$tag" "${arr[@]}" || return $?
rm -f "${renamed_to_remo[@]}"
sleep 1
fi
# local removes
if [ ${#remove_local[@]} -gt 0 ] ; then
rm -f "${remove_local[@]}"
fi
# remote removes
if [ ${#remove_remote[@]} -gt 0 ] ; then
arr=()
# rename :/+ to COLON/PLUS
for file in "${remove_remote[@]}" ; do
remo=${file/:/COLON}
remo=${remo/+/PLUS}
arr+=("$remo")
done
delete-release-assets --quietly "$tag" "${arr[@]}" || return $?
sleep 1
fi
fi
[ "$handle_chmods" = yes ] && chmod u-w .
printf2 "\n<<<<<<<<<< Done. <===============\n\n"
}
ShowFileInfo() {
local msg="$1"
shift
local count="$#"
printf2 "%-5d %s\n" "$count" "$msg"
[ $count -gt 0 ] && printf "%s\n" "$@" | Indent >&2
}
FilterPackages() { grep -P '\.xz$|\.zst$' ; } # Note: exclude *.sig files for now.
Main() {
local tag=""
local dryrun=no
local keep=5 # keeps max 5 latest of each package
local locals=""
local remotes=""
Options "$@"
Tag || return $?
locals=$(/usr/bin/ls -1 | FilterPackages)
remotes=$(release-asset-names "$tag" | FilterPackages | sed -e 's|COLON|:|g' -e 's|PLUS|+|')
AddsAndRemoves || return $?
}
Main "$@"