Attempt to fix a `TODO` in `Automator.pm` in combination with the Mercurial backend.

1. To define hooks, Mercurial uses paths given in the config file `.hg/hgrc`. To enable Mercurial to call `ikiwiki-wrapper` automatically after blog/wiki setup, ikiwiki thus needs to create `hgrc`.
2. To reflect changes in `$config{srcdir}` and/or `$config{mercurial_wrapper}`, relevant lines in `hgrc` need to be updated on wrapper creation.

ikiwiki can keep track of lines in `hgrc` for which it is responsible by adding a `.ikiwiki` suffix to its hooks. This is correct and recommended markup, Mercurial-wise.

Two ways follow below. I prefer the long one. --[[Daniel Andersson]]

> I comment myself: this can probably be solved without adding ad-hoc hooks and stuff (maybe not as "correct" as changing the config file only directly after wrappers have been generated, but good enough). I have a large rewrite of `mercurial.pm` ready, currently under local testing before I upload it for comments, trying to make it equal in function to `git.pm`. Comments below are of course welcome, but I will look into other ways of solving it later. Maybe `rcs_checkconfig` or `rcs_genwrapper` should host the `hgrc`-changing code. --[[Daniel Andersson]]

>> Having a hook that runs after a wrapper is generated may well be a good
>> thing anyway. In ikiwiki-hosting, there are some genwrapper hooks
>> that don't add any code to the wrapper, but are there only to run at,
>> essentially, that time.
>> 
>> With that said, here it seems like unnecessary complexity.
>> Why is `mercurial_wrapper` configurable at all? Why not just always
>> write it to a specific place relative to the srcdir, and always make
>> the hgrc look there?
>> 
>> (Other rcs plugins have good reasons to make their wrappers
>> configurable, because one might want the wrapper to run as a git
>> post-update or post-commit hook.) --[[Joey]]

Compact way (addresses only point 1)
------------------------------------
[This patch at pastebin](http://pastebin.com/by9f4dwX) ([raw version](http://pastebin.com/raw.php?i=by9f4dwX)).

Set default `ikiwiki-wrapper` path.

	diff -r 8faf136ca94f Setup/Automator.pm
	--- a/Setup/Automator.pm	Tue Jul 19 21:04:13 2011 +0200
	+++ b/Setup/Automator.pm	Wed Jul 20 15:33:21 2011 +0200
	@@ -75,8 +75,7 @@
	 			print STDERR "warning: do not know how to set up the bzr_wrapper hook!\n";
	 		}
	 		elsif ($config{rcs} eq 'mercurial') {
	-			# TODO
	-			print STDERR "warning: do not know how to set up the mercurial_wrapper hook!\n";
	+			$config{mercurial_wrapper}=$config{srcdir}."/.hg/ikiwiki-wrapper";
	 		}
	 		elsif ($config{rcs} eq 'tla') {
	 			# TODO

Create `$config{srcdir}/.hg/hgrc` with hook info during auto-installation script. Use relative paths to not require manual `hgrc` intervention if `$config{srcdir}` is changed. If `$config{mercurial_wrapper}` is changed, manual edit of `hgrc` is needed to catch the new wrapper path.

(Is there a security risk with relative paths?)

> The code seems to assume that hg will be run from within the srcdir,
> specifically the top of the srcdir. If it's run from somewhere else,
> even a subdirectory, this will fail to find the wrapper, or could
> run some other program. Unless mercurial always interprets these paths
> as relative to the top of the repository? --[[Joey]]

	@@ -187,6 +186,22 @@
	 		die "ikiwiki --wrappers --setup $config{dumpsetup} failed";
	 	}
	 
	+	# Setup initial config file for Mercurial to hook up the wrapper.
	+	if ($config{rcs} eq 'mercurial' && exists $config{mercurial_wrapper}
	+		&& length $config{mercurial_wrapper}) {
	+		# Use a relative path to avoid having to manually change the
	+		# autogenerated hgrc if the user changes $config{srcdir}.
	+		use File::Spec;
	+		my $mercurial_wrapper_relpath=File::Spec->abs2rel($config{mercurial_wrapper}, $config{srcdir});
	+		open (HGRC, '>', $config{srcdir}.'/.hg/hgrc');
	+		print HGRC <<EOF;
	+[hooks]
	+post-commit.ikiwiki = $mercurial_wrapper_relpath
	+incoming.ikiwiki = $mercurial_wrapper_relpath
	+EOF
	+		close (HGRC);
	+	}
	+
	 	# Add it to the wikilist.
	 	mkpath("$ENV{HOME}/.ikiwiki");
	 	open (WIKILIST, ">>$ENV{HOME}/.ikiwiki/wikilist") || die "$ENV{HOME}/.ikiwiki/wikilist: $!";


