line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package SVN::SVNLook;
|
2
|
1
|
|
|
1
|
|
24900
|
use strict;
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
39
|
|
3
|
1
|
|
|
1
|
|
5
|
use warnings;
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
32
|
|
4
|
1
|
|
|
1
|
|
4
|
use Carp qw(cluck);
|
|
1
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
2447
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $VERSION = 0.04;
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
=head1 NAME
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
SVN::SVNLook - Perl wrapper to the svnlook command.
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
use SVN::SVNLook;
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
my $revision = 1;
|
17
|
|
|
|
|
|
|
my $svnlook = SVN::SVNLook->new(repo => 'repo url',
|
18
|
|
|
|
|
|
|
cmd => 'path to svn look');
|
19
|
|
|
|
|
|
|
my ($author,$date,$logmessage) = $svnlook->info(revision => $revision);
|
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
print "Author $author\n";
|
22
|
|
|
|
|
|
|
print "Date $date\n";
|
23
|
|
|
|
|
|
|
print "LogMessage $logmessage\n";
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
SVN::SVNLook runs the command line client. This module was created to
|
28
|
|
|
|
|
|
|
make adding hooks script easier to manipulate.
|
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
=cut
|
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
=head1 METHODs
|
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
=head2 youngest
|
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
youngest ();
|
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
Perform the youngest command on the repository.
|
39
|
|
|
|
|
|
|
Returns the revision number of the most recent revision as a scalar.
|
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
=head2 info
|
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
info (revision=>$revision);
|
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
Perform the info command, for a given revision or transaction using
|
46
|
|
|
|
|
|
|
named parameters, or a single parameter will be assumed to mean
|
47
|
|
|
|
|
|
|
revision for backwards compatibility. The information returned is an
|
48
|
|
|
|
|
|
|
array containing author, date, and log message. If no $revision is
|
49
|
|
|
|
|
|
|
specified, info for the youngest revision is returned.
|
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
=head2 author
|
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
author (revision=>$revision);
|
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
Perform the author command, for a given revision or transaction using
|
56
|
|
|
|
|
|
|
named parameters or a single parameter will be assumed to mean
|
57
|
|
|
|
|
|
|
revision for backwards compatibility. The information returned is the
|
58
|
|
|
|
|
|
|
author message. If no $revision or transaction is specified, author
|
59
|
|
|
|
|
|
|
for the youngest revision is returned.
|
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
=head2 dirschanged
|
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
dirschanged (revision=>$revision)
|
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
Performs the dirs-changed command, for a given revision or transaction
|
66
|
|
|
|
|
|
|
using named parameters, or a single parameter will be assumed to mean
|
67
|
|
|
|
|
|
|
revision for backwards compatibility. This method returns a boolean and
|
68
|
|
|
|
|
|
|
an array reference.
|
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
=head2 fileschanged
|
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
fileschanged (revision=>$revision)
|
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
Performs the changed command, for a given revision or transaction
|
75
|
|
|
|
|
|
|
using named parameters or a single parameter will be assumed to mean
|
76
|
|
|
|
|
|
|
revision for backwards compatibility this method returns 3 array
|
77
|
|
|
|
|
|
|
references added, deleted and modified.
|
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
=head2 diff
|
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
diff (revision=>$revision)
|
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
Performs the diff command, for a given revision or transaction using
|
84
|
|
|
|
|
|
|
named parameters or a single parameter will be assumed to mean
|
85
|
|
|
|
|
|
|
revision for backwards compatability this method returns a hash
|
86
|
|
|
|
|
|
|
reference, with each file being the key and value being the diff info.
|
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
=cut
|
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
sub new {
|
92
|
0
|
|
|
0
|
0
|
|
my $self = {};
|
93
|
0
|
|
|
|
|
|
my $class = shift;
|
94
|
0
|
|
|
|
|
|
%$self = @_;
|
95
|
0
|
|
0
|
|
|
|
$self->{repo} ||= $self->{target};
|
96
|
0
|
0
|
|
|
|
|
die "no repository specified" unless $self->{repo};
|
97
|
0
|
|
|
|
|
|
return bless $self, $class;
|
98
|
|
|
|
|
|
|
}
|
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
sub youngest
|
101
|
|
|
|
|
|
|
{
|
102
|
0
|
|
|
0
|
1
|
|
my $self = shift;
|
103
|
0
|
|
|
|
|
|
my ($rev) = _read_from_process($self->{cmd}, 'youngest', $self->{repo});
|
104
|
0
|
|
|
|
|
|
return $rev;
|
105
|
|
|
|
|
|
|
}
|
106
|
|
|
|
|
|
|
sub info
|
107
|
|
|
|
|
|
|
{
|
108
|
0
|
|
|
0
|
1
|
|
my $self = shift;
|
109
|
0
|
|
|
|
|
|
my %args;
|
110
|
0
|
0
|
|
|
|
|
if ($#_ == 0)
|
111
|
|
|
|
|
|
|
{
|
112
|
0
|
|
|
|
|
|
$args{revision} = shift;
|
113
|
|
|
|
|
|
|
}
|
114
|
|
|
|
|
|
|
else
|
115
|
|
|
|
|
|
|
{
|
116
|
0
|
|
|
|
|
|
%args = @_;
|
117
|
|
|
|
|
|
|
}
|
118
|
0
|
0
|
|
|
|
|
my @svnlooklines = _read_from_process(
|
|
|
0
|
|
|
|
|
|
119
|
|
|
|
|
|
|
$self->{cmd},
|
120
|
|
|
|
|
|
|
'info',
|
121
|
|
|
|
|
|
|
$self->{repo},
|
122
|
|
|
|
|
|
|
($args{revision} ? ('-r', $args{revision}) : ()),
|
123
|
|
|
|
|
|
|
($args{transaction} ? ('-t', $args{transaction}) : ()),
|
124
|
|
|
|
|
|
|
);
|
125
|
0
|
|
|
|
|
|
my $author = shift @svnlooklines; # author of this change
|
126
|
0
|
|
|
|
|
|
my $date = shift @svnlooklines; # date of change
|
127
|
0
|
|
|
|
|
|
shift @svnlooklines; # log message size
|
128
|
0
|
|
|
|
|
|
my @log = map { "$_\n" } @svnlooklines;
|
|
0
|
|
|
|
|
|
|
129
|
0
|
|
|
|
|
|
my $logmessage = join('',@log);
|
130
|
0
|
|
|
|
|
|
return ($author,$date,$logmessage);
|
131
|
|
|
|
|
|
|
}
|
132
|
|
|
|
|
|
|
sub author
|
133
|
|
|
|
|
|
|
{
|
134
|
0
|
|
|
0
|
1
|
|
my $self = shift;
|
135
|
0
|
|
|
|
|
|
my %args;
|
136
|
0
|
0
|
|
|
|
|
if ($#_ == 0)
|
137
|
|
|
|
|
|
|
{
|
138
|
0
|
|
|
|
|
|
$args{revision} = shift;
|
139
|
|
|
|
|
|
|
}
|
140
|
|
|
|
|
|
|
else
|
141
|
|
|
|
|
|
|
{
|
142
|
0
|
|
|
|
|
|
%args = @_;
|
143
|
|
|
|
|
|
|
}
|
144
|
0
|
0
|
|
|
|
|
my @svnlooklines = _read_from_process(
|
|
|
0
|
|
|
|
|
|
145
|
|
|
|
|
|
|
$self->{cmd},
|
146
|
|
|
|
|
|
|
'author',
|
147
|
|
|
|
|
|
|
$self->{repo},
|
148
|
|
|
|
|
|
|
($args{revision} ? ('-r', $args{revision}) : ()),
|
149
|
|
|
|
|
|
|
($args{transaction} ? ('-t', $args{transaction}) : ()),
|
150
|
|
|
|
|
|
|
);
|
151
|
0
|
|
|
|
|
|
return $svnlooklines[0]; # author of this change
|
152
|
|
|
|
|
|
|
}
|
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
sub dirschanged
|
155
|
|
|
|
|
|
|
{
|
156
|
0
|
|
|
0
|
1
|
|
my $self = shift;
|
157
|
0
|
|
|
|
|
|
my %args;
|
158
|
0
|
0
|
|
|
|
|
if ($#_ == 0)
|
159
|
|
|
|
|
|
|
{
|
160
|
0
|
|
|
|
|
|
$args{revision} = shift;
|
161
|
|
|
|
|
|
|
}
|
162
|
|
|
|
|
|
|
else
|
163
|
|
|
|
|
|
|
{
|
164
|
0
|
|
|
|
|
|
%args = @_;
|
165
|
|
|
|
|
|
|
}
|
166
|
|
|
|
|
|
|
# Figure out what directories have changed using svnlook.
|
167
|
0
|
0
|
|
|
|
|
my @dirschanged = _read_from_process(
|
|
|
0
|
|
|
|
|
|
168
|
|
|
|
|
|
|
$self->{cmd},
|
169
|
|
|
|
|
|
|
'dirs-changed',
|
170
|
|
|
|
|
|
|
$self->{repo},
|
171
|
|
|
|
|
|
|
($args{revision} ? ('-r', $args{revision}) : ()),
|
172
|
|
|
|
|
|
|
($args{transaction} ? ('-t', $args{transaction}) : ()),
|
173
|
|
|
|
|
|
|
);
|
174
|
0
|
|
|
|
|
|
my $rootchanged = 0;
|
175
|
0
|
|
|
|
|
|
for (my $i=0; $i<@dirschanged; ++$i)
|
176
|
|
|
|
|
|
|
{
|
177
|
0
|
0
|
|
|
|
|
if ($dirschanged[$i] eq '/')
|
178
|
|
|
|
|
|
|
{
|
179
|
0
|
|
|
|
|
|
$rootchanged = 1;
|
180
|
|
|
|
|
|
|
}
|
181
|
|
|
|
|
|
|
else
|
182
|
|
|
|
|
|
|
{
|
183
|
0
|
|
|
|
|
|
$dirschanged[$i] =~ s#^(.+)[/\\]$#$1#;
|
184
|
|
|
|
|
|
|
}
|
185
|
|
|
|
|
|
|
}
|
186
|
0
|
|
|
|
|
|
return ($rootchanged,\@dirschanged);
|
187
|
|
|
|
|
|
|
}
|
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
sub fileschanged
|
191
|
|
|
|
|
|
|
{
|
192
|
0
|
|
|
0
|
1
|
|
my $self = shift;
|
193
|
0
|
|
|
|
|
|
my %args;
|
194
|
0
|
0
|
|
|
|
|
if ($#_ == 0)
|
195
|
|
|
|
|
|
|
{
|
196
|
0
|
|
|
|
|
|
$args{revision} = shift;
|
197
|
|
|
|
|
|
|
}
|
198
|
|
|
|
|
|
|
else
|
199
|
|
|
|
|
|
|
{
|
200
|
0
|
|
|
|
|
|
%args = @_;
|
201
|
|
|
|
|
|
|
}
|
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
# Figure out what files have changed using svnlook.
|
204
|
0
|
0
|
|
|
|
|
my @svnlooklines = _read_from_process(
|
|
|
0
|
|
|
|
|
|
205
|
|
|
|
|
|
|
$self->{cmd},
|
206
|
|
|
|
|
|
|
'changed',
|
207
|
|
|
|
|
|
|
$self->{repo},
|
208
|
|
|
|
|
|
|
($args{revision} ? ('-r', $args{revision}) : ()),
|
209
|
|
|
|
|
|
|
($args{transaction} ? ('-t', $args{transaction}) : ()),
|
210
|
|
|
|
|
|
|
);
|
211
|
|
|
|
|
|
|
# Parse the changed nodes.
|
212
|
0
|
|
|
|
|
|
my @adds;
|
213
|
|
|
|
|
|
|
my @dels;
|
214
|
0
|
|
|
|
|
|
my @mods;
|
215
|
0
|
|
|
|
|
|
foreach my $line (@svnlooklines)
|
216
|
|
|
|
|
|
|
{
|
217
|
0
|
|
|
|
|
|
my $path = '';
|
218
|
0
|
|
|
|
|
|
my $code = '';
|
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
# Split the line up into the modification code and path, ignoring
|
221
|
|
|
|
|
|
|
# property modifications.
|
222
|
0
|
0
|
|
|
|
|
if ($line =~ /^(.). (.*)$/)
|
223
|
|
|
|
|
|
|
{
|
224
|
0
|
|
|
|
|
|
$code = $1;
|
225
|
0
|
|
|
|
|
|
$path = $2;
|
226
|
|
|
|
|
|
|
}
|
227
|
0
|
0
|
|
|
|
|
if ($code eq 'A')
|
|
|
0
|
|
|
|
|
|
228
|
|
|
|
|
|
|
{
|
229
|
0
|
|
|
|
|
|
push(@adds, $path);
|
230
|
|
|
|
|
|
|
}
|
231
|
|
|
|
|
|
|
elsif ($code eq 'D')
|
232
|
|
|
|
|
|
|
{
|
233
|
0
|
|
|
|
|
|
push(@dels, $path);
|
234
|
|
|
|
|
|
|
}
|
235
|
|
|
|
|
|
|
else
|
236
|
|
|
|
|
|
|
{
|
237
|
0
|
|
|
|
|
|
push(@mods, $path);
|
238
|
|
|
|
|
|
|
}
|
239
|
|
|
|
|
|
|
}
|
240
|
0
|
|
|
|
|
|
return (\@adds,\@dels,\@mods);
|
241
|
|
|
|
|
|
|
}
|
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
sub diff
|
244
|
|
|
|
|
|
|
{
|
245
|
0
|
|
|
0
|
1
|
|
my $self = shift;
|
246
|
0
|
|
|
|
|
|
my %args;
|
247
|
0
|
0
|
|
|
|
|
if ($#_ == 0)
|
248
|
|
|
|
|
|
|
{
|
249
|
0
|
|
|
|
|
|
$args{revision} = shift;
|
250
|
|
|
|
|
|
|
}
|
251
|
|
|
|
|
|
|
else
|
252
|
|
|
|
|
|
|
{
|
253
|
0
|
|
|
|
|
|
%args = @_;
|
254
|
|
|
|
|
|
|
}
|
255
|
|
|
|
|
|
|
|
256
|
0
|
0
|
|
|
|
|
my @difflines = _read_from_process(
|
|
|
0
|
|
|
|
|
|
257
|
|
|
|
|
|
|
$self->{cmd},
|
258
|
|
|
|
|
|
|
'diff',
|
259
|
|
|
|
|
|
|
$self->{repo},
|
260
|
|
|
|
|
|
|
($args{revision} ? ('-r', $args{revision}) : ()),
|
261
|
|
|
|
|
|
|
($args{transaction} ? ('-t', $args{transaction}) : ()),
|
262
|
|
|
|
|
|
|
('--no-diff-deleted')
|
263
|
|
|
|
|
|
|
);
|
264
|
|
|
|
|
|
|
# Ok we need to split this out now , by file
|
265
|
0
|
|
|
|
|
|
my @lin = split(/Modified: (.*)\n=*\n/,join("\n",@difflines));
|
266
|
0
|
|
|
|
|
|
shift(@lin);
|
267
|
0
|
|
|
|
|
|
my %lines = @lin;
|
268
|
0
|
|
|
|
|
|
return %lines;
|
269
|
|
|
|
|
|
|
}
|
270
|
|
|
|
|
|
|
#
|
271
|
|
|
|
|
|
|
# PRIVATE METHODS
|
272
|
|
|
|
|
|
|
# Methods taken from commit-email.pl Copyright subversion team
|
273
|
|
|
|
|
|
|
#
|
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
# NB. croak is not a defined subroutine - where did this come from?
|
276
|
|
|
|
|
|
|
# croak is defined in Carp, somehow didnt get included in CPAN post
|
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
sub _read_from_process
|
279
|
|
|
|
|
|
|
{
|
280
|
0
|
0
|
|
0
|
|
|
unless (@_)
|
281
|
|
|
|
|
|
|
{
|
282
|
0
|
|
|
|
|
|
cluck("$0: read_from_process passed no arguments.\n");
|
283
|
|
|
|
|
|
|
}
|
284
|
0
|
|
|
|
|
|
my ($status, @output) = _safe_read_from_pipe(@_);
|
285
|
0
|
0
|
|
|
|
|
if ($status)
|
286
|
|
|
|
|
|
|
{
|
287
|
0
|
|
|
|
|
|
cluck("$0: `@_' failed with this output:", @output);
|
288
|
|
|
|
|
|
|
}
|
289
|
|
|
|
|
|
|
else
|
290
|
|
|
|
|
|
|
{
|
291
|
0
|
|
|
|
|
|
return @output;
|
292
|
|
|
|
|
|
|
}
|
293
|
|
|
|
|
|
|
}
|
294
|
|
|
|
|
|
|
sub _safe_read_from_pipe
|
295
|
|
|
|
|
|
|
{
|
296
|
0
|
0
|
|
0
|
|
|
unless (@_)
|
297
|
|
|
|
|
|
|
{
|
298
|
0
|
|
|
|
|
|
croak("$0: safe_read_from_pipe passed no arguments.\n");
|
299
|
|
|
|
|
|
|
}
|
300
|
|
|
|
|
|
|
|
301
|
0
|
|
|
|
|
|
my $pid = open(SAFE_READ, '-|');
|
302
|
0
|
0
|
|
|
|
|
unless (defined $pid)
|
303
|
|
|
|
|
|
|
{
|
304
|
0
|
|
|
|
|
|
die "$0: cannot fork: $!\n";
|
305
|
|
|
|
|
|
|
}
|
306
|
0
|
0
|
|
|
|
|
unless ($pid)
|
307
|
|
|
|
|
|
|
{
|
308
|
0
|
0
|
|
|
|
|
open(STDERR, ">&STDOUT") or die "$0: cannot dup STDOUT: $!\n";
|
309
|
0
|
0
|
|
|
|
|
exec(@_)or die "$0: cannot exec `@_': $!\n";
|
310
|
|
|
|
|
|
|
}
|
311
|
0
|
|
|
|
|
|
my @output;
|
312
|
0
|
|
|
|
|
|
while ()
|
313
|
|
|
|
|
|
|
{
|
314
|
0
|
|
|
|
|
|
s/[\r\n]+$//;
|
315
|
0
|
|
|
|
|
|
push(@output, $_);
|
316
|
|
|
|
|
|
|
}
|
317
|
0
|
|
|
|
|
|
close(SAFE_READ);
|
318
|
0
|
|
|
|
|
|
my $result = $?;
|
319
|
0
|
|
|
|
|
|
my $exit = $result >> 8;
|
320
|
0
|
|
|
|
|
|
my $signal = $result & 127;
|
321
|
0
|
0
|
|
|
|
|
my $cd = $result & 128 ? "with core dump" : "";
|
322
|
0
|
0
|
0
|
|
|
|
if ($signal or $cd)
|
323
|
|
|
|
|
|
|
{
|
324
|
0
|
|
|
|
|
|
warn "$0: pipe from `@_' failed $cd: exit=$exit signal=$signal\n";
|
325
|
|
|
|
|
|
|
}
|
326
|
0
|
0
|
|
|
|
|
if (wantarray)
|
327
|
|
|
|
|
|
|
{
|
328
|
0
|
|
|
|
|
|
return ($result, @output);
|
329
|
|
|
|
|
|
|
}
|
330
|
|
|
|
|
|
|
else
|
331
|
|
|
|
|
|
|
{
|
332
|
0
|
|
|
|
|
|
return $result;
|
333
|
|
|
|
|
|
|
}
|
334
|
|
|
|
|
|
|
}
|
335
|
|
|
|
|
|
|
1;
|
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
__END__
|