* 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
This commit is contained in:
Eelco Dolstra 2009-07-17 15:10:01 +00:00
parent 3451ae1a64
commit 04cc6b721a
3 changed files with 83 additions and 102 deletions

View file

@ -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";
builtins.genericClosure {
startSet = [{key = rootFile;}];
operator =
{key, ...}:
realBuilder = pkgs.perl + "/bin/perl";
args = [ ./find-includes.pl ];
let
rootFile = toString rootFile; # !!! hacky
trace = x: builtins.trace x x;
inherit searchRelativeTo;
# `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}");
# Forces rebuilds.
hack = builtins.currentTime;
# 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);
};

View file

@ -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";
}
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";
}
} 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";
}
# !!! also support \usepackage
}
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");
}
# !!! also support \usepackage
}
close FILE;
}
close FILE;
print OUT "]\n";
close OUT;

View file

@ -7851,7 +7851,7 @@ let
};
texFunctions = import ../misc/tex/nix {
inherit stdenv perl tetex graphviz ghostscript makeFontsConf imagemagick;
inherit stdenv perl tetex graphviz ghostscript makeFontsConf imagemagick runCommand lib;
};
texLive = builderDefsPackage (import ../misc/tex/texlive) {