← Index
NYTProf Performance Profile   « line view »
For ./view
  Run on Fri Jul 31 19:05:14 2015
Reported on Fri Jul 31 19:08:09 2015

Filename/var/www/foswiki11/lib/Foswiki/Store/VC/RcsWrapHandler.pm
StatementsExecuted 48505 statements in 550ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
4735211511ms1.20sFoswiki::Store::VC::RcsWrapHandler::::newFoswiki::Store::VC::RcsWrapHandler::new
1115.16ms8.26msFoswiki::Store::VC::RcsWrapHandler::::BEGIN@22Foswiki::Store::VC::RcsWrapHandler::BEGIN@22
426114.30ms48.0msFoswiki::Store::VC::RcsWrapHandler::::getRevisionFoswiki::Store::VC::RcsWrapHandler::getRevision
22112.47ms10.1sFoswiki::Store::VC::RcsWrapHandler::::getInfoFoswiki::Store::VC::RcsWrapHandler::getInfo
35321.93ms5.47sFoswiki::Store::VC::RcsWrapHandler::::_numRevisionsFoswiki::Store::VC::RcsWrapHandler::_numRevisions
11113µs26µsFoswiki::Store::VC::RcsWrapHandler::::BEGIN@19Foswiki::Store::VC::RcsWrapHandler::BEGIN@19
11110µs16µsFoswiki::Store::VC::RcsWrapHandler::::BEGIN@20Foswiki::Store::VC::RcsWrapHandler::BEGIN@20
1115µs5µsFoswiki::Store::VC::RcsWrapHandler::::BEGIN@25Foswiki::Store::VC::RcsWrapHandler::BEGIN@25
0000s0sFoswiki::Store::VC::RcsWrapHandler::::_deleteRevisionFoswiki::Store::VC::RcsWrapHandler::_deleteRevision
0000s0sFoswiki::Store::VC::RcsWrapHandler::::_lockFoswiki::Store::VC::RcsWrapHandler::_lock
0000s0sFoswiki::Store::VC::RcsWrapHandler::::ciFoswiki::Store::VC::RcsWrapHandler::ci
0000s0sFoswiki::Store::VC::RcsWrapHandler::::deleteRevisionFoswiki::Store::VC::RcsWrapHandler::deleteRevision
0000s0sFoswiki::Store::VC::RcsWrapHandler::::finishFoswiki::Store::VC::RcsWrapHandler::finish
0000s0sFoswiki::Store::VC::RcsWrapHandler::::getRevisionAtTimeFoswiki::Store::VC::RcsWrapHandler::getRevisionAtTime
0000s0sFoswiki::Store::VC::RcsWrapHandler::::initBinaryFoswiki::Store::VC::RcsWrapHandler::initBinary
0000s0sFoswiki::Store::VC::RcsWrapHandler::::initTextFoswiki::Store::VC::RcsWrapHandler::initText
0000s0sFoswiki::Store::VC::RcsWrapHandler::::parseRevisionDiffFoswiki::Store::VC::RcsWrapHandler::parseRevisionDiff
0000s0sFoswiki::Store::VC::RcsWrapHandler::::repRevFoswiki::Store::VC::RcsWrapHandler::repRev
0000s0sFoswiki::Store::VC::RcsWrapHandler::::revisionDiffFoswiki::Store::VC::RcsWrapHandler::revisionDiff
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1# See bottom of file for license and copyright information
2
3=begin TML
4
5---+ package Foswiki::Store::VC::RcsWrapHandler
6
7This class implements the pure methods of the Foswiki::Store::VC::Handler
8superclass. See the superclass for detailed documentation of the methods.
9
10Wrapper around the RCS commands required by Foswiki.
11An object of this class is created for each file stored under RCS.
12
13For readers who are familiar with Foswiki version 1.0, this class
14is analagous to the old =Foswiki::Store::RcsWrap=.
15
16=cut
17
18package Foswiki::Store::VC::RcsWrapHandler;
19255µs239µs
# spent 26µs (13+13) within Foswiki::Store::VC::RcsWrapHandler::BEGIN@19 which was called: # once (13µs+13µs) by Foswiki::Store::RcsWrap::BEGIN@26 at line 19
use strict;
# spent 26µs making 1 call to Foswiki::Store::VC::RcsWrapHandler::BEGIN@19 # spent 13µs making 1 call to strict::import
20226µs222µs
# spent 16µs (10+6) within Foswiki::Store::VC::RcsWrapHandler::BEGIN@20 which was called: # once (10µs+6µs) by Foswiki::Store::RcsWrap::BEGIN@26 at line 20
use warnings;
# spent 16µs making 1 call to Foswiki::Store::VC::RcsWrapHandler::BEGIN@20 # spent 6µs making 1 call to warnings::import
21
222118µs18.26ms
# spent 8.26ms (5.16+3.10) within Foswiki::Store::VC::RcsWrapHandler::BEGIN@22 which was called: # once (5.16ms+3.10ms) by Foswiki::Store::RcsWrap::BEGIN@26 at line 22
use Foswiki::Store::VC::Handler ();
# spent 8.26ms making 1 call to Foswiki::Store::VC::RcsWrapHandler::BEGIN@22
2318µsour @ISA = ('Foswiki::Store::VC::Handler');
24
2522.04ms15µs
# spent 5µs within Foswiki::Store::VC::RcsWrapHandler::BEGIN@25 which was called: # once (5µs+0s) by Foswiki::Store::RcsWrap::BEGIN@26 at line 25
use Foswiki::Sandbox ();
# spent 5µs making 1 call to Foswiki::Store::VC::RcsWrapHandler::BEGIN@25
26
27
# spent 1.20s (511ms+690ms) within Foswiki::Store::VC::RcsWrapHandler::new which was called 47352 times, avg 25µs/call: # 47352 times (511ms+690ms) by Foswiki::Store::RcsWrap::getHandler at line 30 of /var/www/foswiki11/lib/Foswiki/Store/RcsWrap.pm, avg 25µs/call
sub new {
2847352530ms47352690ms return shift->SUPER::new(@_);
# spent 690ms making 47352 calls to Foswiki::Store::VC::Handler::new, avg 15µs/call
29}
30
31=begin TML
32
33---++ ObjectMethod finish()
34Break circular references.
35
36=cut
37
38# Note to developers; please undef *all* fields in the object explicitly,
39# whether they are references or not. That way this method is "golden
40# documentation" of the live fields in the object.
41sub finish {
42 my $this = shift;
43 $this->SUPER::finish();
44 undef $this->{binary};
45}
46
47# implements VC::Handler
48sub initBinary {
49 my ($this) = @_;
50
51 $this->{binary} = 1;
52
53 $this->mkPathTo( $this->{file} );
54
55 return if -e $this->{rcsFile};
56
57 my ( $rcsOutput, $exit ) =
58 Foswiki::Sandbox->sysCommand( $Foswiki::cfg{RCS}{initBinaryCmd},
59 FILENAME => $this->{file} );
60 if ($exit) {
61 throw Error::Simple( $Foswiki::cfg{RCS}{initBinaryCmd} . ' of '
62 . $this->hidePath( $this->{file} )
63 . ' failed: '
64 . $rcsOutput );
65 }
66 elsif ( !-e $this->{rcsFile} ) {
67
68 # Sometimes (on Windows?) rcs file not formed, so check for it
69 throw Error::Simple( $Foswiki::cfg{RCS}{initBinaryCmd} . ' of '
70 . $this->hidePath( $this->{rcsFile} )
71 . ' failed to create history file' );
72 }
73}
74
75# implements VC::Handler
76sub initText {
77 my ($this) = @_;
78 $this->{binary} = 0;
79
80 $this->mkPathTo( $this->{file} );
81
82 return if -e $this->{rcsFile};
83
84 my ( $rcsOutput, $exit ) =
85 Foswiki::Sandbox->sysCommand( $Foswiki::cfg{RCS}{initTextCmd},
86 FILENAME => $this->{file} );
87 if ($exit) {
88 $rcsOutput ||= '';
89 throw Error::Simple( $Foswiki::cfg{RCS}{initTextCmd} . ' of '
90 . $this->hidePath( $this->{file} )
91 . ' failed: '
92 . $rcsOutput );
93 }
94 elsif ( !-e $this->{rcsFile} ) {
95
96 # Sometimes (on Windows?) rcs file not formed, so check for it
97 throw Error::Simple( $Foswiki::cfg{RCS}{initTextCmd} . ' of '
98 . $this->hidePath( $this->{rcsFile} )
99 . ' failed to create history file' );
100 }
101}
102
103# implements VC::Handler
104
105# Designed for calling *only* from the Handler superclass and this class
106sub ci {
107 my ( $this, $isStream, $data, $comment, $user, $date ) = @_;
108
109 _lock($this);
110 if ($isStream) {
111 $this->saveStream($data);
112 }
113 else {
114 $this->saveFile( $this->{file}, $data );
115 }
116
117 $comment = 'none' unless $comment;
118
119 my ( $cmd, $rcsOutput, $exit );
120 if ( defined($date) ) {
121 require Foswiki::Time;
122 $date = Foswiki::Time::formatTime( $date, '$rcs', 'gmtime' );
123 $cmd = $Foswiki::cfg{RCS}{ciDateCmd};
124 ( $rcsOutput, $exit ) = Foswiki::Sandbox->sysCommand(
125 $cmd,
126 USERNAME => $user,
127 FILENAME => $this->{file},
128 COMMENT => $comment,
129 DATE => $date
130 );
131 }
132 else {
133 $cmd = $Foswiki::cfg{RCS}{ciCmd};
134 ( $rcsOutput, $exit ) = Foswiki::Sandbox->sysCommand(
135 $cmd,
136 USERNAME => $user,
137 FILENAME => $this->{file},
138 COMMENT => $comment
139 );
140 }
141 $rcsOutput ||= '';
142
143 if ($exit) {
144 throw Error::Simple( $cmd . ' of '
145 . $this->hidePath( $this->{file} )
146 . ' failed: '
147 . $exit . ' '
148 . $rcsOutput );
149 }
150
151 chmod( $Foswiki::cfg{RCS}{filePermission}, $this->{file} );
152}
153
154# implements VC::Handler
155sub repRev {
156 my ( $this, $text, $comment, $user, $date ) = @_;
157
158 my $rev = $this->_numRevisions() || 0;
159
160 $comment ||= 'none';
161
162 # update repository with same userName and date
163 if ( $rev <= 1 ) {
164
165 # initial revision, so delete repository file and start again
166 unlink $this->{rcsFile};
167 }
168 else {
169 _deleteRevision( $this, $rev );
170 }
171
172 Foswiki::Store::VC::Handler::saveFile( $this, $this->{file}, $text );
173 require Foswiki::Time;
174 $date = Foswiki::Time::formatTime( $date, '$rcs', 'gmtime' );
175
176 _lock($this);
177 my ( $rcsOut, $exit ) = Foswiki::Sandbox->sysCommand(
178 $Foswiki::cfg{RCS}{ciDateCmd},
179 DATE => $date,
180 USERNAME => $user,
181 FILENAME => $this->{file},
182 COMMENT => $comment
183 );
184 if ($exit) {
185 $rcsOut = $Foswiki::cfg{RCS}{ciDateCmd} . "\n" . $rcsOut;
186 return $rcsOut;
187 }
188 chmod( $Foswiki::cfg{RCS}{filePermission}, $this->{file} );
189}
190
191# implements VC::Handler
192sub deleteRevision {
193 my ($this) = @_;
194 my $rev = $this->_numRevisions();
195 return if ( $rev <= 1 );
196 return _deleteRevision( $this, $rev );
197}
198
199sub _deleteRevision {
200 my ( $this, $rev ) = @_;
201
202 # delete latest revision (unlock (may not be needed), delete revision)
203 my ( $rcsOut, $exit ) =
204 Foswiki::Sandbox->sysCommand( $Foswiki::cfg{RCS}{unlockCmd},
205 FILENAME => $this->{file} );
206
207 chmod( $Foswiki::cfg{RCS}{filePermission}, $this->{file} );
208
209 ( $rcsOut, $exit ) = Foswiki::Sandbox->sysCommand(
210 $Foswiki::cfg{RCS}{delRevCmd},
211 REVISION => '1.' . $rev,
212 FILENAME => $this->{file}
213 );
214
215 if ($exit) {
216 throw Error::Simple( $Foswiki::cfg{RCS}{delRevCmd} . ' of '
217 . $this->hidePath( $this->{file} )
218 . ' failed: '
219 . $rcsOut );
220 }
221
222 # Update the checkout
223 $rev--;
224 ( $rcsOut, $exit ) = Foswiki::Sandbox->sysCommand(
225 $Foswiki::cfg{RCS}{coCmd},
226 REVISION => '1.' . $rev,
227 FILENAME => $this->{file}
228 );
229
230 if ($exit) {
231 throw Error::Simple( $Foswiki::cfg{RCS}{coCmd} . ' of '
232 . $this->hidePath( $this->{file} )
233 . ' failed: '
234 . $rcsOut );
235 }
236 Foswiki::Store::VC::Handler::saveFile( $this, $this->{file}, $rcsOut );
237}
238
239# implements VC::Handler
240
# spent 48.0ms (4.30+43.7) within Foswiki::Store::VC::RcsWrapHandler::getRevision which was called 426 times, avg 113µs/call: # 426 times (4.30ms+43.7ms) by Foswiki::Store::VC::Store::readTopic at line 90 of /var/www/foswiki11/lib/Foswiki/Store/VC/Store.pm, avg 113µs/call
sub getRevision {
241426269µs my ( $this, $version ) = @_;
242
24342613.9ms42643.7ms unless ( $version && -e $this->{rcsFile} ) {
# spent 43.7ms making 426 calls to Foswiki::Store::VC::Handler::getRevision, avg 103µs/call
244
245 # Get the latest rev from the cache
246 return ( $this->SUPER::getRevision($version) );
247 }
248
249 # We've been asked for an explicit rev. The rev might be outside the
250 # range of revs in RCS. RCS will return the latest, though it reports
251 # the rev retrieved to STDERR (no use to us, as we have no access
252 # to STDERR)
253
254 # SMELL: we need to determine if the rev we are returning is the latest.
255 # co prints the retrieved revision, but unfortunately it prints it
256 # to STDERR, which the Sandbox can't retrieve.
257
258 my $tmpfile;
259 my $tmpRevFile;
260 my $coCmd = $Foswiki::cfg{RCS}{coCmd};
261 my $file = $this->{file};
262 if ( $Foswiki::cfg{RCS}{coMustCopy} ) {
263
264 # Need to take temporary copy of topic, check it out to file,
265 # then read that. Need to put RCS into binary mode to avoid
266 # extra \r appearing and read from binmode file rather than
267 # stdout to avoid early file read termination
268 # See http://twiki.org/cgi-bin/view/Codev/DakarRcsWrapProblem
269 # for evidence that this code is needed.
270 $tmpfile = Foswiki::Store::VC::Handler::mkTmpFilename($this);
271 $tmpRevFile = $tmpfile . ',v';
272 require File::Copy;
273 File::Copy::copy( $this->{rcsFile}, $tmpRevFile );
274 my ( $tmp, $status ) =
275 Foswiki::Sandbox->sysCommand( $Foswiki::cfg{RCS}{tmpBinaryCmd},
276 FILENAME => $tmpRevFile );
277 $file = $tmpfile;
278 $coCmd =~ s/-p%REVISION/-r%REVISION/;
279 }
280 my ( $text, $status, $stderr ) = Foswiki::Sandbox->sysCommand(
281 $coCmd,
282 REVISION => '1.' . $version,
283 FILENAME => $file
284 );
285
286 # The loaded version is reported on STDERR
287 my $isLatest = 0;
288 if ( defined $stderr
289 && $stderr =~ /revision 1\.(\d+)/s )
290 {
291 $isLatest = ( $version >= $1 );
292 }
293
294 # otherwise we will have to resort to numRevisions to tell if
295 # this is the latest rev, which is expensive. By returning false
296 # for isLatest we will force a reload upstairs if the latest rev
297 # is required.
298
299 if ($tmpfile) {
300 $text = Foswiki::Store::VC::Handler::readFile( $this, $tmpfile );
301 for ( $tmpfile, $tmpRevFile ) {
302 my $f = Foswiki::Sandbox::untaintUnchecked($_);
303 unlink $f or warn "Could not delete $f: $!";
304 }
305 }
306
307 return ( $text, $isLatest );
308}
309
310# implements VC::Handler
311
# spent 10.1s (2.47ms+10.1) within Foswiki::Store::VC::RcsWrapHandler::getInfo which was called 22 times, avg 459ms/call: # 22 times (2.47ms+10.1s) by Foswiki::Store::VC::Store::readTopic at line 100 of /var/www/foswiki11/lib/Foswiki/Store/VC/Store.pm, avg 459ms/call
sub getInfo {
3122225µs my ( $this, $version ) = @_;
313
3142259µs22276µs if ( ( $this->noCheckinPending() )
# spent 276µs making 22 calls to Foswiki::Store::VC::Handler::noCheckinPending, avg 13µs/call
315 && ( !$version || $version > $this->_numRevisions() ) )
316 {
317 $version = $this->_numRevisions();
318 }
319 else {
32022146µs222.59s $version = $this->_numRevisions() + 1
# spent 2.59s making 22 calls to Foswiki::Store::VC::RcsWrapHandler::_numRevisions, avg 118ms/call
321 unless ( $version && $version <= $this->_numRevisions() );
322 }
32322527µs225.00s my ( $rcsOut, $exit ) = Foswiki::Sandbox->sysCommand(
# spent 5.00s making 22 calls to Foswiki::Sandbox::sysCommand, avg 227ms/call
324 $Foswiki::cfg{RCS}{infoCmd},
325 REVISION => '1.' . $version,
326 FILENAME => $this->{rcsFile}
327 );
3282236µs if ( !$exit ) {
3291065µs if ( $rcsOut =~
330 /^.*?date: ([^;]+); author: ([^;]*);[^\n]*\n([^\n]*)\n/s )
331 {
332 require Foswiki::Time;
333 my $info = {
334 version => $version,
335 date => Foswiki::Time::parseTime($1),
336 author => $2,
337 comment => $3,
338 };
339 if ( $rcsOut =~ /revision 1.([0-9]*)/ ) {
340 $info->{version} = $1;
341 }
342 return $info;
343 }
344 }
345
346221.12ms222.49s return $this->SUPER::getInfo($version);
# spent 2.49s making 22 calls to Foswiki::Store::VC::Handler::getInfo, avg 113ms/call
347}
348
349# implements VC::Handler
350
# spent 5.47s (1.93ms+5.47) within Foswiki::Store::VC::RcsWrapHandler::_numRevisions which was called 35 times, avg 156ms/call: # 22 times (853µs+2.59s) by Foswiki::Store::VC::RcsWrapHandler::getInfo at line 320, avg 118ms/call # 10 times (956µs+2.48s) by Foswiki::Store::VC::Handler::getInfo at line 242 of /var/www/foswiki11/lib/Foswiki/Store/VC/Handler.pm, avg 248ms/call # 3 times (120µs+394ms) by Foswiki::Store::VC::Handler::getLatestRevisionID at line 449 of /var/www/foswiki11/lib/Foswiki/Store/VC/Handler.pm, avg 131ms/call
sub _numRevisions {
3513541µs my $this = shift;
352
35335152µs unless ( -e $this->{rcsFile} ) {
354
355 # If there is no history, there can only be one.
35613127µs return 1 if -e $this->{file};
357 return 0;
358 }
359
36022396µs225.47s my ( $rcsOutput, $exit ) =
# spent 5.47s making 22 calls to Foswiki::Sandbox::sysCommand, avg 249ms/call
361 Foswiki::Sandbox->sysCommand( $Foswiki::cfg{RCS}{histCmd},
362 FILENAME => $this->{rcsFile} );
3632213µs if ($exit) {
364 throw Error::Simple( 'RCS: '
365 . $Foswiki::cfg{RCS}{histCmd} . ' of '
366 . $this->hidePath( $this->{rcsFile} )
367 . ' failed: '
368 . $rcsOutput );
369 }
370221.03ms if ( $rcsOutput =~ /head:\s+\d+\.(\d+)\n/ ) {
371 return $1;
372 }
373 if ( $rcsOutput =~ /total revisions: (\d+)\n/ ) {
374 return $1;
375 }
376 return 1;
377}
378
379# implements VC::Handler
380# rev1 is the lower, rev2 is the higher revision
381sub revisionDiff {
382 my ( $this, $rev1, $rev2, $contextLines ) = @_;
383 my $tmp = '';
384 my $exit;
385 if ( $rev1 eq '1' && $rev2 eq '1' ) {
386 my $text = $this->getRevision(1);
387 $tmp = "1a1\n";
388 foreach ( split( /\r?\n/, $text ) ) {
389 $tmp = "$tmp> $_\n";
390 }
391 }
392 else {
393 $contextLines = 3 unless defined($contextLines);
394 ( $tmp, $exit ) = Foswiki::Sandbox->sysCommand(
395 $Foswiki::cfg{RCS}{diffCmd},
396 REVISION1 => '1.' . $rev1,
397 REVISION2 => '1.' . $rev2,
398 FILENAME => $this->{rcsFile},
399 CONTEXT => $contextLines
400 );
401
402 # comment out because we get a non-zero status for a good result!
403 #if( $exit ) {
404 # throw Error::Simple( 'RCS: '.$Foswiki::cfg{RCS}{diffCmd}.
405 # ' failed: '.$! );
406 #}
407 }
408
409 return parseRevisionDiff($tmp);
410}
411
412=begin TML
413
414---++ StaticMethod parseRevisionDiff( $text ) -> \@diffArray
415
416| Description: | parse the text into an array of diff cells |
417| #Description: | unlike Algorithm::Diff I concatinate lines of the same diffType that are sqential (this might be something that should be left up to the renderer) |
418| Parameter: =$text= | currently unified or rcsdiff format |
419| Return: =\@diffArray= | reference to an array of [ diffType, $right, $left ] |
420| TODO: | move into VC::Handler and add indirection in Store |
421
422=cut
423
424sub parseRevisionDiff {
425 my ($text) = @_;
426
427 my ($diffFormat) = 'normal'; #or rcs, unified...
428 my (@diffArray) = ();
429
430 $diffFormat = 'unified' if ( $text =~ /^---/s );
431
432 $text =~ s/\r//go; # cut CR
433
434 my $lineNumber = 1;
435 if ( $diffFormat eq 'unified' ) {
436 foreach ( split( /\r?\n/, $text ) ) {
437 if ( $lineNumber > 2 ) { #skip the first 2 lines (filenames)
438 if (/@@ [-+]([0-9]+)([,0-9]+)? [-+]([0-9]+)(,[0-9]+)? @@/) {
439
440 #line number
441 push @diffArray, [ 'l', $1, $3 ];
442 }
443 elsif (/^\-(.*)$/) {
444 push @diffArray, [ '-', $1, '' ];
445 }
446 elsif (/^\+(.*)$/) {
447 push @diffArray, [ '+', '', $1 ];
448 }
449 else {
450 s/^ (.*)$/$1/go;
451 push @diffArray, [ 'u', $_, $_ ];
452 }
453 }
454 $lineNumber++;
455 }
456 }
457 else {
458
459 #'normal' rcsdiff output
460 foreach ( split( /\r?\n/, $text ) ) {
461 if (/^([0-9]+)[0-9\,]*([acd])([0-9]+)/) {
462
463 #line number
464 push @diffArray, [ 'l', $1, $3 ];
465 }
466 elsif (/^< (.*)$/) {
467 push @diffArray, [ '-', $1, '' ];
468 }
469 elsif (/^> (.*)$/) {
470 push @diffArray, [ '+', '', $1 ];
471 }
472 else {
473
474 #push @diffArray, ['u', '', ''];
475 }
476 }
477 }
478 return \@diffArray;
479}
480
481sub _lock {
482 my $this = shift;
483
484 return unless -e $this->{rcsFile};
485
486 # Try and get a lock on the file
487 my ( $rcsOutput, $exit ) =
488 Foswiki::Sandbox->sysCommand( $Foswiki::cfg{RCS}{lockCmd},
489 FILENAME => $this->{file} );
490
491 if ($exit) {
492
493 # if the lock has been set more than 24h ago, let's try to break it
494 # and then retry. Should not happen unless in Cairo upgrade
495 # scenarios - see Item2102
496 if ( ( time - ( stat( $this->{rcsFile} ) )[9] ) > 3600 ) {
497 warn 'Automatic recovery: breaking lock for ' . $this->{file};
498 Foswiki::Sandbox->sysCommand( $Foswiki::cfg{RCS}{breaklockCmd},
499 FILENAME => $this->{file} );
500 ( $rcsOutput, $exit ) =
501 Foswiki::Sandbox->sysCommand( $Foswiki::cfg{RCS}{lockCmd},
502 FILENAME => $this->{file} );
503 }
504 if ($exit) {
505
506 # still no luck - bailing out
507 $rcsOutput ||= '';
508 throw Error::Simple( 'RCS: '
509 . $Foswiki::cfg{RCS}{lockCmd}
510 . ' failed: '
511 . $rcsOutput );
512 }
513 }
514 chmod( $Foswiki::cfg{RCS}{filePermission}, $this->{file} );
515}
516
517# implements VC::Handler
518sub getRevisionAtTime {
519 my ( $this, $date ) = @_;
520
521 unless ( -e $this->{rcsFile} ) {
522 return ( $date >= ( stat( $this->{file} ) )[9] ) ? 1 : undef;
523 }
524
525 require Foswiki::Time;
526 my $sdate = Foswiki::Time::formatTime( $date, '$rcs', 'gmtime' );
527 my ( $rcsOutput, $exit ) = Foswiki::Sandbox->sysCommand(
528 $Foswiki::cfg{RCS}{rlogDateCmd},
529 DATE => $sdate,
530 FILENAME => $this->{file}
531 );
532
533 my $version = undef;
534 if ( $rcsOutput =~ m/revision \d+\.(\d+)/ ) {
535 $version = $1;
536 }
537
538 if ( $version && !$this->noCheckinPending() ) {
539
540 # Check the file date
541 $version++ if ( $date >= ( stat( $this->{file} ) )[9] );
542 }
543 return $version;
544}
545
54613µs1;
547__END__