/
curl.rakumod
92 lines (60 loc) · 2.8 KB
/
curl.rakumod
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
use Zef;
class Zef::Service::Shell::curl does Fetcher does Probeable does Messenger {
=begin pod
=title class Zef::Service::Shell::curl
=subtitle A curl based implementation of the Fetcher interface
=head1 Synopsis
=begin code :lang<raku>
use Zef;
use Zef::Service::Shell::curl;
my $curl = Zef::Service::Shell::curl.new;
my $source = "https://raw.githubusercontent.com/ugexe/zef/master/META6.json";
my $save-to = $*TMPDIR.child("zef-meta6.json");
my $saved-to = $curl.fetch($source, $save-to);
die "Something went wrong" unless $saved-to;
say "Zef META6 from HEAD: ";
say $saved-to.slurp;
=end code
=head1 Description
C<Fetcher> class for handling http based URIs using the C<curl> command.
You probably never want to use this unless its indirectly through C<Zef::Fetch>;
handling files and spawning processes will generally be easier using core language functionality. This
class exists to provide the means for fetching a file using the C<Fetcher> interfaces that the e.g. git/file
adapters use.
=head1 Methods
=head2 method probe
method probe(--> Bool:D)
Returns C<True> if this module can successfully launch the C<curl> command.
=head2 method fetch-matcher
method fetch-matcher(Str() $uri --> Bool:D)
Returns C<True> if this module knows how to fetch C<$uri>, which it decides based on if C<$uri>
starts with C<http> or C<https>.
=head2 method fetch
method fetch(Str() $uri, IO() $save-as --> IO::Path)
Fetches the given C<$uri>, saving it to C<$save-to>.
On success it returns the C<IO::Path> where the data was actually saved to. On failure it returns C<Nil>.
=end pod
#| Return true if the `curl` command is available to use
method probe(--> Bool:D) {
state $probe = try { Zef::zrun('curl', '--help', :!out, :!err).so };
}
#| Return true if this Fetcher understands the given uri/path
method fetch-matcher(Str() $uri --> Bool:D) {
return so <https http>.first({ $uri.lc.starts-with($_) });
}
#| Fetch the given url
method fetch(Str() $uri, IO() $save-as --> IO::Path) {
die "target download directory {$save-as.parent} does not exist and could not be created"
unless $save-as.parent.d || mkdir($save-as.parent);
my $passed;
react {
my $cwd := $save-as.parent;
my $ENV := %*ENV;
my $proc = Zef::zrun-async('curl', '--silent', '-L', '-z', $save-as.absolute, '-o', $save-as.absolute, $uri);
whenever $proc.stdout(:bin) { }
whenever $proc.stderr(:bin) { }
whenever $proc.start(:$ENV, :$cwd) { $passed = $_.so }
}
return ($passed && $save-as.e) ?? $save-as !! Nil;
}
}