1 Using the Mercurial backend, the lack of `rcs_commit_staged` is noticed frequently. I couldn't find any tries to update `mercurial.pm`, so not letting lack of Mercurial AND Perl knowledge bring me down, I copy-pasted from `git.pm` to mimic its behaviour from a Mercurial perspective. I hope it can be a foundation for development by those more proficient in ikiwiki's inner workings. I have doubts that I personally will be able to revise it more, based on my Perl skills.
3 I've tested it briefly. `ikiwiki-calendar` and posting of comments now works with automatic commits, i.e. the `rcs_commit_staged` function works in those cases. Under my current setup, I don't know where else to expect it to work. I would be flabberghasted if there wasn't any problems with it, though.
5 Diff follows, for anyone to annotate. Code is also available at [my hg-repo](http://510x.se/hg/program/ikiwiki/file/e741fcfd800f/Plugin/mercurial.pm).
7 diff -r 20c61288d7bd Plugin/mercurial.pm
8 --- a/Plugin/mercurial.pm Fri Jul 15 02:55:12 2011 +0200
9 +++ b/Plugin/mercurial.pm Fri Jul 15 03:29:10 2011 +0200
12 use open qw{:utf8 :std};
17 hook(type => "checkconfig", id => "mercurial", call => \&checkconfig);
18 hook(type => "getsetup", id => "mercurial", call => \&getsetup);
20 A corresponding variable is declared for git. It is unused as of yet for Mercurial, but when more advanced merge features become available for `mercurial.pm`, I think it will come into play.
27 + # Start a child process safely without resorting to /bin/sh.
28 + # Returns command output (in list content) or success state
29 + # (in scalar context), or runs the specified data handler.
31 + my ($error_handler, $data_handler, @cmdline) = @_;
33 + my $pid = open my $OUT, "-|";
35 + error("Cannot fork: $!") if !defined $pid;
39 + # hg commands want to be in wc.
40 + if (! defined $hg_dir) {
41 + chdir $config{srcdir}
42 + or error("cannot chdir to $config{srcdir}: $!");
46 + or error("cannot chdir to $hg_dir: $!");
48 + exec @cmdline or error("Cannot exec '@cmdline': $!");
52 + # hg output is probably utf-8 encoded, but may contain
53 + # other encodings or invalidly encoded stuff. So do not rely
54 + # on the normal utf-8 IO layer, decode it by hand.
59 + $_=decode_utf8($_, 0);
63 + if (! defined $data_handler) {
67 + last unless $data_handler->($_);
73 + $error_handler->("'@cmdline' failed: $!") if $? && $error_handler;
75 + return wantarray ? @lines : ($? == 0);
77 +# Convenient wrappers.
78 +sub run_or_die ($@) { safe_hg(\&error, undef, @_) }
79 +sub run_or_cry ($@) { safe_hg(sub { warn @_ }, undef, @_) }
80 +sub run_or_non ($@) { safe_hg(undef, undef, @_) }
82 sub mercurial_log ($) {
89 - my @cmdline = ("hg", "-q", "-R", "$config{srcdir}", "update");
90 - if (system(@cmdline) != 0) {
91 - warn "'@cmdline' failed: $!";
93 + run_or_cry('hg', '-q', 'update');
96 sub rcs_prepedit ($) {
98 With the `run_or_{die,cry,non}()` functions defined as in `git.pm`, some old Mercurial functions can be rewritten more compactly.
104 + return rcs_commit_helper(@_);
107 +sub rcs_commit_helper (@) {
112 my $user="Anonymous";
113 if (defined $params{session}) {
114 if (defined $params{session}->param("name")) {
116 Here comes the `rcs_commit{,_staged}` part. It is modeled on a `rcs_commit_helper` function, as in `git.pm`.
118 Some old `mercurial.pm` logic concerning commiter name is kept instead of transplanting the more elaborate logic from `git.pm`. Maybe it is better to "steal" that as well.
120 @@ -143,43 +206,45 @@
121 $params{message} = "no message given";
124 - my @cmdline = ("hg", "-q", "-R", $config{srcdir}, "commit",
125 - "-m", IkiWiki::possibly_foolish_untaint($params{message}),
126 - "-u", IkiWiki::possibly_foolish_untaint($user));
127 - if (system(@cmdline) != 0) {
128 - warn "'@cmdline' failed: $!";
129 + $params{message} = IkiWiki::possibly_foolish_untaint($params{message});
133 + if (exists $params{file}) {
134 + push @opts, '--', $params{file};
137 + # hg commit returns non-zero if nothing really changed.
138 + # So we should ignore its exit status (hence run_or_non).
139 + run_or_non('hg', 'commit', '-m', $params{message}, '-q', @opts);
142 return undef; # success
145 sub rcs_commit_staged (@) {
146 # Commits all staged changes. Changes can be staged using rcs_add,
147 # rcs_remove, and rcs_rename.
150 - error("rcs_commit_staged not implemented for mercurial"); # TODO
151 + return rcs_commit_helper(@_);
157 - my @cmdline = ("hg", "-q", "-R", "$config{srcdir}", "add", "$config{srcdir}/$file");
158 - if (system(@cmdline) != 0) {
159 - warn "'@cmdline' failed: $!";
161 + run_or_cry('hg', 'add', $file);
165 + # Remove file from archive.
169 - error("rcs_remove not implemented for mercurial"); # TODO
170 + run_or_cry('hg', 'remove', '-f', $file);
173 sub rcs_rename ($$) {
174 my ($src, $dest) = @_;
176 - error("rcs_rename not implemented for mercurial"); # TODO
177 + run_or_cry('hg', 'rename', '-f', $src, $dest);
180 sub rcs_recentchanges ($) {