package ShipIt::Util;
use strict;
use Carp qw(croak confess);
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(slurp write_file bool_prompt edit_file $term make_var tempdir_obj
in_dir);
use Term::ReadLine ();
use File::Temp ();
use File::Path ();
use Cwd;
our $term = Term::ReadLine->new("prompt");
sub slurp {
my ($file) = @_;
open (my $fh, $file) or confess "Failed to open $file: $!\n";
return do { local $/; <$fh>; }
}
sub write_file {
my ($file, $contents) = @_;
open (my $fh, ">", $file) or confess "Failed to open $file for write: $!\n";
print $fh $contents;
close($fh) or confess "Close failed";
die "assert" unless -s $file == length($contents);
return 1;
}
sub bool_prompt {
my ($q, $def) = @_;
$def = uc($def || "");
die "bogus default" unless $def =~ /^[YN]?$/;
my $opts = " [y/n]";
$opts = " [Y/n]" if $def eq "Y";
$opts = " [y/N]" if $def eq "N";
my $to_bool = sub {
my $yn = shift;
return 1 if $yn =~ /^y/i;
return 0 if $yn =~ /^n/i;
return undef;
};
while (1) {
my $ans = $term->readline("$q$opts ");
my $bool = $to_bool->($ans || $def);
return $bool if defined $bool;
warn "Please answer 'y' or 'n'\n";
}
}
sub edit_file {
my ($file) = @_;
my $editor = $ENV{"EDITOR"} || "vi";
system($editor, $file);
}
sub make_var {
my $var = shift;
my $file = slurp("Makefile");
return undef unless $file =~ /^\Q$var\E\s*=\s*(.+)/m;
return $1;
}
# returns either $obj or ($obj->dir, $obj), when in list context.
# when $obj goes out of scope, all temp directory contents are wiped.
sub tempdir_obj {
my $dir = File::Temp::tempdir() or
die "Failed to create temp directory: $!\n";
my $obj = bless {
dir => $dir,
}, "ShipIt::Util::TempDir";
return wantarray ? ($dir, $obj) : $obj;
}
# run a coderef in another directory, then return to old directory,
# even if $code dies.
sub in_dir {
my ($dir, $code) = @_;
my $old_cwd = getcwd;
chdir($dir) or die "chdir to dir $dir failed: $!\n";
my $rv = eval { $code->(); };
my $err = $@;
chdir($old_cwd) or die "chdir back to $old_cwd failed: $!\n";
die $err if $err;
return $rv;
}
############################################################################
package ShipIt::Util::TempDir;
sub directory { $_[0]{dir} };
sub DESTROY {
my $self = shift;
File::Path::rmtree($self->{dir}) if $self->{dir} && -d $self->{dir};
}
1;
syntax highlighted by Code2HTML, v. 0.9.1