--- toast	2005/08/29 04:50:38	1.393
+++ toast	2005/09/04 20:20:54	1.394
@@ -290,6 +290,7 @@
     "showurls" => "true",
     "infodir" => "true",
     "xmlcatalog" => "true",
+    "hspkg" => "true",
     "protect" => "false",
     "relative" => "false",
     "debugrewrite" => "false",
@@ -1430,6 +1431,7 @@
     $defaultman = $out if defined($out) && $out =~ m!^/! && $out !~ /\n/;
   }
   my($x) = path(qw(etc xml toast-xml-catalog));
+  my($hspkgdir) = path(qw(etc toast-hs-package.conf));
 
   my(@vars);
   push(@vars, newenvvar("PATH", "bin"));
@@ -1438,6 +1440,7 @@
   push(@vars, newenvvar("CPATH", "include"));
   push(@vars, newenvvar("LIBRARY_PATH", "lib"));
   push(@vars, newenvvar("XML_CATALOG_FILES", $x, "/$x", " ")) if xmlcatalog;
+  push(@vars, newenvvar("HS_PKG_PATH", $hspkgdir)) if hspkg;
   # there's also a LIBRARY_RUN_PATH or something that affects ld somehow...
   return @vars;
 }
@@ -2615,6 +2618,57 @@
 ]);
 }
 
+sub helphspkg($$$)
+{
+  my($rootdir, $helperdir, $cmd) = @_;
+  helpstub($helperdir, $cmd);
+  writescript(path($helperdir, "$cmd.helper"), "#!/bin/sh\n# $genby\n", q[
+rootdir=], quote($rootdir), q[
+name=], time() . "-$$", q[
+
+cat > "$rootdir/bin/ghc" << "EOF"
+#!/bin/sh
+exec perl -wx "$0"
+#!perl
+
+$0 =~ m!([^/]+)$! or die;
+my($me) = $1;
+my(@mystats) = stat($0) or die("stat $0: $!");
+
+my(@extra);
+push(@extra, "-package-conf", $_) for split(/:/, $ENV{"HS_PKG_PATH"} || "");
+
+for(split(/:/, $ENV{"PATH"}))
+{
+  my($prog) = "$_/$me";
+  if(-x($prog))
+  {
+    my(@progstats) = stat($prog) or die("stat $prog: $!");
+    next if $progstats[0] == $mystats[0] && $progstats[1] == $mystats[1];
+    exec($prog, @extra, @ARGV);
+    die("exec $prog failed: $!");
+  }
+}
+
+die("can't find next $me in PATH");
+EOF
+
+chmod +x "$rootdir/bin/ghc"
+for i in ghc-pkg runghc runhaskell; do
+  ln -sf ghc "$rootdir/bin/$i"
+done
+
+for arg; do
+  case "$arg" in
+    -*) ;;
+    *) [ -r "$arg" ] && exec < "$arg" ;;
+  esac
+done
+
+exec cat > "$rootdir/hspkg/$name"
+]);
+}
+
 sub helplib($$$)
 {
   my($srcdir, $rootdir, $helperdir) = @_;
@@ -2953,6 +3007,7 @@
       xmlcatalog], "[");
   helprewrite($srcdir, $rootdir, $helperdir, $_, true) for (qw[mv]);
   helpnop($helperdir, $_) for (qw[chown chgrp ldconfig install-info mknod]);
+  helphspkg($rootdir, $helperdir, $_) for (qw[ghc-pkg]);
   $env{PATH} = "$helperdir:$env{PATH}";
 
   my($preload) = helplib($srcdir, $rootdir, $helperdir);
