X-Git-Url: http://git.vanrenterghem.biz/git.ikiwiki.info.git/blobdiff_plain/736fa378c586176473d08b24db4e284d629fc8b4..5184b8abfce9f2e6c899f8f00e0ac3341161a1b2:/IkiWiki.pm?ds=inline

diff --git a/IkiWiki.pm b/IkiWiki.pm
index 666a625e6..684713821 100644
--- a/IkiWiki.pm
+++ b/IkiWiki.pm
@@ -7,6 +7,7 @@ use Encode;
 use HTML::Entities;
 use URI::Escape q{uri_escape_utf8};
 use POSIX;
+use Storable;
 use open qw{:utf8 :std};
 
 use vars qw{%config %links %oldlinks %pagemtime %pagectime %pagecase
@@ -896,39 +897,49 @@ sub loadindex () { #{{{
 	%oldrenderedfiles=%pagectime=();
 	if (! $config{rebuild}) {
 		%pagesources=%pagemtime=%oldlinks=%links=%depends=
-			%destsources=%renderedfiles=%pagecase=%pagestate=();
-	}
-	open (my $in, "<", "$config{wikistatedir}/index") || return;
-	while (<$in>) {
-		$_=possibly_foolish_untaint($_);
-		chomp;
-		my %items;
-		$items{link}=[];
-		$items{dest}=[];
-		foreach my $i (split(/ /, $_)) {
-			my ($item, $val)=split(/=/, $i, 2);
-			push @{$items{$item}}, decode_entities($val);
+		%destsources=%renderedfiles=%pagecase=%pagestate=();
+	}
+	my $in;
+	if (! open ($in, "<", "$config{wikistatedir}/indexdb")) {
+		if (-e "$config{wikistatedir}/index") {
+			system("ikiwiki-transition", "indexdb", $config{srcdir});
+			open ($in, "<", "$config{wikistatedir}/indexdb") || return;
 		}
-
-		next unless exists $items{src}; # skip bad lines for now
-
-		my $page=pagename($items{src}[0]);
+		else {
+			return;
+		}
+	}
+	my $ret=Storable::fd_retrieve($in);
+	if (! defined $ret) {
+		return 0;
+	}
+	my %index=%$ret;
+	foreach my $src (keys %index) {
+		my %d=%{$index{$src}};
+		my $page=pagename($src);
+		$pagectime{$page}=$d{ctime};
 		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];
+			$pagesources{$page}=$src;
+			$pagemtime{$page}=$d{mtime};
+			$renderedfiles{$page}=$d{dest};
+			if (exists $d{links} && ref $d{links}) {
+				$links{$page}=$d{links};
+				$oldlinks{$page}=[@{$d{links}}];
+			}
+			if (exists $d{depends}) {
+				$depends{$page}=$d{depends};
+			}
+			if (exists $d{state}) {
+				$pagestate{$page}=$d{state};
 			}
 		}
-		$oldrenderedfiles{$page}=[@{$items{dest}}];
-		$pagectime{$page}=$items{ctime}[0];
+		$oldrenderedfiles{$page}=[@{$d{dest}}];
+	}
+	foreach my $page (keys %pagesources) {
+		$pagecase{lc $page}=$page;
+	}
+	foreach my $page (keys %renderedfiles) {
+		$destsources{$_}=$page foreach @{$renderedfiles{$page}};
 	}
 	return close($in);
 } #}}}
@@ -938,39 +949,45 @@ sub saveindex () { #{{{
 
 	my %hookids;
 	foreach my $type (keys %hooks) {
-		$hookids{encode_entities($_)}=1 foreach keys %{$hooks{$type}};
+		$hookids{$_}=1 foreach keys %{$hooks{$type}};
 	}
-	my @hookids=sort keys %hookids;
+	my @hookids=keys %hookids;
 
 	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;
 	foreach my $page (keys %pagemtime) {
 		next unless $pagemtime{$page};
-		my $line="mtime=$pagemtime{$page} ".
-			"ctime=$pagectime{$page} ".
-			"src=$pagesources{$page}";
-		$line.=" dest=$_" foreach @{$renderedfiles{$page}};
-		my %count;
-		$line.=" link=$_" foreach grep { ++$count{$_} == 1 } @{$links{$page}};
+		my $src=$pagesources{$page};
+
+		$index{$src}={
+			ctime => $pagectime{$page},
+			mtime => $pagemtime{$page},
+			dest => $renderedfiles{$page},
+			links => $links{$page},
+		};
+
 		if (exists $depends{$page}) {
-			$line.=" depends=".encode_entities($depends{$page}, " \t\n");
+			$index{$src}{depends} = $depends{$page};
 		}
+
 		if (exists $pagestate{$page}) {
 			foreach my $id (@hookids) {
 				foreach my $key (keys %{$pagestate{$page}{$id}}) {
-					$line.=' '.$id.'_'.encode_entities($key)."=".encode_entities($pagestate{$page}{$id}{$key}, " \t\n");
+					$index{$src}{state}{$id}{$key}=$pagestate{$page}{$id}{$key};
 				}
 			}
 		}
-		print $out $line."\n" || error("failed writing to $newfile: $!", $cleanup);
 	}
+	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;
 } #}}}
@@ -1106,6 +1123,8 @@ sub add_depends ($$) { #{{{
 	my $page=shift;
 	my $pagespec=shift;
 	
+	return unless pagespec_valid($pagespec);
+
 	if (! exists $depends{$page}) {
 		$depends{$page}=$pagespec;
 	}
@@ -1167,8 +1186,6 @@ sub pagespec_merge ($$) { #{{{
 } #}}}
 
 sub pagespec_translate ($) { #{{{
-	# This assumes that $page is in scope in the function
-	# that evalulates the translated pagespec code.
 	my $spec=shift;
 
 	# Support for old-style GlobLists.
@@ -1205,18 +1222,18 @@ sub pagespec_translate ($) { #{{{
 		}
 		elsif ($word =~ /^(\w+)\((.*)\)$/) {
 			if (exists $IkiWiki::PageSpec::{"match_$1"}) {
-				$code.="IkiWiki::PageSpec::match_$1(\$page, ".safequote($2).", \@params)";
+				$code.="IkiWiki::PageSpec::match_$1(\$page, ".safequote($2).", \@_)";
 			}
 			else {
 				$code.=' 0';
 			}
 		}
 		else {
-			$code.=" IkiWiki::PageSpec::match_glob(\$page, ".safequote($word).", \@params)";
+			$code.=" IkiWiki::PageSpec::match_glob(\$page, ".safequote($word).", \@_)";
 		}
 	}
 
-	return $code;
+	return eval 'sub { my $page=shift; '.$code.' }';
 } #}}}
 
 sub pagespec_match ($$;@) { #{{{
@@ -1229,9 +1246,16 @@ sub pagespec_match ($$;@) { #{{{
 		unshift @params, 'location';
 	}
 
-	my $ret=eval pagespec_translate($spec);
+	my $sub=pagespec_translate($spec);
 	return IkiWiki::FailReason->new('syntax error') if $@;
-	return $ret;
+	return $sub->($page, @params);
+} #}}}
+
+sub pagespec_valid ($) { #{{{
+	my $spec=shift;
+
+	my $sub=pagespec_translate($spec);
+	return ! $@;
 } #}}}
 
 package IkiWiki::FailReason;