File Coverage

blib/lib/Dist/Zilla/Plugin/Repository.pm
Criterion Covered Total %
statement 55 67 82.0
branch 36 54 66.6
condition 8 8 100.0
subroutine 6 7 85.7
pod 0 1 0.0
total 105 137 76.6


line stmt bran cond sub pod time code
1             package Dist::Zilla::Plugin::Repository;
2             $Dist::Zilla::Plugin::Repository::VERSION = '0.21';
3             # ABSTRACT: Automatically sets repository URL from svn/svk/Git checkout for Dist::Zilla
4              
5 2     2   2074909 use Moose;
  2         350490  
  2         19  
6             with 'Dist::Zilla::Role::MetaProvider';
7              
8             has git_remote => (
9             is => 'ro',
10             isa => 'Str',
11             default => 'origin',
12             );
13              
14             has github_http => (
15             is => 'ro',
16             isa => 'Bool',
17             default => 0,
18             );
19              
20             has _found_repo => (
21             is => 'ro',
22             isa => 'HashRef',
23             lazy_build => 1,
24             );
25              
26             sub _build__found_repo {
27 19     19   50 my $self = shift;
28 19         129 my @info = $self->_find_repo(\&_execute);
29              
30 19 50       73 unshift @info, 'url' if @info == 1;
31              
32 19         69 my %repo = @info;
33              
34 19   100     210 $repo{$_} ||= '' for qw(type url web);
35              
36 19         628 return \%repo;
37             }
38              
39             has 'repository' => (
40             is => 'ro',
41             isa => 'Str',
42             lazy_build => 1,
43             );
44              
45             sub _build_repository {
46 16     16   548 shift->_found_repo->{url};
47             }
48              
49             has type => (
50             is => 'ro',
51             isa => 'Str',
52             lazy => 1,
53             default => sub { shift->_found_repo->{type} },
54             );
55              
56             has web => (
57             is => 'ro',
58             isa => 'Str',
59             lazy => 1,
60             default => sub { shift->_found_repo->{web} },
61             );
62              
63             sub metadata {
64 20     20 0 391959 my ($self, $arg) = @_;
65              
66 20         65 my %repo;
67 20 100       799 $repo{url} = $self->repository if $self->repository;
68 20 100       614 $repo{type} = $self->type if $self->type;
69 20 100       593 $repo{web} = $self->web if $self->web;
70              
71 20 100 100     90 return unless $repo{url} or $repo{web};
72              
73 17         126 return {resources => {repository => \%repo}};
74             }
75              
76             sub _execute {
77 0     0   0 my ($command) = @_;
78 0         0 $ENV{LC_ALL} = "C";
79 0         0 `$command`;
80             }
81              
82             # Copy-Paste of Module-Install-Repository, thank MIYAGAWA
83             sub _find_repo {
84 19     19   58 my ($self, $execute) = @_;
85              
86 19         41 my %repo;
87              
88 19 100       872 if (-e ".git") {
    100          
    100          
    100          
    50          
89 10         49 $repo{type} = 'git';
90 10 50       394 if ($execute->('git remote show -n ' . $self->git_remote) =~ /URL: (.*)$/m) {
    0          
91             # XXX Make it public clone URL, but this only works with github
92 10         151 my $git_url = $1;
93              
94 10         83 $git_url =~ s![\w\-]+\@([^:]+):!git://$1/!;
95              
96 10 100       60 $repo{url} = $git_url unless $git_url eq 'origin'; # RT 55136
97              
98 10 100       96 if ($git_url =~ /^(?:git|https?):\/\/((?:git(?:lab|hub)\.com|bitbucket.org).*?)(?:\.git)?$/) {
99 7         37 $repo{web} = "https://$1";
100              
101 7 100       225 if ($self->github_http) {
102             # I prefer https://github.com/user/repository
103             # to git://github.com/user/repository.git
104 2         9 delete $repo{url};
105 2         18 $self->log("github_http is deprecated. "
106             . "Consider using META.json instead,\n"
107             . "which can store URLs for both git clone "
108             . "and the web front-end.");
109             } # end if github_http
110             } # end if Github repository
111              
112             } elsif ($execute->('git svn info') =~ /URL: (.*)$/m) {
113 0         0 %repo = (qw(type svn url), $1);
114             }
115             # invalid github remote might come back with just the remote name
116 10 100 100     1103 if ($repo{url} && $repo{url} =~ /\A\w+\z/) {
117 1         6 delete $repo{$_} for qw/url type web/;
118 1         28 $self->log("Skipping invalid git remote " . $self->git_remote);
119             }
120             } elsif (-e ".svn") {
121 2         10 $repo{type} = 'svn';
122 2 50       12 if ($execute->('svn info') =~ /URL: (.*)$/m) {
123 2         30 my $svn_url = $1;
124 2 50       8 if ($svn_url =~ /^https(\:\/\/.*?\.googlecode\.com\/svn\/.*)$/) {
125 0         0 $svn_url = 'http' . $1;
126             }
127 2         46 $repo{url} = $svn_url;
128             }
129             } elsif (-e "_darcs") {
130             # defaultrepo is better, but that is more likely to be ssh, not http
131 2         9 $repo{type} = 'darcs';
132 2 50       12 if (my $query_repo = $execute->('darcs query repo')) {
133 2 100       35 if ($query_repo =~ m!Default Remote: (http://.+)!) {
134 1         7 return %repo, url => $1;
135             }
136             }
137              
138 1 50       64 open my $handle, '<', '_darcs/prefs/repos' or return;
139 1         34 while (<$handle>) {
140 2         8 chomp;
141 2 100       68 return %repo, url => $_ if m!^http://!;
142             }
143             } elsif (-e ".hg") {
144 2         10 $repo{type} = 'hg';
145 2 50       10 if ($execute->('hg paths') =~ /default = (.*)$/m) {
146 2         43 my $mercurial_url = $1;
147 2         7 $mercurial_url =~ s!^ssh://hg\@(bitbucket\.org/)!https://$1!;
148 2         6 $repo{url} = $mercurial_url;
149             }
150             } elsif (-e "$ENV{HOME}/.svk") {
151             # Is there an explicit way to check if it's an svk checkout?
152 0 0       0 my $svk_info = $execute->('svk info') or return;
153             SVK_INFO: {
154 0 0       0 if ($svk_info =~ /Mirrored From: (.*), Rev\./) {
  0         0  
155 0         0 return qw(type svn url) => $1;
156             }
157              
158 0 0       0 if ($svk_info =~ m!Merged From: (/mirror/.*), Rev\.!) {
159 0 0       0 $svk_info = $execute->("svk info /$1") or return;
160 0         0 redo SVK_INFO;
161             }
162             }
163             }
164              
165 17         468 return %repo;
166             }
167              
168             __PACKAGE__->meta->make_immutable;
169 2     2   13995 no Moose;
  2         5  
  2         13  
170              
171             1;
172              
173             __END__
174              
175             =pod
176              
177             =encoding UTF-8
178              
179             =head1 NAME
180              
181             Dist::Zilla::Plugin::Repository - Automatically sets repository URL from svn/svk/Git checkout for Dist::Zilla
182              
183             =head1 VERSION
184              
185             version 0.21
186              
187             =head1 SYNOPSIS
188              
189             # dist.ini
190             [Repository]
191              
192             =head1 DESCRIPTION
193              
194             The code is mostly a copy-paste of L<Module::Install::Repository>
195              
196             =head2 ATTRIBUTES
197              
198             =over 4
199              
200             =item * git_remote
201              
202             This is the name of the remote to use for the public repository (if
203             you use Git). By default, unsurprisingly, to F<origin>.
204              
205             =item * github_http
206              
207             B<This attribute is deprecated.>
208             If the remote is a GitHub repository, list only the https url
209             (https://github.com/fayland/dist-zilla-plugin-repository) and not the actual
210             clonable url (git://github.com/fayland/dist-zilla-plugin-repository.git).
211             This used to default to true, but as of 0.16 it defaults to false.
212              
213             The CPAN Meta 2 spec defines separate keys for the clonable C<url> and
214             web front-end C<web>. The Meta 1 specs allowed only 1 URL. If you
215             set C<github_http> to true, the C<url> key will be removed from the v2
216             metadata, and the v1 metadata will then use the C<web> key.
217              
218             Instead of setting C<github_http>, you should use the MetaJSON plugin
219             to include a v2 META.json file with both URLs.
220              
221             =item * repository
222              
223             You can set this attribute if you want a specific repository instead of the
224             plugin to auto-identify your repository.
225              
226             An example would be if you're releasing a module from your fork, and you don't
227             want it to identify your fork, so you can specify the repository explicitly.
228              
229             In the L<Meta 2 spec|CPAN::Meta::Spec>, this is the C<url> key.
230              
231             =item * type
232              
233             This should be the (lower-case) name of the most common program used
234             to work with the repository, e.g. git, svn, cvs, darcs, bzr or hg.
235             It's normally determined automatically, but you can override it.
236              
237             =item * web
238              
239             This is a URL pointing to a human-usable web front-end for the
240             repository. Currently, only Github repositories get this set automatically.
241              
242             =back
243              
244             =for Pod::Coverage metadata
245              
246             =head1 AUTHORS
247              
248             =over 4
249              
250             =item *
251              
252             Fayland Lam <fayland@gmail.com>
253              
254             =item *
255              
256             Ricardo SIGNES <rjbs@cpan.org>
257              
258             =item *
259              
260             Moritz Onken <onken@netcubed.de>
261              
262             =item *
263              
264             Christopher J. Madsen <perl@cjmweb.net>
265              
266             =back
267              
268             =head1 COPYRIGHT AND LICENSE
269              
270             This software is copyright (c) 2017 by Fayland Lam, Ricardo SIGNES, Moritz Onken, Christopher J. Madsen.
271              
272             This is free software; you can redistribute it and/or modify it under
273             the same terms as the Perl 5 programming language system itself.
274              
275             =cut