Skip to content

Instantly share code, notes, and snippets.

@ugexe
Created February 18, 2017 05:56
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save ugexe/91ae37b94e57c78a2c5b893eaff32063 to your computer and use it in GitHub Desktop.
Perl6 remote Distribution object access and installation over github http api
use Net::HTTP::GET; # Only dependency is IO::Socket::SSL (and indirectly OpenSSL)
require IO::Socket::SSL; # Github requirement
# Save this code as $PWD/HTTPDistribution.pm6
#
# List meta data
# perl6 -I. -MHTTPDistribution -e 'say HTTPDistribution.new.meta.perl'
#
# List all files
# perl6 -I. -MHTTPDistribution -e 'say HTTPDistribution.new.ls-files'
#
# View the content of a file (this is how it is accessed by rakudo's CompUnit::Repoistory when installing)
# perl6 -I. -MHTTPDistribution -e 'say HTTPDistribution.new.content("lib/Zef/Fetch.pm6").slurp-rest'
# perl6 -I. -MHTTPDistribution -e 'say HTTPDistribution.new.content("resources/config.json").slurp-rest'
#
# View the content of a module by *name* by using its meta data
# perl6 -I. -MHTTPDistribution -e 'HTTPDistribution.new andthen {.content(.meta<provides><Zef::Fetch>).slurp-rest.say}'
#
# Actually install (watch out for github rate limits!)
# perl6 -I. -MHTTPDistribution -e 'say $*REPO.repo-chain[1].install(HTTPDistribution.new)'
class HTTPDistribution does Distribution {
has $.user = 'ugexe';
has $.repo = 'zef';
has $.rev = 'master';
has %!meta;
method meta {
state $meta-basename = self.ls-files.first(*.ends-with('META6.json' | 'META.info'))
or die "No META6.json file found. Aborting";
%!meta ||= do {
my $json = $.slurp-rest($meta-basename, :!bin);
my %hash = %( Rakudo::Internals::JSON.from-json($json) );
%hash<files> = self.ls-files.grep(*.starts-with('bin/' | 'resources/'))
.grep(!*.ends-with('/')).cache;
%hash
}
}
method content($name-path) {
self but role :: {
method open(|) { self }
method close(|) { True }
method slurp-rest(|c) { nextwith($name-path, |c) }
method e { $name-path ~~ any($.ls-files) }
method f { $name-path ~~ any($.ls-files) }
method d { False }
method r { True }
method w { False }
}
}
method !content-uri($name-path = '') { "https://raw.githubusercontent.com/{$.user}/{$.repo}/{$.rev}/{$name-path}" }
method !ls-files-uri { "https://api.github.com/repos/{$.user}/{$.repo}/git/trees/{$.rev}?recursive=1" }
method !https-request($url) { LEAVE sleep 1; Net::HTTP::GET($url, :header(self!header)) }
method !header {
my %header = User-Agent => 'perl6 HTTP::UserAgent';
with self.?api-key { %header<Authorization> = "token {$_}" }
%header;
}
method slurp-rest($name-path, Bool :$bin) {
my $response = self!https-request(self!content-uri($name-path));
$bin ?? $response.body !! $response.content;
}
method ls-files {
state @paths = do {
my $request = self!https-request(self!ls-files-uri);
my $json = Rakudo::Internals::JSON.from-json($request.content)<tree>;
$json.grep(*.<type>.?chars).grep({.<type>.lc eq 'blob'}).map(*.<path>)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment