Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use StorePathDescriptor much more wildly #68

Merged
merged 45 commits into from
Jul 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
20799a5
WIP: Make Hash always store a valid hash type
Ericson2314 Jun 19, 2020
e7a1411
WIP bug fixing
meditans Jun 19, 2020
507aa48
WIP: Make Hash always store a valid hash type
Ericson2314 Jun 19, 2020
73ac003
More bug fixing
meditans Jun 22, 2020
3dc10f7
Merge branch 'hash-always-has-type' of github.com:obsidiansystems/nix…
meditans Jun 22, 2020
55d4bd6
Improve content address parsing
Ericson2314 Jun 22, 2020
98e5d1a
Merge remote-tracking branch 'upstream/master' into hash-always-has-type
Ericson2314 Jun 23, 2020
ec3a857
Fix and clean up hash parser
Ericson2314 Jun 23, 2020
8d51d38
Fix test suite
meditans Jun 23, 2020
987a4a0
Merge remote-tracking branch 'upstream/master' into hash-always-has-type
Ericson2314 Jun 29, 2020
a83566e
Merge branch 'hash-always-has-type' of github.com:obsidiansystems/nix…
Ericson2314 Jun 29, 2020
7ba0fae
Create the spitPrefix function in parser.hh
meditans Jun 30, 2020
77b51f4
Factor the prefix splitting in content-address
meditans Jun 30, 2020
a1f66d1
Factor the prefix splitting in hash
meditans Jun 30, 2020
b798efb
WIP initial design
meditans Jun 30, 2020
c2e7f7a
Fixed build, we still have test errors
meditans Jul 1, 2020
274a813
Correct FIXMEs in libfetchers
meditans Jul 1, 2020
6faeec3
Keep the previous name, for diffing
meditans Jul 1, 2020
d63a5de
Remove unused import
meditans Jul 1, 2020
c8c4bcf
Inline Hash::init()
meditans Jul 1, 2020
263ccdd
Rename two hash constructors to proper functions
meditans Jul 1, 2020
343d156
Fix test suite
meditans Jul 2, 2020
27c8029
Inline newFunction
meditans Jul 2, 2020
f61bc45
Get rid of the std::pair
meditans Jul 2, 2020
9462d8a
Rename fromSRI to parseSRI for constistency
meditans Jul 2, 2020
36cbc74
Inline and simplify in parseAnyPrefixed
meditans Jul 2, 2020
ea48e3a
Abstract common parsing functionality
meditans Jul 2, 2020
b6b10b1
Write the implementation for parseNonSRIUnprefixed
meditans Jul 2, 2020
1fc835a
Tighten parsing for drv files and pathinfo
meditans Jul 2, 2020
1be279a
Fix Narinfo corruption detection bug
Ericson2314 Jul 2, 2020
2f93d9f
Merge branch 'hash-always-has-type' into HEAD
Ericson2314 Jul 2, 2020
a7cd742
Move `getParsedTypeAndSRI` to a more suitable location
Ericson2314 Jul 2, 2020
13796be
Have `splitPrefix` and `splitPrefixTo` parser helpers
Ericson2314 Jul 2, 2020
dbffd30
Merge branch 'master' of github.com:NixOS/nix into hash-always-has-type
Ericson2314 Jul 3, 2020
3134db1
Merge branch 'hash-always-has-type' of github.com:obsidiansystems/nix…
Ericson2314 Jul 3, 2020
d291be4
Fix Perl
Ericson2314 Jul 3, 2020
d4250fe
Fix Perl, again...
Ericson2314 Jul 3, 2020
0f05a36
Merge branch 'master' of github.com:NixOS/nix into better-ca-parse-er…
meditans Jul 6, 2020
323d51a
Merge branch 'master' of github.com:NixOS/nix into better-ca-parse-er…
Ericson2314 Jul 9, 2020
4415765
Merge remote-tracking branch 'upstream/master' into hash-always-has-type
Ericson2314 Jul 13, 2020
c466cb2
Merge branch 'hash-always-has-type' into better-ca-parse-errors
Ericson2314 Jul 13, 2020
f8a1403
Merge commit 'c466cb2091b7a382aba1739c0320f2b6c0a04c1e' into store-pa…
Ericson2314 Jul 21, 2020
ecf65a6
Use StorePathDescriptor more widely
Ericson2314 Jul 21, 2020
f4918ec
Merge branch 'store-path-or-ca' of github.com:obsidiansystems/nix int…
Ericson2314 Jul 21, 2020
c9f83f2
Fix issues with store path descriptor round trip
Ericson2314 Jul 21, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions perl/lib/Nix/Store.xs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ SV * queryReferences(char * path)
SV * queryPathHash(char * path)
PPCODE:
try {
auto s = store()->queryPathInfo(store()->parseStorePath(path))->narHash.to_string(Base32, true);
auto s = store()->queryPathInfo(store()->parseStorePath(path))->narHash->to_string(Base32, true);
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
} catch (Error & e) {
croak("%s", e.what());
Expand All @@ -106,7 +106,7 @@ SV * queryPathInfo(char * path, int base32)
XPUSHs(&PL_sv_undef);
else
XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(*info->deriver).c_str(), 0)));
auto s = info->narHash.to_string(base32 ? Base32 : Base16, true);
auto s = info->narHash->to_string(base32 ? Base32 : Base16, true);
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
mXPUSHi(info->registrationTime);
mXPUSHi(info->narSize);
Expand Down Expand Up @@ -224,7 +224,7 @@ SV * hashString(char * algo, int base32, char * s)
SV * convertHash(char * algo, char * s, int toBase32)
PPCODE:
try {
Hash h(s, parseHashType(algo));
auto h = Hash::parseAny(s, parseHashType(algo));
string s = h.to_string(toBase32 ? Base32 : Base16, false);
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
} catch (Error & e) {
Expand Down Expand Up @@ -285,7 +285,7 @@ SV * addToStore(char * srcPath, int recursive, char * algo)
SV * makeFixedOutputPath(int recursive, char * algo, char * hash, char * name)
PPCODE:
try {
Hash h(hash, parseHashType(algo));
auto h = Hash::parseAny(hash, parseHashType(algo));
auto method = recursive ? FileIngestionMethod::Recursive : FileIngestionMethod::Flat;
auto path = store()->makeFixedOutputPath(name, FixedOutputInfo {
{
Expand Down
7 changes: 5 additions & 2 deletions src/build-remote/build-remote.cc
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,11 @@ static int _main(int argc, char * * argv)
throw Error("build of '%s' on '%s' failed: %s", store->printStorePath(*drvPath), storeUri, result.errorMsg);

StorePathSet missing;
for (auto & path : outputs)
if (!store->isValidPath(store->parseStorePath(path))) missing.insert(store->parseStorePath(path));
for (auto & path : outputs) {
auto storePath = store->parseStorePath(path);
if (!store->isValidPath(storePath))
missing.insert(store->parseStorePath(path));
}

if (!missing.empty()) {
Activity act(*logger, lvlTalkative, actUnknown, fmt("copying outputs from '%s'", storeUri));
Expand Down
5 changes: 3 additions & 2 deletions src/libexpr/common-eval-args.cc
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,9 @@ Path lookupFileArg(EvalState & state, string s)
{
if (isUri(s)) {
return state.store->toRealPath(
fetchers::downloadTarball(
state.store, resolveUri(s), "source", false).first.storePath);
state.store->makeFixedOutputPathFromCA(
fetchers::downloadTarball(
state.store, resolveUri(s), "source", false).first.storePath));
} else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') {
Path p = s.substr(1, s.size() - 2);
return state.findFile(p);
Expand Down
5 changes: 2 additions & 3 deletions src/libexpr/eval-cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -285,11 +285,10 @@ static std::shared_ptr<AttrDb> makeAttrDb(const Hash & fingerprint)
}

EvalCache::EvalCache(
bool useCache,
const Hash & fingerprint,
std::optional<std::reference_wrapper<const Hash>> useCache,
EvalState & state,
RootLoader rootLoader)
: db(useCache ? makeAttrDb(fingerprint) : nullptr)
: db(useCache ? makeAttrDb(*useCache) : nullptr)
, state(state)
, rootLoader(rootLoader)
{
Expand Down
4 changes: 2 additions & 2 deletions src/libexpr/eval-cache.hh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "hash.hh"
#include "eval.hh"

#include <functional>
#include <variant>

namespace nix::eval_cache {
Expand All @@ -26,8 +27,7 @@ class EvalCache : public std::enable_shared_from_this<EvalCache>
public:

EvalCache(
bool useCache,
const Hash & fingerprint,
std::optional<std::reference_wrapper<const Hash>> useCache,
EvalState & state,
RootLoader rootLoader);

Expand Down
9 changes: 5 additions & 4 deletions src/libexpr/flake/flake.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ static std::tuple<fetchers::Tree, FlakeRef, FlakeRef> fetchOrSubstituteTree(
auto [tree, lockedRef] = fetched.value();

debug("got tree '%s' from '%s'",
state.store->printStorePath(tree.storePath), lockedRef);
state.store->printStorePath(state.store->makeFixedOutputPathFromCA(tree.storePath)), lockedRef);

if (state.allowedPaths)
state.allowedPaths->insert(tree.actualPath);
Expand Down Expand Up @@ -179,7 +179,8 @@ static Flake getFlake(
auto flakeFile = canonPath(sourceInfo.actualPath + "/" + lockedRef.subdir + "/flake.nix");
if (!isInDir(flakeFile, sourceInfo.actualPath))
throw Error("'flake.nix' file of flake '%s' escapes from '%s'",
lockedRef, state.store->printStorePath(sourceInfo.storePath));
lockedRef,
state.store->printStorePath(state.store->makeFixedOutputPathFromCA(sourceInfo.storePath)));

Flake flake {
.originalRef = originalRef,
Expand Down Expand Up @@ -591,14 +592,14 @@ static RegisterPrimOp r2("__getFlake", 1, prim_getFlake, "flakes");

}

Fingerprint LockedFlake::getFingerprint() const
Fingerprint LockedFlake::getFingerprint(const Store & store) const
{
// FIXME: as an optimization, if the flake contains a lock file
// and we haven't changed it, then it's sufficient to use
// flake.sourceInfo.storePath for the fingerprint.
return hashString(htSHA256,
fmt("%s;%d;%d;%s",
flake.sourceInfo->storePath.to_string(),
store.makeFixedOutputPathFromCA(flake.sourceInfo->storePath).to_string(),
flake.lockedRef.input.getRevCount().value_or(0),
flake.lockedRef.input.getLastModified().value_or(0),
lockFile));
Expand Down
2 changes: 1 addition & 1 deletion src/libexpr/flake/flake.hh
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ struct LockedFlake
Flake flake;
LockFile lockFile;

Fingerprint getFingerprint() const;
Fingerprint getFingerprint(const Store & store) const;
};

struct LockFlags
Expand Down
2 changes: 1 addition & 1 deletion src/libexpr/flake/lockfile.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ LockedNode::LockedNode(const nlohmann::json & json)
throw Error("lockfile contains mutable lock '%s'", attrsToJson(lockedRef.input.toAttrs()));
}

StorePath LockedNode::computeStorePath(Store & store) const
StorePathDescriptor LockedNode::computeStorePath(Store & store) const
{
return lockedRef.input.computeStorePath(store);
}
Expand Down
3 changes: 2 additions & 1 deletion src/libexpr/flake/lockfile.hh
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "flakeref.hh"
#include "content-address.hh"

#include <nlohmann/json_fwd.hpp>

Expand Down Expand Up @@ -44,7 +45,7 @@ struct LockedNode : Node

LockedNode(const nlohmann::json & json);

StorePath computeStorePath(Store & store) const;
StorePathDescriptor computeStorePath(Store & store) const;
};

struct LockFile
Expand Down
11 changes: 9 additions & 2 deletions src/libexpr/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -718,8 +718,15 @@ std::pair<bool, std::string> EvalState::resolveSearchPathElem(const SearchPathEl

if (isUri(elem.second)) {
try {
res = { true, store->toRealPath(fetchers::downloadTarball(
store, resolveUri(elem.second), "source", false).first.storePath) };
res = {
true,
store->toRealPath(store->makeFixedOutputPathFromCA(
fetchers::downloadTarball(
store,
resolveUri(elem.second),
"source",
false).first.storePath)),
};
} catch (FileTransferError & e) {
logWarning({
.name = "Entry download",
Expand Down
16 changes: 11 additions & 5 deletions src/libexpr/primops.cc
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,13 @@ static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args
Path realPath = state.checkSourcePath(state.toRealPath(path, context));

// FIXME
if (state.store->isStorePath(path) && state.store->isValidPath(state.store->parseStorePath(path)) && isDerivation(path)) {
auto complicatedCondition = [&]() -> bool {
if (!state.store->isStorePath(path))
return false;
auto path2 = state.store->parseStorePath(path);
return state.store->isValidPath(path2) && isDerivation(path);
};
if (complicatedCondition()) {
Derivation drv = readDerivation(*state.store, realPath);
Value & w = *state.allocValue();
state.mkAttrs(w, 3 + drv.outputs.size());
Expand Down Expand Up @@ -1117,7 +1123,7 @@ static void prim_toFile(EvalState & state, const Pos & pos, Value * * args, Valu


static void addPath(EvalState & state, const Pos & pos, const string & name, const Path & path_,
Value * filterFun, FileIngestionMethod method, const Hash & expectedHash, Value & v)
Value * filterFun, FileIngestionMethod method, const std::optional<Hash> expectedHash, Value & v)
{
const auto path = evalSettings.pureEval && expectedHash ?
path_ :
Expand Down Expand Up @@ -1151,7 +1157,7 @@ static void addPath(EvalState & state, const Pos & pos, const string & name, con
expectedStorePath = state.store->makeFixedOutputPath(name, FixedOutputInfo {
{
.method = method,
.hash = expectedHash,
.hash = *expectedHash,
},
{},
});
Expand Down Expand Up @@ -1188,7 +1194,7 @@ static void prim_filterSource(EvalState & state, const Pos & pos, Value * * args
.errPos = pos
});

addPath(state, pos, std::string(baseNameOf(path)), path, args[0], FileIngestionMethod::Recursive, Hash(), v);
addPath(state, pos, std::string(baseNameOf(path)), path, args[0], FileIngestionMethod::Recursive, std::nullopt, v);
}

static void prim_path(EvalState & state, const Pos & pos, Value * * args, Value & v)
Expand All @@ -1198,7 +1204,7 @@ static void prim_path(EvalState & state, const Pos & pos, Value * * args, Value
string name;
Value * filterFun = nullptr;
auto method = FileIngestionMethod::Recursive;
Hash expectedHash;
Hash expectedHash(htSHA256);

for (auto & attr : *args[0]->attrs) {
const string & n(attr.name);
Expand Down
6 changes: 4 additions & 2 deletions src/libexpr/primops/context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,10 @@ static void prim_appendContext(EvalState & state, const Pos & pos, Value * * arg
.hint = hintfmt("Context key '%s' is not a store path", i.name),
.errPos = *i.pos
});
if (!settings.readOnlyMode)
state.store->ensurePath(state.store->parseStorePath(i.name));
if (!settings.readOnlyMode) {
auto path = state.store->parseStorePath(i.name);
state.store->ensurePath(path);
}
state.forceAttrs(*i.value, *i.pos);
auto iter = i.value->attrs->find(sPath);
if (iter != i.value->attrs->end()) {
Expand Down
5 changes: 3 additions & 2 deletions src/libexpr/primops/fetchGit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ static void prim_fetchGit(EvalState & state, const Pos & pos, Value * * args, Va
else if (n == "ref")
ref = state.forceStringNoCtx(*attr.value, *attr.pos);
else if (n == "rev")
rev = Hash(state.forceStringNoCtx(*attr.value, *attr.pos), htSHA1);
rev = Hash::parseAny(state.forceStringNoCtx(*attr.value, *attr.pos), htSHA1);
else if (n == "name")
name = state.forceStringNoCtx(*attr.value, *attr.pos);
else if (n == "submodules")
Expand Down Expand Up @@ -69,7 +69,8 @@ static void prim_fetchGit(EvalState & state, const Pos & pos, Value * * args, Va
auto [tree, input2] = input.fetch(state.store);

state.mkAttrs(v, 8);
auto storePath = state.store->printStorePath(tree.storePath);
auto storePath = state.store->printStorePath(
state.store->makeFixedOutputPathFromCA(tree.storePath));
mkString(*state.allocAttr(v, state.sOutPath), storePath, PathSet({storePath}));
// Backward compatibility: set 'rev' to
// 0000000000000000000000000000000000000000 for a dirty tree.
Expand Down
5 changes: 3 additions & 2 deletions src/libexpr/primops/fetchMercurial.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ static void prim_fetchMercurial(EvalState & state, const Pos & pos, Value * * ar
// be both a revision or a branch/tag name.
auto value = state.forceStringNoCtx(*attr.value, *attr.pos);
if (std::regex_match(value, revRegex))
rev = Hash(value, htSHA1);
rev = Hash::parseAny(value, htSHA1);
else
ref = value;
}
Expand Down Expand Up @@ -71,7 +71,8 @@ static void prim_fetchMercurial(EvalState & state, const Pos & pos, Value * * ar
auto [tree, input2] = input.fetch(state.store);

state.mkAttrs(v, 8);
auto storePath = state.store->printStorePath(tree.storePath);
auto storePath = state.store->printStorePath(
state.store->makeFixedOutputPathFromCA(tree.storePath));
mkString(*state.allocAttr(v, state.sOutPath), storePath, PathSet({storePath}));
if (input2.getRef())
mkString(*state.allocAttr(v, state.symbols.create("branch")), *input2.getRef());
Expand Down
21 changes: 18 additions & 3 deletions src/libexpr/primops/fetchTree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ void emitTreeAttrs(

state.mkAttrs(v, 8);

auto storePath = state.store->printStorePath(tree.storePath);
auto storePath = state.store->printStorePath(
state.store->makeFixedOutputPathFromCA(tree.storePath));

mkString(*state.allocAttr(v, state.sOutPath), storePath, PathSet({storePath}));

Expand Down Expand Up @@ -146,20 +147,34 @@ static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
if (evalSettings.pureEval && !expectedHash)
throw Error("in pure evaluation mode, '%s' requires a 'sha256' argument", who);

// try to substitute if we can
if (settings.useSubstitutes && expectedHash) {
auto substitutableStorePath = fetchers::trySubstitute(state.store,
unpack ? FileIngestionMethod::Recursive : FileIngestionMethod::Flat, *expectedHash, name);
if (substitutableStorePath) {
auto substitutablePath = state.store->toRealPath(*substitutableStorePath);
if (state.allowedPaths)
state.allowedPaths->insert(substitutablePath);

mkString(v, substitutablePath, PathSet({substitutablePath}));
return;
}
}

auto storePath =
unpack
? fetchers::downloadTarball(state.store, *url, name, (bool) expectedHash).first.storePath
: fetchers::downloadFile(state.store, *url, name, (bool) expectedHash).storePath;

auto path = state.store->toRealPath(storePath);
auto path = state.store->toRealPath(state.store->makeFixedOutputPathFromCA(storePath));

if (expectedHash) {
auto hash = unpack
? state.store->queryPathInfo(storePath)->narHash
: hashFile(htSHA256, path);
if (hash != *expectedHash)
throw Error((unsigned int) 102, "hash mismatch in file downloaded from '%s':\n wanted: %s\n got: %s",
*url, expectedHash->to_string(Base32, true), hash.to_string(Base32, true));
*url, expectedHash->to_string(Base32, true), hash->to_string(Base32, true));
}

if (state.allowedPaths)
Expand Down
2 changes: 1 addition & 1 deletion src/libexpr/value-to-xml.hh
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ namespace nix {

void printValueAsXML(EvalState & state, bool strict, bool location,
Value & v, std::ostream & out, PathSet & context);

}
12 changes: 7 additions & 5 deletions src/libfetchers/cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,19 @@ struct CacheImpl : Cache
ref<Store> store,
const Attrs & inAttrs,
const Attrs & infoAttrs,
const StorePath & storePath,
const StorePathDescriptor & storePathDesc,
bool immutable) override
{
_state.lock()->add.use()
(attrsToJson(inAttrs).dump())
(attrsToJson(infoAttrs).dump())
(store->printStorePath(storePath))
// FIXME should use JSON for store path descriptor
(renderStorePathDescriptor(storePathDesc))
(immutable)
(time(0)).exec();
}

std::optional<std::pair<Attrs, StorePath>> lookup(
std::optional<std::pair<Attrs, StorePathDescriptor>> lookup(
ref<Store> store,
const Attrs & inAttrs) override
{
Expand Down Expand Up @@ -90,9 +91,10 @@ struct CacheImpl : Cache
}

auto infoJson = stmt.getStr(0);
auto storePath = store->parseStorePath(stmt.getStr(1));
auto storePathDesc = parseStorePathDescriptor(stmt.getStr(1));
auto immutable = stmt.getInt(2) != 0;
auto timestamp = stmt.getInt(3);
auto storePath = store->makeFixedOutputPathFromCA(storePathDesc);

store->addTempRoot(storePath);
if (!store->isValidPath(storePath)) {
Expand All @@ -107,7 +109,7 @@ struct CacheImpl : Cache
return Result {
.expired = !immutable && (settings.tarballTtl.get() == 0 || timestamp + settings.tarballTtl < time(0)),
.infoAttrs = jsonToAttrs(nlohmann::json::parse(infoJson)),
.storePath = std::move(storePath)
.storePath = std::move(storePathDesc)
};
}
};
Expand Down
Loading