2024-02-03 00:26:55 +01:00
|
|
|
#!/usr/bin/env perl
|
|
|
|
|
|
|
|
use warnings;
|
|
|
|
|
|
|
|
sub quote {
|
|
|
|
my $token = shift;
|
|
|
|
$token =~ s/'/''/g;
|
|
|
|
return "'$token'";
|
|
|
|
}
|
|
|
|
sub fail {
|
|
|
|
my $reason = shift;
|
|
|
|
print "set-register e fail " . quote("diff-parse.pl: $reason");
|
|
|
|
exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
my $begin;
|
|
|
|
my $end;
|
|
|
|
|
|
|
|
while (defined $ARGV[0]) {
|
|
|
|
if ($ARGV[0] eq "--") {
|
|
|
|
shift;
|
|
|
|
last;
|
|
|
|
}
|
|
|
|
if ($ARGV[0] =~ m{^(BEGIN|END)$}) {
|
|
|
|
if (not defined $ARGV[1]) {
|
|
|
|
fail "missing argument to $ARGV[0]";
|
|
|
|
}
|
|
|
|
if ($ARGV[0] eq "BEGIN") {
|
|
|
|
$begin = $ARGV[1];
|
|
|
|
} else {
|
|
|
|
$end = $ARGV[1];
|
|
|
|
}
|
|
|
|
shift, shift;
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
fail "unknown argument: $ARGV[0]";
|
|
|
|
}
|
|
|
|
|
|
|
|
# Inputs
|
|
|
|
our $directory = $ENV{PWD};
|
|
|
|
our $strip;
|
2024-02-03 00:26:56 +01:00
|
|
|
our $in_file;
|
|
|
|
our $in_file_line;
|
2024-02-03 00:26:55 +01:00
|
|
|
our $version = "+";
|
|
|
|
|
|
|
|
eval $begin if defined $begin;
|
|
|
|
|
2024-02-03 00:26:56 +01:00
|
|
|
$in_file = "$directory/$in_file" if defined $in_file;
|
|
|
|
|
2024-02-03 00:26:55 +01:00
|
|
|
# Outputs
|
2024-02-03 00:26:56 +01:00
|
|
|
our $diff_line = 0;
|
|
|
|
our $commit;
|
2024-02-03 00:26:55 +01:00
|
|
|
our $file;
|
|
|
|
our $file_line;
|
|
|
|
our $diff_line_text;
|
|
|
|
|
|
|
|
my $other_version;
|
|
|
|
if ($version eq "+") {
|
|
|
|
$other_version = "-";
|
|
|
|
} else {
|
|
|
|
$other_version = "+";
|
|
|
|
}
|
|
|
|
my $is_recursive_diff = 0;
|
|
|
|
my $state = "header";
|
|
|
|
my $fallback_file;
|
|
|
|
my $other_file;
|
|
|
|
my $other_file_line;
|
|
|
|
|
|
|
|
sub strip {
|
|
|
|
my $is_recursive_diff = shift;
|
|
|
|
my $f = shift;
|
|
|
|
|
|
|
|
my $effective_strip;
|
|
|
|
if (defined $strip) {
|
|
|
|
$effective_strip = $strip;
|
|
|
|
} else {
|
|
|
|
# A "diff -r" or "git diff" adds "diff" lines to
|
|
|
|
# the output. If no such line is present, we have
|
|
|
|
# a plain diff between files (not directories), so
|
|
|
|
# there should be no need to strip the directory.
|
|
|
|
$effective_strip = $is_recursive_diff ? 1 : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($f !~ m{^/}) {
|
|
|
|
$f =~ s,^([^/]+/+){$effective_strip},, or fail "directory prefix underflow";
|
|
|
|
$f = "$directory/$f";
|
|
|
|
}
|
|
|
|
return $f;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (<STDIN>) {
|
2024-02-03 00:26:56 +01:00
|
|
|
$diff_line++;
|
2024-02-03 00:26:55 +01:00
|
|
|
s/^(> )*//g;
|
|
|
|
$diff_line_text = $_;
|
2024-02-03 00:26:56 +01:00
|
|
|
if (m{^commit (\w+)}) {
|
|
|
|
$commit = $1;
|
|
|
|
next;
|
|
|
|
}
|
2024-02-03 00:26:55 +01:00
|
|
|
if (m{^diff\b}) {
|
|
|
|
$state = "header";
|
|
|
|
$is_recursive_diff = 1;
|
|
|
|
if (m{^diff -\S* (\S+) (\S+)$}) {
|
|
|
|
$fallback_file = strip $is_recursive_diff, ($version eq "+" ? $2 : $1);
|
|
|
|
}
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
if ($state eq "header") {
|
|
|
|
if (m{^[$version]{3} ([^\t\n]+)}) {
|
|
|
|
$file = strip $is_recursive_diff, $1;
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
if (m{^[$other_version]{3} ([^\t\n]+)}) {
|
|
|
|
$other_file = strip $is_recursive_diff, $1;
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (m{^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@}) {
|
|
|
|
$state = "contents";
|
|
|
|
$file_line = ($version eq "+" ? $2 : $1) - 1;
|
|
|
|
$other_file_line = ($version eq "+" ? $1 : $2) - 1;
|
|
|
|
} else {
|
|
|
|
my $iscontext = m{^[ ]};
|
|
|
|
if (m{^[ $version]}) {
|
|
|
|
$file_line++ if defined $file_line;
|
|
|
|
}
|
|
|
|
if (m{^[ $other_version]}) {
|
|
|
|
$other_file_line++ if defined $other_file_line;
|
|
|
|
}
|
|
|
|
}
|
2024-02-03 00:26:56 +01:00
|
|
|
if (defined $in_file and defined $file and $file eq $in_file) {
|
|
|
|
if (defined $in_file_line and defined $file_line and $file_line >= $in_file_line) {
|
|
|
|
last;
|
|
|
|
}
|
|
|
|
}
|
2024-02-03 00:26:55 +01:00
|
|
|
}
|
|
|
|
if (not defined $file) {
|
|
|
|
$file = ($fallback_file or $other_file);
|
|
|
|
}
|
|
|
|
if (not defined $file) {
|
|
|
|
fail "missing diff header";
|
|
|
|
}
|
|
|
|
|
|
|
|
eval $end if defined $end;
|