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   157 use strict;
  25         48  
  25         751  
4 25     25   108 use warnings;
  25         44  
  25         631  
5 25     25   122 use version;
  25         60  
  25         201  
6              
7 25     25   1665 use Capture::Tiny qw(:all);
  25         73  
  25         3009  
8 25     25   167 use Carp qw(croak cluck);
  25         44  
  25         1220  
9 25     25   132 use Cwd qw(getcwd);
  25         46  
  25         1321  
10 25     25   138 use Data::Dumper;
  25         42  
  25         1313  
11 25     25   170 use Digest::SHA;
  25         34  
  25         843  
12 25     25   168 use Dist::Mgr::FileData qw(:all);
  25         37  
  25         2873  
13 25     25   162 use File::Copy;
  25         53  
  25         1292  
14 25     25   11701 use File::Copy::Recursive qw(rmove_glob);
  25         88669  
  25         1671  
15 25     25   192 use File::Path qw(make_path rmtree);
  25         43  
  25         1265  
16 25     25   10226 use File::Find::Rule;
  25         156574  
  25         179  
17 25     25   11308 use Module::Starter;
  25         56597  
  25         139  
18 25     25   176198 use PPI;
  25         2233152  
  25         994  
19 25     25   10646 use Term::ReadKey;
  25         44288  
  25         1745  
20 25     25   17557 use Tie::File;
  25         466366  
  25         868  
21              
22 25     25   192 use Exporter qw(import);
  25         46  
  25         32499  
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.12';
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 'git\@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__