package File::ShareDir::Tarball; BEGIN { $File::ShareDir::Tarball::AUTHORITY = 'cpan:YANICK'; } { $File::ShareDir::Tarball::VERSION = '0.2.2'; } # ABSTRACT: Deal transparently with shared files distributed as tarballs use strict; use warnings; use parent qw/ Exporter /; use Carp; use File::ShareDir; use Archive::Tar; use File::Temp qw/ tempdir /; use File::chdir; our @EXPORT_OK = qw{ dist_dir dist_file }; our %EXPORT_TAGS = ( all => [ @EXPORT_OK ], ); my $shared_files_tarball = 'shared-files.tar.gz'; # we don't want to extract the same dirs again and # again within a single program my %DIR_CACHE; sub dist_dir { my $dist = shift; return $DIR_CACHE{$dist} if $DIR_CACHE{$dist}; my $dir = File::ShareDir::dist_dir($dist); # no tarball? Assume regular shared dir return $DIR_CACHE{$dist} = $dir unless -f "$dir/$shared_files_tarball"; my $archive = Archive::Tar->new; $archive->read("$dir/$shared_files_tarball"); # because that would be a veeery bad idea croak "archive '$shared_files_tarball' contains files with absolute path, aborting" if grep { m#^/# } $archive->list_files; my $tmpdir = tempdir( CLEANUP => 1 ); local $CWD = $tmpdir; $archive->extract; return $DIR_CACHE{$dist} = $tmpdir; } sub dist_file { my $dist = File::ShareDir::_DIST(shift); my $file = File::ShareDir::_FILE(shift); my $path = dist_dir($dist).'/'.$file; return undef unless -e $path; croak("Found dist_file '$path', but not a file") unless -f $path; croak("File '$path', no read permissions") unless -r $path; return $path; } 1; __END__ =pod =head1 NAME File::ShareDir::Tarball - Deal transparently with shared files distributed as tarballs =head1 VERSION version 0.2.2 =head1 SYNOPSIS use File::ShareDir::Tarball ':all'; # use exactly like File::ShareDir $dir = dist_dir('File-ShareDir'); =head1 DESCRIPTION If the shared files of a distribution are contained in a tarball (see L for why you would want to do that), automatically extract the archive in a temporary directory and return the path to that directory. If called for a regular distribution without a bundle file (C), it'll return the original shared dir. In other words, from the consumer point of view, it'll behave just like L. =head1 EXPORT TAGS =head2 :all Exports C and C. =head1 EXPORTABLE FUNCTIONS =head2 dist_dir( $distribution ) Behaves just like C from L. =head2 dist_file( $distribution, $file ) Behaves just like C from L. =head1 SEE ALSO =over =item L To test or use a shared dir that is not deployed yet. =item L L plugin to create the tarball effortlessly. =item L Provides an alternative to this module by subclassing L and, upon installation, remove the files from previous installations as given in the I. =back =head1 AUTHOR Yanick Champoux =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Yanick Champoux. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut