]> git.vanrenterghem.biz Git - git.ikiwiki.info.git/blobdiff - IkiWiki/Plugin/mercurial.pm
(no commit message)
[git.ikiwiki.info.git] / IkiWiki / Plugin / mercurial.pm
index 79f0215161836cfd3773b8433ec36d9fd5ed2f64..9f0c5b721ccf13b26325eb5ba299ddbb4f0b7f2b 100644 (file)
@@ -5,6 +5,7 @@ use warnings;
 use strict;
 use IkiWiki;
 use Encode;
+use URI::Escape q{uri_escape_utf8};
 use open qw{:utf8 :std};
 
 sub import {
@@ -180,15 +181,15 @@ sub rcs_commit_helper (@) {
        $ENV{HGENCODING} = 'utf-8';
 
        my $user="Anonymous";
-       my $nickname;
        if (defined $params{session}) {
                if (defined $params{session}->param("name")) {
-                       $user = $params{session}->param("name");
+                       $user = IkiWiki::cloak($params{session}->param("name"));
                }
                elsif (defined $params{session}->remote_addr()) {
-                       $user = $params{session}->remote_addr();
+                       $user = IkiWiki::cloak($params{session}->remote_addr());
                }
 
+               my $nickname=$user;
                if (defined $params{session}->param("nickname")) {
                        $nickname=encode_utf8($params{session}->param("nickname"));
                        $nickname=~s/\s+/_/g;
@@ -258,14 +259,15 @@ sub rcs_recentchanges ($) {
        foreach my $info (mercurial_log($out)) {
                my @pages = ();
                my @message = ();
-        
+
                foreach my $msgline (split(/\n/, $info->{description})) {
                        push @message, { line => $msgline };
                }
 
                foreach my $file (split / /,$info->{files}) {
                        my $diffurl = defined $config{diffurl} ? $config{'diffurl'} : "";
-                       $diffurl =~ s/\[\[file\]\]/$file/go;
+                       my $efile = uri_escape_utf8($file);
+                       $diffurl =~ s/\[\[file\]\]/$efile/go;
                        $diffurl =~ s/\[\[r2\]\]/$info->{changeset}/go;
 
                        push @pages, {
@@ -307,31 +309,92 @@ sub rcs_recentchanges ($) {
 }
 
 sub rcs_diff ($;$) {
-       # TODO
+       my $rev=shift;
+       my $maxlines=shift;
+       my @lines;
+       my $addlines=sub {
+               my $line=shift;
+               return if defined $maxlines && @lines == $maxlines;
+               push @lines, $line."\n"
+                       if (@lines || $line=~/^diff --git/);
+               return 1;
+       };
+       safe_hg(undef, $addlines, "hg", "diff", "-c", $rev, "-g");
+       if (wantarray) {
+               return @lines;
+       }
+       else {
+               return join("", @lines);
+       }
 }
 
-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)) {
+                       if (! defined $date && $line =~ /^(\d+)/) {
+                               $date=$1;
+                       }
+                       elsif (! length $line) {
+                               $date=undef;
+                       }
+                       else {
+                               my $f=$line;
+
+                               if (! $time_cache{$f}) {
+                                       $time_cache{$f}[0]=$date; # mtime
+                               }
+                               $time_cache{$f}[1]=$date; # ctime
+                       }
+               }
+       }
 
-       my @cmdline = ("hg", "-R", $config{srcdir}, "log", "-v",
-               "--style", "default", "$config{srcdir}/$file");
-       open (my $out, "-|", @cmdline);
+       return exists $time_cache{$file} ? $time_cache{$file}[$id] : 0;
+}
 
-       my @log = (mercurial_log($out));
+}
 
-       if (@log < 1) {
-               return 0;
-       }
+sub rcs_getctime ($) {
+       my $file = shift;
 
-       eval q{use Date::Parse};
-       error($@) if $@;
-       
-       my $ctime = str2time($log[$#log]->{"date"});
-       return $ctime;
+       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