diff -Nru ack-3.6.0/ack ack-3.7.0/ack --- ack-3.6.0/ack 2022-08-21 04:00:33.000000000 +0000 +++ ack-3.7.0/ack 2023-02-25 20:34:52.000000000 +0000 @@ -3,7 +3,7 @@ use strict; use warnings; -our $VERSION = 'v3.6.0'; # Check https://beyondgrep.com/ for updates +our $VERSION = 'v3.7.0'; # Check https://beyondgrep.com/ for updates use 5.010001; @@ -59,6 +59,9 @@ # The regex that we search for in each file. our $search_re; +# The regex that matches for things we want to exclude via the --not option. +our $search_not_re; + # Special /m version of our $search_re. our $scan_re; @@ -211,8 +214,10 @@ $files = App::Ack::Files->from_stdin(); $opt_regex //= shift @ARGV; ($search_re, $scan_re) = build_regex( $opt_regex, $opt ); + $search_not_re = _build_search_not_re( $opt ); $stats{search_re} = $search_re; $stats{scan_re} = $scan_re; + $stats{search_not_re} = $search_not_re; } else { if ( $opt_f ) { @@ -221,8 +226,10 @@ else { $opt_regex //= shift @ARGV; ($search_re, $scan_re) = build_regex( $opt_regex, $opt ); + $search_not_re = _build_search_not_re( $opt ); $stats{search_re} = $search_re; $stats{scan_re} = $scan_re; + $stats{search_not_re} = $search_not_re; } # XXX What is this checking for? if ( $search_re && $search_re =~ /\n/ ) { @@ -274,7 +281,7 @@ if ( $opt_debug ) { require List::Util; - my @stats = qw( search_re scan_re prescans linescans filematches linematches ); + my @stats = qw( search_re scan_re search_not_re prescans linescans filematches linematches ); my $width = List::Util::max( map { length } @stats ); for my $stat ( @stats ) { @@ -721,13 +728,17 @@ my $does_match; if ( $in_range ) { + $does_match = /$search_re/o; + if ( $does_match && $search_not_re ) { + local @-; + $does_match = !/$search_not_re/o; + } if ( $opt_v ) { - $does_match = !/$search_re/o; + $does_match = !$does_match; } else { - if ( $does_match = /$search_re/o ) { + if ( $does_match ) { # @- = @LAST_MATCH_START - # @+ = @LAST_MATCH_END $match_colno = $-[0] + 1; } } @@ -779,7 +790,12 @@ $in_range = 1 if ( $using_ranges && !$in_range && $opt_range_start && /$opt_range_start/o ); $match_colno = undef; - if ( $in_range && ($opt_v xor /$search_re/o) ) { + my $does_match = /$search_re/o; + if ( $does_match && $search_not_re ) { + local @-; + $does_match = !/$search_not_re/o; + } + if ( $in_range && ($opt_v xor $does_match) ) { if ( !$opt_v ) { $match_colno = $-[0] + 1; } @@ -821,7 +837,12 @@ $in_range = 1 if ( $using_ranges && !$in_range && $opt_range_start && /$opt_range_start/o ); if ( $in_range ) { - if ( !/$search_re/o ) { + my $does_match = /$search_re/o; + if ( $does_match && $search_not_re ) { + # local @-; No need to localize this because we don't use @-. + $does_match = !/$search_not_re/o; + } + if ( !$does_match ) { if ( !$has_printed_from_this_file ) { if ( $opt_break && $has_printed_from_any_file ) { App::Ack::print_blank_line(); @@ -855,7 +876,12 @@ if ( $in_range ) { $match_colno = undef; - if ( /$search_re/o ) { + my $is_match = /$search_re/o; + if ( $is_match && $search_not_re ) { + local @-; + $is_match = !/$search_not_re/o; + } + if ( $is_match ) { $match_colno = $-[0] + 1; if ( !$has_printed_from_this_file ) { $stats{filematches}++; @@ -1088,7 +1114,11 @@ chomp; $in_range = 1 if ( !$in_range && $opt_range_start && /$opt_range_start/o ); if ( $in_range ) { - if ( /$search_re/o xor $opt_v ) { + my $is_match = /$search_re/o; + if ( $is_match && $search_not_re ) { + $is_match = !/$search_not_re/o; + } + if ( $is_match xor $opt_v ) { ++$nmatches; last if $bail; } @@ -1099,7 +1129,11 @@ else { while ( <$fh> ) { chomp; - if ( /$search_re/o xor $opt_v ) { + my $is_match = /$search_re/o; + if ( $is_match && $search_not_re ) { + $is_match = !/$search_not_re/o; + } + if ( $is_match xor $opt_v ) { ++$nmatches; last if $bail; } @@ -1117,6 +1151,24 @@ } +sub _build_search_not_re { + my $opt = shift; + + my @not = @{$opt->{not}}; + + if ( @not ) { + my @built; + for my $re ( @not ) { + my ($built,undef) = build_regex( $re, $opt ); + push( @built, $built ); + } + return join( '|', @built ); + } + + return; +} + + =pod =encoding UTF-8 @@ -1248,7 +1300,7 @@ You don't have to specify both C<--range-start> and C<--range-end>. IF C<--range-start> is omitted, then the range runs from the first line in the -file unitl the first line that matches C<--range-end>. Similarly, if +file until the first line that matches C<--range-end>. Similarly, if C<--range-end> is omitted, the range runs from the first line matching C<--range-start> to the end of the file. @@ -1541,6 +1593,24 @@ No descending into subdirectories. +=item B<--not=PATTERN> + +Specifies a I that must NOT me true on a given line for a match to +occur. This option can be repeated. + +If you want to find all the lines with "dogs" but not if "cats" or "fish" +appear on the line, use: + + ack dogs --not cats --not fish + +Note that the options that affect "dogs" also affect "cats" and "fish", so +if you have + + ack -i -w dogs --not cats + +the the search for both "dogs" and "cats" will be case-insensitive and be +word-limited. + =item B<-o> Show only the part of each line matching PATTERN (turns off text @@ -1934,8 +2004,8 @@ -------- ----------------- ------------------ --------------- filename --color-filename ACK_COLOR_FILENAME black on_yellow match --color-match ACK_COLOR_MATCH bold green - line no. --color-lineno ACK COLOR_LINENO bold yellow - column no. --color-colno ACK COLOR_COLNO bold yellow + line no. --color-lineno ACK_COLOR_LINENO bold yellow + column no. --color-colno ACK_COLOR_COLNO bold yellow The column number column is only used if the column number is shown because of the --column option. @@ -2325,6 +2395,10 @@ How appropriate to have Inowledgements! Thanks to everyone who has contributed to ack in any way, including +Thomas Gossler, +Kieran Mace, +Volker Glave, +Axel Beckert, Eric Pement, Gabor Szabo, Frieder Bluemle, @@ -2453,7 +2527,7 @@ =head1 COPYRIGHT & LICENSE -Copyright 2005-2022 Andy Lester. +Copyright 2005-2023 Andy Lester. This program is free software; you can redistribute it and/or modify it under the terms of the Artistic License v2.0. diff -Nru ack-3.6.0/Changes ack-3.7.0/Changes --- ack-3.6.0/Changes 2022-08-21 04:00:33.000000000 +0000 +++ ack-3.7.0/Changes 2023-02-25 20:34:52.000000000 +0000 @@ -1,5 +1,22 @@ History file for ack 3. https://beyondgrep.com/ + +v3.7.0 Sat Feb 25 14:00:57 CST 2023 +======================================== +[FEATURES] +Added a repeatable --not option to let you supply patterns that should NOT +match. For example, if you want to search for "dogs" but not if "cats" or +"fish" are on the same line, you can do: + + ack dogs --not cats --not fish + +Added .Rmd to the list of extensions understood to be R. Thanks, Kieran +Mace. (GH#358) + +Added file type for for Powershell (.ps1 and .psm1 files). Thanks, Thomas +Gossler, (GH#362) + + v3.6.0 Sat Aug 20 22:57:47 CDT 2022 ======================================== [FEATURES] @@ -199,7 +216,7 @@ v3.0.0 Mon May 27 21:46:34 CDT 2019 ======================================== -First official release of ack verison 3. +First official release of ack version 3. See "Release notes for ack 3.0.0" at the bottom of this document for details of what has changed between ack 2.x and ack 3. diff -Nru ack-3.6.0/debian/changelog ack-3.7.0/debian/changelog --- ack-3.6.0/debian/changelog 2022-08-22 20:15:06.000000000 +0000 +++ ack-3.7.0/debian/changelog 2023-06-14 21:16:01.000000000 +0000 @@ -1,3 +1,12 @@ +ack (3.7.0-1) unstable; urgency=medium + + * Import new upstream version 3.7.0. + + Refresh sole patch. + + Update copyright years in debian/copyright. + * Declare compliance with Debian Policy 4.6.2. (No changes needed.) + + -- Axel Beckert Wed, 14 Jun 2023 23:16:01 +0200 + ack (3.6.0-1) unstable; urgency=medium [ Debian Janitor ] diff -Nru ack-3.6.0/debian/control ack-3.7.0/debian/control --- ack-3.6.0/debian/control 2022-08-22 16:40:51.000000000 +0000 +++ ack-3.7.0/debian/control 2023-06-14 21:12:34.000000000 +0000 @@ -13,7 +13,7 @@ libtest-differences-perl, libtest-pod-perl, sensible-utils -Standards-Version: 4.6.1 +Standards-Version: 4.6.2 Vcs-Browser: https://salsa.debian.org/perl-team/modules/packages/ack Vcs-Git: https://salsa.debian.org/perl-team/modules/packages/ack.git Homepage: https://beyondgrep.com/ diff -Nru ack-3.6.0/debian/copyright ack-3.7.0/debian/copyright --- ack-3.6.0/debian/copyright 2022-08-22 16:16:55.000000000 +0000 +++ ack-3.7.0/debian/copyright 2023-06-14 21:11:45.000000000 +0000 @@ -8,13 +8,13 @@ t/text/shut-up-be-happy.txt Files: * -Copyright: 2005-2022, Andy Lester +Copyright: 2005-2023, Andy Lester License: Artistic-2.0 Files: debian/* Copyright: 2007-2008, Peter Makholm 2009-2012, Ryan Niebur , - 2013-2022, Axel Beckert + 2013-2023, Axel Beckert License: Artistic or GPL-1+ Files: t/swamp/c-header.h diff -Nru ack-3.6.0/debian/patches/no-standalone-test-but-autopkgtests.patch ack-3.7.0/debian/patches/no-standalone-test-but-autopkgtests.patch --- ack-3.6.0/debian/patches/no-standalone-test-but-autopkgtests.patch 2022-08-22 16:21:12.000000000 +0000 +++ ack-3.7.0/debian/patches/no-standalone-test-but-autopkgtests.patch 2023-06-14 21:05:32.000000000 +0000 @@ -21,7 +21,7 @@ --- a/Makefile.PL +++ b/Makefile.PL -@@ -121,12 +121,12 @@ +@@ -122,12 +122,12 @@ $(CP) $(ACK) ~/bin/ack3 $(CP) ackrc ~/.ack3rc diff -Nru ack-3.6.0/lib/App/Ack/ConfigDefault.pm ack-3.7.0/lib/App/Ack/ConfigDefault.pm --- ack-3.6.0/lib/App/Ack/ConfigDefault.pm 2022-08-21 04:00:33.000000000 +0000 +++ ack-3.7.0/lib/App/Ack/ConfigDefault.pm 2023-02-25 20:34:52.000000000 +0000 @@ -189,7 +189,7 @@ # Visual Studio user and workspace settings # https://code.visualstudio.com/docs/getstarted/settings ---ignore-dir=.vscode +--ignore-dir=is:.vscode ### Filetypes defined @@ -404,6 +404,11 @@ # https://plone.org/ --type-add=plone:ext:pt,cpt,metadata,cpy,py +# PowerShell +# https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scripts +# https://learn.microsoft.com/en-us/powershell/scripting/developer/module/understanding-a-windows-powershell-module +--type-add=powershell:ext:ps1,psm1 + # PureScript # https://www.purescript.org --type-add=purescript:ext:purs @@ -415,7 +420,8 @@ # R # https://www.r-project.org/ ---type-add=rr:ext:R +# https://r4ds.had.co.nz/r-markdown.html +--type-add=rr:ext:R,Rmd # reStructured Text # https://docutils.sourceforge.io/rst.html diff -Nru ack-3.6.0/lib/App/Ack/ConfigLoader.pm ack-3.7.0/lib/App/Ack/ConfigLoader.pm --- ack-3.6.0/lib/App/Ack/ConfigLoader.pm 2022-08-21 04:00:33.000000000 +0000 +++ ack-3.7.0/lib/App/Ack/ConfigLoader.pm 2023-02-25 20:34:52.000000000 +0000 @@ -267,6 +267,8 @@ return; } + $opt->{not} = []; + return { 1 => sub { $opt->{1} = $opt->{m} = 1 }, 'A|after-context:-1' => sub { shift; $opt->{A} = _context_value(shift) }, @@ -330,6 +332,7 @@ }, 'noignore-directory|noignore-dir=s' => _generate_ignore_dir('--noignore-dir', $opt), 'nopager' => sub { $opt->{pager} = undef }, + 'not=s' => $opt->{not}, 'passthru' => \$opt->{passthru}, 'print0' => \$opt->{print0}, 'p|proximate:1' => \$opt->{p}, @@ -1012,6 +1015,7 @@ l => 1, m => 1, match => 1, + not => 1, o => 1, output => 1, p => 1, @@ -1079,6 +1083,9 @@ L => 1, l => 1, }, + not => { + g => 1, + }, o => { A => 1, B => 1, diff -Nru ack-3.6.0/lib/App/Ack.pm ack-3.7.0/lib/App/Ack.pm --- ack-3.6.0/lib/App/Ack.pm 2022-08-21 04:00:33.000000000 +0000 +++ ack-3.7.0/lib/App/Ack.pm 2023-02-25 20:34:52.000000000 +0000 @@ -16,8 +16,8 @@ our $VERSION; our $COPYRIGHT; BEGIN { - $VERSION = 'v3.6.0'; # Check https://beyondgrep.com/ for updates - $COPYRIGHT = 'Copyright 2005-2022 Andy Lester.'; + $VERSION = 'v3.7.0'; # Check https://beyondgrep.com/ for updates + $COPYRIGHT = 'Copyright 2005-2023 Andy Lester.'; } our $STANDALONE = 0; our $ORIGINAL_PROGRAM_NAME; @@ -246,6 +246,8 @@ --range-start PATTERN Specify PATTERN as the start of a match range. --range-end PATTERN Specify PATTERN as the end of a match range. --match PATTERN Specify PATTERN explicitly. Typically omitted. + --not PATTERN Specifies PATTERN that must not be found on + the line for a match to occur. Repeatable. Search output: --output=expr Output the evaluation of expr for each line diff -Nru ack-3.6.0/Makefile.PL ack-3.7.0/Makefile.PL --- ack-3.6.0/Makefile.PL 2022-08-21 00:19:55.000000000 +0000 +++ ack-3.7.0/Makefile.PL 2023-02-25 20:34:52.000000000 +0000 @@ -35,6 +35,7 @@ 'File::Next' => '1.18', 'File::Spec' => '3.00', 'File::Temp' => '0.19', # For newdir() + 'filetest' => 0, 'Getopt::Long' => '2.38', 'if' => 0, 'List::Util' => 0, @@ -134,6 +135,8 @@ test_xt: all $(FULLPERLRUN) t/runtests.pl 0 $(TEST_VERBOSE) "$(INST_LIB)" "$(INST_ARCHLIB)" $(TEST_XT_FILES) +test_all: test_classic test_standalone test_xt + PROF_ARGS = -Mblib blib/script/ack foo ~/parrot nytprof: all diff -Nru ack-3.6.0/MANIFEST ack-3.7.0/MANIFEST --- ack-3.6.0/MANIFEST 2022-08-21 04:02:47.000000000 +0000 +++ ack-3.7.0/MANIFEST 2023-02-25 20:37:22.000000000 +0000 @@ -32,26 +32,30 @@ t/test-pager t/00-load.t +t/FilterTest.pm t/ack-1.t +t/ack-Q.t +t/ack-c.t t/ack-color.t t/ack-column.t -t/ack-c.t -t/ack-files-from.t +t/ack-create-ackrc.t +t/ack-dump.t t/ack-f.t -t/ack-group.t +t/ack-files-from.t t/ack-g.t -t/ack-help.t -t/ack-help-types.t +t/ack-group.t t/ack-h.t +t/ack-help-types.t +t/ack-help.t +t/ack-i.barfly +t/ack-i.t t/ack-ignore-dir.t t/ack-ignore-file.t -t/ack-i.t -t/ack-i.barfly t/ack-k.t t/ack-l.t -t/ack-match.t t/ack-m.t t/ack-man.t +t/ack-match.t t/ack-n.t t/ack-o.t t/ack-output.t @@ -59,30 +63,37 @@ t/ack-passthru.t t/ack-print0.t t/ack-proximate.t -t/ack-Q.t -t/ack-show-types.t t/ack-s.t +t/ack-show-types.t t/ack-type-del.t t/ack-type.t t/ack-underline.barfly t/ack-underline.t t/ack-v.t -t/ack-w.t +t/ack-version.t t/ack-w.barfly +t/ack-w.t t/ack-x.t t/anchored.t t/bad-ackrc-opt.t t/basic.t t/command-line-files.t t/config-backwards-compat.t -t/context.t +t/config-finder.t +t/config-loader.t t/context-with-newlines.t +t/context.t +t/default-filter.t t/double-hyphen.t t/empty-lines.t t/exit-code.t +t/ext-filter.t +t/file-iterator.t t/file-permission.t t/filetype-detection.t t/filetypes.t +t/filter.t +t/firstlinematch-filter.t t/forbidden-options.t t/from-stdin.t t/highlighting.t @@ -92,35 +103,23 @@ t/invalid-ackrc.t t/invalid-options.t t/inverted-file-filter.t +t/is-filter.t t/line-endings.t t/longopts.t +t/lowercase.t +t/match-filter.t t/multiple-captures.t t/mutex-options.t t/named-pipes.t t/needs-line-scan.t t/noackrc.t +t/noenv.t t/prescan-line-boundaries.t t/process-substitution.t t/runtests.pl t/trailing-whitespace.t t/zero.t -t/internals/FilterTest.pm -t/internals/ack-create-ackrc.t -t/internals/ack-dump.t -t/internals/ack-version.t -t/internals/config-finder.t -t/internals/config-loader.t -t/internals/default-filter.t -t/internals/ext-filter.t -t/internals/file-iterator.t -t/internals/filter.t -t/internals/firstlinematch-filter.t -t/internals/is-filter.t -t/internals/lowercase.t -t/internals/match-filter.t -t/internals/noenv.t - t/etc/buttonhook.xml.xxx t/etc/shebang.empty.xxx t/etc/shebang.foobar.xxx diff -Nru ack-3.6.0/META.json ack-3.7.0/META.json --- ack-3.6.0/META.json 2022-08-21 04:02:47.000000000 +0000 +++ ack-3.7.0/META.json 2023-02-25 20:37:22.000000000 +0000 @@ -4,7 +4,7 @@ "Andy Lester " ], "dynamic_config" : 1, - "generated_by" : "ExtUtils::MakeMaker version 7.38, CPAN::Meta::Converter version 2.150010", + "generated_by" : "ExtUtils::MakeMaker version 7.64, CPAN::Meta::Converter version 2.150010", "license" : [ "artistic_2" ], @@ -47,6 +47,7 @@ "Test::Harness" : "2.50", "Test::More" : "0.98", "Text::ParseWords" : "3.1", + "filetest" : "0", "if" : "0", "parent" : "0", "perl" : "5.010001", @@ -69,6 +70,6 @@ }, "x_MailingList" : "https://groups.google.com/group/ack-users" }, - "version" : "v3.6.0", - "x_serialization_backend" : "JSON::PP version 4.02" + "version" : "v3.7.0", + "x_serialization_backend" : "JSON::PP version 4.07" } diff -Nru ack-3.6.0/META.yml ack-3.7.0/META.yml --- ack-3.6.0/META.yml 2022-08-21 04:02:47.000000000 +0000 +++ ack-3.7.0/META.yml 2023-02-25 20:37:22.000000000 +0000 @@ -7,7 +7,7 @@ configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 1 -generated_by: 'ExtUtils::MakeMaker version 7.38, CPAN::Meta::Converter version 2.150010' +generated_by: 'ExtUtils::MakeMaker version 7.64, CPAN::Meta::Converter version 2.150010' license: artistic_2 meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html @@ -33,6 +33,7 @@ Test::Harness: '2.50' Test::More: '0.98' Text::ParseWords: '3.1' + filetest: '0' if: '0' parent: '0' perl: '5.010001' @@ -43,5 +44,5 @@ homepage: https://beyondgrep.com/ license: https://www.perlfoundation.org/artistic-license-20.html repository: git://github.com/beyondgrep/ack3.git -version: v3.6.0 +version: v3.7.0 x_serialization_backend: 'CPAN::Meta::YAML version 0.018' diff -Nru ack-3.6.0/README.md ack-3.7.0/README.md --- ack-3.6.0/README.md 2022-08-21 04:00:33.000000000 +0000 +++ ack-3.7.0/README.md 2023-02-25 20:34:52.000000000 +0000 @@ -69,11 +69,21 @@ See the [Community](https://beyondgrep.com/community/) page. +Please follow the [Code of Conduct](CODE_OF_CONDUCT.md) in all your interactions with our project. + # License -Copyright 2005-2022 Andy Lester. +Copyright 2005-2023 Andy Lester. This program is free software; you can redistribute it and/or modify it under the terms of the [Artistic License v2.0](https://www.perlfoundation.org/artistic_license_2_0). See also the LICENSE.md file that comes with the ack distribution. + +# Support + +[ack](https://github.com/beyondgrep/ack3) and [beyondgrep.com](https://beyondgrep.com) are supported by [DigitalOcean](https://m.do.co/c/6a437192f552). + + + + diff -Nru ack-3.6.0/t/ack-column.t ack-3.7.0/t/ack-column.t --- ack-3.6.0/t/ack-column.t 2019-11-09 03:55:25.000000000 +0000 +++ ack-3.7.0/t/ack-column.t 2023-02-25 20:34:52.000000000 +0000 @@ -3,7 +3,7 @@ use warnings; use strict; -use Test::More tests => 4; +use Test::More tests => 6; use lib 't'; @@ -35,6 +35,26 @@ my @results = run_ack( @args, @files ); lists_match( \@results, \@expected, 'Checking column numbers' ); +} + + +WITH_COLUMNS_AND_NOT: { + # Verify that the --not does not mess up the column number. + my @expected = line_split( <<'HERE' ); +62:24: With such name as "Nevermore." +69:26: Then the bird said, "Nevermore." +76:18: Of 'Never -- nevermore.' +83:24: Meant in croaking "Nevermore." +90:26: She shall press, ah, nevermore! +125:22: Shall be lifted--nevermore! +HERE + @expected = map { "${raven}:$_" } @expected; + + my @files = ( $raven ); + my @args = ( @base_args, '--column', '--not', 'Quoth' ); + my @results = run_ack( @args, @files ); + + lists_match( \@results, \@expected, 'Checking column numbers' ); } diff -Nru ack-3.6.0/t/ack-create-ackrc.t ack-3.7.0/t/ack-create-ackrc.t --- ack-3.6.0/t/ack-create-ackrc.t 1970-01-01 00:00:00.000000000 +0000 +++ ack-3.7.0/t/ack-create-ackrc.t 2023-02-25 20:34:52.000000000 +0000 @@ -0,0 +1,28 @@ +#!perl + +use strict; +use warnings; + +use lib 't'; + +use Test::More tests => 5; +use Util; +use App::Ack (); +use App::Ack::ConfigDefault (); + +prep_environment(); + +my @commented = App::Ack::ConfigDefault::options(); +my @uncommented = App::Ack::ConfigDefault::options_clean(); + +cmp_ok( scalar @commented, '>', scalar @uncommented, 'There are fewer lines in the uncommented options.' ); + +my @output = run_ack( 'ack', '--create-ackrc' ); + +ok(scalar(grep { $_ eq '--ignore-ack-defaults' } @output), '--ignore-ack-defaults should be present in output'); +@output = grep { $_ ne '--ignore-ack-defaults' } @output; + +lists_match(\@output, \@commented, 'lines in output should match the default options'); + +my @versions = grep { /\Qack version $App::Ack::VERSION/ } @commented; +is( scalar @versions, 1, 'Got exactly one version line' ); diff -Nru ack-3.6.0/t/ack-c.t ack-3.7.0/t/ack-c.t --- ack-3.6.0/t/ack-c.t 2019-12-28 21:55:29.000000000 +0000 +++ ack-3.7.0/t/ack-c.t 2023-02-25 20:34:52.000000000 +0000 @@ -3,7 +3,7 @@ use warnings; use strict; -use Test::More tests => 6; +use Test::More tests => 7; use lib 't'; use Util; @@ -80,4 +80,12 @@ ack_sets_match( [ @args, @files ], \@expected, 'ack -c -h should return one line of results' ); } +NOT: { + my @args = qw( Montresor -c -h --not God ); + my @files = ( 't/text/amontillado.txt' ); + my @expected = ( 2 ); + + ack_sets_match( [ @args, @files ], \@expected, 'One line of results, with an accurate count' ); +} + exit 0; diff -Nru ack-3.6.0/t/ack-dump.t ack-3.7.0/t/ack-dump.t --- ack-3.6.0/t/ack-dump.t 1970-01-01 00:00:00.000000000 +0000 +++ ack-3.7.0/t/ack-dump.t 2023-02-25 20:34:52.000000000 +0000 @@ -0,0 +1,35 @@ +#!perl + +use strict; +use warnings; + +use lib 't'; +use Util; + +use Test::More tests => 5; + +use App::Ack::ConfigDefault; + +prep_environment(); + +DUMP: { + my @expected = App::Ack::ConfigDefault::options_clean(); + + my @args = qw( --dump ); + my @results = run_ack( @args ); + + is( $results[0], 'Defaults', 'header should be Defaults' ); + splice @results, 0, 2; # remove header (2 lines) + + s/^\s*// for @results; + + sets_match( \@results, \@expected, __FILE__ ); + + my @perl = grep { /\bperl\b/ } @results; + is( scalar @perl, 2, 'Two specs for Perl' ); + + my @ignore_dir = grep { /ignore-dir/ } @results; + is( scalar @ignore_dir, 28, 'Twenty-eight specs for ignoring directories' ); +} + +exit 0; diff -Nru ack-3.6.0/t/ack-output.t ack-3.7.0/t/ack-output.t --- ack-3.6.0/t/ack-output.t 2019-12-28 21:55:29.000000000 +0000 +++ ack-3.7.0/t/ack-output.t 2023-02-25 20:34:52.000000000 +0000 @@ -303,7 +303,7 @@ } -# $f is the filenname, needed for grep, emulating ack2 $filename:$lineno:$_ +# $f is the filename, needed for grep, emulating ack2 $filename:$lineno:$_ FILENAME_SUBSTITUTION_1 : { my @expected = line_split( <<'HERE' ); t/text/ozymandias.txt:4:Half sunk, a shattered visage lies, whose frown, diff -Nru ack-3.6.0/t/ack-passthru.t ack-3.7.0/t/ack-passthru.t --- ack-3.6.0/t/ack-passthru.t 2019-12-28 21:55:29.000000000 +0000 +++ ack-3.7.0/t/ack-passthru.t 2023-02-25 20:34:52.000000000 +0000 @@ -3,7 +3,7 @@ use warnings; use strict; -use Test::More tests => 6; +use Test::More tests => 7; use lib 't'; use Util; @@ -98,6 +98,34 @@ lists_match( \@results, \@expected, q{With filename} ); }; + + +subtest 'With filename and --not' => sub { + plan tests => 2; + + my $ozy = reslash( 't/text/ozymandias.txt' ); + my @expected = line_split( <<"HERE" ); +$ozy-1-I met a traveller from an antique land +$ozy-2-Who said: Two vast and trunkless legs of stone +$ozy-3-Stand in the desert... Near them, on the sand, +$ozy:4:Half sunk, a shattered visage lies, whose frown, +$ozy:5:And wrinkled lip, and sneer of cold command, +$ozy-6-Tell that its sculptor well those passions read +$ozy-7-Which yet survive, stamped on these lifeless things, +$ozy-8-The hand that mocked them, and the heart that fed: +$ozy-9-And on the pedestal these words appear: +$ozy-10-'My name is Ozymandias, king of kings: +$ozy-11-Look on my works, ye Mighty, and despair!' +$ozy-12-Nothing beside remains. Round the decay +$ozy-13-Of that colossal wreck, boundless and bare +$ozy-14-The lone and level sands stretch far away. +HERE + + # Same results as the "With filename" test except that we exclude "survive". + my @results = run_ack( qw( li\w+ t/text/ozymandias.txt -H --passthru --not survive ) ); + + lists_match( \@results, \@expected, q{With filename} ); +}; SKIP: { diff -Nru ack-3.6.0/t/ack-proximate.t ack-3.7.0/t/ack-proximate.t --- ack-3.6.0/t/ack-proximate.t 2019-11-09 03:55:25.000000000 +0000 +++ ack-3.7.0/t/ack-proximate.t 2023-02-25 20:34:52.000000000 +0000 @@ -3,7 +3,7 @@ use warnings; use strict; -use Test::More tests => 6; +use Test::More tests => 7; use lib 't'; use Util; @@ -114,6 +114,37 @@ }; +subtest 'Grouped proximate=2 with --not' => sub { + plan tests => 2; + + my @expected = line_split( <<"HERE" ); +$bill +53:fact tried by a jury, shall be otherwise re-examined in any Court of + +$const +199:To constitute Tribunals inferior to the supreme Court; + +372:Judges of the supreme Court, and all other Officers of the United States, + +404:Court, and in such inferior Courts as the Congress may from time to +406:Courts, shall hold their Offices during good Behaviour, and shall, at + +425:and those in which a State shall be Party, the supreme Court shall + +441:of two Witnesses to the same overt Act, or on Confession in open Court. +HERE + + my @files = qw( t/text ); + my @args = qw( --proximate=2 --group -i --sort court --not law ); + + for my $arg ( qw( --proximate=2 -p2 ) ) { + $args[0] = $arg; + ack_lists_match( [ @args, @files ], \@expected, 'Grouped proximate=2' ); + } +}; + + + subtest 'Ungrouped proximate=2' => sub { plan tests => 2; diff -Nru ack-3.6.0/t/ack-version.t ack-3.7.0/t/ack-version.t --- ack-3.6.0/t/ack-version.t 1970-01-01 00:00:00.000000000 +0000 +++ ack-3.7.0/t/ack-version.t 2023-02-25 20:34:52.000000000 +0000 @@ -0,0 +1,22 @@ +#!perl + +use strict; +use warnings; + +use Test::More tests => 2; +use lib 't'; +use Util; + +use App::Ack; + +prep_environment(); + +my ( $stdout, $stderr ) = run_ack_with_stderr( '--version' ); + +is_empty_array( $stderr, 'Nothing in stderr' ); +my @lines = @{$stdout}; +like( $lines[0], qr/\Q$App::Ack::VERSION/, 'Found the version in the first line' ); + +done_testing(); + +exit 0; diff -Nru ack-3.6.0/t/ack-v.t ack-3.7.0/t/ack-v.t --- ack-3.6.0/t/ack-v.t 2019-12-28 21:55:29.000000000 +0000 +++ ack-3.7.0/t/ack-v.t 2023-02-25 20:34:52.000000000 +0000 @@ -3,7 +3,7 @@ use warnings; use strict; -use Test::More tests => 2; +use Test::More tests => 3; use lib 't'; use Util; @@ -41,6 +41,29 @@ ack_lists_match( [ @args, @files ], \@expected, 'Find the lines that do not contain a "w", ignoring case' ); } + +# -v and --not means double negation. +WITH_NOT: { + my @expected = line_split( <<'END' ); +I met a traveller from an antique land +Who said: Two vast and trunkless legs of stone +Stand in the desert... Near them, on the sand, +Half sunk, a shattered visage lies, whose frown, +And wrinkled lip, and sneer of cold command, +Tell that its sculptor well those passions read +The hand that mocked them, and the heart that fed: +'My name is Ozymandias, king of kings: +Look on my works, ye Mighty, and despair!' +Of that colossal wreck, boundless and bare +END + + my @args = qw( -i -v the --not them ); + my @files = qw( t/text/ozymandias.txt ); + + ack_lists_match( [ @args, @files ], \@expected, 'Find "the" --not "them"' ); +} + + done_testing(); exit 0; diff -Nru ack-3.6.0/t/ack-x.t ack-3.7.0/t/ack-x.t --- ack-3.6.0/t/ack-x.t 2020-06-30 04:04:32.000000000 +0000 +++ ack-3.7.0/t/ack-x.t 2023-02-25 20:34:52.000000000 +0000 @@ -53,7 +53,7 @@ # GH #175: -s doesn't work with -x -# We have to show that -s supresses errors on missing and unreadable files, +# We have to show that -s suppresses errors on missing and unreadable files, # while still giving results on files that are there. subtest 'GH #175' => sub { diff -Nru ack-3.6.0/t/config-finder.t ack-3.7.0/t/config-finder.t --- ack-3.6.0/t/config-finder.t 1970-01-01 00:00:00.000000000 +0000 +++ ack-3.7.0/t/config-finder.t 2023-02-25 20:34:52.000000000 +0000 @@ -0,0 +1,228 @@ +#!perl + +use strict; +use warnings; + +use lib 't'; +use Util; + +use Cwd qw(realpath); +use File::Spec; +use File::Temp; +use Test::Builder; +use Test::More; + +use App::Ack::ConfigFinder; + +my $tmpdir = $ENV{'TMPDIR'}; +my $home = $ENV{'HOME'}; + +for ( $tmpdir, $home ) { + s{/$}{} if defined; +} + +if ( $tmpdir && ($tmpdir =~ /^\Q$home/) ) { + plan skip_all => "Your \$TMPDIR ($tmpdir) is set to a descendant directory of your home directory. This test is known to fail with such a setting. Please set your TMPDIR to something else to get this test to pass."; + exit; +} + +plan tests => 26; + +# Set HOME to a known value, so we get predictable results. +local $ENV{HOME} = realpath('t/home'); + +# Clear the user's ACKRC so it doesn't throw out expect_ackrcs(). +delete $ENV{'ACKRC'}; + +my $finder; +my @global_filenames = create_globals(); + +my @global_files = map { +{ path => $_ } } @global_filenames; +my @std_files = (@global_files, { path => File::Spec->catfile($ENV{'HOME'}, '.ackrc') }); + +my $wd = getcwd_clean(); +my $tempdir = File::Temp->newdir; +safe_chdir( $tempdir->dirname ); + +$finder = App::Ack::ConfigFinder->new; +with_home( sub { + expect_ackrcs( \@std_files, 'having no project file should return only the top level files' ); +} ); + +no_home( sub { + expect_ackrcs( \@global_files, 'only system-wide ackrc is returned if HOME is not defined with no project files' ); +} ); + +safe_mkdir( 'foo' ); +safe_mkdir( File::Spec->catdir('foo', 'bar') ); +safe_mkdir( File::Spec->catdir('foo', 'bar', 'baz') ); +safe_chdir( File::Spec->catdir('foo', 'bar', 'baz') ); + +touch_ackrc( '.ackrc' ); +with_home( sub { + expect_ackrcs( [ @std_files, { project => 1, path => File::Spec->rel2abs('.ackrc') }], 'a project file in the same directory should be detected' ); +} ); +no_home( sub { + expect_ackrcs( [ @global_files, { project => 1, path => File::Spec->rel2abs('.ackrc') } ], 'a project file in the same directory should be detected' ); +} ); + +unlink '.ackrc'; + +my $project_file = File::Spec->catfile($tempdir->dirname, 'foo', 'bar', '.ackrc'); +touch_ackrc( $project_file ); +with_home( sub { + expect_ackrcs( [ @std_files, { project => 1, path => $project_file } ], 'a project file in the parent directory should be detected' ); +} ); +no_home( sub { + expect_ackrcs( [ @global_files, { project => 1, path => $project_file } ], 'a project file in the parent directory should be detected' ); +} ); +unlink $project_file; + +$project_file = File::Spec->catfile($tempdir->dirname, 'foo', '.ackrc'); +touch_ackrc( $project_file ); +with_home( sub { + expect_ackrcs( [ @std_files, { project => 1, path => $project_file } ], 'a project file in the grandparent directory should be detected' ); +} ); +no_home( sub { + expect_ackrcs( [ @global_files, { project => 1, path => $project_file } ], 'a project file in the grandparent directory should be detected' ); +} ); + +touch_ackrc( '.ackrc' ); + +with_home( sub { + expect_ackrcs( [ @std_files, { project => 1, path => File::Spec->rel2abs('.ackrc') } ], 'a project file in the same directory should be detected, even with another one above it' ); +} ); +no_home( sub { + expect_ackrcs( [ @global_files, { project => 1, path => File::Spec->rel2abs('.ackrc') } ], 'a project file in the same directory should be detected, even with another one above it' ); +} ); + +unlink '.ackrc'; +unlink $project_file; + +touch_ackrc( '_ackrc' ); +with_home( sub { + expect_ackrcs( [ @std_files, { project => 1, path => File::Spec->rel2abs('_ackrc') } ], 'a project file in the same directory should be detected' ); +} ); +no_home( sub { + expect_ackrcs( [ @global_files, { project => 1, path => File::Spec->rel2abs('_ackrc') } ], 'a project file in the same directory should be detected' ); +} ); + +unlink '_ackrc'; + +$project_file = File::Spec->catfile($tempdir->dirname, 'foo', '_ackrc'); +touch_ackrc( $project_file ); +with_home( sub { + expect_ackrcs( [ @std_files, { project => 1, path => $project_file } ], 'a project file in the grandparent directory should be detected' ); +} ); +no_home( sub { + expect_ackrcs( [ @global_files, { project => 1, path => $project_file } ], 'a project file in the grandparent directory should be detected' ); +} ); + +touch_ackrc( '_ackrc' ); +with_home( sub { expect_ackrcs( [ @std_files, { project => 1, path => File::Spec->rel2abs('_ackrc') } ], 'a project file in the same directory should be detected, even with another one above it' ); +} ); +no_home( sub { + expect_ackrcs( [ @global_files, { project => 1, path => File::Spec->rel2abs('_ackrc') } ], 'a project file in the same directory should be detected, even with another one above it' ); +} ); + +unlink $project_file; +touch_ackrc( '.ackrc' ); + +do { + my $finder_fn = sub { + my $ok = eval { $finder->find_config_files }; + my $err = $@; + ok( !$ok, '.ackrc + _ackrc is error' ); + like( $err, qr/contains both \.ackrc and _ackrc/, 'Got the expected error' ); + }; + with_home( $finder_fn ); + no_home( $finder_fn ); + + unlink '.ackrc'; + $project_file = File::Spec->catfile($tempdir->dirname, 'foo', '.ackrc'); + touch_ackrc( $project_file ); + with_home( sub { + expect_ackrcs( [ @std_files, { project => 1, path => File::Spec->rel2abs('_ackrc') }], 'a lower-level _ackrc should be preferred to a higher-level .ackrc' ); + } ); + no_home( sub { + expect_ackrcs( [ @global_files, { project => 1, path => File::Spec->rel2abs('_ackrc') } ], 'a lower-level _ackrc should be preferred to a higher-level .ackrc' ); + } ); + + unlink '_ackrc'; +}; + +do { + my $test_home = File::Spec->catdir( $tempdir->dirname, 'foo' ); + local $ENV{'HOME'} = $test_home; + + my $user_file = File::Spec->catfile( $test_home, '.ackrc'); + touch_ackrc( $user_file ); + + expect_ackrcs( [ @global_files, { path => $user_file } ], q{Don't load the same ackrc file twice} ); + unlink($user_file); +}; + +do { + safe_chdir( $tempdir->dirname ); + local $ENV{'HOME'} = File::Spec->catfile($tempdir->dirname, 'foo'); + + my $user_file = File::Spec->catfile($ENV{'HOME'}, '.ackrc'); + touch_ackrc( $user_file ); + + my $ackrc = create_tempfile(); + local $ENV{'ACKRC'} = $ackrc->filename; + + expect_ackrcs( [ @global_files, { path => $ackrc->filename } ], q{ACKRC overrides user's HOME ackrc} ); + unlink $ackrc->filename; + + expect_ackrcs( [ @global_files, { path => $user_file } ], q{ACKRC doesn't override if it doesn't exist} ); + + touch_ackrc( $ackrc->filename ); + safe_chdir( 'foo' ); + expect_ackrcs( [ @global_files, { path => $ackrc->filename}, { project => 1, path => $user_file } ], q{~/.ackrc should still be found as a project ackrc} ); + unlink $ackrc->filename; +}; + +safe_chdir( $wd ); +clean_up_globals(); + +exit 0; + + +sub with_home { + my ( $fn ) = @_; + + $fn->(); + + return; +} + + +sub no_home { + my ( $fn ) = @_; + + # We have to manually store the value of HOME because localized + # delete isn't supported until Perl 5.12.0. + my $home_saved = delete $ENV{HOME}; + $fn->(); + $ENV{HOME} = $home_saved; + + return; +} + +sub expect_ackrcs { + local $Test::Builder::Level = $Test::Builder::Level + 1; + + my $expected = shift; + my $name = shift; + + my @got = $finder->find_config_files; + my @expected = @{$expected}; + + foreach my $element (@got, @expected) { + $element->{'path'} = realpath($element->{'path'}); + } + is_deeply( \@got, \@expected, $name ) or diag(explain(got=>\@got,expected=>\@expected)); + + return; +} diff -Nru ack-3.6.0/t/config-loader.t ack-3.7.0/t/config-loader.t --- ack-3.6.0/t/config-loader.t 1970-01-01 00:00:00.000000000 +0000 +++ ack-3.7.0/t/config-loader.t 2023-02-25 20:34:52.000000000 +0000 @@ -0,0 +1,295 @@ +#!perl + +use strict; +use warnings; +use lib 't'; +use Util; + +use Test::More tests => 28; + +use App::Ack::Filter::Default; +use App::Ack::ConfigLoader; + +delete @ENV{qw( PAGER ACK_PAGER ACK_PAGER_COLOR )}; + +my %defaults = ( + 'break' => undef, + c => undef, + color => undef, + column => undef, + debug => undef, + f => undef, + files_from => undef, + filters => [ App::Ack::Filter::Default->new ], + follow => undef, + g => undef, + h => undef, + H => undef, + heading => undef, + l => undef, + L => undef, + m => undef, + n => undef, + not => [], + output => undef, + p => undef, + pager => undef, + passthru => undef, + print0 => undef, + Q => undef, + range_start => undef, + range_end => undef, + range_invert => undef, + regex => undef, + s => undef, + show_types => undef, + sort_files => undef, + underline => undef, + v => undef, + w => undef, +); + +test_loader( + expected_opts => { %defaults }, + 'empty inputs should result in default outputs' +); + +# --after_context, --before_context +for my $option ( qw( after_context before_context ) ) { + my $long_arg = $option; + $long_arg =~ s/_/-/ or die; + + my $target_arg = uc substr( $option, 0, 1 ); + + test_loader( + argv => [ "--$long_arg=15" ], + expected_opts => { %defaults, $target_arg => 15 }, + "--$long_arg=15 should set $target_arg to 15", + ); + + test_loader( + argv => [ "--$long_arg=0" ], + expected_opts => { %defaults, $target_arg => 0 }, + "--$long_arg=0 should set $target_arg to 0", + ); + + test_loader( + argv => [ "--$long_arg" ], + expected_opts => { %defaults, $target_arg => 2 }, + "--$long_arg without a value should default $target_arg to 2", + ); + + test_loader( + argv => [ "--$long_arg=-43" ], + expected_opts => { %defaults, $target_arg => 2 }, + "--$long_arg with a negative value should default $target_arg to 2", + ); + + my $short_arg = '-' . uc substr( $option, 0, 1 ); + test_loader( + argv => [ $short_arg, 15 ], + expected_opts => { %defaults, $target_arg => 15 }, + "$short_arg 15 should set $target_arg to 15", + ); + + test_loader( + argv => [ $short_arg, 0 ], + expected_opts => { %defaults, $target_arg => 0 }, + "$short_arg 0 should set $target_arg to 0", + ); + + test_loader( + argv => [ $short_arg ], + expected_opts => { %defaults, $target_arg => 2 }, + "$short_arg without a value should default $target_arg to 2", + ); + + test_loader( + argv => [ $short_arg, '-43' ], + expected_opts => { %defaults, $target_arg => 2 }, + "$short_arg with a negative value should default $target_arg to 2", + ); +} + +test_loader( + argv => ['-C', 5], + expected_opts => { %defaults, A => 5, B => 5 }, + '-C sets both B and A' +); + +test_loader( + argv => ['-C'], + expected_opts => { %defaults, A => 2, B => 2 }, + '-C sets both B and A, with default' +); + +test_loader( + argv => ['-C', 0], + expected_opts => { %defaults, A => 0, B => 0 }, + '-C sets both B and A, with zero overriding default' +); + +test_loader( + argv => ['-C', -43], + expected_opts => { %defaults, A => 2, B => 2 }, + '-C with invalid value sets both B and A to default' +); + +test_loader( + argv => ['--context=5'], + expected_opts => { %defaults, A => 5, B => 5 }, + '--context sets both B and A' +); + +test_loader( + argv => ['--context'], + expected_opts => { %defaults, A => 2, B => 2 }, + '--context sets both B and A, with default' +); + +test_loader( + argv => ['--context=0'], + expected_opts => { %defaults, A => 0, B => 0 }, + '--context sets both B and A, with zero overriding default' +); + +test_loader( + argv => ['--context=-43'], + expected_opts => { %defaults, A => 2, B => 2 }, + '--context with invalid value sets both B and A to default' +); + + +subtest 'ACK_PAGER' => sub { + plan tests => 3; + + local $ENV{'ACK_PAGER'} = 't/test-pager --skip=2'; + + test_loader( + argv => [], + expected_opts => { %defaults, pager => 't/test-pager --skip=2' }, + 'ACK_PAGER should set the default pager', + ); + + test_loader( + argv => ['--pager=t/test-pager'], + expected_opts => { %defaults, pager => 't/test-pager' }, + '--pager should override ACK_PAGER', + ); + + test_loader( + argv => ['--nopager'], + expected_opts => { %defaults }, + '--nopager should suppress ACK_PAGER', + ); +}; + + +subtest 'ACK_PAGER_COLOR' => sub { + plan tests => 6; + + local $ENV{'ACK_PAGER_COLOR'} = 't/test-pager --skip=2'; + + test_loader( + argv => [], + expected_opts => { %defaults, pager => 't/test-pager --skip=2' }, + 'ACK_PAGER_COLOR should set the default pager', + ); + + test_loader( + argv => ['--pager=t/test-pager'], + expected_opts => { %defaults, pager => 't/test-pager' }, + '--pager should override ACK_PAGER_COLOR', + ); + + test_loader( + argv => ['--nopager'], + expected_opts => { %defaults }, + '--nopager should suppress ACK_PAGER_COLOR', + ); + + local $ENV{'ACK_PAGER'} = 't/test-pager --skip=3'; + + test_loader( + argv => [], + expected_opts => { %defaults, pager => 't/test-pager --skip=2' }, + 'ACK_PAGER_COLOR should override ACK_PAGER', + ); + + test_loader( + argv => ['--pager=t/test-pager'], + expected_opts => { %defaults, pager => 't/test-pager' }, + '--pager should override ACK_PAGER_COLOR and ACK_PAGER', + ); + + test_loader( + argv => ['--nopager'], + expected_opts => { %defaults }, + '--nopager should suppress ACK_PAGER_COLOR and ACK_PAGER', + ); +}; + + +subtest 'PAGER' => sub { + plan tests => 3; + + local $ENV{'PAGER'} = 't/test-pager'; + + test_loader( + argv => [], + expected_opts => { %defaults }, + q{PAGER doesn't affect ack by default}, + ); + + test_loader( + argv => ['--pager'], + expected_opts => { %defaults, pager => 't/test-pager' }, + 'PAGER is used if --pager is specified with no argument', + ); + + test_loader( + argv => ['--pager=t/test-pager --skip=2'], + expected_opts => { %defaults, pager => 't/test-pager --skip=2' }, + 'PAGER is not used if --pager is specified with an argument', + ); +}; + +done_testing(); + +exit 0; + + +sub test_loader { + local $Test::Builder::Level = $Test::Builder::Level + 1; + + die 'Must pass key/value pairs, plus a message at the end' unless @_ % 2 == 1; + + my $msg = pop; + my %opts = @_; + + return subtest subtest_name( $msg, \%opts ) => sub { + plan tests => 3; + + my $env = delete $opts{env} // ''; + my $argv = delete $opts{argv} // []; + my $expected_opts = delete $opts{expected_opts}; + + is( scalar keys %opts, 0, 'All the keys are gone' ); + + my $got_opts; + my $got_targets; + do { + local @ARGV = (); + + my @arg_sources = ( + { name => 'ARGV', contents => $argv }, + ); + + $got_opts = App::Ack::ConfigLoader::process_args( @arg_sources ); + $got_targets = [ @ARGV ]; + }; + + is_deeply( $got_opts, $expected_opts, 'Options match' ); + is_empty_array( $got_targets, 'Got no targets' ); + }; +} diff -Nru ack-3.6.0/t/default-filter.t ack-3.7.0/t/default-filter.t --- ack-3.6.0/t/default-filter.t 1970-01-01 00:00:00.000000000 +0000 +++ ack-3.7.0/t/default-filter.t 2023-02-25 20:34:52.000000000 +0000 @@ -0,0 +1,98 @@ +#!perl + +use strict; +use warnings; +use lib 't'; + +use FilterTest; +use Test::More tests => 1; + +use App::Ack::Filter::Default; +use App::Ack::Filter; + +App::Ack::Filter->register_filter('default' => 'App::Ack::Filter::Default'); + +filter_test( + [ 'default' ], [ + 't/swamp/#emacs-workfile.pl#', + 't/swamp/0', + 't/swamp/constitution-100k.pl', + 't/swamp/c-header.h', + 't/swamp/c-source.c', + 't/swamp/crystallography-weenies.f', + 't/swamp/example.R', + 't/swamp/file.bar', + 't/swamp/file.foo', + 't/swamp/fresh.css', + 't/swamp/fresh.min.css', + 't/swamp/fresh.css.min', + 't/swamp/html.htm', + 't/swamp/html.html', + 't/swamp/incomplete-last-line.txt', + 't/swamp/javascript.js', + 't/swamp/lua-shebang-test', + 't/swamp/Makefile', + 't/swamp/Makefile.PL', + 't/swamp/MasterPage.master', + 't/swamp/minified.js.min', + 't/swamp/minified.min.js', + 't/swamp/not-an-#emacs-workfile#', + 't/swamp/notaMakefile', + 't/swamp/notaRakefile', + 't/swamp/notes.md', + 't/swamp/options-crlf.pl', + 't/swamp/options.pl', + 't/swamp/options.pl.bak', + 't/swamp/perl-test.t', + 't/swamp/perl-without-extension', + 't/swamp/perl.cgi', + 't/swamp/perl.handler.pod', + 't/swamp/perl.pl', + 't/swamp/perl.pm', + 't/swamp/perl.pod', + 't/swamp/pipe-stress-freaks.F', + 't/swamp/Rakefile', + 't/swamp/Sample.ascx', + 't/swamp/Sample.asmx', + 't/swamp/sample.asp', + 't/swamp/sample.aspx', + 't/swamp/sample.rake', + 't/swamp/service.svc', + 't/swamp/__pycache__/notes.pl', + 't/swamp/blib/ignore.pm', + 't/swamp/blib/ignore.pod', + 't/swamp/groceries/fruit', + 't/swamp/groceries/junk', + 't/swamp/groceries/meat', + 't/swamp/groceries/another_subdir/fruit', + 't/swamp/groceries/another_subdir/junk', + 't/swamp/groceries/another_subdir/meat', + 't/swamp/groceries/another_subdir/CVS/fruit', + 't/swamp/groceries/another_subdir/CVS/junk', + 't/swamp/groceries/another_subdir/CVS/meat', + 't/swamp/groceries/another_subdir/RCS/fruit', + 't/swamp/groceries/another_subdir/RCS/junk', + 't/swamp/groceries/another_subdir/RCS/meat', + 't/swamp/groceries/dir.d/fruit', + 't/swamp/groceries/dir.d/junk', + 't/swamp/groceries/dir.d/meat', + 't/swamp/groceries/dir.d/CVS/fruit', + 't/swamp/groceries/dir.d/CVS/junk', + 't/swamp/groceries/dir.d/CVS/meat', + 't/swamp/groceries/dir.d/RCS/fruit', + 't/swamp/groceries/dir.d/RCS/junk', + 't/swamp/groceries/dir.d/RCS/meat', + 't/swamp/groceries/CVS/fruit', + 't/swamp/groceries/CVS/junk', + 't/swamp/groceries/CVS/meat', + 't/swamp/groceries/RCS/fruit', + 't/swamp/groceries/RCS/junk', + 't/swamp/groceries/RCS/meat', + 't/swamp/groceries/subdir/fruit', + 't/swamp/groceries/subdir/junk', + 't/swamp/groceries/subdir/meat', + 't/swamp/stuff.cmake', + 't/swamp/CMakeLists.txt', + 't/swamp/swamp/ignoreme.txt', + ], 'only non-binary files should be matched' +); diff -Nru ack-3.6.0/t/ext-filter.t ack-3.7.0/t/ext-filter.t --- ack-3.6.0/t/ext-filter.t 1970-01-01 00:00:00.000000000 +0000 +++ ack-3.7.0/t/ext-filter.t 2023-02-25 20:34:52.000000000 +0000 @@ -0,0 +1,27 @@ +#!perl + +use strict; +use warnings; +use lib 't'; + +use FilterTest; +use Test::More tests => 1; + +use App::Ack::Filter::Extension; + +filter_test( + [ ext => qw/pl pod pm t/ ], [ + 't/swamp/Makefile.PL', + 't/swamp/__pycache__/notes.pl', + 't/swamp/blib/ignore.pm', + 't/swamp/blib/ignore.pod', + 't/swamp/constitution-100k.pl', + 't/swamp/options-crlf.pl', + 't/swamp/options.pl', + 't/swamp/perl-test.t', + 't/swamp/perl.handler.pod', + 't/swamp/perl.pl', + 't/swamp/perl.pm', + 't/swamp/perl.pod', + ], 'only the given extensions should be matched' +); diff -Nru ack-3.6.0/t/file-iterator.t ack-3.7.0/t/file-iterator.t --- ack-3.6.0/t/file-iterator.t 1970-01-01 00:00:00.000000000 +0000 +++ ack-3.7.0/t/file-iterator.t 2023-02-25 20:34:52.000000000 +0000 @@ -0,0 +1,125 @@ +#!perl + +use warnings; +use strict; + +use Test::More tests => 1; + +use File::Next; + +use lib 't'; +use Util; + +prep_environment(); + +sub slurp { + my $iter = shift; + + my @files; + while ( defined ( my $file = $iter->() ) ) { + push( @files, $file ); + } + + return @files; +} + +UNFILTERED: { + my $iter = + File::Next::files( { + file_filter => undef, + descend_filter => undef, + }, 't/swamp' ); + + my @files = slurp( $iter ); + + sets_match( \@files, [qw( + t/swamp/0 + t/swamp/__pycache__/notes.pl + t/swamp/blib/ignore.pm + t/swamp/blib/ignore.pod + t/swamp/constitution-100k.pl + t/swamp/c-header.h + t/swamp/c-source.c + t/swamp/crystallography-weenies.f + t/swamp/example.R + t/swamp/favicon.ico + t/swamp/file.bar + t/swamp/file.foo + t/swamp/fresh.css + t/swamp/fresh.css.min + t/swamp/fresh.min.css + t/swamp/groceries/another_subdir/CVS/fruit + t/swamp/groceries/another_subdir/CVS/junk + t/swamp/groceries/another_subdir/CVS/meat + t/swamp/groceries/another_subdir/fruit + t/swamp/groceries/another_subdir/junk + t/swamp/groceries/another_subdir/meat + t/swamp/groceries/another_subdir/RCS/fruit + t/swamp/groceries/another_subdir/RCS/junk + t/swamp/groceries/another_subdir/RCS/meat + t/swamp/groceries/dir.d/CVS/fruit + t/swamp/groceries/dir.d/CVS/junk + t/swamp/groceries/dir.d/CVS/meat + t/swamp/groceries/dir.d/fruit + t/swamp/groceries/dir.d/junk + t/swamp/groceries/dir.d/meat + t/swamp/groceries/dir.d/RCS/fruit + t/swamp/groceries/dir.d/RCS/junk + t/swamp/groceries/dir.d/RCS/meat + t/swamp/groceries/CVS/fruit + t/swamp/groceries/CVS/junk + t/swamp/groceries/CVS/meat + t/swamp/groceries/fruit + t/swamp/groceries/junk + t/swamp/groceries/meat + t/swamp/groceries/RCS/fruit + t/swamp/groceries/RCS/junk + t/swamp/groceries/RCS/meat + t/swamp/groceries/subdir/fruit + t/swamp/groceries/subdir/junk + t/swamp/groceries/subdir/meat + t/swamp/html.htm + t/swamp/html.html + t/swamp/incomplete-last-line.txt + t/swamp/javascript.js + t/swamp/lua-shebang-test + t/swamp/Makefile + t/swamp/Makefile.PL + t/swamp/MasterPage.master + t/swamp/minified.js.min + t/swamp/minified.min.js + t/swamp/moose-andy.jpg + t/swamp/notaMakefile + t/swamp/notaRakefile + t/swamp/notes.md + t/swamp/options-crlf.pl + t/swamp/options.pl + t/swamp/options.pl.bak + t/swamp/perl-test.t + t/swamp/perl-without-extension + t/swamp/perl.cgi + t/swamp/perl.pl + t/swamp/perl.handler.pod + t/swamp/perl.pm + t/swamp/perl.pod + t/swamp/perl.tar.gz + t/swamp/perltoot.jpg + t/swamp/pipe-stress-freaks.F + t/swamp/Rakefile + t/swamp/Sample.ascx + t/swamp/Sample.asmx + t/swamp/sample.asp + t/swamp/sample.aspx + t/swamp/sample.rake + t/swamp/service.svc + t/swamp/solution8.tar + t/swamp/stuff.cmake + t/swamp/CMakeLists.txt + t/swamp/swamp/ignoreme.txt + ), + 't/swamp/#emacs-workfile.pl#', + 't/swamp/not-an-#emacs-workfile#', + ], 'UNFILTERED' ); +} + +done_testing(); diff -Nru ack-3.6.0/t/filter.t ack-3.7.0/t/filter.t --- ack-3.6.0/t/filter.t 1970-01-01 00:00:00.000000000 +0000 +++ ack-3.7.0/t/filter.t 2023-02-25 20:34:52.000000000 +0000 @@ -0,0 +1,41 @@ +#!perl + +use strict; +use warnings; + +use Test::More tests => 5; + +use App::Ack::Filter; + +my $filter; + +$filter = eval { + App::Ack::Filter->create_filter('test'); +}; + +ok( !$filter, 'Creating an unknown filter should fail' ); +like( $@, qr/unknown filter/i, 'Got the expected error' ); + +App::Ack::Filter->register_filter(test => 'TestFilter'); + +$filter = eval { + App::Ack::Filter->create_filter('test', qw/foo bar/); +}; + +ok( $filter, 'Creating a registered filter should succeed' ) or diag($@); +isa_ok( $filter, 'TestFilter', 'Creating a test filter should be a TestFilter' ); +is_deeply( $filter, [qw/foo bar/], 'Extra arguments should get passed through to constructor' ); + + +package TestFilter; + +use strict; +use warnings; + +sub new { + my ( $class, @args ) = @_; + + return bless \@args, $class; +} + +1; diff -Nru ack-3.6.0/t/FilterTest.pm ack-3.7.0/t/FilterTest.pm --- ack-3.6.0/t/FilterTest.pm 1970-01-01 00:00:00.000000000 +0000 +++ ack-3.7.0/t/FilterTest.pm 2023-02-25 20:34:52.000000000 +0000 @@ -0,0 +1,52 @@ +package FilterTest; + +use strict; +use warnings; +use parent 'Exporter'; + +use App::Ack::File; +use File::Next; +use Util; +use Test::More; + +our @EXPORT = qw(filter_test); + +sub swamp_files { + my @swamp_files; + + my $files = File::Next::files( 't/swamp' ); + while ( my $file = $files->() ) { + push( @swamp_files, $file ); + } + + return @swamp_files; +} + +sub filter_test { + local $Test::Builder::Level = $Test::Builder::Level + 1; + + my $filter_args = shift; + my $expected_matches = shift; + my $msg = shift or die 'Must pass a message to filter_test()'; + + return subtest "filter_test($msg)" => sub { + my $filter = eval { + App::Ack::Filter->create_filter(@{$filter_args}); + }; + + ok($filter) or diag($@); + + my @matches = map { + $_->name + } grep { + $filter->filter($_) + } map { + App::Ack::File->new($_) + } swamp_files(); + + sets_match(\@matches, $expected_matches, $msg); + }; +} + + +1; diff -Nru ack-3.6.0/t/firstlinematch-filter.t ack-3.7.0/t/firstlinematch-filter.t --- ack-3.6.0/t/firstlinematch-filter.t 1970-01-01 00:00:00.000000000 +0000 +++ ack-3.7.0/t/firstlinematch-filter.t 2023-02-25 20:34:52.000000000 +0000 @@ -0,0 +1,29 @@ +#!perl + +use strict; +use warnings; +use lib 't'; + +use FilterTest; +use Test::More tests => 1; + +use App::Ack::Filter::FirstLineMatch; + +filter_test( + [ firstlinematch => '/^#!.*perl/' ], [ + 't/swamp/#emacs-workfile.pl#', + 't/swamp/0', + 't/swamp/Makefile.PL', + 't/swamp/__pycache__/notes.pl', + 't/swamp/options-crlf.pl', + 't/swamp/options.pl', + 't/swamp/options.pl.bak', + 't/swamp/perl-test.t', + 't/swamp/perl-without-extension', + 't/swamp/perl.cgi', + 't/swamp/perl.pl', + 't/swamp/perl.pm', + 't/swamp/blib/ignore.pm', + 't/swamp/blib/ignore.pod', + ], 'only files with "perl" in their first line should be matched' +); diff -Nru ack-3.6.0/t/internals/ack-create-ackrc.t ack-3.7.0/t/internals/ack-create-ackrc.t --- ack-3.6.0/t/internals/ack-create-ackrc.t 2019-12-28 21:55:29.000000000 +0000 +++ ack-3.7.0/t/internals/ack-create-ackrc.t 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -#!perl - -use strict; -use warnings; - -use lib 't'; - -use Test::More tests => 5; -use Util; -use App::Ack (); -use App::Ack::ConfigDefault (); - -prep_environment(); - -my @commented = App::Ack::ConfigDefault::options(); -my @uncommented = App::Ack::ConfigDefault::options_clean(); - -cmp_ok( scalar @commented, '>', scalar @uncommented, 'There are fewer lines in the uncommented options.' ); - -my @output = run_ack( 'ack', '--create-ackrc' ); - -ok(scalar(grep { $_ eq '--ignore-ack-defaults' } @output), '--ignore-ack-defaults should be present in output'); -@output = grep { $_ ne '--ignore-ack-defaults' } @output; - -lists_match(\@output, \@commented, 'lines in output should match the default options'); - -my @versions = grep { /\Qack version $App::Ack::VERSION/ } @commented; -is( scalar @versions, 1, 'Got exactly one version line' ); diff -Nru ack-3.6.0/t/internals/ack-dump.t ack-3.7.0/t/internals/ack-dump.t --- ack-3.6.0/t/internals/ack-dump.t 2019-12-28 21:55:29.000000000 +0000 +++ ack-3.7.0/t/internals/ack-dump.t 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -#!perl - -use strict; -use warnings; - -use lib 't'; -use Util; - -use Test::More tests => 5; - -use App::Ack::ConfigDefault; - -prep_environment(); - -DUMP: { - my @expected = App::Ack::ConfigDefault::options_clean(); - - my @args = qw( --dump ); - my @results = run_ack( @args ); - - is( $results[0], 'Defaults', 'header should be Defaults' ); - splice @results, 0, 2; # remove header (2 lines) - - s/^\s*// for @results; - - sets_match( \@results, \@expected, __FILE__ ); - - my @perl = grep { /\bperl\b/ } @results; - is( scalar @perl, 2, 'Two specs for Perl' ); - - my @ignore_dir = grep { /ignore-dir/ } @results; - is( scalar @ignore_dir, 27, 'Twenty-seven specs for ignoring directories' ); -} - -exit 0; diff -Nru ack-3.6.0/t/internals/ack-version.t ack-3.7.0/t/internals/ack-version.t --- ack-3.6.0/t/internals/ack-version.t 2019-12-28 21:55:29.000000000 +0000 +++ ack-3.7.0/t/internals/ack-version.t 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -#!perl - -use strict; -use warnings; - -use Test::More tests => 2; -use lib 't'; -use Util; - -use App::Ack; - -prep_environment(); - -my ( $stdout, $stderr ) = run_ack_with_stderr( '--version' ); - -is_empty_array( $stderr, 'Nothing in stderr' ); -my @lines = @{$stdout}; -like( $lines[0], qr/\Q$App::Ack::VERSION/, 'Found the version in the first line' ); - -done_testing(); - -exit 0; diff -Nru ack-3.6.0/t/internals/config-finder.t ack-3.7.0/t/internals/config-finder.t --- ack-3.6.0/t/internals/config-finder.t 2019-12-28 21:55:29.000000000 +0000 +++ ack-3.7.0/t/internals/config-finder.t 1970-01-01 00:00:00.000000000 +0000 @@ -1,228 +0,0 @@ -#!perl - -use strict; -use warnings; - -use lib 't'; -use Util; - -use Cwd qw(realpath); -use File::Spec; -use File::Temp; -use Test::Builder; -use Test::More; - -use App::Ack::ConfigFinder; - -my $tmpdir = $ENV{'TMPDIR'}; -my $home = $ENV{'HOME'}; - -for ( $tmpdir, $home ) { - s{/$}{} if defined; -} - -if ( $tmpdir && ($tmpdir =~ /^\Q$home/) ) { - plan skip_all => "Your \$TMPDIR ($tmpdir) is set to a descendant directory of your home directory. This test is known to fail with such a setting. Please set your TMPDIR to something else to get this test to pass."; - exit; -} - -plan tests => 26; - -# Set HOME to a known value, so we get predictable results. -local $ENV{HOME} = realpath('t/home'); - -# Clear the user's ACKRC so it doesn't throw out expect_ackrcs(). -delete $ENV{'ACKRC'}; - -my $finder; -my @global_filenames = create_globals(); - -my @global_files = map { +{ path => $_ } } @global_filenames; -my @std_files = (@global_files, { path => File::Spec->catfile($ENV{'HOME'}, '.ackrc') }); - -my $wd = getcwd_clean(); -my $tempdir = File::Temp->newdir; -safe_chdir( $tempdir->dirname ); - -$finder = App::Ack::ConfigFinder->new; -with_home( sub { - expect_ackrcs( \@std_files, 'having no project file should return only the top level files' ); -} ); - -no_home( sub { - expect_ackrcs( \@global_files, 'only system-wide ackrc is returned if HOME is not defined with no project files' ); -} ); - -safe_mkdir( 'foo' ); -safe_mkdir( File::Spec->catdir('foo', 'bar') ); -safe_mkdir( File::Spec->catdir('foo', 'bar', 'baz') ); -safe_chdir( File::Spec->catdir('foo', 'bar', 'baz') ); - -touch_ackrc( '.ackrc' ); -with_home( sub { - expect_ackrcs( [ @std_files, { project => 1, path => File::Spec->rel2abs('.ackrc') }], 'a project file in the same directory should be detected' ); -} ); -no_home( sub { - expect_ackrcs( [ @global_files, { project => 1, path => File::Spec->rel2abs('.ackrc') } ], 'a project file in the same directory should be detected' ); -} ); - -unlink '.ackrc'; - -my $project_file = File::Spec->catfile($tempdir->dirname, 'foo', 'bar', '.ackrc'); -touch_ackrc( $project_file ); -with_home( sub { - expect_ackrcs( [ @std_files, { project => 1, path => $project_file } ], 'a project file in the parent directory should be detected' ); -} ); -no_home( sub { - expect_ackrcs( [ @global_files, { project => 1, path => $project_file } ], 'a project file in the parent directory should be detected' ); -} ); -unlink $project_file; - -$project_file = File::Spec->catfile($tempdir->dirname, 'foo', '.ackrc'); -touch_ackrc( $project_file ); -with_home( sub { - expect_ackrcs( [ @std_files, { project => 1, path => $project_file } ], 'a project file in the grandparent directory should be detected' ); -} ); -no_home( sub { - expect_ackrcs( [ @global_files, { project => 1, path => $project_file } ], 'a project file in the grandparent directory should be detected' ); -} ); - -touch_ackrc( '.ackrc' ); - -with_home( sub { - expect_ackrcs( [ @std_files, { project => 1, path => File::Spec->rel2abs('.ackrc') } ], 'a project file in the same directory should be detected, even with another one above it' ); -} ); -no_home( sub { - expect_ackrcs( [ @global_files, { project => 1, path => File::Spec->rel2abs('.ackrc') } ], 'a project file in the same directory should be detected, even with another one above it' ); -} ); - -unlink '.ackrc'; -unlink $project_file; - -touch_ackrc( '_ackrc' ); -with_home( sub { - expect_ackrcs( [ @std_files, { project => 1, path => File::Spec->rel2abs('_ackrc') } ], 'a project file in the same directory should be detected' ); -} ); -no_home( sub { - expect_ackrcs( [ @global_files, { project => 1, path => File::Spec->rel2abs('_ackrc') } ], 'a project file in the same directory should be detected' ); -} ); - -unlink '_ackrc'; - -$project_file = File::Spec->catfile($tempdir->dirname, 'foo', '_ackrc'); -touch_ackrc( $project_file ); -with_home( sub { - expect_ackrcs( [ @std_files, { project => 1, path => $project_file } ], 'a project file in the grandparent directory should be detected' ); -} ); -no_home( sub { - expect_ackrcs( [ @global_files, { project => 1, path => $project_file } ], 'a project file in the grandparent directory should be detected' ); -} ); - -touch_ackrc( '_ackrc' ); -with_home( sub { expect_ackrcs( [ @std_files, { project => 1, path => File::Spec->rel2abs('_ackrc') } ], 'a project file in the same directory should be detected, even with another one above it' ); -} ); -no_home( sub { - expect_ackrcs( [ @global_files, { project => 1, path => File::Spec->rel2abs('_ackrc') } ], 'a project file in the same directory should be detected, even with another one above it' ); -} ); - -unlink $project_file; -touch_ackrc( '.ackrc' ); - -do { - my $finder_fn = sub { - my $ok = eval { $finder->find_config_files }; - my $err = $@; - ok( !$ok, '.ackrc + _ackrc is error' ); - like( $err, qr/contains both \.ackrc and _ackrc/, 'Got the expected error' ); - }; - with_home( $finder_fn ); - no_home( $finder_fn ); - - unlink '.ackrc'; - $project_file = File::Spec->catfile($tempdir->dirname, 'foo', '.ackrc'); - touch_ackrc( $project_file ); - with_home( sub { - expect_ackrcs( [ @std_files, { project => 1, path => File::Spec->rel2abs('_ackrc') }], 'a lower-level _ackrc should be preferred to a higher-level .ackrc' ); - } ); - no_home( sub { - expect_ackrcs( [ @global_files, { project => 1, path => File::Spec->rel2abs('_ackrc') } ], 'a lower-level _ackrc should be preferred to a higher-level .ackrc' ); - } ); - - unlink '_ackrc'; -}; - -do { - my $test_home = File::Spec->catdir( $tempdir->dirname, 'foo' ); - local $ENV{'HOME'} = $test_home; - - my $user_file = File::Spec->catfile( $test_home, '.ackrc'); - touch_ackrc( $user_file ); - - expect_ackrcs( [ @global_files, { path => $user_file } ], q{Don't load the same ackrc file twice} ); - unlink($user_file); -}; - -do { - safe_chdir( $tempdir->dirname ); - local $ENV{'HOME'} = File::Spec->catfile($tempdir->dirname, 'foo'); - - my $user_file = File::Spec->catfile($ENV{'HOME'}, '.ackrc'); - touch_ackrc( $user_file ); - - my $ackrc = create_tempfile(); - local $ENV{'ACKRC'} = $ackrc->filename; - - expect_ackrcs( [ @global_files, { path => $ackrc->filename } ], q{ACKRC overrides user's HOME ackrc} ); - unlink $ackrc->filename; - - expect_ackrcs( [ @global_files, { path => $user_file } ], q{ACKRC doesn't override if it doesn't exist} ); - - touch_ackrc( $ackrc->filename ); - safe_chdir( 'foo' ); - expect_ackrcs( [ @global_files, { path => $ackrc->filename}, { project => 1, path => $user_file } ], q{~/.ackrc should still be found as a project ackrc} ); - unlink $ackrc->filename; -}; - -safe_chdir( $wd ); -clean_up_globals(); - -exit 0; - - -sub with_home { - my ( $fn ) = @_; - - $fn->(); - - return; -} - - -sub no_home { - my ( $fn ) = @_; - - # We have to manually store the value of HOME because localized - # delete isn't supported until Perl 5.12.0. - my $home_saved = delete $ENV{HOME}; - $fn->(); - $ENV{HOME} = $home_saved; - - return; -} - -sub expect_ackrcs { - local $Test::Builder::Level = $Test::Builder::Level + 1; - - my $expected = shift; - my $name = shift; - - my @got = $finder->find_config_files; - my @expected = @{$expected}; - - foreach my $element (@got, @expected) { - $element->{'path'} = realpath($element->{'path'}); - } - is_deeply( \@got, \@expected, $name ) or diag(explain(got=>\@got,expected=>\@expected)); - - return; -} diff -Nru ack-3.6.0/t/internals/config-loader.t ack-3.7.0/t/internals/config-loader.t --- ack-3.6.0/t/internals/config-loader.t 2019-12-28 21:55:29.000000000 +0000 +++ ack-3.7.0/t/internals/config-loader.t 1970-01-01 00:00:00.000000000 +0000 @@ -1,294 +0,0 @@ -#!perl - -use strict; -use warnings; -use lib 't'; -use Util; - -use Test::More tests => 28; - -use App::Ack::Filter::Default; -use App::Ack::ConfigLoader; - -delete @ENV{qw( PAGER ACK_PAGER ACK_PAGER_COLOR )}; - -my %defaults = ( - 'break' => undef, - c => undef, - color => undef, - column => undef, - debug => undef, - f => undef, - files_from => undef, - filters => [ App::Ack::Filter::Default->new ], - follow => undef, - g => undef, - h => undef, - H => undef, - heading => undef, - l => undef, - L => undef, - m => undef, - n => undef, - output => undef, - p => undef, - pager => undef, - passthru => undef, - print0 => undef, - Q => undef, - range_start => undef, - range_end => undef, - range_invert => undef, - regex => undef, - s => undef, - show_types => undef, - sort_files => undef, - underline => undef, - v => undef, - w => undef, -); - -test_loader( - expected_opts => { %defaults }, - 'empty inputs should result in default outputs' -); - -# --after_context, --before_context -for my $option ( qw( after_context before_context ) ) { - my $long_arg = $option; - $long_arg =~ s/_/-/ or die; - - my $target_arg = uc substr( $option, 0, 1 ); - - test_loader( - argv => [ "--$long_arg=15" ], - expected_opts => { %defaults, $target_arg => 15 }, - "--$long_arg=15 should set $target_arg to 15", - ); - - test_loader( - argv => [ "--$long_arg=0" ], - expected_opts => { %defaults, $target_arg => 0 }, - "--$long_arg=0 should set $target_arg to 0", - ); - - test_loader( - argv => [ "--$long_arg" ], - expected_opts => { %defaults, $target_arg => 2 }, - "--$long_arg without a value should default $target_arg to 2", - ); - - test_loader( - argv => [ "--$long_arg=-43" ], - expected_opts => { %defaults, $target_arg => 2 }, - "--$long_arg with a negative value should default $target_arg to 2", - ); - - my $short_arg = '-' . uc substr( $option, 0, 1 ); - test_loader( - argv => [ $short_arg, 15 ], - expected_opts => { %defaults, $target_arg => 15 }, - "$short_arg 15 should set $target_arg to 15", - ); - - test_loader( - argv => [ $short_arg, 0 ], - expected_opts => { %defaults, $target_arg => 0 }, - "$short_arg 0 should set $target_arg to 0", - ); - - test_loader( - argv => [ $short_arg ], - expected_opts => { %defaults, $target_arg => 2 }, - "$short_arg without a value should default $target_arg to 2", - ); - - test_loader( - argv => [ $short_arg, '-43' ], - expected_opts => { %defaults, $target_arg => 2 }, - "$short_arg with a negative value should default $target_arg to 2", - ); -} - -test_loader( - argv => ['-C', 5], - expected_opts => { %defaults, A => 5, B => 5 }, - '-C sets both B and A' -); - -test_loader( - argv => ['-C'], - expected_opts => { %defaults, A => 2, B => 2 }, - '-C sets both B and A, with default' -); - -test_loader( - argv => ['-C', 0], - expected_opts => { %defaults, A => 0, B => 0 }, - '-C sets both B and A, with zero overriding default' -); - -test_loader( - argv => ['-C', -43], - expected_opts => { %defaults, A => 2, B => 2 }, - '-C with invalid value sets both B and A to default' -); - -test_loader( - argv => ['--context=5'], - expected_opts => { %defaults, A => 5, B => 5 }, - '--context sets both B and A' -); - -test_loader( - argv => ['--context'], - expected_opts => { %defaults, A => 2, B => 2 }, - '--context sets both B and A, with default' -); - -test_loader( - argv => ['--context=0'], - expected_opts => { %defaults, A => 0, B => 0 }, - '--context sets both B and A, with zero overriding default' -); - -test_loader( - argv => ['--context=-43'], - expected_opts => { %defaults, A => 2, B => 2 }, - '--context with invalid value sets both B and A to default' -); - - -subtest 'ACK_PAGER' => sub { - plan tests => 3; - - local $ENV{'ACK_PAGER'} = 't/test-pager --skip=2'; - - test_loader( - argv => [], - expected_opts => { %defaults, pager => 't/test-pager --skip=2' }, - 'ACK_PAGER should set the default pager', - ); - - test_loader( - argv => ['--pager=t/test-pager'], - expected_opts => { %defaults, pager => 't/test-pager' }, - '--pager should override ACK_PAGER', - ); - - test_loader( - argv => ['--nopager'], - expected_opts => { %defaults }, - '--nopager should suppress ACK_PAGER', - ); -}; - - -subtest 'ACK_PAGER_COLOR' => sub { - plan tests => 6; - - local $ENV{'ACK_PAGER_COLOR'} = 't/test-pager --skip=2'; - - test_loader( - argv => [], - expected_opts => { %defaults, pager => 't/test-pager --skip=2' }, - 'ACK_PAGER_COLOR should set the default pager', - ); - - test_loader( - argv => ['--pager=t/test-pager'], - expected_opts => { %defaults, pager => 't/test-pager' }, - '--pager should override ACK_PAGER_COLOR', - ); - - test_loader( - argv => ['--nopager'], - expected_opts => { %defaults }, - '--nopager should suppress ACK_PAGER_COLOR', - ); - - local $ENV{'ACK_PAGER'} = 't/test-pager --skip=3'; - - test_loader( - argv => [], - expected_opts => { %defaults, pager => 't/test-pager --skip=2' }, - 'ACK_PAGER_COLOR should override ACK_PAGER', - ); - - test_loader( - argv => ['--pager=t/test-pager'], - expected_opts => { %defaults, pager => 't/test-pager' }, - '--pager should override ACK_PAGER_COLOR and ACK_PAGER', - ); - - test_loader( - argv => ['--nopager'], - expected_opts => { %defaults }, - '--nopager should suppress ACK_PAGER_COLOR and ACK_PAGER', - ); -}; - - -subtest 'PAGER' => sub { - plan tests => 3; - - local $ENV{'PAGER'} = 't/test-pager'; - - test_loader( - argv => [], - expected_opts => { %defaults }, - q{PAGER doesn't affect ack by default}, - ); - - test_loader( - argv => ['--pager'], - expected_opts => { %defaults, pager => 't/test-pager' }, - 'PAGER is used if --pager is specified with no argument', - ); - - test_loader( - argv => ['--pager=t/test-pager --skip=2'], - expected_opts => { %defaults, pager => 't/test-pager --skip=2' }, - 'PAGER is not used if --pager is specified with an argument', - ); -}; - -done_testing(); - -exit 0; - - -sub test_loader { - local $Test::Builder::Level = $Test::Builder::Level + 1; - - die 'Must pass key/value pairs, plus a message at the end' unless @_ % 2 == 1; - - my $msg = pop; - my %opts = @_; - - return subtest subtest_name( $msg, \%opts ) => sub { - plan tests => 3; - - my $env = delete $opts{env} // ''; - my $argv = delete $opts{argv} // []; - my $expected_opts = delete $opts{expected_opts}; - - is( scalar keys %opts, 0, 'All the keys are gone' ); - - my $got_opts; - my $got_targets; - do { - local @ARGV = (); - - my @arg_sources = ( - { name => 'ARGV', contents => $argv }, - ); - - $got_opts = App::Ack::ConfigLoader::process_args( @arg_sources ); - $got_targets = [ @ARGV ]; - }; - - is_deeply( $got_opts, $expected_opts, 'Options match' ); - is_empty_array( $got_targets, 'Got no targets' ); - }; -} diff -Nru ack-3.6.0/t/internals/default-filter.t ack-3.7.0/t/internals/default-filter.t --- ack-3.6.0/t/internals/default-filter.t 2019-12-28 21:55:29.000000000 +0000 +++ ack-3.7.0/t/internals/default-filter.t 1970-01-01 00:00:00.000000000 +0000 @@ -1,98 +0,0 @@ -#!perl - -use strict; -use warnings; -use lib 't', 't/internals'; - -use FilterTest; -use Test::More tests => 1; - -use App::Ack::Filter::Default; -use App::Ack::Filter; - -App::Ack::Filter->register_filter('default' => 'App::Ack::Filter::Default'); - -filter_test( - [ 'default' ], [ - 't/swamp/#emacs-workfile.pl#', - 't/swamp/0', - 't/swamp/constitution-100k.pl', - 't/swamp/c-header.h', - 't/swamp/c-source.c', - 't/swamp/crystallography-weenies.f', - 't/swamp/example.R', - 't/swamp/file.bar', - 't/swamp/file.foo', - 't/swamp/fresh.css', - 't/swamp/fresh.min.css', - 't/swamp/fresh.css.min', - 't/swamp/html.htm', - 't/swamp/html.html', - 't/swamp/incomplete-last-line.txt', - 't/swamp/javascript.js', - 't/swamp/lua-shebang-test', - 't/swamp/Makefile', - 't/swamp/Makefile.PL', - 't/swamp/MasterPage.master', - 't/swamp/minified.js.min', - 't/swamp/minified.min.js', - 't/swamp/not-an-#emacs-workfile#', - 't/swamp/notaMakefile', - 't/swamp/notaRakefile', - 't/swamp/notes.md', - 't/swamp/options-crlf.pl', - 't/swamp/options.pl', - 't/swamp/options.pl.bak', - 't/swamp/perl-test.t', - 't/swamp/perl-without-extension', - 't/swamp/perl.cgi', - 't/swamp/perl.handler.pod', - 't/swamp/perl.pl', - 't/swamp/perl.pm', - 't/swamp/perl.pod', - 't/swamp/pipe-stress-freaks.F', - 't/swamp/Rakefile', - 't/swamp/Sample.ascx', - 't/swamp/Sample.asmx', - 't/swamp/sample.asp', - 't/swamp/sample.aspx', - 't/swamp/sample.rake', - 't/swamp/service.svc', - 't/swamp/__pycache__/notes.pl', - 't/swamp/blib/ignore.pm', - 't/swamp/blib/ignore.pod', - 't/swamp/groceries/fruit', - 't/swamp/groceries/junk', - 't/swamp/groceries/meat', - 't/swamp/groceries/another_subdir/fruit', - 't/swamp/groceries/another_subdir/junk', - 't/swamp/groceries/another_subdir/meat', - 't/swamp/groceries/another_subdir/CVS/fruit', - 't/swamp/groceries/another_subdir/CVS/junk', - 't/swamp/groceries/another_subdir/CVS/meat', - 't/swamp/groceries/another_subdir/RCS/fruit', - 't/swamp/groceries/another_subdir/RCS/junk', - 't/swamp/groceries/another_subdir/RCS/meat', - 't/swamp/groceries/dir.d/fruit', - 't/swamp/groceries/dir.d/junk', - 't/swamp/groceries/dir.d/meat', - 't/swamp/groceries/dir.d/CVS/fruit', - 't/swamp/groceries/dir.d/CVS/junk', - 't/swamp/groceries/dir.d/CVS/meat', - 't/swamp/groceries/dir.d/RCS/fruit', - 't/swamp/groceries/dir.d/RCS/junk', - 't/swamp/groceries/dir.d/RCS/meat', - 't/swamp/groceries/CVS/fruit', - 't/swamp/groceries/CVS/junk', - 't/swamp/groceries/CVS/meat', - 't/swamp/groceries/RCS/fruit', - 't/swamp/groceries/RCS/junk', - 't/swamp/groceries/RCS/meat', - 't/swamp/groceries/subdir/fruit', - 't/swamp/groceries/subdir/junk', - 't/swamp/groceries/subdir/meat', - 't/swamp/stuff.cmake', - 't/swamp/CMakeLists.txt', - 't/swamp/swamp/ignoreme.txt', - ], 'only non-binary files should be matched' -); diff -Nru ack-3.6.0/t/internals/ext-filter.t ack-3.7.0/t/internals/ext-filter.t --- ack-3.6.0/t/internals/ext-filter.t 2019-12-28 21:55:29.000000000 +0000 +++ ack-3.7.0/t/internals/ext-filter.t 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -#!perl - -use strict; -use warnings; -use lib 't', 't/internals'; - -use FilterTest; -use Test::More tests => 1; - -use App::Ack::Filter::Extension; - -filter_test( - [ ext => qw/pl pod pm t/ ], [ - 't/swamp/Makefile.PL', - 't/swamp/__pycache__/notes.pl', - 't/swamp/blib/ignore.pm', - 't/swamp/blib/ignore.pod', - 't/swamp/constitution-100k.pl', - 't/swamp/options-crlf.pl', - 't/swamp/options.pl', - 't/swamp/perl-test.t', - 't/swamp/perl.handler.pod', - 't/swamp/perl.pl', - 't/swamp/perl.pm', - 't/swamp/perl.pod', - ], 'only the given extensions should be matched' -); diff -Nru ack-3.6.0/t/internals/file-iterator.t ack-3.7.0/t/internals/file-iterator.t --- ack-3.6.0/t/internals/file-iterator.t 2019-12-28 21:55:29.000000000 +0000 +++ ack-3.7.0/t/internals/file-iterator.t 1970-01-01 00:00:00.000000000 +0000 @@ -1,125 +0,0 @@ -#!perl - -use warnings; -use strict; - -use Test::More tests => 1; - -use File::Next; - -use lib 't'; -use Util; - -prep_environment(); - -sub slurp { - my $iter = shift; - - my @files; - while ( defined ( my $file = $iter->() ) ) { - push( @files, $file ); - } - - return @files; -} - -UNFILTERED: { - my $iter = - File::Next::files( { - file_filter => undef, - descend_filter => undef, - }, 't/swamp' ); - - my @files = slurp( $iter ); - - sets_match( \@files, [qw( - t/swamp/0 - t/swamp/__pycache__/notes.pl - t/swamp/blib/ignore.pm - t/swamp/blib/ignore.pod - t/swamp/constitution-100k.pl - t/swamp/c-header.h - t/swamp/c-source.c - t/swamp/crystallography-weenies.f - t/swamp/example.R - t/swamp/favicon.ico - t/swamp/file.bar - t/swamp/file.foo - t/swamp/fresh.css - t/swamp/fresh.css.min - t/swamp/fresh.min.css - t/swamp/groceries/another_subdir/CVS/fruit - t/swamp/groceries/another_subdir/CVS/junk - t/swamp/groceries/another_subdir/CVS/meat - t/swamp/groceries/another_subdir/fruit - t/swamp/groceries/another_subdir/junk - t/swamp/groceries/another_subdir/meat - t/swamp/groceries/another_subdir/RCS/fruit - t/swamp/groceries/another_subdir/RCS/junk - t/swamp/groceries/another_subdir/RCS/meat - t/swamp/groceries/dir.d/CVS/fruit - t/swamp/groceries/dir.d/CVS/junk - t/swamp/groceries/dir.d/CVS/meat - t/swamp/groceries/dir.d/fruit - t/swamp/groceries/dir.d/junk - t/swamp/groceries/dir.d/meat - t/swamp/groceries/dir.d/RCS/fruit - t/swamp/groceries/dir.d/RCS/junk - t/swamp/groceries/dir.d/RCS/meat - t/swamp/groceries/CVS/fruit - t/swamp/groceries/CVS/junk - t/swamp/groceries/CVS/meat - t/swamp/groceries/fruit - t/swamp/groceries/junk - t/swamp/groceries/meat - t/swamp/groceries/RCS/fruit - t/swamp/groceries/RCS/junk - t/swamp/groceries/RCS/meat - t/swamp/groceries/subdir/fruit - t/swamp/groceries/subdir/junk - t/swamp/groceries/subdir/meat - t/swamp/html.htm - t/swamp/html.html - t/swamp/incomplete-last-line.txt - t/swamp/javascript.js - t/swamp/lua-shebang-test - t/swamp/Makefile - t/swamp/Makefile.PL - t/swamp/MasterPage.master - t/swamp/minified.js.min - t/swamp/minified.min.js - t/swamp/moose-andy.jpg - t/swamp/notaMakefile - t/swamp/notaRakefile - t/swamp/notes.md - t/swamp/options-crlf.pl - t/swamp/options.pl - t/swamp/options.pl.bak - t/swamp/perl-test.t - t/swamp/perl-without-extension - t/swamp/perl.cgi - t/swamp/perl.pl - t/swamp/perl.handler.pod - t/swamp/perl.pm - t/swamp/perl.pod - t/swamp/perl.tar.gz - t/swamp/perltoot.jpg - t/swamp/pipe-stress-freaks.F - t/swamp/Rakefile - t/swamp/Sample.ascx - t/swamp/Sample.asmx - t/swamp/sample.asp - t/swamp/sample.aspx - t/swamp/sample.rake - t/swamp/service.svc - t/swamp/solution8.tar - t/swamp/stuff.cmake - t/swamp/CMakeLists.txt - t/swamp/swamp/ignoreme.txt - ), - 't/swamp/#emacs-workfile.pl#', - 't/swamp/not-an-#emacs-workfile#', - ], 'UNFILTERED' ); -} - -done_testing(); diff -Nru ack-3.6.0/t/internals/filter.t ack-3.7.0/t/internals/filter.t --- ack-3.6.0/t/internals/filter.t 2019-12-28 21:55:29.000000000 +0000 +++ ack-3.7.0/t/internals/filter.t 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -#!perl - -use strict; -use warnings; - -use Test::More tests => 5; - -use App::Ack::Filter; - -my $filter; - -$filter = eval { - App::Ack::Filter->create_filter('test'); -}; - -ok( !$filter, 'Creating an unknown filter should fail' ); -like( $@, qr/unknown filter/i, 'Got the expected error' ); - -App::Ack::Filter->register_filter(test => 'TestFilter'); - -$filter = eval { - App::Ack::Filter->create_filter('test', qw/foo bar/); -}; - -ok( $filter, 'Creating a registered filter should succeed' ) or diag($@); -isa_ok( $filter, 'TestFilter', 'Creating a test filter should be a TestFilter' ); -is_deeply( $filter, [qw/foo bar/], 'Extra arguments should get passed through to constructor' ); - - -package TestFilter; - -use strict; -use warnings; - -sub new { - my ( $class, @args ) = @_; - - return bless \@args, $class; -} - -1; diff -Nru ack-3.6.0/t/internals/FilterTest.pm ack-3.7.0/t/internals/FilterTest.pm --- ack-3.6.0/t/internals/FilterTest.pm 2019-12-28 21:55:29.000000000 +0000 +++ ack-3.7.0/t/internals/FilterTest.pm 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -package FilterTest; - -use strict; -use warnings; -use parent 'Exporter'; - -use App::Ack::File; -use File::Next; -use Util; -use Test::More; - -our @EXPORT = qw(filter_test); - -sub swamp_files { - my @swamp_files; - - my $files = File::Next::files( 't/swamp' ); - while ( my $file = $files->() ) { - push( @swamp_files, $file ); - } - - return @swamp_files; -} - -sub filter_test { - local $Test::Builder::Level = $Test::Builder::Level + 1; - - my $filter_args = shift; - my $expected_matches = shift; - my $msg = shift or die 'Must pass a message to filter_test()'; - - return subtest "filter_test($msg)" => sub { - my $filter = eval { - App::Ack::Filter->create_filter(@{$filter_args}); - }; - - ok($filter) or diag($@); - - my @matches = map { - $_->name - } grep { - $filter->filter($_) - } map { - App::Ack::File->new($_) - } swamp_files(); - - sets_match(\@matches, $expected_matches, $msg); - }; -} - - -1; diff -Nru ack-3.6.0/t/internals/firstlinematch-filter.t ack-3.7.0/t/internals/firstlinematch-filter.t --- ack-3.6.0/t/internals/firstlinematch-filter.t 2019-12-28 21:55:29.000000000 +0000 +++ ack-3.7.0/t/internals/firstlinematch-filter.t 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -#!perl - -use strict; -use warnings; -use lib 't', 't/internals'; - -use FilterTest; -use Test::More tests => 1; - -use App::Ack::Filter::FirstLineMatch; - -filter_test( - [ firstlinematch => '/^#!.*perl/' ], [ - 't/swamp/#emacs-workfile.pl#', - 't/swamp/0', - 't/swamp/Makefile.PL', - 't/swamp/__pycache__/notes.pl', - 't/swamp/options-crlf.pl', - 't/swamp/options.pl', - 't/swamp/options.pl.bak', - 't/swamp/perl-test.t', - 't/swamp/perl-without-extension', - 't/swamp/perl.cgi', - 't/swamp/perl.pl', - 't/swamp/perl.pm', - 't/swamp/blib/ignore.pm', - 't/swamp/blib/ignore.pod', - ], 'only files with "perl" in their first line should be matched' -); diff -Nru ack-3.6.0/t/internals/is-filter.t ack-3.7.0/t/internals/is-filter.t --- ack-3.6.0/t/internals/is-filter.t 2019-12-28 21:55:29.000000000 +0000 +++ ack-3.7.0/t/internals/is-filter.t 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -#!perl - -use strict; -use warnings; -use lib 't', 't/internals'; - -use FilterTest; -use Test::More tests => 1; - -use App::Ack::Filter::Is; - -filter_test( - [ is => 'Makefile' ], - [ 't/swamp/Makefile' ], - 'Only Makefile should be matched' -); diff -Nru ack-3.6.0/t/internals/lowercase.t ack-3.7.0/t/internals/lowercase.t --- ack-3.6.0/t/internals/lowercase.t 2019-12-28 21:55:29.000000000 +0000 +++ ack-3.7.0/t/internals/lowercase.t 1970-01-01 00:00:00.000000000 +0000 @@ -1,111 +0,0 @@ -#!/usr/bin/perl - -use warnings; -use strict; -use 5.010; - -use Test::More tests => 2; - -use App::Ack; - -my $lc_list = <<'END'; ## no critic ( CodeLayout::RequireASCII ) -select . from table -select \S+ from table -select [^\s]+ from table - -# Character specifications -find a tab -> \x09 -"foo" in hex -> \x66\x6f\x6f with lowercase digits -"foo" in hex -> \x66\x6F\x6F with uppercase digits -control sequences: ctrl-x=\cX -# unicode sequences: \N{GRAVE ACCENT} -unicode sequences: \N{U+263D} -ladies and gentlemen, please welcome, ❤️! - -# Regex metacharacters -keep stuff to the left -> \K -non-word character -> \W -non-space character -> \S -non-digit character -> \D -something something \X -not vertical whitespace -> \V -not horizontal whitespace -> \H -linebreak -> \R - -# unicode regex metachars -# https://www.regular-expressions.info/unicode.html -named property -> \p{Word} same as \w -not the named property -> \P{Word} same as \W -single-character named property shorthand -> \pL is any letter -negation of single-character named property shorthand -> \PL is not any letter - -# Not sure about \X -big combination: \W\S\D\V\H\R but still lowercase - -# Zero-width assertions -not a word boundary -> \B -beginning of a string -> \A -end of a string -> \Z -end-of-match position of prior match -> \G - -# Captures -named capture group and backref -> (?'NAME'pattern) \k'NAME' -named capture group and backref -> (?pattern) \k -# Weird combinations -\A\B\S{14}\G\Dfoo\W*\S+\Z -END - - -my $uc_list = <<'END'; -This is \\Here. -foo[A-Z]+ -[A-Z]*bar -parens([A-Z]*) -foo(?!lookahead)([A-Z]*) - -# Don't get confused by regex metacharacters. -\WWhat now? -dumb \DDonald -lost in \SSpace -lost in \\\\Diskland - -# Weird combinations -\A\\\B\S{14}\G\\\D\\Dog\\\W*\\\\\S+\\\\\Z -\\W//\\W//\\Larry//\\D//? -END - - -my @lc_list = _big_split($lc_list); -if ( $] >= 5.012 ) { - push( @lc_list, 'anything but \n -> \N' ); -} - -my @uc_list = _big_split($uc_list); - -subtest 'Check lowercase' => sub { - plan tests => scalar @lc_list; - - for my $lc ( @lc_list ) { - my $re = qr/$lc/; - ok( App::Ack::is_lowercase( $lc ), qq{"$lc" should be lowercase} ); - } -}; - -subtest 'Check uppercase' => sub { - plan tests => scalar @uc_list; - - for my $uc ( @uc_list ) { - my $re = qr/$uc/; - ok( !App::Ack::is_lowercase( $uc ), qq{"$uc" should not be lowercase} ); - } -}; - -done_testing(); -exit 0; - - -sub _big_split { - my $str = shift; - - return grep { /./ && !/^#/ } split( /\n/, $str ); -} diff -Nru ack-3.6.0/t/internals/match-filter.t ack-3.7.0/t/internals/match-filter.t --- ack-3.6.0/t/internals/match-filter.t 2019-12-28 21:55:29.000000000 +0000 +++ ack-3.7.0/t/internals/match-filter.t 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -#!perl - -use strict; -use warnings; -use lib 't', 't/internals'; - -use FilterTest; -use Test::More tests => 1; - -use App::Ack::Filter::Match; - -filter_test( - [ match => '/^.akefile/' ], [ - 't/swamp/Makefile', - 't/swamp/Makefile.PL', - 't/swamp/Rakefile', - ], 'only files matching /^.akefile/ should be matched', -); diff -Nru ack-3.6.0/t/internals/noenv.t ack-3.7.0/t/internals/noenv.t --- ack-3.6.0/t/internals/noenv.t 2019-12-28 21:55:29.000000000 +0000 +++ ack-3.7.0/t/internals/noenv.t 1970-01-01 00:00:00.000000000 +0000 @@ -1,99 +0,0 @@ -#!perl - -use strict; -use warnings; - -use Test::More tests => 3; - -use lib 't'; -use Util; - -use App::Ack::ConfigLoader; -use Cwd qw( realpath ); -use File::Spec (); -use File::Temp (); - -sub is_global_file { - my ( $filename ) = @_; - - return unless -f $filename; - - my ( undef, $dir ) = File::Spec->splitpath($filename); - $dir = File::Spec->canonpath($dir); - - my (undef, $wd) = File::Spec->splitpath(getcwd_clean(), 1); - $wd = File::Spec->canonpath($wd); - - return $wd !~ /^\Q$dir\E/; -} - -sub remove_defaults_and_globals { - my ( @sources ) = @_; - - return grep { - $_->{name} ne 'Defaults' && !is_global_file($_->{name}) - } @sources; -} - -prep_environment(); - -my $wd = getcwd_clean() or die; - -my $tempdir = File::Temp->newdir; - -safe_chdir( $tempdir->dirname ); - -write_file( '.ackrc', <<'ACKRC' ); ---type-add=perl:ext:pl,t,pm -ACKRC - -subtest 'without --noenv' => sub { - plan tests => 1; - - local @ARGV = ('-f', 'lib/'); - - my @sources = App::Ack::ConfigLoader::retrieve_arg_sources(); - @sources = remove_defaults_and_globals(@sources); - - is_deeply( \@sources, [ - { - name => File::Spec->canonpath(realpath(File::Spec->catfile($tempdir->dirname, '.ackrc'))), - contents => [ '--type-add=perl:ext:pl,t,pm' ], - project => 1, - is_ackrc => 1, - }, - { - name => 'ARGV', - contents => ['-f', 'lib/'], - }, - ], 'Get back a long list of arguments' ); -}; - -subtest 'with --noenv' => sub { - plan tests => 1; - - local @ARGV = ('--noenv', '-f', 'lib/'); - - my @sources = App::Ack::ConfigLoader::retrieve_arg_sources(); - @sources = remove_defaults_and_globals(@sources); - - is_deeply( \@sources, [ - { - name => 'ARGV', - contents => ['-f', 'lib/'], - }, - ], 'Short list comes back because of --noenv' ); -}; - -subtest '--noenv in config' => sub { - plan tests => 3; - - append_file( '.ackrc', "--noenv\n" ); - - my ( $stdout, $stderr ) = run_ack_with_stderr('--env', 'perl'); - is_empty_array( $stdout ); - is( @{$stderr}, 1 ); - like( $stderr->[0], qr/--noenv found in (?:.*)[.]ackrc/ ) or diag(explain($stderr)); -}; - -safe_chdir( $wd ); # Go back to the original directory to avoid warnings diff -Nru ack-3.6.0/t/inverted-file-filter.t ack-3.7.0/t/inverted-file-filter.t --- ack-3.6.0/t/inverted-file-filter.t 2019-12-28 21:55:29.000000000 +0000 +++ ack-3.7.0/t/inverted-file-filter.t 2023-02-25 20:34:52.000000000 +0000 @@ -2,7 +2,7 @@ use strict; use warnings; -use lib 't', 't/internals'; +use lib 't'; use Test::More tests => 4; use Util; diff -Nru ack-3.6.0/t/is-filter.t ack-3.7.0/t/is-filter.t --- ack-3.6.0/t/is-filter.t 1970-01-01 00:00:00.000000000 +0000 +++ ack-3.7.0/t/is-filter.t 2023-02-25 20:34:52.000000000 +0000 @@ -0,0 +1,16 @@ +#!perl + +use strict; +use warnings; +use lib 't'; + +use FilterTest; +use Test::More tests => 1; + +use App::Ack::Filter::Is; + +filter_test( + [ is => 'Makefile' ], + [ 't/swamp/Makefile' ], + 'Only Makefile should be matched' +); diff -Nru ack-3.6.0/t/lowercase.t ack-3.7.0/t/lowercase.t --- ack-3.6.0/t/lowercase.t 1970-01-01 00:00:00.000000000 +0000 +++ ack-3.7.0/t/lowercase.t 2023-02-25 20:34:52.000000000 +0000 @@ -0,0 +1,111 @@ +#!/usr/bin/perl + +use warnings; +use strict; +use 5.010; + +use Test::More tests => 2; + +use App::Ack; + +my $lc_list = <<'END'; ## no critic ( CodeLayout::RequireASCII ) +select . from table +select \S+ from table +select [^\s]+ from table + +# Character specifications +find a tab -> \x09 +"foo" in hex -> \x66\x6f\x6f with lowercase digits +"foo" in hex -> \x66\x6F\x6F with uppercase digits +control sequences: ctrl-x=\cX +# unicode sequences: \N{GRAVE ACCENT} +unicode sequences: \N{U+263D} +ladies and gentlemen, please welcome, ❤️! + +# Regex metacharacters +keep stuff to the left -> \K +non-word character -> \W +non-space character -> \S +non-digit character -> \D +something something \X +not vertical whitespace -> \V +not horizontal whitespace -> \H +linebreak -> \R + +# unicode regex metachars +# https://www.regular-expressions.info/unicode.html +named property -> \p{Word} same as \w +not the named property -> \P{Word} same as \W +single-character named property shorthand -> \pL is any letter +negation of single-character named property shorthand -> \PL is not any letter + +# Not sure about \X +big combination: \W\S\D\V\H\R but still lowercase + +# Zero-width assertions +not a word boundary -> \B +beginning of a string -> \A +end of a string -> \Z +end-of-match position of prior match -> \G + +# Captures +named capture group and backref -> (?'NAME'pattern) \k'NAME' +named capture group and backref -> (?pattern) \k +# Weird combinations +\A\B\S{14}\G\Dfoo\W*\S+\Z +END + + +my $uc_list = <<'END'; +This is \\Here. +foo[A-Z]+ +[A-Z]*bar +parens([A-Z]*) +foo(?!lookahead)([A-Z]*) + +# Don't get confused by regex metacharacters. +\WWhat now? +dumb \DDonald +lost in \SSpace +lost in \\\\Diskland + +# Weird combinations +\A\\\B\S{14}\G\\\D\\Dog\\\W*\\\\\S+\\\\\Z +\\W//\\W//\\Larry//\\D//? +END + + +my @lc_list = _big_split($lc_list); +if ( $] >= 5.012 ) { + push( @lc_list, 'anything but \n -> \N' ); +} + +my @uc_list = _big_split($uc_list); + +subtest 'Check lowercase' => sub { + plan tests => scalar @lc_list; + + for my $lc ( @lc_list ) { + my $re = qr/$lc/; + ok( App::Ack::is_lowercase( $lc ), qq{"$lc" should be lowercase} ); + } +}; + +subtest 'Check uppercase' => sub { + plan tests => scalar @uc_list; + + for my $uc ( @uc_list ) { + my $re = qr/$uc/; + ok( !App::Ack::is_lowercase( $uc ), qq{"$uc" should not be lowercase} ); + } +}; + +done_testing(); +exit 0; + + +sub _big_split { + my $str = shift; + + return grep { /./ && !/^#/ } split( /\n/, $str ); +} diff -Nru ack-3.6.0/t/match-filter.t ack-3.7.0/t/match-filter.t --- ack-3.6.0/t/match-filter.t 1970-01-01 00:00:00.000000000 +0000 +++ ack-3.7.0/t/match-filter.t 2023-02-25 20:34:52.000000000 +0000 @@ -0,0 +1,18 @@ +#!perl + +use strict; +use warnings; +use lib 't'; + +use FilterTest; +use Test::More tests => 1; + +use App::Ack::Filter::Match; + +filter_test( + [ match => '/^.akefile/' ], [ + 't/swamp/Makefile', + 't/swamp/Makefile.PL', + 't/swamp/Rakefile', + ], 'only files matching /^.akefile/ should be matched', +); diff -Nru ack-3.6.0/t/noenv.t ack-3.7.0/t/noenv.t --- ack-3.6.0/t/noenv.t 1970-01-01 00:00:00.000000000 +0000 +++ ack-3.7.0/t/noenv.t 2023-02-25 20:34:52.000000000 +0000 @@ -0,0 +1,99 @@ +#!perl + +use strict; +use warnings; + +use Test::More tests => 3; + +use lib 't'; +use Util; + +use App::Ack::ConfigLoader; +use Cwd qw( realpath ); +use File::Spec (); +use File::Temp (); + +sub is_global_file { + my ( $filename ) = @_; + + return unless -f $filename; + + my ( undef, $dir ) = File::Spec->splitpath($filename); + $dir = File::Spec->canonpath($dir); + + my (undef, $wd) = File::Spec->splitpath(getcwd_clean(), 1); + $wd = File::Spec->canonpath($wd); + + return $wd !~ /^\Q$dir\E/; +} + +sub remove_defaults_and_globals { + my ( @sources ) = @_; + + return grep { + $_->{name} ne 'Defaults' && !is_global_file($_->{name}) + } @sources; +} + +prep_environment(); + +my $wd = getcwd_clean() or die; + +my $tempdir = File::Temp->newdir; + +safe_chdir( $tempdir->dirname ); + +write_file( '.ackrc', <<'ACKRC' ); +--type-add=perl:ext:pl,t,pm +ACKRC + +subtest 'without --noenv' => sub { + plan tests => 1; + + local @ARGV = ('-f', 'lib/'); + + my @sources = App::Ack::ConfigLoader::retrieve_arg_sources(); + @sources = remove_defaults_and_globals(@sources); + + is_deeply( \@sources, [ + { + name => File::Spec->canonpath(realpath(File::Spec->catfile($tempdir->dirname, '.ackrc'))), + contents => [ '--type-add=perl:ext:pl,t,pm' ], + project => 1, + is_ackrc => 1, + }, + { + name => 'ARGV', + contents => ['-f', 'lib/'], + }, + ], 'Get back a long list of arguments' ); +}; + +subtest 'with --noenv' => sub { + plan tests => 1; + + local @ARGV = ('--noenv', '-f', 'lib/'); + + my @sources = App::Ack::ConfigLoader::retrieve_arg_sources(); + @sources = remove_defaults_and_globals(@sources); + + is_deeply( \@sources, [ + { + name => 'ARGV', + contents => ['-f', 'lib/'], + }, + ], 'Short list comes back because of --noenv' ); +}; + +subtest '--noenv in config' => sub { + plan tests => 3; + + append_file( '.ackrc', "--noenv\n" ); + + my ( $stdout, $stderr ) = run_ack_with_stderr('--env', 'perl'); + is_empty_array( $stdout ); + is( @{$stderr}, 1 ); + like( $stderr->[0], qr/--noenv found in (?:.*)[.]ackrc/ ) or diag(explain($stderr)); +}; + +safe_chdir( $wd ); # Go back to the original directory to avoid warnings