X-Git-Url: http://git.vanrenterghem.biz/git.ikiwiki.info.git/blobdiff_plain/800dfe6612712c851ba4fdf2baab6e274dabbef2..6652de5e1abcaac3ee2f4bf17e5a4b847fcadb0d:/ikiwiki?ds=sidebyside

diff --git a/ikiwiki b/ikiwiki
index 427243312..e911eaff4 100755
--- a/ikiwiki
+++ b/ikiwiki
@@ -4,11 +4,8 @@ $ENV{PATH}="/usr/local/bin:/usr/bin:/bin";
 package IkiWiki;
 use warnings;
 use strict;
-use File::Spec;
-use HTML::Template;
 use lib '.'; # For use without installation, removed by Makefile.
-
-use vars qw{%config %links %oldlinks %oldpagemtime %renderedfiles %pagesources};
+use IkiWiki;
 
 sub usage () { #{{{
 	die "usage: ikiwiki [options] source dest\n";
@@ -16,44 +13,29 @@ sub usage () { #{{{
 
 sub getconfig () { #{{{
 	if (! exists $ENV{WRAPPED_OPTIONS}) {
-		%config=(
-			wiki_file_prune_regexp => qr{((^|/).svn/|\.\.|^\.|\/\.|\.html?$)},
-			wiki_link_regexp => qr/\[\[([^\s\]]+)\]\]/,
-			wiki_file_regexp => qr/(^[-A-Za-z0-9_.:\/+]+$)/,
-			verbose => 0,
-			wikiname => "wiki",
-			default_pageext => ".mdwn",
-			cgi => 0,
-			svn => 1,
-			url => '',
-			cgiurl => '',
-			historyurl => '',
-			diffurl => '',
-			anonok => 0,
-			rebuild => 0,
-			wrapper => undef,
-			wrappermode => undef,
-			srcdir => undef,
-			destdir => undef,
-			templatedir => "/usr/share/ikiwiki/templates",
-			setup => undef,
-			adminuser => undef,
-		);
-
+		%config=defaultconfig();
 		eval q{use Getopt::Long};
 		GetOptions(
 			"setup|s=s" => \$config{setup},
 			"wikiname=s" => \$config{wikiname},
 			"verbose|v!" => \$config{verbose},
 			"rebuild!" => \$config{rebuild},
+			"refresh!" => \$config{refresh},
+			"getctime" => \$config{getctime},
 			"wrappermode=i" => \$config{wrappermode},
-			"svn!" => \$config{svn},
+			"rcs=s" => \$config{rcs},
+			"no-rcs" => sub { $config{rcs}="" },
 			"anonok!" => \$config{anonok},
+			"rss!" => \$config{rss},
 			"cgi!" => \$config{cgi},
+			"notify!" => \$config{notify},
 			"url=s" => \$config{url},
 			"cgiurl=s" => \$config{cgiurl},
 			"historyurl=s" => \$config{historyurl},
 			"diffurl=s" => \$config{diffurl},
+			"svnrepo" => \$config{svnrepo},
+			"svnpath" => \$config{svnpath},
+			"adminemail=s" => \$config{adminemail},
 			"exclude=s@" => sub {
 				$config{wiki_file_prune_regexp}=qr/$config{wiki_file_prune_regexp}|$_[1]/;
 			},
@@ -63,15 +45,24 @@ sub getconfig () { #{{{
 			"templatedir=s" => sub {
 				$config{templatedir}=possibly_foolish_untaint($_[1])
 			},
+			"underlaydir=s" => sub {
+				$config{underlaydir}=possibly_foolish_untaint($_[1])
+			},
 			"wrapper:s" => sub {
 				$config{wrapper}=$_[1] ? $_[1] : "ikiwiki-wrap"
 			},
+			"plugin=s@" => sub {
+				push @{$config{plugin}}, $_[1];
+			},
+			"disable-plugin=s@" => sub {
+				$config{plugin}=[grep { $_ ne $_[1] } @{$config{plugin}} ];
+			},
 		) || usage();
 
 		if (! $config{setup}) {
 			usage() unless @ARGV == 2;
-			$config{srcdir} = possibly_foolish_untaint(shift);
-			$config{destdir} = possibly_foolish_untaint(shift);
+			$config{srcdir} = possibly_foolish_untaint(shift @ARGV);
+			$config{destdir} = possibly_foolish_untaint(shift @ARGV);
 			checkconfig();
 		}
 	}
@@ -79,358 +70,23 @@ sub getconfig () { #{{{
 		# wrapper passes a full config structure in the environment
 		# variable
 		eval possibly_foolish_untaint($ENV{WRAPPED_OPTIONS});
-		checkconfig();
-	}
-} #}}}
-
-sub checkconfig () { #{{{
-	if ($config{cgi} && ! length $config{url}) {
-		error("Must specify url to wiki with --url when using --cgi");
-	}
-	
-	$config{wikistatedir}="$config{srcdir}/.ikiwiki"
-		unless exists $config{wikistatedir};
-	
-	if ($config{svn}) {
-		require IkiWiki::RCS::SVN;
-		$config{rcs}=1;
-	}
-	else {
-		require IkiWiki::RCS::Stub;
-		$config{rcs}=0;
-	}
-} #}}}
-
-sub error ($) { #{{{
-	if ($config{cgi}) {
-		print "Content-type: text/html\n\n";
-		print misctemplate("Error", "<p>Error: @_</p>");
-	}
-	die @_;
-} #}}}
-
-sub possibly_foolish_untaint ($) { #{{{
-	my $tainted=shift;
-	my ($untainted)=$tainted=~/(.*)/;
-	return $untainted;
-} #}}}
-
-sub debug ($) { #{{{
-	return unless $config{verbose};
-	if (! $config{cgi}) {
-		print "@_\n";
-	}
-	else {
-		print STDERR "@_\n";
-	}
-} #}}}
-
-sub basename ($) { #{{{
-	my $file=shift;
-
-	$file=~s!.*/!!;
-	return $file;
-} #}}}
-
-sub dirname ($) { #{{{
-	my $file=shift;
-
-	$file=~s!/?[^/]+$!!;
-	return $file;
-} #}}}
-
-sub pagetype ($) { #{{{
-	my $page=shift;
-	
-	if ($page =~ /\.mdwn$/) {
-		return ".mdwn";
-	}
-	else {
-		return "unknown";
-	}
-} #}}}
-
-sub pagename ($) { #{{{
-	my $file=shift;
-
-	my $type=pagetype($file);
-	my $page=$file;
-	$page=~s/\Q$type\E*$// unless $type eq 'unknown';
-	return $page;
-} #}}}
-
-sub htmlpage ($) { #{{{
-	my $page=shift;
-
-	return $page.".html";
-} #}}}
-
-sub readfile ($) { #{{{
-	my $file=shift;
-
-	if (-l $file) {
-		error("cannot read a symlink ($file)");
-	}
-	
-	local $/=undef;
-	open (IN, "$file") || error("failed to read $file: $!");
-	my $ret=<IN>;
-	close IN;
-	return $ret;
-} #}}}
-
-sub writefile ($$) { #{{{
-	my $file=shift;
-	my $content=shift;
-	
-	if (-l $file) {
-		error("cannot write to a symlink ($file)");
-	}
-
-	my $dir=dirname($file);
-	if (! -d $dir) {
-		my $d="";
-		foreach my $s (split(m!/+!, $dir)) {
-			$d.="$s/";
-			if (! -d $d) {
-				mkdir($d) || error("failed to create directory $d: $!");
-			}
-		}
-	}
-	
-	open (OUT, ">$file") || error("failed to write $file: $!");
-	print OUT $content;
-	close OUT;
-} #}}}
-
-sub bestlink ($$) { #{{{
-	# Given a page and the text of a link on the page, determine which
-	# existing page that link best points to. Prefers pages under a
-	# subdirectory with the same name as the source page, failing that
-	# goes down the directory tree to the base looking for matching
-	# pages.
-	my $page=shift;
-	my $link=lc(shift);
-	
-	my $cwd=$page;
-	do {
-		my $l=$cwd;
-		$l.="/" if length $l;
-		$l.=$link;
-
-		if (exists $links{$l}) {
-			#debug("for $page, \"$link\", use $l");
-			return $l;
-		}
-	} while $cwd=~s!/?[^/]+$!!;
-
-	#print STDERR "warning: page $page, broken link: $link\n";
-	return "";
-} #}}}
-
-sub isinlinableimage ($) { #{{{
-	my $file=shift;
-	
-	$file=~/\.(png|gif|jpg|jpeg)$/;
-} #}}}
-
-sub htmllink ($$;$$) { #{{{
-	my $page=shift;
-	my $link=shift;
-	my $noimageinline=shift; # don't turn links into inline html images
-	my $forcesubpage=shift; # force a link to a subpage
-
-	my $bestlink;
-	if (! $forcesubpage) {
-		$bestlink=bestlink($page, $link);
-	}
-	else {
-		$bestlink="$page/".lc($link);
-	}
-
-	return $link if length $bestlink && $page eq $bestlink;
-	
-	# TODO BUG: %renderedfiles may not have it, if the linked to page
-	# was also added and isn't yet rendered! Note that this bug is
-	# masked by the bug mentioned below that makes all new files
-	# be rendered twice.
-	if (! grep { $_ eq $bestlink } values %renderedfiles) {
-		$bestlink=htmlpage($bestlink);
-	}
-	if (! grep { $_ eq $bestlink } values %renderedfiles) {
-		return "<a href=\"$config{cgiurl}?do=create&page=$link&from=$page\">?</a>$link"
-	}
-	
-	$bestlink=File::Spec->abs2rel($bestlink, dirname($page));
-	
-	if (! $noimageinline && isinlinableimage($bestlink)) {
-		return "<img src=\"$bestlink\">";
-	}
-	return "<a href=\"$bestlink\">$link</a>";
-} #}}}
-
-sub indexlink () { #{{{
-	return "<a href=\"$config{url}\">$config{wikiname}</a>";
-} #}}}
-
-sub lockwiki () { #{{{
-	# Take an exclusive lock on the wiki to prevent multiple concurrent
-	# run issues. The lock will be dropped on program exit.
-	if (! -d $config{wikistatedir}) {
-		mkdir($config{wikistatedir});
-	}
-	open(WIKILOCK, ">$config{wikistatedir}/lockfile") ||
-		error ("cannot write to $config{wikistatedir}/lockfile: $!");
-	if (! flock(WIKILOCK, 2 | 4)) {
-		debug("wiki seems to be locked, waiting for lock");
-		my $wait=600; # arbitrary, but don't hang forever to 
-		              # prevent process pileup
-		for (1..600) {
-			return if flock(WIKILOCK, 2 | 4);
-			sleep 1;
+		if ($@) {
+			error("WRAPPED_OPTIONS: $@");
 		}
-		error("wiki is locked; waited $wait seconds without lock being freed (possible stuck process or stale lock?)");
-	}
-} #}}}
-
-sub unlockwiki () { #{{{
-	close WIKILOCK;
-} #}}}
-
-sub loadindex () { #{{{
-	open (IN, "$config{wikistatedir}/index") || return;
-	while (<IN>) {
-		$_=possibly_foolish_untaint($_);
-		chomp;
-		my ($mtime, $file, $rendered, @links)=split(' ', $_);
-		my $page=pagename($file);
-		$pagesources{$page}=$file;
-		$oldpagemtime{$page}=$mtime;
-		$oldlinks{$page}=[@links];
-		$links{$page}=[@links];
-		$renderedfiles{$page}=$rendered;
-	}
-	close IN;
-} #}}}
-
-sub saveindex () { #{{{
-	if (! -d $config{wikistatedir}) {
-		mkdir($config{wikistatedir});
-	}
-	open (OUT, ">$config{wikistatedir}/index") || 
-		error("cannot write to $config{wikistatedir}/index: $!");
-	foreach my $page (keys %oldpagemtime) {
-		print OUT "$oldpagemtime{$page} $pagesources{$page} $renderedfiles{$page} ".
-	        	join(" ", @{$links{$page}})."\n"
-				if $oldpagemtime{$page};
-	}
-	close OUT;
-} #}}}
-
-sub misctemplate ($$) { #{{{
-	my $title=shift;
-	my $pagebody=shift;
-	
-	my $template=HTML::Template->new(
-		filename => "$config{templatedir}/misc.tmpl"
-	);
-	$template->param(
-		title => $title,
-		indexlink => indexlink(),
-		wikiname => $config{wikiname},
-		pagebody => $pagebody,
-	);
-	return $template->output;
-}#}}}
-
-sub userinfo_get ($$) { #{{{
-	my $user=shift;
-	my $field=shift;
-
-	eval q{use Storable};
-	my $userdata=eval{ Storable::lock_retrieve("$config{wikistatedir}/userdb") };
-	if (! defined $userdata || ! ref $userdata || 
-	    ! exists $userdata->{$user} || ! ref $userdata->{$user} ||
-            ! exists $userdata->{$user}->{$field}) {
-		return "";
-	}
-	return $userdata->{$user}->{$field};
-} #}}}
-
-sub userinfo_set ($$$) { #{{{
-	my $user=shift;
-	my $field=shift;
-	my $value=shift;
-	
-	eval q{use Storable};
-	my $userdata=eval{ Storable::lock_retrieve("$config{wikistatedir}/userdb") };
-	if (! defined $userdata || ! ref $userdata || 
-	    ! exists $userdata->{$user} || ! ref $userdata->{$user}) {
-		return "";
-	}
-	
-	$userdata->{$user}->{$field}=$value;
-	my $oldmask=umask(077);
-	my $ret=Storable::lock_store($userdata, "$config{wikistatedir}/userdb");
-	umask($oldmask);
-	return $ret;
-} #}}}
-
-sub userinfo_setall ($$) { #{{{
-	my $user=shift;
-	my $info=shift;
-	
-	eval q{use Storable};
-	my $userdata=eval{ Storable::lock_retrieve("$config{wikistatedir}/userdb") };
-	if (! defined $userdata || ! ref $userdata) {
-		$userdata={};
-	}
-	$userdata->{$user}=$info;
-	my $oldmask=umask(077);
-	my $ret=Storable::lock_store($userdata, "$config{wikistatedir}/userdb");
-	umask($oldmask);
-	return $ret;
-} #}}}
-
-sub is_admin ($) { #{{{
-	my $user_name=shift;
-
-	return grep { $_ eq $user_name } @{$config{adminuser}};
-} #}}}
-
-sub glob_match ($$) { #{{{
-	my $page=shift;
-	my $glob=shift;
-
-	# turn glob into safe regexp
-	$glob=quotemeta($glob);
-	$glob=~s/\\\*/.*/g;
-	$glob=~s/\\\?/./g;
-	$glob=~s!\\/!/!g;
-	
-	$page=~/^$glob$/i;
-} #}}}
-
-sub globlist_match ($$) { #{{{
-	my $page=shift;
-	my @globlist=split(" ", shift);
-
-	# check any negated globs first
-	foreach my $glob (@globlist) {
-		return 0 if $glob=~/^!(.*)/ && glob_match($page, $1);
-	}
-
-	foreach my $glob (@globlist) {
-		return 1 if glob_match($page, $glob);
+		checkconfig();
 	}
-	
-	return 0;
 } #}}}
 
 sub main () { #{{{
 	getconfig();
 	
-	if ($config{setup}) {
+	if ($config{cgi}) {
+		lockwiki();
+		loadindex();
+		require IkiWiki::CGI;
+		cgi();
+	}
+	elsif ($config{setup}) {
 		require IkiWiki::Setup;
 		setup();
 	}
@@ -439,17 +95,14 @@ sub main () { #{{{
 		require IkiWiki::Wrapper;
 		gen_wrapper();
 	}
-	elsif ($config{cgi}) {
-		lockwiki();
-		require IkiWiki::CGI;
-		cgi();
-	}
 	else {
 		lockwiki();
-		loadindex() unless $config{rebuild};
+		loadindex();
 		require IkiWiki::Render;
 		rcs_update();
+		rcs_getctime() if $config{getctime};
 		refresh();
+		rcs_notify() if $config{notify};
 		saveindex();
 	}
 } #}}}