File Coverage

blib/lib/SVN/Notify/Filter/Watchers.pm
Criterion Covered Total %
statement 19 76 25.0
branch 2 26 7.6
condition 2 12 16.6
subroutine 4 8 50.0
pod 1 1 100.0
total 28 123 22.7


line stmt bran cond sub pod time code
1             package SVN::Notify::Filter::Watchers;
2              
3 3     3   58741 use warnings;
  3         8  
  3         115  
4 3     3   16 use strict;
  3         6  
  3         100  
5 3     3   3788 use SVN::Notify;
  3         70481  
  3         3139  
6              
7             =begin comment
8              
9             Fake out Test::Pod::Coverage.
10              
11             =head3 post_prepare
12              
13             =head3 _walk_up
14              
15             =head3 _parent
16              
17             =head3 _has_watcher_property
18              
19             =head3 _get_watchers
20              
21             =end comment
22              
23             =head1 NAME
24              
25             SVN::Notify::Filter::Watchers - Subscribe to SVN::Notify commits with a Subversion property.
26              
27             =head1 VERSION
28              
29             Version 0.09
30              
31             =cut
32              
33             our $VERSION = '0.10';
34              
35             =head1 SYNOPSIS
36              
37             Use F in F:
38              
39             svnnotify --p "$1" --r "$2" --to you@example.com --handler HTML \
40             --filter Watchers
41              
42             Use the class in a custom script:
43              
44             use SVN::Notify;
45              
46             my $notifier = SVN::Notify->new(
47             repos_path => $path,
48             revision => $rev,
49             to => 'you@example.com',
50             handler => 'HTML::ColorDiff',
51             filters => [ 'Watchers' ],
52             );
53             $notifier->prepare;
54             $notifier->execute;
55              
56              
57             =head1 DESCRIPTION
58              
59             This L will allow you to add
60             additional recipients to an email by checking a Subversion property
61             (default of C, and can be overridden with
62             C (or C<--watcher-property> option for
63             C). The value of the watcher property is a new line and/or
64             space separated list of email addresses.
65              
66             This filter will walk up the path to root for each path entry that has
67             changed and add recipients if the watcher property has been set. This
68             way you can in effect set the property on C and get ALL
69             commits that happen below C. When an path has been deleted it
70             will check the previous revision for the watcher property. You can
71             also set C (C<--skip-walking-up>) to stop this
72             behavior.
73              
74             By default the filter will then walk down the path of a deleted path
75             and check for recipients to add. This behavior can be changed by adding
76             setting C (or C<--skip-deleted-paths>).
77              
78             Since this is just a filter, there are certain behaviors we can't control, such
79             as not requiring at least on C<--to> address. Unless you have some addresses
80             that should get all commits, regardless of the watcher property, you may want to
81             set the C<--to> to some address that goes to C or does not bounce.
82             However, if you set C (C<--trim-original-to>), it will remove
83             the C<--to> addresses before it finds all the watcher properties.
84              
85             =cut
86              
87             SVN::Notify->register_attributes( watcher_property => 'watcher-property=s',
88             skip_deleted_paths => 'skip-deleted-paths',
89             skip_walking_up => 'skip-walking-up',
90             trim_original_to => 'trim-original-to',
91             );
92              
93             my %seen;
94             my $defaultsvnproperty = "svnx:watchers";
95              
96             sub post_prepare {
97 2     2 1 19094 my ($self, $to) = @_;
98 2 100       12 if($self->trim_original_to) {
99 1         10 @{$self->{to}} = ("");
  1         5  
100             }
101 2         14 my $files_ref = $self->{files};
102 2   66     10 my $svnproperty = $self->watcher_property || $defaultsvnproperty;
103 2         29 foreach my $key (keys(%$files_ref)) {
104 0         0 foreach my $file(@{$files_ref->{$key}}) {
  0         0  
105 0         0 my $revision = $self->{revision};
106             # For Deleted items, check the version before.
107 0 0       0 $revision -=1 if($key eq "D");
108 0 0       0 if(_has_watcher_property($self, $file, $revision)) {
109 0         0 $seen{$file} = 1;
110 0         0 push(@$to, _get_watchers($self, $file, $revision));
111             }
112 0 0       0 if(!$self->skip_walking_up) {
113 0         0 push(@$to, _walk_up($self, _parent($file)));
114             }
115 0 0       0 if($key eq "D") {
116 0 0       0 if(!$self->skip_deleted_paths) {
117 0         0 my $fh = $self->_pipe(
118             $self->{svn_encoding},
119             '-|', $self->{svnlook},
120             'tree',
121             $self->{repos_path},
122             '--full-paths',
123             '-r', $revision,
124             $file
125             );
126 0         0 while(my $entry = <$fh>) {
127 0         0 chomp($entry);
128 0 0       0 next if ($entry eq $file);
129 0 0       0 if(_has_watcher_property($self, $entry, $revision)) {
130 0         0 push(@$to, _get_watchers($self, $entry, $revision));
131             }
132             }
133             }
134             }
135             }
136             }
137              
138 2         7 my %hash = map { $_, 1 } @$to;
  0         0  
139 2         4 push(@{$self->{to}}, keys(%hash));
  2         20  
140             }
141              
142             sub _walk_up {
143 0     0     my $self = shift;
144 0           my $file = shift;
145 0           my $revision = $self->{revision};
146 0           my @watchers;
147 0 0         if(!$seen{$file}) {
148 0 0         if(_has_watcher_property($self, $file, $revision)) {
149 0           $seen{$file} = 1;
150 0           push(@watchers, _get_watchers($self, $file, $revision));
151             }
152             }
153 0 0         if($file ne _parent($file)) {
154 0           push(@watchers, _walk_up($self, _parent($file)));
155             }
156 0           return @watchers;
157             }
158              
159             sub _parent {
160 0     0     my $file = shift;
161 0           $file =~ m/^(.*)\//;
162 0 0 0       if (defined($1) && length($1)) {
163 0           return $1;
164             } else {
165 0           return '/';
166             }
167             }
168              
169             sub _has_watcher_property {
170 0     0     my $self = shift;
171 0           my $file = shift;
172 0           my $revision = shift;
173 0   0       my $svnproperty = $self->watcher_property || $defaultsvnproperty;
174 0           my $fh = $self->_pipe(
175             $self->{svn_encoding},
176             '-|', $self->{svnlook},
177             'proplist',
178             $self->{repos_path},
179             '-r', $revision,
180             $file
181             );
182 0           my $rc = 0;
183 0           while(my $line = <$fh>) {
184 0           chomp($line);
185 0 0         if ($line =~ m/$svnproperty/) {
186 0           $rc = 1;
187             }
188             }
189 0           return $rc;
190             }
191              
192             sub _get_watchers {
193 0     0     my $self = shift;
194 0           my $file = shift;
195 0           my $revision = shift;
196 0   0       my $svnproperty = $self->watcher_property || $defaultsvnproperty;
197 0           my $fh = $self->_pipe(
198             $self->{svn_encoding},
199             '-|', $self->{svnlook},
200             'propget',
201             $self->{repos_path},
202             '-r', $revision,
203             $svnproperty,
204             $file
205             );
206 0           my @watchers;
207 0           while(my $line = <$fh>) {
208 0           chomp($line);
209 0           $line =~ s/^\s*(.+?)\s*/$1/;
210 0           my @entries = split(/\s+/, $line);
211 0           push(@watchers, @entries);
212             }
213 0           return @watchers;
214             }
215              
216              
217             =head1 AUTHOR
218              
219             Larry Shatzer, Jr., C<< >>
220              
221             =head1 BUGS
222              
223             Please report any bugs or feature requests to C, or through
224             the web interface at L. I will be notified, and then you'll
225             automatically be notified of progress on your bug as I make changes.
226              
227             =head1 SUPPORT
228              
229             You can find documentation for this module with the perldoc command.
230              
231             perldoc SVN::Notify::Filter::Watchers
232              
233              
234             You can also look for information at:
235              
236             =over 4
237              
238             =item * RT: CPAN's request tracker
239              
240             L
241              
242             =item * AnnoCPAN: Annotated CPAN documentation
243              
244             L
245              
246             =item * CPAN Ratings
247              
248             L
249              
250             =item * Search CPAN
251              
252             L
253              
254             =back
255              
256              
257             =head1 ACKNOWLEDGEMENTS
258              
259             David Wheeler for L.
260              
261             =head1 SEE ALSO
262              
263             =over
264              
265             =item L
266              
267             =back
268              
269             =head1 COPYRIGHT & LICENSE
270              
271             Copyright 2008-2010 Larry Shatzer, Jr., all rights reserved.
272              
273             This program is free software; you can redistribute it and/or modify it
274             under the same terms as Perl itself.
275              
276              
277             =cut
278              
279             1; # End of SVN::Notify::Filter::Watchers