# downmove.pl - sample script for downgrading inter-codeline moves
#
# This can be run against any client at any time, but an ideal time would be
# right before submit. Note that if you run this in a change-submit trigger
# and it downgrades the files, submit will fail with a scary error because the
# files got changed under it, but if the submit is retried it'll be fine.
#
# Args: %user% %client% %clienthost%
#
# p4 executable with server port, super user credentials:
$P4 = "p4 -p 1981";
$sUser = "super";
$sTicket = "532B0A90E2016A2CFEAD4E94BD3AFC15"; # or password
# This function gets the "unit" (component, codeline, etc) that
# a given depot path is part of. It is expected that all of the
# files within a given unit will stay together during merges.
sub get_unit
{
# This version returns the leading "//depot/directory/" as the unit.
# Substitute your own definition here.
$_[0] =~ /(\/\/[^\/]+\/[^\/]+\/).*/;
return $1;
}
# Script starts now.
# Login as issuing user so we can mess with their client.
$user = $ARGV[0];
$client = $ARGV[1];
$host = $ARGV[2];
$_ = `$P4 -u $sUser -P $sTicket -s login $user`;
if( !/^info:/ )
{
print "Login $_\n";
exit 1;
}
# Ticket acquired. Henceforth we run as that user.
$p4u = "$P4 -u $user -c $client -H $host";
# Get opened files.
@movedDepot = ();
@movedClient = ();
$unit = '';
$safe = 1;
@files = `$p4u -Ztag -F %action%\@%depotFile%\@%clientFile% opened`;
foreach( @files )
{
chomp;
next if( !/^move/ );
if( /^move\/add\@(.+)\@(.+)/ )
{
push @movedDepot, $1;
push @movedClient, $2;
}
s/^move\/[a-z]+://;
$_ = &get_unit( $_ );
if ( $unit eq '' ) { $unit = $_; }
elsif( $unit ne $_ ) { $safe = 0; break; }
}
if( $safe )
{
`$p4u logout`;
exit 0;
}
# If we've gotten this far we know that not all of our moved files
# are in the same unit, so we couldn't do a quick bail. Now we look
# at the individual moves to see which need downgrading.
@resolves = ();
while( @movedDepot )
{
$unit = &get_unit( pop @movedDepot );
$file = pop @movedClient;
# Resolved gives us the depot "fromFile" for a client "toFile".
@resolves = `$p4u -F %how%\@%fromFile% resolved $file`;
foreach( @resolves )
{
chomp;
next if( !/^moved from\@(.+)/ );
if( &get_unit( $1 ) ne $unit ) { `$p4u -s add -d $file`; }
}
}
`$p4u logout`;