eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
& eval 'exec perl -w -S $0 $argv:q'
if 0;
# THE PRECEEDING STUFF EXECS perl via $PATH
# -*-Fundamental-*-
require 5.000;
use P4::Modules;
sub dirname
{
local($dir) = @_;
$dir =~ s%^$%.%; $dir = "$dir/";
if ($dir =~ m%^/[^/]*//*$%) { return "/"; }
if ($dir =~ m%^.*[^/]//*[^/][^/]*//*$%)
{ $dir =~ s%^(.*[^/])//*[^/][^/]*//*$%$1%; { return $dir; } }
return ".";
}
use Carp; # ...or flounder. (This will fail unless 'perl' is a perl5!)
$| = 1;
($Myname = $0) =~ s%^.*/%%;
$Mydir = &dirname($0);
$Here = `/bin/pwd`; chop $Here;
if ($Mydir ne ".") { chdir "$Mydir" || die "$Myname: can't chdir \"$Mydir\": $!"; }
chdir ".." || die "$Myname: can't chdir \"..\": $!";
$Mydir = `/bin/pwd`; chop $Mydir;
chdir $Here || die "$Myname: can't chdir \"$Here\": $!";
require "$Mydir/lib/util.pl";
$P4 = 'p4';
%BRANCHES = ();
@ABBRS = ();
$Convclient = $Modules = '';
$p4modules = '';
$afile = '';
$bfile = '';
$DefaultClient = "cvs2p4";
sub usage
{
print <<_EOF_;
Usage: $Myname [ common options ] [ -c client ] conversiondir
$Myname [ common options ] [ -m modules ] conversiondir
$Myname -h
common options:
-a file file listing directory root to abbreviate (no default)
-b file file listing the branch mappings (no default)
-d file write a file of the depot directories (no default)
-h show this message
-l line only check the mappings for 'line' branch
-v print verbose output
options:
-c client use this client while checking (def. cvs2p4)
-m modules use P4::Modules file 'modules' while checking (no default)
_EOF_
exit $_[0];
}
sub path
{
my($prefix, $file_dir, $file_name) = @_;
$prefix =~ s|/+$||;
my $path = "/$file_name";
$path = "/$file_dir$path" if $file_dir;
$path =~ s|/+|/|g;
return $prefix . $path;
}
sub verbose {
my $level = @_ > 1 ? shift : 1;
print @_, "\n" if $level <= $V;
}
sub p4 {
my $cmd = shift;
my @list = `$P4 $cmd`;
if ($?) {
verbose "p4 return: @{[$?>>8]}";
die "error doing \"$P4 $cmd\"";
}
@list;
}
sub p4where
{
my ($file) = @_;
my $cl = $Convclient;
my (@output) = p4 "where \Q$file\E";
my ($root) = grep /^Root:/, p4 "client -o \Q$cl\E";
chomp @output;
warn "warning: ambiguous mapping for $file\n" if @output > 1;
pop @output while $output[$#output] =~ /^-/;
my $output = pop @output;
chomp $root;
$root =~ s/^Root:\s*//;
my ($depot, $client, $local) = split (/ (?:\/\/$cl|$root)\//, $output);
$client = "//$cl/$client";
$local = "$root/$local";
($depot, $client, $local);
}
# This function is very similar to the one in dochanges.
# If you need to change this, determine if the same change is
# required there.
#
sub prepFile {
my ($file, $line) = @_;
$file =~ s|^/?|/|;
my $file_dir = &dirname($file);
(my $file_name = $file) =~ s%^.*/%%;
my ($Depotfile, $Clientfile) = ('', '');
my $abbr = '';
for my $a (@ABBRS) {
verbose 4, "checking $file against $a";
$abbr = $a, last if $file =~ /^$a/;
}
if (%BRANCHES && !$BRANCHES{$line} and $line ne 'main') {
warn "warning: using branch mappings but no match found for $line. ",
"Is it new?\npath checked: $file\n";
}
my $newbr = $BRANCHES{$line} || $line;
if ($newbr =~ m|^//|) {
$Depotfile = $newbr . "$file";
} elsif ($p4modules) {
$Depotfile = $p4modules->where($newbr, "$file_dir/$file_name");
} else {
my $path = &path("$Client$Depot/" . $newbr, $file_dir, $file_name);
($Depotfile) = &p4where($path);
}
if ($Depotfile and $abbr) {
$newbr =~ s|.*/||;
verbose 2, "removing abbrevation $abbr after $newbr";
$Depotfile =~ s|(.*$newbr.*?)$abbr|$1/|;
}
$Depotfile;
}
###### main starts here
#
(@pwent) = getpwuid($<);
if ($#pwent < 7)
{
print STDERR "$Myname: can't get your passwd file entry.\n";
exit 1;
}
$Username = $pwent[0];
# option switch variables get defaults here...
$V = 0;
$Depot = "/depot";
$help = 0;
$branch = '';
$depotList = "";
use Getopt::Long;
GetOptions(
"abbreviations=s" => \$afile,
"branches=s" => \$bfile,
"client=s" => \$Convclient,
"help" => \$help,
"line=s" => \$branch,
"depot=s" => \$depotList,
"modules=s" => \$Modules,
"verbose+" => \$V,
) || die usage(1);
$help && usage(0);
$Depot = "" if $Convclient || $Modules;
$Convclient = $DefaultClient unless $Convclient;
$Convdir = shift || usage(1);
$p4modules = P4::Modules->new($Modules) if $Modules;
chdir $Convdir || die "$Myname: can't chdir \"$Convdir\": $!";
$Convdir = `/bin/pwd`; chop $Convdir; $Convdir =~ s|/*$||;
chdir $Here || die "$Myname: can't chdir \"$Here\": $!";
$Metadata = "$Convdir/metadata";
$Logmsgs = "$Convdir/logmsgs";
$Tips = "$Convdir/tips";
$Changes = "$Convdir/changes";
$Revlog = "$Convdir/revlog";
$Revmap = "$Convdir/revmap";
$Client = "$Convdir/p4";
$LOGNOTE = 1;
require "$Convdir/config";
if (! defined($P4PORT))
{ print "$Myname: no P4PORT in \"$Convdir/config\".\n"; exit 1; }
else
{ $ENV{"P4PORT"} = $P4PORT; }
($P4HOST = $P4PORT) =~ s/:.*//;
($P4PORTNUM = $P4PORT) =~ s/^.*://;
$P4USER = "cvs2p4";
$ENV{"P4CLIENT"} = $Convclient;
# Path the the p4 client command
#
if (! defined($P4)) { $P4 = "/usr/local/bin/p4"; }
if (! -x ($P4))
{ print "$Myname: No executable \"p4\" command at \"$P4\".\n"; exit 1; }
# Make the client if needed.
if (!$p4modules && $Convclient eq $DefaultClient) {
$P4CMD = "$P4 client -i";
&s("$P4 client -d $Convclient");
if (! open(P4, "| $P4CMD"))
{
die "$Myname: open \"/usr/local/bin/p4 client -i\" failed: $!.\n";
}
my $Map = '';
for my $dview (split /\s+/, $P4_DEPOTS) {
(my $cview = $dview) =~ s|^//|//$Convclient/|;
$Map .= "\t$dview/... $cview/...\n";
}
print P4 <<CLI;
Client: $Convclient
Root: $Client
View:
$Map
CLI
close P4;
if ($?) {
die "$Myname: \"$P4CMD\" failed to create client.\n";
}
}
# Read in the abbreviation and branch mappings
#
if ($afile) {
open ABBRS, "<$afile" or die "can't open $afile: $!\n";
while (<ABBRS>) {
chomp;
next if /^#/;
next if /^\s*$/;
s|^/?|/|;
s|/?$|/|;
verbose "found abbreviation: $_";
push @ABBRS, $_;
}
close ABBRS;
}
if ($bfile) {
open BRANCHES, "<$bfile" or die "can't open $bfile: $!\n";
while (<BRANCHES>) {
chomp;
next if /^#/;
next if /^\s*$/;
my ($p4branch, $cvsbranch) = split /\s+/;
$p4branch =~ s|/$||;
$p4branch =~ s|^/|| unless $p4branch =~ m|^//|;
$cvsbranch = $p4branch unless $cvsbranch;
$BRANCHES{$cvsbranch} = $p4branch;
}
close BRANCHES;
}
# Open the changes file (this is the genchamges output file)
#
my $exit_val = 0;
my $cnt = 1;
my $ch = $Changes;
while (-e $Changes) {
verbose "reading changes from $Changes";
if (! open(CHGS, "<$Changes"))
{ print "$Myname: can't open \"$Changes\": $!\n"; exit 1; }
while (<CHGS>)
{
/^#/ && next;
my @info = split /$S/;
my ($dir, $file) = ($info[0], $info[0]);
$info[5] =~ s|^-:||;
$file =~ s|(.*)/.*|$1|;
$dir =~ s|(.*)/.*/.*|$1/...|;
verbose 3, "checking $file";
my @lines = $info[4] eq $TRUNKLINE ? "main" : $info[4];
push @lines, split(/:/, $info[5])
if $info[3] ne 'dead' and $info[5] ne '-';
for my $line (@lines)
{
verbose(2, qq(unwanted branch "$line")), next
if $branch && $line ne $branch;
verbose(3, "skipping $line and $file - already checked"), next
if exists($checked{"$line/$file"});
verbose(3, "skipping $line and $dir - already checked"), next
if exists($checked{"$line/$dir"});
verbose "trying dir: $line $dir";
my $depotfile = prepFile($dir, $line);
if ($depotfile) {
$checked{"$line/$dir"}++;
} else {
verbose "trying file: $line $file";
$depotfile = prepFile($file, $line);
$checked{"$line/$file"}++;
}
if ($depotfile) {
$depotlist{$depotfile} = 1 if $depotList;
verbose "maps to: $depotfile";
} else {
verbose 0, "no mapping for: $line and $file";
$exit_val = 1;
}
}
}
if ($depotList)
{
open DEPOT, ">$depotList" or die "can't open $depotList: $!\n";
print DEPOT "$_\n" for (sort keys %depotlist);
close DEPOT or die "can't close $depotList: $!\n";
}
close CHGS;
$Changes = $ch . "." . ++$cnt;
}
verbose "$Myname is finished";
exit $exit_val;