#! /nix/store/05aipb9ciqizqq6c43kq6q08jl35xr80-perl-5.24.3/bin/perl -w -I/nix/store/ifmyq5ryfxhhrzh62hiq65xyz1fwffga-nix-1.11.16/lib/perl5/site_perl/5.24.3/i686-linux-thread-multi -I/nix/store/7xspf7a6srkgdmkkslvydahwqrjlhycf-perl-DBI-1.636/lib/perl5/site_perl -I/nix/store/dq2fply95zqdjkawpv70x9cidsx9czw0-perl-DBD-SQLite-1.54/lib/perl5/site_perl -I/nix/store/35kw03bv6a739iyc6fd4j6cwzddwxpw0-perl-WWW-Curl-4.17/lib/perl5/site_perl

use utf8;
use strict;
use Nix::Config;
use Nix::Utils;

binmode STDERR, ":encoding(utf8)";


# Parse the command line arguments.
my @args = @ARGV;

my $source;
my $fromURL = 0;
my @extraNixEnvArgs = ();
my $interactive = 1;
my $op = "--install";

while (scalar @args) {
    my $arg = shift @args;
    if ($arg eq "--help") {
        exec "man nix-install-package" or die;
    }
    elsif ($arg eq "--url") {
        $fromURL = 1;
    }
    elsif ($arg eq "--profile" || $arg eq "-p") {
        my $profile = shift @args;
        die "$0: ‘--profile’ requires an argument\n" if !defined $profile;
        push @extraNixEnvArgs, "-p", $profile;
    }
    elsif ($arg eq "--set") {
        $op = "--set";
    }
    elsif ($arg eq "--non-interactive") {
        $interactive = 0;
    }
    else {
        $source = $arg;
    }
}

die "$0: please specify a .nixpkg file or URL\n" unless defined $source;


# Re-execute in a terminal, if necessary, so that if we're executed
# from a web browser, the user gets to see us.
if ($interactive && !defined $ENV{"NIX_HAVE_TERMINAL"}) {
    $ENV{"NIX_HAVE_TERMINAL"} = "1";
    $ENV{"LD_LIBRARY_PATH"} = "";
    foreach my $term ("xterm", "konsole", "gnome-terminal", "xterm") {
        exec($term, "-e", "$Nix::Config::binDir/nix-install-package", @ARGV);
    }
    die "cannot execute ‘xterm’";
}


my $tmpDir = mkTempDir("nix-install-package");


sub barf {
    my $msg = shift;
    print "\nInstallation failed: $msg\n";
    <STDIN> if $interactive;
    exit 1;
}


# Download the package description, if necessary.
my $pkgFile = $source;
if ($fromURL) {
    $pkgFile = "$tmpDir/tmp.nixpkg";
    system("/nix/store/m95130yhnla8w2brf9vpplyw8ckpf6c9-curl-7.57.0-bin/bin/curl", "-L", "--silent", $source, "-o", $pkgFile) == 0
        or barf "curl failed: $?";
}


# Read and parse the package file.
open PKGFILE, "<$pkgFile" or barf "cannot open ‘$pkgFile’: $!";
my $contents = <PKGFILE>;
close PKGFILE;

my $nameRE = "(?: [A-Za-z0-9\+\-\.\_\?\=]+ )"; # see checkStoreName()
my $systemRE = "(?: [A-Za-z0-9\+\-\_]+ )";
my $pathRE = "(?: \/ [\/A-Za-z0-9\+\-\.\_\?\=]* )";

# Note: $pathRE doesn't check that whether we're looking at a valid
# store path.  We'll let nix-env do that.

$contents =~
    / ^ \s* (\S+) \s+ ($Nix::Utils::urlRE) \s+ ($nameRE) \s+ ($systemRE) \s+ ($pathRE) \s+ ($pathRE) ( \s+ ($Nix::Utils::urlRE) )?  /x
    or barf "invalid package contents";
my $version = $1;
my $manifestURL = $2;
my $drvName = $3;
my $system = $4;
my $drvPath = $5;
my $outPath = $6;
my $binaryCacheURL = $8;

barf "invalid package version ‘$version’" unless $version eq "NIXPKG1";


if ($interactive) {
    # Ask confirmation.
    print "Do you want to install ‘$drvName’ (Y/N)? ";
    my $reply = <STDIN>;
    chomp $reply;
    exit if $reply ne "y" && $reply ne "Y";
}


if (defined $binaryCacheURL) {

    push @extraNixEnvArgs, "--option", "extra-binary-caches", $binaryCacheURL;

} else {

    # Store the manifest in the temporary directory so that we don't
    # pollute /nix/var/nix/manifests.  This also requires that we
    # don't use the Nix daemon (because otherwise
    # download-using-manifests won't see our NIX_MANIFESTS_DIRS
    # environment variable).
    $ENV{NIX_MANIFESTS_DIR} = $tmpDir;
    $ENV{NIX_REMOTE} = "";

    print "\nPulling manifests...\n";
    system("$Nix::Config::binDir/nix-pull", $manifestURL) == 0
        or barf "nix-pull failed: $?";

}


print "\nInstalling package...\n";
system("$Nix::Config::binDir/nix-env", $op, $outPath, "--force-name", $drvName, @extraNixEnvArgs) == 0
    or barf "nix-env failed: $?";


if ($interactive) {
    print "\nInstallation succeeded! Press Enter to continue.\n";
    <STDIN>;
}
