Files
2025-09-29 00:52:08 +02:00

176 lines
3.9 KiB
Perl
Executable File

#! /usr/bin/perl -w
use strict;
if (@ARGV < 1 or $ARGV[0] eq 'default')
{
print "usage: p4rollback <changelist>\n";
exit;
}
foreach my $to (sort @ARGV)
{
my ($from, $age);
print "Looking up current changelist...\n";
if (`p4 changes -m 1` =~ /Change ([0-9]+) on/)
{
$age = $1 - $to + 2;
}
else
{
print "Unable to lookup current changelist\n";
exit;
}
print "Looking for previous changelist...\n";
open CHANGELIST, "p4 changes -m $age |";
while (<CHANGELIST>)
{
if (/Change ([0-9]+) on/ and $1 < $to)
{
$from = $1;
last;
}
}
close CHANGELIST;
if ($from)
{
print "\nUndoing changes between changelist $from and changelist $to...\n";
}
else
{
print "Unable to lookup previous changelist\n";
exit;
}
my (@edited, @deleted, @added, @branched, @integrated);
my $message = '';
print "\nReading changelist description...\n";
open CHANGELIST, "p4 describe -s $to |";
while (<CHANGELIST>)
{
last if (/Affected files/);
$message .= " $_";
}
while (<CHANGELIST>)
{
my $line = Strip($_);
if ($line =~ /^\.\.\. (.*)#[0-9]+ (edit|add|delete|branch|integrat)/)
{
print "$1 was $2ed\n";
if ($2 eq "edit")
{
push @edited, $1;
}
elsif ($2 eq "integrat")
{
push @integrated, $1;
}
elsif ($2 eq "add")
{
push @added, $1;
}
elsif ($2 eq "delete")
{
push @deleted, $1;
}
elsif ($2 eq "branch")
{
push @branched, $1;
}
}
}
close CHANGELIST;
open CHANGELIST, '>changelist.tmp';
print CHANGELIST "Change: new\nDescription:\n Reverting change $to\n\n Original change description:\n\n";
print CHANGELIST $message;
close CHANGELIST;
my $changelist = `p4 change -i < changelist.tmp`;
unlink 'changelist.tmp';
if ($changelist =~ /Change ([0-9]+) created./)
{
$changelist = $1;
print "\nCreated new changelist: $changelist\n";
}
else
{
print "Unable to create new changelist: $changelist\n";
exit;
}
if (@edited or @deleted or @integrated)
{
print "\nSyncing edited, integrated, and deleted files to old revision \@$from...\n";
system("p4", "sync", map { "$_\@$from" } (@edited, @deleted, @integrated));
print "\nAuto resolving edited, integrated, and deleted files...\n";
system("p4", "resolve", "-am", @edited, @deleted, @integrated);
if (@edited or @integrated)
{
print "\nOpening edited and integrated files for edit...\n";
system("p4", "edit", "-c", $changelist, @edited, @integrated);
}
if (@deleted)
{
print "\nOpening deleted files for add...\n";
system("p4", "add", "-c", $changelist, @deleted);
}
print "\nSyncing edited, integrated, and deleted files to new revision \@$to...\n";
system("p4", "sync", map { "$_\@$to" } (@edited, @deleted, @integrated));
print "\nResolving edited, integrated, and deleted files ignoring changes on server...\n";
system("p4", "resolve", "-ay", @edited, @deleted, @integrated);
}
if (@added or @branched)
{
print "\nDeleting added and branched files...\n";
system("p4", "delete", "-c", $changelist, @added, @branched);
}
system("p4", "changelist", "-d", $changelist);
}
sub Strip
{
my $in = shift;
$in =~ s/[^ -~]//go;
return $in;
}