- eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
- & eval 'exec perl -S $0 $argv:q'
- if 0;
- # THE PRECEEDING STUFF EXECS perl via $PATH
- # -*-Fundamental-*-
- # $Id: //guest/richard_geiger/utils/cvs2p4_meta/bin/genmetadata#2 $
- #
- # Richard Geiger
- #
- require 5.000;
- require "timelocal.pl";
- my %Files_seen;
- 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";
- $Usage = <<LIT;
- $Myname: usage: $Myname
- LIT
- sub usage
- {
- print STDERR $Usage;
- exit 1;
- }
- sub help
- {
- print STDERR <<LIT;
- $Usage
- $Myname is not done yet. Be patient.
- LIT
- exit 1;
- }
- ######
- #
- # Perlstuff for parsing RCS repository files
- #
- # Some globals used by these routines...
- #
- $Rcs_Inquote = 0; # remembers when we're in a '@' quoted string
- $Rcs_Eofatal = 1; # die if we hit the end of the file
- $Rcs_File = "?"; # caller should set this for the error message
- sub lead
- { if (defined($Myname)) { return "$Myname: "; } else { return ""; } }
- sub rcsline
- {
- my $line;
- my $m;
- $line = <RCS>;
- if ($line eq "")
- {
- if ($Rcs_Eofatal)
- {
- $m = "unexpected eof on \"$Rcs_File\".";
- printf STDERR "%s$m\n", &lead();
- exit 1;
- }
- else
- { return undef; }
- }
- if ($line =~ /\r{0,1}\n$/) { $line =~ s/\r{0,1}\n$//; }
- return $line;
- }
- $Rcstok_Buf = "";
- $Rcstok_pushed = undef;
- # Return the next token from the RCS repository file.
- # Caller should open the file on descriptor RCS.
- # (Caller should also empty $Rcstok_Buf!)
- sub rcstok
- {
- my $rcsstr;
- my $m;
- my $strpart;
- if (defined($Rcstok_pushed))
- {
- my $ret = $Rcstok_pushed;
- $Rcstok_pushed = undef;
- return $ret;
- }
- $Rcstok_Buf =~ s/^\s+//;
- if ($Rcstok_Buf eq "")
- {
- while (1)
- {
- $Rcstok_Buf = &rcsline();
- if (! defined ($Rcstok_Buf)) { return undef; }
- if ($Rcstok_Buf ne "") { last; }
- }
- $Rcstok_Buf =~ s/^\s+//;
- }
- # num
- #
- if ($Rcstok_Buf =~ /^([0-9][0-9.]*)(.*)$/)
- { $Rcstok_Buf = $2; return $1; }
- # : ; id
- #
- # Note: the character class for "idchar" assumes all characters
- # are printable ascii! May break with binary RCS files.
- # (Actually, I've now convinced myself that there is no
- # concern here).
- #
- if ($Rcstok_Buf =~ /^(:|;|[a-zA-Z][^ \t\r\n$,:;@]*)(.*)$/)
- { $Rcstok_Buf = $2; return $1; }
- # string
- #
- if ($Rcstok_Buf =~ /^@(.*)$/)
- {
- $Rcstok_Buf = $1;
- $rcsstr = "";
- while (1)
- {
- if ($Rcstok_Buf eq "")
- {
- $rcsstr .= "\n";
- $Rcstok_Buf = &rcsline();
- if (! defined ($Rcstok_Buf)) { return undef; }
- }
- if ($Rcstok_Buf =~ /^([^@]+)(.*)$/)
- {
- $rcsstr .= $1;
- $Rcstok_Buf = $2;
- next;
- }
- if ($Rcstok_Buf =~ /^@@(.*)$/)
- {
- $rcsstr .= "@";
- $Rcstok_Buf = $1;
- next;
- }
- if ($Rcstok_Buf =~ /^@(.*)$/)
- {
- $Rcstok_Buf = $1;
- return $rcsstr;
- }
- }
- }
- $m = "rcstok(): internal error: \$Rcstok_Buf <$Rcstok_Buf>";
- printf STDERR "%s$m\n", &lead();
- exit 1;
- }
- sub dirname
- {
- my ($dir) = @_;
- $dir =~ s%^$%.%; $dir = "$dir/";
- if ($dir =~ m%^/[^/]*//*$%) { return "/"; }
- if ($dir =~ m%^.*[^/]//*[^/][^/]*//*$%)
- { $dir =~ s%^(.*[^/])//*[^/][^/]*//*$%$1%; { return $dir; } }
- return ".";
- }
- sub skip_to_rcstok
- {
- my ($this) = @_;
- my $tok;
- while (($tok = &rcstok()) ne $this) { };
- }
- sub skip_to_deltas
- {
- my $tok;
- # Called after we encounter ";" for symbols. We must now skip:
- #
- # locks {id : num}*; {strict ;}
- # { comment {string}; }
- # { expand {string}; }
- # { newphrase }*
- while (1)
- {
- my $fatalsave = $Rcs_eofatal;
- $tok = &rcstok();
- if ($tok eq "expand")
- {
- $RCS_expand = &rcstok();
- if (&rcstok() ne ";")
- { die "$Myname: skip_to_deltas(): expected ';' after expand."; }
- next;
- }
- if ($tok =~ /^[0-9]/) { $Rcstok_pushed = $tok; last; }
- while (1)
- {
- # Turning this off here because it looks like cvs problems can create
- # delta-less ,v files; this allows us to handle this.
- #
- $Rcs_Eofatal = 0;
- $tok = &rcstok();
- $Rcs_Eofatal = $fatalsave;
- if (! defined($tok)) { return undef; }
- if ($tok eq ";") { last; }
- }
- }
- return 1;
- }
- sub test_rcstoks
- {
- my $tok;
- open(RCS, "<$ARGV[1]") || die;
- $Rcstok_Buf = "";
- $Rcs_Eofatal = 0;
- while (defined($tok = &rcstok))
- { print "<$tok>\n"; }
- exit 1;
- }
- sub setrevs
- {
- my($d_rev, $d_next, $d_branches, $d_date, $d_author, $d_state) = @_;
- my($b_rev);
- $RCS_Revs{$d_rev} = "$d_next:$d_branches";
- $d_date = "19$d_date" if length(( split( /\./, $d_date ))[0]) < 4;
- $RCS_Dates{$d_rev} = "$d_date";
- $RCS_Authors{$d_rev} = "$d_author";
- $RCS_States{$d_rev} = "$d_state";
- if ($d_rev =~ /^1\.1\.1\./)
- {
- # We have a "vendor" branch - spoof a branch tag for it.
- #
- $RCS_Branchtags{"import"} = "1.1.0.1";
- $RCS_Tags{"import"} = "1.1.0.1";
- }
- if ($d_rev =~ /^[0-9]+\.[0-9]+$/)
- {
- $RCS_Prevs{$d_rev} = $d_next;
- if ($d_next) { $RCS_Nexts{$d_next} = $d_rev; }
- }
- else
- {
- if ($d_next) { $RCS_Prevs{$d_next} = $d_rev; }
- $RCS_Nexts{$d_rev} = $d_next;
- }
- foreach $b_rev (split(/ /, $d_branches))
- { $RCS_Prevs{$b_rev} = $d_rev; }
- }
- # initialize RCS_Tags, RCS_Revs, (etc.) from an RCS ,v file.
- #
- sub set_RCS_revs
- {
- my ($path, $do_texts) = @_;
- my $repfile;
- my $tag;
- my $rev;
- my $tok;
- my ($d_havedelta, $d_branches, $d_next, $d_rev);
- my $rcspath;
- my $msg;
- undef $RCS_Valid;
- undef $RCS_expand;
- undef $RCS_exec;
- undef %RCS_Tags;
- undef %RCS_Branchtags;
- undef %RCS_Revs;
- undef %RCS_States;
- undef %RCS_Authors;
- undef %RCS_Dates;
- undef %RCS_Prevs;
- undef %RCS_Nexts;
- undef $RCS_Branch;
- undef %RCS_Texts;
- ($Rcs_File = $path) =~ s%^.*/%%;
- $repfile = $path;
- $rcspath = "<$repfile";
- if (! open(RCS, $rcspath))
- {
- printf STDERR "%scan't open \"$rcspath\": $!\n", &lead();
- return 0;
- }
- if (-x $repfile) { $RCS_exec = "x"; }
- $Rcstok_Buf = "";
- # DEBUG # while (1) { $tok = &rcstok(); print "<$tok>\n"; }
- &skip_to_rcstok("head");
- $RCS_Tags{"head"} = &rcstok();
- $tok = &rcstok(); $tok = &rcstok();
- if ($tok eq "branch") { $RCS_Branch = &rcstok(); }
- &skip_to_rcstok("symbols");
- while (1)
- {
- $tok = &rcstok();
- if ($tok eq ";") { last; }
- $tag = $tok; &rcstok(); $rev = &rcstok();
- $RCS_Tags{$tag} = $rev;
- if ($rev =~ /\.0\.[0-9]+$/)
- { $RCS_Branchtags{$tag} = $rev; }
- elsif (($cnt = $rev =~ tr/\./\./) % 2 == 1)
- {
- ($reppath = $repfile) =~ s/,v$//;
- if (! defined($RCS_Revtags{$tag}))
- { $RCS_Revtags{$tag} = [ ] ; }
- if ($IMPORTTAGSPOOF && $rev eq "1.1.1.1") { $rev = "1.1"; }
- push(@{$RCS_Revtags{$tag}}, "$reppath/$rev");
- }
- }
- if (&skip_to_deltas() == undef) { return undef; }
- $d_rev = ""; $d_havedelta = 0; $d_branches = ""; $d_next = "";
- while (1)
- {
- $tok = &rcstok();
- if ($tok =~ /[0-9.]+/)
- {
- if ($d_havedelta)
- { &setrevs($d_rev, $d_next, $d_branches, $d_date, $d_author, $d_state); }
- $d_rev = $tok; $d_havedelta = 1; $d_branches = ""; $d_next = "";
- }
- elsif ($tok eq "branches")
- {
- while (1)
- {
- if (($tok = &rcstok()) eq ";") { last; }
- if ($d_branches ne "") { $d_branches .= " "; }
- $d_branches .= $tok;
- }
- }
- elsif ($tok eq "date") { $tok = &rcstok(); if ($tok ne ";") { $d_date = $tok; &rcstok(); } }
- elsif ($tok eq "author") { $tok = &rcstok(); if ($tok ne ";") { $d_author = $tok; &rcstok(); } }
- elsif ($tok eq "state") { $tok = &rcstok(); if ($tok ne ";") { $d_state = $tok; &rcstok(); } }
- elsif ($tok eq "next") { $tok = &rcstok(); if ($tok ne ";") { $d_next = $tok; &rcstok(); } }
- elsif ($tok eq "desc") { last; }
- else { &skip_to_rcstok(";"); }
- }
- if ($d_havedelta)
- { &setrevs($d_rev, $d_next, $d_branches, $d_date, $d_author, $d_state); }
- if (! defined($do_texts)) { close RCS; $RCS_Valid = 1; return 1; }
- $Rcs_Eofatal = 0;
- while (1)
- {
- $tok = &rcstok();
- if (! defined($tok)) { last; }
- if ($tok =~ /[0-9.]+/)
- { $d_rev = $tok; }
- elsif ($tok eq "text")
- {
- $msg = &rcstok();
- if ($msg eq "") { $RCS_Texts{$d_rev} = 0; } else { $RCS_Texts{$d_rev} = 1; }
- }
- elsif ($tok eq "log")
- { $log = &rcstok(); $RCS_Logs{$d_rev} = $log; }
- }
- $Rcs_Eofatal = 1;
- close RCS;
- $RCS_Valid = 1;
- return 1;
- }
- sub rcs_tip
- {
- my ($rev) = @_;
- my $next;
- # Find the tip of the branch...
- #
- while (1)
- {
- if (! defined($RCS_Revs{$rev}))
- { return "???"; }
- ($next) = split(/:/, $RCS_Revs{$rev});
- if ($next eq "") { return $rev; }
- $rev = $next;
- }
- }
- # given a "CVS line spec" (revision #, "head", or a tag)
- #
- sub rev_on_line
- {
- my($line) = @_;
- if ($line eq $TRUNKLINE)
- { $line = "head"; }
- # else
- # { $line = "${line}_BRANCH"; }
- if (defined($RCS_Tags{$line})) { $line = $RCS_Tags{$line}; }
- elsif ($line !~ /^[0-9.]+$/) { return "none"; }
- if ($line =~ /\.0\.([0-9]+)$/)
- {
- # It's a CVS branch revision number... demunge it:
- #
- $line =~ s/\.0(\.[0-9]+)$/$1/;
- # OK, see whether the branch actually exists:
- # (We have an assumption here that first rev is always ".1")
- #
- $line = "$line.1";
- if (! defined($RCS_Revs{$line}))
- {
- # Nope, so fall back to the root, which we know to be an
- # existing revision...
- $line =~ s/\.[0-9]+\.[0-9]+$//;
- return $line;
- }
- # Yep, the branch exists; so it *is* a branch; so, we go out to
- # the tip. (Right?)
- #
- return &rcs_tip($line);
- }
- # OK, do we have an RCS branch or an RCS revision number? (count
- # the dots)
- #
- if (($line =~ tr/\././) % 2)
- {
- # An odd number of dots... it's a revision number
- #
- if (defined($RCS_Revs{$line})) { return $line; }
- return "none"; # Or should we assert?
- }
- else
- {
- # An even number of dots... it's a branch number
- # (We have an assumption here that first rev is always ".1")
- #
- return &rcs_tip("$line.1");
- }
- }
- # Is rev "$this" < rev "$that"?
- # Note: "" is considered infinitely high
- # revs must be of the same order (I.e., same # of "."s)
- #
- sub rev_lt
- {
- my($this, $that) = @_;
- my(@this, @that);
- if (! $that) { return 1; }
- @this = split(/\./, $this);
- @that = split(/\./, $that);
- while (1)
- {
- $this_n = shift(@this);
- $that_n = shift(@that);
- if ($this_n < $that_n) { return 1; }
- if ($this_n > $that_n) { return 0; }
- if ($#this < 0) { return 0; }
- }
- }
- # Note: "" is considered infinitely high
- #
- sub linerev_gt
- {
- my($this, $that) = @_;
- my $ret;
- if (! $that)
- { $ret = 1; }
- else
- {
- my $thisord, $thatord;
- $thisord = ($this =~ tr/\././);
- $thatord = ($that =~ tr/\././);
- if ($thisord < $thatord)
- { $ret = 1; }
- elsif ($thisord > $thatord)
- { $ret = 0; }
- else
- { $ret = &rev_lt($that, $this); }
- }
- return $ret;
- }
- # Maximum size for a log message we'll keep.
- # Messages beyond this get truncated, to accomodate a limitation
- # on the key/value pair size in ndbm. That's life.
- #
- $MAXSZ = 256*3;
- # Generate the metadata for a single file
- #
- sub dofile
- {
- local($dir, $file) = @_;
- if ($file !~ /,v$/) { return; }
- if ($IGNOREFILES && $file =~ /$IGNOREFILES/) { return; }
- if ($file =~ /[\000-\037\177-\377]/)
- {
- print "$Myname: RCS filename with non-printable characters (skipped): ";
- $l = length($file);
- for ($i = 0; $i <= $l; $i++)
- {
- $c = substr($file, $i, 1);
- if ($c =~ /[\000-\037\177-\377]/)
- { printf "\\%03o", ord($c); }
- else
- { print "$c"; }
- }
- print "\n";
- return;
- }
- elsif ($file =~ /\#|\%|\*|\@|\.\.\./)
- {
- print "$Myname: RCS filename with illegal Perforce characters (skipped): $file\n";
- return;
- }
- #if ($file ne "rm.c,v") { return; }
- undef %RCS_lines;
- undef %RCS_Branches;
- undef $Firstusedrev;
- # This parses the RCS information from the ,v file, filling
- # in various data structures that we use, below.
- #
- if (&set_RCS_revs("$dir/$file", 0) == undef) { return; } # empty ,v
- # What RCS keyword expansion options are in effect?
- # (We use this to detect binary files)
- #
- $options = "${RCS_expand}$RCS_exec";
- if (! $options) { $options = "-"; }
- @path = split(/\//, "$dir/$file");
- $file = pop(@path);
- $file =~ s/,v$//;
- if ($path[$#path] eq "Attic") { pop @path; }
- $na_dir = join("/", @path);
- $path = sprintf("%s%s%s", $dir, $dir ? "/" : "", $file);
- $na_path = sprintf("%s%s%s", $na_dir, $na_dir ? "/" : "", $file);
- print "$path\n";
- # The "defined($Files_seen{$path})" saves lots of stat()s!
- #
- if (defined($Files_seen{$path}))
- {
- my @p = split(/\//, "$na_path");
- splice(@p, $#p, 0, "Attic");
- my $a_path = join("/", @p);
- # Users have seen this, which previous caused mysterious death
- # in the sort phase... let's be a little more informative:
- #
- if (-f "$na_path,v" && -f "$a_path,v")
- {
- die "assert: CVS repository has both\n $na_path\nand\n $a_path"; }
- else
- { die "assert: dofile(): duplicate path: $na_path"; }
- }
- $Files_seen{$path} = 1;
- # For all of the branches we see, store the tip revision in
- # $HAVELINES{$line}; this is also where we weed out
- # codelines we are not interested in.
- #
- foreach $line ((keys %RCS_Branchtags), $TRUNKLINE)
- {
- $no_flash_line = $line;
- if (defined($BRANCH_FLASH)) { $no_flash_line =~ s/$BRANCH_FLASH$//; }
- if ($WANTLINES && ! (defined($WANTLINES{$no_flash_line}))) { next; }
- if (($tiprev = &rev_on_line($line)) eq "none") { next; }
- $HAVELINES{$line} = $tiprev;
- }
- # Now we go through each line, to build a list of the RCS revs that
- # need to be exported into the metadata stream.
- #
- while (1) # We have more lines to deal with...
- {
- (@k) = (keys %HAVELINES);
- if ($#k < 0) { last; }
- my $theline;
- # Choose the highest numbered line of the lowest "order" for
- # the next one to export... this will always pickup lines on
- # branches nearer the trunk first, so the subsequent branches
- # will have a place to branch from!
- #
- foreach $k (@k)
- {
- if ($k eq $TRUNKLINE) { $theline = $k; last; }
- # if both lines select the *same* revision...
- #
- if ($HAVELINES{$k} eq $HAVELINES{$theline})
- {
- # ...take the one with the lower branch tag order first
- #
- if (&linerev_gt($RCS_Branchtags{$k}, $RCS_Branchtags{$theline}))
- { $theline = $k; next; }
- }
- if (&linerev_gt($HAVELINES{$k}, $HAVELINES{$theline}))
- { $theline = $k; }
- }
- $rev = $tiprev = &rev_on_line($theline);
- $t = $theline;
- if (defined($BRANCH_FLASH))
- { $t =~ s/$BRANCH_FLASH$//; }
- # This is where we build the list of codelines we've encountered.
- #
- $All_lines{$t} = 1;
- if ( (defined($RCS_lines{$rev})) &&
- ($theline ne $TRUNKLINE) &&
- (($rev =~ tr/\././) < ($RCS_Branchtags{$theline} =~ tr/\././)))
- {
- if ($RCS_Branches{$rev}) { $RCS_Branches{$rev} .= ":"; }
- $RCS_Branches{$rev} .= $t;
- }
- else
- {
- while ($rev && ! defined($RCS_lines{$rev}))
- {
- $RCS_lines{$rev} = $theline;
- $rev = $RCS_Prevs{$rev};
- }
- if ($rev)
- {
- if ($RCS_Branches{$rev}) { $RCS_Branches{$rev} .= ":"; }
- $RCS_Branches{$rev} .= $t;
- }
- }
- # We test for "if $rev" here cause it may have gone null if the while loop
- # above ran off the end...
- #
- if ($rev && (($rev =~ tr/\././) == 1) && &rev_lt($rev, $Firstusedrev))
- { $Firstusedrev = $rev }
- delete $HAVELINES{$theline};
- }
- # OK, we have the set of revisions to export - write them to the
- # metadata stream.
- #
- foreach $rev (keys %RCS_Revs)
- {
- $revkey = "$path/$rev";
- $state = $RCS_States{$rev};
- $author = $RCS_Authors{$rev};
- $date = $RCS_Dates{$rev};
- my ($yr, $mo, $da, $hr, $mi, $se) = split (/\./, $date);
- $date = timegm($se,$mi,$hr,$da,$mo - 1,$yr);
- $line = $RCS_lines{$rev};
- if (defined($BRANCH_FLASH)) { $line =~ s/$BRANCH_FLASH$//; }
- $branches = $RCS_Branches{$rev};
- # Detect revisions before the first branch point, and
- # omit them if we're not doing ALLTHEWAYBACK.
- #
- if ( (! $ALLTHEWAYBACK)
- && ($line eq $TRUNKLINE)
- && ($rev ne $RCS_Tags{"head"})
- && $Firstusedrev
- && &rev_lt($rev, $Firstusedrev))
- { next; }
- if (! $line) { next; }
- if (! $branches) { $branches = "-"; }
- if ((! $ALLTHEWAYBACK) && $rev eq $Firstusedrev)
- { $prevrev = "-"; }
- elsif ($RCS_Prevs{$rev})
- { $prevrev = $RCS_Prevs{$rev}; }
- else
- { $prevrev = "-"; }
- $All_lines{$line} = 1;
- print METATMP "$revkey$S$date$S$author$S$state$S$line$S$branches$S$prevrev$S$options\n";
- # MAXSZ derives from a ndbm limitation on the size of a key/entry pair.
- # at (256*3) it allows for a $revkey up to 250 chars or so.
- #
- $logmsg = substr($RCS_Logs{$rev}, 0, $MAXSZ);
- if ($logmsg !~ /\n$/) { $logmsg .= "\n"; }
- if (length($logmsg)+length($revkey) > 1010)
- { print "$Myname: revkey + log too long for <$revkey>\n"; exit 1; }
- $MSGS{$revkey} = $logmsg;
- }
- }
- # option switch variables get defaults here...
- $Convdir = "";
- $Boolopt = 0;
- $Valopt = 0;
- while ($#ARGV >= 0)
- {
- if ($ARGV[0] eq "-boolopt") { $Boolopt = 1; shift; next; }
- elsif ($ARGV[0] eq "-valopt")
- {
- shift; if ($ARGV[0] < 0) { &usage; }
- $Valopt = $ARGV[0]; shift; next;
- }
- elsif ($ARGV[0] eq "-help")
- { &help; }
- elsif ($ARGV[0] =~ /^-/) { &usage; }
- if ($Args ne "") { $Args .= " "; }
- push(@Args, $ARGV[0]);
- shift;
- }
- if ($#Args ne 0) { &usage; }
- $Convdir = $Args[0];
- $Metatmp = "$Convdir/metatmp";
- $Metadata = "$Convdir/metadata";
- $Labels = "$Convdir/labels";
- $Logmsgs = "$Convdir/logmsgs";
- $Changes = "$Convdir/changes";
- $Revmap = "$Convdir/revmap";
- $Revtags = "$Convdir/revtags";
- $Clientdir = "$Convdir/p4";
- require "$Convdir/config";
- # (Handle eith f.db or f.pag, f,dir style dbs):
- #
- &s("rm -rf $Logmsgs.db $Logmsgs.pag $Logmsgs.dir ".
- "$Changes $Clientdir ".
- "$Revmap.db $Revmap.pag $Revmap.dir ".
- "$Revtags.db Revtags.pag $Revtags.dir");
- if (! dbmopen(MSGS, $Logmsgs, 0666))
- { print "$Myname: can't dbmopen \"$Logmsgs\": $!\n"; exit 1; }
- if (! dbmopen(RCS_Revtags, $Revtags, 0666))
- { print "$Myname: can't dbmopen \"$Revtags\": $!\n"; exit 1; }
- if (! open(METATMP, ">$Metatmp"))
- { print "$Myname: can't open \">$Metatmp\": $!\n"; exit 1; }
- #chdir $CVS_MODULE || die "$Myname: can't chdir \"$CVS_MODULE\": $!";
- #$CVS_MODULE = `/bin/pwd`; chop $CVS_MODULE;
- #chdir $Here || die "$Myname: can't chdir \"$Here\": $!";
- &traverse($CVS_MODULE, 0, "dofile");
- close METATMP;
- sub metasort
- {
- my @a = split(/$S/, $a);
- my @b = split(/$S/, $b);
- # The revision time is the primary sort key
- # - But this is now handled by the external sort; we still
- # do secondary and tertiary sort keys, below
- #
- # if ($a[1] != $b[1]) { return $a[1] <=> $b[1]; }
- $a[0] =~ s/^(.*)\///; my $apath = $1;
- $b[0] =~ s/^(.*)\///; my $bpath = $1;
- # Next is the pathname
- #
- if ($apath ne $bpath) { return $apath cmp $bpath; }
- # If we're still tied, it goes to the revision number!
- #
- @aa = split(/\./, $a[0]);
- @bb = split(/\./, $b[0]);
- for (my $i = 0; $i <= $#aa; $i=$i+2)
- {
- if (! defined($bb[$i])) { return 1; } # a has more positions, thus greater
- if ($aa[$i] < $bb[$i]) { return -1; } # a is less than b, thus less
- if ($aa[$i] > $bb[$i]) { return 1; } # and vice-versa
- # if they are equal, we look to the next position:
- #
- if (! defined($aa[$i+1]))
- { die "impossible sort key (RCS rev) \"$a[0]\"?\n"; }
- if (! defined($bb[$i+1]))
- { die "impossible sort key (RCS rev) \"$b[0]\"?\n"; }
- if ($aa[$i+1] < $bb[$i+1]) { return -1; } # a is less than b, thus less
- if ($aa[$i+1] > $bb[$i+1]) { return 1; } # and vice-versa
- # Otherwise, we go on to the next level...
- }
- if ($#bb > $#aa) { return -1; }
- die "impossible equal sort keys:\n <$a>\n <$b>\n";
- }
- my $cmd = "sort -n -t $S +1 < $Metatmp |";
- if (! open(METASORT, $cmd))
- { print "$Myname: can't open \"$cmd\": $!\n"; exit 1; }
- if (! open(META, ">$Metadata"))
- { print "$Myname: can't open \">$Metadata\": $!\n"; exit 1; }
- # Do the sorting in chunks, per primary sort key. (We're going through
- # all of this, BTW, in order to constrain genmetadata's memory
- # footprint, which was getting huge when we held all of the tags and
- # metadata in-core)
- #
- my $t = 0;
- my @Meta;
- while (<METASORT>)
- {
- chomp;
- my @r = split(/$S/, $_);
- if ($r[1] ne $t)
- {
- if ($#Meta >= 0)
- {
- my @Metasorted = sort metasort @Meta;
- foreach my $m (@Metasorted) { print META "$m\n"; }
- }
- $t = $r[1];
- @Meta = ();
- }
- push (@Meta, $_);
- }
- if ($#Meta >= 0)
- {
- my @Metasorted = sort metasort @Meta;
- foreach my $m (@Metasorted) { print META "$m\n"; }
- }
- close METASORT;
- close META;
- if (! open(LABELS, ">$Labels"))
- { print "$Myname: can't open \">$Labels\": $!\n"; exit 1; }
- foreach $label (sort(keys(%RCS_Revtags)))
- {
- print LABELS "$label\n";
- foreach $rev (@{$RCS_Revtags{$label}})
- { print LABELS " $rev\n"; }
- }
- close LABELS;
- dbmclose MSGS;
- dbmclose RCS_Revtags;
- &s("rm -rf $Revtags.db $Revtags.pag $Revtags.dir");
- $Lines = "$Convdir/lines";
- if (! open(LINES, ">$Lines"))
- { print "$Myname: can't open \">$Lines\": $!\n"; }
- else
- {
- print "===== Lines referenced:\n";
- print LINES "===== Lines referenced:\n";
- foreach $line (sort keys %All_lines)
- {
- print "$line\n";
- print LINES "$line\n";
- }
- close LINES;
- }
- exit 0;
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#2 | 1744 | Richard Geiger | Changes for 2.0b6: - handle Attic files correctly - this required a change from the old ... version (and required touching genmetadata), since we now use the old RCS archive tree in place (or a copy thereof). - dolabels now closes the labels journal file explicitly. Previously, the subsequent "p4d -jr" could see premature eof to due buffered data, and the last bunch of labels in the dblbls file would not be converted. - fix a bug that broke conversion of files that had been deleted and then re-added in CVS; upon re-adding the file, it would be given revision #1 agian, instead of the next unused revision number. - added a couple of test cases for these. Many thanks to Fan Zhang of Numeritech for helping to wring out these problems! « |
23 years ago | |
#1 | 1636 | Richard Geiger | Branch for working on a direct-metadata generation verison of cvs2p4 | 23 years ago | |
//guest/richard_geiger/utils/cvs2p4/bin/genmetadata | |||||
#19 | 1437 | Richard Geiger | Fix for 1.3.3 - labels on revived Attic files. | 23 years ago | |
#18 | 1404 | Richard Geiger | Oops, fix a bug ni the sort re-do from the last change: the external sort needs a -n. You...'d think it would be smart enought to know what I want. Sheesh. :-) « |
23 years ago | |
#17 | 1388 | Richard Geiger | Put genmetadata on a memory diet. | 23 years ago | |
#16 | 1203 | Richard Geiger | Fix bug where dolables couldn't cope with tag in which the revision for a file was a dele...te Add the IMPORTTAGSPOOF switch. « |
23 years ago | |
#15 | 1185 | Richard Geiger |
Changes for 1.3 (Labels!) |
23 years ago | |
#14 | 1031 | Richard Geiger | Changes for 1.2.17; fix one-letter id internal error bug. | 23 years ago | |
#13 | 823 | Richard Geiger | Add assert for dup d/f,v d/Attic/f,v (like "Giao Phan" <giao@seven.com> saw) | 24 years ago | |
#12 | 474 | Richard Geiger | Reject files with bad characters per perforce filenaming conventions. | 24 years ago | |
#11 | 459 | Richard Geiger | Now performs metadata sort using a sort routine coded directly in perl, rather than by us...ing the host system's "sort" command. (Differences in "sort" behavior from one host to another had been observed to cause irregularities). « |
24 years ago | |
#10 | 416 | Richard Geiger | Pull in Thomas Quinot <quinot@inf.enst.fr>'s UTC bugfix, for 1.2.12. | 25 years ago | |
#9 | 398 | Richard Geiger | Skip (and note) ,v files with nonprintable characters in the fileame. | 25 years ago | |
#8 | 392 | Richard Geiger | CHanges for 1.2.10 (tolerate empty RCS file) | 25 years ago | |
#7 | 342 | Richard Geiger | Allow for "." in "id" symbols. | 25 years ago | |
#6 | 330 | Richard Geiger | This change allows cvs2p4 to cope with RCS archives with CR/LF line endings. (I'm not sur...e how these get created; presumably some weird side effect of Bill Gates. But one user had 'em; RCS seems to cope with 'em, and so I've decided to make cvs2p4 follow suit. « |
25 years ago | |
#5 | 305 | Richard Geiger | Changes for 1.2.7 | 25 years ago | |
#4 | 249 | Richard Geiger | Changes in preparation for supporting spaces in filenames. (In fact, this may work as of... this change, but is not yet tested.) Also, add "runtest -gengood" to allow easier generatino of new *.good files. (It just doesn't quick on a miscompare!). « |
25 years ago | |
#3 | 240 | Richard Geiger | Version 1.2.5, to account for post-1999 RCS behavior. (Courtesy of David Simon, Goldman S...achs) « |
25 years ago | |
#2 | 179 | Richard Geiger | CHanges for 1.2.3 | 26 years ago | |
#1 | 130 | Richard Geiger | CVS-to-Perforce converter. This is release 1.2.2 (first submit to the Perforce Public Dep...ot) « |
26 years ago |