#!perl
# Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved.
# This component and the accompanying materials are made available
# under the terms of the License "Eclipse Public License v1.0"
# which accompanies this distribution, and is available
# at the URL "http://www.eclipse.org/legal/epl-v10.html".
# 
# Initial Contributors:
# Nokia Corporation - initial contribution.
# 
# Contributors:
# 
# Description:
# 
#

use strict;
use FindBin;
use lib "$FindBin::Bin";
use Getopt::Long;
use IniData;
use EnvDb;
use CommandController;


#
# Globals.
#

my $verbose = 0;
my $full = 0;
my $component;
my $iniData = IniData->New();
my $commandController = CommandController->New($iniData, 'EnvInfo');
my $envDb;
my $overallStatus;
my $displayClean = 0;
my $displayDirty = 0;
my $displayPendingRelease = 0;
my $noScan = 0;


#
# Main.
#

ProcessCommandLine();
CheckEnv();
DisplayInfo();


#
# Subs.
#

sub ProcessCommandLine {
  Getopt::Long::Configure ("bundling");
  my $help;
  GetOptions("h" => \$help, "f+" => \$full, "c" => \$displayClean, "d" => \$displayDirty, "p" => \$displayPendingRelease, "n" => \$noScan, "v+" => \$verbose);
  if ($help) {
    Usage(0);
  }

  if (not $full and ($displayClean or $displayDirty or $displayPendingRelease)) {
    print "Warning: Inappropriate option(s), must be invoked together with -f\n";
  }

  if (not $displayClean and not $displayDirty and not $displayPendingRelease) {
    $displayClean = 1;
    $displayDirty = 1;
    $displayPendingRelease = 1;
  }

  $component = $ARGV[0];
  $envDb = EnvDb->Open($iniData, $verbose);
}

