#!/bin/bash
# Copyright (C) 2007-2011 Matias A. Fonzo, Santiago del Estero, AR
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
# Localización % Idioma:
TEXTDOMAINDIR=/usr/share/locale
TEXTDOMAIN=upgrade
VERSION=2.5
# Funciones #
# Una función para mostrar mensajes normales:
msg() { local LC_ALL ; printf '%s\n' "$@"; }
# Una función para mensajes de advertencia:
warn() { local LC_ALL; printf '%b\n' "$@" >&2; }
usage() {
msg $"Upgrade one or more packages in your system." \
"" \
$"Usage: upgrade [options] package_name.tlz ..." \
"" \
$"Short options:" \
$" -h Show this help and exit." \
$" -V Show the version of the program." \
$" -f Force the upgrade if the" \
$" package is already installed." \
$" -i Install the package if not had installed." \
$" -v Enable verbose mode." \
$" -w Warn about of the packages that" \
$" will be upgraded." \
"" \
$"Note:" \
"" \
$" Use the percent symbol (%) if the packages have" \
$" different names. Like, old_package%new_package" \
""
}
version() {
msg "upgrade $VERSION" \
"Copyright (C) 2007-2011 Matias A. Fonzo ." \
"License GPLv3+: GNU GPL version 3 or later:" \
"" \
"This is free software: you are free to change and redistribute it." \
"There is NO WARRANTY, to the extent permitted by law."
}
# Opciones:
OPTIND=1 # Resetea la variable.
while getopts ":fivwhV" opt
do
case "$opt" in
f)
FORCE=on
;;
i)
INSTALL=on
;;
v)
VERBOSE=on
;;
w)
WARN=on
;;
h)
usage
exit 0
;;
V)
version
exit 0
;;
\?)
warn $"${0##*/}: Invalid option: -${OPTARG}"
exit 1
;;
esac
done
shift $((OPTIND - 1))
# Si no hay argumentos, llama a la función de ayuda:
(( $# == 0 )) && { usage ; exit 0; }
# Comprobamos la variable de entorno ROOT:
if [[ -n $ROOT && ! -d $ROOT ]]; then
warn $"${0##*/}: ROOT=${ROOT}: Invalid directory"
exit 1;
fi
# Chequeo de sanidad.
#
# Comprueba si el sistema de archivos
# se encuentra en modo de sólo-lectura:
if ! touch ${ROOT}/pkg-upgrade$$ ; then
warn $"The filesystem (on $ROOT) is in read-only mode."
exit 1;
fi
rm -f ${ROOT}/pkg-upgrade$$
# Sale ante cualquier error:
set -e
# Base de datos por defecto:
DB="${ROOT}/var/db"
if [[ ! -d $DB ]]; then
mkdir -p "$DB"
fi
# Más funciones #
# Una función para reflejar el nombre base:
_basename() { local name ; name=${1##*/} ; printf "${name%$2}"; }
# Función que imprime el nombre del paquete:
pkg_name() {
string=$(_basename $1 .tlz)
seg=${string//[![-]} ## Toma los segmentos "-".
seg=${#seg} ## Los cuenta.
case "$seg" in
0) printf "$string" ;;
1) printf "${string%-*}" ;;
2|3) printf "${string%%-*}" ;;
4) cut -f 1-2 -d - <<<"$string" ;;
*) cut -f 1-$((seg - 2)) -d - <<<"$string" ;;
esac
}
# Función para remover los archivos de paquetes viejos:
move_old() {
for file in "$@" ; do
if [[ -r $file ]]; then
if [[ $(pkg_name $file) = $short ]]; then
mv $file ${file}.UPGRADED_${timestamp}
fi
fi
done
}
# Hace que algunos comandos corran más rápido:
export LC_ALL=C
# Loop:
for package in "$@" ; do
# Figura hacia afuera el nombre del nuevo paquete:
newpkg=${package##*%}
# Comprueba la integridad del archivo de forma simple:
if [[ ! -f $newpkg ]]; then
warn $"${0##*/}: ${newpkg}: File not found or non-regular"
CODE=1
continue;
fi
# Comprueba la extensión del paquete:
case "$newpkg" in
*.tlz)
dirpkg=$(dirname $newpkg)
newpkg=$(_basename $newpkg .tlz)
;;
*)
warn $"${newpkg}: Does not end in .tlz"
CODE=1
continue;
esac
# Figura hacia afuera el nombre del viejo paquete:
oldpkg=${package%%%*}
oldpkg=$(_basename $oldpkg .tlz)
# Comprueba si hay un paquete instalado para su actualización:
short="$(pkg_name $oldpkg)"
if [[ ! -r ${DB}/pkg/$oldpkg ]]; then
if ls ${DB}/pkg/${short}* > /dev/null 2>&1 ; then
for installed_package in ${DB}/pkg/${short}* ; do
if [[ $(pkg_name $installed_package) = $short ]]; then
oldpkg=${installed_package##*/}
break;
fi
done
fi
fi
if [[ ! $INSTALL = on ]]; then
if [[ ! -f ${DB}/pkg/$oldpkg ]]; then
if [[ $WARN != on ]]; then
warn $"${DB}/pkg/${oldpkg}: Package not found in the database"
CODE=1
continue;
else
msg $"${0##*/}: ${short}: Package not installed"
CODE=0
continue;
fi
fi
else
if [[ $FORCE = on ]]; then
OPT=-f
fi
ROOT=$ROOT pkg add $OPT ${dirpkg}/${newpkg}.tlz
CODE=$?
if (( $CODE == 0 )); then
continue;
else
warn "" $"An error occurred while trying to install the package" ""
break;
fi
fi
# Verifica si el paquete para actualizar ya está instalado:
if [[ ! $FORCE = on ]]; then
if [[ $oldpkg = $newpkg ]]; then
if [[ $WARN != on ]]; then
warn $"${DB}/pkg/${newpkg}: Already installed"
CODE=3
continue;
else
msg $"${newpkg}: Would be skipped (already installed)"
CODE=0
continue;
fi
fi
fi
# Movemos los paquetes viejos para removerlos fácilmente:
printf -v timestamp '%+(%Y%m%d_%T)T' -1 ## Formato fecha y hora.
# Renombra paquetes instalados y descripciones:
move_old \
"${DB}/pkg/${short}"* \
"${DB}/pkg/pre-post/${short}"* \
"${DB}/pkg/post-install/${short}"* \
"${DB}/pkg/description/${short}"*
# Antes de remover e instalar el nuevo paquete, necesitamos pre-instalarlo,
# puesto que podría ser crucial si se trata de una herramienta principal:
msg $"Pre-installing $newpkg ..." ""
ROOT=$ROOT pkg add -f ${dirpkg}/${newpkg}.tlz >/dev/null; CODE=$?
if (( $CODE != 0 )); then
warn "" $"An error occurred while trying to install the package" ""
fi
# Remueve el viejo e instala el nuevo paquete. Si se encuentran más
# paquetes viejos con el mismo nombre, los remueve igualmente:
msg $"$oldpkg <-> ${newpkg}.tlz ..."
( cd ${DB}/pkg
# De esta forma mantenemos límpia la base de datos:
for removepkg in *.UPGRADED_${timestamp}; do
if [[ ! $VERBOSE = on ]]; then
ROOT=$ROOT pkg remove -q $removepkg > /dev/null
else
ROOT=$ROOT pkg remove $removepkg
fi
done
# Borra las descripciones del viejo paquete:
if [[ -d ./description ]]; then
( cd ./description
for file in *.UPGRADED_${timestamp}; do
rm -f $file
done
)
fi
)
# Nuevamente instalamos el nuevo paquete:
ROOT=$ROOT pkg add -f ${dirpkg}/${newpkg}.tlz
msg "" $"${oldpkg}: Upgraded with the package: ${dirpkg}/$newpkg" ""
done
exit $CODE