Permalink
Browse files

Merge branch 'mutex-options'

  • Loading branch information...
hoelzro committed Dec 10, 2012
2 parents 1fc2ce8 + 7f2199d commit b75824ce11f5af73cb398a743dcc2d38e8e00194
Showing with 449 additions and 13 deletions.
  1. +74 −0 ConfigLoader.pm
  2. +35 −0 t/Util.pm
  3. +1 −13 t/ack-f.t
  4. +339 −0 t/mutex-options.t
View
@@ -20,6 +20,29 @@ use Text::ParseWords 3.1 ();
=cut
+my @INVALID_COMBINATIONS;
+
+BEGIN {
+ @INVALID_COMBINATIONS = (
+ # XXX normalize
+ [qw(-l)] => [qw(-A -B -C -L -o --passthru --output --max-count -h -H --with-filename --no-filename --column --after-context --before-context --context --heading --break --group -f -g --show-types)],
+ [qw(-L)] => [qw(-A -B -C -l -o --passthru --output --max-count -h -H --with-filename --no-filename --column --after-context --before-context --context --heading --break --group -f -g --show-types -c --count)],
+ [qw(--line)] => [qw(-l --files-with-matches --files-without-matches -L -o --passthru --match -m --max-count -1 -h -H --with-filename --no-filename -c --count --column -A --after-context -B --before-context -C --context --print0 -f -g --show-types)],
+ [qw(-o)] => [qw(--output -c --count --column -A -B -C --after-context --before-context --context --column -f --show-types)],
+ [qw(--passthru)] => [qw(--output -A -B -C --after-context --before-context --context --column -m --max-count -1 -c --count -f -g)],
+ [qw(--output)] => [qw(-c --count -f -g)],
+ [qw(--match)] => [qw(-f -g)],
+ [qw(-m --max-count)] => [qw(-1 -f -g -c --count)],
+ [qw(-h --no-filename)] => [qw(-H --with-filename -c --count -f -g --group --heading)],
+ [qw(-H --with-filename)] => [qw(-h --no-filename -c --count -f -g)],
+ [qw(-c --count)] => [qw(--column -A --after-context -B --before-context -C --context --heading --group --break -f -g)],
+ [qw(--column)] => [qw(-f -g)],
+ [qw(-A -B -C --after-context --before-context --context)] => [qw(-f -g)],
+ [qw(-f)] => [qw(-g --heading --group --break)],
+ [qw(-g)] => [qw(--heading --group --break)],
+ );
+}
+
sub process_filter_spec {
my ( $spec ) = @_;
@@ -161,6 +184,9 @@ EOT
* Your new option is explained when a user invokes ack --man.
(See the POD at the end of ./ack)
* Add your option to t/config-loader.t
+ * Go through the list of options already available, and consider
+ whether your new option can be considered mutually exclusive
+ with another option.
=cut
return {
1 => sub { $opt->{1} = $opt->{m} = 1 },
@@ -504,11 +530,59 @@ sub remove_default_options_if_needed {
return \@copy;
}
+sub check_for_mutually_exclusive_options {
+ my ( $arg_sources ) = @_;
+
+ my %mutually_exclusive_with;
+ my @copy = @$arg_sources;
+
+ for(my $i = 0; $i < @INVALID_COMBINATIONS; $i += 2) {
+ my ( $lhs, $rhs ) = @INVALID_COMBINATIONS[ $i, $i + 1 ];
+
+ foreach my $l_opt ( @$lhs ) {
+ foreach my $r_opt ( @$rhs ) {
+ push @{ $mutually_exclusive_with{ $l_opt } }, $r_opt;
+ push @{ $mutually_exclusive_with{ $r_opt } }, $l_opt;
+ }
+ }
+ }
+
+ while( @copy ) {
+ my %set_opts;
+
+ my ( $source_name, $args ) = splice @copy, 0, 2;
+ $args = ref($args) ? [ @$args ] : [ Text::ParseWords::shellwords($args) ];
+
+ foreach my $opt ( @$args ) {
+ next unless $opt =~ /^[-+]/;
+ last if $opt eq '--';
+
+ if( $opt =~ /^(.*)=/ ) {
+ $opt = $1;
+ }
+
+ $set_opts{ $opt } = 1;
+
+ my $mutex_opts = $mutually_exclusive_with{ $opt };
+
+ next unless $mutex_opts;
+
+ foreach my $mutex_opt ( @$mutex_opts ) {
+ if($set_opts{ $mutex_opt }) {
+ die "Options '$mutex_opt' and '$opt' are mutually exclusive\n";
+ }
+ }
+ }
+ }
+}
+
sub process_args {
my $arg_sources = \@_;
my %opt;
+ check_for_mutually_exclusive_options($arg_sources);
+
$arg_sources = remove_default_options_if_needed($arg_sources);
if ( should_dump_options($arg_sources) ) {
View
@@ -1,10 +1,14 @@
+use Carp ();
use File::Next ();
use App::Ack ();
use Cwd ();
use File::Spec ();
+use File::Temp ();
my $orig_wd;
+my @temp_files; # we store temp files here to make sure they're properly
+ # reclaimed at interpreter shutdown
sub prep_environment {
delete @ENV{qw( ACK_OPTIONS ACKRC ACK_PAGER HOME )};
@@ -22,6 +26,36 @@ sub is_win32 {
sub build_ack_invocation {
my @args = @_;
+ my $options;
+
+ foreach my $arg ( @args ) {
+ if ( ref($arg) eq 'HASH' ) {
+ if ( $options ) {
+ Carp::croak('You may not specify more than one options hash');
+ }
+ else {
+ $options = $arg;
+ }
+ }
+ }
+
+ $options ||= {};
+
+ @args = grep { ref($_) ne 'HASH' } @args;
+
+ if ( my $ackrc = $options->{ackrc} ) {
+ if ( ref($ackrc) eq 'SCALAR' ) {
+ my $temp_ackrc = File::Temp->new;
+ push @temp_files, $temp_ackrc;
+
+ print { $temp_ackrc } $$ackrc, "\n";
+ close $temp_ackrc;
+ $ackrc = $temp_ackrc->filename;
+ }
+
+ unshift @args, '--ackrc', $ackrc;
+ }
+
# The --noenv makes sure we don't pull in anything from the user
# unless explicitly specified in the test
if ( !grep { /^--(no)?env$/ } @args ) {
@@ -102,6 +136,7 @@ sub run_ack {
local $Test::Builder::Level = $Test::Builder::Level + 1;
my ($stdout, $stderr) = run_ack_with_stderr( @args );
+ @args = grep { ref($_) ne 'HASH' } @args;
if ( $TODO ) {
fail( q{Automatically fail stderr check for TODO tests.} );
View
@@ -3,7 +3,7 @@
use warnings;
use strict;
-use Test::More tests => 5;
+use Test::More tests => 4;
use lib 't';
use Util;
@@ -88,16 +88,4 @@ COMBINED_FILTERS: {
ack_sets_match( [ @args ], \@expected );
}
-subtest '-f with a regex is an error' => sub {
- # specifying both -f and a regex should result in an error
- my @files = qw( t/text );
- my @args = qw( -f --match Sue );
-
- my ($stdout, $stderr) = run_ack_with_stderr( @args, @files );
- isnt( get_rc(), 0, 'Specifying both -f and --match must lead to an error RC' );
- is( scalar @{$stdout}, 0, 'No normal output' );
- is( scalar @{$stderr}, 1, 'One line of stderr output' );
- like( $stderr->[0], qr/\Q(Sue)/, 'Error message must contain "(Sue)"' );
-};
-
done_testing();
Oops, something went wrong.

0 comments on commit b75824c

Please sign in to comment.