bug-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

sccs2cvs.pl which supports branches, logs errors, etc.


From: Gloria Willadsen
Subject: sccs2cvs.pl which supports branches, logs errors, etc.
Date: Tue, 02 Sep 2003 10:50:26 -0400
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)

I wrote this about eight years ago. It has been thoroughly tested in several environments. Be sure to set the user configurable parameters in the first few pages of this script. Don't be afraid to run this a few times and overwrite your new repository until you are comfortable with exactly what this script does!

It assumes that one needs to rsh to an older machine supporting sccs.
It will rsh to that older machine, execute the sccs comand, and place the work files on shared disk space visible on both machines. It then runs the RCS commands locally, using work files in this shared space. The SCCS and CVS repositories dot not have to be on this shared disk for this script to execute.

Compiling RCS on the older machine, if possible, will avoid the need for an NFS mount, but will require changing the script everywhere the $SCCSCMD variable is used.
E-mail me (strangest@comcast.net) if you need advice on how to change this.

This script is recursive, and will, by default, traverse the SCCS directory provided. It take an optional third parameter, which is a file list. If it detects a file list, the list will be processed insead of the SCCS directory traversal. This is very handy for converting files which you could not access during the first run, because they were being edited under SCCS.

E-mail me with questions/comments!
Enjoy,
Gloria Willadsen
strangest@comcast.net
#!/usr/local/bin/perl
###############################################################################
# Tunable variables
###############################################################################

# RSH command, in case you need to run it elsewhere.
# NOTE: You'll need to NFS mount the RCSDIR to your SCCS machine, so you
# can "cd" to that cross-mounted file system and check files out onto it
# via rsh. If your RCS and SCCS commands run on the same machine, you don't
# have to worry about any of this. See $SCCSCMD below.

# Don't skip/skip conversion of files which are being edited by someone else.
# This feature is handy while you're testing this script.
$DONT_SKIPEDITS = 0;

# Don't skip errors on individual files.
$DONT_SKIPERRORS = 0;

# Don't prompt for descriptions for each file.
$DONT_PROMPT = 1;

# IF set to 1, a "cvs init" will be invoked in the CVSROOT.
$NEW_REPOSITORY = 0;

# When set to 1, this will run a plain "rcs -l" command on the file.
# Otherwise, you're trying to lock a specific revision (branch) of the file.
# The latter is problematic if your revision numbers skip from 
# X.Y to X.Y.Z.A. The  lock command will fail because X.Y.Z hasn't been 
# created yet (chicken/egg...can you say Buggg-Gawk!) 
# But this problem in branch number lapses has nothing to do with 
# branch locking, really. It is a logistical problem.
$TRUNK_LOCK_ALWAYS = 0;

# 1 = yes, 0 = no. if the RCS dir is not empty and a duplicate file is found
# during the initial RCS revision, an error will occur and the file will be 
# skipped. (ci -i) For files new to the RCS repository, no problems will occur.
$RCSDIR_MUST_BE_EMPTY = 0;

# This will cause the script to move 'v repository files out of all
# the annoying /RCS subdirectories in the RCS repository...highly recommended.
$MV_FILES_OUT_OF_RCS_DIR = 1;

# This lovely variable causes the script to remove the ,v file if it
# is found the first time a CVS checkin is executed. This should be on
# (set to 1) if you wish the existing ,v file to be removed before 
# checking-in other versions. If you are adding to the existing 
# repository file, and the new revision numbers haven't been used yet,
# you'll want to set this to 0 (off).
$REMOVE_REP_FILE_IF_FOUND_FIRSTTIME = 0;

# If this is set, make sure $REMOVE_REP_FILE_IF_FOUND_FIRSTTIME = 0 !
$ONLY_DO_BRANCHES = 1;

# Host name to which we should rshell
$RSH_HOST="any_host_name";

# Debug off=0, 1=on, 2=on automaticually due to an error
$DEBUG=1;

###############################################################################
# Nontunable variables...only touch if you know what you're doing!
###############################################################################
$PID = $$;
   
$tmpfile = "/tmp/sccs2cvs${PID}_tmp";
$emptyfile = "/tmp/sccs2cvs${PID}_empty";
$initialfile = "/tmp/sccs2cvs${PID}_init";
$logfile = "/tmp/sccs2cvs${PID}_log";
$statefile = "/tmp/sccs2cvs${PID}_failed_state";

