unless exists $config{wikistatedir};
if ($config{rcs}) {
- eval qq{use IkiWiki::Rcs::$config{rcs}};
- if ($@) {
- error("Failed to load RCS module IkiWiki::Rcs::$config{rcs}: $@");
- }
+ loadplugin($config{rcs});
}
else {
- require IkiWiki::Rcs::Stub;
+ loadplugin("norcs");
}
if (defined $config{umask}) {
return 1;
} #}}}
+sub rcs_update () { #{{{
+ $hooks{rcs}{rcs_update}{call}->(@_);
+} #}}}
+
+sub rcs_prepedit ($) { #{{{
+ $hooks{rcs}{rcs_prepedit}{call}->(@_);
+} #}}}
+
+sub rcs_commit ($$$;$$) { #{{{
+ $hooks{rcs}{rcs_commit}{call}->(@_);
+} #}}}
+
+sub rcs_commit_staged ($$$) { #{{{
+ $hooks{rcs}{rcs_commit_staged}{call}->(@_);
+} #}}}
+
+sub rcs_add ($) { #{{{
+ $hooks{rcs}{rcs_add}{call}->(@_);
+} #}}}
+
+sub rcs_remove ($) { #{{{
+ $hooks{rcs}{rcs_remove}{call}->(@_);
+} #}}}
+
+sub rcs_rename ($$) { #{{{
+ $hooks{rcs}{rcs_rename}{call}->(@_);
+} #}}}
+
+sub rcs_recentchanges ($) { #{{{
+ $hooks{rcs}{rcs_recentchanges}{call}->(@_);
+} #}}}
+
+sub rcs_diff ($) { #{{{
+ $hooks{rcs}{rcs_diff}{call}->(@_);
+} #}}}
+
+sub rcs_getctime ($) { #{{{
+ $hooks{rcs}{rcs_getctime}{call}->(@_);
+} #}}}
+
sub globlist_to_pagespec ($) { #{{{
my @globlist=split(' ', shift);
#!/usr/bin/perl
-
-package IkiWiki;
+package IkiWiki::Plugin::bzr;
use warnings;
use strict;
use Encode;
use open qw{:utf8 :std};
-hook(type => "checkconfig", id => "bzr", call => sub { #{{{
+sub import { #{{{
+ hook(type => "checkconfig", id => "bzr", call => \&checkconfig);
+ hook(type => "getsetup", id => "bzr", call => \&getsetup);
+ hook(type => "rcs", id => "rcs_update", call => \&rcs_update);
+ hook(type => "rcs", id => "rcs_prepedit", call => \&rcs_prepedit);
+ hook(type => "rcs", id => "rcs_commit", call => \&rcs_commit);
+ hook(type => "rcs", id => "rcs_commit_staged", call => \&rcs_commit_staged);
+ hook(type => "rcs", id => "rcs_add", call => \&rcs_add);
+ hook(type => "rcs", id => "rcs_remove", call => \&rcs_remove);
+ hook(type => "rcs", id => "rcs_rename", call => \&rcs_rename);
+ hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
+ hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
+ hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
+} #}}}
+
+sub checkconfig () { #{{{
if (! defined $config{diffurl}) {
$config{diffurl}="";
}
- if (length $config{bzr_wrapper}) {
+ if (defined $config{bzr_wrapper} && length $config{bzr_wrapper}) {
push @{$config{wrappers}}, {
wrapper => $config{bzr_wrapper},
wrappermode => (defined $config{bzr_wrappermode} ? $config{bzr_wrappermode} : "06755"),
};
}
-}); #}}}
+} #}}}
-hook(type => "getsetup", id => "bzr", call => sub { #{{{
+sub getsetup () { #{{{
return
bzr_wrapper => {
type => "string",
safe => 1,
rebuild => 1,
},
-}); #}}}
+} #}}}
sub bzr_log ($) { #{{{
my $out = shift;
my ($user, $ipaddr) = @_;
if (defined $user) {
- return possibly_foolish_untaint($user);
+ return IkiWiki::possibly_foolish_untaint($user);
}
elsif (defined $ipaddr) {
- return "Anonymous from ".possibly_foolish_untaint($ipaddr);
+ return "Anonymous from ".IkiWiki::possibly_foolish_untaint($ipaddr);
}
else {
return "Anonymous";
$user = bzr_author($user, $ipaddr);
- $message = possibly_foolish_untaint($message);
+ $message = IkiWiki::possibly_foolish_untaint($message);
if (! length $message) {
$message = "no message given";
}
$user = bzr_author($user, $ipaddr);
- $message = possibly_foolish_untaint($message);
+ $message = IkiWiki::possibly_foolish_untaint($message);
if (! length $message) {
$message = "no message given";
}
sub rcs_rename ($$) { # {{{
my ($src, $dest) = @_;
- my $parent = dirname($dest);
+ my $parent = IkiWiki::dirname($dest);
if (system("bzr", "add", "--quiet", "$config{srcdir}/$parent") != 0) {
warn("bzr add $parent failed\n");
}
#!/usr/bin/perl
-
-package IkiWiki;
+package IkiWiki::Plugin::git;
use warnings;
use strict;
my $sha1_pattern = qr/[0-9a-fA-F]{40}/; # pattern to validate Git sha1sums
my $dummy_commit_msg = 'dummy commit'; # message to skip in recent changes
-hook(type => "checkconfig", id => "git", call => sub { #{{{
+sub import { #{{{
+ hook(type => "checkconfig", id => "git", call => \&checkconfig);
+ hook(type => "getsetup", id => "git", call => \&getsetup);
+ hook(type => "rcs", id => "rcs_update", call => \&rcs_update);
+ hook(type => "rcs", id => "rcs_prepedit", call => \&rcs_prepedit);
+ hook(type => "rcs", id => "rcs_commit", call => \&rcs_commit);
+ hook(type => "rcs", id => "rcs_commit_staged", call => \&rcs_commit_staged);
+ hook(type => "rcs", id => "rcs_add", call => \&rcs_add);
+ hook(type => "rcs", id => "rcs_remove", call => \&rcs_remove);
+ hook(type => "rcs", id => "rcs_rename", call => \&rcs_rename);
+ hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
+ hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
+ hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
+} #}}}
+
+sub checkconfig () { #{{{
if (! defined $config{diffurl}) {
$config{diffurl}="";
}
if (! defined $config{gitmaster_branch}) {
$config{gitmaster_branch}="master";
}
- if (length $config{git_wrapper}) {
+ if (defined $config{git_wrapper} && length $config{git_wrapper}) {
push @{$config{wrappers}}, {
wrapper => $config{git_wrapper},
wrappermode => (defined $config{git_wrappermode} ? $config{git_wrappermode} : "06755"),
};
}
-}); #}}}
+} #}}}
-hook(type => "getsetup", id => "git", call => sub { #{{{
+sub getsetup () { #{{{
return
git_wrapper => {
type => "string",
safe => 0, # paranoia
rebuild => 0,
},
-}); #}}}
+} #}}}
-sub _safe_git (&@) { #{{{
+sub safe_git (&@) { #{{{
# Start a child process safely without resorting /bin/sh.
# Return command output or success state (in scalar context).
return wantarray ? @lines : ($? == 0);
}
# Convenient wrappers.
-sub run_or_die ($@) { _safe_git(\&error, @_) }
-sub run_or_cry ($@) { _safe_git(sub { warn @_ }, @_) }
-sub run_or_non ($@) { _safe_git(undef, @_) }
+sub run_or_die ($@) { safe_git(\&error, @_) }
+sub run_or_cry ($@) { safe_git(sub { warn @_ }, @_) }
+sub run_or_non ($@) { safe_git(undef, @_) }
#}}}
-sub _merge_past ($$$) { #{{{
+sub merge_past ($$$) { #{{{
# Unlike with Subversion, Git cannot make a 'svn merge -rN:M file'.
# Git merge commands work with the committed changes, except in the
# implicit case of '-m' of git checkout(1). So we should invent a
return $conflict;
} #}}}
-sub _parse_diff_tree ($@) { #{{{
+sub parse_diff_tree ($@) { #{{{
# Parse the raw diff tree chunk and return the info hash.
# See git-diff-tree(1) for the syntax.
my ($prefix) = run_or_die('git', 'rev-parse', '--show-prefix');
my @ci;
- while (my $parsed = _parse_diff_tree(($prefix or ""), \@raw_lines)) {
+ while (my $parsed = parse_diff_tree(($prefix or ""), \@raw_lines)) {
push @ci, $parsed;
}
my ($prev) = $rcstoken =~ /^($sha1_pattern)$/; # untaint
if (defined $cur && defined $prev && $cur ne $prev) {
- my $conflict = _merge_past($prev, $file, $dummy_commit_msg);
+ my $conflict = merge_past($prev, $file, $dummy_commit_msg);
return $conflict if defined $conflict;
}
# git commit returns non-zero if file has not been really changed.
# so we should ignore its exit status (hence run_or_non).
- $message = possibly_foolish_untaint($message);
+ $message = IkiWiki::possibly_foolish_untaint($message);
if (run_or_non('git', 'commit', '--cleanup=verbatim',
'-q', '-m', $message)) {
if (length $config{gitorigin_branch}) {
#!/usr/bin/perl
-
-package IkiWiki;
+package IkiWiki::Plugin::mercurial;
use warnings;
use strict;
use Encode;
use open qw{:utf8 :std};
-hook(type => "checkconfig", id => "mercurial", call => sub { #{{{
+sub import { #{{{
+ hook(type => "checkconfig", id => "mercurial", call => \&checkconfig);
+ hook(type => "getsetup", id => "mercurial", call => \&getsetup);
+ hook(type => "rcs", id => "rcs_update", call => \&rcs_update);
+ hook(type => "rcs", id => "rcs_prepedit", call => \&rcs_prepedit);
+ hook(type => "rcs", id => "rcs_commit", call => \&rcs_commit);
+ hook(type => "rcs", id => "rcs_commit_staged", call => \&rcs_commit_staged);
+ hook(type => "rcs", id => "rcs_add", call => \&rcs_add);
+ hook(type => "rcs", id => "rcs_remove", call => \&rcs_remove);
+ hook(type => "rcs", id => "rcs_rename", call => \&rcs_rename);
+ hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
+ hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
+ hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
+} #}}}
+
+sub checkconfig () { #{{{
if (! defined $config{diffurl}) {
$config{diffurl}="";
}
- if (length $config{mercurial_wrapper}) {
+ if (exists $config{mercurial_wrapper} && length $config{mercurial_wrapper}) {
push @{$config{wrappers}}, {
wrapper => $config{mercurial_wrapper},
wrappermode => (defined $config{mercurial_wrappermode} ? $config{mercurial_wrappermode} : "06755"),
};
}
-}); #}}}
+} #}}}
-hook(type => "getsetup", id => "mercurial", call => sub { #{{{
+sub getsetup () { #{{{
return
mercurial_wrapper => {
type => "string",
safe => 1,
rebuild => 1,
},
-}); #}}}
+} #}}}
sub mercurial_log ($) { #{{{
my $out = shift;
my ($file, $message, $rcstoken, $user, $ipaddr) = @_;
if (defined $user) {
- $user = possibly_foolish_untaint($user);
+ $user = IkiWiki::possibly_foolish_untaint($user);
}
elsif (defined $ipaddr) {
- $user = "Anonymous from ".possibly_foolish_untaint($ipaddr);
+ $user = "Anonymous from ".IkiWiki::possibly_foolish_untaint($ipaddr);
}
else {
$user = "Anonymous";
}
- $message = possibly_foolish_untaint($message);
+ $message = IkiWiki::possibly_foolish_untaint($message);
if (! length $message) {
$message = "no message given";
}
#!/usr/bin/perl
-
-package IkiWiki;
+package IkiWiki::Plugin::monotone;
use warnings;
use strict;
my $sha1_pattern = qr/[0-9a-fA-F]{40}/; # pattern to validate sha1sums
-hook(type => "checkconfig", id => "monotone", call => sub { #{{{
+sub import { #{{{
+ hook(type => "checkconfig", id => "monotone", call => \&checkconfig);
+ hook(type => "getsetup", id => "monotone", call => \&getsetup);
+ hook(type => "rcs", id => "rcs_update", call => \&rcs_update);
+ hook(type => "rcs", id => "rcs_prepedit", call => \&rcs_prepedit);
+ hook(type => "rcs", id => "rcs_commit", call => \&rcs_commit);
+ hook(type => "rcs", id => "rcs_commit_staged", call => \&rcs_commit_staged);
+ hook(type => "rcs", id => "rcs_add", call => \&rcs_add);
+ hook(type => "rcs", id => "rcs_remove", call => \&rcs_remove);
+ hook(type => "rcs", id => "rcs_rename", call => \&rcs_rename);
+ hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
+ hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
+ hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
+} #}}}
+
+sub checkconfig () { #{{{
if (!defined($config{mtnrootdir})) {
$config{mtnrootdir} = $config{srcdir};
}
wrappermode => (defined $config{mtn_wrappermode} ? $config{mtn_wrappermode} : "06755"),
};
}
-}); #}}}
+} #}}}
-hook(type => "getsetup", id => "monotone", call => sub { #{{{
+sub getsetup () { #{{{
return
mtn_wrapper => {
type => "string",
safe => 0, # path
rebuild => 0,
},
-}); #}}}
+} #}}}
sub get_rev () { #{{{
my $sha1 = `mtn --root=$config{mtnrootdir} automate get_base_revision_id`;
return $mergeRev;
} #}}}
-sub commit_file_to_new_rev($$$$$$$$) { #{{{
+sub commit_file_to_new_rev ($$$$$$$$) { #{{{
my $automator=shift;
my $wsfilename=shift;
my $oldFileID=shift;
if (system("mtn", "--root=$config{mtnrootdir}", "commit", "--quiet",
"--author", $author, "--key", $config{mtnkey}, "-m",
- possibly_foolish_untaint($message), $file) != 0) {
+ IkiWiki::possibly_foolish_untaint($message), $file) != 0) {
debug("Traditional commit failed! Returning data as conflict.");
my $conflict=readfile("$config{srcdir}/$file");
if (system("mtn", "--root=$config{mtnrootdir}", "revert",
if (system("mtn", "--root=$config{mtnrootdir}", "commit", "--quiet",
"--author", $author, "--key", $config{mtnkey}, "-m",
- possibly_foolish_untaint($message)) != 0) {
+ IkiWiki::possibly_foolish_untaint($message)) != 0) {
error("Monotone commit failed");
}
}
#!/usr/bin/perl
# Stubs for no revision control.
-
-package IkiWiki;
+package IkiWiki::Plugin::norcs;
use warnings;
use strict;
use IkiWiki;
-sub rcs_update () {
- # Update working directory to current version.
- # (May be more complex for distributed RCS.)
-}
-
-sub rcs_prepedit ($) {
- # Prepares to edit a file under revision control. Returns a token
- # that must be passed into rcs_commit when the file is ready
- # for committing.
- # The file is relative to the srcdir.
+sub import { #{{{
+ hook(type => "rcs", id => "rcs_update", call => \&rcs_update);
+ hook(type => "rcs", id => "rcs_prepedit", call => \&rcs_prepedit);
+ hook(type => "rcs", id => "rcs_commit", call => \&rcs_commit);
+ hook(type => "rcs", id => "rcs_commit_staged", call => \&rcs_commit_staged);
+ hook(type => "rcs", id => "rcs_add", call => \&rcs_add);
+ hook(type => "rcs", id => "rcs_remove", call => \&rcs_remove);
+ hook(type => "rcs", id => "rcs_rename", call => \&rcs_rename);
+ hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
+ hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
+ hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
+} #}}}
+
+sub rcs_update () { #{{{
+} #}}}
+
+sub rcs_prepedit ($) { #{{{
return ""
-}
+} #}}}
-sub rcs_commit ($$$;$$) {
- # Tries to commit the page; returns undef on _success_ and
- # a version of the page with the rcs's conflict markers on failure.
- # The file is relative to the srcdir.
+sub rcs_commit ($$$;$$) { #{{{
my ($file, $message, $rcstoken, $user, $ipaddr) = @_;
return undef # success
-}
+} #}}}
-sub rcs_commit_staged ($$$) {
- # Commits all staged changes. Changes can be staged using rcs_add,
- # rcs_remove, and rcs_rename.
+sub rcs_commit_staged ($$$) { #{{{
my ($message, $user, $ipaddr)=@_;
return undef # success
-}
+} #}}}
-sub rcs_add ($) {
- # Add a file. The filename is relative to the root of the srcdir.
- # Note that this should not check the new file in, it should only
- # prepare for it to be checked in when rcs_commit is called.
- # Note that the file may be in a new subdir that is not yet added
- # to version control; the subdir can be added if so.
-}
+sub rcs_add ($) { #{{{
+} #}}}
-sub rcs_remove ($) {
- # Remove a file. The filename is relative to the root of the srcdir.
- # Note that this should not check the removal in, it should only
- # prepare for it to be checked in when rcs_commit is called.
- # Note that the new file may be in a new subdir that is not yet added
- # to version control; the subdir can be added if so.
-}
+sub rcs_remove ($) { #{{{
+} #}}}
-sub rcs_rename ($$) {
- # Rename a file. The filenames are relative to the root of the srcdir.
- # Note that this should not commit the rename, it should only
- # prepare it for when rcs_commit is called.
- # The new filename may be in a new subdir, that is not yet added to
- # version control. If so, the subdir will exist already, and should
- # be added to revision control.
-}
+sub rcs_rename ($$) { #{{{
+} #}}}
-sub rcs_recentchanges ($) {
- # Examine the RCS history and generate a list of recent changes.
- # The data structure returned for each change is:
- # {
- # rev => # the RCSs id for this commit
- # user => # name of user who made the change,
- # committype => # either "web" or the name of the rcs,
- # when => # time when the change was made,
- # message => [
- # { line => "commit message line" },
- # { line => "commit message line" },
- # # etc,
- # ],
- # pages => [
- # {
- # page => # name of page changed,
- # diffurl => # optional url to a diff showing
- # # the changes,
- # },
- # # repeat for each page changed in this commit,
- # ],
- # }
-}
+sub rcs_recentchanges ($) { #{{{
+} #}}}
-sub rcs_diff ($) {
- # Optional, used to get diffs for recentchanges.
- # The parameter is the rev from rcs_recentchanges.
- # Should return a list of lines of the diff (including \n) in list
- # context, and the whole diff in scalar context.
-}
+sub rcs_diff ($) { #{{{
+} #}}}
-sub rcs_getctime ($) {
- # Optional, used to get the page creation time from the RCS.
+sub rcs_getctime ($) { #{{{
error gettext("getctime not implemented");
-}
+} #}}}
1
#!/usr/bin/perl
-
-package IkiWiki;
+package IkiWiki::Plugin::svn;
use warnings;
use strict;
use IkiWiki;
use POSIX qw(setlocale LC_CTYPE);
-hook(type => "checkconfig", id => "svn", call => sub { #{{{
+sub import { #{{{
+ hook(type => "checkconfig", id => "svn", call => \&checkconfig);
+ hook(type => "getsetup", id => "svn", call => \&getsetup);
+ hook(type => "rcs", id => "rcs_update", call => \&rcs_update);
+ hook(type => "rcs", id => "rcs_prepedit", call => \&rcs_prepedit);
+ hook(type => "rcs", id => "rcs_commit", call => \&rcs_commit);
+ hook(type => "rcs", id => "rcs_commit_staged", call => \&rcs_commit_staged);
+ hook(type => "rcs", id => "rcs_add", call => \&rcs_add);
+ hook(type => "rcs", id => "rcs_remove", call => \&rcs_remove);
+ hook(type => "rcs", id => "rcs_rename", call => \&rcs_rename);
+ hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
+ hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
+ hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
+} #}}}
+
+sub checkconfig () { #{{{
if (! defined $config{diffurl}) {
$config{diffurl}="";
}
$config{svnpath}=~s/\/$//;
$config{svnpath}=~s/^\///;
}
- if (length $config{svn_wrapper}) {
+ if (defined $config{svn_wrapper} && length $config{svn_wrapper}) {
push @{$config{wrappers}}, {
wrapper => $config{svn_wrapper},
wrappermode => (defined $config{svn_wrappermode} ? $config{svn_wrappermode} : "04755"),
};
}
-}); #}}}
+} #}}}
-hook(type => "getsetup", id => "svn", call => sub { #{{{
+sub getsetup () { #{{{
return
svnrepo => {
type => "string",
safe => 1,
rebuild => 1,
},
-}); #}}}
+} #}}}
# svn needs LC_CTYPE set to a UTF-8 locale, so try to find one. Any will do.
sub find_lc_ctype() {
if (system("svn", "commit", "--quiet",
"--encoding", "UTF-8", "-m",
- possibly_foolish_untaint($message),
+ IkiWiki::possibly_foolish_untaint($message),
$config{srcdir}) != 0) {
my $conflict=readfile("$config{srcdir}/$file");
if (system("svn", "revert", "--quiet", "$config{srcdir}/$file") != 0) {
if (system("svn", "commit", "--quiet",
"--encoding", "UTF-8", "-m",
- possibly_foolish_untaint($message),
+ IkiWiki::possibly_foolish_untaint($message),
$config{srcdir}) != 0) {
warn("svn commit failed\n");
return 1; # failure
my $file=shift;
if (-d "$config{srcdir}/.svn") {
- my $parent=dirname($file);
+ my $parent=IkiWiki::dirname($file);
while (! -d "$config{srcdir}/$parent/.svn") {
$file=$parent;
- $parent=dirname($file);
+ $parent=IkiWiki::dirname($file);
}
if (system("svn", "add", "--quiet", "$config{srcdir}/$file") != 0) {
} #}}}
sub rcs_diff ($) { #{{{
- my $rev=possibly_foolish_untaint(int(shift));
+ my $rev=IkiWiki::possibly_foolish_untaint(int(shift));
return `svnlook diff $config{svnrepo} -r$rev --no-diff-deleted`;
} #}}}
#!/usr/bin/perl
-
-package IkiWiki;
+package IkiWiki::Plugin::tla;
use warnings;
use strict;
use IkiWiki;
-hook(type => "checkconfig", id => "tla", call => sub { #{{{
+sub import { #{{{
+ hook(type => "checkconfig", id => "tla", call => \&checkconfig);
+ hook(type => "getsetup", id => "tla", call => \&getsetup);
+ hook(type => "rcs", id => "rcs_update", call => \&rcs_update);
+ hook(type => "rcs", id => "rcs_prepedit", call => \&rcs_prepedit);
+ hook(type => "rcs", id => "rcs_commit", call => \&rcs_commit);
+ hook(type => "rcs", id => "rcs_commit_staged", call => \&rcs_commit_staged);
+ hook(type => "rcs", id => "rcs_add", call => \&rcs_add);
+ hook(type => "rcs", id => "rcs_remove", call => \&rcs_remove);
+ hook(type => "rcs", id => "rcs_rename", call => \&rcs_rename);
+ hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
+ hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
+ hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
+} #}}}
+
+sub checkconfig () { #{{{
if (! defined $config{diffurl}) {
$config{diffurl}="";
}
- if (length $config{tla_wrapper}) {
+ if (defined $config{tla_wrapper} && length $config{tla_wrapper}) {
push @{$config{wrappers}}, {
wrapper => $config{tla_wrapper},
wrappermode => (defined $config{tla_wrappermode} ? $config{tla_wrappermode} : "06755"),
};
}
-}); #}}}
+} #}}}
-hook(type => "getsetup", id => "tla", call => sub { #{{{
+sub getsetup () { #{{{
return
tla_wrapper => {
type => "string",
safe => 1,
rebuild => 1,
},
-}); #}}}
+} #}}}
-sub quiet_system (@) {
+sub quiet_system (@) { #{{{
# See Debian bug #385939.
open (SAVEOUT, ">&STDOUT");
close STDOUT;
open (STDOUT, ">&SAVEOUT");
close SAVEOUT;
return $ret;
-}
+} #}}}
sub rcs_update () { #{{{
if (-d "$config{srcdir}/{arch}") {
}
if (quiet_system("tla", "commit",
- "-L".possibly_foolish_untaint($message),
+ "-L".IkiWiki::possibly_foolish_untaint($message),
'-d', $config{srcdir}) != 0) {
my $conflict=readfile("$config{srcdir}/$file");
if (system("tla", "undo", "-n", "--quiet", "-d", "$config{srcdir}") != 0) {
* Add getsetup hook, all plugins that add fields to %config should use it.
* ikiwiki --dumpsetup can generate a nice setup file snapshotting ikiwiki's
current configuration.
+ * Large amounts of internal config data reorg.
* The way wrappers are defined in the setup file has changed. Old setup
files will continue to work, for now.
-
+ * Version control backends promoted to first-class plugins.
+
-- Joey Hess <joeyh@debian.org> Mon, 21 Jul 2008 11:35:46 -0400
ikiwiki (2.55) UNRELEASED; urgency=low
### RCS plugins
-ikiwiki's support for [[revision_control_systems|rcs]] also uses pluggable
-perl modules. These are in the `IkiWiki::RCS` namespace, for example
-`IkiWiki::RCS::svn`.
+ikiwiki's support for [[revision_control_systems|rcs]] is also done via
+plugins. See [[RCS_details|rcs/details]] for some more info.
-Each RCS plugin must support all the `IkiWiki::rcs_*` functions.
-See IkiWiki::RCS::Stub for the full list of functions. It's ok if
-`rcs_getctime` does nothing except for throwing an error.
+RCS plugins must register a number of hooks. Each hook has type 'rcs',
+and the 'id' field is set to the name of the hook. For example:
+
+ hook(type => "rcs", id => "rcs_update", call => \&rcs_update);
+ hook(type => "rcs", id => "rcs_prepedit", call => \&rcs_prepedit);
-See [[RCS_details|rcs/details]] for some more info.
+#### `rcs_update()`
+
+Updates the working directory with any remote changes.
+
+#### `rcs_prepedit($)`
+
+Is passed a file to prepare to edit. It can generate and return an arbitrary
+token, that will be passed into `rcs_commit` when committing. For example,
+it might return the current revision ID of the file, and use that
+information later when merging changes.
+
+#### `rcs_commit($$$;$$)`
+
+Passed a file, message, token (from `rcs_prepedit`), user, and ip address.
+Should try to commit the file. Returns `undef` on *success* and a version
+of the page with the rcs's conflict markers on failure.
+
+#### `rcs_commit_staged($$$)`
+
+Passed a message, user, and ip address. Should commit all staged changes.
+Returns undef on success, and an error message on failure.
+
+Changes can be staged by calls to `rcs_add, `rcs_remove`, and
+`rcs_rename`.
+
+#### `rcs_add($)`
+
+Adds the passed file to the archive. The filename is relative to the root
+of the srcdir.
+
+Note that this should not check the new file in, it should only
+prepare for it to be checked in when rcs_commit (or `rcs_commit_staged`) is
+called. Note that the file may be in a new subdir that is not yet in
+to version control; the subdir can be added if so.
+
+#### `rcs_remove($)`
+
+Remove a file. The filename is relative to the root of the srcdir.
+
+Note that this should not check the removal in, it should only prepare for it
+to be checked in when `rcs_commit` (or `rcs_commit_staged`) is called. Note
+that the new file may be in a new subdir that is not yet inversion
+control; the subdir can be added if so.
+
+#### `rcs_rename($$)`
+
+Rename a file. The filenames are relative to the root of the srcdir.
+
+Note that this should not commit the rename, it should only
+prepare it for when `rcs_commit` (or `rcs_commit_staged`) is called.
+The new filename may be in a new subdir, that is not yet added to
+version control. If so, the subdir will exist already, and should
+be added to revision control.
+
+#### `rcs_recentchanges($)`
+
+Examine the RCS history and generate a list of recent changes.
+The parameter is how many changes to return.
+
+The data structure returned for each change is:
+
+ {
+ rev => # the RCSs id for this commit
+ user => # name of user who made the change,
+ committype => # either "web" or the name of the rcs,
+ when => # time when the change was made,
+ message => [
+ { line => "commit message line 1" },
+ { line => "commit message line 2" },
+ # etc,
+ ],
+ pages => [
+ {
+ page => # name of page changed,
+ diffurl => # optional url to a diff of changes
+ },
+ # repeat for each page changed in this commit,
+ ],
+ }
+
+#### `rcs_diff($)`
+
+The parameter is the rev from `rcs_recentchanges`.
+Should return a list of lines of the diff (including \n) in list
+context, and the whole diff in scalar context.
+
+#### `rcs_getctime($)`
+
+This is used to get the page creation time for a file from the RCS, by looking
+it up in the history.
+
+It's ok if this is not implemented, and throws an error.
### PageSpec plugins
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-07-25 16:16-0400\n"
+"POT-Creation-Date: 2008-07-26 22:24-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
msgstr ""
#: ../IkiWiki/CGI.pm:437 ../IkiWiki/Plugin/brokenlinks.pm:24
-#: ../IkiWiki/Plugin/inline.pm:261 ../IkiWiki/Plugin/opendiscussion.pm:17
+#: ../IkiWiki/Plugin/inline.pm:306 ../IkiWiki/Plugin/opendiscussion.pm:17
#: ../IkiWiki/Plugin/orphans.pm:28 ../IkiWiki/Render.pm:78
#: ../IkiWiki/Render.pm:148
msgid "discussion"
msgid "You are banned."
msgstr ""
-#: ../IkiWiki/CGI.pm:758 ../IkiWiki/CGI.pm:759 ../IkiWiki.pm:788
+#: ../IkiWiki/CGI.pm:758 ../IkiWiki/CGI.pm:759 ../IkiWiki.pm:1086
msgid "Error"
msgstr ""
-#: ../IkiWiki/Plugin/aggregate.pm:57
+#: ../IkiWiki/Plugin/aggregate.pm:76
msgid "Aggregation triggered via web."
msgstr ""
-#: ../IkiWiki/Plugin/aggregate.pm:66
+#: ../IkiWiki/Plugin/aggregate.pm:85
msgid "Nothing to do right now, all feeds are up-to-date!"
msgstr ""
-#: ../IkiWiki/Plugin/aggregate.pm:193
+#: ../IkiWiki/Plugin/aggregate.pm:212
#, perl-format
msgid "missing %s parameter"
msgstr ""
-#: ../IkiWiki/Plugin/aggregate.pm:227
+#: ../IkiWiki/Plugin/aggregate.pm:246
msgid "new feed"
msgstr ""
-#: ../IkiWiki/Plugin/aggregate.pm:241
+#: ../IkiWiki/Plugin/aggregate.pm:260
msgid "posts"
msgstr ""
-#: ../IkiWiki/Plugin/aggregate.pm:243
+#: ../IkiWiki/Plugin/aggregate.pm:262
msgid "new"
msgstr ""
-#: ../IkiWiki/Plugin/aggregate.pm:406
+#: ../IkiWiki/Plugin/aggregate.pm:425
#, perl-format
msgid "expiring %s (%s days old)"
msgstr ""
-#: ../IkiWiki/Plugin/aggregate.pm:413
+#: ../IkiWiki/Plugin/aggregate.pm:432
#, perl-format
msgid "expiring %s"
msgstr ""
-#: ../IkiWiki/Plugin/aggregate.pm:440
+#: ../IkiWiki/Plugin/aggregate.pm:459
#, perl-format
msgid "processed ok at %s"
msgstr ""
-#: ../IkiWiki/Plugin/aggregate.pm:444
+#: ../IkiWiki/Plugin/aggregate.pm:463
#, perl-format
msgid "checking feed %s ..."
msgstr ""
-#: ../IkiWiki/Plugin/aggregate.pm:449
+#: ../IkiWiki/Plugin/aggregate.pm:468
#, perl-format
msgid "could not find feed at %s"
msgstr ""
-#: ../IkiWiki/Plugin/aggregate.pm:464
+#: ../IkiWiki/Plugin/aggregate.pm:483
msgid "feed not found"
msgstr ""
-#: ../IkiWiki/Plugin/aggregate.pm:475
+#: ../IkiWiki/Plugin/aggregate.pm:494
#, perl-format
msgid "(invalid UTF-8 stripped from feed)"
msgstr ""
-#: ../IkiWiki/Plugin/aggregate.pm:481
+#: ../IkiWiki/Plugin/aggregate.pm:500
#, perl-format
msgid "(feed entities escaped)"
msgstr ""
-#: ../IkiWiki/Plugin/aggregate.pm:487
+#: ../IkiWiki/Plugin/aggregate.pm:506
msgid "feed crashed XML::Feed!"
msgstr ""
-#: ../IkiWiki/Plugin/aggregate.pm:561
+#: ../IkiWiki/Plugin/aggregate.pm:580
#, perl-format
msgid "creating new page %s"
msgstr ""
-#: ../IkiWiki/Plugin/amazon_s3.pm:30
+#: ../IkiWiki/Plugin/amazon_s3.pm:31
msgid "deleting bucket.."
msgstr ""
-#: ../IkiWiki/Plugin/amazon_s3.pm:37 ../IkiWiki/Setup.pm:117
+#: ../IkiWiki/Plugin/amazon_s3.pm:38 ../ikiwiki.in:188
msgid "done"
msgstr ""
-#: ../IkiWiki/Plugin/amazon_s3.pm:46
+#: ../IkiWiki/Plugin/amazon_s3.pm:93
#, perl-format
msgid "Must specify %s"
msgstr ""
-#: ../IkiWiki/Plugin/amazon_s3.pm:85
+#: ../IkiWiki/Plugin/amazon_s3.pm:132
msgid "Failed to create bucket in S3: "
msgstr ""
-#: ../IkiWiki/Plugin/amazon_s3.pm:170
+#: ../IkiWiki/Plugin/amazon_s3.pm:217
msgid "Failed to save file to S3: "
msgstr ""
-#: ../IkiWiki/Plugin/amazon_s3.pm:192
+#: ../IkiWiki/Plugin/amazon_s3.pm:239
msgid "Failed to delete file from S3: "
msgstr ""
-#: ../IkiWiki/Plugin/attachment.pm:22
+#: ../IkiWiki/Plugin/attachment.pm:34
#, perl-format
msgid "there is already a page named %s"
msgstr ""
-#: ../IkiWiki/Plugin/attachment.pm:41
+#: ../IkiWiki/Plugin/attachment.pm:53
msgid "prohibited by allowed_attachments"
msgstr ""
-#: ../IkiWiki/Plugin/attachment.pm:144
+#: ../IkiWiki/Plugin/attachment.pm:156
msgid "bad attachment filename"
msgstr ""
-#: ../IkiWiki/Plugin/attachment.pm:186
+#: ../IkiWiki/Plugin/attachment.pm:198
msgid "attachment upload"
msgstr ""
msgid "failed to determine size of image %s"
msgstr ""
-#: ../IkiWiki/Plugin/inline.pm:47
+#: ../IkiWiki/Plugin/inline.pm:89
msgid "Must specify url to wiki with --url when using --rss or --atom"
msgstr ""
-#: ../IkiWiki/Plugin/inline.pm:101
+#: ../IkiWiki/Plugin/inline.pm:146
msgid "missing pages parameter"
msgstr ""
-#: ../IkiWiki/Plugin/inline.pm:149
+#: ../IkiWiki/Plugin/inline.pm:194
#, perl-format
msgid "unknown sort type %s"
msgstr ""
-#: ../IkiWiki/Plugin/inline.pm:220
+#: ../IkiWiki/Plugin/inline.pm:265
msgid "Add a new post titled:"
msgstr ""
-#: ../IkiWiki/Plugin/inline.pm:236
+#: ../IkiWiki/Plugin/inline.pm:281
#, perl-format
msgid "nonexistant template %s"
msgstr ""
-#: ../IkiWiki/Plugin/inline.pm:269 ../IkiWiki/Render.pm:82
+#: ../IkiWiki/Plugin/inline.pm:314 ../IkiWiki/Render.pm:82
msgid "Discussion"
msgstr ""
-#: ../IkiWiki/Plugin/inline.pm:506
+#: ../IkiWiki/Plugin/inline.pm:551
msgid "RPC::XML::Client not found, not pinging"
msgstr ""
msgid "%s is locked by %s and cannot be edited"
msgstr ""
-#: ../IkiWiki/Plugin/mdwn.pm:28
+#: ../IkiWiki/Plugin/mdwn.pm:40
msgid "multimarkdown is enabled, but Text::MultiMarkdown is not installed"
msgstr ""
-#: ../IkiWiki/Plugin/mdwn.pm:51
+#: ../IkiWiki/Plugin/mdwn.pm:63
#, perl-format
msgid "failed to load Markdown.pm perl module (%s) or /usr/bin/markdown (%s)"
msgstr ""
msgid "redir cycle is not allowed"
msgstr ""
-#: ../IkiWiki/Plugin/mirrorlist.pm:23
+#: ../IkiWiki/Plugin/mirrorlist.pm:35
msgid "Mirrors"
msgstr ""
-#: ../IkiWiki/Plugin/mirrorlist.pm:23
+#: ../IkiWiki/Plugin/mirrorlist.pm:35
msgid "Mirror"
msgstr ""
msgid "more"
msgstr ""
-#: ../IkiWiki/Plugin/openid.pm:45
+#: ../IkiWiki/Plugin/norcs.pm:55
+msgid "getctime not implemented"
+msgstr ""
+
+#: ../IkiWiki/Plugin/openid.pm:57
msgid "Log in with"
msgstr ""
-#: ../IkiWiki/Plugin/openid.pm:48
+#: ../IkiWiki/Plugin/openid.pm:60
msgid "Get an OpenID"
msgstr ""
msgid "bad or missing template"
msgstr ""
-#: ../IkiWiki/Plugin/passwordauth.pm:223
+#: ../IkiWiki/Plugin/passwordauth.pm:243
msgid "Account creation successful. Now you can Login."
msgstr ""
-#: ../IkiWiki/Plugin/passwordauth.pm:226
+#: ../IkiWiki/Plugin/passwordauth.pm:246
msgid "Error creating account."
msgstr ""
-#: ../IkiWiki/Plugin/passwordauth.pm:233
+#: ../IkiWiki/Plugin/passwordauth.pm:253
msgid "No email address, so cannot email password reset instructions."
msgstr ""
-#: ../IkiWiki/Plugin/passwordauth.pm:265
+#: ../IkiWiki/Plugin/passwordauth.pm:287
msgid "Failed to send mail"
msgstr ""
-#: ../IkiWiki/Plugin/passwordauth.pm:267
+#: ../IkiWiki/Plugin/passwordauth.pm:289
msgid "You have been mailed password reset instructions."
msgstr ""
-#: ../IkiWiki/Plugin/passwordauth.pm:302
+#: ../IkiWiki/Plugin/passwordauth.pm:324
msgid "incorrect password reset url"
msgstr ""
-#: ../IkiWiki/Plugin/passwordauth.pm:305
+#: ../IkiWiki/Plugin/passwordauth.pm:327
msgid "password reset denied"
msgstr ""
msgid "Ping received."
msgstr ""
-#: ../IkiWiki/Plugin/pinger.pm:37
+#: ../IkiWiki/Plugin/pinger.pm:49
msgid "requires 'from' and 'to' parameters"
msgstr ""
-#: ../IkiWiki/Plugin/pinger.pm:42
+#: ../IkiWiki/Plugin/pinger.pm:54
#, perl-format
msgid "Will ping %s"
msgstr ""
-#: ../IkiWiki/Plugin/pinger.pm:45
+#: ../IkiWiki/Plugin/pinger.pm:57
#, perl-format
msgid "Ignoring ping directive for wiki %s (this wiki is %s)"
msgstr ""
-#: ../IkiWiki/Plugin/pinger.pm:61
+#: ../IkiWiki/Plugin/pinger.pm:73
msgid "LWP not found, not pinging"
msgstr ""
msgid "%A night"
msgstr ""
-#: ../IkiWiki/Plugin/prettydate.pm:78
+#: ../IkiWiki/Plugin/prettydate.pm:96
msgid "at teatime on %A"
msgstr ""
-#: ../IkiWiki/Plugin/prettydate.pm:82
+#: ../IkiWiki/Plugin/prettydate.pm:100
msgid "at midnight"
msgstr ""
-#: ../IkiWiki/Plugin/prettydate.pm:85
+#: ../IkiWiki/Plugin/prettydate.pm:103
msgid "at noon on %A"
msgstr ""
-#: ../IkiWiki/Plugin/recentchanges.pm:76
+#: ../IkiWiki/Plugin/recentchanges.pm:95
msgid "missing page"
msgstr ""
-#: ../IkiWiki/Plugin/recentchanges.pm:78
+#: ../IkiWiki/Plugin/recentchanges.pm:97
#, perl-format
msgid "The page %s does not exist."
msgstr ""
msgid "update for rename of %s to %s"
msgstr ""
-#: ../IkiWiki/Plugin/search.pm:20
+#: ../IkiWiki/Plugin/search.pm:32
#, perl-format
msgid "Must specify %s when using the search plugin"
msgstr ""
-#: ../IkiWiki/Plugin/search.pm:166
+#: ../IkiWiki/Plugin/search.pm:178
#, perl-format
msgid "need Digest::SHA1 to index %s"
msgstr ""
-#: ../IkiWiki/Plugin/search.pm:201
+#: ../IkiWiki/Plugin/search.pm:213
msgid "search"
msgstr ""
msgid "failed to generate image from code"
msgstr ""
-#: ../IkiWiki/Rcs/Stub.pm:96
-msgid "getctime not implemented"
-msgstr ""
-
#: ../IkiWiki/Render.pm:276 ../IkiWiki/Render.pm:297
#, perl-format
msgid "skipping bad filename %s"
#. translators: The first parameter is a filename, and the second
#. translators: is a (probably not translated) error message.
-#: ../IkiWiki/Setup.pm:25
+#: ../IkiWiki/Setup.pm:23
#, perl-format
msgid "cannot read %s: %s"
msgstr ""
-#: ../IkiWiki/Setup.pm:58
-msgid "generating wrappers.."
-msgstr ""
-
-#: ../IkiWiki/Setup.pm:107
-msgid "rebuilding wiki.."
-msgstr ""
-
-#: ../IkiWiki/Setup.pm:110
-msgid "refreshing wiki.."
-msgstr ""
-
#: ../IkiWiki/Wrapper.pm:16
#, perl-format
msgid "%s doesn't seem to be executable"
msgid "usage: ikiwiki [options] source dest"
msgstr ""
-#: ../ikiwiki.in:82
+#: ../ikiwiki.in:79
msgid "usage: --set var=value"
msgstr ""
-#: ../IkiWiki.pm:126
+#: ../ikiwiki.in:118
+msgid "generating wrappers.."
+msgstr ""
+
+#: ../ikiwiki.in:177
+msgid "rebuilding wiki.."
+msgstr ""
+
+#: ../ikiwiki.in:180
+msgid "refreshing wiki.."
+msgstr ""
+
+#: ../IkiWiki.pm:410
msgid "Must specify url to wiki with --url when using --cgi"
msgstr ""
-#. translators: The first parameter is a
-#. translators: preprocessor directive name,
-#. translators: the second a page name, the
-#. translators: third a number.
-#: ../IkiWiki.pm:771
+#: ../IkiWiki.pm:1069
#, perl-format
-msgid "%s preprocessing loop detected on %s at depth %i"
+msgid "preprocessing loop detected on %s at depth %i"
msgstr ""
-#: ../IkiWiki.pm:1219
+#: ../IkiWiki.pm:1557
msgid "yes"
msgstr ""
my @progs="ikiwiki.in";
my @libs="IkiWiki.pm";
# monotone, external, amazon_s3 skipped since they need perl modules
-push @libs, map { chomp; $_ } `find IkiWiki -type f -name \\*.pm | grep -v IkiWiki/Rcs/monotone.pm | grep -v IkiWiki/Plugin/external.pm | grep -v IkiWiki/Plugin/amazon_s3.pm`;
+push @libs, map { chomp; $_ } `find IkiWiki -type f -name \\*.pm | grep -v monotone.pm | grep -v external.pm | grep -v amazon_s3.pm`;
plan(tests => (@progs + @libs));