]> git.vanrenterghem.biz Git - git.ikiwiki.info.git/blobdiff - IkiWiki/Plugin/git.pm
minor refactor/optimisation
[git.ikiwiki.info.git] / IkiWiki / Plugin / git.pm
index 6a7f6c3ae3f9eaf3e5dafab166fa3060d946cdf0..b02f4a5ed5750145fe711095c3f7afa085c38732 100644 (file)
@@ -14,6 +14,7 @@ my $no_chdir=0;
 sub import {
        hook(type => "checkconfig", id => "git", call => \&checkconfig);
        hook(type => "getsetup", id => "git", call => \&getsetup);
+       hook(type => "genwrapper", id => "git", call => \&genwrapper);
        hook(type => "rcs", id => "rcs_update", call => \&rcs_update);
        hook(type => "rcs", id => "rcs_prepedit", call => \&rcs_prepedit);
        hook(type => "rcs", id => "rcs_commit", call => \&rcs_commit);
@@ -41,6 +42,7 @@ sub checkconfig () {
                        wrappermode => (defined $config{git_wrappermode} ? $config{git_wrappermode} : "06755"),
                };
        }
+
        if (defined $config{git_test_receive_wrapper} &&
            length $config{git_test_receive_wrapper}) {
                push @{$config{wrappers}}, {
@@ -49,6 +51,16 @@ sub checkconfig () {
                        wrappermode => (defined $config{git_wrappermode} ? $config{git_wrappermode} : "06755"),
                };
        }
+
+       # Avoid notes, parser does not handle and they only slow things down.
+       $ENV{GIT_NOTES_REF}="";
+       
+       # Run receive test only if being called by the wrapper, and not
+       # when generating same.
+       if ($config{test_receive} && ! exists $config{wrapper}) {
+               require IkiWiki::Receive;
+               IkiWiki::Receive::test();
+       }
 }
 
 sub getsetup () {
@@ -56,6 +68,7 @@ sub getsetup () {
                plugin => {
                        safe => 0, # rcs plugin
                        rebuild => undef,
+                       section => "rcs",
                },
                git_wrapper => {
                        type => "string",
@@ -94,8 +107,8 @@ sub getsetup () {
                },
                diffurl => {
                        type => "string",
-                       example => "http://git.example.com/gitweb.cgi?p=wiki.git;a=blobdiff;h=[[sha1_to]];hp=[[sha1_from]];hb=[[sha1_parent]];f=[[file]]",
-                       description => "gitweb url to show a diff ([[sha1_to]], [[sha1_from]], [[sha1_parent]], [[sha1_commit]] and [[file]] substituted)",
+                       example => "http://git.example.com/gitweb.cgi?p=wiki.git;a=blobdiff;f=[[file]];h=[[sha1_to]];hp=[[sha1_from]];hb=[[sha1_commit]];hpb=[[sha1_parent]]",
+                       description => "gitweb url to show a diff ([[file]], [[sha1_to]], [[sha1_from]], [[sha1_commit]], and [[sha1_parent]] substituted)",
                        safe => 1,
                        rebuild => 1,
                },
@@ -115,6 +128,16 @@ sub getsetup () {
                },
 }
 
+sub genwrapper {
+       if ($config{test_receive}) {
+               require IkiWiki::Receive;
+               return IkiWiki::Receive::genwrapper();
+       }
+       else {
+               return "";
+       }
+}
+
 sub safe_git (&@) {
        # Start a child process safely without resorting /bin/sh.
        # Return command output or success state (in scalar context).
@@ -136,9 +159,17 @@ sub safe_git (&@) {
        }
        # In parent.
 
+       # git output is probably utf-8 encoded, but may contain
+       # other encodings or invalidly encoded stuff. So do not rely
+       # on the normal utf-8 IO layer, decode it by hand.
+       binmode($OUT);
+
        my @lines;
        while (<$OUT>) {
+               $_=decode_utf8($_, 0);
+
                chomp;
+
                push @lines, $_;
        }
 
@@ -392,7 +423,10 @@ sub git_sha1 (;$) {
                '--', $file);
        if ($sha1) {
                ($sha1) = $sha1 =~ m/($sha1_pattern)/; # sha1 is untainted now
-       } else { debug("Empty sha1sum for '$file'.") }
+       }
+       else {
+               debug("Empty sha1sum for '$file'.");
+       }
        return defined $sha1 ? $sha1 : q{};
 }
 
@@ -441,7 +475,7 @@ sub rcs_commit_staged ($$$) {
        # Set the commit author and email to the web committer.
        my %env=%ENV;
        if (defined $user || defined $ipaddr) {
-               my $u=defined $user ? $user : $ipaddr;
+               my $u=encode_utf8(defined $user ? $user : $ipaddr);
                $ENV{GIT_AUTHOR_NAME}=$u;
                $ENV{GIT_AUTHOR_EMAIL}="$u\@web";
        }
@@ -586,9 +620,15 @@ sub rcs_getctime ($) {
        # Remove srcdir prefix
        $file =~ s/^\Q$config{srcdir}\E\/?//;
 
-       my $sha1  = git_sha1($file);
-       my $ci    = git_commit_info($sha1, 1);
-       my $ctime = $ci->{'author_epoch'};
+       my @raw_lines = run_or_die('git', 'log', 
+               '--follow', '--no-merges',
+               '--pretty=raw', '--raw', '--abbrev=40', '--always', '-c',
+               '-r', '--', $file);
+       my @ci;
+       while (my $parsed = parse_diff_tree("", \@raw_lines)) {
+               push @ci, $parsed;
+       }
+       my $ctime = $ci[$#ci]->{'author_epoch'};
        debug("ctime for '$file': ". localtime($ctime));
 
        return $ctime;