mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-10 21:19:59 +00:00
Update parse_options.sh in pt-stalk.
This commit is contained in:
281
bin/pt-stalk
281
bin/pt-stalk
@@ -49,21 +49,26 @@ die() {
|
||||
# ###########################################################################
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
set -u
|
||||
|
||||
ARGV="" # Non-option args (probably input files)
|
||||
EXT_ARGV="" # Everything after -- (args for an external command)
|
||||
OPT_ERRS=0 # How many command line option errors
|
||||
OPT_VERSION="no" # If --version was specified
|
||||
OPT_HELP="no" # If --help was specified
|
||||
ARGV="" # Non-option args (probably input files)
|
||||
EXT_ARGV="" # Everything after -- (args for an external command)
|
||||
HAVE_EXT_ARGV="" # Got --, everything else is put into EXT_ARGV
|
||||
OPT_ERRS=0 # How many command line option errors
|
||||
OPT_VERSION="no" # If --version was specified
|
||||
OPT_HELP="no" # If --help was specified
|
||||
PO_DIR="$TMPDIR/po" # Directory with program option spec files
|
||||
|
||||
usage() {
|
||||
local file="$1"
|
||||
|
||||
local usage=$(grep '^Usage: ' "$file")
|
||||
echo $usage >&2
|
||||
echo >&2
|
||||
echo "For more information, 'man $TOOL' or 'perldoc $file'." >&2
|
||||
echo $usage
|
||||
echo
|
||||
echo "For more information, 'man $TOOL' or 'perldoc $file'."
|
||||
}
|
||||
|
||||
usage_or_errors() {
|
||||
@@ -77,20 +82,20 @@ usage_or_errors() {
|
||||
|
||||
if [ "$OPT_HELP" = "yes" ]; then
|
||||
usage "$file"
|
||||
echo >&2
|
||||
echo "Command line options:" >&2
|
||||
echo >&2
|
||||
echo
|
||||
echo "Command line options:"
|
||||
echo
|
||||
for opt in $(ls $TMPDIR/po/); do
|
||||
local desc=$(cat $TMPDIR/po/$opt | grep '^desc:' | sed -e 's/^desc://')
|
||||
echo "--$opt" >&2
|
||||
echo " $desc" >&2
|
||||
echo >&2
|
||||
echo "--$opt"
|
||||
echo " $desc"
|
||||
echo
|
||||
done
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ $OPT_ERRS -gt 0 ]; then
|
||||
echo >&2
|
||||
echo
|
||||
usage "$file"
|
||||
return 1
|
||||
fi
|
||||
@@ -102,54 +107,70 @@ parse_options() {
|
||||
local file="$1"
|
||||
shift
|
||||
|
||||
if [ ! -d "$TMPDIR/po/" ]; then
|
||||
mkdir "$TMPDIR/po/"
|
||||
ARGV=""
|
||||
EXT_ARGV=""
|
||||
HAVE_EXT_ARGV=""
|
||||
OPT_ERRS=0
|
||||
OPT_VERSION="no"
|
||||
OPT_HELP="no"
|
||||
PO_DIR="$TMPDIR/po"
|
||||
|
||||
if [ ! -d "$PO_DIR" ]; then
|
||||
mkdir "$PO_DIR"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Cannot mkdir $TMPDIR/po/" >&2
|
||||
echo "Cannot mkdir $PO_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
rm -rf "$TMPDIR"/po/*
|
||||
rm -rf "$PO_DIR"/*
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Cannot rm -rf $TMPDIR/po/*" >&2
|
||||
echo "Cannot rm -rf $PO_DIR/*" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
(
|
||||
export PO_DIR="$TMPDIR/po"
|
||||
cat "$file" | perl -ne '
|
||||
BEGIN { $/ = ""; }
|
||||
next unless $_ =~ m/^=head1 OPTIONS/;
|
||||
while ( defined(my $para = <>) ) {
|
||||
last if $para =~ m/^=head1/;
|
||||
|
||||
_parse_pod "$file"
|
||||
_eval_po
|
||||
_parse_config_files
|
||||
_parse_command_line "$@"
|
||||
}
|
||||
|
||||
_parse_pod() {
|
||||
local file="$1"
|
||||
|
||||
cat "$file" | PO_DIR="$PO_DIR" perl -ne '
|
||||
BEGIN { $/ = ""; }
|
||||
next unless $_ =~ m/^=head1 OPTIONS/;
|
||||
while ( defined(my $para = <>) ) {
|
||||
last if $para =~ m/^=head1/;
|
||||
chomp;
|
||||
if ( $para =~ m/^=item --(\S+)/ ) {
|
||||
my $opt = $1;
|
||||
my $file = "$ENV{PO_DIR}/$opt";
|
||||
open my $opt_fh, ">", $file or die "Cannot open $file: $!";
|
||||
print $opt_fh "long:$opt\n";
|
||||
$para = <>;
|
||||
chomp;
|
||||
if ( $para =~ m/^=item --(\S+)/ ) {
|
||||
my $opt = $1;
|
||||
my $file = "$ENV{PO_DIR}/$opt";
|
||||
open my $opt_fh, ">", $file or die "Cannot open $file: $!";
|
||||
print $opt_fh "long:$opt\n";
|
||||
if ( $para =~ m/^[a-z ]+:/ ) {
|
||||
map {
|
||||
chomp;
|
||||
my ($attrib, $val) = split(/: /, $_);
|
||||
print $opt_fh "$attrib:$val\n";
|
||||
} split(/; /, $para);
|
||||
$para = <>;
|
||||
chomp;
|
||||
if ( $para =~ m/^[a-z ]+:/ ) {
|
||||
map {
|
||||
chomp;
|
||||
my ($attrib, $val) = split(/: /, $_);
|
||||
print $opt_fh "$attrib:$val\n";
|
||||
} split(/; /, $para);
|
||||
$para = <>;
|
||||
chomp;
|
||||
}
|
||||
my ($desc) = $para =~ m/^([^?.]+)/;
|
||||
print $opt_fh "desc:$desc.\n";
|
||||
close $opt_fh;
|
||||
}
|
||||
my ($desc) = $para =~ m/^([^?.]+)/;
|
||||
print $opt_fh "desc:$desc.\n";
|
||||
close $opt_fh;
|
||||
}
|
||||
last;
|
||||
'
|
||||
)
|
||||
}
|
||||
last;
|
||||
'
|
||||
}
|
||||
|
||||
for opt_spec in $(ls "$TMPDIR/po/"); do
|
||||
_eval_po() {
|
||||
for opt_spec in $(ls "$PO_DIR"); do
|
||||
local opt=""
|
||||
local default_val=""
|
||||
local neg=0
|
||||
@@ -175,13 +196,13 @@ parse_options() {
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Invalid attribute in $TMPDIR/po/$opt_spec: $line" >&2
|
||||
echo "Invalid attribute in $PO_DIR/$opt_spec: $line" >&2
|
||||
exit 1
|
||||
esac
|
||||
done < "$TMPDIR/po/$opt_spec"
|
||||
done < "$PO_DIR/$opt_spec"
|
||||
|
||||
if [ -z "$opt" ]; then
|
||||
echo "No long attribute in option spec $TMPDIR/po/$opt_spec" >&2
|
||||
echo "No long attribute in option spec $PO_DIR/$opt_spec" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -194,69 +215,133 @@ parse_options() {
|
||||
|
||||
eval "OPT_${opt}"="$default_val"
|
||||
done
|
||||
}
|
||||
|
||||
for opt; do
|
||||
if [ $# -eq 0 ]; then
|
||||
break # no more opts
|
||||
_parse_config_files() {
|
||||
for config_file in "/etc/percona-toolkit/percona-toolkit.conf" "/etc/percona-toolkit/$TOOL.conf" "$HOME/.percona-toolkit.conf" "$HOME/.$TOOL.conf"
|
||||
do
|
||||
test -f "$config_file" || continue
|
||||
|
||||
while read config_opt; do
|
||||
|
||||
echo "$config_opt" | grep '^[ ]*[^#]' >/dev/null 2>&1 || continue
|
||||
|
||||
config_opt="$(echo "$config_opt" | sed -e 's/^[ ]*//' -e 's/[ ]*\$//' -e 's/[ ]*=[ ]*/=/' -e 's/[ ]*#.*$//')"
|
||||
|
||||
if ! [ "$HAVE_EXT_ARGV" ]; then
|
||||
config_opt="--$config_opt"
|
||||
fi
|
||||
_parse_command_line "$config_opt"
|
||||
done < "$config_file"
|
||||
|
||||
HAVE_EXT_ARGV="" # reset for each file
|
||||
|
||||
done
|
||||
}
|
||||
|
||||
_parse_command_line() {
|
||||
local opt=""
|
||||
local val=""
|
||||
local next_opt_is_val=""
|
||||
local opt_is_ok=""
|
||||
local opt_is_negated=""
|
||||
local real_opt=""
|
||||
local required_arg=""
|
||||
|
||||
for opt in "$@"; do
|
||||
if [ "$opt" = "--" -o "$opt" = "----" ]; then
|
||||
HAVE_EXT_ARGV=1
|
||||
continue
|
||||
fi
|
||||
opt=$1
|
||||
if [ "$opt" = "--" ]; then
|
||||
shift
|
||||
EXT_ARGV="$@"
|
||||
break
|
||||
fi
|
||||
shift
|
||||
if [ $(expr "$opt" : "-") -eq 0 ]; then
|
||||
if [ -z "$ARGV" ]; then
|
||||
ARGV="$opt"
|
||||
if [ "$HAVE_EXT_ARGV" ]; then
|
||||
if [ "$EXT_ARGV" ]; then
|
||||
EXT_ARGV="$EXT_ARGV $opt"
|
||||
else
|
||||
ARGV="$ARGV $opt"
|
||||
EXT_ARGV="$opt"
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
|
||||
local real_opt="$opt"
|
||||
|
||||
if $(echo $opt | grep -q '^--no-'); then
|
||||
neg=1
|
||||
opt=$(echo $opt | sed 's/^--no-//')
|
||||
else
|
||||
neg=0
|
||||
opt=$(echo $opt | sed 's/^-*//')
|
||||
fi
|
||||
|
||||
if [ -f "$TMPDIR/po/$opt" ]; then
|
||||
spec="$TMPDIR/po/$opt"
|
||||
else
|
||||
spec=$(grep "^short form:-$opt\$" "$TMPDIR"/po/* | cut -d ':' -f 1)
|
||||
if [ -z "$spec" ]; then
|
||||
OPT_ERRS=$(($OPT_ERRS + 1))
|
||||
echo "Unknown option: $real_opt" >&2
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
local required_arg=$(cat $spec | awk -F: '/^type:/{print $2}')
|
||||
if [ -n "$required_arg" ]; then
|
||||
if [ $# -eq 0 ]; then
|
||||
if [ "$next_opt_is_val" ]; then
|
||||
next_opt_is_val=""
|
||||
if [ $# -eq 0 ] || [ $(expr "$opt" : "-") -eq 1 ]; then
|
||||
OPT_ERRS=$(($OPT_ERRS + 1))
|
||||
echo "$real_opt requires a $required_arg argument" >&2
|
||||
continue
|
||||
else
|
||||
val="$1"
|
||||
shift
|
||||
fi
|
||||
val="$opt"
|
||||
opt_is_ok=1
|
||||
else
|
||||
if [ $neg -eq 0 ]; then
|
||||
val="yes"
|
||||
if [ $(expr "$opt" : "-") -eq 0 ]; then
|
||||
if [ -z "$ARGV" ]; then
|
||||
ARGV="$opt"
|
||||
else
|
||||
ARGV="$ARGV $opt"
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
|
||||
real_opt="$opt"
|
||||
|
||||
if $(echo $opt | grep -q '^--no-'); then
|
||||
opt_is_negated=1
|
||||
opt=$(echo $opt | sed 's/^--no-//')
|
||||
else
|
||||
val="no"
|
||||
opt_is_negated=""
|
||||
opt=$(echo $opt | sed 's/^-*//')
|
||||
fi
|
||||
|
||||
if $(echo $opt | grep '^[a-z-][a-z-]*=' >/dev/null 2>&1); then
|
||||
val="$(echo $opt | awk -F= '{print $2}')"
|
||||
opt="$(echo $opt | awk -F= '{print $1}')"
|
||||
fi
|
||||
|
||||
if [ -f "$TMPDIR/po/$opt" ]; then
|
||||
spec="$TMPDIR/po/$opt"
|
||||
else
|
||||
spec=$(grep "^short form:-$opt\$" "$TMPDIR"/po/* | cut -d ':' -f 1)
|
||||
if [ -z "$spec" ]; then
|
||||
OPT_ERRS=$(($OPT_ERRS + 1))
|
||||
echo "Unknown option: $real_opt" >&2
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
required_arg=$(cat "$spec" | awk -F: '/^type:/{print $2}')
|
||||
if [ "$required_arg" ]; then
|
||||
if [ "$val" ]; then
|
||||
opt_is_ok=1
|
||||
else
|
||||
next_opt_is_val=1
|
||||
fi
|
||||
else
|
||||
if [ "$val" ]; then
|
||||
OPT_ERRS=$(($OPT_ERRS + 1))
|
||||
echo "Option $real_opt does not take a value" >&2
|
||||
continue
|
||||
fi
|
||||
if [ "$opt_is_negated" ]; then
|
||||
val=""
|
||||
else
|
||||
val="yes"
|
||||
fi
|
||||
opt_is_ok=1
|
||||
fi
|
||||
fi
|
||||
|
||||
opt=$(cat $spec | grep '^long:' | cut -d':' -f2 | sed 's/-/_/g' | tr [:lower:] [:upper:])
|
||||
if [ "$opt_is_ok" ]; then
|
||||
opt=$(cat "$spec" | grep '^long:' | cut -d':' -f2 | sed 's/-/_/g' | tr [:lower:] [:upper:])
|
||||
|
||||
eval "OPT_$opt"="$val"
|
||||
eval "OPT_$opt"="'$val'"
|
||||
|
||||
opt=""
|
||||
val=""
|
||||
next_opt_is_val=""
|
||||
opt_is_ok=""
|
||||
opt_is_negated=""
|
||||
real_opt=""
|
||||
required_arg=""
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user