Subversion Repositories DevTools

Rev

Go to most recent revision | Details | 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
# Parser object for reading the output for a perforce diff command, such
10
# as:
11
#
12
# p4 diff -du
13
#
14
 
15
package Codestriker::FileParser::PerforceDiff;
16
 
17
use strict;
18
use Codestriker::FileParser::UnidiffUtils;
19
 
20
sub _make_chunk ($);
21
sub _retrieve_file ($$);
22
 
23
# Return the array of filenames, revision number, linenumber, whether its
24
# binary or not, and the diff text.
25
# Return () if the file can't be parsed, meaning it is in another format.
26
sub parse ($$$) {
27
    my ($type, $fh, $repository) = @_;
28
 
29
    # Skip initial whitespace.
30
    my $line = <$fh>;
31
    while (defined($line) && $line =~ /^\s*$/) {
32
	$line = <$fh>;
33
    }
34
 
35
    # Array of results found.
36
    my @result = ();
37
 
38
    # Assume the repository matches this diff, unless we find evidence to
39
    # the contrary.
40
    my $repmatch = 1;
41
 
42
    # Now read the actual diff chunks.
43
    while (defined($line)) {
44
	if ($line =~ /^==== (.*)\#(\d+) \- .* ==== \((.*)\)$/) {
45
	    my $filename = $1;
46
	    my $revision = $2;
47
	    my $file_type = $3;
48
 
49
	    if ($file_type eq "ubinary" || $file_type eq "xbinary" ||
50
		$file_type eq "binary") {
51
		# Binary file, skip the next line and add the record in.
52
		$line = <$fh>;
53
		my $chunk = {};
54
		$chunk->{filename} = $filename;
55
		$chunk->{revision} = $revision;
56
		$chunk->{old_linenumber} = -1;
57
		$chunk->{new_linenumber} = -1;
58
		$chunk->{binary} = 1;
59
		$chunk->{text} = "";
60
		$chunk->{description} = "";
61
		$chunk->{repmatch} = $repmatch;
62
		push @result, $chunk;
63
	    }
64
	    elsif ($file_type eq "text") {
65
		# Note there may be an optional '---' and '+++' lines
66
		# before the chunk.
67
		my $lastpos = tell $fh;
68
		if (<$fh> !~ /^\-\-\-/ || <$fh> !~ /^\+\+\+/) {
69
		    # Move the file pointer back.
70
		    seek $fh, $lastpos, 0;
71
		}
72
 
73
		my @file_diffs = Codestriker::FileParser::UnidiffUtils->
74
		    read_unidiff_text($fh, $filename, $revision, $repmatch);
75
		push @result, @file_diffs;
76
	    }
77
	    else {
78
		# Got knows what this is, can't parse it.
79
		return ();
80
	    }
81
	} elsif ($line =~ /^==== (.*)\#(\d+) \-/) {
82
	    my $filename = $1;
83
	    my $revision = $2;
84
 
85
	    # Now read the entire diff chunk (it may be empty if the
86
	    # user hasn't actually modified the file).  Note there
87
	    # may be an optional '---' and '+++' lines before the
88
	    # chunk.
89
	    my $lastpos = tell $fh;
90
	    if (<$fh> !~ /^\-\-\-/ || <$fh> !~ /^\+\+\+/) {
91
		# Move the file pointer back.
92
		seek $fh, $lastpos, 0;
93
	    }
94
 
95
	    my @file_diffs = Codestriker::FileParser::UnidiffUtils->
96
		read_unidiff_text($fh, $filename, $revision, $repmatch);
97
	    push @result, @file_diffs;
98
	} else {
99
	    # Can't parse this file.
100
	    return ();
101
	}
102
 
103
	# Now read the next chunk.
104
	$line = <$fh> if defined $line;
105
    }
106
 
107
    # Return the found diff chunks.
108
    return @result;
109
}
110
 
111
1;