зеркало из https://github.com/microsoft/git.git
Merge branch 'jn/web' into HEAD
* jn/web: gitweb: Fix and simplify "split patch" detection
This commit is contained in:
Коммит
6beb66968d
|
@ -2017,6 +2017,19 @@ sub parse_difftree_raw_line {
|
|||
return wantarray ? %res : \%res;
|
||||
}
|
||||
|
||||
# wrapper: return parsed line of git-diff-tree "raw" output
|
||||
# (the argument might be raw line, or parsed info)
|
||||
sub parsed_difftree_line {
|
||||
my $line_or_ref = shift;
|
||||
|
||||
if (ref($line_or_ref) eq "HASH") {
|
||||
# pre-parsed (or generated by hand)
|
||||
return $line_or_ref;
|
||||
} else {
|
||||
return parse_difftree_raw_line($line_or_ref);
|
||||
}
|
||||
}
|
||||
|
||||
# parse line of git-ls-tree output
|
||||
sub parse_ls_tree_line ($;%) {
|
||||
my $line = shift;
|
||||
|
@ -2060,6 +2073,7 @@ sub parse_from_to_diffinfo {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
# ordinary (not combined) diff
|
||||
$from->{'file'} = $diffinfo->{'from_file'} || $diffinfo->{'file'};
|
||||
if ($diffinfo->{'status'} ne "A") { # not new (added) file
|
||||
$from->{'href'} = href(action=>"blob", hash_base=>$hash_parent,
|
||||
|
@ -2783,6 +2797,7 @@ sub git_print_tree_entry {
|
|||
## ......................................................................
|
||||
## functions printing large fragments of HTML
|
||||
|
||||
# get pre-image filenames for merge (combined) diff
|
||||
sub fill_from_file_info {
|
||||
my ($diff, @parents) = @_;
|
||||
|
||||
|
@ -2799,28 +2814,25 @@ sub fill_from_file_info {
|
|||
return $diff;
|
||||
}
|
||||
|
||||
# parameters can be strings, or references to arrays of strings
|
||||
sub from_ids_eq {
|
||||
my ($a, $b) = @_;
|
||||
|
||||
if (ref($a) eq "ARRAY" && ref($b) eq "ARRAY" && @$a == @$b) {
|
||||
for (my $i = 0; $i < @$a; ++$i) {
|
||||
return 0 unless ($a->[$i] eq $b->[$i]);
|
||||
}
|
||||
return 1;
|
||||
} elsif (!ref($a) && !ref($b)) {
|
||||
return $a eq $b;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
# is current raw difftree line of file deletion
|
||||
sub is_deleted {
|
||||
my $diffinfo = shift;
|
||||
|
||||
return $diffinfo->{'to_id'} eq ('0' x 40);
|
||||
}
|
||||
|
||||
# does patch correspond to [previous] difftree raw line
|
||||
# $diffinfo - hashref of parsed raw diff format
|
||||
# $patchinfo - hashref of parsed patch diff format
|
||||
# (the same keys as in $diffinfo)
|
||||
sub is_patch_split {
|
||||
my ($diffinfo, $patchinfo) = @_;
|
||||
|
||||
return defined $diffinfo && defined $patchinfo
|
||||
&& ($diffinfo->{'to_file'} || $diffinfo->{'file'}) eq $patchinfo->{'to_file'};
|
||||
}
|
||||
|
||||
|
||||
sub git_difftree_body {
|
||||
my ($difftree, $hash, @parents) = @_;
|
||||
my ($parent) = $parents[0];
|
||||
|
@ -2857,13 +2869,7 @@ sub git_difftree_body {
|
|||
my $alternate = 1;
|
||||
my $patchno = 0;
|
||||
foreach my $line (@{$difftree}) {
|
||||
my $diff;
|
||||
if (ref($line) eq "HASH") {
|
||||
# pre-parsed (or generated by hand)
|
||||
$diff = $line;
|
||||
} else {
|
||||
$diff = parse_difftree_raw_line($line);
|
||||
}
|
||||
my $diff = parsed_difftree_line($line);
|
||||
|
||||
if ($alternate) {
|
||||
print "<tr class=\"dark\">\n";
|
||||
|
@ -3134,10 +3140,12 @@ sub git_patchset_body {
|
|||
my ($fd, $difftree, $hash, @hash_parents) = @_;
|
||||
my ($hash_parent) = $hash_parents[0];
|
||||
|
||||
my $is_combined = (@hash_parents > 1);
|
||||
my $patch_idx = 0;
|
||||
my $patch_number = 0;
|
||||
my $patch_line;
|
||||
my $diffinfo;
|
||||
my $to_name;
|
||||
my (%from, %to);
|
||||
|
||||
print "<div class=\"patchset\">\n";
|
||||
|
@ -3151,73 +3159,46 @@ sub git_patchset_body {
|
|||
|
||||
PATCH:
|
||||
while ($patch_line) {
|
||||
my @diff_header;
|
||||
my ($from_id, $to_id);
|
||||
|
||||
# git diff header
|
||||
#assert($patch_line =~ m/^diff /) if DEBUG;
|
||||
#assert($patch_line !~ m!$/$!) if DEBUG; # is chomp-ed
|
||||
$patch_number++;
|
||||
push @diff_header, $patch_line;
|
||||
|
||||
# extended diff header
|
||||
EXTENDED_HEADER:
|
||||
while ($patch_line = <$fd>) {
|
||||
chomp $patch_line;
|
||||
|
||||
last EXTENDED_HEADER if ($patch_line =~ m/^--- |^diff /);
|
||||
|
||||
if ($patch_line =~ m/^index ([0-9a-fA-F]{40})..([0-9a-fA-F]{40})/) {
|
||||
$from_id = $1;
|
||||
$to_id = $2;
|
||||
} elsif ($patch_line =~ m/^index ((?:[0-9a-fA-F]{40},)+[0-9a-fA-F]{40})..([0-9a-fA-F]{40})/) {
|
||||
$from_id = [ split(',', $1) ];
|
||||
$to_id = $2;
|
||||
}
|
||||
|
||||
push @diff_header, $patch_line;
|
||||
# parse "git diff" header line
|
||||
if ($patch_line =~ m/^diff --git (\"(?:[^\\\"]*(?:\\.[^\\\"]*)*)\"|[^ "]*) (.*)$/) {
|
||||
# $1 is from_name, which we do not use
|
||||
$to_name = unquote($2);
|
||||
$to_name =~ s!^b/!!;
|
||||
} elsif ($patch_line =~ m/^diff --(cc|combined) ("?.*"?)$/) {
|
||||
# $1 is 'cc' or 'combined', which we do not use
|
||||
$to_name = unquote($2);
|
||||
} else {
|
||||
$to_name = undef;
|
||||
}
|
||||
my $last_patch_line = $patch_line;
|
||||
|
||||
# check if current patch belong to current raw line
|
||||
# and parse raw git-diff line if needed
|
||||
if (defined $diffinfo &&
|
||||
defined $from_id && defined $to_id &&
|
||||
from_ids_eq($diffinfo->{'from_id'}, $from_id) &&
|
||||
$diffinfo->{'to_id'} eq $to_id) {
|
||||
if (is_patch_split($diffinfo, { 'to_file' => $to_name })) {
|
||||
# this is continuation of a split patch
|
||||
print "<div class=\"patch cont\">\n";
|
||||
} else {
|
||||
# advance raw git-diff output if needed
|
||||
$patch_idx++ if defined $diffinfo;
|
||||
|
||||
# read and prepare patch information
|
||||
$diffinfo = parsed_difftree_line($difftree->[$patch_idx]);
|
||||
|
||||
# compact combined diff output can have some patches skipped
|
||||
# find which patch (using pathname of result) we are at now
|
||||
my $to_name;
|
||||
if ($diff_header[0] =~ m!^diff --cc "?(.*)"?$!) {
|
||||
$to_name = $1;
|
||||
}
|
||||
|
||||
do {
|
||||
# read and prepare patch information
|
||||
if (ref($difftree->[$patch_idx]) eq "HASH") {
|
||||
# pre-parsed (or generated by hand)
|
||||
$diffinfo = $difftree->[$patch_idx];
|
||||
} else {
|
||||
$diffinfo = parse_difftree_raw_line($difftree->[$patch_idx]);
|
||||
}
|
||||
|
||||
# check if current raw line has no patch (it got simplified)
|
||||
if (defined $to_name && $to_name ne $diffinfo->{'to_file'}) {
|
||||
# find which patch (using pathname of result) we are at now;
|
||||
if ($is_combined) {
|
||||
while ($to_name ne $diffinfo->{'to_file'}) {
|
||||
print "<div class=\"patch\" id=\"patch". ($patch_idx+1) ."\">\n" .
|
||||
format_diff_cc_simplified($diffinfo, @hash_parents) .
|
||||
"</div>\n"; # class="patch"
|
||||
|
||||
$patch_idx++;
|
||||
$patch_number++;
|
||||
|
||||
last if $patch_idx > $#$difftree;
|
||||
$diffinfo = parsed_difftree_line($difftree->[$patch_idx]);
|
||||
}
|
||||
} until (!defined $to_name || $to_name eq $diffinfo->{'to_file'} ||
|
||||
$patch_idx > $#$difftree);
|
||||
}
|
||||
|
||||
# modifies %from, %to hashes
|
||||
parse_from_to_diffinfo($diffinfo, \%from, \%to, @hash_parents);
|
||||
|
@ -3227,30 +3208,36 @@ sub git_patchset_body {
|
|||
print "<div class=\"patch\" id=\"patch". ($patch_idx+1) ."\">\n";
|
||||
}
|
||||
|
||||
# git diff header
|
||||
#assert($patch_line =~ m/^diff /) if DEBUG;
|
||||
#assert($patch_line !~ m!$/$!) if DEBUG; # is chomp-ed
|
||||
$patch_number++;
|
||||
# print "git diff" header
|
||||
$patch_line = shift @diff_header;
|
||||
print format_git_diff_header_line($patch_line, $diffinfo,
|
||||
\%from, \%to);
|
||||
|
||||
# print extended diff header
|
||||
print "<div class=\"diff extended_header\">\n" if (@diff_header > 0);
|
||||
print "<div class=\"diff extended_header\">\n";
|
||||
EXTENDED_HEADER:
|
||||
foreach $patch_line (@diff_header) {
|
||||
while ($patch_line = <$fd>) {
|
||||
chomp $patch_line;
|
||||
|
||||
last EXTENDED_HEADER if ($patch_line =~ m/^--- |^diff /);
|
||||
|
||||
print format_extended_diff_header_line($patch_line, $diffinfo,
|
||||
\%from, \%to);
|
||||
}
|
||||
print "</div>\n" if (@diff_header > 0); # class="diff extended_header"
|
||||
print "</div>\n"; # class="diff extended_header"
|
||||
|
||||
# from-file/to-file diff header
|
||||
$patch_line = $last_patch_line;
|
||||
if (! $patch_line) {
|
||||
print "</div>\n"; # class="patch"
|
||||
last PATCH;
|
||||
}
|
||||
next PATCH if ($patch_line =~ m/^diff /);
|
||||
#assert($patch_line =~ m/^---/) if DEBUG;
|
||||
#assert($patch_line eq $last_patch_line) if DEBUG;
|
||||
|
||||
my $last_patch_line = $patch_line;
|
||||
$patch_line = <$fd>;
|
||||
chomp $patch_line;
|
||||
#assert($patch_line =~ m/^\+\+\+/) if DEBUG;
|
||||
|
@ -3275,16 +3262,11 @@ sub git_patchset_body {
|
|||
|
||||
# for compact combined (--cc) format, with chunk and patch simpliciaction
|
||||
# patchset might be empty, but there might be unprocessed raw lines
|
||||
for ($patch_idx++ if $patch_number > 0;
|
||||
for (++$patch_idx if $patch_number > 0;
|
||||
$patch_idx < @$difftree;
|
||||
$patch_idx++) {
|
||||
++$patch_idx) {
|
||||
# read and prepare patch information
|
||||
if (ref($difftree->[$patch_idx]) eq "HASH") {
|
||||
# pre-parsed (or generated by hand)
|
||||
$diffinfo = $difftree->[$patch_idx];
|
||||
} else {
|
||||
$diffinfo = parse_difftree_raw_line($difftree->[$patch_idx]);
|
||||
}
|
||||
$diffinfo = parsed_difftree_line($difftree->[$patch_idx]);
|
||||
|
||||
# generate anchor for "patch" links in difftree / whatchanged part
|
||||
print "<div class=\"patch\" id=\"patch". ($patch_idx+1) ."\">\n" .
|
||||
|
|
Загрузка…
Ссылка в новой задаче