File Coverage

blib/lib/ShipIt/Util.pm
Criterion Covered Total %
statement 31 77 40.2
branch 4 38 10.5
condition 0 10 0.0
subroutine 8 17 47.0
pod 0 8 0.0
total 43 150 28.6


line stmt bran cond sub pod time code
1             package ShipIt::Util;
2 2     2   8 use strict;
  2         3  
  2         64  
3 2     2   12 use Carp qw(croak confess);
  2         3  
  2         246  
4             require Exporter;
5             our @ISA = qw(Exporter);
6             our @EXPORT_OK = qw(slurp write_file bool_prompt edit_file $term make_var tempdir_obj
7             find_subclasses in_dir);
8 2     2   2006 use Term::ReadLine ();
  2         13299  
  2         44  
9 2     2   3001 use File::Temp ();
  2         59178  
  2         63  
10 2     2   17 use File::Path ();
  2         4  
  2         37  
11 2     2   12 use Cwd;
  2         5  
  2         2138  
12              
13             our $term = eval {
14             Term::ReadLine->new("prompt");
15             };
16              
17             sub slurp {
18 7     7 0 9 my ($file) = @_;
19 7 50       321 open (my $fh, $file) or confess "Failed to open $file: $!\n";
20 7         12 return do { local $/; binmode $fh; <$fh>; }
  7         29  
  7         15  
  7         241  
21             }
22              
23             sub write_file {
24 7     7 0 13 my ($file, $contents) = @_;
25 7 50       568 open (my $fh, ">", $file) or confess "Failed to open $file for write: $!\n";
26 7         14 binmode $fh;
27 7         30 print $fh $contents;
28 7 50       221 close($fh) or confess "Close failed";
29 7 50       108 die "assert" unless -s $file == length($contents);
30 7         33 return 1;
31             }
32              
33             sub bool_prompt {
34 0     0 0   my ($q, $def) = @_;
35 0   0       $def = uc($def || "");
36 0 0         die "bogus default" unless $def =~ /^[YN]?$/;
37 0 0         return $def if !$term;
38 0           my $opts = " [y/n]";
39 0 0         $opts = " [Y/n]" if $def eq "Y";
40 0 0         $opts = " [y/N]" if $def eq "N";
41             my $to_bool = sub {
42 0     0     my $yn = shift;
43 0 0         return 1 if $yn =~ /^y/i;
44 0 0         return 0 if $yn =~ /^n/i;
45 0           return undef;
46 0           };
47 0           while (1) {
48 0           my $ans = $term->readline("$q$opts ");
49 0   0       my $bool = $to_bool->($ans || $def);
50 0 0         return $bool if defined $bool;
51 0           warn "Please answer 'y' or 'n'\n";
52             }
53             }
54              
55             sub edit_file {
56 0     0 0   my ($file) = @_;
57 0   0       my $editor = $ENV{"EDITOR"} || "vi";
58 0           system($editor, $file);
59             }
60              
61             sub make_var {
62 0     0 0   my $var = shift;
63 0           my $file = slurp("Makefile");
64 0 0         return undef unless $file =~ /^\Q$var\E\s*=\s*(.+)\s*/m;
65 0           return $1;
66             }
67              
68             sub find_subclasses {
69             # search for any other custom project type modules
70 0     0 0   my $class = shift;
71 0           my @classes = ();
72 0           for my $dir (@INC) {
73 0           for my $file (glob("$dir/" . join("/", split(/::/, $class)) . "/*.pm")) {
74 0 0         if($file =~ /\/(\w+)\.pm/) {
75 0           push(@classes, "$class" . "::" . "$1");
76             }
77             }
78             }
79 0           return @classes;
80             }
81              
82             # returns either $obj or ($obj->dir, $obj), when in list context.
83             # when $obj goes out of scope, all temp directory contents are wiped.
84             sub tempdir_obj {
85 0 0   0 0   my $dir = File::Temp::tempdir() or
86             die "Failed to create temp directory: $!\n";
87 0           my $obj = bless {
88             dir => $dir,
89             }, "ShipIt::Util::TempDir";
90 0 0         return wantarray ? ($dir, $obj) : $obj;
91             }
92              
93             # run a coderef in another directory, then return to old directory,
94             # even if $code dies.
95             sub in_dir {
96 0     0 0   my ($dir, $code) = @_;
97 0           my $old_cwd = getcwd;
98 0 0         chdir($dir) or die "chdir to dir $dir failed: $!\n";
99 0           my $rv = eval { $code->(); };
  0            
100 0           my $err = $@;
101 0 0         chdir($old_cwd) or die "chdir back to $old_cwd failed: $!\n";
102 0 0         die $err if $err;
103 0           return $rv;
104             }
105              
106              
107             ############################################################################
108              
109             package ShipIt::Util::TempDir;
110 0     0     sub directory { $_[0]{dir} };
111             sub DESTROY {
112 0     0     my $self = shift;
113 0 0 0       File::Path::rmtree($self->{dir}) if $self->{dir} && -d $self->{dir};
114             }
115              
116              
117             1;