#!/usr/local/bin/perl

# clone project databases


use Getopt::Long;

unless($result=GetOptions("h",
			  "source=s", "target=s", "force", "from=s", "nointeg")){
    die "Illegal Input Options, -h for help\n";
}

($prog = $0) =~ s,.*/,,;

$HELP="Usage: $prog -source <source_rev> -target <target_rev>";

unless($opt_source && $opt_target) {
    print "$HELP\n";
    exit(1);
}


if($opt_h) {
    print "$HELP\n";
    exit(0);
}

umask(002);

$project=$ENV{"PROJECT"};

if (!defined($project)) {
	print "$prog: must set env variable PROJECT first\n";
	exit(1);
}

$cmd = "p4 client -o cdsp4_integ | grep '^Root' > /dev/null 2>&1";
system($cmd);

if ($? != 0) {
	print "$prog: dummy integration client cdsp4_integ does not exist!\nContact your cdsp4 administrator; cannot proceed with branch building.\n";
	exit(1);
}

(@pdata)=split('/',$project);

$proj=$pdata[3];

if (!defined($proj)) {
	print "$prog: env variable PROJECT is not correctly set\n";
	exit(1);
}

$tempfile="/tmp/byob.$$";

print "Building physical tree for $proj\n";

print "Log file is $tempfile\n";

# Check for validity of source and target

# expand source and target to follow physical syntax

$sbranch=$opt_source;
$tbranch=$opt_target;

print "Source branch is $sbranch, target is $tbranch\n";

# Check to see if source branch exists

$cmd="p4 branches | grep $sbranch > /dev/null";
system($cmd);

if($? ne 0) {
    print "Error: couldn't locate the source branch\n";
    exit(1);
}
# Don't overwrite a target branch

$cmd="p4 branches | grep $tbranch > /dev/null";
system($cmd);

if($? eq 0 && !$opt_force) {
    print "Error: target branch already exists\n";
    exit(1);
}

# Define the location of the file relative to the tree root (site dependent variable)

$blocation="";

# need to find the root of the branch client to begin

$bclient=$sbranch."_client";
$cmd="p4 client -o $bclient | grep '^Root'";

open(CMD,"$cmd|") || die "error $cmd\n";

while(<CMD>) {
     chomp;
    ($ig,$broot)=split;
}

print "Source branch root is $broot\n";

if ($blocation eq "") {
	$oldbdir = $broot;
} else {
	$oldbdir="$broot/$blocation";
}

($newbdir = $oldbdir) =~ s/$sbranch/$tbranch/;

# Check for existing and writable new branch directory

if (! -d "$newbdir" || ! -w "$newbdir") {
	die "New branch root directory $newbdir does not exist or is not writable\n";
}

# Check for opened files in the source branch
print "Getting check out status for $opt_source\n";

$cmd="(p4 opened -a //depot/$sbranch/... | grep '#' ) > /dev/null 2>&1";
system($cmd);

if($? eq 0) {
  if (!$opt_force) {
    system("cdscheckouts -bname $sbranch");
    print "\n\nError: *** Aborting byob build due to checkouts in $sbranch\n\n";
    print "Suggestion: *** IF you know what you are doing, you can use the -force flag\n";
    print "\t\tto force the creation of your target branch, but this is potentially\n";
    print "\t\tvery dangerous. You have been warned.\n";
    exit;
  } else {
    print "Detected checkouts in source branch...\n";
    print "*** Force option activated ***\n";
    print "Please confirm this operation (accept_knowingly/no):";
    $line = <STDIN>;
    chomp $line;
    if($line ne "accept_knowingly") {
	print "byob aborted by user request\n";
	exit;
    } 
  }
}

# Feeling emboldened, let's do the integrate

print "Integrating the data...\n";

if($opt_nointeg) {
    print "No integrations will be performed\n";
} else {

if($opt_from) {
    print "Changenumber source is $opt_from\n";
    $cmd="p4 -c cdsp4_integ integ -v //depot/$sbranch/...\@$opt_from //depot/$tbranch/... >> $tempfile";
} else {
    $cmd="p4 -c cdsp4_integ integ -v //depot/$sbranch/... //depot/$tbranch/... >> $tempfile";
}


print "$cmd\n";
system($cmd);

print "Submitting the change, please wait, this can take some time due to sheer volume of data...\n";

# First check if there are any pending file to avoid null submits
$cmd="p4 -c cdsp4_integ change -o | grep \\^Files > /dev/null";
system($cmd);

if($? eq 0) {

$cmd="p4 -c cdsp4_integ change -o | sed 's/<enter description here>/Branch submit by byob ($tbranch $opt_from)/g' | p4 -c cdsp4_integ submit -i >> $tempfile";
system($cmd); 
} else {
    print "All revisions appear to be up to date...\n";
}
}

# Now let's do the Cadence stuff

# Need to clone the clients using the clientmapper script
print "Syncing Cadence databases, please wait...\n";

$cmd="projclientmapper $proj $opt_source $proj $opt_target >> $tempfile";
print "$cmd\n";
system($cmd);

# Now, build the branch cds.lib and cds.p4clients file
# and the .branchrc file

$oldcdslib="$oldbdir/cds.lib";
$newcdslib="$newbdir/cds.lib";

$cmd="sed 's/$sbranch/$tbranch/g' < $oldcdslib > $newcdslib";
system($cmd);

#
# Make sure each INCLUDEd file in cds.lib with a pointer into the
# branch actually exists here.  Copy it from the source branch if not.
#

if (!open(C, "<$newcdslib")) {
    print "$prog: couldn't open the new cds.lib we just built!\n";
}
else {
    while(<C>) {
	split($_);
	if ($_[0] eq "INCLUDE" && $_[1] =~ /$newbdir/) {
	    if (! -f $_[1]) {
		($src_file = $_[1]) =~ s/$newbdir/$oldbdir/;
		if (! -f $src_file) {
		    print "$prog: WARNING: need to copy INCLUDEd file $src_file into the new branch directory, but source file does not exist.  Is something wrong with the cds.lib?\n";
		}
		else {
		    print "$prog: INFO: copying cds.lib's INCLUDE file $_[1] from the source branch directory\n";
		    $cmd = "cp $src_file $newbdir";
		    system($cmd);
		}
	    }
	}
    }
    close(C);
}

# cds.p4client

$oldcdsp4="$oldbdir/cds.p4client";
$newcdsp4="$newbdir/cds.p4client";

$cmd="sed 's/$sbranch/$tbranch/g' < $oldcdsp4 > $newcdsp4";
system($cmd);

# .branchrc.il

$branchrc="$newbdir/.branchrc.il";
open(BF,">$branchrc") || die "Could not write $branchrc\n";

print BF "setShellEnvVar(\"PROJECT_BRANCH=$tbranch\")\n";
close(BF);



# build the branch spec to drive addnewbranch
$desc="Created by byob";
$dspec_source="//depot/$sbranch/...";
$dspec_target="//depot/$tbranch/...";
&build_branch($tbranch,$desc,$dspec_source, $dspec_target);
# build the branch client too
# Spec it out
$cname=$tbranch."_client";
$dspec="//depot/$tbranch/... //$cname/...\n\t-//depot/$tbranch/cadence/... //$cname/cadence/...\n";

$root=$broot;
$root=~s/$sbranch/$tbranch/g;
$desc="$tbranch client";
# Call it
&build_client($cname,$root,$desc,$dspec);
# sync it
print "Syncing the branch client...\n";
$cmd="p4 -c $cname sync >> $tempfile 2>&1";
#print "$cmd\n";
system($cmd);

print "byob is done...\n";

exit(0);

# Begin subroutine declarations

sub build_branch() {

    my $bname=shift;
    my $desc=shift;
    my $dspec_s=shift;
    my $dspec_t=shift;
    
    print "Building branch $bname\n";
    my $tmpfile="/tmp/byob.bf.$$";

    open(CF, ">$tmpfile") || die "Couldn't write temp branch file\n";

    print CF "Branch: $bname\n";
    print CF "Description:\n\t$desc\n";
    # accept default options
    print CF "View:\n\t$dspec_s $dspec_t\n";
    close(CF);
    system("p4 branch -i < $tmpfile");
    system("rm $tmpfile");
    
}


sub build_client() {

    my $cname=shift;
    my $root=shift;
    my $desc=shift;
    my $dspec=shift;

    print "Building client $cname\n";
    my $tmpfile="/tmp/byob.cf.$$";

    open(CF, ">$tmpfile") || die "Couldn't write temp client file\n";

    print CF "Client: $cname\n";
    print CF "Description:\n\t$desc\n";
    print CF "Root: $root\n";
    # accept default options
    print CF "View:\n\t$dspec\n";
    close(CF);
    system("p4 client -i < $tmpfile");
    system("rm $tmpfile");
}