ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/SCRAM/src/BuildSystem/ToolManager.pm
Revision: 1.17
Committed: Thu Mar 29 12:43:52 2007 UTC (18 years, 1 month ago) by sashby
Content type: text/plain
Branch: MAIN
CVS Tags: V1_1_0, v110p1
Changes since 1.16: +33 -38 lines
Log Message:
Removed auto inherit of toolcache content. Only use it if SCRAM_INHERIT_COMPAT_CONFIG is set.

File Contents

# User Rev Content
1 sashby 1.2 #____________________________________________________________________
2     # File: ToolManager.pm
3     #____________________________________________________________________
4     #
5     # Author: Shaun Ashby <Shaun.Ashby@cern.ch>
6     # Update: 2003-11-12 15:04:16+0100
7 sashby 1.17 # Revision: $Id: ToolManager.pm,v 1.16 2007/02/27 11:59:45 sashby Exp $
8 sashby 1.2 #
9     # Copyright: 2003 (C) Shaun Ashby
10     #
11     #--------------------------------------------------------------------
12     package BuildSystem::ToolManager;
13     require 5.004;
14    
15     use Exporter;
16     use BuildSystem::ToolCache;
17     use BuildSystem::ToolParser;
18     use Utilities::AddDir;
19     use URL::URLhandler;
20     use Utilities::Verbose;
21    
22     @ISA=qw(BuildSystem::ToolCache Utilities::Verbose);
23     @EXPORT_OK=qw( );
24     #
25 sashby 1.9
26 sashby 1.2 sub new
27     ###############################################################
28     # new #
29     ###############################################################
30     # modified : Wed Nov 12 10:34:10 2003 / SFA #
31     # params : #
32     # : #
33     # function : #
34     # : #
35     ###############################################################
36     {
37     my $proto=shift;
38     my $class=ref($proto) || $proto;
39     my $self=$class->SUPER::new(); # Inherit from ToolCache
40     my $projectarea=shift;
41    
42     bless $self,$class;
43    
44     $self->{arch}=shift;
45     $self->{topdir}=$projectarea->location();
46     $self->{configdir}=$self->{topdir}."/".$projectarea->configurationdir();
47     $self->{cache}=$projectarea->cache(); # Download tool cache
48     $self->{toolfiledir}=$self->{topdir}."/.SCRAM/InstalledTools";
49     $self->{datastore}=$self->{topdir}."/.SCRAM";
50     $self->{archstore}=$self->{topdir}."/.SCRAM/".$ENV{SCRAM_ARCH};
51 sashby 1.16
52     if (exists $ENV{SCRAM_TOOL_TIMESTAMP_DIR})
53     {
54     $self->{tooltimestamp}=$ENV{SCRAM_TOOL_TIMESTAMP_DIR};
55     }
56     else
57     {
58     $self->{tooltimestamp}=$self->{archstore}."/timestamps";
59     }
60 sashby 1.2
61     # Make sure our tool download dir exists:
62     AddDir::adddir($self->{toolfiledir});
63     AddDir::adddir($self->{archstore});
64 sashby 1.16 AddDir::adddir($self->{tooltimestamp});
65 sashby 1.2
66     # Set the tool cache file to read/write:
67     $self->name($projectarea->toolcachename());
68    
69     # Check for the downloaded tools cache:
70     if (exists($self->{cache}))
71     {
72     $self->{urlhandler}=URL::URLhandler->new($self->{cache});
73     }
74    
75     return $self;
76     }
77    
78     sub clone()
79     {
80     my $self=shift;
81     my $projectarea=shift;
82 sashby 1.3
83 sashby 1.2 # Change cache settings to reflect the new location:
84     $self->{topdir}=$projectarea->location();
85    
86     $self->{configdir}=$self->{topdir}."/".$projectarea->configurationdir();
87     $self->{toolfiledir}=$self->{topdir}."/.SCRAM/InstalledTools";
88     $self->{datastore}=$self->{topdir}."/.SCRAM";
89     $self->{archstore}=$self->{topdir}."/.SCRAM/".$ENV{SCRAM_ARCH};
90    
91     # Change the cache name:
92     $self->name($projectarea->toolcachename());
93     $self->cloned_tm(1);
94    
95     return $self;
96     }
97    
98     sub arch_change_after_copy()
99     {
100     my $self=shift;
101     my ($newarch, $cachename)=@_;
102     # Make changes to arch-specific settings when copying tool manager
103     # object to another arch during setup:
104     $self->{arch} = $newarch;
105     $self->{archstore} = $self->{topdir}."/.SCRAM/".$newarch;
106     # Change the name of the cache to reflect new (arch-specific) location:
107     $self->name($cachename);
108     }
109    
110     sub interactive()
111     {
112     my $self=shift;
113     # Interactive mode on/off:
114     @_ ? $self->{interactive} = shift
115     : ((defined $self->{interactive}) ? $self->{interactive} : 0);
116     }
117    
118     sub setupalltools()
119     {
120     my $self = shift;
121     my ($arealocation,$setupopt) = @_;
122     my (@localtools);
123     my $selected;
124    
125     # Get the selected tool list. Handle the case where there might not be
126     # any selected tools: //FIXME: need to handle case where there are no
127     # selected tools (not very often but a possibility):
128     my $sel = $self->selected();
129    
130     if (defined ($sel))
131     {
132     $selected = [ keys %{$sel} ];
133     }
134    
135     # Setup option "setupopt" directs the setup: 1 is for booting from
136     # scratch, 0 is when just doing "scram setup" (in this case we don't
137     # want to pick up everything from any scram-managed projects):
138     if ($setupopt == 1) # We're booting from scratch
139     {
140     # Check to see if there are any SCRAM-managed projects in our local requirements:
141     my $scramprojects = $::scram->_loadscramdb();
142    
143     # Look for a match in the scram db:
144 sashby 1.17 foreach my $S (@$selected) {
145     if (exists ($scramprojects->{$S})) {
146     # Check for environment SCRAM_INHERIT_COMPAT_CONFIG:
147     if (exists($ENV{SCRAM_INHERIT_COMPAT_CONFIG})) {
148     # Now check the version required exists in
149     # list of scram projects with this name:
150     while (my ($pdata,$plocation) = each %{$scramprojects->{$S}}) {
151     # Split the $pdata string to get the real name and the version:
152     my ($pname,$pversion) = split(":",$pdata);
153     if ($pversion eq $self->defaultversion($S)) {
154     # Get the tool manager for the scram project:
155     my $sa=$::scram->scramfunctions()->scramprojectdb()->getarea($pname,$pversion);
156     # Load the tool cache:
157     if ( -r $sa->toolcachename()) {
158     use Cache::CacheUtilities;
159     my $satoolmanager=&Cache::CacheUtilities::read($sa->toolcachename());
160     # Copy needed content from toolmanager for scram-managed project only
161     # if the projects have compatible configurations (compare first set of
162     # digits):
163     if ($self->check_compatibility($satoolmanager)) {
164     $self->inheritcontent($satoolmanager);
165     }
166     }
167     }
168 sashby 1.2 }
169 sashby 1.17 }
170     # Also add this scram-managed project to list of tools to set up:
171     push(@localtools,$S);
172     } else {
173     # Store other tools in ReqDoc in separate array. We will set up these tools later:
174     push(@localtools,$S);
175     }
176     }
177 sashby 1.2
178     # Set up extra tools required in this project, in addition to
179     # any scram-managed projects
180     foreach my $localtool (@localtools)
181     {
182     # First check to see if it's already set up (i.e., was contained
183     # in list of requirements for scram project):
184     if (! $self->definedtool($localtool))
185     {
186     $self->toolsetup($arealocation,$localtool,$self->defaultversion($localtool));
187     $self->addtoselected($localtool);
188     }
189     else
190     {
191     print $localtool," already set up.","\n",if ($ENV{SCRAM_DEBUG});
192     }
193     }
194     }
195     else
196     {
197     # Just loop over all tools and setup again:
198     foreach my $localtool (@{$selected})
199     {
200     $self->toolsetup($arealocation,$localtool,$self->defaultversion($localtool));
201     }
202     }
203    
204     print "\n";
205     }
206    
207     sub coresetup()
208     {
209     my $self=shift;
210 sashby 1.13 my ($toolname, $toolversion, $toolfile, $force) = @_;
211 sashby 1.2 my ($toolcheck, $toolparser);
212    
213     print "\n";
214     print $::bold."Setting up ",$toolname," version ",$toolversion,": ".$::normal,"\n";
215    
216     # New ToolParser object for this tool if there isn't one already.
217     # Look in array of raw tools to see if this tool has a ToolParser object:
218     $toolcheck=0;
219    
220     map
221     {
222     if ($_->toolname() eq $toolname) {$toolcheck = 1; $toolparser = $_;}
223     } $self->rawtools();
224    
225     # Tool not known so we create a new ToolParser object and parse it:
226 sashby 1.13 if ($toolcheck != 1 || $force == 1)
227 sashby 1.2 {
228     $toolparser = BuildSystem::ToolParser->new();
229     # We only want to store the stuff relevant for one particular version:
230     $toolparser->parse($toolname, $toolversion, $toolfile);
231     # Store the ToolParser object in the cache:
232     $self->store($toolparser);
233 sashby 1.13 print "\nFile $toolfile reparsed (modified)","\n",if ($ENV{SCRAM_DEBUG});
234 sashby 1.2 }
235    
236     # Next, set up the tool:
237     my $store = $toolparser->processrawtool($self->interactive());
238     # Make sure that we have this tool in the list of selected tools (just in case this tool was
239     # set up by hand afterwards):
240     $self->addtoselected($toolname);
241 sashby 1.8
242     # Check to see if this tool is a compiler. If so, store it.
243     # Also store the language that this compiler supprots, and a
244     # compiler name (e.g. gcc323) which, in conjunction with a stem
245     # architecture name like slc3_ia32_, can be used to build a complete arch string:
246     if ($store->scram_compiler() == 1)
247     {
248     my @supported_language = $store->flags("SCRAM_LANGUAGE_TYPE");
249     my @compilername = $store->flags("SCRAM_COMPILER_NAME");
250     $self->scram_compiler($supported_language[0],$toolname,$compilername[0]);
251     }
252    
253 sashby 1.16 # Store the ToolData object in the cache:
254 sashby 1.2 $self->storeincache($toolparser->toolname(),$store);
255     return $self;
256     }
257    
258     sub toolsetup()
259     {
260     my $self=shift;
261     my ($arealocation, $toolname, $toolversion, $toolurl) = @_;
262     my ($urlcache, $url, $filename, $tfname);
263     my $toolfile;
264 sashby 1.13 my $force = 0; # we may have to force a reparse of a tool file
265 sashby 1.6
266 sashby 1.2 $toolname =~ tr[A-Z][a-z];
267     $toolversion ||= $self->defaultversion($toolname);
268     $urlcache=URL::URLcache->new($arealocation."/.SCRAM/cache"); # Download tool cache
269 sashby 1.6
270 sashby 1.2 # Check for the downloaded tools cache:
271     if (defined($urlcache))
272     {
273     $self->{urlhandler}=URL::URLhandler->new($urlcache);
274     }
275 sashby 1.6
276 sashby 1.2 $url = $self->toolurls()->{$toolname};
277     $filename = $self->{toolfiledir}."/".$toolname;
278    
279 sashby 1.4 # If .SCRAM/InstalledTools doesn't exist, create it:
280     if (! -d $self->{toolfiledir})
281     {
282     AddDir::adddir($self->{toolfiledir});
283     }
284    
285 sashby 1.2 # First, check to see if there was a tool URL given. If so, we might need to read
286     # from http or from a file: type URL:
287     if (my ($proto, $urlv) = ($toolurl =~ /(.*):(.*)/))
288     {
289     # See what kind of URL (file:, http:, cvs:, svn:, .. ):
290     if ($proto eq 'file')
291     {
292 sashby 1.10 # Check to see if there is a ~ and substitute the user
293 sashby 1.13 # home directory if there is (file:~/xyz):
294     if (my ($urlpath) = ($urlv =~ m|^\~/(.*)$|))
295     {
296     $urlv = $ENV{HOME}."/".$urlpath;
297     }
298     elsif (my ($urlpath) = ($urlv =~ m|^\./(.*)$|))
299     {
300     # Relative to current directory (file:./xyz):
301     use Cwd qw(&cwd);
302     $urlv = cwd()."/".$urlpath;
303     }
304    
305 sashby 1.2 # If the tool url is a file and the file exists,
306     # copy it to .SCRAM/InstalledTools and set the
307     # filename accordingly:
308     if ( -f $urlv)
309     {
310     use File::Copy;
311     copy($urlv, $filename);
312 sashby 1.5 my $mode = 0644; chmod $mode, $filename;
313 sashby 1.2 $toolfile=$filename;
314 sashby 1.13 # Here we must account for the fact that the file tool doc may be
315     # a modified version of an existing tool in the current config. we
316     # make sure that this file is reparsed, even if there is already a
317     # ToolParser object for the tool:
318     $force = 1;
319 sashby 1.2 }
320     else
321     {
322 sashby 1.13 $::scram->scramerror("Unable to set up $toolname from URL \"$toolurl\" - $urlv does not exist!");
323 sashby 1.2 }
324     }
325     elsif ($proto eq 'http')
326     {
327     print "SCRAM: downloading $toolname from $toolurl","\n";
328     # Download from WWW first:
329     use LWP::Simple qw(&getstore);
330     my $http_response_val = &getstore($toolurl, $filename);
331 sashby 1.13
332 sashby 1.2 # Check the HTTP status. If doc not found, exit:
333     if ($http_response_val != 200)
334     {
335     my ($server,$doc) = ($urlv =~ m|//(.*?)/(.*)|);
336     $::scram->scramerror("Unable to set up $toolname: $doc not found on $server!");
337     }
338     else
339     {
340     $toolfile=$filename;
341     }
342     }
343     elsif ($proto eq 'cvs')
344     {
345     print "SCRAM: downloading $toolname from $urlv using protocol $proto.","\n";
346     print "[ not yet supported ]","\n";
347     exit(0);
348     }
349     elsif ($proto eq 'svn')
350     {
351     print "SCRAM: downloading $toolname from $urlv using protocol $proto.","\n";
352     print "[ not yet supported ]","\n";
353     exit(0);
354     }
355     else
356     {
357     $::scram->scramerror("Unable to download $urlv! Unknown protocol \"$proto\". Bye.");
358     }
359     }
360     else
361     {
362     # Copy the downloaded tool file to InstalledTools directory:
363     if ( ! -f $filename )
364     {
365 sashby 1.7 # If the URL is empty, the chances are that this tool was not downloaded to .SCRAM/InstalledTools.
366     # We signal an error and exit:
367 sashby 1.6 if ($url eq '')
368     {
369 sashby 1.7 $::scram->scramerror("$toolname was selected in project requirements but is not in the configuration!");
370 sashby 1.6 }
371     else
372     {
373     # Otherwise, we try to download it:
374     $self->verbose("Attempting Download of $url");
375     # Get file from download cache:
376     ($url,$filename)=$self->{urlhandler}->get($url);
377     use File::Copy;
378     $tfname=$self->{toolfiledir}."/".$toolname;
379     copy($filename, $tfname);
380     my $mode = 0644; chmod $mode, $tfname;
381     $toolfile=$tfname;
382     }
383 sashby 1.2 }
384     else
385     {
386     # File already exists in the .SCRAM/InstallTools directory:
387     $toolfile=$filename;
388     }
389     }
390    
391     # Run the core setup routine:
392 sashby 1.13 $self->coresetup($toolname, $toolversion, $toolfile,$force);
393 sashby 1.2 return $self;
394     }
395    
396     sub setupself()
397     {
398     my $self=shift;
399     my ($location)=@_;
400     # Process the file "Self" in local config directory. This is used to
401     # set all the paths/runtime settings for this project:
402 sashby 1.16 my $filename=$location."/config/Self.xml";
403    
404 sashby 1.2 if ( -f $filename )
405     {
406     print "\n";
407     print $::bold."Setting up SELF:".$::normal,"\n";
408     # Self file exists so process it:
409     $selfparser = BuildSystem::ToolParser->new();
410     $selfparser->parse('self','SELF',$filename);
411    
412     # Next, set up the tool:
413     $store = $selfparser->processrawtool($self->interactive());
414    
415     # If we are in a developer area, also add RELEASETOP paths:
416     if (exists($ENV{RELEASETOP}))
417     {
418     print "\nAdding RELEASE area settings to self....OK","\n", if ($ENV{SCRAM_DEBUG});
419     $store->addreleasetoself();
420     }
421    
422     # Store the ToolData object in the cache:
423     $self->storeincache($selfparser->toolname(),$store);
424     print "\n";
425     }
426     else
427     {
428     print "\n";
429 sashby 1.16 print "SCRAM: No file config/Self.xml...nothing to do.";
430 sashby 1.2 print "\n";
431     return;
432     }
433     }
434    
435     sub defaultversion()
436     {
437     my $self = shift;
438     my ($tool) = @_;
439     # Return default versions as taken from configuration:
440     return (%{$self->defaultversions()}->{$tool});
441     }
442    
443     sub storeincache()
444     {
445     my $self=shift;
446     my ($toolname,$dataobject)=@_;
447    
448     # Store ToolData object (for a set-up tool) in cache:
449     if (ref($dataobject) eq 'BuildSystem::ToolData')
450     {
451 sashby 1.16 $self->updatetooltimestamp($dataobject, $toolname);
452 sashby 1.2 $self->{SETUP}->{$toolname} = $dataobject;
453     }
454     else
455     {
456     $::scram->scramerror("ToolManager: BuildSystem::ToolData object reference expected.")
457     }
458     }
459    
460     sub tools()
461     {
462     my $self = shift;
463     my @tools;
464    
465     map
466     {
467     if ($_ ne "self")
468     {
469     push(@tools, $_);
470     }
471     } keys %{$self->{SETUP}};
472    
473     # Return list of set-up tools:
474     return @tools;
475     }
476    
477     sub toolsdata()
478     {
479     my $self = shift;
480     my $tooldata = [];
481     my $rawsel = $self->selected();
482    
483     foreach my $tool ( sort { %{$rawsel}->{$a}
484     <=> %{$rawsel}->{$b}}
485     keys %{$rawsel} )
486     {
487     # Return tool data objects of all set-up tools, skipping the tool "self":
488     if ($_ ne "self")
489     {
490     # Keep only tools that have really been set up:
491     if (exists $self->{SETUP}->{$tool})
492     {
493     push(@tooldata,$self->{SETUP}->{$tool});
494     }
495     }
496     }
497    
498     # Return the array of tools, in order that they appear in RequirementsDoc:
499     return @tooldata;
500     }
501    
502     sub definedtool()
503     {
504     my $self=shift;
505     my ($tool)=@_;
506    
507     # Check to see if tool X is an external tool:
508     grep ($_ eq $tool, keys %{$self->{SETUP}}) ? return 1
509     : return 0;
510     }
511    
512     sub checkifsetup()
513     {
514     my $self=shift;
515     my ($tool)=@_;
516     # Return the ToolData object if the tool has been set up:
517     (exists $self->{SETUP}->{$tool}) ? return ($self->{SETUP}->{$tool})
518     : return undef;
519     }
520    
521     sub cloned_tm()
522     {
523     my $self=shift;
524     # Has this area already been cloned and brought in-line with current location:
525     @_ ? $self->{CLONED} = $_[0]
526     : $self->{CLONED};
527     }
528    
529     sub remove_tool()
530     {
531     my $self=shift;
532     my ($toolname)=@_;
533     my $tools = $self->{SETUP};
534     my $newtlist = {};
535    
536     while (my ($tool, $tooldata) = each %$tools)
537     {
538     if ($tool ne $toolname)
539     {
540     $newtlist->{$tool} = $tooldata;
541     }
542     else
543     {
544 sashby 1.10 # Is this tool a compiler?
545     if ($tooldata->scram_compiler() == 1)
546     {
547     # Also remove this from the compiler info if there happens to be an entry:
548     while (my ($langtype, $ctool) = each %{$self->{SCRAM_COMPILER}})
549     {
550     if ($toolname eq $ctool->[0])
551     {
552     delete $self->{SCRAM_COMPILER}->{$langtype};
553     print "Deleting compiler $toolname from cache.","\n";
554     }
555     }
556     }
557     else
558     {
559     print "Deleting $toolname from cache.","\n";
560     }
561 sashby 1.2 }
562     }
563    
564     $self->{SETUP} = $newtlist;
565 sashby 1.16 $self->updatetooltimestamp ("", $toolname);
566 sashby 1.2 # Now remove from the RAW tool list:
567     $self->cleanup_raw($toolname);
568     print "ToolManager: Updating tool cache.","\n";
569     $self->writecache();
570     }
571    
572     sub scram_projects()
573     {
574     my $self=shift;
575     my $scram_projects={};
576    
577     foreach my $t ($self->tools())
578     {
579     # Get the ToolData object:
580     my $td=$self->{SETUP}->{$t};
581     $scram_projects->{$t}=$td->variable_data(uc($t)."_BASE"), if ($td->scram_project());
582     }
583    
584     return $scram_projects;
585     }
586    
587 sashby 1.8 sub scram_compiler()
588     {
589     my $self=shift;
590     my ($langtype, $toolname, $compilername)=@_;
591    
592     if ($langtype)
593     {
594     # Store the compiler info according to supported
595     # language types.
596     #
597     # ---------------------- e.g C++ cxxcompiler gcc323
598     $self->{SCRAM_COMPILER}->{$langtype}=[ $toolname, $compilername ];
599     }
600     else
601     {
602     return $self->{SCRAM_COMPILER};
603     }
604     }
605    
606 sashby 1.12 sub updatetool()
607 sashby 1.11 {
608     my $self=shift;
609 sashby 1.12 my ($name, $obj) = @_;
610 sashby 1.11
611     # Replace the existing copy of the tool with the new one:
612 sashby 1.12 if (exists $self->{SETUP}->{$name})
613 sashby 1.11 {
614     # Check to make sure that we were really passed a compiler with
615     # the desired name:
616 sashby 1.12 if ($obj->toolname() eq $name)
617 sashby 1.11 {
618 sashby 1.16 $self->updatetooltimestamp ($obj, $name);
619 sashby 1.12 print "ToolManager: Updating the cached copy of ".$name."\n";
620     delete $self->{SETUP}->{$name};
621     $self->{SETUP}->{$name} = $obj;
622 sashby 1.11 $self->writecache();
623     }
624     else
625     {
626 sashby 1.12 print "WARNING: Tool name (".$name.") and tool obj name (".$obj->toolname().") don't match!","\n";
627 sashby 1.11 print " Not making any changes.","\n";
628     }
629     }
630     else
631     {
632 sashby 1.12 print "WARNING: No entry in cache for ".$name.". Not making any updates.\n";
633 sashby 1.11 }
634     }
635    
636 sashby 1.14 sub check_compatibility()
637     {
638     my $self=shift;
639     my ($itoolmgr)=@_;
640     # Get the version of the toolmanager. If the project fails to return a version
641     # string we return 0 for no compatibility (in which case, all tools will be set
642     # up in the traditional way):
643     my $itm_configversion = $itoolmgr->configversion();
644     if ($itm_configversion)
645     {
646     # The configurations won't be identical. We must compare the digits:
647     my ($numeric_version) = ($itm_configversion =~ /[a-zA-Z]*\_([0-9a-z]*).*?/);
648     my $current_configversion = $self->configversion();
649     my ($current_numeric_version) = ($current_configversion =~ /[a-zA-Z]*\_([0-9a-z]*).*?/);
650     ($current_numeric_version == $numeric_version) && return 1; # OK, compatible;
651     }
652     # Project does not define configuration version so just return:
653     return 0;
654     }
655    
656     sub configversion()
657     {
658     my $self=shift;
659     @_ ? $self->{CONFIGVERSION} = shift
660     : $self->{CONFIGVERSION};
661     }
662    
663 sashby 1.16 sub updatetooltimestamp ()
664     {
665     my $self=shift;
666     my $obj=shift;
667     my $toolname=shift;
668     my $samevalues=0;
669     if (exists $self->{SETUP}->{$toolname})
670     {
671     $samevalues=$self->comparetoolsdata($self->{SETUP}->{$toolname},$obj);
672     }
673     if (!$samevalues)
674     {
675     if (!-d $self->{tooltimestamp})
676     {
677     AddDir::adddir($self->{tooltimestamp});
678     }
679     open(TIMESTAMPFILE,">".$self->{tooltimestamp}."/$toolname");
680     close(TIMESTAMPFILE);
681     }
682     }
683    
684     sub comparetoolsdata ()
685     {
686     my $self=shift;
687     my $data1=shift || ();
688     my $data2=shift || ();
689    
690     my $ref1=ref($data1);
691     my $ref2=ref($data2);
692    
693     if ($ref1 ne $ref2)
694     {
695     return 0;
696     }
697     elsif ($ref1 eq "CODE")
698     {
699     return 1;
700     }
701     elsif(($ref1 eq "SCALAR") || ($ref1 eq ""))
702     {
703     if ($data1 eq $data2)
704     {
705     return 1;
706     }
707     return 0;
708     }
709     elsif ($ref1 eq "ARRAY")
710     {
711     my $count = scalar(@$data1);
712     if ($count != scalar(@$data2))
713     {
714     return 0;
715     }
716     for (my $i=0; $i<$count; $i++)
717     {
718     if (! $self->comparetoolsdata($data1->[$i],$data2->[$i]))
719     {
720     return 0;
721     }
722     }
723     return 1;
724     }
725     else
726     {
727     foreach my $k (keys %{$data1})
728     {
729     if (! exists $data2->{$k})
730     {
731     return 0;
732     }
733     }
734     foreach my $k (keys %{$data2})
735     {
736     if (! exists $data1->{$k})
737     {
738     return 0;
739     }
740     }
741     foreach my $k (keys %{$data2})
742     {
743     if (! $self->comparetoolsdata($data1->{$k},$data2->{$k}))
744     {
745     return 0;
746     }
747     }
748     return 1;
749     }
750     }
751    
752 sashby 1.2 1;