Merge branch 'tova' into autoconfig
authorJoey Hess <joey@kodama.kitenet.net>
Tue, 29 Jul 2008 19:54:45 +0000 (15:54 -0400)
committerJoey Hess <joey@kodama.kitenet.net>
Tue, 29 Jul 2008 19:54:45 +0000 (15:54 -0400)
Conflicts:

debian/changelog

60 files changed:
.gitignore
IkiWiki.pm
IkiWiki/Plugin/aggregate.pm
IkiWiki/Plugin/amazon_s3.pm
IkiWiki/Plugin/anonok.pm
IkiWiki/Plugin/attachment.pm
IkiWiki/Plugin/bzr.pm [moved from IkiWiki/Rcs/bzr.pm with 66% similarity]
IkiWiki/Plugin/calendar.pm
IkiWiki/Plugin/git.pm [moved from IkiWiki/Rcs/git.pm with 79% similarity]
IkiWiki/Plugin/graphviz.pm
IkiWiki/Plugin/inline.pm
IkiWiki/Plugin/mdwn.pm
IkiWiki/Plugin/mercurial.pm [moved from IkiWiki/Rcs/mercurial.pm with 60% similarity]
IkiWiki/Plugin/mirrorlist.pm
IkiWiki/Plugin/monotone.pm [moved from IkiWiki/Rcs/monotone.pm with 82% similarity]
IkiWiki/Plugin/norcs.pm [new file with mode: 0644]
IkiWiki/Plugin/openid.pm
IkiWiki/Plugin/passwordauth.pm
IkiWiki/Plugin/pinger.pm
IkiWiki/Plugin/prettydate.pm
IkiWiki/Plugin/recentchanges.pm
IkiWiki/Plugin/search.pm
IkiWiki/Plugin/shortcut.pm
IkiWiki/Plugin/skeleton.pm.example
IkiWiki/Plugin/svn.pm [moved from IkiWiki/Rcs/svn.pm with 72% similarity]
IkiWiki/Plugin/tag.pm
IkiWiki/Plugin/tla.pm [moved from IkiWiki/Rcs/tla.pm with 71% similarity]
IkiWiki/Plugin/typography.pm
IkiWiki/Rcs/Stub.pm [deleted file]
IkiWiki/Render.pm
IkiWiki/Setup.pm
IkiWiki/Setup/Automator.pm [new file with mode: 0644]
IkiWiki/Setup/Standard.pm
Makefile.PL
auto.setup [new file with mode: 0644]
debian/changelog
debian/examples
debian/rules
doc/bugs/Command-line_arguments_should_override_settings_in_the_setup_file.mdwn
doc/ikiwiki-update-wikilist.mdwn
doc/ikiwiki.setup [deleted file]
doc/plugins.mdwn
doc/plugins/mirrorlist.mdwn
doc/plugins/write.mdwn
doc/rcs/details.mdwn
doc/security.mdwn
doc/setup.mdwn
doc/tips/nearlyfreespeech.mdwn
doc/todo/Make_example_setup_file_consistent.mdwn
doc/todo/cas_authentication.mdwn
doc/todo/color_plugin.mdwn
doc/todo/conditional_underlay_files.mdwn
doc/todo/online_configuration.mdwn
doc/usage.mdwn
doc/w3mmode/ikiwiki.setup
docwiki.setup
ikiwiki-update-wikilist
ikiwiki.in
po/ikiwiki.pot
t/syntax.t

