File Coverage

blib/lib/Alien/Build/Plugin/Download/GitLab.pm
Criterion Covered Total %
statement 29 77 37.6
branch 0 30 0.0
condition 0 6 0.0
subroutine 10 13 76.9
pod 1 1 100.0
total 40 127 31.5


line stmt bran cond sub pod time code
1             package Alien::Build::Plugin::Download::GitLab;
2              
3 1     1   189526 use strict;
  1         6  
  1         24  
4 1     1   5 use warnings;
  1         1  
  1         19  
5 1     1   30 use 5.008004;
  1         3  
6 1     1   5 use Carp qw( croak );
  1         2  
  1         55  
7 1     1   489 use URI;
  1         4061  
  1         28  
8 1     1   689 use JSON::PP qw( decode_json );
  1         12028  
  1         59  
9 1     1   7 use URI::Escape qw( uri_escape );
  1         2  
  1         35  
10 1     1   402 use Alien::Build::Plugin;
  1         10166  
  1         5  
11 1     1   81 use File::Basename qw( basename );
  1         2  
  1         84  
12 1     1   755 use Path::Tiny qw( path );
  1         10265  
  1         724  
13              
14             # ABSTRACT: Alien::Build plugin to download from GitLab
15             our $VERSION = '0.01'; # VERSION
16              
17              
18             has gitlab_host => 'https://gitlab.com';
19             has gitlab_user => undef;
20             has gitlab_project => undef;
21              
22              
23             has type => 'source'; # source or link
24              
25              
26             has format => 'tar.gz';
27              
28              
29             has version_from => 'tag_name'; # tag_name or name
30             has convert_version => undef;
31             has link_name => undef;
32              
33             sub init
34             {
35 0     0 1   my($self, $meta) = @_;
36              
37 0 0         croak("No gitlab_user provided") unless defined $self->gitlab_user;
38 0 0         croak("No gitlab_project provided") unless defined $self->gitlab_project;
39 0 0         croak("Don't set set a start_url with the Download::GitLab plugin") if defined $meta->prop->{start_url};
40              
41 0           $meta->add_requires('configure' => 'Alien::Build::Plugin::Download::GitLab' => 0 );
42              
43 0           my $url = URI->new($self->gitlab_host);
44 0           $url->path("/api/v4/projects/@{[ uri_escape(join '/', $self->gitlab_user, $self->gitlab_project) ]}/releases");
  0            
45 0   0       $meta->prop->{start_url} ||= "$url";
46              
47 0           $meta->apply_plugin('Download');
48 0           $meta->apply_plugin('Extract', format => $self->format );
49              
50             # we assume that GitLab returns the releases in reverse
51             # chronological order.
52             $meta->register_hook(
53             prefer => sub {
54 0     0     my($build, $res) = @_;
55 0           return $res;
56             },
57 0           );
58              
59 0 0         croak "type must be one of source or link" if $self->type !~ /^(source|link)$/;
60 0 0         croak "version_from must be one of tag_name or name" if $self->version_from !~ /^(tag_name|name)$/;
61              
62             ## TODO insert tokens as header if possible
63             ## This may help with rate limiting (or if not then don't bother)
64             # curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/24/releases"
65              
66             $meta->around_hook(
67             fetch => sub {
68 0     0     my $orig = shift;
69 0           my($build, $url, @the_rest) = @_;
70              
71             # only modify the response if we are using the GitLab API
72             # to get the release list
73             return $orig->($build, $url, @the_rest)
74 0 0 0       if defined $url && $url ne $meta->prop->{start_url};
75              
76 0           my $res = $orig->($build, $url, @the_rest);
77              
78 0           my $res2 = {
79             type => 'list',
80             list => [],
81             };
82              
83 0 0         $res2->{protocol} = $res->{protocol} if exists $res->{protocol};
84              
85 0           my $rel;
86 0 0         if($res->{content})
    0          
87             {
88 0           $rel = decode_json $res->{content};
89             }
90             elsif($res->{path})
91             {
92 0           $rel = decode_json path($res->{path})->slurp_raw;
93             }
94             else
95             {
96 0           croak("malformed response object: no content or path");
97             }
98              
99 0           foreach my $release (@$rel)
100             {
101 0 0         my $version = $self->version_from eq 'name' ? $release->{name} : $release->{tag_name};
102 0 0         $version = $self->convert_version->($version) if $self->convert_version;
103              
104 0 0         if($self->type eq 'source')
105             {
106 0           foreach my $source (@{ $release->{assets}->{sources} })
  0            
107             {
108 0 0         next unless $source->{format} eq $self->format;
109 0           my $url = URI->new($source->{url});
110 0           my $filename = basename $url->path;
111 0           push @{ $res2->{list} }, {
112             filename => $filename,
113             url => $source->{url},
114 0           version => $version,
115             };
116             }
117             }
118             else # link
119             {
120 0           foreach my $link (@{ $release->{assets}->{links} })
  0            
121             {
122 0           my $url = URI->new($link->{url});
123 0           my $filename => basename $url->path;
124 0 0         if($self->link_name)
125             {
126 0 0         next unless $filename =~ $self->link_name;
127             }
128 0           push @{ $res2->{list} }, {
129             filename => $filename,
130             url => $link->{url},
131 0           version => $version,
132             };
133             }
134             }
135             }
136              
137 0           return $res2;
138              
139             },
140 0           );
141             }
142              
143             1;
144              
145             __END__