metadata: scripts/feeds: distinguish between source and binary packages, resolve virtual dependencies

Properly resolve build depends to source packages and runtime depends to
binary packages. Dependencies on virtual packages are resolved to the first
provider now.

Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
This commit is contained in:
Matthias Schiffer 2018-01-11 18:38:42 +01:00
parent 47d6b05ad3
commit 52719c2b67
No known key found for this signature in database
GPG key ID: 16EF3F64CB201D9C
2 changed files with 112 additions and 70 deletions

View file

@ -32,12 +32,14 @@ $valid_mk or die "Unsupported version of make found: $mk\n";
my @feeds; my @feeds;
my %build_packages; my %build_packages;
my %installed; my %installed;
my %installed_pkg;
my %installed_targets; my %installed_targets;
my %feed_cache; my %feed_cache;
my $feed_package = {}; my $feed_package = {};
my $feed_src = {}; my $feed_src = {};
my $feed_target = {}; my $feed_target = {};
my $feed_vpackage = {};
sub parse_config() { sub parse_config() {
my $line = 0; my $line = 0;
@ -223,20 +225,21 @@ sub get_feed($) {
parse_package_metadata($file) or return; parse_package_metadata($file) or return;
my %target = get_targets("./feeds/$feed.targetindex"); my %target = get_targets("./feeds/$feed.targetindex");
$feed_cache{$feed} = [ { %package }, { %srcpackage }, { %target } ]; $feed_cache{$feed} = [ { %package }, { %srcpackage }, { %target }, { %vpackage } ];
} }
$feed_package = $feed_cache{$feed}->[0]; $feed_package = $feed_cache{$feed}->[0];
$feed_src = $feed_cache{$feed}->[1]; $feed_src = $feed_cache{$feed}->[1];
$feed_target = $feed_cache{$feed}->[2]; $feed_target = $feed_cache{$feed}->[2];
return $feed_cache{$feed}->[0]; $feed_vpackage = $feed_cache{$feed}->[3];
} }
sub get_installed() { sub get_installed() {
system("$mk -s prepare-tmpinfo OPENWRT_BUILD="); system("$mk -s prepare-tmpinfo OPENWRT_BUILD=");
clear_packages(); clear_packages();
parse_package_metadata("./tmp/.packageinfo"); parse_package_metadata("./tmp/.packageinfo");
%installed = %package; %installed_pkg = %vpackage;
%installed = %srcpackage;
%installed_targets = get_targets("./tmp/.targetinfo"); %installed_targets = get_targets("./tmp/.targetinfo");
} }
@ -371,15 +374,11 @@ sub list {
return 0; return 0;
} }
# TODO: do_install_package etc. should deal with source packages rather sub do_install_src($$) {
# than binary packages
sub do_install_package($$) {
my $feed = shift; my $feed = shift;
my $pkg = shift; my $src = shift;
my $path;
$pkg->{src} and $path = $pkg->{src}{makefile};
my $path = $src->{makefile};
if ($path) { if ($path) {
$path =~ s/\/Makefile$//; $path =~ s/\/Makefile$//;
@ -418,6 +417,18 @@ sub do_install_target($) {
return 0; return 0;
} }
sub lookup_src($$) {
my $feed = shift;
my $src = shift;
foreach my $feed ($feed, @feeds) {
next unless $feed->[1];
next unless $feed_cache{$feed->[1]};
$feed_cache{$feed->[1]}->[1]->{$src} and return $feed;
}
return;
}
sub lookup_package($$) { sub lookup_package($$) {
my $feed = shift; my $feed = shift;
my $package = shift; my $package = shift;
@ -425,7 +436,7 @@ sub lookup_package($$) {
foreach my $feed ($feed, @feeds) { foreach my $feed ($feed, @feeds) {
next unless $feed->[1]; next unless $feed->[1];
next unless $feed_cache{$feed->[1]}; next unless $feed_cache{$feed->[1]};
$feed_cache{$feed->[1]}->[0]->{$package} and return $feed; $feed_cache{$feed->[1]}->[3]->{$package} and return $feed;
} }
return; return;
} }
@ -442,9 +453,9 @@ sub lookup_target($$) {
return; return;
} }
sub is_core_package($) { sub is_core_src($) {
my $package = shift; my $src = shift;
foreach my $file ("tmp/info/.packageinfo-$package", glob("tmp/info/.packageinfo-*_$package")) { foreach my $file ("tmp/info/.packageinfo-$src", glob("tmp/info/.packageinfo-*_$src")) {
next unless index($file, "tmp/info/.packageinfo-feeds_"); next unless index($file, "tmp/info/.packageinfo-feeds_");
return 1 if -s $file; return 1 if -s $file;
} }
@ -455,6 +466,8 @@ sub install_target {
my $feed = shift; my $feed = shift;
my $name = shift; my $name = shift;
$installed_targets{$name} and return 0;
$feed = $feed_cache{$feed->[1]}->[2]; $feed = $feed_cache{$feed->[1]}->[2];
$feed or return 0; $feed or return 0;
@ -465,85 +478,115 @@ sub install_target {
return do_install_target($target); return do_install_target($target);
} }
sub install_package { sub install_src {
my $feed = shift; my $feed = shift;
my $name = shift; my $name = shift;
my $force = shift; my $force = shift;
my $ret = 0; my $ret = 0;
my $this_feed_target = lookup_target($feed, $name); $feed = lookup_src($feed, $name);
$this_feed_target and do { unless ($feed) {
$installed_targets{$name} and return 0;
install_target($this_feed_target, $name);
return 0;
};
$feed = lookup_package($feed, $name);
$feed or do {
$installed{$name} and return 0; $installed{$name} and return 0;
# TODO: check if it's already installed within ./package directory $feed_src->{$name} or warn "WARNING: No feed for source package '$name' found\n";
$feed_src->{$name} or is_core_package($name) or warn "WARNING: No feed for package '$name' found, maybe it's already part of the standard packages?\n";
return 0; return 0;
}; }
# switch to the metadata for the selected feed # switch to the metadata for the selected feed
my $cur = get_feed($feed->[1]); get_feed($feed->[1]);
my $src = $feed_src->{$name} or return 1;
my $pkg = $cur->{$name} or return 1;
$pkg->{name} or do {
$installed{$name} and return 0;
# TODO: check if this is an alias package, maybe it's known by another name
warn "WARNING: Package '$name' is not available in feed $feed->[1].\n";
return 0;
};
my $src = $pkg->{src}{name};
my $type = $feed->[0];
$src or $src = $name;
# If it's a core package and we don't want to override, just return # If it's a core package and we don't want to override, just return
!$force and is_core_package($src) and return 0; my $override = 0;
if (is_core_src($name)) {
return 0 unless $force;
$override = 1;
}
# previously installed packages set the runtime package if ($installed{$name}) {
# newly installed packages set the source package to 1 # newly installed packages set the source package to 1
$installed{$src} and $installed{$src} == 1 and return 0; return 0 if ($installed{$name} == 1);
return 0 unless ($override);
}
# we'll trigger the override only with the 3 conditions below: $installed{$name} = 1;
# - override is allowed by command line (-f) foreach my $pkg (@{$src->{packages}}) {
# - a package with the same src exists in the core packages list foreach my $vpkg (@{$pkg->{provides}}) {
# - the package previously installed is not from a feed $installed_pkg{$vpkg} = 1;
my $override = 1 if ($force and is_core_package($src) and !$installed{$name}->{feed}); }
}
# check previously installed packages if ($override) {
$installed{$name} and !$override and return 0; warn "Overriding core package '$name' with version from $feed->[1]\n";
$installed{$src} = 1; } else {
warn "Installing package '$name' from $feed->[1]\n";
}
defined($override) and $override == 1 do_install_src($feed, $src) == 0 or do {
and warn "Overriding core package '$src' with version from $feed->[1]\n"
or warn "Installing package '$src' from $feed->[1]\n";
do_install_package($feed, $pkg) == 0 or do {
warn "failed.\n"; warn "failed.\n";
return 1; return 1;
}; };
# install all dependencies referenced from the source package # install all dependencies referenced from the source package
foreach my $dep ( foreach my $dep (
@{$feed_src->{$src}{builddepends}}, @{$src->{builddepends}},
@{$feed_src->{$src}{"builddepends/host"}}, @{$src->{'builddepends/host'}},
map { @{$_->{depends}} } @{$feed_src->{$src}{packages}}
) { ) {
# TODO: handle virtual packages and PROVIDES
next if $dep =~ /@/; next if $dep =~ /@/;
$dep =~ s/^\+//;
$dep =~ s/^.+://; $dep =~ s/^.+://;
$dep =~ s/\/.+$//; $dep =~ s/\/.+$//;
next unless $dep; next unless $dep;
install_src($feed, $dep, 0) == 0 or $ret = 1;
}
foreach my $pkg (@{$src->{packages}}) {
foreach my $dep (@{$pkg->{depends}}) {
next if $dep =~ /@/;
$dep =~ s/^\+//;
$dep =~ s/^.+://;
next unless $dep;
install_package($feed, $dep, 0) == 0 or $ret = 1; install_package($feed, $dep, 0) == 0 or $ret = 1;
} }
}
return $ret; return $ret;
} }
sub install_package {
my $feed = shift;
my $name = shift;
my $force = shift;
$feed = lookup_package($feed, $name);
unless ($feed) {
$installed_pkg{$name} and return 0;
$feed_vpackage->{$name} or warn "WARNING: No feed for package '$name' found\n";
return 0;
}
# switch to the metadata for the selected feed
get_feed($feed->[1]);
my $pkg = $feed_vpackage->{$name} or return 1;
return install_src($feed, $pkg->[0]{src}{name}, $force);
}
sub install_target_or_package {
my $feed = shift;
my $name = shift;
my $force = shift;
my $this_feed_target = lookup_target($feed, $name);
$this_feed_target and do {
return install_target($this_feed_target, $name);
};
my $this_feed_src = lookup_src($feed, $name);
$this_feed_src or do {
return install_src($this_feed_src, $name, $force);
};
return install_package($feed, $name, $force);
}
sub refresh_config { sub refresh_config {
my $default = shift; my $default = shift;
@ -591,18 +634,15 @@ sub install {
if (!defined($opts{p}) or $opts{p} eq $f->[1]) { if (!defined($opts{p}) or $opts{p} eq $f->[1]) {
printf "Installing all packages from feed %s.\n", $f->[1]; printf "Installing all packages from feed %s.\n", $f->[1];
get_feed($f->[1]); get_feed($f->[1]);
foreach my $name (sort { lc($a) cmp lc($b) } keys %$feed_package) { foreach my $name (sort { lc($a) cmp lc($b) } keys %$feed_src) {
my $p = $feed_package->{$name}; install_src($feed, $name, exists($opts{f})) == 0 or $ret = 1;
if( $p->{name} ) {
install_package($feed, $p->{name}, exists($opts{f})) == 0 or $ret = 1;
get_feed($f->[1]); get_feed($f->[1]);
} }
} }
} }
}
} else { } else {
while ($name = shift @ARGV) { while ($name = shift @ARGV) {
install_package($feed, $name, exists($opts{f})) == 0 or $ret = 1; install_target_or_package($feed, $name, exists($opts{f})) == 0 or $ret = 1;
} }
} }

