Rev 1295 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
################################################################################ Codestriker: Copyright (c) 2001, 2002, 2003 David Sitsky.# All rights reserved.# sits@users.sourceforge.net## This program is free software; you can redistribute it and modify it under# the terms of the GPL.# Utility object for reading basic diffs.package Codestriker::FileParser::BasicDiffUtils;use strict;# Read from the file the next basic diff chunk, and return it.sub read_diff_text($$$$$$) {my ($type, $fh, $first_line, $filename, $revision, $repmatch) = @_;my $line = $first_line;# For this chunk, determine how many old lines and new lines are in# the chunk.my $old_linenumber = 0;my $new_linenumber = 0;my $old_length = 0;my $new_length = 0;if ($line =~ /^(\d+)a(\d+),(\d+)$/o ||$line =~ /^\-\-\-\-\-\[after (\d+) inserted(?:\/moved)? (\d+)\-(\d+)(?: \(was at [\d\-]+\))?\]\-\-\-\-\-\s*$/o) {# Added multiple lines of text.$old_linenumber = $1+1;$new_linenumber = $2;$new_length = $3 - $2 + 1;} elsif ($line =~ /^(\d+)a(\d+)$/o ||$line =~ /^\-\-\-\-\-\[after (\d+) inserted(?:\/moved)? (\d+)(?: \(was at [\d\-]+\))?\]\-\-\-\-\-\s*$/o) {# Added a single line of text.$old_linenumber = $1+1;$new_linenumber = $2;$new_length = 1;} elsif ($line =~ /^(\d+),(\d+)d(\d+)$/o ||$line =~ /^\-\-\-\-\-\[deleted(?:\/moved)? (\d+)\-(\d+) after (\d+)(?: \(now at [\d\-]+\))?\]\-\-\-\-\-\s*$/o) {# Multiple lines deleted.$old_linenumber = $1;$new_linenumber = $3+1;$old_length = $2 - $1 + 1;} elsif ($line =~ /^(\d+)d(\d+)$/o ||$line =~ /^\-\-\-\-\-\[deleted(?:\/moved)? (\d+) after (\d+)(?: \(now at [\d\-]+\))?\]\-\-\-\-\-\s*$/o) {# Single line deleted.$old_linenumber = $1;$new_linenumber = $2+1;$old_length = 1;} elsif ($line =~ /^(\d+),(\d+)c(\d+),(\d+)$/o ||$line =~ /^\-\-\-\-\-\[(\d+)\-(\d+) changed to (\d+)\-(\d+)\]\-\-\-\-\-\s*$/o) {# Multiple text lines changed.$old_linenumber = $1;$new_linenumber = $3;$old_length = $2 - $1 + 1;$new_length = $4 - $3 + 1;} elsif ($line =~ /^(\d+)c(\d+),(\d+)$/o ||$line =~ /^\-\-\-\-\-\[(\d+) changed to (\d+)\-(\d+)\]\-\-\-\-\-\s*$/o) {# Multiple source lines changed to single line.$old_linenumber = $1;$new_linenumber = $2;$old_length = 1;$new_length = $3 - $2 + 1;} elsif ($line =~ /^(\d+),(\d+)c(\d+)$/o ||$line =~ /^\-\-\-\-\-\[(\d+)\-(\d+) changed to (\d+)\]\-\-\-\-\-\s*$/o) {# Single source line changed to multiple lines.$old_linenumber = $1;$new_linenumber = $3;$old_length = $2 - $1 + 1;$new_length = 1;} elsif ($line =~ /^(\d+)c(\d+)$/o ||$line =~ /^\-\-\-\-\-\[(\d+) changed to (\d+)\]\-\-\-\-\-\s*$/o) {# Single line changed to another line.$old_linenumber = $1;$new_linenumber = $2;$old_length = 1;$new_length = 1;} else {# Some other file format.return undef;}# The chunk in unidiff format.my $chunk_text = "";# First read the old lines, if any.for (my $i = 0; $i < $old_length; $i++) {$line = <$fh>;if (defined $line && $line =~ /^\< (.*)$/) {$chunk_text .= "-${1}\n";} else {# Some other format.return undef;}}# If there is both old and new text, read the separator line.# Note bloody VSS for some versions will put the --- at the end of# the previous line rather than on a new line!if ($old_length > 0 && $new_length > 0) {my $previous_line = $line;my $pos = $fh->getpos;$line = <$fh>;return undef unless defined $line;if ($line !~ /^\-\-\-$/o && $chunk_text =~ /^(.*)\-\-\-$/os) {# Stupid VSS diff format, chop off the seperator characters# and move the file pointer back.$chunk_text = "$1\n";$fh->setpos($pos);} elsif ($line !~ /^\-\-\-$/o) {# Didn't match standard separator, some other format.return undef;}}# Now read the new lines, if any.for (my $i = 0; $i < $new_length; $i++) {$line = <$fh>;if (defined $line && $line =~ /^\> (.*)$/) {$chunk_text .= "+${1}\n";} else {# Some other format.return undef;}}# Now create the chunk object, and return it.my $chunk = {};$chunk->{filename} = $filename;$chunk->{revision} = $revision;$chunk->{old_linenumber} = $old_linenumber;$chunk->{new_linenumber} = $new_linenumber;$chunk->{binary} = 0;$chunk->{text} = $chunk_text;$chunk->{description} = "";$chunk->{repmatch} = $repmatch;return $chunk;}1;