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 <) { 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 () { 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 () { /^#/ && 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;