#!/bin/bash # Copyright (C) 2007-2010 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.2 # 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-2010 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 # 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=$(printf "$string" | sed 's/[^-]//g') seg=${#seg} case "$seg" in 0) printf "$string" ;; 1) printf "${string%-*}" ;; 2|3) printf "${string%%-*}" ;; 4) printf "$string" | cut -f 1-2 -d - ;; *) printf "$string" | cut -f 1-$((seg - 2)) -d - ;; 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: timestamp=$(date +%Y%m%d-%T) # Paquetes instalados: move_old "${DB}/pkg/${short}"* # Scripts instalados: move_old "${DB}/pkg/pre-post/${short}"* move_old "${DB}/pkg/post-install/${short}"* # Descripciones instaladas: move_old "${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 limpia la base de datos: for removepkg in *-${timestamp}; do if [[ ! $VERBOSE = on ]]; then ROOT=$ROOT pkg remove -q $removepkg > /dev/null else ROOT=$ROOT pkg remove $removepkg fi done ) # Nuevamente instalamos el nuevo paquete: ROOT=$ROOT pkg add -f ${dirpkg}/${newpkg}.tlz msg "" $"${oldpkg}: Upgraded with the package: ${dirpkg}/$newpkg" "" done exit $CODE