Subversion Repositories DevTools

Rev

Blame | Last modification | View Log | RSS feed

#! perl
########################################################################
# Copyright ( C ) 2004 ERG Limited, All rights reserved
#
# Module name   : jats.sh
# Module type   : Makefile system
# Compiler(s)   : n/a
# Environment(s): jats
#
# Description   : Save a rewritten build.pl file back into version control
#                 This script is a dedicated part of the auto build system
#
# Usage:
#
# Version   Who      Date        Description
#
#......................................................................#

require 5.6.1;
use strict;
use warnings;
use JatsError;
use Getopt::Long;
use Pod::Usage;                             # required for help support

################################################################################
#   Option variables
#

my $VERSION = "1.2.0";                      # Update this
my $opt_verbose = 0;
my $opt_infile  = "auto.pl";
my $opt_ofile = "build.pl";
my $opt_help = 0;
my $opt_manual;
my $opt_label;
my $opt_branch_default = "AutoBuilder";
my $opt_branch;
my $opt_newbranch;

#
#   Globals
#
my @error_list;
my $last_result;
my $last_result_1;

my $result = GetOptions (
                "help+"         => \$opt_help,          # flag, multiple use allowed
                "manual"        => \$opt_manual,        # flag
                "verbose+"      => \$opt_verbose,       # flag
                "outfile=s"     => \$opt_ofile,         # string
                "infile=s"      => \$opt_infile,        # string
                "label=s"       => \$opt_label,         # string
                "branch=s"      => \$opt_branch,        # string
                "newbranch"     => \$opt_newbranch,     # string
                );

#
#   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_manual || ($opt_help > 2));

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

Error ("No label")
    unless ( $opt_label  );

Error ("Input and output file are the same: $opt_infile" )
    if ( $opt_infile eq $opt_ofile );

Error ("Input file not found: $opt_infile" )
    unless ( -f $opt_infile );

Error ("Output file not found: $opt_ofile" )
    unless ( -f $opt_ofile );

Error ("Must provide a branch when usng newbranch option")
    if ( $opt_newbranch && ! $opt_branch );

$opt_branch = $opt_branch_default
    unless ( $opt_branch );

#
#   Determine the name of the Branch to be used
#   This is based on the branch that the file is already on as ClearCase does
#   not allow multiple instances of a branch on different sub-branches
#
ClearCmd ("describe -fmt \"%n\" \"$opt_ofile\"");
Error ("Program Terminated") if ( @error_list );
Error ("File may not be a VOB object: $opt_ofile" ) unless ( $last_result );
my $full_name = $last_result;

$last_result =~ m~(.*)/([^/]+)$~;
my $full_path = $1;

$last_result =~ m~(.*)/([^/]+)/([^/]+)~;
my $current_branch = $2;

$last_result =~ m~@@(.*)/([^/]+)~;
my $full_branch = $1;
my $target_branch = $full_branch;
my $branch_point = "";

Error ("Cannot determine full pathname of the file: $full_name") unless ( $full_path );

Verbose2 ("FullName     : $full_name" );
Verbose2 ("FullPath     : $full_path" );
Verbose2 ("Branch       : $current_branch" );
Verbose2 ("Userb        : $opt_branch" );
Verbose2 ("FullBranch   : $full_branch" );
#
#
#   Determine the branch that the file is on
#   If it is not on the desired branch then we will need to create the branch
#
#   Ensure that the required branch exists in the current VOB
#   Need to handle some legacy branches that were created with the name AutoBuilder
#   by not creating AutoBuild/AutoBuilder.AutoBuilder branches but retaining the
#   existing AutoBuilder branch.
#
if ( $opt_newbranch )
{
    #
    #   User has asked for a new branch
    #   Place the file on /main/xxxxx
    #
    $branch_point = "-version /main/0";
    $target_branch = "/main/$opt_branch";

}
elsif ( $current_branch =~ m/^$opt_branch/ )
{
    #
    #   Current branch has the same name ( prefix) as the desired branch
    #   Use it
    #
    $opt_branch  = $current_branch;
}
else
{
    #
    #   Current branch has a different name
    #   Construct new branch name
    #
    $opt_branch = "$opt_branch.$current_branch";
    $target_branch .= "/$opt_branch";
}

