package Rcs; use strict; # Wrapper around the RCS commands required by TWiki my $OS = 'WINDOWS'; my $rcsDir = "/apps/rcs/bin/"; # Initialise RCS file, ignored if empty string, # needed on Windows for binary files. Added JET 22-Feb-01 my $rcsArg = ""; my $rcsArg = "-x,v" if( $OS eq "WINDOWS" ); # null device /dev/null for unix, NUL for windows my $nullDev = { UNIX=>'/dev/null', OS2=>'', WINDOWS=>'NUL', DOS=>'NUL', MACINTOSH=>'', VMS=>'' }->{$OS}; # Store RCS history files in directory (RCS under content dir), default "0" # Don't change this in a working installation, only change when initially setting up a TWiki installation # You also need to create an RCS directory for each Web. TWiki will create RCS directories under pub for attachments historys. my $useRcsDir = "0"; # Command quote ' for unix, \" for Windows my $cmdQuote = "'"; my $cmdQuote = "\"" if( $OS eq "WINDOWS" ); # RCS init command, needed when initialising a file as binary my $revInitBinaryCmd = "$rcsDir/rcs $rcsArg -q -i -t-none -kb %FILENAME%"; # RCS check in command : my $revCiCmd = "$rcsDir/ci $rcsArg -q -l -m$cmdQuote%COMMENT%$cmdQuote -t-none -w$cmdQuote%USERNAME%$cmdQuote %FILENAME%"; #FIXME more entries need %COMMENT% # RCS check in command with date : my $revCiDateCmd = "$rcsDir/ci -l $rcsArg -q -mnone -t-none -d$cmdQuote%DATE%$cmdQuote -w$cmdQuote%USERNAME%$cmdQuote %FILENAME%"; # RCS check out command : my $revCoCmd = "$rcsDir/co $rcsArg -q -p%REVISION% %FILENAME%"; # RCS history command : my $revHistCmd = "$rcsDir/rlog $rcsArg -h %FILENAME%"; # RCS history on revision command : my $revInfoCmd = "$rcsDir/rlog $rcsArg -r%REVISION% %FILENAME%"; # RCS revision diff command : my $revDiffCmd = "$rcsDir/rcsdiff $rcsArg -q -w -B -r%REVISION1% -r%REVISION2% %FILENAME%"; # RCS delete revision command : my $revDelRevCmd = "$rcsDir/rcs $rcsArg -q -o%REVISION% %FILENAME%"; # RCS unlock command : my $revUnlockCmd = "$rcsDir/rcs $rcsArg -q -u %FILENAME%"; # RCS lock command : my $revLockCmd = "$rcsDir/rcs $rcsArg -q -l %FILENAME%"; # RCS for breaking a lock my $revBreakLockCmd = "$rcsDir/rcs $rcsArg -q -l -M %FILENAME%"; sub new { my( $file ) = @_; my $self = {}; bless $self; $self->{"file"} = $file; return $self; # TODO: make sure we get a sensible error if TZ not set on Windows } sub _trace { my( $text ) = @_; #print $text; } sub _traceExec { my( $cmd, $string ) = @_; print "Rcs: $cmd $string\n"; } sub _error { my( $txt ) = @_; print "\nRcs: **** Error $txt\n\n"; } sub file { my( $self ) = @_; return $self->{"file"}; } sub saveFile { my( $name, $$text ) = @_; umask( 002 ); open( FILE, ">$name" ) or warn "Can't create file $name\n"; print FILE $$text; close( FILE); } sub addRevision { my( $self, $text, $comment, $userName ) = @_; # Replace file (if exists) with text saveFile( $self->file(), $text ); _ci( $self->file(), $comment, $userName ); } sub _ci { my( $file, $comment, $userName ) = @_; my $tmp = $revCiCmd; my $rcsError = ""; $tmp =~ s/%USERNAME%/$userName/; $tmp =~ s/%FILENAME%/$file/; $tmp =~ s/%COMMENT%/$comment/; $tmp =~ /(.*)/; $tmp = $1; # safe, so untaint variable $tmp .= " 2>&1 1>$nullDev"; $rcsError = `$tmp`; # capture stderr (S.Knutson) _traceExec( $tmp, $rcsError ); $rcsError =~ s/^Warning\: missing newline.*//os; # forget warning if( $rcsError =~ /no lock set by/ ) { # Try and break lock, setting new one and doing ci again my $cmd = $revBreakLockCmd; $cmd =~ s/%FILENAME%/$file/go; $cmd =~ /(.*)/; $cmd = "$1 2>&1 1>$nullDev"; my $out = `$cmd`; _traceExec( $cmd, $out ); # Assume it worked, as not sure how to trap failure $tmp= $revCiCmd; $rcsError = `$tmp`; # capture stderr (S.Knutson) _traceExec( $tmp, $rcsError ); $rcsError = ""; } if( $rcsError ) { # oops, stderr was not empty, return error $rcsError = "$tmp\n$rcsError"; } _error( $rcsError ) if ( $rcsError ); return $rcsError; }