1package CGI::Kwiki::Backup::SVNPerl; 2$VERSION = '0.01'; 3 4use strict; 5use base 'CGI::Kwiki::Backup::SVN'; 6use File::Spec; 7use SVN::Core '0.28'; 8use SVN::Repos; 9use SVN::Fs; 10use SVN::Delta; 11use SVN::Simple::Edit; 12use Text::Diff (); 13 14use constant SVN_DIR => 'metabase/svn'; 15 16my $user_name = ''; 17 18my ($repos, $fs, $pool, $init); 19 20sub init { 21 my $self = shift; 22 $pool = SVN::Pool->new_default; 23 if (-d SVN_DIR) { 24 $repos = SVN::Repos::open (SVN_DIR); 25 } 26 else { 27 $repos = SVN::Repos::create(SVN_DIR, undef, undef, 28 undef, undef); 29 my $edit = $self->_get_edit ('kwiki-install', 'kwiki install'); 30 31 $edit->open_root (0); 32 33 for my $page_id ($self->database->pages) { 34 $edit->add_file ($page_id); 35 open my $fh, $self->database->file_path($page_id); 36 $edit->modify_file ($page_id, $fh) 37 } 38 $edit->close_edit; 39 } 40 $fs = $repos->fs; 41 ++$init; 42} 43 44sub new { 45 my ($class) = shift; 46 my $self = $class->SUPER::new(@_); 47 $self->init unless $init; 48 $self->{pool} = SVN::Pool->new_default_sub(); 49 50 $self->{headrev} = $fs->youngest_rev; 51 52 return $self; 53} 54 55sub _get_edit { 56 my ($self, $author, $comment, $pool) = @_; 57 SVN::Simple::Edit->new (_editor => [SVN::Repos::get_commit_editor 58 ($repos, '', '/', $author, 59 $comment, sub {})], 60 pool => $pool || SVN::Pool->new ($pool)); 61 62} 63 64sub commit { 65 my ($self, $page_id) = @_; 66 my $edit = $self->_get_edit ($user_name || $self->metadata->edit_by, '', 67 $self->{pool}); 68 $edit->open_root ($self->{headrev}); 69 if ($self->database->exists ($page_id)) { 70 open my $fh, $self->database->file_path ($page_id); 71 $edit->modify_file ($self->has_history ($page_id) ? 72 $edit->open_file ($page_id) : 73 $edit->add_file ($page_id), 74 $fh); 75 } 76 else { 77 $edit->delete_entry ($page_id); 78 } 79 80 $edit->close_edit(); 81} 82 83sub has_history { 84 my ($self, $page_id) = @_; 85 $page_id ||= $self->cgi->page_id; 86 my $root = $fs->revision_root($self->{headrev}); 87 88 SVN::Fs::check_path($root, $page_id) == $SVN::Core::node_file; 89} 90 91sub history { 92 my ($self, $page_id) = @_; 93 $page_id ||= $self->cgi->page_id; 94 return [] unless $page_id; 95 96 my $revs = SVN::Repos::revisions_changed ($fs, $page_id, 0, 97 $self->{headrev}, 0); 98 99 my $history = [map { 100 { revision => $_, 101 edit_by => $fs->revision_prop($_, 'svn:author'), 102 date => $fs->revision_prop($_, 'svn:date')}} @$revs]; 103 104 return $self->_build_history($history); 105} 106 107sub fetch { 108 my ($self, $page_id, $revision) = @_; 109 my $root = $fs->revision_root($revision || $self->{headrev}); 110 111 my $stream = SVN::Fs::file_contents($root, $page_id); 112 local $/; 113 return <$stream>; 114} 115 116sub diff { 117 my ($self, $page_id, $r1, $r2, $context) = @_; 118 119 my $root1 = $fs->revision_root ($r1); 120 my $root2 = $fs->revision_root ($r2); 121 122 Text::Diff::diff(SVN::Fs::file_contents($root1, $page_id), 123 SVN::Fs::file_contents($root2, $page_id), 124 { STYLE => "Unified" }); 125} 126 1271; 128