index bb02bcb31de37ae41831c6be5c4cf85f9c207a42..57991a732d698238d8af3ac0e6094d7c445974a9 100644 (file)
@@ -1,3 +1,4 @@
+ikiwiki.setup
 Makefile
 Makefile.old
 blib/*
index 3f8a4bca334debb8a5728b25b258dac50c112f89..ad41215c1e31dd2964312a6f6a48d2aa6508920e 100644 (file)
@@ -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 () { #{{{
@@ -130,16 +414,13 @@ sub checkconfig () { #{{{
                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 (exists $config{umask}) {
+       if (defined $config{umask}) {
                umask(possibly_foolish_untaint($config{umask}));
        }
 
@@ -148,12 +429,32 @@ sub checkconfig () { #{{{
        return 1;
 } #}}}
 
+sub listplugins () { #{{{
+       my %ret;
+
+       foreach my $dir (@INC, $config{libdir}) {
+               next unless defined $dir && length $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 && length $dir;
+               foreach my $file (glob("$dir/plugins/*")) {
+                       $ret{basename($file)}=1 if -x $file;
+               }
+       }
+
+       return keys %ret;
+} #}}}
+
 sub loadplugins () { #{{{
-       if (defined $config{libdir}) {
+       if (defined $config{libdir} && length $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) {
@@ -1124,6 +1425,46 @@ sub run_hooks ($$) { # {{{
        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);
 
index e000bc8648a39f33cea5aef932286255f343f4a2..673668c0ee02cf049740144dbe442d610a7068d2 100644 (file)
@@ -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())) {
index 187700f30d911dee95009a7d2515ef3aca61e176..e181a84da04c6c152b74397fcf5d304a46d1344c 100644 (file)
@@ -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}) {
index 1880516d568b35e2b96463676d23c04c62f103f2..7b966f845338775cb07cc317af7c1b27ca6e811c 100644 (file)
@@ -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;
index 720078be15cfcd51399f375815b4d22e1a2e8d7b..47e165251376ffa817b014fc041ae1a9cc9aa9d3 100644 (file)
@@ -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
similarity index 66%
rename from IkiWiki/Rcs/bzr.pm
rename to IkiWiki/Plugin/bzr.pm
index c80356159f6d97080063da5964bdb904f114e1e2..99025a973db235605cf64448e9ccdd04e1fc687b 100644 (file)
@@ -1,6 +1,5 @@
 #!/usr/bin/perl
-
-package IkiWiki;
+package IkiWiki::Plugin::bzr;
 
 use warnings;
 use strict;
@@ -8,6 +7,62 @@ use IkiWiki;
 use Encode;
 use open qw{:utf8 :std};
 
+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{bzr_wrapper} && length $config{bzr_wrapper}) {
+               push @{$config{wrappers}}, {
+                       wrapper => $config{bzr_wrapper},
+                       wrappermode => (defined $config{bzr_wrappermode} ? $config{bzr_wrappermode} : "06755"),
+               };
+       }
+} #}}}
+
+sub getsetup () { #{{{
+       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 = ();
@@ -57,10 +112,10 @@ sub bzr_author ($$) { #{{{
        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";
@@ -72,7 +127,7 @@ sub rcs_commit ($$$;$$) { #{{{
 
        $user = bzr_author($user, $ipaddr);
 
-       $message = possibly_foolish_untaint($message);
+       $message = IkiWiki::possibly_foolish_untaint($message);
        if (! length $message) {
                $message = "no message given";
        }
@@ -93,7 +148,7 @@ sub rcs_commit_staged ($$$) {
 
        $user = bzr_author($user, $ipaddr);
 
-       $message = possibly_foolish_untaint($message);
+       $message = IkiWiki::possibly_foolish_untaint($message);
        if (! length $message) {
                $message = "no message given";
        }
@@ -128,7 +183,7 @@ sub rcs_remove ($) { # {{{
 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");
        }
@@ -167,7 +222,7 @@ sub rcs_recentchanges ($) { #{{{
                        # Skip source name in renames
                        $filename =~ s/^.* => //;
 
-                       my $diffurl = $config{'diffurl'};
+                       my $diffurl = defined $config{'diffurl'} ? $config{'diffurl'} : "";
                        $diffurl =~ s/\[\[file\]\]/$filename/go;
                        $diffurl =~ s/\[\[file-id\]\]/$fileid/go;
                        $diffurl =~ s/\[\[r2\]\]/$info->{revno}/go;
index aed087eed58248d5da153543dba03abba17b5ef0..6f1f9bd0729d5ccc539fc83a8bd32cb58274a2c0 100644 (file)
@@ -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));
similarity index 79%
rename from IkiWiki/Rcs/git.pm
rename to IkiWiki/Plugin/git.pm
index ecf560d0ba8dc09edf2c48da59eddd0cfe864143..5e302729ea1c26c80c93d4974e94e8a57e444012 100644 (file)
@@ -1,6 +1,5 @@
 #!/usr/bin/perl
-
-package IkiWiki;
+package IkiWiki::Plugin::git;
 
 use warnings;
 use strict;
@@ -11,7 +10,83 @@ 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
 
-sub _safe_git (&@) { #{{{
+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{gitorigin_branch}) {
+               $config{gitorigin_branch}="origin";
+       }
+       if (! defined $config{gitmaster_branch}) {
+               $config{gitmaster_branch}="master";
+       }
+       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"),
+               };
+       }
+} #}}}
+
+sub getsetup () { #{{{
+       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).
 
@@ -43,12 +118,12 @@ sub _safe_git (&@) { #{{{
        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
@@ -142,7 +217,7 @@ sub _merge_past ($$$) { #{{{
        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.
 
@@ -262,7 +337,7 @@ sub git_commit_info ($;$) { #{{{
        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;
        }
 
@@ -315,7 +390,7 @@ sub rcs_commit ($$$;$$) { #{{{
        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;
        }
 
@@ -338,7 +413,7 @@ sub rcs_commit_staged ($$$) {
 
        # 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}) {
@@ -394,7 +469,7 @@ sub rcs_recentchanges ($) { #{{{
                foreach my $detail (@{ $ci->{'details'} }) {
                        my $file = $detail->{'file'};
 
-                       my $diffurl = $config{'diffurl'};
+                       my $diffurl = defined $config{'diffurl'} ? $config{'diffurl'} : "";
                        $diffurl =~ s/\[\[file\]\]/$file/go;
                        $diffurl =~ s/\[\[sha1_parent\]\]/$ci->{'parent'}/go;
                        $diffurl =~ s/\[\[sha1_from\]\]/$detail->{'sha1_from'}/go;
index b13d15fa6350aadd237494350dd1c8949bf72700..021aa6b230c2a61b0a2289d2bbccc4e83abe4ae6 100644 (file)
@@ -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 = (
index 2f09019431b44fd4c5ab458f44fe90026367d996..ed7a584083aeb1cc1b55c321851a094664acb608 100644 (file)
@@ -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 (@) { #{{{
@@ -202,7 +247,7 @@ sub preprocess_inline (@) { #{{{
        my $atomurl=basename(atompage($params{destpage}).$feednum) if $feeds && $atom;
        my $ret="";
 
-       if ($config{cgiurl} && ! $params{preview} && (exists $params{rootpage} ||
+       if (length $config{cgiurl} && ! $params{preview} && (exists $params{rootpage} ||
                        (exists $params{postform} && yesno($params{postform})))) {
                # Add a blog post form, with feed buttons.
                my $formtemplate=template("blogpost.tmpl", blind_cache => 1);
index 11f3f0137627643fe285e0464b59b2e0086b3f88..332325adc814134520381b088e7524b335342921 100644 (file)
@@ -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')) {
similarity index 60%
rename from IkiWiki/Rcs/mercurial.pm
rename to IkiWiki/Plugin/mercurial.pm
index 8c3f03e07145a84f38e80f515b0918be26c9e382..d2c34fa6a5810c43ac999fb23184a08dab1abc76 100644 (file)
@@ -1,6 +1,5 @@
 #!/usr/bin/perl
-
-package IkiWiki;
+package IkiWiki::Plugin::mercurial;
 
 use warnings;
 use strict;
@@ -8,7 +7,63 @@ use IkiWiki;
 use Encode;
 use open qw{:utf8 :std};
 
-sub mercurial_log($) {
+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 (exists $config{mercurial_wrapper} && length $config{mercurial_wrapper}) {
+               push @{$config{wrappers}}, {
+                       wrapper => $config{mercurial_wrapper},
+                       wrappermode => (defined $config{mercurial_wrappermode} ? $config{mercurial_wrappermode} : "06755"),
+               };
+       }
+} #}}}
+
+sub getsetup () { #{{{
+       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 +107,7 @@ sub mercurial_log($) {
        close $out;
 
        return @infos;
-}
+} #}}}
 
 sub rcs_update () { #{{{
        my @cmdline = ("hg", "-q", "-R", "$config{srcdir}", "update");
@@ -69,16 +124,16 @@ sub rcs_commit ($$$;$$) { #{{{
        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";
        }
@@ -141,7 +196,7 @@ sub rcs_recentchanges ($) { #{{{
                }
 
                foreach my $file (split / /,$info->{files}) {
-                       my $diffurl = $config{'diffurl'};
+                       my $diffurl = defined $config{diffurl} ? $config{'diffurl'} : "";
                        $diffurl =~ s/\[\[file\]\]/$file/go;
                        $diffurl =~ s/\[\[r2\]\]/$info->{changeset}/go;
 
index 3997e6fefcd31c15a8fa6df7e559a6ffdf84e863..f7c78fdee33769584278b131955b8eac28291716 100644 (file)
@@ -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};
similarity index 82%
rename from IkiWiki/Rcs/monotone.pm
rename to IkiWiki/Plugin/monotone.pm
index 500af5c587abba1816dd3144c840c54e1afad8a2..4b9be316a4e602f5aaa075c8c62f2e8ade8e3ed2 100644 (file)
@@ -1,6 +1,5 @@
 #!/usr/bin/perl
-
-package IkiWiki;
+package IkiWiki::Plugin::monotone;
 
 use warnings;
 use strict;
@@ -11,7 +10,22 @@ use Date::Format qw(time2str);
 
 my $sha1_pattern = qr/[0-9a-fA-F]{40}/; # pattern to validate sha1sums
 
-sub check_config() { #{{{
+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};
        }
@@ -19,9 +33,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,6 +54,65 @@ 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"),
+               };
+       }
+} #}}}
+
+sub getsetup () { #{{{
+       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 () { #{{{
@@ -100,7 +170,7 @@ sub mtn_merge ($$$$) { #{{{
        return $mergeRev;
 } #}}}
 
-sub commit_file_to_new_rev($$$$$$$$) { #{{{
+sub commit_file_to_new_rev ($$$$$$$$) { #{{{
        my $automator=shift;
        my $wsfilename=shift;
        my $oldFileID=shift;
@@ -190,7 +260,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 +279,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 +308,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();
@@ -339,7 +412,7 @@ sub rcs_commit ($$$;$$) { #{{{
 
        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",
@@ -367,7 +440,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;
 
@@ -383,7 +457,7 @@ sub rcs_commit_staged ($$$) {
 
        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");
        }
 }
@@ -391,7 +465,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 +477,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 +496,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 +509,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 +617,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 +640,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/Plugin/norcs.pm b/IkiWiki/Plugin/norcs.pm
new file mode 100644 (file)
index 0000000..72c6656
--- /dev/null
@@ -0,0 +1,58 @@
+#!/usr/bin/perl
+# Stubs for no revision control.
+package IkiWiki::Plugin::norcs;
+
+use warnings;
+use strict;
+use IkiWiki;
+
+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 ($$$;$$) { #{{{
+       my ($file, $message, $rcstoken, $user, $ipaddr) = @_;
+       return undef # success
+} #}}}
+
+sub rcs_commit_staged ($$$) { #{{{
+       my ($message, $user, $ipaddr)=@_;
+       return undef # success
+} #}}}
+
+sub rcs_add ($) { #{{{
+} #}}}
+
+sub rcs_remove ($) { #{{{
+} #}}}
+
+sub rcs_rename ($$) { #{{{
+} #}}}
+
+sub rcs_recentchanges ($) { #{{{
+} #}}}
+
+sub rcs_diff ($) { #{{{
+} #}}}
+
+sub rcs_getctime ($) { #{{{
+       error gettext("getctime not implemented");
+} #}}}
+
+1
index 10a8fa22f46aa8116f10e13a48ac01678b8ba997..de7f7280e91ce304e91dac1fa2165f5c4326be32 100644 (file)
@@ -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=@_;
 
index f3f1aa4bf2b7b5f761859d7a75a2c0d68f8b4eb7..82afeef989e517171a416749d27194a1e435b672 100644 (file)
@@ -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"));
index 614d428853c7d0d2efbaa74987edc97e6643a452..e72833b8f45353c2fc79c4008412adf813a50e20 100644 (file)
@@ -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) {
index 745e6a1de436e2db15b97ebe897858f891de2a51..db5a94f413b567de7c73f2cb93ac90e1d9697461 100644 (file)
@@ -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') {
index 8383fb72a12e19c8d92627956efc154855ff57e5..d534d0cd96f6a92416a507b34ff3d38c1ac1b7b0 100644 (file)
@@ -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};
index eedfa69244a166092b543b51e61a360b486a00f5..cb12d9500d95a31545426fd3c984e3297286d457 100644 (file)
@@ -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";
        }
 } #}}}
index 8df60cfe2a34b5e428e1eafcae88ac9c71a3c0ed..dfc3cd7c7b3a68a1df29d9d183400e535ea86e0a 100644 (file)
@@ -6,11 +6,11 @@ use strict;
 use IkiWiki 2.00;
 
 sub import { #{{{
-       hook(type => "checkconfig", id => "shortcut", call => \&checkconfig);
+       hook(type => "refresh", id => "shortcut", call => \&refresh);
        hook(type => "preprocess", id => "shortcut", call => \&preprocess_shortcut);
 } #}}}
 
-sub checkconfig () { #{{{
+sub refresh () { #{{{
        # Preprocess the shortcuts page to get all the available shortcuts
        # defined before other pages are rendered.
        my $srcfile=srcfile("shortcuts.mdwn", 1);
index 10c7002e478919ca5b84a74549350ecc815a5377..bbf11e603839a24f787f0f2ec02ac0f7774f9235 100644 (file)
@@ -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 => "refresh", id => "skeleton", call => \&refresh);
        hook(type => "needsbuild", id => "skeleton", call => \&needsbuild);
@@ -39,6 +40,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");
 } #}}}
similarity index 72%
rename from IkiWiki/Rcs/svn.pm
rename to IkiWiki/Plugin/svn.pm
index 9081c39027b0d21e3cfb15b4e3716c7f1b0fcc3d..51683704c5928d6e5577a3e1f92b62adbb41849f 100644 (file)
@@ -1,6 +1,5 @@
 #!/usr/bin/perl
-
-package IkiWiki::Rcs::svn;
+package IkiWiki::Plugin::svn;
 
 use warnings;
 use strict;
@@ -8,16 +7,83 @@ use IkiWiki;
 use POSIX qw(setlocale LC_CTYPE);
 
 sub import { #{{{
-       if (exists $IkiWiki::config{svnpath}) {
+       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{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/^\///;
+       }
+       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"),
+               };
        }
 } #}}}
 
-
-package IkiWiki;
+sub getsetup () { #{{{
+       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() {
@@ -105,7 +171,7 @@ sub rcs_commit ($$$;$$) { #{{{
 
                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) {
@@ -131,7 +197,7 @@ sub rcs_commit_staged ($$$) {
        
        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     
@@ -144,10 +210,10 @@ sub rcs_add ($) { #{{{
        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) {
@@ -249,7 +315,7 @@ sub rcs_recentchanges ($) { #{{{
                                $file=$1;
                        }
 
-                       my $diffurl=$config{diffurl};
+                       my $diffurl=defined $config{diffurl} ? $config{diffurl} : "";
                        $diffurl=~s/\[\[file\]\]/$file/g;
                        $diffurl=~s/\[\[r1\]\]/$rev - 1/eg;
                        $diffurl=~s/\[\[r2\]\]/$rev/g;
@@ -274,7 +340,7 @@ sub rcs_recentchanges ($) { #{{{
 } #}}}
 
 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`;
 } #}}}
 
index b0a0e53be7cec3c73147ce61fe353aaa9b8a3d69..36b434f675c5d0303aa9bd4962bd7302e85afdd0 100644 (file)
@@ -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;
                        
similarity index 71%
rename from IkiWiki/Rcs/tla.pm
rename to IkiWiki/Plugin/tla.pm
index 4232e1fe8372429902b7438f20e6c0c25189ce52..6faaecccc5d7a48a1f44e3fd40aa6376c8d8cf48 100644 (file)
@@ -1,12 +1,67 @@
 #!/usr/bin/perl
-
-package IkiWiki;
+package IkiWiki::Plugin::tla;
 
 use warnings;
 use strict;
 use IkiWiki;
 
-sub quiet_system (@) {
+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{tla_wrapper} && length $config{tla_wrapper}) {
+               push @{$config{wrappers}}, {
+                       wrapper => $config{tla_wrapper},
+                       wrappermode => (defined $config{tla_wrappermode} ? $config{tla_wrappermode} : "06755"),
+               };
+       }
+} #}}}
+
+sub getsetup () { #{{{
+       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");
        close STDOUT;
@@ -16,7 +71,7 @@ sub quiet_system (@) {
        open (STDOUT, ">&SAVEOUT");
        close SAVEOUT;
        return $ret;
-}
+} #}}}
 
 sub rcs_update () { #{{{
        if (-d "$config{srcdir}/{arch}") {
@@ -66,7 +121,7 @@ sub rcs_commit ($$$;$$) { #{{{
                }
 
                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) {
@@ -157,7 +212,7 @@ sub rcs_recentchanges ($) {
                my @pages;
 
                foreach my $file (@paths) {
-                       my $diffurl=$config{diffurl};
+                       my $diffurl=defined $config{diffurl} ? $config{diffurl} : "";
                        $diffurl=~s/\[\[file\]\]/$file/g;
                        $diffurl=~s/\[\[rev\]\]/$change/g;
                        push @pages, {
index fe69968981029f07e0a60c2903bfb9e02fe6a4a6..6229e6c33258b9d6a12a43c8957cb5facbcb3739 100644 (file)
@@ -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/Stub.pm b/IkiWiki/Rcs/Stub.pm
deleted file mode 100644 (file)
index 04ba5f0..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/usr/bin/perl
-# Stubs for no revision control.
-
-package IkiWiki;
-
-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.
-       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.
-       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.
-       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_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_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_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_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_getctime ($) {
-       # Optional, used to get the page creation time from the RCS.
-       error gettext("getctime not implemented");
-}
-
-1
index 90058199c128ebd68f7fa41c2e0f4d71c36e6d32..cb92d1ade947290edef6afd14636fd4d15c8ca63 100644 (file)
@@ -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);
index 3b7a112539acf794e855a6daffb192f657c49f11..c2fd59b21479f96bc4d70d68981a36e0edfed593 100644 (file)
@@ -1,22 +1,14 @@
 #!/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};
 
-our $raw_setup;
-
 sub load ($) { # {{{
        my $setup=IkiWiki::possibly_foolish_untaint(shift);
        delete $config{setup};
@@ -33,55 +25,35 @@ sub load ($) { # {{{
 
        eval $code;
        error("$setup: ".$@) if $@;
-
-       my $ret=$raw_setup;
-       $raw_setup=undef;
-
-       return %$ret;
 } #}}}
 
-package IkiWiki;
+sub merge ($) {
+       my %setup=%{shift()};
 
-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 +62,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/Automator.pm b/IkiWiki/Setup/Automator.pm
new file mode 100644 (file)
index 0000000..ee83a2f
--- /dev/null
@@ -0,0 +1,136 @@
+#!/usr/bin/perl
+# Ikiwiki setup automator.
+
+package IkiWiki::Setup::Automator;
+
+use warnings;
+use strict;
+use IkiWiki;
+use IkiWiki::UserInfo;
+use Term::ReadLine;
+use File::Path;
+
+sub ask ($$) { #{{{
+       my ($question, $default)=@_;
+
+       my $r=Term::ReadLine->new("ikiwiki");
+       $r->readline($question." ", $default);
+} #}}}
+
+sub prettydir ($) { #{{{
+       my $dir=shift;
+       $dir=~s/^\Q$ENV{HOME}\E\//~\//;
+       return $dir;
+} #}}}
+
+sub import (@) { #{{{
+       my $this=shift;
+       IkiWiki::Setup::merge({@_});
+
+       # Sanitize this to avoid problimatic directory names.
+       $config{wikiname}=~s/[^-A-Za-z0-9_] //g;
+       if (! length $config{wikiname}) {
+               die "you must enter a wikiname\n";
+       }
+
+       # Avoid overwriting any existing files.
+       foreach my $key (qw{srcdir destdir repository dumpsetup}) {
+               next unless exists $config{$key};
+               my $add="";
+               while (-e $add.$config{$key}) {
+                       $add=1 if ! $add;
+                       $add++;
+               }
+               $config{$key}=$add.$config{$key};
+       }
+
+       IkiWiki::checkconfig();
+
+       print "\n\nSetting up $config{wikiname} ...\n";
+
+       # Set up the repository.
+       mkpath($config{srcdir}) || die "mkdir $config{srcdir}: $!";
+       delete $config{repository} if ! $config{rcs} || $config{rcs}=~/bzr|mercurial/;
+       if ($config{rcs}) {
+               my @params=($config{rcs}, $config{srcdir});
+               push @params, $config{repository} if exists $config{repository};
+               if (system("ikiwiki-makerepo", @params) != 0) {
+                       die "failed: ikiwiki-makerepo @params";
+               }
+       }
+
+       # Generate setup file.
+       require IkiWiki::Setup;
+       if ($config{rcs}) {
+               if ($config{rcs} eq 'git') {
+                       $config{git_wrapper}=$config{repository}."/hooks/post-update";
+               }
+               elsif ($config{rcs} eq 'svn') {
+                       $config{svn_wrapper}=$config{repository}."/hooks/post-commit";
+               }
+               elsif ($config{rcs} eq 'bzr') {
+                       # TODO
+               }
+               elsif ($config{rcs} eq 'mercurial') {
+                       # TODO
+               }
+       }
+       IkiWiki::Setup::dump($config{dumpsetup});
+
+       # Build the wiki, but w/o wrappers, so it's not live yet.
+       mkpath($config{destdir}) || die "mkdir $config{destdir}: $!";
+       if (system("ikiwiki", "--refresh", "--setup", $config{dumpsetup}) != 0) {
+               die "ikiwiki --refresh --setup $config{dumpsetup} failed";
+       }
+
+       # Create admin user(s).
+       foreach my $admin (@{$config{adminuser}}) {
+               next if $admin=~/^http\?:\/\//; # openid
+               
+               # Prompt for password w/o echo.
+               system('stty -echo 2>/dev/null');
+               local $|=1;
+               print "\n\nCreating wiki admin $admin ...\n";
+               print "Choose a password: ";
+               chomp(my $password=<STDIN>);
+               print "\n\n\n";
+               system('stty sane 2>/dev/null');
+
+               if (IkiWiki::userinfo_setall($admin, { regdate => time }) &&
+                   IkiWiki::Plugin::passwordauth::setpassword($admin, $password)) {
+                       IkiWiki::userinfo_set($admin, "email", $config{adminemail}) if defined $config{adminemail};
+               }
+               else {
+                       error("problem setting up $admin user");
+               }
+       }
+       
+       # Add wrappers, make live.
+       if (system("ikiwiki", "--wrappers", "--setup", $config{dumpsetup}) != 0) {
+               die "ikiwiki --wrappers --setup $config{dumpsetup} failed";
+       }
+
+       # Add it to the wikilist.
+       mkpath("$ENV{HOME}/.ikiwiki");
+       open (WIKILIST, ">>$ENV{HOME}/.ikiwiki/wikilist") || die "$ENV{HOME}/.ikiwiki/wikilist: $!";
+       print WIKILIST "$ENV{USER} $config{dumpsetup}\n";
+       close WIKILIST;
+       if (system("ikiwiki-update-wikilist") != 0) {
+               print STDERR "** Failed to add you to the system wikilist file.\n";
+               print STDERR "** (Probably ikiwiki-update-wikilist is not SUID root.)\n";
+               print STDERR "** Your wiki will not be automatically updated when ikiwiki is upgraded.\n";
+       }
+       
+       # Done!
+       print "\n\nSuccessfully set up $config{wikiname}:\n";
+       foreach my $key (qw{url srcdir destdir repository}) {
+               next unless exists $config{$key};
+               print "\t$key: ".(" " x (10 - length($key)))." ".
+                       prettydir($config{$key})."\n";
+       }
+       print "To modify settings, edit ".prettydir($config{dumpsetup})." and then run:\n";
+       print " ikiwiki -setup ".prettydir($config{dumpsetup})."\n";
+       exit 0;
+} #}}}
+
+1
index f67c3829b71d437dc73ed7477196d9323247ece4..9d4732b6f87825c3594f061ec6a41dcee6c8203e 100644 (file)
@@ -7,9 +7,125 @@ package IkiWiki::Setup::Standard;
 
 use warnings;
 use strict;
+use IkiWiki;
 
-sub import {
-       $IkiWiki::Setup::raw_setup=$_[1];
-}
+sub import { #{{{
+       IkiWiki::Setup::merge($_[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}, "#");
+               }
+               else {
+                       push @ret, dumpline($key, "", $info{type}, "#");
+               }
+       }
+       return @ret;
+} #}}}
+
+sub gendump ($) { #{{{
+       my $description=shift;
+       my %setup=(%config);
+       my @ret;
+       
+       # disable logging to syslog while dumping
+       $config{syslog}=0;
+
+       push @ret, "\t# basic setup";
+       push @ret, dumpvalues(\%setup, IkiWiki::getsetup());
+
+       # Load all plugins, so that all setup options are available.
+       # (But skip a few problematic external demo plugins.)
+       my @plugins=grep { ! /^(externaldemo|pythondemo|\Q$config{rcs}\E)$/ }
+               sort(IkiWiki::listplugins());
+       unshift @plugins, $config{rcs} if $config{rcs}; # rcs plugin 1st
+       foreach my $plugin (@plugins) {
+               eval { IkiWiki::loadplugin($plugin) };
+               if (exists $IkiWiki::hooks{checkconfig}{$plugin}{call}) {
+                       my @s=eval { $IkiWiki::hooks{checkconfig}{$plugin}{call}->() };
+               }
+       }
+
+       foreach my $id (@plugins) {
+               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, "", "\t# $id plugin";
+                       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
index 8c7ac70190ad26eba142abe79bb3a703036dd27e..a805f41a244ec1d473b0e626ad04940ab608eab5 100755 (executable)
@@ -30,7 +30,10 @@ ikiwiki.out: ikiwiki.in
        ./pm_filter $(PREFIX) $(VER) $(PROBABLE_INST_LIB) < ikiwiki.in > ikiwiki.out
        chmod +x ikiwiki.out
 
-extra_build: ikiwiki.out
+ikiwiki.setup: ikiwiki.out
+       HOME=/home/me $(PERL) -Iblib/lib $(extramodules) $(tflag) ikiwiki.out -libdir . -dumpsetup ikiwiki.setup
+
+extra_build: ikiwiki.out ikiwiki.setup
        $(PERL) -Iblib/lib $(extramodules) $(tflag) ikiwiki.out -libdir . -setup docwiki.setup -refresh
        ./mdwn2man ikiwiki 1 doc/usage.mdwn > ikiwiki.man
        ./mdwn2man ikiwiki-mass-rebuild 8 doc/ikiwiki-mass-rebuild.mdwn > ikiwiki-mass-rebuild.man
@@ -41,11 +44,14 @@ extra_build: ikiwiki.out
 
 extra_clean:
        rm -rf html doc/.ikiwiki
-       rm -f *.man ikiwiki.out
-       rm -f plugins/*.pyc
+       rm -f *.man ikiwiki.out ikiwiki.setup plugins/*.pyc
        $(MAKE) -C po clean
 
 extra_install:
+       install -d $(DESTDIR)/etc/ikiwiki
+       install -m 0644 wikilist $(DESTDIR)/etc/ikiwiki
+       install -m 0644 auto.setup $(DESTDIR)/etc/ikiwiki
+
        install -d $(DESTDIR)$(PREFIX)/share/ikiwiki
        for dir in `cd underlays && find . -follow -type d ! -regex '.*\.svn.*'`; do \
                install -d $(DESTDIR)$(PREFIX)/share/ikiwiki/$$dir; \
@@ -62,7 +68,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/auto.setup b/auto.setup
new file mode 100644 (file)
index 0000000..6958a76
--- /dev/null
@@ -0,0 +1,43 @@
+#!/usr/bin/perl
+# Ikiwiki setup automator.
+# 
+# This setup file causes ikiwiki to create a wiki, check it into revision
+# control, generate a setup file for the new wiki, and set everything up.
+#
+# Just run: ikiwiki -setup /etc/ikiwiki/auto.setup
+#
+# By default, it asks a few questions, and confines itself to the user's home
+# directory. You can edit it to change what it asks questions about, or to
+# modify the values to use site-specific settings.
+
+require IkiWiki::Setup::Automator;
+
+our $wikiname=IkiWiki::Setup::Automator::ask(
+       "What will the wiki be named?", "wiki");
+our $rcs=IkiWiki::Setup::Automator::ask(
+       "What revision control system to use?", "git");
+our $admin=IkiWiki::Setup::Automator::ask(
+       "What wiki user (or openid) will be wiki admin?", $ENV{USER});
+our $hostname=`hostname -f`; chomp $hostname;
+
+IkiWiki::Setup::Automator->import(
+       wikiname => $wikiname,
+       adminuser => [$admin],
+       rcs => $rcs,
+       srcdir => "$ENV{HOME}/$wikiname",
+       destdir => "$ENV{HOME}/public_html/$wikiname",
+       repository => "$ENV{HOME}/$wikiname.$rcs",
+       dumpsetup => "$ENV{HOME}/$wikiname.setup",
+       url => "http://$hostname/~$ENV{USER}/$wikiname",
+       cgiurl => "http://$hostname/~$ENV{USER}/$wikiname/ikiwiki.cgi",
+       cgi_wrapper => "$ENV{HOME}/public_html/$wikiname/ikiwiki.cgi",
+       adminemail => "$ENV{USER}\@$hostname",
+       add_plugins => [qw{ goodstuff }],
+       disable_plugins => [qw{  }],
+       libdir => "$ENV{HOME}/.ikiwiki",
+       rss => 1,
+       atom => 1,
+       syslog => 1,
+       prefix_directives => 1,
+       hardlink => 1,
+)
index 7fd135700aef62b92e76edcb8dc5ddca2c8297b1..c4e4b7f48a34b1bbac5c92b6ed1090662ef37421 100644 (file)
@@ -1,3 +1,19 @@
+ikiwiki (2.60) UNRELEASED; urgency=low
+  * Starting with this version, "ikiwiki -setup /etc/ikiwiki/auto.setup"
+    can be used set up a new wiki in seconds.
+  * 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.
+  * ikiwiki-update-wikilist: Add -r switch to remove. Default behavior is now
+    always to add.
+
+ -- Joey Hess <joeyh@debian.org>  Mon, 21 Jul 2008 11:35:46 -0400
+
 ikiwiki (2.56) UNRELEASED; urgency=low
 
   * autoindex: New plugin that generates missing index pages.
index d94312ed00f9af26ba392b0e9b6c21f989286ab8..a1e6231929cd8e6a42c6b076bf3caa2d285598ba 100644 (file)
@@ -1 +1 @@
-doc/ikiwiki.setup
+ikiwiki.setup
index 2af69a5f793753418b8a31a4e6376ccb41479f90..25b1f57b6a636ffe170efaf6b208bb61346ef9b9 100755 (executable)
@@ -24,7 +24,6 @@ binary-indep: build
        dh_testroot
        dh_clean -k
        $(MAKE) pure_install DESTDIR=$(shell pwd)/debian/ikiwiki
-       dh_install wikilist etc/ikiwiki
        dh_installdocs html
        dh_installexamples doc/examples/*
        dh_link usr/share/common-licenses/GPL-2 usr/share/doc/ikiwiki/html/GPL
index f1ccf589689c1c95ede9d83423c597d05429a69f..22b1c2cb5e2e5e5c23e2b9135a5933391d45df56 100644 (file)
@@ -1,5 +1,5 @@
 In setting up my wiki I followed the [[setup]] instruction which point
-to an [[ikiwiki.setup]] file that contains "verbose => 0".
+to an ikiwiki.setup file that contains "verbose => 0".
 
 I hadn't noticed that setting in there, but later when I changed my
 standard command of:
index 4e87f92e67b31b81ae8dcd6864f2a2bd471628ff..e5ea72e36cf519816489c17d34b45c9eb895031e 100644 (file)
@@ -4,14 +4,16 @@ ikiwiki-update-wikilist - add or remove user from /etc/ikiwiki/wikilist
 
 # SYNOPSIS
 
-ikiwiki-update-wikilist
+ikiwiki-update-wikilist [-r]
 
 # DESCRIPTION
 
-`ikiwiki-update-wikilist` is designed to be made suid root, but not installed
+`ikiwiki-update-wikilist` is designed to be made suid root, but is not installed
 suid by default. If made suid, it allows users to add or remove their names
-from the `/etc/ikiwiki/wikilist` file. If a user's name is not in the file,
-it will be added; if the name is already present, it will be removed.
+from the `/etc/ikiwiki/wikilist` file. 
+
+By default, the user's name will be added.
+The `-r` switch causes the user's name to be removed.
 
 If your name is in `/etc/ikiwiki/wikilist`, the [[ikiwiki-mass-rebuild]](8)
 command will look for a ~/.ikiwiki/wikilist file, and rebuild the wikis listed
diff --git a/doc/ikiwiki.setup b/doc/ikiwiki.setup
deleted file mode 100644 (file)
index 31a60b9..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-#!/usr/bin/perl
-# Configuration file for ikiwiki.
-# 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 {
-       wikiname => "MyWiki",
-       #adminuser => ["yourname", ],
-       adminemail => 'me@example.org',
-
-       # Be sure to customise these..
-       srcdir => "/path/to/source",
-       destdir => "/var/www/wiki",
-
-       url => "http://example.org/wiki",
-       cgiurl => "http://example.org/wiki/ikiwiki.cgi",
-       #templatedir => "/usr/share/ikiwiki/templates",
-       #underlaydir => "/usr/share/ikiwiki/basewiki",
-
-       # Subversion stuff.
-       #rcs => "svn",
-       #historyurl => "http://svn.example.org/trunk/[[file]]",
-       #diffurl => "http://svn.example.org/trunk/[[file]]?root=wiki&amp;r1=[[r1]]&amp;r2=[[r2]]",
-       #svnrepo => "/svn/wiki",
-       #svnpath => "trunk",
-
-       # Git stuff.
-       #rcs => "git",
-       #historyurl => "http://git.example.org/gitweb.cgi?p=wiki.git;a=history;f=[[file]]",
-       #diffurl => "http://git.example.org/gitweb.cgi?p=wiki.git;a=blobdiff;h=[[sha1_to]];hp=[[sha1_from]];hb=[[sha1_parent]];f=[[file]]",
-       #gitorigin_branch => "origin",
-       #gitmaster_branch => "master",
-
-       # Tla stuff.
-       #rcs => "tla"
-       #historyurl => ??,
-       #diffurl => ??,
-
-       # Mercurial stuff.
-       #rcs => "mercurial",
-       #historyurl => "http://localhost:8000/log/tip/[[file]]", # hg serve'd local repository
-       #diffurl => "http://localhost:8000/?fd=[[r2]];file=[[file]]",
-
-       # Bazaar stuff.
-       #rcs => "bzr",
-       #historyurl => "", 
-       #diffurl => "http://example.com/revision?start_revid=[[r2]]#[[file]]-s", # using loggerhead
-
-       # Monotone stuff
-       #rcs => "monotone",
-       #mtnkey => "web\@machine.company.com",
-       #historyurl => "http://viewmtn.example.com/branch/head/filechanges/com.example.branch/[[file]]",
-       #diffurl => "http://viewmtn.example.com/revision/diff/[[r1]]/with/[[r2]]/[[file]]",
-       # Set if you want the wiki to sync on update and commit.
-       #mtnsync => 0,
-       # The path to your workspace (defaults to the srcdir itself)
-       # e.g. use if your srcdir is a subdirectory of the workspace.
-       #mtnrootdir => "path/to/root/of/workspace",
-
-       wrappers => [
-               #{
-               #       # The cgi wrapper.
-               #       cgi => 1,
-               #       wrapper => "/var/www/wiki/ikiwiki.cgi",
-               #       wrappermode => "06755",
-               #},
-               #{
-               #       # The svn post-commit wrapper.
-               #       # Note that this will overwrite any existing
-               #       # post-commit hook script, which may not be
-               #       # what you want.
-               #       wrapper => "/svn/wikirepo/hooks/post-commit",
-               #       wrappermode => "04755",
-               #       # Log to syslog since svn post-commit hooks
-               #       # hide output and errors.
-               #       syslog => 1,
-               #},
-               #{
-               #       # The git post-update wrapper.
-               #       # Note that this will overwrite any existing
-               #       # post-update hook script, which may not be
-               #       # what you want.
-               #       wrapper => "/git/wiki.git/hooks/post-update",
-               #       wrappermode => "06755",
-               #},
-               #{
-               #       # The monotone netsync hook.
-               #       wrapper => "path/to/root/of/workspace/_MTN/ikiwiki-netsync-hook",
-               #       wrappermode => "06755",
-               #},
-       ],
-
-       # Default to generating rss feeds for pages with feeds?
-       #rss => 1,
-       # Default to generating atom feeds for pages with feeds?
-       #atom => 1,
-       # Allow generating feeds even if not generated by default?
-       #allowrss => 1,
-       #allowatom => 1,
-       # Urls to ping with XML-RPC when feeds are updated
-       #pingurl => [qw{http://rpc.technorati.com/rpc/ping}],
-       # Include discussion links on all pages?
-       discussion => 1,
-       # To exclude files matching a regexp from processing. This adds to
-       # the default exclude list.
-       #exclude => qr/\.wav$/,
-       # To change the extension used for generated html files.
-       #htmlext => 'htm',
-       # Time format (for strftime)
-       #timeformat => '%c',
-       # Locale to use. Must be a UTF-8 locale.
-       #locale => 'en_US.UTF-8',
-       # Only send cookies over SSL connections.
-       #sslcookie => 1,
-       # Logging settings:
-       #verbose => 1,
-       syslog => 0,
-       # To link to user pages in a subdirectory of the wiki.
-       #userdir => "users",
-       # To create output files named page.html rather than page/index.html.
-       #usedirs => 0,
-       # Simple spam prevention: require an account-creation password.
-       #account_creation_password => "example",
-       # Cost of generating a password using Authen::Passphrase::BlowfishCrypt
-       #password_cost => 8,
-       # Uncomment to force ikiwiki to run with a particular umask.
-       #umask => 022,
-       # Default settings for the recentchanges page.
-       #recentchangespage => "recentchanges",
-       #recentchangesnum => 100,
-       # Use new '!'-prefixed preprocessor directive syntax
-       #prefix_directives => 1,
-       # Attempt to make hardlinks to source files instead of copying them.
-       # Useful if the wiki contains large media files.
-       #hardlink => 1,
-       # Enable use of multimarkdown features in .mdwn files.
-       #multimarkdown => 1,
-
-       # To add plugins, list them here.
-       #add_plugins => [qw{goodstuff search wikitext camelcase
-       #                   htmltidy fortune sidebar map rst anonok}],
-       # If you want to disable any of the default plugins, list them here.
-       #disable_plugins => [qw{inline htmlscrubber passwordauth openid}],
-       # To add a directory to the perl search path, use this.
-       #libdir => "/home/me/.ikiwiki/",
-       
-       # To override environment variable settings, you can list values here.
-       #ENV => {
-       #       TZ => "America/New_York",
-       #       PATH => "/home/me/bin:/usr/local/bin:/usr/bin:/bin",
-       #},
-
-       # For use with the tag plugin, make all tags be located under a
-       # base page.
-       #tagbase => "tag",
-
-       # For use with the search plugin if the omega cgi is located
-       # somewhere else.
-       #omega_cgi => "/usr/lib/cgi-bin/omega/omega",
-
-       # For use with the openid plugin, to give an url to a page users
-       # can use to signup for an OpenID.
-       #openidsignup => "http://myopenid.com/",
-
-       # For use with the mirrorlist plugin, a list of mirrors.
-       #mirrorlist => {
-       #       mirror1 => "http://hostname1",
-       #       mirror2 => "http://hostname2/mirror",
-       #},
-       
-       # For use with the anonok plugin, a PageSpec specifying what
-       # pages anonymous users can edit
-       #anonok_pagespec => "*",
-       
-       # For use with the aggregate plugin.
-       # Enable aggregation to internal pages. New wikis should set this to 1,
-       # but if you use aggregate already, read the aggregate plugin docs
-       # before enabling it.
-       #aggregateinternal => 1,
-       # Allow aggregation to be triggered via the web.
-       #aggregate_webtrigger => 1,
-       
-       # For use with the pinger plugin, how many seconds to wait before
-       # timing out.
-       #pinger_timeout => 15.
-       
-       # For use with the amazon S3 plugin, your public access key id.
-       #amazon_s3_key_id => 'XXXXXXXXXXXXXXXXXXXX',
-       # And a file holding your secret key. This file *must* not be
-       # readable by others!
-       #amazon_s3_key_file => "/home/me/.hide/.s3_key
-       # The globally unique name of the bucket to use to store the wiki.
-       #amazon_s3_bucket => "mywiki",
-       # A prefix to prepend to each page name.
-       #amazon_s3_prefix => "wiki/",
-       # Uncomment to use the S3 European datacenter.
-       #amazon_s3_location => "EU",
-       # Uncomment if you need to store each index file twice.
-       #amazon_s3_dupindex => 1,
-       
-       # For use with the attachment plugin, a program that returns
-       # nonzero if its standard input contains an virus.
-       #virus_checker => "clamdscan -",
-}
index 5ee2bae893e54768a60546b4f16bb137edaae587..83735c5fd2225606fa71c60d11ff5de2c7409806 100644 (file)
@@ -7,7 +7,7 @@ There's documentation if you want to [[write]] your own plugins, or you can
 [[install]] plugins [[contributed|contrib]] by others.
 
 To enable a plugin, use the `--plugin` switch described in
-[[usage]], or the equivalent `add_plugins` line in [[ikiwiki.setup]].
+[[usage]], or the equivalent `add_plugins` line in ikiwiki.setup.
 Enable the [[goodstuff]] plugin to get a nice selection of plugins that
 will fit most uses of ikiwiki.
 
index 89022e5abb4db4dd768912557b08e13f07b16249..b371e8eb7f9a36f4462f49077a41e5d0ae7a2754 100644 (file)
@@ -4,5 +4,4 @@
 This plugin allows adding links a list of mirrors to each page in the
 wiki. For each mirror, a name and an url should be specified. Pages are
 assumed to exist in the same location under the specified url on each
-mirror. The [[ikiwiki.setup]] file has an example of configuring a list of
-mirrors.
+mirror.
index 7c28088ded55f9fce9b9012e9c31f9e72814145e..04b6ea8e9d4528291ffeac1791a993d7f3e0c87c 100644 (file)
@@ -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 not, 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", "pagespec", or "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:
@@ -376,7 +417,7 @@ it's not exported, the wise choice is to not use it.
 
 A plugin can access the wiki's configuration via the `%config`
 hash. The best way to understand the contents of the hash is to look at
-[[ikiwiki.setup]], which sets the hash content to configure the wiki.
+your ikiwiki setup file, which sets the hash content to configure the wiki.
 
 ### %pagestate
 
@@ -613,15 +654,107 @@ PageSpecs glob patterns, but instead only by a special `internal()`
 
 ### 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.
+
+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);
+
+#### `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($)`
 
-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.
+This is used to get the page creation time for a file from the RCS, by looking
+it up in the history.
 
-See [[RCS_details|rcs/details]] for some more info.
+It's ok if this is not implemented, and throws an error.
 
 ### PageSpec plugins
 
@@ -636,15 +769,15 @@ IkiWiki::FailReason object if the match fails.
 
 ### Setup plugins
 
-The ikiwiki setup file is loaded using a pluggable mechanism. If you
-look at the top of [[ikiwiki.setup]], it starts with 
-'use IkiWiki::Setup::Standard', and the rest of the file is passed to
-that module's import method.
+The ikiwiki setup file is loaded using a pluggable mechanism. If you look
+at the top of a setup file, it starts with 'use IkiWiki::Setup::Standard',
+and the rest of the file is passed to that module's import method.
 
 It's possible to write other modules in the `IkiWiki::Setup::` namespace that
 can be used to configure ikiwiki in different ways. These modules should,
 when imported, populate `$IkiWiki::Setup::raw_setup` with a reference
-to a hash containing all the config items.
+to a hash containing all the config items. They should also implement a
+`gendump` function.
 
 By the way, to parse a ikiwiki setup file, a program just needs to
 do something like:
index 9bf65762f4e6fe62d5138bf00393d9f1bb90cb8e..e62f3ef49fb2127c78e32686d97e2a267441d904 100644 (file)
@@ -266,8 +266,7 @@ on the same local machine, I suggest to create the latter with the "`git clone -
 command to save disk space.
 
 Note that, as a rule of thumb, you should always put the rcs wrapper (`post-update`)
-into the master repository (`.git/hooks/`) as can be noticed in the Git wrappers of
-the sample [[ikiwiki.setup]].
+into the master repository (`.git/hooks/`).
 
 Here is how a web edit works with ikiwiki and git:
 
index 498d2b4e77ef30006311fb8d7c5735eab7d95470..0841abf495a3d62580bfa849bbc8bafe13d58497 100644 (file)
@@ -66,8 +66,7 @@ So it's best if only one person can ever directly write to those directories.
 ## setup files
 
 Setup files are not safe to keep in the same revision control repository
-with the rest of the wiki. Just don't do it. [[ikiwiki.setup]] is *not*
-used as the setup file for this wiki, BTW.
+with the rest of the wiki. Just don't do it.
 
 ## page locking can be bypassed via direct commits
 
index 174d6ceb972d8c38f17b021246244e05052a9317..2989485f9af926d6c91688a91e6612dec214dc97 100644 (file)
@@ -7,6 +7,21 @@ This tutorial will walk you through setting up a wiki with ikiwiki.
 If you're using Debian or Ubuntu, ikiwiki is an `apt-get install ikiwiki` away.
 If you're not, see the [[download]] and [[install]] pages.
 
+## Quick start
+
+If you'd like to set up a wiki now, and learn more later, just run this command
+and answer a couple of questions.
+
+       % ikiwiki -setup /etc/ikiwiki/auto.setup
+       What will the wiki be named? mywiki
+       What revision control system to use? git
+       What wiki user (or openid) will be wiki admin? joey
+
+Wait for it to tell you an url for your new wiki.. Done!
+
+(If the CGI doesn't seem to let you edit pages, you might need to
+[[configure_apache|apache_cgi]]).)
+
 ## Decide where your wiki's files will go.
 
 As a wiki compiler, ikiwiki builds a wiki from files in a source directory,
@@ -74,11 +89,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 +111,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 +133,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 +187,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 +208,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
index 435743bf9c1331e0e33c72e2727ed667ba5a733d..6715f0c29b44a4a37f8f620b41c0b1ce2cd9eade 100644 (file)
@@ -76,16 +76,15 @@ Here is an example of how I set up a wiki:
 
        mkdir ~/wiki
        cd ~/wiki
-       cp ~/ikiwiki/doc/ikiwiki.setup .
        cp -r ~/ikiwiki/doc/examples/blog/* .
+       ikiwiki -dumpsetup ikiwiki.setup
        nano ikiwiki.setup
        # Set destdir to /home/htdocs
        # Set srcdir to /home/private/wiki
        # Set url to http://yoursite.nfshost.com/ , set cgiurl likewise
-       # Uncomment the `rcs => "git"` line, and the cgi and git
-       # post-update wrapper blocks.
-       # Set the cgi wrapper path to /home/htdocs/ikiwiki.cgi
-       # Set the git wrapper path to /home/private/wiki.git/hooks/post-update
+       # Uncomment the `rcs => "git"` line.
+       # Set the cgi_wrapper path to /home/htdocs/ikiwiki.cgi
+       # Set the git_wrapper path to /home/private/wiki.git/hooks/post-update
        # Configure the rest to your liking and save the file.
        ikiwiki-makerepo git . ../wiki.git
        ikiwiki -setup ikiwiki.setup
index 1fdff7b0f957979a905b883a5b137fa8d44431e9..54cc34af6a3fe9a2fe91849ff8506cacd425aa59 100644 (file)
@@ -1,4 +1,4 @@
-The current example [[ikiwiki.setup]] file has a number of options included, but commented out.  This is standard.  Unfortunately there are two standards for the settings of those commented out options:
+The current example ikiwiki.setup file has a number of options included, but commented out.  This is standard.  Unfortunately there are two standards for the settings of those commented out options:
 
   - Have the commented out options showing the default setting, or
   - Have the commented out options showing the most common alternate setting.
@@ -26,4 +26,8 @@ What do others think?
 > I may not work on it myself, since I have some
 > [[interesting_ideas|online_configuration]] that would let ikiwiki
 > generate a setup file for you, rather than having to keep maintain the
-> current example. --[[Joey]]
+> current example. 
+> 
+> And.. [[done]].. setup files are now generated with `--dumpsetup`, based on
+> the built-in defaults, and commented options show an example
+> setting, not a default. --[[Joey]]
index a6b428207357b9ed1970bb49041aafcf552976a7..c8ffe70055dcb2a2186fcdc10ff64500fceaf245 100644 (file)
@@ -163,7 +163,7 @@ follows) ?
     +`/etc/ssl/certs/ca-certificates.crt` is sufficient).
 
 > It would be good to add commented-out examples of these to
-> [[ikiwiki.setup]] as well.
+> ikiwiki.setup as well.
 
     +This plugin is not enabled by default. It can not be used with other
     +authentication plugin, such as [[passwordauth]] or [[openid]].
index 1e1fb174e43d9fb18ffced9500b02123b4da4178..511851ba3b5920e6afd97809ec713fb5fa336694 100644 (file)
@@ -193,9 +193,6 @@ Of course, I'm open for discussion or exchange of ideas :) --[[PaweÅ‚|ptecza]]
        +    \[[!color background=#ff0000 text="Default color text on red background"]]
        +
        +Foreground is missing, so the text has default color.
-       +
-       +This plugin is not enabled by default. You can do that in [[ikiwiki.setup]]
-       +file (hint: `add_plugins` variable).
        --- style.css-orig      2008-07-27 15:12:39.000000000 +0200
        +++ style.css   2008-07-27 15:15:06.000000000 +0200
        @@ -333,3 +333,7 @@
index 14ab4dac3906d7e3d6ee23f4d46611c110163ffd..c578bceafacc96ff12f8d2816130ab6715adf61d 100644 (file)
@@ -12,7 +12,7 @@ I can see two good ways to implement this.  Ideally, with
 [[conditional_text_based_on_ikiwiki_features]] available, ikiwiki could
 parse a page like conditionalpages.mdwn, which could contain a set of
 conditional-wrapped page names; that seems like the most elegant and
-ikiwiki-like approach.  Alternatively, [[/ikiwiki.setup]] could contain a
+ikiwiki-like approach.  Alternatively, ikiwiki.setup could contain a
 Perl-generated exclude option by default; that would work, but it seems
 hackish.
 
index 94c4c66f85d886e95029c8f4980b7285ffeccc67..2393b75afd34e5bd763be6e090106e49dc5b707f 100644 (file)
@@ -11,56 +11,21 @@ Currently admin prefs are per-admin, and are stored in the userdb.
 That seems like a bad choice in the context of this idea. Instead, admin
 setup should be configured on a separate page than the regular user prefs
 page, and should be shared amoung all admins, and the ideal storage would be
-another ikiwiki setup file, which could be loaded in, and written back out.
+a ikiwiki setup file, which could be loaded in, and written back out.
 
-If `ikiwiki-makerepo` were extended a little bit to generate the stub setup
-file that's enough to get `ikiwiki.cgi` working, and that sets values for
-all the dangerous options, leaving only safe ones 'undef', then users could
-set up ikiwiki using it, and configure the rest with the web interface,
-without ever needing to edit a setup file.
+The underlying work has been done to privide metadata about all options via
+getsetup hooks, so it's just a matter of writing a web interface plugin.
 
-The setup page could `require` every available plugin, and then call a
-`getsetup` function, which would look something like:
+The plugin could have these config options:
 
-       sub getsetup () {
-               eval q{use Some::Thing};
-               die $@ if $@;
+       # list of options to include in web setup (safe = all things with safe = 1)
+       websetup_include => [qw{safe}],
+       # list of options to exclude from web setup
+       websetup_exclude => [qw{option_baz}],
 
-               return option_foo => {
-                       safe => 1,
-                       rebuild => 1,
-                       type => "boolean",
-                       default => 0,
-                       description => gettext("Enable foo."),
-               },
-               option_bar => {
-                       safe => 0,
-                       rebuild => 0,
-                       type => "password",
-                       default => "",
-                       description => gettext("Password for bar."),
-               };
-       }
-
-The types would be: boolean, string, password, filename, other.
-This would be the type of the leaf fields; if a value in `%config` is an
-array or hash, the type specifies the type of values that go into it.
-
-From this info, a form can be built, that has core setup values at the
-top, followed by each plugin whose `getsetup` succeeded, with a check box
-to enable/disable that plugin, and all of its setup options listed after
-it.
-
-The main setup file could control what options are read from the
-online setup file:
-
-       online_setup_include => 'safe', # all things with safe = 1
-       online_setup_exclude => [qw{option_baz}],
-
-Note that posting the setup form would sometimes need to cause a rebuild
-of the whole wiki. This could be done with output streamed to the admin in
-the web browser. The `rebuild` fields would be set to 1 for values that
-require a wiki rebuild when changed, and to 0 for values that only need the
-wrappers to be refreshed.
+Leaning toward just making it write out to the same setup file, rather than
+writing to a subsidiary setup file. However, this would mean that any
+comments in the file would be lost, and that it couldn't be used if the
+setup file had weird stuff (perl code, etc).
 
 [[!tag wishlist]]
index 2b104bcdb5597659f08c734046ba89ddd711741c..511bb687a16c0aa9c84643e7b9b409f4099edafa 100644 (file)
@@ -55,13 +55,16 @@ These options control the mode that ikiwiki operates in.
   In setup mode, ikiwiki reads the config file, which is really a perl
   program that can call ikiwiki internal functions.
 
-  [[ikiwiki.setup]] is an example of such a config file.
-
   The default action when --setup is specified is to automatically generate
   wrappers for a wiki based on data in a config file, and rebuild the wiki.
   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
index e088561581b580bfa11fe4eb4e2dbbd391df2d34..5f5cbbff927476d1ca85d74657d26f9560d8c5e4 100644 (file)
@@ -17,19 +17,13 @@ use IkiWiki::Setup::Standard {
        cgiurl => 'ikiwiki.cgi',
        rcs => "",
 
-       wrappers => [
-               {
-                       # The cgi wrapper.
-                       cgi => 1,
-                       # The wrapper must be put in ~/.ikiwiki/wrappers/, since
-                       # ikiwiki-w3m.cgi only looks in this one location.
-                       # The wrapper can be given any name as long as it's 
-                       # in that directory.
-                       wrapper => "$ENV{HOME}/.ikiwiki/wrappers/ikiwiki.cgi",
-                       wrappermode => "0755",
-               },
-       ],
-       
+       # The wrapper must be put in ~/.ikiwiki/wrappers/, since
+       # ikiwiki-w3m.cgi only looks in this one location.
+       # The wrapper can be given any name as long as it's 
+       # in that directory.
+       cgi_wrapper => "$ENV{HOME}/.ikiwiki/wrappers/ikiwiki.cgi",
+       cgi_wrappermode => "0755",
+
        add_plugins => [qw{anonok}],
        rss => 1,
        atom => 1,
index 99a7f0e41586a0ced98fdc564d713295d21cd1cf..6d732fd6b1d59818687a930342b9b02a123e99f5 100644 (file)
@@ -7,7 +7,6 @@ use IkiWiki::Setup::Standard {
        destdir => "html",
        templatedir => "templates",
        underlaydir => "underlays/basewiki",
-       wrappers => [],
        discussion => 0,
        exclude => qr/\/discussion|bugs\/*|todo\/*/,
        locale => '',
