This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
In bisect-runner.pl, don't set $defines{cc} if printing usage messages.
[perl5.git] / Porting / bisect-runner.pl
index d8d7948..f0cc795 100755 (executable)
@@ -53,7 +53,6 @@ my %defines =
     (
      usedevel => '',
      optimize => '-g',
-     cc => (`ccache --version`, $?) ? 'cc' : 'ccache cc',
      ld => 'cc',
      ($linux64 ? (libpth => \@paths) : ()),
     );
@@ -61,9 +60,13 @@ my %defines =
 unless(GetOptions(\%options,
                   'target=s', 'make=s', 'jobs|j=i', 'expect-pass=i',
                   'expect-fail' => sub { $options{'expect-pass'} = 0; },
-                  'clean!', 'one-liner|e=s', 'match=s', 'force-manifest',
-                  'force-regen', 'test-build', 'A=s@', 'l', 'w',
-                  'check-args', 'check-shebang!', 'usage|help|?', 'validate',
+                  'clean!', 'one-liner|e=s', 'c', 'l', 'w', 'match=s',
+                  'no-match=s' => sub {
+                      $options{match} = $_[1];
+                      $options{'expect-pass'} = 0;
+                  },
+                  'force-manifest', 'force-regen', 'test-build', 'validate',
+                  'check-args', 'check-shebang!', 'usage|help|?', 'A=s@',
                   'D=s@' => sub {
                       my (undef, $val) = @_;
                       if ($val =~ /\A([^=]+)=(.*)/s) {
@@ -84,13 +87,14 @@ my ($target, $j, $match) = @options{qw(target jobs match)};
 @ARGV = ('sh', '-c', 'cd t && ./perl TEST base/*.t')
     if $options{validate} && !@ARGV;
 
-pod2usage(exitval => 255, verbose => 1) if $options{usage};
+pod2usage(exitval => 0, verbose => 2) if $options{usage};
 pod2usage(exitval => 255, verbose => 1)
     unless @ARGV || $match || $options{'test-build'} || defined $options{'one-liner'};
 pod2usage(exitval => 255, verbose => 1)
     if !$options{'one-liner'} && ($options{l} || $options{w});
 
-check_shebang($ARGV[0]) if $options{'check-shebang'} && @ARGV;
+check_shebang($ARGV[0])
+    if $options{'check-shebang'} && @ARGV && !$options{match};
 
 exit 0 if $options{'check-args'};
 
@@ -184,8 +188,10 @@ If your F<db.h> is old enough you can override this with C<-Unoextensions>.
 
 Earliest revision to test, as a I<commit-ish> (a tag, commit or anything
 else C<git> understands as a revision). If not specified, F<bisect.pl> will
-search stable perl releases from 5.002 to 5.14.0 until it finds one where
-the test case passes.
+search stable perl releases until it finds one where the test case passes.
+The default is to search from 5.002 to 5.14.0. If F<bisect.pl> detects that
+the checkout is on a case insensitive file system, it will search from
+5.005 to 5.14.0
 
 =item *
 
@@ -277,6 +283,12 @@ which interferes with detecting errors in the example code itself.
 
 =item *
 
+-c
+
+Add C<-c> to the command line, to cause perl to exit after syntax checking.
+
+=item *
+
 -l
 
 Add C<-l> to the command line with C<-e>
@@ -293,8 +305,8 @@ a full test case, instead of using C<bisect.pl>'s C<-e> shortcut.
 
 Add C<-w> to the command line with C<-e>
 
-It's not valid to pass C<-l> or C<-w> to C<bisect.pl> unless you are also
-using C<-e>
+It's not valid to pass C<-c>,  C<-l> or C<-w> to C<bisect.pl> unless you are
+also using C<-e>
 
 =item *
 
@@ -347,14 +359,43 @@ I<number of CPUs>. Otherwise defaults to 2.
 
 --match pattern
 
-Instead of running a test program to determine I<pass> or I<fail>, pass
-if the given regex matches, and hence search for the commit that removes
-the last matching file.
+=item *
+
+--no-match pattern
+
+Instead of running a test program to determine I<pass> or I<fail>,
+C<--match> will pass if the given regex matches, and hence search for the
+commit that removes the last matching file. C<--no-match> inverts the test,
+to search for the first commit that adds files that match.
+
+The remaining command line arguments are treated as glob patterns for files
+to match against. If none are specified, then they default as follows:
+
+=over 4
+
+=item *
 
 If no I<target> is specified, the match is against all files in the
-repository (which is fast). If a I<target> is specified, that target is
-built, and the match is against only the built files. C<--expect-fail> can
-be used with C<--match> to search for a commit that adds files that match.
+repository (which is fast).
+
+=item *
+
+If a I<target> is specified, that target is built, and the match is against
+only the built files.
+
+=back
+
+Treating the command line arguments as glob patterns should not cause
+problems, as the perl distribution has never shipped or built files with
+names that contain characters which are globbing metacharacters.
+
+Anything which is not a readable file is ignored, instead of generating an
+error. (If you want an error, run C<grep> or C<ack> as a test case). This
+permits one to easily search in a file that changed its name. For example:
+
+    .../Porting/bisect.pl --match 'Pod.*Functions' 'pod/buildtoc*'
+
+C<--no-match ...> is implemented as C<--expect-fail --match ...>
 
 =item *
 
@@ -425,7 +466,8 @@ Passing this to F<bisect.pl> will likely cause the bisect to fail badly.
 --validate
 
 Test that all stable revisions can be built. By default, attempts to build
-I<blead>, I<v5.14.0> .. I<perl-5.002>. Stops at the first failure, without
+I<blead>, I<v5.14.0> .. I<perl-5.002> (or I<perl5.005> on a case insensitive
+file system). Stops at the first failure, without
 cleaning the checkout. Use I<--start> to specify the earliest revision to
 test, I<--end> to specify the most recent. Useful for validating a new
 OS/CPU/compiler combination. For example
@@ -475,6 +517,15 @@ Display the usage information and exit.
 
 die "$0: Can't build $target" if defined $target && !grep {@targets} $target;
 
+unless (exists $defines{cc}) {
+    # If it fails, the heuristic of 63f9ec3008baf7d6 is noisy, and hence
+    # confusing. Additionally, it doesn't correctly cope with ccache 2.4
+    # FIXME - really it should be replaced with a proper test of
+    # "can we build something?" and a helpful diagnostic if we can't.
+    # For now, simply move it here.
+    $defines{cc} = (`ccache --version`, $?) ? 'cc' : 'ccache cc';
+}
+
 $j = "-j$j" if $j =~ /\A\d+\z/;
 
 if (exists $options{make}) {
@@ -675,7 +726,8 @@ sub apply_patch {
     print $fh $patch_to_use;
     return if close $fh;
     print STDERR "Patch is <<'EOPATCH'\n${patch}EOPATCH\n";
-    print STDERR "\nConverted to a context diff <<'EOCONTEXT'\n${patch_to_use}EOCONTEXT\n";
+    print STDERR "\nConverted to a context diff <<'EOCONTEXT'\n${patch_to_use}EOCONTEXT\n"
+        if $patch_to_use ne $patch;
     die "Can't $what$files: $?, $!";
 }
 
@@ -770,12 +822,21 @@ sub report_and_exit {
 }
 
 sub match_and_exit {
-    my $target = shift;
+    my ($target, @globs) = @_;
     my $matches = 0;
     my $re = qr/$match/;
     my @files;
 
-    {
+    if (@globs) {
+        require File::Glob;
+        foreach (sort map { File::Glob::bsd_glob($_)} @globs) {
+            if (!-f $_ || !-r _) {
+                warn "Skipping matching '$_' as it is not a readable file\n";
+            } else {
+                push @files, $_;
+            }
+        }
+    } else {
         local $/ = "\0";
         @files = defined $target ? `git ls-files -o -z`: `git ls-files -z`;
         chomp @files;
@@ -805,13 +866,22 @@ sub match_and_exit {
 system 'git clean -dxf </dev/null' and die;
 
 if (!defined $target) {
-    match_and_exit() if $match;
+    match_and_exit(undef, @ARGV) if $match;
     $target = 'test_prep';
 }
 
 skip('no Configure - is this the //depot/perlext/Compiler branch?')
     unless -f 'Configure';
 
+my $case_insensitive;
+{
+    my ($dev_C, $ino_C) = stat 'Configure';
+    die "Could not stat Configure: $!" unless defined $dev_C;
+    my ($dev_c, $ino_c) = stat 'configure';
+    ++$case_insensitive
+        if defined $dev_c && $dev_C == $dev_c && $ino_C == $ino_c;
+}
+
 # This changes to PERL_VERSION in 4d8076ea25903dcb in 1999
 my $major
     = extract_from_file('patchlevel.h',
@@ -901,10 +971,12 @@ if (-f 'config.sh') {
 }
 
 if ($target =~ /config\.s?h/) {
-    match_and_exit($target) if $match && -f $target;
+    match_and_exit($target, @ARGV) if $match && -f $target;
     report_and_exit(!-f $target, 'could build', 'could not build', $target)
         if $options{'test-build'};
 
+    skip("could not build $target") unless -f $target;
+
     my $ret = system @ARGV;
     report_and_exit($ret, 'zero exit from', 'non-zero exit from', "@ARGV");
 } elsif (!-f 'config.sh') {
@@ -930,10 +1002,12 @@ patch_ext();
 # Parallel build for miniperl is safe
 system "$options{make} $j miniperl </dev/null";
 
-my $expected = $target =~ /^test/ ? 't/perl'
+# This is the file we expect make to create
+my $expected_file = $target =~ /^test/ ? 't/perl'
     : $target eq 'Fcntl' ? "lib/auto/Fcntl/Fcntl.$Config{so}"
     : $target;
-my $real_target = $target eq 'Fcntl' ? $expected : $target;
+# This is the target we tell make to build in order to get $expected_file
+my $real_target = $target eq 'Fcntl' ? $expected_file : $target;
 
 if ($target ne 'miniperl') {
     # Nearly all parallel build issues fixed by 5.10.0. Untrustworthy before that.
@@ -953,22 +1027,41 @@ if ($target ne 'miniperl') {
     system "$options{make} $j $real_target </dev/null";
 }
 
-my $missing_target = $expected =~ /perl$/ ? !-x $expected : !-r $expected;
+my $expected_file_found = $expected_file =~ /perl$/
+    ? -x $expected_file : -r $expected_file;
+
+if ($expected_file_found && $expected_file eq 't/perl') {
+    # Check that it isn't actually pointing to ../miniperl, which will happen
+    # if the sanity check ./miniperl -Ilib -MExporter -e '<?>' fails, and
+    # Makefile tries to run minitest.
+
+    # Of course, helpfully sometimes it's called ../perl, other times .././perl
+    # and who knows if that list is exhaustive...
+    my ($dev0, $ino0) = stat 't/perl';
+    my ($dev1, $ino1) = stat 'perl';
+    unless (defined $dev0 && defined $dev1 && $dev0 == $dev1 && $ino0 == $ino1) {
+        undef $expected_file_found;
+        my $link = readlink $expected_file;
+        warn "'t/perl' => '$link', not 'perl'";
+        die "Could not realink t/perl: $!" unless defined $link;
+    }
+}
 
 if ($options{'test-build'}) {
-    report_and_exit($missing_target, 'could build', 'could not build',
+    report_and_exit(!$expected_file_found, 'could build', 'could not build',
                     $real_target);
-} elsif ($missing_target) {
+} elsif (!$expected_file_found) {
     skip("could not build $real_target");
 }
 
-match_and_exit($real_target) if $match;
+match_and_exit($real_target, @ARGV) if $match;
 
 if (defined $options{'one-liner'}) {
     my $exe = $target =~ /^(?:perl$|test)/ ? 'perl' : 'miniperl';
     unshift @ARGV, '-e', $options{'one-liner'};
-    unshift @ARGV, '-l' if $options{l};
-    unshift @ARGV, '-w' if $options{w};
+    foreach (qw(c l w)) {
+        unshift @ARGV, "-$_" if $options{$_};
+    }
     unshift @ARGV, "./$exe", '-Ilib';
 }
 
@@ -1409,6 +1502,19 @@ index 4b55fa6..60c3c64 100755
 EOPATCH
     }
 
+    if ($major < 8 && $^O eq 'aix') {
+        edit_file('Configure', sub {
+                      my $code = shift;
+                      # Replicate commit a8c676c69574838b
+                      # Whitespace allowed at the ends of /lib/syscalls.exp lines
+                      # and half of commit c6912327ae30e6de
+                      # AIX syscalls.exp scan: the syscall might be marked 32, 3264, or 64
+                      $code =~ s{(\bsed\b.*\bsyscall)(?:\[0-9\]\*)?(\$.*/lib/syscalls\.exp)}
+                                {$1 . "[0-9]*[ \t]*" . $2}e;
+                      return $code;
+                  });
+    }
+
     if ($major < 8 && !extract_from_file('Configure',
                                          qr/^\t\tif test ! -t 0; then$/)) {
         # Before dfe9444ca7881e71, Configure would refuse to run if stdin was
@@ -1567,6 +1673,15 @@ sub patch_hints {
                       # to 5.002, lets just turn it off.
                       $code =~ s/^useshrplib='true'/useshrplib='false'/m
                           if $faking_it;
+
+                      # Part of commit d235852b65d51c44
+                      # Don't do this on a case sensitive HFS+ partition, as it
+                      # breaks the build for 5.003 and earlier.
+                      if ($case_insensitive
+                          && $code !~ /^firstmakefile=GNUmakefile/) {
+                          $code .= "\nfirstmakefile=GNUmakefile;\n";
+                      }
+
                       return $code;
                   });
         }
@@ -2388,6 +2503,207 @@ EOPATCH
                   });
     }
 
+    if ($major < 5 && $^O eq 'aix'
+        && !extract_from_file('pp_sys.c',
+                              qr/defined\(HOST_NOT_FOUND\) && !defined\(h_errno\)/)) {
+        # part of commit dc45a647708b6c54
+        # Andy Dougherty's configuration patches (Config_63-01 up to 04).
+        apply_patch(<<'EOPATCH')
+diff --git a/pp_sys.c b/pp_sys.c
+index c2fcb6f..efa39fb 100644
+--- a/pp_sys.c
++++ b/pp_sys.c
+@@ -54,7 +54,7 @@ extern "C" int syscall(unsigned long,...);
+ #endif
+ #endif
+-#ifdef HOST_NOT_FOUND
++#if defined(HOST_NOT_FOUND) && !defined(h_errno)
+ extern int h_errno;
+ #endif
+EOPATCH
+    }
+
+    if ($major == 5
+        && `git rev-parse HEAD` eq "22c35a8c2392967a5ba6b5370695be464bd7012c\n") {
+        # Commit 22c35a8c2392967a is significant,
+        # "phase 1 of somewhat major rearrangement of PERL_OBJECT stuff"
+        # but doesn't build due to 2 simple errors. blead in this broken state
+        # was merged to the cfgperl branch, and then these were immediately
+        # corrected there. cfgperl (with the fixes) was merged back to blead.
+        # The resultant rather twisty maze of commits looks like this:
+
+=begin comment
+
+* | |   commit 137225782c183172f360c827424b9b9f8adbef0e
+|\ \ \  Merge: 22c35a8 2a8ee23
+| |/ /  Author: Gurusamy Sarathy <gsar@cpan.org>
+| | |   Date:   Fri Oct 30 17:38:36 1998 +0000
+| | |
+| | |       integrate cfgperl tweaks into mainline
+| | |
+| | |       p4raw-id: //depot/perl@2144
+| | |
+| * | commit 2a8ee23279873759693fa83eca279355db2b665c
+| | | Author: Jarkko Hietaniemi <jhi@iki.fi>
+| | | Date:   Fri Oct 30 13:27:39 1998 +0000
+| | |
+| | |     There can be multiple yacc/bison errors.
+| | |
+| | |     p4raw-id: //depot/cfgperl@2143
+| | |
+| * | commit 93fb2ac393172fc3e2c14edb20b718309198abbc
+| | | Author: Jarkko Hietaniemi <jhi@iki.fi>
+| | | Date:   Fri Oct 30 13:18:43 1998 +0000
+| | |
+| | |     README.posix-bc update.
+| | |
+| | |     p4raw-id: //depot/cfgperl@2142
+| | |
+| * | commit 4ec43091e8e6657cb260b5e563df30aaa154effe
+| | | Author: Jarkko Hietaniemi <jhi@iki.fi>
+| | | Date:   Fri Oct 30 09:12:59 1998 +0000
+| | |
+| | |     #2133 fallout.
+| | |
+| | |     p4raw-id: //depot/cfgperl@2141
+| | |
+| * |   commit 134ca994cfefe0f613d43505a885e4fc2100b05c
+| |\ \  Merge: 7093112 22c35a8
+| |/ /  Author: Jarkko Hietaniemi <jhi@iki.fi>
+|/| |   Date:   Fri Oct 30 08:43:18 1998 +0000
+| | |
+| | |       Integrate from mainperl.
+| | |
+| | |       p4raw-id: //depot/cfgperl@2140
+| | |
+* | | commit 22c35a8c2392967a5ba6b5370695be464bd7012c
+| | | Author: Gurusamy Sarathy <gsar@cpan.org>
+| | | Date:   Fri Oct 30 02:51:39 1998 +0000
+| | |
+| | |     phase 1 of somewhat major rearrangement of PERL_OBJECT stuff
+| | |     (objpp.h is gone, embed.pl now does some of that); objXSUB.h
+| | |     should soon be automated also; the global variables that
+| | |     escaped the PL_foo conversion are now reined in; renamed
+| | |     MAGIC in regcomp.h to REG_MAGIC to avoid collision with the
+| | |     type of same name; duplicated lists of pp_things in various
+| | |     places is now gone; result has only been tested on win32
+| | |
+| | |     p4raw-id: //depot/perl@2133
+
+=end comment
+
+=cut
+
+        # and completely confuses git bisect (and at least me), causing it to
+        # the bisect run to confidently return the wrong answer, an unrelated
+        # commit on the cfgperl branch.
+
+        apply_commit('4ec43091e8e6657c');
+    }
+
+    if ($major == 5
+        && extract_from_file('pp_sys.c', qr/PERL_EFF_ACCESS_R_OK/)
+        && !extract_from_file('pp_sys.c', qr/XXX Configure test needed for eaccess/)) {
+        # Between 5ff3f7a4e03a6b10 and c955f1177b2e311d^
+        # This is the meat of commit c955f1177b2e311d (without the other
+        # indenting changes that would cause a conflict).
+        # Without this 538 revisions won't build on (at least) Linux
+        apply_patch(<<'EOPATCH');
+diff --git a/pp_sys.c b/pp_sys.c
+index d60c8dc..867dee4 100644
+--- a/pp_sys.c
++++ b/pp_sys.c
+@@ -198,9 +198,18 @@ static char zero_but_true[ZBTLEN + 1] = "0 but true";
+ #   if defined(I_SYS_SECURITY)
+ #       include <sys/security.h>
+ #   endif
+-#   define PERL_EFF_ACCESS_R_OK(p) (eaccess((p), R_OK, ACC_SELF))
+-#   define PERL_EFF_ACCESS_W_OK(p) (eaccess((p), W_OK, ACC_SELF))
+-#   define PERL_EFF_ACCESS_X_OK(p) (eaccess((p), X_OK, ACC_SELF))
++    /* XXX Configure test needed for eaccess */
++#   ifdef ACC_SELF
++        /* HP SecureWare */
++#       define PERL_EFF_ACCESS_R_OK(p) (eaccess((p), R_OK, ACC_SELF))
++#       define PERL_EFF_ACCESS_W_OK(p) (eaccess((p), W_OK, ACC_SELF))
++#       define PERL_EFF_ACCESS_X_OK(p) (eaccess((p), X_OK, ACC_SELF))
++#   else
++        /* SCO */
++#       define PERL_EFF_ACCESS_R_OK(p) (eaccess((p), R_OK))
++#       define PERL_EFF_ACCESS_W_OK(p) (eaccess((p), W_OK))
++#       define PERL_EFF_ACCESS_X_OK(p) (eaccess((p), X_OK))
++#   endif
+ #endif
+ #if !defined(PERL_EFF_ACCESS_R_OK) && defined(HAS_ACCESSX) && defined(ACC_SELF)
+EOPATCH
+    }
+
+    if ($major == 5
+        && extract_from_file('mg.c', qr/If we're still on top of the stack, pop us off/)
+        && !extract_from_file('mg.c', qr/PL_savestack_ix -= popval/)) {
+        # Fix up commit 455ece5e082708b1:
+        # SSNEW() API for allocating memory on the savestack
+        # Message-Id: <tqemtae338.fsf@puma.genscan.com>
+        # Subject: [PATCH 5.005_51] (was: why SAVEDESTRUCTOR()...)
+        apply_commit('3c8a44569607336e', 'mg.c');
+    }
+
+    if ($major == 5) {
+        if (extract_from_file('doop.c', qr/croak\(no_modify\);/)
+            && extract_from_file('doop.c', qr/croak\(PL_no_modify\);/)) {
+            # Whilst the log suggests that this would only fix 5 commits, in
+            # practice this area of history is a complete tarpit, and git bisect
+            # gets very confused by the skips in the middle of the back and
+            # forth merging between //depot/perl and //depot/cfgperl
+            apply_commit('6393042b638dafd3');
+        }
+
+        # One error "fixed" with another:
+        if (extract_from_file('pp_ctl.c',
+                              qr/\Qstatic void *docatch_body _((void *o));\E/)) {
+            apply_commit('5b51e982882955fe');
+        }
+        # Which is then fixed by this:
+        if (extract_from_file('pp_ctl.c',
+                              qr/\Qstatic void *docatch_body _((valist\E/)) {
+            apply_commit('47aa779ee4c1a50e');
+        }
+
+        if (extract_from_file('thrdvar.h', qr/PERLVARI\(Tprotect/)
+            && !extract_from_file('embedvar.h', qr/PL_protect/)) {
+            # Commit 312caa8e97f1c7ee didn't update embedvar.h
+            apply_commit('e0284a306d2de082', 'embedvar.h');
+        }
+    }
+
+    if ($major == 5
+        && extract_from_file('sv.c',
+                             qr/PerlDir_close\(IoDIRP\((?:\(IO\*\))?sv\)\);/)
+        && !(extract_from_file('toke.c',
+                               qr/\QIoDIRP(FILTER_DATA(AvFILLp(PL_rsfp_filters))) = NULL\E/)
+             || extract_from_file('toke.c',
+                                  qr/\QIoDIRP(datasv) = (DIR*)NULL;\E/))) {
+        # Commit 93578b34124e8a3b, //depot/perl@3298
+        # close directory handles properly when localized,
+        # tweaked slightly by commit 1236053a2c722e2b,
+        # add test case for change#3298
+        #
+        # The fix is the last part of:
+        #
+        # various fixes for clean build and test on win32; configpm broken,
+        # needed to open myconfig.SH rather than myconfig; sundry adjustments
+        # to bytecode stuff; tweaks to DYNAMIC_ENV_FETCH code to make it
+        # work under win32; getenv_sv() changed to getenv_len() since SVs
+        # aren't visible in the lower echelons; remove bogus exports from
+        # config.sym; PERL_OBJECT-ness for C++ exception support; null out
+        # IoDIRP in filter_del() or sv_free() will attempt to close it
+        #
+        # The changed code is modified subsequently by commit e0c198038146b7a4
+        apply_commit('a6c403648ecd5cc7', 'toke.c');
+    }
+
     if ($major < 6 && $^O eq 'netbsd'
         && !extract_from_file('unixish.h',
                               qr/defined\(NSIG\).*defined\(__NetBSD__\)/)) {
@@ -2501,6 +2817,16 @@ sub patch_ext {
         apply_commit('6695a346c41138df');
     }
 
+    if (-f 'ext/Hash/Util/Makefile.PL'
+        && extract_from_file('ext/Hash/Util/Makefile.PL',
+                             qr/\bDIR\b.*'FieldHash'/)) {
+        # ext/Hash/Util/Makefile.PL should not recurse to FieldHash's Makefile.PL
+        # *nix, VMS and Win32 all know how to (and have to) call the latter directly.
+        # As is, targets in ext/Hash/Util/FieldHash get called twice, which may result
+        # in race conditions, and certainly messes up make clean; make distclean;
+        apply_commit('550428fe486b1888');
+    }
+
     if ($major < 8 && $^O eq 'darwin' && !-f 'ext/DynaLoader/dl_dyld.xs') {
         checkout_file('ext/DynaLoader/dl_dyld.xs', 'f556e5b971932902');
         apply_patch(<<'EOPATCH');