libfetchers: asyncify Input{,Scheme}::{putFile,clone}

Change-Id: I084b6fc2271ea99a9325b1969f18b83778702bea
This commit is contained in:
eldritch horrors
2025-09-12 11:52:03 +00:00
parent 078e1d7245
commit 9b01455ada
8 changed files with 104 additions and 56 deletions
+7 -3
View File
@@ -853,9 +853,13 @@ LockedFlake lockFlake(
commitMessage = cm;
}
topRef.input.putFile(
CanonPath((topRef.subdir == "" ? "" : topRef.subdir + "/") + "flake.lock"),
newLockFileS, commitMessage);
state.aio.blockOn(topRef.input.putFile(
CanonPath(
(topRef.subdir == "" ? "" : topRef.subdir + "/") + "flake.lock"
),
newLockFileS,
commitMessage
));
}
/* Rewriting the lockfile changed the top-level
+25 -15
View File
@@ -3,6 +3,7 @@
#include "lix/libstore/store-api.hh"
#include "lix/libutil/async.hh"
#include "lix/libutil/json.hh"
#include "lix/libutil/result.hh"
#include "lix/libutil/source-path.hh"
#include "lix/libfetchers/fetch-to-store.hh"
@@ -220,10 +221,13 @@ Input Input::applyOverrides(
return scheme->applyOverrides(*this, ref, rev);
}
void Input::clone(const Path & destDir) const
{
kj::Promise<Result<void>> Input::clone(const Path & destDir) const
try {
assert(scheme);
scheme->clone(*this, destDir);
TRY_AWAIT(scheme->clone(*this, destDir));
co_return result::success();
} catch (...) {
co_return result::current_exception();
}
std::optional<Path> Input::getSourcePath() const
@@ -232,13 +236,15 @@ std::optional<Path> Input::getSourcePath() const
return scheme->getSourcePath(*this);
}
void Input::putFile(
const CanonPath & path,
std::string_view contents,
std::optional<std::string> commitMsg) const
{
kj::Promise<Result<void>> Input::putFile(
const CanonPath & path, std::string_view contents, std::optional<std::string> commitMsg
) const
try {
assert(scheme);
return scheme->putFile(*this, path, contents, commitMsg);
TRY_AWAIT(scheme->putFile(*this, path, contents, commitMsg));
co_return result::success();
} catch (...) {
co_return result::current_exception();
}
std::string Input::getName() const
@@ -345,18 +351,22 @@ std::optional<Path> InputScheme::getSourcePath(const Input & input) const
return {};
}
void InputScheme::putFile(
kj::Promise<Result<void>> InputScheme::putFile(
const Input & input,
const CanonPath & path,
std::string_view contents,
std::optional<std::string> commitMsg) const
{
std::optional<std::string> commitMsg
) const
try {
throw Error("input '%s' does not support modifying file '%s'", input.to_string(), path);
} catch (...) {
co_return result::current_exception();
}
void InputScheme::clone(const Input & input, const Path & destDir) const
{
kj::Promise<Result<void>> InputScheme::clone(const Input & input, const Path & destDir) const
try {
throw Error("do not know how to clone input '%s'", input.to_string());
} catch (...) {
co_return result::current_exception();
}
}
+8 -8
View File
@@ -102,7 +102,7 @@ public:
std::optional<std::string> ref,
std::optional<Hash> rev) const;
void clone(const Path & destDir) const;
kj::Promise<Result<void>> clone(const Path & destDir) const;
std::optional<Path> getSourcePath() const;
@@ -110,10 +110,9 @@ public:
* Write a file to this input, for input types that support
* writing. Optionally commit the change (for e.g. Git inputs).
*/
void putFile(
const CanonPath & path,
std::string_view contents,
std::optional<std::string> commitMsg) const;
kj::Promise<Result<void>> putFile(
const CanonPath & path, std::string_view contents, std::optional<std::string> commitMsg
) const;
std::string getName() const;
@@ -160,15 +159,16 @@ struct InputScheme
std::optional<std::string> ref,
std::optional<Hash> rev) const;
virtual void clone(const Input & input, const Path & destDir) const;
virtual kj::Promise<Result<void>> clone(const Input & input, const Path & destDir) const;
virtual std::optional<Path> getSourcePath(const Input & input) const;
virtual void putFile(
virtual kj::Promise<Result<void>> putFile(
const Input & input,
const CanonPath & path,
std::string_view contents,
std::optional<std::string> commitMsg) const;
std::optional<std::string> commitMsg
) const;
virtual kj::Promise<Result<std::pair<StorePath, Input>>>
fetch(ref<Store> store, const Input & input) = 0;
+14 -5
View File
@@ -7,6 +7,7 @@
#include "lix/libstore/globals.hh"
#include "lix/libfetchers/builtin-fetchers.hh"
#include "lix/libutil/processes.hh"
#include "lix/libutil/result.hh"
#include "lix/libutil/tarfile.hh"
#include "lix/libstore/store-api.hh"
#include "lix/libstore/temporary-dir.hh"
@@ -398,8 +399,8 @@ struct GitInputScheme : InputScheme
return res;
}
void clone(const Input & input, const Path & destDir) const override
{
kj::Promise<Result<void>> clone(const Input & input, const Path & destDir) const override
try {
auto [isLocal, actualUrl] = getActualUrl(input);
Strings args = {"clone"};
@@ -416,6 +417,9 @@ struct GitInputScheme : InputScheme
args.push_back(destDir);
runProgram("git", true, args, true);
co_return result::success();
} catch (...) {
co_return result::current_exception();
}
std::optional<Path> getSourcePath(const Input & input) const override
@@ -426,12 +430,13 @@ struct GitInputScheme : InputScheme
return {};
}
void putFile(
kj::Promise<Result<void>> putFile(
const Input & input,
const CanonPath & path,
std::string_view contents,
std::optional<std::string> commitMsg) const override
{
std::optional<std::string> commitMsg
) const override
try {
auto root = getSourcePath(input);
if (!root)
throw Error("cannot commit '%s' to Git repository '%s' because it's not a working tree", path, input.to_string());
@@ -461,6 +466,10 @@ struct GitInputScheme : InputScheme
{ "-C", *root, "--git-dir", gitDir, "commit", std::string(path.rel()), "-F", msgPath }, true);
}
}
co_return result::success();
} catch (...) {
co_return result::current_exception();
}
std::pair<bool, std::string> getActualUrl(const Input & input) const
+30 -15
View File
@@ -4,6 +4,7 @@
#include "lix/libstore/store-api.hh"
#include "lix/libutil/async.hh"
#include "lix/libutil/regex.hh"
#include "lix/libutil/result.hh"
#include "lix/libutil/types.hh"
#include "lix/libutil/url-parts.hh"
#include "lix/libutil/git.hh"
@@ -309,13 +310,17 @@ struct GitHubInputScheme : GitArchiveInputScheme
return DownloadUrl { url, headers };
}
void clone(const Input & input, const Path & destDir) const override
{
kj::Promise<Result<void>> clone(const Input & input, const Path & destDir) const override
try {
auto host = getHost(input);
Input::fromURL(fmt("git+https://%s/%s/%s.git",
host, getOwner(input), getRepo(input)))
TRY_AWAIT(
Input::fromURL(fmt("git+https://%s/%s/%s.git", host, getOwner(input), getRepo(input)))
.applyOverrides(input.getRef(), input.getRev())
.clone(destDir);
.clone(destDir)
);
co_return result::success();
} catch (...) {
co_return result::current_exception();
}
Headers makeHeadersWithAuthTokens(const std::string & host) const
@@ -391,14 +396,19 @@ struct GitLabInputScheme : GitArchiveInputScheme
return DownloadUrl { url, headers };
}
void clone(const Input & input, const Path & destDir) const override
{
kj::Promise<Result<void>> clone(const Input & input, const Path & destDir) const override
try {
auto host = maybeGetStrAttr(input.attrs, "host").value_or("gitlab.com");
// FIXME: get username somewhere
Input::fromURL(fmt("git+https://%s/%s/%s.git",
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo")))
TRY_AWAIT(Input::fromURL(fmt("git+https://%s/%s/%s.git",
host,
getStrAttr(input.attrs, "owner"),
getStrAttr(input.attrs, "repo")))
.applyOverrides(input.getRef(), input.getRev())
.clone(destDir);
.clone(destDir));
co_return result::success();
} catch (...) {
co_return result::current_exception();
}
};
@@ -485,13 +495,18 @@ struct SourceHutInputScheme : GitArchiveInputScheme
return DownloadUrl { url, headers };
}
void clone(const Input & input, const Path & destDir) const override
{
kj::Promise<Result<void>> clone(const Input & input, const Path & destDir) const override
try {
auto host = maybeGetStrAttr(input.attrs, "host").value_or("git.sr.ht");
Input::fromURL(fmt("git+https://%s/%s/%s",
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo")))
TRY_AWAIT(Input::fromURL(fmt("git+https://%s/%s/%s",
host,
getStrAttr(input.attrs, "owner"),
getStrAttr(input.attrs, "repo")))
.applyOverrides(input.getRef(), input.getRev())
.clone(destDir);
.clone(destDir));
co_return result::success();
} catch (...) {
co_return result::current_exception();
}
};
+8 -3
View File
@@ -6,6 +6,7 @@
#include "lix/libutil/processes.hh"
#include "lix/libstore/store-api.hh"
#include "lix/libstore/temporary-dir.hh"
#include "lix/libutil/result.hh"
#include "lix/libutil/url-parts.hh"
#include "lix/libutil/users.hh"
@@ -128,12 +129,13 @@ struct MercurialInputScheme : InputScheme
return {};
}
void putFile(
kj::Promise<Result<void>> putFile(
const Input & input,
const CanonPath & path,
std::string_view contents,
std::optional<std::string> commitMsg) const override
{
std::optional<std::string> commitMsg
) const override
try {
auto [isLocal, repoPath] = getActualUrl(input);
if (!isLocal)
throw Error("cannot commit '%s' to Mercurial repository '%s' because it's not a working tree", path, input.to_string());
@@ -149,6 +151,9 @@ struct MercurialInputScheme : InputScheme
if (commitMsg)
runHg(
{ "commit", absPath.abs(), "-m", *commitMsg });
co_return result::success();
} catch (...) {
co_return result::current_exception();
}
std::pair<bool, std::string> getActualUrl(const Input & input) const
+8 -3
View File
@@ -3,6 +3,7 @@
#include "lix/libstore/store-api.hh"
#include "lix/libutil/archive.hh"
#include "lix/libutil/async-io.hh"
#include "lix/libutil/result.hh"
namespace nix::fetchers {
@@ -82,13 +83,17 @@ struct PathInputScheme : InputScheme
return getStrAttr(input.attrs, "path");
}
void putFile(
kj::Promise<Result<void>> putFile(
const Input & input,
const CanonPath & path,
std::string_view contents,
std::optional<std::string> commitMsg) const override
{
std::optional<std::string> commitMsg
) const override
try {
writeFile((CanonPath(getAbsPath(input)) + path).abs(), contents);
co_return result::success();
} catch (...) {
co_return result::current_exception();
}
CanonPath getAbsPath(const Input & input) const
+1 -1
View File
@@ -1043,7 +1043,7 @@ struct CmdFlakeClone : FlakeCommand
if (destDir.empty())
throw Error("missing flag '--dest'");
aio().blockOn(getFlakeRef().resolve(store)).input.clone(destDir);
aio().blockOn(aio().blockOn(getFlakeRef().resolve(store)).input.clone(destDir));
}
};