From a8eaf215b956dfaf97fed974ef1dee201a2d7762 Mon Sep 17 00:00:00 2001 From: Yves Orton Date: Fri, 11 Mar 2022 04:27:47 +0100 Subject: [PATCH 01/13] manisort: rework, add new convenience option "fix" and add pod, etc Add a new convenience option to manisort for a common case manisort --fix=MANIFEST_FILE is the same as manisort --nocheck --output=MANIFEST_FILE MANIFEST_FILE Eg, it runs quietly, returns an exit code of 0 on success and rewrites the file in correctly sorted order while removing true dupes. --- Porting/README.pod | 19 +++- Porting/manisort | 229 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 219 insertions(+), 29 deletions(-) diff --git a/Porting/README.pod b/Porting/README.pod index e8f14a9cd7fd..e011a5439a56 100644 --- a/Porting/README.pod +++ b/Porting/README.pod @@ -258,11 +258,26 @@ list of files that exist and aren't in F. =head2 F -This library provides functions used in checking and sorting the F. +This library provides functions used in checking and sorting the +F. The sort order is similar to +dictionary sort order (alphabetical case insensitive) but where path +components and extensions are sorted independently such that the +following files would be sorted into the following order: + + Configure + configure + lib/Foo/Bar + lib/Foo/Bar.pm + lib/Foo/Bar/Alpha.pm + lib/Foo-Alpha/Baz + +Currently this code does not support EBCDIC. Patches welcome. =head2 F -This script sorts the files in F. +This script sorts the files in F or F. It uses +F to do the sorting. Use C +to see instructions for use. =head2 F diff --git a/Porting/manisort b/Porting/manisort index 167aada7345d..10991155ba06 100644 --- a/Porting/manisort +++ b/Porting/manisort @@ -12,52 +12,227 @@ use strict; use warnings; $| = 1; +sub abort { + my ($exit_code, $message) = @_; + print STDERR $message, "\n"; + exit $exit_code; +} + # Get command line options -use Getopt::Long; +use Getopt::Long qw(GetOptions); +use Pod::Usage qw(pod2usage); require "./Porting/manifest_lib.pl"; +my $man = 0; +my $help = 0; my $outfile; -my $check_only = 0; -my $quiet = 0; -GetOptions ('output=s' => \$outfile, - 'check' => \$check_only, - 'quiet' => \$quiet); +my $fixfile; +my $quiet; +my $check; # legacy support - does nothing. +GetOptions( + 'check!' => \$check, + 'output=s' => \$outfile, + 'fix=s' => \$fixfile, + 'quiet!' => \$quiet, + 'help|?' => \$help, + 'man' => \$man +) or pod2usage(2); +pod2usage(42) if $help; +pod2usage(-verbose => 2, -exitval => 42) if $man; -my $file = (@ARGV) ? shift : 'MANIFEST'; +my $file = (@ARGV) ? shift : $fixfile ? $fixfile : 'MANIFEST'; + +if ($fixfile) { + $outfile //= $fixfile; + $check //= 0; +} + +if (defined $check){ + $quiet //= 1 unless $check; +} else { + $check = 1; +} + +if (!$check and !defined $outfile) { + abort(2, "Using --nocheck without providing a file makes no sense!"); +} # Read in the MANIFEST file open(my $IN, '<', $file) - or die("Can't read '$file': $!"); + or abort(3, "Can't read '$file': $!"); my @manifest = <$IN>; -close($IN) or die($!); +close($IN) + or abort(3, "Failed to close '$file': $!"); chomp(@manifest); -my %seen= ( '' => 1 ); # filter out blank lines +# note the seen filter only removes /exact/ dupes if the same file is +# listed twice with different descriptions or separators it will not +# filter them out. +my %seen = ( '' => 1 ); # filter out blank lines my @sorted = grep { !$seen{$_}++ } - sort_manifest(@manifest) -; - -# Check if the file is sorted or not -my $exit_code = 0; -for (my $ii = 0; $ii < $#manifest; $ii++) { - next if ($manifest[$ii] eq $sorted[$ii]); - $exit_code = 1; # Not sorted - last; + sort_manifest(@manifest); + +# Check if the file has any exact dupes, and if it is sorted or not. +my $was_well_formed = 1; +if (@sorted != @manifest) { + $was_well_formed = 0; +} else { + for my $idx (0 .. $#sorted) { + next if ($manifest[$idx] eq $sorted[$idx]); + $was_well_formed = 0; # Not sorted + last; + } } # Output sorted file if (defined($outfile)) { - open(my $OUT, '>', $outfile) - or die("Can't open output file '$outfile': $!"); - binmode($OUT); - print($OUT join("\n", @sorted), "\n"); - close($OUT) or die($!); + my $tmpfile= "$outfile.$$"; # avoid partially written output on error + open(my $OUT, '>', $tmpfile) + or abort(3, "Can't open output file '$tmpfile': $!"); + binmode($OUT) + or abort(3, "Can't binmode '$tmpfile': $!"); + print($OUT join("\n", @sorted), "\n") + or abort(3, "Can't print to '$tmpfile': $!"); + close($OUT) + or abort(3, "Can't print to '$tmpfile': $!"); + rename $tmpfile, $outfile + or abort(3, "Can't rename '$tmpfile' into place as '$outfile': $!"); } # Report on sort results printf(STDERR "'$file' is%s sorted properly\n", - (($exit_code) ? ' NOT' : '')) if (! $quiet); + ($was_well_formed ? '' : ' NOT')) + unless $quiet; # Exit with the sort results status -exit($exit_code); +if (!$check or $was_well_formed) { + exit 0; +} else { + exit 1; +} +__END__ + +=head1 NAME + +manisort - Sort MANIFEST files according to the Perl sort order conventions + +=head1 SYNOPSIS + +manisort [options] [MANIFEST_FILE] + + Options: + --help brief help message + --check check FILE, signal status via exit code (default) + --nocheck do not check file, status will be 0 after update + --man full documentation + --quiet do not output a message if the file is not sorted + --noquiet output a message if file is not sorted + --output=FILE specify file to write to + --fix=FILE quietly fix the specified file + + +=head1 OPTIONS + +=over 4 + +=item B<--help> + +Print a brief help message and exits with an exit code of 42. + +=item B<--man> + +Prints the manual page and exits with an exit code of 42. + +=item B<--check> + +This is the default mode of the tool, check the file for whether it is +sorted and whether it contains any exact duplicate lines, and then +return an exit code of 0 if it is fine, and an exit code of 1 if it is +not, optionally outputting a message to STDERR to reflect the status +which can be suppressed with the B<--quiet> option. + +=item B<--nocheck> + +Do not check the original state of the file, and return an exit code of +0 unless there were errors during processing. Intended to be combined +with the B<--output> option. Implies B<--quiet>. + +If this option is provided and the B<--output> option is not specified +then the tool will output an error message and return with an exit code +of 2. + +=item B<--quiet> + +Do not output any status messages during processing. + +=item B<--noquiet> + +Output a message if the specified MANIFEST_FILE is not already sorted. + +=item B<--output=FILE> + +Write the sorted results to the specified FILE. If this option is +not provided the tool checks the sort order of a file only. + +=item B<--fix=FILE> + +Read this file, sort it, and write it back. By default does so quietly +and return exit 0 unless there were errors during processing. Using this +option alone is equivalent to: + + manisort --nocheck --output=MANIFEST_FILE MANIFEST_FILE + +Can be combined with the B<--check>, B<--noquiet> or B<--output> options, +in which case it is an alternative way to specify the MANIFEST_FILE. + +=back + +=head1 DESCRIPTION + +B is used to verify the sort order and/or fix the sort order +of the F file and F files included in +the Perl project. The sort order is similar to dictionary sort order +(alphabetical case insensitive) but where path components and extensions +are sorted independently such that the following files would be sorted +into the following order: + + Configure + configure + lib/Foo/Bar + lib/Foo/Bar.pm + lib/Foo/Bar/Alpha.pm + lib/Foo-Alpha/Baz + +When provided with no options or arguments the B operates on +the F in the root directory of the project. This may be +overriden by providing a MANIFEST_FILE argument. + +By default if the file is already sorted correctly the tool will print a +message to STDERR saying so and return an exit code of 0. If the file is +B already sorted then a message will be printed to STDERR and it +will return an exit code of 1. The output message may be suppressed with +the B<--quiet> option. The B<--nocheck> option may be used to disable +the check feature, in which case the tool will return an exit code of +0 provided it did something, and 2 if it did not. + +If the B<--output=FILE> option is provided the sorted version of the +file will be written to the specified FILE. The FILE and MANIFEST_FILE +arguments may be the same, the file will be read first and then output. + +If the B<--fix=FILE> option is provided then it is equivalent to saying + + manisort --nocheck --output=FILE FILE + +This is likely what you want if you just want to ensure the file is sorted. + +In all cases if there is an error reading or writing the file a message +will be printed to STDERR and the tool will return an exit code of 3. + +=head1 SEE ALSO + +F - the code that does the sorting. + +F - test manifest files are well formed. + +F - find missing or superfluous files in manifests. -# EOF +=cut From e00398bb5491ed0b5aa35d17e683c73fee06158e Mon Sep 17 00:00:00 2001 From: Yves Orton Date: Fri, 11 Mar 2022 05:26:35 +0100 Subject: [PATCH 02/13] Makefile.SH - use new --fix option to manisort and simplify The --fix option returns true if it worked, and so the use of the true command is not required. --- Makefile.SH | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.SH b/Makefile.SH index 0bc65f88968b..f9748f3c226e 100755 --- a/Makefile.SH +++ b/Makefile.SH @@ -667,7 +667,7 @@ all: $(FIRSTMAKEFILE) $(MINIPERL_EXE) $(generated_pods) $(private) $(unidatafile $(MANIFEST_SRT): MANIFEST $(PERL_EXE) @$(RUN_PERL) Porting/manisort -q || (echo "WARNING: re-sorting MANIFEST"; \ - $(RUN_PERL) Porting/manisort -q -o MANIFEST; sh -c true) + $(RUN_PERL) Porting/manisort --fix=MANIFEST) @touch $(MANIFEST_SRT) .PHONY: all utilities @@ -1287,7 +1287,7 @@ regen_all regen-all: regen regen_meta manisort: FORCE @perl Porting/manisort -q || (echo "WARNING: re-sorting MANIFEST"; \ - perl Porting/manisort -q -o MANIFEST; sh -c true) + perl Porting/manisort --fix=MANIFEST) manicheck: FORCE perl Porting/manicheck From 233f92ce8af7fa823c4c510ddbf625c71e95e62a Mon Sep 17 00:00:00 2001 From: Yves Orton Date: Fri, 11 Mar 2022 05:29:56 +0100 Subject: [PATCH 03/13] release_managers_guide.pod: point out the --fix option to manisort --- Porting/release_managers_guide.pod | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Porting/release_managers_guide.pod b/Porting/release_managers_guide.pod index f782aaedede1..f4b833f9086e 100644 --- a/Porting/release_managers_guide.pod +++ b/Porting/release_managers_guide.pod @@ -295,13 +295,16 @@ to the repository. =item * -For any files that are gone, remove them from C, and use +For any files that are gone, remove them from F, and use C to tell git the files will be gone. =item * -If the C file was changed in any of the previous steps, run -C. +If the F file was changed in any of the +previous steps, run C which will sort the file, or you +can manually run: + + perl Porting/manisort --fix MANIFEST =item * From 605f007a22f5bd471878fbc7de3d7569857a1b0f Mon Sep 17 00:00:00 2001 From: Yves Orton Date: Fri, 11 Mar 2022 05:22:13 +0100 Subject: [PATCH 04/13] Add descriptions to dead pods in pod/perl.pod Even though these pods are dead we should keep their descriptions for the manifest. --- MANIFEST | 12 ++++++------ pod/perl.pod | 13 ++++++------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/MANIFEST b/MANIFEST index 24c6831606a7..f4168399a45c 100644 --- a/MANIFEST +++ b/MANIFEST @@ -5310,8 +5310,8 @@ pod/perl58delta.pod Perl changes in version 5.8.0 pod/perlapio.pod Perl internal IO abstraction interface pod/perlartistic.pod Perl Artistic License pod/perlbook.pod Perl book information -pod/perlboot.pod -pod/perlbot.pod +pod/perlboot.pod Links to info on OO programming in Perl +pod/perlbot.pod Links to info on OO programming in Perl pod/perlcall.pod Perl calling conventions from C pod/perlcheat.pod Perl cheat sheet pod/perlclib.pod Internal replacements for standard C library functions @@ -5375,7 +5375,7 @@ pod/perlrecharclass.pod Perl regular expression character classes pod/perlref.pod Perl references, the rest of the story pod/perlreftut.pod Perl references short introduction pod/perlreguts.pod Perl regular expression engine internals -pod/perlrepository.pod +pod/perlrepository.pod Links to current info on the Perl source repository pod/perlrequick.pod Perl regular expressions quick start pod/perlreref.pod Perl regular expressions quick reference pod/perlretut.pod Perl regular expressions tutorial @@ -5388,9 +5388,9 @@ pod/perlsub.pod Perl subroutines pod/perlsyn.pod Perl syntax pod/perlthrtut.pod Perl threads tutorial pod/perltie.pod Perl objects hidden behind simple variables -pod/perltodo.pod -pod/perltooc.pod -pod/perltoot.pod +pod/perltodo.pod Link to the Perl to-do list +pod/perltooc.pod Links to info on OO programming in Perl +pod/perltoot.pod Links to info on OO programming in Perl pod/perltrap.pod Perl traps for the unwary pod/perlunicode.pod Perl Unicode support pod/perlunicook.pod Perl Unicode cookbook diff --git a/pod/perl.pod b/pod/perl.pod index 06470bd9443e..11ae197e0321 100644 --- a/pod/perl.pod +++ b/pod/perl.pod @@ -308,12 +308,12 @@ aux h2ph h2xs perlbug pl2pm pod2html pod2man splain xsubpp =head2 Stubs for Deleted Documents - perlboot - perlbot - perlrepository - perltodo - perltooc - perltoot + perlboot Links to info on OO programming in Perl + perlbot Links to info on OO programming in Perl + perlrepository Links to current info on the Perl source repository + perltodo Link to the Perl to-do list + perltooc Links to info on OO programming in Perl + perltoot Links to info on OO programming in Perl =for buildtoc __END__ @@ -455,4 +455,3 @@ how many more is left as an exercise to the reader. The three principal virtues of a programmer are Laziness, Impatience, and Hubris. See the Camel Book for why. - From 89528f5c2f5cc65c96d5bcdd3f31dee162a0a2e7 Mon Sep 17 00:00:00 2001 From: Yves Orton Date: Fri, 11 Mar 2022 09:22:52 +0100 Subject: [PATCH 05/13] manicheck: fix broken exitcode logic The comment says the highest exit code we should return is 124, but the code will return 125 if there are 125 problems, if it is higher than 125 it will return 124. Which doesn't make sense. This patch changes the logic to do what the comment says, return 124 if there are 124 or more problems, otherwise it returns the count of problems. --- Porting/manicheck | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Porting/manicheck b/Porting/manicheck index 6db1fd21204a..d059328554a1 100644 --- a/Porting/manicheck +++ b/Porting/manicheck @@ -8,7 +8,7 @@ use v5.14; use warnings; use File::Find; use Getopt::Long; -use constant SKIP => 125; +use constant MAX_EXIT_CODE => 124; my $exitstatus; GetOptions('exitstatus!', \$exitstatus) @@ -45,14 +45,16 @@ find { }, }, "."; -my $exitcode = $exitstatus ? $missing + $bonus : 0; +my $problems = $missing + $bonus; # We can't (meaningfully) exit with codes above 255, so we're going to have to # clamp them to some range whatever we do. So as we need the code anyway, use # 124 as our maximum instead, and then we can run as a useful git bisect run # script if needed... - -$exitcode = SKIP - 1 - if $exitcode > SKIP; +my $exitcode = (!$exitstatus) + ? 0 + : ($problems > MAX_EXIT_CODE) + ? MAX_EXIT_CODE + : $problems; exit $exitcode; From 0068e39a31f9d41dfc08d27c9e5b117872e96b2d Mon Sep 17 00:00:00 2001 From: Yves Orton Date: Thu, 10 Mar 2022 10:29:40 +0100 Subject: [PATCH 06/13] Create Porting/MANIFEST.dev as a complement to MANIFEST and related infra This file is intended to list all the files in the repo which are not listed in the main MANIFEST file, and which are used only for development purposes, especially those files which are only useful when working in a git checkout of the main perl git repository. The files it contains will NOT be added to the production tarball release. The file has the exact same format as the main MANIFEST: "file\t+description" or "file". Q. Why didn't I call this Porting/MANIFEST as mentioned in the discussion thread that lead to this patch? A. The main reason was that Porting/README.pod includes a list of files in Porting with descriptions and explanations for what the files do or how they are used. In several places the file refers to "MANIFEST", which lead to ambiguity that would have had to be resolved by changing all the entries to refer to "Porting/whatever" instead. It was much simpler to give the new file an extension, and I thought that '.dev' suggests it is for "development" purposes. Q. Why isn't this using MANIFEST.skip style functionality? A1. Various parts of our build and test process expect to read the MANIFEST file and then do things based on the entries contained within. Eg, run tests, or extract data, or compare the file list to content in another file. Those parts of our build process would break if we used a skip style list of regexen. So it would be more work to teach them to deal with such a file, assuming it was actually doable - given the additional work I have not considered it deeply. On the other hand teaching that logic to simply read two files was and is easy. A2. I think each file we have in the repo should have a description. This patch currently doesn't provide a description for each, but it does for many, especially those migrated from MANIFEST. A3. I think that MANIFEST.skip style files of exclusion regexens and globs are error prone and easy to mess up, for instance by excluding far more than you had intended to. They can also be annoying to get right, obviously not impossible, but sometimes annoying. Explicitly listing everything is easy in every way, especially to mechanize. A4. I would like to be able to move verbatim entries from our existing MANIFEST into the new Porting/MANIFEST.dev, description and all. MANIFEST.skip style files do not support descriptions except as comments as far as I recall. That would have meant munging the data from MANIFEST during the move process which would be annoying. A5. I would like to be able to reuse our sorting logic to keep the files nicely sorted in a way where the file is somewhat readable. A list of skip files would be less amenable to doing so. Q. There is a lot of duplicated logic related to testing manifests, should we refactor it out into a module or some resuable tool set? A. YES! We already have Porting/manifest_lib.pm, but it currently does not declare a package, and it only contains one function. Instead of adding yet more code that depends on requiring a file and having it inject subs into package main I decided that doing the refactoring could wait for a separate commit or PR. But I definitely think we should refactor as much of this logic as possible. Q. Some of the test files were fairly significantly changed, are you sure you didn't break or drop any of the tests? A. I am reasonably confident I did not. Secondary review appreciated. Some of the touched files are quite old and obviously "quick hack" scripts. By rewriting them quite a bit I was able to simplify and perform some of the tests in different ways or parts of the script. As far as I know I didn't drop any. Q. Why didn't you use newer features in the rewrite? A. I am a bit conservative in my taste, and I like build tools to be able to run on older perls, and for things like this I prefer to stick with what I know well. Patches welcome. Q. Why didn't you move more of the stuff we shouldn't bundle with our releases? A. I figured someone like Nicolas R. (who helped motivate this patch) would feel left out if I didn't leave him anything to do. :-) --- MANIFEST | 10 -- Makefile.SH | 6 + Porting/MANIFEST.dev | 84 ++++++++++ Porting/README.pod | 21 ++- Porting/manicheck | 56 ++++--- Porting/manifest_lib.pl | 4 +- Porting/release_managers_guide.pod | 6 +- t/porting/exec-bit.t | 9 +- t/porting/known_pod_issues.dat | 2 +- t/porting/manifest.t | 239 +++++++++++++++++++---------- t/porting/readme.t | 13 +- 11 files changed, 316 insertions(+), 134 deletions(-) create mode 100644 Porting/MANIFEST.dev diff --git a/MANIFEST b/MANIFEST index f4168399a45c..1fd31fb4a314 100644 --- a/MANIFEST +++ b/MANIFEST @@ -2,7 +2,6 @@ .editorconfig EditorConfig style file .lgtm.yml LGTM.com configuration file .metaconf-exclusions.txt Symbols that should ignored when generating Configure -.travis.yml continuous integration on github (where enabled) amigaos4/amigaio.c AmigaOS4 port amigaos4/amigaio.h AmigaOS4 port amigaos4/amigaos.c AmigaOS4 port @@ -5408,14 +5407,10 @@ Porting/acknowledgements.pl Generate perldelta acknowledgements text Porting/add-package.pl Add/Update CPAN modules that are part of Core Porting/add-pod-file Utility to add new pod/*.pod file to core distribution Porting/bench.pl Run benchmarks against t/perf/benchmarks -Porting/bisect.pl A tool to make bisecting easy -Porting/bisect-example.sh Example script to use with git bisect run -Porting/bisect-runner.pl Tool to be called by git bisect run Porting/bump-perl-version bump the perl version in relevant files Porting/check-cpan-pollution Check for commits that may wrongly touch CPAN distros Porting/check83.pl Check whether we are 8.3-friendly Porting/checkansi.pl Check source code for ANSI-C violations -Porting/checkAUTHORS.pl Check that the AUTHORS file is complete Porting/checkcfguse.pl Check that config symbols are being used Porting/checkcfgvar.pl Check that config scripts define all symbols Porting/checkpodencoding.pl Check POD encoding @@ -5438,10 +5433,6 @@ Porting/exec-bit.txt List of files that get +x in release tarball Porting/exercise_makedef.pl Brute force testing for makedef.pl Porting/expand-macro.pl A tool to expand C macro definitions in the Perl source Porting/findrfuncs Find reentrant variants of functions used in an executable -Porting/git-deltatool Mark commits for perldelta in git notes -Porting/git-find-p4-change Find the change for a p4 change number -Porting/git-make-p4-refs Output git refs for each p4 change number, suitable for appending to .git/packed-refs -Porting/GitUtils.pm Generate the contents of a .patch file Porting/Glossary Glossary of config.sh variables Porting/harness-timer-report.pl Analyze the timings from the test harness Porting/how_to_write_a_perldelta.pod Bluffer's guide to writing a perldelta. @@ -5479,7 +5470,6 @@ Porting/sync-with-cpan Sync with CPAN Porting/timecheck.c Test program for the 2038 fix Porting/timecheck2.c Test program for the 2038 fix Porting/todo.pod Perl things to do -Porting/updateAUTHORS.pl Tool to automatically update AUTHORS and .mailmap from git log data Porting/valgrindpp.pl Summarize valgrind reports Porting/vote_admin_guide.pod Perlgov Vote Administrator guide pp.c Push/Pop code diff --git a/Makefile.SH b/Makefile.SH index f9748f3c226e..07737c998667 100755 --- a/Makefile.SH +++ b/Makefile.SH @@ -668,6 +668,9 @@ all: $(FIRSTMAKEFILE) $(MINIPERL_EXE) $(generated_pods) $(private) $(unidatafile $(MANIFEST_SRT): MANIFEST $(PERL_EXE) @$(RUN_PERL) Porting/manisort -q || (echo "WARNING: re-sorting MANIFEST"; \ $(RUN_PERL) Porting/manisort --fix=MANIFEST) + @$(RUN_PERL) Porting/manisort -q Porting/MANIFEST.dev || \ + (echo "WARNING: re-sorting Porting/MANIFEST.dev"; \ + $(RUN_PERL) Porting/manisort --fix=Porting/MANIFEST.dev) @touch $(MANIFEST_SRT) .PHONY: all utilities @@ -1288,6 +1291,9 @@ regen_all regen-all: regen regen_meta manisort: FORCE @perl Porting/manisort -q || (echo "WARNING: re-sorting MANIFEST"; \ perl Porting/manisort --fix=MANIFEST) + @perl Porting/manisort -q Porting/MANIFEST.dev || \ + (echo "WARNING: re-sorting Porting/MANIFEST.dev"; \ + perl Porting/manisort --fix=Porting/MANIFEST.dev) manicheck: FORCE perl Porting/manicheck diff --git a/Porting/MANIFEST.dev b/Porting/MANIFEST.dev new file mode 100644 index 000000000000..47797ac404e2 --- /dev/null +++ b/Porting/MANIFEST.dev @@ -0,0 +1,84 @@ +.git_patch Format used by make_patchnum.pl +.gitattributes See: git --help gitattributes +.github/ISSUE_TEMPLATE/01-perlbug-core.md +.github/ISSUE_TEMPLATE/02-perlbug-docs.md +.github/ISSUE_TEMPLATE/config.yml +.github/workflows/detect-conflicts.yml +.github/workflows/irc-notifications.yaml +.github/workflows/testsuite.yml +.gitignore Generic .gitignore rules. See: git --help gitignore +.mailmap Map canonical name/email to those in commits +.travis.yml continuous integration on github (where enabled) +cpan/.gitignore Generic .gitignore for the cpan/ tree +cpan/Compress-Raw-Bzip2/.gitignore .gitignore rules for the Compress-Raw-Bzip2 cpan distribution +cpan/Compress-Raw-Zlib/.gitignore .gitignore rules for the Compress-Raw-Zlib cpan distribution +cpan/DB_File/.gitignore .gitignore rules for the DB_File cpan distribution +cpan/Digest-MD5/.gitignore .gitignore rules for the Digest-MD5 cpan distribution +cpan/Digest-SHA/.gitignore .gitignore rules for the Digest-SHA cpan distribution +cpan/Encode/.gitignore .gitignore rules for the Encode cpan distribution +cpan/IO-Compress/.gitignore .gitignore rules for the IO-Compress cpan distribution +cpan/IPC-SysV/.gitignore .gitignore rules for the IPC-SysV cpan distribution +cpan/libnet/.gitignore .gitignore rules for the libnet cpan distribution +cpan/perlfaq/.gitignore .gitignore rules for the perlfaq cpan distribution +cpan/Pod-Checker/.gitignore .gitignore rules for the Pod-Checker cpan distribution +cpan/Pod-Perldoc/.gitignore .gitignore rules for the Pod-Perldoc cpan distribution +cpan/Pod-Usage/.gitignore .gitignore rules for the Pod-Usage cpan distribution +cpan/podlators/.gitignore .gitignore rules for the podlators cpan distribution +cpan/Scalar-List-Utils/.gitignore .gitignore rules for the Scalar-List-Utils cpan distribution +cpan/Socket/.gitignore .gitignore rules for the Socket cpan distribution +cpan/Sys-Syslog/.gitignore .gitignore rules for the Sys-Syslog cpan distribution +cpan/Unicode-Collate/.gitignore .gitignore rules for the Unicode-Collate cpan distribution +cpan/Win32/.gitignore .gitignore rules for the Win32 cpan distribution +cpan/Win32API-File/.gitignore .gitignore rules for the Win32API-File cpan distribution +dist/.gitignore Generic .gitignore for the dist/ tree +dist/base/.gitignore .gitignore rules for the base distribution +dist/Carp/.gitignore .gitignore rules for the Carp distribution +dist/Devel-PPPort/.gitignore .gitignore rules for the Devel-PPPort distribution +dist/ExtUtils-CBuilder/.gitignore .gitignore rules for the ExtUtils-CBuilder distribution +dist/IO/.gitignore .gitignore rules for the IO distribution +dist/lib/.gitignore .gitignore rules for the lib distribution +dist/Module-CoreList/.gitignore .gitignore rules for the Module-CoreList distribution +dist/PathTools/.gitignore .gitignore rules for the PathTools distribution +dist/Safe/.gitignore .gitignore rules for the Safe distribution +dist/Search-Dict/.gitignore .gitignore rules for the Search-Dict distribution +dist/Storable/.gitignore .gitignore rules for the Storable distribution +dist/Time-HiRes/.gitignore .gitignore rules for the Time-HiRes distribution +dist/Unicode-Normalize/.gitignore .gitignore rules for the Unicode-Normalize distribution +dist/XSLoader/.gitignore .gitignore rules for the XSLoader distribution +ext/.gitignore Generic .gitignore for the ext/ tree +ext/Amiga-ARexx/.gitignore .gitignore rules for the Amiga-ARexx extension +ext/Amiga-Exec/.gitignore .gitignore rules for the Amiga-Exec extension +ext/B/.gitignore .gitignore rules for the B extension +ext/DynaLoader/.gitignore .gitignore rules for the DynaLoader extension +ext/Errno/.gitignore .gitignore rules for the Errno extension +ext/Fcntl/.gitignore .gitignore rules for the Fcntl extension +ext/File-Glob/.gitignore .gitignore rules for the File-Glob extension +ext/GDBM_File/.gitignore .gitignore rules for the GDBM_File extension +ext/Hash-Util/.gitignore .gitignore rules for the Hash-Util extension +ext/I18N-Langinfo/.gitignore .gitignore rules for the I18N-Langinfo extension +ext/NDBM_File/.gitignore .gitignore rules for the NDBM_File extension +ext/ODBM_File/.gitignore .gitignore rules for the ODBM_File extension +ext/Pod-Functions/.gitignore .gitignore rules for the Pod-Functions extension +ext/Pod-Html/.gitignore .gitignore rules for the Pod-Html extension +ext/POSIX/.gitignore .gitignore rules for the POSIX extension +ext/re/.gitignore .gitignore rules for the re extension +ext/SDBM_File/.gitignore .gitignore rules for the SDBM_File extension +ext/VMS-DCLsym/.gitignore .gitignore rules for the VMS-DCLsym extension +ext/VMS-Stdio/.gitignore .gitignore rules for the VMS-Stdio extension +ext/Win32CORE/.gitignore .gitignore rules for the Win32CORE extension +ext/XS-APItest/.gitignore .gitignore rules for the XS-APItest extension +ext/XS-Typemap/.gitignore .gitignore rules for the XS-Typemap extension +lib/.gitignore Generic .gitignore for the lib/ tree +pod/.gitignore Generic .gitignore for the pod/ tree +Porting/bisect.pl A tool to make bisecting easy +Porting/bisect-example.sh Example script to use with git bisect run +Porting/bisect-runner.pl Tool to be called by git bisect run +Porting/checkAUTHORS.pl Check that the AUTHORS file is complete +Porting/git-deltatool Mark commits for perldelta in git notes +Porting/git-find-p4-change Find the change for a p4 change number +Porting/git-make-p4-refs Output git refs for each p4 change number, suitable for appending to .git/packed-refs +Porting/GitUtils.pm Generate the contents of a .patch file +Porting/MANIFEST.dev Porting files - all files in repo we do not ship +Porting/updateAUTHORS.pl Tool to automatically update AUTHORS and .mailmap from git log data +utils/.gitignore Generic .gitignore for the utils/ tree +win32/.gitignore Generic .gitignore for the win32/ tree diff --git a/Porting/README.pod b/Porting/README.pod index e011a5439a56..6a840bf03717 100644 --- a/Porting/README.pod +++ b/Porting/README.pod @@ -253,13 +253,21 @@ web page to use to generate the snapshot files. =head2 F -This script outputs a list of files in F which don't exist and a -list of files that exist and aren't in F. +This script outputs a list of files in F and F +which don't exist and a list of files that exist and aren't in +F or in F + +=head2 F + +This file lists all files that are not included in the F +file in the root of the repo. The union of the files it contains with +the files in C should be the same the list of file produced +by C from a git checkout. =head2 F This library provides functions used in checking and sorting the -F. The sort order is similar to +F and F files. The sort order is similar to dictionary sort order (alphabetical case insensitive) but where path components and extensions are sorted independently such that the following files would be sorted into the following order: @@ -314,6 +322,12 @@ distribution, provides functions useful during testing. Generate the sections of files listed in C<%Targets> from F. Mostly these are rules in Makefiles. +An example of what this tool does is to ensure that every podfile listed +in F is also listed in F with the same +description in F. If they differ in test mode it will +complain. To update the manifest entries run it from the command line +without the --test argument. + --verbose gives slightly more output --build-all tries to build everything --build-foo updates foo as follows @@ -418,4 +432,3 @@ leaks. Guide for Vote Administrators for running Steering Council elections. =cut - diff --git a/Porting/manicheck b/Porting/manicheck index d059328554a1..cfe2b20dcc6f 100644 --- a/Porting/manicheck +++ b/Porting/manicheck @@ -4,6 +4,9 @@ # a) files listed in MANIFEST which don't exist # b) files which exist but which aren't in MANIFEST +# this file should be refactored with t/porting/manifest.t and +# Porting/manifest_list.pm + use v5.14; use warnings; use File::Find; @@ -14,38 +17,47 @@ my $exitstatus; GetOptions('exitstatus!', \$exitstatus) or die "$0 [--exitstatus]"; -my %files; -my $missing = 0; my $bonus = 0; -open my $fh, '<', 'MANIFEST' or die "Can't read MANIFEST: $!\n"; -for my $line (<$fh>) { - my ($file) = $line =~ /^(\S+)/; - ++$files{$file}; - next if -f $file; - ++$missing; - print "$file from MANIFEST doesn't exist\n"; +sub read_manifest { + my ($manifest_file) = @_; + open my $fh, '<', $manifest_file + or die "Can't read '$manifest_file': $!\n"; + my %files; + my $missing = 0; + for my $line (<$fh>) { + my ($file) = $line =~ /^(\S+)/; + if (!defined($file)) { + warn "No file specified in '$manifest_file' line $.\n"; + next; + } + $files{$file} = $.; + next if -f $file; + $missing++; + print "'$file' from '$manifest_file' at line $. doesn't exist\n"; + } + close $fh or die "Failed to close '$manifest_file': $!\n"; + return (\%files, $missing); } -close $fh; + +my ($manifest_files, $manifest_missing) = read_manifest("MANIFEST"); +my ($porting_files, $porting_missing) = read_manifest("Porting/MANIFEST.dev"); find { + no_chdir => 1, wanted => sub { - return if -d; - return if $_ eq '.mailmap'; - return if $_ eq '.gitignore'; - return if $_ eq '.gitattributes'; - return if $_ eq '.git_patch'; - - my $x = $File::Find::name =~ s!^\./!!r; - return if $x =~ /^\.git\b/; - return if $x =~ m{^\.github/}; - return if $files{$x}; + return if -d $_; + my $file = $_; + $file =~s!^\./!!; + return if $file=~m!^\.git/!; + return if $porting_files->{$file}; + return if $manifest_files->{$file}; ++$bonus; - print "$x\t\tnot in MANIFEST\n"; + print "$file\t\tnot in MANIFEST and not in Porting/MANIFEST.dev\n"; }, }, "."; -my $problems = $missing + $bonus; +my $problems = $manifest_missing + $porting_missing + $bonus; # We can't (meaningfully) exit with codes above 255, so we're going to have to # clamp them to some range whatever we do. So as we need the code anyway, use diff --git a/Porting/manifest_lib.pl b/Porting/manifest_lib.pl index 95d49be9cd31..c0337ed7b8cd 100644 --- a/Porting/manifest_lib.pl +++ b/Porting/manifest_lib.pl @@ -1,5 +1,4 @@ #!/usr/bin/perl - use strict; =head1 NAME @@ -21,6 +20,9 @@ =head2 C =cut +# this file should be refactored with t/porting/manifest.t and +# Porting/manicheck + # Try to get a sane sort. case insensitive, more or less # sorted such that path components are compared independently, # and so that lib/Foo/Bar sorts before lib/Foo-Alpha/Baz diff --git a/Porting/release_managers_guide.pod b/Porting/release_managers_guide.pod index f4b833f9086e..1b10c7fbb850 100644 --- a/Porting/release_managers_guide.pod +++ b/Porting/release_managers_guide.pod @@ -300,11 +300,12 @@ C to tell git the files will be gone. =item * -If the F file was changed in any of the -previous steps, run C which will sort the file, or you +If the F file or F was changed in any of the +previous steps, run C which will sort both files, or you can manually run: perl Porting/manisort --fix MANIFEST + perl Porting/manisort --fix Porting/MANIFEST.dev =item * @@ -1616,4 +1617,3 @@ L, plus a whole bunch of other sources, including private correspondence. =cut - diff --git a/t/porting/exec-bit.t b/t/porting/exec-bit.t index 3e80f8447977..a2002e48c441 100644 --- a/t/porting/exec-bit.t +++ b/t/porting/exec-bit.t @@ -38,6 +38,12 @@ plan('no_plan'); use ExtUtils::Manifest qw(maniread); +# Get MANIFEST +$ExtUtils::Manifest::Quiet = 1; +my @manifest = (keys(%{ maniread("../MANIFEST") }), + keys(%{ maniread("../Porting/MANIFEST.dev") })); +@manifest = sort @manifest; + # Copied from Porting/makerel - these will get +x in the tarball # XXX refactor? -- dagolden, 2010-07-23 my %exe_list = @@ -47,9 +53,6 @@ my %exe_list = map { split "\n" } do { local (@ARGV, $/) = '../Porting/exec-bit.txt'; <> }; -# Get MANIFEST -$ExtUtils::Manifest::Quiet = 1; -my @manifest = sort keys %{ maniread("../MANIFEST") }; # Check that +x files in repo get +x from makerel for my $f ( map { "../$_" } @manifest ) { diff --git a/t/porting/known_pod_issues.dat b/t/porting/known_pod_issues.dat index ac554f21d13c..4d1923e46f18 100644 --- a/t/porting/known_pod_issues.dat +++ b/t/porting/known_pod_issues.dat @@ -384,7 +384,7 @@ ext/pod-html/corpus/perlvar-copy.pod Verbatim line length including indents exce ext/vms-filespec/lib/vms/filespec.pm Verbatim line length including indents exceeds 78 by 1 install ? Should you be using F<...> or maybe L<...> instead of 1 install Verbatim line length including indents exceeds 78 by 2 -pod/perl.pod Verbatim line length including indents exceeds 78 by 5 +pod/perl.pod Verbatim line length including indents exceeds 78 by 6 pod/perlandroid.pod Verbatim line length including indents exceeds 78 by 3 pod/perlbook.pod Verbatim line length including indents exceeds 78 by 1 pod/perldebguts.pod Verbatim line length including indents exceeds 78 by 24 diff --git a/t/porting/manifest.t b/t/porting/manifest.t index 666c2d9204fa..3bf67df09a3d 100644 --- a/t/porting/manifest.t +++ b/t/porting/manifest.t @@ -1,122 +1,193 @@ #!./perl -w -# What does this test? -# This tests the well-formed-ness of the MANIFEST file. +# * What does this test? * # -# Why do we test this? -# TK +# This tests the well-formed-ness of the MANIFEST file +# and of the Porting/MANIFEST.dev file, and if git is present +# it will confirm that every file known to git ls-files is +# listed in one of the two MANIFEST files. # -# It's broken - how do I fix it? -# If MANIFEST is not sorted properly, you will get this error output: -# got ''MANIFEST' is NOT sorted properly -# # ' +# * Why do we test this? * +# +# We want to keep the files sorted according to our preferred +# sort order. See t/manifest_lib.pm for details. We also want +# to ensure that the file doesn't have any issues that would +# break any parsers that process it. +# +# * It's broken - how do I fix it? * +# +# If MANIFEST or Porting/MANIFEST.dev are not sorted properly, +# you will get this error output something like this: +# +# got ''MANIFEST' is NOT sorted properly' # # expected /(?^:is sorted properly)/ # -# To correct this, run either: +# To correct this, run this: +# +# make manisort +# +# which will output something like "WARNING: re-sorting MANIFEST" but which +# will also correct the problem. This will sort BOTH files with one simple +# command so it is the preferred option. +# +# Alternatively you can manually run what it does under the hood: # # ./perl -Ilib Porting/manisort -o MANIFEST MANIFEST +# ./perl -Ilib Porting/manisort -o Porting/MANIFEST.dev Porting/MANIFEST.dev # -# which will output "'MANIFEST' is NOT sorted properly" but which will -# correct the problem; or: +# which will output something like "'MANIFEST' is NOT sorted properly" but +# which will also correct the problem. # -# make manisort +# For other errors you may need to hand edit the file, for instance if a file +# is listed in both MANIFEST or Porting/MANIFEST.dev then you will need to +# decide which file should keep the listing. The rule of thumb is whether +# the file is used only for development purposes when there is a git repo +# available, in which case it should go in Porting/MANIFEST.dev, or if the +# file is required to build perl, in which case it should go in MANIFEST. +# If the file is missing outright you will need to add the file to one of the +# manifests, etc. +# +# Note the file format for MANIFEST files uses *tabs* as a separator, NOT +# spaces, and mixed tabs and spaces as a separator will trigger a test +# failure. Make sure the separator does not contain spaces. You may add a +# description for each file after the tabs, but it is not required. If you +# omit the description then you should trim trailing spaces from the line. +# The description itself may contain spaces however. # -# which will output "WARNING: re-sorting MANIFEST" but which will also -# correct the problem. use Config; BEGIN { - @INC = '..' if -f '../TestInit.pm'; + if (-f '../TestInit.pm') { + @INC = '..'; + } elsif (-f './TestInit.pm') { + @INC = '.'; + } } -use TestInit qw(T); # T is chdir to the top level +use TestInit qw(T); # T is chdir to the top level require './t/test.pl'; +use strict; skip_all("Cross-compiling, the entire source might not be available") if $Config{usecrosscompile}; - plan('no_plan'); -my $manifest = 'MANIFEST'; - -open my $m, '<', $manifest or die "Can't open '$manifest': $!"; -my @files; -# Test that MANIFEST uses tabs - not spaces - after the name of the file. -while (<$m>) { - chomp; - unless( /\s/ ) { - push @files, $_; - # no need for further tests on lines without whitespace (i.e., filename only) - next; - } - my ($file, $separator) = /^(\S+)(\s+)/; - push @files, $file; - - isnt($file, undef, "Line $. doesn't start with a blank") or next; - ok(-f $file, "File $file exists"); - if ($separator !~ tr/\t//c) { - # It's all tabs - next; - } elsif ($separator !~ tr/ //c) { - # It's all spaces - fail("Spaces in entry for $file in MANIFEST at line $."); - } elsif ($separator =~ tr/\t//) { - fail("Mixed tabs and spaces in entry for $file in MANIFEST at line $."); - } else { - fail("Odd whitespace in entry for $file in MANIFEST at line $."); +# this script should be refactored with Porting/manifest_lib.pm and +# Porting/manicheck + +sub read_manifest { + my ($manifest) = @_; + + open my $m, '<', $manifest or die "Can't open '$manifest': $!"; + my @files_array; + my %files_hash; + + # Test that MANIFEST uses tabs - not spaces - after the name of the file. + while (defined(my $input_line = <$m>)) { + chomp($input_line); + my $file_and_line = "'$manifest' at line $."; + + my ($file, $sep, $descr) = $input_line =~ m/^(\S+)(\s+)?(\S+.*)?\z/; + + isnt($file, undef, "Line does not start with whitespace in $file_and_line") + or next; + + ok(-f $file, "File '$file' exists in $file_and_line"); + + if (my $prev_line = $files_hash{$file}) { + fail("File '$file' is not duplicated in $file_and_line # previous at line $prev_line"); + } + + push @files_array, $file unless $files_hash{$file}; + $files_hash{$file} = $.; + + next unless defined $sep; + + $sep =~ s/\t/\\t/g; + + ok($sep !~ /\s/, "Separator is all tabs in $file_and_line") + or diag("Separator is '$sep'"); + + ok(defined($descr), "Line with separator also has description in $file_and_line"); + } + close $m or die "Failed to close '$manifest': $!"; + return (\@files_array, \%files_hash); } -close $m or die $!; +my $manifest_file = "MANIFEST"; +my $porting_file = "Porting/MANIFEST.dev"; +my ($manifest_files, $manifest_hash) = read_manifest("MANIFEST"); +my ($porting_files, $porting_hash) = read_manifest("Porting/MANIFEST.dev"); + +foreach my $file (@$manifest_files) { + if ($porting_hash->{$file}) { + fail("File '$file' is not listed in both manifests"); + _diag("# File '$file' is listed in '$manifest_file' at line $manifest_hash->{$file} " . + "and in '$porting_file' at line $porting_hash->{$file}"); + } +} # Test that MANIFEST is properly sorted SKIP: { - skip("Sorting order is different under EBCDIC", 1) if $::IS_EBCDIC || $::IS_EBCDIC; - skip("'Porting/manisort' not found", 1) if (! -f 'Porting/manisort'); - - my $result = runperl('progfile' => 'Porting/manisort', - 'args' => [ '-c', $manifest ], + my @files = ($manifest_file, $porting_file); + skip("Sorting order is different under EBCDIC", 0+@files) + if $::IS_EBCDIC || $::IS_EBCDIC; + skip("'Porting/manisort' not found", 0+@files) + if (! -f 'Porting/manisort'); + + for my $file ( @files ) { + my $result = runperl( + 'progfile' => 'Porting/manisort', + 'args' => [ $file ], 'stderr' => 1, 'nolib' => 1 ); - - like($result, qr/is sorted properly/, 'MANIFEST sorted properly'); + chomp $result; + like($result, qr/is sorted properly/, + "'$file' sorted properly"); + } } SKIP: { - find_git_or_skip(6); - my %seen; # De-dup ls-files output (can appear more than once) - my @repo= grep { - chomp(); - !m{\.git_patch$} && - !m{\.gitattributes$} && - !m{\.gitignore$} && - !m{\.mailmap$} && - !m{^\.github/} && - -e $_ && - !$seen{$_}++ - } `git ls-files`; - skip("git ls-files didnt work",3) - if !@repo; - is( 0+@repo, 0+@files, "git ls-files gives the same number of files as MANIFEST lists"); - my %repo; - ++$repo{$_} for @repo; - my %mani; - ++$mani{$_} for @files; - is( 0+keys %mani, 0+@files, "no duplicate files in MANIFEST") - or diag(join("\n ", "Duplicates:",grep $mani{$_} > 1, keys %mani)); - delete $mani{$_} for @repo; - delete $repo{$_} for @files; - my @not_in_mani= keys %repo; - my @still_in_mani= keys %mani; - - is( 0+@not_in_mani, 0, "Nothing added to the repo that isn't in MANIFEST"); - is( "not in MANIFEST: @not_in_mani", "not in MANIFEST: ", - "Nothing added to the repo that isn't in MANIFEST"); - is( 0+@still_in_mani, 0, "Nothing in the MANIFEST that isn't tracked by git"); - is( "should not be in MANIFEST: @still_in_mani", "should not be in MANIFEST: ", - "Nothing in the MANIFEST that isn't tracked by git"); + find_git_or_skip(5); + my %repo_seen; # De-dup ls-files output (can appear more than once) + my @unlisted; + foreach my $file (`git ls-files`) { + chomp($file); + next if !-e($file) + or $repo_seen{$file}++; + if (!$porting_hash->{$file} and !$manifest_hash->{$file}) { + push @unlisted, $file; + } + } + skip("git ls-files didnt work (this shouldn't happen)",5) + unless keys %repo_seen; + is("Unlisted: @unlisted", "Unlisted: ", + "All files are listed in either '$manifest_file' or '$porting_file'"); + + foreach my $file (keys %repo_seen) { + delete $porting_hash->{$file}; + delete $manifest_hash->{$file}; + } + my @still_in_porting = sort keys %$porting_hash; + my @still_in_manifest = sort keys %$manifest_hash; + + is("Git does not know file: @still_in_porting", + "Git does not know file: ", + "Git knows about all files in '$porting_file'"); + is("Git does not know file: @still_in_manifest", + "Git does not know file: ", + "Git knows about all files in '$manifest_file'"); + is(0+keys(%repo_seen),@$manifest_files+@$porting_files, + "git ls-files has the same count of files as our manifests"); + + delete $repo_seen{$_} for @$manifest_files, @$porting_files; + my @still_in_repo_seen = sort keys %repo_seen; + is("Not listed in either manifest: @still_in_repo_seen", + "Not listed in either manifest: ", + "All files from git ls-files are in one of our manifests"); } # EOF diff --git a/t/porting/readme.t b/t/porting/readme.t index 1d79d2caed7a..088a6fd9e19e 100644 --- a/t/porting/readme.t +++ b/t/porting/readme.t @@ -10,14 +10,15 @@ BEGIN { use TestInit qw(T); # T is chdir to the top level use strict; use warnings; +use ExtUtils::Manifest qw(maniread); require './t/test.pl'; -my @porting_files; -open my $man, "MANIFEST" or die "Can't open MANIFEST: $!"; -while(<$man>) { - /^Porting\// and s/[\t\n].*//s, push @porting_files, $_; -} -close $man or die "Can't close MANIFEST: $!"; +# Get MANIFEST +$ExtUtils::Manifest::Quiet = 1; +my @manifest = (keys(%{ maniread("MANIFEST") }), + keys(%{ maniread("Porting/MANIFEST.dev") })); +my @porting_files = grep { /^Porting/ } sort @manifest; + # It seems that dying here is nicer than having several dozen failing tests # later. But that assumes one will see the message from die. die "Can't get contents of Porting/ directory.\n" unless @porting_files > 1; From 5cd4d89bc1af546b6cb52b318a1b01cbef8934f2 Mon Sep 17 00:00:00 2001 From: Yves Orton Date: Fri, 11 Mar 2022 06:36:00 +0100 Subject: [PATCH 07/13] Teach Porting/Maintainers.pm about Porting/MANIFEST.dev Patch best viewed with -w --- Porting/Maintainers.pm | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/Porting/Maintainers.pm b/Porting/Maintainers.pm index 5ffcfb28c8fc..eebb92859b7f 100644 --- a/Porting/Maintainers.pm +++ b/Porting/Maintainers.pm @@ -21,7 +21,7 @@ our @EXPORT_OK = qw(%Modules %Maintainers show_results process_options files_to_modules finish_tap_output reload_manifest); -our $VERSION = 0.14; +our $VERSION = 0.15; require Exporter; @@ -35,23 +35,24 @@ my %MANIFEST; sub reload_manifest { %MANIFEST = (); - my $manifest_path = 'MANIFEST'; - if (! -e $manifest_path) { - $manifest_path = "../MANIFEST"; - } - - if (open(my $manfh, '<', $manifest_path )) { - while (<$manfh>) { - if (/^(\S+)/) { - $MANIFEST{$1}++; - } - else { - warn "MANIFEST:$.: malformed line: $_\n"; - } - } - close $manfh; - } else { - die "$0: Failed to open MANIFEST for reading: $!\n"; + foreach my $manifest_path ('MANIFEST','Porting/MANIFEST.dev') { + if (! -e $manifest_path) { + $manifest_path = "../MANIFEST"; + } + + if (open(my $manfh, '<', $manifest_path )) { + while (<$manfh>) { + if (/^(\S+)/) { + $MANIFEST{$1}++; + } + else { + warn "MANIFEST:$.: malformed line: $_\n"; + } + } + close $manfh; + } else { + die "$0: Failed to open MANIFEST for reading: $!\n"; + } } } @@ -355,7 +356,8 @@ sub duplicated_maintainers { sub warn_maintainer { my $name = shift; - ok($files{$name}, "$name has a maintainer (see Porting/Maintainers.pl)"); + ok($name=~/\.gitignore\z/ or $files{$name}, + "$name has a maintainer (see Porting/Maintainers.pl)"); } sub missing_maintainers { @@ -380,4 +382,3 @@ sub finish_tap_output { } 1; - From 3c1d8e620193879ec02a31e8165d198291555828 Mon Sep 17 00:00:00 2001 From: Yves Orton Date: Fri, 11 Mar 2022 06:36:20 +0100 Subject: [PATCH 08/13] Teach Porting/check83.pl about Porting/MANIFEST.dev Patch best viewed with -w --- Porting/check83.pl | 51 +++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/Porting/check83.pl b/Porting/check83.pl index fbe565558985..d69bd36e5f78 100755 --- a/Porting/check83.pl +++ b/Porting/check83.pl @@ -44,32 +44,33 @@ sub eight_dot_three { } my %dir; - -if (open(MANIFEST, '<', 'MANIFEST')) { - while () { - chomp; - s/\s.+//; - unless (-f) { - print "missing: $_\n"; - next; - } - if (tr/././ > 1) { - print "more than one dot: $_\n"; - next; - } - if ((my $slashes = $_ =~ tr|\/|\/|) > 7) { - print "more than eight levels deep: $_\n"; - next; - } - while (m!/|\z!g) { - my ($dir, $edt) = eight_dot_three("$`"); - next unless defined $dir; - ($dir, $edt) = map { lc } ($dir, $edt); - push @{$dir{$dir}->{$edt}}, $_; - } +foreach my $manifest_file ('MANIFEST', 'Porting/MANIFEST.dev') { + if (open(MANIFEST, '<', $manifest_file)) { + while () { + chomp; + s/\s.+//; + unless (-f) { + print "missing: $_\n"; + next; + } + if (tr/././ > 1) { + print "more than one dot: $_\n"; + next; + } + if ((my $slashes = $_ =~ tr|\/|\/|) > 7) { + print "more than eight levels deep: $_\n"; + next; + } + while (m!/|\z!g) { + my ($dir, $edt) = eight_dot_three("$`"); + next unless defined $dir; + ($dir, $edt) = map { lc } ($dir, $edt); + push @{$dir{$dir}->{$edt}}, $_; + } + } + } else { + die "$0: $manifest_file: $!\n"; } -} else { - die "$0: MANIFEST: $!\n"; } for my $dir (sort keys %dir) { From 2db617226bdc2c36f9a1c5a6238837379dff739c Mon Sep 17 00:00:00 2001 From: Yves Orton Date: Fri, 11 Mar 2022 06:36:39 +0100 Subject: [PATCH 09/13] Teach Porting/checkcfguse.pl about Porting/MANIFEST.dev Patch best viewed with -w --- Porting/checkcfguse.pl | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/Porting/checkcfguse.pl b/Porting/checkcfguse.pl index 6dea4a84c6fe..d1cfc73a03fc 100755 --- a/Porting/checkcfguse.pl +++ b/Porting/checkcfguse.pl @@ -69,25 +69,33 @@ my $SYM = join("|", sort { length($b) <=> length($a) || $a cmp $b } keys %SYM); -open(my $mani, '<', "MANIFEST") or die "$0: Failed to open MANIFEST\n"; - my %found; -while (<$mani>) { - if (/^(\S+)\s+/) { - my $fn = $1; - # Skip matches from the config files themselves, - # from metaconfig generated files that refer to - # the config symbols, and from pods. - next if $fn =~ m{^(?:config_h.SH|Configure|configure\.com|Porting/(?:config|Glossary)|(?:plan9|win32)/(?:config|(?:GNU)?[Mm]akefile)|uconfig)|\.pod$}; - open my $fh, '<', $fn or die qq[$0: Failed to open $fn: $!]; - while (<$fh>) { - while (/\b($SYM)\b/go) { - $found{$1}{$fn}++; +foreach my $manifest_file ('MANIFEST', 'Porting/MANIFEST.dev') { + open(my $mani, '<', $manifest_file) + or die "$0: Failed to open '$manifest_file'\n"; + + while (<$mani>) { + if (/^(\S+)\s+/) { + my $fn = $1; + # Skip matches from the config files themselves, + # from metaconfig generated files that refer to + # the config symbols, and from pods. + next if $fn =~ m{^(?:config_h\.SH + |Configure + |configure\.com + |Porting/(?:config|Glossary) + |(?:plan9|win32)/(?:config|(?:GNU)?[Mm]akefile) + |uconfig) + |\.pod$}x; + open my $fh, '<', $fn or die qq[$0: Failed to open $fn: $!]; + while (<$fh>) { + while (/\b($SYM)\b/go) { + $found{$1}{$fn}++; + } } } } } - for my $sym (sort keys %SYM) { if (exists $found{$sym}) { my @found = keys %{$found{$sym}}; From 5a5eccb3d64f81e29f38bd6277bf6fe581c2b5b9 Mon Sep 17 00:00:00 2001 From: Yves Orton Date: Fri, 11 Mar 2022 06:36:55 +0100 Subject: [PATCH 10/13] Teach t/TEST about Porting/MANIFEST.dev Patch best viewed with -w --- t/TEST | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/t/TEST b/t/TEST index 72c865d4ce60..974da11c1fed 100755 --- a/t/TEST +++ b/t/TEST @@ -402,8 +402,12 @@ sub _tests_from_manifest { } my @results; - my $mani = '../MANIFEST'; - if (open(MANI, $mani)) { + foreach my $manifest_file ('../MANIFEST','../Porting/MANIFEST.dev') { + if (!open(MANI,$manifest_file)) { + warn "$0: cannot open '$manifest_file': $!\n" + if $manifest_file!~/Porting/ or -e $manifest_file; + next; + } while () { if (m!^((?:cpan|dist|ext)/(\S+)/+(?:[^/\s]+\.t|test\.pl)|lib/\S+?(?:\.t|test\.pl))\s!) { my $t = $1; @@ -458,9 +462,8 @@ sub _tests_from_manifest { } } close MANI; - } else { - warn "$0: cannot open $mani: $!\n"; } + return @results; } From ca78d0cbef0228f2933845ba546f01dce1624e13 Mon Sep 17 00:00:00 2001 From: Yves Orton Date: Fri, 11 Mar 2022 06:37:16 +0100 Subject: [PATCH 11/13] Teach t/porting/filenames.t about Porting/MANIFEST.dev Patch best viewed with -w --- t/porting/filenames.t | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/t/porting/filenames.t b/t/porting/filenames.t index b65ab8e2c9e1..b76215b6f7fb 100644 --- a/t/porting/filenames.t +++ b/t/porting/filenames.t @@ -31,17 +31,13 @@ use File::Basename; require './test.pl'; -my $manifest = '../MANIFEST'; +use ExtUtils::Manifest qw(maniread); -open my $m, '<', $manifest or die "Can't open '$manifest': $!"; -my @files; -while (<$m>) { - chomp; - my($path) = split /\t+/; - push @files, $path; - -} -close $m or die $!; +# Get MANIFEST +$ExtUtils::Manifest::Quiet = 1; +my @files = (keys(%{ maniread("../MANIFEST") }), + keys(%{ maniread("../Porting/MANIFEST.dev") })); +@files = sort @files; plan(scalar @files); @@ -49,6 +45,7 @@ PATHNAME: for my $pathname (@files) { my @path_components = split('/',$pathname); my $filename = pop @path_components; for my $component (@path_components) { + next if $component eq ".github"; if ($component =~ /\./) { fail("$pathname has directory components containing '.'"); next PATHNAME; From 3cd79ce5279d1b785ba255b06a121d4141e98973 Mon Sep 17 00:00:00 2001 From: Yves Orton Date: Fri, 11 Mar 2022 06:37:30 +0100 Subject: [PATCH 12/13] Teach t/porting/podcheck.t about Porting/MANIFEST.dev Patch best viewed with -w --- t/porting/podcheck.t | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/t/porting/podcheck.t b/t/porting/podcheck.t index 22abfba8c0d7..7e2459817983 100644 --- a/t/porting/podcheck.t +++ b/t/porting/podcheck.t @@ -358,6 +358,8 @@ my $original_dir = File::Spec->rel2abs(File::Spec->curdir); my $data_dir = File::Spec->catdir($original_dir, 'porting'); my $known_issues = File::Spec->catfile($data_dir, 'known_pod_issues.dat'); my $MANIFEST = File::Spec->catfile(File::Spec->updir($original_dir), 'MANIFEST'); +my $MANIFEST_DEV = File::Spec->catfile(File::Spec->updir($original_dir), + 'Porting/MANIFEST.dev'); my $copy_fh; my $MAX_LINE_LENGTH = 78; # 78 columns @@ -475,21 +477,22 @@ my $C_path_re = qr{ ^ # for .PL files and get their full path names, so we can exclude each such # file explicitly. This works because other porting tests prohibit having two # files with the same names except for case. -open my $manifest_fh, '<:bytes', $MANIFEST or die "Can't open $MANIFEST"; -while (<$manifest_fh>) { - - # While we have MANIFEST open, on VMS platforms, look for files that match - # the magic VMS file names that have to be handled specially. Add these - # to the list of them. - if ($^O eq 'VMS' && / ^ ( [^\t]* $vms_re ) \t /x) { - $special_vms_files{$1} = 1; - } - if (/ ^ ( [^\t]* \. PL ) \t /x) { - $excluded_files{canonicalize($1)} = 1; +foreach my $manifest_file ($MANIFEST, $MANIFEST_DEV) { + open my $manifest_fh, '<:bytes', $manifest_file or die "Can't open $manifest_file"; + while (<$manifest_fh>) { + + # While we have MANIFEST open, on VMS platforms, look for files that match + # the magic VMS file names that have to be handled specially. Add these + # to the list of them. + if ($^O eq 'VMS' && m/ ^ ( [^\t]* $vms_re ) \t /x) { + $special_vms_files{$1} = 1; + } + if (m/ ^ ( [^\t]* \. PL ) \t /x) { + $excluded_files{canonicalize($1)} = 1; + } } + close $manifest_fh, or die "Can't close $manifest_file"; } -close $manifest_fh, or die "Can't close $MANIFEST"; - # Pod::Checker messages to suppress my @suppressed_messages = ( From ff9e589c1ed06a24bbb645ff125f853b255b986f Mon Sep 17 00:00:00 2001 From: Yves Orton Date: Fri, 11 Mar 2022 06:37:51 +0100 Subject: [PATCH 13/13] Teach t/porting/utils.t about Porting/MANIFEST.dev Patch best viewed with -w --- t/porting/utils.t | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/t/porting/utils.t b/t/porting/utils.t index 92eafbd3b9a2..5212d4d96e9a 100644 --- a/t/porting/utils.t +++ b/t/porting/utils.t @@ -33,13 +33,15 @@ find_git_or_skip('all'); my @maybe; -open my $fh, '<', 'MANIFEST' or die "Can't open MANIFEST: $!"; -while (<$fh>) { - push @maybe, $1 if m!^(Porting/\S+)!; +foreach my $manifest_file ('MANIFEST','Porting/MANIFEST.dev') { + open my $fh, '<', $manifest_file or die "Can't open '$manifest_file': $!"; + while (<$fh>) { + push @maybe, $1 if m!^(Porting/\S+)!; + } + close $fh or die "Failed to close '$manifest_file': $!"; } -close $fh or die $!; -open $fh, '<', 'utils.lst' or die "Can't open utils.lst: $!"; +open my $fh, '<', 'utils.lst' or die "Can't open utils.lst: $!"; while (<$fh>) { die unless m!^(\S+)!; push @maybe, $1;