# Files which this script will remove at the very end.
@tmplist = ($tmpfile,$emptyfile,$initialfile);

# State transition table, in order, reflects failed state.
$FileState{'GENERIC'} = "Error not related to a file";
$FileState{'FRSCCS'} = "Finding Revision info in SCCS";
$FileState{'COSCCS'} = "Checking out of SCCS";
$FileState{'LOCKRCS'} = "Locking in RCS";
$FileState{'CIRCS'} = "Checking into RCS (automatically unlocked)";
$FileState{'UESCCS'} = "\"Un\"checking out (unedited) from SCCS";
$FileState{'OFE'} = "Out for edit, not converted";
$FileState{'OTE'} = "Other oddity";

# Keyword arrays for conversion 
@sccs_keywords = (
   '%W%\s*%G%',
   '%W%\s*%E%',
   '%W%',
   '%Z%%M%\s*%I%\s*%G%',
   '%Z%%M%\s*%I%\s*%E%',
   '%M%\s*%I%\s*%G%',
   '%M%\s*%I%\s*%E%',
   '%M%',
   '%I%',
   '%G%',
   '%E%',
   '%U%');
   
@rcs_keywords = (
   '$Id$',
   '$Id$',
   '$Id$',
   '$SunId$',
   '$SunId$',
   '$Id$',
   '$Id$',
   '$RCSfile$',
   '$Revision$',
   '$Date$',
   '$Date$',
   '');
   
# Used for turning on/off debug automatically when skipping errors.
$OLDDEBUG = $DEBUG;

###############################################################################
# main code
###############################################################################
$SCCSBASE = $SCCSDIR = $ARGV[0];
$RCSBASE = $RCSDIR = $ARGV[1];
$FILELIST = $ARGV[2];

$THIS_SCRIPT = "$0" ;

if(("$SCCSDIR" eq "") || ("$RCSDIR" eq ""))
{
   &printAndLog("Usage: $THIS_SCRIPT sccs_top_dir rcs_top_dir(not including 
\"/RCS\") optional_file_list",0);
   exit -1;
}

if(!open(LOG,">$logfile"))
{
   # Fatal error
   $errmsg = "$!";
   print "********* ERROR: Cannot open $logfile for logging: $errmsg\n";
   exit 1;
}
   
&printAndLog("Current PID: $PID",0);
   
