File Coverage

blib/lib/Test/BrewBuild/Git.pm
Criterion Covered Total %
statement 21 112 18.7
branch 0 26 0.0
condition n/a
subroutine 7 20 35.0
pod 8 8 100.0
total 36 166 21.6


line stmt bran cond sub pod time code
1             package Test::BrewBuild::Git;
2 37     37   30408 use strict;
  37         230  
  37         930  
3 37     37   158 use warnings;
  37         59  
  37         1090  
4              
5 37     37   1071 use Capture::Tiny qw(:all);
  37         56013  
  37         4006  
6 37     37   236 use Carp qw(croak);
  37         57  
  37         1448  
7 37     37   1442 use Logging::Simple;
  37         28982  
  37         965  
8 37     37   14562 use LWP::Simple qw(head);
  37         2079222  
  37         271  
9 37     37   8363 use Test::BrewBuild::Regex;
  37         78  
  37         45797  
10              
11             our $VERSION = '2.22';
12              
13             my $log;
14              
15             sub new {
16 0     0 1   my ($class, %args) = @_;
17 0           my $self = bless {}, $class;
18              
19 0           $log = Logging::Simple->new(
20             name => 'Git',
21             level => 0
22             );
23              
24 0 0         if (defined $args{debug}){
25 0           $log->level($args{debug});
26             }
27              
28 0           $log->child('new')->_5("instantiating new object");
29              
30 0           return $self;
31             }
32             sub git {
33 0     0 1   my $self = shift;
34 0           my $cmd;
35              
36 0 0         return $self->{git} if defined $self->{git};
37              
38 0 0         if ($^O =~ /MSWin/){
39 0           for (split /;/, $ENV{PATH}){
40 0 0         if (-x "$_/git.exe"){
41 0           $cmd = "$_/git.exe";
42 0           last;
43             }
44             }
45             }
46             else {
47 0           $cmd = 'git';
48             }
49              
50 0           $log->child('git')->_6("git command set to '$cmd'");
51              
52 0           $self->{git} = $cmd;
53              
54 0           return $cmd;
55             }
56             sub link {
57 0     0 1   my $self = shift;
58 0           my $git = $self->git;
59 0           my $link = (split /\n/, `"$git" config --get remote.origin.url`)[0];
60 0           $log->child('link')->_6("found $link for the repo");
61 0           return $link
62             }
63             sub name {
64 0     0 1   my ($self, $repo) = @_;
65              
66 0           $log->child('name')->_6("converting repository link to repo name");
67              
68 0 0         if ($repo =~ m!${ re_git('extract_repo_name') }!){
  0            
69 0           $log->child('name')->_6("repo link converted to $1");
70 0           return $1;
71             }
72             }
73             sub clone {
74 0     0 1   my ($self, $repo) = @_;
75              
76 0           $log->child('clone')->_7("initiating remote repo clone");
77              
78 0 0         if ($repo !~ /https/){
79 0           $log->child('clone')->_2("git clone failed, repo doesn't exist");
80 0           croak "repository $repo doesn't exist; can't clone...\n";
81             }
82              
83 0           my $git = $self->git;
84              
85 0           _repo_availability_check($git, $repo);
86              
87             my $output = capture_merged {
88 0     0     `"$git" clone $repo`;
89 0           };
90              
91 0 0         if ($output =~ /fatal/){
92 0           croak "fatal error cloning $repo, can't clone...\n";
93             }
94              
95 0           return $output;
96             }
97             sub pull {
98 0     0 1   my $self = shift;
99 0           my $git = $self->git;
100              
101 0           $log->child('clone')->_6("initiating git pull");
102              
103 0           my $output = `"$git" pull`;
104 0           return $output;
105             }
106             sub revision {
107 0     0 1   my ($self, %args) = @_;
108              
109 0           my $remote = $args{remote};
110 0           my $repo = $args{repo};
111              
112 0           my $log = $log->child('revision');
113              
114 0           my $git = $self->git;
115              
116 0           $log->child('revision')->_6("initiating git revision");
117              
118 0           my $csum;
119              
120 0 0         if (! $remote) {
121 0           $log->_6("local: 'rev-parse HEAD' sent");
122 0           $csum = `"$git" rev-parse HEAD`;
123             }
124             else {
125 0 0         if (! defined $repo){
126 0           $log->_0(
127             "Git::revision() requires a repo sent in while in remote " .
128             "mode. Croaking."
129             );
130 0           croak "Git::revision() requires a repo sent in while in " .
131             "remote mode.";
132             }
133              
134 0           _repo_availability_check($git, $repo);
135              
136             capture_stderr {
137 0     0     my $sums = `"$git" ls-remote $repo`;
138 0 0         if ($sums =~ /${ re_git('extract_commit_csum') }/){
  0            
139 0           $csum = $1;
140             }
141 0           };
142              
143 0           $log->_6("remote: 'ls-remote $repo' sent");
144             }
145              
146 0           chomp $csum;
147 0           $log->_5("commit checksum: $csum");
148 0           return $csum;
149             }
150             sub status {
151 0     0 1   my ($self) = @_;
152              
153 0           $log->child('status')->_7("checking git status");
154              
155 0           my $git = $self->git;
156              
157 0           my $status = `$git status`;
158              
159 0 0         if ($status =~ /Your branch is ahead/){
160 0           return 0;
161             }
162 0           return 1;
163             }
164             sub _repo_availability_check {
165 0     0     my ($git, $repo) = @_;
166              
167             my $repo_availability_check = capture_stderr {
168 0     0     my $git_protocol_repo = $repo;
169 0           $git_protocol_repo =~ s/https/git/;
170 0           $git_protocol_repo =~ s|git://.*?@|git://|;
171 0           `"$git" ls-remote $git_protocol_repo`;
172 0           };
173              
174 0 0         if ($repo_availability_check =~ /fatal/) {
175 0           $log->_0("fatal: repository '$repo' not found. Typo?...\n");
176 0           croak "fatal: repository '$repo' not found. Typo?...\n";
177             }
178             }
179             sub _separate_url {
180             # this method is actually not needed. Was going to be used if we used the
181             # github API to fetch stuff...
182             # eg: https://api.github.com/repos/$user/$repo/commits
183              
184 0     0     my ($self, $repo) = @_;
185              
186 0 0         if (! defined $repo){
187 0           $repo = $self->link;
188             }
189              
190 0           my ($user, $repo_name) = (split /\//, $repo)[-2, -1];
191              
192 0           return ($user, $repo_name);
193             }
194              
195             1;
196              
197             =head1 NAME
198              
199             Test::BrewBuild::Git - Git repository manager for the C test
200             platform system.
201              
202             =head1 SYNOPSIS
203              
204             use Test::BrewBuild::Git;
205              
206             my $git = Test::BrewBuild::Git->new;
207              
208             my $repo_link = $git->link;
209              
210             my $repo_name = $git->name($link);
211              
212             $git->clone($repo_link);
213              
214             $git->pull;
215              
216             =head1 DESCRIPTION
217              
218             Manages Git repositories, including gathering names, cloning, pulling etc.
219              
220             =head1 METHODS
221              
222             =head2 new
223              
224             Returns a new C object.
225              
226             Parameters:
227              
228             debug => $level
229              
230             Optional, Integer. $level vary between 0-7, 0 being the least verbose.
231              
232             =head2 git
233              
234             Returns the C command for the local platform.
235              
236             =head2 link
237              
238             Fetches and returns the full link to the master repository from your current
239             working directory. This is the link you used to originally clone the repo.
240              
241             =head2 name($link)
242              
243             Extracts the repo name from the full link path.
244              
245             =head2 clone($repo)
246              
247             Clones the repo into the current working directory.
248              
249             =head2 pull
250              
251             While in a repository directory, pull down any updates.
252              
253             =head2 revision(remote => $bool, repo => $github_url)
254              
255             Returns the current commit SHA1 for a repo, with ability to get the local commit
256             or remote commit SHA1 sum.
257              
258             Parameters:
259              
260             All parameters are passed in as a hash.
261              
262             repo
263              
264             Optional, string. The Github url to the repo. If not sent in, we will attempt
265             to get this information from the current working directory. Mandatory if the
266             C parameter is sent in.
267              
268             remote
269              
270             Optional, bool. If sent in, we'll fetch the current commit's SHA1 sum from
271             Github itself, else we'll get the sum from the most recent local, unpushed
272             commit. The C parameter is mandatory if this one is sent in.
273              
274             =head2 status
275              
276             Returns true of the repo we're working on is behind or equal to the remote
277             regarding commits, and false if we're ahead.
278              
279             =head1 AUTHOR
280              
281             Steve Bertrand, C<< >>
282              
283             =head1 LICENSE AND COPYRIGHT
284              
285             Copyright 2017 Steve Bertrand.
286              
287             This program is free software; you can redistribute it and/or modify it
288             under the terms of either: the GNU General Public License as published
289             by the Free Software Foundation; or the Artistic License.
290              
291             See L for more information.
292              
293             =cut
294