Verbose2 ("TargetBranch : $target_branch" );
Verbose2 ("BranchPoint  : $branch_point" );

#
#   Ensure that the specified label exists
#   Determine if it is locked too
#
ClearCmd ("describe -fmt %[locked]p lbtype:$opt_label" );
Error ("Program Terminated") if ( @error_list );
my $was_locked = 1 unless ( $last_result =~ m~unlocked~ );

#
#   Create the desired branch if it does not already exist
#   Dtected locked element and unlock it
#
ClearCmd ("lstype -short brtype:$opt_branch" );
if ( $last_result =~ m~\(locked\)~ )
{
    ClearCmd( "unlock -c \"Unlocked by JATS ASAVE\" brtype:$opt_branch" );
}
elsif ( $last_result ne $opt_branch )
{
    ClearCmd ("mkbrtype -c \"Contains saved versions of $opt_ofile files created by the AutoBuild system\" $opt_branch" );
    Error ("Program Terminated") if ( @error_list );
}

#
#   Ensure that the file is not locked
#   Unlock the file - can't do anything to a 'locked' file
#
ClearCmd ("lslock -short $opt_ofile" );
if ( $last_result )
{
    ClearCmd( "unlock -c \"Unlocked by JATS ASAVE\" $opt_ofile" );
}

if ( $current_branch ne $opt_branch )
{
    #
    #   Need to create the initial branch point, but only if one does not already
    #   exists
    #
    Verbose ("Does a branch exist" );
    if ( ClearCmd( "find $opt_ofile -version \"brtype($opt_branch)\" -print" ) )
    {
        Error ("Internal error. Cleartool find should not fail");
    }
    if ( $last_result )
    {
        #
        #   A branch already exists - and there can only be one
        #
        $last_result =~ m~@@(.*)/([^/]+)~;
        $target_branch = $1;
        Error ("Cannot determine full branch path: $last_result") unless ( $target_branch );
        Verbose2 ("Target Branch: $target_branch" );
    }
    else
    {
        Verbose ("Create the initial branch point" );
        ClearCmd( "mkbranch -nco -nc -nwarn $branch_point $opt_branch $opt_ofile" );
    }
}

#
#   Ensure that the branch with the target auto builder file on is not locked
#
ClearCmd ("lslock -short \"$opt_ofile\@\@$target_branch\"" );
if ( $last_result )
{
    ClearCmd( "unlock -c \"Unlocked by JATS ASAVE\" \"$opt_ofile\@\@$target_branch\"" );
}


#
#   Look for a checked out file on the target branch
#   It may be reserved - this will kill the process, so unreserve it
#
if ( ClearCmd( "lsco -long -brtype $opt_branch $opt_ofile" ) )
{
    Error ("Internal error. Cleartool lsco should not fail");
}

