File Coverage

blib/lib/VCS/Rcs/Deltatext.pm
Criterion Covered Total %
statement 134 144 93.0
branch 15 22 68.1
condition 2 6 33.3
subroutine 22 23 95.6
pod 4 10 40.0
total 177 205 86.3


line stmt bran cond sub pod time code
1             #
2             # Copyright (c) 2001 by RIPE-NCC. All rights reserved.
3             #
4             # This program is free software; you can redistribute it and/or
5             # modify it under the same terms as Perl itself.
6             #
7             # You should have received a copy of the Perl license along with
8             # Perl; see the file README in Perl distribution.
9             #
10             # You should have received a copy of the GNU General Public License
11             # along with Perl; see the file Copying. If not, write to
12             # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
13             #
14             # You should have received a copy of the Artistic License
15             # along with Perl; see the file Artistic.
16             #
17             # NO WARRANTY
18             #
19             # BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
20             # FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
21             # OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
22             # PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
23             # OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24             # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
25             # TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
26             # PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
27             # REPAIR OR CORRECTION.
28             #
29             # IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
30             # WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
31             # REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
32             # INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
33             # OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
34             # TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
35             # YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
36             # PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
37             # POSSIBILITY OF SUCH DAMAGES.
38             #
39             # END OF TERMS AND CONDITIONS
40             #
41             #
42             package VCS::Rcs::Deltatext;
43              
44             require 5.8.0;
45 2     2   18 use strict;
  2         5  
  2         101  
46 2     2   12 use warnings;
  2         5  
  2         144  
47              
48 2     2   3523 use Data::Dumper;
  2         41970  
  2         179  
49              
50 2     2   20 use constant LINE => 0;
  2         14  
  2         124  
51 2     2   10 use constant NEXT => 1;
  2         4  
  2         78  
52 2     2   10 use constant PREV => 2;
  2         4  
  2         3256  
