545 lines
21 KiB
Bash
Executable file
545 lines
21 KiB
Bash
Executable file
#!/bin/bash
|
|
# shellcheck disable=SC2015,SC2059
|
|
VERSION="0.3.2"
|
|
# Copyright (c) 2005-2022:
|
|
# Darren 'Tadgy' Austin <darren (at) afterdark.org.uk>
|
|
# Licensed under the terms of the GNU General Public License version 3.
|
|
|
|
# Configuration.
|
|
REPO_ROOT="${REPO_ROOT:-/data/slackware/repo}"
|
|
REPO_PACKAGE_DIRS=( "$REPO_ROOT"/slackware* )
|
|
GPG_KEY="${GPG_KEY:-Darren 'Tadgy' Austin <darren@slackware.uk>}"
|
|
|
|
# Defaults
|
|
FORCE=0
|
|
NO_CL=0
|
|
NO_MD5=0
|
|
NO_SIGN=0
|
|
LOCKFILE=".${0##*/}.lock"
|
|
|
|
# Timestamp to be used in ChangeLog.txt and a few other files.
|
|
NOW="$(date --utc)"
|
|
|
|
# Extra shell features.
|
|
shopt -s extglob globstar nullglob
|
|
set -o pipefail
|
|
|
|
die() {
|
|
# $* = Error message output before exiting.
|
|
printf "\\033[1;31;40m%s\\033[0;39m\\n" "${*:-abort}." >&2
|
|
exit 1
|
|
}
|
|
|
|
display_version() {
|
|
# |........1.........2.........3.........4.........5.........6.........7.........8
|
|
cat <<-EOF
|
|
${0##*/} v$VERSION.
|
|
Copyright (c) 2005-2022 Darren 'Tadgy' Austin <darren (at) afterdark.org.uk>.
|
|
Licensed under the terms of the GNU GPL v3 <http://gnu.org/licenses/gpl.html>.
|
|
This program is free software; you can modify or redistribute it in accordence
|
|
with the GNU GPL. However, it comes with ABSOLUTELY NO WARRANTY; not even the
|
|
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
EOF
|
|
}
|
|
|
|
display_help() {
|
|
# |........1.........2.........3.........4.........5.........6.........7.........8
|
|
cat <<-EOF
|
|
Usage: ${0##*/} [options] [directory] [...]
|
|
Generate slapt-get compatible meta-files for a Slackware package repository.
|
|
|
|
Options (all of which are optional):
|
|
-b, --blurb When generating the ChangeLog.txt, prompt for the blurb
|
|
to appear above the individual package log entries, and
|
|
for every ChangeLog.txt entry.
|
|
-f, --force Force rebuild of metdata for all packages.
|
|
-h, --help This help text.
|
|
-nc, --no-changelog No ChangeLog.txt updates.
|
|
-nm, --no-md5 No .md5sums checksum cache generation for packages.
|
|
Without checksum cache files, creation of the repository
|
|
CHECKSUMS.md5 file will md5sum every file every time.
|
|
-ns, --no-sign No .asc GPG signature generation for packages, or
|
|
generation of the final CHECKSUMS.md5.asc file.
|
|
-v, --version Display the version and copyright information.
|
|
-- Cease option processing and begin argument parsing.
|
|
Option processing ceases with the first non-option argument or --.
|
|
|
|
Arguments (all of which are optional):
|
|
[directory] [...] Only process the (space delimited) list of directories
|
|
given on the command line.
|
|
EOF
|
|
}
|
|
|
|
gen_changelog() {
|
|
local CUR_X CUR_Y ENTRY JUNK LINES ORIG_X ORIG_Y TEXT
|
|
|
|
{ [[ -s ".ChangeLog.stub" ]] && {
|
|
printf "%s\\n" "$NOW" >&20
|
|
# Read and add header blurb.
|
|
(( BLURB == 1 )) && {
|
|
# Do some terminal trickery to recover the space used.
|
|
printf "\\033[6n"
|
|
IFS='[;' read -r -s -d R JUNK ORIG_Y ORIG_X
|
|
printf "\\033[1;31;40m%s:\\033[0;39m\\n" "Enter the (optional) ChangeLog.txt header blurb - finish with Ctl+D"
|
|
IFS= read -r -d$'\004' TEXT
|
|
LINES="$(wc -l <<<"$TEXT")"
|
|
# More terminal trickery.
|
|
printf "\\033[6n"
|
|
IFS='[;' read -r -s -d R JUNK CUR_Y CUR_X
|
|
printf "\\033[$(( CUR_Y - LINES ));${ORIG_X}f\\033[J"
|
|
# Output the header to the log.
|
|
[[ -n "$TEXT" ]] && printf "%s\\n" "$(fmt -s -u -w 78 <<<"$TEXT")" >&20
|
|
}
|
|
# Process each package that is in the stub file.
|
|
while read -r -u 21 ENTRY; do
|
|
(( BLURB == 1 )) && {
|
|
printf "\\033[6n"
|
|
# shellcheck disable=SC2034
|
|
IFS='[;' read -r -s -d R JUNK ORIG_Y ORIG_X
|
|
printf "\\033[1;33;40m%s: %s\\n" "ChangeLog.txt entry" "$ENTRY"
|
|
printf "\\033[1;31;40m%s:\\n" "Enter the (optional) blurb for the above ChangeLog.txt entry - finish with Ctl+D"
|
|
printf "%s\\033[0;39m\\n" "(Text will be re-formatted, wraped to 78 chars and indented automatically)"
|
|
IFS= read -r -d$'\004' TEXT
|
|
LINES="$(( $(wc -l <<<"$TEXT") + 2 ))"
|
|
printf "\\033[6n"
|
|
# shellcheck disable=SC2034
|
|
IFS='[;' read -r -s -d R JUNK CUR_Y CUR_X
|
|
printf "\\033[$(( CUR_Y - LINES ));${ORIG_X}f\\033[J"
|
|
}
|
|
# Output to the log.
|
|
printf "%s\\n" "$ENTRY" >&20
|
|
[[ -n "$TEXT" ]] && printf "%s\\n" "$(fmt -s -u -w 76 <<<"$TEXT" | sed -re 's/^/ /g')" >&20
|
|
done 21<.ChangeLog.stub
|
|
# If there's a previous changelog, append it to the end of the new one.
|
|
[[ -e ChangeLog.txt ]] && printf "+--------------------------+\\n" >&20
|
|
}
|
|
[[ -e ChangeLog.txt ]] && cat ChangeLog.txt >&20
|
|
} 20>.ChangeLog.staged
|
|
rm -f .ChangeLog.stub
|
|
return 0
|
|
}
|
|
|
|
gen_checksums() {
|
|
local FILE
|
|
|
|
# shellcheck disable=SC2094
|
|
{ cat <<-EOF
|
|
These are the MD5 message digests for the files in this directory.
|
|
If you want to test your files, use 'md5sum' and compare the values to
|
|
the ones listed here.
|
|
|
|
To test all these files, use this command:
|
|
|
|
tail +13 CHECKSUMS.md5 | md5sum -c --quiet - | less
|
|
|
|
'md5sum' can be found in the GNU coreutils package on ftp.gnu.org in
|
|
/pub/gnu, or at any GNU mirror site.
|
|
|
|
MD5 message digest Filename
|
|
EOF
|
|
|
|
if (( NO_MD5 == 0 )); then
|
|
# Create from the .md5sums files if possible, otherwise sum individually.
|
|
for FILE in **/!(*.asc|*.manifest|*.md5sums|*-*-*-*.txt|CHECKSUMS.md5); do
|
|
if [[ "$FILE" == *.t?z ]]; then
|
|
if [[ -e "${FILE%.t?z}.md5sums" ]]; then
|
|
# Just cat the .md5sums file.
|
|
cat "${FILE%.t?z}.md5sums"
|
|
else
|
|
# No .md5sums file - sum the relevant files.
|
|
if [[ -e "$FILE.asc" ]]; then
|
|
md5sum "$FILE" "$FILE.asc" "${FILE%.t?z}.txt" 2>/dev/null || return 1
|
|
else
|
|
md5sum "$FILE" "${FILE%.t?z}.txt" 2>/dev/null || return 1
|
|
fi
|
|
fi
|
|
else
|
|
# md5sum the file.
|
|
[[ -f "$FILE" ]] && { md5sum "$FILE" || return 1; }
|
|
fi
|
|
done
|
|
else
|
|
# Ignore the .md5sums files and sum everything.
|
|
find . \( ! -type f -o -path '*/.*' -o -name '*.manifest' -o -name '*.md5sums' -a -prune \) -o -printf "%P\\n" | sort | xargs md5sum || return 1
|
|
fi
|
|
} >CHECKSUMS.md5
|
|
return 0
|
|
}
|
|
|
|
gen_filelist() {
|
|
{ printf "%s\\n\\n" "$NOW"
|
|
printf "%s\\n" "Here is the file list for this directory. If you are using a"
|
|
printf "%s\\n" "mirror site and find missing or extra files in the disk"
|
|
printf "%s\\n" "subdirectories, please have the archive administrator refresh"
|
|
printf "%s\\n\\n" "the mirror."
|
|
|
|
# Trying to use the output of ls is always a bad idea, but there's little choice here....
|
|
find . \( -path '*/.*' -o -name '*.manifest' -o -name '*.md5sums' -a -prune \) -o -print | sort | xargs ls -1bld --time-style=long-iso | \
|
|
sed -re 's/([^[:space:]]+[[:space:]]+[[:digit:]]+[[:space:]]+)[^[:space:]]+([[:space:]]+)[^[:space:]]+(.*)/\1root\2root\3/g' || return 1
|
|
} >FILELIST.TXT
|
|
return 0
|
|
}
|
|
|
|
gen_manifest() {
|
|
local FILE
|
|
|
|
# Create from the .manifest cache files if possible, otherwise create inline.
|
|
{ for FILE in **/*-*-*-*.t?z; do
|
|
printf "++========================================\\n||\\n"
|
|
printf "|| Package: ./%s\\n" "$FILE"
|
|
printf "||\\n++========================================\\n"
|
|
if [[ -e "${FILE%.t?z}.manifest" ]]; then
|
|
# Include the .manifest file.
|
|
cat "${FILE%.t?z}.manifest" 2>/dev/null || return 1
|
|
else
|
|
# No .manifest file.
|
|
tar -vvtf "$FILE" 2>/dev/null || return 1
|
|
fi
|
|
printf "\\n\\n"
|
|
done
|
|
} | bzip2 -c9 >MANIFEST.bz2 2>/dev/null || return 1
|
|
return 0
|
|
}
|
|
|
|
gen_packages() {
|
|
{ printf "%s; %s\\n\\n" "PACKAGES.TXT" "$NOW"
|
|
printf "%s\\n%s\\n\\n" "This file provides details on the Slackware packages found" "in this directory."
|
|
# shellcheck disable=SC2046
|
|
printf "%s: %s MB\\n" "Total size of all packages (compressed)" "$(numfmt --from=iec --to-unit=1048576 "$(( \
|
|
($(awk -F' ' -e '/^PACKAGE SIZE \(compressed\)/ { print $4 " + "}' $(find . -type f -name '*-*-*-*.txt'; printf "/dev/null"))0) * 1024 ))")"
|
|
# shellcheck disable=SC2046
|
|
printf "%s: %s MB\\n\\n\\n" "Total size of all packages (uncompressed)" "$(numfmt --from=iec --to-unit=1048576 "$(( \
|
|
($(awk -F' ' -e '/^PACKAGE SIZE \(uncompressed\)/ { print $4 " + "}' $(find . -type f -name '*-*-*-*.txt'; printf "/dev/null"))0) * 1024 ))")"
|
|
for TXT in **/*-*-*-*.txt; do
|
|
cat "$TXT" || return 1
|
|
printf "\\n"
|
|
done
|
|
} >PACKAGES.TXT
|
|
return 0
|
|
}
|
|
|
|
gen_pkg_changelog() {
|
|
# $1 = Package file to process [required].
|
|
local CACHE=() CACHED_ARCH CACHED_BUILD CACHED_DIR CACHED_EXT CACHED_TAG CACHED_VER
|
|
local I J PKG_ARCH PKG_BUILD PKG_DIR PKG_EXT PKG_NAME PKG_TAG PKG_VER TMP
|
|
|
|
[[ -z "$1" ]] || [[ ! -e "$1" ]] && die "abort: ${FUNCNAME[0]} ($LINENO)"
|
|
|
|
# Get the new package details.
|
|
PKG_DIR="${1%/*}"; [[ "$PKG_DIR" == "$1" ]] && PKG_DIR=""
|
|
PKG_NAME="$(printf "$1" | rev | cut -d- -f4- | cut -d/ -f1 | rev)"
|
|
PKG_VER="$(printf "$1" | rev | cut -d- -f3 | rev)"
|
|
PKG_ARCH="$(printf "$1" | rev | cut -d- -f2 | rev)"
|
|
TMP="$(printf "$1" | rev | cut -d- -f1 | rev)"
|
|
PKG_BUILD="${TMP%%[^[:digit:]]*}"
|
|
TMP="${TMP/#+([[:digit:]])}"
|
|
PKG_TAG="${TMP%.t?z}"
|
|
PKG_EXT="${TMP##*.}"
|
|
unset TMP
|
|
|
|
# Read the cache file.
|
|
[[ -e ".versions.cache" ]] && { mapfile -t CACHE <.versions.cache || die "Failed to read .versions.cache"; }
|
|
|
|
# Find the package details in the array.
|
|
for ((I = 0; I < ${#CACHE[*]}; I++)); do
|
|
IFS=';' read -r CACHED_DIR CACHED_NAME CACHED_VER CACHED_ARCH CACHED_BUILD CACHED_TAG CACHED_EXT <<<"${CACHE[I]}"
|
|
[[ "$CACHED_NAME" == "$PKG_NAME" ]] && break
|
|
done
|
|
|
|
{ # If there's no CACHED_VER set, then there's either no cache or the package isn't in it.
|
|
# Either way, just mark the package as added.
|
|
if [[ -z "$CACHED_VER" ]]; then
|
|
printf "%s: %s.\\n" "$1" "Added"
|
|
elif [[ "$PKG_DIR" != "$CACHED_DIR" ]] || [[ "$PKG_EXT" != "$CACHED_EXT" ]]; then
|
|
# Package has changed directory or extension - mark new one as added; the other as removed.
|
|
printf "%s: %s.\\n" "$1" "Added"
|
|
printf "%s: %s.\\n" "${CACHED_DIR:+$CACHED_DIR/}$PKG_NAME-$CACHED_VER-$CACHED_ARCH-$CACHED_BUILD$CACHED_TAG.$CACHED_EXT" "Removed"
|
|
elif [[ "$PKG_VER" != "$CACHED_VER" ]]; then
|
|
# Versions are different, no need to do more than mark as upgraded.
|
|
printf "%s: %s.\\n" "$1" "Upgraded"
|
|
else
|
|
# Versions are the same, check the build details.
|
|
if [[ "$PKG_TAG" != "$CACHED_TAG" ]]; then
|
|
# Different build tag, no need to test the build number.
|
|
# Mark the new package as added; the old one as removed.
|
|
printf "%s: %s.\\n" "$1" "Added"
|
|
printf "%s: %s.\\n" "${CACHED_DIR:+$CACHED_DIR/}$PKG_NAME-$CACHED_VER-$CACHED_ARCH-$CACHED_BUILD$CACHED_TAG.$CACHED_EXT" "Removed"
|
|
elif (( PKG_BUILD != CACHED_BUILD )); then
|
|
# If the build numbers differ, just mark a rebuild.
|
|
printf "%s: %s.\\n" "$1" "Rebuilt"
|
|
fi
|
|
fi
|
|
} | sort >>.ChangeLog.stub
|
|
|
|
# There may still be old entries for the package in the cache.
|
|
for ((J = I; J < ${#CACHE[*]}; J++)); do
|
|
[[ "$(printf "${CACHE[J]}" | cut -d: -f2)" == "$PKG_NAME" ]] && unset 'CACHE[J]'
|
|
done
|
|
|
|
# Remove the upgraded/rebuilt package from the cache.
|
|
[[ -n "${CACHE[I]}" ]] && unset 'CACHE[I]'
|
|
|
|
# Finally, add the new package to the cache.
|
|
CACHE+="$PKG_DIR;$PKG_NAME;$PKG_VER;$PKG_ARCH;$PKG_BUILD;$PKG_TAG;$PKG_EXT"
|
|
|
|
# Write the new cache file.
|
|
printf "%s\\n" "${CACHE[@]}" | sort -r >.versions.cache
|
|
}
|
|
|
|
gen_pkg_md5sums() {
|
|
# $1 = Package file to process [required].
|
|
local TXT="${1%.t?z}.txt"
|
|
local MD5="${1%.t?z}.md5sums"
|
|
|
|
[[ -z "$1" ]] || [[ ! -e "$1" ]] && die "abort: ${FUNCNAME[0]} ($LINENO)"
|
|
if [[ -e "$1.asc" ]]; then
|
|
md5sum "$1" "$1.asc" "$TXT" >"$MD5" || return 1
|
|
else
|
|
md5sum "$1" "$TXT" >"$MD5" || return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
gen_pkg_txt() {
|
|
# $1 = Package file to process [required].
|
|
local TXT="${1%.t?z}.txt"
|
|
|
|
[[ -z "$1" ]] || [[ ! -e "$1" ]] && die "abort: ${FUNCNAME[0]} ($LINENO)"
|
|
{ printf "%s: %s\\n" "PACKAGE NAME" "${1##*/}"
|
|
printf "%s: %s\\n" "PACKAGE LOCATION" "./${1%/*}"
|
|
printf "%s: %s\\n" "PACKAGE SIZE (compressed)" "$(du -k "$1" | cut -d $'\t' -f 1) K"
|
|
printf "%s: %s\\n" "PACKAGE SIZE (uncompressed)" "$(numfmt --to-unit=1024 "$(tar -xOf "$1" | wc -c)") K"
|
|
printf "%s: %s\\n" "PACKAGE REQUIRED" "$(tar --occurrence=1 -xOf "$1" install/slack-required 2>/dev/null | tr $'\n' ',' | sed -e 's/,$//')"
|
|
printf "%s: %s\\n" "PACKAGE CONFLICTS" "$(tar --occurrence=1 -xOf "$1" install/slack-conflicts 2>/dev/null | tr $'\n' ',' | sed -e 's/,$//')"
|
|
printf "%s: %s\\n" "PACKAGE SUGGESTS" "$(tar --occurrence=1 -xOf "$1" install/slack-suggests 2>/dev/null | tr $'\n' ' ' | sed -e 's/ $//')"
|
|
printf "%s:\\n" "PACKAGE DESCRIPTION"
|
|
tar --occurrence=1 -xOf "$1" install/slack-desc 2>/dev/null
|
|
} >"$TXT" || return 1
|
|
return 0
|
|
}
|
|
|
|
runtime() {
|
|
# $1 = Number of seconds to convert to readable text [required].
|
|
|
|
[[ -z "$1" ]] && die "abort: ${FUNCNAME[0]} ($LINENO)"
|
|
local D=$(( $1 / 86400 ))
|
|
local H=$(( ($1 - (D * 86400)) / 3600 ))
|
|
local M=$(( ($1 - (D * 86400) - (H * 3600)) / 60 ))
|
|
local S=$(( $1 - (D * 86400) - (H * 3600) - (M * 60) ))
|
|
|
|
if (( D > 0 )); then
|
|
printf "%s, %s %s %s" "${D}d" "${H}h" "${M}m" "${S}s"
|
|
else
|
|
printf "%s, %s %s" "${H}h" "${M}m" "${S}s"
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
sign_file() {
|
|
# $1 = The file to sign [required].
|
|
|
|
[[ -z "$1" ]] || [[ ! -e "$1" ]] && die "abort: ${FUNCNAME[0]} ($LINENO)"
|
|
gpg2 --sign --detach-sign --armor --batch --quiet --local-user "$GPG_KEY" "$1" || return 1
|
|
return 0
|
|
}
|
|
|
|
|
|
# Parse command line options.
|
|
while [[ -n "$1" ]]; do
|
|
case "$1" in
|
|
-b|-blub|--blurb)
|
|
BLURB=1
|
|
shift
|
|
;;
|
|
-f|-force|--force)
|
|
FORCE=1
|
|
shift
|
|
;;
|
|
-h|-help|--help)
|
|
display_help
|
|
exit 0
|
|
;;
|
|
-nc|-no-changelog|--no-changelog)
|
|
NO_CL=1
|
|
shift
|
|
;;
|
|
-nm|-no-md5|--no-md5)
|
|
NO_MD5=1
|
|
shift
|
|
;;
|
|
-ns|-no-sign|--no-sign)
|
|
NO_SIGN=1
|
|
shift
|
|
;;
|
|
-v|-version|--version)
|
|
display_version
|
|
exit 0
|
|
;;
|
|
--)
|
|
shift
|
|
break
|
|
;;
|
|
-*)
|
|
printf "%s: %s: %s\\n" "${0##*/}" "invalid option" "$1" >&2
|
|
printf "Try: %s %s\\n" "${0##*/}" "--help" >&2
|
|
exit 1
|
|
;;
|
|
*)
|
|
break
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Operate from the top level of the repository.
|
|
cd "$REPO_ROOT" || die "Failed to change directory to repo root"
|
|
|
|
# Any remaining command line arguments are the directories to process.
|
|
[[ -n "$*" ]] && REPO_PACKAGE_DIRS=( "$@" ) || REPO_PACKAGE_DIRS=( slackware* )
|
|
|
|
# Sanity check of REPO_PACKAGE_DIRS.
|
|
for ((I = 0; I < ${#REPO_PACKAGE_DIRS[*]}; I++)); do
|
|
[[ ! -e "${REPO_PACKAGE_DIRS[I]}" ]] && die "no such package directory: ${REPO_PACKAGE_DIRS[I]}"
|
|
done
|
|
|
|
# Create lockfile.
|
|
{ exec {FD}>"$LOCKFILE" && flock -E 10 -e -w 0.5 "$FD"; } || {
|
|
if (( $? == 10 )); then
|
|
die "Failed to obtain lockfile - another instance is running"
|
|
else
|
|
die "flock usage error"
|
|
fi
|
|
}
|
|
trap 'exec {FD}<&-; rm -f "$LOCKFILE"' EXIT INT TERM
|
|
|
|
# Check gpg-agent and unlock key if required.
|
|
(( NO_SIGN == 0 )) && {
|
|
gpg2 -K "$GPG_KEY" >/dev/null 2>&1
|
|
(( $? == 2 )) && die "no key available for ID: $GPG_KEY"
|
|
printf "test" | gpg2 --sign -o /dev/null --pinentry-mode error --local-user "$GPG_KEY" >/dev/null 2>&1
|
|
(( $? == 2 )) && {
|
|
printf "\\033[1;31;40m%s\\033[0;39m\\n" "GPG signing key is locked - passphrase required."
|
|
while :; do
|
|
printf "test" | gpg2 --sign -o /dev/null --local-user "$GPG_KEY" 2>/dev/null
|
|
ERR=$?
|
|
(( ERR == 130 )) && die "caught interrupt - aborting"
|
|
(( ERR == 2 )) && {
|
|
printf "\\033[1;31;40m%s\\033[0;39m" "Incorrect passphrase. Retry? (Y/n): "
|
|
read -r -N 1
|
|
printf "\\n"
|
|
[[ "$REPLY" =~ [Nn] ]] && die "cannot continue without unlocking GPG signing key"
|
|
continue
|
|
}
|
|
(( ERR > 0 )) && die "unknown error -aborting"
|
|
break
|
|
done
|
|
}
|
|
}
|
|
|
|
# Process the package dirs.
|
|
for ((I = 0; I < ${#REPO_PACKAGE_DIRS[*]}; I++)); do
|
|
cd "${REPO_PACKAGE_DIRS[I]}" >/dev/null 2>&1 || die "abort: $LINENO"
|
|
printf "\\033[1;32;40m%s '%s':\\033[0;39m\\n" "Processing repository directory" "${REPO_PACKAGE_DIRS[I]}"
|
|
SECONDS=0
|
|
|
|
# Sanity check: make sure there is not more than one package of each name in the repository.
|
|
PKGS=()
|
|
for FILE in **/*-*-*-*.t?z; do
|
|
PKG_NAME="$(printf "$FILE" | rev | cut -d- -f4- | cut -d/ -f1 | rev)"
|
|
PKG_ARCH="${PKG_ARCH:-$(printf "$FILE" | rev | cut -d- -f2 | rev)}"
|
|
if printf "%s " "${PKGS[@]}" | grep -E "\<$PKG_NAME\>" >/dev/null 2>&1; then
|
|
die "Repository corrupt: more than one package of the same name in repository ($PKG_NAME)"
|
|
elif [[ "$PKG_ARCH" != "$(printf "$FILE" | rev | cut -d- -f2 | rev)" ]]; then
|
|
die "Repository corrupt: more than one package architecture in repository"
|
|
else
|
|
PKGS+=("$PKG_NAME")
|
|
fi
|
|
done
|
|
unset FILE PKG_ARCH PKG_NAME PKGS
|
|
|
|
# Process each package in repository.
|
|
for FILE in **/*-*-*-*.t?z; do
|
|
printf "\\033[1;33;40m %s: " "$FILE"
|
|
if (( FORCE == 1 )) || [[ "$FILE" -nt "$FILE.asc" ]] || [[ "$FILE" -nt "${FILE%.t?z}.txt" ]] || [[ "$FILE" -nt "${FILE%.t?z}.md5sums" ]] || \
|
|
[[ "$FILE" -nt "${FILE%.t?z}.manifest" ]] || ! grep -E "\<$(gpg2 --list-packets "$FILE.asc" | awk -e '/:signature packet:/ { print $6 }')\>" \
|
|
< <(gpg2 --list-keys --with-colons "$GPG_KEY" | awk -F: -e '/sub/ { if ($11 == "") print $5 }') >/dev/null 2>&1; then
|
|
rm -f "$FILE.asc" "${FILE%.t?z}.txt" "${FILE%.t?z}.md5sums"
|
|
|
|
# GPG signature.
|
|
(( NO_SIGN == 0 )) && { sign_file "$FILE" && printf "%s " "signed" || die "signing failed"; }
|
|
|
|
# .txt file metadata.
|
|
gen_pkg_txt "$FILE" && printf "%s " "metadata generated" || die "metadata generation failed"
|
|
|
|
# md5sums cache.
|
|
(( NO_MD5 == 0 )) && { gen_pkg_md5sums "$FILE" && printf "%s " "md5sums calculated" || die "md5sums calculation failed"; }
|
|
|
|
# Manifest cache.
|
|
(( VERBOSE == 1 )) && printf " %s " "manifest"
|
|
tar -vvtf "$FILE" >"${FILE%.t?z}.manifest" && printf "%s " "manifest extracted" || die "manifest extraction failed"
|
|
|
|
# ChangeLog.txt entry.
|
|
(( NO_CL == 0 )) && { gen_pkg_changelog "$FILE" && printf "%s" "changelog created" || die "changelog creation failed"; }
|
|
|
|
# Force update of top-level repository files.
|
|
FLAG_UPDATES=1
|
|
else
|
|
printf "\\033[1;32;40m%s\\033[0;39m\\n" "up to date"
|
|
FLAG_UPDATES=0
|
|
fi
|
|
done
|
|
|
|
# Formatting.
|
|
printf "\\033[0;39m\\n"
|
|
|
|
# Only update the top level files if there was a change in the repository or files don't exist.
|
|
(( FLAG_UPDATES == 1 )) || [[ ! -e "GPG-KEY" ]] || [[ ! -e "PACKAGES.TXT" ]] || [[ ! -e "FILELIST.TXT" ]] || [[ ! -e "MANIFEST.bz2" ]] || \
|
|
[[ ! -e "CHECKSUMS.md5" ]] && {
|
|
printf "\\033[1;33;40m %s\\n" "Generating:"
|
|
|
|
# Add the GPG signing key if required.
|
|
(( FORCE == 1 )) || [[ ! -e GPG-KEY ]] || [[ "$(gpg2 --with-colons <GPG-KEY 2>/dev/null | awk -F: -e '/^fpr/ { print $10; exit }')" != \
|
|
"$(gpg2 --with-colons --list-keys "$GPG_KEY" 2>/dev/null | awk -F: -e '/^fpr/ { print $10; exit }')" ]] && (( NO_SIGN == 0 )) && {
|
|
printf " %s\\n" "GPG-KEY"
|
|
gpg2 --list-keys "$GPG_KEY" >GPG-KEY && gpg2 --export --armor "$GPG_KEY" >>GPG-KEY || die "Failed to export GPG key"
|
|
}
|
|
|
|
# Pull all the ChangeLog parts together.
|
|
(( NO_CL == 0 )) && [[ -e ".ChangeLog.stub" ]] && {
|
|
printf " %s\\n" "ChangeLog.txt"
|
|
gen_changelog && mv .ChangeLog.staged ChangeLog.txt 2>/dev/null || die "Failed to generate ChangeLog.txt"
|
|
}
|
|
|
|
# Create the top-level PACKAGES.TXT.
|
|
printf "\\033[1;33;40m %s\\n" "PACKAGES.TXT"
|
|
gen_packages || die "Failed to generate PACKAGES.TXT"
|
|
|
|
# Generate MANIFEST.bz2.
|
|
printf " %s\\n" "MANIFEST.bz2"
|
|
gen_manifest || die "Failed to generate MANIFEST.bz2"
|
|
|
|
# Create stub files to be included in FILELIST.TXT.
|
|
: >CHECKSUMS.md5
|
|
(( NO_SIGN == 0 )) && : >CHECKSUMS.md5.asc
|
|
|
|
# Crate FILELIST.TXT.
|
|
printf " %s\\n" "FILELIST.TXT"
|
|
gen_filelist || die "Failed to generate FILELIST.TXT"
|
|
|
|
# Generate repository CHECKSUMS.md5.
|
|
printf " %s\\n" "CHECKSUMS.md5"
|
|
gen_checksums || die "Failed to generate CHECKSUMS.md5"
|
|
|
|
(( NO_SIGN == 0 )) && printf " %s:\\n" "Signing"
|
|
|
|
# Sign the checksums.
|
|
(( NO_SIGN == 0 )) && printf " %s\\n" "CHECKSUMS.md5"
|
|
(( NO_SIGN == 0 )) && { rm -f CHECKSUMS.md5.asc; sign_file "CHECKSUMS.md5" || die "Failed to sign CHECKSUMS.md5"; }
|
|
}
|
|
|
|
# Sanity check.
|
|
[[ ! -e "CHECKSUMS.md5" ]] || [[ ! -e "FILELIST.TXT" ]] || [[ ! -e "PACKAGES.TXT" ]] && \
|
|
printf "\\033[1;31;40m%s\\033[0;39m\\n" "Warning: files missing from repository - not Slackware compliant."
|
|
|
|
printf "\\033[1;32;40m%s: %s\\033[0;39m\\n" "Repository updated in" "$(runtime "$SECONDS")."
|
|
cd - >/dev/null 2>&1 || die "abort: $LINENO"
|
|
done
|