File Coverage

blib/lib/App/ChangeShebang.pm
Criterion Covered Total %
statement 71 82 86.5
branch 13 24 54.1
condition 1 3 33.3
subroutine 13 15 86.6
pod 0 5 0.0
total 98 129 75.9


line stmt bran cond sub pod time code
1             package App::ChangeShebang v1.0.0;
2 2     2   221119 use v5.24;
  2         7  
3 2     2   7 use warnings;
  2         3  
  2         95  
4 2     2   8 use experimental qw(lexical_subs signatures);
  2         2  
  2         12  
5              
6 2     2   2009 use ExtUtils::MakeMaker ();
  2         215925  
  2         61  
7 2     2   12 use File::Basename ();
  2         5  
  2         49  
8 2     2   954 use File::Temp ();
  2         23686  
  2         59  
9 2     2   1343 use Getopt::Long ();
  2         21993  
  2         56  
10 2     2   1027 use Pod::Usage ();
  2         82564  
  2         1906  
11              
12             our $TRIAL = 0;
13              
14 4     4 0 151342 sub new ($class) {
  4         8  
  4         6  
15 4         38 bless {}, $class;
16             }
17              
18 4     4 0 6 sub parse_options ($self, @argv) {
  4         8  
  4         9  
  4         6  
19 4         35 my $parser = Getopt::Long::Parser->new(
20             config => [qw(no_auto_abbrev no_ignore_case)],
21             );
22 0     0   0 $parser->getoptionsfromarray(
23             \@argv,
24 0         0 "version|v" => sub (@) { printf "%s %s\n", __PACKAGE__, __PACKAGE__->VERSION; exit },
  0         0  
  0         0  
25             "quiet|q" => \$self->{quiet},
26             "force|f" => \$self->{force},
27 0     0   0 "help|h" => sub (@) { Pod::Usage::pod2usage(0) },
  0         0  
  0         0  
28 4 50       1494 ) or Pod::Usage::pod2usage(1);
29              
30 4         1913 my @file = @argv;
31 4 50       9 if (!@file) {
32 0         0 warn "Missing file arguments.\n";
33 0         0 Pod::Usage::pod2usage(1);
34             }
35 4         10 $self->{file} = \@file;
36 4         34 $self;
37             }
38              
39 4     4 0 8 sub run ($self) {
  4         6  
  4         5  
40 4         9 for my $file ($self->{file}->@*) {
41 12 50 33     247 next unless -f $file && !-l $file;
42 12 100       38 next unless $self->is_perl_shebang( $file );
43 11 50       27 unless ($self->{force}) {
44 0         0 my $anser = ExtUtils::MakeMaker::prompt( "change shebang line of $file? (y/N)", "N" );
45 0 0       0 next if $anser !~ /^y(es)?$/i;
46             }
47 11         28 $self->change_shebang($file);
48 11 50       57 warn "changed shebang line of $file\n" unless $self->{quiet};
49             }
50             }
51              
52 12     12 0 13 sub is_perl_shebang ($self, $file) {
  12         12  
  12         16  
  12         11  
53 12 50       341 open my $fh, "<:raw", $file or die "open $file: $!\n";
54 12 50       216 read $fh, my $first, 100 or die "read $file: $!\n";
55 12 100       205 return $first =~ /^#!([^\n]*)perl/ ? 1 : 0;
56             }
57              
58             my $remove = do {
59             my $s = qr/[ \t]*/;
60             my $w = qr/[^\n]*/;
61             my $running_under_some_shell = qr/\n*
62             $s eval $s ['"] exec $w \n
63             $s if $s (?:0|\$running_under_some_shell) $w \n
64             /xsm;
65             my $shebang = qr/\n*
66             \#! $w \n
67             /xsm;
68             qr/\A(?:$running_under_some_shell|$shebang)+/;
69             };
70              
71 11     11 0 14 sub change_shebang ($self, $file) {
  11         13  
  11         13  
  11         8  
72 11         14 my $content = do {
73 11 50       209 open my $fh, "<:raw", $file or die "open $file: $!\n";
74 11         39 local $/; <$fh>;
  11         189  
75             };
76              
77 11         121 $content =~ s/$remove//;
78              
79 11         92 my $mode = (stat $file)[2];
80              
81 11         390 my ($tmp_fh, $tmp_name) = File::Temp::tempfile UNLINK => 0, DIR => File::Basename::dirname($file);
82 11         3498 chmod $mode, $tmp_name;
83 11         17 print {$tmp_fh} <<'...';
  11         41  
84             #!/bin/sh
85             exec "$(dirname "$0")"/perl -x "$0" "$@"
86             #!perl
87             ...
88 11         13 print {$tmp_fh} $content;
  11         15  
89 11         349 close $tmp_fh;
90 11 50       1890 rename $tmp_name, $file or die "rename $tmp_name, $file: $!\n";
91             }
92              
93             1;
94             __END__