--- ChangeLog	1 Jul 2004 14:25:17 -0000	1.237
+++ ChangeLog	1 Jul 2004 14:26:51 -0000
@@ -1,3 +1,7 @@
+2004-06-30  Benjamin Reed  <rangerrick@users.sourceforge.net>
+
+	* install.sh: install Fink/Package/*.pm as well
+
 2004-06-30  Daniel Macks  <dmacks@netspace.org>
 
 	* bootstrap.pl: remove redundancy in perl version checking.
--- install.sh	1 Jul 2004 14:25:17 -0000	1.21
+++ install.sh	1 Jul 2004 14:26:51 -0000
@@ -38,7 +38,7 @@
 chmod 755 "$basepath"
 
 for dir in bin lib lib/fink lib/perl5 lib/perl5/Fink \
-	   lib/fink/update etc etc/dpkg \
+	   lib/perl5/Fink/Package lib/fink/update etc etc/dpkg \
 	   share share/doc share/doc/fink share/man \
 	   share/man/man8 share/man/man5 ; do
   mkdir "$basepath/$dir"
@@ -62,6 +62,12 @@
   fi
 done
 
+for file in perlmod/Fink/Package/*.pm ; do
+  if [ -f $file ]; then
+    install -c -p -m 644 $file "$basepath/lib/perl5/Fink/Package/"
+  fi
+done
+
 for file in update/config.guess update/config.sub update/ltconfig ; do
   install -c -p -m 755 $file "$basepath/lib/fink/update/"
 done
--- perlmod/Fink/ChangeLog	1 Jul 2004 14:25:17 -0000	1.652
+++ perlmod/Fink/ChangeLog	1 Jul 2004 14:26:52 -0000
@@ -2,6 +2,11 @@
 
 	* VirtPackage.pm: Just a little rearranging to make things easier.
 
+2004-06-30  Benjamin Reed  <rangerrick@users.sourceforge.net>
+
+	* Engine.pm, Package.pm, Package/Mini.pm: Create a mini package index
+	used (currently) only for 'fink list' operations.
+
 2004-06-29  Daniel Macks  <dmacks@netspace.org>
 
 	* PkgVersion.pm: Mention which SourceN failed if missing SourceN-MD5.
--- perlmod/Fink/Engine.pm	1 Jul 2004 14:25:17 -0000	1.182
+++ perlmod/Fink/Engine.pm	1 Jul 2004 14:26:52 -0000
@@ -26,6 +26,7 @@
 use Fink::Services qw(&latest_version &sort_versions &execute &file_MD5_checksum &get_arch &expand_percent);
 use Fink::CLI qw(&print_breaking &prompt_boolean &prompt_selection_new &get_term_width &parse_cmd_options);
 use Fink::Package;
+use Fink::Package::Mini;
 use Fink::PkgVersion;
 use Fink::Config qw($config $basepath $debarch);
 use File::Find;
@@ -325,7 +326,7 @@
 
 EOF
 		}
-	exit 0;
+		exit 0;
 	}
 	if ($options{installedstate} == 0) {$options{installedstate} = 7;}
 
@@ -353,14 +354,14 @@
 		$formatstr = "%s\t%s\t%s\t%s\n";
 		$desclen = 0;
 	}
-	Fink::Package->require_packages();
+	Fink::Package::Mini->require_packages();
 	@_ = @ARGV;
 	@ARGV = @temp_ARGV;
-	@allnames = Fink::Package->list_packages();
 	if ($cmd eq "list") {
 		if ($#_ < 0) {
-			@selected = @allnames;
+			@selected = Fink::Package::Mini->list_packages();
 		} else {
+			@allnames = Fink::Package::Mini->list_packages();
 			@selected = ();
 			while (defined($pattern = shift)) {
 				$pattern = lc quotemeta $pattern; # fixes bug about ++ etc in search string.
@@ -375,24 +376,22 @@
 		}
 	} else {
 		$pattern = shift;
-		@selected = @allnames;
+		@selected = Fink::Package::Mini->list_packages();
 		unless ($pattern) {
 			die "no keyword specified for command 'apropos'!\n";
 		}
 	}
 
 	foreach $pname (sort @selected) {
-		$package = Fink::Package->package_by_name($pname);
+		$package = Fink::Package::Mini->package_by_name($pname);
 		if ($package->is_virtual() == 1) {
-			$lversion = "";
 			$iflag = "   ";
 			$description = "[virtual package]";
 			next if ($cmd eq "apropos"); 
 			next unless ($options{installedstate} & 4);
 		} else {
-			$lversion = &latest_version($package->list_versions());
-			$vo = $package->get_version($lversion);
-			if ($vo->is_installed()) {
+			$description = $package->get_description();
+			if ($package->is_installed()) {
 				next unless ($options{installedstate} & 2);
 				$iflag = " i ";
 			} elsif ($package->is_any_installed()) {
@@ -402,32 +401,30 @@
 				$iflag = "   ";
 				next unless ($options{installedstate} & 4);
 			}
-
-			$description = $vo->get_shortdescription($desclen);
 		}
 		if (defined $buildonly) {
-			next unless $vo->param_boolean("builddependsonly");
+			next unless $package->get_builddepensonly();
 		}
 		if (defined $section) {
 			$section =~ s/[\=]?(.*)/$1/;
-			next unless $vo->get_section($vo) =~ /\Q$section\E/i;
+			next unless $package->get_section() =~ /\Q$section\E/i;
 		}
 		if (defined $maintainer) {
-			next unless ( $vo->has_param("maintainer") && $vo->param("maintainer")  =~ /\Q$maintainer\E/i );
+			next unless ( $package->get_maintainer() ne "" && $package->get_maintainer() =~ /\Q$maintainer\E/i );
 		}
 		if (defined $pkgtree) {
 #			$pkgtree =~ s/[\=]?(.*)/$1/;    # not sure if needed...
-			next unless $vo->get_tree($vo) =~ /\b\Q$pkgtree\E\b/i;
+			next unless $package->get_tree() =~ /\b\Q$pkgtree\E\b/i;
 		}
 		if ($cmd eq "apropos") {
-			next unless ( $vo->has_param("Description") && $vo->param("Description") =~ /\Q$pattern\E/i ) || $vo->get_name() =~ /\Q$pattern\E/i;  
+			next unless ( $package->get_description() ne "" && $package->get_description() =~ /\Q$pattern\E/i ) || $pname =~ /\Q$pattern\E/i;  
 		}
 		if ($namelen && length($pname) > $namelen) {
 			$pname = substr($pname, 0, $namelen - 3)."...";
 		}
 
 		printf $formatstr,
-				$iflag, $pname, $lversion, $description;
+				$iflag, $pname, $package->get_version(), $description;
 	}
 }
 
--- perlmod/Fink/Package.pm	1 Jul 2004 14:25:17 -0000	1.76
+++ perlmod/Fink/Package.pm	1 Jul 2004 14:26:53 -0000
@@ -31,6 +31,7 @@
 use Fink::PkgVersion;
 use Fink::FinkVersion;
 use File::Find;
+use Fink::Package::Mini;
 
 use strict;
 use warnings;
@@ -415,12 +416,15 @@
 
 	# read data from descriptions
 	if (&get_term_width) {
-		print STDERR "Reading package info...\n";
+		print STDERR "Reading package info... ";
 	}
 	foreach $tree ($config->get_treelist()) {
 		$dir = "$basepath/fink/dists/$tree/finkinfo";
 		Fink::Package->scan($dir);
 	}
+	if (&get_term_width) {
+		print STDERR "done.\n";
+	}
 	eval {
 		require Storable; 
 		if ($> == 0) {
@@ -432,7 +436,9 @@
 			}
 			Storable::lock_store ($packages, "$basepath/var/db/fink.db.tmp");
 			rename "$basepath/var/db/fink.db.tmp", "$basepath/var/db/fink.db";
-			print "done.\n";
+			if (&get_term_width) {
+				print STDERR "done.\n";
+			}
 		} else {
 			&print_breaking_stderr( "\nFink has detected that your package cache is out of date and needs" .
 				" an update, but does not have privileges to modify it. Please re-run fink as root," .
@@ -440,6 +446,10 @@
 		}
 	};
 	$db_outdated = 0;
+
+	# update the mini-index for 'fink list' when we update
+	# the full index
+	Fink::Package::Mini->scan_all();
 }
 
 ### scan one tree for package desccriptions
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ perlmod/Fink/Package/Mini.pm	1 Jul 2004 14:26:53 -0000
@@ -0,0 +1,256 @@
+# -*- mode: Perl; tab-width: 4; -*-
+#
+# Fink::Package::Mini class
+#
+# Fink - a package manager that downloads source and installs it
+# Copyright (c) 2001 Christoph Pfisterer
+# Copyright (c) 2001-2004 The Fink Package Manager Team
+#
+# 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 the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA	 02111-1307, USA.
+#
+
+package Fink::Package::Mini;
+use Fink::Base;
+use Fink::Config qw($basepath $config $debarch);
+use Fink::CLI qw(&get_term_width);
+use Fink::Package;
+use Fink::Services qw(&latest_version);
+
+use strict;
+use warnings;
+
+our $VERSION = 1.00;
+our @ISA = qw(Fink::Base Fink::Package);
+
+our $have_packages = 0;
+our $packages_mini = {};
+our $db_outdated   = 1;
+
+END { }				# module clean-up code here (global destructor)
+
+
+### constructor taking a name
+
+### self-initialization
+
+sub initialize {
+	my $self = shift;
+
+	$self->SUPER::initialize();
+
+	$self->{_name} = $self->param_default("Package", "");
+	$self->{_versions} = {};
+	$self->{_virtual} = 1;
+	$self->{_providers} = [];
+
+	$packages_mini->{$self->{package}} = $self;
+}
+
+### get package name
+
+sub get_name {
+	my $self = shift;
+
+	return $self->{_name};
+}
+
+### get pure virtual package flag
+
+sub package_by_name {
+	shift;
+	my $pkgname = shift;
+	$packages_mini->{$pkgname};
+}
+sub list_packages {
+	shift;   # class method - ignore first parameter
+
+	return keys %$packages_mini;
+}
+sub is_installed {
+	my $package = shift;
+	return $package->{is_installed};
+}
+sub is_any_installed {
+	my $package = shift;
+	return $package->{is_any_installed};
+}
+sub is_virtual {
+	my $package = shift;
+	return $package->{is_virtual};
+}
+sub get_builddependsonly {
+	my $package = shift;
+	return $package->{buildonly};
+}
+sub get_description {
+	my $package = shift;
+	return $package->{description};
+}
+sub get_maintainer {
+	my $package = shift;
+	return $package->{maintainer};
+}
+sub get_section {
+	my $package = shift;
+	return $package->{section};
+}
+sub get_tree {
+	my $package = shift;
+	return $package->{tree};
+}
+sub get_version {
+	my $package = shift;
+	return $package->{version};
+}
+
+sub require_packages {
+	shift;	# class method - ignore first parameter
+
+	if (!$have_packages) {
+		Fink::Package::Mini->scan_all();
+	}
+}
+
+sub forget_packages {
+	shift;	# class method - ignore first parameter
+
+	$have_packages = 0;
+	%$packages_mini = ();
+	$db_outdated = 1;
+}
+
+
+### read list of packages, either from cache or files
+
+sub scan_all {
+	shift;	# class method - ignore first parameter
+	my ($time) = time;
+	my ($db_mtime, $dbmini_mtime, $dlist, $pkgname, $po, $hash, $fullversion, @versions);
+
+	Fink::Package::Mini->forget_packages();
+	
+	# If we have the Storable perl module, try to use the package index
+	if (-e "$basepath/var/db/fink-list.db") {
+		eval {
+			require Storable; 
+
+			# We assume the DB is up-to-date unless proven otherwise
+			$db_outdated = 0;
+		
+			# Unless the NoAutoIndex option is set, check whether we should regenerate
+			# the index based on its modification date and that of the package descs.
+			if (not $config->param_boolean("NoAutoIndex")) {
+				$db_mtime = (stat("$basepath/var/db/fink.db"))[9];
+				$dbmini_mtime = (stat("$basepath/var/db/fink-list.db"))[9];
+				if (((lstat("$basepath/etc/fink.conf"))[9] > $dbmini_mtime)
+					or ((stat("$basepath/etc/fink.conf"))[9] > $dbmini_mtime)) {
+					$db_outdated = 1;
+				} elsif ($dbmini_mtime < $db_mtime) {
+					$db_outdated = 1;
+				} else {
+					$db_outdated = &search_comparedb( "$basepath/fink/dists" );
+				}
+			}
+			
+			# If the index is not outdated, we can use it, and thus safe a lot of time
+			 if (not $db_outdated) {
+				$packages_mini = Storable::retrieve("$basepath/var/db/fink-list.db") if (-f "$basepath/var/db/fink-list.db");
+			 }
+		}
+	}
+
+	# Regenerate the DB if it is outdated
+	if ($db_outdated) {
+		Fink::Package::Mini->update_db();
+	}
+
+	$have_packages = 1;
+}
+
+### scan for info files and compare to $dbmini_mtime
+
+sub search_comparedb {
+	my $path = shift;
+	$path .= "/";  # forces find to follow the symlink
+
+	# Using find is much faster than doing it in Perl
+	return
+	  (grep !m{/(CVS|binary-$debarch)/},
+	   `/usr/bin/find $path \\( -type f -or -type l \\) -and -name '*.info' -newer $basepath/var/db/fink-list.db`)
+		 ? 1 : 0;
+}
+
+
+### read the packages and update the database, if needed and we are root
+
+sub update_db {
+	shift;	# class method - ignore first parameter
+	my ($tree, $dir);
+
+	my ($packagename, $package, $vo);
+	foreach $packagename (Fink::Package->list_packages()) {
+		$packages_mini->{$packagename} = {
+			buildonly        => 0,
+			description      => '',
+			is_any_installed => 0,
+			is_installed     => 0,
+			is_virtual       => 0,
+			maintainer       => '',
+			section          => '',
+			tree             => 'stable',
+			version          => '',
+		};
+		bless($packages_mini->{$packagename}, 'Fink::Package::Mini');
+		$package = Fink::Package->package_by_name($packagename);
+		if ($package->is_virtual() == 1) {
+			$packages_mini->{$packagename}->{description} = "[virtual package]";
+			$packages_mini->{$packagename}->{is_virtual}  = 1;
+		} else {
+			$packages_mini->{$packagename}->{version} = &latest_version($package->list_versions());
+			$vo = $package->get_version($packages_mini->{$packagename}->{version});
+			if ($vo->is_installed()) {
+				$packages_mini->{$packagename}->{is_installed} = 1;
+			} elsif ($package->is_any_installed()) {
+				$packages_mini->{$packagename}->{is_any_installed} = 1;
+			}
+			$packages_mini->{$packagename}->{description} = $vo->get_shortdescription();
+			$packages_mini->{$packagename}->{buildonly}   = $vo->param_boolean("builddependsonly");
+			$packages_mini->{$packagename}->{section}     = $vo->get_section($vo);
+			$packages_mini->{$packagename}->{maintainer}  = $vo->param("maintainer");
+			$packages_mini->{$packagename}->{tree}        = $vo->get_tree($vo);
+		}
+	}
+
+	eval {
+		require Storable; 
+		if ($> == 0) {
+			if (&get_term_width) {
+				print STDERR "Updating 'fink list' index... "
+			}
+			unless (-d "$basepath/var/db") {
+				mkdir("$basepath/var/db", 0755) || die "Error: Could not create directory $basepath/var/db";
+			}
+			Storable::lock_store ($packages_mini, "$basepath/var/db/fink-list.db.tmp") or die "couldn't store: $!\n";
+			rename "$basepath/var/db/fink-list.db.tmp", "$basepath/var/db/fink-list.db";
+			if (&get_term_width) {
+				print STDERR "done.\n";
+			}
+		}
+	};
+
+	$db_outdated = 0;
+}
+
+1;
