Last active
July 1, 2016 04:05
-
-
Save ugexe/2ca5464cd440ab651f9409f575ec3dac to your computer and use it in GitHub Desktop.
Install Perl6 module from .tar.gz file without extracting entire archive to temp location using new Distribution interface
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Example: | |
# $ wget https://github.com/ugexe/zef/archive/master.tar.gz -O zef.tar.gz | |
# $ perl6 install-tar-dist.pl6 zef.tar.gz | |
# Does not install prereqs | |
class Distribution::Cmd::Tar does Distribution { | |
has IO::Path $.path; | |
has %!meta; | |
method new($path, :%meta) { | |
self.bless(:$path, :%meta); | |
} | |
method meta { | |
state $meta-basename = self!list.first(*.ends-with('META6.json' | 'META.info')) | |
or die "No META6.json file found in archive. Aborting"; | |
%!meta ||= try { | |
my $json = self!extract($meta-basename, :!bin); | |
my %hash = %( Rakudo::Internals::JSON.from-json($json) ); | |
%hash<files> = self!list.grep(*.starts-with('bin/' | 'resources/')) | |
.grep(!*.ends-with('/')); | |
%hash | |
} | |
} | |
method content($name-path) { | |
class :: { | |
has $.data; | |
method open(|) { | |
$.data but role :: { | |
method slurp-rest(Bool :$bin) { | |
?$bin ?? self !! self.encode | |
} | |
} | |
} | |
method close(|) { True } | |
}.new(data => self!extract($name-path, :bin)); | |
} | |
method !list { | |
state @paths = do { | |
my @tar-paths = self!run-tar('--list', '-f', $!path.relative, :cwd($!path.CWD))<out>.lines; | |
my $root = self!tar-prefix; | |
@tar-paths.map(*.subst(/^$root/, '')).grep(*.chars) | |
} | |
} | |
method !extract($name-path, Bool :$bin) { | |
self!run-tar('--to-stdout', '--extract', '-zf', $!path.relative, self!tar-path($name-path), :$bin, :cwd($!path.CWD))<out>; | |
} | |
method !run-tar(*@cmd, :%env = %*ENV, :$cwd, Bool :$bin) { | |
my $proc = $*DISTRO.is-win | |
?? run('cmd', '/c', 'tar', |@cmd, :out, :err, :$bin, :$cwd, :%env) | |
!! run('tar', |@cmd, :out, :err, :$bin, :$cwd, :%env); | |
my $out = |$proc.out.slurp-rest(:$bin); | |
my $err = |$proc.err.slurp-rest(:$bin); | |
$ = $proc.out.close unless $err; | |
$ = $proc.err.close; | |
%( :$out, :$err ) | |
} | |
# Construct a path that the tar command understands | |
method !tar-path($name-path) { | |
state $prefix = self!tar-prefix; | |
$prefix ~ $name-path; | |
} | |
method !tar-prefix { | |
state $prefix = self!run-tar('--list', '-f', $!path.relative, :cwd($!path.CWD))<out>.lines[0]; | |
} | |
} | |
BEGIN { die "Need a bleading edge rakudo" if ::("Distribution::Hash") ~~ Failure } | |
sub MAIN($path where *.ends-with('.tar.gz'), Bool :$force) { | |
say "Installing distribution from: $path"; | |
my $dist = Distribution::Cmd::Tar.new($path.IO); | |
say "# Name: {$dist.meta<name>}"; | |
say "# Provides:"; | |
say "#\t$_" for $dist.meta<provides>.values; | |
my $curi = CompUnit::RepositoryRegistry.repository-for-name("site"); | |
say try { | |
CATCH { default { say "Error: $_" } } | |
$curi.install($dist, :$force) | |
} ?? "Install OK" !! "Install FAIL"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment