<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">#!/usr/bin/perl -T
# For subversion support.

use warnings;
use strict;

package IkiWiki;

sub svn_info ($$) { #{{{
	my $field=shift;
	my $file=shift;

	my $info=`LANG=C svn info $file`;
	my ($ret)=$info=~/^$field: (.*)$/m;
	return $ret;
} #}}}

sub rcs_update () { #{{{
	if (-d "$config{srcdir}/.svn") {
		if (system("svn", "update", "--quiet", $config{srcdir}) != 0) {
			warn("svn update failed\n");
		}
	}
} #}}}

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.
	my $file=shift;
	
	if (-d "$config{srcdir}/.svn") {
		# For subversion, return the revision of the file when
		# editing begins.
		my $rev=svn_info("Revision", "$config{srcdir}/$file");
		return defined $rev ? $rev : "";
	}
} #}}}

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=shift;
	my $message=shift;
	my $rcstoken=shift;

	if (-d "$config{srcdir}/.svn") {
		# Check to see if the page has been changed by someone
		# else since rcs_prepedit was called.
		my ($oldrev)=$rcstoken=~/^([0-9]+)$/; # untaint
		my $rev=svn_info("Revision", "$config{srcdir}/$file");
		if (defined $rev &amp;&amp; defined $oldrev &amp;&amp; $rev != $oldrev) {
			# Merge their changes into the file that we've
			# changed.
			chdir($config{srcdir}); # svn merge wants to be here
			if (system("svn", "merge", "--quiet", "-r$oldrev:$rev",
			           "$config{srcdir}/$file") != 0) {
				warn("svn merge -r$oldrev:$rev failed\n");
			}
		}

		if (system("svn", "commit", "--quiet", "-m",
		           possibly_foolish_untaint($message),
			   "$config{srcdir}") != 0) {
			my $conflict=readfile("$config{srcdir}/$file");
			if (system("svn", "revert", "--quiet", "$config{srcdir}/$file") != 0) {
				warn("svn revert failed\n");
			}
			return $conflict;
		}
	}
	return undef # success
} #}}}

sub rcs_add ($) { #{{{
	# filename is relative to the root of the srcdir
	my $file=shift;

	if (-d "$config{srcdir}/.svn") {
		my $parent=dirname($file);
		while (! -d "$config{srcdir}/$parent/.svn") {
			$file=$parent;
			$parent=dirname($file);
		}
		
		if (system("svn", "add", "--quiet", "$config{srcdir}/$file") != 0) {
			warn("svn add failed\n");
		}
	}
} #}}}

sub rcs_recentchanges ($) { #{{{
	my $num=shift;
	my @ret;
	
	eval q{use CGI 'escapeHTML'};
	eval q{use Date::Parse};
	eval q{use Time::Duration};
	
	if (-d "$config{srcdir}/.svn") {
		my $svn_url=svn_info("URL", $config{srcdir});

		# FIXME: currently assumes that the wiki is somewhere
		# under trunk in svn, doesn't support other layouts.
		my ($svn_base)=$svn_url=~m!(/trunk(?:/.*)?)$!;
		
		my $div=qr/^--------------------+$/;
		my $infoline=qr/^r(\d+)\s+\|\s+([^\s]+)\s+\|\s+(\d+-\d+-\d+\s+\d+:\d+:\d+\s+[-+]?\d+).*/;
		my $state='start';
		my ($rev, $user, $when, @pages, @message);
		foreach (`LANG=C svn log --limit $num -v '$svn_url'`) {
			chomp;
			if ($state eq 'start' &amp;&amp; /$div/) {
				$state='header';
			}
			elsif ($state eq 'header' &amp;&amp; /$infoline/) {
				$rev=$1;
				$user=$2;
				$when=concise(ago(time - str2time($3)));
		    	}
			elsif ($state eq 'header' &amp;&amp; /^\s+[A-Z]\s+\Q$svn_base\E\/([^ ]+)(?:$|\s)/) {
				my $file=$1;
				my $diffurl=$config{diffurl};
				$diffurl=~s/\[\[file\]\]/$file/g;
				$diffurl=~s/\[\[r1\]\]/$rev - 1/eg;
				$diffurl=~s/\[\[r2\]\]/$rev/g;
				push @pages, {
					link =&gt; htmllink("", pagename($file), 1),
					diffurl =&gt; $diffurl,
				} if length $file;
			}
			elsif ($state eq 'header' &amp;&amp; /^$/) {
				$state='body';
			}
			elsif ($state eq 'body' &amp;&amp; /$div/) {
				my $committype="web";
				if (defined $message[0] &amp;&amp;
				    $message[0]-&gt;{line}=~/^web commit by (\w+):?(.*)/) {
					$user="$1";
					$message[0]-&gt;{line}=$2;
				}
				else {
					$committype="svn";
				}
				
				push @ret, { rev =&gt; $rev,
					user =&gt; htmllink("", $user, 1),
					committype =&gt; $committype,
					when =&gt; $when, message =&gt; [@message],
					pages =&gt; [@pages],
				} if @pages;
				return @ret if @ret &gt;= $num;
				
				$state='header';
				$rev=$user=$when=undef;
				@pages=@message=();
			}
			elsif ($state eq 'body') {
				push @message, {line =&gt; escapeHTML($_)},
			}
		}
	}

	return @ret;
} #}}}

1
</pre></body></html>