Subversion Repositories DevTools

Rev

Rev 1295 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1293 dpurdie 1
###############################################################################
2
# Codestriker: Copyright (c) 2001, 2002, 2003 David Sitsky.
3
# All rights reserved.
4
# sits@users.sourceforge.net
5
#
6
# This program is free software; you can redistribute it and modify it under
7
# the terms of the GPL.
8
 
9
# Utility object for reading basic diffs.
10
 
11
package Codestriker::FileParser::BasicDiffUtils;
12
 
13
use strict;
14
 
15
# Read from the file the next basic diff chunk, and return it.
16
sub read_diff_text($$$$$$) {
17
    my ($type, $fh, $first_line, $filename, $revision, $repmatch) = @_;
18
 
19
    my $line = $first_line;
20
 
21
    # For this chunk, determine how many old lines and new lines are in
22
    # the chunk.
23
    my $old_linenumber = 0;
24
    my $new_linenumber = 0;
25
    my $old_length = 0;
26
    my $new_length = 0;
27
 
28
    if ($line =~ /^(\d+)a(\d+),(\d+)$/o ||
29
	$line =~ /^\-\-\-\-\-\[after (\d+) inserted(?:\/moved)? (\d+)\-(\d+)(?: \(was at [\d\-]+\))?\]\-\-\-\-\-\s*$/o) {
30
	# Added multiple lines of text.
31
	$old_linenumber = $1+1;
32
	$new_linenumber = $2;
33
	$new_length = $3 - $2 + 1;
34
    } elsif ($line =~ /^(\d+)a(\d+)$/o ||
35
	     $line =~ /^\-\-\-\-\-\[after (\d+) inserted(?:\/moved)? (\d+)(?: \(was at [\d\-]+\))?\]\-\-\-\-\-\s*$/o) {
36
	# Added a single line of text.
37
	$old_linenumber = $1+1;
38
	$new_linenumber = $2;
39
	$new_length = 1;
40
    } elsif ($line =~ /^(\d+),(\d+)d(\d+)$/o ||
41
	     $line =~ /^\-\-\-\-\-\[deleted(?:\/moved)? (\d+)\-(\d+) after (\d+)(?: \(now at [\d\-]+\))?\]\-\-\-\-\-\s*$/o) {
42
	# Multiple lines deleted.
43
	$old_linenumber = $1;
44
	$new_linenumber = $3+1;
45
	$old_length = $2 - $1 + 1;
46
    } elsif ($line =~ /^(\d+)d(\d+)$/o ||
47
	     $line =~ /^\-\-\-\-\-\[deleted(?:\/moved)? (\d+) after (\d+)(?: \(now at [\d\-]+\))?\]\-\-\-\-\-\s*$/o) {
48
	# Single line deleted.
49
	$old_linenumber = $1;
50
	$new_linenumber = $2+1;
51
	$old_length = 1;
52
    } elsif ($line =~ /^(\d+),(\d+)c(\d+),(\d+)$/o ||
53
	     $line =~ /^\-\-\-\-\-\[(\d+)\-(\d+) changed to (\d+)\-(\d+)\]\-\-\-\-\-\s*$/o) {
54
	# Multiple text lines changed.
55
	$old_linenumber = $1;
56
	$new_linenumber = $3;
57
	$old_length = $2 - $1 + 1;
58
	$new_length = $4 - $3 + 1;
59
    } elsif ($line =~ /^(\d+)c(\d+),(\d+)$/o ||
60
	     $line =~ /^\-\-\-\-\-\[(\d+) changed to (\d+)\-(\d+)\]\-\-\-\-\-\s*$/o) {
61
	# Multiple source lines changed to single line.
62
	$old_linenumber = $1;
63
	$new_linenumber = $2;
64
	$old_length = 1;
65
	$new_length = $3 - $2 + 1;
66
    } elsif ($line =~ /^(\d+),(\d+)c(\d+)$/o ||
67
	     $line =~ /^\-\-\-\-\-\[(\d+)\-(\d+) changed to (\d+)\]\-\-\-\-\-\s*$/o) {
68
	# Single source line changed to multiple lines.
69
	$old_linenumber = $1;
70
	$new_linenumber = $3;
71
	$old_length = $2 - $1 + 1;
72
	$new_length = 1;
73
    } elsif ($line =~ /^(\d+)c(\d+)$/o ||
74
	     $line =~ /^\-\-\-\-\-\[(\d+) changed to (\d+)\]\-\-\-\-\-\s*$/o) {
75
	# Single line changed to another line.
76
	$old_linenumber = $1;
77
	$new_linenumber = $2;
78
	$old_length = 1;
79
	$new_length = 1;
80
    } else {
81
	# Some other file format.
82
	return undef;
83
    }
84
 
85
    # The chunk in unidiff format.
86
    my $chunk_text = "";
87
 
88
    # First read the old lines, if any.
89
    for (my $i = 0; $i < $old_length; $i++) {
90
	$line = <$fh>;
91
	if (defined $line && $line =~ /^\< (.*)$/) {
92
	    $chunk_text .= "-${1}\n";
93
	} else {
94
	    # Some other format.
95
	    return undef;
96
	}
97
    }
98
 
99
    # If there is both old and new text, read the separator line.
100
    # Note bloody VSS for some versions will put the --- at the end of
101
    # the previous line rather than on a new line!
102
    if ($old_length > 0 && $new_length > 0) {
103
	my $previous_line = $line;
104
	my $pos = $fh->getpos;
105
	$line = <$fh>;
106
	return undef unless defined $line;
107
	if ($line !~ /^\-\-\-$/o && $chunk_text =~ /^(.*)\-\-\-$/os) {
108
	    # Stupid VSS diff format, chop off the seperator characters
109
	    # and move the file pointer back.
110
	    $chunk_text = "$1\n";
111
	    $fh->setpos($pos);
112
	} elsif ($line !~ /^\-\-\-$/o) {
113
	    # Didn't match standard separator, some other format.
114
	    return undef;
115
	}
116
    }
117
 
118
    # Now read the new lines, if any.
119
    for (my $i = 0; $i < $new_length; $i++) {
120
	$line = <$fh>;
121
	if (defined $line && $line =~ /^\> (.*)$/) {
122
	    $chunk_text .= "+${1}\n";
123
	} else {
124
	    # Some other format.
125
	    return undef;
126
	}
127
    }
128
 
129
    # Now create the chunk object, and return it.
130
    my $chunk = {};
131
    $chunk->{filename} = $filename;
132
    $chunk->{revision} = $revision;
133
    $chunk->{old_linenumber} = $old_linenumber;
134
    $chunk->{new_linenumber} = $new_linenumber;
135
    $chunk->{binary} = 0;
136
    $chunk->{text} = $chunk_text;
137
    $chunk->{description} = "";
138
    $chunk->{repmatch} = $repmatch;
139
 
140
    return $chunk;
141
}
142
 
143
1;