Sort MANIFEST using Perl
Jerry D. Hedden [Thu, 30 Jul 2009 00:31:30 +0000 (20:31 -0400)]
MANIFEST
Makefile.SH
Porting/manisort [new file with mode: 0644]
t/lib/manifest.t

index 8288a47..95e9ac6 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -3782,6 +3782,7 @@ Porting/makemeta  Create the top-level META.yml
 Porting/makerel                Release making utility
 Porting/make_snapshot.pl       Make a tgz snapshot of our tree with a .patch file in it
 Porting/manicheck      Check against MANIFEST
+Porting/manisort       Sort the MANIFEST
 Porting/podtidy                Reformat pod using Pod::Tidy
 Porting/pumpkin.pod    Guidelines and hints for Perl maintainers
 Porting/README.y2038   Perl notes for the 2038 fix
index 9f37133..17ffa71 100644 (file)
@@ -1123,8 +1123,8 @@ regen_all: regen
 .PHONY:        manisort manicheck
 
 manisort:      FORCE
-       LC_ALL=C sort -fdc MANIFEST || (echo "WARNING: re-sorting MANIFEST"; \
-               LC_ALL=C sort -fdo MANIFEST MANIFEST)
+       @perl Porting/manisort -q || (echo "WARNING: re-sorting MANIFEST"; \
+               perl Porting/manisort -q -o MANIFEST; sh -c true)
 
 manicheck:     FORCE
        perl Porting/manicheck
diff --git a/Porting/manisort b/Porting/manisort
new file mode 100644 (file)
index 0000000..1c02120
--- /dev/null
@@ -0,0 +1,64 @@
+#!/usr/bin/perl
+
+# Usage:  manisort [-q] [-o outfile] [filename]
+#
+# Without 'filename', looks for MANIFEST in the current dir.
+# With '-o outfile', writes the sorted MANIFEST to the specified file.
+# Prints the result of the sort to stderr.  '-q' silences this.
+# The exit code for the script is the sort result status
+# (i.e., 0 means already sorted properly, 1 means not properly sorted)
+
+use strict;
+use warnings;
+$| = 1;
+
+# Get command line options
+use Getopt::Long;
+my $outfile;
+my $check_only = 0;
+my $quiet = 0;
+GetOptions ('output=s' => \$outfile,
+            'check'    => \$check_only,
+            'quiet'    => \$quiet);
+
+my $file = (@ARGV) ? shift : 'MANIFEST';
+
+# Read in the MANIFEST file
+open(my $IN, '<', $file)
+    or die("Can't read '$file': $!");
+my @manifest = <$IN>;
+close($IN) or die($!);
+chomp(@manifest);
+
+# Sort by dictionary order (ignore-case and
+#   consider whitespace and alphanumeric only)
+my @sorted = sort {
+                      (my $aa = $a) =~ s/[^\s\da-zA-Z]//g;
+                      (my $bb = $b) =~ s/[^\s\da-zA-Z]//g;
+                      uc($aa) cmp uc($bb)
+                  } @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;
+}
+
+# Output sorted file
+if (defined($outfile)) {
+    open(my $OUT, '>', $outfile)
+        or die("Can't open output file '$outfile': $!");
+    print($OUT join("\n", @sorted), "\n");
+    close($OUT) or die($!);
+}
+
+# Report on sort results
+printf(STDERR "'$file' is%s sorted properly\n",
+            (($exit_code) ? ' NOT' : '')) if (! $quiet);
+
+# Exit with the sort results status
+exit($exit_code);
+
+# EOF
index bbf038a..377f666 100644 (file)
@@ -17,30 +17,13 @@ my $manifest = File::Spec->catfile(File::Spec->updir(), 'MANIFEST');
 
 open my $m, '<', $manifest or die "Can't open '$manifest': $!";
 
-my $last_seen = '';
-my $sorted = 1;
-
 # Test that MANIFEST uses tabs - not spaces - after the name of the file.
 while (<$m>) {
     chomp;
-
-    my ($file, $separator) = /^(\S+)(\s*)/;
+    next unless /\s/;   # Ignore lines without whitespace (i.e., filename only)
+    my ($file, $separator) = /^(\S+)(\s+)/;
     isnt($file, undef, "Line $. doesn't start with a blank") or next;
-
-    # Manifest order is "dictionary order, lowercase" for ASCII:
-    my $normalised = $_;
-    $normalised =~ tr/A-Z/a-z/;
-    $normalised =~ s/[^a-z0-9\s]//g;
-
-    if ($normalised le $last_seen) {
-       fail("Sort order broken by $file");
-       undef $sorted;
-    }
-    $last_seen = $normalised;
-
-    if (!$separator) {
-       # Ignore lines without whitespace (i.e., filename only)
-    } elsif ($separator !~ tr/\t//c) {
+    if ($separator !~ tr/\t//c) {
        # It's all tabs
        next;
     } elsif ($separator !~ tr/ //c) {
@@ -55,6 +38,15 @@ while (<$m>) {
 
 close $m or die $!;
 
-ok($sorted, 'MANIFEST properly sorted');
+# Test that MANIFEST is properly sorted
+SKIP: {
+    skip("'Porting/manisort' not found", 1) if (! -f '../Porting/manisort');
+
+    my $result = runperl('progfile' => '../Porting/manisort',
+                         'args'     => [ '-c', '../MANIFEST' ],
+                         'stderr'   => 1);
+
+    like($result, qr/is sorted properly/, 'MANIFEST sorted properly');
+}
 
 # EOF