if ( $last_result && $last_result_1 =~ m/\(reserved\)/ )
{
    #
    #   Determine the target view an unreserve the checkout
    #   There will only be one as one one version can be reserved on a branch
    #
    $last_result =~ m~\(\"(.+)\"\)~;
    my $view = $1;
    $view =~ s~/~\\~g unless ( $ENV{GBE_UNIX} );
    Verbose2 ("Reserved checkout: Target View: $view" );
    ClearCmd( "unreserve -comment \"Unreserved by JATS ASAVE\" -view \"$view\" $opt_ofile" );
}


#
#   Use clearcase to checkout the output file
#
ClearCmd ("co -nc -nq -ndata -nwarn -branch \"$target_branch\" $opt_ofile");
Error ("Program Terminated") if ( @error_list );

#
#   Place the label on this file
#       If the label is locked then unlock it first
#       This is OK, because we are the builder ( or have permission )
#
ClearCmd ("unlock lbtype:$opt_label" ) if $was_locked;

ClearCmd ("mklabel -replace $opt_label \"$opt_ofile\"" );
my @delayed_error = @error_list;

ClearCmd ("lock lbtype:$opt_label" ) if $was_locked;

#
#   Place a Hyperlink Merge arrow between the two files if it looks as though we
#   have stolen the file or its label. If the original build file is on a different branch
#   the we have stolen it.
#
Verbose ("Do we need to create a Hyperlink" );

my $target_name = $opt_ofile;
Verbose2 ("FullName: $full_name :Branch: $full_branch" );
Verbose2 ("TargetName: $target_name :Branch: $target_branch" );

if ( ( $full_branch ne $target_branch ) && ( !$opt_newbranch ) )
{
    ClearCmd ("mkhlink Merge \"$full_name\" \"$target_name\" ");
}

#
#   Check in the file auto.pl file as the new build.pl file
#   This may get ugly if the current config-spec does not have a rule to
#   select the "new" build.pl file. This is often the case
#
#   Examine the error output and discard these errors
#
ClearCmd ("ci -c \"AutoBuilder checkin: $opt_label\" -identical -from \"$opt_infile\" \"$opt_ofile\"");
Error ("Program Terminated") unless ( $last_result =~ m/Checked in "$opt_ofile" version/ );

@error_list = @delayed_error;
Error ("Program Terminated") if ( @error_list );

exit 0;

#-------------------------------------------------------------------------------
# Function        : ClearCmd
#
# Description     : Similar to the system command
#                   Does allow standard output and standard error to be captured
#                   to a log file
#
#                   Used since I was having problems with calling other programs
#                   and control-C. It could hang the terminal session.
#
# Inputs          :
#
# Returns         :
#
sub ClearCmd
{
    my( $cmd ) = @_;
    Verbose2( "cleartool $cmd" );

        @error_list = ();
        $last_result = undef;
        $last_result_1 = undef;

        open(CMD, "cleartool $cmd  2>&1 |")    || Error( "can't run command: $!" );
        while (<CMD>)
        {
            chomp;
            $last_result_1 = $last_result;
            $last_result = $_;
            $last_result =~ tr~\\/~/~s;

            Verbose ( "cleartool resp:" . $_);
            push @error_list, $_ if ( m~Error:~ );
        }
        close(CMD);

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

#-------------------------------------------------------------------------------
# Function        : display_error_list
#
# Description     : Display the error list
#                   This function is registered as an Error callback function
#                   it will be called on error exit
#
# Inputs          :
#
# Returns         :
#
sub display_error_list
{
    foreach ( @error_list )
    {
        print "$_\n";
    }
}

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

=pod

=head1 NAME

jats_save_build - Save a modified build.pl/depends.xml file into version control

=head1 SYNOPSIS

  jats etool jats_save_build [options]

 Options:
    -help               - brief help message
    -help -help         - Detailed help message
    -man                - Full documentation
    -verbose            - Verbose operation
    -infile xxx         - Input file (auto.pl)
    -outfile xxx        - Output file (build.pl)
    -label xxx          - Label the new file (mandatory)
    -branch xxx         - Branch to create (AutoBuilder)
    -newbranch          - Force file to be on a new (project) branch

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

This option will force the file to be checked into a new branch
The branch will be created on /main/0 unless it is already found elsewhere

This option allows a build.pl file to be placed on a new project branch.

=back

=head1 DESCRIPTION

This utility is used by the automated build system to place a modified build.pl
or a depends.xml file under version control, and then place a label on the file.

The utility will place the "new" build.pl file on a named branch of the branch
that contains the current build.pl file.

If the build.pl file is sourced from a different branch then a Merge arrow
will be created to indicate where the file and its label was taken from.

The operation will fail if that file is checked out "reserved". The program
can work around this - but its not done yet.

=cut