mirror of
https://github.com/NixOS/nix
synced 2024-09-19 10:50:24 -04:00
Raise EvalError if remote is missing. Unpack archive before adding to nix store
This commit is contained in:
parent
566103edb8
commit
4452d36181
|
@ -1,14 +1,17 @@
|
||||||
#include "primops.hh"
|
#include "primops.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
#include "cache.hh"
|
#include "cache.hh"
|
||||||
|
#include "tarfile.hh"
|
||||||
|
#include "archive.hh"
|
||||||
|
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
static void prim_fetchGitArchive(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
static void prim_fetchGitArchive(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
std::optional<Hash> expectedHash;
|
std::optional<Hash> expectedHash;
|
||||||
std::string name = "source.tar.gz";
|
std::optional<std::string> remote;
|
||||||
std::string remote = "";
|
std::string name = "source";
|
||||||
std::string format = "tar.gz";
|
std::string format = "tar.gz";
|
||||||
std::string version = "HEAD";
|
std::string version = "HEAD";
|
||||||
|
|
||||||
|
@ -20,7 +23,7 @@ static void prim_fetchGitArchive(EvalState & state, const PosIdx pos, Value * *
|
||||||
else if (n == "sha256")
|
else if (n == "sha256")
|
||||||
expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the sha256 of the git archive we should fetch"), htSHA256);
|
expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the sha256 of the git archive we should fetch"), htSHA256);
|
||||||
else if (n == "remote")
|
else if (n == "remote")
|
||||||
remote = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the remote of the git archive we should fetch");
|
remote.emplace(state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the remote of the git archive we should fetch"));
|
||||||
else if (n == "format")
|
else if (n == "format")
|
||||||
format = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the format of the git archive we should fetch");
|
format = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the format of the git archive we should fetch");
|
||||||
else if (n == "version")
|
else if (n == "version")
|
||||||
|
@ -32,6 +35,12 @@ static void prim_fetchGitArchive(EvalState & state, const PosIdx pos, Value * *
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!remote) {
|
||||||
|
state.debugThrowLastTrace(EvalError({
|
||||||
|
.msg = hintfmt("missing required argument 'remote' to 'fetchGitArchive'"),
|
||||||
|
.errPos = state.positions[pos]
|
||||||
|
}));
|
||||||
|
}
|
||||||
if (evalSettings.pureEval && !expectedHash) {
|
if (evalSettings.pureEval && !expectedHash) {
|
||||||
state.debugThrowLastTrace(EvalError({
|
state.debugThrowLastTrace(EvalError({
|
||||||
.msg = hintfmt("in pure evaluation mode, 'fetchGitArchive' requires a 'sha256' argument"),
|
.msg = hintfmt("in pure evaluation mode, 'fetchGitArchive' requires a 'sha256' argument"),
|
||||||
|
@ -49,7 +58,7 @@ static void prim_fetchGitArchive(EvalState & state, const PosIdx pos, Value * *
|
||||||
auto inAttrs = fetchers::Attrs({
|
auto inAttrs = fetchers::Attrs({
|
||||||
{"type", "git-archive"},
|
{"type", "git-archive"},
|
||||||
{"name", name},
|
{"name", name},
|
||||||
{"remote", remote},
|
{"remote", *remote},
|
||||||
{"version", version},
|
{"version", version},
|
||||||
{"format", format}
|
{"format", format}
|
||||||
});
|
});
|
||||||
|
@ -61,38 +70,43 @@ static void prim_fetchGitArchive(EvalState & state, const PosIdx pos, Value * *
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run `git archive`
|
|
||||||
auto [errorCode, programOutput] = runProgram(RunOptions {
|
auto [errorCode, programOutput] = runProgram(RunOptions {
|
||||||
.program = "git",
|
.program = "git",
|
||||||
.args = {"archive", "--format=" + format, "--remote=" + remote, version},
|
.args = {"archive", "--format=" + format, "--remote=" + *remote, version},
|
||||||
.mergeStderrToStdout = true
|
.mergeStderrToStdout = true
|
||||||
});
|
});
|
||||||
if (errorCode) {
|
if (errorCode) {
|
||||||
state.debugThrowLastTrace(EvalError({
|
state.debugThrowLastTrace(EvalError({
|
||||||
.msg = hintfmt(programOutput),
|
.msg = hintfmt("git archive failed with exit code %i:\n" + programOutput, errorCode),
|
||||||
.errPos = state.positions[pos]
|
.errPos = state.positions[pos]
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add archive to nix store
|
auto tarSource = StringSource(programOutput);
|
||||||
auto hash = expectedHash ? expectedHash.value() : hashString(htSHA256, programOutput);
|
auto tmpDir = createTempDir();
|
||||||
auto storePath = state.store->makeFixedOutputPath(FileIngestionMethod::Flat, hash, name);
|
AutoDelete(tmpDir, true);
|
||||||
|
unpackTarfile(tarSource, tmpDir);
|
||||||
|
|
||||||
StringSink narSink;
|
PathFilter filter = [](const Path &) { return true; };
|
||||||
narSink << "nix-archive-1" << "(" << "type" << "regular" << "contents" << programOutput << ")";
|
auto storePath = state.store->addToStore(name, tmpDir, FileIngestionMethod::Recursive, htSHA256, filter);
|
||||||
auto narSource = StringSource(narSink.s);
|
if (expectedHash) {
|
||||||
auto narHash = hashString(htSHA256, narSink.s);
|
auto narHash = state.store->queryPathInfo(storePath)->narHash;
|
||||||
auto narSize = narSink.s.size();
|
if (narHash != *expectedHash) {
|
||||||
|
state.debugThrowLastTrace(EvalError({
|
||||||
auto info = ValidPathInfo { storePath, narHash };
|
.msg = hintfmt(
|
||||||
info.narSize = narSize;
|
"hash mismatch in git archive downloaded from (remote) :\n specified: %s\n got: %s",
|
||||||
info.ca = FixedOutputHash { FileIngestionMethod::Flat, hash };
|
expectedHash->to_string(Base32, true),
|
||||||
|
narHash.to_string(Base32, true)
|
||||||
state.store->addToStore(info, narSource, NoRepair, NoCheckSigs);
|
),
|
||||||
|
.errPos = state.positions[pos]
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
state.allowAndSetStorePathString(storePath, v);
|
state.allowAndSetStorePathString(storePath, v);
|
||||||
|
|
||||||
|
auto infoAttrs = fetchers::Attrs({});
|
||||||
bool locked = (bool) expectedHash;
|
bool locked = (bool) expectedHash;
|
||||||
fetchers::getCache()->add(state.store, inAttrs, {}, storePath, locked);
|
fetchers::getCache()->add(state.store, inAttrs, infoAttrs, storePath, locked);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_fetchGitArchive({
|
static RegisterPrimOp primop_fetchGitArchive({
|
||||||
|
|
Loading…
Reference in a new issue