Skip to content

Instantly share code, notes, and snippets.

@ugexe
Last active July 1, 2016 04:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ugexe/2ca5464cd440ab651f9409f575ec3dac to your computer and use it in GitHub Desktop.
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
# 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