Send patches - preferably formatted by git format-patch - to patches at archlinux32 dot org.
summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/.gitignore1
-rw-r--r--scripts/Makefile.am24
-rw-r--r--scripts/library/README24
-rw-r--r--scripts/library/parse_options.sh105
-rw-r--r--scripts/library/parseopts.sh141
-rw-r--r--scripts/makepkg.sh.in732
-rw-r--r--scripts/pacman-db-upgrade.sh.in2
-rw-r--r--scripts/pacman-key.sh.in256
-rw-r--r--scripts/pacman-optimize.sh.in49
-rw-r--r--scripts/pkgdelta.sh.in40
-rw-r--r--scripts/po/POTFILES.in2
-rw-r--r--scripts/rankmirrors.sh.in212
-rw-r--r--scripts/repo-add.sh.in66
13 files changed, 825 insertions, 829 deletions
diff --git a/scripts/.gitignore b/scripts/.gitignore
index 21b671c0..9e403bfb 100644
--- a/scripts/.gitignore
+++ b/scripts/.gitignore
@@ -3,7 +3,6 @@ pacman-db-upgrade
pacman-key
pacman-optimize
pkgdelta
-rankmirrors
repo-add
repo-elephant
repo-remove
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index d89fd306..ae366241 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -12,7 +12,6 @@ OURSCRIPTS = \
pacman-key \
pacman-optimize \
pkgdelta \
- rankmirrors \
repo-add
EXTRA_DIST = \
@@ -21,13 +20,12 @@ EXTRA_DIST = \
pacman-key.sh.in \
pacman-optimize.sh.in \
pkgdelta.sh.in \
- rankmirrors.sh.in \
repo-add.sh.in \
$(LIBRARY)
LIBRARY = \
library/output_format.sh \
- library/parse_options.sh
+ library/parseopts.sh
# Files that should be removed, but which Automake does not know.
MOSTLYCLEANFILES = $(bin_SCRIPTS)
@@ -60,18 +58,15 @@ edit = sed \
## All the scripts depend on Makefile so that they are rebuilt when the
## prefix etc. changes. Use chmod -w to prevent people from editing the
## wrong file by accident.
-# two 'test' lines- make sure we can handle both sh and py type scripts
-# third 'test' line- make sure one of the two checks succeeded
$(OURSCRIPTS): Makefile
- @echo ' ' GEN $@;
- @$(RM) $@
- @test -f $(srcdir)/$@.sh.in && m4 -P -I $(srcdir) $(srcdir)/$@.sh.in | $(edit) >$@
- @chmod +x $@
- @chmod a-w $@
+ $(AM_V_at)$(RM) $@
+ $(AM_V_GEN)test -f $(srcdir)/$@.sh.in && m4 -P -I $(srcdir) $(srcdir)/$@.sh.in | $(edit) >$@
+ $(AM_V_at)chmod +x,a-w $@
+ @$(BASH_SHELL) -O extglob -n $@
makepkg: \
$(srcdir)/makepkg.sh.in \
- $(srcdir)/library/parse_options.sh
+ $(srcdir)/library/parseopts.sh
pacman-db-upgrade: \
$(srcdir)/pacman-db-upgrade.sh.in \
@@ -80,7 +75,7 @@ pacman-db-upgrade: \
pacman-key: \
$(srcdir)/pacman-key.sh.in \
$(srcdir)/library/output_format.sh \
- $(srcdir)/library/parse_options.sh
+ $(srcdir)/library/parseopts.sh
pacman-optimize: \
$(srcdir)/pacman-optimize.sh.in \
@@ -88,9 +83,8 @@ pacman-optimize: \
pkgdelta: \
$(srcdir)/pkgdelta.sh.in \
- $(srcdir)/library/output_format.sh
-
-rankmirrors: $(srcdir)/rankmirrors.sh.in
+ $(srcdir)/library/output_format.sh \
+ $(srcdir)/library/parseopts.sh
repo-add: \
$(srcdir)/repo-add.sh.in \
diff --git a/scripts/library/README b/scripts/library/README
index 1e9c962b..c71c0714 100644
--- a/scripts/library/README
+++ b/scripts/library/README
@@ -8,8 +8,22 @@ and can be silenced by defining 'QUIET'. The 'warning' and 'error'
functions print to stderr with the appropriate prefix added to the
message.
-parse_options.sh:
-A getopt replacement to avoids portability issues, in particular the
-lack of long option name support in the default getopt provided by some
-platforms.
-Usage: parse_option $SHORT_OPTS $LONG_OPTS "$@"
+parseopts.sh:
+A getopt_long-like parser which portably supports longopts and shortopts
+with some GNU extensions. It does not allow for options with optional
+arguments. For both short and long opts, options requiring an argument
+should be suffixed with a colon. After the first argument containing
+the short opts, any number of valid long opts may be be passed. The end
+of the options delimiter must then be added, followed by the user arguments
+to the calling program.
+
+Reccommended Usage:
+ OPT_SHORT='fb:z'
+ OPT_LONG=('foo' 'bar:' 'baz')
+ if ! parseopts "$OPT_SHORT" "${OPT_LONG[@]}" -- "$@"; then
+ exit 1
+ fi
+ set -- "${OPTRET[@]}"
+Returns:
+ 0: parse success
+ 1: parse failure (error message supplied)
diff --git a/scripts/library/parse_options.sh b/scripts/library/parse_options.sh
deleted file mode 100644
index 039eef92..00000000
--- a/scripts/library/parse_options.sh
+++ /dev/null
@@ -1,105 +0,0 @@
-# getopt like parser
-parse_options() {
- local short_options=$1; shift;
- local long_options=$1; shift;
- local ret=0;
- local unused_options=""
- local i
-
- while [[ -n $1 ]]; do
- if [[ ${1:0:2} = '--' ]]; then
- if [[ -n ${1:2} ]]; then
- local match=""
- for i in ${long_options//,/ }; do
- if [[ ${1:2} = ${i//:} ]]; then
- match=$i
- break
- fi
- done
- if [[ -n $match ]]; then
- local needsargument=0
-
- [[ ${match} = ${1:2}: ]] && needsargument=1
- [[ ${match} = ${1:2}:: && -n $2 && ${2:0:1} != "-" ]] && needsargument=1
-
- if (( ! needsargument )); then
- printf ' %s' "$1"
- else
- if [[ -n $2 ]]; then
- printf ' %s ' "$1"
- shift
- printf "'%q" "$1"
- while [[ -n $2 && ${2:0:1} != "-" ]]; do
- shift
- printf " %q" "$1"
- done
- printf "'"
- else
- printf "@SCRIPTNAME@: $(gettext "option %s requires an argument\n")" "'$1'" >&2
- ret=1
- fi
- fi
- else
- echo "@SCRIPTNAME@: $(gettext "unrecognized option") '$1'" >&2
- ret=1
- fi
- else
- shift
- break
- fi
- elif [[ ${1:0:1} = '-' ]]; then
- for ((i=1; i<${#1}; i++)); do
- if [[ $short_options =~ ${1:i:1} ]]; then
- local needsargument=0
-
- [[ $short_options =~ ${1:i:1}: && ! $short_options =~ ${1:i:1}:: ]] && needsargument=1
- [[ $short_options =~ ${1:i:1}:: && \
- ( -n ${1:$i+1} || ( -n $2 && ${2:0:1} != "-" ) ) ]] && needsargument=1
-
- if (( ! needsargument )); then
- printf ' -%s' "${1:i:1}"
- else
- if [[ -n ${1:$i+1} ]]; then
- printf ' -%s ' "${1:i:1}"
- printf "'%q" "${1:$i+1}"
- while [[ -n $2 && ${2:0:1} != "-" ]]; do
- shift
- printf " %q" "$1"
- done
- printf "'"
- else
- if [[ -n $2 ]]; then
- printf ' -%s ' "${1:i:1}"
- shift
- printf "'%q" "$1"
- while [[ -n $2 && ${2:0:1} != "-" ]]; do
- shift
- printf " %q" "$1"
- done
- printf "'"
-
- else
- printf "@SCRIPTNAME@: $(gettext "option %s requires an argument\n")" "'-${1:i:1}'" >&2
- ret=1
- fi
- fi
- break
- fi
- else
- echo "@SCRIPTNAME@: $(gettext "unrecognized option") '-${1:i:1}'" >&2
- ret=1
- fi
- done
- else
- unused_options="${unused_options} '$1'"
- fi
- shift
- done
-
- printf " --"
- [[ $unused_options ]] && printf ' %s' "${unused_options[@]}"
- [[ $1 ]] && printf " '%s'" "$@"
- printf "\n"
-
- return $ret
-}
diff --git a/scripts/library/parseopts.sh b/scripts/library/parseopts.sh
new file mode 100644
index 00000000..11589ce3
--- /dev/null
+++ b/scripts/library/parseopts.sh
@@ -0,0 +1,141 @@
+# getopt-like parser
+parseopts() {
+ local opt= optarg= i= shortopts=$1
+ local -a longopts=() unused_argv=()
+
+ shift
+ while [[ $1 && $1 != '--' ]]; do
+ longopts+=("$1")
+ shift
+ done
+ shift
+
+ longoptmatch() {
+ local o longmatch=()
+ for o in "${longopts[@]}"; do
+ if [[ ${o%:} = "$1" ]]; then
+ longmatch=("$o")
+ break
+ fi
+ [[ ${o%:} = "$1"* ]] && longmatch+=("$o")
+ done
+
+ case ${#longmatch[*]} in
+ 1)
+ # success, override with opt and return arg req (0 == none, 1 == required)
+ opt=${longmatch%:}
+ if [[ $longmatch = *: ]]; then
+ return 1
+ else
+ return 0
+ fi ;;
+ 0)
+ # fail, no match found
+ return 255 ;;
+ *)
+ # fail, ambiguous match
+ printf "@SCRIPTNAME@: $(gettext "option '%s' is ambiguous; possibilities:")" "--$1"
+ printf " '%s'" "${longmatch[@]%:}"
+ printf '\n'
+ return 254 ;;
+ esac >&2
+ }
+
+ while (( $# )); do
+ case $1 in
+ --) # explicit end of options
+ shift
+ break
+ ;;
+ -[!-]*) # short option
+ for (( i = 1; i < ${#1}; i++ )); do
+ opt=${1:i:1}
+
+ # option doesn't exist
+ if [[ $shortopts != *$opt* ]]; then
+ printf "@SCRIPTNAME@: $(gettext "invalid option") -- '%s'\n" "$opt" >&2
+ OPTRET=(--)
+ return 1
+ fi
+
+ OPTRET+=("-$opt")
+ # option requires optarg
+ if [[ $shortopts = *$opt:* ]]; then
+ # if we're not at the end of the option chunk, the rest is the optarg
+ if (( i < ${#1} - 1 )); then
+ OPTRET+=("${1:i+1}")
+ break
+ # if we're at the end, grab the the next positional, if it exists
+ elif (( i == ${#1} - 1 )) && [[ $2 ]]; then
+ OPTRET+=("$2")
+ shift
+ break
+ # parse failure
+ else
+ printf "@SCRIPTNAME@: $(gettext "option requires an argument") -- '%s'\n" "$opt" >&2
+ OPTRET=(--)
+ return 1
+ fi
+ fi
+ done
+ ;;
+ --?*=*|--?*) # long option
+ IFS='=' read -r opt optarg <<< "${1#--}"
+ longoptmatch "$opt"
+ case $? in
+ 0)
+ # parse failure
+ if [[ $optarg ]]; then
+ printf "@SCRIPTNAME@: $(gettext "option '%s' does not allow an argument")\n" "--$opt" >&2
+ OPTRET=(--)
+ return 1
+ # --longopt
+ else
+ OPTRET+=("--$opt")
+ shift
+ continue 2
+ fi
+ ;;
+ 1)
+ # --longopt=optarg
+ if [[ $optarg ]]; then
+ OPTRET+=("--$opt" "$optarg")
+ shift
+ # --longopt optarg
+ elif [[ $2 ]]; then
+ OPTRET+=("--$opt" "$2" )
+ shift 2
+ # parse failure
+ else
+ printf "@SCRIPTNAME@: $(gettext "option '%s' requires an argument")\n" "--$opt" >&2
+ OPTRET=(--)
+ return 1
+ fi
+ continue 2
+ ;;
+ 254)
+ # ambiguous option -- error was reported for us by longoptmatch()
+ OPTRET=(--)
+ return 1
+ ;;
+ 255)
+ # parse failure
+ printf "@SCRIPTNAME@: $(gettext "invalid option") '--%s'\n" "$opt" >&2
+ OPTRET=(--)
+ return 1
+ ;;
+ esac
+ ;;
+ *) # non-option arg encountered, add it as a parameter
+ unused_argv+=("$1")
+ ;;
+ esac
+ shift
+ done
+
+ # add end-of-opt terminator and any leftover positional parameters
+ OPTRET+=('--' "${unused_argv[@]}" "$@")
+ unset longoptmatch
+
+ return 0
+}
diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in
index 6990572b..44b1c2cb 100644
--- a/scripts/makepkg.sh.in
+++ b/scripts/makepkg.sh.in
@@ -1,4 +1,4 @@
-#!/bin/bash -e
+#!/bin/bash
#
# makepkg - make packages compatible for use with pacman
# @configure_input@
@@ -39,10 +39,10 @@ export COMMAND_MODE='legacy'
# Ensure CDPATH doesn't screw with our cd calls
unset CDPATH
-myver='@PACKAGE_VERSION@'
-confdir='@sysconfdir@'
-BUILDSCRIPT='@BUILDSCRIPT@'
-startdir="$PWD"
+declare -r myver='@PACKAGE_VERSION@'
+declare -r confdir='@sysconfdir@'
+declare -r BUILDSCRIPT='@BUILDSCRIPT@'
+declare -r startdir="$PWD"
packaging_options=('strip' 'docs' 'libtool' 'emptydirs' 'zipman' 'purge' 'upx')
other_options=('ccache' 'distcc' 'buildflags' 'makeflags')
@@ -168,7 +168,7 @@ clean_up() {
# clean up dangling symlinks to packages
for pkg in ${pkgname[@]}; do
- for file in ${pkg}-*-*-${CARCH}{${PKGEXT},${SRCEXT}}; do
+ for file in ${pkg}-*-*-*{${PKGEXT},${SRCEXT}}; do
if [[ -h $file && ! -e $file ]]; then
rm -f "$file"
fi
@@ -211,7 +211,7 @@ get_filepath() {
return 1
fi
- echo "$file"
+ printf "%s\n" "$file"
}
# Print 'source not found' error message and exit makepkg
@@ -226,13 +226,13 @@ get_filename() {
# if a filename is specified, use it
local filename="${1%%::*}"
# if it is just an URL, we only keep the last component
- echo "${filename##*/}"
+ printf "%s\n" "${filename##*/}"
}
# extract the URL from a source entry
get_url() {
# strip an eventual filename
- echo "${1#*::}"
+ printf "%s\n" "${1#*::}"
}
##
@@ -242,9 +242,9 @@ get_url() {
get_full_version() {
if [[ -z $1 ]]; then
if [[ $epoch ]] && (( ! $epoch )); then
- echo $pkgver-$pkgrel
+ printf "%s\n" "$pkgver-$pkgrel"
else
- echo $epoch:$pkgver-$pkgrel
+ printf "%s\n" "$epoch:$pkgver-$pkgrel"
fi
else
for i in pkgver pkgrel epoch; do
@@ -253,9 +253,32 @@ get_full_version() {
[[ -z ${!indirect} ]] && eval ${indirect}=\"${!i}\"
done
if (( ! $epoch_override )); then
- echo $pkgver_override-$pkgrel_override
+ printf "%s\n" "$pkgver_override-$pkgrel_override"
else
- echo $epoch_override:$pkgver_override-$pkgrel_override
+ printf "%s\n" "$epoch_override:$pkgver_override-$pkgrel_override"
+ fi
+ fi
+}
+
+##
+# usage : get_pkg_arch( [$pkgname] )
+# return : architecture of the package
+##
+get_pkg_arch() {
+ if [[ -z $1 ]]; then
+ if [[ $arch = "any" ]]; then
+ printf "%s\n" "any"
+ else
+ printf "%s\n" "$CARCH"
+ fi
+ else
+ local arch_override
+ eval $(declare -f package_$1 | sed -n 's/\(^[[:space:]]*arch=\)/arch_override=/p')
+ (( ${#arch_override[@]} == 0 )) && arch_override=("${arch[@]}")
+ if [[ $arch_override = "any" ]]; then
+ printf "%s\n" "any"
+ else
+ printf "%s\n" "$CARCH"
fi
fi
}
@@ -264,63 +287,84 @@ get_full_version() {
# Checks to see if options are present in makepkg.conf or PKGBUILD;
# PKGBUILD options always take precedence.
#
-# usage : check_option( $option )
-# return : y - enabled
-# n - disabled
-# ? - not found
+# usage : check_option( $option, $expected_val )
+# return : 0 - matches expected
+# 1 - does not match expected
+# 127 - not found
##
check_option() {
- local ret=$(in_opt_array "$1" ${options[@]})
- if [[ $ret != '?' ]]; then
- echo $ret
- return
- fi
+ in_opt_array "$1" ${options[@]}
+ case $? in
+ 0) # assert enabled
+ [[ $2 = y ]]
+ return ;;
+ 1) # assert disabled
+ [[ $2 = n ]]
+ return
+ esac
# fall back to makepkg.conf options
- ret=$(in_opt_array "$1" ${OPTIONS[@]})
- if [[ $ret != '?' ]]; then
- echo $ret
- return
- fi
+ in_opt_array "$1" ${OPTIONS[@]}
+ case $? in
+ 0) # assert enabled
+ [[ $2 = y ]]
+ return ;;
+ 1) # assert disabled
+ [[ $2 = n ]]
+ return
+ esac
- echo '?' # Not Found
+ # not found
+ return 127
}
##
# Check if option is present in BUILDENV
#
-# usage : check_buildenv( $option )
-# return : y - enabled
-# n - disabled
-# ? - not found
+# usage : check_buildenv( $option, $expected_val )
+# return : 0 - matches expected
+# 1 - does not match expected
+# 127 - not found
##
check_buildenv() {
in_opt_array "$1" ${BUILDENV[@]}
+ case $? in
+ 0) # assert enabled
+ [[ $2 = "y" ]]
+ return ;;
+ 1) # assert disabled
+ [[ $2 = "n" ]]
+ return ;;
+ esac
+
+ # not found
+ return 127
}
##
# usage : in_opt_array( $needle, $haystack )
-# return : y - enabled
-# n - disabled
-# ? - not found
+# return : 0 - enabled
+# 1 - disabled
+# 127 - not found
##
in_opt_array() {
local needle=$1; shift
local opt
for opt in "$@"; do
- if [[ $opt = $needle ]]; then
- echo 'y' # Enabled
- return
+ if [[ $opt = "$needle" ]]; then
+ # enabled
+ return 0
elif [[ $opt = "!$needle" ]]; then
- echo 'n' # Disabled
- return
+ # disabled
+ return 1
fi
done
- echo '?' # Not Found
+ # not found
+ return 127
}
@@ -333,15 +377,15 @@ in_array() {
local needle=$1; shift
local item
for item in "$@"; do
- [[ $item = $needle ]] && return 0 # Found
+ [[ $item = "$needle" ]] && return 0 # Found
done
return 1 # Not Found
}
-source_has_signatures(){
+source_has_signatures() {
local file
for file in "${source[@]}"; do
- if [[ $file = *.@(sig?(n)|asc) ]]; then
+ if [[ ${file%%::*} = *.@(sig?(n)|asc) ]]; then
return 0
fi
done
@@ -357,7 +401,7 @@ get_downloadclient() {
local i
for i in "${DLAGENTS[@]}"; do
local handler="${i%%::*}"
- if [[ $proto = $handler ]]; then
+ if [[ $proto = "$handler" ]]; then
local agent="${i##*::}"
break
fi
@@ -379,7 +423,7 @@ get_downloadclient() {
exit 1 # $E_MISSING_PROGRAM
fi
- echo "$agent"
+ printf "%s\n" "$agent"
}
download_file() {
@@ -420,33 +464,30 @@ download_file() {
run_pacman() {
local cmd
if [[ ! $1 = -@(T|Qq) ]]; then
- printf -v cmd "%q " "$PACMAN" $PACMAN_OPTS "$@"
+ cmd=("$PACMAN" $PACMAN_OPTS "$@")
else
- printf -v cmd "%q " "$PACMAN" "$@"
+ cmd=("$PACMAN" "$@")
fi
if (( ! ASROOT )) && [[ ! $1 = -@(T|Qq) ]]; then
if type -p sudo >/dev/null; then
- cmd="sudo $cmd"
+ cmd=(sudo "${cmd[@]}")
else
- cmd="su root -c '$cmd'"
+ cmd=(su root -c "$(printf '%q ' "${cmd[@]}")")
fi
fi
- eval "$cmd"
+ "${cmd[@]}"
}
check_deps() {
(( $# > 0 )) || return 0
- # Disable error trap in pacman subshell call as this breaks bash-3.2 compatibility
- # Also, a non-zero return value is not unexpected and we are manually dealing them
- set +E
local ret=0
local pmout
- pmout=$(run_pacman -T "$@") || ret=$?
- set -E
+ pmout=$(run_pacman -T "$@")
+ ret=$?
if (( ret == 127 )); then #unresolved deps
- echo "$pmout"
+ printf "%s\n" "$pmout"
elif (( ret )); then
error "$(gettext "'%s' returned a fatal error (%i): %s")" "$PACMAN" "$ret" "$pmout"
return "$ret"
@@ -476,13 +517,11 @@ handle_deps() {
fi
# we might need the new system environment
- # avoid triggering the ERR trap and exiting
- set +e
- local restoretrap=$(trap -p ERR)
- trap - ERR
+ # save our shell options and turn off extglob
+ local shellopts=$(shopt -p)
+ shopt -u extglob
source /etc/profile &>/dev/null
- eval $restoretrap
- set -e
+ eval "$shellopts"
return $R_DEPS_SATISFIED
}
@@ -557,7 +596,7 @@ download_sources() {
local url=$(get_url "$netfile")
# if we get here, check to make sure it was a URL, else fail
- if [[ $file = $url ]]; then
+ if [[ $file = "$url" ]]; then
error "$(gettext "%s was not found in the build directory and is not a URL.")" "$file"
exit 1 # $E_MISSING_FILE
fi
@@ -594,9 +633,9 @@ get_integlist() {
done
if (( ${#integlist[@]} > 0 )); then
- echo ${integlist[@]}
+ printf "%s\n" "${integlist[@]}"
else
- echo ${INTEGRITY_CHECK[@]}
+ printf "%s\n" "${INTEGRITY_CHECK[@]}"
fi
}
@@ -627,7 +666,7 @@ generate_checksums() {
local ct=0
local numsrc=${#source[@]}
- echo -n "${integ}sums=("
+ printf "%s" "${integ}sums=("
local i
local indent=''
@@ -641,8 +680,8 @@ generate_checksums() {
file="$(get_filepath "$netfile")" || missing_source_file "$netfile"
local sum="$(openssl dgst -${integ} "$file")"
sum=${sum##* }
- (( ct )) && echo -n "$indent"
- echo -n "'$sum'"
+ (( ct )) && printf "%s" "$indent"
+ printf "%s" "'$sum'"
ct=$(($ct+1))
(( $ct < $numsrc )) && echo
done
@@ -668,7 +707,7 @@ check_checksums() {
for file in "${source[@]}"; do
local found=1
file="$(get_filename "$file")"
- echo -n " $file ... " >&2
+ printf "%s" " $file ... " >&2
if ! file="$(get_filepath "$file")"; then
printf -- "$(gettext "NOT FOUND")\n" >&2
@@ -677,14 +716,18 @@ check_checksums() {
fi
if (( $found )) ; then
- local expectedsum=$(tr '[:upper:]' '[:lower:]' <<< "${integrity_sums[$idx]}")
- local realsum="$(openssl dgst -${integ} "$file")"
- realsum="${realsum##* }"
- if [[ $expectedsum = $realsum ]]; then
- printf -- "$(gettext "Passed")\n" >&2
+ if [[ ${integrity_sums[$idx]} = 'SKIP' ]]; then
+ echo "$(gettext "Skipped")" >&2
else
- printf -- "$(gettext "FAILED")\n" >&2
- errors=1
+ local expectedsum=$(tr '[:upper:]' '[:lower:]' <<< "${integrity_sums[$idx]}")
+ local realsum="$(openssl dgst -${integ} "$file")"
+ realsum="${realsum##* }"
+ if [[ $expectedsum = "$realsum" ]]; then
+ printf -- "$(gettext "Passed")\n" >&2
+ else
+ printf -- "$(gettext "FAILED")\n" >&2
+ errors=1
+ fi
fi
fi
@@ -838,10 +881,10 @@ extract_sources() {
local ret=0
msg2 "$(gettext "Extracting %s with %s")" "$file" "$cmd"
- if [[ $cmd = bsdtar ]]; then
+ if [[ $cmd = "bsdtar" ]]; then
$cmd -xf "$file" || ret=$?
else
- rm -f "${file%.*}"
+ rm -f -- "${file%.*}"
$cmd -dcf "$file" > "${file%.*}" || ret=$?
fi
if (( ret )); then
@@ -870,6 +913,40 @@ error_function() {
exit 2 # $E_BUILD_FAILED
}
+cd_safe() {
+ if ! cd "$1"; then
+ error "$(gettext "Failed to change to directory %s")" "$1"
+ plain "$(gettext "Aborting...")"
+ exit 1
+ fi
+}
+
+source_safe() {
+ shopt -u extglob
+ if ! source "$@"; then
+ error "$(gettext "Failed to source %s")" "$1"
+ exit 1
+ fi
+ shopt -s extglob
+}
+
+run_function_safe() {
+ local restoretrap
+
+ set -e
+ set -E
+
+ restoretrap=$(trap -p ERR)
+ trap 'error_function $pkgfunc' ERR
+
+ run_function "$1"
+
+ eval $restoretrap
+
+ set +E
+ set +e
+}
+
run_function() {
if [[ -z $1 ]]; then
return 1
@@ -877,17 +954,17 @@ run_function() {
local pkgfunc="$1"
# clear user-specified buildflags if requested
- if [[ $(check_option buildflags) = "n" ]]; then
+ if check_option "buildflags" "n"; then
unset CFLAGS CXXFLAGS LDFLAGS
fi
# clear user-specified makeflags if requested
- if [[ $(check_option makeflags) = "n" ]]; then
+ if check_option "makeflags" "n"; then
unset MAKEFLAGS
fi
msg "$(gettext "Starting %s()...")" "$pkgfunc"
- cd "$srcdir"
+ cd_safe "$srcdir"
# ensure all necessary build variables are exported
export CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST
@@ -895,7 +972,6 @@ run_function() {
local shellopts=$(shopt -p)
local ret=0
- local restoretrap
if (( LOGGING )); then
local fullver=$(get_full_version)
local BUILDLOG="${startdir}/${pkgbase}-${fullver}-${CARCH}-$pkgfunc.log"
@@ -917,18 +993,12 @@ run_function() {
tee "$BUILDLOG" < "$logpipe" &
local teepid=$!
- restoretrap=$(trap -p ERR)
- trap 'error_function $pkgfunc' ERR
$pkgfunc &>"$logpipe"
- eval $restoretrap
wait $teepid
rm "$logpipe"
else
- restoretrap=$(trap -p ERR)
- trap 'error_function $pkgfunc' ERR
$pkgfunc 2>&1
- eval $restoretrap
fi
# reset our shell options
eval "$shellopts"
@@ -936,21 +1006,21 @@ run_function() {
run_build() {
# use distcc if it is requested (check buildenv and PKGBUILD opts)
- if [[ $(check_buildenv distcc) = "y" && $(check_option distcc) != "n" ]]; then
+ if check_buildenv "distcc" "y" && ! check_option "distc" "n"; then
[[ -d /usr/lib/distcc/bin ]] && export PATH="/usr/lib/distcc/bin:$PATH"
export DISTCC_HOSTS
fi
# use ccache if it is requested (check buildenv and PKGBUILD opts)
- if [[ $(check_buildenv ccache) = "y" && $(check_option ccache) != "n" ]]; then
+ if check_buildenv "ccache" "y" && ! check_option "ccache" "n"; then
[[ -d /usr/lib/ccache/bin ]] && export PATH="/usr/lib/ccache/bin:$PATH"
fi
- run_function "build"
+ run_function_safe "build"
}
run_check() {
- run_function "check"
+ run_function_safe "check"
}
run_package() {
@@ -961,23 +1031,23 @@ run_package() {
pkgfunc="package_$1"
fi
- run_function "$pkgfunc"
+ run_function_safe "$pkgfunc"
}
tidy_install() {
- cd "$pkgdir"
+ cd_safe "$pkgdir"
msg "$(gettext "Tidying install...")"
- if [[ $(check_option docs) = "n" && -n ${DOC_DIRS[*]} ]]; then
+ if check_option "docs" "n" && [[ -n ${DOC_DIRS[*]} ]]; then
msg2 "$(gettext "Removing doc files...")"
- rm -rf ${DOC_DIRS[@]}
+ rm -rf -- ${DOC_DIRS[@]}
fi
- if [[ $(check_option purge) = "y" && -n ${PURGE_TARGETS[*]} ]]; then
+ if check_option "purge" "y" && [[ -n ${PURGE_TARGETS[*]} ]]; then
msg2 "$(gettext "Purging unwanted files...")"
local pt
for pt in "${PURGE_TARGETS[@]}"; do
- if [[ ${pt} = ${pt//\/} ]]; then
+ if [[ ${pt} = "${pt//\/}" ]]; then
find . -type f -name "${pt}" -exec rm -f -- '{}' \;
else
rm -f ${pt}
@@ -985,7 +1055,7 @@ tidy_install() {
done
fi
- if [[ $(check_option zipman) = "y" && -n ${MAN_DIRS[*]} ]]; then
+ if check_option "zipman" "y" && [[ -n ${MAN_DIRS[*]} ]]; then
msg2 "$(gettext "Compressing man and info pages...")"
local manpage ext file link hardlinks hl
find ${MAN_DIRS[@]} -type f 2>/dev/null |
@@ -997,7 +1067,7 @@ tidy_install() {
find ${MAN_DIRS[@]} -lname "$file" 2>/dev/null |
while read link ; do
rm -f "$link" "${link}.gz"
- ln -s "${file}.gz" "${link}.gz"
+ ln -s -- "${file}.gz" "${link}.gz"
done
# check file still exists (potentially already compressed due to hardlink)
@@ -1005,9 +1075,8 @@ tidy_install() {
# find hard links and remove them
# the '|| true' part keeps the script from bailing on the EOF returned
# by read at the end of the find output
- IFS=$'\n' read -rd '' -a hardlinks < \
- <(find ${MAN_DIRS[@]} \! -name "$file" -samefile "$manpage" \
- 2>/dev/null || true) || true
+ mapfile -t hardlinks < \
+ <(find ${MAN_DIRS[@]} ! -name "$file" -samefile "$manpage" 2>/dev/null)
rm -f "${hardlinks[@]}"
# compress the original
gzip -9 "$manpage"
@@ -1021,13 +1090,13 @@ tidy_install() {
done
fi
- if [[ $(check_option strip) = y ]]; then
+ if check_option "strip" "y"; then
msg2 "$(gettext "Stripping unneeded symbols from binaries and libraries...")"
# make sure library stripping variables are defined to prevent excess stripping
[[ -z ${STRIP_SHARED+x} ]] && STRIP_SHARED="-S"
[[ -z ${STRIP_STATIC+x} ]] && STRIP_STATIC="-S"
local binary
- find . -type f -perm -u+w 2>/dev/null | while read binary ; do
+ find . -type f -perm -u+w -print0 2>/dev/null | while read -d '' binary ; do
case "$(file -bi "$binary")" in
*application/x-sharedlib*) # Libraries (.so)
strip $STRIP_SHARED "$binary";;
@@ -1039,17 +1108,17 @@ tidy_install() {
done
fi
- if [[ $(check_option libtool) = "n" ]]; then
+ if check_option "libtool" "n"; then
msg2 "$(gettext "Removing "%s" files...")" "libtool"
find . ! -type d -name "*.la" -exec rm -f -- '{}' \;
fi
- if [[ $(check_option emptydirs) = "n" ]]; then
+ if check_option "emptydirs" "n"; then
msg2 "$(gettext "Removing empty directories...")"
find . -depth -type d -empty -delete
fi
- if [[ $(check_option upx) = "y" ]]; then
+ if check_option "upx" "y"; then
msg2 "$(gettext "Compressing binaries with %s...")" "UPX"
local binary
find . -type f -perm -u+w 2>/dev/null | while read binary ; do
@@ -1078,8 +1147,8 @@ find_libdepends() {
if in_array "${soname}" ${depends[@]}; then
if ! in_array "${soname}=${soversion}-${soarch}" ${libdepends[@]}; then
# libfoo.so=1-64
- echo "${soname}=${soversion}-${soarch}"
- libdepends=(${libdepends[@]} "${soname}=${soversion}-${soarch}")
+ printf "%s" "${soname}=${soversion}-${soarch}"
+ libdepends+=("${soname}=${soversion}-${soarch}")
fi
fi
done
@@ -1087,30 +1156,62 @@ find_libdepends() {
}
find_libprovides() {
- local libprovides
- find "$pkgdir" -type f -name \*.so\* | while read filename
- do
- # check if we really have a shared object
- if LC_ALL=C readelf -h "$filename" 2>/dev/null | grep -q '.*Type:.*DYN (Shared object file).*'; then
- # 64
- soarch=$(LC_ALL=C readelf -h "$filename" | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
- # get the string binaries link to: libfoo.so.1.2 -> libfoo.so.1
- sofile=$(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -n 's/.*Library soname: \[\(.*\)\].*/\1/p')
- [ -z "$sofile" ] && sofile="${filename##*/}"
-
- # extract the library name: libfoo.so
- soname="${sofile%%\.so\.*}.so"
- # extract the major version: 1
- soversion="${sofile##*\.so\.}"
- if in_array "${soname}" ${provides[@]}; then
- if ! in_array "${soname}=${soversion}-${soarch}" ${libprovides[@]}; then
- # libfoo.so=1-64
- echo "${soname}=${soversion}-${soarch}"
- libprovides=(${libprovides[@]} "${soname}=${soversion}-${soarch}")
+ local libprovides missing
+ for p in "${provides[@]}"; do
+ missing=0
+ case "$p" in
+ *.so)
+ mapfile -t filename < <(find "$pkgdir" -type f -name $p\*)
+ if [[ $filename ]]; then
+ # packages may provide multiple versions of the same library
+ for fn in "${filename[@]}"; do
+ # check if we really have a shared object
+ if LC_ALL=C readelf -h "$fn" 2>/dev/null | grep -q '.*Type:.*DYN (Shared object file).*'; then
+ # get the string binaries link to (e.g. libfoo.so.1.2 -> libfoo.so.1)
+ local sofile=$(LC_ALL=C readelf -d "$fn" 2>/dev/null | sed -n 's/.*Library soname: \[\(.*\)\].*/\1/p')
+ if [[ -z "$sofile" ]]; then
+ warning "$(gettext "Library listed in %s is not versioned: %s")" "'provides'" "$p"
+ libprovides+=("$p")
+ continue
+ fi
+
+ # get the library architecture (32 or 64 bit)
+ local soarch=$(LC_ALL=C readelf -h "$fn" | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
+
+ # extract the library major version
+ local soversion="${sofile##*\.so\.}"
+
+ libprovides+=("${p}=${soversion}-${soarch}")
+ else
+ warning "$(gettext "Library listed in %s is not a shared object: %s")" "'provides'" "$p"
+ libprovides+=("$p")
+ fi
+ done
+ else
+ libprovides+=("$p")
+ missing=1
fi
- fi
- fi
+ ;;
+ *)
+ libprovides+=("$p")
+ ;;
+ esac
+
+ if (( missing )); then
+ warning "$(gettext "Can not find library listed in %s: %s")" "'provides'" "$p"
+ fi
done
+
+ printf '%s\n' "${libprovides[@]}"
+}
+
+check_license() {
+ # TODO maybe remove this at some point
+ # warn if license array is not present or empty
+ if [[ -z $license ]]; then
+ warning "$(gettext "Please add a license line to your %s!")" "$BUILDSCRIPT"
+ plain "$(gettext "Example for GPL\'ed software: %s.")" "license=('GPL')"
+ fi
}
write_pkginfo() {
@@ -1135,29 +1236,31 @@ write_pkginfo() {
echo "# using $(fakeroot -v)"
fi
echo "# $(LC_ALL=C date -u)"
- echo "pkgname = $1"
+ printf "pkgname = %s\n" "$1"
(( SPLITPKG )) && echo pkgbase = $pkgbase
echo "pkgver = $(get_full_version)"
- echo "pkgdesc = $pkgdesc"
- echo "url = $url"
- echo "builddate = $builddate"
- echo "packager = $packager"
- echo "size = $size"
- echo "arch = $PKGARCH"
+ printf "pkgdesc = %s\n" "$pkgdesc"
+ printf "url = %s\n" "$url"
+ printf "builddate = %s\n" "$builddate"
+ printf "packager = %s\n" "$packager"
+ printf "size = %s\n" "$size"
+ printf "arch = %s\n" "$pkgarch"
[[ $license ]] && printf "license = %s\n" "${license[@]}"
[[ $replaces ]] && printf "replaces = %s\n" "${replaces[@]}"
[[ $groups ]] && printf "group = %s\n" "${groups[@]}"
[[ $optdepends ]] && printf "optdepend = %s\n" "${optdepends[@]//+([[:space:]])/ }"
[[ $conflicts ]] && printf "conflict = %s\n" "${conflicts[@]}"
+
+ mapfile -t provides < <(find_libprovides)
+ [[ $provides ]] && printf "provides = %s\n" "${provides[@]}"
+
[[ $backup ]] && printf "backup = %s\n" "${backup[@]}"
- local it
- libprovides=$(find_libprovides)
- libdepends=$(find_libdepends)
- provides=("${provides[@]}" ${libprovides})
- depends=("${depends[@]}" ${libdepends})
+ local it
+ mapfile -t libdepends < <(find_libdepends)
+ depends+=("${libdepends[@]}")
for it in "${depends[@]}"; do
if [[ $it = *.so ]]; then
@@ -1169,45 +1272,27 @@ write_pkginfo() {
return 1
fi
else
- echo "depend = $it"
- fi
- done
-
- for it in "${provides[@]}"; do
- # ignore versionless entires (those come from the PKGBUILD)
- if [[ $it = *.so ]]; then
- # check if the entry has been found by find_libprovides
- # if not, it's unneeded; tell the user so he can remove it
- if [[ ! $libprovides =~ (^|\s)${it}=.* ]]; then
- error "$(gettext "Cannot find library listed in %s: %s")" "'provides'" "$it"
- return 1
- fi
- else
- echo "provides = $it"
+ printf "depend = %s\n" "$it"
fi
done
for it in "${packaging_options[@]}"; do
- local ret="$(check_option $it)"
- if [[ $ret != "?" ]]; then
- if [[ $ret = y ]]; then
- echo "makepkgopt = $it"
- else
- echo "makepkgopt = !$it"
- fi
- fi
+ check_option "$it" "y"
+ case $? in
+ 0)
+ printf "makepkgopt = %s\n" "$it"
+ ;;
+ 1)
+ printf "makepkgopt = %s\n" "!$it"
+ ;;
+ esac
done
- # TODO maybe remove this at some point
- # warn if license array is not present or empty
- if [[ -z $license ]]; then
- warning "$(gettext "Please add a license line to your %s!")" "$BUILDSCRIPT"
- plain "$(gettext "Example for GPL\'ed software: %s.")" "license=('GPL')"
- fi
+ check_license
}
check_package() {
- cd "$pkgdir"
+ cd_safe "$pkgdir"
# check existence of backup files
local file
@@ -1236,7 +1321,7 @@ create_package() {
check_package
- cd "$pkgdir"
+ cd_safe "$pkgdir"
msg "$(gettext "Creating package...")"
local nameofpkg
@@ -1246,15 +1331,11 @@ create_package() {
nameofpkg="$1"
fi
- if [[ $arch = "any" ]]; then
- PKGARCH="any"
- else
- PKGARCH=$CARCH
- fi
+ pkgarch=$(get_pkg_arch)
write_pkginfo $nameofpkg > .PKGINFO
- local comp_files=".PKGINFO"
+ local comp_files=('.PKGINFO')
# check for changelog/install files
for i in 'changelog/.CHANGELOG' 'install/.INSTALL'; do
@@ -1264,7 +1345,7 @@ create_package() {
msg2 "$(gettext "Adding %s file...")" "$orig"
cp "$startdir/${!orig}" "$dest"
chmod 644 "$dest"
- comp_files+=" $dest"
+ comp_files+=("$dest")
fi
done
@@ -1272,7 +1353,7 @@ create_package() {
msg2 "$(gettext "Compressing package...")"
local fullver=$(get_full_version)
- local pkg_file="$PKGDEST/${nameofpkg}-${fullver}-${PKGARCH}${PKGEXT}"
+ local pkg_file="$PKGDEST/${nameofpkg}-${fullver}-${pkgarch}${PKGEXT}"
local ret=0
[[ -f $pkg_file ]] && rm -f "$pkg_file"
@@ -1286,12 +1367,12 @@ create_package() {
# bsdtar's gzip compression always saves the time stamp, making one
# archive created using the same command line distinct from another.
# Disable bsdtar compression and use gzip -n for now.
- bsdtar -cf - $comp_files * |
+ bsdtar -cf - "${comp_files[@]}" * |
case "$PKGEXT" in
- *tar.gz) gzip -c -f -n ;;
- *tar.bz2) bzip2 -c -f ;;
- *tar.xz) xz -c -z - ;;
- *tar.Z) compress -c -f ;;
+ *tar.gz) ${COMPRESSGZ[@]:-gzip -c -f -n} ;;
+ *tar.bz2) ${COMPRESSBZ2[@]:-bzip2 -c -f} ;;
+ *tar.xz) ${COMPRESSXZ[@]:-xz -c -z -} ;;
+ *tar.Z) ${COMPRESSZ[@]:-compress -c -f} ;;
*tar) cat ;;
*) warning "$(gettext "'%s' is not a valid archive extension.")" \
"$PKGEXT"; cat ;;
@@ -1351,12 +1432,14 @@ create_srcpackage() {
local srclinks="$(mktemp -d "$startdir"/srclinks.XXXXXXXXX)"
mkdir "${srclinks}"/${pkgbase}
+ check_license
+
msg2 "$(gettext "Adding %s...")" "$BUILDSCRIPT"
ln -s "${BUILDFILE}" "${srclinks}/${pkgbase}/${BUILDSCRIPT}"
local file
for file in "${source[@]}"; do
- if [[ "$file" == $(get_filename "$file") ]] || (( SOURCEONLY == 2 )); then
+ if [[ "$file" = "$(get_filename "$file")" ]] || (( SOURCEONLY == 2 )); then
local absfile
absfile=$(get_filepath "$file") || missing_source_file "$file"
msg2 "$(gettext "Adding %s...")" "${absfile##*/}"
@@ -1393,7 +1476,7 @@ create_srcpackage() {
# tar it up
msg2 "$(gettext "Compressing source package...")"
- cd "${srclinks}"
+ cd_safe "${srclinks}"
if ! bsdtar -c${TAR_OPT}Lf "$pkg_file" ${pkgbase}; then
error "$(gettext "Failed to create source package file.")"
exit 1 # TODO: error code
@@ -1409,7 +1492,7 @@ create_srcpackage() {
warning "$(gettext "Failed to create symlink to source package file.")"
fi
- cd "${startdir}"
+ cd_safe "${startdir}"
rm -rf "${srclinks}"
}
@@ -1422,17 +1505,14 @@ install_package() {
msg "$(gettext "Installing %s package group with %s...")" "$pkgbase" "$PACMAN -U"
fi
- local fullver pkg pkglist
+ local fullver pkgarch pkg pkglist
for pkg in ${pkgname[@]}; do
fullver=$(get_full_version $pkg)
- if [[ -f $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT} ]]; then
- pkglist+=" $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT}"
- else
- pkglist+=" $PKGDEST/${pkg}-${fullver}-any${PKGEXT}"
- fi
+ pkgarch=$(get_pkg_arch $pkg)
+ pkglist+=("$PKGDEST/${pkg}-${fullver}-${pkgarch}${PKGEXT}")
done
- if ! run_pacman -U $pkglist; then
+ if ! run_pacman -U ${pkglist[@]}; then
warning "$(gettext "Failed to install built package(s).")"
return 0
fi
@@ -1478,8 +1558,8 @@ check_sanity() {
awk -F'=' '$1 ~ /^[[:space:]]*pkgrel$/' "$BUILDFILE" | sed "s/[[:space:]]*#.*//" |
while IFS='=' read -r _ i; do
eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\"
- if [[ $i = *[[:space:]-]* ]]; then
- error "$(gettext "%s is not allowed to contain hyphens or whitespace.")" "pkgrel"
+ if [[ $i != +([0-9])?(.+([0-9])) ]]; then
+ error "$(gettext "%s must be a decimal.")" "pkgrel"
return 1
fi
done || ret=1
@@ -1571,7 +1651,7 @@ check_sanity() {
known=0
# check if option matches a known option or its inverse
for kopt in ${packaging_options[@]} ${other_options[@]}; do
- if [[ ${i} = ${kopt} || ${i} = "!${kopt}" ]]; then
+ if [[ ${i} = "${kopt}" || ${i} = "!${kopt}" ]]; then
known=1
fi
done
@@ -1610,12 +1690,12 @@ check_software() {
# check for sudo if we will need it during makepkg execution
if (( ! ( ASROOT || INFAKEROOT ) && ( DEP_BIN || RMDEPS || INSTALL ) )); then
if ! type -p sudo >/dev/null; then
- warning "$(gettext "Sudo can not be found. Will use su to acquire root privileges.")"
+ warning "$(gettext "Cannot find the %s binary. Will use %s to acquire root privileges.")" "sudo" "su"
fi
fi
# fakeroot - building as non-root user
- if [[ $(check_buildenv fakeroot) = "y" ]] && (( EUID > 0 )); then
+ if check_buildenv "fakeroot" "y" && (( EUID > 0 )); then
if ! type -p fakeroot >/dev/null; then
error "$(gettext "Cannot find the %s binary required for building as non-root user.")" "fakeroot"
ret=1
@@ -1623,7 +1703,7 @@ check_software() {
fi
# gpg - package signing
- if [[ $SIGNPKG == 'y' || (-z "$SIGNPKG" && $(check_buildenv sign) == 'y') ]]; then
+ if [[ $SIGNPKG == 'y' ]] || { [[ -z $SIGNPKG ]] && check_buildenv "sign" "y"; }; then
if ! type -p gpg >/dev/null; then
error "$(gettext "Cannot find the %s binary required for signing packages.")" "gpg"
ret=1
@@ -1647,7 +1727,7 @@ check_software() {
fi
# upx - binary compression
- if [[ $(check_option upx) == 'y' ]]; then
+ if check_option "upx" "y"; then
if ! type -p upx >/dev/null; then
error "$(gettext "Cannot find the %s binary required for compressing binaries.")" "upx"
ret=1
@@ -1655,7 +1735,7 @@ check_software() {
fi
# distcc - compilation with distcc
- if [[ $(check_buildenv distcc) = "y" && $(check_option distcc) != "n" ]]; then
+ if check_buildenv "distcc" "y" && ! check_option "distcc" "n" ]]; then
if ! type -p distcc >/dev/null; then
error "$(gettext "Cannot find the %s binary required for distributed compilation.")" "distcc"
ret=1
@@ -1663,7 +1743,7 @@ check_software() {
fi
# ccache - compilation with ccache
- if [[ $(check_buildenv ccache) = "y" && $(check_option ccache) != "n" ]]; then
+ if check_buildenv "ccache" "y" && ! check_option "ccache" "n"; then
if ! type -p ccache >/dev/null; then
error "$(gettext "Cannot find the %s binary required for compiler cache usage.")" "ccache"
ret=1
@@ -1671,7 +1751,7 @@ check_software() {
fi
# strip - strip symbols from binaries/libraries
- if [[ $(check_option strip) = "y" ]]; then
+ if check_option "strip" "y"; then
if ! type -p strip >/dev/null; then
error "$(gettext "Cannot find the %s binary required for object file stripping.")" "strip"
ret=1
@@ -1679,7 +1759,7 @@ check_software() {
fi
# gzip - compressig man and info pages
- if [[ $(check_option zipman) = "y" ]]; then
+ if check_option "zipman" "y"; then
if ! type -p gzip >/dev/null; then
error "$(gettext "Cannot find the %s binary required for compressing man and info pages.")" "gzip"
ret=1
@@ -1695,7 +1775,7 @@ devel_check() {
# Do not update pkgver if --holdver is set, when building a source package, repackaging,
# reading PKGBUILD from pipe (-f), or if we cannot write to the file (-w)
if (( HOLDVER || SOURCEONLY || REPKG )) ||
- [[ ! -f $BUILDFILE || ! -w $BUILDFILE || $BUILDFILE = /dev/stdin ]]; then
+ [[ ! -f $BUILDFILE || ! -w $BUILDFILE || $BUILDFILE = "/dev/stdin" ]]; then
return
fi
@@ -1705,66 +1785,67 @@ devel_check() {
# calls to makepkg via fakeroot will explicitly pass the version
# number to avoid having to determine the version number twice.
# Also do a check to make sure we have the VCS tool available.
- oldpkgver=$pkgver
- if [[ -n ${_darcstrunk} && -n ${_darcsmod} ]] ; then
- if ! type -p darcs >/dev/null; then
- warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "darcs" "darcs"
- return 0
- fi
- msg "$(gettext "Determining latest %s revision...")" 'darcs'
- newpkgver=$(date +%Y%m%d)
- elif [[ -n ${_cvsroot} && -n ${_cvsmod} ]] ; then
- if ! type -p cvs >/dev/null; then
- warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "cvs" "cvs"
- return 0
- fi
- msg "$(gettext "Determining latest %s revision...")" 'cvs'
- newpkgver=$(date +%Y%m%d)
- elif [[ -n ${_gitroot} && -n ${_gitname} ]] ; then
- if ! type -p git >/dev/null; then
- warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "git" "git"
- return 0
- fi
- msg "$(gettext "Determining latest %s revision...")" 'git'
- newpkgver=$(date +%Y%m%d)
- elif [[ -n ${_svntrunk} && -n ${_svnmod} ]] ; then
- if ! type -p svn >/dev/null; then
- warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "svn" "svn"
- return 0
- fi
- msg "$(gettext "Determining latest %s revision...")" 'svn'
- newpkgver=$(LC_ALL=C svn info $_svntrunk | sed -n 's/^Last Changed Rev: \([0-9]*\)$/\1/p')
- elif [[ -n ${_bzrtrunk} && -n ${_bzrmod} ]] ; then
- if ! type -p bzr >/dev/null; then
- warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "bzr" "bzr"
- return 0
- fi
- msg "$(gettext "Determining latest %s revision...")" 'bzr'
- newpkgver=$(bzr revno ${_bzrtrunk})
- elif [[ -n ${_hgroot} && -n ${_hgrepo} ]] ; then
- if ! type -p hg >/dev/null; then
- warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "hg" "hg"
- return 0
- fi
- msg "$(gettext "Determining latest %s revision...")" 'hg'
- if [[ -d ./src/$_hgrepo ]] ; then
- cd ./src/$_hgrepo
- local ret=0
- hg pull || ret=$?
- if (( ! ret )); then
- hg update
- elif (( ret != 1 )); then
- return 1
- fi
- else
- [[ ! -d ./src/ ]] && mkdir ./src/
- hg clone $_hgroot/$_hgrepo ./src/$_hgrepo
- cd ./src/$_hgrepo
- fi
- newpkgver=$(hg tip --template "{rev}")
- cd ../../
+ local vcs=()
+
+ [[ -n ${_darcstrunk} && -n ${_darcsmod} ]] && vcs+=("darcs")
+ [[ -n ${_cvsroot} && -n ${_cvsmod} ]] && vcs+=("cvs")
+ [[ -n ${_gitroot} && -n ${_gitname} ]] && vcs+=("git")
+ [[ -n ${_svntrunk} && -n ${_svnmod} ]] && vcs+=("svn")
+ [[ -n ${_bzrtrunk} && -n ${_bzrmod} ]] && vcs+=("bzr")
+ [[ -n ${_hgroot} && -n ${_hgrepo} ]] && vcs+=("hg")
+
+ if (( ${#vcs[@]} == 0 )); then
+ return
+ elif (( ${#vcs[@]} > 1 )); then
+ warning "$(gettext "Ambiguous VCS package. Cannot pick from: %s.")" "${vcs[*]}"
+ return 0
fi
+ if ! type -p "$vcs" >/dev/null; then
+ warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "$vcs" "$vcs"
+ return 0
+ fi
+
+ msg "$(gettext "Determining latest %s revision...")" "$vcs"
+
+ case "$vcs" in
+ darcs)
+ newpkgver=$(date +%Y%m%d)
+ ;;
+ cvs)
+ newpkgver=$(date +%Y%m%d)
+ ;;
+ git)
+ newpkgver=$(date +%Y%m%d)
+ ;;
+ svn)
+ newpkgver=$(LC_ALL=C svn info $_svntrunk | sed -n 's/^Last Changed Rev: \([0-9]*\)$/\1/p')
+ ;;
+ bzr)
+ newpkgver=$(bzr revno ${_bzrtrunk})
+ ;;
+ hg)
+ if pushd "./src/$_hgrepo" > /dev/null; then
+ local ret=0
+ hg pull || ret=$?
+ if (( ! ret )); then
+ hg update
+ elif (( ret != 1 )); then
+ return 1
+ fi
+ else
+ [[ ! -d ./src/ ]] && mkdir ./src/
+ hg clone "$_hgroot/$_hgrepo" "./src/$_hgrepo"
+ if ! pushd "./src/$_hgrepo" > /dev/null; then
+ warning "$(gettext "An error occured while determining the hg version number.")"
+ return 0
+ fi
+ fi
+ newpkgver=$(hg tip --template "{rev}")
+ popd > /dev/null
+ ;;
+ esac
+
if [[ -n $newpkgver ]]; then
msg2 "$(gettext "Version found: %s")" "$newpkgver"
fi
@@ -1785,13 +1866,13 @@ devel_update() {
# ...
# _foo=pkgver
#
- if [[ -n $newpkgver ]]; then
- if [[ $newpkgver != "$pkgver" ]]; then
- if [[ -f $BUILDFILE && -w $BUILDFILE ]]; then
- @SEDINPLACE@ "s/^pkgver=[^ ]*/pkgver=$newpkgver/" "$BUILDFILE"
- @SEDINPLACE@ "s/^pkgrel=[^ ]*/pkgrel=1/" "$BUILDFILE"
- source "$BUILDFILE"
- fi
+ if [[ -n $newpkgver && $newpkgver != "$pkgver" ]]; then
+ if [[ -f $BUILDFILE && -w $BUILDFILE ]]; then
+ @SEDINPLACE@ "s/^pkgver=[^ ]*/pkgver=$newpkgver/" "$BUILDFILE"
+ @SEDINPLACE@ "s/^pkgrel=[^ ]*/pkgrel=1/" "$BUILDFILE"
+ source "$BUILDFILE"
+ else
+ warning "$(gettext "%s is not writeable -- pkgver will not be updated")" "$BUILDFILE"
fi
fi
}
@@ -1838,15 +1919,15 @@ canonicalize_path() {
if [[ -d $path ]]; then
(
- cd "$path"
+ cd_safe "$path"
pwd -P
)
else
- echo "$path"
+ printf "%s\n" "$path"
fi
}
-m4_include(library/parse_options.sh)
+m4_include(library/parseopts.sh)
usage() {
printf "makepkg (pacman) %s\n" "$myver"
@@ -1907,7 +1988,7 @@ There is NO WARRANTY, to the extent permitted by law.\n")"
# determine whether we have gettext; make it a no-op if we do not
if ! type -p gettext >/dev/null; then
gettext() {
- echo "$@"
+ printf "%s\n" "$@"
}
fi
@@ -1915,19 +1996,20 @@ ARGLIST=("$@")
# Parse Command Line Options.
OPT_SHORT="AcdefFghiLmop:rRsSV"
-OPT_LONG="allsource,asroot,ignorearch,check,clean,nodeps"
-OPT_LONG+=",noextract,force,forcever:,geninteg,help,holdver,skippgpcheck"
-OPT_LONG+=",install,key:,log,nocolor,nobuild,nocheck,nosign,pkg:,rmdeps"
-OPT_LONG+=",repackage,skipchecksums,skipinteg,skippgpcheck,sign,source,syncdeps"
-OPT_LONG+=",version,config:"
+OPT_LONG=('allsource' 'asroot' 'ignorearch' 'check' 'clean' 'nodeps'
+ 'noextract' 'force' 'forcever:' 'geninteg' 'help' 'holdver' 'skippgpcheck'
+ 'install' 'key:' 'log' 'nocolor' 'nobuild' 'nocheck' 'nosign' 'pkg:' 'rmdeps'
+ 'repackage' 'skipchecksums' 'skipinteg' 'skippgpcheck' 'sign' 'source' 'syncdeps'
+ 'version' 'config:')
# Pacman Options
-OPT_LONG+=",noconfirm,noprogressbar"
-if ! OPT_TEMP="$(parse_options $OPT_SHORT $OPT_LONG "$@")"; then
- echo; usage; exit 1 # E_INVALID_OPTION;
+OPT_LONG+=('noconfirm' 'noprogressbar')
+
+if ! parseopts "$OPT_SHORT" "${OPT_LONG[@]}" -- "$@"; then
+ exit 1 # E_INVALID_OPTION;
fi
-eval set -- "$OPT_TEMP"
-unset OPT_SHORT OPT_LONG OPT_TEMP
+set -- "${OPTRET[@]}"
+unset OPT_SHORT OPT_LONG OPTRET
while true; do
case "$1" in
@@ -1958,7 +2040,7 @@ while true; do
--nosign) SIGNPKG='n' ;;
-o|--nobuild) NOBUILD=1 ;;
-p) shift; BUILDFILE=$1 ;;
- --pkg) shift; PKGLIST=($1) ;;
+ --pkg) shift; IFS=, read -ra p <<<"$1"; PKGLIST+=("${p[@]}"); unset p ;;
-r|--rmdeps) RMDEPS=1 ;;
-R|--repackage) REPKG=1 ;;
--skipchecksums) SKIPCHECKSUMS=1 ;;
@@ -1971,8 +2053,7 @@ while true; do
-h|--help) usage; exit 0 ;; # E_OK
-V|--version) version; exit 0 ;; # E_OK
- --) OPT_IND=0; shift; break;;
- *) usage; exit 1 ;; # E_INVALID_OPTION
+ --) OPT_IND=0; shift; break 2;;
esac
shift
done
@@ -1984,7 +2065,6 @@ for signal in TERM HUP QUIT; do
done
trap 'trap_exit INT "$(gettext "Aborted by user! Exiting...")"' INT
trap 'trap_exit USR1 "$(gettext "An unknown error has occurred. Exiting...")"' ERR
-set -E
# preserve environment variables and canonicalize path
[[ -n ${PKGDEST} ]] && _PKGDEST=$(canonicalize_path ${PKGDEST})
@@ -1994,13 +2074,14 @@ set -E
[[ -n ${PKGEXT} ]] && _PKGEXT=${PKGEXT}
[[ -n ${SRCEXT} ]] && _SRCEXT=${SRCEXT}
[[ -n ${GPGKEY} ]] && _GPGKEY=${GPGKEY}
+[[ -n ${PACKAGER} ]] && _PACKAGER=${PACKAGER}
# default config is makepkg.conf
MAKEPKG_CONF=${MAKEPKG_CONF:-$confdir/makepkg.conf}
# Source the config file; fail if it is not found
if [[ -r $MAKEPKG_CONF ]]; then
- source "$MAKEPKG_CONF"
+ source_safe "$MAKEPKG_CONF"
else
error "$(gettext "%s not found.")" "$MAKEPKG_CONF"
plain "$(gettext "Aborting...")"
@@ -2010,7 +2091,7 @@ fi
# Source user-specific makepkg.conf overrides, but only if no override config
# file was specified
if [[ $MAKEPKG_CONF = "$confdir/makepkg.conf" && -r ~/.makepkg.conf ]]; then
- source ~/.makepkg.conf
+ source_safe ~/.makepkg.conf
fi
# set pacman command if not already defined
@@ -2018,7 +2099,7 @@ PACMAN=${PACMAN:-pacman}
# check if messages are to be printed using color
unset ALL_OFF BOLD BLUE GREEN RED YELLOW
-if [[ -t 2 && ! $USE_COLOR = "n" && $(check_buildenv color) = "y" ]]; then
+if [[ -t 2 && ! $USE_COLOR = "n" ]] && check_buildenv "color" "y"; then
# prefer terminal safe colored and bold text when tput is supported
if tput setaf 0 &>/dev/null; then
ALL_OFF="$(tput sgr0)"
@@ -2042,8 +2123,11 @@ readonly ALL_OFF BOLD BLUE GREEN RED YELLOW
BUILDDIR=${_BUILDDIR:-$BUILDDIR}
BUILDDIR=${BUILDDIR:-$startdir} #default to $startdir if undefined
if [[ ! -d $BUILDDIR ]]; then
- mkdir -p "$BUILDDIR" ||
- error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
+ if ! mkdir -p "$BUILDDIR"; then
+ error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
+ plain "$(gettext "Aborting...")"
+ exit 1
+ fi
chmod a-s "$BUILDDIR"
fi
if [[ ! -w $BUILDDIR ]]; then
@@ -2051,8 +2135,6 @@ if [[ ! -w $BUILDDIR ]]; then
plain "$(gettext "Aborting...")"
exit 1
fi
-srcdir="$BUILDDIR/src"
-pkgdir="$BUILDDIR/pkg"
PKGDEST=${_PKGDEST:-$PKGDEST}
PKGDEST=${PKGDEST:-$startdir} #default to $startdir if undefined
@@ -2081,6 +2163,7 @@ fi
PKGEXT=${_PKGEXT:-$PKGEXT}
SRCEXT=${_SRCEXT:-$SRCEXT}
GPGKEY=${_GPGKEY:-$GPGKEY}
+PACKAGER=${_PACKAGER:-$PACKAGER}
if (( HOLDVER )) && [[ -n $FORCE_VER ]]; then
# The '\\0' is here to prevent gettext from thinking --holdver is an option
@@ -2100,7 +2183,7 @@ use the %s option.")" "makepkg" "--asroot"
error "$(gettext "The %s option is meant for the root user only. Please\n\
rerun %s without the %s flag.")" "--asroot" "makepkg" "--asroot"
exit 1 # $E_USER_ABORT
- elif (( EUID > 0 )) && [[ $(check_buildenv fakeroot) != "y" ]]; then
+ elif (( EUID > 0 )) && ! check_buildenv "fakeroot" "y"; then
warning "$(gettext "Running %s as an unprivileged user will result in non-root\n\
ownership of the packaged files. Try using the %s environment by\n\
placing %s in the %s array in %s.")" "makepkg" "fakeroot" "'fakeroot'" "BUILDENV" "$MAKEPKG_CONF"
@@ -2125,9 +2208,7 @@ if [[ ! -f $BUILDFILE ]]; then
else
# PKGBUILD passed through a pipe
BUILDFILE=/dev/stdin
- shopt -u extglob
- source "$BUILDFILE"
- shopt -s extglob
+ source_safe "$BUILDFILE"
fi
else
crlftest=$(file "$BUILDFILE" | grep -F 'CRLF' || true)
@@ -2139,19 +2220,25 @@ else
if [[ ${BUILDFILE:0:1} != "/" ]]; then
BUILDFILE="$startdir/$BUILDFILE"
fi
- shopt -u extglob
- source "$BUILDFILE"
- shopt -s extglob
+ source_safe "$BUILDFILE"
fi
# set defaults if they weren't specified in buildfile
pkgbase=${pkgbase:-${pkgname[0]}}
epoch=${epoch:-0}
+if [[ $BUILDDIR = "$startdir" ]]; then
+ srcdir="$BUILDDIR/src"
+ pkgdir="$BUILDDIR/pkg"
+else
+ srcdir="$BUILDDIR/$pkgbase/src"
+ pkgdir="$BUILDDIR/$pkgbase/pkg"
+fi
+
if (( GENINTEG )); then
mkdir -p "$srcdir"
chmod a-s "$srcdir"
- cd "$srcdir"
+ cd_safe "$srcdir"
download_sources
generate_checksums
exit 0 # $E_OK
@@ -2180,7 +2267,7 @@ if declare -f build >/dev/null; then
fi
if declare -f check >/dev/null; then
# "Hide" check() function if not going to be run
- if [[ $RUN_CHECK = 'y' || (! $(check_buildenv check) = "n" && ! $RUN_CHECK = "n") ]]; then
+ if [[ $RUN_CHECK = 'y' ]] || { ! check_buildenv "check" "n" && [[ $RUN_CHECK != "n" ]]; }; then
CHECKFUNC=1
fi
fi
@@ -2196,8 +2283,7 @@ if [[ -n "${PKGLIST[@]}" ]]; then
fi
# check if gpg signature is to be created and if signing key is valid
-[[ -z $SIGNPKG ]] && SIGNPKG=$(check_buildenv sign)
-if [[ $SIGNPKG == 'y' ]]; then
+if { [[ -z $SIGNPKG ]] && check_buildenv "sign" "y"; } || [[ $SIGNPKG == 'y' ]]; then
if ! gpg --list-key ${GPGKEY} &>/dev/null; then
if [[ ! -z $GPGKEY ]]; then
error "$(gettext "The key %s does not exist in your keyring.")" "${GPGKEY}"
@@ -2211,8 +2297,8 @@ fi
if (( ! SPLITPKG )); then
fullver=$(get_full_version)
- if [[ -f $PKGDEST/${pkgname}-${fullver}-${CARCH}${PKGEXT} \
- || -f $PKGDEST/${pkgname}-${fullver}-any${PKGEXT} ]] \
+ pkgarch=$(get_pkg_arch)
+ if [[ -f $PKGDEST/${pkgname}-${fullver}-${pkgarch}${PKGEXT} ]] \
&& ! (( FORCE || SOURCEONLY || NOBUILD )); then
if (( INSTALL )); then
warning "$(gettext "A package has already been built, installing existing package...")"
@@ -2228,8 +2314,8 @@ else
somepkgbuilt=0
for pkg in ${pkgname[@]}; do
fullver=$(get_full_version $pkg)
- if [[ -f $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT} \
- || -f $PKGDEST/${pkg}-${fullver}-any${PKGEXT} ]]; then
+ pkgarch=$(get_pkg_arch $pkg)
+ if [[ -f $PKGDEST/${pkg}-${fullver}-${pkgarch}${PKGEXT} ]]; then
somepkgbuilt=1
else
allpkgbuilt=0
@@ -2301,17 +2387,17 @@ if (( SOURCEONLY )); then
# Get back to our src directory so we can begin with sources.
mkdir -p "$srcdir"
chmod a-s "$srcdir"
- cd "$srcdir"
+ cd_safe "$srcdir"
if ( (( ! SKIPCHECKSUMS )) || \
( (( ! SKIPPGPCHECK )) && source_has_signatures ) ) || \
(( SOURCEONLY == 2 )); then
download_sources
fi
check_source_integrity
- cd "$startdir"
+ cd_safe "$startdir"
# if we are root or if fakeroot is not enabled, then we don't use it
- if [[ $(check_buildenv fakeroot) != "y" ]] || (( EUID == 0 )); then
+ if ! check_buildenv "fakeroot" "y" || (( EUID == 0 )); then
create_srcpackage
else
enter_fakeroot
@@ -2364,7 +2450,7 @@ umask 0022
# get back to our src directory so we can begin with sources
mkdir -p "$srcdir"
chmod a-s "$srcdir"
-cd "$srcdir"
+cd_safe "$srcdir"
if (( NOEXTRACT )); then
warning "$(gettext "Skipping source retrieval -- using existing %s tree")" "src/"
@@ -2400,10 +2486,10 @@ else
fi
mkdir -p "$pkgdir"
chmod a-s "$pkgdir"
- cd "$startdir"
+ cd_safe "$startdir"
# if we are root or if fakeroot is not enabled, then we don't use it
- if [[ $(check_buildenv fakeroot) != "y" ]] || (( EUID == 0 )); then
+ if ! check_buildenv "fakeroot" "y" || (( EUID == 0 )); then
if (( ! REPKG )); then
devel_update
(( BUILDFUNC )) && run_build
@@ -2430,7 +2516,7 @@ else
devel_update
(( BUILDFUNC )) && run_build
(( CHECKFUNC )) && run_check
- cd "$startdir"
+ cd_safe "$startdir"
fi
enter_fakeroot
diff --git a/scripts/pacman-db-upgrade.sh.in b/scripts/pacman-db-upgrade.sh.in
index e0a049c5..894152f6 100644
--- a/scripts/pacman-db-upgrade.sh.in
+++ b/scripts/pacman-db-upgrade.sh.in
@@ -23,7 +23,7 @@
export TEXTDOMAIN='pacman-scripts'
export TEXTDOMAINDIR='@localedir@'
-myver='@PACKAGE_VERSION@'
+declare -r myver='@PACKAGE_VERSION@'
eval $(awk '/DBPath/ {print $1$2$3}' @sysconfdir@/pacman.conf)
dbroot="${DBPath:-@localstatedir@/lib/pacman/}"
diff --git a/scripts/pacman-key.sh.in b/scripts/pacman-key.sh.in
index 948c8d52..ae491d26 100644
--- a/scripts/pacman-key.sh.in
+++ b/scripts/pacman-key.sh.in
@@ -24,7 +24,7 @@
export TEXTDOMAIN='pacman-scripts'
export TEXTDOMAINDIR='@localedir@'
-myver="@PACKAGE_VERSION@"
+declare -r myver="@PACKAGE_VERSION@"
# Options
ADD=0
@@ -49,40 +49,43 @@ DEFAULT_KEYSERVER='hkp://pool.sks-keyservers.net'
m4_include(library/output_format.sh)
-m4_include(library/parse_options.sh)
+m4_include(library/parseopts.sh)
usage() {
printf "pacman-key (pacman) %s\n" ${myver}
echo
- printf -- "$(gettext "Usage: %s [options]")\n" $(basename $0)
+ printf -- "$(gettext "Usage: %s [options] operation [targets]")\n" $(basename $0)
echo
printf -- "$(gettext "Manage pacman's list of trusted keys")\n"
echo
- printf -- "$(gettext "Options:")\n"
- printf -- "$(gettext " -a, --add [file(s)] Add the specified keys (empty for stdin)")\n"
- printf -- "$(gettext " -d, --delete <keyid(s)> Remove the specified keyids")\n"
- printf -- "$(gettext " -e, --export [keyid(s)] Export the specified or all keyids")\n"
- printf -- "$(gettext " -f, --finger [keyid(s)] List fingerprint for specified or all keyids")\n"
- printf -- "$(gettext " -h, --help Show this help message and exit")\n"
- printf -- "$(gettext " -l, --list-keys [keyid(s)] List the specified or all keys")\n"
- printf -- "$(gettext " -r, --recv-keys <keyid(s)> Fetch the specified keyids")\n"
+ printf -- "$(gettext "Operations:")\n"
+ printf -- "$(gettext " -a, --add Add the specified keys (empty for stdin)")\n"
+ printf -- "$(gettext " -d, --delete Remove the specified keyids")\n"
+ printf -- "$(gettext " -e, --export Export the specified or all keyids")\n"
+ printf -- "$(gettext " -f, --finger List fingerprint for specified or all keyids")\n"
+ printf -- "$(gettext " -l, --list-keys List the specified or all keys")\n"
+ printf -- "$(gettext " -r, --recv-keys Fetch the specified keyids")\n"
printf -- "$(gettext " -u, --updatedb Update the trustdb of pacman")\n"
- printf -- "$(gettext " -v, --verify <signature> Verify the file specified by the signature")\n"
- printf -- "$(gettext " -V, --version Show program version")\n"
+ printf -- "$(gettext " -v, --verify Verify the file(s) specified by the signature(s)")\n"
+ printf -- "$(gettext " --edit-key Present a menu for key management task on keyids")\n"
+ printf -- "$(gettext " --import Imports pubring.gpg from dir(s)")\n"
+ printf -- "$(gettext " --import-trustdb Imports ownertrust values from trustdb.gpg in dir(s)")\n"
+ printf -- "$(gettext " --init Ensure the keyring is properly initialized")\n"
+ printf -- "$(gettext " --list-sigs List keys and their signatures")\n"
+ printf -- "$(gettext " --lsign-key Locally sign the specified keyid")\n"
+ printf -- "$(gettext " --populate Reload the default keys from the (given) keyrings\n\
+ in '%s'")\n" "@pkgdatadir@/keyrings"
+ printf -- "$(gettext " --refresh-keys Update specified or all keys from a keyserver")\n"
+ echo
+ printf -- "$(gettext "Options:")\n"
printf -- "$(gettext " --config <file> Use an alternate config file (instead of\n\
'%s')")\n" "@sysconfdir@/pacman.conf"
- printf -- "$(gettext " --edit-key <keyid(s)> Present a menu for key management task on keyids")\n"
printf -- "$(gettext " --gpgdir <dir> Set an alternate directory for GnuPG (instead\n\
of '%s')")\n" "@sysconfdir@/pacman.d/gnupg"
- printf -- "$(gettext " --import <dir(s)> Imports pubring.gpg from dir(s)")\n"
- printf -- "$(gettext " --import-trustdb <dir(s)> Imports ownertrust values from trustdb.gpg in dir(s)")\n"
- printf -- "$(gettext " --init Ensure the keyring is properly initialized")\n"
- printf -- "$(gettext " --keyserver Specify a keyserver to use if necessary")\n"
- printf -- "$(gettext " --list-sigs [keyid(s)] List keys and their signatures")\n"
- printf -- "$(gettext " --lsign-key <keyid> Locally sign the specified keyid")\n"
- printf -- "$(gettext " --populate [keyring(s)] Reload the default keys from the (given) keyrings\n\
- in '%s'")\n" "@pkgdatadir@/keyrings"
- printf -- "$(gettext " --refresh-keys [keyid(s)] Update specified or all keys from a keyserver")\n"
+ printf -- "$(gettext " --keyserver <server-url> Specify a keyserver to use if necessary")\n"
+ echo
+ printf -- "$(gettext " -h, --help Show this help message and exit")\n"
+ printf -- "$(gettext " -V, --version Show program version")\n"
}
version() {
@@ -113,6 +116,30 @@ get_from() {
return 1
}
+key_lookup_from_name() {
+ local ids
+
+ mapfile -t ids < \
+ <("${GPG_PACMAN[@]}" --search-keys --batch --with-colons "$1" 2>/dev/null |
+ awk -F: '$1 == "pub" { print $2 }')
+
+ # only return success on non-ambiguous lookup
+ case ${#ids[*]} in
+ 0)
+ error "$(gettext "Failed to lookup key by name:") %s" "$name"
+ return 1
+ ;;
+ 1)
+ printf '%s' "${ids[0]}"
+ return 0
+ ;;
+ *)
+ error "$(gettext "Key name is ambiguous:") %s" "$name"
+ return 1
+ ;;
+ esac
+}
+
generate_master_key() {
# Generate the master key, which will be in both pubring and secring
"${GPG_PACMAN[@]}" --gen-key --batch <<EOF
@@ -146,7 +173,7 @@ add_gpg_conf_option() {
check_keyids_exist() {
local ret=0
- for key in "${KEYIDS[@]}"; do
+ for key in "$@"; do
# Verify if the key exists in pacman's keyring
if ! "${GPG_PACMAN[@]}" --list-keys "$key" &>/dev/null ; then
error "$(gettext "The key identified by %s could not be found locally.")" "$key"
@@ -217,16 +244,16 @@ check_keyring() {
populate_keyring() {
local KEYRING_IMPORT_DIR='@pkgdatadir@/keyrings'
- local keyring
+ local keyring KEYRINGIDS=("$@")
local ret=0
- if [[ -z ${KEYRINGIDS[@]} ]]; then
+ if (( ${#KEYRINGIDS[*]} == 0 )); then
# get list of all available keyrings
shopt -s nullglob
KEYRINGIDS=("$KEYRING_IMPORT_DIR"/*.gpg)
shopt -u nullglob
KEYRINGIDS=("${KEYRINGIDS[@]##*/}")
KEYRINGIDS=("${KEYRINGIDS[@]%.gpg}")
- if [[ -z ${KEYRINGIDS[@]} ]]; then
+ if (( ${#KEYRINGIDS[*]} == 0 )); then
error "$(gettext "No keyring files exist in %s.")" "$KEYRING_IMPORT_DIR"
ret=1
fi
@@ -245,8 +272,7 @@ populate_keyring() {
fi
# Variable used for iterating on keyrings
- local key
- local key_id
+ local keys key_id
# Add keys from requested keyrings
for keyring in "${KEYRINGIDS[@]}"; do
@@ -262,14 +288,12 @@ populate_keyring() {
local -A trusted_ids
for keyring in "${KEYRINGIDS[@]}"; do
if [[ -s "${KEYRING_IMPORT_DIR}/${keyring}-trusted" ]]; then
- while read key; do
- # skip comments; these are valid in this file
- [[ $key = \#* ]] && continue
- key_id="${key%%:*}"
- if [[ -n ${key_id} ]]; then
- # Mark this key to be lsigned
- trusted_ids[$key_id]="${keyring}"
- fi
+ while IFS=: read key_id _; do
+ # skip blank lines, comments; these are valid in this file
+ [[ -z $key_id || ${key_id:0:1} = \# ]] && continue
+
+ # Mark this key to be lsigned
+ trusted_ids[$key_id]=$keyring
done < "${KEYRING_IMPORT_DIR}/${keyring}-trusted"
fi
done
@@ -294,13 +318,13 @@ populate_keyring() {
local -A revoked_ids
for keyring in "${KEYRINGIDS[@]}"; do
if [[ -s "${KEYRING_IMPORT_DIR}/${keyring}-revoked" ]]; then
- while read key; do
- key_id="$("${GPG_PACMAN[@]}" --quiet --with-colons --list-key "${key}" 2>/dev/null | grep ^pub | cut -d: -f5)"
- if [[ -n ${key_id} ]]; then
+ mapfile -t keys < "${KEYRING_IMPORT_DIR}/${keyring}-revoked"
+ while IFS=: read _ _ _ _ key_id _; do
+ if [[ -n $key_id ]]; then
# Mark this key to be disabled
revoked_ids[$key_id]="${keyring}"
fi
- done < "${KEYRING_IMPORT_DIR}/${keyring}-revoked"
+ done < <("${GPG_PACMAN[@]}" --quiet --with-colons --list-keys "${keys[@]}" 2>/dev/null)
fi
done
@@ -314,24 +338,24 @@ populate_keyring() {
}
add_keys() {
- if ! "${GPG_PACMAN[@]}" --quiet --batch --import "${KEYFILES[@]}" ; then
+ if ! "${GPG_PACMAN[@]}" --quiet --batch --import "$@" ; then
error "$(gettext "A specified keyfile could not be added to the keyring.")"
exit 1
fi
}
delete_keys() {
- check_keyids_exist
- if ! "${GPG_PACMAN[@]}" --quiet --batch --delete-key --yes "${KEYIDS[@]}" ; then
+ check_keyids_exist "$@"
+ if ! "${GPG_PACMAN[@]}" --quiet --batch --delete-key --yes "$@" ; then
error "$(gettext "A specified key could not be removed from the keyring.")"
exit 1
fi
}
edit_keys() {
- check_keyids_exist
+ check_keyids_exist "$@"
local ret=0
- for key in "${KEYIDS[@]}"; do
+ for key in "$@"; do
if ! "${GPG_PACMAN[@]}" --edit-key "$key" ; then
error "$(gettext "The key identified by %s could not be edited.")" "$key"
ret=1
@@ -343,8 +367,8 @@ edit_keys() {
}
export_keys() {
- check_keyids_exist
- if ! "${GPG_PACMAN[@]}" --armor --export "${KEYIDS[@]}" ; then
+ check_keyids_exist "$@"
+ if ! "${GPG_PACMAN[@]}" --armor --export "$@" ; then
error "$(gettext "A specified key could not be exported from the keyring.")"
exit 1
fi
@@ -352,7 +376,7 @@ export_keys() {
finger_keys() {
check_keyids_exist
- if ! "${GPG_PACMAN[@]}" --batch --fingerprint "${KEYIDS[@]}" ; then
+ if ! "${GPG_PACMAN[@]}" --batch --fingerprint "$@" ; then
error "$(gettext "The fingerprint of a specified key could not be determined.")"
exit 1
fi
@@ -361,7 +385,7 @@ finger_keys() {
import_trustdb() {
local importdir
local ret=0
- for importdir in "${IMPORT_DIRS[@]}"; do
+ for importdir in "$@"; do
if [[ -f "${importdir}/trustdb.gpg" ]]; then
gpg --homedir "${importdir}" --export-ownertrust | \
"${GPG_PACMAN[@]}" --import-ownertrust -
@@ -382,7 +406,7 @@ import_trustdb() {
import() {
local importdir
local ret=0
- for importdir in "${IMPORT_DIRS[@]}"; do
+ for importdir in "$@"; do
if [[ -f "${importdir}/pubring.gpg" ]]; then
if ! "${GPG_PACMAN[@]}" --quiet --batch --import "${importdir}/pubring.gpg" ; then
error "$(gettext "%s could not be imported.")" "${importdir}/pubring.gpg"
@@ -400,7 +424,7 @@ import() {
list_keys() {
check_keyids_exist
- if ! "${GPG_PACMAN[@]}" --batch --list-keys "${KEYIDS[@]}" ; then
+ if ! "${GPG_PACMAN[@]}" --batch --list-keys "$@" ; then
error "$(gettext "A specified key could not be listed.")"
exit 1
fi
@@ -408,7 +432,7 @@ list_keys() {
list_sigs() {
check_keyids_exist
- if ! "${GPG_PACMAN[@]}" --batch --list-sigs "${KEYIDS[@]}" ; then
+ if ! "${GPG_PACMAN[@]}" --batch --list-sigs "$@" ; then
error "$(gettext "A specified signature could not be listed.")"
exit 1
fi
@@ -416,7 +440,7 @@ list_sigs() {
lsign_keys() {
check_keyids_exist
- printf 'y\ny\n' | LANG=C "${GPG_PACMAN[@]}" --command-fd 0 --quiet --batch --lsign-key "${KEYIDS[@]}" 2>/dev/null
+ printf 'y\ny\n' | LANG=C "${GPG_PACMAN[@]}" --command-fd 0 --quiet --batch --lsign-key "$@" 2>/dev/null
if (( PIPESTATUS[1] )); then
error "$(gettext "A specified key could not be locally signed.")"
exit 1
@@ -424,25 +448,45 @@ lsign_keys() {
}
receive_keys() {
- if ! "${GPG_PACMAN[@]}" --recv-keys "${KEYIDS[@]}" ; then
+ local name id keyids
+
+ # if the key is not a hex ID, do a lookup
+ for name; do
+ if [[ $name = ?(0x)+([0-9a-fA-F]) ]]; then
+ keyids+=("$name")
+ else
+ if id=$(key_lookup_from_name "$name"); then
+ keyids+=("$id")
+ fi
+ fi
+ done
+
+ (( ${#keyids[*]} > 0 )) || exit 1
+
+ if ! "${GPG_PACMAN[@]}" --recv-keys "${keyids[@]}" ; then
error "$(gettext "Remote key not fetched correctly from keyserver.")"
exit 1
fi
}
refresh_keys() {
- check_keyids_exist
- if ! "${GPG_PACMAN[@]}" --refresh-keys "${KEYIDS[@]}" ; then
+ check_keyids_exist "$@"
+ if ! "${GPG_PACMAN[@]}" --refresh-keys "$@" ; then
error "$(gettext "A specified local key could not be updated from a keyserver.")"
exit 1
fi
}
verify_sig() {
- if ! "${GPG_PACMAN[@]}" --status-fd 1 --verify $SIGNATURE | grep -qE 'TRUST_(FULLY|ULTIMATE)'; then
- error "$(gettext "The signature identified by %s could not be verified.")" "$SIGNATURE"
- exit 1
- fi
+ local ret=0
+ for sig; do
+ msg "Checking %s ..." "$sig"
+ if ! "${GPG_PACMAN[@]}" --status-fd 1 --verify "$sig" | grep -qE 'TRUST_(FULLY|ULTIMATE)'; then
+ error "$(gettext "The signature identified by %s could not be verified.")" "$sig"
+ ret=1
+ fi
+ done
+ exit $ret
}
updatedb() {
@@ -460,56 +504,55 @@ if ! type gettext &>/dev/null; then
}
fi
-OPT_SHORT="a::d:e::f::hl::r:uv:V"
-OPT_LONG="add::,config:,delete:,edit-key:,export::,finger::,gpgdir:"
-OPT_LONG+=",help,import:,import-trustdb:,init,keyserver:,list-keys::,list-sigs::"
-OPT_LONG+=",lsign-key:,populate::,recv-keys:,refresh-keys::,updatedb"
-OPT_LONG+=",verify:,version"
-if ! OPT_TEMP="$(parse_options $OPT_SHORT $OPT_LONG "$@")"; then
- echo; usage; exit 1 # E_INVALID_OPTION;
+OPT_SHORT="adefhlruvV"
+OPT_LONG=('add' 'config:' 'delete' 'edit-key' 'export' 'finger' 'gpgdir:'
+ 'help' 'import' 'import-trustdb' 'init' 'keyserver:' 'list-keys' 'list-sigs'
+ 'lsign-key' 'populate' 'recv-keys' 'refresh-keys' 'updatedb'
+ 'verify' 'version')
+if ! parseopts "$OPT_SHORT" "${OPT_LONG[@]}" -- "$@"; then
+ exit 1 # E_INVALID_OPTION;
fi
-eval set -- "$OPT_TEMP"
-unset OPT_SHORT OPT_LONG OPT_TEMP
+set -- "${OPTRET[@]}"
+unset OPT_SHORT OPT_LONG OPTRET
if [[ $1 == "--" ]]; then
usage;
exit 0;
fi
-while true; do
- case "$1" in
- -a|--add) ADD=1; [[ -n $2 && ${2:0:1} != "-" ]] && shift && KEYFILES=($1); UPDATEDB=1 ;;
+while (( $# )); do
+ case $1 in
+ -a|--add) ADD=1 UPDATEDB=1 ;;
--config) shift; CONFIG=$1 ;;
- -d|--delete) DELETE=1; shift; KEYIDS=($1); UPDATEDB=1 ;;
- --edit-key) EDITKEY=1; shift; KEYIDS=($1); UPDATEDB=1 ;;
- -e|--export) EXPORT=1; [[ -n $2 && ${2:0:1} != "-" ]] && shift && KEYIDS=($1) ;;
- -f|--finger) FINGER=1; [[ -n $2 && ${2:0:1} != "-" ]] && shift && KEYIDS=($1) ;;
+ -d|--delete) DELETE=1 UPDATEDB=1 ;;
+ --edit-key) EDITKEY=1 UPDATEDB=1 ;;
+ -e|--export) EXPORT=1 ;;
+ -f|--finger) FINGER=1 ;;
--gpgdir) shift; PACMAN_KEYRING_DIR=$1 ;;
- --import) IMPORT=1; shift; IMPORT_DIRS=($1); UPDATEDB=1 ;;
- --import-trustdb) IMPORT_TRUSTDB=1; shift; IMPORT_DIRS=($1); UPDATEDB=1 ;;
+ --import) IMPORT=1 UPDATEDB=1 ;;
+ --import-trustdb) IMPORT_TRUSTDB=1 UPDATEDB=1 ;;
--init) INIT=1 ;;
--keyserver) shift; KEYSERVER=$1 ;;
- -l|--list-keys) LISTKEYS=1; [[ -n $2 && ${2:0:1} != "-" ]] && shift && KEYIDS=($1) ;;
- --list-sigs) LISTSIGS=1; [[ -n $2 && ${2:0:1} != "-" ]] && shift && KEYIDS=($1) ;;
- --lsign-key) LSIGNKEY=1; shift; KEYIDS=($1); UPDATEDB=1 ;;
- --populate) POPULATE=1; [[ -n $2 && ${2:0:1} != "-" ]] && shift && KEYRINGIDS=($1); UPDATEDB=1 ;;
- -r|--recv-keys) RECEIVE=1; shift; KEYIDS=($1); UPDATEDB=1 ;;
- --refresh-keys) REFRESH=1; [[ -n $2 && ${2:0:1} != "-" ]] && shift && KEYIDS=($1) ;;
+ -l|--list-keys) LISTKEYS=1 ;;
+ --list-sigs) LISTSIGS=1 ;;
+ --lsign-key) LSIGNKEY=1 UPDATEDB=1 ;;
+ --populate) POPULATE=1 UPDATEDB=1 ;;
+ -r|--recv-keys) RECEIVE=1 UPDATEDB=1 ;;
+ --refresh-keys) REFRESH=1 ;;
-u|--updatedb) UPDATEDB=1 ;;
- -v|--verify) VERIFY=1; shift; SIGNATURE=$1 ;;
+ -v|--verify) VERIFY=1 ;;
-h|--help) usage; exit 0 ;;
-V|--version) version; exit 0 ;;
- --) OPT_IND=0; shift; break;;
- *) usage; exit 1 ;;
+ --) shift; break 2 ;;
esac
shift
done
if ! type -p gpg >/dev/null; then
- error "$(gettext "Cannot find the %s binary required for all %s operations.")" "gpg" "pacman-key"
+ error "$(gettext "Cannot find the %s binary required for all %s operations.")" "gpg" "pacman-key"
exit 1
fi
@@ -552,23 +595,30 @@ case $numopt in
;;
esac
+# check for targets where needed
+if (( (ADD || DELETE || EDIT || IMPORT || IMPORT_TRUSTDB ||
+ LSIGNKEY || RECEIVE || VERIFY) && $# == 0 )); then
+ error "$(gettext "No targets specified")"
+ exit 1
+fi
+
(( ! INIT )) && check_keyring
-(( ADD )) && add_keys
-(( DELETE )) && delete_keys
-(( EDITKEY )) && edit_keys
-(( EXPORT )) && export_keys
-(( FINGER )) && finger_keys
-(( IMPORT )) && import
-(( IMPORT_TRUSTDB)) && import_trustdb
+(( ADD )) && add_keys "$@"
+(( DELETE )) && delete_keys "$@"
+(( EDITKEY )) && edit_keys "$@"
+(( EXPORT )) && export_keys "$@"
+(( FINGER )) && finger_keys "$@"
+(( IMPORT )) && import "$@"
+(( IMPORT_TRUSTDB)) && import_trustdb "$@"
(( INIT )) && initialize
-(( LISTKEYS )) && list_keys
-(( LISTSIGS )) && list_sigs
-(( LSIGNKEY )) && lsign_keys
-(( POPULATE )) && populate_keyring
-(( RECEIVE )) && receive_keys
-(( REFRESH )) && refresh_keys
-(( VERIFY )) && verify_sig
+(( LISTKEYS )) && list_keys "$@"
+(( LISTSIGS )) && list_sigs "$@"
+(( LSIGNKEY )) && lsign_keys "$@"
+(( POPULATE )) && populate_keyring "$@"
+(( RECEIVE )) && receive_keys "$@"
+(( REFRESH )) && refresh_keys "$@"
+(( VERIFY )) && verify_sig "$@"
(( UPDATEDB )) && updatedb
diff --git a/scripts/pacman-optimize.sh.in b/scripts/pacman-optimize.sh.in
index 8a4e7224..4a84c0bb 100644
--- a/scripts/pacman-optimize.sh.in
+++ b/scripts/pacman-optimize.sh.in
@@ -24,7 +24,7 @@
export TEXTDOMAIN='pacman-scripts'
export TEXTDOMAINDIR='@localedir@'
-myver='@PACKAGE_VERSION@'
+declare -r myver='@PACKAGE_VERSION@'
eval $(awk '/DBPath/ {print $1$2$3}' @sysconfdir@/pacman.conf)
dbroot="${DBPath:-@localstatedir@/lib/pacman/}"
@@ -88,9 +88,8 @@ if [[ -n $1 ]]; then
dbroot="$1"
fi
-# make sure diff is installed
-if ! type diff >/dev/null 2>&1; then
- die "$(gettext "diff tool was not found, please install diffutils.")"
+if ! type -p openssl >/dev/null; then
+ die "$(gettext "Cannot find the %s binary required for verifying integrity.")" "openssl"
fi
if [[ ! -d $dbroot || ! -d $dbroot/local ]]; then
@@ -103,8 +102,8 @@ fi
# strip any trailing slash from our dbroot
dbroot="${dbroot%/}"
-# form the path to our lockfile location
lockfile="${dbroot}/db.lck"
+localdb="${dbroot}/local"
# make sure pacman isn't running
if [[ -f $lockfile ]]; then
@@ -113,42 +112,44 @@ fi
# do not let pacman run while we do this
touch "$lockfile"
-workdir=$(mktemp -d /tmp/pacman-optimize.XXXXXXXXXX) ||
+workdir=$(mktemp -d "${TMPDIR:-/tmp}/pacman-optimize.XXXXXXXXXX") ||
die_r "$(gettext "Can not create temp directory for database building.")\n" >&2
# step 1: sum the old db
msg "$(gettext "MD5sum'ing the old database...")"
-find "$dbroot" -type f | sort | xargs md5sum > "$workdir/pacsums.old"
+(cd "$localdb" && find . -type f -print0 | \
+ xargs -0 openssl dgst -md5 | sort > "$workdir/pacsums.old")
# step 2: tar it up
-msg "$(gettext "Tar'ing up %s...")" "$dbroot"
-bsdtar -czf "$workdir/pacman-db.tar.gz" -C "$dbroot" ./
+msg "$(gettext "Tar'ing up %s...")" "$localdb"
+bsdtar -czf "$workdir/pacman-db.tar.gz" -C "$localdb" ./
if (( $? )); then
rm -rf "$workdir"
- die_r "$(gettext "Tar'ing up %s failed.")" "$dbroot"
+ die_r "$(gettext "Tar'ing up %s failed.")" "$localdb"
fi
# step 3: make and sum the new db side-by-side with the old
msg "$(gettext "Making and MD5sum'ing the new database...")"
-mkdir "$dbroot.new"
-bsdtar -xpf "$workdir/pacman-db.tar.gz" -C "$dbroot.new"
+mkdir "$localdb.new"
+bsdtar -xpf "$workdir/pacman-db.tar.gz" -C "$localdb.new"
if (( $? )); then
rm -rf "$workdir"
- die_r "$(gettext "Untar'ing %s failed.")" "$dbroot"
+ die_r "$(gettext "Untar'ing %s failed.")" "$localdb"
fi
# immediate sync following extraction should get it written continuously on HDD
msg "$(gettext "Syncing database to disk...")"
sync
-find "$dbroot.new" -type f | sort | \
- xargs md5sum | sed 's#.new##' > "$workdir/pacsums.new"
+(cd "$localdb.new" && find . -type f -print0 | \
+ xargs -0 openssl dgst -md5 | sort > "$workdir/pacsums.new")
# step 4: compare the sums
msg "$(gettext "Checking integrity...")"
-diff "$workdir/pacsums.old" "$workdir/pacsums.new" >/dev/null 2>&1
-if (( $? )); then
+read -ra old_dgst < <(openssl dgst -md5 < "$workdir/pacsums.old")
+read -ra new_dgst < <(openssl dgst -md5 < "$workdir/pacsums.new")
+if [[ ${old_dgst[@]:(-1)} != ${new_dgst[@]:(-1)} ]]; then
# failed
# leave our pacman-optimize tmpdir for checking to see what doesn't match up
- rm -rf "$dbroot.new"
+ rm -rf "$localdb.new"
die_r "$(gettext "Integrity check FAILED, reverting to old database.")"
fi
@@ -156,15 +157,15 @@ fi
msg "$(gettext "Rotating database into place...")"
fail=0
-mv "$dbroot" "$dbroot.old" || fail=1
-mv "$dbroot.new" "$dbroot" || fail=1
-chmod --reference="$dbroot.old" "$dbroot" || fail=1
-chown --reference="$dbroot.old" "$dbroot" || fail=1
+mv "$localdb" "$localdb.old" || fail=1
+mv "$localdb.new" "$localdb" || fail=1
+chmod --reference="$localdb.old" "$localdb" || fail=1
+chown --reference="$localdb.old" "$localdb" || fail=1
if (( fail )); then
# failure with our directory shuffle
- die_r "$(gettext "New database substitution failed. Check for $dbroot,\n$dbroot.old, and $dbroot.new directories.")"
+ die_r "$(gettext "New database substitution failed. Check for %s, %s, and %s directories.")" "$localdb" "$localdb.old" "$localdb.new"
fi
-rm -rf "$dbroot.old"
+rm -rf "$localdb.old"
# remove the lock file and our working directory with sums and tarfile
rm -f "$lockfile"
diff --git a/scripts/pkgdelta.sh.in b/scripts/pkgdelta.sh.in
index ae0bfc38..0aa6169a 100644
--- a/scripts/pkgdelta.sh.in
+++ b/scripts/pkgdelta.sh.in
@@ -26,7 +26,7 @@ set -o errexit
export TEXTDOMAIN='pacman-scripts'
export TEXTDOMAINDIR='@localedir@'
-myver='@PACKAGE_VERSION@'
+declare -r myver='@PACKAGE_VERSION@'
QUIET=0
@@ -40,6 +40,7 @@ max_delta_size=70
# ensure we have a sane umask set
umask 0022
+m4_include(library/parseopts.sh)
m4_include(library/output_format.sh)
# print usage instructions
@@ -155,22 +156,32 @@ create_xdelta()
return 0
}
-declare -a args
+OPT_SHORT='hqV'
+OPT_LONG=('help' 'quiet' 'max-delta-size:' 'min-pkg-size:')
+if ! parseopts "$OPT_SHORT" "${OPT_LONG[@]}" -- "$@"; then
+ exit 1
+fi
+set -- "${OPTRET[@]}"
+unset OPT_SHORT OPT_LONG OPTRET
# parse arguments
-while (( $# )); do
- case "$1" in
- -h|--help) usage; exit 0 ;;
- -V|--version) version; exit 0 ;;
- -q|--quiet) QUIET=1;;
+while :; do
+ case $1 in
+ -h|--help)
+ usage
+ exit 0 ;;
+ -V|--version)
+ version
+ exit 0 ;;
+ -q|--quiet)
+ QUIET=1;;
--min-pkg-size)
if ! isnumeric "$2"; then
echo "invalid argument '$2' for option -- '$1'"
exit 1
fi
min_pkg_size=$2
- shift
- ;;
+ shift ;;
--max-delta-size)
arg=$(echo "$2" | awk '{print $1 * 100}')
if ! isnumeric "$arg" || (($arg > 200)); then
@@ -178,21 +189,20 @@ while (( $# )); do
exit 1
fi
max_delta_size=$arg
+ shift ;;
+ --)
shift
- ;;
- --) shift; args+=("$@"); break 2 ;;
- -*) echo "invalid option -- '$1'"; usage; exit 1 ;;
- *) args+=("$1");;
+ break 2 ;;
esac
shift
done
-if (( ${#args[@]} != 2 )); then
+if (( $# != 2 )); then
usage
exit 1
fi
-for i in "${args[@]}"; do
+for i in "$@"; do
if [[ ! -f $i ]]; then
error "$(gettext "File '%s' does not exist")" "$i"
exit 1
diff --git a/scripts/po/POTFILES.in b/scripts/po/POTFILES.in
index 007e535f..162731b9 100644
--- a/scripts/po/POTFILES.in
+++ b/scripts/po/POTFILES.in
@@ -8,4 +8,4 @@ scripts/pacman-optimize.sh.in
scripts/pkgdelta.sh.in
scripts/repo-add.sh.in
scripts/library/output_format.sh
-scripts/library/parse_options.sh
+scripts/library/parseopts.sh
diff --git a/scripts/rankmirrors.sh.in b/scripts/rankmirrors.sh.in
deleted file mode 100644
index 875a1439..00000000
--- a/scripts/rankmirrors.sh.in
+++ /dev/null
@@ -1,212 +0,0 @@
-#!/bin/bash
-#
-# rankmirrors - read a list of mirrors from a file and rank them by speed
-# @configure_input@
-#
-# Copyright (c) 2009 Matthew Bruenig <matthewbruenig@gmail.com>
-#
-# 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 <http://www.gnu.org/licenses/>.
-
-# traps interrupt key to spit out pre-interrupt info
-trap finaloutput INT
-
-usage() {
- echo "Usage: rankmirrors [options] MIRRORFILE | URL"
- echo
- echo "Ranks pacman mirrors by their connection and opening speed. Pacman mirror"
- echo "files are located in @sysconfdir@/pacman.d/. It can also rank one mirror if the URL is"
- echo "provided."
- echo
- echo "Options:"
- echo " --version show program's version number and exit"
- echo " -h, --help show this help message and exit"
- echo " -n NUM number of servers to output, 0 for all"
- echo " -t, --times only output mirrors and their response times"
- echo " -u, --url test a specific url"
- echo " -v, --verbose be verbose in ouptut"
- echo " -r, --repo specify a specific repo name instead of guessing"
- exit 0
-}
-
-version() {
- echo "rankmirrors (pacman) @PACKAGE_VERSION@"
- echo "Copyright (c) 2009 Matthew Bruenig <matthewbruenig@gmail.com>."
- echo
- echo "This is free software; see the source for copying conditions."
- echo "There is NO WARRANTY, to the extent permitted by law."
- exit 0
-}
-
-err() {
- echo "$1" >&2
- exit 1
-}
-
-# gettime fetchurl (e.g gettime http://foo.com/core/os/i686/core.db.tar.gz)
-# returns the fetching time, or timeout, or unreachable
-gettime() {
- IFS=' ' output=( $(curl -s -m 10 -w "%{time_total} %{http_code}" "$1" -o/dev/null) )
- (( $? == 28 )) && echo timeout && return
- (( ${output[1]} >= 400 || ! ${output[1]} )) && echo unreachable && return
- echo "${output[0]}"
-}
-
-# getfetchurl serverurl (e.g. getturl http://foo.com/core/os/i686)
-# if $repo is in the line, then assumes core
-# if $arch is in the line, then assumes $(uname -m)
-# returns a fetchurl (e.g. http://foo.com/core/os/i686/core.db.tar.gz)
-ARCH="$(uname -m)"
-getfetchurl() {
- local strippedurl="${1%/}"
-
- local replacedurl="${strippedurl//'$arch'/$ARCH}"
- if [[ ! $TARGETREPO ]]; then
- replacedurl="${replacedurl//'$repo'/core}"
- local tmp="${replacedurl%/*}"
- tmp="${tmp%/*}"
-
- local reponame="${tmp##*/}"
- else
- replacedurl="${replacedurl//'$repo'/$TARGETREPO}"
- local reponame="$TARGETREPO"
- fi
-
- if [[ -z $reponame || $reponame = $replacedurl ]]; then
- echo "fail"
- else
- local fetchurl="${replacedurl}/$reponame.db"
- echo "$fetchurl"
- fi
-}
-
-# This exists to remove the need for a separate interrupt function
-finaloutput() {
- IFS=$'\n' read -r -d '' -a sortedarray < \
- <(printf '%s\n' "${timesarray[@]}" | LC_COLLATE=C sort)
-
- # Final output for mirrorfile
- numiterator="0"
- if [[ $TIMESONLY ]]; then
- echo
- echo " Servers sorted by time (seconds):"
- for line in "${sortedarray[@]}"; do
- echo "${line#* } : ${line% *}"
- ((numiterator++))
- (( NUM && numiterator >= NUM )) && break
- done
- else
- for line in "${sortedarray[@]}"; do
- echo "Server = ${line#* }"
- ((numiterator++))
- (( NUM && numiterator >= NUM )) && break
- done
- fi
- exit 0
-}
-
-
-# Argument parsing
-[[ $1 ]] || usage
-while [[ $1 ]]; do
- if [[ ${1:0:2} = -- ]]; then
- case "${1:2}" in
- help) usage ;;
- version) version ;;
- times) TIMESONLY=1 ; shift ;;
- verbose) VERBOSE=1 ; shift ;;
- url) CHECKURL=1; [[ $2 ]] || err "Must specify url."; URL="$2"; shift 2;;
- repo) [[ $2 ]] || err "Must specify repo name."; TARGETREPO="$2"; shift 2;;
- *) err "\`$1' is an invalid argument."
- esac
- elif [[ ${1:0:1} = - ]]; then
-
- if [[ ! ${1:1:1} ]]; then
- [[ -t 0 ]] && err "Stdin is empty."
- IFS=$'\n' linearray=( $(</dev/stdin) )
- STDIN=1
- shift
- else
- snum=1
- for ((i=1 ; i<${#1}; i++)); do
- case ${1:$i:1} in
- h) usage ;;
- t) TIMESONLY=1 ;;
- v) VERBOSE=1 ;;
- u) CHECKURL=1; [[ $2 ]] || err "Must specify url."; URL="$2"; snum=2;;
- r) [[ $2 ]] || err "Must specify repo name."; TARGETREPO="$2"; snum=2;;
- n) [[ $2 ]] || err "Must specify number." ; NUM="$2" ; snum=2;;
- *) err "\`-$1' is an invald argument." ;;
- esac
- done
- shift $snum
- fi
- elif [[ -f $1 ]]; then
- FILE="1"
- IFS=$'\n' linearray=( $(<$1) )
- [[ $linearray ]] || err "File is empty."
- shift
- else
- err "\`$1' does not exist."
- fi
-done
-
-# Some sanity checks
-[[ $NUM ]] || NUM=0
-[[ $FILE && $CHECKURL ]] && err "Cannot specify a url and mirrorfile."
-[[ $FILE || $CHECKURL || $STDIN ]] || err "Must specify url, mirrorfile, or stdin."
-
-# Single url handling
-if [[ $CHECKURL ]]; then
- url="$(getfetchurl "$URL")"
- [[ $url = fail ]] && err "url \`$URL' is malformed."
- [[ $VERBOSE ]] && echo "Testing $url..."
- time=$(gettime "$url")
- echo "$URL : $time"
- exit 0
-fi
-
-# Get url results from mirrorfile, fill up the array, and so on
-if [[ $TIMESONLY ]]; then
- echo "Querying servers, this may take some time..."
-elif [[ $FILE ]]; then
- echo "# Server list generated by rankmirrors on $(date +%Y-%m-%d)"
-fi
-
-timesarray=()
-for line in "${linearray[@]}"; do
- if [[ $line =~ ^[[:space:]]*# ]]; then
- [[ $TIMESONLY ]] || echo $line
- elif [[ $line =~ ^[[:space:]]*Server ]]; then
-
- # Getting values and times and such
- server="${line#*= }"
- server="${server%%#*}"
- url="$(getfetchurl "$server")"
- [[ $url = fail ]] && err "url \`$URL' is malformed."
- time=$(gettime "$url")
- timesarray+=("$time $server")
-
- # Output
- if [[ $VERBOSE && $TIMESONLY ]]; then
- echo "$server ... $time"
- elif [[ $VERBOSE ]]; then
- echo "# $server ... $time"
- elif [[ $TIMESONLY ]]; then
- echo -n " *"
- fi
- fi
-done
-finaloutput
-
-# vim: set ts=2 sw=2 noet:
diff --git a/scripts/repo-add.sh.in b/scripts/repo-add.sh.in
index 5724022a..006672a0 100644
--- a/scripts/repo-add.sh.in
+++ b/scripts/repo-add.sh.in
@@ -25,8 +25,8 @@ shopt -s extglob
export TEXTDOMAIN='pacman-scripts'
export TEXTDOMAINDIR='@localedir@'
-myver='@PACKAGE_VERSION@'
-confdir='@sysconfdir@'
+declare -r myver='@PACKAGE_VERSION@'
+declare -r confdir='@sysconfdir@'
QUIET=0
DELTA=0
@@ -176,6 +176,11 @@ db_remove_delta() {
if grep -q "$filename" "$deltas"; then
sed -i.backup "/$filename/d" "$deltas" && rm -f "$deltas.backup"
msg2 "$(gettext "Removing existing entry '%s'...")" "$filename"
+ # empty deltas file contains only "%DELTAS%"
+ if (( $(wc -l < "$deltas") == 1 )); then
+ msg2 "$(gettext "Removing empty deltas file ...")"
+ rm "$deltas"
+ fi
return 0
fi
@@ -203,7 +208,7 @@ create_signature() {
gpg --detach-sign --use-agent ${SIGNWITHKEY} "$dbfile" &>/dev/null || ret=$?
if (( ! ret )); then
- msg2 "$(gettext "Created signature file %s.")" "${dbfile##*/}.sig"
+ msg2 "$(gettext "Created signature file %s.")" "${dbfile##*/.tmp.}.sig"
else
warning "$(gettext "Failed to sign package database.")"
fi
@@ -424,13 +429,8 @@ elephant() {
check_repo_db() {
local repodir
- # ensure the path to the DB exists
- if [[ "$LOCKFILE" == /* ]]; then
- repodir=${LOCKFILE%/*}/
- else
- repodir=$PWD/$LOCKFILE
- repodir=${repodir%/*}/
- fi
+ # ensure the path to the DB exists; $LOCKFILE is always an absolute path
+ repodir=${LOCKFILE%/*}/
if [[ ! -d $repodir ]]; then
error "$(gettext "%s does not exist or is not a directory.")" "$repodir"
@@ -579,7 +579,7 @@ if [[ $cmd != "repo-add" && $cmd != "repo-remove" ]]; then
exit 1
fi
-tmpdir=$(mktemp -d /tmp/repo-tools.XXXXXXXXXX) || (\
+tmpdir=$(mktemp -d "${TMPDIR:-/tmp}/repo-tools.XXXXXXXXXX") || (\
error "$(gettext "Cannot create temp directory for database building.")"; \
exit 1)
mkdir "$tmpdir/tree"
@@ -637,7 +637,11 @@ if [[ -z $REPO_DB_FILE ]]; then
exit 1
fi
-LOCKFILE=$REPO_DB_FILE.lck
+if [[ $REPO_DB_FILE == /* ]]; then
+ LOCKFILE=$REPO_DB_FILE.lck
+else
+ LOCKFILE=$PWD/$REPO_DB_FILE.lck
+fi
verify_repo_extension "$REPO_DB_FILE" >/dev/null
check_repo_db
@@ -654,37 +658,51 @@ if (( success )); then
msg "$(gettext "Creating updated database file '%s'")" "$REPO_DB_FILE"
TAR_OPT=$(verify_repo_extension "$REPO_DB_FILE")
+ # $LOCKFILE is already guaranteed to be absolute so this is safe
+ dirname=${LOCKFILE%/*}
filename=${REPO_DB_FILE##*/}
+ # this ensures we create it on the same filesystem, making moves atomic
+ tempname=$dirname/.tmp.$filename
pushd "$tmpdir/tree" >/dev/null
if ( shopt -s nullglob; files=(*); (( ${#files[*]} )) ); then
- bsdtar -c${TAR_OPT}f "$tmpdir/$filename" *
+ bsdtar -c${TAR_OPT}f "$tempname" *
else
# we have no packages remaining? zip up some emptyness
warning "$(gettext "No packages remain, creating empty database.")"
- bsdtar -c${TAR_OPT}f "$tmpdir/$filename" -T /dev/null
+ bsdtar -c${TAR_OPT}f "$tempname" -T /dev/null
fi
popd >/dev/null
- create_signature "$tmpdir/$filename"
+ create_signature "$tempname"
- [[ -f $REPO_DB_FILE ]] && mv -f "$REPO_DB_FILE" "${REPO_DB_FILE}.old"
+ # hardlink or move the previous version of the database and signature to .old
+ # extension as a backup measure
+ if [[ -f $REPO_DB_FILE ]]; then
+ ln -f "$REPO_DB_FILE" "$REPO_DB_FILE.old" 2>/dev/null || \
+ mv -f "$REPO_DB_FILE" "$REPO_DB_FILE.old"
+ fi
if [[ -f $REPO_DB_FILE.sig ]]; then
- mv -f "$REPO_DB_FILE.sig" "$REPO_DB_FILE.old.sig"
+ ln -f "$REPO_DB_FILE.sig" "$REPO_DB_FILE.old.sig" 2>/dev/null || \
+ mv -f "$REPO_DB_FILE.sig" "$REPO_DB_FILE.old.sig"
else
rm -f "$REPO_DB_FILE.old.sig"
fi
- [[ -f $tmpdir/$filename ]] && mv "$tmpdir/$filename" "$REPO_DB_FILE"
- [[ -f $tmpdir/$filename.sig ]] && mv "$tmpdir/$filename.sig" "$REPO_DB_FILE.sig"
+
+ # rotate the newly-created database and signature into place
+ mv "$tempname" "$REPO_DB_FILE"
+ if [[ -f $tempname.sig ]]; then
+ mv "$tempname.sig" "$REPO_DB_FILE.sig"
+ fi
+
dblink=${REPO_DB_FILE%.tar*}
- target=${REPO_DB_FILE##*/}
rm -f "$dblink" "$dblink.sig"
- ln -s "$target" "$dblink" 2>/dev/null || \
- ln "$target" "$dblink" 2>/dev/null || \
+ ln -s "$filename" "$dblink" 2>/dev/null || \
+ ln "$filename" "$dblink" 2>/dev/null || \
cp "$REPO_DB_FILE" "$dblink"
if [[ -f "$REPO_DB_FILE.sig" ]]; then
- ln -s "$target.sig" "$dblink.sig" 2>/dev/null || \
- ln "$target.sig" "$dblink.sig" 2>/dev/null || \
+ ln -s "$filename.sig" "$dblink.sig" 2>/dev/null || \
+ ln "$filename.sig" "$dblink.sig" 2>/dev/null || \
cp "$REPO_DB_FILE.sig" "$dblink.sig"
fi
else