@@ -3510,11 +3565,14 @@
 sub stddirs()
 {
   my(@result) =
-      (qw[bin boot etc include info lib libexec man share src var],
-      map(path("man", "man$_"), 1..9), path(qw[var spool]),
-      path(qw[etc rc.d]), map(path("etc", "rc.d", "rc$_.d"), 0..6), # vmware
-      path(qw[var run]), # hotplug/2004_01_05
-      path(qw[share aclocal])); # librep/0.16.1
+  (
+    qw[bin boot etc include info lib libexec man share src var],
+    map(path("man", "man$_"), 1..9), path(qw[var spool]),
+    path(qw[etc rc.d]), map(path("etc", "rc.d", "rc$_.d"), 0..6), # vmware
+    path(qw[var run]), # hotplug/2004_01_05
+    path(qw[share aclocal]), # librep/0.16.1
+    "hspkg", # holding area for Haskell package files; see sub helphspkg()
+  );
   sort(@result);
 }
 
@@ -4051,6 +4109,41 @@
   }
 }
 
+sub rebuildhspkg($)
+{
+  my($armdir) = @_;
+
+  my($dir) = path($armdir, "hspkg");
+  my(@pkgs);
+  @pkgs = absls($dir) if hspkg and -d($dir);
+
+  my($etcdir) = path($armdir, "etc");
+  my($file) = path($etcdir, "toast-hs-package.conf");
+  return -e($file) || -l($file) ? rm($file) : true unless @pkgs;
+
+  if(!-d($etcdir))
+  {
+    my($mode) = getmode($armdir);
+    safechmod(0777, $armdir);
+    md(path($etcdir));
+    safechmod($mode, $armdir);
+  }
+
+  my($mode) = getmode($etcdir);
+  safechmod(0777, $etcdir);
+  safechmod(0666, $file) if -e($file);
+  writefile($file, "[]\n");
+  optrun("ghc-pkg", "--force", "-f", $file, "register", $_) for(@pkgs);
+  optrmall("$file.old");
+  safechmod($mode, $etcdir);
+
+  if(protect)
+  {
+    safechmod(0444, $file);
+    safechmod(0555, $_) for($etcdir, $armdir);
+  }
+}
+
 sub arm(@)
 {
   my($name, $version, $build, @urls) = @_;
@@ -4120,6 +4213,7 @@
 
   rebuildinfodir(armdir);
   rebuildxmlcatalog(armdir);
+  rebuildhspkg(armdir);
   run(postarmprog) if postarmprog;
 
   unlock(armdir);
@@ -4212,6 +4306,7 @@
 
     rebuildinfodir($armdir) if $changed;
     rebuildxmlcatalog($armdir) if $changed;
+    rebuildhspkg($armdir) if $changed;
     $anychanged ||= $changed;
     run(postarmprog) if ++$i == scalar(@armdirs) && $anychanged && postarmprog;
     unlock($armdir);
@@ -6703,6 +6798,23 @@
 C<toast-xml-catalog> file, if present, instead of rebuilding it.
 Default: enabled.
 
+=item S<B<--hspkg> | B<--nohspkg>>
+
+When B<hspkg> is enabled, B<toast arm> and B<toast disarm>
+will maintain a Haskell package database B<armdir> called
+C<etc/xml/toast-hs-package.conf>, whose presence and contents depend on
+the contents of B<armdir>'s C<hspkg> subdirectory, which in turn will be
+automatically populated by a wrapper script whenever a Haskell library
+tries to register itself in the package database.  If the package database
+already exists, it may be overwritten or deleted.  The B<toast env>
+command will set C<HS_PKG_PATH> to point to this file when this option
+is set, which will cause further wrapper scripts automatically installed
+with Haskell libraries to insert a -package-conf argument into the command
+lines of all the appropriate programs.  If B<hspkg> is disabled, B<toast
+arm> and B<toast disarm> will delete the C<toast-hs-package.conf> file,
+if present, instead of rebuilding it.  Tested with GHC 6.4.  Default:
+enabled.
+
 =item S<B<--protect> | B<--noprotect>>
 
 If B<protect> is enabled, B<toast build> will make some of the directories
@@ -6843,6 +6955,7 @@
   - "toast edit" leaves things in an odd state if you hang up on it
   - "toast rename" is more case-sensitive than it ought to be
   - "toast get" prevents wget from truncating output if transfer restarts
+  - "toast env" doesn't set PYTHONPATH
 
 Wish list: