package Magus::Index; # # Copyright (c) 2007,2008 Chris Reinhardt. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions of source code must retain the above copyright notice # this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # MAINTAINER= ctriv@MidnightBSD.org # use strict; use warnings; use Mport::Utils qw(make_var recurse_ports); use YAML qw(Load); sub sync { my ($class, $root, $run) = @_; my $arch = $run->arch; my $osrel = $run->osversion; my $osversion; my %visited; if ($osrel eq "4.1") { $osversion = 401000; } elsif ($osrel eq "4.0") { $osversion = 400002; } elsif ($osrel eq "3.2") { $osversion = 302001; } elsif ($osrel eq "3.1") { $osversion = 301000; } elsif ($osrel eq "3.0") { $osversion = 300005; } elsif ($osrel eq "2.2") { $osversion = 202000; } elsif ($osrel eq "2.1") { $osversion = 201001; } elsif ($osrel eq "2.0") { $osversion = 200000; } elsif ($osrel eq "1.3") { $osversion = 103000; } elsif ($osrel eq "1.2") { $osversion = 102000; } elsif ($osrel eq "1.1") { $osversion = 101000; } elsif ($osrel eq "1.0") { $osversion = 100000; } else { $osversion = 500000; } $root ||= "$Magus::Config{MasterDataDir}/$Magus::Config{MportsVcsDir}"; local $| = 1; my %depends; recurse_ports { print @_, "... "; my $yaml = `__MAKE_CONF=/dev/null SSL_DEFAULT=base INDEXING=1 ARCH=$arch OSREL=$osrel OSVERSION=$osversion PORTSDIR=$root BATCH=1 PACKAGE_BUILDING=1 MAGUS=1 make describe-yaml`; my %dump; eval { %dump = %{ Load($yaml) }; }; if ($@) { warn "Unable to parse yaml for $_[0]: $@\n"; return; } my $primaryFlavor = $dump{flavor}; my $defaultFlavor = 0; my $port = Magus::Port->insert({ run => $run, name => $dump{name}, version => $dump{version}, description => $dump{description}, license => join(" ", @{$dump{'license'}}), restricted => $dump{restricted}, www => $dump{www}, pkgname => $dump{pkgname}, flavor => $dump{flavor}, cpe => $dump{cpe}, default_flavor => 1, }); for (@{$dump{'master_sites'}}) { Magus::MasterSite->insert({ port => $port->id, url => $_ }); } for (@{$dump{'distfiles'}}) { Magus::Distfile->insert({ port => $port->id, filename => $_ }); } for (@{$dump{'restricted_distfiles'}}) { Magus::RestrictedDistfile->insert({ port => $port->id, filename => $_ }); } for (@{$dump{'license_perms'}}) { Magus::PortLicensePerms->insert({ port => $port->id, perm => $_ }); } $depends{$port->id} = []; while (my ($type, $deps) = each %{$dump{'depends'}}) { foreach my $dep (@$deps) { my %dependsItem; my @deporigin = split /@/, $dep; $dependsItem{name} = $deporigin[0]; $dependsItem{type} = $type; my $len = @deporigin; if ($len > 1) { $dependsItem{flavor} = $deporigin[1]; } else { $dependsItem{flavor} = ""; } push(@{$depends{$port->id}}, \%dependsItem); } } $class->sync_categories(\%dump, $port, $arch); $class->mark_ignored(\%dump, $port); foreach my $flav (@{$dump{'flavors'}}) { print "Flavor: $flav\n"; if ($flav eq $primaryFlavor) { print "Default flavor $flav processed.\n"; next; } $yaml = `__MAKE_CONF=/dev/null SSL_DEFAULT=base INDEXING=1 ARCH=$arch OSREL=$osrel OSVERSION=$osversion PORTSDIR=$root BATCH=1 PACKAGE_BUILDING=1 MAGUS=1 make describe-yaml FLAVOR=$flav`; eval { %dump = %{ Load($yaml) }; }; if ($@) { warn "Unable to parse yaml for $_[0]: $@\n"; next; } $port = Magus::Port->insert({ run => $run, name => $dump{name}, version => $dump{version}, description => $dump{description}, license => join(" ", @{$dump{'license'}}), restricted => $dump{restricted}, www => $dump{www}, pkgname => $dump{pkgname}, flavor => $dump{flavor}, default_flavor => 0, }); for (@{$dump{'master_sites'}}) { Magus::MasterSite->insert({ port => $port->id, url => $_ }); } for (@{$dump{'distfiles'}}) { Magus::Distfile->insert({ port => $port->id, filename => $_ }); } for (@{$dump{'restricted_distfiles'}}) { Magus::RestrictedDistfile->insert({ port => $port->id, filename => $_ }); } $depends{$port->id} = []; while (my ($type, $deps) = each %{$dump{'depends'}}) { foreach my $dep (@$deps) { my %dependsItem; my @deporigin = split /@/, $dep; $dependsItem{name} = $deporigin[0]; $dependsItem{type} = $type; my $len = @deporigin; if ($len > 1) { $dependsItem{flavor} = $deporigin[1]; } else { $dependsItem{flavor} = ""; } push(@{$depends{$port->id}}, \%dependsItem); } } $class->sync_categories(\%dump, $port, $arch); $class->mark_ignored(\%dump, $port); } print "done.\n"; } root => $root, nochdir => sub { warn "ERROR: no such port $_[0]\n" }; print "Building depends list... \n"; PORT: while (my ($id, $depends) = each %depends) { my $port = Magus::Port->retrieve($id) || die "Got an invalid port in the depends list! ($id)"; my %seen_depends; foreach my $item (@$depends) { my $fl = $item->{flavor}; if (length $fl < 1) { $fl = ""; } my $depend = Magus::Port->retrieve(run => $run, name => $item->{name}, flavor => $fl); if (!defined($depend) && length $fl) { warn "\tMissing flavor for $port: $item->{name} with flavor: $fl. Trying no flavor.\n"; $depend = Magus::Port->retrieve(run => $run, name => $item->{name}, flavor => ""); } if (!defined($depend)) { warn "\tMissing flavor for $port: $item->{name} , falling back to default flavor.\n"; $depend = Magus::Port->retrieve(run => $run, name => $item->{name}, default_flavor => 1); } if (!defined($depend)) { warn "\tMissing depend for $port: $item->{name}\n"; $port->set_result_fail(qq(depend "$item->{name}" with flavor: "$fl" does not exist.)); next PORT; } my $depend_key = join(":", $depend->id, $item->{type}); if ($seen_depends{$depend_key}) { warn "\tBad depends for $port: duplicate $item->{type} dependency " . "$item->{name}" . (length $fl ? "\@$fl" : "") . " resolves to " . $depend->name . " with flavor \"" . ($depend->flavor // "") . "\". Skipping duplicate.\n"; next; } $seen_depends{$depend_key} = 1; $port->add_to_depends({ dependency => $depend, type => $item->{type} }); } } print "Building MOVED list... \n"; moved_list($run, $root); print "done.\n"; } sub moved_list { my ($run, $root) = @_; my $fh; my %result; open($fh, $root . "/MOVED") || die "failed to read MOVED file: $!"; while (my $line = <$fh>) { chomp $line; # skip comments and blank lines next if $line =~ /^\#/ || $line =~ /^\s*$/ || $line =~ /^\+/; #split each line into array my ($port, $moved_to, $date, $why) = split(/\|/, $line); next unless defined $port; print "Adding MOVED entry: $port $moved_to $date $why \n"; if (defined($date) && length($date)) { $port = Magus::Moved->insert({ run => $run, port => $port, moved_to => $moved_to, date => $date, why => $why, }); } else { $port = Magus::Moved->insert({ run => $run, port => $port, moved_to => $moved_to, date => undef, why => $why, }); } } } sub sync_categories { my ($class, $dump, $port, $arch) = @_; Magus::PortCategory->search(port => $port)->delete_all; for (@{$dump->{'categories'}}) { my $cat = Magus::Category->find_or_create({ category => $_}); $port->add_to_categories({ category => $cat }); } } sub mark_ignored { my ($class, $dump, $port) = @_; my $ignore = $dump->{ignore} // ""; if ($class->ignore_is_metaport($ignore)) { print "\n\tMetaport. Marking as internal."; $port->set_result_internal($ignore); } elsif ($dump->{is_interactive}) { print "\n\tIGNORE set. Marking as skipped."; $port->set_result_skip("Port is marked as interactive."); } elsif (length $ignore) { print "\n\tIGNORE set. Marking as skipped."; $port->set_result_skip($ignore); } } sub ignore_is_metaport { my ($class, $ignore) = @_; return defined($ignore) && $ignore =~ /\bis a meta[- ]?port; there is nothing to build\b/; } 1; __END__