summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--IkiWiki.pm424
-rw-r--r--IkiWiki/Plugin/aggregate.pm19
-rw-r--r--IkiWiki/Plugin/amazon_s3.pm47
-rw-r--r--IkiWiki/Plugin/anonok.pm14
-rw-r--r--IkiWiki/Plugin/attachment.pm12
-rw-r--r--IkiWiki/Plugin/calendar.pm14
-rw-r--r--IkiWiki/Plugin/graphviz.pm2
-rw-r--r--IkiWiki/Plugin/inline.pm49
-rw-r--r--IkiWiki/Plugin/mdwn.pm16
-rw-r--r--IkiWiki/Plugin/mirrorlist.pm12
-rw-r--r--IkiWiki/Plugin/openid.pm12
-rw-r--r--IkiWiki/Plugin/passwordauth.pm36
-rw-r--r--IkiWiki/Plugin/pinger.pm12
-rw-r--r--IkiWiki/Plugin/prettydate.pm18
-rw-r--r--IkiWiki/Plugin/recentchanges.pm19
-rw-r--r--IkiWiki/Plugin/search.pm14
-rw-r--r--IkiWiki/Plugin/skeleton.pm.example12
-rw-r--r--IkiWiki/Plugin/tag.pm12
-rw-r--r--IkiWiki/Plugin/typography.pm17
-rw-r--r--IkiWiki/Rcs/bzr.pm44
-rw-r--r--IkiWiki/Rcs/git.pm64
-rw-r--r--IkiWiki/Rcs/mercurial.pm48
-rw-r--r--IkiWiki/Rcs/monotone.pm96
-rw-r--r--IkiWiki/Rcs/svn.pm75
-rw-r--r--IkiWiki/Rcs/tla.pm44
-rw-r--r--IkiWiki/Render.pm2
-rw-r--r--IkiWiki/Setup.pm97
-rw-r--r--IkiWiki/Setup/Standard.pm113
-rwxr-xr-xMakefile.PL2
-rw-r--r--debian/changelog10
-rw-r--r--doc/plugins/write.mdwn41
-rw-r--r--doc/setup.mdwn31
-rw-r--r--doc/usage.mdwn5
-rwxr-xr-xikiwiki.in58
34 files changed, 1300 insertions, 191 deletions
diff --git a/IkiWiki.pm b/IkiWiki.pm
index 3f8a4bca3..4ad19a499 100644
--- a/IkiWiki.pm
+++ b/IkiWiki.pm
@@ -32,65 +32,349 @@ memoize("abs2rel");
memoize("pagespec_translate");
memoize("file_pruned");
+sub getsetup () { #{{{
+ wikiname => {
+ type => "string",
+ default => "wiki",
+ description => "name of the wiki",
+ safe => 1,
+ rebuild => 1,
+ },
+ srcdir => {
+ type => "string",
+ default => undef,
+ example => "$ENV{HOME}/wiki",
+ description => "where the source of the wiki is located",
+ safe => 0, # path
+ rebuild => 1,
+ },
+ destdir => {
+ type => "string",
+ default => undef,
+ example => "/var/www/wiki",
+ description => "where to build the wiki",
+ safe => 0, # path
+ rebuild => 1,
+ },
+ adminuser => {
+ type => "string",
+ default => [],
+ description => "user names of wiki admins",
+ safe => 1,
+ rebuild => 0,
+ },
+ adminemail => {
+ type => "string",
+ default => undef,
+ example => 'me@example.com',
+ description => "contact email for wiki",
+ safe => 1,
+ rebuild => 0,
+ },
+ url => {
+ type => "string",
+ default => '',
+ example => "http://example.com/wiki",
+ description => "base url to the wiki",
+ safe => 1,
+ rebuild => 1,
+ },
+ cgiurl => {
+ type => "string",
+ default => '',
+ example => "http://example.com/wiki/ikiwiki.cgi",
+ description => "url to the ikiwiki.cgi",
+ safe => 1,
+ rebuild => 1,
+ },
+ cgi_wrapper => {
+ type => "string",
+ default => '',
+ example => "/var/www/wiki/ikiwiki.cgi",
+ description => "cgi executable to generate",
+ safe => 0, # file
+ rebuild => 0,
+ },
+ cgi_wrappermode => {
+ type => "string",
+ default => '06755',
+ description => "mode for cgi_wrapper (can safely be made suid)",
+ safe => 0,
+ rebuild => 0,
+ },
+ rcs => {
+ type => "string",
+ default => '',
+ description => "rcs backend to use",
+ safe => 0, # don't allow overriding
+ rebuild => 0,
+ },
+ default_plugins => {
+ type => "internal",
+ default => [qw{mdwn link inline htmlscrubber passwordauth
+ openid signinedit lockedit conditional
+ recentchanges parentlinks}],
+ description => "plugins to enable by default",
+ safe => 1,
+ rebuild => 1,
+ },
+ add_plugins => {
+ type => "string",
+ default => [],
+ description => "plugins to add to the default configuration",
+ safe => 1,
+ rebuild => 1,
+ },
+ disable_plugins => {
+ type => "string",
+ default => [],
+ description => "plugins to disable",
+ safe => 1,
+ rebuild => 1,
+ },
+ templatedir => {
+ type => "string",
+ default => "$installdir/share/ikiwiki/templates",
+ description => "location of template files",
+ safe => 0, # path
+ rebuild => 1,
+ },
+ underlaydir => {
+ type => "string",
+ default => "$installdir/share/ikiwiki/basewiki",
+ description => "base wiki source location",
+ safe => 0, # path
+ rebuild => 0,
+ },
+ wrappers => {
+ type => "internal",
+ default => [],
+ description => "wrappers to generate",
+ safe => 0,
+ rebuild => 0,
+ },
+ underlaydirs => {
+ type => "internal",
+ default => [],
+ description => "additional underlays to use",
+ safe => 0,
+ rebuild => 0,
+ },
+ verbose => {
+ type => "boolean",
+ default => 0,
+ description => "display verbose messages when building?",
+ safe => 1,
+ rebuild => 0,
+ },
+ syslog => {
+ type => "boolean",
+ default => 0,
+ description => "log to syslog?",
+ safe => 1,
+ rebuild => 0,
+ },
+ usedirs => {
+ type => "boolean",
+ default => 1,
+ description => "create output files named page/index.html?",
+ safe => 0, # changing requires manual transition
+ rebuild => 1,
+ },
+ prefix_directives => {
+ type => "boolean",
+ default => 0,
+ description => "use '!'-prefixed preprocessor directives?",
+ safe => 0, # changing requires manual transition
+ rebuild => 1,
+ },
+ discussion => {
+ type => "boolean",
+ default => 1,
+ description => "enable Discussion pages?",
+ safe => 1,
+ rebuild => 1,
+ },
+ default_pageext => {
+ type => "string",
+ default => "mdwn",
+ description => "extension to use for new pages",
+ safe => 0, # not sanitized
+ rebuild => 0,
+ },
+ htmlext => {
+ type => "string",
+ default => "html",
+ description => "extension to use for html files",
+ safe => 0, # not sanitized
+ rebuild => 1,
+ },
+ timeformat => {
+ type => "string",
+ default => '%c',
+ description => "strftime format string to display date",
+ safe => 1,
+ rebuild => 1,
+ },
+ locale => {
+ type => "string",
+ default => undef,
+ example => "en_US.UTF-8",
+ description => "UTF-8 locale to use",
+ safe => 0,
+ rebuild => 1,
+ },
+ sslcookie => {
+ type => "boolean",
+ default => 0,
+ description => "only send cookies over SSL connections?",
+ safe => 1,
+ rebuild => 0,
+ },
+ userdir => {
+ type => "string",
+ default => "",
+ example => "users",
+ description => "put user pages below specified page",
+ safe => 1,
+ rebuild => 1,
+ },
+ numbacklinks => {
+ type => "integer",
+ default => 10,
+ description => "how many backlinks to show before hiding excess (0 to show all)",
+ safe => 1,
+ rebuild => 1,
+ },
+ hardlink => {
+ type => "boolean",
+ default => 0,
+ description => "attempt to hardlink source files? (optimisation for large files)",
+ safe => 0, # paranoia
+ rebuild => 0,
+ },
+ umask => {
+ type => "integer",
+ description => "",
+ example => "022",
+ description => "force ikiwiki to use a particular umask",
+ safe => 0, # paranoia
+ rebuild => 0,
+ },
+ libdir => {
+ type => "string",
+ default => "",
+ example => "$ENV{HOME}/.ikiwiki/",
+ description => "extra library and plugin directory",
+ safe => 0, # directory
+ rebuild => 0,
+ },
+ ENV => {
+ type => "string",
+ default => {},
+ description => "environment variables",
+ safe => 0, # paranoia
+ rebuild => 0,
+ },
+ exclude => {
+ type => "string",
+ default => undef,
+ example => '\.wav$',
+ description => "regexp of source files to ignore",
+ safe => 0, # regexp
+ rebuild => 1,
+ },
+ wiki_file_prune_regexps => {
+ type => "internal",
+ default => [qr/(^|\/)\.\.(\/|$)/, qr/^\./, qr/\/\./,
+ qr/\.x?html?$/, qr/\.ikiwiki-new$/,
+ qr/(^|\/).svn\//, qr/.arch-ids\//, qr/{arch}\//,
+ qr/(^|\/)_MTN\//,
+ qr/\.dpkg-tmp$/],
+ description => "regexps of source files to ignore",
+ safe => 0,
+ rebuild => 1,
+ },
+ wiki_file_regexp => {
+ type => "internal",
+ default => qr/(^[-[:alnum:]_.:\/+]+$)/,
+ description => "regexp of legal source files",
+ safe => 0,
+ rebuild => 1,
+ },
+ web_commit_regexp => {
+ type => "internal",
+ default => qr/^web commit (by (.*?(?=: |$))|from (\d+\.\d+\.\d+\.\d+)):?(.*)/,
+ description => "regexp to parse web commits from logs",
+ safe => 0,
+ rebuild => 0,
+ },
+ cgi => {
+ type => "internal",
+ default => 0,
+ description => "run as a cgi",
+ safe => 0,
+ rebuild => 0,
+ },
+ cgi_disable_uploads => {
+ type => "internal",
+ default => 1,
+ description => "whether CGI should accept file uploads",
+ safe => 0,
+ rebuild => 0,
+ },
+ post_commit => {
+ type => "internal",
+ default => 0,
+ description => "run as a post-commit hook",
+ safe => 0,
+ rebuild => 0,
+ },
+ rebuild => {
+ type => "internal",
+ default => 0,
+ description => "running in rebuild mode",
+ safe => 0,
+ rebuild => 0,
+ },
+ refresh => {
+ type => "internal",
+ default => 0,
+ description => "running in refresh mode",
+ safe => 0,
+ rebuild => 0,
+ },
+ getctime => {
+ type => "internal",
+ default => 0,
+ description => "running in getctime mode",
+ safe => 0,
+ rebuild => 0,
+ },
+ w3mmode => {
+ type => "internal",
+ default => 0,
+ description => "running in w3mmode",
+ safe => 0,
+ rebuild => 0,
+ },
+ setup => {
+ type => "internal",
+ default => undef,
+ description => "setup file to read",
+ safe => 0,
+ rebuild => 0,
+ },
+} #}}}
+
sub defaultconfig () { #{{{
- return
- wiki_file_prune_regexps => [qr/(^|\/)\.\.(\/|$)/, qr/^\./, qr/\/\./,
- qr/\.x?html?$/, qr/\.ikiwiki-new$/,
- qr/(^|\/).svn\//, qr/.arch-ids\//, qr/{arch}\//,
- qr/(^|\/)_MTN\//,
- qr/\.dpkg-tmp$/],
- wiki_file_regexp => qr/(^[-[:alnum:]_.:\/+]+$)/,
- web_commit_regexp => qr/^web commit (by (.*?(?=: |$))|from (\d+\.\d+\.\d+\.\d+)):?(.*)/,
- verbose => 0,
- syslog => 0,
- wikiname => "wiki",
- default_pageext => "mdwn",
- htmlext => "html",
- cgi => 0,
- post_commit => 0,
- rcs => '',
- url => '',
- cgiurl => '',
- historyurl => '',
- diffurl => '',
- rss => 0,
- atom => 0,
- allowrss => 0,
- allowatom => 0,
- discussion => 1,
- rebuild => 0,
- refresh => 0,
- getctime => 0,
- w3mmode => 0,
- wrapper => undef,
- wrappermode => undef,
- svnpath => "trunk",
- gitorigin_branch => "origin",
- gitmaster_branch => "master",
- srcdir => undef,
- destdir => undef,
- pingurl => [],
- templatedir => "$installdir/share/ikiwiki/templates",
- underlaydir => "$installdir/share/ikiwiki/basewiki",
- underlaydirs => [],
- setup => undef,
- adminuser => undef,
- adminemail => undef,
- plugin => [qw{mdwn link inline htmlscrubber passwordauth openid
- signinedit lockedit conditional recentchanges
- parentlinks}],
- libdir => undef,
- timeformat => '%c',
- locale => undef,
- sslcookie => 0,
- httpauth => 0,
- userdir => "",
- usedirs => 1,
- numbacklinks => 10,
- account_creation_password => "",
- prefix_directives => 0,
- hardlink => 0,
- cgi_disable_uploads => 1,
+ my %s=getsetup();
+ my @ret;
+ foreach my $key (keys %s) {
+ push @ret, $key, $s{$key}->{default};
+ }
+ use Data::Dumper;
+ return @ret;
} #}}}
sub checkconfig () { #{{{
@@ -139,7 +423,7 @@ sub checkconfig () { #{{{
require IkiWiki::Rcs::Stub;
}
- if (exists $config{umask}) {
+ if (defined $config{umask}) {
umask(possibly_foolish_untaint($config{umask}));
}
@@ -148,12 +432,32 @@ sub checkconfig () { #{{{
return 1;
} #}}}
+sub listplugins () { #{{{
+ my %ret;
+
+ foreach my $dir (@INC, $config{libdir}) {
+ next unless defined $dir;
+ foreach my $file (glob("$dir/IkiWiki/Plugin/*.pm")) {
+ my ($plugin)=$file=~/.*\/(.*)\.pm$/;
+ $ret{$plugin}=1;
+ }
+ }
+ foreach my $dir ($config{libdir}, "$installdir/lib/ikiwiki") {
+ next unless defined $dir;
+ foreach my $file (glob("$dir/plugins/*")) {
+ $ret{basename($file)}=1 if -x $file;
+ }
+ }
+
+ return keys %ret;
+} #}}}
+
sub loadplugins () { #{{{
if (defined $config{libdir}) {
unshift @INC, possibly_foolish_untaint($config{libdir});
}
- loadplugin($_) foreach @{$config{plugin}};
+ loadplugin($_) foreach @{$config{default_plugins}}, @{$config{add_plugins}};
run_hooks(getopt => sub { shift->() });
if (grep /^-/, @ARGV) {
diff --git a/IkiWiki/Plugin/aggregate.pm b/IkiWiki/Plugin/aggregate.pm
index e000bc864..673668c0e 100644
--- a/IkiWiki/Plugin/aggregate.pm
+++ b/IkiWiki/Plugin/aggregate.pm
@@ -16,6 +16,7 @@ my %guids;
sub import { #{{{
hook(type => "getopt", id => "aggregate", call => \&getopt);
+ hook(type => "getsetup", id => "aggregate", call => \&getsetup);
hook(type => "checkconfig", id => "aggregate", call => \&checkconfig);
hook(type => "needsbuild", id => "aggregate", call => \&needsbuild);
hook(type => "preprocess", id => "aggregate", call => \&preprocess);
@@ -37,6 +38,24 @@ sub getopt () { #{{{
);
} #}}}
+sub getsetup () { #{{{
+ return
+ aggregateinternal => {
+ type => "boolean",
+ example => 0,
+ description => "enable aggregation to internal pages?",
+ safe => 0, # enabling needs manual transition
+ rebuild => 0,
+ },
+ aggregate_webtrigger => {
+ type => "boolean",
+ example => 0,
+ description => "allow aggregation to be triggered via the web?",
+ safe => 1,
+ rebuild => 0,
+ },
+} #}}}
+
sub checkconfig () { #{{{
if ($config{aggregate} && ! ($config{post_commit} &&
IkiWiki::commit_hook_enabled())) {
diff --git a/IkiWiki/Plugin/amazon_s3.pm b/IkiWiki/Plugin/amazon_s3.pm
index 187700f30..e181a84da 100644
--- a/IkiWiki/Plugin/amazon_s3.pm
+++ b/IkiWiki/Plugin/amazon_s3.pm
@@ -18,6 +18,7 @@ BEGIN {
sub import { #{{{
hook(type => "getopt", id => "amazon_s3", call => \&getopt);
+ hook(type => "getsetup", id => "amazon_s3", call => \&getsetup);
hook(type => "checkconfig", id => "amazon_s3", call => \&checkconfig);
} # }}}
@@ -39,6 +40,52 @@ sub getopt () { #{{{
});
} #}}}
+sub getsetup () { #{{{
+ return
+ amazon_s3_key_id => {
+ type => "string",
+ example => "XXXXXXXXXXXXXXXXXXXX",
+ description => "public access key id",
+ safe => 1,
+ rebuild => 0,
+ },
+ amazon_s3_key_id => {
+ type => "string",
+ example => "$ENV{HOME}/.s3_key",
+ description => "file holding secret key (must not be readable by others!)",
+ safe => 0, # ikiwiki reads this file
+ rebuild => 0,
+ },
+ amazon_s3_bucket => {
+ type => "string",
+ example => "mywiki",
+ description => "globally unique name of bucket to store wiki in",
+ safe => 1,
+ rebuild => 1,
+ },
+ amazon_s3_prefix => {
+ type => "string",
+ example => "wiki/",
+ description => "a prefix to prepend to each page name",
+ safe => 1,
+ rebuild => 1,
+ },
+ amazon_s3_location => {
+ type => "string",
+ example => "EU",
+ description => "which S3 datacenter to use (leave blank for default)",
+ safe => 1,
+ rebuild => 1,
+ },
+ amazon_s3_dupindex => {
+ type => "boolean",
+ example => 0,
+ description => "store each index file twice? (allows urls ending in \"/index.html\" and \"/\")",
+ safe => 1,
+ rebuild => 1,
+ },
+} #}}}
+
sub checkconfig { #{{{
foreach my $field (qw{amazon_s3_key_id amazon_s3_key_file
amazon_s3_bucket}) {
diff --git a/IkiWiki/Plugin/anonok.pm b/IkiWiki/Plugin/anonok.pm
index 1880516d5..7b966f845 100644
--- a/IkiWiki/Plugin/anonok.pm
+++ b/IkiWiki/Plugin/anonok.pm
@@ -6,9 +6,21 @@ use strict;
use IkiWiki 2.00;
sub import { #{{{
- hook(type => "canedit", id => "anonok", call => \&canedit,);
+ hook(type => "getsetup", id => "anonok", call => \&getsetup);
+ hook(type => "canedit", id => "anonok", call => \&canedit);
} # }}}
+sub getsetup () { #{{{
+ return
+ anonok_pagespec => {
+ type => "string",
+ example => "*/discussion",
+ description => "PageSpec to limit which pages anonymous users can edit",
+ safe => 1,
+ rebuild => 0,
+ },
+} #}}}
+
sub canedit ($$$) { #{{{
my $page=shift;
my $cgi=shift;
diff --git a/IkiWiki/Plugin/attachment.pm b/IkiWiki/Plugin/attachment.pm
index 720078be1..47e165251 100644
--- a/IkiWiki/Plugin/attachment.pm
+++ b/IkiWiki/Plugin/attachment.pm
@@ -6,11 +6,23 @@ use strict;
use IkiWiki 2.00;
sub import { #{{{
+ hook(type => "getsetup", id => "attachment", call => \&getsetup);
hook(type => "checkconfig", id => "attachment", call => \&checkconfig);
hook(type => "formbuilder_setup", id => "attachment", call => \&formbuilder_setup);
hook(type => "formbuilder", id => "attachment", call => \&formbuilder);
} # }}}
+sub getsetup () { #{{{
+ return
+ virus_checker => {
+ type => "string",
+ example => "clamdscan -",
+ description => "virus checker program (reads STDIN, returns nonzero if virus found)",
+ safe => 0, # executed
+ rebuild => 0,
+ },
+} #}}}
+
sub check_canattach ($$;$) { #{{{
my $session=shift;
my $dest=shift; # where it's going to be put, under the srcdir
diff --git a/IkiWiki/Plugin/calendar.pm b/IkiWiki/Plugin/calendar.pm
index aed087eed..6f1f9bd07 100644
--- a/IkiWiki/Plugin/calendar.pm
+++ b/IkiWiki/Plugin/calendar.pm
@@ -30,10 +30,22 @@ my $time=time;
my @now=localtime($time);
sub import { #{{{
- hook(type => "needsbuild", id => "version", call => \&needsbuild);
+ hook(type => "getsetup", id => "calendar", call => \&getsetup);
+ hook(type => "needsbuild", id => "calendar", call => \&needsbuild);
hook(type => "preprocess", id => "calendar", call => \&preprocess);
} #}}}
+sub getsetup () { #{{{
+ return
+ archivebase => {
+ type => "string",
+ example => "archives",
+ description => "base of the archives hierarchy",
+ safe => 1,
+ rebuild => 1,
+ },
+} #}}}
+
sub is_leap_year (@) { #{{{
my %params=@_;
return ($params{year} % 4 == 0 && (($params{year} % 100 != 0) || $params{year} % 400 == 0));
diff --git a/IkiWiki/Plugin/graphviz.pm b/IkiWiki/Plugin/graphviz.pm
index b13d15fa6..021aa6b23 100644
--- a/IkiWiki/Plugin/graphviz.pm
+++ b/IkiWiki/Plugin/graphviz.pm
@@ -9,7 +9,7 @@ use IkiWiki 2.00;
use IPC::Open2;
sub import { #{{{
- hook(type => "preprocess", id => "graph", call => \&graph);
+ hook(type => "preprocess", id => "graphviz", call => \&graph);
} # }}}
my %graphviz_programs = (
diff --git a/IkiWiki/Plugin/inline.pm b/IkiWiki/Plugin/inline.pm
index 2f0901943..cdd0ab0dc 100644
--- a/IkiWiki/Plugin/inline.pm
+++ b/IkiWiki/Plugin/inline.pm
@@ -15,6 +15,7 @@ my $nested=0;
sub import { #{{{
hook(type => "getopt", id => "inline", call => \&getopt);
+ hook(type => "getsetup", id => "inline", call => \&getsetup);
hook(type => "checkconfig", id => "inline", call => \&checkconfig);
hook(type => "sessioncgi", id => "inline", call => \&sessioncgi);
hook(type => "preprocess", id => "inline",
@@ -27,7 +28,6 @@ sub import { #{{{
# pings interrupting page builds.
hook(type => "change", id => "inline",
call => \&IkiWiki::pingurl);
-
} # }}}
sub getopt () { #{{{
@@ -39,8 +39,50 @@ sub getopt () { #{{{
"atom!" => \$config{atom},
"allowrss!" => \$config{allowrss},
"allowatom!" => \$config{allowatom},
+ "pingurl=s" => sub {
+ push @{$config{pingurl}}, $_[1];
+ },
);
-}
+} #}}}
+
+sub getsetup () { #{{{
+ return
+ rss => {
+ type => "boolean",
+ example => 0,
+ description => "enable rss feeds by default?",
+ safe => 1,
+ rebuild => 1,
+ },
+ atom => {
+ type => "boolean",
+ example => 0,
+ description => "enable atom feeds by default?",
+ safe => 1,
+ rebuild => 1,
+ },
+ allowrss => {
+ type => "boolean",
+ example => 0,
+ description => "allow rss feeds to be used?",
+ safe => 1,
+ rebuild => 1,
+ },
+ allowatom => {
+ type => "boolean",
+ example => 0,
+ description => "allow atom feeds to be used?",
+ safe => 1,
+ rebuild => 1,
+ },
+ pingurl => {
+ type => "string",
+ example => "http://rpc.technorati.com/rpc/ping",
+ description => "urls to ping (using XML-RPC) on feed update",
+ safe => 1,
+ rebuild => 0,
+ },
+} #}}}
sub checkconfig () { #{{{
if (($config{rss} || $config{atom}) && ! length $config{url}) {
@@ -52,6 +94,9 @@ sub checkconfig () { #{{{
if ($config{atom}) {
push @{$config{wiki_file_prune_regexps}}, qr/\.atom$/;
}
+ if (! exists $config{pingurl}) {
+ $config{pingurl}=[];
+ }
} #}}}
sub format (@) { #{{{
diff --git a/IkiWiki/Plugin/mdwn.pm b/IkiWiki/Plugin/mdwn.pm
index 11f3f0137..332325adc 100644
--- a/IkiWiki/Plugin/mdwn.pm
+++ b/IkiWiki/Plugin/mdwn.pm
@@ -7,9 +7,21 @@ use strict;
use IkiWiki 2.00;
sub import { #{{{
+ hook(type => "getsetup", id => "mdwn", call => \&getsetup);
hook(type => "htmlize", id => "mdwn", call => \&htmlize);
} # }}}
+sub getsetup () { #{{{
+ return
+ multimarkdown => {
+ type => "boolean",
+ example => 0,
+ description => "enable multimarkdown features?",
+ safe => 1,
+ rebuild => 1,
+ },
+} #}}}
+
my $markdown_sub;
sub htmlize (@) { #{{{
my %params=@_;
@@ -25,13 +37,13 @@ sub htmlize (@) { #{{{
if (exists $config{multimarkdown} && $config{multimarkdown}) {
eval q{use Text::MultiMarkdown};
if ($@) {
- error(gettext("multimarkdown is enabled, but Text::MultiMarkdown is not installed"));
+ debug(gettext("multimarkdown is enabled, but Text::MultiMarkdown is not installed"));
}
$markdown_sub=sub {
Text::MultiMarkdown::markdown(shift, {use_metadata => 0});
}
}
- else {
+ if (! defined $markdown_sub) {
eval q{use Text::Markdown};
if (! $@) {
if (Text::Markdown->can('markdown')) {
diff --git a/IkiWiki/Plugin/mirrorlist.pm b/IkiWiki/Plugin/mirrorlist.pm
index 3997e6fef..f7c78fdee 100644
--- a/IkiWiki/Plugin/mirrorlist.pm
+++ b/IkiWiki/Plugin/mirrorlist.pm
@@ -6,9 +6,21 @@ use strict;
use IkiWiki 2.00;
sub import { #{{{
+ hook(type => "getsetup", id => "mirrorlist", call => \&getsetup);
hook(type => "pagetemplate", id => "mirrorlist", call => \&pagetemplate);
} # }}}
+sub getsetup () { #{{{
+ return
+ mirrorlist => {
+ type => "string",
+ example => {},
+ description => "list of mirrors",
+ safe => 1,
+ rebuild => 1,
+ },
+} #}}}
+
sub pagetemplate (@) { #{{{
my %params=@_;
my $template=$params{template};
diff --git a/IkiWiki/Plugin/openid.pm b/IkiWiki/Plugin/openid.pm
index 10a8fa22f..de7f7280e 100644
--- a/IkiWiki/Plugin/openid.pm
+++ b/IkiWiki/Plugin/openid.pm
@@ -8,6 +8,7 @@ use IkiWiki 2.00;
sub import { #{{{
hook(type => "getopt", id => "openid", call => \&getopt);
+ hook(type => "getsetup", id => "openid", call => \&getsetup);
hook(type => "auth", id => "openid", call => \&auth);
hook(type => "formbuilder_setup", id => "openid",
call => \&formbuilder_setup, last => 1);
@@ -20,6 +21,17 @@ sub getopt () { #{{{
GetOptions("openidsignup=s" => \$config{openidsignup});
} #}}}
+sub getsetup () { #{{{
+ return
+ openidsignup => {
+ type => "string",
+ example => "http://myopenid.com/",
+ description => "an url where users can signup for an OpenID",
+ safe => 1,
+ rebuild => 0,
+ },
+} #}}}
+
sub formbuilder_setup (@) { #{{{
my %params=@_;
diff --git a/IkiWiki/Plugin/passwordauth.pm b/IkiWiki/Plugin/passwordauth.pm
index f3f1aa4bf..82afeef98 100644
--- a/IkiWiki/Plugin/passwordauth.pm
+++ b/IkiWiki/Plugin/passwordauth.pm
@@ -7,13 +7,30 @@ use strict;
use IkiWiki 2.00;
sub import { #{{{
- hook(type => "formbuilder_setup", id => "passwordauth",
- call => \&formbuilder_setup);
- hook(type => "formbuilder", id => "passwordauth",
- call => \&formbuilder);
+ hook(type => "getsetup", id => "passwordauth", "call" => \&getsetup);
+ hook(type => "formbuilder_setup", id => "passwordauth", call => \&formbuilder_setup);
+ hook(type => "formbuilder", id => "passwordauth", call => \&formbuilder);
hook(type => "sessioncgi", id => "passwordauth", call => \&sessioncgi);
} # }}}
+sub getsetup () { #{{{
+ return
+ account_creation_password => {
+ type => "string",
+ example => "s3cr1t",
+ description => "a password that must be entered when signing up for an account",
+ safe => 1,
+ rebuild => 0,
+ },
+ password_cost => {
+ type => "integer",
+ example => 8,
+ description => "cost of generating a password using Authen::Passphrase::BlowfishCrypt",
+ safe => 1,
+ rebuild => 0,
+ },
+} #}}}
+
# Checks if a string matches a user's password, and returns true or false.
sub checkpassword ($$;$) { #{{{
my $user=shift;
@@ -88,7 +105,9 @@ sub formbuilder_setup (@) { #{{{
if ($form->submitted eq "Register" || $form->submitted eq "Create Account") {
$form->field(name => "confirm_password", type => "password");
- $form->field(name => "account_creation_password", type => "password") if (length $config{account_creation_password});
+ $form->field(name => "account_creation_password", type => "password")
+ if (defined $config{account_creation_password} &&
+ length $config{account_creation_password});
$form->field(name => "email", size => 50);
$form->title("register");
$form->text("");
@@ -125,7 +144,8 @@ sub formbuilder_setup (@) { #{{{
shift eq $config{account_creation_password};
},
required => 1,
- ) if (length $config{account_creation_password});
+ ) if (defined $config{account_creation_password} &&
+ length $config{account_creation_password});
$form->field(
name => "email",
validate => "EMAIL",
@@ -259,7 +279,9 @@ sub formbuilder (@) { #{{{
error($@) if $@;
sendmail(
To => IkiWiki::userinfo_get($user_name, "email"),
- From => "$config{wikiname} admin <$config{adminemail}>",
+ From => "$config{wikiname} admin <".
+ (defined $config{adminemail} ? $config{adminemail} : "")
+ .">",
Subject => "$config{wikiname} information",
Message => $template->output,
) or error(gettext("Failed to send mail"));
diff --git a/IkiWiki/Plugin/pinger.pm b/IkiWiki/Plugin/pinger.pm
index 614d42885..e72833b8f 100644
--- a/IkiWiki/Plugin/pinger.pm
+++ b/IkiWiki/Plugin/pinger.pm
@@ -9,12 +9,24 @@ my %pages;
my $pinged=0;
sub import { #{{{
+ hook(type => "getsetup", id => "pinger", call => \&getsetup);
hook(type => "needsbuild", id => "pinger", call => \&needsbuild);
hook(type => "preprocess", id => "ping", call => \&preprocess);
hook(type => "delete", id => "pinger", call => \&ping);
hook(type => "change", id => "pinger", call => \&ping);
} # }}}
+sub getsetup () { #{{{
+ return
+ pinger_timeout => {
+ type => "integer",
+ example => 15,
+ description => "how many seconds to try pinging before timing out",
+ safe => 1,
+ rebuild => 0,
+ },
+} #}}}
+
sub needsbuild (@) { #{{{
my $needsbuild=shift;
foreach my $page (keys %pagestate) {
diff --git a/IkiWiki/Plugin/prettydate.pm b/IkiWiki/Plugin/prettydate.pm
index 745e6a1de..db5a94f41 100644
--- a/IkiWiki/Plugin/prettydate.pm
+++ b/IkiWiki/Plugin/prettydate.pm
@@ -40,9 +40,27 @@ sub default_timetable {
}
sub import { #{{{
+ hook(type => "getsetup", id => "prettydate", call => \&getsetup);
hook(type => "checkconfig", id => "prettydate", call => \&checkconfig);
} # }}}
+sub getsetup () { #{{{
+ return
+ prettydateformat => {
+ type => "string",
+ example => '%X, %B %o, %Y',
+ description => "format to use to display date",
+ safe => 1,
+ rebuild => 1,
+ },
+ timetable => {
+ type => "internal",
+ description => "array of time descriptions",
+ safe => 1,
+ rebuild => 1,
+ },
+} #}}}
+
sub checkconfig () { #{{{
if (! defined $config{prettydateformat} ||
$config{prettydateformat} eq '%c') {
diff --git a/IkiWiki/Plugin/recentchanges.pm b/IkiWiki/Plugin/recentchanges.pm
index 8383fb72a..d534d0cd9 100644
--- a/IkiWiki/Plugin/recentchanges.pm
+++ b/IkiWiki/Plugin/recentchanges.pm
@@ -6,6 +6,7 @@ use strict;
use IkiWiki 2.00;
sub import { #{{{
+ hook(type => "getsetup", id => "recentchanges", call => \&getsetup);
hook(type => "checkconfig", id => "recentchanges", call => \&checkconfig);
hook(type => "refresh", id => "recentchanges", call => \&refresh);
hook(type => "pagetemplate", id => "recentchanges", call => \&pagetemplate);
@@ -13,6 +14,24 @@ sub import { #{{{
hook(type => "cgi", id => "recentchanges", call => \&cgi);
} #}}}
+sub getsetup () { #{{{
+ return
+ recentchangespage => {
+ type => "string",
+ example => "recentchanges",
+ description => "name of the recentchanges page",
+ safe => 1,
+ rebuild => 1,
+ },
+ recentchangesnum => {
+ type => "integer",
+ example => 100,
+ description => "number of changes to track",
+ safe => 1,
+ rebuild => 0,
+ },
+} #}}}
+
sub checkconfig () { #{{{
$config{recentchangespage}='recentchanges' unless defined $config{recentchangespage};
$config{recentchangesnum}=100 unless defined $config{recentchangesnum};
diff --git a/IkiWiki/Plugin/search.pm b/IkiWiki/Plugin/search.pm
index eedfa6924..cb12d9500 100644
--- a/IkiWiki/Plugin/search.pm
+++ b/IkiWiki/Plugin/search.pm
@@ -7,6 +7,7 @@ use strict;
use IkiWiki 2.00;
sub import { #{{{
+ hook(type => "getsetup", id => "search", call => \&getsetup);
hook(type => "checkconfig", id => "search", call => \&checkconfig);
hook(type => "pagetemplate", id => "search", call => \&pagetemplate);
hook(type => "postscan", id => "search", call => \&index);
@@ -14,6 +15,17 @@ sub import { #{{{
hook(type => "cgi", id => "search", call => \&cgi);
} # }}}
+sub getsetup () { #{{{
+ return
+ omega_cgi => {
+ type => "string",
+ example => "/usr/lib/cgi-bin/omega/omega",
+ description => "path to the omega cgi program",
+ safe => 0, # external program
+ rebuild => 0,
+ },
+} #}}}
+
sub checkconfig () { #{{{
foreach my $required (qw(url cgiurl)) {
if (! length $config{$required}) {
@@ -21,7 +33,7 @@ sub checkconfig () { #{{{
}
}
- if (! exists $config{omega_cgi}) {
+ if (! defined $config{omega_cgi}) {
$config{omega_cgi}="/usr/lib/cgi-bin/omega/omega";
}
} #}}}
diff --git a/IkiWiki/Plugin/skeleton.pm.example b/IkiWiki/Plugin/skeleton.pm.example
index 1af8e4e9d..49c4d88f2 100644
--- a/IkiWiki/Plugin/skeleton.pm.example
+++ b/IkiWiki/Plugin/skeleton.pm.example
@@ -10,6 +10,7 @@ use IkiWiki 2.00;
sub import { #{{{
hook(type => "getopt", id => "skeleton", call => \&getopt);
+ hook(type => "getsetup", id => "skeleton", call => \&getsetup);
hook(type => "checkconfig", id => "skeleton", call => \&checkconfig);
hook(type => "needsbuild", id => "skeleton", call => \&needsbuild);
hook(type => "preprocess", id => "skeleton", call => \&preprocess);
@@ -38,6 +39,17 @@ sub getopt () { #{{{
debug("skeleton plugin getopt");
} #}}}
+sub getsetup () { #{{{
+ return
+ skeleton => {
+ type => "boolean",
+ example => 0,
+ description => "example option",
+ safe => 0,
+ rebuild => 0,
+ },
+} #}}}
+
sub checkconfig () { #{{{
debug("skeleton plugin checkconfig");
} #}}}
diff --git a/IkiWiki/Plugin/tag.pm b/IkiWiki/Plugin/tag.pm
index b0a0e53be..36b434f67 100644
--- a/IkiWiki/Plugin/tag.pm
+++ b/IkiWiki/Plugin/tag.pm
@@ -10,6 +10,7 @@ my %tags;
sub import { #{{{
hook(type => "getopt", id => "tag", call => \&getopt);
+ hook(type => "getsetup", id => "tag", call => \&getsetup);
hook(type => "preprocess", id => "tag", call => \&preprocess_tag, scan => 1);
hook(type => "preprocess", id => "taglink", call => \&preprocess_taglink, scan => 1);
hook(type => "pagetemplate", id => "tag", call => \&pagetemplate);
@@ -22,6 +23,17 @@ sub getopt () { #{{{
GetOptions("tagbase=s" => \$config{tagbase});
} #}}}
+sub getsetup () { #{{{
+ return
+ tagbase => {
+ type => "string",
+ example => "tag",
+ description => "parent page tags are located under",
+ safe => 1,
+ rebuild => 1,
+ },
+} #}}}
+
sub tagpage ($) { #{{{
my $tag=shift;
diff --git a/IkiWiki/Plugin/typography.pm b/IkiWiki/Plugin/typography.pm
index fe6996898..6229e6c33 100644
--- a/IkiWiki/Plugin/typography.pm
+++ b/IkiWiki/Plugin/typography.pm
@@ -8,6 +8,7 @@ use IkiWiki 2.00;
sub import { #{{{
hook(type => "getopt", id => "typography", call => \&getopt);
+ hook(type => "getsetup", id => "typography", call => \&getsetup);
IkiWiki::hook(type => "sanitize", id => "typography", call => \&sanitize);
} # }}}
@@ -18,11 +19,25 @@ sub getopt () { #{{{
GetOptions("typographyattributes=s" => \$config{typographyattributes});
} #}}}
+sub getsetup () { #{{{
+ eval q{use Text::Typography};
+ error($@) if $@;
+
+ return
+ typographyattributes => {
+ type => "string",
+ example => "3",
+ description => "Text::Typography attributes value",
+ safe => 1,
+ rebuild => 1,
+ },
+} #}}}
+
sub sanitize (@) { #{{{
my %params=@_;
eval q{use Text::Typography};
- error($@) if $@;
+ return $params{content} if $@;
my $attributes=defined $config{typographyattributes} ? $config{typographyattributes} : '3';
return Text::Typography::typography($params{content}, $attributes);
diff --git a/IkiWiki/Rcs/bzr.pm b/IkiWiki/Rcs/bzr.pm
index c80356159..5df522f6e 100644
--- a/IkiWiki/Rcs/bzr.pm
+++ b/IkiWiki/Rcs/bzr.pm
@@ -8,6 +8,50 @@ use IkiWiki;
use Encode;
use open qw{:utf8 :std};
+hook(type => "checkconfig", id => "bzr", call => sub { #{{{
+ if (! defined $config{diffurl}) {
+ $config{diffurl}="";
+ }
+ if (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 { #{{{
+ return
+ bzr_wrapper => {
+ type => "string",
+ #example => "", # FIXME add example
+ description => "bzr post-commit executable to generate",
+ safe => 0, # file
+ rebuild => 0,
+ },
+ bzr_wrappermode => {
+ type => "string",
+ example => '06755',
+ description => "mode for bzr_wrapper (can safely be made suid)",
+ safe => 0,
+ rebuild => 0,
+ },
+ historyurl => {
+ type => "string",
+ #example => "", # FIXME add example
+ description => "url to show file history, using loggerhead ([[file]] substituted)",
+ safe => 1,
+ rebuild => 1,
+ },
+ diffurl => {
+ type => "string",
+ example => "http://example.com/revision?start_revid=[[r2]]#[[file]]-s",
+ description => "url to view a diff, using loggerhead ([[file]] and [[r2]] substituted)",
+ safe => 1,
+ rebuild => 1,
+ },
+}); #}}}
+
sub bzr_log ($) { #{{{
my $out = shift;
my @infos = ();
diff --git a/IkiWiki/Rcs/git.pm b/IkiWiki/Rcs/git.pm
index ecf560d0b..6c9aca650 100644
--- a/IkiWiki/Rcs/git.pm
+++ b/IkiWiki/Rcs/git.pm
@@ -11,6 +11,70 @@ use open qw{:utf8 :std};
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 { #{{{
+ if (! defined $config{diffurl}) {
+ $config{diffurl}="";
+ }
+ if (! defined $config{gitorigin_branch}) {
+ $config{gitorigin_branch}="origin";
+ }
+ if (! defined $config{gitmaster_branch}) {
+ $config{gitmaster_branch}="master";
+ }
+ if (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 { #{{{
+ return
+ git_wrapper => {
+ type => "string",
+ example => "/git/wiki.git/hooks/post-update",
+ description => "git post-update executable to generate",
+ safe => 0, # file
+ rebuild => 0,
+ },
+ git_wrappermode => {
+ type => "string",
+ example => '06755',
+ description => "mode for git_wrapper (can safely be made suid)",
+ safe => 0,
+ rebuild => 0,
+ },
+ historyurl => {
+ type => "string",
+ example => "http://git.example.com/gitweb.cgi?p=wiki.git;a=history;f=[[file]]",
+ description => "gitweb url to show file history ([[file]] substituted)",
+ safe => 1,
+ rebuild => 1,
+ },
+ diffurl => {
+ type => "string",
+ example => "http://git.example.com/gitweb.cgi?p=wiki.git;a=blobdiff;h=[[sha1_to]];hp=[[sha1_from]];hb=[[sha1_parent]];f=[[file]]",
+ description => "gitweb url to show a diff ([[sha1_to]], [[sha1_from]], [[sha1_parent]], and [[file]] substituted)",
+ safe => 1,
+ rebuild => 1,
+ },
+ gitorigin_branch => {
+ type => "string",
+ example => "origin",
+ description => "where to pull and push changes (set to empty string to disable)",
+ safe => 0, # paranoia
+ rebuild => 0,
+ },
+ gitmaster_branch => {
+ type => "string",
+ example => "master",
+ description => "branch that the wiki is stored in",
+ safe => 0, # paranoia
+ rebuild => 0,
+ },
+}); #}}}
+
sub _safe_git (&@) { #{{{
# Start a child process safely without resorting /bin/sh.
# Return command output or success state (in scalar context).
diff --git a/IkiWiki/Rcs/mercurial.pm b/IkiWiki/Rcs/mercurial.pm
index 8c3f03e07..3a98e09d8 100644
--- a/IkiWiki/Rcs/mercurial.pm
+++ b/IkiWiki/Rcs/mercurial.pm
@@ -8,7 +8,51 @@ use IkiWiki;
use Encode;
use open qw{:utf8 :std};
-sub mercurial_log($) {
+hook(type => "checkconfig", id => "mercurial", call => sub { #{{{
+ if (! defined $config{diffurl}) {
+ $config{diffurl}="";
+ }
+ if (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 { #{{{
+ return
+ mercurial_wrapper => {
+ type => "string",
+ #example => # FIXME add example
+ description => "mercurial post-commit executable to generate",
+ safe => 0, # file
+ rebuild => 0,
+ },
+ mercurial_wrappermode => {
+ type => "string",
+ example => '06755',
+ description => "mode for mercurial_wrapper (can safely be made suid)",
+ safe => 0,
+ rebuild => 0,
+ },
+ historyurl => {
+ type => "string",
+ example => "http://example.com:8000/log/tip/[[file]]",
+ description => "url to hg serve'd repository, to show file history ([[file]] substituted)",
+ safe => 1,
+ rebuild => 1,
+ },
+ diffurl => {
+ type => "string",
+ example => "http://localhost:8000/?fd=[[r2]];file=[[file]]",
+ description => "url to hg serve'd repository, to show diff ([[file]] and [[r2]] substituted)",
+ safe => 1,
+ rebuild => 1,
+ },
+}); #}}}
+
+sub mercurial_log ($) { #{{{
my $out = shift;
my @infos;
@@ -52,7 +96,7 @@ sub mercurial_log($) {
close $out;
return @infos;
-}
+} #}}}
sub rcs_update () { #{{{
my @cmdline = ("hg", "-q", "-R", "$config{srcdir}", "update");
diff --git a/IkiWiki/Rcs/monotone.pm b/IkiWiki/Rcs/monotone.pm
index 500af5c58..d7e8f296a 100644
--- a/IkiWiki/Rcs/monotone.pm
+++ b/IkiWiki/Rcs/monotone.pm
@@ -11,7 +11,7 @@ use Date::Format qw(time2str);
my $sha1_pattern = qr/[0-9a-fA-F]{40}/; # pattern to validate sha1sums
-sub check_config() { #{{{
+hook(type => "checkconfig", id => "monotone", call => sub { #{{{
if (!defined($config{mtnrootdir})) {
$config{mtnrootdir} = $config{srcdir};
}
@@ -19,9 +19,6 @@ sub check_config() { #{{{
error("Ikiwiki srcdir does not seem to be a Monotone workspace (or set the mtnrootdir)!");
}
- chdir $config{srcdir}
- or error("Cannot chdir to $config{srcdir}: $!");
-
my $child = open(MTN, "-|");
if (! $child) {
open STDERR, ">/dev/null";
@@ -43,7 +40,66 @@ sub check_config() { #{{{
if ($version < 0.38) {
error("Monotone version too old, is $version but required 0.38");
}
-} #}}}
+
+ if (length $config{mtn_wrapper}) {
+ push @{$config{wrappers}}, {
+ wrapper => $config{mtn_wrapper},
+ wrappermode => (defined $config{mtn_wrappermode} ? $config{mtn_wrappermode} : "06755"),
+ };
+ }
+}); #}}}
+
+hook(type => "getsetup", id => "monotone", call => sub { #{{{
+ return
+ mtn_wrapper => {
+ type => "string",
+ example => "/srv/mtn/wiki/_MTN/ikiwiki-netsync-hook",
+ description => "monotone netsync hook executable to generate",
+ safe => 0, # file
+ rebuild => 0,
+ },
+ mtn_wrappermode => {
+ type => "string",
+ example => '06755',
+ description => "mode for mtn_wrapper (can safely be made suid)",
+ safe => 0,
+ rebuild => 0,
+ },
+ mtnkey => {
+ type => "string",
+ example => 'web@example.com',
+ description => "your monotone key",
+ safe => 1,
+ rebuild => 0,
+ },
+ historyurl => {
+ type => "string",
+ example => "http://viewmtn.example.com/branch/head/filechanges/com.example.branch/[[file]]",
+ description => "viewmtn url to show file history ([[file]] substituted)",
+ safe => 1,
+ rebuild => 1,
+ },
+ diffurl => {
+ type => "string",
+ example => "http://viewmtn.example.com/revision/diff/[[r1]]/with/[[r2]]/[[file]]",
+ description => "viewmtn url to show a diff ([[r1]], [[r2]], and [[file]] substituted)",
+ safe => 1,
+ rebuild => 1,
+ },
+ mtnsync => {
+ type => "boolean",
+ example => 0,
+ description => "sync on update and commit?",
+ safe => 0, # paranoia
+ rebuild => 0,
+ },
+ mtnrootdir => {
+ type => "string",
+ description => "path to your workspace (defaults to the srcdir; specify if the srcdir is a subdirectory of the workspace)",
+ safe => 0, # path
+ rebuild => 0,
+ },
+}); #}}}
sub get_rev () { #{{{
my $sha1 = `mtn --root=$config{mtnrootdir} automate get_base_revision_id`;
@@ -190,7 +246,8 @@ sub get_changed_files ($$) { #{{{
} #}}}
sub rcs_update () { #{{{
- check_config();
+ chdir $config{srcdir}
+ or error("Cannot chdir to $config{srcdir}: $!");
if (defined($config{mtnsync}) && $config{mtnsync}) {
if (system("mtn", "--root=$config{mtnrootdir}", "sync",
@@ -208,7 +265,8 @@ sub rcs_update () { #{{{
sub rcs_prepedit ($) { #{{{
my $file=shift;
- check_config();
+ chdir $config{srcdir}
+ or error("Cannot chdir to $config{srcdir}: $!");
# For monotone, return the revision of the file when
# editing begins.
@@ -236,7 +294,8 @@ sub rcs_commit ($$$;$$) { #{{{
$author="Web: Anonymous";
}
- check_config();
+ chdir $config{srcdir}
+ or error("Cannot chdir to $config{srcdir}: $!");
my ($oldrev)= $rcstoken=~ m/^($sha1_pattern)$/; # untaint
my $rev = get_rev();
@@ -367,7 +426,8 @@ sub rcs_commit_staged ($$$) {
# Note - this will also commit any spurious changes that happen to be
# lying around in the working copy. There shouldn't be any, but...
- check_config();
+ chdir $config{srcdir}
+ or error("Cannot chdir to $config{srcdir}: $!");
my $author;
@@ -391,7 +451,8 @@ sub rcs_commit_staged ($$$) {
sub rcs_add ($) { #{{{
my $file=shift;
- check_config();
+ chdir $config{srcdir}
+ or error("Cannot chdir to $config{srcdir}: $!");
if (system("mtn", "--root=$config{mtnrootdir}", "add", "--quiet",
$file) != 0) {
@@ -402,7 +463,8 @@ sub rcs_add ($) { #{{{
sub rcs_remove ($) { # {{{
my $file = shift;
- check_config();
+ chdir $config{srcdir}
+ or error("Cannot chdir to $config{srcdir}: $!");
# Note: it is difficult to undo a remove in Monotone at the moment.
# Until this is fixed, it might be better to make 'rm' move things
@@ -420,7 +482,8 @@ sub rcs_remove ($) { # {{{
sub rcs_rename ($$) { # {{{
my ($src, $dest) = @_;
- check_config();
+ chdir $config{srcdir}
+ or error("Cannot chdir to $config{srcdir}: $!");
if (system("mtn", "--root=$config{mtnrootdir}", "rename", "--quiet",
$src, $dest) != 0) {
@@ -432,7 +495,8 @@ sub rcs_recentchanges ($) { #{{{
my $num=shift;
my @ret;
- check_config();
+ chdir $config{srcdir}
+ or error("Cannot chdir to $config{srcdir}: $!");
# use log --brief to get a list of revs, as this
# gives the results in a nice order
@@ -539,7 +603,8 @@ sub rcs_diff ($) { #{{{
my $rev=shift;
my ($sha1) = $rev =~ /^($sha1_pattern)$/; # untaint
- check_config();
+ chdir $config{srcdir}
+ or error("Cannot chdir to $config{srcdir}: $!");
my $child = open(MTNDIFF, "-|");
if (! $child) {
@@ -561,7 +626,8 @@ sub rcs_diff ($) { #{{{
sub rcs_getctime ($) { #{{{
my $file=shift;
- check_config();
+ chdir $config{srcdir}
+ or error("Cannot chdir to $config{srcdir}: $!");
my $child = open(MTNLOG, "-|");
if (! $child) {
diff --git a/IkiWiki/Rcs/svn.pm b/IkiWiki/Rcs/svn.pm
index 9081c3902..0e7df3659 100644
--- a/IkiWiki/Rcs/svn.pm
+++ b/IkiWiki/Rcs/svn.pm
@@ -1,23 +1,78 @@
#!/usr/bin/perl
-package IkiWiki::Rcs::svn;
+package IkiWiki;
use warnings;
use strict;
use IkiWiki;
use POSIX qw(setlocale LC_CTYPE);
-sub import { #{{{
- if (exists $IkiWiki::config{svnpath}) {
+hook(type => "checkconfig", id => "svn", call => sub { #{{{
+ if (! defined $config{diffurl}) {
+ $config{diffurl}="";
+ }
+ if (! defined $config{svnpath}) {
+ $config{svnpath}="trunk";
+ }
+ if (exists $config{svnpath}) {
# code depends on the path not having extraneous slashes
- $IkiWiki::config{svnpath}=~tr#/#/#s;
- $IkiWiki::config{svnpath}=~s/\/$//;
- $IkiWiki::config{svnpath}=~s/^\///;
+ $config{svnpath}=~tr#/#/#s;
+ $config{svnpath}=~s/\/$//;
+ $config{svnpath}=~s/^\///;
}
-} #}}}
-
-
-package IkiWiki;
+ if (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 { #{{{
+ return
+ svnrepo => {
+ type => "string",
+ example => "/svn/wiki",
+ description => "subversion repository location",
+ safe => 0, # path
+ rebuild => 0,
+ },
+ svnpath => {
+ type => "string",
+ example => "trunk",
+ description => "path inside repository where the wiki is located",
+ safe => 0, # paranoia
+ rebuild => 0,
+ },
+ svn_wrapper => {
+ type => "string",
+ example => "/svn/wikirepo/hooks/post-commit",
+ description => "svn post-commit executable to generate",
+ safe => 0, # file
+ rebuild => 0,
+ },
+ svn_wrappermode => {
+ type => "string",
+ example => '04755',
+ description => "mode for svn_wrapper (can safely be made suid)",
+ safe => 0,
+ rebuild => 0,
+ },
+ historyurl => {
+ type => "string",
+ example => "http://svn.example.org/trunk/[[file]]",
+ description => "viewvc url to show file history ([[file]] substituted)",
+ safe => 1,
+ rebuild => 1,
+ },
+ diffurl => {
+ type => "string",
+ example => "http://svn.example.org/trunk/[[file]]?root=wiki&amp;r1=[[r1]]&amp;r2=[[r2]]",
+ description => "viewvc url to show a diff ([[file]], [[r1]], and [[r2]] substituted)",
+ 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() {
diff --git a/IkiWiki/Rcs/tla.pm b/IkiWiki/Rcs/tla.pm
index 4232e1fe8..e1389a346 100644
--- a/IkiWiki/Rcs/tla.pm
+++ b/IkiWiki/Rcs/tla.pm
@@ -6,6 +6,50 @@ use warnings;
use strict;
use IkiWiki;
+hook(type => "checkconfig", id => "tla", call => sub { #{{{
+ if (! defined $config{diffurl}) {
+ $config{diffurl}="";
+ }
+ if (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 { #{{{
+ return
+ tla_wrapper => {
+ type => "string",
+ #example => "", # TODO example
+ description => "tla post-commit executable to generate",
+ safe => 0, # file
+ rebuild => 0,
+ },
+ tla_wrappermode => {
+ type => "string",
+ example => '06755',
+ description => "mode for tla_wrapper (can safely be made suid)",
+ safe => 0,
+ rebuild => 0,
+ },
+ historyurl => {
+ type => "string",
+ #example => "", # TODO example
+ description => "url to show file history ([[file]] substituted)",
+ safe => 1,
+ rebuild => 1,
+ },
+ diffurl => {
+ type => "string",
+ #example => "", # TODO example
+ description => "url to show a diff ([[file]] and [[rev]] substituted)",
+ safe => 1,
+ rebuild => 1,
+ },
+}); #}}}
+
sub quiet_system (@) {
# See Debian bug #385939.
open (SAVEOUT, ">&STDOUT");
diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm
index 90058199c..cb92d1ade 100644
--- a/IkiWiki/Render.pm
+++ b/IkiWiki/Render.pm
@@ -68,7 +68,7 @@ sub genpage ($$) { #{{{
$actions++;
}
- if (length $config{historyurl}) {
+ if (defined $config{historyurl} && length $config{historyurl}) {
my $u=$config{historyurl};
$u=~s/\[\[file\]\]/$pagesources{$page}/g;
$template->param(historyurl => $u);
diff --git a/IkiWiki/Setup.pm b/IkiWiki/Setup.pm
index 3b7a11253..38b715202 100644
--- a/IkiWiki/Setup.pm
+++ b/IkiWiki/Setup.pm
@@ -1,20 +1,18 @@
#!/usr/bin/perl
# Ikiwiki setup files are perl files that 'use IkiWiki::Setup::foo',
# passing it some sort of configuration data.
-#
-# There can be multiple modules, with different configuration styles.
-# The setup modules each convert the data into the hashes used by ikiwiki
-# internally (if it's not already in that format), and store it in
-# IkiWiki::Setup::$raw_setup, to pass it back to this module.
package IkiWiki::Setup;
use warnings;
use strict;
use IkiWiki;
-use IkiWiki::Wrapper;
use open qw{:utf8 :std};
+# There can be multiple modules, with different configuration styles.
+# The setup modules each convert the data into the hashes used by ikiwiki
+# internally (if it's not already in that format), and store it in
+# IkiWiki::Setup::$raw_setup, to pass it back to this module.
our $raw_setup;
sub load ($) { # {{{
@@ -34,54 +32,33 @@ sub load ($) { # {{{
eval $code;
error("$setup: ".$@) if $@;
- my $ret=$raw_setup;
+ my %setup=%{$raw_setup};
$raw_setup=undef;
- return %$ret;
-} #}}}
-
-package IkiWiki;
-
-sub setup () { #{{{
- my %setup=IkiWiki::Setup::load($config{setup});
-
- $setup{plugin}=$config{plugin};
+ # Merge setup into existing config and untaint.
if (exists $setup{add_plugins}) {
- push @{$setup{plugin}}, @{$setup{add_plugins}};
- delete $setup{add_plugins};
+ push @{$setup{add_plugins}}, @{$config{add_plugins}};
}
if (exists $setup{exclude}) {
push @{$config{wiki_file_prune_regexps}}, $setup{exclude};
}
-
- if (! $config{render} && (! $config{refresh} || $config{wrappers})) {
- debug(gettext("generating wrappers.."));
- my @wrappers=@{$setup{wrappers}};
- delete $setup{wrappers};
- my %startconfig=(%config);
- foreach my $wrapper (@wrappers) {
- %config=(%startconfig, rebuild => 0, verbose => 0, %setup, %{$wrapper});
- checkconfig();
- if (! $config{cgi} && ! $config{post_commit}) {
- $config{post_commit}=1;
- }
- gen_wrapper();
- }
- %config=(%startconfig);
- }
-
foreach my $c (keys %setup) {
- next if $c eq 'syslog';
if (defined $setup{$c}) {
- if (! ref $setup{$c}) {
- $config{$c}=possibly_foolish_untaint($setup{$c});
+ if (! ref $setup{$c} || ref $setup{$c} eq 'Regexp') {
+ $config{$c}=IkiWiki::possibly_foolish_untaint($setup{$c});
}
elsif (ref $setup{$c} eq 'ARRAY') {
- $config{$c}=[map { possibly_foolish_untaint($_) } @{$setup{$c}}]
+ if ($c eq 'wrappers') {
+ # backwards compatability code
+ $config{$c}=$setup{$c};
+ }
+ else {
+ $config{$c}=[map { IkiWiki::possibly_foolish_untaint($_) } @{$setup{$c}}]
+ }
}
elsif (ref $setup{$c} eq 'HASH') {
foreach my $key (keys %{$setup{$c}}) {
- $config{$c}{$key}=possibly_foolish_untaint($setup{$c}{$key});
+ $config{$c}{$key}=IkiWiki::possibly_foolish_untaint($setup{$c}{$key});
}
}
}
@@ -90,32 +67,24 @@ sub setup () { #{{{
}
}
- if (! $config{refresh}) {
- $config{rebuild}=1;
- }
-
- loadplugins();
- checkconfig();
-
- require IkiWiki::Render;
-
- if ($config{render}) {
- commandline_render();
- }
-
- if (! $config{refresh}) {
- debug(gettext("rebuilding wiki.."));
- }
- else {
- debug(gettext("refreshing wiki.."));
+ if (length $config{cgi_wrapper}) {
+ push @{$config{wrappers}}, {
+ cgi => 1,
+ wrapper => $config{cgi_wrapper},
+ wrappermode => (defined $config{cgi_wrappermode} ? $config{cgi_wrappermode} : "06755"),
+ };
}
+} #}}}
- lockwiki();
- loadindex();
- refresh();
+sub dump ($) { #{{{
+ my $file=IkiWiki::possibly_foolish_untaint(shift);
+
+ require IkiWiki::Setup::Standard;
+ my @dump=IkiWiki::Setup::Standard::gendump("Setup file for ikiwiki.");
- debug(gettext("done"));
- saveindex();
-} #}}}
+ open (OUT, ">", $file) || die "$file: $!";
+ print OUT "$_\n" foreach @dump;
+ close OUT;
+}
1
diff --git a/IkiWiki/Setup/Standard.pm b/IkiWiki/Setup/Standard.pm
index f67c3829b..d96964a23 100644
--- a/IkiWiki/Setup/Standard.pm
+++ b/IkiWiki/Setup/Standard.pm
@@ -7,9 +7,118 @@ package IkiWiki::Setup::Standard;
use warnings;
use strict;
+use IkiWiki;
-sub import {
+sub import { #{{{
$IkiWiki::Setup::raw_setup=$_[1];
-}
+} #}}}
+
+sub dumpline ($$$$) { #{{{
+ my $key=shift;
+ my $value=shift;
+ my $type=shift;
+ my $prefix=shift;
+
+ eval q{use Data::Dumper};
+ error($@) if $@;
+ local $Data::Dumper::Terse=1;
+ local $Data::Dumper::Indent=1;
+ local $Data::Dumper::Pad="\t";
+ local $Data::Dumper::Sortkeys=1;
+ local $Data::Dumper::Quotekeys=0;
+
+ my $dumpedvalue;
+ if ($type eq 'boolean' || $type eq 'integer') {
+ # avoid quotes
+ $dumpedvalue=$value;
+ }
+ elsif ($type eq 'string' && ref $value eq 'ARRAY' && @$value &&
+ ! grep { /[^-A-Za-z0-9_]/ } @$value) {
+ # dump simple array as qw{}
+ $dumpedvalue="[qw{ ".join(" ", @$value)." }]";
+ }
+ else {
+ $dumpedvalue=Dumper($value);
+ chomp $dumpedvalue;
+ if (length $prefix) {
+ # add to second and subsequent lines
+ my @lines=split(/\n/, $dumpedvalue);
+ $dumpedvalue="";
+ for (my $x=0; $x <= $#lines; $x++) {
+ $lines[$x] =~ s/^\t//;
+ $dumpedvalue.="\t".($x ? $prefix : "").$lines[$x]."\n";
+ }
+ }
+ $dumpedvalue=~s/^\t//;
+ chomp $dumpedvalue;
+ }
+
+ return "\t$prefix$key => $dumpedvalue,";
+} #}}}
+
+sub dumpvalues ($@) { #{{{
+ my $setup=shift;
+ my @ret;
+ while (@_) {
+ my $key=shift;
+ my %info=%{shift()};
+
+ next if $info{type} eq "internal";
+
+ push @ret, "\t# ".$info{description} if exists $info{description};
+
+ if (exists $setup->{$key} && defined $setup->{$key}) {
+ push @ret, dumpline($key, $setup->{$key}, $info{type}, "");
+ delete $setup->{$key};
+ }
+ elsif (exists $info{example}) {
+ push @ret, dumpline($key, $info{example}, $info{type}, "#");
+ }
+ }
+ return @ret;
+} #}}}
+
+sub gendump ($) { #{{{
+ my $description=shift;
+ my %setup=(%config);
+ my @ret;
+
+ push @ret, "\t# basic setup";
+ push @ret, dumpvalues(\%setup, IkiWiki::getsetup());
+
+ # Load all plugins, so that all setup options are available.
+ my @plugins=grep { ! /externaldemo|pythondemo/ } sort(IkiWiki::listplugins());
+ foreach my $plugin (@plugins) {
+ eval { IkiWiki::loadplugin($plugin) };
+ if (exists $IkiWiki::hooks{checkconfig}{$plugin}{call}) {
+ my @s=eval { $IkiWiki::hooks{checkconfig}{$plugin}{call}->() };
+ }
+ }
+ unshift @plugins, $config{rcs} if $config{rcs};
+
+ foreach my $id (@plugins) {
+ my $title="\t# $id".($id ne $config{rcs} ? " plugin" : "");
+ if (exists $IkiWiki::hooks{getsetup}{$id}{call}) {
+ # use an array rather than a hash, to preserve order
+ my @s=eval { $IkiWiki::hooks{getsetup}{$id}{call}->() };
+ next unless @s;
+ push @ret, "", $title;
+ push @ret, dumpvalues(\%setup, @s);
+ }
+ }
+
+ unshift @ret,
+ "#!/usr/bin/perl",
+ "# $description",
+ "#",
+ "# Passing this to ikiwiki --setup will make ikiwiki generate",
+ "# wrappers and build the wiki.",
+ "#",
+ "# Remember to re-run ikiwiki --setup any time you edit this file.",
+ "use IkiWiki::Setup::Standard {";
+ push @ret, "}";
+
+ return @ret;
+} #}}}
1
diff --git a/Makefile.PL b/Makefile.PL
index 8c7ac7019..01a59eaf6 100755
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -62,7 +62,7 @@ extra_install:
install -d $(DESTDIR)$(PREFIX)/lib/ikiwiki/plugins
for file in `find plugins -maxdepth 1 -type f ! -wholename plugins/.\*`; do \
- install -m 755 $$file $(DESTDIR)$(PREFIX)/lib/ikiwiki/plugins; \
+ cp -a $$file $(DESTDIR)$(PREFIX)/lib/ikiwiki/plugins; \
done; \
install -d $(DESTDIR)$(PREFIX)/share/man/man1
diff --git a/debian/changelog b/debian/changelog
index 348d30997..205620508 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,13 @@
+ikiwiki (2.60) UNRELEASED; urgency=low
+
+ * 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.
+ * The way wrappers are defined in the setup file has changed. Old setup
+ files will continue to work, for now.
+
+ -- Joey Hess <joeyh@debian.org> Mon, 21 Jul 2008 11:35:46 -0400
+
ikiwiki (2.55) UNRELEASED; urgency=low
* remove: New plugin that adds the ability to remove pages via the web.
diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn
index 7c28088de..686f7e518 100644
--- a/doc/plugins/write.mdwn
+++ b/doc/plugins/write.mdwn
@@ -357,6 +357,47 @@ something. The hook is passed named parameters: `page`, `oldpage`,
`newpage`, and `content`, and should try to modify the content to reflect
the name change. For example, by converting links to point to the new page.
+### getsetup
+
+ hook(type => "getsetup", id => "foo", call => \&getsetup);
+
+This hooks is not called during normal operation, but only when setting up
+the wiki, or generating a setup file. Plugins can use this hook to add
+configuration options.
+
+The hook is passed no parameters. It returns data about the configuration
+options added by the plugin. It can also check if the plugin is usable, and
+die if the plugin is not available, which will cause the plugin to not be
+offered in the configuration interface.
+
+The data returned is a list of `%config` options, followed by a hash
+describing the option. For example:
+
+ return
+ option_foo => {
+ type => "boolean",
+ description => "enable foo",
+ safe => 1,
+ rebuild => 1,
+ },
+ option_bar => {
+ type => "string",
+ example => "hello",
+ description => "what to say",
+ safe => 1,
+ rebuild => 0,
+ },
+
+* `type` can be "boolean", "string", "integer", "internal" (used for values
+ that are not user-visible). The type is the type of the leaf values;
+ the `%config` option may be an array or hash of these.
+* `example` can be set to an example value.
+* `description` is a short description of the option.
+* `safe` should be false if the option should not be displayed in unsafe
+ configuration methods, such as the web interface. Anything that specifies
+ a command to run, a path on disk, or a regexp should be marked as unsafe.
+* `rebuild` should be true if changing the option will require a wiki rebuild.
+
## Plugin interface
To import the ikiwiki plugin interface:
diff --git a/doc/setup.mdwn b/doc/setup.mdwn
index 174d6ceb9..9c67c2a6c 100644
--- a/doc/setup.mdwn
+++ b/doc/setup.mdwn
@@ -74,11 +74,16 @@ and `--rebuild` too. Get comfortable with its command line (see
By now you should be getting tired of typing in all the command line
options each time you change something in your wiki's setup. Time to
introduce setup files.
-
-A sample setup file is [[ikiwiki.setup]]. Download it (or copy it from
-`doc/ikiwiki.setup` in the ikiwiki sources), and edit it. Note that this
-file should *not* be put in your wiki's directory with the rest of the
-files. A good place to put it is in a ~/.ikiwiki/ subdirectory.
+
+To generate a setup file, use `ikiwiki --dumpsetup`. You can pass
+all the options have you been including at the command line, and they
+will be stored in the setup file.
+
+ ikiwiki $SRCDIR $DESTDIR --url=http://example.org/~you/wiki/ --dumpsetup ikiwiki.setup
+
+Note that this file should *not* be put in your wiki's directory with
+the rest of the files. A good place to put it is in a ~/.ikiwiki/
+subdirectory.
Most of the options, like `wikiname` in the setup file are the same as
ikiwiki's command line options (documented in [[usage]]. `srcdir` and
@@ -91,12 +96,12 @@ will set everything up.
## Turn on additional features.
-Now you have a basic wiki with a configuration file. Time to experiment
+Now you have a basic wiki with a setup file. Time to experiment
with ikiwiki's many features.
Let's first enable a key wiki feature and set up [[CGI]] to allow
editing the wiki from the web. Just edit ikiwiki.setup, uncomment the
-block for the cgi wrapper, make sure the filename for the cgi wrapper
+settings for the `cgi_wrapper`, make sure the filename for the cgi wrapper
is ok, run `ikiwiki --setup ikiwiki.setup`, and you're done!
There are lots of other configuration options in ikiwiki.setup that you
@@ -113,7 +118,7 @@ on the revision control system you choose, the way this is done varies.
Note that the .ikiwiki subdirectory is where ikiwiki keeps its state, and
should be preserved, but not checked into revision control.
-The new [[ikiwiki-makerepo]] command automates setting up a wiki in
+The [[ikiwiki-makerepo]] command automates setting up a wiki in
revision control.
[[!toggle id=subversion text="Subversion"]]
@@ -167,7 +172,7 @@ about using the git repositories.
# remember the password you use in the next step and
# substitute it for 'wikiKeyPass' in the get_passphrase() hook below
# note the you should never generate two monotone keys with the same name
- mtn genkey web@machine.company.com
+ mtn genkey web@example.com
mtn db init --db=$REPOSITORY
mv $SRCDIR $SRCDIR-old
cd $SRCDIR-old
@@ -188,11 +193,11 @@ about using the git repositories.
Once your wiki is checked in to the revision control system,
you should configure ikiwiki to use revision control. Edit your
-ikiwiki.setup, and uncomment the lines for the revision control system
+ikiwiki.setup, set `rcs` to the the revision control system
you chose to use. Be sure to set `svnrepo` to $REPOSITORY, if using
-subversion. Uncomment the block for the wrapper for your revision
-control system, and configure the wrapper path in that block
-appropriately (for Git, it should be `$REPOSITORY/hooks/post-update`).
+subversion. Uncomment the configuration for the wrapper for your revision
+control system, and configure the wrapper path appropriately
+(for Git, it should be `$REPOSITORY/hooks/post-update`).
Once it's all set up, run `ikiwiki --setup ikiwiki.setup` once more.
Now you should be able to edit files in $SRCDIR, and use your revision
diff --git a/doc/usage.mdwn b/doc/usage.mdwn
index 2b104bcdb..473d1c9b1 100644
--- a/doc/usage.mdwn
+++ b/doc/usage.mdwn
@@ -62,6 +62,11 @@ These options control the mode that ikiwiki operates in.
If you only want to build any changed pages, you can use --refresh with
--setup.
+* --dumpsetup configfile
+
+ Causes ikiwiki to write to the specified config file, dumping out
+ its current configuration.
+
* --wrappers
If used with --setup --refresh, this makes it also update any configured
diff --git a/ikiwiki.in b/ikiwiki.in
index 3bb881c43..febc8ff56 100755
--- a/ikiwiki.in
+++ b/ikiwiki.in
@@ -20,6 +20,7 @@ sub getconfig () { #{{{
Getopt::Long::Configure('pass_through');
GetOptions(
"setup|s=s" => \$config{setup},
+ "dumpsetup|s=s" => \$config{dumpsetup},
"wikiname=s" => \$config{wikiname},
"verbose|v!" => \$config{verbose},
"syslog!" => \$config{syslog},
@@ -27,7 +28,7 @@ sub getconfig () { #{{{
"refresh!" => \$config{refresh},
"post-commit" => \$config{post_commit},
"render=s" => \$config{render},
- "wrappers!" => \$config{wrappers},
+ "wrappers!" => \$config{genwrappers},
"usedirs!" => \$config{usedirs},
"prefix-directives!" => \$config{prefix_directives},
"getctime" => \$config{getctime},
@@ -45,7 +46,6 @@ sub getconfig () { #{{{
"adminemail=s" => \$config{adminemail},
"timeformat=s" => \$config{timeformat},
"sslcookie!" => \$config{sslcookie},
- "httpauth!" => \$config{httpauth},
"userdir=s" => \$config{userdir},
"htmlext=s" => \$config{htmlext},
"libdir=s" => \$config{libdir},
@@ -68,14 +68,11 @@ sub getconfig () { #{{{
$config{wrappermode}=possibly_foolish_untaint($_[1])
},
"plugin=s@" => sub {
- push @{$config{plugin}}, $_[1];
+ push @{$config{add_plugins}}, $_[1];
},
"disable-plugin=s@" => sub {
push @{$config{disable_plugins}}, $_[1];
},
- "pingurl=s" => sub {
- push @{$config{pingurl}}, $_[1];
- },
"set=s" => sub {
my ($var, $val)=split('=', $_[1], 2);
if (! defined $var || ! defined $val) {
@@ -114,7 +111,47 @@ sub main () { #{{{
if ($config{setup}) {
require IkiWiki::Setup;
- setup();
+ IkiWiki::Setup::load($config{setup});
+ if (@{$config{wrappers}} &&
+ ! $config{render} && ! $config{dumpsetup} &&
+ (! $config{refresh} || $config{genwrappers})) {
+ debug(gettext("generating wrappers.."));
+ require IkiWiki::Wrapper;
+ my %origconfig=(%config);
+ my @wrappers=@{$config{wrappers}};
+ delete $config{wrappers};
+ delete $config{genwrappers};
+ foreach my $wrapper (@wrappers) {
+ %config=(%origconfig,
+ rebuild => 0,
+ verbose => 0,
+ %{$wrapper},
+ );
+ checkconfig();
+ if (! $config{cgi} && ! $config{post_commit}) {
+ $config{post_commit}=1;
+ }
+ gen_wrapper();
+ }
+ %config=(%origconfig);
+ }
+
+ # setup implies a wiki rebuild by default
+ if (! $config{refresh}) {
+ $config{rebuild}=1;
+ }
+
+ # ignore syslog setting from setup file
+ # while doing initial setup
+ $config{syslog}=0 unless $config{dumpsetup};
+
+ loadplugins();
+ checkconfig();
+ }
+
+ if ($config{dumpsetup}) {
+ require IkiWiki::Setup;
+ IkiWiki::Setup::dump($config{dumpsetup});
}
elsif ($config{wrapper}) {
lockwiki();
@@ -136,12 +173,19 @@ sub main () { #{{{
# do nothing
}
else {
+ if (! $config{refresh}) {
+ debug(gettext("rebuilding wiki.."));
+ }
+ else {
+ debug(gettext("refreshing wiki.."));
+ }
lockwiki();
loadindex();
require IkiWiki::Render;
rcs_update();
refresh();
saveindex();
+ debug(gettext("done"));
}
} #}}}