index 0f3f0bcc6497f2b6f6b73cf6821f01847bb6925c..a6425f011c6a7e04c281cdfe8f70094d302818e5 100755 (executable)
@@ -5,6 +5,8 @@ use warnings;
 use strict;
 use English;
 
+my $remove=(@ARGV && $ARGV[0] eq '-r');
+
 my $username=getpwuid($REAL_USER_ID);
 if (! defined $username || ! length $username) {
        die "unable to determine user name for UID $REAL_USER_ID\n";
@@ -15,7 +17,8 @@ if (! -e $wikilist) {
        die "$wikilist does not exist\n";
 }
 
-my $removed=0;
+my $changed=0;
+my $seen=0;
 my @lines;
 open (my $list, "<$wikilist") || die "read $wikilist: $!";
 while (<$list>) {
@@ -23,7 +26,10 @@ while (<$list>) {
        if (/^\s*([^\s]+)\s*$/) {
                my $user=$1;
                if ($user eq $username) {
-                       $removed=1;             
+                       if (! $remove) {
+                               $seen=1;
+                               push @lines, $_;
+                       }
                }
                else {
                        push @lines, $_;
@@ -33,16 +39,24 @@ while (<$list>) {
                push @lines, $_;
        }
 }
-close $list || die "error reading $list: $!";
-open ($list, ">$wikilist") || die "write $wikilist: $!";
-foreach (@lines) {
-       print $list "$_\n";
+if (! $seen && ! $remove) {
+       push @lines, $username;
+       $changed=1;
 }
-if ($removed) {
-       print "removed user $username from $wikilist\n";
+if ($changed) {
+       close $list || die "ikiwiki-update-wikilist: error reading $list: $!\n";
+       open ($list, ">$wikilist") || die "ikiwiki-update-wikilist: cannot write to $wikilist\n";
+       foreach (@lines) {
+               print $list "$_\n";
+       }
+       if ($remove) {
+               print "ikiwiki-update-wikilist: removed user $username from $wikilist\n";
+       }
+       else {
+               print "ikiwiki-update-wikilist: added user $username to $wikilist\n";
+       }
+       close $list || die "ikiwiki-update-wikilist: error writing $wikilist: $!\n";
 }
 else {
-       print $list "$username\n";
-       print "added user $username to $wikilist\n";
+       print "ikiwiki-update-wikilist: no changes need to be made\n";
 }
-close $list || die "error writing $list: $!";
index 3bb881c4320f246b1edd4f9af80014149036d9e4..d8e848f8727c5dbfd11bc0f9ce976e0821b68cff 100755 (executable)
@@ -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) {
@@ -91,10 +88,14 @@ sub getconfig () { #{{{
 
                if (! $config{setup} && ! $config{render}) {
                        loadplugins();
-                       usage() unless @ARGV == 2;
-                       $config{srcdir} = possibly_foolish_untaint(shift @ARGV);
-                       $config{destdir} = possibly_foolish_untaint(shift @ARGV);
-                       checkconfig();
+                       if (@ARGV == 2) {
+                               $config{srcdir} = possibly_foolish_untaint(shift @ARGV);
+                               $config{destdir} = possibly_foolish_untaint(shift @ARGV);
+                               checkconfig();
+                       }
+                       else {
+                               usage() unless $config{dumpsetup};
+                       }
                }
        }
        else {
@@ -114,7 +115,48 @@ sub main () { #{{{
        
        if ($config{setup}) {
                require IkiWiki::Setup;
-               setup();
+               IkiWiki::Setup::load($config{setup});
+               
+               loadplugins();
+               checkconfig();
+
+               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};
+       }
+
+       if ($config{dumpsetup}) {
+               require IkiWiki::Setup;
+               IkiWiki::Setup::dump($config{dumpsetup});
        }
        elsif ($config{wrapper}) {
                lockwiki();
@@ -136,12 +178,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"));
        }
 } #}}}
 
index b6e2dc68c0076e62e7fb430026ea75be1d7d6dd9..aa61c0673e61ab0bef1150f6dc9d88168d94f56c 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 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-27 01:52-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"
@@ -50,7 +50,7 @@ msgid "%s is not an editable page"
 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"
@@ -71,122 +71,122 @@ msgstr ""
 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:193
 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 ""
 
@@ -199,11 +199,22 @@ msgstr ""
 msgid "There are no broken links!"
 msgstr ""
 
-#: ../IkiWiki/Plugin/conditional.pm:18 ../IkiWiki/Plugin/testpagespec.pm:17
+#: ../IkiWiki/Plugin/conditional.pm:18 ../IkiWiki/Plugin/cutpaste.pm:22
+#: ../IkiWiki/Plugin/cutpaste.pm:37 ../IkiWiki/Plugin/cutpaste.pm:53
+#: ../IkiWiki/Plugin/testpagespec.pm:17
 #, perl-format
 msgid "%s parameter is required"
 msgstr ""
 
+#: ../IkiWiki/Plugin/cutpaste.pm:58
+msgid "no text was copied in this page"
+msgstr ""
+
+#: ../IkiWiki/Plugin/cutpaste.pm:61
+#, perl-format
+msgid "no text was copied in this page with id %s"
+msgstr ""
+
 #: ../IkiWiki/Plugin/edittemplate.pm:41
 msgid "template not specified"
 msgstr ""
@@ -262,33 +273,33 @@ 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 ""
 
@@ -301,11 +312,11 @@ 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 ""
@@ -322,11 +333,11 @@ 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 ""
 
@@ -334,11 +345,15 @@ 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 ""
 
@@ -350,31 +365,31 @@ 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 ""
 
@@ -382,21 +397,21 @@ 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 ""
 
@@ -476,23 +491,23 @@ 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 ""
@@ -576,17 +591,17 @@ 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 ""
 
@@ -688,10 +703,6 @@ 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"
@@ -739,23 +750,11 @@ msgstr ""
 
 #. 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"
@@ -792,23 +791,31 @@ msgstr ""
 msgid "usage: ikiwiki [options] source dest"
 msgstr ""
 
-#: ../ikiwiki.in:82
+#: ../ikiwiki.in:79
 msgid "usage: --set var=value"
 msgstr ""
 
-#: ../IkiWiki.pm:126
+#: ../ikiwiki.in:126
+msgid "generating wrappers.."
+msgstr ""
+
+#: ../ikiwiki.in:182
+msgid "rebuilding wiki.."
+msgstr ""
+
+#: ../ikiwiki.in:185
+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 ""
index 01346a33842d256ea6fd6f1d7b390f686ebbd8c7..694bb01df2f52d6a01477d14049611f291ab97b1 100755 (executable)
@@ -6,7 +6,7 @@ use Test::More;
 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));