1102840Speter#! @PERL@ 2102840Speter# --------------------------------- 3102840Speter# This program is free software; you can redistribute it and/or modify 4102840Speter# it under the terms of the GNU General Public License as published by 5102840Speter# the Free Software Foundation; either version 2, or (at your option) 6102840Speter# any later version. 7102840Speter# 8102840Speter# This program is distributed in the hope that it will be useful, 9102840Speter# but WITHOUT ANY WARRANTY; without even the implied warranty of 10102840Speter# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11102840Speter# GNU General Public License for more details. 12102840Speter 13102840Speter########################################################################### 14102840Speter# FUNCTION: 15102840Speter# To recursively walk through a PVCS archive directory tree (archives 16102840Speter# located in VCS/ or vcs/ subdirectories) and convert them to RCS archives. 17102840Speter# The RCS archive name is the PVCS workfile name with ",v" appended. 18102840Speter# 19102840Speter# SYNTAX: 20102840Speter# pvcs_to_rcs.pl --help 21102840Speter# 22102840Speter# where -l indicates the operation is to be performed only in the current 23102840Speter# directory (no recursion) 24102840Speter# 25102840Speter# EXAMPLE: 26102840Speter# pvcs_to_rcs 27102840Speter# Would walk through every VCS or vcs subdir starting at the current directory, 28102840Speter# and produce corresponding RCS archives one level above the VCS or vcs subdir. 29102840Speter# (VCS/../RCS/) 30102840Speter# 31102840Speter# NOTES: 32102840Speter# * This script performs little error checking and logging 33102840Speter# (i.e. USE AT YOUR OWN RISK) 34102840Speter# * This script was last tested using ActiveState's port of Perl 5.005_02 35102840Speter# (internalcut #507) under Win95, though it does compile under Perl-5.00404 36102840Speter# for Solaris 2.4 run on a Solaris 2.6 system. The script crashed 37102840Speter# occasionally under ActiveState's port of Perl 5.003_07 but this stopped 38102840Speter# happening with the update so if you are having problems, try updating Perl. 39102840Speter# Upgrading to cut #507 also seemed to coincide with a large speed 40102840Speter# improvement, so try and keep up, hey? :) It was executed from MKS's 41102840Speter# UNIX tools version 6.1 for Win32's sh. ALWAYS redirect your output to 42102840Speter# a log!!! 43102840Speter# * PVCS archives are left intact 44102840Speter# * RCS archives are created in VCS/../RCS/ (or ./RCS using '-pflat') 45102840Speter# * Branch labels in this script will be attached to the CVS magic 46102840Speter# revision number. For branch a.b.c of a particular file, this means 47102840Speter# the label will be attached to revision a.b.0.c of the converted 48102840Speter# file. If you use the TrunkTip (1.*) label, be aware that it will convert 49102840Speter# to RCS revision 0.1, which is useless to RCS and CVS. You'll probably 50102840Speter# have to delete these. 51102840Speter# * All revisions are saved with correct "metadata" (i.e. check-in date, 52102840Speter# author, and log message). Any blank log message is replaced with 53102840Speter# "no comment". This is because RCS does not allow non-interactive 54102840Speter# check in of a new revision without a comment string. 55102840Speter# * Revision numbers are incremented by 1 during the conversion (since 56102840Speter# RCS does not allow revision 1.0). 57102840Speter# * All converted branch numbers are even (the CVS paradigm) 58102840Speter# * Version labels are assigned to the appropriate (incremented) revision 59102840Speter# numbers. PVCS allows spaces and periods in version labels while RCS 60102840Speter# does not. A global search and replace converts " " and "." to "_" 61102840Speter# There may be other cases that ought to be added. 62102840Speter# * Any working (checked-out) copies of PVCS archives 63102840Speter# within the VCS/../ or vcs/../ (or possibly ./ with '-pflat') 64102840Speter# will be deleted (or overwritten) depending on your mode of 65102840Speter# operation since the current ./ is used in the checkout of each revision. 66102840Speter# I suppose if development continues these files could be redirected to 67102840Speter# temp space rather than ./ . 68102840Speter# * Locks on PVCS archives should be removed (or the workfiles should be 69102840Speter# checked-in) prior to conversion, although the script will blaze through 70102840Speter# the archive nonetheless (But you would lose any checked out revision(s)) 71102840Speter# * The -kb option is added to the RCS archive for workfiles with the following 72102840Speter# extensions: .bin .out .btl .rom .a07 .lib .exe .tco .obj .t8u .c8u .o .lku 73102840Speter# .a and a few others. The %bin_ext variable holds these values in regexp 74102840Speter# form. 75102840Speter# * the --force-binary option can be used to convert binary files which don't 76102840Speter# have proper extensions, but I'd *probably* edit the %bin_ext variable. 77102840Speter# * This script will abort occasionally with the error "invalid revision 78102840Speter# number". This is known to happen when a revision comment has 79102840Speter# /^\s*Rev/ (Perl regexp notation) in it. Fix the comment and start over. 80102840Speter# (The directory locks and existance checking make this a fairly quick 81102840Speter# process.) 82102840Speter# * This script writes lockfiles in the RCS/ directories. It will also not 83102840Speter# convert an archive if it finds the RCS Archive existant in the RCS/ 84102840Speter# directory. This enables the conversion to quickly pick up where it left 85102840Speter# off after errors or interrupts occur. If you interrupt the script make 86102840Speter# sure you delete the last RCS Archive File which was being written. 87102840Speter# If you recieve the "Invalid revision number" error, then the RCS archive 88102840Speter# file for that particular PVCS file will not have been created yet. 89102840Speter# * This script will not create lockfiles when processing single 90102840Speter# filenames passed into the script, for hopefully obvious reasons. 91102840Speter# (lockfiles lock directories - DRP) 92102840Speter# * Log the output to a file. That makes it real easy to grep for errors 93102840Speter# later. (grep for "^[ \t]*(rcs|ci):" and be aware I might have missed 94102840Speter# a few cases (get? vcs?) !!!) *** Also note that this script will 95102840Speter# exibit some harmless RCS errors. Namely, it will attempt to lock 96102840Speter# branches which haven't been created yet. *** 97102840Speter# * I tried to keep the error and warning info up to date, but it seems 98102840Speter# to mean very little. This script almost always exits with a warning 99102840Speter# or an error that didn't seem to cause any harm. I didn't trace it 100102840Speter# and our imported source checks out and builds... 101102840Speter# It is probably happening when trying to convert empty directories 102102840Speter# or read files (possibly checked out workfiles ) which are not 103102840Speter# pvcs_archives. 104102840Speter# * You must use the -pflat option when processing single filenames 105102840Speter# passed as arguments to the script. This is probably a bug. 106175261Sobrien# * questions, comments, additions can be sent to info-cvs@nongnu.org 107102840Speter######################################################################### 108102840Speter 109102840Speter 110102840Speter 111102840Speter# 112102840Speter# USER Configurables 113102840Speter# 114102840Speter 115102840Speter# %bin_ext should be editable from the command line. 116102840Speter# 117102840Speter# NOTE: Each possible binary extension is listed as a Perl regexp 118102840Speter# 119102840Speter# The value associated with each regexp key is used to print a log 120102840Speter# message when a binary file is found. 121102840Spetermy %bin_ext = 122102840Speter ( 123102840Speter '\.(?i)bin$' => "Binary", 124102840Speter '\.(?i)out$' => "Default Compiler Output", 125102840Speter '\.(?i)btl$' => "", 126102840Speter '\.(?i)rom$' => "", 127102840Speter '\.(?i)a07$' => "", 128102840Speter '\.(?i)lib$' => "DOS/Wintel/Netware Compiler Library", 129102840Speter '\.(?i)lif$' => "Netware Binary File", 130102840Speter '\.(?i)exe$' => "DOS/Wintel Executable", 131102840Speter '\.(?i)tco$' => "", 132102840Speter '\.(?i)obj$' => "DOS/Wintel Compiler Object", 133102840Speter '\.(?i)res$' => "DOS/Wintel Resource File", 134102840Speter '\.(?i)ico$' => "DOS/Wintel Icon File", 135102840Speter '\.(?i)nlm$' => "Netware Loadable Module", 136102840Speter '\.(?i)t8u$' => "", 137102840Speter '\.(?i)c8u$' => "", 138102840Speter '\.(?i)lku$' => "", 139102840Speter '\.(?i)(bmp|gif|jpg|jpeg|jfif|tif|tiff|xbm)$' => "Image", 140102840Speter '\.(?i)dll$' => "DOS/Wintel Dynamically Linked Library", 141102840Speter '\.o$' => "UNIX Compiler Object", 142102840Speter '\.a$' => "UNIX Compiler Library", 143102840Speter '\.so(\.\d+\.\d+)?$' => "UNIX Shared Library" 144102840Speter ); 145102840Speter 146102840Speter# The binaries this script is dependant on: 147102840Spetermy @bin_dependancies = ("vcs", "vlog", "rcs", "ci"); 148102840Speter 149102840Speter# Where we should put temporary files 150102840Spetermy $tmpdir = $ENV{TMPDIR} ? $ENV{TMPDIR} : "/var/tmp"; 151102840Speter 152102840Speter# We use these... 153102840Speteruse strict; 154102840Speter 155102840Speteruse Cwd; 156102840Speteruse File::Path; 157102840Speteruse IO::File; 158102840Speteruse Getopt::Long; 159102840Speter $Getopt::Long::bundling = 1; 160102840Speter# $Getopt::Long::ignorecase = 0; 161102840Speter 162102840Spetermy $usage = "\ 163102840Speterusage: $0 -h 164102840Speter $0 [-lt] [-i vcsid] [-r flat|leaf] [-p flat|leaf] [-x rcs_extension] 165102840Speter [-v none|locks|exists] [options] [path...] 166102840Speter"; 167102840Speter 168102840Spetermy $help = "\ 169102840Speter$usage 170102840Speter ---------------------------- ----------------------------------- 171102840Speter -h | --Help Print this text 172102840Speter 173102840Speter General Settings 174102840Speter ---------------------------- ----------------------------------- 175102840Speter --Recurse Recurse through directories 176102840Speter (default) 177102840Speter -l | --NORecurse Process only . 178102840Speter --Errorfiles Save a count of conversion errors 179102840Speter in the RCS archive directory 180102840Speter (default) (unimplemented) 181102840Speter --NOErrorfiles Don't save a count of conversion 182102840Speter errors (unimplemented) 183102840Speter ( -m | --Mode ) Convert Convert PVCS files to RCS files 184102840Speter (default) 185102840Speter ( -m | --Mode ) Verify Perform verification ONLY (unimplemented) 186102840Speter ( -v | --VERIfy ) None Always replace existing RCS files 187102840Speter ( -v | --VERIfy ) LOCKS Same as exists unless a #conv.done 188102840Speter file exists in the RCS directory. 189102840Speter In that case, only the #conv.done 190102840Speter file's existance is verified for 191102840Speter that directory. (default) 192102840Speter ( -v | --VERIfy ) Exists Don't replace existing RCS files 193102840Speter ( -v | --VERIfy ) LOCKDates Verify that an existing RCS file's 194102840Speter last modification date is older 195102840Speter than that of the lockfile 196102840Speter (unimplemented) 197102840Speter ( -v | --VERIfy ) Revs Verify that the PVCS archive files 198102840Speter and RCS archive file contain the 199102840Speter same number of corresponding 200102840Speter revisions. Add only new revisions 201102840Speter to the RCS file. (unimplemented) 202102840Speter ( -v | --VERIfy ) Full Perform --verify=Revs and confirm 203102840Speter that the text of the revisions is 204102840Speter identical. Add only new revisions 205102840Speter unless an error is found. Then 206102840Speter erase the RCS archive and recreate 207102840Speter it. (unimplemented) 208102840Speter -t | --Test-binaries Use 'which' to check \$PATH for 209102840Speter the binaries required by this 210102840Speter script (default) 211102840Speter --NOTest-binaries Don't check for binaries 212102840Speter --VERBose Enable verbose output 213102840Speter --NOVerbose Disable verbose output (default) 214102840Speter -w | --Warnings Print warning messages (default) 215102840Speter --NOWarnings Don't print warning messages 216102840Speter 217102840Speter RCS Settings 218102840Speter ---------------------------- ----------------------------------- 219102840Speter ( -r | --RCS-Dirs ) leaf RCS files stored in ./RCS (default) 220102840Speter ( -r | --RCS-Dirs ) flat RCS files stored in . 221102840Speter (unimplemented) 222102840Speter ( -x | --RCS-Extension ) Set RCS file extension 223102840Speter (default = ',v') 224102840Speter --Force-binary Pass '-kb' to 'rcs -i' regardless of 225102840Speter the file extension 226102840Speter --NOForce-binary Only use '-kb' when the file has 227102840Speter a binary extension (default) 228102840Speter --Cvs-branch-labels Use CVS magic branch revision 229102840Speter numbers when attaching branch 230102840Speter labels (default) 231102840Speter --NOCvs-branch-labels Attach branch labels to RCS branch 232102840Speter revision numbers (unimplemented) 233102840Speter 234102840Speter PVCS Settings 235102840Speter ---------------------------- ----------------------------------- 236102840Speter ( -p | --Pvcs-dirs ) leaf PVCS files expected in ./VCS 237102840Speter (default) 238102840Speter ( -p | --Pvcs-dirs ) flat PVCS files expected in . 239102840Speter ( -i | --VCsid ) vcsid Use vcsid instead of \$VCSID 240102840Speter 241102840Speter -------------------------------------------------------------------------- 242102840Speter The optional path argument should contain the name of a file or directory 243102840Speter to convert. If not given, it will default to '.'. 244102840Speter -------------------------------------------------------------------------- 245102840Speter"; 246102840Speter 247102840Speter 248102840Speter 249102840Speter# 250102840Speter# Initialize globals 251102840Speter# 252102840Speter 253102840Spetermy ($errors, $warnings) = (0, 0); 254102840Spetermy ($curlevel, $maxlevel); 255102840Spetermy ($rcs_base_command, $ci_base_command); 256102840Spetermy ($donefile_name, $errorfile_name); 257102840Speter 258102840Speter# set up the default options 259102840Spetermy %options = ( 260102840Speter recurse => 1, 261102840Speter mode => "convert", 262102840Speter errorfiles => 1, 263102840Speter 'rcs-dirs' => "leaf", 264102840Speter 'rcs-extension' => ",v", 265102840Speter 'force-binary' => 0, 266102840Speter 'cvs-branch-labels' => 1, 267102840Speter 'pvcs-dirs' => "leaf", 268102840Speter verify => "locks", 269102840Speter 'test-binaries' => 1, 270102840Speter vcsid => $ENV{VCSID} || "", 271102840Speter verbose => 0, 272102840Speter debug => 0, 273102840Speter warnings => 1 274102840Speter ); 275102840Speter 276102840Speter 277102840Speter 278102840Speter# This is untested except under Solaris 2.4 or 2.6 and 279102840Speter# may not be portable 280102840Speter# 281102840Speter# I think the readline lib or some such has an interface 282102840Speter# which may enable this now. The perl installer sure looks 283102840Speter# like it's testing this kind of thing, anyhow. 284102840Spetersub hit_any_key 285102840Speter { 286102840Speter STDOUT->autoflush; 287102840Speter system "stty", "-icanon", "min", "1"; 288102840Speter 289102840Speter print "Hit any key to continue..."; 290102840Speter getc; 291102840Speter 292102840Speter system "stty", "icanon", "min", "0"; 293102840Speter STDOUT->autoflush (0); 294102840Speter 295102840Speter print "\nI always wondered where that key was...\n"; 296102840Speter } 297102840Speter 298102840Speter 299102840Speter 300102840Speter# print the usage 301102840Spetersub print_usage 302102840Speter { 303102840Speter my $fh = shift; 304102840Speter unless (ref $fh) 305102840Speter { 306102840Speter my $fdn = $fh ? $fh : "STDERR"; 307102840Speter $fh = new IO::File; 308102840Speter $fh->fdopen ($fdn, "w"); 309102840Speter } 310102840Speter 311102840Speter $fh->print ($usage); 312102840Speter } 313102840Speter 314102840Speter# print the help 315102840Spetersub print_help 316102840Speter { 317102840Speter my $fh = shift; 318102840Speter unless (ref $fh) 319102840Speter { 320102840Speter my $fdn = $fh ? $fh : "STDOUT"; 321102840Speter $fh = new IO::File; 322102840Speter $fh->fdopen ($fdn, "w"); 323102840Speter } 324102840Speter 325102840Speter $fh->print ($help); 326102840Speter } 327102840Speter 328102840Speter# print the help and exit $_[0] || 0 329102840Spetersub exit_help 330102840Speter { 331102840Speter print_help; 332102840Speter exit shift || 0; 333102840Speter } 334102840Speter 335102840Spetersub error_count 336102840Speter { 337102840Speter my $type = shift or die "$0: error - error_count usage: error_count type [, ref] [, LIST]\n"; 338102840Speter my $error_count_ref; 339102840Speter my $outstring; 340102840Speter 341102840Speter if (ref ($_[0]) && ref ($_[0]) == "SCALAR") 342102840Speter { 343102840Speter $error_count_ref = shift; 344102840Speter } 345102840Speter else 346102840Speter { 347102840Speter $error_count_ref = \$errors; 348102840Speter } 349102840Speter $$error_count_ref++; 350102840Speter 351102840Speter push @_, "something wrong.\n" unless ( @_ > 0 ); 352102840Speter 353102840Speter $outstring = sprintf "$0: $type - " . join ("", @_); 354102840Speter $outstring .= sprintf " - $!\n" unless ($outstring =~ /\n$/); 355102840Speter 356102840Speter print STDERR $outstring; 357102840Speter 358102840Speter if ($options{errorfiles}) 359102840Speter { 360102840Speter my $fh = new IO::File ">>$errorfile_name" or new IO::File ">$errorfile_name"; 361102840Speter if ($fh) 362102840Speter { 363102840Speter $fh->print ($$error_count_ref . "\n"); 364102840Speter $fh->print ($outstring); 365102840Speter $fh->close; 366102840Speter } 367102840Speter else 368102840Speter { 369102840Speter my $cd = cwd; 370102840Speter print STDERR "$0: error - failed to open errorfile $cd/$errorfile_name - $!\n" 371102840Speter if ($options{debug}); 372102840Speter } 373102840Speter } 374102840Speter 375102840Speter return $$error_count_ref; 376102840Speter } 377102840Speter 378102840Speter 379102840Speter 380102840Speter# the main procedure that is run once in each directory 381102840Spetersub execdir 382102840Speter { 383102840Speter my $dir = shift; 384102840Speter my ($errors, $warnings) = (0, 0); # We return these error counters 385102840Speter my $old_dir = cwd; 386102840Speter 387102840Speter local ($_, @_); 388102840Speter 389102840Speter my $i; # Generic counter 390102840Speter my ($pvcsarchive, $workfile, $rcsarchive); # .??v, checked out file, and ,v files, 391102840Speter # respectively 392102840Speter my ($rev_count, $first_vl, $last_vl, $description, 393102840Speter $rev_index, @rev_num, %checked_in, %author, 394102840Speter $relative_comment_index, @comment_string, 395102840Speter %comment); 396102840Speter my ($num_version_labels, $label_index, @label_revision, $label, 397102840Speter @new_label, $rcs_rev); 398102840Speter my ($revision, %rcs_rev_num); 399102840Speter my ($get_output, $rcs_output, $ci_output, $mv_output); 400102840Speter my ($ci_command, $rcs_command, $wtr); 401102840Speter my @hits; 402102840Speter my ($num_fields); 403102840Speter my $skipdirlock; # if true, don't write conv.out 404102840Speter # used only for single file operations 405102840Speter # at the moment 406102840Speter my $cd; 407102840Speter 408102840Speter my @filenames; 409102840Speter # We may have recieved a single file name to process... 410102840Speter if ( -d $dir ) 411102840Speter { 412102840Speter # change into the directory to be processed 413102840Speter # open the current directory for listing 414102840Speter # initialize the list of filenames 415102840Speter # and set filenames equal to directory listing 416102840Speter unless ( ( chdir $dir ) and ( opendir CURDIR, "." ) and ( @filenames = readdir CURDIR ) ) 417102840Speter { 418102840Speter $cd = cwd; 419102840Speter error_count 'error', \$errors, "skipping directory $dir from $cd"; 420102840Speter chdir $old_dir or die "Failed to restore original directory ($old_dir): ", $!, ", stopped"; 421102840Speter return ($errors, $warnings); 422102840Speter } 423102840Speter 424102840Speter # clean up by closing the directory 425102840Speter closedir(CURDIR); 426102840Speter } 427102840Speter elsif ( -f $dir ) # we recieved a single file 428102840Speter { 429102840Speter push @filenames, $dir; 430102840Speter $skipdirlock = 1; 431102840Speter } 432102840Speter else 433102840Speter { 434102840Speter $cd = cwd; 435102840Speter error_count 'error', \$errors, "no such directory/file $dir from $cd\n"; 436102840Speter # chdir $old_dir or die "Failed to restore original directory ($old_dir): ", $!, ", stopped"; 437102840Speter return ($errors, $warnings); 438102840Speter } 439102840Speter 440102840Speter # save the current directory 441102840Speter $cd = cwd; 442102840Speter 443102840Speter # increment the global $curlevel variable 444102840Speter $curlevel = $curlevel +1; 445102840Speter 446102840Speter # initialize a list for any subdirectories and any files 447102840Speter # we need to process 448102840Speter my $vcsdir = ""; 449102840Speter my (@subdirs, $fn, $file, @files, @pvcsarchives); 450102840Speter 451102840Speter # print "$cd: " . join (", ", @filenames) . "\n"; 452102840Speter # hit_any_key; 453102840Speter 454102840Speter (@files, @pvcsarchives) = ( (), () ); 455102840Speter # begin a for loop to execute on each filename in the list @filename 456102840Speter foreach $fn (@filenames) 457102840Speter { 458102840Speter # if the file is a directory... 459102840Speter if (-d $fn) 460102840Speter { 461102840Speter # then if we are not expecting a flat arrangement of pvcs files 462102840Speter # and we found a vcs directory add its files to @pvcsarchives 463102840Speter if (!$options{'pvcs-dirs-flat'} and $fn =~ /^vcs$/i) 464102840Speter { 465102840Speter if ($options{verify} =~ /^locks$/ ) { 466102840Speter if ( -f $donefile_name ) { 467102840Speter print "Verified existence of lockfile $cd/$donefile_name." 468102840Speter . ( ($options{mode} =~ /^convert$/) ? " Skipping directory." : "" ) 469102840Speter . "\n" if ($options{verbose}); 470102840Speter next; 471102840Speter } elsif ( $options{mode} =~ /^verify$/ ) { 472102840Speter print "No lockfile found for $cd .\n"; 473102840Speter next; 474102840Speter } 475102840Speter } 476102840Speter 477102840Speter # else add the files in the vcs dir to our list of files to process 478102840Speter error_count 'warning', \$warnings, "Found two vcs dirs in directory $cd.\n" 479102840Speter if ($vcsdir and $options{warnings}); 480102840Speter 481102840Speter $vcsdir = $fn; 482102840Speter 483102840Speter unless ( ( opendir VCSDIR, $vcsdir ) and ( @files = readdir VCSDIR ) ) 484102840Speter { 485102840Speter error_count 'error', \$errors, "skipping directory &cd/$fn"; 486102840Speter next; 487102840Speter } 488102840Speter closedir VCSDIR; 489102840Speter 490102840Speter # and so we don't need to worry about where these 491102840Speter # files came from later... 492102840Speter foreach $file (@files) 493102840Speter { 494102840Speter push @pvcsarchives, "$vcsdir/$file" if (-f "$vcsdir/$file"); 495102840Speter } 496102840Speter 497102840Speter # don't want recursion here... 498102840Speter @pvcsarchives = grep !/^\.\.?$/, @pvcsarchives; 499102840Speter } 500102840Speter elsif ($fn !~ /^\.\.?$/) 501102840Speter { 502102840Speter next if (!$options{'rcs-dirs-flat'} and $fn =~ /^rcs$/i); 503102840Speter # include it in @subdir if it's not a parent directory 504102840Speter push(@subdirs,$fn); 505102840Speter } 506102840Speter } 507102840Speter # else if we are processing a flat arrangement of pvcs files... 508102840Speter elsif ($options{'pvcs-dirs-flat'} and -f $fn) 509102840Speter { 510102840Speter if ($options{verify} =~ /^locks$/) { 511102840Speter if ( -f $donefile_name) { 512102840Speter print "Found lockfile $cd/$donefile_name." 513102840Speter . ( ($options{mode} =~ /^convert$/) ? " Skipping directory." : "" ) 514102840Speter . "\n" if ($options{verbose}); 515102840Speter last; 516102840Speter } elsif ($options{mode} =~ /^verify$/) { 517102840Speter print "No lockfile found for $cd .\n"; 518102840Speter last; 519102840Speter } 520102840Speter } 521102840Speter # else add this to the list of files to process 522102840Speter push (@pvcsarchives, $fn); 523102840Speter } 524102840Speter } 525102840Speter 526102840Speter # print "pvcsarchives: " . join (", ", @pvcsarchives) . "\n"; 527102840Speter # print "subdirs: " . join (", ", @subdirs) . "\n"; 528102840Speter # hit_any_key; 529102840Speter 530102840Speter # for loop of subdirs 531102840Speter foreach (@subdirs) 532102840Speter { 533102840Speter # run execdir on each sub dir 534102840Speter if ($maxlevel >= $curlevel) 535102840Speter { 536102840Speter my ($e, $w) = execdir ($_); 537102840Speter $errors += $e; 538102840Speter $warnings += $w; 539102840Speter } 540102840Speter } 541102840Speter 542102840Speter # Print output header for each directory 543102840Speter print("Directory: $cd\n"); 544102840Speter 545102840Speter # the @files variable should already contain the list of files 546102840Speter # we should attempt to process 547102840Speter if ( @pvcsarchives && ( $options{mode} =~ /^convert$/ ) ) 548102840Speter { 549102840Speter # create an RCS directory in parent to store RCS files in 550102840Speter if ( !( $options{'rcs-dirs-flat'} or (-d "RCS") or mkpath ( "RCS" ) ) ) 551102840Speter { 552102840Speter error_count 'error', \$errors, "failed to make directory $cd/RCS - skipping directory $cd"; 553102840Speter @pvcsarchives = (); 554102840Speter # after all, we have nowhere to put them... 555102840Speter } 556102840Speter } 557102840Speter 558102840Speter # begin a for loop to execute on each filename in the list @files 559102840Speter foreach $pvcsarchive (@pvcsarchives) 560102840Speter { 561102840Speter my $got_workfile = 0; 562102840Speter my $got_version_labels = 0; 563102840Speter my $got_description = 0; 564102840Speter my $got_rev_count = 0; 565102840Speter 566102840Speter my $abs_file = $cd . "/" . $pvcsarchive; 567102840Speter 568102840Speter print("Verifying $abs_file...\n") if ($options{verbose}); 569102840Speter 570102840Speter print "vlog $pvcsarchive\n"; 571102840Speter my $vlog_output = `vlog $pvcsarchive`; 572102840Speter $_ = $vlog_output; 573102840Speter 574102840Speter # Split the vcs status output into individual lines 575102840Speter my @vlog_strings = split /\n/; 576102840Speter my $num_vlog_strings = @vlog_strings; 577102840Speter $_ = $vlog_strings[0]; 578102840Speter if ( /^\s*$/ || /^vlog: warning/ ) 579102840Speter { 580102840Speter error_count 'warning', \$warnings, "$abs_file is NOT a valid PVCS archive!!!\n"; 581102840Speter next; 582102840Speter } 583102840Speter 584102840Speter my $num; 585102840Speter # Collect all vlog output into appropriate variables 586102840Speter # 587102840Speter # This will ignore at the very least the /^\s*Archive:\s*/ field 588102840Speter # and maybe more. This should not be a problem. 589102840Speter for ( $num = 0; $num < $num_vlog_strings; $num++ ) 590102840Speter { 591102840Speter # print("$vlog_strings[$num]\n"); 592102840Speter $_ = $vlog_strings[$num]; 593102840Speter 594102840Speter if( ( /^Workfile:\s*/ ) && (!$got_workfile ) ) 595102840Speter { 596102840Speter my $num_fields; 597102840Speter 598102840Speter $got_workfile = 1; 599102840Speter # get the string to the right of the above search (with any path stripped) 600102840Speter $workfile = $'; 601102840Speter $_ = $workfile; 602102840Speter $num_fields = split /[\/\\]/; 603102840Speter if ( $num_fields > 1 ) 604102840Speter { 605102840Speter $workfile = $_[$num_fields - 1 ]; 606102840Speter } 607102840Speter 608102840Speter $rcsarchive = $options{'rcs-dirs-flat'} ? "" : "RCS/"; 609102840Speter $rcsarchive .= $workfile; 610102840Speter $rcsarchive .= $options{'rcs-extension'} if ($options{'rcs-extension'}); 611102840Speter print "Workfile is $workfile\n" if ($options{debug}); 612102840Speter } 613102840Speter 614102840Speter elsif ( ( /^Rev count:\s*/ ) && (!$got_rev_count ) ) 615102840Speter { 616102840Speter $got_rev_count = 1; 617102840Speter # get the string to the right of the above search 618102840Speter $rev_count = $'; 619102840Speter print "Revision count is $rev_count\n"; 620102840Speter } 621102840Speter 622102840Speter elsif ( ( /^Version labels:\s*/ ) && (!$got_version_labels ) ) 623102840Speter { 624102840Speter $got_version_labels = 1; 625102840Speter $first_vl = $num+1; 626102840Speter print "Version labels start at $first_vl\n" if ($options{debug}); 627102840Speter } 628102840Speter 629102840Speter elsif ( ( /^Description:\s*/ ) && (!$got_description ) ) 630102840Speter { 631102840Speter $got_description = 1; 632102840Speter $description = "\"" . $vlog_strings[$num+1] . "\""; 633102840Speter print "Description is $description\n" if ($options{debug}); 634102840Speter $last_vl = $num - 1; 635102840Speter } 636102840Speter 637102840Speter elsif ( /^Rev\s+/ ) # get all the revision information at once 638102840Speter { 639102840Speter $rev_index = 0; 640102840Speter @rev_num = (); 641102840Speter while ( $rev_index < $rev_count ) 642102840Speter { 643102840Speter $_ = $vlog_strings[$num]; 644102840Speter /^\s*Rev\s+(\d+\.(\d+\.\d+\.)*\d+)$/; 645102840Speter $rev_num[$rev_index] = $1; 646102840Speter print "Found revision: $rev_num[$rev_index]\n" if ($options{debug}); 647102840Speter die "Not a valid revision ($rev_num[$rev_index]).\n" 648102840Speter if ($rev_num[$rev_index] !~ /^(\d+\.)(\d+\.\d+\.)*\d+$/); 649102840Speter 650102840Speter $_ = $vlog_strings[$num+1]; 651102840Speter /^\s*Locked\s*/ and $num++; 652102840Speter 653102840Speter $_ = $vlog_strings[$num+1]; 654102840Speter /^\s*Checked in:\s*/; 655102840Speter $checked_in{$rev_num[$rev_index]} = "\"" . $' . "\""; 656102840Speter print "Checked in: $checked_in{$rev_num[$rev_index]}\n" if ($options{debug}); 657102840Speter 658102840Speter $_ = $vlog_strings[$num+3]; 659102840Speter /^\s*Author id:\s*/; 660102840Speter split; 661102840Speter $author{$rev_num[$rev_index]} = "\"" . $_[2] . "\""; 662102840Speter print "Author: $author{$rev_num[$rev_index]}\n" if ($options{debug}); 663102840Speter 664102840Speter my @branches = (); 665102840Speter $_ = $vlog_strings[$num+1]; 666102840Speter if (/^\s*Branches:\s*/) 667102840Speter { 668102840Speter $num++; 669102840Speter @branches = split /\s+/, $'; 670102840Speter } 671102840Speter 672102840Speter $relative_comment_index = 0; 673102840Speter @comment_string = (); 674102840Speter while( ( ( $num + 4 + $relative_comment_index ) < @vlog_strings) 675102840Speter && ( $vlog_strings[$num+4+$relative_comment_index] 676102840Speter !~ /^\s*Rev\s+(\d+\.(\d+\.\d+\.)*\d+)$/ ) ) 677102840Speter { 678102840Speter # We need the \n added for multi-line comments. There is no effect for 679102840Speter # single-line comments since RCS inserts the \n if it doesn't exist already 680102840Speter # print "Found commment line: $vlog_strings[$num+4+$relative_comment_index]\n" 681102840Speter # if ($options{debug}); 682102840Speter push @comment_string, $vlog_strings[$num+4+$relative_comment_index], "\n"; 683102840Speter $relative_comment_index += 1; 684102840Speter } 685102840Speter # print "Popped from comment: " . join ("", splice (@comment_string, -2)) 686102840Speter # . "\n" 687102840Speter # if ($options{debug}); 688102840Speter # Pop the "-+" or "=+" line from the comment 689102840Speter while ( (pop @comment_string) !~ /^-{35}|={35}$/ ) 690102840Speter {} 691102840Speter $comment{$rev_num[$rev_index]} = join "", @comment_string; 692102840Speter 693102840Speter $num += ( 4 + $relative_comment_index ); 694102840Speter print "Got comment for $rev_num[$rev_index]\n" if ($options{debug}); 695102840Speter print "comment string: $comment{$rev_num[$rev_index]}\n" if ($options{debug}); 696102840Speter $rev_index += 1; 697102840Speter } # while ( $rev_index < $rev_count ) 698102840Speter $num -= 1; #although there should be nothing left for this to matter 699102840Speter } # Get Rev information 700102840Speter } # for ($num = 0; $num < $num_vlog_strings; $num++) 701102840Speter # hit_any_key if ($options{debug}); 702102840Speter # Create RCS revision numbers corresponding to PVCS version numbers 703102840Speter foreach $revision (@rev_num) 704102840Speter { 705102840Speter $rcs_rev_num{ $revision } = &pvcs_to_rcs_rev_number( $revision ); 706102840Speter print"PVCS revision is $revision; RCS revision is $rcs_rev_num{ $revision }\n" 707102840Speter if ($options{debug}); 708102840Speter } 709102840Speter 710102840Speter # Sort the revision numbers - PVCS and RCS store them in different orders 711102840Speter # Clear @_ so we don't pass anything in by accident... 712102840Speter @_ = (); 713102840Speter @rev_num = sort revisions @rev_num; 714102840Speter print "Sorted rev_nums:\n" . join ("\n", @rev_num) . "\n" if ($options{debug}); 715102840Speter # hit_any_key; 716102840Speter 717102840Speter # Loop through each version label, checking for need to relabel ' ' with '_'. 718102840Speter $num_version_labels = $last_vl - $first_vl + 1; 719102840Speter print "Version label count is $num_version_labels\n"; 720102840Speter for( $i = $first_vl; $i <= $last_vl; $i += 1 ) 721102840Speter { 722102840Speter # print("$vlog_strings[$i]\n"); 723102840Speter $label_index = $i - $first_vl; 724102840Speter $_=$vlog_strings[$i]; 725102840Speter print "Starting with string '$_'\n" if ($options{debug}); 726102840Speter split /\"/; 727102840Speter $label = $_[1]; 728102840Speter print "Got label '$label'\n" if ($options{debug}); 729102840Speter split /\s+/, $_[2]; 730102840Speter $label_revision[$label_index] = $_[2]; 731102840Speter print "Original label is $label_revision[$label_index]\n" if ($options{debug}); 732102840Speter 733102840Speter # Create RCS revision numbers corresponding to PVCS version numbers by 734102840Speter # adding 1 to the revision number (# after last .) 735102840Speter $label_revision[ $label_index ] = pvcs_to_rcs_rev_number( $label_revision [ $label_index ] ); 736102840Speter # replace ' ' with '_', if needed 737102840Speter $_=$label; 738102840Speter $new_label[$label_index] = $label; 739102840Speter $new_label[$label_index] =~ s/ /_/g; 740102840Speter $new_label[$label_index] =~ s/\./_/g; 741102840Speter $new_label[$label_index] = "\"" . $new_label[$label_index] . "\""; 742102840Speter print"Label $new_label[$label_index] is for revision $label_revision[$label_index]\n" if ($options{debug}); 743102840Speter } 744102840Speter 745102840Speter ########## 746102840Speter # 747102840Speter # See if the RCS archive is up to date with the PVCS archive 748102840Speter # 749102840Speter ########## 750102840Speter if ($options{verify} =~ /^locks|exists$/ and -f $rcsarchive) 751102840Speter { 752102840Speter print "Verified existence of $cd/$rcsarchive." 753102840Speter . ( ($options{mode} =~ /^convert$/) ? " Skipping." : "" ) 754102840Speter . "\n" if ($options{verbose}); 755102840Speter next; 756102840Speter } 757102840Speter 758102840Speter # Create RCS archive and check in all revisions, then label. 759102840Speter my $first_time = 1; 760102840Speter foreach $revision (@rev_num) 761102840Speter { 762102840Speter # print "get -p$revision $pvcsarchive >$workfile\n"; 763102840Speter print "get -r$revision $pvcsarchive\n"; 764102840Speter # $vcs_output = `vcs -u -r$revision $pvcsarchive`; 765102840Speter # $get_output = `get -p$revision $pvcsarchive >$workfile`; 766102840Speter $get_output = `get -r$revision $pvcsarchive`; 767102840Speter 768102840Speter # if this is the first time, delete the rcs archive if it exists 769102840Speter # need for $options{verify} == none 770102840Speter unlink $rcsarchive if ($first_time and $options{verify} =~ /^none$/ and -f $rcsarchive); 771102840Speter 772102840Speter # Also check here whether this file ought to be "binary" 773102840Speter if ( $first_time ) 774102840Speter { 775102840Speter $rcs_command = "$rcs_base_command -i"; 776102840Speter if ( ( @hits = grep { $workfile =~ /$_/ } keys %bin_ext ) || $options{'force-binary'} ) 777102840Speter { 778102840Speter $rcs_command .= " -kb"; 779102840Speter $workfile =~ /$hits[0]/ if (@hits); 780102840Speter print "Binary attribute -kb added (" 781102840Speter . (@hits ? "file type is '$bin_ext{$hits[0]}' for extension '$&'" : "forced") 782102840Speter . ")\n"; 783102840Speter } 784102840Speter $first_time and $ci_command .= " -t-$description"; 785102840Speter 786102840Speter $rcs_command .= " $workfile"; 787102840Speter 788102840Speter # print and execute the rcs archive initialization command 789102840Speter print "$rcs_command\n"; 790102840Speter $wtr = new IO::File "|$rcs_command"; 791102840Speter $wtr->print ($description); 792102840Speter $wtr->print ("\n") unless ($description =~ /\n$/s); 793102840Speter $wtr->print (".\n"); 794102840Speter $wtr->close; 795102840Speter 796102840Speter # $rcs_output = `$rcs_base_command -i -kb $workfile`; 797102840Speter } 798102840Speter 799102840Speter # if this isn't the first time, we need to lock the rcs branch 800102840Speter # 801102840Speter # This is a little messy, but it works. Some extra locking is attempted. 802102840Speter # (This happens the first time a branch is used, at the least) 803102840Speter my $branch = ""; 804102840Speter my @branch; 805102840Speter @branch = split /\./, $rcs_rev_num{$revision}; 806102840Speter pop @branch; 807102840Speter $branch = join ".", @branch; 808102840Speter 809102840Speter $rcs_output = `$rcs_base_command -l$branch $workfile` if (!$first_time); 810102840Speter 811102840Speter # If an empty comment is specified, RCS will not check in the file; 812102840Speter # check for this case. (but an empty -t- description is fine - go figure!) 813102840Speter # Since RCS will pause and ask for a comment if one is not given, 814102840Speter # substitute a dummy comment "no comment". 815102840Speter $comment{$revision} =~ /^\s*$/ and $comment{$revision} = "no comment\n"; 816102840Speter 817102840Speter $ci_command = $ci_base_command; 818102840Speter $ci_command .= " -f -r$rcs_rev_num{$revision} -d$checked_in{$revision}" 819102840Speter . " -w$author{$revision}"; 820102840Speter 821102840Speter $ci_command .= " $workfile"; 822102840Speter 823102840Speter # print and execute the ci command 824102840Speter print "$ci_command\n"; 825102840Speter $wtr = new IO::File "|$ci_command"; 826102840Speter $wtr->print ($comment{$revision}); 827102840Speter $wtr->print ("\n") unless ($comment{$revision} =~ /\n$/s); 828102840Speter $wtr->print (".\n"); 829102840Speter $wtr->close; 830102840Speter # $ci_output = `$ci_command`; 831102840Speter # $ci_output = `cat $tmpdir/ci.out`; 832102840Speter 833102840Speter $first_time = 0 if ($first_time); 834102840Speter } # foreach revision 835102840Speter 836102840Speter # Attach version labels 837102840Speter for( $i = $num_version_labels - 1; $i >= 0; $i -= 1 ) 838102840Speter { 839102840Speter # print "rcs -x,v -n$new_label[$i]:$label_revision[$i] $workfile\n"; 840102840Speter $rcs_output = `$rcs_base_command -n$new_label[$i]:$label_revision[$i] $workfile`; 841102840Speter print "Version label $new_label[$i] added to revision $label_revision[$i]\n"; 842102840Speter } # foreach label 843102840Speter 844102840Speter # hit_any_key; 845102840Speter } # foreach pvcs archive file 846102840Speter 847102840Speter # We processed a vcs directory, so if there were any files, lock it. 848102840Speter # We are guaranteed to have made the attempt at 849102840Speter # 850102840Speter # $skipdirlock gets set if a single file name was passed to this function to enable 851102840Speter # a '$0 *' operation... 852102840Speter if ( @pvcsarchives && !$skipdirlock) 853102840Speter { 854102840Speter my $fh = new IO::File ">>$donefile_name" or new IO::File ">$donefile_name"; 855102840Speter if ($fh) 856102840Speter { 857102840Speter $fh->close; 858102840Speter } 859102840Speter else 860102840Speter { 861102840Speter error_count 'error', \$errors, "couldn't create lockfile $cd/$donefile_name"; 862102840Speter } 863102840Speter } 864102840Speter 865102840Speter $curlevel = $curlevel - 1; 866102840Speter 867102840Speter chdir $old_dir or die "Failed to restore original directory ($old_dir): ", $!, ", stopped"; 868102840Speter return ($errors, $warnings); 869102840Speter } 870102840Speter 871102840Speter 872102840Speter 873102840Speter# 874102840Speter# This function effectively does a cmp between two revision numbers 875102840Speter# It is intended to be passed into Perl's sort routine. 876102840Speter# 877102840Speter# the pvcs_out is not implemented well. It should probably be 878102840Speter# returnning $b[0] <=> $a[0] rather than $a[0] <=> $b[0] 879102840Speter# 880102840Speter# The @_ argument implementation was going to be used for revision 881102840Speter# comparison as an aid to remove the /^\sRev/ in revision comment 882102840Speter# error. The effort was fruitless at the time. 883102840Spetersub revisions 884102840Speter { 885102840Speter my @a = split /\./, (defined $a) ? $a : shift; 886102840Speter my @b = split /\./, (defined $b) ? $b : shift; 887102840Speter my $function = @_ ? shift : 'rcs_in'; 888102840Speter my ($i, $ret_val); 889102840Speter 890102840Speter die "Not enough arguments to revisions : a = ", join (".", @a), 891102840Speter "; b = ", join (".", @b), ", stopped" 892102840Speter unless (@a and @b); 893102840Speter 894102840Speter for ($i = 0; $i < scalar( @a ) && $i < scalar( @b ); $i++) 895102840Speter { 896102840Speter $a[$i] == $b[$i] or return ($a[$i] <=> $b[$i]); 897102840Speter } 898102840Speter 899102840Speter return 0 if (scalar (@a) == scalar (@b)); 900102840Speter 901102840Speter if ($function eq 'rcs_in') 902102840Speter { 903102840Speter return (($i == @b) || -1); 904102840Speter } 905102840Speter elsif ($function eq 'pvcs_out') 906102840Speter { 907102840Speter return (($i == @a) || -1); 908102840Speter } 909102840Speter else 910102840Speter { 911102840Speter die "error - Invalid function type passed to revisions ($function)", ", stopped"; 912102840Speter } 913102840Speter } 914102840Speter 915102840Speter 916102840Speter 917102840Spetersub pvcs_to_rcs_rev_number 918102840Speter { 919102840Speter my($input, $num_fields, @rev_string, $return_rev_num, $i); 920102840Speter 921102840Speter $input = $_[0]; 922102840Speter $_ = $input; 923102840Speter $num_fields = split /\./; 924102840Speter @rev_string = @_; 925102840Speter # @rev_string[$num_fields-1] += 1; 926102840Speter 927102840Speter for( $i = 1; $i < $num_fields; $i += 1 ) 928102840Speter { 929102840Speter if ( $i % 2 ) 930102840Speter { 931102840Speter # DRP: 10/1 932102840Speter # RCS does not allow revision zero 933102840Speter $rev_string[ $i ] += 1; 934102840Speter } 935102840Speter elsif ( $i ) 936102840Speter { 937102840Speter # DRP: 10/1 938102840Speter # Branches must have even references for compatibility 939102840Speter # with CVS's magic branch numbers. 940102840Speter # (Indexes 2, 4, 6...) 941102840Speter $rev_string[ $i ] *= 2; 942102840Speter } 943102840Speter } 944102840Speter 945102840Speter # If this is a branch revision # (PVCS: a.b.c.*) then we want the CVS 946102840Speter # revision # instead. It's okay to do this conversion here since we 947102840Speter # never commit to branches. We'll only get a PVCS revision # in that 948102840Speter # form when looking through the revision labels. 949102840Speter if ($input =~ /\*$/) 950102840Speter { 951102840Speter pop @rev_string; 952102840Speter push @rev_string, splice (@rev_string, -1, 1, "0"); 953102840Speter } 954102840Speter 955102840Speter $return_rev_num = join ".", @rev_string; 956102840Speter return $return_rev_num; 957102840Speter } 958102840Speter 959102840Speter 960102840Speter 961102840Speter 962102840Speter 963102840Speter### 964102840Speter### 965102840Speter### 966102840Speter### 967102840Speter### 968102840Speter### MAIN program: checks to see if there are command line parameters 969102840Speter### 970102840Speter### 971102840Speter### 972102840Speter### 973102840Speter### 974102840Speter 975102840Speter 976102840Speter 977102840Speter 978102840Speter 979102840Speter# and read the options 980102840Speterdie $usage unless GetOptions (\%options, "h|help" => \&exit_help, 981102840Speter "recurse!", "mode|m=s", "errorfiles!", "l", "rcs-dirs|rcs-directories|r=s", 982102840Speter "pvcs-dirs|pvcs-directories|p=s", "test-binaries|t!", 983102840Speter "rcs-extension=s", "verify|v=s", "vcsid|i=s", "verbose!", "debug!", 984102840Speter "force-binary!", "cvs-branch-labels!", "warnings|w!"); 985102840Speter 986102840Speter 987102840Speter 988102840Speter# 989102840Speter# Special processing for -l !^#%$^@#$%#$ 990102840Speter# 991102840Speter# At the moment, -l overrides --recurse, regardless of the order the 992102840Speter# options were passed in 993102840Speter# 994102840Speter$options{recurse} = 0 if defined $options{l}; 995102840Speterdelete $options{l}; 996102840Speter 997102840Speter 998102840Speter 999102840Speter# Make sure we got acceptable values for rcs-dirs and pvcs-dirs 1000102840Spetermy @hits = grep /^$options{'rcs-dirs'}/i, ("leaf", "flat"); 1001102840Speter@hits == 1 or die 1002102840Speter "$0: $options{'rcs-dirs'} invalid argument to --rcs-dirs or ambiguous\n" 1003102840Speter . " abbreviation.\n" 1004102840Speter . " Must be one of: 'leaf' or 'flat'.\n" 1005102840Speter . $usage; 1006102840Speter$options{'rcs-dirs'} = $hits[0]; 1007102840Speter$options{'rcs-dirs-flat'} = ($options{'rcs-dirs'} =~ /flat/); 1008102840Speterdelete $options{'rcs-dirs'}; 1009102840Speter 1010102840Speter@hits = grep /^$options{'pvcs-dirs'}/i, ("leaf", "flat"); 1011102840Speter@hits == 1 or die 1012102840Speter "$0: $options{'pvcs-dirs'} invalid argument to --pvcs-dirs or ambiguous\n" 1013102840Speter . " abbreviation.\n" 1014102840Speter . " Must be one of: 'leaf' or 'flat'.\n" 1015102840Speter . $usage; 1016102840Speter$options{'pvcs-dirs'} = $hits[0]; 1017102840Speter$options{'pvcs-dirs-flat'} = ($options{'pvcs-dirs'} =~ /flat/); 1018102840Speterdelete $options{'pvcs-dirs'}; 1019102840Speter 1020102840Speter# and for verify 1021102840Speter@hits = grep /^$options{verify}/i, ("none", "locks", "exists", "lockdates", "revs", "full"); 1022102840Speter@hits == 1 or die 1023102840Speter "$0: $options{verify} invalid argument to --verify or ambiguous\n" 1024102840Speter . " abbreviation.\n" 1025102840Speter . " Must be one of: 'none', 'locks', 'exists', 'lockdates', 'revs',\n" 1026102840Speter . " or 'full'.\n" 1027102840Speter . $usage; 1028102840Speter$options{verify} = $hits[0]; 1029102840Speter$options{verify} =~ /^none|locks|exists$/ or die 1030102840Speter "$0: --verify=$options{verify} unimplemented.\n" 1031102840Speter . $usage; 1032102840Speter 1033102840Speter# and mode 1034102840Speter@hits = grep /^$options{mode}/i, ("convert", "verify"); 1035102840Speter@hits == 1 or die 1036102840Speter "$0: $options{mode} invalid argument to --mode or ambiguous abbreviation.\n" 1037102840Speter . " Must be 'convert' or 'verify'.\n" 1038102840Speter . $usage; 1039102840Speter$options{mode} = $hits[0]; 1040102840Speter 1041102840Speter$options{'cvs-branch-labels'} or die 1042102840Speter "$0: RCS Branch Labels unimplemented.\n" 1043102840Speter . $usage; 1044102840Speter 1045102840Speter# export VCSID into th environment for ourselves and our children 1046102840Speter$ENV{VCSID} = $options{vcsid}; 1047102840Speter 1048102840Speter 1049102840Speter 1050102840Speter# 1051102840Speter# Verify we have all the binary executables we need to run this script 1052102840Speter# 1053102840Speter# Allowed this feature to be disabled in case which is missing or we are 1054102840Speter# running on a system which does not return error codes properly (e.g. WIN95) 1055102840Speter# 1056102840Speter# -- i.e. I don't feel like grepping output yet. -- 1057102840Speter# 1058102840Spetermy @missing_binaries = (); 1059102840Speterif ($options{'test-binaries'}) 1060102840Speter { 1061102840Speter foreach (@bin_dependancies) 1062102840Speter { 1063102840Speter if (system "which", $_) 1064102840Speter { 1065102840Speter push @missing_binaries, $_; 1066102840Speter } 1067102840Speter } 1068102840Speter 1069102840Speter if (scalar @missing_binaries) 1070102840Speter { 1071102840Speter print STDERR "The following executables were not found in your PATH: " 1072102840Speter . join ( " ", @missing_binaries ) 1073102840Speter . "\n" 1074102840Speter . "You must correct this before continuing.\n"; 1075102840Speter exit 1; 1076102840Speter } 1077102840Speter } 1078102840Speterdelete $options{'test-binaries'}; 1079102840Speter 1080102840Speter 1081102840Speter 1082102840Speter# 1083102840Speter# set up our base archive manipulation commands 1084102840Speter# 1085102840Speter 1086102840Speter# set up our rcs_command mods 1087102840Speter$rcs_base_command = "rcs"; 1088102840Speter$rcs_base_command .= " -x$options{'rcs-extension'}" if ($options{'rcs-extension'}); 1089102840Speter 1090102840Speter# set up our rcs_command mods 1091102840Speter$ci_base_command = "ci"; 1092102840Speter$ci_base_command .= " -x$options{'rcs-extension'}" if ($options{'rcs-extension'}); 1093102840Speter 1094102840Speter 1095102840Speter 1096102840Speter# 1097102840Speter# So our logs fill in a manner we can monitor with 'tail -f' fairly easily: 1098102840Speter# 1099102840SpeterSTDERR->autoflush (1); 1100102840SpeterSTDOUT->autoflush (1); 1101102840Speter 1102102840Speter 1103102840Speter 1104102840Speter# Initialize the globals we use to keep track of recursion 1105102840Speterif ($options{recurse}) 1106102840Speter { 1107102840Speter $maxlevel = 10000; # Arbitrary recursion limit 1108102840Speter } 1109102840Speterelse 1110102840Speter { 1111102840Speter $maxlevel = 1; 1112102840Speter } 1113102840Speterdelete $options{recurse}; 1114102840Speter 1115102840Speter# So we can lock the directories behind us 1116102840Speter$donefile_name = $options{'rcs-dirs-flat'} ? "" : "RCS/"; 1117102840Speter$errorfile_name = $donefile_name . "#conv.errors"; 1118102840Speter$donefile_name .= "#conv.done"; 1119102840Speter 1120102840Speter 1121102840Speter 1122102840Speter# 1123102840Speter# start the whole thing and drop the return code on exit 1124102840Speter# 1125102840Speterpush (@ARGV, ".") unless (@ARGV); 1126102840Speterwhile ($_ = shift) 1127102840Speter { 1128102840Speter # reset the recursion level (corresponds to directory depth) 1129102840Speter # level 0 is the first directory we enter... 1130102840Speter $curlevel = -1; 1131102840Speter my ($e, $w) = execdir($_); 1132102840Speter $errors += $e; 1133102840Speter $warnings += $w; 1134102840Speter } 1135102840Speter 1136102840Speter 1137102840Speter 1138102840Speterprint STDERR "$0: " . ($errors ? "Aborted" : "Done") . ".\n"; 1139102840Speterprint STDERR "$0: "; 1140102840Speterprint STDERR ($errors ? $errors : "No") . " error" . (($errors != 1) ? "s" : ""); 1141102840Speterprint STDERR ", " . ($warnings ? $warnings : "no") . " warning" . (($warnings != 1) ? "s" : "") 1142102840Speter if ($options{warnings}); 1143102840Speterprint STDERR ".\n"; 1144102840Speter 1145102840Speter 1146102840Speter 1147102840Speter# 1148102840Speter# Woo-hoo! We made it! 1149102840Speter# 1150102840Speterexit $errors; 1151