Something I have been toying with for a while now is fink being able
to use apt-get-able packages.  Sometimes when building something large,
many of the dependency packages are already in a bindist somewhere, and
I'd rather not build each and every one, just the packages newer than
what is in the bindist.  So, I thought about using apt-get to get the
ones that I could.

My requirements were:
1) Don't break what currently works.  If a package can't be fetched
from apt-get, then fall back to building from scratch.
Also as a result of this requirement, fink's dependency engine must
be used instead of apt-get's.  Fink also must perform all package
installations instead of apt-get.
2) Don't download things that won't be used to satisfy the request.
apt-get has its own dependency engine and it might not necissarily
agree with what fink wants to install.  We don't want apt-get going
off and downloading everything, and then fink not using it later on.

As a result of these, this patch may end up not downloading things
that it might otherwise be able to.  Part of the problem here is apt-get
does not allow downloading arbitrary files.  It wants all dependencies
installed to satisfy the requirements of the file it is downloading,
even if its not actually going to install the file.

I've come up with a patch that does this.  I've been testing the
patch locally, but have not tested it extensively.  I'll test it with
larger dependency chains later, when I get access to better connectivity.
Known issues: it is not controllable by a switch (command line or 
otherwise).  The plan is to not have this on by default, but use
a switch of some sort to enable it.  I'm open to suggestions on how
best to toggle this.  Also, it does not run apt-get update from
fink index, so you'll need to do that seperately.  It should update
apt-get's notion of reality.

Rob
diff -udr Fink.orig/Engine.pm Fink/Engine.pm
--- Fink.orig/Engine.pm Mon Sep  6 11:34:09 2004
+++ Fink/Engine.pm      Mon Sep  6 11:41:26 2004
@@ -1382,6 +1382,20 @@
        foreach $pkgname (sort keys %deps) {
                $item = $deps{$pkgname};
                next if $item->[OP] == $OP_INSTALL and $item->[PKGVER]->is_installed();
+               if (!$item->[PKGVER]->is_present() && $item->[OP] != $OP_REBUILD) {
+                       my ($aptcmd, $pkgg, $package);
+                       $package = $item->[PKGVER];
+                       if (exists $package->{_relatives}) {
+                               foreach $pkgg (@{$package->{_relatives}}){
+                                       if (!$pkgg->is_present() && 
$pkgg->is_aptgetable()) {
+                                               $pkgg->apt_fetch();
+                                               &real_install($OP_INSTALL, 0, 1, 
$pkgg->get_name());
+                                       }
+                               }
+                       }
+                       $item->[PKGVER]->apt_fetch();
+               }
+
                if ($item->[OP] == $OP_REBUILD or not $item->[PKGVER]->is_present()) {
                        $item->[PKGVER]->phase_fetch(1, 0);
                }
diff -udr Fink.orig/Package.pm Fink/Package.pm
--- Fink.orig/Package.pm        Mon Sep  6 11:34:09 2004
+++ Fink/Package.pm     Mon Sep  6 16:15:08 2004
@@ -44,6 +44,7 @@
 our $essential_valid = 0;
 our $db_outdated = 1;
 our $db_mtime = 0;
+our $aptdb = {};
 
 END { }                                # module clean-up code here (global destructor)
 
@@ -221,6 +222,19 @@
        return 0;
 }
 
+### Find a specific package name/version in aptdb
+
+sub is_in_apt{
+       my $self = shift;
+       my $name = shift;
+       my $version = shift;
+
+       if (defined $aptdb->{$name}{$version}) {
+               return 1;
+       }
+       return 0;
+}
+
 ### get version object by exact name
 
 sub get_version {
@@ -340,6 +354,7 @@
                         if (not $db_outdated) {
                                $packages = 
Storable::retrieve("$basepath/var/db/fink.db");
                         }
+                       $aptdb = Storable::retrieve("$basepath/var/db/finkapt.db");
                }
        }
        
@@ -407,6 +422,33 @@
                 ? 1 : 0;
 }
 
+### update the apt-get db file
+
+sub update_aptdb {
+       shift;
+
+       my ($pkg, $ver);
+       open(APTDUMP, "apt-cache dump |") || die "Can't run apt-cache dump: $!\n";
+       $aptdb = {};
+       while(<APTDUMP>) {
+               if (grep(/Package:/,$_)) {
+                       chomp;
+                       $pkg = $_;
+                       $pkg =~ s/.*Package:[\ ]*//; 
+               }
+               if (grep(/Version:/,$_)) {
+                       my $count;
+                       chomp;
+                       $ver = $_;
+                       $ver =~ s/.*Version:[\ ]*//;
+                       $aptdb->{$pkg}{$ver}++;
+               }
+       }
+       close APTDUMP;
+
+       Storable::lock_store($aptdb, "$basepath/var/db/finkapt.db");
+}
+
 ### read the packages and update the database, if needed and we are root
 
 sub update_db {
@@ -440,6 +482,7 @@
                }
        };
        $db_outdated = 0;
+       Fink::Package->update_aptdb();
 }
 
 ### scan one tree for package desccriptions
diff -udr Fink.orig/PkgVersion.pm Fink/PkgVersion.pm
--- Fink.orig/PkgVersion.pm     Mon Sep  6 11:34:09 2004
+++ Fink/PkgVersion.pm  Mon Sep  6 16:17:15 2004
@@ -1037,6 +1037,26 @@
        return 1;
 }
 
+sub is_aptgetable {
+       my $self = shift;
+       if (defined Fink::Package->is_in_apt($self->get_name(), 
$self->get_fullversion())) {
+               return 1;
+       }
+       return 0;
+}
+
+sub apt_fetch {
+       my $self = shift;
+       my $aptcmd = "apt-get -d --trivial-only -q  install " . $self->get_name() . 
"=" . $self->get_fullversion() . " > /dev/null 2>&1";
+       print STDERR "Retrieving " . $self->get_debname() . " via apt-get\n";
+       if (!&execute($aptcmd)) {
+               my $tmpdeb = "$basepath/fink/debs/" . $self->get_debname();
+               symlink "$basepath/var/cache/apt/archives/" . $self->get_debfile(), 
$tmpdeb;
+               return 1;
+       }
+       return 0;
+}
+
 sub is_present {
        my $self = shift;
 
@@ -1098,6 +1118,11 @@
                        return $fn;
                }
        }
+       $fn = "$basepath/var/cache/apt/archives/$self->{_debname}";
+       if (-f $fn) {
+               return $fn;
+       }
+
        return undef;
 }
 

Reply via email to