about summary refs log tree commit diff
path: root/pkgs/misc
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2009-07-17 15:10:01 +0000
committerEelco Dolstra <eelco.dolstra@logicblox.com>2009-07-17 15:10:01 +0000
commit04cc6b721a32d783c7e878c9a8c5fa5e304d5334 (patch)
treef3b0cc22cffd6033604fe340d71dca4a08470e14 /pkgs/misc
parent3451ae1a64e5e2b87875fb5f949c5308f0f9542a (diff)
* Made findLaTeXIncludes pure. Previously find-includes.pl looked
  outside of the Nix store for the dependencies of the root source
  file, which is impure.  That's why it needed the
  `builtins.currentTime' hack to force a rebuild.  It also didn't work
  in a chroot.  Now find-includes.pl only scans the source file at
  hand, and we use builtins.genericClosure to find all includes
  recursively.

svn path=/nixpkgs/trunk/; revision=16414
Diffstat (limited to 'pkgs/misc')
-rw-r--r--pkgs/misc/tex/nix/default.nix61
-rw-r--r--pkgs/misc/tex/nix/find-includes.pl126
2 files changed, 84 insertions, 103 deletions
diff --git a/pkgs/misc/tex/nix/default.nix b/pkgs/misc/tex/nix/default.nix
index 2fb50bf70237c..0f0c798a2e2d0 100644
--- a/pkgs/misc/tex/nix/default.nix
+++ b/pkgs/misc/tex/nix/default.nix
@@ -10,7 +10,6 @@ rec {
     , extraFiles ? []
     , compressBlanksInIndex ? true
     , packages ? []
-    , searchRelativeTo ? dirOf (toString rootFile) # !!! duplication
     , copySources ? false
     }:
 
@@ -25,31 +24,57 @@ rec {
       inherit rootFile generatePDF generatePS extraFiles
         compressBlanksInIndex copySources;
 
-      includes = import (findLaTeXIncludes {inherit rootFile searchRelativeTo;});
+      includes = map (x: [x.key (baseNameOf (toString x.key))])
+        (findLaTeXIncludes {inherit rootFile;});
       
       buildInputs = [ pkgs.tetex pkgs.perl ] ++ packages;
     };
 
-    
+
+  # Returns the closure of the "dependencies" of a LaTeX source file.
+  # Dependencies are other LaTeX source files (e.g. included using
+  # \input{}), images (e.g. \includegraphics{}), bibliographies, and
+  # so on.
   findLaTeXIncludes =
     { rootFile
-    , searchRelativeTo ? dirOf (toString rootFile)
     }:
 
-    pkgs.stdenv.mkDerivation {
-      name = "latex-includes";
-
-      realBuilder = pkgs.perl + "/bin/perl";
-      args = [ ./find-includes.pl ];
-
-      rootFile = toString rootFile; # !!! hacky
-
-      inherit searchRelativeTo;
-
-      # Forces rebuilds.
-      hack = builtins.currentTime;
+    builtins.genericClosure {
+      startSet = [{key = rootFile;}];
+      
+      operator =
+        {key, ...}:
+
+        let
+
+          trace = x: builtins.trace x x;
+
+          # `find-includes.pl' returns the dependencies of the current
+          # source file (`key') as a list, e.g. [{type = "tex"; name =
+          # "introduction.tex";} {type = "img"; name = "example"}].
+          # The type denotes the kind of dependency, which determines
+          # what extensions we use to look for it.
+          deps = import (pkgs.runCommand "latex-includes"
+            { src = trace key; }
+            "${pkgs.perl}/bin/perl ${./find-includes.pl}");
+
+          # Look for the dependencies of `key', trying various
+          # extensions determined by the type of each dependency.
+          # TODO: support a search path.
+          foundDeps = dep: xs:
+            let
+              exts =
+                if dep.type == "img" then [".pdf" ".png" ".ps" ".jpg"]
+                else if dep.type == "tex" then [".tex" ""]
+                else [""];
+              fn = pkgs.lib.findFirst (fn: builtins.pathExists fn) null
+                (map (ext: "${dirOf key}/${dep.name}${ext}") exts);
+            in if fn != null then [{key = fn;}] ++ xs
+               else builtins.trace "not found: ${dep.name}" xs;
+
+        in pkgs.lib.fold foundDeps [] deps;
     };
-
+    
 
   dot2pdf =
     { dotGraph
@@ -158,7 +183,6 @@ rec {
         inherit packages;
         generatePDF = false;
         generatePS = true;
-        searchRelativeTo = dirOf (toString body);
       };
     };
 
@@ -176,7 +200,6 @@ rec {
         inherit body preamble;
       };
       inherit packages;
-      searchRelativeTo = dirOf (toString body);
     };
 
 
diff --git a/pkgs/misc/tex/nix/find-includes.pl b/pkgs/misc/tex/nix/find-includes.pl
index eb36cefc7de66..99204b467509b 100644
--- a/pkgs/misc/tex/nix/find-includes.pl
+++ b/pkgs/misc/tex/nix/find-includes.pl
@@ -1,102 +1,60 @@
 use strict;
 use File::Basename;
 
