File Coverage

blib/lib/Dist/Mgr/Git.pm
Criterion Covered Total %
statement 54 163 33.1
branch 0 66 0.0
condition 0 16 0.0
subroutine 18 34 52.9
pod n/a
total 72 279 25.8


line stmt bran cond sub pod time code
1             package Dist::Mgr::Git;
2              
3 25     25   191 use strict;
  25         60  
  25         830  
4 25     25   132 use warnings;
  25         57  
  25         881  
5 25     25   138 use version;
  25         47  
  25         221  
6              
7 25     25   2027 use Capture::Tiny qw(:all);
  25         71  
  25         3770  
8 25     25   195 use Carp qw(croak cluck);
  25         60  
  25         1460  
9 25     25   154 use Cwd qw(getcwd);
  25         123  
  25         1655  
10 25     25   202 use Data::Dumper;
  25         108  
  25         1586  
11 25     25   210 use Digest::SHA;
  25         63  
  25         1189  
12 25     25   165 use Dist::Mgr::FileData qw(:all);
  25         50  
  25         3498  
13 25     25   13060 use File::Copy;
  25         57905  
  25         1799  
14 25     25   14717 use File::Copy::Recursive qw(rmove_glob);
  25         107503  
  25         2395  
15 25     25   309 use File::Path qw(make_path rmtree);
  25         55  
  25         1552  
16 25     25   13029 use File::Find::Rule;
  25         191255  
  25         277  
17 25     25   14375 use Module::Starter;
  25         68257  
  25         181  
18 25     25   218119 use PPI;
  25         2775523  
  25         1405  
19 25     25   14131 use Term::ReadKey;
  25         54421  
  25         2342  
20 25     25   20307 use Tie::File;
  25         574769  
  25         1198  
21              
22 25     25   282 use Exporter qw(import);
  25         63  
  25         40093  
