#!/usr/bin/env cmperl #-*-mode:perl-*- #*************************************************************************** # (c) Copyright 2003 Reshape Inc., All Rights Reserved. # www.reshape.com #*************************************************************************** # # File : revert_changelist # Author : Jeremy Russell # Date : February 12, 2003 # # Description : Obliterates changes made to a server. This is not a mere # revert of a change list. This actually obliterates a set # of files. # #*************************************************************************** use strict; use Carp; use P4; use Getopt::Long; use Dumpvalue; my (%opts); GetOptions( \%opts, 'revert=i', # Change number. 'client=s', # Client under which to execute. 'debug=i', # Spits out debug messages. 'execute', # Does the actual obliterate. 'changelist=i', # Previously created changelist in which to open the reverts. 'submit', # Submit the revert change list as needed. 'user=s', # User under which to execute. 'port=s', # Port of the Perforce server on which to execute. ); sub main { my (%opts) = @_; $opts{debug} = 0 if not $opts{debug}; # Create a set up a Perforce client connection. my ($p4) = P4->new(); $p4->SetClient($opts{client}) if $opts{client}; $p4->SetPort($opts{port}) if $opts{port}; $p4->SetUser($opts{user}) if $opts{user}; $p4->ParseForms(); my ($count) = 1; while (($count < 5) && (not ($p4->Init()))){ $count++; } my ($change) = $p4->Describe('-s', $opts{revert}); Dumpvalue->new->dumpValue($change) if $opts{debug} > 4; # Iterate through each file and revert it in the specified style. if ($opts{execute}) { my ($number); if ($opts{changelist}) { $number = $opts{changelist}; } else { # Create change list. my ($form) = $p4->FetchChange(); delete $form->{Files}; $form->{Description} = "SW Internal\n\n\tAutomated revert of a bad checkin from change number $opts{revert}."; my ($msg) = $p4->SaveChange($form); $msg =~ /(\d+)/; $number = $1; } print "Change List Number: $number\n"; for (my $x = 0; $x < scalar @{$change->{depotFile}}; $x++) { # Handle integrates and edits alike. if (($change->{action}->[$x] eq 'integrate') || ($change->{action}->[$x] eq 'edit')) { my ($backrev) = $change->{rev}->[$x] - 1; my ($file) = "$change->{depotFile}->[$x]#$backrev"; my ($local) = $p4->Fstat($change->{depotFile}->[$x])->{clientFile}; # Sync to the previous revision and open it for edit into the desired change list. $p4->Sync('-f', $file); $p4->Edit('-c', $number, $change->{depotFile}->[$x]); # Sync and Resolve sequence for text files. For some reason this method does not work for binaries (.pdf). $p4->Sync('-f', $local); $p4->Resolve('-ay', $local); # Sync and Resolve sequence for binaries. For some reason this method does not work on text files. $p4->Sync('-f', $change->{depotFile}->[$x]); $p4->Resolve('-ay', $change->{depotFile}->[$x]); # We do not want to revert files that turn out ot be the same as the current revision and three revisions identical. $p4->Revert('-a', $local); print uc($change->{action}->[$x] ) . " (edit previous version): $file\n" if $opts{debug} > 1; # Handle deletes. } elsif ($change->{action}->[$x] eq 'delete') { my ($backrev) = $change->{rev}->[$x] - 1; my ($file) = "$change->{depotFile}->[$x]#$backrev"; $p4->Sync('-f', $file); $p4->Add('-c', $number, $change->{depotFile}->[$x]); print uc($change->{action}->[$x] ) . " (adds file): $file\n" if $opts{debug} > 1; # Handle branch and add actions alike. } elsif (($change->{action}->[$x] eq 'branch') || ($change->{action}->[$x] eq 'add')) { my ($file) = "$change->{depotFile}->[$x]#$change->{rev}->[$x]"; $p4->Delete('-c', $number, $change->{depotFile}->[$x]); print uc($change->{action}->[$x] ) . " (deletes file): $file\n" if $opts{debug} > 1; } } if ($opts{submit}) { my (@output) = $p4->Submit('-c', $number); print join ("\n", @output), "\n"; } } else { for (my $x = 0; $x < scalar @{$change->{depotFile}}; $x++) { my ($local) = $p4->Fstat($change->{depotFile}->[$x])->{clientFile}; # Handle integrates and edits alike. if (($change->{action}->[$x] eq 'integrate') || ($change->{action}->[$x] eq 'edit')) { my ($backrev) = $change->{rev}->[$x] - 1; my ($file) = "$change->{depotFile}->[$x]#$backrev"; print "[Preview] " . uc($change->{action}->[$x] ) . " (edit previous version): $file $local\n"; # Handle deletes. } elsif ($change->{action}->[$x] eq 'delete') { my ($backrev) = $change->{rev}->[$x] - 1; my ($file) = "$change->{depotFile}->[$x]#$backrev"; print "[Preview] " . uc($change->{action}->[$x] ) . " (adds file): $file $local\n"; # Handle branch and add actions alike. } elsif (($change->{action}->[$x] eq 'branch') || ($change->{action}->[$x] eq 'add')) { my ($file) = "$change->{depotFile}->[$x]#$change->{rev}->[$x]"; print "[Preview] " . uc($change->{action}->[$x] ) . " (deletes file): $file $local\n"; } } } $p4->Final(); return 1; } exit not main(%opts);