Less compact but more robust way (addresses point 1 and 2)
----------------------------------------------------------
[This complete patch at pastebin](http://pastebin.com/AcDHjbK6) ([raw version](http://pastebin.com/raw.php?i=AcDHjbK6)).

This way leaks onto additional files and adds general functionality that may or may not be wanted. The main part of the extra code is contained within `mercurial.pm`, though.

Set default `ikiwiki-wrapper` path.

	diff -r b08179653c00 IkiWiki/Setup/Automator.pm
	--- a/IkiWiki/Setup/Automator.pm	Wed Jul 20 16:56:09 2011 +0200
	+++ b/IkiWiki/Setup/Automator.pm	Wed Jul 20 19:28:21 2011 +0200
	@@ -75,8 +75,7 @@
	 			print STDERR "warning: do not know how to set up the bzr_wrapper hook!\n";
	 		}
	 		elsif ($config{rcs} eq 'mercurial') {
	-			# TODO
	-			print STDERR "warning: do not know how to set up the mercurial_wrapper hook!\n";
	+			$config{mercurial_wrapper}=$config{srcdir}."/.hg/ikiwiki-wrapper";
	 		}
	 		elsif ($config{rcs} eq 'tla') {
	 			# TODO

Create `$config{srcdir}/.hg/hgrc` during auto-installation with hook info.

	@@ -182,6 +181,19 @@
	 		}
	 	}
	 	
	+	# Setup initial config file for Mercurial to hook up the wrapper. The
	+	# path to the wrapper will be automatically added when it is generated.
	+	if ($config{rcs} eq 'mercurial' && exists $config{mercurial_wrapper}
	+		&& length $config{mercurial_wrapper}) {
	+		open (HGRC, '>', $config{srcdir}.'/.hg/hgrc');
	+		print HGRC <<EOF;
	+[hooks]
	+post-commit.ikiwiki = 
	+incoming.ikiwiki = 
	+EOF
	+		close (HGRC);
	+	}
	+
	 	# Add wrappers, make live.
	 	if (system("ikiwiki", "--wrappers", "--setup", $config{dumpsetup}) != 0) {
	 		die "ikiwiki --wrappers --setup $config{dumpsetup} failed";

`hgrc` is setup initially. Below follows code to keep `hgrc` updated.

Add backend specific function `rcs_wrapper_postcall()` for later call in `Wrappers.pm`.

	diff -r b08179653c00 IkiWiki/Plugin/mercurial.pm
	--- a/IkiWiki/Plugin/mercurial.pm	Wed Jul 20 16:56:09 2011 +0200
	+++ b/IkiWiki/Plugin/mercurial.pm	Wed Jul 20 19:28:21 2011 +0200
	@@ -21,6 +21,7 @@
	 	hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
	 	hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
	 	hook(type => "rcs", id => "rcs_getmtime", call => \&rcs_getmtime);
	+	hook(type => "rcs", id => "rcs_wrapper_postcall", call => \&rcs_wrapper_postcall);
	 }
	 
	 sub checkconfig () {

Pass variable to `gen_wrapper()` to decide if `rcs_wrapper_postcall()` should run. Default is `1` to update `hgrc`, since it is done non-intrusive (won't create `hgrc` if it doesn't exist, won't overwrite anything unless it is set by ikiwiki itself).

	@@ -28,6 +29,7 @@
	 		push @{$config{wrappers}}, {
	 			wrapper => $config{mercurial_wrapper},
	 			wrappermode => (defined $config{mercurial_wrappermode} ? $config{mercurial_wrappermode} : "06755"),
	+			wrapper_postcall => (defined $config{mercurial_wrapper_hgrc_update} ? $config{mercurial_wrapper_hgrc_update} : "1"),
	 		};
	 	}
	 }

