Subversion Repositories DevTools

Rev

Rev 2931 | Blame | Compare with Previous | Last modification | View Log | RSS feed

########################################################################
# Copyright (C) 1998-2012 Vix Technology, All rights reserved
#
# Module name   : cc2svn_rollbackrm.pl
# Module type   : Makefile system
# Compiler(s)   : Perl
# Environment(s): jats
#
# Description   : Rollback RM with ClearCase to Subversion conversion info
#                 May get merged into updaterm
#
# Usage:
#
# Version   Who      Date        Description
#
#......................................................................#

require 5.008_002;
use strict;
use warnings;

use Pod::Usage;
use Getopt::Long;

use JatsError;
use JatsRmApi;

#
#   Globals
#
my $RM_DB;
my $VERSION = "1.0.0";                      # Update this
my %packageVcs;

#
#   Options
#
my $opt_verbose = 0;
my $opt_help = 0;
my $opt_package;
my $opt_rm = 'RELMANU1';
my $opt_test = 1;
my $opt_force;
my $opt_checkOperation;
my $opt_report = 0;
my $opt_live;
my $opt_loseData;

#-------------------------------------------------------------------------------
# Function        : Main Entry
#
# Description     :
#
# Inputs          :
#
# Returns         :
#
my $result = GetOptions (
                "help+"         => \$opt_help,          # flag, multiple use allowed
                "manual:3"      => \$opt_help,
                "verbose:+"     => \$opt_verbose,       # flag
                'package:s'     => \$opt_package,
                'database:s'    => \$opt_rm,
                'test!'         => \$opt_test,
                'force!'        => \$opt_force,
                'check:s'       => \$opt_checkOperation,
                'report:+'      => \$opt_report,
                'live!'         => \$opt_live,
                'loseData!'     => \$opt_loseData,
                );

#
#   Process help and manual options
#
pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result);
pod2usage(-verbose => 1)  if ($opt_help == 2);
pod2usage(-verbose => 2)  if ($opt_help > 2);

ErrorConfig( 'name'    =>'CC2SVN_UPDATERM',
             'verbose' => $opt_verbose,
              );