View file

@ -228,6 +228,7 @@ sub parse_package_metadata($) {
$pkg->{title} = ""; $pkg->{title} = "";
$pkg->{depends} = []; $pkg->{depends} = [];
$pkg->{mdepends} = []; $pkg->{mdepends} = [];
$pkg->{provides} = [$1];
$pkg->{tristate} = 1; $pkg->{tristate} = 1;
$pkg->{override} = $override; $pkg->{override} = $override;
$package{$1} = $pkg; $package{$1} = $pkg;
@ -268,6 +269,7 @@ sub parse_package_metadata($) {
/^Default: \s*(.+)\s*$/ and $pkg->{default} = $1; /^Default: \s*(.+)\s*$/ and $pkg->{default} = $1;
/^Provides: \s*(.+)\s*$/ and do { /^Provides: \s*(.+)\s*$/ and do {
my @vpkg = split /\s+/, $1; my @vpkg = split /\s+/, $1;
@{$pkg->{provides}} = ($pkg->{name}, @vpkg);
foreach my $vpkg (@vpkg) { foreach my $vpkg (@vpkg) {
$vpackage{$vpkg} or $vpackage{$vpkg} = []; $vpackage{$vpkg} or $vpackage{$vpkg} = [];
push @{$vpackage{$vpkg}}, $pkg; push @{$vpackage{$vpkg}}, $pkg;