Include default configuration value and comment.

	@@ -53,6 +55,13 @@
	 			safe => 0,
	 			rebuild => 0,
	 		},
	+		mercurial_wrapper_hgrc_update => {
	+			type => "string",
	+			example => "1",
	+			description => "updates existing hgrc to reflect path changes for mercurial_wrapper",
	+			safe => 0,
	+			rebuild => 0,
	+		},
	 		historyurl => {
	 			type => "string",
	 			example => "http://example.com:8000/log/tip/\[[file]]",

`hgrc` should be updated to point to the new wrapper path. The regexp transforms lines as e.g.

	post-commit.ikiwiki = /home/daniel/blog/.hg/ikiwiki-wrapper-oldpath
	incoming.ikiwiki = /home/daniel/blog/.hg/ikiwiki-wrapper-oldpath

to

	post-commit.ikiwiki = $config{mercurial_wrapper}
	incoming.ikiwiki = $config{mercurial_wrapper}

with absolute paths.

	@@ -402,4 +411,23 @@
	 	return findtimes($file, 0);
	 }
	 
	+sub rcs_wrapper_postcall($) {
	+	# Update hgrc if it exists. Change post-commit/incoming hooks with the
	+	# .ikiwiki suffix to point to the wrapper path given in the setup file.
	+	# Work with a tempfile to not delete hgrc if the loop is interrupted
	+	# midway.
	+	my $hgrc=$config{srcdir}.'/.hg/hgrc';
	+	my $backup_suffix='.ikiwiki.bak';
	+	if (-e $hgrc) {
	+		use File::Spec;
	+		my $mercurial_wrapper_abspath=File::Spec->rel2abs($config{mercurial_wrapper}, $config{srcdir});
	+		local ($^I, @ARGV)=($backup_suffix, $hgrc);
	+		while (<>) {
	+			s/^(post-commit|incoming)(\.ikiwiki[ \t]*=[ \t]*).*$/$1$2$mercurial_wrapper_abspath/;
	+			print;
	+		}
	+		unlink($hgrc.$backup_suffix);
	+	}
	+}
	+
	 1

`rcs_wrapper_postcall` is made available.

	diff -r b08179653c00 IkiWiki.pm
	--- a/IkiWiki.pm	Wed Jul 20 16:56:09 2011 +0200
	+++ b/IkiWiki.pm	Wed Jul 20 19:28:21 2011 +0200
	@@ -2059,6 +2059,10 @@
	 	$hooks{rcs}{rcs_getmtime}{call}->(@_);
	 }
	 
	+sub rcs_wrapper_postcall (@) {
	+	$hooks{rcs}{rcs_wrapper_postcall}{call}->(@_);
	+}
	+
	 sub rcs_receive () {
	 	$hooks{rcs}{rcs_receive}{call}->();
	 }


`rcs_wrapper_postcall` is called if $config{wrapper_postcall} is true, which it should only be for Mercurial at the moment.

	diff -r b08179653c00 IkiWiki/Wrapper.pm
	--- a/IkiWiki/Wrapper.pm	Wed Jul 20 16:56:09 2011 +0200
	+++ b/IkiWiki/Wrapper.pm	Wed Jul 20 19:28:21 2011 +0200
	@@ -238,6 +238,10 @@
	 	}
	 	#translators: The parameter is a filename.
	 	debug(sprintf(gettext("successfully generated %s"), $wrapper));
	+
	+	if (defined $config{wrapper_postcall} && $config{wrapper_postcall} ) {
	+		IkiWiki::rcs_wrapper_postcall();
	+	}
	 }
	 
	 1