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 %build_packages;
my %installed;
my %installed_pkg;
my %installed_targets;
my %feed_cache;
my $feed_package = {};
my $feed_src = {};
my $feed_target = {};
my $feed_vpackage = {};
sub parse_config() {
my $line = 0;
@ -223,20 +225,21 @@ sub get_feed($) {
parse_package_metadata($file) or return;
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_src = $feed_cache{$feed}->[1];
$feed_target = $feed_cache{$feed}->[2];
return $feed_cache{$feed}->[0];
$feed_vpackage = $feed_cache{$feed}->[3];
}
sub get_installed() {
system("$mk -s prepare-tmpinfo OPENWRT_BUILD=");
clear_packages();
parse_package_metadata("./tmp/.packageinfo");
%installed = %package;
%installed_pkg = %vpackage;
%installed = %srcpackage;
%installed_targets = get_targets("./tmp/.targetinfo");
}
@ -371,16 +374,12 @@ sub list {
return 0;
}
# TODO: do_install_package etc. should deal with source packages rather
# than binary packages
sub do_install_package($$) {
sub do_install_src($$) {
my $feed = shift;
my $pkg = shift;
my $src = shift;
my $path;
$pkg->{src} and $path = $pkg->{src}{makefile};
if($path) {
my $path = $src->{makefile};
if ($path) {
$path =~ s/\/Makefile$//;
-d "./package/feeds" or mkdir "./package/feeds";
@ -418,6 +417,18 @@ sub do_install_target($) {
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($$) {
my $feed = shift;
my $package = shift;
@ -425,7 +436,7 @@ sub lookup_package($$) {
foreach my $feed ($feed, @feeds) {
next unless $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;
}
@ -442,9 +453,9 @@ sub lookup_target($$) {
return;
}
sub is_core_package($) {
my $package = shift;
foreach my $file ("tmp/info/.packageinfo-$package", glob("tmp/info/.packageinfo-*_$package")) {
sub is_core_src($) {
my $src = shift;
foreach my $file ("tmp/info/.packageinfo-$src", glob("tmp/info/.packageinfo-*_$src")) {
next unless index($file, "tmp/info/.packageinfo-feeds_");
return 1 if -s $file;
}
@ -455,6 +466,8 @@ sub install_target {
my $feed = shift;
my $name = shift;
$installed_targets{$name} and return 0;
$feed = $feed_cache{$feed->[1]}->[2];
$feed or return 0;
@ -465,85 +478,115 @@ sub install_target {
return do_install_target($target);
}
sub install_package {
sub install_src {
my $feed = shift;
my $name = shift;
my $force = shift;
my $ret = 0;
my $this_feed_target = lookup_target($feed, $name);
$this_feed_target and do {
$installed_targets{$name} and return 0;
install_target($this_feed_target, $name);
return 0;
};
$feed = lookup_package($feed, $name);
$feed or do {
$feed = lookup_src($feed, $name);
unless ($feed) {
$installed{$name} and return 0;
# TODO: check if it's already installed within ./package directory
$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";
$feed_src->{$name} or warn "WARNING: No feed for source package '$name' found\n";
return 0;
};
}
# switch to the metadata for the selected feed
my $cur = get_feed($feed->[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;
get_feed($feed->[1]);
my $src = $feed_src->{$name} or return 1;
# 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
$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:
# - override is allowed by command line (-f)
# - a package with the same src exists in the core packages list
# - the package previously installed is not from a feed
my $override = 1 if ($force and is_core_package($src) and !$installed{$name}->{feed});
$installed{$name} = 1;
foreach my $pkg (@{$src->{packages}}) {
foreach my $vpkg (@{$pkg->{provides}}) {
$installed_pkg{$vpkg} = 1;
}
}
# check previously installed packages
$installed{$name} and !$override and return 0;
$installed{$src} = 1;
if ($override) {
warn "Overriding core package '$name' with version from $feed->[1]\n";
} else {
warn "Installing package '$name' from $feed->[1]\n";
}
defined($override) and $override == 1
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 {
do_install_src($feed, $src) == 0 or do {
warn "failed.\n";
return 1;
};
# install all dependencies referenced from the source package
foreach my $dep (
@{$feed_src->{$src}{builddepends}},
@{$feed_src->{$src}{"builddepends/host"}},
map { @{$_->{depends}} } @{$feed_src->{$src}{packages}}
@{$src->{builddepends}},
@{$src->{'builddepends/host'}},
) {
# TODO: handle virtual packages and PROVIDES
next if $dep =~ /@/;
$dep =~ s/^\+//;
$dep =~ s/^.+://;
$dep =~ s/\/.+$//;
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;
}
}
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 {
my $default = shift;
@ -591,18 +634,15 @@ sub install {
if (!defined($opts{p}) or $opts{p} eq $f->[1]) {
printf "Installing all packages from feed %s.\n", $f->[1];
get_feed($f->[1]);
foreach my $name (sort { lc($a) cmp lc($b) } keys %$feed_package) {
my $p = $feed_package->{$name};
if( $p->{name} ) {
install_package($feed, $p->{name}, exists($opts{f})) == 0 or $ret = 1;
foreach my $name (sort { lc($a) cmp lc($b) } keys %$feed_src) {
install_src($feed, $name, exists($opts{f})) == 0 or $ret = 1;
get_feed($f->[1]);
}
}
}
}
} else {
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->{depends} = [];
$pkg->{mdepends} = [];
$pkg->{provides} = [$1];
$pkg->{tristate} = 1;
$pkg->{override} = $override;
$package{$1} = $pkg;
@ -268,6 +269,7 @@ sub parse_package_metadata($) {
/^Default: \s*(.+)\s*$/ and $pkg->{default} = $1;
/^Provides: \s*(.+)\s*$/ and do {
my @vpkg = split /\s+/, $1;
@{$pkg->{provides}} = ($pkg->{name}, @vpkg);
foreach my $vpkg (@vpkg) {
$vpackage{$vpkg} or $vpackage{$vpkg} = [];
push @{$vpackage{$vpkg}}, $pkg;