1
0
mirror of https://github.com/moparisthebest/pacman synced 2024-08-13 17:03:46 -04:00

Merge branch 'parse-opts'

This commit is contained in:
Dan McGee 2012-04-24 08:39:31 -05:00
commit ac6ebcfe93
14 changed files with 505 additions and 259 deletions

View File

@ -1,4 +1,4 @@
SUBDIRS = lib/libalpm src/util src/pacman scripts etc test/pacman test/util
SUBDIRS = lib/libalpm src/util src/pacman scripts etc test/pacman test/util test/scripts
if WANT_DOC
SUBDIRS += doc
endif
@ -23,7 +23,7 @@ dist_pkgdata_DATA = \
proto/ChangeLog.proto
# run the pactest test suite and vercmp tests
check-local: test/pacman test/util src/pacman src/util
check-local: test/pacman test/scripts test/util src/pacman src/util
LC_ALL=C $(PYTHON) $(top_srcdir)/test/pacman/pactest.py --debug=1 \
--test $(top_srcdir)/test/pacman/tests/*.py \
-p $(top_builddir)/src/pacman/pacman
@ -31,6 +31,8 @@ check-local: test/pacman test/util src/pacman src/util
$(top_builddir)/src/util/pacsort
$(SH) $(top_srcdir)/test/util/vercmptest.sh \
$(top_builddir)/src/util/vercmp
$(BASH_SHELL) $(top_srcdir)/test/scripts/parseopts_test.sh \
$(top_srcdir)/scripts/library/parseopts.sh
# create the pacman DB and cache directories upon install
install-data-local:

View File

@ -442,6 +442,7 @@ doc/Makefile
etc/Makefile
test/pacman/Makefile
test/pacman/tests/Makefile
test/scripts/Makefile
test/util/Makefile
contrib/Makefile
Makefile

View File

@ -27,19 +27,44 @@ _arch_incomp() {
local r="\s-(-${1#* }\s|\w*${1% *})"; [[ $COMP_LINE =~ $r ]]
}
_pacman_keyids() {
\pacman-key --list-keys 2>/dev/null | awk '
$1 == "pub" {
# key id
split($2, a, "/"); print a[2]
}
$1 == "uid" {
# email
if (match($NF, /<[^>]+>/))
print substr($NF, RSTART + 1, RLENGTH - 2)
}'
}
_pacman_key() {
local cur opts prev
local o cur opts prev wantfiles
COMPREPLY=()
_get_comp_words_by_ref cur prev
opts=('add delete export finger help list-keys recv-keys updatedb verify
version config edit-key gpgdir import import-trustdb init keyserver
list-sigs lsign-key populate refresh-keys'
'a d e f h l r u v V')
if [[ $prev = 'pacman-key' ]]; then
_arch_ptr2comp opts
elif [[ $cur = -* &&
$prev != -@(a|-add|c|-config|g|-gpgdir|h|-help|import?(-trustdb)) ]]; then
# operations for which we want to complete keyids
for o in 'd delete' 'e export' 'f finger' 'l list-keys' 'r recv-keys' \
'edit-key' 'list-sigs' 'refresh-keys'; do
_arch_incomp "$o" && break
unset o
done
# options for which we want file completion
wantfiles='-@(c|-config|g|-gpgdir)'
if [[ $prev = 'pacman-key' || ( $cur = -* && $prev != $wantfiles ) ]]; then
_arch_ptr2comp opts
elif [[ $prev = @(-k|--keyserver) ]]; then
return
elif [[ $prev != $wantfiles && $o ]]; then
COMPREPLY=($(compgen -W '$(_pacman_keyids)' -- "$cur"))
fi
true
}

View File

@ -152,8 +152,9 @@ Options
such as a chroot or remote builder. It will also satisfy requirements of
the GPL when distributing binary packages.
*\--pkg <list>*::
Only build listed packages from a split package.
*\--pkg* <list>::
Only build listed packages from a split package. Multiple packages should
be comma separated in the list. This option can be specified multiple times.
*\--check*::
Run the check() function in the PKGBUILD, overriding the setting in

View File

@ -12,7 +12,7 @@ pacman-key - manage pacman's list of trusted keys
Synopsis
--------
'pacman-key' [options]
'pacman-key' [options] operation [targets]
Description
@ -26,45 +26,40 @@ More complex keyring management can be achieved using GnuPG directly combined wi
the '\--homedir' option pointing at the pacman keyring (located in
+{sysconfdir}/pacman.d/gnupg+ by default).
Invoking pacman-key consists of supplying an operation with any potential
options and targets to operate on. Depending on the operation, a 'target' may
be a valid key identifier, filename, or directory.
Options
-------
*-a, \--add* [file(s)]::
Operations
----------
*-a, \--add*::
Add the key(s) contained in the specified file or files to pacman's
keyring. If a key already exists, update it.
*\--config* <file>::
Use an alternate config file instead of the +{sysconfdir}/pacman.conf+
default.
*-d, \--delete* <keyid(s)>::
*-d, \--delete*::
Remove the key(s) identified by the specified keyid(s) from pacman's
keyring.
*-e, \--export* [keyid(s)]::
*-e, \--export*::
Export key(s) identified by the specified keyid(s) to 'stdout'. If no keyid
is specified, all keys will be exported.
*\--edit-key* <keyid(s)>::
*\--edit-key*::
Present a menu for key management task on the specified keyid(s). Useful
for adjusting a keys trust level.
*-f, \--finger* [keyid(s)]::
*-f, \--finger*::
List a fingerprint for each specified keyid, or for all known keys if no
keyids are specified.
*\--gpgdir* <dir>::
Set an alternate home directory for GnuPG. If unspecified, the value is
read from +{sysconfdir}/pacman.conf+.
*-h, \--help*::
Output syntax and command line options.
*\--import* <dir(s)>::
*\--import*::
Imports keys from `pubring.gpg` into the public keyring from the specified
directories.
*\--import-trustdb* <dir(s)> ::
*\--import-trustdb*::
Imports ownertrust values from `trustdb.gpg` into the shared trust database
from the specified directories.
@ -72,42 +67,53 @@ Options
Ensure the keyring is properly initialized and has the required access
permissions.
*\--keyserver* <keyserver>::
Use the specified keyserver if the operation requires one. This will take
precedence over any keyserver option specified in a `gpg.conf`
configuration file. Running '\--init' with this option will set the default
keyserver if one was not already configured.
*-l, \--list-keys* [keyid(s)]::
*-l, \--list-keys*::
Lists all or specified keys from the public keyring.
*\--list-sigs* [keyid(s)]::
*\--list-sigs*::
Same as '\--list-keys', but the signatures are listed too.
*\--lsign-key* <keyid>::
*\--lsign-key*::
Locally sign the given key. This is primarily used to root the web of trust
in the local private key generated by '\--init'.
*-r, \--recv-keys* <keyid(s)>::
*-r, \--recv-keys*::
Equivalent to '\--recv-keys' in GnuPG.
*\--refresh-keys* [keyid(s)]::
*\--refresh-keys*::
Equivalent to '\--refresh-keys' in GnuPG.
*\--populate* [keyring(s)]::
*\--populate*::
Reload the default keys from the (optionally provided) keyrings in
+{pkgdatadir}/keyrings+. For more information, see
<<SC,Providing a Keyring for Import>> below.
*-u, \--updatedb*::
Equivalent to '\--check-trustdb' in GnuPG.
*-v, \--verify* <signature>::
Verify the given signature file.
Equivalent to '\--check-trustdb' in GnuPG. This operation can be specified with
other operations.
*-V, \--version*::
Displays the program version.
*-v, \--verify*::
Verify the file(s) specified by the signature(s).
Options
-------
*\--config* <file>::
Use an alternate config file instead of the +{sysconfdir}/pacman.conf+
default.
*\--gpgdir* <dir>::
Set an alternate home directory for GnuPG. If unspecified, the value is
read from +{sysconfdir}/pacman.conf+.
*\--keyserver* <keyserver>::
Use the specified keyserver if the operation requires one. This will take
precedence over any keyserver option specified in a `gpg.conf`
configuration file. Running '\--init' with this option will set the default
keyserver if one was not already configured.
Providing a Keyring for Import
------------------------------

View File

@ -27,7 +27,7 @@ EXTRA_DIST = \
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)
@ -67,7 +67,7 @@ $(OURSCRIPTS): Makefile
makepkg: \
$(srcdir)/makepkg.sh.in \
$(srcdir)/library/parse_options.sh
$(srcdir)/library/parseopts.sh
pacman-db-upgrade: \
$(srcdir)/pacman-db-upgrade.sh.in \
@ -76,7 +76,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 \

View File

@ -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)

View File

@ -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
}

View File

@ -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
}

View File

@ -1885,7 +1885,7 @@ canonicalize_path() {
fi
}
m4_include(library/parse_options.sh)
m4_include(library/parseopts.sh)
usage() {
printf "makepkg (pacman) %s\n" "$myver"
@ -1954,19 +1954,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
@ -1997,7 +1998,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 ;;
@ -2010,8 +2011,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

View File

@ -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() {
@ -146,7 +149,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 +220,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
@ -311,24 +314,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 gpg keychain.")"
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 gpg keychain.")"
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
@ -340,8 +343,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 gpg keychain.")"
exit 1
fi
@ -349,7 +352,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
@ -358,7 +361,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 -
@ -379,7 +382,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"
@ -397,7 +400,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
@ -405,7 +408,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
@ -413,7 +416,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
@ -421,25 +424,30 @@ lsign_keys() {
}
receive_keys() {
if ! "${GPG_PACMAN[@]}" --recv-keys "${KEYIDS[@]}" ; then
if ! "${GPG_PACMAN[@]}" --recv-keys "$@" ; 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() {
@ -457,56 +465,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
@ -549,23 +556,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

View File

@ -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

9
test/scripts/Makefile.am Normal file
View File

@ -0,0 +1,9 @@
check_SCRIPTS = \
parseopts_test.sh
noinst_SCRIPTS = $(check_SCRIPTS)
EXTRA_DIST = \
$(check_SCRIPTS)
# vim:set ts=2 sw=2 noet:

138
test/scripts/parseopts_test.sh Executable file
View File

@ -0,0 +1,138 @@
#!/bin/bash
declare -i testcount=0 pass=0 fail=0
# source the library function
if [[ -z $1 || ! -f $1 ]]; then
printf "error: path to parseopts library not provided or does not exist\n"
exit 1
fi
. "$1"
if ! type -t parseopts >/dev/null; then
printf 'parseopts function not found\n'
exit 1
fi
# borrow opts from makepkg
OPT_SHORT="AcdefFghiLmop:rRsV"
OPT_LONG=('allsource' 'asroot' 'ignorearch' 'check' 'clean:' 'cleanall' 'nodeps'
'noextract' 'force' 'forcever:' 'geninteg' 'help' 'holdver'
'install' 'key:' 'log' 'nocolor' 'nobuild' 'nocheck' 'nosign' 'pkg:' 'rmdeps'
'repackage' 'skipinteg' 'sign' 'source' 'syncdeps' 'version' 'config:'
'noconfirm' 'noprogressbar')
parse() {
local result=$1 tokencount=$2; shift 2
(( ++testcount ))
parseopts "$OPT_SHORT" "${OPT_LONG[@]}" -- "$@" 2>/dev/null
test_result "$result" "$tokencount" "$*" "${OPTRET[@]}"
unset OPTRET
}
test_result() {
local result=$1 tokencount=$2 input=$3; shift 3
if [[ $result = "$*" ]] && (( tokencount == $# )); then
(( ++pass ))
else
printf '[TEST %3s]: FAIL\n' "$testcount"
printf ' input: %s\n' "$input"
printf ' output: %s (%s tokens)\n' "$*" "$#"
printf ' expected: %s (%s tokens)\n' "$result" "$tokencount"
echo
(( ++fail ))
fi
}
summarize() {
if (( !fail )); then
printf 'All %s tests successful\n' "$testcount"
exit 0
else
printf '%s of %s tests failed\n' "$fail" "$testcount"
exit 1
fi
}
trap 'summarize' EXIT
printf 'Beginning parseopts tests\n'
# usage: parse <expected result> <token count> test-params...
# a failed parse will match only the end of options marker '--'
# no options
parse '--' 1
# short options
parse '-s -r --' 3 -s -r
# short options, no spaces
parse '-s -r --' 3 -sr
# short opt missing an opt arg
parse '--' 1 -s -p
# short opt with an opt arg
parse '-p PKGBUILD -L --' 4 -p PKGBUILD -L
# short opt with an opt arg, no space
parse '-p PKGBUILD --' 3 -pPKGBUILD
# valid shortopts as a long opt
parse '--' 1 --sir
# long opt wiht no optarg
parse '--log --' 2 --log
# long opt with missing optarg
parse '--' 1 -sr --pkg
# long opt with optarg
parse '--pkg foo --' 3 --pkg foo
# long opt with optarg with whitespace
parse '--pkg foo bar -- baz' 4 --pkg "foo bar" baz
# long opt with optarg with =
parse '--pkg foo=bar -- baz' 4 --pkg foo=bar baz
# long opt with explicit optarg
parse '--pkg bar -- foo baz' 5 foo --pkg=bar baz
# long opt with explicit optarg, with whitespace
parse '--pkg foo bar -- baz' 4 baz --pkg="foo bar"
# long opt with explicit optarg that doesn't take optarg
parse '--' 1 --force=always -s
# long opt with explicit optarg with =
parse '--pkg foo=bar --' 3 --pkg=foo=bar
# explicit end of options with options after
parse '-s -r -- foo bar baz' 6 -s -r -- foo bar baz
# non-option parameters mixed in with options
parse '-s -r -- foo baz' 5 -s foo baz -r
# optarg with whitespace
parse '-p foo bar -s --' 4 -p'foo bar' -s
# non-option parameter with whitespace
parse '-i -- foo bar' 3 -i 'foo bar'
# successful stem match (opt has no arg)
parse '--nocolor --' 2 --nocol
# successful stem match (opt has arg)
parse '--config foo --' 3 --conf foo
# ambiguous long opt
parse '--' 1 '--for'
# exact match on a possible stem (--force & --forcever)
parse '--force --' 2 --force
# exact match on possible stem (opt has optarg)
parse '--clean foo --' 3 --clean=foo