X-Git-Url: http://git.tremily.us/?a=blobdiff_plain;f=IkiWiki%2FPlugin%2Fgit.pm;h=a43b8592048a54d0e9cd91565bb95f5d4510ab3c;hb=c46bcb425af0948ac59581d6ba7b477826d83ae3;hp=86d80186f3f8671140dc01a00706e2d265545779;hpb=b14f84c4acccbc8450a9102b3b647013989b27bb;p=ikiwiki.git diff --git a/IkiWiki/Plugin/git.pm b/IkiWiki/Plugin/git.pm index 86d80186f..a43b85920 100644 --- a/IkiWiki/Plugin/git.pm +++ b/IkiWiki/Plugin/git.pm @@ -280,11 +280,35 @@ sub merge_past ($$$) { return $conflict; } -sub parse_diff_tree ($@) { +{ +my $prefix; +sub decode_git_file ($) { + my $file=shift; + + # git does not output utf-8 filenames, but instead + # double-quotes them with the utf-8 characters + # escaped as \nnn\nnn. + if ($file =~ m/^"(.*)"$/) { + ($file=$1) =~ s/\\([0-7]{1,3})/chr(oct($1))/eg; + } + + # strip prefix if in a subdir + if (! defined $prefix) { + ($prefix) = run_or_die('git', 'rev-parse', '--show-prefix'); + if (! defined $prefix) { + $prefix=""; + } + } + $file =~ s/^\Q$prefix\E//; + + return decode("utf8", $file); +} +} + +sub parse_diff_tree ($) { # Parse the raw diff tree chunk and return the info hash. # See git-diff-tree(1) for the syntax. - - my ($prefix, $dt_ref) = @_; + my $dt_ref = shift; # End of stream? return if !defined @{ $dt_ref } || @@ -318,8 +342,9 @@ sub parse_diff_tree ($@) { $ci{ "${who}_epoch" } = $epoch; $ci{ "${who}_tz" } = $tz; - if ($name =~ m/^[^<]+\s+<([^@>]+)/) { - $ci{"${who}_username"} = $1; + if ($name =~ m/^([^<]+)\s+<([^@>]+)/) { + $ci{"${who}_name"} = $1; + $ci{"${who}_username"} = $2; } elsif ($name =~ m/^([^<]+)\s+<>$/) { $ci{"${who}_username"} = $1; @@ -367,16 +392,9 @@ sub parse_diff_tree ($@) { my $sha1_to = shift(@tmp); my $status = shift(@tmp); - # git does not output utf-8 filenames, but instead - # double-quotes them with the utf-8 characters - # escaped as \nnn\nnn. - if ($file =~ m/^"(.*)"$/) { - ($file=$1) =~ s/\\([0-7]{1,3})/chr(oct($1))/eg; - } - $file =~ s/^\Q$prefix\E//; if (length $file) { push @{ $ci{'details'} }, { - 'file' => decode("utf8", $file), + 'file' => decode_git_file($file), 'sha1_from' => $sha1_from[0], 'sha1_to' => $sha1_to, 'mode_from' => $mode_from[0], @@ -403,10 +421,9 @@ sub git_commit_info ($;$) { my @raw_lines = run_or_die('git', 'log', @opts, '--pretty=raw', '--raw', '--abbrev=40', '--always', '-c', '-r', $sha1, '--', '.'); - my ($prefix) = run_or_die('git', 'rev-parse', '--show-prefix'); my @ci; - while (my $parsed = parse_diff_tree(($prefix or ""), \@raw_lines)) { + while (my $parsed = parse_diff_tree(\@raw_lines)) { push @ci, $parsed; } @@ -572,9 +589,14 @@ sub rcs_recentchanges ($) { push @messages, { line => $line }; } - my $user=$ci->{'author_username'}; + my $user=$ci->{'author_name'}; + my $usershort=$ci->{'author_username'}; my $web_commit = ($ci->{'author'} =~ /\@web>/); - + + if ($usershort =~ /:\/\//) { + $usershort=undef; # url; not really short + } + # compatability code for old web commit messages if (! $web_commit && defined $messages[0] && @@ -587,6 +609,7 @@ sub rcs_recentchanges ($) { push @rets, { rev => $sha1, user => $user, + usershort => $usershort, committype => $web_commit ? "web" : "git", when => $when, message => [@messages], @@ -616,27 +639,53 @@ sub rcs_diff ($) { } } -sub rcs_getctime ($) { +{ +my %time_cache; + +sub findtimes ($$) { my $file=shift; + my $id=shift; # 0 = mtime ; 1 = ctime + # Remove srcdir prefix $file =~ s/^\Q$config{srcdir}\E\/?//; - 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; + if (! keys %time_cache) { + my $date; + foreach my $line (run_or_die('git', 'log', + '--pretty=format:%ct', + '--name-only', '--relative')) { + if (! defined $date && $line =~ /^(\d+)$/) { + $date=$line; + } + elsif (! length $line) { + $date=undef; + } + else { + my $f=decode_git_file($line); + + if (! $time_cache{$f}) { + $time_cache{$f}[0]=$date; # mtime + } + $time_cache{$f}[1]=$date; # ctime + } + } } - my $ctime = $ci[$#ci]->{'author_epoch'}; - debug("ctime for '$file': ". localtime($ctime)); - return $ctime; + return exists $time_cache{$file} ? $time_cache{$file}[$id] : 0; +} + +} + +sub rcs_getctime ($) { + my $file=shift; + + return findtimes($file, 1); } sub rcs_getmtime ($) { - error "rcs_getmtime is not implemented for git\n"; # TODO + my $file=shift; + + return findtimes($file, 0); } sub rcs_receive () {