|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
  
 
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package App::ChangeShebang 0.10;  | 
| 
2
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
166340
 | 
 use v5.16;  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
    | 
| 
3
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
9
 | 
 use warnings;  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
    | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
59
 | 
    | 
| 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
5
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
1668
 | 
 use Getopt::Long ();  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24429
 | 
    | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
60
 | 
    | 
| 
6
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
1137
 | 
 use Pod::Usage ();  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
103052
 | 
    | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
52
 | 
    | 
| 
7
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
1916
 | 
 use ExtUtils::MakeMaker ();  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
200262
 | 
    | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
59
 | 
    | 
| 
8
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
14
 | 
 use File::Basename ();  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
    | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
    | 
| 
9
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
760
 | 
 use File::Temp ();  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19216
 | 
    | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1709
 | 
    | 
| 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
11
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
 sub prompt { ExtUtils::MakeMaker::prompt(@_) }  | 
| 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub new {  | 
| 
14
 | 
4
 | 
 
 | 
 
 | 
  
4
  
 | 
  
0
  
 | 
18756
 | 
     my $class = shift;  | 
| 
15
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
49
 | 
     bless {@_}, $class;  | 
| 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub parse_options {  | 
| 
19
 | 
4
 | 
 
 | 
 
 | 
  
4
  
 | 
  
0
  
 | 
16
 | 
     my ($self, @argv) = @_;  | 
| 
20
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
31
 | 
     my $parser = Getopt::Long::Parser->new(  | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         config => [qw(no_auto_abbrev no_ignore_case)],  | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     );  | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $parser->getoptionsfromarray(  | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         \@argv,  | 
| 
25
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
         "version|v" => sub { printf "%s %s\n", __PACKAGE__, __PACKAGE__->VERSION; exit },  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         "quiet|q"   => \$self->{quiet},  | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         "force|f"   => \$self->{force},  | 
| 
28
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
         "help|h"    => sub { Pod::Usage::pod2usage(0) },  | 
| 
29
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
400
 | 
     ) or Pod::Usage::pod2usage(1);  | 
| 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
31
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2301
 | 
     my @file = @argv;  | 
| 
32
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
10
 | 
     if (!@file) {  | 
| 
33
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         warn "Missing file arguments.\n";  | 
| 
34
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         Pod::Usage::pod2usage(1);  | 
| 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
36
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
     $self->{file} = \@file;  | 
| 
37
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
     $self;  | 
| 
38
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
39
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub run {  | 
| 
41
 | 
4
 | 
 
 | 
 
 | 
  
4
  
 | 
  
0
  
 | 
11
 | 
     my $self = shift;  | 
| 
42
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
     for my $file (@{ $self->{file} }) {  | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
    | 
| 
43
 | 
12
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
288
 | 
         next unless -f $file && !-l $file;  | 
| 
44
 | 
12
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
52
 | 
         next unless $self->is_perl_shebang( $file );  | 
| 
45
 | 
11
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
36
 | 
         unless ($self->{force}) {  | 
| 
46
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             my $anser = prompt "change shebang line of $file? (y/N)", "N";  | 
| 
47
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             next if $anser !~ /^y(es)?$/i;  | 
| 
48
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
49
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
37
 | 
         $self->change_shebang($file);  | 
| 
50
 | 
11
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
54
 | 
         warn "changed shebang line of $file\n" unless $self->{quiet};  | 
| 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
53
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub is_perl_shebang {  | 
| 
55
 | 
12
 | 
 
 | 
 
 | 
  
12
  
 | 
  
0
  
 | 
26
 | 
     my ($self, $file) = @_;  | 
| 
56
 | 
12
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
417
 | 
     open my $fh, "<:raw", $file or die "open $file: $!\n";  | 
| 
57
 | 
12
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
217
 | 
     read $fh, my $first, 100 or die "read $file: $!\n";  | 
| 
58
 | 
12
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
273
 | 
     return $first =~ /^#!([^\n]*)perl/ ? 1 : 0;  | 
| 
59
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
61
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $remove = do {  | 
| 
62
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $s = qr/[ \t]*/;  | 
| 
63
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $w = qr/[^\n]*/;  | 
| 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $running_under_some_shell = qr/\n*  | 
| 
65
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $s eval $s ['"] exec $w \n  | 
| 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             $s if $s (?:0|\$running_under_some_shell) $w \n  | 
| 
67
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     /xsm;  | 
| 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $shebang = qr/\n*  | 
| 
69
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         \#! $w \n  | 
| 
70
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     /xsm;  | 
| 
71
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     qr/\A(?:$running_under_some_shell|$shebang)+/;  | 
| 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 };  | 
| 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
74
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub change_shebang {  | 
| 
75
 | 
11
 | 
 
 | 
 
 | 
  
11
  
 | 
  
0
  
 | 
33
 | 
     my ($self, $file) = @_;  | 
| 
76
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
     my $content = do {  | 
| 
77
 | 
11
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
341
 | 
         open my $fh, "<:raw", $file or die "open $file: $!\n";  | 
| 
78
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
55
 | 
         local $/; <$fh>;  | 
| 
 
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
340
 | 
    | 
| 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     };  | 
| 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
81
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
139
 | 
     $content =~ s/$remove//;  | 
| 
82
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
83
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
138
 | 
     my $mode = (stat $file)[2];  | 
| 
84
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
85
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
394
 | 
     my ($tmp_fh, $tmp_name) = File::Temp::tempfile UNLINK => 0, DIR => File::Basename::dirname($file);  | 
| 
86
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3538
 | 
     chmod $mode, $tmp_name;  | 
| 
87
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29
 | 
     print {$tmp_fh} <<'...';  | 
| 
 
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
55
 | 
    | 
| 
88
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #!/bin/sh  | 
| 
89
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 exec "$(dirname "$0")"/perl -x "$0" "$@"  | 
| 
90
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #!perl  | 
| 
91
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ...  | 
| 
92
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
     print {$tmp_fh} $content;  | 
| 
 
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
    | 
| 
93
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
344
 | 
     close $tmp_fh;  | 
| 
94
 | 
11
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
1097
 | 
     rename $tmp_name, $file or die "rename $tmp_name, $file: $!\n";  | 
| 
95
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
97
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
98
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  | 
| 
99
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 __END__  |