diff --git a/corepkgs/fetchurl/fetchurl.sh b/corepkgs/fetchurl/fetchurl.sh index 7b6243974d..1479e898b9 100644 --- a/corepkgs/fetchurl/fetchurl.sh +++ b/corepkgs/fetchurl/fetchurl.sh @@ -4,7 +4,9 @@ echo "downloading $url into $out..." wget "$url" -O "$out" || exit 1 actual=$(md5sum -b $out | cut -c1-32) -if ! test "$actual" == "$md5"; then - echo "hash is $actual, expected $md5" - exit 1 +if ! test "$md5" == "ignore"; then + if ! test "$actual" == "$md5"; then + echo "hash is $actual, expected $md5" + exit 1 + fi fi diff --git a/corepkgs/nar/nar.sh b/corepkgs/nar/nar.sh index 3dbeed0295..059bca8ba1 100644 --- a/corepkgs/nar/nar.sh +++ b/corepkgs/nar/nar.sh @@ -1,3 +1,3 @@ #! /bin/sh -/tmp/nix/bin/nix --dump --file "$path" | bzip2 > $out || exit 1 +/nix/bin/nix --dump --file "$path" | bzip2 > $out || exit 1 diff --git a/scripts/nix-pull.in b/scripts/nix-pull.in index a75c1f258b..47762e8576 100644 --- a/scripts/nix-pull.in +++ b/scripts/nix-pull.in @@ -38,7 +38,7 @@ while () { # Nix archive from the network. my $fetch = "App(IncludeFix(\"fetchurl/fetchurl.fix\"), " . - "[(\"url\", \"$url/$fn\"), (\"hash\", \"\")])"; + "[(\"url\", \"$url/$fn\"), (\"md5\", \"ignore\")])"; my $fixexpr = "App(IncludeFix(\"nar/unnar.fix\"), " . "[ (\"nar\", $fetch)" . diff --git a/scripts/nix-push.in b/scripts/nix-push.in index bf30f3a49d..fdb4323038 100644 --- a/scripts/nix-push.in +++ b/scripts/nix-push.in @@ -2,14 +2,14 @@ my @pushlist; -foreach my $hash (@ARGV) { +foreach my $id (@ARGV) { - die unless $hash =~ /^([0-9a-z]{32})$/; + die unless $id =~ /^([0-9a-z]{32})$/; # Get all paths referenced by the normalisation of the given # fstate expression. my @paths; - open PATHS, "nix -qrh $hash 2> /dev/null |" or die "nix -qrh"; + open PATHS, "nix -qrh $id 2> /dev/null |" or die "nix -qrh"; while () { chomp; next unless /^\//; @@ -21,15 +21,12 @@ foreach my $hash (@ARGV) { # a Nix archive. foreach my $path (@paths) { - # Hash the path. - my $phash = `nix-hash $path`; - $? and die "nix-hash"; - chomp $phash; - die unless $phash =~ /^([0-9a-z]{32})$/; + next unless ($path =~ /\/([0-9a-z]{32})[^\/]*/); + my $pathid = $1; # Construct a name for the Nix archive. If the file is an # fstate successor, encode this into the name. - my $name = $phash; + my $name = $pathid; if ($path =~ /-s-([0-9a-z]{32}).nix$/) { $name = "$name-s-$1"; } @@ -38,7 +35,7 @@ foreach my $hash (@ARGV) { # Construct a Fix expression that creates a Nix archive. my $fixexpr = "App(IncludeFix(\"nar/nar.fix\"), " . - "[ (\"path\", Path(\"$path\", Hash(\"$phash\"), [Include(\"$hash\")]))" . + "[ (\"path\", Slice([\"$pathid\"], [(\"$path\", \"$pathid\", [])]))" . ", (\"name\", \"$name\")" . "])"; @@ -48,13 +45,13 @@ foreach my $hash (@ARGV) { close FIX; # Instantiate a Nix expression from the Fix expression. - my $nhash = `fix $fixfile`; + my $nid = `fix $fixfile`; $? and die "instantiating Nix archive expression"; - chomp $nhash; - die unless $nhash =~ /^([0-9a-z]{32})$/; + chomp $nid; + die unless $nid =~ /^([0-9a-z]{32})$/; # Realise the Nix expression. - my $npath = `nix -qph $nhash 2> /dev/null`; + my $npath = `nix -qph $nid 2> /dev/null`; $? and die "creating Nix archive"; chomp $npath; diff --git a/src/db.cc b/src/db.cc index 89cee32ba4..64f9813a40 100644 --- a/src/db.cc +++ b/src/db.cc @@ -65,7 +65,10 @@ bool queryDB(const string & filename, const string & dbname, err = db->get(0, &kt, &dt, 0); if (err) return false; - data = string((char *) dt.get_data(), dt.get_size()); + if (!dt.get_data()) + data = ""; + else + data = string((char *) dt.get_data(), dt.get_size()); } catch (DbException e) { rethrow(e); } diff --git a/src/fix.cc b/src/fix.cc index d954abfe4b..f55074907f 100644 --- a/src/fix.cc +++ b/src/fix.cc @@ -111,6 +111,14 @@ static Expr evalExpr(Expr e) ATmatch(e, "FSId()", &s1)) return e; + if (ATgetType(e) == AT_APPL && + ((string) ATgetName(ATgetAFun(e)) == "Slice" || + (string) ATgetName(ATgetAFun(e)) == "Derive")) + { + return ATmake("FSId()", + ((string) writeTerm(e, "", 0)).c_str()); + } + /* Application. */ if (ATmatch(e, "App(, [])", &e1, &e2)) { e1 = evalExpr(e1); diff --git a/src/fstate.cc b/src/fstate.cc index cdd620cf10..11a91cffcb 100644 --- a/src/fstate.cc +++ b/src/fstate.cc @@ -21,15 +21,22 @@ typedef map Environment; class AutoDelete { string path; + bool del; public: AutoDelete(const string & p) : path(p) { + del = true; } ~AutoDelete() { - deletePath(path); + if (del) deletePath(path); + } + + void cancel() + { + del = false; } }; @@ -114,8 +121,10 @@ static void runProgram(const string & program, Environment env) if (waitpid(pid, &status, 0) != pid) throw Error("unable to wait for child"); - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + delTmpDir.cancel(); throw Error("unable to build package"); + } } @@ -336,7 +345,7 @@ static Slice normaliseFState2(FSId id, StringSet & usedPaths) bnds = ATgetNext(bnds); } - /* Check that none of the output paths exist. */ + /* Parse the outputs. */ typedef map OutPaths; OutPaths outPaths; while (!ATisEmpty(outs)) { @@ -349,14 +358,36 @@ static Slice normaliseFState2(FSId id, StringSet & usedPaths) outs = ATgetNext(outs); } + /* We can skip running the builder if we can expand all output + paths from their ids. */ + bool fastBuild = false; +#if 0 for (OutPaths::iterator i = outPaths.begin(); i != outPaths.end(); i++) - if (pathExists(i->first)) - throw Error(format("path `%1%' exists") % i->first); + { + try { + expandId(i->second, i->first); + } catch (...) { + fastBuild = false; + break; + } + } +#endif - /* Run the builder. */ - runProgram(builder, env); + if (!fastBuild) { + + /* Check that none of the outputs exist. */ + for (OutPaths::iterator i = outPaths.begin(); + i != outPaths.end(); i++) + if (pathExists(i->first)) + throw Error(format("path `%1%' exists") % i->first); + + /* Run the builder. */ + runProgram(builder, env); + } else + debug(format("skipping build")); + Slice slice; /* Check whether the output paths were created, and register each diff --git a/src/store.cc b/src/store.cc index c8b3bd37f4..d75458d8a5 100644 --- a/src/store.cc +++ b/src/store.cc @@ -86,6 +86,7 @@ void copyPath(string src, string dst) void registerSubstitute(const FSId & srcId, const FSId & subId) { +#if 0 Strings subs; queryListDB(nixDB, dbSubstitutes, srcId, subs); /* non-existence = ok */ @@ -94,6 +95,12 @@ void registerSubstitute(const FSId & srcId, const FSId & subId) subs.push_back(subId); + setListDB(nixDB, dbSubstitutes, srcId, subs); +#endif + + /* For now, accept only one substitute per id. */ + Strings subs; + subs.push_back(subId); setListDB(nixDB, dbSubstitutes, srcId, subs); } @@ -126,6 +133,8 @@ void unregisterPath(const string & _path) return; FSId id(parseHash(_id)); + delDB(nixDB, dbPath2Id, path); + /* begin transaction */ Strings paths, paths2; @@ -140,6 +149,7 @@ void unregisterPath(const string & _path) setListDB(nixDB, dbId2Paths, id, paths2); /* end transaction */ + } @@ -189,32 +199,31 @@ string expandId(const FSId & id, const string & target, } } -#if 0 /* Try to realise the substitutes. */ Strings subs; queryListDB(nixDB, dbSubstitutes, id, subs); /* non-existence = ok */ for (Strings::iterator it = subs.begin(); it != subs.end(); it++) { - realiseSlice(normaliseFState(*it)); + FSId subId = parseHash(*it); + Slice slice = normaliseFState(subId); + realiseSlice(slice); - FState nf = realiseFState(hash2fstate(parseHash(*it)), dummy); - string path = fstatePath(nf); - - if (hashPath(path) != hash) - throw Error(format("bad substitute in `%1%'") % (string) path); + Strings paths = fstatePaths(subId, true); + if (paths.size() != 1) + throw Error("substitute created more than 1 path"); + string path = *(paths.begin()); if (target.empty()) return path; /* !!! prefix */ else { if (path != target) { copyPath(path, target); - registerPath(target, hash); + registerPath(target, id); } return target; } } -#endif throw Error(format("cannot expand id `%1%'") % (string) id); }