mirror of
https://github.com/Perl/perl5.git
synced 2026-01-26 08:38:23 +00:00
Makefile.mk is redundant with GNUmakefile. See https://www.nntp.perl.org/group/perl.perl5.porters/2021/01/msg258848.html for more details. We planned to remove it shortly after the introduction of GNUmakefile but that slipped through the cracks for some reason: https://github.com/Perl/perl5/issues/14341
506 lines
17 KiB
Perl
Executable File
506 lines
17 KiB
Perl
Executable File
#!/opt/bin/perl
|
|
use strict;
|
|
use warnings;
|
|
|
|
use Cwd;
|
|
use Getopt::Std;
|
|
use File::Basename;
|
|
use FindBin;
|
|
|
|
my $Opts = {};
|
|
getopts( 'r:p:e:c:vudn', $Opts );
|
|
|
|
my $Cwd = cwd();
|
|
my $Verbose = 1;
|
|
my $ExcludeRe = $Opts->{e} ? qr/$Opts->{e}/i : undef;
|
|
my $Debug = $Opts->{v} || 0;
|
|
my $RunDiff = $Opts->{d} || 0;
|
|
my $PkgDir = $Opts->{p} || cwd();
|
|
my $Repo = $Opts->{r} or die "Need repository!\n". usage();
|
|
my $Changes = $Opts->{c} || 'Changes ChangeLog';
|
|
my $NoBranch = $Opts->{n} || 0;
|
|
|
|
### strip trailing slashes;
|
|
$Repo =~ s|/$||;
|
|
|
|
my $CPV = $Debug ? '-v' : '';
|
|
my $TestBin = 'ptardiff';
|
|
my $PkgDirRe = quotemeta( $PkgDir .'/' );
|
|
my $BranchName = basename( $PkgDir ) . '.' . $$;
|
|
my $OrigRepo = $Repo;
|
|
|
|
### establish working directory, either branch or full copy
|
|
if ( $NoBranch ) {
|
|
### create a copy of the repo directory
|
|
my $RepoCopy = "$Repo-$BranchName";
|
|
print "Copying repository to $RepoCopy ..." if $Verbose;
|
|
|
|
### --archive == -dPpR, but --archive is not portable, and neither
|
|
### is -d, so settling for -PpR
|
|
system( "cp -PpR -f $Repo $RepoCopy" )
|
|
and die "Copying master repo to $RepoCopy failed: $?";
|
|
|
|
### Going forward, use the copy in place of the original repo
|
|
$Repo = $RepoCopy;
|
|
|
|
print "done\n" if $Verbose;
|
|
}
|
|
else {
|
|
### create a git branch for the new package
|
|
print "Setting up a branch from blead called '$BranchName'..." if $Verbose;
|
|
chdir $Repo or die "Could not chdir to $Repo: $!";
|
|
unless ( -d '.git' ) {
|
|
die "\n$Repo is not a git repository\n";
|
|
}
|
|
my $status = `git status`;
|
|
unless ( $status =~ /nothing to commit/ims ) {
|
|
die "\nWorking directory not clean. Stopping.\n";
|
|
}
|
|
system( "git checkout -b $BranchName blead" )
|
|
and die "Could not create branch '$BranchName': $?";
|
|
|
|
print "done\n" if $Verbose;
|
|
}
|
|
|
|
### chdir there
|
|
chdir $PkgDir or die "Could not chdir to $PkgDir: $!";
|
|
|
|
### copy over all files under lib/
|
|
my @LibFiles;
|
|
{ print "Copying libdir..." if $Verbose;
|
|
die "Can't (yet) copy from a repository (found .git or .svn)"
|
|
if -d '.git' || -d '.svn';
|
|
die "No lib/ directory found\n" unless -d 'lib';
|
|
system( "cp -fR $CPV lib $Repo" ) and die "Copy of lib/ failed: $?";
|
|
|
|
@LibFiles = map { chomp; $_ }
|
|
### should we get rid of this file?
|
|
grep { $ExcludeRe && $_ =~ $ExcludeRe
|
|
? do { warn "Removing $Repo/$_\n";
|
|
system("rm $Repo/$_") and die "rm '$Repo/$_' failed: $?";
|
|
undef
|
|
}
|
|
: 1
|
|
} `find lib -type f`
|
|
or die "Could not detect library files\n";
|
|
|
|
print "done\n" if $Verbose;
|
|
}
|
|
|
|
### find the directory to put the t/ and bin/ files under
|
|
my $RelTopDir; # topdir from the repo root
|
|
my $TopDir; # full path to the top dir
|
|
my $ModName; # name of the module
|
|
my @ModFiles; # the .PMs in this package
|
|
{ print "Creating top level dir..." if $Verbose;
|
|
|
|
### make sure we get the shortest file, so we don't accidentally get
|
|
### a subdir
|
|
@ModFiles = sort { length($a) <=> length($b) }
|
|
map { chomp; $_ }
|
|
grep { $ExcludeRe ? $_ !~ $ExcludeRe : 1 }
|
|
grep /\.p(?:m|od)$/,
|
|
`find $PkgDir/lib -type f`
|
|
or die "No TopDir detected\n";
|
|
|
|
$RelTopDir = $ModFiles[0];
|
|
$RelTopDir =~ s/^$PkgDirRe//;
|
|
$RelTopDir =~ s/\.p(m|od)$//;
|
|
$TopDir = "$Repo/$RelTopDir";
|
|
|
|
### create the dir if it's not there yet
|
|
unless( -d $TopDir ) {
|
|
system( "mkdir $TopDir" ) and die "Creating dir $TopDir failed: $?";
|
|
}
|
|
|
|
### the module name, like Foo::Bar
|
|
### slice syntax not elegant, but we need to remove the
|
|
### leading 'lib/' entry
|
|
### stupid temp vars! stupid perl! it doesn't do @{..}[0..-1] :(
|
|
{ my @list = @{[split '/', $RelTopDir]};
|
|
$ModName = join '::', @list[1 .. $#list];
|
|
}
|
|
|
|
### the .pm files in this package
|
|
@ModFiles = map { s|^$PkgDirRe||; $_ } @ModFiles
|
|
or die "Could not detect modfiles\n";
|
|
|
|
print "done\n" if $Verbose;
|
|
}
|
|
|
|
my $TopDirRe = quotemeta( $TopDir . '/' );
|
|
|
|
### copy over t/ and bin/ directories to the $TopDir
|
|
my @TestFiles;
|
|
{ print "Copying t/* files to $TopDir..." if $Verbose;
|
|
|
|
-d 't'
|
|
? system( "cp -fR $CPV t $TopDir" ) && die "Copy of t/ failed: $?"
|
|
: warn "No t/ directory found\n";
|
|
|
|
@TestFiles = map { chomp; s|^$TopDirRe||; s|//|/|g; $_ }
|
|
### should we get rid of this file?
|
|
grep { $ExcludeRe && $_ =~ $ExcludeRe
|
|
? do { warn "Removing $_\n";
|
|
system("rm $TopDir/$_") and die "rm '$_' failed: $?";
|
|
undef
|
|
}
|
|
: 1
|
|
} `find t -type f`
|
|
or die "Could not detect testfiles\n";
|
|
|
|
print "done\n" if $Verbose;
|
|
}
|
|
|
|
my $BinDir;
|
|
my @BinFiles;
|
|
my $TopBinDir;
|
|
BIN: {
|
|
$BinDir = -d 'bin' ? 'bin' :
|
|
-d 'scripts' ? 'scripts' : undef ;
|
|
unless ($BinDir) {
|
|
print "No bin/ or scripts/ directory found\n" if $Verbose;
|
|
last BIN;
|
|
}
|
|
my $TopBinDir = "$TopDir/$BinDir/";
|
|
print "Copying $BinDir/* files to $TopBinDir..." if $Verbose;
|
|
|
|
my $CopyCmd = "cp -fR $CPV $BinDir $TopDir";
|
|
print "Running '$CopyCmd'..." if $Verbose;
|
|
|
|
system($CopyCmd) && die "Copy of $BinDir failed: $?";
|
|
|
|
@BinFiles = map { chomp; s|^$TopDirRe||; s|//|/|g; $_ }
|
|
### should we get rid of this file?
|
|
grep { $ExcludeRe && $_ =~ $ExcludeRe
|
|
? do { warn "Removing $_\n";
|
|
system("rm $TopDir/$_") and die "rm '$_' failed: $?";
|
|
undef
|
|
}
|
|
: 1
|
|
} `find $BinDir -type f`
|
|
or die "Could not detect binfiles\n";
|
|
|
|
print "done\n" if $Verbose;
|
|
}
|
|
|
|
### copy over change log
|
|
my @Changes;
|
|
foreach my $cl (split m/\s+/ => $Changes) {
|
|
-f $cl or next;
|
|
push @Changes, $cl;
|
|
print "Copying $cl files to $TopDir..." if $Verbose;
|
|
|
|
system( "cp -f $CPV $cl $TopDir" )
|
|
and die "Copy of $cl failed: $?";
|
|
}
|
|
|
|
|
|
### add files where they are required
|
|
my @NewFiles;
|
|
my @ChangedFiles;
|
|
{ for my $bin ( map { basename( $_ ) } @BinFiles ) {
|
|
print "Registering $bin with system files...\n";
|
|
|
|
### fix installperl, so these files get installed by other utils
|
|
### ./installperl: return if $name =~
|
|
### /^(?:cpan|instmodsh|prove|corelist|ptar|ptardiff)\z/;
|
|
{ my $file = 'installperl';
|
|
|
|
### not there already?
|
|
unless( `grep $TestBin $Repo/$file| grep $bin` ) {
|
|
print " Adding $bin to $file..." if $Verbose;
|
|
|
|
### double \\| required --> once for in this script, once
|
|
### for the cli
|
|
system("$^X -pi -e 's/($TestBin\\|)/$bin|\$1/' $Repo/$file")
|
|
and die "Could not add $bin to $file: $?";
|
|
print "done\n" if $Verbose;
|
|
push @ChangedFiles, $file;
|
|
} else {
|
|
print " $bin already mentioned in $file\n" if $Verbose;
|
|
}
|
|
}
|
|
|
|
### fix utils.lst, so the new tools are mentioned
|
|
{ my $file = 'utils.lst';
|
|
|
|
### not there already?
|
|
unless( `grep $bin $Repo/$file` ) {
|
|
print " Adding $bin to $file..." if $Verbose;
|
|
|
|
### double \\| required --> once for in this script, once
|
|
### for the cli
|
|
system("$^X -pi -e 's!($TestBin)!\$1\nutils/$bin!' $Repo/$file")
|
|
and die "Could not add $bin to $file: $?";
|
|
print "done\n" if $Verbose;
|
|
push @ChangedFiles, $file;
|
|
} else {
|
|
print " $bin already mentioned in $file\n" if $Verbose;
|
|
}
|
|
}
|
|
|
|
### make a $bin.PL file and fix it up
|
|
{ my $src = "utils/${TestBin}.PL";
|
|
my $file = "utils/${bin}.PL";
|
|
|
|
### not there already?
|
|
unless( -e "$Repo/$file" ) {
|
|
print " Creating $file..." if $Verbose;
|
|
|
|
### important part of the template looks like this
|
|
### (we'll need to change it):
|
|
# my $script = File::Spec->catfile(
|
|
# File::Spec->catdir(
|
|
# File::Spec->updir, qw[lib Archive Tar bin]
|
|
# ), "module-load.pl");
|
|
|
|
### copy another template file
|
|
system( "cp -f $Repo/$src $Repo/$file" )
|
|
and die "Could not create $file from $src: $?";
|
|
|
|
### change the 'updir' path
|
|
### make sure to escape the \[ character classes
|
|
my $updir = join ' ', (split('/', $RelTopDir), $BinDir);
|
|
system( "$^X -pi -e'".
|
|
's/^(.*?File::Spec->updir, qw\[).+?(\].*)$/'.
|
|
"\$1 $updir \$2/' $Repo/$file"
|
|
) and die "Could not fix updir for $bin in $file: $?";
|
|
|
|
|
|
### change the name of the file from $TestBin to $bin
|
|
system( "$^X -pi -e's/$TestBin/$bin/' $Repo/$file" )
|
|
and die "Could not update $file with '$bin' as name: $?";
|
|
|
|
print "done\n" if $Verbose;
|
|
|
|
} else {
|
|
print " $file already exists\n" if $Verbose;
|
|
}
|
|
|
|
### we've may just have created a new file, it will have to
|
|
### go into the manifest
|
|
push @NewFiles, $file;
|
|
}
|
|
|
|
### add an entry to utils/Makefile.PL for $bin
|
|
{ my $file = "utils/Makefile.PL";
|
|
|
|
### not there already?
|
|
unless( `grep $bin $Repo/$file` ) {
|
|
print " Adding $bin entries to $file..." if $Verbose;
|
|
|
|
### $bin appears on 4 lines in this file, so replace all 4
|
|
### first, pl =
|
|
system( "$^X -pi -e'/^pl\\s+=/ && s/(${TestBin}.PL)/".
|
|
"\$1 ${bin}.PL/' $Repo/$file"
|
|
) and die "Could not add $bin to the pl = entry: $?";
|
|
|
|
### next, plextract =
|
|
system( "$^X -pi -e'/^plextract\\s+=/ " .
|
|
"&& s/(${TestBin})/\$1 $bin/' $Repo/$file"
|
|
) and die "Could not add $bin to the plextract = entry: $?";
|
|
|
|
### third, plextractexe =
|
|
system( "$^X -pi -e'/^plextractexe\\s+=/ " .
|
|
"&& s!(\./${TestBin})!\$1 ./$bin!' $Repo/$file"
|
|
) and die "Could not add $bin to the plextractexe = entry: $?";
|
|
|
|
### last, the make directive $bin:
|
|
system( "$^X -pi -e'/^(${TestBin}:.+)/; \$x=\$1 or next;" .
|
|
"\$x =~ s/$TestBin/$bin/g;" . '$_.=$/.$x.$/;' .
|
|
"' $Repo/$file"
|
|
) and die "Could not add $bin as a make directive: $?";
|
|
|
|
push @ChangedFiles, $file;
|
|
print "done\n" if $Verbose;
|
|
} else {
|
|
print " $bin already added to $file\n" if $Verbose;
|
|
}
|
|
}
|
|
|
|
### add entries to win32/Makefile
|
|
### they contain the following lines:
|
|
# ./win32/makefile.mk: ..\utils\ptardiff \
|
|
# ./win32/makefile.mk: xsubpp instmodsh prove ptar ptardiff
|
|
for my $file ( qw[win32/Makefile] ) {
|
|
unless ( `grep $bin $Repo/$file` ) {
|
|
print " Adding $bin entries to $file..." if $Verbose;
|
|
|
|
system( "$^X -pi -e'/^(.+?utils.${TestBin}.+)/;".
|
|
'$x=$1 or next;' .
|
|
"\$x =~ s/$TestBin/$bin/g;" . '$_.=$x.$/;' .
|
|
"' $Repo/$file"
|
|
) and die "Could not add $bin to UTILS section in $file: $?\n";
|
|
|
|
system( "$^X -pi -e's/( $TestBin)/\$1 $bin/' $Repo/$file" )
|
|
and die "Could not add $bin to $file: $?\n";
|
|
|
|
push @ChangedFiles, $file;
|
|
print "done\n" if $Verbose;
|
|
} else {
|
|
print " $bin already added to $file\n" if $Verbose;
|
|
}
|
|
}
|
|
|
|
### we need some entries in a vms specific file as well..
|
|
### except, I don't understand how it works or what it does, and it
|
|
### looks all a bit odd... so lets just print a warning...
|
|
### the entries look something like this:
|
|
# ./vms/descrip_mms.template:utils4 = [.utils]enc2xs.com
|
|
# [.utils]piconv.com [.utils]cpan.com [.utils]prove.com
|
|
# [.utils]ptar.com [.utils]ptardiff.com [.utils]shasum.com
|
|
# ./vms/descrip_mms.template:[.utils]ptardiff.com : [.utils]ptardiff.PL
|
|
# $(ARCHDIR)Config.pm
|
|
{ my $file = 'vms/descrip_mms.template';
|
|
|
|
unless( `grep $bin $Repo/$file` ) {
|
|
print $/.$/;
|
|
print " WARNING! You should add entries like the following\n"
|
|
. " to $file (Using $TestBin as an example)\n"
|
|
. " Unfortunately I don't understand what these entries\n"
|
|
. " do, so I won't change them automatically:\n\n";
|
|
|
|
print `grep -nC1 $TestBin $Repo/$file`;
|
|
print $/.$/;
|
|
|
|
} else {
|
|
print " $bin already added to $file\n" if $Verbose;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
### update the manifest
|
|
{ my $file = $Repo . '/MANIFEST';
|
|
my @manifest;
|
|
{ open my $fh, '<', $file or die "Could not open $file: $!";
|
|
@manifest = <$fh>;
|
|
close $fh;
|
|
}
|
|
|
|
### fill it with files from our package
|
|
my %pkg_files;
|
|
for ( @ModFiles ) {
|
|
$pkg_files{$_} = "$_\t$ModName\n";
|
|
}
|
|
|
|
for ( @TestFiles ) {
|
|
$pkg_files{"$RelTopDir/$_"} = "$RelTopDir/$_\t$ModName tests\n"
|
|
}
|
|
|
|
for ( @BinFiles ) {
|
|
$pkg_files{"$RelTopDir/$_"} = "$RelTopDir/$_\tthe ".
|
|
basename($_) ." utility\n";
|
|
}
|
|
|
|
for ( @Changes ) {
|
|
$pkg_files{"$RelTopDir/$_"} = "$RelTopDir/$_\t$ModName change log\n";
|
|
}
|
|
|
|
for ( @NewFiles ) {
|
|
$pkg_files{$_} = "$_\tthe ".
|
|
do { m/(.+?)\.PL$/; basename($1) } .
|
|
" utility\n"
|
|
}
|
|
|
|
### remove all the files that are already in the manifest;
|
|
delete $pkg_files{ [split]->[0] } for @manifest;
|
|
|
|
print "Adding the following entries to the MANIFEST:\n" if $Verbose;
|
|
print "\t$_" for sort values %pkg_files;
|
|
print $/.$/;
|
|
|
|
push @manifest, values %pkg_files;
|
|
|
|
{ chmod 0644, $file;
|
|
open my $fh, '>', $file or die "Could not open $file for writing: $!";
|
|
#print $fh sort { lc $a cmp lc $b } @manifest;
|
|
### XXX stolen from pod/buildtoc:sub do_manifest
|
|
print $fh
|
|
map { $_->[0] }
|
|
sort { $a->[1] cmp $b->[1] || $a->[0] cmp $b->[0] }
|
|
map { my $f = lc $_; $f =~ s/[^a-z0-9\s]//g; [ $_, $f ] }
|
|
@manifest;
|
|
|
|
close $fh;
|
|
}
|
|
push @ChangedFiles, 'MANIFEST';
|
|
}
|
|
|
|
|
|
### would you like us to show you a diff?
|
|
if( $RunDiff ) {
|
|
if ( $NoBranch ) {
|
|
|
|
my $diff = $Repo; $diff =~ s/$$/patch/;
|
|
|
|
### weird RV ;(
|
|
my $master = basename( $OrigRepo );
|
|
my $repo = basename( $Repo );
|
|
my $chdir = dirname( $OrigRepo );
|
|
|
|
### the .patch file is added by an rsync from the APC
|
|
### but isn't actually in the p4 repo, so exclude it
|
|
my $cmd = "cd $chdir; diff -ruN --exclude=.patch $master $repo > $diff";
|
|
|
|
print "Running: '$cmd'\n";
|
|
|
|
print "Generating diff..." if $Verbose;
|
|
|
|
system( $cmd );
|
|
#and die "Could not write diff to '$diff': $?";
|
|
die "Could not write diff to '$diff'" unless -e $diff && -s _;
|
|
|
|
print "done\n" if $Verbose;
|
|
print "\nDiff can be applied with patch -p1 in $OrigRepo\n\n";
|
|
print " Diff written to: $diff\n\n" if $Verbose;
|
|
}
|
|
else {
|
|
my $diff = "$Repo/$BranchName"; $diff =~ s/$$/patch/;
|
|
my $cmd = "cd $Repo; git diff > $diff";
|
|
|
|
print "Running: '$cmd'\n";
|
|
|
|
print "Generating diff..." if $Verbose;
|
|
|
|
system( $cmd );
|
|
#and die "Could not write diff to '$diff': $?";
|
|
die "Could not write diff to '$diff'" unless -e $diff && -s _;
|
|
|
|
print "done\n" if $Verbose;
|
|
print " Diff written to: $diff\n\n" if $Verbose;
|
|
}
|
|
}
|
|
|
|
|
|
# add files to git index
|
|
unless ( $NoBranch ) {
|
|
chdir $Repo;
|
|
system( "git add $CPV $_" )
|
|
for ( @LibFiles, @NewFiles, @ChangedFiles,
|
|
map { "$RelTopDir/$_" } @TestFiles, @BinFiles, @Changes );
|
|
}
|
|
|
|
# return to original directory
|
|
chdir $Cwd;
|
|
|
|
sub usage {
|
|
my $me = basename($0);
|
|
return qq[
|
|
|
|
Usage: $me -r PERL_REPO_DIR [-p PACKAGE_DIR] [-v] [-d] [-e REGEX]
|
|
|
|
Options:
|
|
-r Path to perl-core git repository
|
|
-v Run verbosely
|
|
-c File containing changelog (default 'Changes' or 'ChangeLog')
|
|
-e Perl regex matching files that shouldn't be included
|
|
-d Create a diff as patch file
|
|
-p Path to the package to add. Defaults to cwd()
|
|
-n No branching; repository is not a git repo
|
|
|
|
\n];
|
|
|
|
}
|