2e2ab2
#!/usr/bin/perl
2e2ab2
use strict;
2e2ab2
use warnings;
2e2ab2
use File::Path;
2e2ab2
use File::Spec;
2e2ab2
use Getopt::Long;
2e2ab2
2e2ab2
my $libdir = 'lib';
2e2ab2
my $filter = '';
2e2ab2
2e2ab2
GetOptions('libdir=s' => \$libdir, 'filter=s' => \$filter) or
2e2ab2
    die "Could not parse arguments\n";
2e2ab2
if ($filter eq '') {
2e2ab2
    # Empty pattern passes previous result by definition. Do not use it.
2e2ab2
    # Interpolared compilation is fixed in perl 5.18.0. RT#119095.
2e2ab2
    $filter = qr/(?:)/;
2e2ab2
}
2e2ab2
eval { $filter = qr{$filter}; 1} or
2e2ab2
    die "Could not compile filter as a regular expression: $@\n";
2e2ab2
2e2ab2
my ($file, $filename, $delimiter);
2e2ab2
while (<>) {
2e2ab2
    if (/^\$fatpacked\{\s*"([^"]*)"\s*\}\s*=.*<<\s*'([^']*)'\s*;/) {
2e2ab2
        # Packed module beginning found
2e2ab2
        $filename = $1;
2e2ab2
        $delimiter = $2;
2e2ab2
        if ($filename =~ $filter) {
2e2ab2
            print STDERR "Extracting `$filename'\n";
2e2ab2
            my $directory = (File::Spec->splitpath($filename))[1];
2e2ab2
            File::Path::make_path(File::Spec->catfile($libdir, $directory));
2e2ab2
            if ($file) {
2e2ab2
                die "Unballanced fat-packed module at line $.\n";
2e2ab2
            }
2e2ab2
            open($file, '>', File::Spec->catfile($libdir, $filename)) or
2e2ab2
                die "Could not create `",
2e2ab2
                    File::Spec->catfile($libdir, $filename), "': $!\n";
2e2ab2
        } else {
2e2ab2
            print STDERR "Removing `$filename'\n";
2e2ab2
        }
2e2ab2
    } elsif (defined $delimiter and /^\Q$delimiter\E$/) {
2e2ab2
        # Packed module end found
2e2ab2
        if (defined $file) {
2e2ab2
            close($file) or
2e2ab2
                die "Could not close `",
2e2ab2
                    File::Spec->catfile($libdir, $filename), "': $!\n";
2e2ab2
            $file = undef;
2e2ab2
        }
2e2ab2
        $filename = undef;
2e2ab2
        $delimiter = undef;
2e2ab2
    } elsif (defined $file) {
2e2ab2
        # Packed module to extract
2e2ab2
        s/^  //;    # de-escape recursive here-documents
2e2ab2
        print $file $_;
2e2ab2
    } elsif (! defined $delimiter) {
2e2ab2
        # Rest of code to output
2e2ab2
        print STDOUT $_;
2e2ab2
    }
2e2ab2
}
2e2ab2
2e2ab2
__END__
2e2ab2
2e2ab2
=encoding utf8
2e2ab2
2e2ab2
=head1 NAME
2e2ab2
2e2ab2
fatunpack - Unpacker for App::FatPacker packets
2e2ab2
2e2ab2
=head1 SYNOPSYS
2e2ab2
2e2ab2
fatunpack [OPTION…] [PACKED_SCRIPT…]
2e2ab2
2e2ab2
=head1 DESCRIPTION
2e2ab2
2e2ab2
This tool unpacks scripts packed with App::FatPacker.
2e2ab2
2e2ab2
Packed script's file names are specified as positional arguments. If no
2e2ab2
argument is given, a script from standard intput will be processed.
2e2ab2
2e2ab2
The content of packed script stripped of all bundled modules is written to
2e2ab2
standard output.
2e2ab2
2e2ab2
=head1 OPTIONS
2e2ab2
2e2ab2
=over 8
2e2ab2
2e2ab2
=item B<--libdir DIRECTORY>
2e2ab2
2e2ab2
Directory to output unpacked modules to that where bundled into the input
2e2ab2
script. Default value is C<lib>.
2e2ab2
2e2ab2
=item B<--filter REGULAR_EXPRESSION>
2e2ab2
2e2ab2
Save only modules whose file name matches the B<REGULAR_EXPRESSION>. The file
2e2ab2
names are compared without B<--libdir> prefix. The expession is not anchored
2e2ab2
by default. Empty expression matches any file name. Default value is empty
2e2ab2
regular expression, i.e. to save all modules.
2e2ab2
2e2ab2
=back
2e2ab2
2e2ab2
=head1 VERSION
2e2ab2
2e2ab2
This is version 2.
2e2ab2
2e2ab2
=head1 COPYRIGHT
2e2ab2
2e2ab2
Copyright © 2013, 2014  Petr Písař <ppisar@redhat.com>.
2e2ab2
2e2ab2
=head1 LICENSE
2e2ab2
2e2ab2
This is free software.  You may redistribute copies of it under the terms of
2e2ab2
the GNU General Public License L<http://www.gnu.org/licenses/gpl.html>.
2e2ab2
There is NO WARRANTY, to the extent permitted by law.
2e2ab2
2e2ab2
=cut