Subversion Repositories DevTools

Rev

Rev 2026 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

#! /usr/bin/perl
########################################################################
# Copyright (c) VIX TECHNOLOGY (AUST) LTD
#
# Module name   : jats_cbuilder.pl
# Module type   : Makefile system
# Compiler(s)   : n/a
# Environment(s):
#
# Description   : A script to determine differences between two versions of
#                 a build.
#
#                 Can, with a bit of work, create a BeyondCompare@ view of
#                 the stuff
#
#
#......................................................................#

require 5.006_001;
use strict;
use warnings;
use JatsError;
use JatsSystem;
use FileUtils;

use Pod::Usage;                             # required for help support
use Getopt::Long;
use File::Path;
use Cwd;
use Sys::Hostname;                          # For hostname

my $VERSION = "1.5.5";                      # Update this

#
#   Options
#
my $opt_debug   = $ENV{'GBE_DEBUG'};        # Allow global debug
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
my $opt_help = 0;
my $opt_manual = 0;
my $opt_drive = 'o';
my $opt_tag = 'dynamic';
my $opt_outfile;

#
#   Globals - Provided by the JATS environment
#
my $USER            = $ENV{'USER'};
my $UNIX            = $ENV{'GBE_UNIX'};
my $TMP             = $UNIX ? "/tmp" : $ENV{'TMP'};

#
#   Globals
#
my $MACHINENAME;
my @error_list;                             # ClearCmd detected errors
my $UNIX_VOB_PREFIX = '/vobs';
my $VOB_SEP         = $UNIX ? '/' : '\\';
my $BC2             = 'c:/Program Files/Beyond Compare 2/BC2.exe';

my @view_tags;
my %files;


#-------------------------------------------------------------------------------
# Function        : Mainline Entry Point
#
# Description     :
#
# Inputs          :
#

#
#   Parse the user options
#
my $result = GetOptions (
                "help+"         => \$opt_help,              # flag, multiple use allowed
                "manual"        => \$opt_manual,            # flag, multiple use allowed
                "verbose+"      => \$opt_verbose,           # flag, multiple use allowed
                "out=s"         => \$opt_outfile,           # String
                );

                #
                #   UPDATE THE DOCUMENTATION AT THE END OF THIS FILE !!!
                #

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

InitFileUtils();

#
#   Configure the error reporting process now that we have the user options
#
ErrorConfig( 'name'    => 'CCVIEW',
             'verbose' => $opt_verbose );

#
#   Only for windows
#
Error ("This program only works under WIndows")
    if ( $UNIX );

#Error ("No output file specified")
#    unless ( $opt_outfile );

#
#   Validate user options
#   Use either -label or one command line argument
#
my $label1 = shift @ARGV;
my $label2 = shift @ARGV;

Error ("Need two labels on the command line")
    unless ( $label1 && $label2 );
