package CGI::Kwiki::Backup::Rcs; $VERSION = '0.18'; use strict; use base 'CGI::Kwiki::Backup'; use File::Spec; use constant RCS_DIR => 'metabase/rcs'; sub file_path { my ($self, $page_id) = @_; RCS_DIR . '/' . $self->escape($page_id) . ',v'; } my $user_name = ''; sub new { my ($class) = shift; my $self = $class->SUPER::new(@_); unless (-d RCS_DIR) { mkdir RCS_DIR; umask 0000; chmod 0777, RCS_DIR; $user_name = 'kwiki-install'; for my $page_id ($self->database->pages) { $self->commit($page_id); } } return $self; } sub commit { my ($self, $page_id) = @_; my $rcs_file_path = $self->file_path($page_id); if (not -f $rcs_file_path) { $self->shell("rcs -q -i $rcs_file_path < /dev/null"); } my $msg = $self->escape($user_name || $self->metadata->edit_by); my $page_file_path = $self->database->file_path($page_id); $self->shell(qq{ci -q -l -m"$msg" $page_file_path $rcs_file_path}); } sub has_history { my ($self, $page_id) = @_; $page_id ||= $self->cgi->page_id; -f $self->file_path($page_id); } sub history { my ($self, $page_id) = @_; $page_id ||= $self->cgi->page_id; my $rcs_file_path = $self->file_path($page_id); open RLOG, "rlog -zLT $rcs_file_path |" or DIE $!; binmode(RLOG, ':utf8') if $self->use_utf8; local $/; my $input = ; close RLOG; (my $rlog = $input) =~ s/\n=+$.*\Z//ms; my @rlog = split /^-+\n/m, $rlog; shift(@rlog); my $history = []; for (@rlog) { /^revision\s+(\S+).*? ^date:\s+(.+?);.*?\n (.*) /xms or die "Couldn't parse rlog for '$page_id':\n$rlog"; push @$history, { revision => $1, file_rev => $1, date => $2, edit_by => $self->unescape($3), }; } return $history; } sub file_rev { my ($self, $page_id, $revision) = @_; return $revision; } sub fetch { my ($self, $page_id, $revision) = @_; my $rcs_file_path = $self->file_path($page_id); local($/, *CO); open CO, qq{co -q -p$revision $rcs_file_path |} or die $!; binmode(CO, ':utf8') if $self->use_utf8; ; } sub diff { my ($self, $page_id, $r1, $r2, $context) = @_; $context ||= 1000000; my $rcs_file_path = $self->file_path($page_id); local(*RCSDIFF); open RCSDIFF, qq{rcsdiff -q -r$r1 -r$r2 --unified=$context $rcs_file_path |} or die "rcsdiff failed:\n$!"; binmode(RCSDIFF, ':utf8') if $self->use_utf8; my $line1 = ; my $line2 = ; $line2 =~ s/\+/%2B/g; # counter ->unescape local $/; return($self->unescape($line1) . $self->unescape($line2) . ); } sub shell { my ($self, $command) = @_; use Cwd; $! = undef; system($command) == 0 or die "$command failed:\n$?\nin " . Cwd::cwd(); } 1;