(no commit message)
[ikiwiki] / doc / todo / Auto-setup_and_maintain_Mercurial_wrapper_hooks.mdwn
1 Attempt to fix a `TODO` in `Automator.pm` in combination with the Mercurial backend.
2
3 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`.
4 2. To reflect changes in `$config{srcdir}` and/or `$config{mercurial_wrapper}`, relevant lines in `hgrc` need to be updated on wrapper creation.
5
6 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.
7
8 Two ways follow below. I prefer the long one. --[[Daniel Andersson]]
9
10 > 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 here, 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. --[[Daniel Andersson]]
11
12 Compact way (addresses only point 1)
13 ------------------------------------
14 [This patch at pastebin](http://pastebin.com/by9f4dwX) ([raw version](http://pastebin.com/raw.php?i=by9f4dwX)).
15
16 Set default `ikiwiki-wrapper` path.
17
18         diff -r 8faf136ca94f Setup/Automator.pm
19         --- a/Setup/Automator.pm        Tue Jul 19 21:04:13 2011 +0200
20         +++ b/Setup/Automator.pm        Wed Jul 20 15:33:21 2011 +0200
21         @@ -75,8 +75,7 @@
22                                 print STDERR "warning: do not know how to set up the bzr_wrapper hook!\n";
23                         }
24                         elsif ($config{rcs} eq 'mercurial') {
25         -                       # TODO
26         -                       print STDERR "warning: do not know how to set up the mercurial_wrapper hook!\n";
27         +                       $config{mercurial_wrapper}=$config{srcdir}."/.hg/ikiwiki-wrapper";
28                         }
29                         elsif ($config{rcs} eq 'tla') {
30                                 # TODO
31
32 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.
33
34 (Is there a security risk with relative paths?)
35
36         @@ -187,6 +186,22 @@
37                         die "ikiwiki --wrappers --setup $config{dumpsetup} failed";
38                 }
39          
40         +       # Setup initial config file for Mercurial to hook up the wrapper.
41         +       if ($config{rcs} eq 'mercurial' && exists $config{mercurial_wrapper}
42         +               && length $config{mercurial_wrapper}) {
43         +               # Use a relative path to avoid having to manually change the
44         +               # autogenerated hgrc if the user changes $config{srcdir}.
45         +               use File::Spec;
46         +               my $mercurial_wrapper_relpath=File::Spec->abs2rel($config{mercurial_wrapper}, $config{srcdir});
47         +               open (HGRC, '>', $config{srcdir}.'/.hg/hgrc');
48         +               print HGRC <<EOF;
49         +[hooks]
50         +post-commit.ikiwiki = $mercurial_wrapper_relpath
51         +incoming.ikiwiki = $mercurial_wrapper_relpath
52         +EOF
53         +               close (HGRC);
54         +       }
55         +
56                 # Add it to the wikilist.
57                 mkpath("$ENV{HOME}/.ikiwiki");
58                 open (WIKILIST, ">>$ENV{HOME}/.ikiwiki/wikilist") || die "$ENV{HOME}/.ikiwiki/wikilist: $!";
59
60
61 Less compact but more robust way (addresses point 1 and 2)
62 ----------------------------------------------------------
63 [This complete patch at pastebin](http://pastebin.com/AcDHjbK6) ([raw version](http://pastebin.com/raw.php?i=AcDHjbK6)).
64
65 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.
66
67 Set default `ikiwiki-wrapper` path.
68
69         diff -r b08179653c00 IkiWiki/Setup/Automator.pm
70         --- a/IkiWiki/Setup/Automator.pm        Wed Jul 20 16:56:09 2011 +0200
71         +++ b/IkiWiki/Setup/Automator.pm        Wed Jul 20 19:28:21 2011 +0200
72         @@ -75,8 +75,7 @@
73                                 print STDERR "warning: do not know how to set up the bzr_wrapper hook!\n";
74                         }
75                         elsif ($config{rcs} eq 'mercurial') {
76         -                       # TODO
77         -                       print STDERR "warning: do not know how to set up the mercurial_wrapper hook!\n";
78         +                       $config{mercurial_wrapper}=$config{srcdir}."/.hg/ikiwiki-wrapper";
79                         }
80                         elsif ($config{rcs} eq 'tla') {
81                                 # TODO
82
83 Create `$config{srcdir}/.hg/hgrc` during auto-installation with hook info.
84
85         @@ -182,6 +181,19 @@
86                         }
87                 }
88                 
89         +       # Setup initial config file for Mercurial to hook up the wrapper. The
90         +       # path to the wrapper will be automatically added when it is generated.
91         +       if ($config{rcs} eq 'mercurial' && exists $config{mercurial_wrapper}
92         +               && length $config{mercurial_wrapper}) {
93         +               open (HGRC, '>', $config{srcdir}.'/.hg/hgrc');
94         +               print HGRC <<EOF;
95         +[hooks]
96         +post-commit.ikiwiki = 
97         +incoming.ikiwiki = 
98         +EOF
99         +               close (HGRC);
100         +       }
101         +
102                 # Add wrappers, make live.
103                 if (system("ikiwiki", "--wrappers", "--setup", $config{dumpsetup}) != 0) {
104                         die "ikiwiki --wrappers --setup $config{dumpsetup} failed";
105
106 `hgrc` is setup initially. Below follows code to keep `hgrc` updated.
107
108 Add backend specific function `rcs_wrapper_postcall()` for later call in `Wrappers.pm`.
109
110         diff -r b08179653c00 IkiWiki/Plugin/mercurial.pm
111         --- a/IkiWiki/Plugin/mercurial.pm       Wed Jul 20 16:56:09 2011 +0200
112         +++ b/IkiWiki/Plugin/mercurial.pm       Wed Jul 20 19:28:21 2011 +0200
113         @@ -21,6 +21,7 @@
114                 hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
115                 hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
116                 hook(type => "rcs", id => "rcs_getmtime", call => \&rcs_getmtime);
117         +       hook(type => "rcs", id => "rcs_wrapper_postcall", call => \&rcs_wrapper_postcall);
118          }
119          
120          sub checkconfig () {
121
122 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).
123
124         @@ -28,6 +29,7 @@
125                         push @{$config{wrappers}}, {
126                                 wrapper => $config{mercurial_wrapper},
127                                 wrappermode => (defined $config{mercurial_wrappermode} ? $config{mercurial_wrappermode} : "06755"),
128         +                       wrapper_postcall => (defined $config{mercurial_wrapper_hgrc_update} ? $config{mercurial_wrapper_hgrc_update} : "1"),
129                         };
130                 }
131          }
132
133 Include default configuration value and comment.
134
135         @@ -53,6 +55,13 @@
136                                 safe => 0,
137                                 rebuild => 0,
138                         },
139         +               mercurial_wrapper_hgrc_update => {
140         +                       type => "string",
141         +                       example => "1",
142         +                       description => "updates existing hgrc to reflect path changes for mercurial_wrapper",
143         +                       safe => 0,
144         +                       rebuild => 0,
145         +               },
146                         historyurl => {
147                                 type => "string",
148                                 example => "http://example.com:8000/log/tip/\[[file]]",
149
150 `hgrc` should be updated to point to the new wrapper path. The regexp transforms lines as e.g.
151
152         post-commit.ikiwiki = /home/daniel/blog/.hg/ikiwiki-wrapper-oldpath
153         incoming.ikiwiki = /home/daniel/blog/.hg/ikiwiki-wrapper-oldpath
154
155 to
156
157         post-commit.ikiwiki = $config{mercurial_wrapper}
158         incoming.ikiwiki = $config{mercurial_wrapper}
159
160 with absolute paths.
161
162         @@ -402,4 +411,23 @@
163                 return findtimes($file, 0);
164          }
165          
166         +sub rcs_wrapper_postcall($) {
167         +       # Update hgrc if it exists. Change post-commit/incoming hooks with the
168         +       # .ikiwiki suffix to point to the wrapper path given in the setup file.
169         +       # Work with a tempfile to not delete hgrc if the loop is interrupted
170         +       # midway.
171         +       my $hgrc=$config{srcdir}.'/.hg/hgrc';
172         +       my $backup_suffix='.ikiwiki.bak';
173         +       if (-e $hgrc) {
174         +               use File::Spec;
175         +               my $mercurial_wrapper_abspath=File::Spec->rel2abs($config{mercurial_wrapper}, $config{srcdir});
176         +               local ($^I, @ARGV)=($backup_suffix, $hgrc);
177         +               while (<>) {
178         +                       s/^(post-commit|incoming)(\.ikiwiki[ \t]*=[ \t]*).*$/$1$2$mercurial_wrapper_abspath/;
179         +                       print;
180         +               }
181         +               unlink($hgrc.$backup_suffix);
182         +       }
183         +}
184         +
185          1
186
187 `rcs_wrapper_postcall` is made available.
188
189         diff -r b08179653c00 IkiWiki.pm
190         --- a/IkiWiki.pm        Wed Jul 20 16:56:09 2011 +0200
191         +++ b/IkiWiki.pm        Wed Jul 20 19:28:21 2011 +0200
192         @@ -2059,6 +2059,10 @@
193                 $hooks{rcs}{rcs_getmtime}{call}->(@_);
194          }
195          
196         +sub rcs_wrapper_postcall (@) {
197         +       $hooks{rcs}{rcs_wrapper_postcall}{call}->(@_);
198         +}
199         +
200          sub rcs_receive () {
201                 $hooks{rcs}{rcs_receive}{call}->();
202          }
203
204
205 `rcs_wrapper_postcall` is called if $config{wrapper_postcall} is true, which it should only be for Mercurial at the moment.
206
207         diff -r b08179653c00 IkiWiki/Wrapper.pm
208         --- a/IkiWiki/Wrapper.pm        Wed Jul 20 16:56:09 2011 +0200
209         +++ b/IkiWiki/Wrapper.pm        Wed Jul 20 19:28:21 2011 +0200
210         @@ -238,6 +238,10 @@
211                 }
212                 #translators: The parameter is a filename.
213                 debug(sprintf(gettext("successfully generated %s"), $wrapper));
214         +
215         +       if (defined $config{wrapper_postcall} && $config{wrapper_postcall} ) {
216         +               IkiWiki::rcs_wrapper_postcall();
217         +       }
218          }
219          
220          1