File Coverage

perllib/Arch/Changes.pm
Criterion Covered Total %
statement 80 89 89.8
branch 12 20 60.0
condition 9 17 52.9
subroutine 20 21 95.2
pod 9 9 100.0
total 130 156 83.3


line stmt bran cond sub pod time code
1             # Arch Perl library, Copyright (C) 2004 Mikhael Goikhman, Enno Cramer
2             #
3             # This program is free software; you can redistribute it and/or modify
4             # it under the terms of the GNU General Public License as published by
5             # the Free Software Foundation; either version 2 of the License, or
6             # (at your option) any later version.
7             #
8             # This program is distributed in the hope that it will be useful,
9             # but WITHOUT ANY WARRANTY; without even the implied warranty of
10             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11             # GNU General Public License for more details.
12             #
13             # You should have received a copy of the GNU General Public License
14             # along with this program; if not, write to the Free Software
15             # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16              
17 5     5   88 use 5.005;
  5         15  
  5         204  
18 5     5   29 use strict;
  5         8  
  5         205  
19              
20             package Arch::Changes;
21              
22 5     5   24 use Exporter;
  5         8  
  5         230  
23 5     5   132 BEGIN { *Arch::Changes::import = *Exporter::import; }
24 5     5   29 use vars qw(@EXPORT_OK %EXPORT_TAGS);
  5         8  
  5         437  
25              
26             @EXPORT_OK = qw(
27             ADD DELETE REMOVE MODIFY META_MODIFY RENAME
28             );
29             %EXPORT_TAGS = (
30             type => [ qw(ADD DELETE REMOVE MODIFY META_MODIFY RENAME) ],
31             );
32              
33              
34 5     5   1147 use Arch::Util qw(run_tla);
  5         15  
  5         282  
35              
36 5     5   30 use constant ADD => 'A';
  5         8  
  5         352  
37 5     5   24 use constant DELETE => 'D';
  5         6  
  5         187  
38 5     5   24 use constant REMOVE => 'D'; # obsolete, may be removed after summer 2005
  5         7  
  5         309  
39 5     5   25 use constant MODIFY => 'M';
  5         10  
  5         269  
40 5     5   22 use constant META_MODIFY => '-';
  5         19  
  5         233  
41 5     5   28 use constant RENAME => '=';
  5         107  
  5         4510  
42              
43             sub new ($$) {
44 1     1 1 3 my $class = shift;
45              
46 1         6 my $self = {
47             changes => [],
48             };
49              
50 1         5 return bless $self, $class;
51             }
52              
53             sub add ($$$@) {
54 6     6 1 9 my $self = shift;
55 6         18 my ($type, $is_dir, @args) = @_;
56              
57 6 100       8 push @{$self->{changes}}, {
  6         48  
58             type => $type,
59             is_dir => $is_dir ? 1 : 0,
60             arguments => [ @args ],
61             };
62             }
63              
64             sub count ($) {
65 1     1 1 3 my $self = shift;
66              
67 1         2 return scalar @{$self->{changes}};
  1         9  
68             }
69              
70             sub get ($;$) {
71 6     6 1 7 my $self = shift;
72 6         9 my $num = shift;
73              
74 6 100       19 return $self->{changes}->[$num]
75             if defined $num;
76              
77 5         6 return @{$self->{changes}};
  5         19  
78             }
79              
80             sub get_listing ($) {
81 1     1 1 2 my $self = shift;
82              
83 1         2 my $ret = '';
84 1         5 foreach my $change ($self->get) {
85 6         32 $ret .= Arch::Changes->to_string($change);
86 6         15 $ret .= "\n";
87             }
88              
89 1         6 return $ret;
90             }
91              
92             sub is_changed ($$$;$) {
93 4     4 1 7 my $self = shift;
94 4         21 my $to = { qw(0 0 1 1 from 0 to 1) }->{shift()};
95 4 50       17 die "No 0/1/from/to param" unless defined $to;
96 4   50     10 my $filepath = shift || die "No file/dir name";
97 4         6 my $is_dir = shift;
98              
99 4         5 my $changed = {};
100 4         12 foreach my $change (reverse $self->get) {
101 24         43 my $dst_filepath = $change->{arguments}->[$to - 1];
102 24         35 my $src_filepath = $change->{arguments}->[0 - $to];
103              
104             # support larch "features"
105 24         26 $dst_filepath =~ s!^\./!!;
106 24         23 $src_filepath =~ s!^\./!!;
107              
108             # flag the file change if matching
109 24 50 66     63 if ($src_filepath eq $filepath
      66        
110             && (!defined $is_dir || $change->{is_dir} == $is_dir)
111             ) {
112 5 100       21 $changed->{$change->{type}} =
113             $change->{type} ne RENAME? 1: $dst_filepath;
114             }
115              
116             # handle renames of parent directories (the most close change)
117 24 0 66     84 if ($change->{type} eq RENAME && $change->{is_dir}
      33        
      33        
118             && $filepath =~ m!^\Q$src_filepath\E(/.+)$!
119             && !exists $changed->{RENAME()}
120             ) {
121 0         0 $changed->{$change->{type}} = "$dst_filepath$1";
122             }
123             }
124 4 50       15 $changed = undef unless %$changed;
125              
126 4         22 return $changed;
127             }
128              
129             sub dump ($) {
130 0     0 1 0 my $self = shift;
131              
132 0         0 require Data::Dumper;
133 0         0 my $dumper = Data::Dumper->new([$self->get]);
134 0 0       0 $dumper->Sortkeys(1) if $dumper->can('Sortkeys');
135 0         0 $dumper->Quotekeys(0);
136 0         0 $dumper->Indent(1);
137 0         0 $dumper->Terse(1);
138              
139 0         0 return $dumper->Dump;
140             }
141              
142             my %TYPE_EXT = (
143             ADD() => ' ',
144             DELETE() => ' ',
145             MODIFY() => ' ',
146             META_MODIFY() => '-',
147             RENAME() => '>',
148             );
149              
150             sub type_string ($$) {
151 6     6 1 7 my $class = shift;
152 6         7 my $change = shift;
153              
154 6 100       16 if ($change->{is_dir}) {
155 2 50       11 return $change->{type} eq RENAME
156             ? '/>'
157             : $change->{type} . '/';
158             } else {
159 4         14 return $change->{type} . $TYPE_EXT{$change->{type}};
160             }
161             }
162              
163             sub to_string ($$) {
164 6     6 1 7 my $class = shift;
165 6         9 my $change = shift;
166              
167 6         27 return sprintf("%s %s",
168             Arch::Changes->type_string($change),
169 6         16 join("\t", @{$change->{arguments}}),
170             );
171             }
172              
173             1;
174              
175             __END__