#!/usr/bin/perl

# Branch engine for cdsp4
# Author: Shiv Sikand 


open(DT,"date|") || die;

while(<DT>) {
    $date=$_;
}


use Getopt::Long;

$Getopt::Long::autoabbrev=0;  #make them specify exact option

unless($result=GetOptions("h",
			  "tp=s","block=s",
			  "user=s",
			  "lib=s",
			  "add=s",
			  "site=s",
			  "bname=s","from=s", "noint","force","lastchange=s")){
    die "Illegal Input Options, -h for help\n";
}

$HELP="OPTION ERRORS\n";

$opt_top=1;


if($opt_block && $opt_top) {

    die "Mutex block/top !!!!\n";
}

$opt_sp=$ENV{"PROJECT"};

print "Project is $opt_sp\n";


unless($opt_sp && $opt_tp && ( $opt_top || $opt_block || $opt_lib) && ($opt_bname || $opt_user)) {
    print "$HELP\n";
    exit;
}


if($opt_from && $opt_lastchange) {
    print "from and lastchange are conflicting options !!\n";
    exit;
}

if($opt_add && !$opt_bname) {
    print "add requires the bname argument!!\n";
    exit;
}


# Project specific variables

(@projparse)=split('/',$opt_sp);


# Derived chip and rev from $opt_sp

