#!/usr/bin/perl -w
use Data::Dumper;
use Getopt::Long;
my %DEPENDENCIES = ();
my %LOCATIONS = ();
my %depotmap = ();
my %MODNAMES = ();
my $files = "";
my @files = ();
my $mapfile = "";
my $module = 'BOGUS';
my $verbose = 0;
my $error_seen = 0;
$|=1;
sub usage {
my $cmd = $0;
$cmd =~ s|.*/||;
print <<_EOF_;
Usage: $cmd [ -f files -m mapfile -v ] cvs-modules
-h|--help print this message
-f|--files files a set of regexps to define files in the cvs modules
-m|--map mapfile use a module to depot mapping instead of a default one
-v|--verbose add comments to the output (option can be repeated)
_EOF_
exit $_[0];
}
Getopt::Long::Configure ("bundling");
GetOptions(
"h|help" => sub { usage(0) },
"f|files=s" => \$files,
"m|map=s" => \$mapfile,
"v|verbose+" => \$verbose,
) || usage(1);
my $cvsmod = shift || usage(1);
sub verbose {
my $level = @_ > 1 ? shift : 1;
print @_, "\n" if $level <= $verbose;
}
sub _add_path {
local $_ = shift;
if (exists($MODNAMES{$_})) {
verbose 2, "# adding MODULE $_ to $module";
push @{$DEPENDENCIES{$module}}, $_;
} else {
s|/$||;
my $isfile = 0;
my $depot = $depotmap{$module} || "//depot/$module";
if ($mapfile && !$depotmap{$module}) {
warn "No mapping for '$module' in '$mapfile'\n";
$error_seen = 1;
}
for my $re (@files) {
verbose 3, "# checking for file match against: $re";
$isfile = 1, last if /$re/;
}
if ($isfile) {
verbose 2, "# adding FILE $_ to $module";
$LOCATIONS{$module}->{"$depot/\@B@/" . $_ } = "/$_";
} else {
verbose 2, "# adding DIRECTORY $_ to $module";
$LOCATIONS{$module}->{"$depot/\@B@/" . $_ . "/..."} = "/$_/...";
}
}
}
if ($files) {
open FILES, "<$files" or die "can't open \"$files\": $!\n";
@files = <FILES>;
chomp @files;
close FILES or die "can't close \"$files\": $!\n";
}
if ($mapfile) {
open MAP, "<$mapfile" or die "can't open \"$mapfile\": $!\n";
%depotmap = map { /^#/ ? () : reverse split /\s+/ } <MAP>;
close MAP or die "can't close \"$mapfile\": $!\n";
}
open CVSMOD, "<$cvsmod" or die "can't open \"$cvsmod\": $!\n";
verbose "# looking for modulenames";
while (<CVSMOD>) {
chomp;
next if /^#/;
next if /^\s*$/;
s/\\\s*$//;
if (/^(\S+)/) {
verbose "# found module: $1";
$MODNAMES{$1} = 1;
}
}
verbose "# filling in module dependencies and locations";
seek(CVSMOD, 0, 0) or die "couldn't go back to the start of \"$cvsmod\": $!\n";
while (<CVSMOD>) {
chomp;
next if /^#/;
next if /^\s*$/;
s/\\\s*$//;
verbose 3, "# parsing line: $_";
# Look for new modules.
if (/^(\S+)/) {
verbose "# found module: $1";
$module = $1;
s/^(\S+)//;
}
# There may be spurious '-a' options. Delete them.
for my $path (m/'.*?'|".*?"|\S+/g) {
$path =~ s/^['"]|['"]$//g;
next if $path eq "-a";
next if $path eq "";
_add_path($path);
}
}
close CVSMOD or die "can't close \"$cvsmod\": $!\n";
if ($error_seen) {
die "An error occurred. See warning.\n"
}
$Data::Dumper::Indent = 1;
print Dumper \%DEPENDENCIES, \%LOCATIONS;
print "%P4::Modules::DEPENDENCIES = (%\$VAR1);\n";
print "%P4::Modules::LOCATIONS = (%\$VAR2);\n";
print "1;\n";