File Coverage

blib/lib/Git/Repository/Plugin/Blame.pm
Criterion Covered Total %
statement 49 49 100.0
branch 13 18 72.2
condition 2 2 100.0
subroutine 10 10 100.0
pod 1 1 100.0
total 75 80 93.7


line stmt bran cond sub pod time code
1             package Git::Repository::Plugin::Blame;
2              
3 2     2   49731 use warnings;
  2         5  
  2         79  
4 2     2   9 use strict;
  2         4  
  2         67  
5 2     2   48 use 5.006;
  2         9  
  2         65  
6              
7 2     2   1132 use Git::Repository::Plugin;
  2         1016  
  2         211  
8             our @ISA = qw( Git::Repository::Plugin );
9 1     1   57 sub _keywords { return qw( blame ) } ## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
10              
11 2     2   12 use Carp;
  2         3  
  2         108  
12 2     2   1178 use Class::Load qw();
  2         59643  
  2         69  
13 2     2   1346 use Perl6::Slurp qw();
  2         3175  
  2         54  
14 2     2   969 use Git::Repository::Plugin::Blame::Line;
  2         4  
  2         1914  
15              
16              
17             =head1 NAME
18              
19             Git::Repository::Plugin::Blame - Add a blame() method to L.
20              
21              
22             =head1 VERSION
23              
24             Version 1.2.3
25              
26             =cut
27              
28             our $VERSION = '1.2.3';
29              
30              
31             =head1 SYNOPSIS
32              
33             # Load the plugin.
34             use Git::Repository 'Blame';
35              
36             my $repository = Git::Repository->new();
37              
38             # Get the git blame information.
39             my $blame_lines = $repository->blame( $file );
40              
41              
42             =head1 DESCRIPTION
43              
44             This module adds a new C method to L, which can be
45             used to determine what the last change for each line in a file is.
46              
47              
48             =head1 METHODS
49              
50             =head2 blame()
51              
52             Return the git blame information for a given file as an arrayref of
53             L objects.
54              
55             my $blame_lines = $repository->blame(
56             $file,
57             use_cache => $boolean, # default 0
58             );
59              
60             Arguments:
61              
62             =over 4
63              
64             =item * use_cache (default: 0)
65              
66             Cache the git blame output.
67              
68             =back
69              
70             =cut
71              
72             sub blame
73             {
74 2     2 1 169200 my ( $repository, $file, %args ) = @_;
75 2   100     53 my $use_cache = delete( $args{'use_cache'} ) || 0;
76 2 50       8 croak 'The following arguments are not valid: ' . join( ', ' , keys %args )
77             if scalar( keys %args ) != 0;
78              
79             # Check if the cache is enabled and if the file has already been parsed.
80 2         4 my $cache;
81 2 100       9 if ( $use_cache )
82             {
83 1         11 my $class = Class::Load::load_class( 'Git::Repository::Plugin::Blame::Cache' );
84 1         112 $cache = $class->new( repository => $repository->work_tree() );
85 1 50       4 croak 'Failed to initialize cache for repository ' . $repository->work_tree()
86             if !defined( $cache );
87              
88 1         3 my $blame_lines = $cache->get_blame_lines( file => $file );
89 1 50       3 return $blame_lines
90             if defined( $blame_lines );
91             }
92              
93             # Run the command.
94 2         13 my $command = $repository->command( 'blame', '--porcelain', $file );
95 2         18708 my @output = $command->final_output();
96              
97             # Parse the output.
98 2         4427 my ( $commit_id, $original_line_number, $final_line_number, $lines_count_in_group );
99 2         6 my $commit_attributes = {};
100 2         4 my $lines = [];
101 2         5 foreach my $line ( @output )
102             {
103 60 100       117 if ( $line =~ /^\t(.*)$/x )
104             {
105             # It's a line from the file we git blamed.
106 8 50       73 push(
107             @$lines,
108             Git::Repository::Plugin::Blame::Line->new(
109             line_number => $final_line_number,
110             line => defined( $1 ) ? $1 : '',
111             commit_attributes => $commit_attributes->{ $commit_id },
112             commit_id => $commit_id,
113             )
114             );
115             }
116             else
117             {
118             # It's a git header line.
119 52 100       239 if ( $line =~ /^([0-9a-f]+)\s(\d+)\s(\d+)\s*(\d*)$/x )
    50          
120             {
121 8         55 ( $commit_id, $original_line_number, $final_line_number, $lines_count_in_group ) = ( $1, $2, $3, $4 );
122             }
123             elsif ( $line =~ m/^([\w\-]+)\s*(.*)$/x )
124             {
125 44         190 $commit_attributes->{ $commit_id }->{ $1 } = $2;
126             }
127             }
128             }
129              
130             # If we have a cache object, cache the output.
131 2 100       12 if ( defined( $cache ) )
132             {
133 1         12 $cache->set_blame_lines(
134             file => $file,
135             blame_lines => $lines,
136             );
137             }
138              
139 2         54 return $lines;
140             }
141              
142              
143             =head1 BUGS
144              
145             Please report any bugs or feature requests through the web interface at
146             L.
147             I will be notified, and then you'll automatically be notified of progress on
148             your bug as I make changes.
149              
150              
151             =head1 SUPPORT
152              
153             You can find documentation for this module with the perldoc command.
154              
155             perldoc Git::Repository::Plugin::Blame
156              
157              
158             You can also look for information at:
159              
160             =over 4
161              
162             =item * GitHub (report bugs there)
163              
164             L
165              
166             =item * AnnoCPAN: Annotated CPAN documentation
167              
168             L
169              
170             =item * CPAN Ratings
171              
172             L
173              
174             =item * MetaCPAN
175              
176             L
177              
178             =back
179              
180              
181             =head1 AUTHOR
182              
183             L,
184             C<< >>.
185              
186              
187             =head1 COPYRIGHT & LICENSE
188              
189             Copyright 2012-2014 Guillaume Aubert.
190              
191             This program is free software: you can redistribute it and/or modify it under
192             the terms of the GNU General Public License version 3 as published by the Free
193             Software Foundation.
194              
195             This program is distributed in the hope that it will be useful, but WITHOUT ANY
196             WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
197             PARTICULAR PURPOSE. See the GNU General Public License for more details.
198              
199             You should have received a copy of the GNU General Public License along with
200             this program. If not, see http://www.gnu.org/licenses/
201              
202             =cut
203              
204             1;