#!/bin/bash PROGNAME=$(basename $0) # $HeadURL$ $LastChangedRevision$ set -e # # Global variables # CURRENT_EXT="current" RCDIR=$HOME/.$PROGNAME DBFILE=$RCDIR/$PROGNAME.sqlite TMP_DIR=/tmp SQLITE_CMD=sqlite3 REPONAME_FMTSTR="%-22.22s" LONGOK_FMTSTR="%-10.10s" DATE_FMTSTR="%-30.30s" HOSTNAME_FMTSTR="%-10.10s" LOCALFLAG_FMTSTR="%-5.5s" ARCHS_FMTSTR="%-15.15s" DISTS_FMTSTR="%-15.15s" SECTIONS_FMTSTR="%-25.25s" FREEZE_FMTSTR="%-8.8s" AVAIL_FMTSTR="%-32.32s" INTEGRITY_FMTSTR="%-35.35s" UNDERLINE="-----------------------------------------------" main() { # # Option defaults # VERBOSELEVEL=2 # # Option processing # while [ "X$1" != X ]; do case $1 in -v|--verbose) VERBOSELEVEL=3 ;; -d) VERBOSELEVEL=$2; shift ;; --debug=*) VERBOSELEVEL=${1#*=} ;; --rcdir=*) RCDIR=${1#*=} ;; -h|--help) usage 0 ;; # Any other option is handled within each individual function *) break ;; esac shift done # # Argument processing # debug 10 "main: argument processing" [ "X$1" != X ] || usage # better arg checking done on per-opmode basis OPMODE=$1 shift # # Sanity checks and derivations # debug 10 "main: sanity checks and derivations ..." case $OPMODE in initialise|upstream|create|insert|control|mirror|freeze|listrepos|listmirrors|listfreezes|listavails|avail|unavail|apache|unapache|listapaches|apt|unapt) : ;; *) usage ;; esac # # Guts start here # debug 10 "main: calling $OPMODE() ..." # Very important to set a sensible umask umask 022 $OPMODE "$@" } usage() { local RC RC=${1:-1} { echo "Usage: $PROGNAME [ ] initialise" echo " $PROGNAME [ ] upstream " echo " $PROGNAME [ ] create " echo " $PROGNAME [ ] listrepos" echo " $PROGNAME [ ] insert [ --section=
] [ --dists=[,...] ] ..." echo " $PROGNAME [ ] control " echo " $PROGNAME [ ] mirror { --all-repos | }" echo " $PROGNAME [ ] listmirrors" echo " $PROGNAME [ ] freeze { --all-repos | }" echo " $PROGNAME [ ] listfreezes" echo " $PROGNAME [ ] avail { --all-hosts | }" echo " $PROGNAME [ ] unavail " echo " $PROGNAME [ ] listavails" echo " $PROGNAME [ ] apache " echo " $PROGNAME [ ] unapache " echo " $PROGNAME [ ] listapaches" echo " $PROGNAME [ ] apt " echo " $PROGNAME [ ] unapt " echo echo "Options: -v | --verbose be verbose" echo " -d | --debug= be very verbose" echo " -h | --help show this text" echo " --rcdir= change rc directory (default: $RCDIR)" } | if [ $RC == 0 ]; then cat else cat >&2 fi exit $RC } initialise() { # Defaults for directive-specific options # Process directive-specific options while [ "X$1" != X ]; do case $1 in --) shift; break ;; -*) usage ;; *) break ;; esac shift done # Process directive-specific arguments [ $# = 0 ] || usage # Sanity checks and derivations [ ! -f $RCDIR/general ] || error "it looks like you've already run in initialise mode" # Guts info "initialising ..." mkdir -p $RCDIR { echo "# This file was generated automatically on $(date)" echo echo "# The following settings need to be adjusted but" echo "# paa will complain if they're needed but not set" echo "# so you might not need to worry about them now." echo "#PAACRT_ROOT=/pub/paacrt" echo "#PAACRT_URL=http://paacrt.pasta.net/paacrt/" echo "#APACHE_CFG_MDI_DIR=/etc/apache2/mdi.d" echo } > $RCDIR/general # Create SQL table with silent ignoring of duplicates (remember that the 'cpu' # column is just a cache of info we could find out anyway so it is not included # in the UNIQUE clause). $SQLITE_CMD $DBFILE "CREATE TABLE debs (timestamp INTEGER, path TEXT, package TEXT, repo TEXT, dist TEXT, section TEXT, cpu TEXT, UNIQUE (path, package, repo, dist) ON CONFLICT REPLACE);" } create() { local SECTION SECTIONS CPU CPUS DIST DISTS DATE # Defaults for directive-specific options # Process directive-specific options while [ "X$1" != X ]; do debug 10 "create: processing option $1 ..." case $1 in --) shift; break ;; -*) usage ;; *) break ;; esac shift done # Process directive-specific arguments debug 10 "create: arguments are: $*" [ $# = 3 ] || usage REPONAME=$1 REPODIR=$2 MIRRORDIR=$3 # Sanity checks and derivations [ -d $RCDIR ] || error "$RCDIR: no such directory (did you run '$PROGNAME initialise'?)" ORIGIN="$(getent passwd $LOGNAME | cut -f5 -d: | cut -f1 -d,)" LABEL="$ORIGIN" SIGNER=$LOGNAME [ ! -f $RCDIR/$REPONAME -a ! -e $REPODIR ] || error "$REPONAME: repository exists already" # Guts info "creating $REPONAME ..." mkdir -p $REPODIR/{pool,dists} DATE=$(date) { echo "# This file was generated automatically on $DATE" echo echo "# The following settings need to be adjusted." echo "#ALL_SECTIONS=main" echo "#DFLT_SECTION=main" echo "#ALL_DISTS=\"lenny squeeze\"" echo "#DFLT_DISTS=lenny" echo "#ALL_CPUS=i386" echo echo "# The following settings should not need to be adjusted." echo "REPOLOCAL=\"true\"" echo "REPODIR=\"$REPODIR\"" echo "MIRRORDIR=\"$MIRRORDIR\"" echo "ORIGIN=\"$ORIGIN\"" echo "LABEL=\"$LABEL\"" echo "SIGNER=\"$SIGNER\"" echo "MIRRORER=\"rsync -a --delete \\\"\\\$1/\\\" \\\"\\\$2/\\\"\"" echo "DATE_CREATED=\"$DATE\"" } > $RCDIR/$REPONAME } insert() { local SECTION CPU DIST DISTS TIMSTAMP # Defaults for directive-specific options TAKE_DFLT_SECTION_FROM_RC=true TAKE_DFLT_DISTS_FROM_RC=true DFLT_SECTION= DFLT_DISTS= # Process directive-specific options while [ "X$1" != X ]; do debug 10 "insert: processing option $1 ..." case $1 in --section=*) DFLT_SECTION=${1#*=} TAKE_DFLT_SECTION_FROM_RC=false ;; --dists=*) DFLT_DISTS=${1#*=} TAKE_DFLT_DISTS_FROM_RC=false ;; --) shift; break ;; -*) usage ;; *) break ;; esac shift done debug 10 "insert: REPOS=\"$REPOS\", DFLT_SECTION=$DFLT_SECTION, DFLT_DISTS=\"$DFLT_DISTS\", TAKE_DFLT_SECTION_FROM_RC=$TAKE_DFLT_SECTION_FROM_RC, TAKE_DFLT_DISTS_FROM_RC=$TAKE_DFLT_DISTS_FROM_RC" # Process arguments [ $# -ge 2 ] || usage REPONAME=$1; shift DEBS="$@" # Sanity checks and derivations assign_var_from_rc_file $RCDIR/$REPONAME REPOLOCAL $REPOLOCAL || error "$REPONAME: not a local repo" assign_var_from_rc_file $RCDIR/$REPONAME REPODIR ! $TAKE_DFLT_SECTION_FROM_RC || assign_var_from_rc_file $RCDIR/$REPONAME DFLT_SECTION ! $TAKE_DFLT_DISTS_FROM_RC || assign_var_from_rc_file $RCDIR/$REPONAME DFLT_DISTS DFLT_DISTS=${DFLT_DISTS//,/ } [ "X$DFLT_SECTION" != X ] || error "DFLT_SECTION: undefined (do you need to use '--section' or define DFLT_SECTION in $RCDIR/$REPONAME?)" [ "X$DFLT_DISTS" != X ] || error "DFLT_DISTS: undefined (do you need to use '--dists' or define DFLT_DISTS in $RCDIR/$REPONAME?)" for DEB in $DEBS; do [ -f $DEB -a -r $DEB ] || error "$DEB: not accessible" done # Guts # Put debs in pool TIMESTAMP=$(date +%s) for DEB in $DEBS; do info "inserting $DEB in $REPONAME ..." cp $DEB $REPODIR/pool/ chmod 644 $REPODIR/pool/$(basename $DEB) PACKAGE=$(dpkg-deb -I $DEB | sed -n 's/^ Package: //p') CPU=$(dpkg-deb -I $DEB | sed -n 's/^ Architecture: //p') # Record the dist, section and CPU in the database for DFLT_DIST in $DFLT_DISTS; do debug 10 "insert: about to run SQL command [INSERT INTO debs (timestamp, path, package, repo, dist, section, cpu) VALUES ($TIMESTAMP, \"pool/$(basename $DEB)\", \"$PACKAGE\", \"$REPONAME\", \"$DFLT_DIST\", \"$DFLT_SECTION\", \"$CPU\");] ..." $SQLITE_CMD $DBFILE "INSERT INTO debs (timestamp, path, package, repo, dist, section, cpu) VALUES ($TIMESTAMP, \"pool/$(basename $DEB)\", \"$PACKAGE\", \"$REPONAME\", \"$DFLT_DIST\", \"$DFLT_SECTION\", \"$CPU\");" done done # section and dists were specified above but we don't know what CPUs to do. Do them all. assign_var_from_rc_file $RCDIR/$REPONAME ALL_CPUS control --sections=$DFLT_SECTION --dists=${DFLT_DISTS// /,} --cpus=${ALL_CPUS// /,} $REPONAME } control() { local SECTION CPU DIST DISTS VERSION # Defaults for directive-specific options TAKE_ALL_SECTIONS_FROM_RC=true TAKE_ALL_DISTS_FROM_RC=true TAKE_ALL_CPUS_FROM_RC=true ALL_SECTIONS= ALL_DISTS= ALL_CPUS= # Process directive-specific options while [ "X$1" != X ]; do debug 10 "control: processing option $1 ..." case $1 in --sections=*) ALL_SECTIONS=${1#*=} TAKE_ALL_SECTIONS_FROM_RC=false ;; --dists=*) ALL_DISTS=${1#*=} TAKE_ALL_DISTS_FROM_RC=false ;; --cpus=*) ALL_CPUS=${1#*=} TAKE_ALL_CPUS_FROM_RC=false ;; --) shift; break ;; -*) usage ;; *) break ;; esac shift done debug 10 "control: ALL_SECTIONS=\"$ALL_SECTIONS\", ALL_CPUS=\"$ALL_CPUS\", ALL_DISTS=\"$ALL_DISTS\", TAKE_ALL_SECTIONS_FROM_RC=$TAKE_ALL_SECTIONS_FROM_RC, TAKE_ALL_DISTS_FROM_RC=$TAKE_ALL_DISTS_FROM_RC, TAKE_ALL_CPUS_FROM_RC=$TAKE_ALL_CPUS_FROM_RC" # Process arguments [ $# = 1 ] || usage REPONAME=$1 # Sanity checks and derivations assign_var_from_rc_file $RCDIR/$REPONAME REPOLOCAL $REPOLOCAL || error "$REPONAME: not a local repo" assign_var_from_rc_file $RCDIR/$REPONAME REPODIR assign_var_from_rc_file $RCDIR/$REPONAME LABEL assign_var_from_rc_file $RCDIR/$REPONAME ORIGIN ! $TAKE_ALL_SECTIONS_FROM_RC || assign_var_from_rc_file $RCDIR/$REPONAME ALL_SECTIONS ! $TAKE_ALL_DISTS_FROM_RC || assign_var_from_rc_file $RCDIR/$REPONAME ALL_DISTS ! $TAKE_ALL_CPUS_FROM_RC || assign_var_from_rc_file $RCDIR/$REPONAME ALL_CPUS ALL_DISTS=${ALL_DISTS//,/ } ALL_SECTIONS=${ALL_SECTIONS//,/ } ALL_CPUS=${ALL_CPUS//,/ } [ "X$ALL_SECTIONS" != X ] || error "ALL_SECTIONS: undefined (do you need to use '--sections' or define ALL_SECTIONS in $RCDIR/$REPONAME?" [ "X$ALL_DISTS" != X ] || error "ALL_DISTS: undefined (do you need to use '--dists' or define ALL_DISTS in $RCDIR/$REPONAME?" [ "X$ALL_CPUS" != X ] || error "ALL_CPUS: undefined (do you need to use '--cpus' or define DFLT_CPUS in $RCDIR/$REPONAME?" [ "X$GPG_AGENT_INFO" != X ] || error "gpg-agent: not running (do you need to run 'eval \`gpg-agent --daemon\`'?)" # Guts info "regenerating control files ..." for EACH_DIST in $ALL_DISTS; do for EACH_CPU in $ALL_CPUS; do for EACH_SECTION in $ALL_SECTIONS; do info "regenerating Packages and Packages.gz for ($REPONAME, $EACH_DIST, $EACH_CPU, $EACH_SECTION) ..." mkdir -p $REPODIR/dists/$EACH_DIST/$EACH_SECTION/binary-$EACH_CPU SYMLINKED_POOL_DIR=$TMP_DIR/$PROGNAME.$$.repo=$REPONAME,dist=$EACH_DIST,cpu=$EACH_CPU,section=$EACH_SECTION mkdir -p $SYMLINKED_POOL_DIR debug 10 "control: generating symlinks in $SYMLINKED_POOL_DIR and overrides file $SYMLINKED_POOL_DIR/overrides ..." # Without column width, file and package names are shortened which makes symlink names not unique and # not even correspond to valid symlink targets. We select *only* the most recently inserted entry deb # (there is no SQL-ish way to find the package with highesr version number, so we use the timestamp # at which it was inserted.) Note that the conditions of the sub-query match the conditions of the main # query *except* for the pathname; this is because we want the subquery to return the *newest* of the # packages which match the main query's selection conditions. echo -e ".width 100 100\nSELECT path, package FROM debs AS debs1 WHERE debs1.repo == \"$REPONAME\" AND debs1.dist == \"$EACH_DIST\" AND (cpu == \"$EACH_CPU\" OR cpu == \"all\") AND debs1.section == \"$EACH_SECTION\" AND debs1.timestamp == (SELECT MAX(debs2.timestamp) FROM debs AS debs2 WHERE debs1.package == debs2.package AND debs1.repo ==debs2.repo AND debs1.dist == debs2.dist);" | $SQLITE_CMD -column $DBFILE | while read PATHNAME PACKAGENAME; do debug 10 "control: generating override entry for $PATHNAME ..." # Files which have been removed from the filesystem but for which the row in the table has not been removed # should be ignored. [ -f $REPODIR/$PATHNAME ] || continue # Create leading directories mkdir -p $SYMLINKED_POOL_DIR/$(dirname $PATHNAME) ln -s $REPODIR/$PATHNAME $SYMLINKED_POOL_DIR/$PATHNAME echo "$PACKAGENAME optional $EACH_SECTION" done > $SYMLINKED_POOL_DIR/overrides COUNT=$(wc -l < $SYMLINKED_POOL_DIR/overrides) debug 10 "control: running dpkg-scanpackages onto $REPODIR/dists/$EACH_DIST/$EACH_SECTION/binary-$EACH_CPU/Packages ..." mkdir -p $REPODIR/dists/$EACH_DIST/$EACH_SECTION/binary-$EACH_CPU DPKGSCANPACKAGES_STDERR=`( cd $SYMLINKED_POOL_DIR && dpkg-scanpackages -m . overrides ) 2>&1 1> $REPODIR/dists/$EACH_DIST/$EACH_SECTION/binary-$EACH_CPU/Packages` rm -fr $SYMLINKED_POOL_DIR chmod a+r $REPODIR/dists/$EACH_DIST/$EACH_SECTION/binary-$EACH_CPU/Packages gzip -c $REPODIR/dists/$EACH_DIST/$EACH_SECTION/binary-$EACH_CPU/Packages > $REPODIR/dists/$EACH_DIST/$EACH_SECTION/binary-$EACH_CPU/Packages.gz chmod a+r $REPODIR/dists/$EACH_DIST/$EACH_SECTION/binary-$EACH_CPU/Packages.gz done info "regenerating Contents-$EACH_CPU.gz ($REPONAME) ..." debug 10 "control: running 'apt-ftparchive contents' onto $REPODIR/dists/$EACH_DIST/Contents-$EACH_CPU.gz ..." ( cd $REPODIR && apt-ftparchive contents . -o APT::FTPArchive::Release::Codename=$EACH_DIST -o APT::FTPArchive::Release::Architectures=$EACH_CPU | gzip > dists/$EACH_DIST/Contents-$EACH_CPU.gz ) chmod a+r $REPODIR/dists/$EACH_DIST/Contents-$EACH_CPU.gz done info "regenerating Release and Release.gpg ($REPONAME, $EACH_DIST) ..." mkdir -p $REPODIR/dists/$EACH_DIST ( cd $REPODIR && apt-ftparchive release -o APT::FTPArchive::Release::Origin="$ORIGIN" -o APT::FTPArchive::Release::Label="$LABEL" -o APT::FTPArchive::Release::Components="$ALL_SECTIONS" -o APT::FTPArchive::Release::Suite=$EACH_DIST -o APT::FTPArchive::Release::Codename=$EACH_DIST -o APT::FTPArchive::Release::Architectures="$ALL_CPUS" dists/$EACH_DIST ) > $REPODIR/dists/$EACH_DIST/Release || error "apt-ftparchive failed" chmod a+r $REPODIR/dists/$EACH_DIST/Release rm -f $REPODIR/dists/$EACH_DIST/Release.gpg ( cd $REPODIR && gpg --batch --use-agent -abs -o $REPODIR/dists/$EACH_DIST/Release.gpg $REPODIR/dists/$EACH_DIST/Release ) chmod a+r $REPODIR/dists/$EACH_DIST/Release.gpg done } upstream() { local REPO CPU DIST SECTIONS DATE # Defaults for directive-specific options # Process directive-specific options while [ "X$1" != X ]; do case $1 in --) shift; break ;; -*) usage ;; *) break ;; esac shift done # Process directive-specific arguments [ $# = 2 ] || usage REPONAME=$1 MIRRORDIR=$2 # Sanity checks and derivations [ ! -f $RCDIR/$REPONAME ] || error "$REPONAME: repository already exists" # Guts DATE="$(date)" info "defining an upstream repository ..." { echo "# This file was generated automatically on $DATE" echo echo "# The following settings need to be adjusted." echo "#ALL_SECTIONS=\"main contrib non-free\"" echo "#ALL_DISTS=\"lenny squeeze\"" echo "#ALL_CPUS=\"i386 amd64\"" echo "#MIRRORER=\"debmirror --ignore-release-gpg --getcontents --nosource --method=rsync --host=ftp2.de.debian.org --root=:debian --arch=\\\${1// /,} --dist=\\\${2// /,} --section=\\\${3// /,},main/debian-installer --di-dist=dists --di-arch=arches \\\"\\\$4\\\"\"" echo echo "# The following settings should not need to be adjusted." echo "REPOLOCAL=\"false\"" echo "MIRRORDIR=\"$MIRRORDIR\"" echo "DATE_CREATED=\"$DATE\"" } > $RCDIR/$REPONAME } mirror() { local REPO MIRRORER DOWNLOAD_DIR OPT_REPOS # Defaults for directive-specific options ALLREPOS=false # Process directive-specific options while [ "X$1" != X ]; do case $1 in --all-repos) ALLREPOS=true ;; --) shift; break ;; -*) usage ;; *) break ;; esac shift done # Process directive-specific arguments if $ALLREPOS; then REPONAMES=$(listrepos --format=plain | paste -s -d' ') else [ $# = 1 ] || usage REPONAMES=$1 fi debug 10 "mirror: REPONAMES=\"$REPONAMES\"" # Sanity checks and derivations for REPONAME in $REPONAMES; do assign_var_from_rc_file $RCDIR/$REPONAME MIRRORER assign_var_from_rc_file $RCDIR/$REPONAME MIRRORDIR assign_var_from_rc_file $RCDIR/$REPONAME REPOLOCAL assign_var_from_rc_file $RCDIR/$REPONAME ALL_CPUS assign_var_from_rc_file $RCDIR/$REPONAME ALL_DISTS assign_var_from_rc_file $RCDIR/$REPONAME ALL_SECTIONS done # Guts for REPONAME in $REPONAMES; do info "updating $REPONAME ..." assign_var_from_rc_file $RCDIR/$REPONAME MIRRORER assign_var_from_rc_file $RCDIR/$REPONAME MIRRORDIR assign_var_from_rc_file $RCDIR/$REPONAME REPOLOCAL assign_var_from_rc_file $RCDIR/$REPONAME ALL_CPUS assign_var_from_rc_file $RCDIR/$REPONAME ALL_DISTS assign_var_from_rc_file $RCDIR/$REPONAME ALL_SECTIONS mkdir -p $MIRRORDIR debug 10 "mirror: MIRRORER=[$MIRRORER]" if $REPOLOCAL; then assign_var_from_rc_file $RCDIR/$REPONAME REPODIR bash -c "$MIRRORER" dummy "$REPODIR" "$MIRRORDIR" else bash -c "$MIRRORER" dummy "$ALL_CPUS" "$ALL_DISTS" "$ALL_SECTIONS" "$MIRRORDIR" fi date > $MIRRORDIR/.$PROGNAME.mirrored done } freeze() { local REPO SNAPSHOT_EXT # Defaults for directive-specific options ALLREPOS=false # Process directive-specific options while [ "X$1" != X ]; do case $1 in --all-repos) ALLREPOS=true ;; --) shift; break ;; -*) usage ;; *) break ;; esac shift done # Process directive-specific arguments if $ALLREPOS; then REPONAMES=$(listrepos --format=plain | paste -s -d' ') else [ $# = 1 ] || usage REPONAMES=$1 fi # Sanity checks and derivations assign_var_from_rc_file $RCDIR/general PAACRT_ROOT for REPONAME in $REPONAMES; do assign_var_from_rc_file $RCDIR/$REPONAME MIRRORDIR done SNAPSHOT_EXT=$(date '+%Y%m%d') # Guts for REPONAME in $REPONAMES; do assign_var_from_rc_file $RCDIR/$REPONAME MIRRORDIR info "cloning $MIRRORDIR to $PAACRT_ROOT/$REPONAME.$SNAPSHOT_EXT ..." mkdir -p $PAACRT_ROOT/$REPONAME.$SNAPSHOT_EXT rsync -a --delete $MIRRORDIR/ $PAACRT_ROOT/$REPONAME.$SNAPSHOT_EXT/ find $PAACRT_ROOT/$REPONAME.$SNAPSHOT_EXT/ -type d -exec chmod 755 {} \; find $PAACRT_ROOT/$REPONAME.$SNAPSHOT_EXT/ -type f -exec chmod 644 {} \; echo "Tag: $SNAPSHOT_EXT" date > $PAACRT_ROOT/$REPONAME.$SNAPSHOT_EXT/.$PROGNAME.frozen done } listrepos() { FORMAT=human while [ "X$1" != X ]; do case $1 in --format=*) FORMAT=${1#*=} ;; --) shift; break ;; -*) internal "listrepos: usage" ;; *) break ;; esac shift done FMTSTR="$REPONAME_FMTSTR $LOCALFLAG_FMTSTR $ARCHS_FMTSTR $DISTS_FMTSTR $SECTIONS_FMTSTR $DATE_FMTSTR\n" if [ $FORMAT = human ]; then printf "$FMTSTR" "repository" "local" "archs" "dists" "sections" "date created/defined" printf "$FMTSTR" $UNDERLINE $UNDERLINE $UNDERLINE $UNDERLINE $UNDERLINE $UNDERLINE fi for REPONAME in $(ls $RCDIR 2>/dev/null); do [ $REPONAME != $(basename $DBFILE) -a $REPONAME != general ] || continue if [ $FORMAT = human ]; then assign_var_from_rc_file $RCDIR/$REPONAME REPOLOCAL assign_var_from_rc_file $RCDIR/$REPONAME ALL_CPUS assign_var_from_rc_file $RCDIR/$REPONAME ALL_DISTS assign_var_from_rc_file $RCDIR/$REPONAME ALL_SECTIONS assign_var_from_rc_file $RCDIR/$REPONAME DATE_CREATED # For display to humans change true/false to yes/no { $REPOLOCAL && REPOLOCAL=yes; } || REPOLOCAL=no printf "$FMTSTR" $REPONAME $REPOLOCAL ${ALL_CPUS// /,} ${ALL_DISTS// /,} ${ALL_SECTIONS// /,} "$DATE_CREATED" elif [ $FORMAT = plain ]; then echo $REPONAME fi done if [ $FORMAT = human ]; then echo fi } listmirrors() { FMTSTR="$REPONAME_FMTSTR $DATE_FMTSTR\n" printf "$FMTSTR" "mirror" "date mirrored" printf "$FMTSTR" $UNDERLINE $UNDERLINE for REPONAME in $(ls $RCDIR 2>/dev/null); do [ $REPONAME != $(basename $DBFILE) -a $REPONAME != general ] || continue assign_var_from_rc_file $RCDIR/$REPONAME MIRRORDIR if [ ! -f $MIRRORDIR/.$PROGNAME.mirrored ]; then LINKED=unknown else LINKED=$(cat $MIRRORDIR/.$PROGNAME.mirrored) fi printf "$FMTSTR" $REPONAME "$LINKED" done echo } listfreezes() { FMTSTR="$FREEZE_FMTSTR $REPONAME_FMTSTR $DATE_FMTSTR $INTEGRITY_FMTSTR\n" assign_var_from_rc_file $RCDIR/general PAACRT_ROOT printf "$FMTSTR" "freeze" "repository" "date frozen" "integrity" printf "$FMTSTR" $UNDERLINE $UNDERLINE $UNDERLINE $UNDERLINE for THING in $(ls $PAACRT_ROOT 2>/dev/null); do REPO= FREEZEDATE= INTEGRITY= if [ -h $PAACRT_ROOT/$THING ]; then continue elif [ ! -d $PAACRT_ROOT/$THING ]; then INTEGRITY="orphaned (not a directory)" elif [ $THING = lost+found ]; then continue elif ! [[ $THING =~ ^([^.]+)\.([^.]+)$ ]]; then INTEGRITY="orphaned (non-standard name)" else REPONAME=${BASH_REMATCH[1]} FREEZE=${BASH_REMATCH[2]} if [ ! -f $RCDIR/$REPONAME ]; then INTEGRITY="orphaned (no such repository)" else assign_var_from_rc_file $RCDIR/$REPONAME MIRRORDIR if [ ! -f $MIRRORDIR/.$PROGNAME.mirrored ]; then INTEGRITY="orphaned (mirror lacks integrity)" elif [ ! -f $PAACRT_ROOT/$THING/.$PROGNAME.frozen ]; then FREEZEDATE="unknown (no .$PROGNAME.frozen)" INTEGRITY="bad (no .$PROGNAME.frozen)" else FREEZEDATE=$(cat $PAACRT_ROOT/$THING/.$PROGNAME.frozen) INTEGRITY="ok" fi fi fi printf "$FMTSTR" "$FREEZE" "$REPONAME" "$FREEZEDATE" "$INTEGRITY" done | sed 's/ *$//' echo } listavails() { FMTSTR="$REPONAME_FMTSTR $HOSTNAME_FMTSTR $FREEZE_FMTSTR $DATE_FMTSTR $INTEGRITY_FMTSTR\n" FORMAT=human while [ "X$1" != X ]; do case $1 in --format=*) FORMAT=${1#*=} ;; --) shift; break ;; -*) internal "listrepos: usage" ;; *) break ;; esac shift done assign_var_from_rc_file $RCDIR/general PAACRT_ROOT if [ $FORMAT = human ]; then printf "$FMTSTR" "repository" "host" "freeze" "date availed" "integrity" printf "$FMTSTR" $UNDERLINE $UNDERLINE $UNDERLINE $UNDERLINE $UNDERLINE fi for THING in $(ls $PAACRT_ROOT 2>/dev/null); do debug 10 "listavails: THING=$THING" REPONAME= AVAILDATE= INTEGRITY= FREEZE= if [ -d $PAACRT_ROOT/$THING -a ! -h $PAACRT_ROOT/$THING ]; then continue elif [ ! -h $PAACRT_ROOT/$THING ]; then INTEGRITY="orphaned (not a symlink)" elif ! [[ $THING =~ ^([^.]+)\.([^.]+)$ ]]; then INTEGRITY="orphaned (non-standard name)" else REPONAME=${BASH_REMATCH[1]} HOST=${BASH_REMATCH[2]} debug 10 "listavails: REPONAME=$REPONAME, HOST=$HOST" THING2=$(readlink $PAACRT_ROOT/$THING) [[ $THING2 =~ ^([^.]+)\.([^.]+)$ ]] REPONAME2=${BASH_REMATCH[1]} FREEZE=${BASH_REMATCH[2]} debug 10 "listavails: REPONAME2=$REPONAME2, FREEZE=$FREEZE" # These next tests are in order of severity with the most # severe first (this is because we won't display *all* # reasons why an avail is not ok, only the worst; there's # not enough room on the screen). if [ ! -f $RCDIR/$REPONAME ]; then INTEGRITY="orphaned (no such repository)" elif [ -h $PAACRT_ROOT/$REPONAME.$FREEZE -o ! -d $PAACRT_ROOT/$REPONAME.$FREEZE ]; then INTEGRITY="orphaned (no such freeze)" elif [ ! -f $PAACRT_ROOT/$REPONAME.$FREEZE/.$PROGNAME.frozen ]; then INTEGRITY="orphaned (freeze lacks integrity)" else INTEGRITY="ok" fi AVAILDATE="$(date -d "$(stat -c %y $PAACRT_ROOT/$REPONAME.$HOST | sed 's/\+.*//')")" fi if [ $FORMAT = human ]; then printf "$FMTSTR" "$REPONAME" "$HOST" "$FREEZE" "$AVAILDATE" "$INTEGRITY" else echo "$HOST:$REPONAME:$FREEZE" fi done | sed 's/ *$//' if [ $FORMAT = human ]; then echo fi } avail() { local REPO HOST SNAPSHOT_EXT # Defaults for directive-specific options ALLHOSTS=false # Process directive-specific options while [ "X$1" != X ]; do case $1 in --all-hosts) ALLHOSTS=true ;; --) shift; break ;; -*) usage ;; *) break ;; esac shift done # Process directive-specific arguments REPONAME=$1 FREEZE=$2 shift 2 if $ALLHOSTS; then HOSTS=$(listavails --format=plain | sed -n "s/:$REPONAME:.*//p" | paste -s -d' ') else [ $# = 1 ] || usage HOSTS=$1 fi # Sanity checks and derivations assign_var_from_rc_file $RCDIR/general PAACRT_ROOT [ -d $PAACRT_ROOT/$REPONAME.$FREEZE ] || error "$PAACRT_ROOT/$REPONAME.$FREEZE: no such directory" for HOST in "$@"; do [ ! -e $PAACRT_ROOT/$REPONAME.$HOST -o -h $PAACRT_ROOT/$REPONAME.$HOST ] || error "$PAACRT_ROOT/$REPONAME.$HOST: won't delete what was expected to be a symlink" done # Guts for HOST in $HOSTS; do # Above checks ensure either does not exist or is symlink so we can safely blindly remove it. rm -f $PAACRT_ROOT/$REPONAME.$HOST ln -s $REPONAME.$FREEZE $PAACRT_ROOT/$REPONAME.$HOST done } unavail() { # Process directive-specific arguments [ $# = 2 ] || usage REPONAME=$1 HOST=$2 # Sanity checks and derivations assign_var_from_rc_file $RCDIR/general PAACRT_ROOT if [ -h $PAACRT_ROOT/$REPONAME.$HOST ]; then rm -f $PAACRT_ROOT/$REPONAME.$HOST elif [ ! -e $PAACRT_ROOT/$REPONAME.$HOST ]; then : else error "$PAACRT_ROOT/$REPONAME.$HOST: not a symlink" fi } apache() { local REPO REPOS HOST PAACRT_URL_PATHCMPNT MISSING_REPO_IS_ERROR_FLAG # Defaults for directive-specific options # Process directive-specific options while [ "X$1" != X ]; do case $1 in --) shift; break ;; -*) usage ;; *) break ;; esac shift done # Process directive-specific arguments [ $# -ge 2 ] || usage REPONAME=$1; shift # Sanity checks and derivations assign_var_from_rc_file $RCDIR/general PAACRT_ROOT assign_var_from_rc_file $RCDIR/general PAACRT_URL assign_var_from_rc_file $RCDIR/general APACHE_CFG_MDI_DIR for HOST in "$@"; do [ -h $PAACRT_ROOT/$REPONAME.$HOST ] || error "$REPONAME: not generating apache config because repo has not availed to $HOST" done # Guts for HOST in "$@"; do # Extract the path component of the PAACRT URL to put at the beginning of the PAACRT_URL_PATHCMPNT=/${PAACRT_URL#http://*/} # Strip trailing slash if present 'cos we'll add again in a sec. PAACRT_URL_PATHCMPNT=${PAACRT_URL_PATHCMPNT%/} # Output the apache config stanza for this repo { echo " Alias $PAACRT_URL_PATHCMPNT/$REPONAME.$HOST/ \"$PAACRT_ROOT/$REPONAME.$HOST/\"" echo " " echo " Options Indexes FollowSymLinks MultiViews" echo " AllowOverride None" echo " Order allow,deny" echo " Allow from 192.168.0.0/255.255.0.0" echo " " } > $APACHE_CFG_MDI_DIR/$REPONAME.$HOST done } unapache() { local REPONAME HOST # Defaults for directive-specific options # Process directive-specific options while [ "X$1" != X ]; do case $1 in --) shift; break ;; -*) usage ;; *) break ;; esac shift done # Process directive-specific arguments [ $# -ge 2 ] || usage REPONAME=$1; shift # Sanity checks and derivations assign_var_from_rc_file $RCDIR/general APACHE_CFG_MDI_DIR # Guts for HOST in "$@"; do rm -f $APACHE_CFG_MDI_DIR/$REPONAME.$HOST done } listapaches() { local FMTSTR FMTSTR="$REPONAME_FMTSTR $HOSTNAME_FMTSTR $DATE_FMTSTR $INTEGRITY_FMTSTR\n" # Defaults for directive-specific options FORMAT=human # Process directive-specific options while [ "X$1" != X ]; do case $1 in --format=*) FORMAT=${1#*=} ;; --) shift; break ;; -*) internal "listrepos: usage" ;; *) break ;; esac shift done # Process directive-specific arguments [ $# -eq 0 ] || usage # Sanity checks and derivations assign_var_from_rc_file $RCDIR/general APACHE_CFG_MDI_DIR if [ $FORMAT = human ]; then printf "$FMTSTR" "repository" "host" "date apached" "integrity" printf "$FMTSTR" $UNDERLINE $UNDERLINE $UNDERLINE $UNDERLINE fi # Guts for THING in $(ls $APACHE_CFG_MDI_DIR 2>/dev/null); do debug 10 "listapaches: THING=$THING" REPONAME= HOST= INTEGRITY= if ! [[ $THING =~ ^([^.]+)\.([^.]+)$ ]]; then INTEGRITY="orphaned (non-standard name)" else REPONAME=${BASH_REMATCH[1]} HOST=${BASH_REMATCH[2]} debug 10 "listavails: REPONAME=$REPONAME, HOST=$HOST" APACHEDATE="$(date -d "$(stat -c %y $APACHE_CFG_MDI_DIR/$REPONAME.$HOST | sed 's/\+.*//')")" INTEGRITY=ok fi if [ $FORMAT = human ]; then printf "$FMTSTR" "$REPONAME" "$HOST" "$APACHEDATE" "$INTEGRITY" else internal "listapache: non-human output format not implemented" fi done if [ $FORMAT = human ]; then echo fi } apt() { local REPO HOST SECTIONS DIST SECTIONS MISSING_REPO_IS_ERROR_FLAG REPOS # Defaults for directive-specific options # Process directive-specific options while [ "X$1" != X ]; do case $1 in --) shift; break ;; -*) usage ;; *) break ;; esac shift done # Process directive-specific arguments [ $# = 3 ] || usage REPONAME=$1 DFLT_DIST=$2 HOST=$3 # Sanity checks and derivations assign_var_from_rc_file $RCDIR/general PAACRT_URL assign_var_from_rc_file $RCDIR/$REPONAME ALL_SECTIONS # Guts echo "deb ${PAACRT_URL%/}/$REPONAME.$HOST/ $DFLT_DIST $ALL_SECTIONS" > /etc/apt/sources.list.d/$REPONAME.list } unapt() { local REPO HOST SECTIONS DIST SECTIONS MISSING_REPO_IS_ERROR_FLAG REPOS # Defaults for directive-specific options # Process directive-specific options while [ "X$1" != X ]; do case $1 in --) shift; break ;; -*) usage ;; *) break ;; esac shift done # Process directive-specific arguments [ $# = 1 ] || usage REPONAME=$1 # Sanity checks and derivations # Guts rm -f /etc/apt/sources.d/$REPONAME.list } assign_var_from_rc_file() { local RCFILE VARREF VALUE RCFILE=$1 VARREF=$2 [ -f $RCFILE ] || error "$RCFILE: not accessible" VALUE="$(bash -c ". $RCFILE; echo \$$VARREF")" [ "X$VALUE" != X ] || error "$RCFILE: doesn't define $VARREF" eval "$VARREF=\"\$VALUE\"" } # Messaging functions debug() { [ $VERBOSELEVEL -lt $1 ] || echo "$PROGNAME: DEBUG[$1]: $2" >&2; } info() { [ $VERBOSELEVEL -lt 3 ] || echo "$PROGNAME: INFO: $1" >&2; } warning() { [ $VERBOSELEVEL -lt 2 ] || echo "$PROGNAME: WARNING: $1" >&2; } error() { [ $VERBOSELEVEL -lt 1 ] || echo "$PROGNAME: ERROR: $1" >&2; exit 1; } internal() { echo "$PROGNAME: INTERNAL ERROR: $1" >&2; exit 2; } main "$@"