root/juggler/branches/2.0_alpha_2/cvs-gather.pl

Revision 14567, 38.5 kB (checked in by patrickh, 5 years ago)

Updated to match the version used on the HEAD branch.

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1 #!/usr/bin/env perl
2
3 # ************** <auto-copyright.pl BEGIN do not edit this line> **************
4 #
5 # Doozer++ is (C) Copyright 2000-2003 by Iowa State University
6 #
7 # Original Author:
8 #   Patrick Hartling
9 #
10 # This library is free software; you can redistribute it and/or
11 # modify it under the terms of the GNU Library General Public
12 # License as published by the Free Software Foundation; either
13 # version 2 of the License, or (at your option) any later version.
14 #
15 # This library is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 # Library General Public License for more details.
19 #
20 # You should have received a copy of the GNU Library General Public
21 # License along with this library; if not, write to the
22 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 # Boston, MA 02111-1307, USA.
24 #
25 # *************** <auto-copyright.pl END do not edit this line> ***************
26
27 # cvs-gather.pl,v 1.31 2003/07/03 16:54:54 patrickh Exp
28
29 use 5.005;
30
31 use Cwd qw(chdir getcwd);
32 use File::Basename;
33 use File::Path;
34 use Getopt::Long;
35 use Pod::Usage;
36
37 use strict 'vars';
38 use vars qw($indent $log_file $full_path $debug_level $override $max_cvs_tries
39             $cvs_wait_length $cvs_wait_multiplier $cvs_wait_unit);
40 use vars qw($CRITICAL_LVL $WARNING_LVL $CONFIG_LVL $STATE_LVL $VERB_LVL
41             $HVERB_LVL $HEX_LVL);
42
43 # Subroutine prototypes.
44 sub printVersion();
45 sub parse($$);
46 sub parseModule($$$;$);
47 sub handleInclude($$$);
48 sub expandWildcardLine($$);
49 sub expandWildcards($$$$$);
50 sub doOverride($$);
51 sub overrideValue($$$);
52 sub checkoutModules($);
53 sub updateModule($$$$$$);
54 sub checkoutModule($$$$$$$);
55 sub runCvsCommand($);
56 sub modifyCvsEntries($$);
57 sub expandEnvVars($);
58 sub printDebug($@);
59 sub nextSpinnerFrame($);
60
61 # *********************************************************************
62 # Here is the version for this script!
63
64 my $VERSION = '0.1.10';
65 # *********************************************************************
66
67 my $cfg_file         = '';
68 my $help             = 0;
69 my $ignore_overrides = 0;
70 my $print_version    = 0;
71 my $verbose          = 0;
72 my $entry_mod        = 0;
73 my $force_install    = 0;
74 my $manual           = 0;
75
76 my (@limit_modules) = ();
77 my (@overrides)     = ();
78 my (%cmd_overrides) = ();
79
80 $max_cvs_tries = 10;
81 my $cvs_wait   = "1s";
82
83 $CRITICAL_LVL = 0;
84 $WARNING_LVL  = 1;
85 $CONFIG_LVL   = 2;
86 $STATE_LVL    = 3;
87 $VERB_LVL     = 4;
88 $HVERB_LVL    = 5;
89 $HEX_LVL      = 6;
90
91 $debug_level = $CRITICAL_LVL;
92 GetOptions('cfg=s' => \$cfg_file, 'help' => \$help, 'override=s' => \@overrides,
93            'ignore-overrides' => \$ignore_overrides,
94            'debug=i' => \$debug_level, 'set=s' => \%cmd_overrides,
95            'version' => \$print_version, 'verbose' => \$verbose,
96            'entry-mod' => \$entry_mod, 'force-install' => \$force_install,
97            'target=s' => \@limit_modules, 'manual' => \$manual,
98            'cvs-tries=i' => \$max_cvs_tries, 'cvs-wait=s' => \$cvs_wait)
99    or pod2usage(2);
100
101 # Print the help output and exit if --help was on the command line.
102 pod2usage(1) if $help;
103 pod2usage(-exitstatus => 0, -verbose => 2) if $manual;
104
105 # Print the version number and exit if --version was on the command line.
106 printVersion() && exit(0) if $print_version;
107
108 # If we are doing verbose output and the user did not change the debug level,
109 # then we push the debug level up to the max.
110 $debug_level = $HVERB_LVL if $verbose && $debug_level <= $CRITICAL_LVL;
111
112 $cvs_wait =~ /^(\d+)(\w?)$/;
113 $cvs_wait_length = $1;
114 my $wait_unit    = "$2";
115
116 if ( "$wait_unit" == "s" )
117 {
118    $cvs_wait_multiplier = 1;
119    $cvs_wait_unit       = "second";
120 }
121 elsif ( "$wait_unit" == "m" )
122 {
123    $cvs_wait_multiplier = 60;
124    $cvs_wait_unit       = "minute";
125 }
126
127 if ( ! $cfg_file )
128 {
129    if ( -r "Gatherrc" )
130    {
131       $cfg_file = 'Gatherrc';
132    }
133    elsif ( -r ".gatherrc" )
134    {
135       $cfg_file = '.gatherrc';
136    }
137    else
138    {
139       $cfg_file = "$ENV{'HOME'}/.gatherrc";
140    }
141 }
142
143 $log_file = "gather.log";
144 open(LOG_FILE, "> $log_file")
145    or warn "WARNING: Could not create log file $log_file: $!\n";
146
147 my (%orig_modules) = ();
148 parse("$cfg_file", \%orig_modules) or die "ERROR: Failed to parse $cfg_file\n";
149
150 # %orig_modules contains the set of modules with all options set as read from
151 # $cfg_file.  %override_modules is a copy of that information that will be
152 # passed around to doOverride() below.  In this way, we can retain the original
153 # module information if we need it for comparison purposes or something.  Once
154 # all the doOverride() calls are complete, %override_modules will contain
155 # exactly what the user wants in terms of modules to retrieve and what options
156 # should be used in the retrieval process.
157 my %override_modules = %orig_modules;
158
159 # If --ignore-overrides was not passed in, process any override files and
160 # override command-line arguments.
161 if ( ! $ignore_overrides )
162 {
163    # If the list of override files is empty, try the default files.
164    if ( $#overrides == -1 )
165    {
166       if ( -r ".gatherrc-override" )
167       {
168          push(@overrides, '.gatherrc-override');
169       }
170       elsif ( -r "$ENV{'HOME'}/.gatherrc-override" )
171       {
172          push(@overrides, "$ENV{'HOME'}/.gatherrc-override");
173       }
174    }
175
176    # This is a global variable (argh!) that will contain the name of the
177    # current override file being processed.
178    $override = '';
179
180    # Iterate over the list of override files passed in on the command line and
181    # apply each of them to the current environment.
182    foreach $override ( @overrides )
183    {
184       if ( open(OVERRIDE, "$override") )
185       {
186          my $line;
187          while ( $line = <OVERRIDE> )
188          {
189             chomp($line);
190
191             # Strip comments.
192             $line =~ s/#.*$//;
193
194             # Skip blank lines.
195             next if $line =~ /^\s*$/;
196
197             # The current line has at least one wildcard.
198             if ( $line =~ /\*/ )
199             {
200                if ( $line !~ /\*\./ )
201                {
202                   warn "ERROR: Invalid wildcard use at $override:$.\n";
203                }
204                else
205                {
206                   my(@override_lines) = expandWildcardLine("$line",
207                                                            \%orig_modules);
208
209                   foreach ( @override_lines )
210                   {
211                      doOverride("$_", \%override_modules);
212                   }
213                }
214             }
215             # The current line has no wildcards.
216             else
217             {
218                doOverride("$line", \%override_modules);
219             }
220          }
221
222          close(OVERRIDE);
223       }
224       else
225       {
226          warn "WARNING: Could not open override file $override: $!\n";
227       }
228    }
229
230    # Loop over all the command-line overrides (--set key=value arguments) and
231    # apply them to the current environment.
232    my $key;
233    foreach $key ( keys(%cmd_overrides) )
234    {
235       # This is needed because expandWildcardLine() and doOverride() expect to
236       # see something of the form "<key> = <value>".
237       my $line = "$key = $cmd_overrides{$key}";
238
239       # The current line has at least one wildcard.
240       if ( $key =~ /\*/ )
241       {
242          if ( $key !~ /\*\./ )
243          {
244             warn "ERROR: Invalid wildcard use at $override:$.\n";
245          }
246          else
247          {
248             my(@override_lines) = expandWildcardLine("$line", \%orig_modules);
249
250             foreach ( @override_lines )
251             {
252                doOverride("$_", \%override_modules);
253             }
254          }
255       }
256       # The current line has no wildcards.
257       else
258       {
259          doOverride("$line", \%override_modules);
260       }
261    }
262 }
263
264 my (%targeted_modules) = ();
265
266 # If the list of target modules is empty, then %override_modules contains the
267 # module list we will use.  This hash may be different from %orig_modules
268 # depending on what command-line options were given.
269 if ( $#limit_modules == -1 )
270 {
271    %targeted_modules = %override_modules;
272 }
273 else
274 {
275    foreach ( @limit_modules )
276    {
277       if ( ! defined($override_modules{"$_"}) )
278       {
279          warn "WARNING: Trying to target unknown module '$_'\n";
280          next;
281       }
282
283       $targeted_modules{"$_"} = $override_modules{"$_"};
284    }
285 }
286
287 checkoutModules(\%targeted_modules);
288 exit 0;
289
290 # -----------------------------------------------------------------------------
291 # Subroutines follow.
292 # -----------------------------------------------------------------------------
293
294 sub printVersion ()
295 {
296    print "$VERSION\n";
297
298    return 1;
299 }
300
301 sub parse ($$)
302 {
303    my $file       = shift;
304    my $module_ref = shift;
305
306    my $status = 1;
307
308    open(INPUT, "$file") or die "ERROR: Could not open $file: $!\n";
309
310    my $cfg_data = '';
311    while ( <INPUT> )
312    {
313       $cfg_data .= $_;
314    }
315    close(INPUT);
316
317    $cfg_data =~ s|/\*.*?\*/||gs; # Strip out C-style comments
318    $cfg_data =~ s/#.*$//gm;      # Strip out shell-style comments
319    $cfg_data =~ s|//.*$||gm;     # Strip out C++-style comments
320
321    my $mod_count = 0;
322    while ( $cfg_data =~ /\s*(\w.*?\w?)\s*{\s*(.*?)\s*}\s*;\s*/s )
323    {
324       my $module_name = "$1";
325       my $module_body = "$2";
326       $cfg_data       = $';
327
328       $indent = 0;
329       print "Loading $module_name from $file ...\n";
330       my $parse_stat = parseModule("$module_body", "$module_name", $module_ref);
331       return 0 if $parse_stat == -1;
332       $mod_count++
333    }
334
335    warn "WARNING: Nothing happened which probably means a parse error\n"
336       unless $mod_count > 0;
337
338    return $status;
339 }
340
341 sub parseModule ($$$;$)
342 {
343    my $module_body = shift;
344    my $module_name = shift;
345    my $module_ref  = shift;
346    my $in_module   = shift || 0;
347
348    print " " x $indent, "Parsing $module_name\n";
349
350    my $status = 1;
351
352    # Ensure that all of these are initialized just for safety's sake.
353    $$module_ref{"$module_name"}{'CVSROOT'} = '';
354    $$module_ref{"$module_name"}{'Module'}  = [];
355    $$module_ref{"$module_name"}{'Date'}    = '';
356    $$module_ref{"$module_name"}{'Tag'}     = '';
357    $$module_ref{"$module_name"}{'Path'}    = '.';
358
359    # Initialize this module's dependency hash with an anonymous hash
360    # reference.
361    $$module_ref{"$module_name"}{'deps'} = {};
362
363    while ( "$module_body" ne "" && $status == 1 )
364    {
365       printDebug $HEX_LVL, ">" x 78, "\nNew module body:\n$module_body\n",
366                            "<" x 78, "\n";
367
368       SWITCH:
369       {
370          # Matched an include.
371          if ( $module_body =~ /^(s?include\s+(.+?);)/s )
372          {
373             my $inc_string = "$1";
374             my $inc_file   = "$2";
375
376             $indent += 4;
377             $status = handleInclude("$inc_string", "$inc_file", \$module_body);
378             $indent -= 4;
379
380             last SWITCH;
381          }
382
383          if ( $module_body =~ /^CVSROOT:\s+(\S+?)\s*;/s )
384          {
385             $$module_ref{"$module_name"}{'CVSROOT'} = "$1";
386             $module_body = $';
387             last SWITCH;
388          }
389
390          if ( $module_body =~ /^Module:\s+(.+?)\s*;/s )
391          {
392             my $temp = "$1";
393             $module_body = $';
394
395             my($cvs_module_name, $install_name) = ('', '');
396
397             if ( $temp =~ /^(.+?)\s*\[(.*)\]\s*$/ )
398             {
399                $cvs_module_name = "$1";
400                $install_name    = "$2";
401             }
402             else
403             {
404                $cvs_module_name = "$temp";
405             }
406
407             push(@{$$module_ref{"$module_name"}{'Module'}},
408                  {$cvs_module_name => $install_name});
409             last SWITCH;
410          }
411
412          # Matched a tag/branch setting for this module.
413          if ( $module_body =~ /^Tag:\s+(\S+?)\s*;/s )
414          {
415             $$module_ref{"$module_name"}{'Tag'}  = "$1";
416             $module_body = $';
417             last SWITCH;
418          }
419
420          # Matched a date setting for this module.
421          if ( $module_body =~ /^Date:\s+(.+?)\s*;/s )
422          {
423             $$module_ref{"$module_name"}{'Date'}  = "$1";
424             $module_body = $';
425             last SWITCH;
426          }
427
428          # Matched a path setting for this module.
429          if ( $module_body =~ /^Path:\s+(.+?)\s*;/s )
430          {
431             my $path = "$1";
432             expandEnvVars(\$path);
433             $$module_ref{"$module_name"}{'Path'}  = "$path";
434             $module_body   = $';
435             last SWITCH;
436          }
437
438          # Matched the beginning of a sub-module.
439          if ( $module_body =~ /^(\w.*?\w?)\s*{\s*(.*)/s )
440          {
441             $indent += 4;
442             ($module_body = parseModule("$2", "$1",
443                                         $$module_ref{"$module_name"}{'deps'},
444                                         1))
445                or return 0;
446             $indent -= 4;
447             print " " x $indent, "Returning to $module_name\n";
448             last SWITCH;
449          }
450
451          # We have reached the end of the module.
452          if ( $module_body =~ /^}/ && $in_module )
453          {
454             print " " x $indent, "Finished parsing $module_name\n";
455             return $';
456          }
457
458          warn "Parse error in the following:\n$module_body\n";
459          $status = -1;
460       }
461
462       $module_body =~ s/^\s+(\S*)/$1/s;
463    }
464
465    return $status;
466 }
467
468 sub handleInclude ($$$)
469 {
470    my $inc_string = shift;
471    my $inc_file   = shift;
472    my $text_ref   = shift;
473
474    my $sinclude = 1 if $inc_string =~ /^sinclude/;
475
476    my $status = 1;
477
478    expandEnvVars(\$inc_file);
479
480    if ( open(INC_FILE, "$inc_file") )
481    {
482       my $loaded_body = '';
483       while ( <INC_FILE> )
484       {
485          $loaded_body .= $_;
486       }
487       close(INC_FILE);
488
489       $$text_ref =~ s/\Q$inc_string\E/$loaded_body/s;
490    }
491    else
492    {
493       warn "WARNING: Failed to load $inc_file: $!\n" unless $sinclude;
494       $$text_ref =~ s/\Q$inc_string\E//s;
495       $status = 0;
496    }
497
498    return $status;
499 }
500
501 sub expandWildcardLine ($$)
502 {
503    my $line       = shift;
504    my $module_ref = shift;
505
506    my (@expanded_lines) = ();
507
508    my ($path, $value) = split(/\s*=\s*/, "$line");
509    my (@path_arr)     = split(/\./, "$path");
510
511    local $full_path = "$path";
512
513    if ( $#path_arr < 1 )
514    {
515       warn "ERROR: Invalid hierarchy in $line ($override:$.)\n";
516    }
517    else
518    {
519       my (@modules) = ();
520
521       if ( "$path_arr[0]" eq "*" )
522       {
523          @modules = keys(%$module_ref);
524       }
525       else
526       {
527          $modules[0] = $path_arr[0];
528       }
529
530       my $module;
531       foreach $module ( @modules )
532       {
533          my (@work_arr) = @path_arr;
534          $work_arr[0] = "$module";
535          my $work_path = "$full_path";
536          $work_path =~ s/^\*/$module/;
537
538          expandWildcards(\@work_arr, $module_ref, $value, \@expanded_lines,
539                          $work_path);
540       }
541    }
542
543    return @expanded_lines;
544 }
545
546 sub expandWildcards ($$$$$)
547 {
548    my $path_ref       = shift;
549    my $module_ref     = shift;
550    my $override_value = shift;
551    my $lines_ref      = shift;
552    my $work_path      = shift;
553
554    my $current_value = shift(@$path_ref);
555    printDebug $VERB_LVL, "current_value: $current_value\n";
556
557    if ( "$current_value" eq "*" )
558    {
559       die "This should never happen!\n";
560    }
561    else
562    {
563       # A wildcard in this position (<Module>.*) must always indicate a
564       # project dependency.
565       if ( $$path_ref[0] && $$path_ref[0] eq "*" )
566       {
567          my (@temp_arr) = ();
568          my ($dep_name, $new_path);
569
570          shift(@$path_ref);
571          my $save_path = $work_path;
572          printDebug $VERB_LVL, "Unexpanded Path: $work_path\n";
573
574          foreach $dep_name ( keys(%{$$module_ref{"$current_value"}{'deps'}}) )
575          {
576             printDebug $VERB_LVL, "Dep: $dep_name\n";
577             @temp_arr = @$path_ref;
578             unshift(@temp_arr, "$dep_name");
579             printDebug $HVERB_LVL, "path_arr: @$path_ref\n";
580             printDebug $HVERB_LVL, "temp_arr: @temp_arr\n";
581
582             $work_path =~ s/\*/$dep_name/;
583             printDebug $VERB_LVL, "New Path: $work_path\n";
584
585             expandWildcards(\@temp_arr, $$module_ref{"$current_value"}{'deps'},
586                             $override_value, $lines_ref, $work_path);
587             $work_path = $save_path;
588          }
589
590          # If the above expansion gave us <Module>.<Setting>, we now have
591          # only <Setting> which is meaningless.
592          # XXX: It seems like this should not be necessary, but it may be the
593          # result of using a different array reference in the recursive calls.
594          shift(@$path_ref) if $#$path_ref == 0;
595       }
596       elsif ( defined($$module_ref{"$current_value"}) )
597       {
598          printDebug $STATE_LVL, "Matched $current_value\n";
599          printDebug $VERB_LVL, "Checking for $$path_ref[0] in $current_value\n";
600
601          # We have reached the end of the recursion.
602          if ( defined($$module_ref{"$current_value"}{$$path_ref[0]}) )
603          {
604             printDebug $STATE_LVL,
605                        "Adding line '$work_path = $override_value'\n";
606             push(@$lines_ref, "$work_path = $override_value");
607          }
608          elsif ( defined($$module_ref{"$current_value"}{'deps'}{$$path_ref[0]}) )
609          {
610             printDebug $STATE_LVL, "Matched dependency $$path_ref[0]\n";
611             expandWildcards($path_ref, $$module_ref{"$current_value"}{'deps'},
612                             $override_value, $lines_ref, $work_path);
613          }
614          else
615          {
616             warn "WARNING: $work_path not found!\n";
617          }
618       }
619       else
620       {
621          warn "WARNING: $work_path not found!\n";
622       }
623    }
624 }
625
626 sub doOverride ($$)
627 {
628    my $line       = shift;
629    my $module_ref = shift;
630
631    my ($path, $value) = split(/\s*=\s*/, "$line");
632    my (@path_arr)     = split(/\./, "$path");
633
634    if ( $#path_arr < 1 )
635    {
636       warn "ERROR: Invalid hierarchy in $line ($override:$.)\n";
637    }
638    else
639    {
640       local $full_path = "$path";
641       overrideValue(\@path_arr, $module_ref, "$value");
642    }
643 }
644
645 sub overrideValue ($$$)
646 {
647    my $path_ref       = shift;
648    my $module_ref     = shift;
649    my $override_value = shift;
650
651    my $current_value = shift(@$path_ref);
652
653    if ( defined($$module_ref{"$current_value"}) )
654    {
655 #      print "Matched $current_value\n";
656 #      print "Checking for ", $$path_ref[0], " in $current_value\n";
657
658       # We have reached the end of the recursion.
659       if ( defined($$module_ref{"$current_value"}{$$path_ref[0]}) )
660       {
661          if ( $$path_ref[0] eq "Module" )
662          {
663             my $module_list = "$override_value";
664             $module_list =~ s/;/ /g;
665
666             my(@modules)       = split(/;/, "$module_list");
667             my(@mod_overrides) = ();
668
669             my $mod;
670             foreach $mod ( @modules )
671             {
672                my($module_name, $install_name) = ('', '');
673
674                if ( $mod =~ /^\s*(.+?)\s*\[(.*)\]\s*$/ )
675                {
676                   $module_name  = "$1";
677                   $install_name = "$2";
678                }
679                else
680                {
681                   $module_name = "$mod";
682                }
683
684                push(@mod_overrides, {$module_name => $install_name});
685             }
686
687             print "Overriding $full_path with $module_list\n";
688             $$module_ref{"$current_value"}{'Module'} = \@mod_overrides;
689          }
690          elsif ( $$path_ref[0] eq "Path" )
691          {
692             my $new_path = "$override_value";
693             expandEnvVars(\$new_path);
694
695             print "Overriding $full_path with $new_path\n";
696             $$module_ref{"$current_value"}{'Path'} = "$new_path";
697          }
698          else
699          {
700             print "Overriding $full_path with $override_value\n";
701             $$module_ref{"$current_value"}{$$path_ref[0]} = "$override_value";
702          }
703       }
704       elsif ( defined($$module_ref{"$current_value"}{'deps'}{$$path_ref[0]}) )
705       {
706 #         print "Matched dependency $$path_ref[0]\n";
707          overrideValue($path_ref, $$module_ref{"$current_value"}{'deps'},
708                        $override_value);
709       }
710       else
711       {
712          warn "WARNING: $full_path not found!\n";
713       }
714    }
715    else
716    {
717       warn "WARNING: $full_path not found!\n";
718    }
719 }
720
721 sub checkoutModules ($)
722 {
723    my $mod_ref = shift;
724
725    my $mod_name;
726    foreach $mod_name ( keys(%$mod_ref) )
727    {
728       my $module = '';
729       foreach $module ( @{$$mod_ref{"$mod_name"}{'Module'}} )
730       {
731          my($cvs_module_name, $install_name) = each(%$module);
732
733          if ( defined($$mod_ref{"$mod_name"}{'CVSROOT'}) && $cvs_module_name )
734          {
735             # If a module is already checked out, update it instead of doing
736             # a new checkout.
737             if ( ($install_name &&
738                     -d "$$mod_ref{$mod_name}{'Path'}/$install_name") ||
739                  -d "$$mod_ref{$mod_name}{'Path'}/$cvs_module_name" )
740             {
741                updateModule("$mod_name", $$mod_ref{"$mod_name"}{'Tag'},
742                             $$mod_ref{"$mod_name"}{'Date'},
743                             $$mod_ref{"$mod_name"}{'Path'},
744                             "$cvs_module_name", "$install_name");
745             }
746             else
747             {
748                printDebug $VERB_LVL, "$mod_name --> ",
749                           "$$mod_ref{$mod_name}{'CVSROOT'} ",
750                           "$$mod_ref{$mod_name}{'Tag'} ",
751                           "$$mod_ref{$mod_name}{'Date'} ",
752                           "$cvs_module_name (to $$mod_ref{$mod_name}{'Path'}";
753                printDebug $VERB_LVL, "/$install_name" if $install_name;
754                printDebug $VERB_LVL, ")\n";
755
756                checkoutModule($mod_name, $$mod_ref{"$mod_name"}{'CVSROOT'},
757                               $$mod_ref{"$mod_name"}{'Tag'},
758                               $$mod_ref{"$mod_name"}{'Date'},
759                               "$cvs_module_name",
760                               $$mod_ref{"$mod_name"}{'Path'},
761                               "$install_name");
762             }
763          }
764       }
765
766       checkoutModules($$mod_ref{"$mod_name"}{'deps'});
767    }
768 }
769
770 sub updateModule ($$$$$$)
771 {
772    my $name         = shift;
773    my $tag          = shift;
774    my $date         = shift;
775    my $path         = shift;
776    my $cvs_module   = shift;
777    my $install_name = shift;
778
779    my $module = ("$install_name" ne "") ? "$install_name" : "$cvs_module";
780
781    print "Updating $name ($module) in $path ...\n";
782
783    my $cur_dir = getcwd();
784    chdir("$path") if "$path" ne "" && "$path" ne ".";
785
786    my $status;
787
788    if ( chdir("$module") )
789    {
790       my $cmd_line = "cvs update ";
791
792       # If we are updating on the HEAD branch and no date is specified, use
793       # 'cvs update -A' to remove any sticky tags that may exist from an
794       # earlier update or checkout.
795       if ( "$tag" eq "HEAD" && ! $date )
796       {
797          $cmd_line .= "-A ";
798       }
799       # If we are not updating on the HEAD branch or a date is given, then we
800       # need extra arguments to get sticky tags put into place.
801