Re: Git help for kernel archeology, suppress diffs caused by CVS keyword expansion
- From
Johannes Schindelin <johannes.schindelin@gmx.de>
- Date
- Jul 24, 2007, 01:16 UTC
- Message-ID
- <Pine.LNX.4.64.0707240214500.14781@racer.site>
- In-Reply-To
- <9e4733910707231743w759afabfvd43045ad2e2eba5a@mail.gmail.com>
Hi,
On Mon, 23 Jul 2007, Jon Smirl wrote:
> Thanks for working on this. I'd like to see it added to git toolkit.
I plan to submit it to patchutils instead, since this is not really dependent on git.
Show 5 quoted lines
> This diff is way easier to read now. I can see that it has SPI support > backported from some future version. > > But... it still has some problems. For the phytec patch it's not getting > the $Log changes in the qlogic files right.
You are correct. This slipped by my eyes.
> I'm checking the output diff line by line for problems. It's down to > 11,528 lines from 88,787. That's a lot of junk removed, I'll have to > make sure it isn't removing too much.
May I ask you to test this version?
Thanks, Dscho
-- snipsnap -- #!/usr/bin/perl
# This is a simple state machine. # # There is the state of the current file; its header is stored # in $current_file to avoid outputting it when all hunks were # culled. It is only printed before the first hunk, and then # set to "" to avoid outputting it twice. # # There are the states of the current hunk, stored in # * $current_hunk (possibly modified hunk) # * $start_minus, $start_plus (from the original) # * $plus, $minus, $space (the current count of the respective lines) # a hunk is only printed (in flush_hunk) if any '+' or '-' lines # are left after filtering. # # For $Log..$, there is the state $skip_logs, which is set to 1 # after seeing such a line, and set to 0 when the first line # was seen which does not begin with '+'. # # A particularly nasty special case is when a single "*" was # misattributed by the diff to be _inserted before_ a $Log, instead # of _appended after_ a $Log. # This is the purpose of the $before_log and $after_log variables: # if not empty, the state machine expects the next line to begin # with '+' or '-', respectively, and followed by a $Log. If this # expectation is not met, the variable is output. # # The variable $plus_minus_adjust contains the number of lines which # were skipped from the "+" side, so that the correct offset is shown.
# This function gets a hunk header. # # It initializes the state variables described above
sub init_hunk {
my $line = $_[0];
$current_hunk = "";
($start_minus, $dummy, $start_plus, $dummy) =
($line =~ /^\@\@ -(\d+)(,\d+|) \+(\d+)(,\d+|) \@\@/);
$plus = $minus = $space = 0;
$skip_logs = 0;
$before_log = '';
$after_log = ''; # we prefer /dev/null as original file name when a file is new
if ($start_minus eq 0) {
$current_file =~ s/\n--- .*\n/\n--- \/dev\/null\n/;
} elsif ($start_plus eq 0) {
$current_file =~ s/\n\+\+\+ .*\n/\n+++ \/dev\/null\n/;
}
}# This function is called whenever there is possibly a hunk to print. # Nothing is printed if no '+' or '-' lines are left. # Otherwise, if the file header was not yet shown, it does so now.
sub flush_hunk {
if (($plus > 0 || $minus > 0) && $current_hunk ne '') {
if ($current_file ne "") {
print $current_file;
$current_file = "";
}
$minus += $space;
$plus += $space;
print "\@\@ -$start_minus,$minus "
. "+" . ($start_plus - $start_plus_adjust)
. ",$plus \@\@\n";
print $current_hunk;
$current_hunk = '';
}
}# This adds a line to the current hunk and updates $space, $plus or $minus
sub add_line {
my $line = $_[0];
$current_hunk .= $line;
if ($line =~ /^ /) {
$space++;
} elsif ($line =~ /^\+/) {
$plus++;
} elsif ($line =~ /^-/) {
$minus++;
} elsif ($line =~ /^\\/) {
# do nothing
} else {
die "Unexpected line: $line";
}
}# This function splits the current hunk into the part before the current # line, and the part after the current line.
sub skip_line {
my $line = $_[0]; if ($start_minus == 0) {
# This patch adds a new file, just ignore that line
return;
} elsif ($start_plus == 0) {
# This patch removes a file, so include the line nevertheless
add_line $_;
return;
} flush_hunk;
if ($line =~ /^-/) {
$minus++;
} elsif ($line =~ /^\+/) {
$plus++;
$start_plus_adjust++;
}
init_hunk "@@ -" . ($start_minus + $minus + $space)
. " +" . ($start_plus + $plus + $space)
. " @@\n";
}$simple_keyword = "Id|Revision|Author|Date|Source|Header";
# This is the main loop
sub check_file {
$_ = $_[0];
$current_file = $_;
$start_plus_adjust = 0;
while (<>) {
if (/^\@\@/) {
last;
}
$current_file .= $_;
}init_hunk $_;
# check hunks
while (<>) {
if ($before_log) {
if (!/\+.*\$Log.*\$/) {
add_line $before_log;
} else {
skip_line $before_log;
}
$before_log = '';
} if ($after_log) {
if (!/-.*\$Log.*\$/) {
add_line $after_log;
} else {
skip_line $after_log;
}
$after_log = '';
} if ($skip_logs) {
if (/^\+/) {
skip_line $_;
$skip_logs = 1;
} else {
$skip_logs = 0;
if (/^ *\*$/) {
$after_log = $_;
}
}
} elsif (/^\+.*\$($simple_keyword).*\$/) {
skip_line $_;
} elsif (/^\@\@.*/) {
flush_hunk;
init_hunk $_;
} elsif (/^diff/) {
flush_hunk;
return;
} elsif (/^-.*\$($simple_keyword).*\$/) {
# fake new hunk
skip_line $_;
} elsif (/^\+ *\*$/) {
$before_log = $_;
} elsif (/^([- \+]).*\$Log.*\$/) {
skip_line $_;
$skip_logs = 1;
} else {
add_line $_;
}
}
}# This loop just shows everything before the first diff, and then hands # over to check_file whenever it sees a line beginning with "diff".
while (<>) {
if (/^diff/) {
do {
check_file $_;
} while(/^diff/);
} else {
printf $_;
}
}
flush_hunk;