1package SVN::Web::Blame;
2
3use strict;
4use warnings;
5
6use base 'SVN::Web::action';
7
8use Encode ();
9
10our $VERSION = 0.62;
11
12=head1 NAME
13
14SVN::Web::Blame - SVN::Web action to show blame/annotation information
15
16=head1 SYNOPSIS
17
18In F<config.yaml>
19
20  actions:
21    ...
22    blame:
23      class: SVN::Web::Blame
24      action_menu:
25        show:
26          - file
27        link_text: (view blame)
28    ...
29
30=head1 DESCRIPTION
31
32Shows a specific revision of a file in the Subversion repository, with
33blame/annotation information.
34
35=head1 OPTIONS
36
37=over 8
38
39=item rev
40
41The revision of the file to show.  Defaults to the repository's
42youngest revision.
43
44If this is not an interesting revision for this file, the repository history
45is searched to find the youngest interesting revision for this file that is
46less than C<rev>.
47
48=back
49
50=head1 TEMPLATE VARIABLES
51
52=over 8
53
54=item at_head
55
56A boolean value, indicating whether the user is currently viewing the
57HEAD of the file in the repository.
58
59=item context
60
61Always C<file>.
62
63=item rev
64
65The revision that has been returned.  This is not necessarily the same
66as the C<rev> option passed to the action.  If the C<rev> passed to the
67action is not interesting (i.e., there were no changes to the file at that
68revision) then the file's history is searched backwards to find the next
69oldest interesting revision.
70
71=item youngest_rev
72
73The youngest interesting revision of the file.
74
75=item mimetype
76
77The file's MIME type, extracted from the file's C<svn:mime-type>
78property.  If this is not set then C<text/plain> is used.
79
80=item blame_details
81
82An array of hashes.  Each entry in the array corresponds to a line from
83the file.  Each hash contains the following keys:
84
85=over
86
87=item line_no
88
89The line number (starting with 0) in the file.
90
91=item revision
92
93The revision in which this line was last changed.
94
95=item author
96
97The author of the revision that changed this line
98
99=item date
100
101The date on which the line was changed, formatted according to
102L<SVN::Web/"Time and date formatting">.
103
104=item line
105
106The contents of this line.
107
108=back
109
110=back
111
112=head1 EXCEPTIONS
113
114None.
115
116=cut
117
118sub cache_key {
119    my $self = shift;
120    my $path = $self->{path};
121
122    my ( undef, undef, $act_rev, $head ) = $self->get_revs();
123
124    return "$act_rev:$head:$path";
125}
126
127sub run {
128    my $self = shift;
129    my $uri  = $self->{repos}{uri} . $self->{path};
130
131    my ( $exp_rev, $yng_rev, $act_rev, $head ) = $self->get_revs();
132
133    my $rev = $act_rev;
134
135    my @blame_details;
136
137    $self->ctx_blame(
138        $uri,
139        1, $rev,
140        sub {
141            push @blame_details,
142              {
143                line_no => $_[0],
144                rev     => $_[1],
145                author  => $_[2],
146                date    => $self->format_svn_timestamp( $_[3] ),
147                line    => Encode::decode('utf8',$_[4]),
148              };
149        }
150    );
151
152    my $mime_type;
153    my $props = $self->ctx_propget( 'svn:mime-type', $uri, $rev, 0 );
154    if ( exists $props->{$uri} ) {
155        $mime_type = $props->{$uri};
156    }
157    else {
158        $mime_type = 'text/plain';
159    }
160
161    return {
162        template => 'blame',
163        data     => {
164            context       => 'file',
165            rev           => $act_rev,
166            youngest_rev  => $yng_rev,
167            at_head       => $head,
168            mimetype      => $mime_type,
169            blame_details => \@blame_details,
170        }
171    };
172}
173
1741;
175
176=head1 COPYRIGHT
177
178Copyright 2007 by Nik Clayton C<< <nik@FreeBSD.org> >>.
179
180This program is free software; you can redistribute it and/or modify it
181under the same terms as Perl itself.
182
183See L<http://www.perl.com/perl/misc/Artistic.html>
184
185=cut
186