File Coverage

blib/lib/Dist/Zilla/Plugin/ContributorsFromGit.pm
Criterion Covered Total %
statement 75 97 77.3
branch 3 6 50.0
condition 0 3 0.0
subroutine 21 23 91.3
pod 0 2 0.0
total 99 131 75.5


line stmt bran cond sub pod time code
1             #
2             # This file is part of Dist-Zilla-Plugin-ContributorsFromGit
3             #
4             # This software is Copyright (c) 2012 by Chris Weyl.
5             #
6             # This is free software, licensed under:
7             #
8             # The GNU Lesser General Public License, Version 2.1, February 1999
9             #
10             package Dist::Zilla::Plugin::ContributorsFromGit;
11             our $AUTHORITY = 'cpan:RSRCHBOY';
12             # git description: 0.016-3-gee7ffea
13             $Dist::Zilla::Plugin::ContributorsFromGit::VERSION = '0.017';
14              
15             # ABSTRACT: Populate your 'CONTRIBUTORS' POD from the list of git authors
16              
17 3     3   1470891 use utf8;
  3         12  
  3         18  
18 3     3   91 use v5.10;
  3         7  
  3         89  
19              
20 3     3   454 use Moose;
  3         105130  
  3         17  
21 3     3   16172 use MooseX::AttributeShortcuts;
  3         506935  
  3         35  
22 3     3   74834 use MooseX::Types::Moose ':all';
  3         10  
  3         24  
23 3     3   17224 use Encode qw(decode_utf8);
  3         7250  
  3         166  
24 3     3   587 use autobox::Core;
  3         12080  
  3         28  
25 3     3   2815 use autobox::Junctions;
  3         13763  
  3         16  
26 3     3   1422 use File::Which 'which';
  3         677  
  3         148  
27 3     3   24 use List::AllUtils qw{ max uniq };
  3         4  
  3         130  
28 3     3   468 use File::ShareDir qw/ dist_dir /;
  3         4125  
  3         149  
29 3     3   601 use YAML::Tiny;
  3         4105  
  3         179  
30 3     3   456 use Path::Class;
  3         30816  
  3         130  
31              
32 3     3   460 use autodie 'system';
  3         10410  
  3         19  
33 3     3   11713 use IPC::System::Simple ( ); # explict dep for autodie system
  3         4  
  3         38  
34              
35 3     3   9 use aliased 'Dist::Zilla::Stash::PodWeaver';
  3         2  
  3         25  
