diff --git a/IkiWiki.pm b/IkiWiki.pm index e7422cba5..db16a0854 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -899,7 +899,16 @@ sub loadindex () { #{{{ %pagesources=%pagemtime=%oldlinks=%links=%depends= %destsources=%renderedfiles=%pagecase=%pagestate=(); } - open (my $in, "<", "$config{wikistatedir}/index") || return; + my $in; + if (! open ($in, "<", "$config{wikistatedir}/indexdb")) { + if (-e "$config{wikistatedir}/index") { + system("ikiwiki-transition", "indexdb", $config{wikistatedir}); + open ($in, "<", "$config{wikistatedir}/indexdb") || return; + } + else { + return; + } + } my $ret=Storable::fd_retrieve($in); if (! defined $ret) { return 0; @@ -946,7 +955,7 @@ sub saveindex () { #{{{ if (! -d $config{wikistatedir}) { mkdir($config{wikistatedir}); } - my $newfile="$config{wikistatedir}/index.new"; + my $newfile="$config{wikistatedir}/indexdb.new"; my $cleanup = sub { unlink($newfile) }; open (my $out, '>', $newfile) || error("cannot write to $newfile: $!", $cleanup); my %index; @@ -976,8 +985,8 @@ sub saveindex () { #{{{ my $ret=Storable::nstore_fd(\%index, $out); return if ! defined $ret || ! $ret; close $out || error("failed saving to $newfile: $!", $cleanup); - rename($newfile, "$config{wikistatedir}/index") || - error("failed renaming $newfile to $config{wikistatedir}/index", $cleanup); + rename($newfile, "$config{wikistatedir}/indexdb") || + error("failed renaming $newfile to $config{wikistatedir}/indexdb", $cleanup); return 1; } #}}} diff --git a/doc/ikiwiki-transition.mdwn b/doc/ikiwiki-transition.mdwn index 118050a6c..da3b3a8d5 100644 --- a/doc/ikiwiki-transition.mdwn +++ b/doc/ikiwiki-transition.mdwn @@ -4,7 +4,7 @@ ikiwiki-transition - transition ikiwiki pages to new syntaxes # SYNOPSIS -ikiwiki-transition prefix_directives page.mdwn... +ikiwiki-transition type ... # DESCRIPTION @@ -12,8 +12,8 @@ ikiwiki-transition prefix_directives page.mdwn... there's a major change in ikiwiki syntax. Currently only one such transition is handled, the `prefix_directives` mode -converts an ikiwiki page from the old preprocessor directive syntax, -requiring a space, to the new syntax, prefixed by '!'. +converts the specified ikiwiki page from the old preprocessor directive +syntax, requiring a space, to the new syntax, prefixed by '!'. Preprocessor directives which already use the new syntax will remain unchanged. @@ -22,6 +22,12 @@ Note that if the page contains wiki links with spaces, which some older versions of ikiwiki accepted, the prefix_directives transition will treat these as preprocessor directives and convert them. +One other transition is handled, the `indexdb` mode handles converting +a plain text `.ikiwiki/index` file to a binary `.ikiwiki/indexdb`. In this +mode, you should specify the srcdir of the wiki as the second parameter. +You do not normally need to run `ikiwiki-transition indexdb`; ikiwiki will +automatically run it as necessary. + # AUTHOR Josh Triplett diff --git a/ikiwiki-transition b/ikiwiki-transition index 1fd23cec5..0e2bd4e22 100755 --- a/ikiwiki-transition +++ b/ikiwiki-transition @@ -1,6 +1,8 @@ #!/usr/bin/perl -i use warnings; use strict; +use IkiWiki; +use HTML::Entities; my $regex = qr{ (\\?) # 1: escape? @@ -48,10 +50,32 @@ sub prefix_directives { } } +sub indexdb { + $config{wikistatedir}=shift()."/.ikiwiki"; + + if (! defined $config{wikistatedir}) { + usage(); + } + + if (! IkiWiki::oldloadindex()) { + die "failed to load index\n"; + } + if (! IkiWiki::saveindex()) { + die "failed to save indexdb\n" + } + if (! IkiWiki::loadindex()) { + die "transition failed, cannot load new indexdb\n"; + } + if (! unlink("$config{wikistatedir}/index")) { + die "unlink failed: $!\n"; + } +} + sub usage { - print STDERR "Usage: ikiwiki-transition type file ...\n"; - print STDERR "Currently supported transition types:\n"; - print STDERR " prefix_directives\n"; + print STDERR "Usage: ikiwiki-transition type ...\n"; + print STDERR "Currently supported transition subcommands:\n"; + print STDERR " prefix_directives file\n"; + print STDERR " indexdb srcdir\n"; exit 1; } @@ -61,6 +85,51 @@ my $mode=shift; if ($mode eq 'prefix_directives') { prefix_directives(@ARGV); } +elsif ($mode eq 'indexdb') { + indexdb(@ARGV); +} else { usage(); } + +package IkiWiki; + +sub oldloadindex { + %oldrenderedfiles=%pagectime=(); + if (! $config{rebuild}) { + %pagesources=%pagemtime=%oldlinks=%links=%depends= + %destsources=%renderedfiles=%pagecase=%pagestate=(); + } + open (my $in, "<", "$config{wikistatedir}/index") || return; + while (<$in>) { + chomp; + my %items; + $items{link}=[]; + $items{dest}=[]; + foreach my $i (split(/ /, $_)) { + my ($item, $val)=split(/=/, $i, 2); + push @{$items{$item}}, decode_entities($val); + } + + next unless exists $items{src}; # skip bad lines for now + + my $page=pagename($items{src}[0]); + if (! $config{rebuild}) { + $pagesources{$page}=$items{src}[0]; + $pagemtime{$page}=$items{mtime}[0]; + $oldlinks{$page}=[@{$items{link}}]; + $links{$page}=[@{$items{link}}]; + $depends{$page}=$items{depends}[0] if exists $items{depends}; + $destsources{$_}=$page foreach @{$items{dest}}; + $renderedfiles{$page}=[@{$items{dest}}]; + $pagecase{lc $page}=$page; + foreach my $k (grep /_/, keys %items) { + my ($id, $key)=split(/_/, $k, 2); + $pagestate{$page}{decode_entities($id)}{decode_entities($key)}=$items{$k}[0]; + } + } + $oldrenderedfiles{$page}=[@{$items{dest}}]; + $pagectime{$page}=$items{ctime}[0]; + } + return close($in); +}