diff --git a/lix/libexpr/flake/flake.cc b/lix/libexpr/flake/flake.cc index 374852607..eb91d4b62 100644 --- a/lix/libexpr/flake/flake.cc +++ b/lix/libexpr/flake/flake.cc @@ -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 diff --git a/lix/libfetchers/fetchers.cc b/lix/libfetchers/fetchers.cc index 4a76ed2dc..30c9ce47b 100644 --- a/lix/libfetchers/fetchers.cc +++ b/lix/libfetchers/fetchers.cc @@ -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> 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 Input::getSourcePath() const @@ -232,13 +236,15 @@ std::optional Input::getSourcePath() const return scheme->getSourcePath(*this); } -void Input::putFile( - const CanonPath & path, - std::string_view contents, - std::optional commitMsg) const -{ +kj::Promise> Input::putFile( + const CanonPath & path, std::string_view contents, std::optional 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 InputScheme::getSourcePath(const Input & input) const return {}; } -void InputScheme::putFile( +kj::Promise> InputScheme::putFile( const Input & input, const CanonPath & path, std::string_view contents, - std::optional commitMsg) const -{ + std::optional 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> 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(); } - } diff --git a/lix/libfetchers/fetchers.hh b/lix/libfetchers/fetchers.hh index 77bbc8805..e9ee88555 100644 --- a/lix/libfetchers/fetchers.hh +++ b/lix/libfetchers/fetchers.hh @@ -102,7 +102,7 @@ public: std::optional ref, std::optional rev) const; - void clone(const Path & destDir) const; + kj::Promise> clone(const Path & destDir) const; std::optional 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 commitMsg) const; + kj::Promise> putFile( + const CanonPath & path, std::string_view contents, std::optional commitMsg + ) const; std::string getName() const; @@ -160,15 +159,16 @@ struct InputScheme std::optional ref, std::optional rev) const; - virtual void clone(const Input & input, const Path & destDir) const; + virtual kj::Promise> clone(const Input & input, const Path & destDir) const; virtual std::optional getSourcePath(const Input & input) const; - virtual void putFile( + virtual kj::Promise> putFile( const Input & input, const CanonPath & path, std::string_view contents, - std::optional commitMsg) const; + std::optional commitMsg + ) const; virtual kj::Promise>> fetch(ref store, const Input & input) = 0; diff --git a/lix/libfetchers/git.cc b/lix/libfetchers/git.cc index d7a2a9b2a..94e2344ba 100644 --- a/lix/libfetchers/git.cc +++ b/lix/libfetchers/git.cc @@ -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> 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 getSourcePath(const Input & input) const override @@ -426,12 +430,13 @@ struct GitInputScheme : InputScheme return {}; } - void putFile( + kj::Promise> putFile( const Input & input, const CanonPath & path, std::string_view contents, - std::optional commitMsg) const override - { + std::optional 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 getActualUrl(const Input & input) const diff --git a/lix/libfetchers/github.cc b/lix/libfetchers/github.cc index 7623c1e0e..970e1e345 100644 --- a/lix/libfetchers/github.cc +++ b/lix/libfetchers/github.cc @@ -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> 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))) - .applyOverrides(input.getRef(), input.getRev()) - .clone(destDir); + TRY_AWAIT( + Input::fromURL(fmt("git+https://%s/%s/%s.git", host, getOwner(input), getRepo(input))) + .applyOverrides(input.getRef(), input.getRev()) + .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> 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"))) - .applyOverrides(input.getRef(), input.getRev()) - .clone(destDir); + 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)); + 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> 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"))) - .applyOverrides(input.getRef(), input.getRev()) - .clone(destDir); + 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)); + co_return result::success(); + } catch (...) { + co_return result::current_exception(); } }; diff --git a/lix/libfetchers/mercurial.cc b/lix/libfetchers/mercurial.cc index 09c8ece12..11682bfbe 100644 --- a/lix/libfetchers/mercurial.cc +++ b/lix/libfetchers/mercurial.cc @@ -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> putFile( const Input & input, const CanonPath & path, std::string_view contents, - std::optional commitMsg) const override - { + std::optional 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 getActualUrl(const Input & input) const diff --git a/lix/libfetchers/path.cc b/lix/libfetchers/path.cc index c2da221b5..ce1b9f01f 100644 --- a/lix/libfetchers/path.cc +++ b/lix/libfetchers/path.cc @@ -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> putFile( const Input & input, const CanonPath & path, std::string_view contents, - std::optional commitMsg) const override - { + std::optional 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 diff --git a/lix/nix/flake.cc b/lix/nix/flake.cc index c2f83ba97..6e135b276 100644 --- a/lix/nix/flake.cc +++ b/lix/nix/flake.cc @@ -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)); } };