#!/usr/bin/perl -w
use
5.006;
my
(
$diffs
,
$exclude_upstream
,
$tag_to_compare
,
$tap
);
unless
(GetOptions(
'diffs'
=> \
$diffs
,
'exclude|x'
=> \
$exclude_upstream
,
'tag=s'
=> \
$tag_to_compare
,
'tap'
=> \
$tap
,
) &&
@ARGV
== 0) {
die
"usage: $0 [ -d -x --tag TAG --tap]"
;
}
die
"$0: This does not look like a Perl directory\n"
unless
-f
"perl.h"
&& -d
"Porting"
;
if
(-d
".git"
|| (
exists
$ENV
{GIT_DIR} && -d
$ENV
{GIT_DIR})) {
}
else
{
my
$found
;
if
(-f
'.git'
) {
my
$commit
=
'8d063cd8450e59ea1c611a2f4f5a21059a2804f1'
;
my
$out
= `git rev-parse --verify --quiet
'$commit^{commit}'
`;
chomp
$out
;
if
(
$out
eq
$commit
) {
++
$found
;
}
}
die
"$0: This is a Perl directory but does not look like Git working directory\n"
unless
$found
;
}
my
$null
= devnull();
unless
(
defined
$tag_to_compare
) {
my
$check
=
'HEAD'
;
while
(1) {
$check
= `git describe --abbrev=0
$check
2>
$null
`;
chomp
$check
;
last
unless
$check
=~ /-RC/;
$check
.=
'~1'
;
}
$tag_to_compare
=
$check
;
}
unless
(
length
$tag_to_compare
) {
die
"$0: Git found, but no Git tags found\n"
unless
$tap
;
print
"1..0 # SKIP: Git found, but no Git tags found\n"
;
exit
0;
}
my
$tag_exists
= `git --
no
-pager tag -l
$tag_to_compare
2>
$null
`;
chomp
$tag_exists
;
unless
(
$tag_exists
eq
$tag_to_compare
) {
die
"$0: '$tag_to_compare' is not a known Git tag\n"
unless
$tap
;
print
"1..0 # SKIP: '$tag_to_compare' is not a known Git tag\n"
;
exit
0;
}
my
%upstream_files
;
if
(
$exclude_upstream
) {
unshift
@INC
,
'Porting'
;
for
my
$m
(
grep
{!
defined
$Maintainers::Modules
{
$_
}{UPSTREAM}
or
$Maintainers::Modules
{
$_
}{UPSTREAM} ne
'blead'
}
keys
%Maintainers::Modules
) {
$upstream_files
{
$_
} = 1
for
Maintainers::get_module_files(
$m
);
}
}
my
%skip
;
@skip
{
'cpan/Digest/t/lib/Digest/Dummy.pm'
,
'cpan/ExtUtils-Install/t/lib/MakeMaker/Test/Setup/BFD.pm'
,
'cpan/ExtUtils-MakeMaker/t/lib/MakeMaker/Test/Setup/BFD.pm'
,
'cpan/ExtUtils-MakeMaker/t/lib/MakeMaker/Test/Setup/XS.pm'
,
'cpan/IO-Compress/lib/File/GlobMapper.pm'
,
'cpan/Math-BigInt/t/Math/BigFloat/Subclass.pm'
,
'cpan/Math-BigInt/t/Math/BigInt/BareCalc.pm'
,
'cpan/Math-BigInt/t/Math/BigInt/Scalar.pm'
,
'cpan/Math-BigInt/t/Math/BigInt/Subclass.pm'
,
'cpan/Math-BigRat/t/Math/BigRat/Test.pm'
,
'cpan/Module-Load/t/to_load/LoadIt.pm'
,
'cpan/Module-Load/t/to_load/Must/Be/Loaded.pm'
,
'cpan/Module-Load-Conditional/t/test_lib/a/X.pm'
,
'cpan/Module-Load-Conditional/t/test_lib/b/X.pm'
,
'cpan/Module-Load-Conditional/t/to_load/Commented.pm'
,
'cpan/Module-Load-Conditional/t/to_load/HereDoc.pm'
,
'cpan/Module-Load-Conditional/t/to_load/InPod.pm'
,
'cpan/Module-Load-Conditional/t/to_load/LoadIt.pm'
,
'cpan/Module-Load-Conditional/t/to_load/MustBe/Loaded.pm'
,
'cpan/Module-Load-Conditional/t/to_load/NotMain.pm'
,
'cpan/Module-Load-Conditional/t/to_load/NotX.pm'
,
'cpan/Pod-Usage/t/inc/Pod/InputObjects.pm'
,
'cpan/Pod-Usage/t/inc/Pod/Parser.pm'
,
'cpan/Pod-Usage/t/inc/Pod/PlainText.pm'
,
'cpan/Pod-Usage/t/inc/Pod/Select.pm'
,
'cpan/podlators/t/lib/Test/Podlators.pm'
,
'cpan/podlators/t/lib/Test/RRA.pm'
,
'cpan/podlators/t/lib/Test/RRA/Config.pm'
,
'cpan/version/t/coretests.pm'
,
'dist/Attribute-Handlers/demo/MyClass.pm'
,
'dist/Exporter/lib/Exporter/Heavy.pm'
,
'dist/Module-CoreList/lib/Module/CoreList.pm'
,
'dist/Module-CoreList/lib/Module/CoreList/Utils.pm'
,
'lib/Carp/Heavy.pm'
,
'lib/Config.pm'
,
'win32/FindExt.pm'
,
} = ();
my
%skip_versions
= (
);
my
$skip_dirs
=
qr|^t/lib|
;
sub
pm_file_from_xs {
my
$xs
=
shift
;
foreach
my
$try
(
sub
{
return
shift
=~ s/\.xs\z//r;
},
sub
{
my
(
$path
) =
shift
=~ m!^(.*)/!;
my
(
$last
) =
$path
=~ m!([^-/]+)\z!;
return
"$path/$last"
;
},
sub
{
my
(
$path
) =
shift
=~ m!^(.*)/!;
my
(
$last
) =
$path
=~ m!([^/]+)\z!;
$last
=
'List-Util'
if
$last
eq
'Scalar-List-Utils'
;
$last
=~
tr
!-!/!;
return
"$path/lib/$last"
;
}) {
my
$base
=
$try
->(
$xs
);
return
"${base}_pm.PL"
if
-f
"${base}_pm.PL"
;
return
"${base}.pm"
if
-f
"${base}.pm"
;
}
die
"No idea which .pm file corresponds to '$xs', so aborting"
;
}
my
%module_diffs
;
foreach
(`git --
no
-pager diff --name-only
$tag_to_compare
--diff-filter=ACMRTUXB`) {
chomp
;
next
unless
m/^(.*)\//;
my
$this_dir
= $1;
next
if
$this_dir
=~
$skip_dirs
||
exists
$skip
{
$_
};
next
if
exists
$upstream_files
{
$_
};
if
(/\.pm\z/ || m|^lib/.*\.pl\z| || /_pm\.PL\z/) {
push
@{
$module_diffs
{
$_
}},
$_
;
}
elsif
(/\.xs\z/ && !/\bt\b/) {
push
@{
$module_diffs
{pm_file_from_xs(
$_
)}},
$_
;
}
}
unless
(
%module_diffs
) {
print
"1..1\nok 1 - No difference found\n"
if
$tap
;
exit
;
}
printf
"1..%d\n"
=>
scalar
keys
%module_diffs
if
$tap
;
print
"#\n# Comparing against $tag_to_compare ....\n#\n"
if
$tap
;
my
$count
;
my
$diff_cmd
=
"git --no-pager diff $tag_to_compare "
;
my
$q
= ($^O eq
'MSWin32'
|| $^O eq
'VMS'
) ?
'"'
: "'";
my
(
@diff
);
foreach
my
$pm_file
(
sort
keys
%module_diffs
) {
my
$pm_version
=
eval
{MM->parse_version(
$pm_file
)};
my
$orig_pm_content
= get_file_from_git(
$pm_file
,
$tag_to_compare
);
my
$orig_pm_version
=
eval
{MM->parse_version(\
$orig_pm_content
)};
++
$count
;
if
(!
defined
$orig_pm_version
||
$orig_pm_version
eq
'undef'
) {
print
"ok $count - SKIP Can't parse \$VERSION in $pm_file\n"
if
$tap
;
}
elsif
(!
defined
$pm_version
||
$pm_version
eq
'undef'
) {
my
$nok
=
"not ok $count - in $pm_file version was $orig_pm_version, now unparsable\n"
;
print
$nok
if
$tap
;
print
STDERR
"# $nok\n"
;
}
elsif
(
$pm_version
ne
$orig_pm_version
) {
print
"ok $count - $pm_file\n"
if
$tap
;
}
else
{
if
(
$tap
) {
print
"#\n# "
.
'-'
x 75 .
"\n"
.
"# Version number ($pm_version) unchanged since"
.
" $tag_to_compare, but contents have changed:\n#\n"
;
foreach
(
sort
@{
$module_diffs
{
$pm_file
}}) {
print
"# $_"
for
`
$diff_cmd
$q
$_
$q
`;
}
print
"# "
.
'-'
x 75 .
"\n"
;
if
(
exists
$skip_versions
{
$pm_file
}
and
grep
$pm_version
eq
$_
, @{
$skip_versions
{
$pm_file
}}) {
print
"ok $count - SKIP $pm_file version $pm_version\n"
;
}
else
{
my
$nok
=
"not ok $count - $pm_file version $pm_version\n"
;
print
$nok
;
print
STDERR
"# $nok"
;
}
}
else
{
push
@diff
, @{
$module_diffs
{
$pm_file
}};
print
"$pm_file version $pm_version\n"
;
}
}
}
sub
get_file_from_git {
my
(
$file
,
$tag
) =
@_
;
local
$/;
use
open
IN
=>
':raw'
;
return
scalar
`git --
no
-pager show
$tag
:
$file
2>
$null
`;
}
if
(
$diffs
) {
for
(
sort
@diff
) {
print
"\n"
;
system
"$diff_cmd $q$_$q"
;
}
}