Update of /cvsroot/fink/scripts/buildfink
In directory sc8-pr-cvs5.sourceforge.net:/tmp/cvs-serv26835

Modified Files:
        buildfink 
Log Message:
Here's a shot at support for building only a subset of packages...

Index: buildfink
===================================================================
RCS file: /cvsroot/fink/scripts/buildfink/buildfink,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -d -r1.28 -r1.29
--- buildfink   8 Aug 2006 19:25:28 -0000       1.28
+++ buildfink   19 Oct 2006 20:48:51 -0000      1.29
@@ -1,6 +1,6 @@
 #!/usr/bin/perl
 
-#Copyright (c) 2005 Apple Computer, Inc.  All Rights Reserved.
+#Copyright (c) 2005-2006 Apple Computer, Inc.  All Rights Reserved.
 #
 #This program is free software; you can redistribute it and/or modify
 #it under the terms of the GNU General Public License as published by
@@ -24,7 +24,7 @@
 
 =head1 USAGE
 
-       buildfink [-n] [--infofilter SCRIPT] [--patchdir DIR] [--skip PACKAGE] 
[--skip PACKAGE] [--validate] [--build-as-nobody] [--max-log-size [P:]N] 
[--max-build-time [P:]T] [FINKDIR OUTDIR
+       buildfink [-n] [--infofilter SCRIPT] [--patchdir DIR] [--skip PACKAGE] 
[--skip PACKAGE] [--validate] [--build-as-nobody] [--max-log-size [P:]N] 
[--max-build-time [P:]T] [--packages PKGLIST] [--rebuild-dependents] [--dirty] 
[FINKDIR OUTDIR]
        buildfink [-r CHECKPOINT]
 
 C<buildfink> builds every package in Fink, taking care of things like avoiding 
repeated building
@@ -71,6 +71,15 @@
 C<--max-build-time openoffice.org:24h> would specify a 24-hour limit for 
 openoffice.org.
 
+Normally, buildfink will attempt to build every package it knows about.  To
+build only a subset of packages, give C<--packages PKGLIST>, where C<PKGLIST>
+is a comma-separated list of packages.  Packages necessary to satisfy 
+dependencies of these will be installed or built as necessary.  If operating in
+this mode, you may also want the C<--dirty> option to avoid purging all
+non-essential packages before performing each build.  The
+C<--rebuild-dependents> option will add any packages which depend on anything
+in C<PKGLIST> .
+
 =head2 CHECKPOINTS
 
 Sometimes there will be system issues partway through a build.  For instance, 
a recalcitrant
@@ -93,7 +102,7 @@
 use lib "$Bin";
 use FinkLib;
 
-our($Bin, $FinkConfig, $FinkDir, $rundir, $dryrun, $infofilter, $patchdir, 
@skiplist, $checkpoint, $DoValidate, $BuildNobody);
+our($Bin, $FinkConfig, $FinkDir, $rundir, $dryrun, $infofilter, $patchdir, 
@skiplist, $checkpoint, $DoValidate, $BuildNobody, $Dirty, $RebuildDeps, 
$BuildAll);
 our $VERSION = '$Revision$';
 
 our $max_build_time = 60*60*4;
@@ -139,6 +148,16 @@
        }
 }
 
+# Keys will be package names.  Values will be:
+my %pkglist;
+use constant PKGSTATUS_INSTALLED => 3;
+use constant PKGSTATUS_REBUILD => 2;
+use constant PKGSTATUS_INSTALL => 1;
+use constant PKGSTATUS_PROCESSING => 0;
+use constant PKGSTATUS_FAILED => -1;
+use constant PKGSTATUS_SKIP => -2;
+
+$BuildAll = 1;
 my $opts_ok = GetOptions(
        "n" => \$dryrun,
        "infofilter=s" => \$infofilter,
@@ -146,6 +165,12 @@
        "skip=s" => [EMAIL PROTECTED],
        "r=s" => \$checkpoint,
        "validate" => \$DoValidate,
+       "dirty" => \$Dirty,
+       "rebuild-dependents" => \$RebuildDeps,
+       "packages=s" => sub {
+               %pkglist = map { $_ => PKGSTATUS_REBUILD } 
filterSplitoffs(split(/,/, $_[1]));
+               $BuildAll = 0;
+       },
        "build-as-nobody:s" => \$BuildNobody,
        "max-build-time=s" => \&limit_arg,
        "max-log-size=s" => \&limit_arg
@@ -191,44 +216,56 @@
        die "See 'perldoc $0' for more information.\n";
 }
 
