File Coverage

blib/lib/Ixchel/functions/github_fetch_release_asset.pm
Criterion Covered Total %
statement 23 78 29.4
branch 0 36 0.0
condition 0 21 0.0
subroutine 8 9 88.8
pod 1 1 100.0
total 32 145 22.0


line stmt bran cond sub pod time code
1             package Ixchel::functions::github_fetch_release_asset;
2              
3 4     4   116564 use 5.006;
  4         15  
4 4     4   34 use strict;
  4         6  
  4         99  
5 4     4   15 use warnings;
  4         7  
  4         265  
6 4     4   623 use File::Slurp;
  4         75906  
  4         379  
7 4     4   25 use Exporter 'import';
  4         7  
  4         182  
8             our @EXPORT = qw(github_fetch_release_asset);
9 4     4   928 use Ixchel::functions::github_releases;
  4         14  
  4         327  
10 4     4   71 use LWP::UserAgent ();
  4         9  
  4         84  
11 4     4   17 use JSON;
  4         15  
  4         23  
12              
13             =head1 NAME
14              
15             Ixchel::functions::github_fetch_release_asset - Fetches a release asset from a Github repo.
16              
17             =head1 VERSION
18              
19             Version 0.0.1
20              
21             =cut
22              
23             our $VERSION = '0.0.1';
24              
25             =head1 SYNOPSIS
26              
27             use Ixchel::functions::github_fetch_release_asset;
28              
29             my $releases;
30             eval{ $releases=github_fetch_release_asset(owner=>'mikefarah', repo=>'yq'); };
31             if ($@) {
32             print 'Error: '.$@."\n";
33             }
34              
35             =head1 Functions
36              
37             =head2 github_fetch_release_asset
38              
39             The following args are required.
40              
41             - owner :: The owner of the repo in question.
42              
43             - repo :: Repo to fetch the releases for.
44              
45             - asset :: The name of the asset to fetch.
46              
47             The following are optional.
48              
49             - pre :: If prereleases are okay fetch fetch or not.
50             Default :: 0
51              
52             - draft :: If draft releases are okay.
53             Default :: 0
54              
55             - output :: Where to write the file to. If undef, will be writen
56             to a file named the same as the asset under the current dir.
57              
58             - atomic :: If it should attempt to write the file atomically.
59             Default :: 0
60              
61             - append :: Append the fetched data to the output file if it already exists.
62             Default :: 0
63              
64             - umask :: The umask to use. Defaults to what ever sysopen uses.
65              
66             - return :: Return the fetched item instead of writing it to a file.
67             Default :: 0
68              
69             If the $ENV variables below are set, they will be used for proxy info.
70              
71             $ENV{FTP_PROXY}
72             $ENV{HTTP_PROXY}
73             $ENV{HTTPS_PROXY}
74              
75             Upon errors, this will die.
76              
77             =cut
78              
79             sub github_fetch_release_asset {
80 0     0 1   my (%opts) = @_;
81              
82 0 0         if ( !defined( $opts{owner} ) ) {
83 0           die('owner not specified');
84             }
85              
86 0 0         if ( !defined( $opts{repo} ) ) {
87 0           die('repo not specified');
88             }
89              
90 0 0         if ( !defined( $opts{asset} ) ) {
91 0           die('asset not specified');
92             }
93              
94 0           my $releases;
95 0           eval { $releases = github_releases( owner => $opts{owner}, repo => $opts{repo} ); };
  0            
96 0 0         if ($@) {
97 0           die( 'Failed to fetch the release info for ' . $opts{owner} . '/' . $opts{repo} . '... ' . $@ );
98             }
99              
100 0           foreach my $release ( @{$releases} ) {
  0            
101 0           my $use_release = 1;
102              
103 0 0         if ( ref($release) ne 'HASH' ) {
104 0           $use_release = 0;
105             }
106              
107             # if it is a draft, check if fetching of drafts is allowed
108 0 0 0       if ( $use_release
      0        
      0        
109             && defined( $release->{draft} )
110             && $release->{draft} =~ /$[Tt][Rr][Uu][Ee]^/
111             && !$opts{draft} )
112             {
113 0           $use_release = 0;
114             }
115              
116             # if it is a prerelease, check if fetching of prerelease is allowed
117 0 0 0       if ( $use_release
      0        
      0        
118             && defined( $release->{prerelease} )
119             && $release->{prerelease} =~ /$[Tt][Rr][Uu][Ee]^/
120             && !$opts{pre} )
121             {
122 0           $use_release = 0;
123             }
124              
125 0 0         if ($use_release) {
126 0           foreach my $asset ( @{ $release->{assets} } ) {
  0            
127 0           my $fetch_it = 0;
128 0 0 0       if ( defined( $asset->{name} ) && $asset->{name} eq $opts{asset} ) {
129 0           $fetch_it = 1;
130             }
131              
132 0 0         if ($fetch_it) {
133 0           my $asset_url = $asset->{browser_download_url};
134 0           my $content;
135 0           eval {
136 0           my $ua = LWP::UserAgent->new( timeout => 10 );
137 0 0         if ( defined( $ENV{HTTP_PROXY} ) ) {
138 0           $ua->proxy( ['http'], $ENV{HTTP_PROXY} );
139             }
140 0 0         if ( defined( $ENV{HTTPS_PROXY} ) ) {
141 0           $ua->proxy( ['https'], $ENV{HTTPS_PROXY} );
142             }
143 0 0         if ( defined( $ENV{FTP_PROXY} ) ) {
144 0           $ua->proxy( ['ftp'], $ENV{FTP_PROXY} );
145             }
146              
147 0           my $response = $ua->get($asset_url);
148              
149 0 0         if ( $response->is_success ) {
150 0           $content = $response->decoded_content;
151             } else {
152 0           die( $response->status_line );
153             }
154             };
155 0 0         if ($@) {
156 0           die( 'Fetching "' . $asset_url . '" failed' ... $@ );
157             }
158              
159 0 0         if ( $opts{return} ) {
160 0           return ($content);
161             }
162              
163 0           my $write_to = $asset->{name};
164 0           $write_to =~ s/\//_/g;
165 0 0         if ( defined( $opts{output} ) ) {
166 0           $write_to = $opts{output};
167             }
168              
169 0           eval {
170             write_file(
171             $write_to,
172             {
173             append => $opts{append},
174             atomic => $opts{atomic},
175             perms => $opts{umask}
176             },
177 0           $content
178             );
179             };
180 0 0         if ($@) {
181             die( 'Failed to write "'
182             . $asset->{browser_download_url}
183 0           . '" out to "'
184             . $write_to . '"... '
185             . $@ );
186             }
187              
188 0           return;
189             } ## end if ($fetch_it)
190             } ## end foreach my $asset ( @{ $release->{assets} } )
191             } ## end if ($use_release)
192             } ## end foreach my $release ( @{$releases} )
193              
194             } ## end sub github_fetch_release_asset
195              
196             1;