$chip=$projparse[$#projparse-1];
$rev=$projparse[$#projparse];

# Define cadence location within the tree

$libsubdir="layout/cadence";
$sourceproj=$opt_sp;
$targetproj=$opt_tp;

# Define cds.lib and cds.p4client locations

$cdslibsfile=$sourceproj."/$libsubdir/cds.lib";
$cdslibtfile=$targetproj."/$bdir"."/$libsubdir/cds.lib";
$cfile=$sourceproj."/$libsubdir/cds.p4client";


# Traling slashes can cause a big nightmare
# if they exist in one but not in the other



if(substr($opt_sp,-1,1) eq "/") {
    print "ERROR: No trailing slashes allowed in sp or tp\n";
    exit;
}

if(substr($opt_tp,-1,1) eq "/") {
    print "ERROR: No trailing slashes allowed in sp or tp\n";
    exit;
}

$user=$ENV{USER};
$block=$opt_block;
$ubname=$opt_bname;



if(!$ubname) {
    
    @df=split(' ',$date);
    $cnumspec="";
    # build the branch spec
    if($opt_block) {
      if($opt_block eq "tapeout") {
	$bname=$chip."_".$rev."_".$block."_".$df[1].$df[2]."_".$df[5];
      } else {
	$bname=$chip."_".$rev."_".$block."_".$df[1].$df[2]."_".$df[5]."_$opt_user";
      }
    }
    elsif($opt_top) {
	$bname=$chip."_".$rev."_top_".$df[1].$df[2]."_".$df[5]."_$opt_user";
    }
    
    elsif($opt_lib) {
	$bname=$chip."_".$rev."_".$lib."_".$df[1].$df[2]."_".$df[5];
    }
  }
else {
    $bname = $ubname;
  }


# add the site based postfix

if(!$ubname && $opt_site) {
  $bname=$bname."_".$opt_site;
}



if($opt_lastchange) {
    print "\nBranch will be integrated to state at Change $opt_lastchange\n\n";
    $cnumspec="@".$opt_lastchange;
}

if($opt_from) {

    $bfname=$opt_from;
# get the file list for the client (excludes cds libs)
    $bfclient=$bfname."_client";
#set up the names
    if(!$opt_bname) {
	(@bname2)=split('_',$opt_from);
	$bname=$bname."_".$bname2[2];
	# has the name got a month field instead of a year field at the end
	# if so, it was a bob itself
	# if that's the case we to contruct the complex name
	
	# find everything after the year field
	# and append it
	(@bname3)=split(/_[0-9]+/,$opt_from);
	if($bname3[1]) {
	    $bname=$bname.$bname3[1];
	}
    }

    $newclient=$bname."_client";

    if(!$opt_add) {
	# get the non cds data
	%flist=();
	%flistl=();
	&getfileparents($bfname,$bfclient,\%flist,\%flistl);
	# assoc array flist contains list of files for non-cds data
	# dump it to a file so we can use it with -x
	open(BFILES1,">/tmp/bfilesmain.$$") || die;
	foreach $key (sort(keys %flist)) {
	    print BFILES1 "$flist{$key}\n";
	}
	close(BFILES1);
	
	# locally edited files need to be handled separately
	
	if(%flistl) {
	    $dolocal=1;
	    open(BFILES2,">/tmp/bfilesmainl.$$") || die;
	    foreach $key (sort(keys %flistl)) {
		print BFILES2 "$flistl{$key}\n";
	    }
	    close(BFILES2);
	}

	# Build a label to mark the files so we can easily integrate the label's contents 
	$lname=$bfname."label";
	$cmd="p4 label -o $lname | p4 label -i > /dev/null";
	system($cmd);
	# sync the label to the file list
	print "Syncing to label for mainline files\n";
	$cmd="p4 -c $bfclient -x /tmp/bfilesmain.$$ labelsync -a -l $lname >> /tmp/bflsync.$$ 2>&1";
	system($cmd);
	#set up the integration command
	$int_cmd="p4 -c $newclient integrate //depot/...@".$lname." //depot/$bname/...";
	
	# Do the same (similar) for local files
	if($dolocal) {
	    $lnamel=$bfname."label_local";
	    $cmd="p4 label -o $lnamel | p4 label -i ";
	    system($cmd);
	    # sync the label to the file list
	    print "Syncing to label for local files\n";
	    $cmd="p4 -c $bfclient -x /tmp/bfilesmainl.$$ labelsync -a -l $lnamel >> /tmp/bflsyncl.$$ 2>&1";
	    system($cmd);
	    # create the crossbranch spec
	    $crossbranch="cb".$bfrom.$bname;
	    $cmd="p4 branch -o $crossbranch | p4 branch -i > /dev/null";
	    system($cmd);
	    # fix the view
	    $cmd="p4 branch -o $crossbranch | sed 's/\\/\\/depot\\/\\.\\.\\. \\/\\/depot\\/\\.\\.\\./\\/\\/depot\\/$bfname\\/\\.\\.\\. \\/\\/depot\\/$bname\\/\\.\\.\\./g' | p4 branch -i > /dev/null";
	    system($cmd);
	    #set up the integration command
	    $int_cmd2="p4 -c $newclient integrate -b $crossbranch //depot/...\@".$lnamel;
	}
    }
}
print "\nSource project is $sourceproj\n";

if($opt_block) {
    $branchdes=$opt_block;
}
else {
    if($opt_top) {
	$branchdes="top";
    } else {
	$branchdes=$opt_lib;
    }
}


# Build the branches

if($bname eq "") {
    die "Null bname!";
}

if($opt_add) {
    print "Updating $bname to include $opt_add\n";
    $newclient=$bname."_client";
    print "$newclient\n";
} else {

    if(!$opt_from2) {

      # Get the refclient spec
      $refclient=$chip."_".$rev."_ref_".$branchdes;

      # Check to see if it exists
      $cmd="p4 clients | grep $refclient > /dev/null";
      system($cmd);
      # Good exit means it exists
      if ($? ne 0) {
	print "Couldn't find $refclient, aborting\n";
	exit(1);
	
	
      }


      $cmd="p4 client -o $refclient | grep \"^\t//\*\" ";
      
      $bstring="Branch: $bname\nDescription: $branchdes $chip $rev (by $user)\nView:\n";

      # This gives us the LHS view mappings
      open(CMD, "$cmd|") || die ;
      while(<CMD>) {
	chop;
	(@ddata)=split;
	$rhs=$ddata[0];
	$rhs =~ s/$chip\/$rev/$bname/g;
	
	$dstring="\t$ddata[0] $rhs\n";
	$bstring=$bstring.$dstring;

      }

      $cmd="echo \"$bstring\" > /tmp/bspec; p4 branch -i < /tmp/bspec";
      system($cmd);
    }
    else {

      die("Cloning not supported\n");
    # Clone named branch
    if(!$ubname) {
      $bname=$opt_from2."_".$df[1].$df[2];
    }
	else {
	    $bname=$ubname;
	}
	print "Target project is $targetproj/$bname\n\n";
	print "Building branch $bname from $opt_from2\n";
	die("Broken");
	$cmd="echo \"Branch: $bname\nDescription: $branchdes sub branch built by $user\nView:\n\t//depot/$chip/$rev/$opt_from2/layout/blocks/$block/cadence/$block/... //depot/$bname/layout/blocks/$block/cadence/$block/...\n\t//depot/layout/reference/*/cadence/...  //depot/$bname/layout/reference/*/cadence/...\"> /tmp/bspec; p4 branch -i < /tmp/bspec > /dev/null";
	system($cmd);
	
    }

# build a client

# clone the main gfxdesign view spec
    
    $newclient=$bname."_client";


    if(!$opt_from2) {
	
	#$refclient=$chip."_ref_".$branchdes;
	$refclient=$chip."_".$rev."_ref_".$branchdes;	
    } else {
	
	$refclient=$opt_from2."_client";
    }

    # Make client building a subroutine with nocds flag
    if($opt_top) {
	&buildclient($refclient,$newclient,$sourceproj,$targetproj,1,1);
    }
    else {
	&buildclient($refclient,$newclient,$sourceproj,$targetproj,1,0);
    }
    

    if( !$opt_noint) {
	
	# Integrate the new branch 
	print "Integrating the branch\n";
	if(!$int_cmd) {
	    $int_cmd="p4 -c $newclient integrate -v -b $bname $cnumspec";
	}

	print "\n$int_cmd\n\n";
	system($int_cmd);
	
	if($int_cmd2) {
	    print "\n$int_cmd2\n\n";
	    system($int_cmd2);
	}

	
	if($opt_from) {
	    # delete the temp label
	    $cmd="p4 label -d $lname";
	    system($cmd);
	    $cmd="p4 label -d $lnamel";
	    system($cmd);
	}
	
	
# Submit the branch
	
	$cmd="p4 -c $newclient change -o | sed 's/<.*>/Branch submit by buildbranch/' > /tmp/subout.$$";
	system($cmd);
	open(SUB, "</tmp/subout.$$") || die "Couldn't read change description\n";
	$submit=0;
	while(<SUB>) {
	    
	    if(/^Files/) {
		$submit++;
		close(SUB);
	    }
	}
	if($submit) {
	    $cmd="p4 -c $newclient submit -i < /tmp/subout.$$";
	    system($cmd);
	}
    }


# Rebuild the client correctly

#&buildclient($refclient,$newclient,$sourceproj,$targetproj,0);

# Fake sync the client to update the files

#$cmd="p4 -c $newclient flush";
#system($cmd);


# Delete newclient if mode layout since it's now empty


}


if($opt_nocds) {
    exit;
}


$bdir="$bname";




# Build Cadence library clients


print "\nBuilding Cadence library clients\n";
$cdslibsfile=$sourceproj."/$libsubdir/cds.lib";

if($opt_block eq "tapeout") {
  $cdslibtfile=$targetproj."/$libsubdir/cds.lib";
} else {
  $cdslibtfile=$targetproj."/$bdir"."/$libsubdir/cds.lib";
}

$p4 = "p4";

open(CFILE, "<$cfile") || die "Couldn't read $cfile\n";

print "Reading $cfile\n";

while(<CFILE>) {

    if(/^\#/) {
	next;
    }

    chop;


(@cdata)=split;

$path=$cdata[1];

$client=$cdata[2];
(@cinfo)=split(':',$cdata[2]);

#$client2=$cinfo[0].":".$cinfo[1];

$client2=$cinfo[0];


# Read the client spec so that we can clone it
# Only clone libraries that are in the branch spec!!
if($opt_add) {
    if($client =~ /$opt_add/) {
	$vclient{$client}=$client2;
	print "Accepting requested client $client\n";
	close(CFILE);
    }
}

if(!$opt_add)  {
    if(!$opt_top) {
	$match=$blocklib.":".$chip."_".$rev;
	# Accept this blocks libraries or reference libs only
	if($client =~ /$match/ || $path =~ /reference/) {
	    #print "Acepting client $client\n";
	    $vclient{$client}=$client2;
	}
    } else {
	# Accept all clients since it's a top level build
	print "Acepting client $client\n";
	$vclient{$client}=$client2;
    }
}
}


foreach $client (keys %vclient) {
    
    $client2=$vclient{$client};
$cmd="p4 -c $client client -o";

open(CMD, "$cmd|") || die ;

open(CMDOUT, ">/tmp/cbout") || die ;

while(<CMD>) {


    if(/^Options/) {
	# Modtime is nice for sorting in lbb
	s/nomodtime/modtime/g;
	if($opt_site) {
	  s/nocompress/compress/g;
	}
	print CMDOUT $_;
    }

    if(/^Client/) {

	print CMDOUT "Client: $client2:$bdir\n\n";
	
    }
    
    if(/^Description/) {

	print CMDOUT "Description:\n\tcds library\n\n";
	
    }

    if(/^Root/) {
	# Add the branch spec to the root
	# where's a perl manual when you need one
	$swap=0;

	if($opt_block eq "tapeout") {
	  $newroot=$targetproj;
	} else {
	$newroot=$targetproj."/".$bdir;
      }
	$swap = s/$sourceproj/$newroot/g ;
	
	#s/$sourceproj/$newroot/g ;
	

	if($swap eq 1) {
	    print CMDOUT "$_\n";
	    
	}
	else {
	    print "Failed to map root for client $client\n$_\n";
	    print "Check your -sp flag!\n";
	    exit;
	}
	
    }


    if(/^View/) {

	print CMDOUT "$_\n";
    }



    # BOB depot spec has extra component that we need to skip
    if(/^\t\-{0,1}\/\/depot/) {
	
	if(!($opt_from || $opt_from2)) {
	    $newdepot="depot/".$bdir;
	    # New LHS
	    s/depot\/$chip\/$rev/$newdepot/g ; 
	    #print "$_\n";
	    # New RHS
	    # Everything before the colon
	    # eg aq:n1 becomes aq:n1_aq_Oct7_1999

	    $newcdsclient=$client2.":".$bdir ;
	    s/$client/$newcdsclient/g;
	    print CMDOUT $_;
	} else {
	    if($opt_from) {
		$newdepot="depot/".$bdir;
		s/$opt_from\///;
		s/depot\/$chip\/$rev/$newdepot/g ; 
		# New RHS
		$newcdsclient=$client2.":".$bdir ;
		s/$client/$newcdsclient/g;
		print CMDOUT $_;
	    }
	    
	    if($opt_from2) {
		$newdepot="depot/".$bdir;
		s/$opt_from2\///;
		s/depot\/$chip\/$rev/$newdepot/g ; 
		# New RHS
		$newcdsclient=$client2.":".$bdir ;
		s/$client/$newcdsclient/g;
		print CMDOUT $_;
	    }


	}
    }
}
close(CMDOUT);
#print "Building client $newcdsclient\n";
$cmd=$p4." -c $newcdsclient client -i < /tmp/cbout > /dev/null";
system($cmd);


# integrate the cadence libraries
# since we don't allow overlapping clients
# and need to set up the right state for a
# Fast integrate using -v


# These should already be integrated at branch build time


#if( !$opt_noint && !$opt_from && !opt_add) {
#    $cmd="p4 -c $newcdsclient integrate -v -b $bname $cnumspec";
#    print "$cmd\n";
#    system($cmd);
#}


if($opt_from) {
    # Do the same thing that we did earlier to build a file set
    %flist=();
    %flistl=();
    $cdsname=$client.":".$bfname;

    
    &getfileparents($bfname,$cdsname,\%flist,\%flistl);
    # assoc array flist contains list of files for non-cds data
    # dump it to a file so we can use it with -x
    if(%flist) {
	open(BFILES1,">/tmp/bfilecds.$newcdsclient.$$") || die;
	foreach $key (sort(keys %flist)) {
	    print BFILES1 "$flist{$key}\n";
	}
	close(BFILES1);
    }
    
    if(%flistl) {
	open(BFILES2,">/tmp/bfilecdsl.$newcdsclient.$$") || die;
	foreach $key (sort(keys %flistl)) {
	    print BFILES2 "$flistl{$key}\n";
	}
	close(BFILES2);
    }
    if(%flist) {
	# Build a label to mark the files so we can easily integrate the label's contents 
	$lname=$newcdsclient."label";
	$cmd="p4 label -o $lname | p4 label -i > /dev/null";
	system($cmd);
	# sync the label to the file list
	$cmd="p4 -c $newcdsclient -x /tmp/bfilecds.$newcdsclient.$$ labelsync -a -l $lname> /tmp/bflsync.$$ 2>&1";
	system($cmd);
	#set up the integration command
	print "INTEGRATING mainline\n";
	$int_cmd="p4 -c $newcdsclient integrate //depot/...@".$lname." //depot/$bname/...";
	print "\n$int_cmd\n\n";
	system($int_cmd);
	$cmd="p4 label -d $lname";
	system($cmd);
    }
    # Do the same for the locals
    if(%flistl) {
	$lnamel=$newcdsclient."label_local";
	$cmd="p4 label -o $lnamel | p4 label -i > /dev/null";
	system($cmd);
	# sync the label to the file list
	$cmd="p4 -c $newcdsclient -x /tmp/bfilecdsl.$newcdsclient.$$ labelsync -a -l $lnamel > /tmp/bflsyncl.$$ 2>&1";
	system($cmd);
	#set up the integration command
	print "INTEGRATING local edits\n";
	$int_cmd="p4 -c $newcdsclient integrate -b $crossbranch //depot/...\@".$lnamel;
	print "\n$int_cmd\n\n";
	system($int_cmd);
	$cmd="p4 label -d $lnamel";
	system($cmd);
    }
}

#Manual submit

# But don't submit empty files

$cmd="p4 -c $newcdsclient change -o | sed 's/<.*>/Branch submit by buildbranch/' > /tmp/subout.$$";
system($cmd);
open(SUB, "</tmp/subout.$$") || die "Couldn't read change description\n";
$submit=0;
while(<SUB>) {
    
    if(/^Files/) {
	$submit++;
	close(SUB);
    }
}
if($submit) {
    $cmd="p4 -c $newcdsclient submit -i < /tmp/subout.$$";
    system($cmd);
}

# Now sync to bring in the files

if($opt_force) {
    $cmd="p4 -c $newcdsclient sync -f";
} else {
    if(!$opt_add) {
	if(!$opt_noint) {
	    #print "Syncing client $newcdsclient\n";
	    $cmd="p4 -c $newcdsclient sync";
	} else {
	    $cmd="p4 -c $newcdsclient sync -n";
	}
    } else {
	# bring in the new data
	$cmd="p4 -c $newcdsclient integrate -v -b $bname\n";
    }
	
}


# Need to read stderror for the error
print "Int cmd is $cmd\n";
open(CMD, "$cmd 2>&1 |") || die "Couldn't do an integrate....\n";

while(<CMD>) {

    
    if(/No such file/) {

	# Delete the client, it's not valid
	print "ERROR: $newcdsclient does not contain any data\n";
	print "ERROR: If this is expected, please use the -skip option\n";
	print "ERROR: Or integrate this library explicitly by typing\n";
	print "p4 -c $newclient integrate -b $bname\n";
	print "Then run this script again with the -add option\n";
    }
}



}

close(CFILE);

#Manual submit

# But don't submit empty files

$cmd="p4 -c $newcdsclient change -o | sed 's/<.*>/Branch submit by buildbranch/' > /tmp/subout.$$";
system($cmd);
open(SUB, "</tmp/subout.$$") || die "Couldn't read change description\n";
$submit=0;
while(<SUB>) {
    
    if(/^Files/) {
	$submit++;
	close(SUB);
    }
}
if($submit) {
    $cmd="p4 -c $newcdsclient submit -i < /tmp/subout.$$";
    system($cmd);
}


# write the master client file

# branch may not have all the chip clients that match this grep spec

$cmd="$p4 clients | grep 'cds library' | grep '$bdir '  > /tmp/client";
system($cmd);

open(CDATA, "</tmp/client") || die ;

if($opt_block eq "tapeout") {
  $cfile=$targetproj."/$libsubdir/cds.p4client";
} else {
$cfile=$targetproj."/".$bdir."/$libsubdir/cds.p4client";
}


open(CDOUT, ">$cfile") || die "Couldn't write $cfile\n";

print "Writing $cfile\n";



if(!$opt_add) {
    print CDOUT "# Master Client file for $targetproj/$bdir\n# Built by buildbranch $date";
}

while(<CDATA>) {

    @cdata=split;
# Key it on the root
$cdslist{$cdata[4]}=$cdata[1];

(@lib)=split('/',$cdata[4]);

# Last element in path is lib name

$libname=$lib[($#)-1];

#print "LIB: $libname PATH:$cdata[4] CLIENT: $cdata[1]\n";

print CDOUT "$libname $cdata[4] $cdata[1]\n";

}

if($opt_add) {
    print "Updating branch cds.lib file\n";
}
else {
    print "Building branch cds.lib file\n";
}

# Unamanaged in trex

#$cmd="p4 -c $newclient edit $cdslibtfile";
#system($cmd);

# Process it !
open(CDSL, "<$cdslibsfile") || die "Couldn't read $cdslibsfile!\n";

if($opt_add) {
    open(CDSLB, ">>$cdslibtfile") || die "Couldn't open $cdslibtfile!\n";
} else {
    open(CDSLB, ">$cdslibtfile") || die "Couldn't open $cdslibtfile!\n";
}


if(!$opt_add) {
    print CDSLB "--  File Created by buildbranch $date\n";
}


$client=0;


while(<CDSL>) {


    $match=0;
if($opt_add) {
    
    if(!(/ $opt_add /)) {
	next;
	
    }
}


if( /^DEFINE/ || /^INCLUDE/) {
    $save=$_;
    ($ig,$libname,$path)=split;

    if($opt_add) {
	
	if(!(/ $opt_add /)) {
	    next;
	    
	}
    }

    $newproj=$targetproj."/$bdir";
    # only map out the library if it is p4 controlled
    # since it won't exist in the branch otherwise
    $gotc=0;

    $bpath=$path;
    $bpath=~ s/$sourceproj/$newproj/g;


    if($client=$cdslist{$bpath}) {
	$gotc++;
    }

    # handle basic library
    # bring it in exactly as defined !
    if(/INCLUDE/) {
	print "Bringing in $_\n";
	print CDSLB $_;
	next;
    }

    
    if($gotc) {
	$client=$save;
	s/$sourceproj/$newproj/g;
	
	# Check to see if the directory exists
	# since it may not have been branched
	$copy=$_;
	(@elements)=split(' ',$copy);
	$cmd="ls -d $elements[2] >>/dev/null 2>&1";
	#print "$cmd\n";
	system($cmd);
	
	if($? ne 0) {
	    print "Skipping unbranched lib: $elements[1]\n";
	    next;
	}
	print "Mapping $libname in branch cds.lib\n";
	print CDSLB $_;
    }
    else {
	# bring in non-managed libs directly as references to mainline
	# except for rams
	if(!( $save =~ /$chip_ram/)) {
	    print "Writing $libname in branch cds.lib file\n";
	    print CDSLB $save;
	}
    }
}
else {
    
    if(/ \./)  {

	print "Couldn't map dot in $_\n";
	exit;
    }
    
    print CDSLB $_;
}
}


close(CDSLB);
close(CDSL);



unlink("/tmp/cbout");
unlink("/tmp/client");

if($opt_from) {
    system("rm /tmp/bf*.$$");
}

# delete crossbranch
if($crossbranch) {
    $cmd="p4 branch -d $crossbranch";
system($cmd);
}

# delete main labels ????


sub buildclient {


    my($refclient,$newclient,$sourceproj,$targetproj,$nominus,$top)=@_;
    
    print "Reading reference client $refclient\n";

    #Check to see if it really exists
    # Check to see if it exists
    $cmd="p4 clients | grep $refclient";
    system($cmd);
    # Good exit means it exists
    if ($? ne 0) {
      print "Couldn't find it, aborting\n";
      exit(1);
      

    }

    print "Newclient is $newclient\n";
    
    $cmd="p4 -c $refclient client -o";
    
    open(CMD, "$cmd|") || die ;
    
    open(CMDOUT, ">/tmp/cbout") || die ;
    
    while(<CMD>) {


      # Enable site compression
      if($opt_site) {
	if(/nocompress/) {
	  s/nocompress/compress/g;
	  
	  print CMDOUT "$_\n";
	}
      }
	
	if(/^Client/) {
	    
	    print CMDOUT "Client: $newclient\n\n";
	    
	}
	
	if(/^Description/) {
	    
	    print CMDOUT "Description: client for $bname $df[0] $df[1] $df[2] $df[5] built by $user\n";
	    
	}
	
	if(/^Root/) {
	    
	  if($opt_block eq "tapeout") {
	    $root=$targetproj;
	  } else {
	    $root=$targetproj."/".$bname;
	  }
	    print CMDOUT "Root: $root\n";
	    
	}
	
	if(/^View/) {
	    
	    print CMDOUT "$_\n";
	}
	

	if(/^\t\-{0,1}\/\/depot/) {
	    
	    if(!$opt_from2) {
		$newdepot="depot/".$bname;
		
		# New LHS
		s/depot\/$chip\/$rev/$newdepot/g ; 
	    } else {
		$newdepot="depot/".$bname;
		s/$opt_from2\///g;
		s/depot\/$chip\/$rev/$newdepot/g ; 
	    }
	    # New RHS
	    
	    s/$refclient/$newclient/g;
	    
	    # Skip the minus
	    # to make sure that minus lines get branched
	    # even though we want them (the minus signs) in the client after
	    # branching is complete 
	    # to prevent overlapping Cadence library clients
	    # are you following me ?
	    
	    if($nominus eq "1") {
		if(/^\t\-/) {
		    s/\-//g;
		}
	    }

	    print CMDOUT $_;
	}
    }
    close(CMDOUT);
    
    print "Building $newclient from $refclient\n";
    
    $cmd="p4 -c $newclient client -i < /tmp/cbout > /dev/null";
    system($cmd);
}


sub getfileparents {

    if($opt_noint) {
	return;
    }

    # Minimise the number of system calls so use lots of files
    # and pass to p4 using -x option

    my($branch,$client,$flist,$flistl)=@_;

    my($cmd);

    print "\nGetting file list for $client\n";

    $cmd="p4 files //depot/".$branch."/...@".$client.">/tmp/bfiles.$$";
    system($cmd);


    # get branch and integrate files
    # since they (most likely) came from the mainline
    
    # TODO: TRAP if they didn't here or later 

    $cmd="grep  '\\- branch change'  /tmp/bfiles.$$ > /tmp/bfilesib.$$";
    system($cmd);
    $cmd="grep  '\\- integrate change' /tmp/bfiles.$$ >> /tmp/bfilesib.$$";
    system($cmd);

    $cmd="grep -v '\\- integrate change' /tmp/bfiles.$$ > /tmp/bfilesnib.$$";
    system($cmd);
    $cmd="grep -v '\\- branch change'  /tmp/bfilesnib.$$ > /tmp/bfileslocal.$$";
    system($cmd);

    #print "Generating integrated file list\n";
    &genlist("/tmp/bfilesib.$$",\%$flist,\%$flistl,"ib");
    #print "Generating local file list\n";
    &genlist("/tmp/bfileslocal.$$",\%$flist,\%$flistl,"local");
}



sub genlist {


    my($infile,$flist,$flistl,$faction)=@_;

    my($cmd,$record,$checkri,$catchver,@vinfo,$index,$count);
    my($version,$action,$dfv,@dinfo,$ldf,$getver,$pversion,@pdata,@copydata);
    
    
    # read the file list and produce a list to pass to filelog
    # but stash the version numbers in an array so we can pull 
    # out the right data from the filelog
    
    open(FLISTF, ">/tmp/bflist.$$") || die;
    open(INFILEF, "< $infile") || die ;
    
    
    while(<INFILEF>) {
	
	
	(@fdata)=split;

	$dfv=$fdata[0];

	(@dinfo)=split('#',$dfv);


	$df=$dinfo[0];
	$version=$dinfo[1];
	$action=$fdata[2];
	
	print FLISTF "$df\n";
	push(@vinfo,$version);
    }

    close(FLISTF);
    close(INFILEF);

    $cmd="p4 -x /tmp/bflist.$$ filelog >/tmp/bflog.$$";
    system($cmd);

    

    open(CMD, "</tmp/bflog.$$") || die;
    
    $record=0;
    # reverse integrate check
    $checkri=1;
    $catchver=0;
    $index=0;
    while(<CMD>) {
	chop;
	
	
	if( (/^\/\/depot/ || eof) && $record && $faction eq "local") {
	    $ldf=$depot."#".$getver;
	    #print "FLISTL $ldf\n";
	    $$flistl{$depot}=$ldf;
	    $record=0;
	    $catchver=0;
	    $index++;
	    
	}
	
	# if a branch back/from record could not be found treat as local edit
	if( /^\/\/depot/ && $record && $faction eq "ib") {
	    $ldf=$depot."#".$getver;
	    $$flistl{$depot}=$ldf;
	    $record=0;
	    $catchver=0;
	    $index++;
	}

	

	# New depot file record begins here
	if( /^\/\/depot/ && !$record) {
	    $depot=$_;
	    $catchver=1;
	    $checkri=1;
	}
	
	
	$getver=$vinfo[$index];
	

	# Got a new record, make sure we catch the right version
	# $record now signifies that we are ready to process the info
	
	if(/\.\.\. \#$getver/ && $catchver) {
	    $record=1;
	}

	# Look for branch into info if in local mode
	# if we find it, reset counter so we can find next valid record
	if(/\.\.\. \.\.\. [a-z]+ into \/\/depot\/BALI/ && $record && $faction eq "local") {
	    (@copydata)=split;
	    $count++;
	    (@pdata)=split('#',$copydata[4]);
	    # eliminate #1,#4 style syntax ( ie we want #4)
	    $pversion=$pdata[0]."#".$pdata[$#pdata];
	    #print "K $pdata[0]\n";
	    $$flist{$pdata[0]}=$pversion;	    
	    $checkri=0;
	    $record=0;
	    $catchver=0;
	    $index++;
	}

	#if we didn't find a branch into record, it was a local edit


	
	
	if(/\.\.\. \.\.\. [a-z]+ from/ && $record && $faction eq "ib" && !/gfx_$chip/) {
	    # may not have been branched from mainline
	    (@copydata)=split;
	    $count++;
	    #print "$count $pversion\n";
	    (@pdata)=split('#',$copydata[4]);
	    # eliminate #1,#4 style syntax ( ie we want #4)
	    $pversion=$pdata[0]."#".$pdata[$#pdata];
	    #print "Pushing $pversion\n";
	    $$flist{$pdata[0]}=$pversion;
	    $record=0;
	    $catchver=0;
	    $index++;
	}
    }
    close(OFILE);
    
}

# interrupt signal handler

sub handler {    
    my $sig = @_;
    $SIG{'INT'} = 'IGNORE';  # ignore SIGINT
    warn "Caught a SIG$sig--shutting down\n";
    exit();
}