#!/l/local/bin/perl -wspi.bak # # reads a perforce style diff on stdin and outputs appropriate headers # so the diff can be applied with the patch program # # Gurusamy Sarathy <gsar@umich.edu> # BEGIN { $0 =~ s|.*/||; if ($h or $help) { print STDERR <<USAGE; Usage: $0 [-v] [-h] files -h print this help -v output progress messages Does inplace edit of diff files output by the perforce commands "p4 describe", "p4 diff", and "p4 diff2". The result is suitable for feeding to the "patch" program. If no files are specified, reads from stdin and writes to stdout. WARNING: It only handles context or unified diffs. Example: p4 describe -du 123 | $0 > change-123.patch USAGE exit(0); } unless (@ARGV) { @ARGV = '-'; undef $^I; } use vars qw($thisfile $time $file $fnum $v $h $help); $thisfile = ""; $time = localtime(time); } my ($cur, $match); $cur = m<^==== //depot/(.+?)\#\d+.* ====$> ... m<^(\@\@.+\@\@|\*+)$>; $match = $1; if ($ARGV ne $thisfile) { warn "processing patchfile [$ARGV]\n" unless $ARGV eq '-'; $thisfile = $ARGV; } # while we are within range if ($cur) { # set the file name after first line if ($cur == 1) { $file = $match; $fnum++; } # emit the diff header when we hit last line elsif ($cur =~ /E0$/) { my $f = $file; # special hack for perl so we can always use "patch -p1" $f =~ s<^.*?(perl.*?/)><$1>; # unified diff if ($match =~ /^\@/) { warn "emitting udiff header\n" if $v; $_ = "Index: $f\n--- $f.~1~\t$time\n+++ $f\t$time\n$_"; } # context diff elsif ($match =~ /^\*/) { warn "emitting cdiff header\n" if $v; $_ = "Index: $f\n*** $f.~1~\t$time\n--- $f\t$time\n$_"; } } # see if we hit another patch (i.e. previous patch was empty) elsif (m<^==== //depot/(.+?)\#\d+.* ====$>) { $file = $match = $1; } # suppress all other lines in the header else { $_ = ""; } warn "file [$file] line [$cur] file# [$fnum]\n" if $v; } $_ .= "End of Patch.\n" if eof;