releasing/cbrtools/perl/EnvDifferencer.pm
changeset 602 3145852acc89
equal deleted inserted replaced
600:6d08f4a05d93 602:3145852acc89
       
     1 # Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 # All rights reserved.
       
     3 # This component and the accompanying materials are made available
       
     4 # under the terms of the License "Eclipse Public License v1.0"
       
     5 # which accompanies this distribution, and is available
       
     6 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 # 
       
     8 # Initial Contributors:
       
     9 # Nokia Corporation - initial contribution.
       
    10 # 
       
    11 # Contributors:
       
    12 # 
       
    13 # Description:
       
    14 # 
       
    15 #
       
    16 
       
    17 package EnvDifferencer;
       
    18 
       
    19 use strict;
       
    20 use RelData;
       
    21 
       
    22 sub New {
       
    23   my $class = shift;
       
    24   my $self = bless {}, (ref $class || $class);
       
    25   $self->{iniData} = shift;
       
    26   $self->{verbose} = shift;
       
    27   $self->{startcomp} = undef;
       
    28   $self->{endcomp} = undef;
       
    29   $self->{startver} = undef;
       
    30   $self->{endver} = undef;
       
    31   $self->{reldatacache} = {}; # keyed by concatenated of comp and ver
       
    32   $self->{results} = undef;
       
    33   if ($self->{verbose}) {
       
    34     require Data::Dumper ;
       
    35     Data::Dumper->import();
       
    36   }
       
    37   return $self;
       
    38 }
       
    39 
       
    40 sub SetStartCompVer {
       
    41   my $self = shift;
       
    42   my $comp = shift;
       
    43   my $ver = shift;
       
    44   $self->Reset();
       
    45   $self->{startcomp} = $comp;
       
    46   $self->{startver} = $ver;
       
    47 }
       
    48 
       
    49 sub SetEndCompVer {
       
    50   my $self = shift;
       
    51   my $comp = shift;
       
    52   my $ver = shift;
       
    53   $self->Reset();
       
    54   $self->{endcomp} = $comp;
       
    55   $self->{endver} = $ver;
       
    56 }
       
    57 
       
    58 sub Reset {
       
    59   my $self = shift;
       
    60   $self->{results} = undef;
       
    61 }
       
    62 
       
    63 # Accessor methods
       
    64 
       
    65 sub StartEnvReldata {
       
    66   my $self = shift;
       
    67   die "Start component not defined" unless $self->{startcomp};
       
    68   die "Start version not defined" unless $self->{startver};
       
    69   return $self->RelData($self->{startcomp}, $self->{startver});
       
    70 }
       
    71 
       
    72 sub EndEnvReldata {
       
    73   my $self = shift;
       
    74   die "End component not defined" unless $self->{endcomp};
       
    75   die "End version not defined" unless $self->{endver};
       
    76   return $self->RelData($self->{endcomp}, $self->{endver});
       
    77 }
       
    78 
       
    79 sub StartReldata {
       
    80   my $self = shift;
       
    81   my $comp = shift;
       
    82   return $self->RelData($comp, $self->StartVersion($comp));
       
    83 }
       
    84 
       
    85 sub EndReldata {
       
    86   my $self = shift;
       
    87   my $comp = shift;
       
    88   return $self->RelData($comp, $self->EndVersion($comp));
       
    89 }
       
    90 
       
    91 sub StartVersion {
       
    92   my $self = shift;
       
    93   my $comp = shift;
       
    94   return $self->GetStartEnv()->{$comp};
       
    95 }
       
    96 
       
    97 sub EndVersion {
       
    98   my $self = shift;
       
    99   my $comp = shift;
       
   100   return $self->GetEndEnv()->{$comp};
       
   101 }
       
   102 
       
   103 sub ChangedComps {
       
   104   my $self = shift;
       
   105   $self->DoDiff;
       
   106   return $self->{results}->{diff}->{changed};
       
   107 }
       
   108 
       
   109 sub NewerComps {
       
   110   my $self = shift;
       
   111   $self->CompareDiffDates;
       
   112   return $self->{results}->{diffdates}->{newer};
       
   113 }
       
   114 
       
   115 sub OlderComps {
       
   116   my $self = shift;
       
   117   $self->CompareDiffDates;
       
   118   return $self->{results}->{diffdates}->{older};
       
   119 }
       
   120 
       
   121 sub UnchangedComps {
       
   122   my $self = shift;
       
   123   $self->DoDiff;
       
   124   return $self->{results}->{diff}->{same};
       
   125 }
       
   126 
       
   127 sub OnlyStart {
       
   128   my $self = shift;
       
   129   $self->DoDiff;
       
   130   return $self->{results}->{diff}->{onlystart};
       
   131 }
       
   132 
       
   133 sub OnlyEnd {
       
   134   my $self = shift;
       
   135   $self->DoDiff;
       
   136   return $self->{results}->{diff}->{onlyend};
       
   137 }
       
   138 
       
   139 sub IntermediateReldatas {
       
   140   my $self = shift;
       
   141   my $comp = shift;
       
   142   my $relDataObjects = RelData->OpenSet($self->{iniData}, $comp, $self->{verbose});
       
   143 
       
   144   my $startdate = $self->StartReldata($comp)->ReleaseTime();
       
   145   my $enddate = $self->EndReldata($comp)->ReleaseTime();
       
   146 
       
   147   # Specifically exclude the start and end reldatas... i.e use < > not <= >=
       
   148   my @results = grep { $_->ReleaseTime() < $enddate and $_->ReleaseTime() > $startdate } @$relDataObjects;
       
   149   return \@results;
       
   150 }
       
   151 
       
   152 sub GetStartEnv {
       
   153   my $self = shift;
       
   154   unless ($self->{results}->{startenv}) {
       
   155     if ($self->{startcomp}) {
       
   156       $self->{results}->{startenv} = $self->StartEnvReldata()->Environment();
       
   157     } else {
       
   158       $self->{results}->{startenv} = $self->CurrentEnv;
       
   159     }
       
   160   }
       
   161   return $self->{results}->{startenv};
       
   162 }
       
   163 
       
   164 sub GetEndEnv {
       
   165   my $self = shift;
       
   166   unless ($self->{results}->{endenv}) {
       
   167     if ($self->{endcomp}) {
       
   168       $self->{results}->{endenv} = $self->EndEnvReldata()->Environment();
       
   169     } else {
       
   170       $self->{results}->{endenv} = $self->CurrentEnv;
       
   171     }
       
   172   }
       
   173   return $self->{results}->{endenv};
       
   174 }
       
   175 
       
   176 ### Private
       
   177 
       
   178 sub CurrentEnv {
       
   179   my $self = shift;
       
   180   my $envDb = EnvDb->Open($self->{iniData}, $self->{verbose});
       
   181   return $envDb->VersionInfo();
       
   182 }
       
   183 
       
   184 sub DoDiff {
       
   185   my $self = shift;
       
   186 
       
   187   return if $self->{results}->{diff};
       
   188 
       
   189   die "Neither environment was specified.\n" unless ($self->{startcomp} || $self->{endcomp});
       
   190 
       
   191   my %env1 = %{$self->GetStartEnv()};
       
   192   my %env2 = %{$self->GetEndEnv()};
       
   193   # Deliberately make copies, as we will be deleting stuff from them
       
   194   
       
   195   if ($self->{verbose}>1) {
       
   196     print "Start environment is ".Dumper(\%env1)."\n";
       
   197     print "End environment is ".Dumper(\%env2)."\n";
       
   198   }
       
   199 
       
   200   my @changed;
       
   201   my @onlynew;
       
   202   my @onlyold;
       
   203   my @same;
       
   204 
       
   205   # Compare $env1 against $env2 first.
       
   206   foreach my $thisComp (keys %env1) {
       
   207     my $ver1 = $env1{$thisComp};
       
   208     my $ver2 = $env2{$thisComp};
       
   209     if (not defined $ver2) {
       
   210       push @onlyold, $thisComp;
       
   211     }
       
   212     elsif (lc($ver1) eq lc($ver2)) {
       
   213       push @same, $thisComp;
       
   214     }
       
   215     else {
       
   216       push @changed, $thisComp;
       
   217     }
       
   218 
       
   219     if (defined $ver2) {
       
   220       # Remove this component from $env2 because it has been accounted for.
       
   221       # Components left over in the $env2 hash are those not present in $env1.
       
   222       delete $env2{$thisComp};
       
   223     }
       
   224   }
       
   225 
       
   226   # List the components in $env2 but not in $env1.
       
   227   @onlynew = keys %env2;
       
   228 
       
   229   $self->{results}->{diff} = {
       
   230     same => \@same,
       
   231     onlyend => \@onlynew,
       
   232     onlystart => \@onlyold,
       
   233     changed => \@changed
       
   234   };
       
   235 
       
   236   print "At end of main comparison... with results ".Dumper($self->{results}->{diff})."\n" if $self->{verbose}>1;
       
   237 }
       
   238 
       
   239 sub CompareDiffDates {
       
   240   my $self = shift;
       
   241   return if $self->{results}->{diffdates};
       
   242   $self->DoDiff; # returns if already completed
       
   243 
       
   244   my @older;
       
   245   my @newer;
       
   246   foreach my $thisComp (@{$self->{results}->{diff}->{changed}}) {
       
   247     my $relData1 = $self->StartReldata($thisComp);
       
   248     my $relData2 = $self->EndReldata($thisComp);
       
   249     if ($relData1->ReleaseTime() <= $relData2->ReleaseTime()) {
       
   250       push @newer, $thisComp;
       
   251     } else {
       
   252       push @older, $thisComp;
       
   253     }
       
   254   }
       
   255 
       
   256   $self->{results}->{diffdates} = {
       
   257     older => \@older,
       
   258     newer => \@newer
       
   259   };
       
   260   print "At end of date comparison... with results ".Dumper($self->{results}->{diffdates})."\n" if $self->{verbose}>1;
       
   261 }
       
   262 
       
   263 sub RelData {
       
   264   my $self = shift;
       
   265   my $comp = shift;
       
   266   my $ver = shift;
       
   267 
       
   268   print "Asked for reldata for $comp $ver\n" if $self->{verbose}>2;
       
   269 
       
   270   die "Can't get reldata for undefined comp" unless $comp;
       
   271   die "Can't get reldata for undefined version of $comp" unless $ver;
       
   272 
       
   273   my $key = "$comp$ver";
       
   274   unless ($self->{reldatacache}->{$key}) {
       
   275     $self->{reldatacache}->{$key} = RelData->Open
       
   276       ($self->{iniData}, $comp, $ver, $self->{verbose});
       
   277   }
       
   278   return $self->{reldatacache}->{$key};
       
   279 }
       
   280 
       
   281 1;
       
   282 
       
   283 __END__
       
   284 
       
   285 =head1 NAME
       
   286 
       
   287 EnvDifferencer.pm - A class to find differences between two environments.
       
   288 
       
   289 =head1 DESCRIPTION
       
   290 
       
   291 This class is used by C<DiffEnv> and C<ViewNotes> to examine the differences between two environments. To use it, first create an object, then use the C<SetStartCompVer> and C<SetEndCompVer> methods to set the component name and version that you wish to compare. You can then use any of the other methods to access information about the differences between them.
       
   292 
       
   293 =head1 INTERFACE
       
   294 
       
   295 =head2 Necessary calls
       
   296 
       
   297 =head3 New
       
   298 
       
   299 Expects to be passed two arguments; firstly, an C<IniData> object, and secondly, a verbosity level.
       
   300 
       
   301 =head3 SetStartCompVer
       
   302 
       
   303 =head3 SetEndCompVer
       
   304 
       
   305 These two methods are each passed a component name a version number. These two environments are used for differencing. Note that no differencing is actually performed until information is requested by one of the accessor methods. These methods also call C<Reset>, which means that all results are deleted and a new diff will be performed whenever information is requested.
       
   306 
       
   307 If one of these is not called before the comparison, then the current environment (as returned by a C<EnvDb> object) will be used for the missing environment.
       
   308 
       
   309 =head3 Reset
       
   310 
       
   311 This method should never be needed. It resets the object so that it performs a new diff the next time some information is requested.
       
   312 
       
   313 =head2 Accessor Methods
       
   314 
       
   315 Any of these may trigger a differencing to happen.
       
   316 
       
   317 =head3 StartReldata
       
   318 
       
   319 =head3 EndReldata
       
   320 
       
   321 Takes a component name. Returns a C<RelData> object corresponding to that component in the start or the end environment.
       
   322 
       
   323 =head3 StartVersion
       
   324 
       
   325 =head3 EndVersion
       
   326 
       
   327 Given a component name, returns the version number of that component in the start or the end environment. The behaviour is undefined if that component doesn't exist in the given environment.
       
   328 
       
   329 =head3 GetStartEnv
       
   330 
       
   331 =head3 GetEndEnv
       
   332 
       
   333 Returns a hashref of the components and version numbers in each environment.
       
   334 
       
   335 =head3 StartEnvReldata
       
   336 
       
   337 =head3 EndEnvReldata
       
   338 
       
   339 Returns the C<RelData> object corresponding to the environment itself.
       
   340 
       
   341 =head3 ChangedComps
       
   342 
       
   343 Returns a list of component names in both environments, but with different version numbers.
       
   344 
       
   345 =head3 UnchangedComps
       
   346 
       
   347 Returns a similar list of those components which are identical in both environments.
       
   348 
       
   349 =head3 OnlyStart
       
   350 
       
   351 =head3 OnlyEnd
       
   352 
       
   353 Return lists of those components only in one or other environment.
       
   354 
       
   355 =head3 NewerComps
       
   356 
       
   357 =head3 OlderComps
       
   358 
       
   359 These two methods trigger some additional differencing, which compares the dates of each changed component. They then return a list of those components which are newer, or older, in the end environment.
       
   360 
       
   361 =head3 IntermediateReldatas
       
   362 
       
   363 Given a component name, this returns a list of C<RelData> objects belonging to releases of that component made between the start and end release. It specifically does not include the start or end release.
       
   364 
       
   365 =head1 KNOWN BUGS
       
   366 
       
   367 None.
       
   368 
       
   369 =head1 COPYRIGHT
       
   370 
       
   371  Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
       
   372  All rights reserved.
       
   373  This component and the accompanying materials are made available
       
   374  under the terms of the License "Eclipse Public License v1.0"
       
   375  which accompanies this distribution, and is available
       
   376  at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
   377  
       
   378  Initial Contributors:
       
   379  Nokia Corporation - initial contribution.
       
   380  
       
   381  Contributors:
       
   382  
       
   383  Description:
       
   384  
       
   385 
       
   386 =cut