sub Usage {
  my $exitCode = shift;

  Utils::PrintDeathMessage($exitCode, "\nUsage: envinfo [options] [<component>]

options:

-h  help
-v  verbose output (-vv very verbose)
-f  display fuller information (the remaining switches only apply when this is used)
-ff display even fuller information (internal version and mrp name)
-c  display the components with status \"clean\"
-d  display the components with status \"dirty\"
-p  display the components with status \"pending release\"
-n  no scan\n");
}

sub CheckEnv {
  unless ($noScan or not $full) {
    if (defined $component) {
      $envDb->CheckComp($component, undef, 1);
    }
    else {
      ($overallStatus, undef, undef, my $unaccountedFiles, my $duplicates) = $envDb->CheckEnv(1, 0, 1);
      if (scalar (@$unaccountedFiles) > 0) {
	foreach my $line (@$unaccountedFiles) {
	  print "Warning: $line has unknown origin\n"; 
	}
      }
      if (scalar (@$duplicates) > 0) {
	foreach my $args (@$duplicates) {
	  print "Warning: $args->[1] attempting to release $args->[0] which has already been released by $args->[2]\n"; 
	}
      }
    }
  }
}

sub DisplayInfo {
  # Create a list of the components to be displayed.
  my @comps;
  if (defined $component) {
    my $ver = $envDb->Version($component);
    unless (defined $ver) {
      die "Error: $component not found\n";
    }
    push @comps, $component;
  }
  else {
    my $versionInfo = $envDb->VersionInfo();
    foreach my $comp (sort keys %{$versionInfo}) {
      push @comps, $comp;
    }
  }

  my $tableData;
  if ($full == 1) {
    $tableData = GenFullInfoTable(\@comps);
  }
  elsif ($full > 1) {
    $tableData = GenEvenFullerInfoTable(\@comps);
  }
  else {
    $tableData = GenMinimalInfoTable(\@comps);
  }

  # Only print the table if there's something in it.
  if (scalar(@$tableData) > 1) {
    print "\n";
    $iniData->TableFormatter->PrintTable($tableData, 1);
  }

  # Only display the overall status if a full check was done.
  if (defined $overallStatus) {
    print "\nOverall status: ", EnvDb::StatusString($overallStatus), "\n";
  }
}

sub GenMinimalInfoTable {
  my $comps = shift;

  # Create a two dimentional array of the data to be printed.
  my $tableData = [["Component", "Version"]];
  my $row = 1;
  foreach my $comp (@$comps) {
    my $ver = $envDb->Version($comp);
    $tableData->[$row++] = [$comp, $ver];
  }
  return $tableData;
}

sub GenFullInfoTable {
  my $comps = shift;

  # Create a two dimentional array of the data to be printed.
  my $tableData = [["Component", "Version", "Project", "Status"]];
  my $row = 1;
  foreach my $comp (@$comps) {
    my $ver = $envDb->Version($comp);
    my $status = $envDb->Status($comp);
    if (not $displayClean and $status == EnvDb::STATUS_CLEAN) {
      next;
    }
    elsif (not $displayDirty and ($status == EnvDb::STATUS_DIRTY or $status == EnvDb::STATUS_DIRTY_SOURCE)) {
      next;
    }
    elsif (not $displayPendingRelease and $status == EnvDb::STATUS_PENDING_RELEASE) {
      next;
    }
    my $project = $iniData->PathData->ComponentProject($comp, $ver);
    unless (defined $project) {
      $project = "-";
    }
    $tableData->[$row++] = [$comp, $ver, $project, EnvDb::StatusString($status)];
  }
  return $tableData;
}

sub GenEvenFullerInfoTable {
  my $comps = shift;

  # Create a two dimentional array of the data to be printed.
  my $tableData = [["Component", "Version", "Internal version", "Project",  "Status", "Mrp"]];
  my $row = 1;
  foreach my $comp (@$comps) {
    my $ver = $envDb->Version($comp);
    my $status = $envDb->Status($comp);
    if (not $displayClean and $status == EnvDb::STATUS_CLEAN) {
      next;
    }
    elsif (not $displayDirty and ($status == EnvDb::STATUS_DIRTY or $status == EnvDb::STATUS_DIRTY_SOURCE)) {
      next;
    }
    elsif (not $displayPendingRelease and $status == EnvDb::STATUS_PENDING_RELEASE) {
      next;
    }

    my $mrpName = $envDb->MrpName($comp);
    unless (defined $mrpName) {
      $mrpName = "-";
    }
    my $intVer = $envDb->InternalVersion($comp);
    unless (defined $intVer) {
      $intVer = "-";
    }
    my $project = $iniData->PathData->ComponentProject($comp, $ver);
    unless (defined $project) {
      $project= "-";
    }
    $tableData->[$row++] = [$comp, $ver, $intVer, $project, EnvDb::StatusString($status), $mrpName];
  }
  return $tableData;
}


=head1 NAME

EnvInfo - Displays information about the installed components in the current environment.

=head1 SYNOPSIS

  envinfo [options] [<component>]

options:

  -h  help
  -v  verbose output (-vv very verbose)
  -f  display fuller information (the remaining switches only apply when this is used)
  -ff display even fuller information (internal version and mrp name)
  -c  display the components with status "clean"
  -d  display the components with status "dirty"
  -p  display the components with status "pending release"
  -n  no scan

=head1 DESCRIPTION

By default displays a brief summary table of the information contained in the current drive's environment database. For example:

 Component   Version

 mycomp1     026
 mycomp2     057

If envoked with the C<-f> switch, a scan is performed of the F<\epoc32> tree and the status of each component is also reported:

 Component   Version   Status

 mycomp1     026       clean
 mycomp2     057       clean

 Overall status: clean

The C<Status> field may have the following values:

=over 4

=item *

B<clean> - The component's binaries all match the time stamp information that was stored when they were installed (or when they were last validated using either C<ValidateRel> or C<ValidateEnv>).

=item *

B<dirty> - One or more of the component's binaries doesn't match the time stamp information that was stored when they were installed. This may be because the source has been re-built but not changed (see the commands C<ValidateRel> and C<ValidateEnv> for details of how to check if a re-built set of binaries are identical to an already released set), or because changes have been made.

=item *

B<pending release> - The component is waiting to be released (see the commands C<PrepEnv> and C<MakeEnv> for details of how to make releases).

=back

The overall status of the environment is displayed last. This may have the following values:

=over 4

=item *

B<clean> - All the installed components have a status of C<clean> and there are no files in the F<\epoc32> tree that have unkown origins (i.e. they are all known to belong to a component).

=item *

B<dirty> - One or more of the installed components has a status of C<dirty>, or there is one or more files in the F<\epoc32> tree that has unknown origins.

=item *

B<pending release> - All components have a status of either C<clean> or C<pending release> and there are no files in the F<\epoc32> with unknown origins. This status indicates that C<MakeEnv> may be used to release this environment.

=back


By default when C<EnvInfo> is envoked with the C<-f> switch, it will perform a scan of the F<\epoc32> tree checking all the time stamps. To avoid this processing, use the C<-n> switch also. This will cause the status of each component when the last scan was performed to be displayed (which may now be out of date). The output of C<EnvInfo> can be filtered according to status using the switches C<-c>, C<-d> and C<-p>. For example, if you wanted to view all the components that are either C<dirty> or C<pending release>, type:

  envinfo -fdp

If envoked with a C<component> argument, then only the details of the specified component will be displayed and a scan of the F<\epoc32> tree will not be performed.

=head1 KNOWN BUGS

None.

=head1 COPYRIGHT

 Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
 All rights reserved.
 This component and the accompanying materials are made available
 under the terms of the License "Eclipse Public License v1.0"
 which accompanies this distribution, and is available
 at the URL "http://www.eclipse.org/legal/epl-v10.html".
 
 Initial Contributors:
 Nokia Corporation - initial contribution.
 
 Contributors:
 
 Description:
 

=cut