23             our @ISA = qw(Exporter);
24             our @EXPORT_OK = qw(
25             _git_add
26             _git_commit
27             _git_clone
28             _git_push
29             _git_pull
30             _git_release
31             _git_repo
32             _git_status_differs
33             _git_tag
34             );
35             our %EXPORT_TAGS = (
36             all => [@EXPORT_OK],
37             );
38              
39             our $VERSION = '1.10';
40              
41             my $spinner_count;
42              
43             sub _exec {
44 0     0     my ($cmd, $verbose) = @_;
45              
46 0 0         croak("_exec() requires cmd parameter sent in") if ! defined $cmd;
47              
48 0 0         if ($verbose) {
49 0           print `$cmd`;
50             }
51             else {
52             capture_merged {
53 0     0     `$cmd`;
54 0           };
55             }
56             }
57             sub _git_add {
58 0     0     my ($verbose) = @_;
59              
60 0 0         if (_validate_git()) {
61 0           _exec('git add .', $verbose);
62 0 0         croak("Git add failed with exit code: $?") if $? != 0;
63             }
64             else {
65 0           warn "'git' not installed, can't add\n";
66             }
67              
68 0           return $?;
69             }
70             sub _git_commit {
71 0     0     my ($msg, $verbose) = @_;
72              
73 0 0         croak("git_commit() requires a commit message sent in") if ! defined $msg;
74              
75 0 0         if ( _validate_git()) {
76 0           _exec("git commit -am '$msg'", $verbose);
77              
78 0 0         if ($? != 0) {
79 0 0         if ($? == 256) {
80 0 0         print "\nNothing to commit, proceeding...\n" if $verbose;
81             }
82             else {
83 0 0         croak("Git commit failed with exit code: $?") if $? != 0;
84             }
85             }
86             }
87             else {
88 0           warn "'git' not installed, can't commit\n";
89             }
90              
91 0           return $?;
92             }
93             sub _git_clone {
94 0     0     my ($user, $repo, $verbose) = @_;
95              
96 0 0 0       if (! defined $user || ! defined $repo) {
97 0           croak("git_clone() requires a user and repository sent in");
98             }
99              
100 0 0         if ( _validate_git()) {
101 0           _exec("git clone 'https://$user\@github.com/$user/$repo'", $verbose);
102              
103 0 0         if ($? != 0) {
104 0 0         if ($? == 32768) {
105 0           croak(
106             "Git clone failed with exit code: $? DIRECTORY $repo ALREADY EXISTS\n"
107             );
108             }
109 0 0         croak("Git clone failed with exit code: $?\n") if $? != 0;
110             }
111             }
112             else {
113 0           warn "'git' not installed, can't clone\n";
114             }
115              
116 0           return $?;
117             }
118             sub _git_pull {
119 0     0     my ($verbose) = @_;
120              
121 0 0         if (_validate_git()) {
122 0           _exec('git pull', $verbose);
123 0 0         croak("Git pull failed with exit code: $?") if $? != 0;
124             }
125             else {
126 0           warn "'git' not installed, can't commit\n";
127             }
128              
129 0           return $?;
130             }
131             sub _git_push {
132 0     0     my ($verbose) = @_;
133              
134 0 0         if (_validate_git()) {
135 0           _exec('git push', $verbose);
136 0           _exec('git push --tags', $verbose);
137 0 0         croak("Git push failed with exit code: $?") if $? != 0;
138             }
139             else {
140 0           warn "'git' not installed, can't push\n";
141             }
142              
143 0           return $?;
144             }
145             sub _git_release {
146 0     0     my ($version, $wait_for_ci) = @_;
147              
148 0 0         croak("git_release() requires a version sent in") if ! defined $version;
149              
150 0           my $git_status_differs = _git_status_differs();
151 0   0       $wait_for_ci //= 1;
152 0           my $verbose = 0;
153              
154 0 0         if ($git_status_differs) {
155 0           _git_pull();
156 0           _git_commit($version, $verbose);
157 0           _git_push($verbose);
158             }
159              
160 0 0 0       if ($wait_for_ci && $git_status_differs) {
161 0           `clear`;
162              
163 0           print "\n\nWaiting for CI tests to complete.\n\n";
164 0           print "Hit ENTER on failure, and CTRL-C to continue on...\n\n";
165              
166 0           local $| = 1;
167              
168 0           my $interrupt = 0;
169 0     0     $SIG{INT} = sub {$interrupt = 1;};
  0            
170              
171 0           my $key = '';
172              
173 0   0       do {
      0        
174 0           _wait_spinner("Waiting: ");
175 0           $key = ReadKey(-1);
176             }
177             until ($interrupt || defined $key && $key eq "\n");
178              
179 0 0         if ($interrupt) {
180 0           print "\nTests pass, continuing with release\n";
181 0           return 1;
182             }
183             else {
184 0           print "\nTests failed, halting progress\n";
185 0           return 0;
186             }
187             }
188              
189 0           return 1;
190             }
191             sub _git_repo {
192 0     0     my $repo;
193              
194 0 0         if (_validate_git()) {
195             capture_merged {
196 0     0     $repo = `git rev-parse --show-toplevel`;
197 0           };
198             }
199              
200 0 0         if ($? == 0) {
201 0           $repo =~ s|.*/(.*)|$1|;
202 0           return $repo;
203             }
204             else {
205 0           return $?;
206             }
207             }
208             sub _git_status_differs {
209 0     0     my $status_output;
210              
211 0 0         if (_validate_git()) {
212 0           $status_output = `git status`;
213             }
214             else {
215 0           warn "'git' not installed, can't get status\n";
216             }
217              
218 0           my @git_output = (
219             'On branch',
220             'Your branch is up-to-date with',
221             'nothing to commit, working directory clean'
222             );
223              
224 0           my @status = split /\n/, $status_output;
225              
226 0           for (0..$#status) {
227 0 0         return 1 if $status[$_] !~ /$git_output[$_]/;
228             }
229              
230 0           return 0;
231             }
232             sub _git_tag {
233 0     0     my ($version, $verbose) = @_;
234              
235 0 0         croak("git_tag() requires a version sent in") if ! defined $version;
236              
237 0 0         if (_validate_git()) {
238 0           _exec('git tag', $verbose);
239 0 0         croak("Git tag failed... needs intervention...") if $? != 0;
240              
241             # croak("Git tag failed... needs intervention...") if $exit != 0;
242             }
243             else {
244 0           warn "'git' not installed, can't commit\n";
245             }
246              
247 0           return $?;
248             }
249             sub _wait_spinner {
250 0     0     my ($msg) = @_;
251              
252 0 0         croak("_wait_spinner() needs a message sent in") if ! $msg;
253              
254 0   0       $spinner_count //= 0;
255 0           my $num = 20 - $spinner_count;
256 0           my $spinner = '.' x $spinner_count . ' ' x $num;
257 0           $spinner_count++;
258 0 0         $spinner_count = 0 if $spinner_count == 20;
259 0           print STDERR "$msg: $spinner\r";
260 0           select(undef, undef, undef, 0.1);
261             }
262             sub _validate_git {
263 0 0   0     my $sep = $^O =~ /win32/i ? ';' : ':';
264 0           return grep {-x "$_/git" } split /$sep/, $ENV{PATH};
  0            
265             }
266       0     sub __placeholder {}
267              
268             1;
269             __END__