Fix addPath()

This commit is contained in:
Eelco Dolstra 2022-05-11 16:29:17 +02:00
parent 8b5f37ea92
commit feac6d8651
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
4 changed files with 47 additions and 49 deletions

View file

@ -1587,6 +1587,15 @@ static RegisterPrimOp primop_hashFile({
.fun = prim_hashFile, .fun = prim_hashFile,
}); });
static std::string_view fileTypeToString(InputAccessor::Type type)
{
return
type == InputAccessor::Type::tRegular ? "regular" :
type == InputAccessor::Type::tDirectory ? "directory" :
type == InputAccessor::Type::tSymlink ? "symlink" :
"unknown";
}
/* Read a directory (without . or ..) */ /* Read a directory (without . or ..) */
static void prim_readDir(EvalState & state, const PosIdx pos, Value * * args, Value & v) static void prim_readDir(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{ {
@ -1599,13 +1608,9 @@ static void prim_readDir(EvalState & state, const PosIdx pos, Value * * args, Va
#if 0 #if 0
// FIXME? // FIXME?
if (type == InputAccessor::Type::Misc) if (type == InputAccessor::Type::Misc)
ent.type = getFileType(path + "/" + name); type = getFileType(path + "/" + name);
#endif #endif
attrs.alloc(name).mkString( attrs.alloc(name).mkString(fileTypeToString(type.value_or(InputAccessor::Type::tMisc)));
type == InputAccessor::Type::tRegular ? "regular" :
type == InputAccessor::Type::tDirectory ? "directory" :
type == InputAccessor::Type::tSymlink ? "symlink" :
"unknown");
} }
v.mkAttrs(attrs); v.mkAttrs(attrs);
@ -1912,7 +1917,7 @@ static void addPath(
EvalState & state, EvalState & state,
const PosIdx pos, const PosIdx pos,
std::string_view name, std::string_view name,
Path path, const SourcePath & path,
Value * filterFun, Value * filterFun,
FileIngestionMethod method, FileIngestionMethod method,
const std::optional<Hash> expectedHash, const std::optional<Hash> expectedHash,
@ -1920,13 +1925,18 @@ static void addPath(
const PathSet & context) const PathSet & context)
{ {
try { try {
// FIXME
#if 0
// FIXME: handle CA derivation outputs (where path needs to // FIXME: handle CA derivation outputs (where path needs to
// be rewritten to the actual output). // be rewritten to the actual output).
auto rewrites = state.realiseContext(context); auto rewrites = state.realiseContext(context);
path = state.toRealPath(rewriteStrings(path, rewrites), context); path = state.toRealPath(rewriteStrings(path, rewrites), context);
#endif
StorePathSet refs; StorePathSet refs;
// FIXME
#if 0
if (state.store->isInStore(path)) { if (state.store->isInStore(path)) {
try { try {
auto [storePath, subPath] = state.store->toStorePath(path); auto [storePath, subPath] = state.store->toStorePath(path);
@ -1936,28 +1946,21 @@ static void addPath(
} catch (Error &) { // FIXME: should be InvalidPathError } catch (Error &) { // FIXME: should be InvalidPathError
} }
} }
// FIXME
#if 0
path = evalSettings.pureEval && expectedHash
? path
: state.checkSourcePath(path);
#endif #endif
PathFilter filter = filterFun ? ([&](const Path & path) { PathFilter filter = filterFun ? ([&](const Path & p) {
auto st = lstat(path); SourcePath path2{path.accessor, canonPath(p)};
auto st = path2.lstat();
/* Call the filter function. The first argument is the path, /* Call the filter function. The first argument is the path,
the second is a string indicating the type of the file. */ the second is a string indicating the type of the file. */
Value arg1; Value arg1;
arg1.mkString(path); arg1.mkString(path2.path);
Value arg2; Value arg2;
arg2.mkString( // assert that type is not "unknown"
S_ISREG(st.st_mode) ? "regular" : arg2.mkString(fileTypeToString(st.type));
S_ISDIR(st.st_mode) ? "directory" :
S_ISLNK(st.st_mode) ? "symlink" :
"unknown" /* not supported, will fail! */);
Value * args []{&arg1, &arg2}; Value * args []{&arg1, &arg2};
Value res; Value res;
@ -1970,10 +1973,18 @@ static void addPath(
if (expectedHash) if (expectedHash)
expectedStorePath = state.store->makeFixedOutputPath(method, *expectedHash, name); expectedStorePath = state.store->makeFixedOutputPath(method, *expectedHash, name);
// FIXME: instead of a store path, we could return a
// SourcePath that applies the filter lazily and copies to the
// store on-demand.
if (!expectedHash || !state.store->isValidPath(*expectedStorePath)) { if (!expectedHash || !state.store->isValidPath(*expectedStorePath)) {
StorePath dstPath = settings.readOnlyMode auto source = sinkToSource([&](Sink & sink) {
? state.store->computeStorePathForPath(name, path, method, htSHA256, filter).first path.dumpPath(sink, filter);
: state.store->addToStore(name, path, method, htSHA256, filter, state.repair, refs); });
auto dstPath =
settings.readOnlyMode
? state.store->computeStorePathFromDump(*source, name, method, htSHA256, refs).first
: state.store->addToStoreFromDump(*source, name, method, htSHA256, state.repair);
if (expectedHash && expectedStorePath != dstPath) if (expectedHash && expectedStorePath != dstPath)
throw Error("store path mismatch in (possibly filtered) path added from '%s'", path); throw Error("store path mismatch in (possibly filtered) path added from '%s'", path);
state.allowAndSetStorePathString(dstPath, v); state.allowAndSetStorePathString(dstPath, v);
@ -2000,8 +2011,7 @@ static void prim_filterSource(EvalState & state, const PosIdx pos, Value * * arg
.errPos = state.positions[pos] .errPos = state.positions[pos]
}); });
// FIXME: use SourcePath addPath(state, pos, path.baseName(), path, args[0], FileIngestionMethod::Recursive, std::nullopt, v, context);
addPath(state, pos, path.baseName(), path.path, args[0], FileIngestionMethod::Recursive, std::nullopt, v, context);
} }
static RegisterPrimOp primop_filterSource({ static RegisterPrimOp primop_filterSource({
@ -2096,8 +2106,7 @@ static void prim_path(EvalState & state, const PosIdx pos, Value * * args, Value
if (name.empty()) if (name.empty())
name = path->baseName(); name = path->baseName();
// FIXME: use SourcePath addPath(state, pos, name, *path, filterFun, method, expectedHash, v, context);
addPath(state, pos, name, path->path, filterFun, method, expectedHash, v, context);
} }
static RegisterPrimOp primop_path({ static RegisterPrimOp primop_path({

View file

@ -93,6 +93,9 @@ struct SourcePath
bool pathExists() const bool pathExists() const
{ return accessor.pathExists(path); } { return accessor.pathExists(path); }
InputAccessor::Stat lstat() const
{ return accessor.lstat(path); }
InputAccessor::DirEntries readDirectory() const InputAccessor::DirEntries readDirectory() const
{ return accessor.readDirectory(path); } { return accessor.readDirectory(path); }

View file

@ -220,26 +220,17 @@ StorePath Store::makeTextPath(std::string_view name, const Hash & hash,
} }
std::pair<StorePath, Hash> Store::computeStorePathForPath(std::string_view name,
const Path & srcPath, FileIngestionMethod method, HashType hashAlgo, PathFilter & filter) const
{
Hash h = method == FileIngestionMethod::Recursive
? hashPath(hashAlgo, srcPath, filter).first
: hashFile(hashAlgo, srcPath);
return std::make_pair(makeFixedOutputPath(method, h, name), h);
}
std::pair<StorePath, Hash> Store::computeStorePathFromDump( std::pair<StorePath, Hash> Store::computeStorePathFromDump(
Source & dump, Source & dump,
std::string_view name, std::string_view name,
FileIngestionMethod method, FileIngestionMethod method,
HashType hashAlgo) const HashType hashAlgo,
const StorePathSet & references) const
{ {
HashSink sink(hashAlgo); HashSink sink(hashAlgo);
dump.drainInto(sink); dump.drainInto(sink);
auto hash = sink.finish().first; auto hash = sink.finish().first;
return {makeFixedOutputPath(method, hash, name), hash}; return {makeFixedOutputPath(method, hash, name, references), hash};
} }

View file

@ -216,19 +216,14 @@ public:
const StorePathSet & references = {}, const StorePathSet & references = {},
bool hasSelfReference = false) const; bool hasSelfReference = false) const;
/* This is the preparatory part of addToStore(); it computes the /* Read-only variant of addToStoreFromDump(). It returns the store
store path to which srcPath is to be copied. Returns the store path to which a NAR or flat file would be written. */
path and the cryptographic hash of the contents of srcPath. */
// FIXME: remove
std::pair<StorePath, Hash> computeStorePathForPath(std::string_view name,
const Path & srcPath, FileIngestionMethod method = FileIngestionMethod::Recursive,
HashType hashAlgo = htSHA256, PathFilter & filter = defaultPathFilter) const;
std::pair<StorePath, Hash> computeStorePathFromDump( std::pair<StorePath, Hash> computeStorePathFromDump(
Source & dump, Source & dump,
std::string_view name, std::string_view name,
FileIngestionMethod method = FileIngestionMethod::Recursive, FileIngestionMethod method = FileIngestionMethod::Recursive,
HashType hashAlgo = htSHA256) const; HashType hashAlgo = htSHA256,
const StorePathSet & references = {}) const;
/* Preparatory part of addTextToStore(). /* Preparatory part of addTextToStore().