Error ("Must specify a package name") unless ( defined $opt_package || $#ARGV >= 0 );

if ( $opt_live )
{
    $opt_rm = 'RELEASEM';
}


$ENV{GBE_RM_LOCATION} = 'jdbc:oracle:thin:@auperaprm01:1521:' . $opt_rm;
unless ( $opt_rm eq 'RELEASEM' )
{
    Warning ("Using internal user/passowrd");
    $ENV{GBE_RM_USERNAME} = 'RELEASE_MANAGER';
    $ENV{GBE_RM_PASSWORD} = 'RELEASE_MANAGER';
    $ENV{GBE_RM_LOCATION} = 'jdbc:oracle:thin:@auperaora07.vix.local:1521:' . $opt_rm;
}
else
{
    $ENV{GBE_RM_USERNAME} = 'RM_READONLY';
    $ENV{GBE_RM_PASSWORD} = 'RM_READONLY';
}

#
#   Check operation
#
if ( $opt_checkOperation )
{
    Message ("Check RM operation");
    Error ("PVID must be specified via -package option") unless $opt_package;
    intoReleaseManager ($opt_package, $opt_checkOperation);
    Message ("Check Complete OK");
    exit 0;
}


foreach my $packagePath ( $opt_package, @ARGV )
{
    next unless ( defined $packagePath );
    my $packageName = $packagePath;
    $packageName =~ s~\.data$~~;
    $packageName =~ s~.*/~~;
    getVcsData($packageName) if ( $opt_report <= 1 );
    readPackageData($packagePath);
}
exit 0;

#-------------------------------------------------------------------------------
# Function        : getVcsData
#
# Description     : Get existing VCS data from the release Manager
#
# Inputs          : 
#
# Returns         : 
#
sub getVcsData
{
    my ($packageName) = @_;
    %packageVcs = ();
    my $pkg_id = GetPkgIdByName ( $packageName );
    GetData_by_pkg_id ( $pkg_id, $packageName  );
#    DebugDumpData("packageVcs", \%packageVcs );
}

#-------------------------------------------------------------------------------
# Function        : readPackageData
#
# Description     : Read in package data
#
# Inputs          : Name of the package
#
# Returns         : 
#
our %ScmVersions;
sub readPackageData
{
    my ($pname) = @_;
    $pname =~ s~\.data$~~;
    my $fname = $pname . '.data';
    my @updateList;
    Verbose2 ('Reading Package Data: ' . $fname);
    Error "Cannot locate $fname" unless ( -f $fname );
    %ScmVersions = ();
    require $fname;

    Error "Data in $fname is not valid\n"
        unless ( keys(%ScmVersions) >= 0 );

    my %packageVcsRemaining = %packageVcs;

    my $essentialCount = 0;
    my $errorCount = 0;
    my $ecount = 0;
    my $transferred = 0;
    my $totalCount = 0;
    my $diffCount = 0;
    my $missingPVID = 0;
    my $rippleProcessed = 0;
    my $globalErrors = 0;
    my $notProcessed = 0;
    my $pkgBase = 0;
    my $adjustedPath = 0;
    my $postMigrationUpdate = 0;

    foreach my $entry (sort {$a <=> $b}  keys(%ScmVersions) )
    {
        $totalCount ++;
        $notProcessed++ unless $ScmVersions{$entry}{Scanned};
        $essentialCount++ if ( $ScmVersions{$entry}{Essential}  );
        $rippleProcessed++ if ( $ScmVersions{$entry}{rippleProcessed} );

        #
        #   Handle old fomat
        #
        if ( ! exists  $ScmVersions{$entry}{data} )
        {
            $ScmVersions{$entry}{data}{errFlags}  = $ScmVersions{$entry}{errFlags};
            $ScmVersions{$entry}{data}{BadProjectBase}  = $ScmVersions{$entry}{BadProjectBase} if defined $ScmVersions{$entry}{BadProjectBase};
        }


        $globalErrors++ if ( $ScmVersions{$entry}{data}{errFlags} eq 'e' );
        $pkgBase++ if ( $ScmVersions{$entry}{data}{BadProjectBase} );
        $adjustedPath++ if ( $ScmVersions{$entry}{data}{adjustedPath} );
        unless ( $ScmVersions{$entry}{TagCreated} )
        {
            $errorCount++ if ( $ScmVersions{$entry}{Essential}  );
            $ecount++;
            Verbose ("Package Not Processed: " . $ScmVersions{$entry}{vname} . ' - ' . ($ScmVersions{$entry}{data}{errStr} || 'Unspecified Error')  );
        }
    }

    foreach my $entry (sort {$a <=> $b}  keys(%ScmVersions) )
    {
        if ( $ScmVersions{$entry}{TagCreated} )
        {
            $transferred++;
            my $done = '';
            my $rmRef = $ScmVersions{$entry}{rmRef} ;
            my $ccTag = $ScmVersions{$entry}{vcsTag};

            my $include = 1;
            if ( exists $packageVcs{$entry} )
            {
#                $include = 0 if ( ($packageVcs{$entry} eq $rmRef) );
                $include = 0 if ( ($packageVcs{$entry} eq $ccTag) );
                delete $packageVcsRemaining{$entry};
            }
            else
            {
                $missingPVID++;
                $done = ' < Missing' unless $done;
                $include = 0 ;
            }

            if ( $include || $opt_force)
            {
                    $diffCount++;
                    $done = ' *' unless $done;
                    push @updateList, $entry;
            }

            Verbose ("Processed: " . $ScmVersions{$entry}{vname} . ' :: ' . ($ccTag || '???') . $done );
            
        }
    }

    #
    #   Process versions that are not a part of the backout data
    #
    foreach my $entry ( keys %packageVcsRemaining )
    {
        my $vcsTag = $packageVcsRemaining{$entry};
        if ( $vcsTag =~ m~SVN::~ )
        {
            $postMigrationUpdate++;
            print "Modified after migration: $entry: $vcsTag\n";
        }
    }

    if ( $opt_report )
    {
        return unless ($globalErrors || $pkgBase ||  $errorCount || $notProcessed || $postMigrationUpdate);
    }

    sub highlight
    {
        my ($value) = @_;
        return $value ? ' <------' : '';
    }

    my $rmTotal = scalar keys %packageVcs;
    Message ("Transfer Stats",
            ,"Package                   : $pname"
            ,"Total RM Versions         : $rmTotal"
            ,"Total Packages Processed  : $totalCount"
            ,"Packages NOT Processed    : $notProcessed"
            ,"Packages pruned           : " . ($rmTotal - $totalCount)
            ,"Essential Packages        : $essentialCount"
            ,"Essential Packages Errors : $errorCount"
            ,"Global Import Errors      : $globalErrors"
            ,"PackageBase Error         : $pkgBase"
            ,"Adjusted Paths            : $adjustedPath"
            ,"Not Transferred Packages  : $ecount"
            ,"Transferred Packages      : $transferred"
            ,"Transfer to RM            : $diffCount"
            ,"Missing PackageVersions   : $missingPVID" . highlight($missingPVID)
            ,"Ripple Processed Early    : $rippleProcessed"
            ,"Post Migration in SVN     : $postMigrationUpdate" . highlight($postMigrationUpdate)
            );

    if ( $opt_report )
    {
        return;
    }
        

    if ( $opt_test )
    {
        Message('Test Mode : No changes made to RM');
        return;
    }

    unless ( $diffCount )
    {
        Message ('Release Manager entries are all upto date');
        return;
    }

    if ( $postMigrationUpdate && !$opt_loseData )
    {
        Error ("Packages have been modified in SVN",
                "Reverting this package will lose data");
    }

    #
    #   Now do the RM Update
    #
    Message('Updating Release Manager: ' . $opt_rm);
    foreach my $entry ( @updateList )
    {
        intoReleaseManager ( $entry, $ScmVersions{$entry}{vcsTag} );
    }
}

#-------------------------------------------------------------------------------
# Function        : intoReleaseManager
#
# Description     : Update VCS tags in RM
#
# Inputs          : $pvid           - PVId
#                   $tag            - New Tag
#
# Returns         : 
#
sub intoReleaseManager
{
    my ($pvid, $new_tag ) = @_;
    my @row;
    my $user = 3768;            # buildadm

    connectRM(\$RM_DB, $opt_verbose) unless $RM_DB;

    #
    #   Clean UP some CC bits
    #
    if ( $new_tag =~ m~CC::~ )
    {
        $new_tag =~ s~CC::([^/])~CC::/$1~;
print "Modified tag $pvid: $new_tag\n";
    }


    my $m_sqlstr =  "begin release_manager.PK_RMAPI.update_vcs_details($pvid, '$new_tag', $user); end;";
    my $sth = $RM_DB->prepare($m_sqlstr);
    if ( defined($sth) )
    {
        if ( $sth->execute( ) )
        {
            if ( $sth->rows )
            {
                while ( @row = $sth->fetchrow_array )
                {
                    print "Data: @row\n";
                }
            }
            $sth->finish();
        }
        else
        {
            Error("Execute failure: $m_sqlstr", $sth->errstr() );
        }
    }
    else
    {
        Error("Prepare failure" );
    }
}

#-------------------------------------------------------------------------------
# Function        : GetPkgIdByName
#
# Description     :
#
# Inputs          : pkg_name
#
# Returns         : pkg_id
#
sub GetPkgIdByName
{
    my ( $pkg_name ) = @_;
    my (@row);
    my $pv_id;
    my $pkg_id;

    #
    #   Establish a connection to Release Manager
    #
    connectRM(\$RM_DB) unless ( $RM_DB );

    #
    #   Extract data from Release Manager
    #
    my $m_sqlstr = "SELECT pkg.PKG_NAME, pkg.PKG_ID" .
                   " FROM RELEASE_MANAGER.PACKAGES pkg" .
                   " WHERE pkg.PKG_NAME = \'$pkg_name\'";
                   
    my $sth = $RM_DB->prepare($m_sqlstr);
    if ( defined($sth) )
    {
        if ( $sth->execute( ) )
        {
            if ( $sth->rows )
            {
                while ( @row = $sth->fetchrow_array )
                {
                    Verbose3( "DATA: " . join(',', @row) );
                    $pkg_id = $row[1] || 0;
                    last;
                }
            }
            else
            {
                Error ("GetPkgIdByName:No Data for package: $pkg_name");
            }
            $sth->finish();
        }
    }
    else
    {
        Error("GetPkgIdByName:Prepare failure" );
    }

    return $pkg_id;
}

#-------------------------------------------------------------------------------
# Function        : GetData_by_pkg_id
#
# Description     : Create a hash of VCS tags for a given package
#
# Inputs          : pv_id
#
# Returns         :
#
sub GetData_by_pkg_id
{
    my ( $pkg_id, $packageName ) = @_;
    my (@row);

    #
    #   Establish a connection to Release Manager
    #
    Verbose2("Extract package versions from Release Manager: $packageName");
    connectRM(\$RM_DB) unless ( $RM_DB );

    #
    #   Extract data from Release Manager
    #
    my $m_sqlstr = "SELECT pkg.PKG_NAME, pv.PKG_VERSION, pkg.PKG_ID, pv.PV_ID, release_manager.PK_RMAPI.return_vcs_tag(pv.PV_ID)".
                   " FROM RELEASE_MANAGER.PACKAGES pkg, RELEASE_MANAGER.PACKAGE_VERSIONS pv" .
                   " WHERE pv.PKG_ID = \'$pkg_id\' AND pkg.PKG_ID = pv.PKG_ID";
                   
                   
    my $sth = $RM_DB->prepare($m_sqlstr);
    if ( defined($sth) )
    {
        if ( $sth->execute( ) )
        {
            if ( $sth->rows )
            {
                while ( @row = $sth->fetchrow_array )
                {
                    Verbose3( "DATA: " . join(',', @row) );
                    $packageVcs{$row[3]} = $row[4];
                }
            }
            else
            {
                Error ("GetData_by_pkg_id: No Data: $m_sqlstr");
            }
            $sth->finish();
        }
        else
        {
                Error ("GetData_by_pkg_id: Execute: $m_sqlstr");
        }
    }
    else
    {
        Error("GetData_by_pkg_id:Prepare failure" );
    }
}


#-------------------------------------------------------------------------------
#   Documentation
#

=pod

=for htmltoc    SYSUTIL::cc2svn::

=head1 NAME

cc2svn_updaterm - Update Release Manager with CC2SVN information

=head1 SYNOPSIS

  jats cc2svn_rollback [options] [PackageName]*

 Options:
    -help              - brief help message
    -help -help        - Detailed help message
    -man               - Full documentation
    -verbose           - Enable verbosity
    -[no]test          - Test update. Default: -notest
    -package=name      - Specify single package to be processed
    -database=name     - Default: RELMANU1 (test db) Live: RELEASEM
    -[no]force         - Force update of all entries
    -check=string      - Check operation with string
    -report            - Report on errors
    -report=2          - Report on errors, don't access RM
    -loseData          - Allow update where new versions are in SVN

=head1 OPTIONS

=over 8

=item B<-help>

Print a brief help message and exits.

=item B<-help -help>

Print a detailed help message with an explanation for each option.

=item B<-man>

Prints the manual page and exits.

=item B<-[no]test>

Invoke the program in test mode. This is the default.

In test mode the program will examine each packages 'data' results file
and report status and errors.

In 'notest' the program will update the Release Manager database.

=item B<-package=name>

This option will name one package to be processed. Packages to be
processed can just be named on the command line.

=item B<-database=name>

This option specifies the target database. The default value is 'RELMANU1'.
This is a test database.

The production database is RELEASEM.

The user must specifically specify the database to update the production system.

=item B<-[no]force>

This option will force the Release Manager entries to be updated - even if the
current entry matches the desired result.

Useful in testing.

=item B<-check=string>

This option will pass a string directly to the Release Manager updating proceedure.

With this option no packages will be examined or processed.

It is only useful for testing.

=back

=head1 DESCRIPTION

This program is a tool used in the conversion of ClearCase VOBS to subversion.
It will:

=over 8

=item *

Process all packages named on the command line or with the -package option.

=item *

Examine the packages '.data' file, whcih is created as the package is inserted
into Subversion.

=item *

Report the status of the package import and highlight issues.

=item *

Read the Release Manager entry and ensure that the entry is not the same.
If the entry is the same then it will not be updated, unless the '-force'
option has been used.

=item *

Insert the new Version Control information into the Release Manager entry.

=back

The default operation of this utility is to test the import process. The
user needs to provide specific options in order to update the production
database. This is intentional.

=cut