#!/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 = ; 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+/ } ; close MAP or die "can't close \"$mapfile\": $!\n"; } open CVSMOD, "<$cvsmod" or die "can't open \"$cvsmod\": $!\n"; verbose "# looking for modulenames"; while () { 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 () { 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";