1package Magus::Index; 2# 3# Copyright (c) 2007,2008 Chris Reinhardt. All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions are 7# met: 8# 9# 1. Redistributions of source code must retain the above copyright notice 10# this list of conditions and the following disclaimer. 11# 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 17# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 18# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26# 27 28# 29# MAINTAINER= ctriv@MidnightBSD.org 30# 31 32use strict; 33use warnings; 34 35use Mport::Utils qw(make_var recurse_ports); 36 37use YAML qw(Load); 38 39sub sync { 40 my ($class, $root, $run) = @_; 41 my $arch = $run->arch; 42 my $osrel = $run->osversion; 43 my $osversion; 44 my %visited; 45 46 if ($osrel eq "4.1") { 47 $osversion = 401000; 48 } elsif ($osrel eq "4.0") { 49 $osversion = 400002; 50 } elsif ($osrel eq "3.2") { 51 $osversion = 302001; 52 } elsif ($osrel eq "3.1") { 53 $osversion = 301000; 54 } elsif ($osrel eq "3.0") { 55 $osversion = 300005; 56 } elsif ($osrel eq "2.2") { 57 $osversion = 202000; 58 } elsif ($osrel eq "2.1") { 59 $osversion = 201001; 60 } elsif ($osrel eq "2.0") { 61 $osversion = 200000; 62 } elsif ($osrel eq "1.3") { 63 $osversion = 103000; 64 } elsif ($osrel eq "1.2") { 65 $osversion = 102000; 66 } elsif ($osrel eq "1.1") { 67 $osversion = 101000; 68 } elsif ($osrel eq "1.0") { 69 $osversion = 100000; 70 } else { 71 $osversion = 500000; 72 } 73 74 $root ||= "$Magus::Config{MasterDataDir}/$Magus::Config{MportsVcsDir}"; 75 76 local $| = 1; 77 78 my %depends; 79 80 recurse_ports { 81 print @_, "... "; 82 83 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`; 84 my %dump; 85 86 eval { 87 %dump = %{ Load($yaml) }; 88 }; 89 90 if ($@) { 91 warn "Unable to parse yaml for $_[0]: $@\n"; 92 return; 93 } 94 95 my $primaryFlavor = $dump{flavor}; 96 my $defaultFlavor = 0; 97 98 my $port = Magus::Port->insert({ 99 run => $run, 100 name => $dump{name}, 101 version => $dump{version}, 102 description => $dump{description}, 103 license => join(" ", @{$dump{'license'}}), 104 restricted => $dump{restricted}, 105 www => $dump{www}, 106 pkgname => $dump{pkgname}, 107 flavor => $dump{flavor}, 108 cpe => $dump{cpe}, 109 default_flavor => 1, 110 }); 111 112 for (@{$dump{'master_sites'}}) { 113 Magus::MasterSite->insert({ 114 port => $port->id, 115 url => $_ 116 }); 117 } 118 119 for (@{$dump{'distfiles'}}) { 120 Magus::Distfile->insert({ 121 port => $port->id, 122 filename => $_ 123 }); 124 } 125 126 for (@{$dump{'restricted_distfiles'}}) { 127 Magus::RestrictedDistfile->insert({ 128 port => $port->id, 129 filename => $_ 130 }); 131 } 132 133 134 for (@{$dump{'license_perms'}}) { 135 Magus::PortLicensePerms->insert({ 136 port => $port->id, 137 perm => $_ 138 }); 139 } 140 141 $depends{$port->id} = []; 142 while (my ($type, $deps) = each %{$dump{'depends'}}) { 143 foreach my $dep (@$deps) { 144 my %dependsItem; 145 my @deporigin = split /@/, $dep; 146 $dependsItem{name} = $deporigin[0]; 147 $dependsItem{type} = $type; 148 my $len = @deporigin; 149 if ($len > 1) { 150 $dependsItem{flavor} = $deporigin[1]; 151 } else { 152 $dependsItem{flavor} = ""; 153 } 154 push(@{$depends{$port->id}}, \%dependsItem); 155 } 156 } 157 158 $class->sync_categories(\%dump, $port, $arch); 159 160 $class->mark_ignored(\%dump, $port); 161 162 foreach my $flav (@{$dump{'flavors'}}) { 163 print "Flavor: $flav\n"; 164 if ($flav eq $primaryFlavor) { 165 print "Default flavor $flav processed.\n"; 166 next; 167 } 168 $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`; 169 eval { 170 %dump = %{ Load($yaml) }; 171 }; 172 if ($@) { 173 warn "Unable to parse yaml for $_[0]: $@\n"; 174 next; 175 } 176 177 $port = Magus::Port->insert({ 178 run => $run, 179 name => $dump{name}, 180 version => $dump{version}, 181 description => $dump{description}, 182 license => join(" ", @{$dump{'license'}}), 183 restricted => $dump{restricted}, 184 www => $dump{www}, 185 pkgname => $dump{pkgname}, 186 flavor => $dump{flavor}, 187 default_flavor => 0, 188 }); 189 190 for (@{$dump{'master_sites'}}) { 191 Magus::MasterSite->insert({ 192 port => $port->id, 193 url => $_ 194 }); 195 } 196 197 for (@{$dump{'distfiles'}}) { 198 Magus::Distfile->insert({ 199 port => $port->id, 200 filename => $_ 201 }); 202 } 203 204 for (@{$dump{'restricted_distfiles'}}) { 205 Magus::RestrictedDistfile->insert({ 206 port => $port->id, 207 filename => $_ 208 }); 209 } 210 211 $depends{$port->id} = []; 212 while (my ($type, $deps) = each %{$dump{'depends'}}) { 213 foreach my $dep (@$deps) { 214 my %dependsItem; 215 my @deporigin = split /@/, $dep; 216 $dependsItem{name} = $deporigin[0]; 217 $dependsItem{type} = $type; 218 my $len = @deporigin; 219 if ($len > 1) { 220 $dependsItem{flavor} = $deporigin[1]; 221 } else { 222 $dependsItem{flavor} = ""; 223 } 224 push(@{$depends{$port->id}}, \%dependsItem); 225 } 226 } 227 228 $class->sync_categories(\%dump, $port, $arch); 229 230 $class->mark_ignored(\%dump, $port); 231 } 232 233 print "done.\n"; 234 } root => $root, nochdir => sub { warn "ERROR: no such port $_[0]\n" }; 235 236 print "Building depends list... \n"; 237 238 PORT: while (my ($id, $depends) = each %depends) { 239 my $port = Magus::Port->retrieve($id) || die "Got an invalid port in the depends list! ($id)"; 240 my %seen_depends; 241 242 foreach my $item (@$depends) { 243 my $fl = $item->{flavor}; 244 if (length $fl < 1) { 245 $fl = ""; 246 } 247 my $depend = Magus::Port->retrieve(run => $run, name => $item->{name}, flavor => $fl); 248 249 if (!defined($depend) && length $fl) { 250 warn "\tMissing flavor for $port: $item->{name} with flavor: $fl. Trying no flavor.\n"; 251 $depend = Magus::Port->retrieve(run => $run, name => $item->{name}, flavor => ""); 252 } 253 254 if (!defined($depend)) { 255 warn "\tMissing flavor for $port: $item->{name} , falling back to default flavor.\n"; 256 $depend = Magus::Port->retrieve(run => $run, name => $item->{name}, default_flavor => 1); 257 } 258 259 if (!defined($depend)) { 260 warn "\tMissing depend for $port: $item->{name}\n"; 261 $port->set_result_fail(qq(depend "$item->{name}" with flavor: "$fl" does not exist.)); 262 next PORT; 263 } 264 265 my $depend_key = join(":", $depend->id, $item->{type}); 266 if ($seen_depends{$depend_key}) { 267 warn "\tBad depends for $port: duplicate $item->{type} dependency " 268 . "$item->{name}" . (length $fl ? "\@$fl" : "") 269 . " resolves to " . $depend->name . " with flavor \"" 270 . ($depend->flavor // "") . "\". Skipping duplicate.\n"; 271 next; 272 } 273 $seen_depends{$depend_key} = 1; 274 275 $port->add_to_depends({ 276 dependency => $depend, 277 type => $item->{type} 278 }); 279 } 280 } 281 282 print "Building MOVED list... \n"; 283 moved_list($run, $root); 284 285 print "done.\n"; 286} 287 288sub moved_list { 289 my ($run, $root) = @_; 290 291 my $fh; 292 my %result; 293 open($fh, $root . "/MOVED") || die "failed to read MOVED file: $!"; 294 while (my $line = <$fh>) { 295 chomp $line; 296 # skip comments and blank lines 297 next if $line =~ /^\#/ || $line =~ /^\s*$/ || $line =~ /^\+/; 298 #split each line into array 299 my ($port, $moved_to, $date, $why) = split(/\|/, $line); 300 301 next unless defined $port; 302 303 print "Adding MOVED entry: $port $moved_to $date $why \n"; 304 305 if (defined($date) && length($date)) { 306 $port = Magus::Moved->insert({ 307 run => $run, 308 port => $port, 309 moved_to => $moved_to, 310 date => $date, 311 why => $why, 312 }); 313 } else { 314 $port = Magus::Moved->insert({ 315 run => $run, 316 port => $port, 317 moved_to => $moved_to, 318 date => undef, 319 why => $why, 320 }); 321 } 322 } 323} 324 325 326sub sync_categories { 327 my ($class, $dump, $port, $arch) = @_; 328 329 Magus::PortCategory->search(port => $port)->delete_all; 330 331 for (@{$dump->{'categories'}}) { 332 my $cat = Magus::Category->find_or_create({ category => $_}); 333 $port->add_to_categories({ category => $cat }); 334 } 335} 336 337sub mark_ignored { 338 my ($class, $dump, $port) = @_; 339 my $ignore = $dump->{ignore} // ""; 340 341 if ($class->ignore_is_metaport($ignore)) { 342 print "\n\tMetaport. Marking as internal."; 343 $port->set_result_internal($ignore); 344 } elsif ($dump->{is_interactive}) { 345 print "\n\tIGNORE set. Marking as skipped."; 346 $port->set_result_skip("Port is marked as interactive."); 347 } elsif (length $ignore) { 348 print "\n\tIGNORE set. Marking as skipped."; 349 $port->set_result_skip($ignore); 350 } 351} 352 353sub ignore_is_metaport { 354 my ($class, $ignore) = @_; 355 356 return defined($ignore) && $ignore =~ /\bis a meta[- ]?port; there is nothing to build\b/; 357} 358 3591; 360__END__ 361 362