Error ("Too many command line arguments" )
    unless ( $#ARGV < 0 );

#
#   Determine the machine type
#
Verbose ("Machine Type: UNIX=$UNIX");

$MACHINENAME = hostname;
Error ("Machine Name not determined")
    unless ( $MACHINENAME );
chomp( $MACHINENAME );

Error ("USER name not determined" )
    unless ( $USER );

Error ("TMP not found or not a directory")
    unless ( $TMP && -d $TMP );
$TMP = "$TMP/$$";

Error ("Beyond Compare not found",
       "Looking in: $BC2" )
    unless ( -x $BC2 );

#
#   Ensure that the 'cleartool' program can be located
#
Verbose ("Locate clearcase utility in users path");
Error ("Cannot locate the 'cleartool' utility in the users PATH")
    unless ( LocateProgInPath('cleartool', '--All') );


#
#   Create dynamic views for the two views
#   Verify that the view are present
#

my $tag1 = create_dynamic_view( $label1 );
my $tag2 = create_dynamic_view( $label2 );

my $path1 = "$opt_drive:/$tag1";
my $path2 = "$opt_drive:/$tag2";

Error ("Cannot locate view directory: $path1" ) unless (-d $path1);
Error ("Cannot locate view directory: $path2" ) unless (-d $path2);

System ( $BC2, $path1, $path2 );
exit 0;

#
#   Scan the two views and create a hash of the files int he view with a
#   tag of the view that they are in. The hash key is the file name+branch
#

my @files1 = files_from_from_view( $path1, 1 );
my @files2 = files_from_from_view( $path2, 2 );

#DebugDumpData ("Files", \%files );

#
#   Create a hash of files that are different
#   The hash key will be the file name
#   The tag will be the branch that the file is on
#
my %diffs;
foreach my $file ( sort keys %files )
{
    #
    #   These files are the same
    #
    next if ( $files{$file}{1} && $files{$file}{2} );

    my $tag = 1;
    $tag = 2 if $files{$file}{2};

    #
    #   Break path into file and version
    #
    my ($f,$b) = split ('@@', $file );
    $diffs{$f}{$tag} = $file;

#    print "$file\n";
}

#
#   Process files that are common, but have changed
#
open (FO, ">", $opt_outfile) || Error ("Cannot open file: $opt_outfile");
foreach my $file ( sort keys %diffs )
{
    #
    #   Files are are common
    #
    if ( $diffs{$file}{1} && $diffs{$file}{2} )
    {
        ClearDiff("-serial_format $path1/$diffs{$file}{1} $path2/$diffs{$file}{2}");
    }
    elsif ($diffs{$file}{1} )
    {
        #
        #   File has been deleted
        #
    }
    else
    {
        #
        #   File has been added
        #
    }
}
close FO;



#DebugDumpData ("Files", \%diffs);



#System ( $BC2, $path1, $path2 );

exit (0);

#-------------------------------------------------------------------------------
# Function        : create_dynamic_view
#
# Description     : Create a dynamic view, based on a label
#
# Inputs          : $label          - Base label
#
# Returns         : 
#
sub create_dynamic_view
{
    my ($label) = @_;
    my $config = "${TMP}.config_ccview.txt";

    #
    #   Create a config spec
    #
    Verbose ("Create tmp file: $config");
    open (CF, ">$config" ) || Error ("Cannot create temp config spec file");
    print CF "element * CHECKEDOUT\n";
    print CF "element .../lost+found -none\n";
    print CF "element * $label\n";
    close CF;

    my $tag = "${USER}_${MACHINENAME}_${opt_tag}_${label}";
    push @view_tags, $tag;

    ClearCmd ( "rmview -tag $tag" );
    ClearCmd ( "mkview -tag $tag -stgloc -auto" );
    ClearCmd ( "setcs  -tag $tag $config" );

    unlink $config;

    return $tag;
}

#-------------------------------------------------------------------------------
# Function        : files_from_from_view
#
# Description     : Determine the list of files/versions in a given view
#
# Inputs          : $vpath          - Path to the view
#                   $tag            - File tag
#
# Returns         : Nothing
#                   Populates the %files array
#
sub files_from_from_view
{
    my ($vpath, $tag) = @_;
    my @files;
    my $cutlen = length ($vpath );

    my @dir_list = glob ( "$vpath/*" );
    foreach my $dir ( @dir_list )
    {
        #
        #   Skip top-level files - there will not be any
        #   Skip ClearCase directories that are place-holders
        #
        next unless ( -d $dir );
        next unless ( glob ("$dir/*") );

print "Processing: $dir\n";
        my $cmd = "cleartool ls -rec -short $dir";

        Verbose ("ClearTool: $cmd");
        open(CMD, "$cmd 2>&1 |") || Error "can't run command: $!";
        while (<CMD>)
        {
            s~[\r\n]+$~~;
            tr~\\/~/~s;
            print "$_\n" if $opt_verbose;

            #
            #   Strip the base path of the file name
            #   They are in differnt VOBS
            #
            my $file = substr ($_, $cutlen );
            $files{$file}{$tag} = 1;
        }
        close(CMD);
        Verbose2 "ClearTool Exit Status: $?";
    }
}

#-------------------------------------------------------------------------------
# Function        : END
#
# Description     : This function will be called as the program exists
#                   It will also be called under error conditions
#                   Close down stuff we created
#
# Inputs          : 
#
# Returns         : 
#

sub END
{
    Message ("Cleaning up views") if @view_tags;
    foreach my $tag ( @view_tags )
    {
#        Message ("NOT Cleaning up views");
        ClearCmd ( "rmview -tag $tag" );
    }
}

#-------------------------------------------------------------------------------
# Function        : ClearDiff
#
# Description     : Issue a cleartool command
#                   Filter out many of the stupid messages
#
# Inputs          : Options and Command line
#                   Options:
#                       --Quiet     - Supress all command output
#
# Returns         : Error code
#
sub ClearDiff
{
    my $quiet;

    #
    #   Scan for initial options
    #       --Quiet
    #
    if ( $_[0] eq '--Quiet' )
    {
        $quiet = 1;
        shift;
    }

    my $cmd = "cleardiff @_";

    Verbose ("ClearTool: $cmd");
    open(CMD, "$cmd 2>&1 |") || Error "can't run command: $!";
    while (<CMD>)
    {
        #
        #   Filter output from the user
        #
        next if ( $quiet );
        s~(file 1: )$path1/~$1~;
        s~(file 2: )$path2/~$1~;
        print FO $_;
    }
    close(CMD);

    Verbose2 "ClearTool Exit Status: $?";
    return $? / 256;
}

#-------------------------------------------------------------------------------
# Function        : ClearCmd
#
# Description     : Execute a cleartool command
#                   Capture error messages only
#
# Inputs          : Command to execute
#
# Returns         : Exit code
#                   Also the global @error_list
#
sub ClearCmd
{
    my( $cmd ) = @_;
    Verbose2 "cleartool $cmd";

        @error_list = ();
        open(CMD, "cleartool $cmd  2>&1 |")    || Error "can't run command: $!";
        while (<CMD>)
        {
            chomp;
            Verbose ($_);
            push @error_list, $_ if ( m~Error:~ );
        }
        close(CMD);

    Verbose2 "Exit Status: $?";
    return $? / 256;
}

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

=pod

=head1 NAME

jats_cbuilder - Build a package given a clearcase label

=head1 SYNOPSIS

  jats jats_ccview [options] label-1 label-2

 Options:
    -help              - brief help message
    -help -help        - Detailed help message
    -man               - Full documentation

=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.

=back

=head1 DESCRIPTION

This program is the primary tool for ...

=cut