mirror of
https://github.com/NixOS/nix
synced 2025-07-07 01:51:47 +02:00
GitArchiveInputScheme: Verify the locked tree hash
This commit is contained in:
parent
ca26ce994b
commit
219510b6ab
3 changed files with 36 additions and 19 deletions
|
@ -132,24 +132,24 @@ std::pair<StorePath, Input> Input::fetchToStore(ref<Store> store) const
|
||||||
return {std::move(storePath), input};
|
return {std::move(storePath), input};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Input::checkLocks(Input & input) const
|
void InputScheme::checkLocks(const Input & specified, const Input & final) const
|
||||||
{
|
{
|
||||||
if (auto prevNarHash = getNarHash()) {
|
if (auto prevNarHash = specified.getNarHash()) {
|
||||||
if (input.getNarHash() != prevNarHash)
|
if (final.getNarHash() != prevNarHash)
|
||||||
throw Error((unsigned int) 102, "NAR hash mismatch in input '%s', expected '%s'",
|
throw Error((unsigned int) 102, "NAR hash mismatch in input '%s', expected '%s'",
|
||||||
to_string(), prevNarHash->to_string(SRI, true));
|
specified.to_string(), prevNarHash->to_string(SRI, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto prevLastModified = getLastModified()) {
|
if (auto prevLastModified = specified.getLastModified()) {
|
||||||
if (input.getLastModified() != prevLastModified)
|
if (final.getLastModified() != prevLastModified)
|
||||||
throw Error("'lastModified' attribute mismatch in input '%s', expected %d",
|
throw Error("'lastModified' attribute mismatch in input '%s', expected %d",
|
||||||
input.to_string(), *prevLastModified);
|
final.to_string(), *prevLastModified);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto prevRevCount = getRevCount()) {
|
if (auto prevRevCount = specified.getRevCount()) {
|
||||||
if (input.getRevCount() != prevRevCount)
|
if (final.getRevCount() != prevRevCount)
|
||||||
throw Error("'revCount' attribute mismatch in input '%s', expected %d",
|
throw Error("'revCount' attribute mismatch in input '%s', expected %d",
|
||||||
input.to_string(), *prevRevCount);
|
final.to_string(), *prevRevCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ std::pair<ref<InputAccessor>, Input> Input::getAccessor(ref<Store> store) const
|
||||||
try {
|
try {
|
||||||
auto [accessor, final] = scheme->getAccessor(store, *this);
|
auto [accessor, final] = scheme->getAccessor(store, *this);
|
||||||
accessor->fingerprint = scheme->getFingerprint(store, final);
|
accessor->fingerprint = scheme->getFingerprint(store, final);
|
||||||
checkLocks(final);
|
scheme->checkLocks(*this, final);
|
||||||
return {accessor, std::move(final)};
|
return {accessor, std::move(final)};
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
e.addTrace({}, "while fetching the input '%s'", to_string());
|
e.addTrace({}, "while fetching the input '%s'", to_string());
|
||||||
|
|
|
@ -92,10 +92,6 @@ public:
|
||||||
// For locked inputs, returns a string that uniquely specifies the
|
// For locked inputs, returns a string that uniquely specifies the
|
||||||
// content of the input (typically a commit hash or content hash).
|
// content of the input (typically a commit hash or content hash).
|
||||||
std::optional<std::string> getFingerprint(ref<Store> store) const;
|
std::optional<std::string> getFingerprint(ref<Store> store) const;
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
void checkLocks(Input & input) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The InputScheme represents a type of fetcher. Each fetcher
|
/* The InputScheme represents a type of fetcher. Each fetcher
|
||||||
|
@ -142,6 +138,8 @@ struct InputScheme
|
||||||
{ return std::nullopt; }
|
{ return std::nullopt; }
|
||||||
|
|
||||||
virtual std::optional<std::string> getFingerprint(ref<Store> store, const Input & input) const;
|
virtual std::optional<std::string> getFingerprint(ref<Store> store, const Input & input) const;
|
||||||
|
|
||||||
|
virtual void checkLocks(const Input & specified, const Input & final) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
void registerInputScheme(std::shared_ptr<InputScheme> && fetcher);
|
void registerInputScheme(std::shared_ptr<InputScheme> && fetcher);
|
||||||
|
|
|
@ -107,8 +107,11 @@ struct GitArchiveInputScheme : InputScheme
|
||||||
{
|
{
|
||||||
if (maybeGetStrAttr(attrs, "type") != type()) return {};
|
if (maybeGetStrAttr(attrs, "type") != type()) return {};
|
||||||
|
|
||||||
|
static std::unordered_set<std::string> known =
|
||||||
|
{"type", "owner", "repo", "ref", "rev", "narHash", "lastModified", "host", "treeHash"};
|
||||||
|
|
||||||
for (auto & [name, value] : attrs)
|
for (auto & [name, value] : attrs)
|
||||||
if (name != "type" && name != "owner" && name != "repo" && name != "ref" && name != "rev" && name != "narHash" && name != "lastModified" && name != "host")
|
if (!known.contains(name))
|
||||||
throw Error("unsupported input attribute '%s'", name);
|
throw Error("unsupported input attribute '%s'", name);
|
||||||
|
|
||||||
getStrAttr(attrs, "owner");
|
getStrAttr(attrs, "owner");
|
||||||
|
@ -155,6 +158,23 @@ struct GitArchiveInputScheme : InputScheme
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<Hash> getTreeHash(const Input & input) const
|
||||||
|
{
|
||||||
|
if (auto treeHash = maybeGetStrAttr(input.attrs, "treeHash"))
|
||||||
|
return Hash::parseAny(*treeHash, htSHA1);
|
||||||
|
else
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkLocks(const Input & specified, const Input & final) const override
|
||||||
|
{
|
||||||
|
if (auto prevTreeHash = getTreeHash(specified)) {
|
||||||
|
if (getTreeHash(final) != prevTreeHash)
|
||||||
|
throw Error("Git tree hash mismatch in input '%s', expected '%s'",
|
||||||
|
specified.to_string(), prevTreeHash->gitRev());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<std::string> getAccessToken(const std::string & host) const
|
std::optional<std::string> getAccessToken(const std::string & host) const
|
||||||
{
|
{
|
||||||
auto tokens = fetchSettings.accessTokens.get();
|
auto tokens = fetchSettings.accessTokens.get();
|
||||||
|
@ -214,9 +234,6 @@ struct GitArchiveInputScheme : InputScheme
|
||||||
|
|
||||||
auto treeHash = importTarball(*source);
|
auto treeHash = importTarball(*source);
|
||||||
|
|
||||||
// FIXME: verify against locked tree hash.
|
|
||||||
input.attrs.insert_or_assign("treeHash", treeHash.gitRev());
|
|
||||||
|
|
||||||
cache->upsertFact(treeHashKey, treeHash.gitRev());
|
cache->upsertFact(treeHashKey, treeHash.gitRev());
|
||||||
|
|
||||||
return {std::move(input), treeHash};
|
return {std::move(input), treeHash};
|
||||||
|
@ -226,6 +243,8 @@ struct GitArchiveInputScheme : InputScheme
|
||||||
{
|
{
|
||||||
auto [input, treeHash] = downloadArchive(store, _input);
|
auto [input, treeHash] = downloadArchive(store, _input);
|
||||||
|
|
||||||
|
input.attrs.insert_or_assign("treeHash", treeHash.gitRev());
|
||||||
|
|
||||||
auto accessor = makeTarballCacheAccessor(treeHash);
|
auto accessor = makeTarballCacheAccessor(treeHash);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue