mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-10 13:11:32 +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
|
set -u
|
||||||
|
|
||||||
ARGV="" # Non-option args (probably input files)
|
ARGV="" # Non-option args (probably input files)
|
||||||
EXT_ARGV="" # Everything after -- (args for an external command)
|
EXT_ARGV="" # Everything after -- (args for an external command)
|
||||||
OPT_ERRS=0 # How many command line option errors
|
HAVE_EXT_ARGV="" # Got --, everything else is put into EXT_ARGV
|
||||||
OPT_VERSION="no" # If --version was specified
|
OPT_ERRS=0 # How many command line option errors
|
||||||
OPT_HELP="no" # If --help was specified
|
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() {
|
usage() {
|
||||||
local file="$1"
|
local file="$1"
|
||||||
|
|
||||||
local usage=$(grep '^Usage: ' "$file")
|
local usage=$(grep '^Usage: ' "$file")
|
||||||
echo $usage >&2
|
echo $usage
|
||||||
echo >&2
|
echo
|
||||||
echo "For more information, 'man $TOOL' or 'perldoc $file'." >&2
|
echo "For more information, 'man $TOOL' or 'perldoc $file'."
|
||||||
}
|
}
|
||||||
|
|
||||||
usage_or_errors() {
|
usage_or_errors() {
|
||||||
@@ -77,20 +82,20 @@ usage_or_errors() {
|
|||||||
|
|
||||||
if [ "$OPT_HELP" = "yes" ]; then
|
if [ "$OPT_HELP" = "yes" ]; then
|
||||||
usage "$file"
|
usage "$file"
|
||||||
echo >&2
|
echo
|
||||||
echo "Command line options:" >&2
|
echo "Command line options:"
|
||||||
echo >&2
|
echo
|
||||||
for opt in $(ls $TMPDIR/po/); do
|
for opt in $(ls $TMPDIR/po/); do
|
||||||
local desc=$(cat $TMPDIR/po/$opt | grep '^desc:' | sed -e 's/^desc://')
|
local desc=$(cat $TMPDIR/po/$opt | grep '^desc:' | sed -e 's/^desc://')
|
||||||
echo "--$opt" >&2
|
echo "--$opt"
|
||||||
echo " $desc" >&2
|
echo " $desc"
|
||||||
echo >&2
|
echo
|
||||||
done
|
done
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $OPT_ERRS -gt 0 ]; then
|
if [ $OPT_ERRS -gt 0 ]; then
|
||||||
echo >&2
|
echo
|
||||||
usage "$file"
|
usage "$file"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@@ -102,54 +107,70 @@ parse_options() {
|
|||||||
local file="$1"
|
local file="$1"
|
||||||
shift
|
shift
|
||||||
|
|
||||||
if [ ! -d "$TMPDIR/po/" ]; then
|
ARGV=""
|
||||||
mkdir "$TMPDIR/po/"
|
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
|
if [ $? -ne 0 ]; then
|
||||||
echo "Cannot mkdir $TMPDIR/po/" >&2
|
echo "Cannot mkdir $PO_DIR" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -rf "$TMPDIR"/po/*
|
rm -rf "$PO_DIR"/*
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo "Cannot rm -rf $TMPDIR/po/*" >&2
|
echo "Cannot rm -rf $PO_DIR/*" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
(
|
_parse_pod "$file"
|
||||||
export PO_DIR="$TMPDIR/po"
|
_eval_po
|
||||||
cat "$file" | perl -ne '
|
_parse_config_files
|
||||||
BEGIN { $/ = ""; }
|
_parse_command_line "$@"
|
||||||
next unless $_ =~ m/^=head1 OPTIONS/;
|
}
|
||||||
while ( defined(my $para = <>) ) {
|
|
||||||
last if $para =~ m/^=head1/;
|
_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;
|
chomp;
|
||||||
if ( $para =~ m/^=item --(\S+)/ ) {
|
if ( $para =~ m/^[a-z ]+:/ ) {
|
||||||
my $opt = $1;
|
map {
|
||||||
my $file = "$ENV{PO_DIR}/$opt";
|
chomp;
|
||||||
open my $opt_fh, ">", $file or die "Cannot open $file: $!";
|
my ($attrib, $val) = split(/: /, $_);
|
||||||
print $opt_fh "long:$opt\n";
|
print $opt_fh "$attrib:$val\n";
|
||||||
|
} split(/; /, $para);
|
||||||
$para = <>;
|
$para = <>;
|
||||||
chomp;
|
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 opt=""
|
||||||
local default_val=""
|
local default_val=""
|
||||||
local neg=0
|
local neg=0
|
||||||
@@ -175,13 +196,13 @@ parse_options() {
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Invalid attribute in $TMPDIR/po/$opt_spec: $line" >&2
|
echo "Invalid attribute in $PO_DIR/$opt_spec: $line" >&2
|
||||||
exit 1
|
exit 1
|
||||||
esac
|
esac
|
||||||
done < "$TMPDIR/po/$opt_spec"
|
done < "$PO_DIR/$opt_spec"
|
||||||
|
|
||||||
if [ -z "$opt" ]; then
|
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
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -194,69 +215,133 @@ parse_options() {
|
|||||||
|
|
||||||
eval "OPT_${opt}"="$default_val"
|
eval "OPT_${opt}"="$default_val"
|
||||||
done
|
done
|
||||||
|
}
|
||||||
|
|
||||||
for opt; do
|
_parse_config_files() {
|
||||||
if [ $# -eq 0 ]; then
|
for config_file in "/etc/percona-toolkit/percona-toolkit.conf" "/etc/percona-toolkit/$TOOL.conf" "$HOME/.percona-toolkit.conf" "$HOME/.$TOOL.conf"
|
||||||
break # no more opts
|
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
|
fi
|
||||||
opt=$1
|
if [ "$HAVE_EXT_ARGV" ]; then
|
||||||
if [ "$opt" = "--" ]; then
|
if [ "$EXT_ARGV" ]; then
|
||||||
shift
|
EXT_ARGV="$EXT_ARGV $opt"
|
||||||
EXT_ARGV="$@"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
shift
|
|
||||||
if [ $(expr "$opt" : "-") -eq 0 ]; then
|
|
||||||
if [ -z "$ARGV" ]; then
|
|
||||||
ARGV="$opt"
|
|
||||||
else
|
else
|
||||||
ARGV="$ARGV $opt"
|
EXT_ARGV="$opt"
|
||||||
fi
|
fi
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local real_opt="$opt"
|
if [ "$next_opt_is_val" ]; then
|
||||||
|
next_opt_is_val=""
|
||||||
if $(echo $opt | grep -q '^--no-'); then
|
if [ $# -eq 0 ] || [ $(expr "$opt" : "-") -eq 1 ]; 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
|
|
||||||
OPT_ERRS=$(($OPT_ERRS + 1))
|
OPT_ERRS=$(($OPT_ERRS + 1))
|
||||||
echo "$real_opt requires a $required_arg argument" >&2
|
echo "$real_opt requires a $required_arg argument" >&2
|
||||||
continue
|
continue
|
||||||
else
|
|
||||||
val="$1"
|
|
||||||
shift
|
|
||||||
fi
|
fi
|
||||||
|
val="$opt"
|
||||||
|
opt_is_ok=1
|
||||||
else
|
else
|
||||||
if [ $neg -eq 0 ]; then
|
if [ $(expr "$opt" : "-") -eq 0 ]; then
|
||||||
val="yes"
|
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
|
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
|
||||||
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
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user