porg/scripts/porgball.in

262 lines
6.0 KiB
Bash
Executable File

#!/bin/bash
#-----------------------------------------------------------------------
# porgball - binary package support for porg
#
# This file is part of the package porg
# Copyright (C) 2015 David Ricart
# For more information visit http://porg.sourceforge.net
#-----------------------------------------------------------------------
me=$(basename $0)
sed_cmd=@SED@
warn() { echo "$me: $*" >&2; exit_status=1; }
die() { warn "$*"; exit 1; }
say() { [ "$opt_verb" ] && echo "$*"; }
do_help()
{
cat << EOF
$me - binary package support for porg.
Usage:
$me [OPTIONS] [<packages>|<porgballs>]
General options:
-v, --verbose Explain what is being done
-V, --version Display version information and exit
-h, --help Display this help message and exit
-L, --logdir=DIR Porg log directory (default is $def_logdir)
Porgball creation options:
-a, --all Create a porgball for each logged package
-X, --exact-version Do not expand version of packages given as arguments
-d, --directory=DIR Create the porgballs in DIR (default is '.')
-g, --gzip Compress with gzip (default)
-b, --bzip2 Compress with bzip2
-x, --xz Compress with xz
-<1..9> Compression level (speed/quality balance)
--fast Like -1: Compress faster
--best Like -9: Compress better (default)
-f, --force Force overwrite of existing output files
-t, --test Test integrity of the porgball after creating it
-n, --no-porg-suffix Do not append '.porg' suffix to the name of the
porgballs.
Porgball extraction options:
-e, --extract Extract the porgballs given as arguments
-d, --directory=DIR Extract the files into root directory DIR
(default is '/')
-l, --log Log the extraction with porg
Note:
Options cannot be joined up; for instance: '-af' is not correct,
type '-a -f' instead.
EOF
exit 0
}
# 1st parameter ($1) = flag to test (-w, -r, ...)
# 2nd parameter ($2) = directory
#
do_check_dir()
{
[ -d "$2" ] || die "$2: No such directory"
eval [ $1 "$2" ] || die "$2: Permission denied"
}
# Extract a porgball
do_extract()
{
ball=$1
[ -e $ball ] || { warn "$ball: No such file"; return; }
if ! echo $ball | egrep --quiet '\.tar\.(gz|bz2|xz)$'; then
warn "$ball: Does not look like a porgball; skipped"
return
fi
say "Extracting files from $ball"
cmd="tar --directory=$destdir $opt_verb --auto-compress --extract --file=$ball"
if [ "$opt_log" ]; then
pkg=${ball%.tar.*}
pkg=${pkg%.porg}
pkg=${pkg##*/}
porg $opt_logdir $opt_verb --log --package="$pkg" -- $cmd
else
eval $cmd
fi
[ $? -eq 0 ] || exit_status=$?
}
# Create a porgball for a package logged in the porg database.
do_create()
{
pkg=$1
say "Processing $pkg"
# Write list of files logged by the package into tmpfile.
> $tmpfile
for file in $(porg $opt_logdir --no-package-name --files $pkg); do
[ -e $file ] && echo $file >> $tmpfile
done
[ -s $tmpfile ] || { warn "No files to process"; return; }
# Get names of tar file and porgball
tarfile=$(echo $destdir/${pkg}${porg_suffix}.tar | tr -s /)
case $opt_prog in
bzip2) suf=bz2;;
xz) suf=xz;;
*) suf=gz;;
esac
ball=${tarfile}.$suf
if [ -e $ball -a -z "$opt_force" ]; then
read -p "$me: $ball already exists; do you wish to overwrite it (y/N)? "
[ "$REPLY" = y -o "$REPLY" = Y ] || return
fi
# Create intermediate tar archive
say "Creating $tarfile"
tar $opt_verb --create --file=$tarfile --ignore-failed-read --files-from=$tmpfile \
|| { exit_status=1; return; }
# Create porgball
say "Creating $ball"
eval $opt_prog --force $opt_level $opt_verb $tarfile \
|| { exit_status=1; return; }
# Test integrity of the created porgball, if needed
if [ "$opt_test" ]; then
say "Testing integrity of $ball"
eval $opt_prog $opt_verb --test $ball || exit_status=$?
fi
}
#-------
exit_status=0
# Defaults
opt_prog=gzip
opt_level=-9
porg_suffix=".porg"
# Get default log directory
for dir in /etc /usr/local/etc /usr/etc /opt/etc; do
if [ -f $dir/porgrc ]; then
def_logdir=$($sed_cmd -n '/^LOGDIR=/ s///p' $dir/porgrc 2>/dev/null)
break;
fi
done
def_logdir=${def_logdir:-/var/log/porg}
logdir=$def_logdir
# Parse the command line
while [ "$1" ]; do
case $1 in
-V|--version) porg --version | $sed_cmd "s/^porg/$me/"; exit 0;;
-h|--help) do_help;;
-t|--test) opt_test=-t;;
-v|--verbose) opt_verb=-v;;
-a|--all) opt_all=-a;;
-X|--exact-version) opt_exact=-X;;
-g|--gzip) opt_prog=gzip;;
-b|--bzip2) opt_prog=bzip2;;
-x|--xz) opt_prog=xz;;
-[0-9]) opt_level=$1;;
--fast) opt_level=-1;;
--best) opt_level=-9;;
-f|--force) opt_force=-f;;
-e|--extract) opt_extract=1;;
-l|--log) opt_log=1;;
-n|--no-porg-suffix) porg_suffix="";;
-L|--logdir)
[ "$2" ] && logdir=$2 || die "Option '$1' requires an argument"
shift
;;
--logdir=*)
logdir=${1#*=}
[ "$logdir" ] || die "Option '${1%=*}' requires an argument"
;;
-d|-C|--directory|--dir|--root)
[ "$2" ] && destdir=$2 || die "Option '$1' requires an argument"
shift
;;
--directory=*|--dir=*|--root=*)
destdir=${1#*=}
[ "$destdir" ] || die "Option '${1%=*}' requires an argument"
;;
-*) die "$1: Unrecognized option";;
*) args="$args $1";;
esac
shift
done
do_check_dir -r $logdir
opt_logdir="--logdir=$logdir"
# Extraction of porgballs
if [ "$opt_extract" ]; then
[ "$args" ] || die "No arguments provided"
destdir=${destdir:-/} # default dir = /
do_check_dir -w $destdir
for ball in $args; do
do_extract $ball
done
# Creation of porgballs
else
[ "$args" -o "$opt_all" ] || die "No arguments provided"
destdir=${destdir:-.} # default dir = .
do_check_dir -w $destdir
# Create tmpfile and assure it's removed on exit
tmpfile=$(mktemp || echo /tmp/$me.$$)
trap 'rm -f $tmpfile' 0
for pkg in $(porg $opt_logdir $opt_verb $opt_exact $opt_all $args); do
do_create $pkg
done
fi
exit $exit_status