mercurial: Make both rcs_getctime and rcs_getmtime fast. (Daniel Andersson)
authorJoey Hess <joey@kitenet.net>
Tue, 19 Jul 2011 15:39:32 +0000 (11:39 -0400)
committerJoey Hess <joey@kitenet.net>
Tue, 19 Jul 2011 15:39:32 +0000 (11:39 -0400)
IkiWiki/Plugin/mercurial.pm
debian/changelog
doc/rcs.mdwn
doc/todo/rcs__95__get__123__c__44__m__125__time_implementation_for_Mercurial_backend__44___based_on_Git_backend.mdwn

index 79f0215161836cfd3773b8433ec36d9fd5ed2f64..e64e00512155e3bd6aa94839b85a6102fcc73b98 100644 (file)
@@ -258,7 +258,7 @@ sub rcs_recentchanges ($) {
        foreach my $info (mercurial_log($out)) {
                my @pages = ();
                my @message = ();
-        
+
                foreach my $msgline (split(/\n/, $info->{description})) {
                        push @message, { line => $msgline };
                }
@@ -310,28 +310,80 @@ sub rcs_diff ($;$) {
        # TODO
 }
 
-sub rcs_getctime ($) {
-       my ($file) = @_;
+{
+my %time_cache;
+
+sub findtimes ($$) {
+       my $file=shift;
+       my $id=shift; # 0 = mtime ; 1 = ctime
+
+       if (! keys %time_cache) {
+               my $date;
+
+               # It doesn't seem possible to specify the format wanted for the
+               # changelog (same format as is generated in git.pm:findtimes(),
+               # though the date differs slightly) without using a style
+               # _file_. There is a "hg log" switch "--template" to directly
+               # control simple output formatting, but in this case, the
+               # {file} directive must be redefined, which can only be done
+               # with "--style".
+               #
+               # If {file} is not redefined, all files 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).
+               
+               eval q{use File::Temp};
+               error $@ if $@;
+               my ($tmpl_fh, $tmpl_filename) = File::Temp::tempfile(UNLINK => 1);
+               
+               print $tmpl_fh 'changeset = "{date}\\n{files}\\n"' . "\n";
+               print $tmpl_fh 'file = "{file}\\n"' . "\n";
+               
+               foreach my $line (run_or_die('hg', 'log', '--style', $tmpl_filename)) {
+                       # {date} gives output on the form
+                       # 1310694511.0-7200
+                       # where the first number is UTC Unix timestamp with one
+                       # decimal (decimal always 0, at least on my system)
+                       # followed by local timezone offset from UTC in
+                       # seconds.
+                       if (! defined $date && $line =~ /^\d+\.\d[+-]\d*$/) {
+                               $line =~ s/^(\d+).*/$1/;
+                               $date=$line;
+                       }
+                       elsif (! length $line) {
+                               $date=undef;
+                       }
+                       else {
+                               my $f=$line;
 
-       my @cmdline = ("hg", "-R", $config{srcdir}, "log", "-v",
-               "--style", "default", "$config{srcdir}/$file");
-       open (my $out, "-|", @cmdline);
+                               if (! $time_cache{$f}) {
+                                       $time_cache{$f}[0]=$date; # mtime
+                               }
+                               $time_cache{$f}[1]=$date; # ctime
+                       }
+               }
+       }
 
-       my @log = (mercurial_log($out));
+       return exists $time_cache{$file} ? $time_cache{$file}[$id] : 0;
+}
 
-       if (@log < 1) {
-               return 0;
-       }
+}
 
-       eval q{use Date::Parse};
-       error($@) if $@;
-       
-       my $ctime = str2time($log[$#log]->{"date"});
-       return $ctime;
+sub rcs_getctime ($) {
+       my $file = shift;
+
+       return findtimes($file, 1);
 }
 
 sub rcs_getmtime ($) {
-       error "rcs_getmtime is not implemented for mercurial\n"; # TODO
+       my $file = shift;
+
+       return findtimes($file, 0);
 }
 
 1
index 30084304aad64375e8980488d115a690a200334f..562816083d7065bae238b5c504940a486e78fa19 100644 (file)
@@ -5,6 +5,7 @@ ikiwiki (3.20110716) UNRELEASED; urgency=low
     can be used. (Daniel Andersson)
   * mercurial: fix viewing of a diff containing non-utf8 changes.
     (Daniel Andersson)
+  * mercurial: Make both rcs_getctime and rcs_getmtime fast. (Daniel Andersson)
 
  -- Joey Hess <joeyh@debian.org>  Tue, 19 Jul 2011 11:22:52 -0400
 
index 9f531d4427bbdfd0cff39e35119fa8ffc3232511..f2c6f192fd5d1e10c40681665a781ea782ecc159 100644 (file)
@@ -21,8 +21,8 @@ auto.setup          |yes    |yes    |incomplete|yes         |incomplete   |yes
 `rcs_rename`        |yes    |yes    |yes       |yes         |no           |yes      |no        |yes
 `rcs_remove`        |yes    |yes    |yes       |yes         |no           |yes      |no        |yes
 `rcs_diff`          |yes    |yes    |yes       |yes         |no           |yes      |yes       |yes
-`rcs_getctime`      |fast   |slow   |slow      |slow        |slow         |slow     |slow      |slow
-`rcs_getmtime`      |fast   |slow   |slow      |slow        |no           |no       |no        |no
+`rcs_getctime`      |fast   |slow   |slow      |slow        |fast         |slow     |slow      |slow
+`rcs_getmtime`      |fast   |slow   |slow      |slow        |fast         |no       |no        |no
 `rcs_preprevert`    |yes    |no     |no        |no          |no           |no       |no        |no
 `rcs_revert`        |yes    |no     |no        |no          |no           |no       |no        |no
 anonymous push      |yes    |no     |no        |no          |no           |no       |no        |no
index 6cd195a53528ef0aa3a1e55381dfa3f5fc2ab384..54ab4ad3a97b9e7cf995ced961cca7fd0bf59771 100644 (file)
@@ -21,6 +21,11 @@ In the patch listing below, I've marked the parts of the patch that should be re
 
 --[[Daniel Andersson]]
 
+> I have applied this, but I left the temp file in. 
+> The overhead seems small since it will only be run once per ikiwiki run,
+> and only when `ikiwiki --gettime` is run, or the first time
+> ikiwiki runs. Thanks for this! [[done]] --[[Joey]] 
+
 ---
 
        diff -r 78a217fb13f3 -r 1b6c46b62a28 Plugin/mercurial.pm