36              
37             with
38             'Dist::Zilla::Role::BeforeBuild',
39             'Dist::Zilla::Role::RegisterStash',
40             'Dist::Zilla::Role::MetaProvider',
41             ;
42              
43             has _contributor_list => (
44             is => 'lazy',
45             isa => 'ArrayRef[Str]',
46             builder => sub {
47 2     2   4 my $self = shift @_;
48 2         93 my @authors = $self->zilla->authors->flatten;
49              
50             ### and get our list from git, filtering: "@authors"
51 0   0     0 my @contributors = uniq
52 0         0 map { $self->_contributor_emails->{$_} // $_ }
53 0         0 grep { $_ ne 'Your Name <you@example.com>' }
54 0         0 grep { [ map { lc } @authors ]->none eq lc }
  0         0  
55 0         0 map { decode_utf8($_) }
56 2         9435 map { chomp; s/^\s*\d+\s*//; $_ }
  0         0  
  0         0  
57             `git shortlog -s -e`
58             ;
59              
60 2         362 return [ sort @contributors ];
61             },
62             );
63              
64             has _contributor_emails => (
65             is => 'lazy',
66             isa => HashRef[Str],
67             init_arg => undef,
68              
69             builder => sub {
70              
71 0     0   0 my $mapping = YAML::Tiny
72             ->read(
73             file(
74             dist_dir('Dist-Zilla-Plugin-ContributorsFromGit'),
75             'author-emails.yaml',
76             ),
77             )
78             ->[0]
79             ;
80              
81             my $_map_it = sub {
82 0     0   0 my ($canonical, @alternates) = @_;
83 0         0 return ( map { $_ => $canonical } @alternates );
  0         0  
84 0         0 };
85              
86             return {
87 0         0 map { $_map_it->($_ => $mapping->{$_}->flatten) }
  0         0  
88             $mapping->keys->flatten
89             };
90             },
91             );
92              
93             has _stopwords => (
94             is => 'lazy',
95             isa => ArrayRef[Str],
96             init_arg => undef,
97              
98             builder => sub {
99 2     2   60 my $self = shift @_;
100              
101             # break contributor names into a stopwords-suitable list
102 0         0 my @stopwords =
103 0         0 map { (split / /) }
104 2         115 map { /^(.*) <.*$/; $1 }
  0         0  
105             $self->_contributor_list->flatten
106             ;
107              
108 2         99 return [ uniq sort @stopwords ];
109             },
110             );
111              
112             sub before_build {
113 2     2 0 159995 my $self = shift @_;
114              
115             # skip if we can't find git
116 2 50       16 unless (which 'git') {
117 0         0 $self->log('The "git" executable has not been found');
118 0         0 return;
119             }
120              
121             # XXX we should also check here that we're in a git repo, but I'm going to
122             # leave that for the git stash (when it's not vaporware)
123              
124             ### get our stash...
125 2         281 my $stash = $self->zilla->stash_named('%PodWeaver');
126 2 50       100 do { $stash = PodWeaver->new; $self->_register_stash('%PodWeaver', $stash) }
  2         41  
  2         1627  
127             unless defined $stash;
128              
129             ### ...and config...
130 2         603 my $config = $stash->_config;
131              
132             # helper sub to keep us from clobbering existing values, until (and if):
133             # https://github.com/rwstauner/Dist-Zilla-Role-Stash-Plugins/pull/1
134             my $_append = sub {
135 4     4   28 my ($key, @values) = @_;
136              
137 4         10 my $i = -1;
138 4         6 do { $i++ } while exists $config->{$key."[$i]"};
  4         26  
139 0         0 do { $config->{$key."[$i]"} = $_; $i++ }
  0         0  
140 4         11 for @values;
141              
142 4         8 return;
143 2         31 };
144              
145 2         96 $_append->('Contributors.contributors' => $self->_contributor_list->flatten);
146 2         143 $_append->('-StopWords.include' => $self->_stopwords->flatten);
147              
148             ### $config
149 2         32 return;
150             }
151              
152             sub metadata {
153 2     2 0 55342 my $self = shift @_;
154 2         73 my $list = $self->_contributor_list;
155 2 50       17 return @$list ? { 'x_contributors' => $list } : {};
156             }
157              
158             __PACKAGE__->meta->make_immutable;
159             !!42;
160              
161             __END__
162              
163             =pod
164              
165             =encoding UTF-8
166              
167             =for :stopwords Chris Weyl Brendan Randy Stauner Tatsuhiko Yanick Byrd Champoux David
168             Golden Graham Greb Knop Mike Miyagawa zilla BeforeBuild metacpan shortlog
169             committer mailmap
170              
171             =for :stopwords Wishlist flattr flattr'ed gittip gittip'ed
172              
173             =head1 NAME
174              
175             Dist::Zilla::Plugin::ContributorsFromGit - Populate your 'CONTRIBUTORS' POD from the list of git authors
176              
177             =head1 VERSION
178              
179             This document describes version 0.017 of Dist::Zilla::Plugin::ContributorsFromGit - released April 09, 2015 as part of Dist-Zilla-Plugin-ContributorsFromGit.
180              
181             =head1 SYNOPSIS
182              
183             ; in your dist.ini
184             [ContributorsFromGit]
185              
186             ; in your weaver.ini
187             [Contributors]
188              
189             =head1 DESCRIPTION
190              
191             This plugin makes it easy to acknowledge the contributions of others by
192             populating a L<%PodWeaver|Dist::Zilla::Stash::PodWeaver> stash with the unique
193             list of all git commit authors reachable from the current HEAD.
194              
195             =head1 OVERVIEW
196              
197             On collecting the unique list of reachable commit authors from git, we search
198             and remove any git authors from the list of authors L<Dist::Zilla> knows
199             about. We then look for a stash named C<%PodWeaver>; if we don't find one
200             then we create an instance of L<Dist::Zilla::Stash::PodWeaver> and register it
201             with our zilla instance. Then we add the list of contributors (the filtered
202             git authors list) to the stash in such a way that
203             L<Pod::Weaver::Section::Contributors> can find them.
204              
205             Note that you do not need to have the C<%PodWeaver> stash created; it will be
206             added if it is not found. However, your L<Pod::Weaver> config (aka
207             c<weaver.ini>) must include the
208             L<Contributors|Pod::Weaver::Section::Contributors> section plugin.
209              
210             =head2 Dist::Zilla Phase
211              
212             This plugin runs during the L<BeforeBuild|Dist::Zilla::Role::BeforeBuild>
213             phase.
214              
215             =head2 Metadata Keys
216              
217             The list of contributors is also added to distribution metadata under the custom
218             C<x_contributors> key. (e.g. in C<META.yml>, C<META.json>, etc)
219              
220             If you have duplicate contributors because of differences in committer name
221             or email you can use a C<.mailmap> file to canonicalize contributor names
222             and emails. See L<git help shortlog|git-shortlog(1)> for details.
223              
224             =head2 Pod::Weaver::Section::Contributors is OPTIONAL
225              
226             Note that using the L<Pod::Weaver::Section::Contributors> section is in no way
227             mandated or necessitated by this package; if you wish to use it you must
228             include the Contributors section in your L<Pod::Weaver> configuration in the
229             traditional fashion.
230              
231             =for Pod::Coverage before_build metadata
232              
233             =head1 METACPAN CONTRIBUTOR MATCHING
234              
235             L<MetaCPAN|http://metacpan.org> will attempt to match a contributor address
236             back to a PAUSE account. However, it (currently) can only do that if the
237             contributor's email address is their C<PAUSEID@cpan.org> address. There are
238             two mechanisms for helping to resolve this, if your commits are not using this
239             address.
240              
241             Both of these approaches have pros and cons that have been discussed at
242             levels nearing the heat brought to any discussion of religion, homosexuality,
243             or Chief O'Brien's actual rank at any ST:TNG convention. However, they both
244             have the advantage of *working*, and through different modes of action. You
245             are free to use one, both or neither. These are only important if you're not
246             committing with your C<@cpan.org> email address B<and> want the MetaCPAN to
247             link to your author page from the page of the package you contributed to.
248              
249             =head2 Using a .mailmap file
250              
251             See C<git help shortlog> for help on how to use this. A C<.mailmap> file must
252             be maintained in each repository using it.
253              
254             =head2 Globally, via the authors mapping
255              
256             This package contains a YAML file containing a mapping of C<@cpan.org> author
257             addresses; this list is consulted while building the contributors list, and
258             can be used to replace a non-cpan.org address with one.
259              
260             To add to or modify this mapping, please feel free to fork, add your alternate
261             email addresses to C<share/author-emails.yaml>, and submit a pull-request for
262             inclusion. It'll be merged and released; as various authors update their set
263             of installed modules and cut new releases, the mapping will appear.
264              
265             =head1 SEE ALSO
266              
267             Please see those modules/websites for more information related to this module.
268              
269             =over 4
270              
271             =item *
272              
273             L<Pod::Weaver::Section::Contributors>
274              
275             =item *
276              
277             L<Dist::Zilla::Stash::PodWeaver>
278              
279             =item *
280              
281             L<http://www.dagolden.com/index.php/1921/how-im-using-distzilla-to-give-credit-to-contributors/>
282              
283             =back
284              
285             =head1 SOURCE
286              
287             The development version is on github at L<http://https://github.com/RsrchBoy/Dist-Zilla-Plugin-ContributorsFromGit>
288             and may be cloned from L<git://https://github.com/RsrchBoy/Dist-Zilla-Plugin-ContributorsFromGit.git>
289              
290             =head1 BUGS
291              
292             Please report any bugs or feature requests on the bugtracker website
293             https://github.com/RsrchBoy/Dist-Zilla-Plugin-ContributorsFromGit/issues
294              
295             When submitting a bug or request, please include a test-file or a
296             patch to an existing test-file that illustrates the bug or desired
297             feature.
298              
299             =head1 AUTHOR
300              
301             Chris Weyl <cweyl@alumni.drew.edu>
302              
303             =head2 I'm a material boy in a material world
304              
305             =begin html
306              
307             <a href="https://www.gittip.com/RsrchBoy/"><img src="https://raw.githubusercontent.com/gittip/www.gittip.com/master/www/assets/%25version/logo.png" /></a>
308             <a href="http://bit.ly/rsrchboys-wishlist"><img src="http://wps.io/wp-content/uploads/2014/05/amazon_wishlist.resized.png" /></a>
309             <a href="https://flattr.com/submit/auto?user_id=RsrchBoy&url=https%3A%2F%2Fgithub.com%2FRsrchBoy%2FDist-Zilla-Plugin-ContributorsFromGit&title=RsrchBoy's%20CPAN%20Dist-Zilla-Plugin-ContributorsFromGit&tags=%22RsrchBoy's%20Dist-Zilla-Plugin-ContributorsFromGit%20in%20the%20CPAN%22"><img src="http://api.flattr.com/button/flattr-badge-large.png" /></a>
310              
311             =end html
312              
313             Please note B<I do not expect to be gittip'ed or flattr'ed for this work>,
314             rather B<it is simply a very pleasant surprise>. I largely create and release
315             works like this because I need them or I find it enjoyable; however, don't let
316             that stop you if you feel like it ;)
317              
318             L<Flattr this|https://flattr.com/submit/auto?user_id=RsrchBoy&url=https%3A%2F%2Fgithub.com%2FRsrchBoy%2FDist-Zilla-Plugin-ContributorsFromGit&title=RsrchBoy's%20CPAN%20Dist-Zilla-Plugin-ContributorsFromGit&tags=%22RsrchBoy's%20Dist-Zilla-Plugin-ContributorsFromGit%20in%20the%20CPAN%22>,
319             L<gittip me|https://www.gittip.com/RsrchBoy/>, or indulge my
320             L<Amazon Wishlist|http://bit.ly/rsrchboys-wishlist>... If you so desire.
321              
322             =head1 CONTRIBUTORS
323              
324             =for stopwords Brendan Byrd David Golden Graham Knop Mike Greb Randy Stauner Tatsuhiko Miyagawa Yanick Champoux
325              
326             =over 4
327              
328             =item *
329              
330             Brendan Byrd <Perl@ResonatorSoft.org>
331              
332             =item *
333              
334             David Golden <dagolden@cpan.org>
335              
336             =item *
337              
338             Graham Knop <haarg@haarg.org>
339              
340             =item *
341              
342             Mike Greb <mikegrb@cpan.org>
343              
344             =item *
345              
346             Randy Stauner <randy@magnificent-tears.com>
347              
348             =item *
349              
350             Tatsuhiko Miyagawa <miyagawa@bulknews.net>
351              
352             =item *
353              
354             Yanick Champoux <yanick@babyl.dyndns.org>
355              
356             =back
357              
358             =head1 COPYRIGHT AND LICENSE
359              
360             This software is Copyright (c) 2012 by Chris Weyl.
361              
362             This is free software, licensed under:
363              
364             The GNU Lesser General Public License, Version 2.1, February 1999
365              
366             =cut