From a957893b261a4438101c205e38fe8ce62b83a121 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 8 Jan 2015 14:32:45 +0100 Subject: Allow nix-shell to be used as a #! interpreter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows scripts to fetch their own dependencies via nix-shell. For instance, here is a Haskell script that, when executed, pulls in GHC and the HTTP package: #! /usr/bin/env nix-shell #! nix-shell -i runghc -p haskellPackages.ghc haskellPackages.HTTP import Network.HTTP main = do resp <- Network.HTTP.simpleHTTP (getRequest "http://nixos.org/") body <- getResponseBody resp print (take 100 body) Or a Perl script that pulls in Perl and some CPAN packages: #! /usr/bin/env nix-shell #! nix-shell -i perl -p perl perlPackages.HTMLTokeParserSimple perlPackages.LWP use HTML::TokeParser::Simple; my $p = HTML::TokeParser::Simple->new(url => 'http://nixos.org/'); while (my $token = $p->get_tag("a")) { my $href = $token->get_attr("href"); print "$href\n" if $href; } Note that the options to nix-shell must be given on a separate line that starts with the magic string ‘#! nix-shell’. This is because ‘env’ does not allow passing arguments to an interpreter directly. --- scripts/nix-build.in | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'scripts') diff --git a/scripts/nix-build.in b/scripts/nix-build.in index 3ac02ad35ea5..b7c923f88607 100755 --- a/scripts/nix-build.in +++ b/scripts/nix-build.in @@ -25,6 +25,8 @@ my @envExclude = (); my $myName = $runEnv ? "nix-shell" : "nix-build"; +my $inShebang = 0; +my $script; my $tmpDir = mkTempDir($myName); @@ -35,6 +37,29 @@ my $drvLink = "$tmpDir/derivation"; $SIG{'INT'} = sub { exit 1 }; +# Heuristic to see if we're invoked as a shebang script, namely, if we +# have a single argument, it's the name of an executable file, and it +# starts with "#!". +if ($runEnv && scalar @ARGV == 1) { + $script = $ARGV[0]; + if (-f $script && -x $script) { + open SCRIPT, "<$script" or die "$0: cannot open ‘$script’: $!\n"; + my $first =