Skip to content

Commit

Permalink
allow option bundling, e.g. -c -D can be written as -cD
Browse files Browse the repository at this point in the history
+ add --default-directory as an alias for -D
+ allow the user agent to be defined via $WAX_USER_AGENT
  • Loading branch information
chocolateboy committed Aug 2, 2020
1 parent 532083c commit 29cf0a7
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 96 deletions.
6 changes: 6 additions & 0 deletions Changes
@@ -1,5 +1,11 @@
Revision history for Perl extension App::Wax.

2.4.0 - TBD

- allow option bundling, e.g. `-c -D` can be written as `-cD`
- add --default-directory as an alias for -D
- allow the user agent to be defined via $WAX_USER_AGENT

2.3.3 - 2020-05-04

- version bump to fix deletion of previous version from PAUSE
Expand Down
12 changes: 4 additions & 8 deletions bin/README.md
Expand Up @@ -8,7 +8,7 @@
- [OPTIONS](#options)
- [-c, --cache](#-c---cache)
- [-d, --dir, --directory STRING](#-d---dir---directory-string)
- [-D](#-d)
- [-D, --default-directory](#-d---default-directory)
- [-h, -?, --help](#-h-----help)
- [-m, --mirror](#-m---mirror)
- [-s, --separator STRING](#-s---separator-string)
Expand Down Expand Up @@ -77,10 +77,6 @@ Note that the `--cache` and `--mirror` options are mutually exclusive i.e. only
one (or neither) should be supplied. Supplying both will cause `wax` to
terminate with an error.

Note that option bundling is not currently supported e.g. `wax --cache
--verbose ...` can't be condensed to `wax -cv ...`, and would need to be
written as `wax -c -v ...`.

### -c, --cache

Don't remove the downloaded file(s) after the command exits. Subsequent
Expand All @@ -91,7 +87,7 @@ If a local file no longer exists, the resource is re-downloaded.

Note: by default, files are saved to the system's temp directory, which is
typically cleared when the system restarts. To save files to another directory,
use the `-D` or `--directory` option.
use the `--directory` or `--default-directory` option.

### -d, --dir, --directory STRING

Expand All @@ -101,10 +97,10 @@ Specify the directory to download files to. Default: the system's
If the directory doesn't exist, it is created if its parent directory exists.
Otherwise, an error is raised.

### -D
### -D, --default-directory

Download files to `$XDG_CACHE_HOME/wax` or `$HOME/.cache/wax` rather than the
system's temp directory. Can be overriden by `-d`.
system's temp directory. Can be overriden by `--directory`.

If the directory doesn't exist, it is created if its parent directory exists.
Otherwise, an error is raised.
Expand Down
9 changes: 3 additions & 6 deletions bin/wax
Expand Up @@ -75,9 +75,6 @@ Note that the C<--cache> and C<--mirror> options are mutually exclusive i.e.
only one (or neither) should be supplied. Supplying both will cause C<wax> to
terminate with an error.
Note that option bundling is not currently supported e.g. C<wax --cache --verbose ...>
can't be condensed to C<wax -cv ...>, and would need to be written as C<wax -c -v ...>.
=head2 -c, --cache
Don't remove the downloaded file(s) after the command exits. Subsequent
Expand All @@ -88,7 +85,7 @@ If a local file no longer exists, the resource is re-downloaded.
Note: by default, files are saved to the system's temp directory, which is
typically cleared when the system restarts. To save files to another directory,
use the C<-D> or C<--directory> option.
use the C<--directory> or C<--default-directory> option.
=head2 -d, --dir, --directory STRING
Expand All @@ -98,10 +95,10 @@ L<temp directory|https://en.wikipedia.org/wiki/Temporary_folder>.
If the directory doesn't exist, it is created if its parent directory exists.
Otherwise, an error is raised.
=head2 -D
=head2 -D, --default-directory
Download files to C<$XDG_CACHE_HOME/wax> or C<$HOME/.cache/wax> rather than the
system's temp directory. Can be overriden by C<-d>.
system's temp directory. Can be overriden by C<--directory>.
If the directory doesn't exist, it is created if its parent directory exists.
Otherwise, an error is raised.
Expand Down
131 changes: 54 additions & 77 deletions lib/App/Wax.pm
Expand Up @@ -6,6 +6,7 @@ use Digest::SHA qw(sha1_hex);
use File::Slurper qw(read_text write_text);
use File::Spec;
use File::Temp;
use Getopt::Long qw(GetOptionsFromArray :config posix_default require_order bundling no_auto_abbrev no_ignore_case);
use IPC::System::Simple qw(EXIT_ANY $EXITVAL systemx);
use LWP::UserAgent;
use Method::Signatures::Simple;
Expand All @@ -31,7 +32,7 @@ use constant {
SEPARATOR => '--',
TEMPLATE => 'XXXXXXXX',
TIMEOUT => 60,
USER_AGENT => 'Mozilla/5.0 (Windows NT 10.0; rv:68.0) Gecko/20100101 Firefox/68.0',
USER_AGENT => ($ENV{WAX_USER_AGENT} || 'Mozilla/5.0 (Windows NT 10.0; rv:68.0) Gecko/20100101 Firefox/68.0'),
VERBOSE => 0,
};

Expand All @@ -51,11 +52,9 @@ use constant INFER_EXTENSION => {
use constant {
OK => 0,
E_DOWNLOAD => -1,
E_INVALID_OPTION => -2,
E_INVALID_DIRECTORY => -2,
E_INVALID_OPTIONS => -3,
E_INVALID_DIRECTORY => -4,
E_NO_ARGUMENTS => -5,
E_NO_COMMAND => -6,
E_NO_COMMAND => -4,
};

has app_name => (
Expand Down Expand Up @@ -262,6 +261,19 @@ func _escape ($arg) {
return $arg;
}

method _use_default_directory () {
# "${XDG_CACHE_HOME:-$HOME/.cache}/wax"
require File::BaseDir;
$self->directory(File::BaseDir::cache_home($self->app_name));
}

# dump the version (a combination of the app version and the module version) and
# exit
method version () {
printf "%s (%s %s)$/", $self->app_version, __PACKAGE__, $VERSION;
exit 0;
}

# log a message to stderr with the app's name and message's log level
method log ($level, $template, @args) {
my $name = $self->app_name;
Expand Down Expand Up @@ -312,7 +324,7 @@ method is_url ($url) {
my ($scheme, $domain, $path, $query, $fragment) = uri_split($url);

if ($scheme && ($domain || $path)) { # no domain for file:// URLs
return [ $scheme, $domain, $path, $query, $fragment ];
return [$scheme, $domain, $path, $query, $fragment];
}
}
}
Expand Down Expand Up @@ -443,83 +455,44 @@ method resolve_temp ($_url) {

# parse the supplied arrayref of options and return a triple of:
#
# command: an arrayref containing the command to execute
# command: an arrayref containing the command to execute and its arguments
# resolve: an arrayref of [index, URL] pairs, where index refers to the URL's
# (0-based) index in the commmand array
# test: true if --test was seen; false otherwise
method _parse ($argv) {
my @argv = @$argv;
my @argv = @$argv; # don't mutate the original
my $test = 0;

unless (@argv) {
my $parsed = GetOptionsFromArray(\@argv,
'c|cache' => sub { $self->cache(1) },
'd|dir|directory=s' => sub { $self->directory($_[1]) },
'D|default-directory' => sub { $self->_use_default_directory },
'h|?|help' => sub { pod2usage(-input => $0, -verbose => 2, -exitval => 0) },
'm|mirror' => sub { $self->mirror(1) },
's|separator=s' => sub { $self->separator($_[1]) },
'S|no-separator' => sub { $self->clear_separator() },
't|timeout=i' => sub { $self->timeout($_[1]) },
'test' => \$test,
'u|user-agent=s' => sub { $self->user_agent($_[1]) },
'v|verbose' => sub { $self->verbose(1) },
'V|version' => sub { $self->version },
);

unless ($parsed) {
pod2usage(
-exitval => E_NO_ARGUMENTS,
-exitval => E_INVALID_OPTIONS,
-input => $0,
-msg => 'no arguments supplied',
-verbose => 0,
);
}

my $wax_options = 1;
my $seen_url = 0;
my $test = 0;
my (@command, @resolve);
my $seen_url = 0;

while (@argv) {
my $arg = shift @argv;

my $val = sub {
if (@argv) {
return shift(@argv);
} else {
pod2usage(
-exitval => E_INVALID_OPTION,
-input => $0,
-msg => "missing value for $arg option",
-verbose => 1,
);
}
};
my $arg = shift(@argv);

if ($wax_options) {
if ($arg =~ /^(?:-c|--cache)$/) {
$self->cache(1);
} elsif ($arg =~ /^(?:-d|--dir|--directory)$/) {
$self->directory($val->());
} elsif ($arg eq '-D') {
# "${XDG_CACHE_HOME:-$HOME/.cache}/wax"
require File::BaseDir;
$self->directory(File::BaseDir::cache_home($self->app_name));
} elsif ($arg =~ /^(?:-v|--verbose)$/) {
$self->verbose(1);
} elsif ($arg =~ /^(?:-[?h]|--help)$/) {
pod2usage(-input => $0, -verbose => 2, -exitval => 0);
} elsif ($arg =~ /^(?:-m|--mirror)$/) {
$self->mirror(1);
} elsif ($arg =~ /^(?:-s|--separator)$/) {
$self->separator($val->());
} elsif ($arg =~ /^(?:-S|--no-separator)$/) {
$self->clear_separator();
} elsif ($arg eq '--test') {
$test = 1;
} elsif ($arg =~ /^(?:-t|--timeout)$/) {
$self->timeout($val->());
} elsif ($arg =~ /^(?:-u|--user-agent)$/) {
$self->user_agent($val->());
} elsif ($arg =~ /^(?:-V|--version)$/) {
printf "%s (%s %s)$/", $self->app_version, __PACKAGE__, $VERSION;
exit 0;
} elsif ($arg =~ /^-/) { # unknown option
pod2usage(
-exitval => E_INVALID_OPTION,
-input => $0,
-msg => "invalid option: $arg",
-verbose => 1,
);
} else { # non-option: exit the wax-options processing stage
push @command, $arg;
$wax_options = 0;
}
} elsif ($self->has_separator && ($arg eq $self->separator)) {
if ($self->has_separator && ($arg eq $self->separator)) {
push @command, @argv;
last;
} elsif ($self->is_url($arg)) {
Expand All @@ -530,17 +503,26 @@ method _parse ($argv) {
}

my $url_index = @resolve + 1; # 1-based
my $_url = [ $arg, $url_index ];
my $_url = [$arg, $url_index];

$self->debug('url (%d): %s', $url_index, $arg);

push @command, $arg;
push @resolve, [ $#command, $_url ];
push @resolve, [$#command, $_url];
} else {
push @command, $arg;
}
}

unless (@command) {
pod2usage(
-exitval => E_NO_COMMAND,
-input => $0,
-msg => 'no command supplied',
-verbose => 0,
)
}

return \@command, \@resolve, $test;
}

Expand All @@ -550,22 +532,17 @@ method run ($argv) {
my $unlink = [];
my ($command, $resolve, $test) = $self->_parse($argv);

unless (@$command) {
$self->log(ERROR => 'no command supplied');
return $test ? $command : E_NO_COMMAND;
}

if (@$resolve == 1) {
my ($command_index, $_url) = @{ $resolve->[0] };
my @resolved = $self->resolve($_url);

$error = $self->_handle([ $command_index, @resolved ], $command, $unlink);
$error = $self->_handle([$command_index, @resolved], $command, $unlink);
} elsif (@$resolve) {
$self->debug('jobs: %d', scalar(@$resolve));

my @resolved = parallel_map {
my ($command_index, $_url) = @$_;
[ $command_index, $self->resolve($_url) ]
[$command_index, $self->resolve($_url)]
} @$resolve;

for my $resolved (@resolved) {
Expand Down
18 changes: 18 additions & 0 deletions t/bundling.t
@@ -0,0 +1,18 @@
use strict;
use warnings;

use FindBin qw($Bin);
use lib "$Bin/lib";

use Test::App::Wax qw(@DEFAULT @URL wax_is);
use Test::More tests => 2;

wax_is(
"wax -cD cmd --foo $URL[0]",
"cmd --foo $DEFAULT[0]"
);

wax_is(
"wax -Dc cmd --foo $URL[0]",
"cmd --foo $DEFAULT[0]"
);
28 changes: 28 additions & 0 deletions t/default-directory.t
@@ -0,0 +1,28 @@
use strict;
use warnings;

use FindBin qw($Bin);
use lib "$Bin/lib";

use Test::App::Wax qw(@DEFAULT @URL wax_is);
use Test::More tests => 4;

wax_is(
"wax --cache --default-directory cmd --foo $URL[0]",
"cmd --foo $DEFAULT[0]"
);

wax_is(
"wax --cache -D cmd --foo $URL[0]",
"cmd --foo $DEFAULT[0]"
);

wax_is(
"wax -c --default-directory cmd --foo $URL[0]",
"cmd --foo $DEFAULT[0]"
);

wax_is(
"wax -c -D cmd --foo $URL[0]",
"cmd --foo $DEFAULT[0]"
);

0 comments on commit 29cf0a7

Please sign in to comment.