Merge branch 'master' of git://github.com/bobtfish/Gitalist
[catagits/Gitalist.git] / lib / Gitalist / Git / Object / Commit.pm
index 5a125f6..817c99f 100644 (file)
@@ -140,4 +140,70 @@ class Gitalist::Git::Object::Commit
             return @ret;
         }
 
+
+  # XXX A prime candidate for caching.
+  method blame ( NonEmptySimpleStr $filename ) {
+    my @blameout = $self->_run_cmd_list(
+      blame => '-p', $self->sha1, '--', $filename
+    );
+
+    my(%commitdata, @filedata);
+    while(defined(local $_ = shift @blameout)) {
+      my ($sha1, $orig_lineno, $lineno, $group_size) =
+        /^([0-9a-f]{40}) (\d+) (\d+)(?: (\d+))?$/;
+
+      $commitdata{$sha1} = {}
+        unless exists $commitdata{$sha1};
+
+      my $commit = $commitdata{$sha1};
+      my $line;
+      until(($line = shift @blameout) =~ s/^\t//) {
+        $commit->{$1} = $2
+         if $line =~ /^(\S+) (.*)/;
+      }
+
+      unless(exists $commit->{author_dt}) {
+        for my $t (qw/author committer/) {
+          my $dt = DateTime->from_epoch(epoch => $commit->{"$t-time"});
+          $dt->set_time_zone($commit->{"$t-tz"});
+          $commit->{"$t\_dt"} = $dt;
+        }
+      }
+
+      push @filedata, {
+        line => $line,
+        commit => { sha1 => $sha1, %$commit },
+        meta => {
+          orig_lineno => $orig_lineno,
+          lineno => $lineno,
+          ( $group_size ? (group_size => $group_size) : () ),
+        },
+      };
     }
+
+    return \@filedata;
+  }
+}
+
+
+1;
+
+__END__
+
+=head1 NAME
+
+Gitalist::Git::Object::Commit
+
+=head1 DESCRIPTION
+
+Gitalist::Git::Object::Commit.
+
+=head1 AUTHORS
+
+See L<Gitalist> for authors.
+
+=head1 LICENSE
+
+See L<Gitalist> for the license.
+
+=cut