summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--urpm/args.pm10
-rw-r--r--urpm/download.pm82
2 files changed, 84 insertions, 8 deletions
diff --git a/urpm/args.pm b/urpm/args.pm
index 58cbdacd..14ebaf57 100644
--- a/urpm/args.pm
+++ b/urpm/args.pm
@@ -109,10 +109,12 @@ my %options_spec = (
wget => sub { $urpm->{options}{downloader} = 'wget' },
curl => sub { $urpm->{options}{downloader} = 'curl' },
prozilla => sub { $urpm->{options}{downloader} = 'prozilla' },
+ aria2 => sub { $urpm->{options}{downloader} = 'aria2' },
'curl-options=s' => sub { $urpm->{options}{'curl-options'} = $_[1] },
'rsync-options=s' => sub { $urpm->{options}{'rsync-options'} = $_[1] },
'wget-options=s' => sub { $urpm->{options}{'wget-options'} = $_[1] },
'prozilla-options=s' => sub { $urpm->{options}{'prozilla-options'} = $_[1] },
+ 'aria2-options=s' => sub { $urpm->{options}{'aria2-options'} = $_[1] },
'limit-rate=s' => sub { $urpm->{options}{'limit-rate'} = $_[1] },
'resume!' => sub { $urpm->{options}{resume} = $_[1] },
'retry=s' => sub { $urpm->{options}{retry} = $_[1] },
@@ -370,17 +372,17 @@ foreach my $k ("help|h", "version", "no-locales", "update", "media|mediums=s",
$options_spec{urpmf}{$k} = $options_spec{urpmi}{$k};
}
-foreach my $k ("help|h", "version", "wget", "curl", "prozilla", "proxy=s", "proxy-user=s",
+foreach my $k ("help|h", "version", "wget", "curl", "prozilla", "aria2", "proxy=s", "proxy-user=s",
'limit-rate=s',
- "wget-options=s", "curl-options=s", "rsync-options=s", "prozilla-options=s")
+ "wget-options=s", "curl-options=s", "rsync-options=s", "prozilla-options=s", "aria2-options=s")
{
$options_spec{'urpmi.update'}{$k} =
$options_spec{urpmq}{$k} = $options_spec{urpmi}{$k};
}
-foreach my $k ("help|h", "wget", "curl", "prozilla", "proxy=s", "proxy-user=s", "c", "f", "z",
+foreach my $k ("help|h", "wget", "curl", "prozilla", "aria2", "proxy=s", "proxy-user=s", "c", "f", "z",
"limit-rate=s", "no-md5sum", "update", "norebuild!", "probe-rpms",
- "wget-options=s", "curl-options=s", "rsync-options=s", "prozilla-options=s", '<>')
+ "wget-options=s", "curl-options=s", "rsync-options=s", "prozilla-options=s", "aria2-options=s", '<>')
{
$options_spec{'urpmi.addmedia'}{$k} = $options_spec{'urpmi.update'}{$k};
}
diff --git a/urpm/download.pm b/urpm/download.pm
index d368ab4e..18ab4bb5 100644
--- a/urpm/download.pm
+++ b/urpm/download.pm
@@ -26,18 +26,18 @@ our $CONNECT_TIMEOUT = 60; #- (in seconds)
-sub ftp_http_downloaders() { qw(curl wget prozilla) }
+sub ftp_http_downloaders() { qw(curl wget prozilla aria2) }
sub available_ftp_http_downloaders() {
my %binaries = (
curl => 'curl',
wget => 'wget',
prozilla => 'proz',
+ aria2 => 'aria2c',
);
grep { -x "/usr/bin/$binaries{$_}" || -x "/bin/$binaries{$_}" } ftp_http_downloaders();
}
-
#- parses proxy.cfg (private)
sub load_proxy_config () {
return if defined $proxy_config;
@@ -182,6 +182,16 @@ sub set_proxy {
}
last;
};
+ /\baria2\b/ and do {
+ for ($proxy->{proxy}) {
+ push @res, ('--http-proxy', $_->{http_proxy}) if defined $_->{http_proxy};
+ push @res, ('--http-proxy', $_->{ftp_proxy}) if defined $_->{ftp_proxy};
+ push @res, ("--http-proxy-user=$_->{user}", "--http-proxy-passwd=$_->{pwd}")
+ if defined $_->{user} && defined $_->{pwd};
+ }
+ last;
+ };
+
die N("Unknown webfetch `%s' !!!\n", $proxy->{type});
}
}
@@ -559,6 +569,69 @@ sub sync_prozilla {
}
}
+sub sync_aria2 {
+ -x "/usr/bin/aria2c" or die N("aria2 is missing\n");
+ my $options = shift;
+ $options = { dir => $options } if !ref $options;
+ #- force download to be done in cachedir to avoid polluting cwd.
+ (my $cwd) = getcwd() =~ /(.*)/;
+ chdir $options->{dir};
+ my ($buf, $total, $file) = ('', undef, undef);
+ my $aria2c_command = join(" ", map { "'$_'" }
+ "/usr/bin/aria2c",
+ "--timeout", $CONNECT_TIMEOUT,
+ "--auto-file-renaming=false",
+ "--follow-metalink=mem",
+ "-Z", "-j1",
+ ($options->{limit_rate} ? "--max-download-limit=$options->{limit_rate}" : ()),
+ ($options->{resume} ? "--continue" : "--allow-overwrite=true"),
+ ($options->{proxy} ? set_proxy({ type => "aria2", proxy => $options->{proxy} }) : ()),
+ ($options->{retry} ? "--max-tries=$options->{retry}" : "--max-tries=3"),
+ (defined $options->{'aria2-options'} ? split /\s+/, $options->{'aria2-options'} : ()),
+ @_);
+
+ $options->{debug} and $options->{debug}($aria2c_command);
+
+ my $aria2_pid = open (my $aria2, "$aria2c_command |");
+
+ local $/ = \1; #- read input by only one char, this is slow but very nice (and it works!).
+ local $_;
+
+ while(<$aria2>) {
+ $buf .= "$_";
+ if ($_ eq "\r" || $_ eq "\n") {
+ if ($options->{callback}) {
+ if (! defined $file and @_) {
+ $file = shift @_;
+ propagate_sync_callback($options, 'start', $file);
+ }
+ if ($buf =~ /^\[\#\d*\s+\S+:([\d\.]+\w*).([\d\.]+\w*)\S([\d]+)\S+\s+\S+\s*([\d\.]+)\s\w*:([\d\.]+\w*\/\w)\s\w*:([\d]+\w*)\][\r\n]$/) {
+ my ($total, $percent, $speed, $eta) = ($2, $3, $5, $6);
+ #- $1 = current downloaded size, $4 = connections
+ if (propagate_sync_callback($options, 'progress', $file, $percent, $total, $eta, $speed) eq 'canceled') {
+ kill 15, $aria2_pid;
+ close $aria2;
+ return;
+ }
+ }
+ if ($buf =~ /Download\scomplete:\s\.\//) {
+ propagate_sync_callback($options, 'end', $file);
+ $file = undef;
+ } elsif ($buf =~ /ERR\|/) {
+ local $/ = "\n";
+ chomp $buf;
+ propagate_sync_callback($options, 'error', $file, $buf);
+ }
+ } else {
+ $options->{quiet} or print STDERR $buf;
+ }
+ $buf = '';
+ }
+ }
+ chdir $cwd;
+ close $aria2 or _error('aria2');
+}
+
sub start_ssh_master {
my ($server, $user) = @_;
$server or return 0;
@@ -653,7 +726,7 @@ sub sync {
$urpm->{debug} ? (debug => $urpm->{debug}) : (),
%options,
);
- foreach my $cpt (qw(compress limit-rate retry wget-options curl-options rsync-options prozilla-options)) {
+ foreach my $cpt (qw(compress limit-rate retry wget-options curl-options rsync-options prozilla-options aria2-options)) {
$all_options{$cpt} = $urpm->{options}{$cpt} if defined $urpm->{options}{$cpt};
}
@@ -685,6 +758,7 @@ sub _sync_webfetch_raw {
delete @files{qw(removable file)};
}
if ($files{ftp} || $files{http} || $files{https}) {
+
my @available = urpm::download::available_ftp_http_downloaders();
#- use user default downloader if provided and available
@@ -702,7 +776,7 @@ sub _sync_webfetch_raw {
my @l = (@{$files{ftp} || []}, @{$files{http} || []}, @{$files{https} || []});
while (@l) {
my $half_MAX_ARG = 131072 / 2;
- # restrict the number of elements so that it fits on cmdline of curl/wget/proz
+ # restrict the number of elements so that it fits on cmdline of curl/wget/proz/aria2c
my $n = 0;
for (my $len = 0; $n < @l && $len < $half_MAX_ARG; $len += length($l[$n++])) {}
$sync->($options, splice(@l, 0, $n));