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 David Sitsky.  All rights reserved.
3
# sits@users.sourceforge.net
4
#
5
# This program is free software; you can redistribute it and modify it under
6
# the terms of the GPL.
7
 
8
# Model object for handling topic file data.
9
 
10
package Codestriker::Model::Delta;
11
 
12
use strict;
13
use Encode qw(decode_utf8);
14
 
15
# Create the appropriate delta rows for this review. This gets called
16
# by File::get_deltas. It passes in the result of a sql query on the
17
# delta table.
18
sub new {
19
    my $class = shift;
20
    my $self = {};
21
    bless $self;
22
 
23
    $self->{filename} = decode_utf8($_[1]);
24
    $self->{revision} = $_[2];
25
    $self->{binary} = $_[3];
26
    $self->{old_linenumber} = $_[4];
27
    $self->{new_linenumber} = $_[5];
28
    $self->{text} = decode_utf8($_[6]);
29
    $self->{description} = (defined $_[7]) ? decode_utf8($_[7]) : "";
30
    $self->{filenumber} = $_[8];
31
    $self->{repmatch} = $_[9];
32
    $self->{only_delta_in_file} = 0;
33
 
34
    return $self;
35
}
36
 
37
# Retrieve the number of lines in the data for a given file.
38
# Input -1 for filenumber for a full file list of a specific topic.
39
sub get_delta_size($$$) {
40
    my ($type, $topicid, $filenumber) = @_;
41
 
42
    my @deltas = ();
43
    @deltas = $type->get_deltas($topicid, $filenumber);
44
 
45
    my $addedLines = 0;
46
    my $removedLines = 0;
47
 
48
    for (my $i = 0; $i <= $#deltas; $i++) {
49
	my $delta = $deltas[$i];
50
	my @lines = split '\n', $delta->{text};
51
 
52
	for (my $j = 0; $j <= $#lines; $j++) {
53
	    my @aLine = $lines[$j];
54
	    if (scalar( grep !/^\+/, @aLine ) == 0) {
55
		$addedLines++;
56
	    } elsif (scalar( grep !/^\-/, @aLine ) == 0) {
57
		$removedLines++;
58
	    }
59
	}
60
    }
61
 
62
    my $numLines = "";
63
 
64
    # Return the changes if one is non zero.
65
    if (($removedLines != 0) || ($addedLines != 0)) {
66
	$numLines = "+$addedLines,-$removedLines";
67
    }
68
 
69
    return $numLines;
70
}
71
 
72
 
73
# Retrieve the ordered list of deltas that comprise this review.
74
# Input -1 for filenumber for a full file list of a specific topic.
75
sub get_delta_set($$$) {
76
    my ($type, $topicid, $filenumber) = @_;
77
    return $type->get_deltas($topicid, $filenumber);
78
}
79
 
80
# Retrieve the delta for the specific filename and linenumber.
81
sub get_delta($$$) {
82
    my ($type, $topicid, $filenumber, $linenumber, $new) = @_;
83
 
84
    # Grab all the deltas for this file, and grab the delta with the highest
85
    # starting line number lower than or equal to the specific linenumber,
86
    # and matching the same file number.
87
    my @deltas = $type->get_deltas($topicid, $filenumber);
88
    my $found_delta = undef;
89
    for (my $i = 0; $i <= $#deltas; $i++) {
90
	my $delta = $deltas[$i];
91
	my $delta_linenumber = $new ?
92
	    $delta->{new_linenumber} : $delta->{old_linenumber};
93
	if ($delta_linenumber <= $linenumber) {
94
	    $found_delta = $delta;
95
	} else {
96
	    # Passed the delta of interest, return the previous one found.
97
	    return $found_delta;
98
	}
99
    }
100
 
101
    # Return the matching delta found, if any.
102
    return $found_delta;
103
}
104
 
105
# Retrieve the ordered list of deltas applied to a specific file. Class factory
106
# method, returns a list of delta objects.
107
sub get_deltas($$$) {
108
    my ($type, $topicid, $filenumber) = @_;
109
 
110
    # Obtain a database connection.
111
    my $dbh = Codestriker::DB::DBI->get_connection();
112
 
113
    # Setup the appropriate statement and execute it.
114
    my $select_deltas =
115
	$dbh->prepare_cached('SELECT delta_sequence, filename, revision, ' .
116
			     'binaryfile, old_linenumber, new_linenumber, ' .
117
			     'deltatext, description, topicfile.sequence, ' .
118
			     'repmatch FROM topicfile, delta ' .
119
			     'WHERE delta.topicid = ? AND ' .
120
			     'delta.topicid = topicfile.topicid AND ' .
121
			     'delta.file_sequence = topicfile.sequence ' .
122
			     (($filenumber != -1) ?
123
			      'AND topicfile.sequence = ? ' : '') .
124
			     'ORDER BY delta_sequence ASC');
125
 
126
    my $success = defined $select_deltas;
127
    if ($filenumber != -1) {
128
	$success &&= $select_deltas->execute($topicid, $filenumber);
129
    } else {
130
	$success &&= $select_deltas->execute($topicid);
131
    }
132
 
133
    # Store the results into an array of objects.
134
    my @results = ();
135
    if ($success) {
136
	my @data;
137
	while (@data = $select_deltas->fetchrow_array()) {
138
            my $delta = Codestriker::Model::Delta->new( @data );
139
	    push @results, $delta;
140
	}
141
    }
142
 
143
    # The delta object needs to know if there are only delta objects
144
    # in this file so it can figure out if the delta is a new file.
145
 
146
    # Set the 'only_delta_in_file' field for each delta.
147
    if (scalar(@results) > 0) {
148
        # Assume the first delta is the only delta unless proven otherwise.
149
        $results[0]->{only_delta_in_file} = 1;
150
        for (my $i = 1; $i < scalar(@results); $i++) {
151
            if ($results[$i-1]->{filenumber} == $results[$i]->{filenumber}) {
152
                # If the previous file has the same filenumber, then
153
                # we know that neither the current file nor the
154
                # previous file are the only deltas for the file.
155
                $results[$i]->{only_delta_in_file} = 0;
156
                $results[$i-1]->{only_delta_in_file} = 0;
157
            } else {
158
                # This is the first delta of a file.  We'll assume it's the
159
                # only delta for this file.  If there are more deltas, the next
160
                # loop will correct the assumption.
161
                $results[$i]->{only_delta_in_file} = 1;
162
        }
163
        }
164
    }
165
 
166
    Codestriker::DB::DBI->release_connection($dbh, $success);
167
    die $dbh->errstr unless $success;
168
 
169
    return @results;
170
}
171
 
172
 
173
# This function looks at the delta, and will return 1 if the delta looks like
174
# it is a delta for a completly new file. This happens when a new file is added
175
# to SCM system, or the user updated a plain old text document to be reviewed
176
# without diffs. We need this function because we want to format this case
177
# special.
178
sub is_delta_new_file
179
{
180
    my $self = shift;
181
 
182
    # All of the following must be true:
183
    # - one delta for the entire file
184
    # - delta must start at line 1 (0ld, and new)
185
    my $is_new_file = 0;
186
    if ($self->{only_delta_in_file} &&
187
	$self->{old_linenumber} == 0 &&
188
	$self->{new_linenumber} == 1) {
189
	# All of the delta text lines must start with +.
190
	my @lines = split '\n', $self->{text};
191
	if ( scalar( grep !/^\+/, @lines ) == 0) {
192
	    $is_new_file = 1;
193
	}
194
    }
195
 
196
    return $is_new_file;
197
}
198
 
199
1;