]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/cvs/contrib/pvcs_to_rcs
unfinished sblive driver, playback/mixer only for now - not enabled in
[FreeBSD/FreeBSD.git] / contrib / cvs / contrib / pvcs_to_rcs
1 #! /opt/bin/perl5
2 #
3 # Beware of the fact that this script was not written to handle
4 # branches in the PVCS archives, but it might work nontheless.  I have
5 # a specific addition in this latest version that would not be
6 # globally useful: automatically making Framemaker files binary with
7 # -kb (regardless of the file extension).
8 # ---------------------------------
9 # This program is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 2, or (at your option)
12 # any later version.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 # GNU General Public License for more details.
18
19 ###########################################################################
20 # FUNCTION:
21 # To recursively walk through a PVCS archive directory tree (archives
22 # located in VCS/ or vcs/ subdirectories) and convert them to RCS archives.
23 # The RCS archive name is the PVCS workfile name with ",v" appended.
24 #
25 # SYNTAX:
26 # The calling syntax is:
27 # pvcs_to_rcs [-l]
28 #
29 # where -l indicates the operation is to be performed only in the current
30 # directory (no recursion)
31
32 # EXAMPLE:
33 # pvcs_to_rcs
34 #
35 # Would walk through every VCS or vcs subdir starting at the current directory,
36 # and produce corresponding RCS archives one level above the VCS or vcs subdir.
37 #
38 # NOTES:
39 # * This script does not perform any error checking or logging of any kind
40 #   (i.e. USE AT YOUR OWN RISK)
41 # * This script was developed using perl-5.003 on a Sun Solaris 2.5 machine
42 #   and executed from a csh
43 # * PVCS archives in VCS/ or vcs/ subdirectories are left intact
44 # * RCS archives are processed in the VCS/ or vcs/ subdirectories and
45 #   are moved (forcibly) up one level upon completion of the conversion
46 # * This script has *not* been tested with PVCS archives with branches,
47 #   although the only thing I believe that might need to be changed
48 #   is the ORDER of revision processing (e.g. you can't checkin 1.2.4.1 if
49 #   you haven't yet checked in 1.2).
50 # * All revisions are saved with correct "metadata" (i.e. check-in date,
51 #   author, and log message).  Any blank log message is replaced with
52 #   "no comment".  This is because RCS does not allow non-interactive
53 #   checkin of a new revision without a comment string.
54 # * Revision numbers are incremented by 1 during the conversion (since
55 #   RCS does not allow revision 1.0).
56 # * Version labels are assigned to the appropriate (incremented) revision
57 #   numbers.  PVCS allows spaces and periods in version labels while RCS
58 #   does not.  A global search and replace converts " " and "." to "_"
59 #   There may be other cases that ought to be added.
60 # * Any workfile within the VCS/ or vcs/ will be deleted (or overwritten)
61 #   since it is used in the checkout of each revision
62 # * Locks on PVCS archives should be removed (or the workfiles should be
63 #   checked-in) prior to conversion, although the script will blaze through
64 #   the archive nonetheless (But you would lose any checked out revision(s))
65 # * The -kb option is added to the RCS archive for workfiles with the following
66 #   extensions: .bin .out .btl .rom .a07 .lib .exe .tco .obj .t8u .c8u .o .lku
67 #########################################################################
68
69 require("getcwd.pl");
70
71 #NOTE:  Each possible binary extension is delimited by '.'
72 $bin_ext = 
73 ".bin.out.btl.rom.a07.lib.exe.tco.obj.t8u.c8u.o.lku.BIN.OUT.BTL.ROM.A07.LIB.EXE.TCO.OBJ
74 .T8U.C8U.O.LKU.";
75
76 # the main procedure that is run once in each directory
77 sub execdir
78 {
79   $curlevel= $curlevel +1;
80
81 #local sets the variables directory and prev directory local to the procedure
82
83   local($dir,$prevdir)=@_;
84
85 #change into the directory to be processed
86
87   chdir($dir);
88
89 #open the current directory for listing
90
91   opendir(CURDIR,".");
92
93 #initialize the list of filenames
94
95   local(@filenames);
96
97 #set filenames equal to directory listing
98
99   @filenames = readdir(CURDIR);
100
101 #clean up by closing the directory
102
103   closedir(CURDIR);
104
105 #initialize a list for any subdirectories
106   local(@subdirs);
107
108 #begin a for loop to execute on each filename in the list @filename
109   for (@filenames) 
110
111   {
112 #if the file is a directory...
113     if (-d $_) 
114     {
115 #include it in @subdir
116       push(@subdirs,$_);
117     }
118   }
119
120 #for loop of subdirs
121   for (@subdirs)
122 #if not a parent directory, run execdir on each sub dir
123   {
124     if (($_ ne '.') and ($_ ne '..') and ($maxlevel > $curlevel))
125     {
126       &execdir($_,$dir);
127     }
128   }
129
130 #save the current directory 
131   $cd = &getcwd;
132
133 #Print output header for each directory
134   print("Directory: $cd\n");
135
136 #determine the last directory in this path (to only process vcs or VCS)
137   $_ = $cd;
138   $num_dirs = split /\//;
139   @dirs = @_;
140   $last_dir = $dirs[$num_dirs-1];
141 #  print"Last directory is $last_dir\n";
142
143 #shell redirection: output from command in @ARGV is put in $output
144 # $output = `@ARGV`; 
145 #begin a for loop to execute on each filename in the list @filename
146   for (@filenames) 
147   {
148     if ( (-f $_) and ($_ ne '.') and ($_ ne '..') and ($maxlevel > $curlevel)
149          and ( ( $last_dir eq 'vcs' ) or ( $last_dir eq 'VCS' )  ) )
150     {
151       $got_archivefile = 0;
152       $got_workfile = 0;
153       $got_version_labels = 0;
154       $got_description = 0;
155       $got_rev_count = 0;
156       
157       $file = $_;
158       $abs_file = $cd . "/" . $file;
159       print("Converting $abs_file...\n");
160       $vlog_output = `vlog $_`;
161       $_ = $vlog_output;
162 # Split the cvs status output into individual lines
163       @vlog_strings = split /\n/;
164       $num_vlog_strings = @vlog_strings;
165       $_ = $vlog_string[0];
166       if ( /^vlog: warning/ )
167       {
168         print("$abs_file is NOT a valid PVCS archive!!!\n");
169       }
170       elsif( $vlog_output )
171       {
172
173 # Collect all vlog output into appropriate variables
174
175         $num = 0;
176         while( $num < $num_vlog_strings )
177         {
178 #          print("$vlog_strings[$num]\n");
179
180           $_ = $vlog_strings[$num];
181
182           if( ( /^Workfile:\s*/ ) && (!$got_workfile ) )
183           {
184             $got_workfile = 1;
185 # get the string to the right of the above search (with any path stripped)
186             $workfile = $';
187             $_=$workfile;
188             $num_fields = split /\//;
189             if ( $num_fields > 1 ) 
190             { 
191               $workfile = $_[$num_fields - 1 ];
192             }
193 #            print"Workfile is $workfile\n";
194           }
195
196           elsif( ( /^Archive:\s*/ ) && (!$got_archivefile ) )
197           {
198             $got_archivefile = 1;
199 # get the string to the right of the above search (with any path stripped)
200             $archivefile = $';
201             $_=$archivefile;
202             $num_fields = split /\//;
203             if ( $num_fields > 1 ) 
204             { 
205               $archivefile = $_[$num_fields - 1 ];
206             }
207 #            print"Archive is $archivefile\n";
208           }
209
210           elsif ( ( /^Rev count:\s*/ ) && (!$got_rev_count ) )
211           {
212             $got_rev_count = 1;
213 # get the string to the right of the above search
214             $rev_count = $';
215             print"Revision count is $rev_count\n";
216           }
217
218           elsif ( ( /^Version labels:\s*/ ) && (!$got_version_labels ) )
219           {
220             $got_version_labels = 1;
221             $first_vl = $num+1;
222           }
223
224           elsif ( ( /^Description:\s*/ ) && (!$got_description ) )
225           {
226             $got_description = 1;
227             $description = "\"" . $vlog_strings[$num+1] . "\"";
228 #            print"Description is $description\n";
229             $last_vl = $num - 1;
230           }
231
232           elsif ( /^Rev\s*/ ) # get all the revision information at once
233           {
234             $rev_index = 0;
235             while ( $rev_index < $rev_count )
236             {
237               $_=$vlog_strings[$num];
238               /^Rev\s*/;
239               $rev_num[$rev_index] = $';
240               $_=$vlog_strings[$num+1];
241               if ( /^Locked\s*/ )
242               {
243                 $num += 1;
244               }
245               $_=$vlog_strings[$num+1];
246               /^Checked in:\s*/;
247               $checked_in[$rev_index] = "\"" . $' . "\"";
248               $_=$vlog_strings[$num+3];
249               /^Author id:\s*/;
250               split;
251               $author[$rev_index] = "\"" . $_[2] . "\"";
252               $relative_comment_index = 0;
253               $comment_string = "";
254               while( ( $vlog_strings[$num+4+$relative_comment_index] ne
255                        "-----------------------------------" ) &&
256                      ( $vlog_strings[$num+4+$relative_comment_index] ne
257                        "===================================" ) )
258               {
259 # We need the \n added for multi-line comments.  There is no effect for
260 # single-line comments since RCS inserts the \n if it doesn't exist already
261                 $comment_string = $comment_string . 
262 $vlog_strings[$num+4+$relative_comment_index] . "\n";
263                 $relative_comment_index += 1;
264               }
265 # Convert any double quotes to an escaped double quote
266               $comment_string =~ s/\"/\\\"/g;
267               $comment[$rev_index] = "\"" . $comment_string . "\"";
268               $num += ( 5 + $relative_comment_index );
269               $rev_index += 1;
270             }
271             $num -= 1; #although there should be nothing left for this to matter
272           }
273
274           $num += 1;
275
276         }
277
278 # Loop through each version label, checking for need to relabel ' ' with '_'.
279         $num_version_labels = $last_vl - $first_vl + 1;
280         print"Version label count is $num_version_labels\n";
281         for( $i = $first_vl; $i <= $last_vl; $i += 1 )
282         {
283 #          print("$vlog_strings[$i]\n");
284           $label_index = $i - $first_vl;
285           $_=$vlog_strings[$i];
286           split /\"/;
287           $label = @_[1];
288           $_=@_[2];
289           split;
290           $label_revision[$label_index] = @_[1];
291
292 # Create RCS revision numbers corresponding to PVCS version numbers by
293 # adding 1 to the revision number (# after last .)
294           $rcs_rev = &pvcs_to_rcs_rev_number( $label_revision[$label_index]);
295           $label_revision[ $label_index ] = $rcs_rev;
296 # replace ' ' with '_', if needed
297           $_=$label;
298           $new_label[$label_index] = $label;
299           $new_label[$label_index] =~ s/ /_/g;
300           $new_label[$label_index] =~ s/\./_/g;
301           $new_label[$label_index] = "\"" . $new_label[$label_index] . "\"";
302 #          print"Label $new_label[$label_index] is for revision 
303 $label_revision[$label_index]\n";
304         }
305         
306 # Create RCS revision numbers corresponding to PVCS version numbers by
307 # adding 1 to the revision number (# after last .)
308
309         for( $i = 0; $i < $rev_count; $i += 1 )
310         {
311           $rcs_rev_num[ $i ] = &pvcs_to_rcs_rev_number( $rev_num[ $i ] );
312 #          print"PVCS is $rev_num[ $i ]; RCS is $rcs_rev_num[ $i ]\n"
313         }
314
315 # Create RCS archive and check in all revisions, then label.
316 # PVCS vlog lists revisions last-revision-first; reverse that ordering
317         $first_time = 1;
318
319         for( $i = $rev_count - 1; $i >= 0; $i -= 1 )
320         {
321           print "get -r$rev_num[$i] $archivefile\\($workfile\\)\n";
322 #          $vcs_output = `vcs -u -r$rev_num[$i] $file`;
323           $get_output = `get -r$rev_num[$i] $archivefile\\($workfile\\)`;
324           if( $first_time )
325           {
326             $first_time = 0;
327             $file_output = `file $workfile`;
328 # If an empty comment is specified, RCS will not check in the file;
329 # check for this case.  (but an empty -t- description is fine - go figure!)
330 # Since RCS will pause and ask for a comment if one is not given,
331 # substitute a dummy comment "no comment".
332             if ( $comment[$i] eq "\"\"" )
333             {
334               $ci_command = "ci -f -r$rcs_rev_num[$i] -d$checked_in[$i] -w$author[$i] 
335 -t-$description -m\"no comment\" $workfile";
336             }
337             else
338             {
339               $ci_command = "ci -f -r$rcs_rev_num[$i] -d$checked_in[$i] -w$author[$i] 
340 -t-$description -m$comment[$i] $workfile";
341             }
342             print "$ci_command\n";
343             $ci_output = `$ci_command`;
344
345 # Also check here whether this file ought to be "binary"
346             $_=$file_output;
347             split;
348             if( $_[1] eq "Frame" )
349             {
350               print"Binary attribute -kb added (file type is Frame)\n";
351               $rcs_output = `rcs -kb $workfile,v`;
352             }
353             else
354             {
355               $_=$workfile;
356               $num_fields = split /\./;
357               if ( $num_fields > 1 ) 
358               { 
359                 $ext = "." . $_[$num_fields - 1] . ".";
360                 if ( ( index $bin_ext, $ext ) > - 1 ) 
361                 {
362                   print"Binary attribute -kb added (file type is $ext)\n";
363                   $rcs_output = `rcs -kb $workfile,v`;
364                 }
365               }
366             }
367           }
368           else
369           {
370             $rcs_output = `rcs -l $workfile`;
371 # If an empty comment is specified, RCS will not check in the file;
372 # check for this case.  (but an empty -t- description is fine - go figure!)
373             if ( $comment[$i] eq "\"\"" )
374             {
375               $ci_command = "ci -f -r$rcs_rev_num[$i] -d$checked_in[$i] -w$author[$i] 
376 -m\"no comment\" $workfile";
377             }
378             else
379             {
380               $ci_command = "ci -f -r$rcs_rev_num[$i] -d$checked_in[$i] -w$author[$i] 
381 -m$comment[$i] $workfile";
382             }
383             print "$ci_command\n";
384             $ci_output = `$ci_command`;
385           } 
386         }
387 # Attach version labels
388         for( $i = $num_version_labels - 1; $i >= 0; $i -= 1 )
389         {
390 #          print "rcs -n$new_label[$i]:$label_revision[$i] $workfile\n";
391           $rcs_output = `rcs -n$new_label[$i]:$label_revision[$i] $workfile`;
392           print "Version label $new_label[$i] added to revision $label_revision[$i]\n";
393         }
394
395 # Move archive file up one directory level (above vcs/ or VCS/)
396         $mv_output = `mv -f $workfile",v" ..`;
397       }
398     }
399   }
400
401 #print the output to STDOUT
402 # print("$output");
403
404   $curlevel=$curlevel - 1;
405   if ($dir ne $prevdir)
406   {
407     chdir('..');
408   }
409 }
410
411 sub pvcs_to_rcs_rev_number
412 {
413   local($input, $num_fields, @rev_string, $return_rev_num, $i);
414
415   $input = @_[0];
416   $_ = $input;
417   $num_fields = split /\./;
418   @rev_string = @_;
419   @rev_string[$num_fields-1] += 1;
420   $return_rev_num = @rev_string[ 0 ];
421   for( $i = 1; $i < $num_fields; $i += 1 )
422   {
423     $return_rev_num = $return_rev_num . "." . @rev_string[ $i ];
424   }
425   return $return_rev_num;
426 }
427
428 ##MAIN program: checks to see if there are command line parameters
429 if ($#ARGV > 2) {
430
431 #if not then end and print help message
432 die "Usage: pvcsns [-l]\n"};
433 $curlevel=0-1;$maxlevel=10000;
434
435 if (@ARGV[0] eq "-l") {$maxlevel=1;shift @ARGV;}
436
437 #start the whole thing
438 &execdir(".",".");
439