(no commit message)
[ikiwiki] / doc / todo / rcs__95__get__123__c__44__m__125__time_implementation_for_Mercurial_backend__44___based_on_Git_backend.mdwn
1 (**Note:** this patch is built on top of the patch discussed at [[Attempt to extend Mercurial backend support]]. The `run_or_die()` function declared therein is needed for this patch to run.)
2
3 Patch to change the Mercurial entries for `rcs_getctime` and `rcs_getmtime` from "slow"/"no" to "fast"/"fast" in [[/rcs]].
4
5 The patch is mostly a slightly modified cc of the code in `git.pm`. The exception is that a Mercurial style file is needed to get a reasonable output from `hg log`. To make the file self-contained in its current state, this was solved with a generated temp file, but that section could and should be replaced with just setting `$tmpl_filename` to a path to a static file `map-cmdline.ikiwiki-log` (to conform with Mercurial's naming of its default styles) in the Ikiwiki distribution, with contents
6
7         changeset = "{date}\n{files}\n"
8         file = "{file}\n"
9
10 which is based on an [example](http://hgbook.red-bean.com/read/customizing-the-output-of-mercurial.html#id417978) in [Mercurial: The Definitive Guide](http://hgbook.red-bean.com/) (and otherwise fascinatingly undocumented). A style *file* is required for this kind of formatting. There is a switch `hg log --template` to directly control simple output formatting, but in this case, the `{file}` directive must be redefined, which can only be done with `hg log --style`.
11
12 If `{file}` is not redefined, all filenames are output on a single line separated with a space. It is not possible to conclude if the space is part of a filename or just a separator, and thus impossible to use in this case. Some output filters are available in hg, but they are not fit for this cause (and would slow down the process unnecessarily).
13
14 In the patch listing below, I've marked the parts of the patch that should be removed when the tempfile replacement is done with **Marker# start** and **Marker# end**.
15
16 [Patch at pastebin](http://pastebin.com/QBE4UH6n).
17
18 [Patch at pastebin with tempfile code replaced by a path to a static file (change path accordingly)](http://pastebin.com/dmSCRkUK).
19
20 [My `mercurial.pm` in raw format after this and beforementioned patches (tempfile code present)](http://510x.se/hg/program/ikiwiki/raw-file/1b6c46b62a28/Plugin/mercurial.pm).
21
22 --[[Daniel Andersson]]
23
24 ---
25
26         diff -r 78a217fb13f3 -r 1b6c46b62a28 Plugin/mercurial.pm
27         --- a/Plugin/mercurial.pm       Sat Jul 16 03:19:25 2011 +0200
28         +++ b/Plugin/mercurial.pm       Tue Jul 19 13:35:17 2011 +0200
29         @@ -310,28 +310,91 @@
30                 # TODO
31          }
32          
33         -sub rcs_getctime ($) {
34         -       my ($file) = @_;
35         +{
36         +my %time_cache;
37          
38         -       my @cmdline = ("hg", "-R", $config{srcdir}, "log", "-v",
39         -               "--style", "default", "$config{srcdir}/$file");
40         -       open (my $out, "-|", @cmdline);
41         +sub findtimes ($$) {
42         +       my $file=shift;
43         +       my $id=shift; # 0 = mtime ; 1 = ctime
44          
45         -       my @log = (mercurial_log($out));
46         +       if (! keys %time_cache) {
47         +               my $date;
48          
49         -       if (@log < 1) {
50         -               return 0;
51
52 **Marker1 start**
53
54         +               # The tempfile logic should be replaced with a file included
55         +               # with ikiwiki containing
56         +               # --
57         +               # changeset = "{date}\n{files}\n"
58         +               # file = "{file}\n"
59         +               # --
60         +               # to avoid creating a file with static contents every time this
61         +               # function is called. The path to this file should replace
62         +               # $tmpl_filename in run_or_die() below.
63         +               #
64
65 **Marker1 end**
66
67         +               # It doesn't seem possible to specify the format wanted for the
68         +               # changelog (same format as is generated in git.pm:findtimes(),
69         +               # though the date differs slightly) without using a style
70         +               # _file_. There is a "hg log" switch "--template" to directly
71         +               # control simple output formatting, but in this case, the
72         +               # {file} directive must be redefined, which can only be done
73         +               # with "--style".
74         +               #
75         +               # If {file} is not redefined, all files are output on a single
76         +               # line separated with a space. It is not possible to conclude
77         +               # if the space is part of a filename or just a separator, and
78         +               # thus impossible to use in this case.
79         +               # 
80         +               # Some output filters are available in hg, but they are not fit
81         +               # for this cause (and would slow down the process
82         +               # unnecessarily).
83         +
84
85 **Marker2 start**
86
87         +               use File::Temp qw(tempfile);
88         +               my ($tmpl_fh, $tmpl_filename) = tempfile(UNLINK => 1);
89         +
90         +               print $tmpl_fh 'changeset = "{date}\\n{files}\\n"' . "\n";
91         +               print $tmpl_fh 'file = "{file}\\n"' . "\n";
92         +
93
94 **Marker2 end**
95
96         +               foreach my $line (run_or_die('hg', 'log', '--style',
97         +                               $tmpl_filename)) {
98         +                       # {date} gives output on the form
99         +                       # 1310694511.0-7200
100         +                       # where the first number is UTC Unix timestamp with one
101         +                       # decimal (decimal always 0, at least on my system)
102         +                       # followed by local timezone offset from UTC in
103         +                       # seconds.
104         +                       if (! defined $date && $line =~ /^\d+\.\d[+-]\d*$/) {
105         +                               $line =~ s/^(\d+).*/$1/;
106         +                               $date=$line;
107         +                       }
108         +                       elsif (! length $line) {
109         +                               $date=undef;
110         +                       }
111         +                       else {
112         +                               my $f=$line;
113         +
114         +                               if (! $time_cache{$f}) {
115         +                                       $time_cache{$f}[0]=$date; # mtime
116         +                               }
117         +                               $time_cache{$f}[1]=$date; # ctime
118         +                       }
119         +               }
120
121 **Marker3 start**
122
123         +               close ($tmpl_fh);
124
125 **Marker3 end**
126
127                 }
128          
129         -       eval q{use Date::Parse};
130         -       error($@) if $@;
131         -       
132         -       my $ctime = str2time($log[$#log]->{"date"});
133         -       return $ctime;
134         +       return exists $time_cache{$file} ? $time_cache{$file}[$id] : 0;
135         +}
136         +
137         +}
138         +
139         +sub rcs_getctime ($) {
140         +       my $file = shift;
141         +
142         +       return findtimes($file, 1);
143          }
144          
145          sub rcs_getmtime ($) {
146         -       error "rcs_getmtime is not implemented for mercurial\n"; # TODO
147         +       my $file = shift;
148         +
149         +       return findtimes($file, 0);
150          }
151          
152          1