53              
54             our ($VERSION) = (q$Revision: 1.11 $ =~ /([\d\.]+)/);
55              
56             our $debug = 0;
57              
58             our $AUTOLOAD;
59              
60              
61             # Constractor
62             sub new {
63 8     8 1 26 my $this = shift;
64 8   33     46 my $class = ref($this) || $this;
65 8         18 my $self = {};
66              
67 8         42 bless $self, $class;
68             }
69              
70              
71             # Get revisions to checkout
72             sub revs2co {
73 8     8 0 15 my $self = shift;
74 8         28 $self->{__revs__} = shift;
75             }
76              
77              
78             # Convert plain text into linked list by lines
79             sub _text2list {
80 8     8   18 my $text = shift;
81            
82 8 50       26 return [undef,undef,undef] unless defined($$text);
83            
84 8         11 my $pp;
85 8         19 my $p0 = [undef,undef,undef];
86 8         13 my $p = $p0;
87 8         56 while ($$text=~/\G([^\n]*\n)/gcs) {
88 2770         3392 $pp = $p;
89 2770         7955 $p = [$1, undef, $pp];
90 2770         11364 $pp->[NEXT] = $p;
91             }
92 8         34 $p0;
93             }
94              
95              
96             # Convert a linked list into plain text
97             sub _list2text {
98 48     48   76 my $p = shift;
99 48         77 my $text;
100 48         31415 $text .= $p->[LINE] while ($p = $p->[NEXT]);
101 48         220 return \$text;
102             }
103              
104              
105             # Keyword subs. (only Revision for now)
106             sub _kv {
107 56     56   104 my $text = shift;
108 56         100 my $rev = shift;
109              
110 56         283 pos($$text)=0;
111              
112 56         1354 $rev = '$'."Revision: $rev ".'$';
113              
114 56         159 my $ltext;
115 56         911 while ($$text=~/\G([^\n]*\n)/gcs) {
116 25486         54743 my $tmp = $1;
117 25486         85909 $tmp=~s{\x24Revision:[^\$]*\$}{$rev}g;
118 25486         138611 $ltext .= $tmp;
119             }
120 56         3554 return $ltext;
121             }
122              
123             # Get the 'latest revision' first
124             sub lastrev {
125 8     8 1 14 my $self = shift;
126 8         14 my $text = shift;
127 8         12 my $rev = shift;
128              
129 8         31 $self->{__t__} = &_text2list($text);
130              
131 8         36 $self->{rev}->{$rev}->{__text__} = &_kv($text,$rev);
132             }
133              
134              
135             # Apply deltatexts to the last state of revisions
136             sub deltarev {
137 48     48 1 80 my $self = shift;
138 48         210 my $text = shift;
139 48         73 my $rev = shift;
140              
141 48 50       156 if ($debug) {
142 0         0 print STDERR "\nself:", Data::Dumper->Dump([$self]);
143 0         0 print STDERR "\ntext:", $$text, "<<<";
144 0         0 print STDERR "\nrev:", $rev;
145             }
146              
147 48 50       317 return unless (defined($text));
148              
149             # parse deltatext into a struct
150 48         162 $self->{__a__} = {};
151 48         19768 pos($$text)=0;
152 48         643 while ($$text=~/\G([^\n]*\n)/gcs) {
153              
154 420         1388 my $tmp=$1;
155 420         2456 my($ad,$lineno,$numoflines) = ($tmp =~ /^(a|d)(\d+)\s+(\d+)/);
156              
157 420         1531 $self->{__a__}{$lineno}{$ad} = $numoflines;
158              
159 420 100       1975 next if ($ad eq 'd');
160              
161 199         1003 for (my $i = 0; $i < $numoflines; $i++){
162 228         1319 $$text=~/\G([^\n]*\n)/gcs;
163 228         402 push @{ $self->{__a__}{$lineno}{a_line} } , $1;
  228         3689  
164             }
165             }
166              
167 48 50       128 if ($debug) {
168 0         0 print STDERR "\na:", Data::Dumper->Dump([$self->{__a__}]);
169             }
170              
171             # do 'co' one revision
172 48         96 my $p = $self->{__t__};
173 48         65 my $i = 0;
174 48         132 while ($p->[NEXT]){
175              
176 22712         72471 ($p, $i) = $self->do_rev($p, $i);
177              
178 22712         61158 $p = $p->[NEXT]; # next
179 22712         94100 $i++;
180             }
181             # anything left to do? do it then:
182 48         142 ($p, $i) = $self->do_rev($p, $i);
183              
184 2     2   15 no warnings;
  2         5  
  2         336  
185             # co everything if nothing is specified or
186             # co only the wanted revisions texts ( this may save memory sometimes ;)
187 48 50 33     392 if ( !$self->{__revs__} or (grep {$rev eq $_} @{$self->{__revs__}}) ) {
  0         0  
  0         0  
188 48         227 $self->{rev}->{$rev}->{__text__} =
189             &_kv(&_list2text($self->{__t__}),$rev);
190             }
191              
192             }
193              
194              
195             # Get a specific revision.
196             sub rev {
197 8     8 1 18 my $self = shift;
198              
199 2     2   10 no warnings;
  2         4  
  2         2720  
200 8         15 my $rev = shift;
201              
202 8         97 $self->{rev}->{$rev}->{__text__};
203             }
204              
205              
206             # Get a list of all or specified revisions.
207             sub revs {
208 8     8 0 20 my $self = shift;
209              
210 8 50       26 $self->{__revs__} ? @{$self->{__revs__}} : keys(%{$self->{rev}})
  0         0  
  8         71  
211             }
212              
213              
214             # Get a list of all revisions explicitly.
215             sub allrevs {
216 0     0 0 0 my $self = shift;
217              
218 0         0 keys(%{$self->{rev}});
  0         0  
219             }
220              
221              
222             # internal: wrapper aroud 'add's and 'delete's
223             sub do_rev {
224 22760     22760 0 32599 my $self = shift;
225 22760         29482 my $p = shift;
226 22760         27072 my $i = shift;
227              
228 22760 100       153833 ($p, $i) = &d_rev($p, $self->{__a__}{$i}{d}, $i)
229             if (exists $self->{__a__}{$i}{d});
230              
231 22760 100       98254 $p = &a_rev($p, $self->{__a__}{$i}{a_line},$i)
232             if (exists $self->{__a__}{$i}{a});
233              
234 22760         97373 ($p, $i)
235             }
236              
237              
238             # internal: apply delete command
239             sub d_rev {
240 221     221 0 319 my $p = shift;
241 221         290 my $j = shift;
242 221         296 my $i = shift;
243              
244 221         668 for (my $k = 0; $k < $j; $k++) {
245 633         1128 $p->[PREV]->[NEXT] = $p->[NEXT];
246 633         930 $p->[NEXT]->[PREV] = $p->[PREV];
247 633         1490 $p = $p->[NEXT];
248             }
249              
250 221         357 $i = $i + $j - 1;
251              
252 221         1669 ($p->[PREV], $i)
253             }
254              
255              
256             # internal: apply add command
257             sub a_rev {
258 199     199 0 286 my $p = shift;
259 199         320 my $a = shift;
260              
261 199         219 my $n;
262 199         420 for (@$a) {
263 228         701 $n = [$_,$p->[NEXT],$p];
264 228         382 $p->[NEXT]->[PREV] = $n;
265 228         291 $p->[NEXT] = $n;
266 228         487 $p = $n;
267             }
268             $p
269 199         383 }
270              
271              
272             # Assingne other specials to the revisions (like date and author)
273             sub AUTOLOAD {
274 112     112   1341 my $self = shift;
275 112         192 my $rev = shift;
276 112         145 my $val = shift;
277              
278 112 50       867 return unless (defined $rev);
279              
280 112 100       589 $self->{rev}->{$rev}->{$AUTOLOAD} = $val if defined($val);
281 112         2973 $self->{rev}->{$rev}->{$AUTOLOAD};
282             }
283              
284              
285             sub DESTROY {
286 7     7   19 my $self = shift;
287 7         22 my $p = $self->{__t__};
288              
289 7         14 my $tmp_p;
290             my $i;
291             #warn "\n\n";
292 7         30 while ($p->[NEXT]){
293 1985         2627 $tmp_p = $p->[NEXT];
294 1985         1929 $p->[NEXT]=undef;
295 1985         2102 $p->[PREV]=undef;
296 1985         18785 $p = $tmp_p; # next
297             #print STDERR $i++;
298             }
299 7         20 $self->{__t__}=undef;
300             #print STDERR Data::Dumper->Dump([$self->{__t__}]);
301              
302 7         15 for my $arevs (keys %{$self->{rev}}) {
  7         6862  
303 45         149 $self->{rev}->{$arevs}->{__text__}=undef;
304             }
305            
306 7         1369 $self={};
307             #warn "\n\n";
308             }
309              
310              
311             1;
312              
313              
314             __END__