slpkg/tools/gen_repos_files.sh
2016-10-11 11:52:40 +03:00

916 lines
29 KiB
Bash

#!/bin/bash
# Copyright (c) 2006-2014 Eric Hameleers, Eindhoven, The Netherlands
# All rights reserved.
#
# Permission to use, copy, modify, and distribute this software for
# any purpose with or without fee is hereby granted, provided that
# the above copyright notice and this permission notice appear in all
# copies.
#
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
# ---------------------------------------------------------------------------
#
# Generate the PACKAGES.TXT FILELIST.TXT and CHECKSUMS.md5 files,
# needed by 3rd-party Slackware package management tools.
#
# Eric Hameleers <alien@slackware.com>
# ---------------------------------------------------------------------------
cat <<"EOT"
# -------------------------------------------------------------------#
# $Id: gen_repos_files.sh,v 1.92 2014/07/31 20:27:53 root Exp root $ #
# -------------------------------------------------------------------#
EOT
# The script's basename will be displayed in the RSS feed:
BASENAME=$( basename $0 )
# The script'""s revision number will be displayed in the RSS feed:
REV=$( echo "$Revision: 1.92 $" | cut -d' ' -f2 )
# The repository owner's defaults file;
# you can override any of the default values in this file:
USERDEFS=${USERDEFS:-~/.genreprc}
# ---------------------------------------------------------------------------
# Sane defaults:
# The directory of the Slackware package repository:
REPOSROOT=${REPOSROOT:-"/home/www/sox/slackware/slackbuilds/"}
# Repository maintainer
REPOSOWNER=${REPOSOWNER:-"Eric Hameleers <alien@slackware.com>"}
# The GPG key for the repository owner can contain a different string than
# the value of $REPOSOWNER . If you leave $REPOSOWNERGPG empty, the script will
# use the value you've set for $REPOSOWNER instead to search the GPG keyfile.
REPOSOWNERGPG=${REPOSOWNERGPG:-""}
# Under what URL is the repository accessible:
DL_URL=${DL_URL:-""}
# The title of the generated RSS feed:
RSS_TITLE=${RSS_TITLE:-"Alien's Slackware packages"}
# The logo picture used for the RSS feed:
RSS_ICON=${RSS_ICON:-"http://www.slackware.com/~alien/graphics/blueorb.png"}
# The URL linked to when clicking on the logo:
RSS_LINK=${RSS_LINK:-"http://www.slackware.com/~alien/"}
# URL to the full changelog.txt:
RSS_CLURL=${RSS_CLURL:-"http://www.slackware.com/~alien/slackbuilds/ChangeLog.txt"}
# The descriptive text for the RSS feed:
RSS_DESCRIPTION=${RSS_DESCRIPTION:-"Eric Hameleers (alien's) Slackware package repository. The package directories include the SlackBuild script and sources."}
# Maximum number of RSS feed entries to display:
RSS_FEEDMAX=${RSS_FEEDMAX:-15}
# The RSS generator must use a unique feed identifier.
# Generate one for your feed by using the string returned by "uuidgen -t":
RSS_UUID=${RSS_UUID:-""}
# Either use gpg or gpg2:
GPGBIN=${GPGBIN:-"/usr/bin/gpg"}
# Optionally use gpg-agent to cache the gpg passphrase instead of letting the
# script keep it in the environment (note that if you define USE_GPGAGENT=1
# but gpg-agent is not running, you will get prompted for a passphrase every
# single time gpg runs):
USE_GPGAGENT=${USE_GPGAGENT:-0}
# Generate slack-requires, slack-suggests, and slack-conflicts lines in the
# metadata files by setting FOR_SLAPTGET to "1" -- these are used by slapt-get
FOR_SLAPTGET=${FOR_SLAPTGET:-0}
# Follow symlinks in case the repository has symlinks like 14.0 -> 13.37
# indicating that one package works for those two Slackware releases.
# If the script does _not_ follow symlinks, then the symlinks will appear in
# the repository listing instead of the packages they point to.
FOLLOW_SYMLINKS=${FOLLOW_SYMLINKS:-1}
# If the repository has separate package subdirectories (for separate
# Slackware releases or architectures) then define them here.
# Separate FILELIST.TXT, MANIFEST etc.. files will be created for all of them:
REPO_SUBDIRS=${REPO_SUBDIRS:-""}
# If you want to exclude certain directories or files from being included
# in the repository metadata, define them here (space-separated).
# Example: REPO_EXCLUDES="RCS logs .genreprc"
REPO_EXCLUDES=${REPO_EXCLUDES:-""}
# ---------------------------------------------------------------------------
# By default, no debug messages
DEBUG=0
# Timestamp to be used all around the script:
UPDATEDATE="$(LC_ALL=C date -u)"
# A value of "yes" means that .meta .md5 and/or .asc files are
# always (re)generated.
# while "no" means: only generate these files if they are missing.
FORCEMD5="no" # .md5 files
FORCEPKG="no" # .meta files
FORCEASC="no" # .asc files
TOUCHUP="no" # rsync has issues with files whose content has changed, but
# both size and timestamp remain unchanged (needs expensive
# '--checksum' to detect these file changes)
# We may have a need to only update the ChangeLog files:
RSSONLY="no" # ChangeLog .rss and .txt
# For a sub-repository we do not have a ChangeLog:
CHANGELOG="yes"
# Variable used to limit the search for packages which lack .md5/.asc file,
# to those packages changed less than NOTOLDER days ago.
NOTOLDER=""
# Variable used to import the content of a text file as the new ChangeLog.txt
# entry. If empty, you will be asked to type a new entry yourself.
LOGINPUT=""
#
# --- no need to change anything below this line ----------------------------
#
# Import the repository owner's defaults
if [ -f $USERDEFS ]; then
echo "Importing user defaults."
. $USERDEFS
fi
# We prevent the mirror from running more than one instance:
PIDFILE=/var/tmp/$(basename $0 .sh).pid
# Make sure the PID file is removed when we kill the process
trap 'rm -f $PIDFILE; exit 1' TERM INT
# Determine the prune parameters for the 'find' commands:
PRUNES=""
if [ -n "$REPO_EXCLUDES" ]; then
echo "--- Excluding: $REPO_EXCLUDES"
for substr in $REPO_EXCLUDES ; do
PRUNES="${PRUNES} -o -name ${substr} -prune "
done
fi
# Command line parameter processing:
while getopts ":ahl:mn:prstv" Option
do
case $Option in
h ) echo "Parameters are:"
echo " -h : This help text"
echo " -a : Force generation of .asc gpg signature files"
echo " -l <log> : Use file <log> as input for ChangeLog.txt"
echo " -m : Force generation of .md5 files"
echo " -n <days> : Only look for packages not older than <days> days"
echo " -p : Force generation of package .meta files"
echo " -r : Update ChangeLog TXT and RSS files only"
echo " -s : Sub-repository: does not have ChangeLog TXT or RSS"
echo " -t : Timestamp of metafiles equal to package timestamp"
echo " -v : Verbose messages about packages found"
exit
;;
a ) FORCEASC="yes"
;;
l ) LOGINPUT="${OPTARG}"
;;
m ) FORCEMD5="yes"
;;
n ) NOTOLDER=${OPTARG}
;;
p ) FORCEPKG="yes"
;;
r ) RSSONLY="yes"
;;
s ) CHANGELOG="no"
;;
t ) TOUCHUP="yes"
;;
v ) DEBUG=1
;;
* ) echo "You passed an illegal switch to the program!"
echo "Run '$0 -h' for more help."
exit
;; # DEFAULT
esac
done
# End of option parsing.
shift $(($OPTIND - 1))
# $1 now references the first non option item supplied on the command line
# if one exists.
# ---------------------------------------------------------------------------
#
# --- HELPER FUNCTIONS ------------------------------------------------------
#
#
# pkgcomp
#
function pkgcomp {
# Return the compression utility used for this package,
# based on the package's extension.
# Determine extension:
PEXT="$( echo $1 | rev | cut -f 1 -d . | rev)"
# Determine compression used:
case $PEXT in
'tgz' )
COMP=gzip
;;
'tbz' )
COMP=bzip2
;;
'tlz' )
COMP=lzma
;;
'txz' )
COMP=xz
;;
esac
echo ${COMP:-"gzip"}
}
#
# addpkg
#
function addpkg {
# -----------------------------------------------
# Functionality used from the slapt-get FAQ#17 at
# http://software.jaos.org/BUILD/slapt-get/FAQ :
# -----------------------------------------------
# Generate a package's metafile if missing, and add the content of
# this metafile to the PACKAGES.TXT
# Argument #1 : full path to a package
# Argument #2 : full path to PACKAGES.TXT file/
if [ ! -f "$1" -o ! -f "$2" ]; then
echo "Required arguments '$1' and/or '$2' are invalid files!"
exit 1
fi
PKG=$1
PACKAGESFILE=$2
if [ "$(echo $PKG|grep -E '(.*{1,})\-(.*[\.\-].*[\.\-].*).t[blxg]z[ ]{0,}$')" == "" ];
then
return;
fi
NAME=$(echo $PKG|sed -re "s/(.*\/)(.*.t[blxg]z)$/\2/")
LOCATION=$(echo $PKG|sed -re "s/(.*)\/(.*.t[blxg]z)$/\1/")
METAFILE=${NAME%t[blxg]z}meta
TXTFILE=${NAME%t[blxg]z}txt
if [ "$FORCEPKG" == "yes" -o ! -f $LOCATION/$TXTFILE ]; then
# This is a courtesy service:
echo "--> Generating .txt file for $NAME"
$COMPEXE -cd $PKG | tar xOf - install/slack-desc | sed -n '/^#/d;/:/p' > $LOCATION/$TXTFILE
[ "$TOUCHUP" == "yes" ] && touch -r $PKG $LOCATION/$TXTFILE || touch -d "$UPDATEDATE" $LOCATION/$TXTFILE
fi
if [ "$FORCEPKG" == "yes" -o ! -f $LOCATION/$METAFILE ]; then
echo "--> Generating .meta file for $NAME"
# Determine the compression tool used for this package:
COMPEXE=$( pkgcomp $PKG )
SIZE=$(du -s $PKG | cut -f 1)
if [ "$COMPEXE" = "xz" ]; then
# xz does not support the "-l" switch yet:
cat $PKG | $COMPEXE -dc | dd 1> /dev/null 2> $HOME/.temp.uncomp.$$
USIZE="$(expr $(cat $HOME/.temp.uncomp.$$ | head -n 1 | cut -f1 -d+) / 2)"
rm -f $HOME/.temp.uncomp.$$
else
USIZE=$( expr $(gunzip -l $PKG |tail -1|awk '{print $2}') / 1024 )
fi
if [ $FOR_SLAPTGET -eq 1 ]; then
REQUIRED=$($COMPEXE -cd $PKG | tar xOf - install/slack-required 2>/dev/null|tr -d ' '|xargs -r -iZ echo -n "Z,"|sed -e "s/,$//")
CONFLICTS=$($COMPEXE -cd $PKG | tar xOf - install/slack-conflicts 2>/dev/null|tr -d ' '|xargs -r -iZ echo -n "Z,"|sed -e "s/,$//")
SUGGESTS=$($COMPEXE -cd $PKG | tar xOf - install/slack-suggests 2>/dev/null|xargs -r )
fi
echo "PACKAGE NAME: $NAME" > $LOCATION/$METAFILE
if [ -n "$DL_URL" ]; then
echo "PACKAGE MIRROR: $DL_URL" >> $LOCATION/$METAFILE
fi
echo "PACKAGE LOCATION: $LOCATION" >> $LOCATION/$METAFILE
echo "PACKAGE SIZE (compressed): $SIZE K" >> $LOCATION/$METAFILE
echo "PACKAGE SIZE (uncompressed): $USIZE K" >> $LOCATION/$METAFILE
if [ $FOR_SLAPTGET -eq 1 ]; then
echo "PACKAGE REQUIRED: $REQUIRED" >> $LOCATION/$METAFILE
echo "PACKAGE CONFLICTS: $CONFLICTS" >> $LOCATION/$METAFILE
echo "PACKAGE SUGGESTS: $SUGGESTS" >> $LOCATION/$METAFILE
fi
echo "PACKAGE DESCRIPTION:" >> $LOCATION/$METAFILE
if [ -f $LOCATION/$TXTFILE ]; then
cat $LOCATION/$TXTFILE >> $LOCATION/$METAFILE
else
$COMPEXE -cd $PKG | tar xOf - install/slack-desc | sed -n '/^#/d;/:/p' >> $LOCATION/$METAFILE
fi
echo "" >> $LOCATION/$METAFILE
[ "$TOUCHUP" == "yes" ] && touch -r $PKG $LOCATION/$METAFILE || touch -d "$UPDATEDATE" $LOCATION/$METAFILE
fi
# Package location may have changed:
sed -e "/^PACKAGE LOCATION: /s,^.*$,PACKAGE LOCATION: $LOCATION," $LOCATION/$METAFILE >> $PACKAGESFILE
} # end of function 'addpkg'
#
# addman
#
function addman {
# Add a package's content to the MANIFEST file
# Argument #1 : full path to a package
# Argument #2 : full path to MANIFEST file
if [ ! -f "$1" -o ! -f "$2" ]; then
echo "Required arguments '$1' and/or '$2' are invalid files!"
exit 1
fi
PKG=$1
MANIFESTFILE=$2
if [ "$(echo $PKG|grep -E '(.*{1,})\-(.*[\.\-].*[\.\-].*).t[blxg]z[ ]{0,}$')" == "" ];
then
return;
fi
NAME=$(echo $PKG|sed -re "s/(.*\/)(.*.t[blxg]z)$/\2/")
LOCATION=$(echo $PKG|sed -re "s/(.*)\/(.*.t[blxg]z)$/\1/")
LSTFILE=${NAME%t[blxg]z}lst
if [ "$FORCEPKG" == "yes" -o ! -f $LOCATION/$LSTFILE ]; then
echo "--> Generating .lst file for $NAME"
# Determine the compression tool used for this package:
COMPEXE=$( pkgcomp $PKG )
cat << EOF > $LOCATION/$LSTFILE
++========================================
||
|| Package: $PKG
||
++========================================
EOF
$COMPEXE -cd $PKG | tar -tvvf - >> $LOCATION/$LSTFILE
echo "" >> $LOCATION/$LSTFILE
echo "" >> $LOCATION/$LSTFILE
[ "$TOUCHUP" == "yes" ] && touch -r $PKG $LOCATION/$LSTFILE || touch -d "$UPDATEDATE" $LOCATION/$LSTFILE
fi
# Compensate for partial pathnames in .lst files found in sub-repos:
cat $LOCATION/$LSTFILE \
| sed -e "s%^|| Package: .*$%|| Package: $PKG%" \
>> $MANIFESTFILE
} # end of function 'addman'
#
# genmd5
#
function genmd5 {
# Generate a package's MD5SUM (*.md5 file) if missing,
# Argument #1 : full path to a package
if [ ! -f "$1" ]; then
echo "Required argument '$1' is an invalid file!"
exit 1
fi
PKG=$1
NAME=$(echo $PKG|sed -re "s/(.*\/)(.*.t[blxg]z)$/\2/")
LOCATION=$(echo $PKG|sed -re "s/(.*)\/(.*.t[blxg]z)$/\1/")
BASE=${NAME%.t[blxg]z}
MD5FILE=${NAME}.md5
if [ "$FORCEMD5" == "yes" -o ! -f $LOCATION/$MD5FILE ]; then
echo "--> Generating .md5 file for $NAME"
(cd $LOCATION
md5sum $NAME > $MD5FILE
)
[ "$TOUCHUP" == "yes" ] && touch -r $PKG $LOCATION/$MD5FILE || touch -d "$UPDATEDATE" $LOCATION/$MD5FILE
fi
} # end of function 'genmd5'
#
# genasc
#
function genasc {
# Generate a package's GPG signature (*.asc file) if missing,
# Argument #1 : full path to a package
if [ ! -f "$1" ]; then
echo "Required argument '$1' is invalid filename!"
exit 1
fi
PKG=$1
NAME=$(echo $PKG|sed -re "s/(.*\/)(.*.t[blxg]z)$/\2/")
LOCATION=$(echo $PKG|sed -re "s/(.*)\/(.*.t[blxg]z)$/\1/")
ASCFILE=${NAME}.asc
if [ "$FORCEASC" == "yes" -o ! -f $LOCATION/$ASCFILE ]; then
echo "--> Generating .asc file for $NAME"
(cd $LOCATION
rm -f $ASCFILE
gpg_sign $NAME
)
[ "$TOUCHUP" == "yes" ] && touch -r $PKG $LOCATION/$ASCFILE || touch -d "$UPDATEDATE" $LOCATION/$ASCFILE
fi
} # end of function 'genasc'
#
# gen_filelist
#
function gen_filelist {
# Argument #1 : full path to a directory
# Argument #2 : output filename (defaults to FILELIST.TXT) will be
# created in directory $1 (overwriting existing file).
if [ ! -d "$1" ]; then
echo "Required argument '$1' must be a directory!"
exit 1
fi
DIR=$1
LISTFILE=${2:-FILELIST.TXT}
( cd ${DIR}
cat <<EOT > ${LISTFILE}
$UPDATEDATE
Here is the file list for ${DL_URL:-this directory} ,
maintained by ${REPOSOWNER} .
If you are using a mirror site and find missing or extra files
in the subdirectories, please have the archive administrator
refresh the mirror.
EOT
if [ $FOLLOW_SYMLINKS -eq 1 ]; then
find -L . -print $PRUNES | sort | xargs ls -nld --time-style=long-iso >> ${LISTFILE}
else
find . -print $PRUNES | sort | xargs ls -nld --time-style=long-iso >> ${LISTFILE}
fi
)
} # end of function 'gen_filelist'
#
# upd_changelog
#
function upd_changelog {
# Update the ChangeLog.txt with a new entry
# - written at the beginning of the file.
# Argument #1 : full path to a directory
# Argument #2 : a filename (defaults to 'ChangeLog.txt')
if [ ! -d "$1" ]; then
echo "Required argument '$1' must be an existing directory!"
exit 1
fi
local DIR=$1
local CHANGELOG=${2:-ChangeLog.txt}
if [ -e $DIR/$CHANGELOG -a ! -w $DIR/$CHANGELOG ]; then
echo "Can not write to file ${DIR}/${CHANGELOG}!"
exit 1
fi
local MAXLINE=78 # Lines will be wrapped at MAXLINE characters.
local LOGTEXT=""
local i=0
if [ "$LOGINPUT" == "" ]; then
# Ask for a new ChangeLog entry
read -er -p "Enter ChangeLog.txt description: "
else
REPLY=$(cat "$LOGINPUT" 2>/dev/null)
fi
if [ "$REPLY" == "" ]; then
echo "No input, so I won't update your $CHANGELOG"
return
fi
LOGTXT=""
for WORD in $REPLY ; do
# The word 'NEWLINE' forces a... newline in the output.
# The word 'LINEFEED' also signals the start of a new line, but indented.
if [ "${WORD}" == "NEWLINE" ]; then
LOGLINE[$i]="$LOGTXT"
LOGTXT=""
i=$(( $i+1 ))
elif [ "${WORD}" == "LINEFEED" ]; then
LOGLINE[$i]="$LOGTXT"
LOGTXT=" "
i=$(( $i+1 ))
elif [ $(( ${#LOGTXT}+1+${#WORD} )) -gt $MAXLINE ]; then
LOGLINE[$i]="$LOGTXT"
LOGTXT=" ${WORD}" # indent the text two spaces.
i=$(( $i+1 ))
else
[ "$LOGTXT" != "" ] && LOGTXT="${LOGTXT} ${WORD}" || LOGTXT="${WORD}"
fi
done
LOGLINE[$i]="$LOGTXT"
cat <<-EOT > ${DIR}/.${CHANGELOG}
+--------------------------+
$UPDATEDATE
EOT
for IND in $(seq 0 $i); do
echo "${LOGLINE[$IND]}" >> ${DIR}/.${CHANGELOG}
done
echo "" >> ${DIR}/.${CHANGELOG}
if [ -f "${DIR}/${CHANGELOG}" ]; then
cat ${DIR}/${CHANGELOG} >> ${DIR}/.${CHANGELOG}
fi
mv -f ${DIR}/.${CHANGELOG} ${DIR}/${CHANGELOG}
}
#
# gpg_sign
#
function gpg_sign {
# Create a gpg signature for a file. Use either gpg or gpg2 and optionally
# let gpg-agent provide the passphrase.
if [ $USE_GPGAGENT -eq 1 ]; then
$GPGBIN --use-agent -bas -u "$REPOSOWNERGPG" --batch --quiet $1
else
echo $TRASK | $GPGBIN -bas -u "$REPOSOWNERGPG" --passphrase-fd 0 --batch --quiet $1
fi
return $?
}
#
# rss_changelog
#
function rss_changelog {
# Create a RSS feed out of the ChangeLog.txt
# Argument #1 : full path to a directory
# Argument #2 : a filename (defaults to 'ChangeLog.txt')
# Argument #2 : a filename (defaults to 'ChangeLog.rss')
if [ ! -d "$1" ]; then
echo "Required argument '$1' must be an existing directory!"
exit 1
fi
DIR=$1
INFILE=${DIR}/${2:-ChangeLog.txt}
RSSFILE=${DIR}/${3:-ChangeLog.rss}
if [ -e $RSSFILE -a ! -w $RSSFILE ]; then
echo "Can not write to RSS file ${RSSFILE}!"
exit 1
fi
# These values are all set in the beginning (can be user-overridden):
TITLE="$RSS_TITLE"
LINK="$RSS_LINK"
ICON="$RSS_ICON"
CLURL="$RSS_CLURL"
DESCRIPTION="$RSS_DESCRIPTION"
FEEDMAX=$RSS_FEEDMAX
UUID="$RSS_UUID"
PUBDATE=""
LASTBUILDDATE=$(LC_ALL=C TZ=GMT date +"%a, %e %b %Y %H:%M:%S GMT")
# The 'date -R' RFC-2822 compliant string
# does not work for Thunderbird!
counter=0
# Parse the input file
cat ${INFILE} | while IFS= read cline ; do
if [ "$PUBDATE" == "" ]; then
# PUBDATE is empty, means we're reading the first line of input.
# The first line contains the most recent pubdate.
# For backward compatibility, if the file starts with
# "+--------------------------+" then we just skip that.
[ "$cline" == "+--------------------------+" ] && read cline
PUBDATE=$(LC_ALL=C TZ=GMT date +"%a, %e %b %Y %H:%M:%S GMT" -d "$cline")
cat <<-_EOT_ > ${RSSFILE}
<?xml version="1.0" encoding="iso-8859-1"?>
<rss version="2.0">
<channel>
<title>${TITLE}</title>
<link>${LINK}</link>
<image>
<title>${TITLE}</title>
<url>${ICON}</url>
<link>${LINK}</link>
</image>
<description>${DESCRIPTION}</description>
<language>en-us</language>
<id xmlns="http://www.w3.org/2005/Atom">urn:uuid:${UUID}</id>
<pubDate>${PUBDATE}</pubDate>
<lastBuildDate>${LASTBUILDDATE}</lastBuildDate>
<generator>${BASENAME} v ${REV}</generator>
<item>
<title>${PUBDATE}</title>
<link>${CLURL}</link>
<pubDate>${PUBDATE}</pubDate>
<guid isPermaLink="false">$(LC_ALL=C date -d "${PUBDATE}" +%Y%m%d%H%M%S)</guid>
<description>
<![CDATA[<pre>
_EOT_
elif [ "$cline" == "+--------------------------+" ]; then
# This line masrks the start of a new entry.
# Only dump a certain amount of recent entries.
[ $counter -gt $FEEDMAX ] && break
# Close the previous entry:
cat <<-_EOT_ >> ${RSSFILE}
</pre>]]>
</description>
</item>
_EOT_
# Next line is the pubdate for the next entry:
read PUBDATE
PUBDATE=$(LC_ALL=C TZ=GMT date +"%a, %e %b %Y %H:%M:%S GMT" -d "$PUBDATE")
# Write the header for the next entry:
cat <<-_EOT_ >> ${RSSFILE}
<item>
<title>${PUBDATE}</title>
<link>${CLURL}</link>
<pubDate>${PUBDATE}</pubDate>
<guid isPermaLink="false">$(LC_ALL=C date -d "${PUBDATE}" +%Y%m%d%H%M%S)</guid>
<description>
<![CDATA[<pre>
_EOT_
counter=$(( ${counter}+1 ))
else
# Add a line of description
[ "${cline}" != "" ] && echo "${cline}" >> ${RSSFILE}
fi
done
# Close the last entry:
cat <<-_EOT_ >> ${RSSFILE}
</pre>]]>
</description>
</item>
_EOT_
# Close the XML output:
cat <<-_EOT_ >> ${RSSFILE}
</channel>
</rss>
_EOT_
}
#
# run_repo
#
run_repo() {
# Run through a repository tree, generating the repo meta files.
# Change directory to the root of the repository, so all generated
# information is relative to here:
local RDIR=$1
cd $RDIR
# Create temporary MANIFEST and PACKAGES.TXT files:
cat /dev/null > .MANIFEST
cat /dev/null > .PACKAGES.TXT
# This tries to look for filenames with the Slackware package name format:
if [ $FOLLOW_SYMLINKS -eq 1 ]; then
PKGS=$( find -L . -type f -name '*-*-*-*.t[blxg]z' -print $PRUNES | sort )
else
PKGS=$( find . -type f -name '*-*-*-*.t[blxg]z' -print $PRUNES | sort )
fi
for pkg in $PKGS; do
# Found a filename with matching format, is it really a slackpack?
COMPEXE=$( pkgcomp $pkg )
if $COMPEXE -cd $pkg | tar tOf - install/slack-desc 1>/dev/null 2>&1 ; then
[ $DEBUG -eq 1 ] && echo "+++ Found package $pkg"
# We need to run addpkg for every package, to populate PACKAGES.TXT:
addpkg $pkg ${RDIR}/.PACKAGES.TXT
# We need to run addman for every package, to populate MANIFEST
addman $pkg ${RDIR}/.MANIFEST
if [ "x$NOTOLDER" != "x" ]; then
# When to generate md5sum/gpg signature if we have a $NOTOLDER value:
# 'date +%s' gives the current time in seconds since the Epoch;
# 'stat -c %Z $pkg' gives the ctime of $pkg file in seconds since Epoch;
# The difference of these two divided by 3600 is the file age in hours.
# '24 * $NOTOLDER' gives the maximum allowed age of the file in hours.
# If the package is too old, we do not try to create md5sum/gpg sig.
if [ $(( ( $(LC_ALL=C date +%s) - $(stat -c %Z $pkg) ) / 3600 )) -lt $(( 24 * $NOTOLDER )) ]; then
[ "$USEGPG" == "yes" ] && genasc $pkg
genmd5 $pkg
else
[ $DEBUG -eq 1 ] && echo " - Skipping md5/gpg calculation for $(basename $pkg)"
fi
else
[ "$USEGPG" == "yes" ] && genasc $pkg
genmd5 $pkg
fi
else
echo "*** Warning: $pkg does not contain a slack-desc file. ***"
fi
done
# Make the changes visible:
echo "PACKAGES.TXT; $UPDATEDATE" > PACKAGES.TXT
echo "" >> PACKAGES.TXT
if [ -n "$DL_URL" ]; then
cat .PACKAGES.TXT >> PACKAGES.TXT
else
cat .PACKAGES.TXT | grep -v "PACKAGE MIRROR: " >> PACKAGES.TXT
fi
rm -f .PACKAGES.TXT
cat .MANIFEST > MANIFEST
rm -f .MANIFEST
bzip2 -9f MANIFEST
gzip -9cf PACKAGES.TXT > PACKAGES.TXT.gz
if [ "${CHANGELOG}" == "yes" -a -f ChangeLog.txt ]; then
gzip -9cf ChangeLog.txt > ChangeLog.txt.gz
fi
} # End run_repo()
#
# gen_checksums
#
gen_checksums() {
# Run through a repository tree, generating the checksum files.
# Change directory to the root of the repository, so all generated
# information is relative to here:
local RDIR=$1
cd $RDIR
# Create temporary CHECKSUMS.md5 file:
cat /dev/null > .CHECKSUMS.md5
# Generate the overall CHECKSUMS.md5 for this (sub-)repo:
cat << EOF > .CHECKSUMS.md5
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 --check | 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 [ $FOLLOW_SYMLINKS -eq 1 ]; then
find -L . -type f -print $PRUNES | grep -v CHECKSUMS | sort | xargs md5sum $1 2>/dev/null >> .CHECKSUMS.md5
else
find . -type f -print $PRUNES | grep -v CHECKSUMS | sort | xargs md5sum $1 2>/dev/null >> .CHECKSUMS.md5
fi
cat .CHECKSUMS.md5 > CHECKSUMS.md5
gzip -9cf CHECKSUMS.md5 > CHECKSUMS.md5.gz
rm -f .CHECKSUMS.md5 CHECKSUMS.md5.asc CHECKSUMS.md5.gz.asc
if [ "$USEGPG" == "yes" ]; then
# The CHECKSUMS.md5* files need a gpg signature:
gpg_sign CHECKSUMS.md5
gpg_sign CHECKSUMS.md5.gz
fi
} # End gen_checksums()
#
# --- MAIN ------------------------------------------------------------------
#
# Abort if we need to create the RSS file and RSS_UUID is empty:
if [ -z "${RSS_UUID}" -a "${CHANGELOG}" = "yes" ]; then
echo "**"
echo "** Please supply a value for the Universally Unique IDentifier (UUID) !"
echo "** Look for the RSS_UUID variable inside the script or in '$USERDEFS',"
echo "** and (for instance) use the return value from command 'uuidgen -t'."
echo "**"
exit 1
fi
echo "--- Generating repository metadata for $REPOSROOT ---"
echo "--- Repository owner is $REPOSOWNER ---"
echo ""
# If the GPG key contains a different identification string than the name
# you want to use for the repository owner, set the REPOSOWNERGPG variable.
# If $REPOSOWNERGPG has an empty value we will use the value of $REPOSOWNER
# to search the GPG keyring.
if [ "x${REPOSOWNERGPG}" == "x" ]; then
REPOSOWNERGPG="${REPOSOWNER}"
fi
# We will test correctness of the GPG passphrase against a temp file:
TESTTMP=$(mktemp)
if [ "${CHANGELOG}" == "yes" ]; then
# Update ChangeLog.txt with a new entry
upd_changelog $REPOSROOT
# Write a RSS file for the ChangeLog.txt
rss_changelog $REPOSROOT
fi
# If we only want to update the ChangeLog files, then we skip a lot:
if [ "$RSSONLY" = "yes" ]; then
echo "--- Exiting after re-generation of ChangeLog files (requested). ---"
echo ""
else
# Only generate GPG signatures if we have a GPG key
if ! $GPGBIN --list-secret-keys "$REPOSOWNERGPG" >/dev/null 2>&1 ; then
USEGPG="no"
echo "The GPG private key for \"$REPOSOWNERGPG\" wasn't found!"
echo "*** packages will not be signed! ***"
read -er -p "Continue? [y|N] "
[ "${REPLY:0:1}" = "y" -o "${REPLY:0:1}" = "Y" ] || exit 1
else
USEGPG="yes"
if [ $USE_GPGAGENT -eq 0 ]; then
read -ers -p "Enter your GPG passphrase: "
TRASK=$REPLY
echo "."
if [ "$REPLY" == "" ]; then
echo "Empty GPG passphrase - disabling generation of signatures."
USEGPG="no"
fi
fi
fi
if [ "$USEGPG" == "yes" ]; then
gpg_sign $TESTTMP 2>/dev/null
if [ $? -ne 0 ]; then
echo "GPG test failed, incorrect GPG passphrase? Aborting the script."
rm -f $TESTTMP
exit 1
else
if [ ! -r ${REPOSROOT}/GPG-KEY ]; then
echo "Generating a "GPG-KEY" file in '$REPOSROOT',"
echo " containing the public key information for '$REPOSOWNERGPG'..."
$GPGBIN --list-keys "$REPOSOWNERGPG" > ${REPOSROOT}/GPG-KEY
$GPGBIN -a --export "$REPOSOWNERGPG" >> ${REPOSROOT}/GPG-KEY
chmod 444 ${REPOSROOT}/GPG-KEY
fi
if [ -n "$REPO_SUBDIRS" ]; then
for SUBDIR in $REPO_SUBDIRS ; do
if [ ! -r ${REPOSROOT}/${SUBDIR}/GPG-KEY ]; then
echo "Generating a "GPG-KEY" file in '$REPOSROOT/$SUBDIR',"
echo " containing the public key information for '$REPOSOWNERGPG'."
$GPGBIN --list-keys "$REPOSOWNERGPG" > $REPOSROOT/$SUBDIR/GPG-KEY
$GPGBIN -a --export "$REPOSOWNERGPG" >> $REPOSROOT/$SUBDIR/GPG-KEY
chmod 444 ${REPOSROOT}/${SUBDIR}/GPG-KEY
fi
done
fi
fi
fi
# Run through the repository, generating the MANIFEST etc:
if [ -n "$REPO_SUBDIRS" ]; then
echo "--- Populating repo subdirectories '${REPO_SUBDIRS}' ---"
for SUBDIR in $REPO_SUBDIRS ; do
run_repo $REPOSROOT/$SUBDIR
gen_filelist ${REPOSROOT}/$SUBDIR
gen_checksums ${REPOSROOT}/$SUBDIR
done
fi
run_repo $REPOSROOT
fi # end !RSSONLY
# Finally, generate the FILELIST.TXT and CHECKSUMS.md5* for the whole repo:
gen_filelist ${REPOSROOT}
gen_checksums ${REPOSROOT}
# Clean up:
TRASK=""
rm -f ${TESTTMP}*
# Done.