-
 if($checkpoint) {
        restoreCheckpoint($checkpoint);
        exit();
 }
 
-
 restoreSystem();
 prepSystem();
-FinkLib::purgeNonEssential();
+FinkLib::purgeNonEssential() unless $Dirty;
 FinkLib::readPackages();
 removeBuildLocks();
-my(@pkglist) = Fink::Package->list_packages();
+%pkglist = map { $_ => PKGSTATUS_REBUILD } 
filterSplitoffs(Fink::Package->list_packages()) if $BuildAll;
+foreach (filterSplitoffs(@skiplist)) {
+       $pkglist{$_} = PKGSTATUS_SKIP;
+       logPackageFail($_, "Package is on the skip list.");
+}
 
-if(!$dryrun) {
-       # Then copy the .info files to our private repository and patch them if 
necessary.
-       patchPackages(@pkglist);
+# Don't try to install uninstalled virtual packages.
+# We can't use them to satisfy dependencies and we can't build them...
+my $vpinfo = Fink::VirtPackage->list();
+while(my($pkgname, $hash) = each(%$vpinfo)) {
+       if($hash->{status} !~ / installed$/) {
+               $pkglist{$pkgname} = PKGSTATUS_SKIP;
+               logPackageFail($_, "Package is an uninstalled virtual 
package.");
+       } else {
+               $pkglist{$pkgname} = PKGSTATUS_INSTALLED;
+       }
+}
 
-       # Only let Fink see our modified packages
-       injectPackages();
+
+if(!$BuildAll and $RebuildDeps) {
+       foreach my $pkg (keys %pkglist) {
+               my @deps = getDependsRecursive($pkg);
+               foreach my $dep (@deps) {
+                       $pkglist{$dep} = PKGSTATUS_REBUILD;
+               }
+       }
 }
 
-# Now order the list of packages in dependency order, so that all of X's
-# dependencies come before X.  Filter out all of the split-offs, so we only
-# build root packages, and then remove everything on the skip list and anything
-# which depends on anything on the skip list.
-my(%deps) = getAllDepends([EMAIL PROTECTED]);
-my(@orderedPkgs) = filterSplitOffs(orderByDepends([EMAIL PROTECTED], \%deps));
+if(!$dryrun) {
+       # Then copy the .info files to our private repository and patch them if 
necessary.
+       patchPackages(keys %pkglist);
 
-if($dryrun) {
-       print join("\n", @orderedPkgs), "\n";
-       exit;
+       # Only let Fink see our modified packages
+       injectPackages() if $BuildAll;
 }
 
 # Now do the run
-initCheckpoint([EMAIL PROTECTED], \%deps, {});
-FinkLib::installEssentials();
-buildAll([EMAIL PROTECTED], [EMAIL PROTECTED], \%deps, {});
+initCheckpoint(\%pkglist) unless $dryrun;
+FinkLib::installEssentials() unless $dryrun;
+buildAll(\%pkglist);
 doLog("Done building");
 
 restoreSystem();
@@ -486,157 +523,233 @@
        }
 }
 
-# Build all packages, skipping any with failed deps
-# pkglist is a list of package names to build in order.
-# skiplist is a list of package names to never build.
-sub buildAll {
-       my($pkgs, $skiplist, $deps, $failures) = @_;
-       my %skiphash = map {$_ => 1} @$skiplist;
+sub setPackageStatus {
+       my($pkglist, $pkg, $status) = @_;
+       $pkglist->{$pkg} = $status;
+       updaetCheckpoint($pkg => $status);
+}
 
-       # First, we set all uninstalled virtual packages as 'failed'.
-       # We can't use them to satisfy dependencies and we can't build them...
-       my $vpinfo = Fink::VirtPackage->list();
-       while(my($pkgname, $hash) = each(%$vpinfo)) {
-               $failures->{$pkgname} = 1 if $hash->{status} !~ / installed$/;
-       }
+sub setPackageFail {
+       my($pkglist, $pkg, $reason) = @_;
+       logPackageFail($pkg, $reason);
+       setPackageStatus($pkglist, $pkg, PKGSTATUS_FAILED);
+}
 
-       # Also set packages on the skiplist to failed
-       $failures->{$_} = 1 foreach keys %skiphash;
+# Try to build an individual package.
+sub recurseOnDepends {
+       my($pkglist, $pkg, $install, $finkfiles) = @_;
+       $pkglist->{$pkg} = PKGSTATUS_PROCESSING;
+       doLog("Trying to satisfy $pkg");
 
-       my %finkfiles;
-       if($DoValidate) {
-               Fink::Config::set_options({"Pedantic" => 1});
+       my $obj;
+       eval {
+               $obj = Fink::PkgVersion->match_package($pkg);
+       };
+       if($@ or !$obj) {
+               setPackageFail($pkglist, $pkg, "Couldn't get package object: 
$@");
+               return;
+       }
 
-               # One of the validation steps is to identify files left in /sw
-               # by the build process.
-               find({no_chdir => 1, wanted => sub {
-                       $finkfiles{$File::Find::name} = 1;
-               }}, $FinkDir);
+       if($obj->is_type('dummy')) {
+               doLog("$pkg is a dummy.");
+               setPackageStatus($pkglist, $pkg, PKGSTATUS_INSTALLED);
+               return 1;
        }
 
-       my @newfails;
-       PACKAGE: foreach my $pkg(@$pkgs) {
-               doLog("Thinking about building $pkg");
+       # Build deps, and maybe run deps
+       my @deps;
+       eval {
+               @deps = $obj->resolve_depends(2, "depends");
+               push @deps, $obj->resolve_depends(0, "depends") if $install;
+       };
+       if($@) {
+               setPackageFail($pkglist, $pkg, "Couldn't get depends: $@");
+               return;
+       }
 
-               my $skipcause = "";
-               if($skiphash{$pkg}) {
-                       $skipcause = "$pkg is on the skip list";
-               } else {
-                       my $dep = findFailedDep($pkg, $deps, $failures);
-                       $skipcause = "Dependency $dep failed to build" if $dep;
+       # @deps is in conjunctive normal form.  That is, it is a list like:
+       #       {{A ^ B ^ C} v {D ^ E} v {F}}
+       # In other words, a list of alternatives, and each alternative is a
+       # series of packages which must all be satisfied.
+       my $satisfied = 0;
+       my @faildep;
+       CHECKSAT: foreach my $alternative (@deps) {
+               foreach my $altdep (@$alternative) {
+                       my $depstat = $pkglist->{$altdep};
+                       $depstat = PKGSTATUS_INSTALL unless defined($depstat);
+                       if($depstat == PKGSTATUS_FAILED or $depstat == 
PKGSTATUS_PROCESSING) {
+                               push @faildep, $altdep;
+                               next CHECKSAT;
+                       }
                }
 
-               if($skipcause) {
-                       logPackageFail($pkg, $skipcause);
-                       next;
+               # This alternative is satisfiable
+               foreach my $altdep (@$alternative) {
+                       $pkglist->{$altdep} = PKGSTATUS_INSTALL if 
!defined($pkglist->{$altdep});
+                       next if $pkglist->{$altdep} == PKGSTATUS_INSTALLED;
+                       recurseOnDepends($pkglist, filterSplitoffs($altdep), 1, 
$finkfiles);
+                       if($pkglist->{$altdep} == PKGSTATUS_FAILED) {
+                               push @faildep, $altdep;
+                               next CHECKSAT;
+                       }
                }
 
-               my $obj;
-               eval {
-                       $obj = Fink::PkgVersion->match_package($pkg);
-               };
-               if($@ or !$obj) {
-                       doLog("Couldn't get object for $pkg: $@");
-                       next;
-               }
+               $satisfied = 1;
+               last;
+       }
 
-               next if $obj->is_type('dummy');
+       if(!$satisfied) {
+               logPackageFail($pkg, "Can't figure out how to build.  
Unsatisfied dependencies: " . join(" ", sort @faildep));
+               return;
+       }
 
-               if($DoValidate) {
-                       open(VAL, ">>", "$rundir/validate/$pkg") or die 
"Couldn't open validation log for $pkg: $!\n";
-                       my $oldfh = select(VAL);
-                       
Fink::Validation::validate_info_file($obj->get_info_filename());
-                       select($oldfh);
-                       close(VAL);
-               }
+       if($DoValidate) {
+               open(VAL, ">>", "$rundir/validate/$pkg") or die "Couldn't open 
validation log for $pkg: $!\n";
+               my $oldfh = select(VAL);
+               Fink::Validation::validate_info_file($obj->get_info_filename());
+               select($oldfh);
+               close(VAL);
+       }
 
-               doLog("Building package $pkg...");
-               my $srcdir = $Fink::Config::buildpath; # Suppress "used only 
once" warning
-               $srcdir = "$Fink::Config::buildpath/" . $obj->get_fullname();
+       doLog("Building package $pkg...");
+       my $srcdir = $Fink::Config::buildpath; # Suppress "used only once" 
warning
+       $srcdir = "$Fink::Config::buildpath/" . $obj->get_fullname();
 
-               my $buildcmd = "printf '\n\n' | fink --yes";
-               $buildcmd .= " --build-as-nobody" if $BuildNobody;
-               $buildcmd .= " rebuild $pkg 2>&1";
-               my $ret = doBuild($buildcmd, $pkg);
+       my $buildcmd = "printf '\n\n' | fink --yes ";
+       $buildcmd .= "--build-as-nobody " if $BuildNobody;
+       if($pkglist->{$pkg} == PKGSTATUS_REBUILD) {
+               $buildcmd .= "rebuild ";
+       } else {
+               $buildcmd .= "install ";
+       }
+       $buildcmd .= "$pkg 2>&1";
+       my $ret = doBuild($buildcmd, $pkg);
 
-               if($ret != 0 and defined($BuildNobody) and $BuildNobody eq 
"try") {
-                       $buildcmd =~ s/ --build-as-nobody//;
-                       move("$rundir/logs/$pkg.log", 
"$rundir/logs/$pkg.log.nobody");
-                       doLog("Build of $pkg failed, trying as root...");
-                       $ret = doBuild($buildcmd, $pkg);
-                       if($ret != 0) {
-                               unlink("$rundir/logs/$pkg.log.nobody");
-                       } else {
-                               move("$rundir/logs/$pkg.log.nobody", 
"$rundir/nobody/$pkg.log");
-                       }
-               }
-               
+       if($ret != 0 and defined($BuildNobody) and $BuildNobody eq "try") {
+               $buildcmd =~ s/ --build-as-nobody//;
+               move("$rundir/logs/$pkg.log", "$rundir/logs/$pkg.log.nobody");
+               doLog("Build of $pkg failed, trying as root...");
+               $ret = doBuild($buildcmd, $pkg);
                if($ret != 0) {
-                       doLog("Build of $pkg failed!");
-                       $failures->{$pkg} = 1;
-                       push @newfails, $pkg;
+                       unlink("$rundir/logs/$pkg.log.nobody");
+               } else {
+                       move("$rundir/logs/$pkg.log.nobody", 
"$rundir/nobody/$pkg.log");
+               }
+       }
 
-                       # Also, any splitoffs of this package have failed.
-                       my @relatives = getRelatives($obj);
-                       foreach (@relatives) {
-                               my $name = $_->get_name();
-                               $failures->{$name} = 1;
-                               push @newfails, $name;
-                       }
+       if($ret != 0) {
+               doLog("Build of $pkg failed!");
+               my @failpkgs = $pkg;
+
+               # Also, any splitoffs of this package have failed.
+               my @relatives = getRelatives($obj);
+               foreach (@relatives) {
+                       my $name = $_->get_name();
+                       push @failpkgs, $pkg;
 
                        system("mv", $srcdir, "$rundir/src/$pkg") or 
doLog("Couldn't move $srcdir to $rundir/src/$pkg: $!");
-               } else {
-                       doLog("Build of $pkg succeeded!");
-                       system("rm", "-rf", $srcdir);
+               }
 
+               $pkglist->{$_} = PKGSTATUS_FAILED foreach @failpkgs;
+               updateCheckpoint(map { $_ => PKGSTATUS_FAILED } @failpkgs);
+               return;
+       } else {
+               doLog("Build of $pkg succeeded!");
+               system("rm", "-rf", $srcdir);
 
-                       my $deb = $obj->get_debname();
+               my $deb = $obj->get_debname();
+               move(readlink("$FinkDir/fink/debs/$deb"), 
"$rundir/pkginfo/binary-darwin-powerpc/$deb");
+               unlink("$FinkDir/fink/debs/$deb");
+               symlink("$rundir/pkginfo/binary-darwin-powerpc/$deb", 
"$FinkDir/fink/debs/$deb");
+
+               my @okpkgs = $pkg;
+               foreach my $relative(getRelatives($obj)) {
+                       push @okpkgs, $relative->get_name();
+
+                       my $deb = $relative->get_debname();
                        move(readlink("$FinkDir/fink/debs/$deb"), 
"$rundir/pkginfo/binary-darwin-powerpc/$deb");
                        unlink("$FinkDir/fink/debs/$deb");
                        symlink("$rundir/pkginfo/binary-darwin-powerpc/$deb", 
"$FinkDir/fink/debs/$deb");
+               }
 
-                       foreach my $relative(getRelatives($obj)) {
-                               my $deb = $relative->get_debname();
-                               move(readlink("$FinkDir/fink/debs/$deb"), 
"$rundir/pkginfo/binary-darwin-powerpc/$deb");
-                               unlink("$FinkDir/fink/debs/$deb");
-                               
symlink("$rundir/pkginfo/binary-darwin-powerpc/$deb", 
"$FinkDir/fink/debs/$deb");
+               $pkglist->{$_} = PKGSTATUS_INSTALLED foreach @okpkgs;
+               updateCheckpoint(map { $_ => PKGSTATUS_INSTALLED } @okpkgs);
+       }
+
+       FinkLib::purgeNonEssential() unless $Dirty;
+
+       if($DoValidate) {
+               my @killqueue;
+
+               find({no_chdir => 1, wanted => sub {
+                       if(/\.deb$/ or $_ =~ /fink\.build$/  or 
$File::Find::name eq "$FinkDir/var/lib/fink/finkinfodb") {
+                               $File::Find::prune = 1;
+                       } elsif(!$finkfiles->{$File::Find::name}) {
+                               doValidateWarn($pkg, "Leftover file 
$File::Find::name");
+                               push @killqueue, $File::Find::name;
                        }
+               }}, $FinkDir);
+
+               #system("rm", "-rf", @killqueue);
+               $finkfiles->{$_} = 1 foreach @killqueue;
+
+               open(VAL, ">>", "$rundir/validate/$pkg") or die "Couldn't open 
validation log for $pkg: $!\n";
+               my $oldfh = select(VAL);
+
+               my $deb = "$rundir/pkginfo/binary-darwin-powerpc/" . 
$obj->get_debname();
+               Fink::Validation::validate_dpkg_file($deb) if -f $deb;
+               foreach my $relative(getRelatives($obj)) {
+                       my $deb = "$rundir/pkginfo/binary-darwin-powerpc/" . 
$relative->get_debname();
+                       Fink::Validation::validate_dpkg_file($deb) if -f $deb;
                }
 
-               FinkLib::purgeNonEssential();
+               select($oldfh);
+               close(VAL);
+       }
 
-               if($DoValidate) {
-                       my @killqueue;
+       return 1;
+}
 
-                       find({no_chdir => 1, wanted => sub {
-                               if(/\.deb$/ or $_ =~ /fink\.build$/  or 
$File::Find::name eq "$FinkDir/var/lib/fink/finkinfodb") {
-                                       $File::Find::prune = 1;
-                               } elsif(!$finkfiles{$File::Find::name}) {
-                                       doValidateWarn($pkg, "Leftover file 
$File::Find::name");
-                                       push @killqueue, $File::Find::name;
-                               }
-                       }}, $FinkDir);
+# Try to build packages, adding to pkglist as we encounter deps.
+# pkglist is a list of package names to build in order.
+# skiplist is a list of package names to never build.
+sub buildAll {
+       my($pkglist) = @_;
 
-                       #system("rm", "-rf", @killqueue);
-                       $finkfiles{$_} = 1 foreach @killqueue;
+       my %finkfiles;
+       if($DoValidate) {
+               Fink::Config::set_options({"Pedantic" => 1});
 
+               # One of the validation steps is to identify files left in /sw
+               # by the build process.
+               find({no_chdir => 1, wanted => sub {
+                       $finkfiles{$File::Find::name} = 1;
+               }}, $FinkDir);
+       }
 
-                       open(VAL, ">>", "$rundir/validate/$pkg") or die 
"Couldn't open validation log for $pkg: $!\n";
-                       my $oldfh = select(VAL);
+       my @newfails;
+       PACKAGE: while(1) {
+               my($pkg, $pkgval);
+               foreach my $p (keys %$pkglist) {
+                       my $v = $pkglist->{$p};
+                       next unless $v == PKGSTATUS_REBUILD or $v == 
PKGSTATUS_INSTALL;
+                       $pkg = $p;
+                       $pkgval = $v;
+                       last;
+               }
 
-                       my $deb = "$rundir/pkginfo/binary-darwin-powerpc/" . 
$obj->get_debname();
-                       Fink::Validation::validate_dpkg_file($deb) if -f $deb;
-                       foreach my $relative(getRelatives($obj)) {
-                               my $deb = 
"$rundir/pkginfo/binary-darwin-powerpc/" . $relative->get_debname();
-                               Fink::Validation::validate_dpkg_file($deb) if 
-f $deb;
+               if(!$pkg) {
+                       my @unsats = sort grep { $pkglist->{$_} == 
PKGSTATUS_PROCESSING } keys %$pkglist;
+                       if(@unsats) {
+                               doLog("Couldn't figure out how to build: " . 
join(", ", @unsats));
+                               return;
+                       } else {
+                               doLog("Done!");
+                               return 1;
                        }
-
-                       select($oldfh);
-                       close(VAL);
                }
-       } continue {
-               updateCheckpoint(@newfails);
-               @newfails = ();
+
+               recurseOnDepends($pkglist, $pkg, 0, \%finkfiles);
        }
 }
 
@@ -663,181 +776,10 @@
        }
 }
 
-# Get dependency information
-sub getAllDepends {
-       my($pkglist) = @_;
-
-       doLog("Getting dependency graph.");
-
-       my %deps;
-       foreach my $pkgname (@$pkglist) {
-               $deps{$pkgname} = getDepends($pkgname);
-       }
-
-       return %deps;
-}
-
-# Order a list of packages in dependency order.
-# pkglist is a listref of package names to order.
-sub orderByDepends {
-       my($pkglist, $deps) = @_;
-
-       doLog("Getting dependency graph.");
-
-       my(@ret, %revdeps);
-
-       foreach my $pkgname (@$pkglist) {
-               $deps{$pkgname} = getDepends($pkgname);
-               $deps->{$pkgname}->{ordered} = 0;
-               my $pkg = $deps->{$pkgname};
-
-               # Build hash showing which packages are depended on by a given 
package
-               foreach my $dep (@{$pkg->{build}}, @{$pkg->{run}}) {
-                       foreach my $deppkg (@$dep) {
-                               $revdeps{$deppkg} ||= [];
-                               push @{$revdeps{$deppkg}}, $pkgname;
-                       }
-               }
-
-               # Keep track of which dependencies we've satisfied
-               $pkg->{unsatisfied} = {
-                       build => {map {$_ => 1} map [EMAIL PROTECTED] 
@{$pkg->{build}} },
-                       run => {map {$_ => 1} map [EMAIL PROTECTED] 
@{$pkg->{run}} }
-               };
-       }
-
-       doLog("Ordering packages.");
-
-       # Do a topological sort of the dependency graph.
-       my @queue;
-
-       # Force dtqa-finkenv to build first.
-       # This package dumps the environment to standard out during the compile
-       # phase and does nothing else.  We can use it to verify the build 
environment.
-       # (e.g. see what environment variables Fink is setting for package 
builds.)
-       if($deps->{'dtqa-finkenv'}) {
-               push @ret, 'dtqa-finkenv';
-               $deps->{'dtqa-finkenv'}->{ordered} = 2;
-       }
-
-       # First, bootstrap it with packages that have no dependencies.
-       # Those'll be the virtual packages.
-       my(%virtuals) = %{Fink::VirtPackage->list()};
-       push @queue, keys(%virtuals);
-
-       # Also, add in any non-virtual packages with no deps
-       foreach my $pkgname(keys %deps) {
-               next if $pkgname eq "dtqa-finkenv";
-               my $dep = $deps->{$pkgname};
-               next if keys %{$dep->{unsatisfied}->{build}} or keys 
%{$dep->{unsatisfied}->{run}};
-
-               push @queue, $pkgname;
-
-               # Also add split-offs of the package.
-               my $obj;
-               eval {
-                       $obj = Fink::PkgVersion->match_package($pkgname);
-               };
-               if($@) {
-                       doLog("Couldn't order $pkgname: $@");
-                       next;
-               }
-
-               my @relatives = getRelatives($obj);
-               foreach (@relatives) {
-                       my $name = $_->get_name();
-                       push @queue, $name;
-               }
-       }
-
-       doLog("Processing queue");
-
-       while(@queue) {
-               my $pkgname = shift @queue;
-
-               #ordered==2 indicates that the package is installable as well 
as buildable
-               next if $deps->{$pkgname}->{ordered} == 2;
-
-               if(!$deps->{$pkgname}->{ordered} and not $virtuals{$pkgname}) {
-                       push @ret, $pkgname;
-                       $deps->{$pkgname}->{ordered} = 1;
-               }
-
-               # We will place packages on the queue if they are buildable.
-               # However, the package can only be used to satisfy dependencies
-               # if it is *installable*.
-               next if !$virtuals{$pkgname} and 
keys(%{$deps->{$pkgname}->{unsatisfied}->{run}});
-
-               $deps->{$pkgname}->{ordered} = 2;
-
-               my @revdeps = @{$revdeps{$pkgname} || []};
-               my @provides = ($pkgname);
-
-               my $pkgobj = Fink::Package->package_by_name($pkgname);
-
-               # is_virtual == 1 are the Provides: aliases of regular packages.
-               # This is not to be confused with is_virtual == 2, which are the
-               # regular virtual packages.
-               next if $pkgobj->is_virtual() == 1;
-
-               # We've also satisfied things which depend on somethign we 
provide
-               foreach my $provider ($pkgobj->get_all_providers()) {
-                       my $pname = $provider->get_name();
-                       push @provides, $pname;
-                       push @revdeps, @{$revdeps{$pname} || []};
-               }
-
-               # For every package that is depended on by this one...
-               foreach my $revdep (@revdeps) {
-                       my $dep = $deps->{$revdep};
-
-                       # Remove this one from the list of unsatisfied deps...
-                       foreach my $pname(@provides) {
-                               delete $dep->{unsatisfied}->{run}->{$pname};
-                               delete $dep->{unsatisfied}->{build}->{$pname};
-                       }
-
-                       # If we've satisfied all builddeps, we can build it.
-                       next if keys(%{$dep->{unsatisfied}->{build}});
-                       
-                       push @queue, $revdep;
-
-                       # And add any splitoffs
-                       my $obj;
-                       eval {
-                               $obj = Fink::PkgVersion->match_package($revdep);
-                       };
-                       if($@) {
-                               doLog("Couldn't order $obj: $@");
-                               next;
-                       }
-
-                       my @relatives = getRelatives($obj);
-                       foreach (@relatives) {
-                               my $name = $_->get_name();
-                               push @queue, $name;
-                       }
-               }
-       }
-
-       foreach my $pkgname(keys %$deps) {
-               my $dep = $deps->{$pkgname};
-               next if $dep->{ordered};
-               my(%unsats) = (%{$dep->{unsatisfied}->{build}}, 
%{$dep->{unsatisfied}->{run}});
-               my $failmsg = "Can't figure out how to build.  Unsatisfied 
dependencies: " . join(" ", sort keys %unsats);
-               if($dryrun) {
-                       doLog($failmsg);
-               } else {
-                       logPackageFail($pkgname, $failmsg);
-               }
-       }
-
-       return @ret;
-}
-
-# Get list of dependencies for a package
-sub getDepends {
-       my($pkgname) = @_;
+# Get a flat list of buidl and run dependencies for a package and its 
dependencies
+sub getDependsRecursive {
+       my($pkgname, $seen) = @_;
+       $seen ||= {$pkgname => 1};
 
        # create a variable to hold the main package's object
        my $pkgobj;
@@ -850,11 +792,10 @@
        }
 
        # now get a list of references to packages
-       my(@rundeps, @builddeps);
-       # populate the @deplist with references to arrays of packages
+       my(@deplist);
        eval {
-               @rundeps = $pkgobj->resolve_depends(0, "depends");
-               @builddeps = $pkgobj->resolve_depends(2, "depends");
+               @deplist = $pkgobj->resolve_depends(0, "depends");
+               push @deplist, $pkgobj->resolve_depends(2, "depends");
        };
        if($@) {
                doLog("Couldn't get dependencies for $pkgname: $@");
@@ -867,89 +808,16 @@
        #
        # [[foo-dev], [xorg, xfree86, system-xfree86]]
        #
-
-       my(%ret) = (build => [], run => []);
-       foreach my $deps ({in => [EMAIL PROTECTED], out => $ret{run}}, {in => 
[EMAIL PROTECTED], out => $ret{build}}) {
-               foreach my $dep (@{$deps->{in}}) {
-
-                       # If you have two versions of package X, both of them
-                       # will appear in the dependency list; we don't want 
those
-                       # duplicates, so keep track of what we've seen.
-                       my %alt_seen_pkgs;
-
-                       my @alternatives;
-
-                       foreach my $dp (@$dep) {
-                               # each $dp is a package object
-
-                               # get the name, so we can keep recursing
-                               my $next_dep = $dp->get_name();
-                               next if $alt_seen_pkgs{$next_dep}++;
-                       
-                               # don't bother recursing if it already has been 
seen or if it's the same pkg
-                               if(!$next_dep or $next_dep eq $pkgname) {
-                                       next;
-                               } else {
-                                       push @alternatives, $next_dep;
-                               }
-                       }
-
-                       push @{$deps->{out}}, [EMAIL PROTECTED];
-               }
-       }
-
-       # and we're done!
-       return \%ret;
-}
-
-# Find the first unsatisfiable dependency for a package.
-# This may be a string containing multiple alternatives, ala "foo | bar | baz".
-# If all dependencies can be satisfied, returns the empty string.
-#
-# We normally only check the build dependencies, unless the "rundeps" 
parameter is true.
-# We set this parameter when recursing.  That's because we only need the 
builddeps
-# satisfied in order to build a package, but those builddeps will need to be 
installed,
-# so they need their runtime depends.
-#
-# pkgstack is used to avoid circular loops; its a hash of all the packages in 
the
-# recursion chain for this lookup.  We'll ignore attempts to check something 
already
-# in the chain.  depcache is used to avoid having to do repeated computations 
on
-# the same package.
-sub findFailedDep {
-       my($pkg, $deps, $failures, $rundeps, $pkgstack, $depcache) = @_;
-       $rundeps ||= 0;
-
-       $pkgstack ||= {};
-       $depcache ||= {};
-
-       return $depcache->{$pkg} if exists($depcache->{$pkg});
-
-       my @altsets = @{$deps->{$pkg}->{build} || []};
-       push @altsets, @{$deps->{$pkg}->{run} || []} if $rundeps;
-
-       foreach my $altset(@altsets) {
-               my $satisfied = 0;
-
-               foreach my $alt(@$altset) {
-                       next if
-                         $failures->{$alt} or
-                         $pkgstack->{$alt} or
-                         findFailedDep($alt, $deps, $failures, 1, {%$pkgstack, 
$alt => 1}, $depcache);
-
-                       # We found a way to satisfy this set of alternatives.
-                       $satisfied = 1;
-                       last;
-               }
-
-               if(!$satisfied) {
-                       my $ret = join(" | ", @$altset);
-                       $depcache->{$pkg} = $ret;
-                       return $ret;
+       my @ret;
+       foreach my $alternative (@deplist) {
+               foreach my $dep (@$alternative) {
+                       my $depname = $dep->get_name();
+                       next unless $seen->{$depname};
+                       push @ret, $depname;
+                       push @ret, getDependsRecursive($depname, $seen);
                }
        }
-
-       $depcache->{$pkg} = "";
-       return "";
+       return @ret;
 }
 
 # Take a list of package names and filter out the ones which are split-offs.
@@ -993,7 +861,7 @@
 
 sub restoreCheckpoint {
        my($checkpoint) = shift;
-       my($orderedPkgs, $skiplist, $deps, $failures);
+       my($pkglist, $skiplist);
 
        # We use eval "STRING" so that the variables in the checkpoint are
        # bound to this sub's lexical scope.
@@ -1005,25 +873,25 @@
        die "[EMAIL PROTECTED]" if $@;
 
        prepSystem();
-       injectPackages();
+       injectPackages() unless $BuildAll;
        removeBuildLocks();
 
        doLog("Restored from checkpoint");
        @skiplist = @$skiplist;
        doLog("Building packages");
-       buildAll($orderedPkgs, [EMAIL PROTECTED], $deps, $failures);
+       buildAll(\%$pkglist);
        doLog("Done building");
        restoreSystem();
 }
 
 sub initCheckpoint {
-       my($orderedPkgs, $deps, $failures) = @_;
+       my($pkglist) = @_;
 
        open(CHECKPOINT, ">", "$rundir/checkpoint");
 
        print CHECKPOINT Data::Dumper->Dump(
-               [$FinkDir, $rundir, $BuildNobody, $DoValidate, [EMAIL 
PROTECTED], $orderedPkgs, $deps, $failures],
-               [qw(FinkDir rundir BuildNobody DoValidate skiplist orderedPkgs 
deps failures)]
+               [$FinkDir, $rundir, $BuildNobody, $BuildAll, $DoValidate, 
$pkglist],
+               [qw(FinkDir rundir BuildNobody BuildAll DoValidate pkglist)]
        );
 
        close CHECKPOINT;
@@ -1031,11 +899,10 @@
 
 # Updates the checkpoint after a package build.
 sub updateCheckpoint {
-       my(@failed) = @_;
+       my(%changes) = @_;
 
        open(CHECKPOINT, ">>", "$rundir/checkpoint");
-       print CHECKPOINT "shift [EMAIL PROTECTED];";
-       print CHECKPOINT " \$failures->{'$_'} = 1;" foreach @failed;
+       print CHECKPOINT "\$pkglist->{$_} = $changes{$_}; " foreach keys 
%changes;
        print CHECKPOINT "\n";
        close CHECKPOINT;
 }


-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Fink-commits mailing list
Fink-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/fink-commits

Reply via email to