mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2025-02-16 23:27:17 +02:00
Remove InputScheme::fetchToStore()
InputSchemes now only have a getAccessor(). They could be implemented internally by fetching the input to the store, but in that case they will just return a FSInputAccessor.
This commit is contained in:
parent
360a1284db
commit
55c63c9b89
13 changed files with 168 additions and 162 deletions
|
@ -94,7 +94,7 @@ SourcePath lookupFileArg(EvalState & state, std::string_view s)
|
|||
if (isUri(s)) {
|
||||
auto storePath = fetchers::downloadTarball(
|
||||
state.store, resolveUri(s), "source", false).first;
|
||||
auto accessor = makeFSInputAccessor(CanonPath(state.store->toRealPath(storePath)));
|
||||
auto accessor = makeStorePathAccessor(state.store, storePath);
|
||||
state.registerAccessor(accessor);
|
||||
return {accessor, CanonPath::root};
|
||||
} else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') {
|
||||
|
|
|
@ -791,7 +791,7 @@ SourcePath EvalState::findFile(SearchPath & searchPath, const std::string_view p
|
|||
try {
|
||||
auto storePath = fetchers::downloadTarball(
|
||||
store, resolveUri(elem.second), "source", false).first;
|
||||
auto accessor = makeFSInputAccessor(CanonPath(store->toRealPath(storePath)));
|
||||
auto accessor = makeStorePathAccessor(store, storePath);
|
||||
registerAccessor(accessor);
|
||||
res.emplace(SourcePath {accessor, CanonPath::root});
|
||||
} catch (FileTransferError & e) {
|
||||
|
|
|
@ -115,32 +115,40 @@ bool Input::contains(const Input & other) const
|
|||
|
||||
std::pair<StorePath, Input> Input::fetchToStore(ref<Store> store) const
|
||||
{
|
||||
if (!scheme)
|
||||
throw Error("cannot fetch unsupported input '%s'", attrsToJSON(toAttrs()));
|
||||
|
||||
auto [storePath, input] = [&]() -> std::pair<StorePath, Input> {
|
||||
try {
|
||||
return scheme->fetchToStore(store, *this);
|
||||
auto [accessor, input2] = getAccessor(store);
|
||||
|
||||
// FIXME: add an optimisation for the case where the
|
||||
// accessor is an FSInputAccessor pointing to a store
|
||||
// path.
|
||||
auto source = sinkToSource([&, accessor{accessor}](Sink & sink) {
|
||||
accessor->dumpPath(CanonPath::root, sink);
|
||||
});
|
||||
|
||||
auto storePath = store->addToStoreFromDump(*source, input2.getName());
|
||||
|
||||
return {storePath, input2};
|
||||
} catch (Error & e) {
|
||||
e.addTrace({}, "while fetching the input '%s'", to_string());
|
||||
throw;
|
||||
}
|
||||
}();
|
||||
|
||||
checkLocked(*store, storePath, input);
|
||||
|
||||
return {std::move(storePath), input};
|
||||
}
|
||||
|
||||
void Input::checkLocked(Store & store, const StorePath & storePath, Input & input) const
|
||||
void Input::checkLocks(Input & input) const
|
||||
{
|
||||
#if 0
|
||||
auto narHash = store.queryPathInfo(storePath)->narHash;
|
||||
input.attrs.insert_or_assign("narHash", narHash.to_string(SRI, true));
|
||||
#endif
|
||||
|
||||
if (auto prevNarHash = getNarHash()) {
|
||||
if (narHash != *prevNarHash)
|
||||
throw Error((unsigned int) 102, "NAR hash mismatch in input '%s' (%s), expected '%s', got '%s'",
|
||||
to_string(), store.printStorePath(storePath), prevNarHash->to_string(SRI, true), narHash.to_string(SRI, true));
|
||||
if (input.getNarHash() != prevNarHash)
|
||||
throw Error((unsigned int) 102, "NAR hash mismatch in input '%s', expected '%s'",
|
||||
to_string(), prevNarHash->to_string(SRI, true));
|
||||
}
|
||||
|
||||
if (auto prevLastModified = getLastModified()) {
|
||||
|
@ -155,9 +163,12 @@ void Input::checkLocked(Store & store, const StorePath & storePath, Input & inpu
|
|||
input.to_string(), *prevRevCount);
|
||||
}
|
||||
|
||||
// FIXME
|
||||
#if 0
|
||||
input.locked = true;
|
||||
|
||||
assert(input.hasAllInfo());
|
||||
#endif
|
||||
}
|
||||
|
||||
std::pair<ref<InputAccessor>, Input> Input::getAccessor(ref<Store> store) const
|
||||
|
@ -166,7 +177,9 @@ std::pair<ref<InputAccessor>, Input> Input::getAccessor(ref<Store> store) const
|
|||
throw Error("cannot fetch unsupported input '%s'", attrsToJSON(toAttrs()));
|
||||
|
||||
try {
|
||||
return scheme->getAccessor(store, *this);
|
||||
auto [accessor, final] = scheme->getAccessor(store, *this);
|
||||
checkLocks(final);
|
||||
return {accessor, std::move(final)};
|
||||
} catch (Error & e) {
|
||||
e.addTrace({}, "while fetching the input '%s'", to_string());
|
||||
throw;
|
||||
|
@ -262,7 +275,7 @@ std::optional<std::string> Input::getFingerprint(ref<Store> store) const
|
|||
return scheme->getFingerprint(store, *this);
|
||||
}
|
||||
|
||||
ParsedURL InputScheme::toURL(const Input & input)
|
||||
ParsedURL InputScheme::toURL(const Input & input) const
|
||||
{
|
||||
throw Error("don't know how to convert input '%s' to a URL", attrsToJSON(input.attrs));
|
||||
}
|
||||
|
@ -270,7 +283,7 @@ ParsedURL InputScheme::toURL(const Input & input)
|
|||
Input InputScheme::applyOverrides(
|
||||
const Input & input,
|
||||
std::optional<std::string> ref,
|
||||
std::optional<Hash> rev)
|
||||
std::optional<Hash> rev) const
|
||||
{
|
||||
if (ref)
|
||||
throw Error("don't know how to set branch/tag name of input '%s' to '%s'", input.to_string(), *ref);
|
||||
|
@ -288,31 +301,9 @@ void InputScheme::putFile(
|
|||
throw Error("input '%s' does not support modifying file '%s'", input.to_string(), path);
|
||||
}
|
||||
|
||||
void InputScheme::clone(const Input & input, const Path & destDir)
|
||||
void InputScheme::clone(const Input & input, const Path & destDir) const
|
||||
{
|
||||
throw Error("do not know how to clone input '%s'", input.to_string());
|
||||
}
|
||||
|
||||
std::pair<StorePath, Input> InputScheme::fetchToStore(ref<Store> store, const Input & input)
|
||||
{
|
||||
auto [accessor, input2] = getAccessor(store, input);
|
||||
|
||||
auto source = sinkToSource([&, accessor{accessor}](Sink & sink) {
|
||||
accessor->dumpPath(CanonPath::root, sink);
|
||||
});
|
||||
|
||||
auto storePath = store->addToStoreFromDump(*source, "source");
|
||||
|
||||
return {storePath, input2};
|
||||
}
|
||||
|
||||
std::pair<ref<InputAccessor>, Input> InputScheme::getAccessor(ref<Store> store, const Input & input)
|
||||
{
|
||||
auto [storePath, input2] = fetchToStore(store, input);
|
||||
|
||||
input.checkLocked(*store, storePath, input2);
|
||||
|
||||
return {makeFSInputAccessor(CanonPath(store->toRealPath(storePath))), input2};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
void checkLocked(Store & store, const StorePath & storePath, Input & input) const;
|
||||
void checkLocks(Input & input) const;
|
||||
};
|
||||
|
||||
/* The InputScheme represents a type of fetcher. Each fetcher
|
||||
|
@ -116,20 +116,20 @@ struct InputScheme
|
|||
virtual ~InputScheme()
|
||||
{ }
|
||||
|
||||
virtual std::optional<Input> inputFromURL(const ParsedURL & url) = 0;
|
||||
virtual std::optional<Input> inputFromURL(const ParsedURL & url) const = 0;
|
||||
|
||||
virtual std::optional<Input> inputFromAttrs(const Attrs & attrs) = 0;
|
||||
virtual std::optional<Input> inputFromAttrs(const Attrs & attrs) const = 0;
|
||||
|
||||
virtual ParsedURL toURL(const Input & input);
|
||||
virtual ParsedURL toURL(const Input & input) const;
|
||||
|
||||
virtual bool hasAllInfo(const Input & input) = 0;
|
||||
virtual bool hasAllInfo(const Input & input) const = 0;
|
||||
|
||||
virtual Input applyOverrides(
|
||||
const Input & input,
|
||||
std::optional<std::string> ref,
|
||||
std::optional<Hash> rev);
|
||||
std::optional<Hash> rev) const;
|
||||
|
||||
virtual void clone(const Input & input, const Path & destDir);
|
||||
virtual void clone(const Input & input, const Path & destDir) const;
|
||||
|
||||
virtual void putFile(
|
||||
const Input & input,
|
||||
|
@ -137,13 +137,7 @@ struct InputScheme
|
|||
std::string_view contents,
|
||||
std::optional<std::string> commitMsg) const;
|
||||
|
||||
/* Note: the default implementations of fetchToStore() and
|
||||
getAccessor() are defined using the other, so implementations
|
||||
have to override at least one. */
|
||||
|
||||
virtual std::pair<StorePath, Input> fetchToStore(ref<Store> store, const Input & input);
|
||||
|
||||
virtual std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store, const Input & input);
|
||||
virtual std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store, const Input & input) const = 0;
|
||||
|
||||
virtual std::optional<CanonPath> isRelative(const Input & input) const
|
||||
{ return std::nullopt; }
|
||||
|
|
|
@ -140,7 +140,7 @@ bool isNotDotGitDirectory(const Path & path)
|
|||
|
||||
struct GitInputScheme : InputScheme
|
||||
{
|
||||
std::optional<Input> inputFromURL(const ParsedURL & url) override
|
||||
std::optional<Input> inputFromURL(const ParsedURL & url) const override
|
||||
{
|
||||
if (url.scheme != "git" &&
|
||||
url.scheme != "git+http" &&
|
||||
|
@ -169,7 +169,7 @@ struct GitInputScheme : InputScheme
|
|||
return inputFromAttrs(attrs);
|
||||
}
|
||||
|
||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) override
|
||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) const override
|
||||
{
|
||||
if (maybeGetStrAttr(attrs, "type") != "git") return {};
|
||||
|
||||
|
@ -192,7 +192,7 @@ struct GitInputScheme : InputScheme
|
|||
return input;
|
||||
}
|
||||
|
||||
ParsedURL toURL(const Input & input) override
|
||||
ParsedURL toURL(const Input & input) const override
|
||||
{
|
||||
auto url = parseURL(getStrAttr(input.attrs, "url"));
|
||||
if (url.scheme != "git") url.scheme = "git+" + url.scheme;
|
||||
|
@ -203,7 +203,7 @@ struct GitInputScheme : InputScheme
|
|||
return url;
|
||||
}
|
||||
|
||||
bool hasAllInfo(const Input & input) override
|
||||
bool hasAllInfo(const Input & input) const override
|
||||
{
|
||||
bool maybeDirty = !input.getRef();
|
||||
bool shallow = maybeGetBoolAttr(input.attrs, "shallow").value_or(false);
|
||||
|
@ -215,7 +215,7 @@ struct GitInputScheme : InputScheme
|
|||
Input applyOverrides(
|
||||
const Input & input,
|
||||
std::optional<std::string> ref,
|
||||
std::optional<Hash> rev) override
|
||||
std::optional<Hash> rev) const override
|
||||
{
|
||||
auto res(input);
|
||||
if (rev) res.attrs.insert_or_assign("rev", rev->gitRev());
|
||||
|
@ -225,7 +225,7 @@ struct GitInputScheme : InputScheme
|
|||
return res;
|
||||
}
|
||||
|
||||
void clone(const Input & input, const Path & destDir) override
|
||||
void clone(const Input & input, const Path & destDir) const override
|
||||
{
|
||||
auto repoInfo = getRepoInfo(input);
|
||||
|
||||
|
@ -394,7 +394,7 @@ struct GitInputScheme : InputScheme
|
|||
return repoInfo;
|
||||
}
|
||||
|
||||
std::set<CanonPath> listFiles(const RepoInfo & repoInfo)
|
||||
std::set<CanonPath> listFiles(const RepoInfo & repoInfo) const
|
||||
{
|
||||
auto gitOpts = Strings({ "-C", repoInfo.url, "--git-dir", repoInfo.gitDir, "ls-files", "-z" });
|
||||
if (repoInfo.submodules)
|
||||
|
@ -409,14 +409,14 @@ struct GitInputScheme : InputScheme
|
|||
return res;
|
||||
}
|
||||
|
||||
void updateRev(Input & input, const RepoInfo & repoInfo, const std::string & ref)
|
||||
void updateRev(Input & input, const RepoInfo & repoInfo, const std::string & ref) const
|
||||
{
|
||||
if (!input.getRev())
|
||||
input.attrs.insert_or_assign("rev",
|
||||
Hash::parseAny(chomp(runProgram("git", true, { "-C", repoInfo.url, "--git-dir", repoInfo.gitDir, "rev-parse", ref })), htSHA1).gitRev());
|
||||
}
|
||||
|
||||
uint64_t getLastModified(const RepoInfo & repoInfo, const std::string & repoDir, const std::string & ref)
|
||||
uint64_t getLastModified(const RepoInfo & repoInfo, const std::string & repoDir, const std::string & ref) const
|
||||
{
|
||||
return
|
||||
repoInfo.hasHead
|
||||
|
@ -426,7 +426,7 @@ struct GitInputScheme : InputScheme
|
|||
: 0;
|
||||
}
|
||||
|
||||
uint64_t getRevCount(const RepoInfo & repoInfo, const std::string & repoDir, const Hash & rev)
|
||||
uint64_t getRevCount(const RepoInfo & repoInfo, const std::string & repoDir, const Hash & rev) const
|
||||
{
|
||||
// FIXME: cache this.
|
||||
return
|
||||
|
@ -437,7 +437,7 @@ struct GitInputScheme : InputScheme
|
|||
: 0;
|
||||
}
|
||||
|
||||
std::string getDefaultRef(const RepoInfo & repoInfo)
|
||||
std::string getDefaultRef(const RepoInfo & repoInfo) const
|
||||
{
|
||||
auto head = repoInfo.isLocal
|
||||
? readHead(repoInfo.url)
|
||||
|
@ -449,11 +449,14 @@ struct GitInputScheme : InputScheme
|
|||
return *head;
|
||||
}
|
||||
|
||||
std::pair<StorePath, Input> fetchToStore(ref<Store> store, const Input & _input) override
|
||||
StorePath fetchToStore(
|
||||
ref<Store> store,
|
||||
RepoInfo & repoInfo,
|
||||
Input & input) const
|
||||
{
|
||||
Input input(_input);
|
||||
assert(!repoInfo.isDirty);
|
||||
|
||||
auto repoInfo = getRepoInfo(input);
|
||||
auto origRev = input.getRev();
|
||||
|
||||
std::string name = input.getName();
|
||||
|
||||
|
@ -466,15 +469,21 @@ struct GitInputScheme : InputScheme
|
|||
});
|
||||
};
|
||||
|
||||
auto makeResult = [&](const Attrs & infoAttrs, StorePath && storePath)
|
||||
-> std::pair<StorePath, Input>
|
||||
auto makeResult = [&](const Attrs & infoAttrs, const StorePath & storePath) -> StorePath
|
||||
{
|
||||
assert(input.getRev());
|
||||
assert(!_input.getRev() || _input.getRev() == input.getRev());
|
||||
assert(!origRev || origRev == input.getRev());
|
||||
if (!repoInfo.shallow)
|
||||
input.attrs.insert_or_assign("revCount", getIntAttr(infoAttrs, "revCount"));
|
||||
input.attrs.insert_or_assign("lastModified", getIntAttr(infoAttrs, "lastModified"));
|
||||
return {std::move(storePath), input};
|
||||
|
||||
// FIXME: remove?
|
||||
//input.attrs.erase("narHash");
|
||||
auto narHash = store->queryPathInfo(storePath)->narHash;
|
||||
input.attrs.insert_or_assign("narHash", narHash.to_string(SRI, true));
|
||||
input.locked = true;
|
||||
|
||||
return storePath;
|
||||
};
|
||||
|
||||
if (input.getRev()) {
|
||||
|
@ -482,9 +491,6 @@ struct GitInputScheme : InputScheme
|
|||
return makeResult(res->first, std::move(res->second));
|
||||
}
|
||||
|
||||
if (repoInfo.isDirty)
|
||||
return fetchFromWorkdir(store, repoInfo, std::move(input));
|
||||
|
||||
auto originalRef = input.getRef();
|
||||
auto ref = originalRef ? *originalRef : getDefaultRef(repoInfo);
|
||||
input.attrs.insert_or_assign("ref", ref);
|
||||
|
@ -674,7 +680,7 @@ struct GitInputScheme : InputScheme
|
|||
infoAttrs.insert_or_assign("revCount",
|
||||
getRevCount(repoInfo, repoDir, rev));
|
||||
|
||||
if (!_input.getRev())
|
||||
if (!origRev)
|
||||
getCache()->add(
|
||||
store,
|
||||
unlockedAttrs,
|
||||
|
@ -692,45 +698,27 @@ struct GitInputScheme : InputScheme
|
|||
return makeResult(infoAttrs, std::move(storePath));
|
||||
}
|
||||
|
||||
std::pair<StorePath, Input> fetchFromWorkdir(
|
||||
ref<Store> store,
|
||||
const RepoInfo & repoInfo,
|
||||
Input input)
|
||||
{
|
||||
/* This is an unclean working tree. So copy all tracked
|
||||
files. */
|
||||
repoInfo.checkDirty();
|
||||
|
||||
auto files = listFiles(repoInfo);
|
||||
|
||||
CanonPath repoDir(repoInfo.url);
|
||||
|
||||
PathFilter filter = [&](const Path & p) -> bool {
|
||||
return CanonPath(p).removePrefix(repoDir).isAllowed(files);
|
||||
};
|
||||
|
||||
auto storePath = store->addToStore(input.getName(), repoInfo.url, FileIngestionMethod::Recursive, htSHA256, filter);
|
||||
|
||||
// FIXME: maybe we should use the timestamp of the last
|
||||
// modified dirty file?
|
||||
input.attrs.insert_or_assign(
|
||||
"lastModified",
|
||||
getLastModified(repoInfo, repoInfo.url, "HEAD"));
|
||||
|
||||
return {std::move(storePath), input};
|
||||
}
|
||||
|
||||
std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store, const Input & _input) override
|
||||
std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store, const Input & _input) const override
|
||||
{
|
||||
Input input(_input);
|
||||
|
||||
auto repoInfo = getRepoInfo(input);
|
||||
|
||||
auto makeNotAllowedError = [url{repoInfo.url}](const CanonPath & path) -> RestrictedPathError
|
||||
{
|
||||
if (nix::pathExists(path.abs()))
|
||||
return RestrictedPathError("access to path '%s' is forbidden because it is not under Git control; maybe you should 'git add' it to the repository '%s'?", path, url);
|
||||
else
|
||||
return RestrictedPathError("path '%s' does not exist in Git repository '%s'", path, url);
|
||||
};
|
||||
|
||||
/* Unless we're using the working tree, copy the tree into the
|
||||
Nix store. TODO: We could have an accessor for fetching
|
||||
files from the Git repository directly. */
|
||||
if (input.getRef() || input.getRev() || !repoInfo.isLocal)
|
||||
return InputScheme::getAccessor(store, input);
|
||||
if (input.getRef() || input.getRev() || !repoInfo.isLocal) {
|
||||
auto storePath = fetchToStore(store, repoInfo, input);
|
||||
return {makeStorePathAccessor(store, storePath, std::move(makeNotAllowedError)), input};
|
||||
}
|
||||
|
||||
repoInfo.checkDirty();
|
||||
|
||||
|
@ -753,14 +741,6 @@ struct GitInputScheme : InputScheme
|
|||
"lastModified",
|
||||
getLastModified(repoInfo, repoInfo.url, ref));
|
||||
|
||||
auto makeNotAllowedError = [url{repoInfo.url}](const CanonPath & path) -> RestrictedPathError
|
||||
{
|
||||
if (nix::pathExists(path.abs()))
|
||||
return RestrictedPathError("access to path '%s' is forbidden because it is not under Git control; maybe you should 'git add' it to the repository '%s'?", path, url);
|
||||
else
|
||||
return RestrictedPathError("path '%s' does not exist in Git repository '%s'", path, url);
|
||||
};
|
||||
|
||||
return {makeFSInputAccessor(CanonPath(repoInfo.url), listFiles(repoInfo), std::move(makeNotAllowedError)), input};
|
||||
}
|
||||
};
|
||||
|
|
|
@ -26,11 +26,11 @@ std::regex hostRegex(hostRegexS, std::regex::ECMAScript);
|
|||
|
||||
struct GitArchiveInputScheme : InputScheme
|
||||
{
|
||||
virtual std::string type() = 0;
|
||||
virtual std::string type() const = 0;
|
||||
|
||||
virtual std::optional<std::pair<std::string, std::string>> accessHeaderFromToken(const std::string & token) const = 0;
|
||||
|
||||
std::optional<Input> inputFromURL(const ParsedURL & url) override
|
||||
std::optional<Input> inputFromURL(const ParsedURL & url) const override
|
||||
{
|
||||
if (url.scheme != type()) return {};
|
||||
|
||||
|
@ -100,7 +100,7 @@ struct GitArchiveInputScheme : InputScheme
|
|||
return input;
|
||||
}
|
||||
|
||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) override
|
||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) const override
|
||||
{
|
||||
if (maybeGetStrAttr(attrs, "type") != type()) return {};
|
||||
|
||||
|
@ -116,7 +116,7 @@ struct GitArchiveInputScheme : InputScheme
|
|||
return input;
|
||||
}
|
||||
|
||||
ParsedURL toURL(const Input & input) override
|
||||
ParsedURL toURL(const Input & input) const override
|
||||
{
|
||||
auto owner = getStrAttr(input.attrs, "owner");
|
||||
auto repo = getStrAttr(input.attrs, "repo");
|
||||
|
@ -132,7 +132,7 @@ struct GitArchiveInputScheme : InputScheme
|
|||
};
|
||||
}
|
||||
|
||||
bool hasAllInfo(const Input & input) override
|
||||
bool hasAllInfo(const Input & input) const override
|
||||
{
|
||||
return input.getRev() &&
|
||||
true; // FIXME
|
||||
|
@ -142,7 +142,7 @@ struct GitArchiveInputScheme : InputScheme
|
|||
Input applyOverrides(
|
||||
const Input & _input,
|
||||
std::optional<std::string> ref,
|
||||
std::optional<Hash> rev) override
|
||||
std::optional<Hash> rev) const override
|
||||
{
|
||||
auto input(_input);
|
||||
if (rev && ref)
|
||||
|
@ -185,7 +185,7 @@ struct GitArchiveInputScheme : InputScheme
|
|||
|
||||
virtual DownloadUrl getDownloadUrl(const Input & input) const = 0;
|
||||
|
||||
std::pair<StorePath, Input> downloadArchive(ref<Store> store, Input input)
|
||||
std::pair<StorePath, Input> downloadArchive(ref<Store> store, Input input) const
|
||||
{
|
||||
if (!maybeGetStrAttr(input.attrs, "ref")) input.attrs.insert_or_assign("ref", "HEAD");
|
||||
|
||||
|
@ -228,7 +228,7 @@ struct GitArchiveInputScheme : InputScheme
|
|||
return {res.storePath, input};
|
||||
}
|
||||
|
||||
std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store, const Input & input) override
|
||||
std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store, const Input & input) const override
|
||||
{
|
||||
auto [storePath, input2] = downloadArchive(store, input);
|
||||
|
||||
|
@ -242,7 +242,7 @@ struct GitArchiveInputScheme : InputScheme
|
|||
|
||||
struct GitHubInputScheme : GitArchiveInputScheme
|
||||
{
|
||||
std::string type() override { return "github"; }
|
||||
std::string type() const override { return "github"; }
|
||||
|
||||
std::optional<std::pair<std::string, std::string>> accessHeaderFromToken(const std::string & token) const override
|
||||
{
|
||||
|
@ -291,7 +291,7 @@ struct GitHubInputScheme : GitArchiveInputScheme
|
|||
return DownloadUrl { url, headers };
|
||||
}
|
||||
|
||||
void clone(const Input & input, const Path & destDir) override
|
||||
void clone(const Input & input, const Path & destDir) const override
|
||||
{
|
||||
auto host = maybeGetStrAttr(input.attrs, "host").value_or("github.com");
|
||||
Input::fromURL(fmt("git+https://%s/%s/%s.git",
|
||||
|
@ -303,7 +303,7 @@ struct GitHubInputScheme : GitArchiveInputScheme
|
|||
|
||||
struct GitLabInputScheme : GitArchiveInputScheme
|
||||
{
|
||||
std::string type() override { return "gitlab"; }
|
||||
std::string type() const override { return "gitlab"; }
|
||||
|
||||
std::optional<std::pair<std::string, std::string>> accessHeaderFromToken(const std::string & token) const override
|
||||
{
|
||||
|
@ -358,7 +358,7 @@ struct GitLabInputScheme : GitArchiveInputScheme
|
|||
return DownloadUrl { url, headers };
|
||||
}
|
||||
|
||||
void clone(const Input & input, const Path & destDir) override
|
||||
void clone(const Input & input, const Path & destDir) const override
|
||||
{
|
||||
auto host = maybeGetStrAttr(input.attrs, "host").value_or("gitlab.com");
|
||||
// FIXME: get username somewhere
|
||||
|
@ -371,7 +371,7 @@ struct GitLabInputScheme : GitArchiveInputScheme
|
|||
|
||||
struct SourceHutInputScheme : GitArchiveInputScheme
|
||||
{
|
||||
std::string type() override { return "sourcehut"; }
|
||||
std::string type() const override { return "sourcehut"; }
|
||||
|
||||
std::optional<std::pair<std::string, std::string>> accessHeaderFromToken(const std::string & token) const override
|
||||
{
|
||||
|
@ -445,7 +445,7 @@ struct SourceHutInputScheme : GitArchiveInputScheme
|
|||
return DownloadUrl { url, headers };
|
||||
}
|
||||
|
||||
void clone(const Input & input, const Path & destDir) override
|
||||
void clone(const Input & input, const Path & destDir) const override
|
||||
{
|
||||
auto host = maybeGetStrAttr(input.attrs, "host").value_or("git.sr.ht");
|
||||
Input::fromURL(fmt("git+https://%s/%s/%s",
|
||||
|
|
|
@ -7,7 +7,7 @@ std::regex flakeRegex("[a-zA-Z][a-zA-Z0-9_-]*", std::regex::ECMAScript);
|
|||
|
||||
struct IndirectInputScheme : InputScheme
|
||||
{
|
||||
std::optional<Input> inputFromURL(const ParsedURL & url) override
|
||||
std::optional<Input> inputFromURL(const ParsedURL & url) const override
|
||||
{
|
||||
if (url.scheme != "flake") return {};
|
||||
|
||||
|
@ -50,7 +50,7 @@ struct IndirectInputScheme : InputScheme
|
|||
return input;
|
||||
}
|
||||
|
||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) override
|
||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) const override
|
||||
{
|
||||
if (maybeGetStrAttr(attrs, "type") != "indirect") return {};
|
||||
|
||||
|
@ -68,7 +68,7 @@ struct IndirectInputScheme : InputScheme
|
|||
return input;
|
||||
}
|
||||
|
||||
ParsedURL toURL(const Input & input) override
|
||||
ParsedURL toURL(const Input & input) const override
|
||||
{
|
||||
ParsedURL url;
|
||||
url.scheme = "flake";
|
||||
|
@ -78,7 +78,7 @@ struct IndirectInputScheme : InputScheme
|
|||
return url;
|
||||
}
|
||||
|
||||
bool hasAllInfo(const Input & input) override
|
||||
bool hasAllInfo(const Input & input) const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ struct IndirectInputScheme : InputScheme
|
|||
Input applyOverrides(
|
||||
const Input & _input,
|
||||
std::optional<std::string> ref,
|
||||
std::optional<Hash> rev) override
|
||||
std::optional<Hash> rev) const override
|
||||
{
|
||||
auto input(_input);
|
||||
if (rev) input.attrs.insert_or_assign("rev", rev->gitRev());
|
||||
|
@ -94,7 +94,7 @@ struct IndirectInputScheme : InputScheme
|
|||
return input;
|
||||
}
|
||||
|
||||
std::pair<StorePath, Input> fetchToStore(ref<Store> store, const Input & input) override
|
||||
std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store, const Input & input) const override
|
||||
{
|
||||
throw Error("indirect input '%s' cannot be fetched directly", input.to_string());
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "input-accessor.hh"
|
||||
#include "util.hh"
|
||||
#include "store-api.hh"
|
||||
|
||||
#include <atomic>
|
||||
|
||||
|
@ -235,6 +236,14 @@ ref<FSInputAccessor> makeFSInputAccessor(
|
|||
return make_ref<FSInputAccessorImpl>(root, std::move(allowedPaths), std::move(makeNotAllowedError));
|
||||
}
|
||||
|
||||
ref<FSInputAccessor> makeStorePathAccessor(
|
||||
ref<Store> store,
|
||||
const StorePath & storePath,
|
||||
MakeNotAllowedError && makeNotAllowedError)
|
||||
{
|
||||
return makeFSInputAccessor(CanonPath(store->toRealPath(storePath)), {}, std::move(makeNotAllowedError));
|
||||
}
|
||||
|
||||
std::ostream & operator << (std::ostream & str, const SourcePath & path)
|
||||
{
|
||||
str << path.to_string();
|
||||
|
|
|
@ -10,6 +10,8 @@ namespace nix {
|
|||
MakeError(RestrictedPathError, Error);
|
||||
|
||||
struct SourcePath;
|
||||
class StorePath;
|
||||
class Store;
|
||||
|
||||
struct InputAccessor : public std::enable_shared_from_this<InputAccessor>
|
||||
{
|
||||
|
@ -91,6 +93,11 @@ ref<FSInputAccessor> makeFSInputAccessor(
|
|||
std::optional<std::set<CanonPath>> && allowedPaths = {},
|
||||
MakeNotAllowedError && makeNotAllowedError = {});
|
||||
|
||||
ref<FSInputAccessor> makeStorePathAccessor(
|
||||
ref<Store> store,
|
||||
const StorePath & storePath,
|
||||
MakeNotAllowedError && makeNotAllowedError = {});
|
||||
|
||||
struct SourcePath;
|
||||
|
||||
struct MemoryInputAccessor : InputAccessor
|
||||
|
|
|
@ -43,7 +43,7 @@ static std::string runHg(const Strings & args, const std::optional<std::string>
|
|||
|
||||
struct MercurialInputScheme : InputScheme
|
||||
{
|
||||
std::optional<Input> inputFromURL(const ParsedURL & url) override
|
||||
std::optional<Input> inputFromURL(const ParsedURL & url) const override
|
||||
{
|
||||
if (url.scheme != "hg+http" &&
|
||||
url.scheme != "hg+https" &&
|
||||
|
@ -69,7 +69,7 @@ struct MercurialInputScheme : InputScheme
|
|||
return inputFromAttrs(attrs);
|
||||
}
|
||||
|
||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) override
|
||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) const override
|
||||
{
|
||||
if (maybeGetStrAttr(attrs, "type") != "hg") return {};
|
||||
|
||||
|
@ -89,7 +89,7 @@ struct MercurialInputScheme : InputScheme
|
|||
return input;
|
||||
}
|
||||
|
||||
ParsedURL toURL(const Input & input) override
|
||||
ParsedURL toURL(const Input & input) const override
|
||||
{
|
||||
auto url = parseURL(getStrAttr(input.attrs, "url"));
|
||||
url.scheme = "hg+" + url.scheme;
|
||||
|
@ -98,7 +98,7 @@ struct MercurialInputScheme : InputScheme
|
|||
return url;
|
||||
}
|
||||
|
||||
bool hasAllInfo(const Input & input) override
|
||||
bool hasAllInfo(const Input & input) const override
|
||||
{
|
||||
// FIXME: ugly, need to distinguish between dirty and clean
|
||||
// default trees.
|
||||
|
@ -108,7 +108,7 @@ struct MercurialInputScheme : InputScheme
|
|||
Input applyOverrides(
|
||||
const Input & input,
|
||||
std::optional<std::string> ref,
|
||||
std::optional<Hash> rev) override
|
||||
std::optional<Hash> rev) const override
|
||||
{
|
||||
auto res(input);
|
||||
if (rev) res.attrs.insert_or_assign("rev", rev->gitRev());
|
||||
|
@ -148,9 +148,9 @@ struct MercurialInputScheme : InputScheme
|
|||
return {isLocal, isLocal ? url.path : url.base};
|
||||
}
|
||||
|
||||
std::pair<StorePath, Input> fetchToStore(ref<Store> store, const Input & _input) override
|
||||
StorePath fetchToStore(ref<Store> store, Input & input) const
|
||||
{
|
||||
Input input(_input);
|
||||
auto origRev = input.getRev();
|
||||
|
||||
auto name = input.getName();
|
||||
|
||||
|
@ -200,7 +200,7 @@ struct MercurialInputScheme : InputScheme
|
|||
|
||||
auto storePath = store->addToStore(input.getName(), actualPath, FileIngestionMethod::Recursive, htSHA256, filter);
|
||||
|
||||
return {std::move(storePath), input};
|
||||
return storePath;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -224,13 +224,13 @@ struct MercurialInputScheme : InputScheme
|
|||
});
|
||||
};
|
||||
|
||||
auto makeResult = [&](const Attrs & infoAttrs, StorePath && storePath)
|
||||
-> std::pair<StorePath, Input>
|
||||
auto makeResult = [&](const Attrs & infoAttrs, const StorePath & storePath) -> StorePath
|
||||
{
|
||||
assert(input.getRev());
|
||||
assert(!_input.getRev() || _input.getRev() == input.getRev());
|
||||
assert(!origRev || origRev == input.getRev());
|
||||
input.attrs.insert_or_assign("revCount", getIntAttr(infoAttrs, "revCount"));
|
||||
return {std::move(storePath), input};
|
||||
input.locked = true;
|
||||
return storePath;
|
||||
};
|
||||
|
||||
if (input.getRev()) {
|
||||
|
@ -310,7 +310,7 @@ struct MercurialInputScheme : InputScheme
|
|||
{"revCount", (uint64_t) revCount},
|
||||
});
|
||||
|
||||
if (!_input.getRev())
|
||||
if (!origRev)
|
||||
getCache()->add(
|
||||
store,
|
||||
unlockedAttrs,
|
||||
|
@ -327,6 +327,15 @@ struct MercurialInputScheme : InputScheme
|
|||
|
||||
return makeResult(infoAttrs, std::move(storePath));
|
||||
}
|
||||
|
||||
std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store, const Input & _input) const override
|
||||
{
|
||||
Input input(_input);
|
||||
|
||||
auto storePath = fetchToStore(store, input);
|
||||
|
||||
return {makeStorePathAccessor(store, storePath), input};
|
||||
}
|
||||
};
|
||||
|
||||
static auto rMercurialInputScheme = OnStartup([] { registerInputScheme(std::make_unique<MercurialInputScheme>()); });
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace nix::fetchers {
|
|||
|
||||
struct PathInputScheme : InputScheme
|
||||
{
|
||||
std::optional<Input> inputFromURL(const ParsedURL & url) override
|
||||
std::optional<Input> inputFromURL(const ParsedURL & url) const override
|
||||
{
|
||||
if (url.scheme != "path") return {};
|
||||
|
||||
|
@ -32,7 +32,7 @@ struct PathInputScheme : InputScheme
|
|||
return input;
|
||||
}
|
||||
|
||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) override
|
||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) const override
|
||||
{
|
||||
if (maybeGetStrAttr(attrs, "type") != "path") return {};
|
||||
|
||||
|
@ -54,7 +54,7 @@ struct PathInputScheme : InputScheme
|
|||
return input;
|
||||
}
|
||||
|
||||
ParsedURL toURL(const Input & input) override
|
||||
ParsedURL toURL(const Input & input) const override
|
||||
{
|
||||
auto query = attrsToQuery(input.attrs);
|
||||
query.erase("path");
|
||||
|
@ -75,7 +75,7 @@ struct PathInputScheme : InputScheme
|
|||
return CanonPath(path);
|
||||
}
|
||||
|
||||
bool hasAllInfo(const Input & input) override
|
||||
bool hasAllInfo(const Input & input) const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ struct PathInputScheme : InputScheme
|
|||
throw Error("cannot fetch input '%s' because it uses a relative path", input.to_string());
|
||||
}
|
||||
|
||||
std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store, const Input & input) override
|
||||
std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store, const Input & input) const override
|
||||
{
|
||||
auto absPath = getAbsPath(input);
|
||||
auto input2(input);
|
||||
|
|
|
@ -185,7 +185,7 @@ struct CurlInputScheme : InputScheme
|
|||
|
||||
virtual bool isValidURL(const ParsedURL & url) const = 0;
|
||||
|
||||
std::optional<Input> inputFromURL(const ParsedURL & url) override
|
||||
std::optional<Input> inputFromURL(const ParsedURL & url) const override
|
||||
{
|
||||
if (!isValidURL(url))
|
||||
return std::nullopt;
|
||||
|
@ -203,7 +203,7 @@ struct CurlInputScheme : InputScheme
|
|||
return input;
|
||||
}
|
||||
|
||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) override
|
||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) const override
|
||||
{
|
||||
auto type = maybeGetStrAttr(attrs, "type");
|
||||
if (type != inputType()) return {};
|
||||
|
@ -220,7 +220,7 @@ struct CurlInputScheme : InputScheme
|
|||
return input;
|
||||
}
|
||||
|
||||
ParsedURL toURL(const Input & input) override
|
||||
ParsedURL toURL(const Input & input) const override
|
||||
{
|
||||
auto url = parseURL(getStrAttr(input.attrs, "url"));
|
||||
// NAR hashes are preferred over file hashes since tar/zip
|
||||
|
@ -230,7 +230,7 @@ struct CurlInputScheme : InputScheme
|
|||
return url;
|
||||
}
|
||||
|
||||
bool hasAllInfo(const Input & input) override
|
||||
bool hasAllInfo(const Input & input) const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -250,10 +250,18 @@ struct FileInputScheme : CurlInputScheme
|
|||
: !hasTarballExtension(url.path));
|
||||
}
|
||||
|
||||
std::pair<StorePath, Input> fetchToStore(ref<Store> store, const Input & input) override
|
||||
std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store, const Input & _input) const override
|
||||
{
|
||||
auto input(_input);
|
||||
|
||||
auto file = downloadFile(store, getStrAttr(input.attrs, "url"), input.getName(), false);
|
||||
return {std::move(file.storePath), input};
|
||||
|
||||
// FIXME: remove?
|
||||
auto narHash = store->queryPathInfo(file.storePath)->narHash;
|
||||
input.attrs.insert_or_assign("narHash", narHash.to_string(SRI, true));
|
||||
input.locked = true;
|
||||
|
||||
return {makeStorePathAccessor(store, file.storePath), input};
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -271,12 +279,18 @@ struct TarballInputScheme : CurlInputScheme
|
|||
: hasTarballExtension(url.path));
|
||||
}
|
||||
|
||||
std::pair<StorePath, Input> fetchToStore(ref<Store> store, const Input & input) override
|
||||
std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store, const Input & _input) const override
|
||||
{
|
||||
return {
|
||||
downloadTarball(store, getStrAttr(input.attrs, "url"), input.getName(), false).first,
|
||||
input
|
||||
};
|
||||
auto input(_input);
|
||||
|
||||
auto storePath = downloadTarball(store, getStrAttr(input.attrs, "url"), input.getName(), false).first;
|
||||
|
||||
// FIXME: remove?
|
||||
auto narHash = store->queryPathInfo(storePath)->narHash;
|
||||
input.attrs.insert_or_assign("narHash", narHash.to_string(SRI, true));
|
||||
input.locked = true;
|
||||
|
||||
return {makeStorePathAccessor(store, storePath), input};
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -120,6 +120,7 @@ git -C $repo commit -m 'Bla3' -a
|
|||
path4=$(nix eval --impure --refresh --raw --expr "(builtins.fetchGit file://$repo).outPath")
|
||||
[[ $path2 = $path4 ]]
|
||||
|
||||
status=0
|
||||
nix eval --impure --raw --expr "(builtins.fetchGit { url = $repo; rev = \"$rev2\"; narHash = \"sha256-B5yIPHhEm0eysJKEsO7nqxprh9vcblFxpJG11gXJus1=\"; }).outPath" || status=$?
|
||||
[[ "$status" = "102" ]]
|
||||
|
||||
|
@ -223,4 +224,5 @@ rm -rf $repo/.git
|
|||
|
||||
# should succeed for a repo without commits
|
||||
git init $repo
|
||||
git -C $repo add hello # need to add at least one file to cause the root of the repo to be visible
|
||||
path10=$(nix eval --impure --raw --expr "(builtins.fetchGit \"file://$repo\").outPath")
|
||||
|
|
Loading…
Add table
Reference in a new issue