# 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`;