-my $root = $ENV{"rootFile"};
+my $src = $ENV{"src"};
 my $out = $ENV{"out"};
 my $path = $ENV{"searchRelativeTo"};
-my $store = $ENV{"NIX_STORE"};
 
 open OUT, ">$out" or die;
 print OUT "[\n";
 
-my @workset = ();
-my %doneset = ();
+open FILE, "< $src" or die;
 
-sub addToWorkSetExts {
-    my $base = shift;
-    foreach my $ext (@_) {
-        push @workset, "$base$ext";
-    }
+sub addName {
+    my ($type, $name) = @_;
+    print OUT "{ type = \"$type\"; name = \"$name\"; }\n";
 }
-
-push @workset, $root;
-
-while (scalar @workset > 0) {
-
-    my $fn = pop @workset;
-    next if (defined $doneset{$fn});
-
-    $doneset{$fn} = 1;
-
-    if (!-e "$fn") {
-        print STDERR "cannot access `$fn': $!\n" if !$!{ENOENT};
-        next;
-    }
-
-    next unless -e "$fn";
-    
     
-    # Print out the full path *and* its relative path to $root.
-
-    if (substr($fn, 0, length $path) eq $path) {
-        my $relFN = substr($fn, (length $path) + 1);
-        print OUT "$fn \"$relFN\"\n";
-    } else {
-        my $base = basename $fn;
-        my $x = substr($fn, 0, length($store) + 1);
-        if (substr($fn, 0, length($store) + 1) eq "$store/") {
-            $base = substr($base, 33);
-        }
-        print OUT "$fn \"$base\"\n";
-    }
-
-    
-    # If this is a TeX file, recursively find include in $fn.
-    next unless $fn =~ /.tex$/ or $fn =~ /.ltx$/; 
-    open FILE, "< $fn" or die;
-    
-    while (<FILE>) {
-	if (/\\input\{(.*)\}/) {
-	    my $fn2 = $1;
-            die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
-	    push @workset, "$path/$fn2.tex";
-	    push @workset, "$path/$fn2";
-	} elsif (/\\usepackage(\[.*\])?\{(.*)\}/) {
-	    my $fn2 = $2;
-            die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
-	    push @workset, "$path/$fn2.sty";
-	} elsif (/\\documentclass(\[.*\])?\{(.*)\}/) {
-	    my $fn2 = $2;
-            die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
-	    push @workset, "$path/$fn2.cls";
-	} elsif (/\\bibliographystyle\{(.*)\}/) {
-	    my $fn2 = $1;
-            die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
-	    push @workset, "$path/$fn2.bst";
-	} elsif (/\\bibliography\{(.*)\}/) {
-            foreach my $bib (split /,/, $1) {
-                $bib =~ s/^\s+//; # remove leading / trailing whitespace
-                $bib =~ s/\s+$//;
-                push @workset, "$path/$bib.bib";
-            }
-	} elsif (/\\includegraphics(\[.*\])?\{(.*)\}/) {
-	    my $fn2 = $2;
-            die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
-            addToWorkSetExts("$path/$fn2", ".pdf", ".png", ".ps", ".jpg");
-	} elsif (/\\pgfdeclareimage(\[.*\])?\{.*\}\{(.*)\}/) {
-	    my $fn2 = $2;
-            die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
-            addToWorkSetExts("$path/$fn2", ".pdf", ".png", ".jpg");
-	} elsif (/\\pgfimage(\[.*\])?\{(.*)\}/) {
-	    my $fn2 = $2;
-            die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
-            addToWorkSetExts("$path/$fn2", ".pdf", ".png", ".jpg");
+while (<FILE>) {
+    if (/\\input\{(.*)\}/) {
+        my $fn2 = $1;
+        die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
+        addName "tex", "$fn2";
+    } elsif (/\\usepackage(\[.*\])?\{(.*)\}/) {
+        my $fn2 = $2;
+        die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
+        addName "misc", "$fn2.sty";
+    } elsif (/\\documentclass(\[.*\])?\{(.*)\}/) {
+        my $fn2 = $2;
+        die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
+        addName "misc", "$fn2.cls";
+    } elsif (/\\bibliographystyle\{(.*)\}/) {
+        my $fn2 = $1;
+        die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
+        addName "misc", "$fn2.bst";
+    } elsif (/\\bibliography\{(.*)\}/) {
+        foreach my $bib (split /,/, $1) {
+            $bib =~ s/^\s+//; # remove leading / trailing whitespace
+            $bib =~ s/\s+$//;
+            addName "misc", "$bib.bib";
         }
-        # !!! also support \usepackage
+    } elsif (/\\includegraphics(\[.*\])?\{(.*)\}/) {
+        my $fn2 = $2;
+        die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
+        addName "img", "$fn2";
+    } elsif (/\\pgfdeclareimage(\[.*\])?\{.*\}\{(.*)\}/) {
+        my $fn2 = $2;
+        die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
+        addName "img", "$fn2";
+    } elsif (/\\pgfimage(\[.*\])?\{(.*)\}/) {
+        my $fn2 = $2;
+        die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
+        addName "img", "$fn2";
     }
-    
-    close FILE;
+    # !!! also support \usepackage
 }
 
+close FILE;
+
 print OUT "]\n";
 close OUT;