#!/usr/bin/env bash name="Libredbdiff" # Copyright (C) 2014 Esteban Carnevale # Copyright (C) 2014 Luke Shumaker # # License: GNU GPLv3+ # # 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 . baseconfpath="/etc/libredbdiff" basedbpath="/var/lib/libredbdiff" conffile="$baseconfpath/pacman.conf.parabola" conffilearch="$baseconfpath/pacman.conf.archlinux" dbpath="$basedbpath/pacman.parabola" dbpatharch="$basedbpath/pacman.archlinux" mirrorlist="$baseconfpath/mirrorlist.parabola" mirrorlistarch="$baseconfpath/mirrorlist.archlinux" mirror='http://repo.parabola.nu/$repo/os/$arch' mirrorarch='http://mirrors.kernel.org/archlinux/$repo/os/$arch' . libremessages cmd="${0##*/}" downloadfile() { local outfile=$1 local url=$2 local mesg=("${@:3}") if [[ ! -e $outfile ]] ; then msg "${mesg[@]}" if wget -q "$url" -O "$outfile"; then return 255 else die "Failed to download %q. Exiting." "$outfile" fi elif [[ $init ]]; then warning "%q already exists. Skipping." "$outfile" fi } createdir() { local dir=$1 if [[ ! -e $dir ]] ; then msg "Creating directory %q" "$dir" mkdir -- "$1" || die "Failed to create directory %q. Exiting." "$dir" elif [[ $init ]]; then warning "%q already exists. Skipping." "$dir" fi } setmirror() { local distro="$1" local mirror="$2" local mirrorlist="$3" if [[ $init ]] && [[ $mirror ]]; then mirrorescaped="${mirror//./\\.}" mirrorescaped="${mirrorescaped//\$/\\$}" msg "Setting %q as the only enabled %s mirror." "${mirror}" "${distro}" sed -i 's|^#\(Server = '"${mirrorescaped}"'\)$|\1|' "${mirrorlist}" fi } filenotfound() { local file=$1 if [[ ! -r $1 ]]; then die "Could not read %q. Nothing done." "$file" plain "It may be necessary to run %q without arguments as root to initialize %s." "$cmd" "$name" fi } comparepkgs() { if [[ ${verarch[$pkgname]} ]] ; then cmp=$(vercmp "${ver[$pkgname]}" "${verarch[$pkgname]}") if [[ $cmp -lt 0 ]]; then msg "%s needs update from the Arch package of the same name. Versions: %s - %s" "${pkgname}" "${ver[$pkgname]}" "${verarch[$pkgname]}" fi elif [[ ${provides[$pkgname]} ]]; then for provide in "${provides[$pkgname]}"; do if [[ ${verarch["$provide"]} ]]; then cmp=$(vercmp "${ver[$pkgname]}" "${verarch[$provide]}") if [[ $cmp -lt 0 ]]; then msg "%s may need update from provide candidate %s. Versions: %s - %s" "${pkgname}" "${provide}" "${ver[$pkgname]}" "${verarch[$provide]}" fi fi done else msg "Could not find candidate to compare %s" "${pkgname}" fi } usage() { print "Usage: %q [-n|-h]" "$cmd" print 'Show [libre] packages that need to be updated from Arch repositories.' echo prose "The default mode of operation is to download/update all necessary files for comparison, but not compare them. Specify the \`-n\` flag to not download anything, but to compare already downloaded files." echo print 'Options:' flag '-n' "Don't update anything, just compare already downloaded files." flag '-h' 'Show this message' } main() { local UPDATE=1 local arg for arg in "$@"; do case "$arg" in -n) UPDATE=0;; -h) usage; return 0;; *) error "Bad arguments. Nothing done." usage >&2 return 1 ;; esac done if (( $UPDATE )) ; then if [[ $EUID != 0 ]]; then die "To initialize $name or update %s pacman databases, the script must be run as root. Nothing done." "$name" fi if ! [[ -d "$baseconfpath" && -d "$basedbpath" && -d "$dbpath" && -d "$dbpatharch" && -e "${conffile}" && -e "${conffilearch}" && -e "${mirrorlist}" && -e "${mirrorlist}" ]]; then msg "%s files are missing. Initializing." "${name}" init=1 fi createdir "$baseconfpath" createdir "$basedbpath" createdir "$dbpath" createdir "$dbpatharch" downloadfile "${conffile}" "https://projects.parabola.nu/abslibre.git/plain/libre/pacman/pacman.conf.x86_64" \ "Downloading Parabola %q" pacman.conf downloadfile "${conffilearch}" "https://projects.archlinux.org/svntogit/packages.git/plain/pacman/trunk/pacman.conf.x86_64" \ "Downloading Arch %q" pacman.conf if [[ $? == 255 ]] ; then msg "Setting Arch mirrorlist file in %q" "${conffilearch}" sed -i "s|/etc/pacman\.d/mirrorlist$|$baseconfpath/mirrorlist.archlinux|" "${conffilearch}" fi downloadfile "${mirrorlist}" "https://repo.parabola.nu/mirrorlist.txt" \ "Downloading Parabola %q" mirrorlist if [[ $? == 255 ]] ; then sed -i 's|^Server|#Server|' "${mirrorlist}" setmirror "Parabola" "$mirror" "$mirrorlist" fi downloadfile "${mirrorlistarch}" "https://projects.archlinux.org/svntogit/packages.git/plain/pacman-mirrorlist/trunk/mirrorlist" \ "Downloading Arch %q" mirrorlist if [[ $? == 255 ]] ; then setmirror "Arch" "$mirrorarch" "$mirrorlistarch" fi msg "Synchronizing %s pacman databases for Parabola" "$name" pacman --config "${conffile}" -b "${dbpath}" -Sy || die "Failed to synchronize pacman database for Parabola. Exiting." msg "Synchronizing %s pacman databases for Arch" "$name" pacman --config "${conffilearch}" -b "${dbpatharch}" -Sy || die "Failed to synchronize pacman database for Arch. Exiting." msg "%s pacman databases are updated. %s is ready. Run %q -n to print results." "$name" "$name" "$cmd" return 0 else filenotfound "${dbpath}" filenotfound "${dbpatharch}" filenotfound "${conffile}" filenotfound "${conffilearch}" filenotfound "${mirrorlist}" filenotfound "${mirrorlistarch}" fi unset provides ver verarch declare -gA provides ver verarch while read -a line; do verarch["${line[0]}"]="${line[1]}" done < <(pacman --dbpath "${dbpatharch}" --config "${conffilearch}" -Ss | grep -v '^ ' | awk -F/ '{print $2}') while read -a line; do ver[${line[0]}]="${line[1]}" provides[${line[0]}]="${line[@]:2}" pkgname=${line[0]} comparepkgs done < <(expac -b "${dbpath}" -c "${conffile}" -Ss '%r/%n %v %S' | awk -F/ '$1 == "libre" {print $2}') } main "$@"