if(!open(INIT,">$initialfile"))
{
   # Fatal error
   $errmsg = "$!";
   &printAndLog("********* ERROR: Cannot open $initialfile for editing: $errmsg 
\n");
   exit 1;
}

print INIT "Initial revision, conversion from SCCS to RCS\n";
close(INIT);
   
if(! open(STATE,">$statefile")) 
{
   # Fatal error
   $errmsg = "$!";
   &printAndLog("********* ERROR: Cannot open $statefile for recording file 
failure state: $errmsg \n");
   exit 1;
}

print STATE "SCCS Repository Path               RCS Path                Failed 
State    Error\n";
print STATE "--------------------               --------                
------------    -----\n";
   
if(!open(EMP,">$emptyfile")) 
{
   # Fatal error
   $errmsg = "$!";
   &printAndLog("********* ERROR: Cannot open $emptyfile for editing: $errmsg 
\n");
   print STATE "-               -               $FileState{'OTE'}       $errmsg 
\n";
   exit 1;
}

print EMP "\n";
close(EMP);

$FINDCMD = "rsh $RSH_HOST \"cd $SCCSDIR \; find . -name \\\"p.*\\\" -print\"";

# "sccs tell" does not work recursively. Just find all "p." files.
&printAndLog("Running: find for all checked-out files: $FINDCMD\n",0);
@out = `$FINDCMD`;

@out_for_edit = grep(!/^\s*$/,@out);
@out = ();

foreach $file (@out_for_edit)
{
   chomp($file);
   $file =~ s/p\.//;
   &printAndLog("File $SCCSDIR/$file is already out for edit...can\'t convert 
this file.",0);
}

if(($DONT_SKIPEDITS == 1) && ($#out_for_edit >= 0))
{
   &printAndLog("Aborting. Not configured to skip edited files.",0);
   &exitGracefully();
}

if($NEW_REPOSITORY == 1)
{
   $result = `cvs -d $RCSDIR init 2>&1`; 
   if($? != 0)
   {
      &checkForError($SCCSCMD,$SCCSDIR,$RCSDIR,$FileState{'GENERIC'},"Failed to 
create directory $RCSDIR/CVSROOT",$?,$result,"");
      &exitGracefully();
   }
   &printAndLog("Created CVSROOT directory: $RCSDIR/CVSROOT",0);
}

&doConversion($SCCSDIR,$RCSDIR);

if($NEW_REPOSITORY == 1)
{
   # Clean up residual files if there are any
   chdir("$RCSDIR");
   `find \. \! -name \"*,v\" -exec rm -f \{\} \\\;`
}
   
&exitGracefully();

###############################################################################
# subroutines
###############################################################################
sub doConversion()
{
   my($SCCSDIR,$RCSDIR) = @_;
   my($cwd, $SCCSCMD,$file,@filelist,$element,$newdir);
   my($first_time_for_this_file,@revs,$rev,@whole_entry,$entry,$year,$author);
   my($lockrev,$date,$result,$adir,$bdir,@filelist,$relative_dir,$do_filelist);
   my(@lastnumlock);

   $cwd = `pwd`;
   chomp($cwd);
   
   if($RCSDIR !~ /^\//)
   {
      $RCSDIR = "$cwd/$RCSDIR";
   }
   
   if($RCSDIR =~ /\/SCCS/)
   {
      # Remove the SCCS component of this path. We won't need it anymore
      $RCSDIR = s/\/SCCS$//;
   }
   
   # Notice the missing double-quotes. This is intentional. Your command
   # using this prefix has to end in double-quotes so that rsh can pass the 
   # entire string.
   $SCCSCMD = "rsh $RSH_HOST \"cd $RCSDIR \; /usr/ucb/sccs -d$SCCSDIR -p./";
   
   
##############################################################################
   if(("$SCCSDIR" eq "") || ("$RCSDIR" eq ""))
   {
      &printAndLog("Usage: $THIS_SCRIPT sccs_top_dir rcs_top_dir(not including 
\"/RCS\") optional_file_list",0);
      &checkForError($SCCSCMD,$SCCSDIR,$RCSDIR,$FileState{'GENERIC'},"Usage: 
$THIS_SCRIPT sccs_top_dir rcs_top_dir(not including \"RCS\") 
optional_file_list",-1,"","");
   }
   
   if(! -d "$SCCSDIR")
   {
      &checkForError($SCCSCMD,$SCCSDIR,$RCSDIR,$FileState{'GENERIC'},"$SCCSDIR 
is not a valid directory",-1,"","");
   }
   
   if(! -d "${RCSDIR}/RCS")
   {
      $result = `mkdir -p -m775 $RCSDIR/RCS 2>&1`;
      
&checkForError($SCCSCMD,$SCCSDIR,"$RCSDIR/RCS",$FileState{'GENERIC'},"Failed to 
create directory $RCSDIR/RCS",$?,$result,"");

      # Down here if we were successful.
      &printAndLog("Created RCS directory: $RCSDIR/RCS",0);
   }
   elsif ((`ls -a $RCSDIR/RCS | wc -l` > 2) && ($RCSDIR_MUST_BE_EMPTY == 1))
   {
      &checkForError($SCCSCMD,$SCCSDIR,$RCSDIR,$FileState{'GENERIC'},"RCS 
directory $RCSDIR/RCS not empty. This script is not configured to continue if 
the RCS repository directory is not empty. Aborting.",-1,"","");
   }
   # We're down here if the user chooses to move ,v files out of each /RCS dir
   # when complete. We have to check for the pre-existing file in both places.
   elsif(($MV_FILES_OUT_OF_RCS_DIR == 1) && (`ls -a $RCSDIR | wc -l` > 2) && 
($RCSDIR_MUST_BE_EMPTY == 1))
   {
      &checkForError($SCCSCMD,$SCCSDIR,$RCSDIR,$FileState{'GENERIC'},"RCS 
directory $RCSDIR not empty. This script is not configured to continue if the 
RCS repository directory is not empty. Aborting.",-1,"","");
   }
   
   # Be in the directory above the new archive RCS directory.
   chdir("$RCSDIR");
   
   $do_filelist = 0;
   if($FILELIST eq "")
   {
      if(!opendir(SDIR,"$SCCSDIR"))
      {
         $errmsg = "$!";
         &checkForError($SCCSCMD,$SCCSDIR,$RCSDIR,$FileState{'OTE'},"Cannot 
read SCCS directory $SCCSDIR",-1,"$errmsg","");
      }
   
      @filelist = readdir(SDIR);
      closedir(SDIR);
   }
   else
   {
      if(!open(SLIST,"<$FILELIST"))
      {
         $errmsg = "$!";
         &checkForError($SCCSCMD,$SCCSDIR,$RCSDIR,$FileState{'OTE'},"Cannot 
open file list provided: $FILELIST",-1,"$errmsg","");
      }
   
      @filelist = <SLIST>;
      close(SLIST);

      # Reset this, since this script is recursive. Only read the file once.
      $FILELIST = "";
      $do_filelist = 1;
   }
   
   foreach $element (sort @filelist)
   {
      chomp($element);
      next if ($element =~ /^\.+$/);

      $element =~ s/\s*$//;
      $element =~ s/^\s//;

      if($do_filelist == 1)
      {
         @a = split('/',$element);
         $element = pop(@a);
         $relative_dir = join('/',@a);

         # Remove all absolute components from the file path.
         # We have to be able to handle absolute and relative paths.
         $adir = $RCSBASE;
         $bdir = $SCCSBASE;
         $adir =~ s/\//\\\//g;
         $bdir =~ s/\//\\\//g;

         $relative_dir =~ s/$adir\/?//;
         $relative_dir =~ s/$bdir\/?//;

         if($relative_dir =~ /^\s*$/)
         {
            $RCSDIR = "$RCSBASE";
            $SCCSDIR = "$SCCSBASE";
         }
         else
         {
            $RCSDIR = "$RCSBASE/$relative_dir";
            $SCCSDIR = "$SCCSBASE/$relative_dir";
         }
         $SCCSCMD = "rsh $RSH_HOST \"cd $RCSDIR \; /usr/ucb/sccs -d$SCCSDIR 
-p./";

         # Make the directory in case it doesn't exist. No error if it does.
         $result = `mkdir -p -m775 $RCSDIR/RCS 2>&1`;
         
&checkForError($SCCSCMD,$SCCSDIR,"$RCSDIR/RCS",$FileState{'GENERIC'},"Failed to 
create directory $RCSDIR/RCS",$?,$result,"");

         chdir($RCSDIR);

         # In case the user didn't put the s. prefix on the file name,
         # add it if this is a file (and not a directory).
         if(($element !~ /^s\./) && (! -d "$SCCSDIR/$element"))
         {
            $file = $element;
            $element = "s.${element}";
         }
         # Otherwise set $file as normal.
         else 
         {
            # May or may not be a file. We'll find out soon.
            $element =~ /^s\.(.*)$/;
            $file = $1;
         }
      }
      else
      {
         # May or may not be a file. We'll find out soon.
         $element =~ /^s\.(.*)$/;
         $file = $1;
      }

      @found_edited = grep(/^${file}$/,@out_for_edit);
      if($#found_edited >= 0)
      {
         &printAndLog("Found $file in list of files already checked out under 
SCCS.: < @found_edited >. Skipping this file.",0);
         print STATE "$SCCSDIR/$file            $RCSDIR/$file           
$FileState{'OFE'}       - \n";
         next;
      }

      if($element =~ /^s\.(.*)$/)
      {
         $first_time_for_this_file = 1;
   
         # Extract each rev for current file.
         &printAndLog("Running: $SCCSCMD prs $element \" | grep \"^D \" | awk 
\'{print \$2}\' | sed \'s/\\./ /g\' | sort -n -u +0 +1 +2 +3 +4 +5 +6 +7 +8 | 
sed \'s/ /./g\'\n",1);
         @revs = `$SCCSCMD prs $file \" | grep "^D " | awk '{print \$2}' | sed 
's/\\./ /g' | sort -n -u +0 +1 +2 +3 +4 +5 +6 +7 +8 | sed 's/ /./g'`;
   
         # Whoops...error condition occurred.
         if($revs[0] =~ /^\s*$/)
         {
            # Run the command again to grab the real error
            $errmsg = `$SCCSCMD prs $file \"`;
            
&checkForError($SCCSCMD,$SCCSDIR,$RCSDIR,$FileState{'FRSCCS'},"Found no 
revision info for file $file in $SCCSDIR",$?,"$errmsg","");
            next; # Next if this script is configured to continue upon error.
         }
   
         $error = 0;

         foreach $rev (@revs)
         {
            # Above set of code guarantees that @revs contains at least
            # one line of text.
            next if($rev =~ /^\s+$/);
            chomp ($rev);

            if(($rev !~ /\.\d+\.\d+/) && ($ONLY_DO_BRANCHES == 1))
            {
               &printAndLog("Skipping revision $rev, since we're only doing 
branches");
               $first_time_for_this_file = 0;
               next;
            }

            &printAndLog("Running: $SCCSCMD prs -r$rev $file \" | sed \'/\^\[   
      \]\*\$/d\'\n",1);
            @whole_entry = `$SCCSCMD prs -r$rev $file \" | sed '/\^\[   
\]\*\$/d'`;
            if($DEBUG >= 1)
            {
               $prscount = 0;
               foreach $a (@whole_entry)
               {
                  $prscount++;
                  &printAndLog("Results of prs, line count = $prscount : $a",0);
               }
            }

            $entry = "";
            $entry = shift(@whole_entry) while(($entry !~ 
/^[A-Z]\s+\d+(\.\d+)+\s+/) && ($#whole_entry >= 0));

            $entry =~ /(\d+)\/\d+\/\d+/;
            $year = $1;

            # If we didn't find the year, this record is bad!
            if($year =~ /^\s*$/)
            {
               $entry = join('\n',@whole_entry);
               &rshCheckForError($SCCSDIR,$RCSDIR,$FileState{'COSCCS'},"Failed 
to find proper revision info for $file from $SCCSDIR",-1,$entry,$file);
               next;
            }
    
            @entry = split(' ',$entry);
            $author = $entry[4]; 
   
            # Y2K Bug, change century to 20
            if ($year < 70)
            {
               $date = "20$entry[2] $entry[3]";
            }
            else
            {
               $date = "19$entry[2] $entry[3]";
            }
   
            &printAndLog("\n==> SCCS dir $SCCSDIR file $file, rev=$rev, 
date=$date, author=$author\n",0);
            &printAndLog("Running: $SCCSCMD edit -r$rev $file 2>&1 \"",1); 
            $result = `$SCCSCMD edit -r$rev $file 2>&1 \"`;
            &rshCheckForError($SCCSDIR,$RCSDIR,$FileState{'COSCCS'},"Failed to 
check out file $file from $SCCSDIR",$?,$result,$file);

            # This is necessary because rsh will place the file in your home 
dir.
            if(! open(SFILE,"<$RCSDIR/$file"))
            {
               $errmsg = "$!";
               
&checkForError($SCCSCMD,$SCCSDIR,$RCSDIR,$FileState{'OTE'},"Cannot open edited 
file $RCSDIR/$file, maybe the edit 
failed.",-1,"Edit:$result,\nFile:$errmsg",$file);

               next; # Next if this script is configured to continue upon error.
            }

            if(!open(TFILE,">$tmpfile"))
            {
               $errmsg = "$!";
               
&checkForError($SCCSCMD,$SCCSDIR,$RCSDIR,$FileState{'OTE'},"Cannot open 
temporary file $tmpfile",-1,$errmsg,$file);

               next; # Next if this script is configured to continue upon error.
            }

            &printAndLog("Running keyword replacement loop from file 
$RCSDIR/$file to file $tmpfile.",0);

            while(<SFILE>)
            {
               for($i=0; $i <= $#sccs_keywords; $i++)
               {
                  s/$sccs_keywords[$i]/$rcs_keywords[$i]/g;
               }
               print TFILE $_;
            }
            close(SFILE);
            close(TFILE);
   
            &printAndLog("Running: cp $tmpfile $RCSDIR/$file",1);
            `cp $tmpfile $RCSDIR/$file 2>&1`;
            unlink($tmpfile);
   
            # Get to the comments for ths rev.
            while(($#whole_entry >= 0) && ($whole_entry[0] !~ /^\s*COMMENTS:/))
            {
               shift(@whole_entry);
            }
            shift(@whole_entry);

            if(!open("CMTS",">$tmpfile"))
            {
               $errmsg = "$!";
               
&checkForError($SCCSCMD,$SCCSDIR,$RCSDIR,$FileState{'OTE'},"Cannot open 
temporary file $tmpfile for comments storage",-1,$errmsg,$file);
               next; # Next if this script is configured to continue upon error.
            }

            print CMTS "@whole_entry";
            close(CMTS);
            &printAndLog("\n==> Comments for file $file, rev=$rev: @whole_entry 
\n",0);
   
            if($first_time_for_this_file == 1)
            {
               $first_time_for_this_file = 0;

               if($REMOVE_REP_FILE_IF_FOUND_FIRSTTIME == 1)
               {
                  &printAndLog("Running: rm -f $RCSDIR/RCS/$file,v 
$RCSDIR/$file,v 2>&1",1);
                  $result = `rm -f $RCSDIR/RCS/$file,v $RCSDIR/$file,v 2>&1`;
               }
   
               if($DONT_PROMPT)
               {
                  &printAndLog("Running:  ** First Time ** ci -i -f -r$rev 
-d\"$date\" -w$author $RCSDIR/$file < $tmpfile 2>&1",1);
                  $result = `ci -i -f -r$rev -d"$date" -w$author $RCSDIR/$file 
< $tmpfile 2>&1`;
               }
               else
               {
                  print "Enter a brief description of the file $RCSDIR/$file 
(end w/ Ctrl-D):\n";
                  `cat > $tmpfile`;
   
                  &printAndLog("Running: ** First time** ci -i -f -r$rev 
-d\"$date\" -w$author $RCSDIR/$file < $tmpfile 2>&1",1);
                  $result = `ci -i -f -r$rev -d"$date" -w$author $RCSDIR/$file 
< $tmpfile 2>&1`;
               }
               $error = $?;
            }
            else # Not first time, entering subsequent revisions for same file.
            {
               $lockrev = $rev;
               # If the revision number has a branch, lock the branch. 
               # Otherwise just lock the file.
               if(($lockrev =~ /\.\d+\.\d+/) && ($TRUNK_LOCK_ALWAYS == 0))
               {
                  # Locking branches is a bit weird. You have to make sure that 
                  # it is not the first in a branch series (which requires 
                  # only a file-level lock). If it is not the first in a 
                  # branch series, figure out the previous number in this 
                  # branch series, and lock it!
                  @lastnumlock = split(/\./,$lockrev);
                  if($lastnumlock[$#lastnumlock] >= 2)
                  {
                     $lastnumlock[$#lastnumlock]--;
                     $lockrev = join('.',@lastnumlock);
                     &printAndLog("Running: rcs -l$lockrev $RCSDIR/$file 
2>&1",1);
                     $result = `rcs -l$lockrev $RCSDIR/$file 2>&1`;
                  }
                  else
                  {
                     &printAndLog("Running: rcs -l $RCSDIR/$file 2>&1",1);
                     $result = `rcs -l $RCSDIR/$file 2>&1`;
                  }
               }
               else
               {
                  &printAndLog("Running: rcs -l $RCSDIR/$file 2>&1",1);
                  $result = `rcs -l $RCSDIR/$file 2>&1`;
               }
               $error = $?;
   
               
&checkForError($SCCSCMD,$SCCSDIR,$RCSDIR,$FileState{'LOCKRCS'},"Failed to lock 
file $RCSDIR/$file lock rev $lockrev edited from 
$SCCSDIR",$error,$result,$file);
   
               &printAndLog("Running: ci -f -r$rev -d\"$date\" -w$author 
$RCSDIR/$file < $tmpfile 2>&1",1);
               $result = `ci -f -r$rev -d"$date" -w$author $RCSDIR/$file < 
$tmpfile 2>&1`;
   
               $error = $?;
            }

            # Clean-up after successful rev conversion.
            &doCleanup($SCCSCMD,"$file",$SCCSDIR,$RCSDIR);
         }
   
         &checkForError($SCCSCMD,$SCCSDIR,$RCSDIR,$FileState{'CIRCS'},"Failed 
to check in file $file from $SCCSDIR to $RCSDIR",$error,$result,$file);

         # Now make sure any residual locks are removed. I think permissions
         # cause strange residual locks to hang around.
         &printAndLog("Running: rcs -u $RCSDIR/$file 2>&1",1);
         $result = `rcs -u $RCSDIR/$file 2>&1`;
      }
      else # found directory or non-SCCS file
      {
         if(-d "$SCCSDIR/$element")
         {
            # Skip empty directories.
            if (`ls -a $SCCSDIR/$element | wc -l` <= 2)
            {
               &printAndLog("Empty directory: $SCCSDIR/$element, skipping 
it.",0);
               print STATE "$SCCSDIR/$element           -               
$FileState{'OTE'}       -1:Empty directory: $SCCSDIR/$element, skipping it. \n";
               next;
            }
    
            # Remove the SCCS component of this path. We won't need it anymore
            $newdir = "$RCSDIR/$element";
            $newdir =~ s/\/SCCS$//;

            $result = `mkdir -p -m775 $newdir 2>&1`;
            
&checkForError($SCCSCMD,$SCCSDIR,$RCSDIR,$FileState{'GENERIC'},"Failed to 
create directory $newdir",$?,$result,"");
            &printAndLog("Created subdirectory: $newdir",0);
   
            &printAndLog("Found directory $newdir, processing 
recursively...",0);
            &printAndLog("Running: doConversion($SCCSDIR/$element,$newdir)",1);
            &doConversion("$SCCSDIR/$element","$newdir");
         }
         else
         {
            &printAndLog("Found file $element, not an archive file. 
Skipping.",0);
            print STATE "$SCCSDIR/$element              -               
$FileState{'OTE'}       -1:Found file $element, not an archive file. Skipping. 
\n";
         }
      }
   }

   if($MV_FILES_OUT_OF_RCS_DIR == 1)
   {
      # Now move everything out of the RCS subdirectory just created.
      $result = `mv $RCSDIR/RCS/* $RCSDIR 2>&1`;
      &checkForError($SCCSCMD,$SCCSDIR,$RCSDIR,$FileState{'OTE'},"Failed to 
move files from $RCSDIR/RCS to $RCSDIR",$?,$result,"");
      $result = `rm -rf $RCSDIR/RCS 2>&1`;
   }
}

sub doCleanup() {
   # File name includes a relative path, assuming it's in PWD.
   my($SCCSCMD,$file,$SCCSDIR,$RCSDIR) = @_;

   &printAndLog("Running: $SCCSCMD unedit $file 2>&1 \"",0);
   `$SCCSCMD unedit $RCSDIR/$file 2>&1 \"`;

   &printAndLog("Removing file $RCSDIR/$file and residual RCS directory",0);
   # Try both commands. One isn't working.
   `rm -f $RCSDIR/$file $RCSDIR/RCS/$file $RCSDIR/RCS 2>&1`;
   unlink("$RCSDIR/$file");
   unlink("$RCSDIR/RCS");

   if("$SCCSDIR" ne "")
   {
      &printAndLog("Removing the \"p.\" file in case the unedit command failed: 
p.${file}",0);
      # Try both commands. One isn't working.
      `rm -f SCCSDIR/p.${file} 2>&1`;
      unlink("$SCCSDIR/p.${file}");
   }
}

sub checkForError() {
   my($SCCSCMD,$SCCSDIR,$RCSDIR,$State,$message,$error,$errmsg,$file) = @_;
   if($error != 0)
   {
      &printAndLog("********* ERROR: $message, errno $error, error: $errmsg. 
",0);
      print STATE "$SCCSDIR/$file               $RCSDIR/$file           $State  
$error:$errmsg\n";
      &doCleanup($SCCSCMD,$file,$SCCSDIR,$RCSDIR) if($file !~ /^\s*$/);

      if($DONT_SKIPERRORS == 1)
      {
         &printAndLog("Aborting.",0);
         &exitGracefully();
      }
      &printAndLog("Skipping file/error condition.",0);
      $DEBUG=2;
      $OLDDEBUG = $DEBUG;
   }
   elsif($DEBUG==2)
   {
      $DEBUG = $OLDDEBUG;
   }
}

sub rshCheckForError() {
   my($message,$error,$errmsg,$file) = @_;
   # Rsh will never return the proper return code, so rely on the grep().
   if(($error != 0) || (grep/[eE][rR][rR][oO][rR]/,$errmsg))
   {
      &printAndLog("********* ERROR: $message, errno $error, error: $errmsg. 
",0);
      &doCleanup($SCCSCMD,$file,$SCCSDIR,$RCSDIR) if($file !~ /^\s*$/);

      if($DONT_SKIPERRORS == 1)
      {
         &printAndLog("Aborting.");
         &exitGracefully();
      }
      &printAndLog("Skipping file/error condition.",0);
   }
}

sub printAndLog() {
   my($msg,$check_for_debug) = @_;

   if( (($check_for_debug == 1) && ($DEBUG == 1))
      || ($check_for_debug == 0))
   {
      print "$msg\n";
      print LOG "$msg\n";
   }
}

sub exitGracefully() {
   unlink(@tmplist);
   close(STATE);
   close(LOG);
   exit;
}

reply via email to

[Prev in Thread] Current Thread [Next in Thread]