libutil: asyncify runProgram

Change-Id: I397d02b1a993dc4f0c2dc2b2f90d0c1aebda4c2e
This commit is contained in:
eldritch horrors
2025-09-15 16:18:01 +00:00
parent 8981fb5a18
commit 812f466e0d
11 changed files with 302 additions and 100 deletions
+25 -9
View File
@@ -9,6 +9,7 @@
#include "lix/libstore/temporary-dir.hh"
#include "lix/libutil/async.hh"
#include "lix/libutil/regex.hh"
#include "lix/libutil/result.hh"
#include "lix/libutil/users.hh"
#include "nix-channel.hh"
@@ -65,13 +66,18 @@ static void addChannel(const std::string & url, const std::string & name)
static Path profile;
// Remove a channel.
static void removeChannel(const std::string & name)
{
static kj::Promise<Result<void>> removeChannel(const std::string & name)
try {
readChannels();
channels.erase(name);
writeChannels();
runProgram(settings.nixBinDir + "/nix-env", true, { "--profile", profile, "--uninstall", name });
TRY_AWAIT(runProgram(
settings.nixBinDir + "/nix-env", true, {"--profile", profile, "--uninstall", name}
));
co_return result::success();
} catch (...) {
co_return result::current_exception();
}
static Path nixDefExpr;
@@ -127,8 +133,14 @@ static void update(AsyncIoRoot & aio, const StringSet & channelNames)
bool unpacked = false;
if (std::regex_search(filename, regex::parse("\\.tar\\.(gz|bz2|xz)$"))) {
runProgram(settings.nixBinDir + "/nix-build", false, { "--no-out-link", "--expr", "import " + unpackChannelPath +
"{ name = \"" + cname + "\"; channelName = \"" + name + "\"; src = builtins.storePath \"" + filename + "\"; }" });
aio.blockOn(runProgram(
settings.nixBinDir + "/nix-build",
false,
{"--no-out-link",
"--expr",
"import " + unpackChannelPath + "{ name = \"" + cname + "\"; channelName = \""
+ name + "\"; src = builtins.storePath \"" + filename + "\"; }"}
));
unpacked = true;
}
@@ -158,7 +170,7 @@ static void update(AsyncIoRoot & aio, const StringSet & channelNames)
for (auto & expr : exprs)
envArgs.push_back(std::move(expr));
envArgs.push_back("--quiet");
runProgram(settings.nixBinDir + "/nix-env", false, envArgs);
aio.blockOn(runProgram(settings.nixBinDir + "/nix-env", false, envArgs));
// Make the channels appear in nix-env.
struct stat st;
@@ -244,7 +256,7 @@ static int main_nix_channel(AsyncIoRoot & aio, std::string programName, Strings
case cRemove:
if (args.size() != 1)
throw UsageError("'--remove' requires one argument");
removeChannel(args[0]);
aio.blockOn(removeChannel(args[0]));
break;
case cList:
if (!args.empty())
@@ -259,7 +271,11 @@ static int main_nix_channel(AsyncIoRoot & aio, std::string programName, Strings
case cListGenerations:
if (!args.empty())
throw UsageError("'--list-generations' expects no arguments");
std::cout << runProgram(settings.nixBinDir + "/nix-env", false, {"--profile", profile, "--list-generations"}) << std::flush;
std::cout << aio.blockOn(runProgram(
settings.nixBinDir + "/nix-env",
false,
{"--profile", profile, "--list-generations"}
)) << std::flush;
break;
case cRollback:
if (args.size() > 1)
@@ -271,7 +287,7 @@ static int main_nix_channel(AsyncIoRoot & aio, std::string programName, Strings
} else {
envArgs.push_back("--rollback");
}
runProgram(settings.nixBinDir + "/nix-env", false, envArgs);
aio.blockOn(runProgram(settings.nixBinDir + "/nix-env", false, envArgs));
break;
}
+1 -1
View File
@@ -321,7 +321,7 @@ void prim_exec(EvalState & state, Value * * args, Value & v)
throw;
}
auto output = runProgram(program, true, commandArgs);
auto output = state.aio.blockOn(runProgram(program, true, commandArgs));
Expr * parsed;
try {
parsed = &state.ctx.parseExprFromString(std::move(output), CanonPath::root);
+199 -50
View File
@@ -69,12 +69,12 @@ Path getCachePath(std::string_view key)
// ...
static kj::Promise<Result<std::optional<std::string>>> readHead(const Path & path)
try {
auto [status, output] = runProgram(RunOptions {
auto [status, output] = TRY_AWAIT(runProgram(RunOptions{
.program = "git",
// FIXME: use 'HEAD' to avoid returning all refs
.args = {"ls-remote", "--symref", path},
.isInteractive = true,
});
}));
if (status != 0) {
co_return std::nullopt;
}
@@ -103,9 +103,13 @@ storeCachedHead(const std::string & actualUrl, const std::string & headRef)
try {
Path cacheDir = getCachePath(actualUrl);
try {
runProgram("git", true, { "-C", cacheDir, "--git-dir", ".", "symbolic-ref", "--", "HEAD", headRef });
} catch (ExecError &e) {
if (!WIFEXITED(e.status)) throw;
TRY_AWAIT(runProgram(
"git", true, {"-C", cacheDir, "--git-dir", ".", "symbolic-ref", "--", "HEAD", headRef}
));
} catch (ExecError & e) {
if (!WIFEXITED(e.status)) {
throw;
}
co_return false;
}
/* No need to touch refs/HEAD, because `git symbolic-ref` updates the mtime. */
@@ -182,7 +186,7 @@ try {
/* Check whether HEAD points to something that looks like a commit,
since that is the refrence we want to use later on. */
auto result = runProgram(RunOptions{
auto result = TRY_AWAIT(runProgram(RunOptions{
.program = "git",
.args =
{"-C",
@@ -195,7 +199,7 @@ try {
"HEAD^{commit}"},
.environment = env,
.redirections = {{.dup = STDERR_FILENO, .from = STDOUT_FILENO}},
});
}));
auto exitCode = WEXITSTATUS(result.first);
auto errorMessage = result.second;
@@ -223,7 +227,7 @@ try {
gitDiffOpts.emplace_back("--ignore-submodules");
}
gitDiffOpts.emplace_back("--");
runProgram("git", true, gitDiffOpts);
TRY_AWAIT(runProgram("git", true, gitDiffOpts));
clean = true;
}
@@ -252,8 +256,8 @@ try {
if (submodules)
gitOpts.emplace_back("--recurse-submodules");
auto files = tokenizeString<std::set<std::string>>(
runProgram("git", true, gitOpts), "\0"s);
auto files =
tokenizeString<std::set<std::string>>(TRY_AWAIT(runProgram("git", true, gitOpts)), "\0"s);
Path actualPath(absPath(workdir));
@@ -280,13 +284,39 @@ try {
// modified dirty file?
input.attrs.insert_or_assign(
"lastModified",
workdirInfo.hasHead ? std::stoull(runProgram("git", true, { "-C", actualPath, "--git-dir", gitDir, "log", "-1", "--format=%ct", "--no-show-signature", "HEAD" })) : 0);
workdirInfo.hasHead ? std::stoull(TRY_AWAIT(runProgram(
"git",
true,
{"-C",
actualPath,
"--git-dir",
gitDir,
"log",
"-1",
"--format=%ct",
"--no-show-signature",
"HEAD"}
)))
: 0
);
if (workdirInfo.hasHead) {
input.attrs.insert_or_assign("dirtyRev", chomp(
runProgram("git", true, { "-C", actualPath, "--git-dir", gitDir, "rev-parse", "--verify", "HEAD" })) + "-dirty");
input.attrs.insert_or_assign("dirtyShortRev", chomp(
runProgram("git", true, { "-C", actualPath, "--git-dir", gitDir, "rev-parse", "--verify", "--short", "HEAD" })) + "-dirty");
input.attrs.insert_or_assign(
"dirtyRev",
chomp(TRY_AWAIT(runProgram(
"git",
true,
{"-C", actualPath, "--git-dir", gitDir, "rev-parse", "--verify", "HEAD"}
))) + "-dirty"
);
input.attrs.insert_or_assign(
"dirtyShortRev",
chomp(TRY_AWAIT(runProgram(
"git",
true,
{"-C", actualPath, "--git-dir", gitDir, "rev-parse", "--verify", "--short", "HEAD"}
))) + "-dirty"
);
}
co_return {std::move(storePath), input};
@@ -429,7 +459,7 @@ struct GitInputScheme : InputScheme
args.push_back(destDir);
runProgram("git", true, args, true);
TRY_AWAIT(runProgram("git", true, args, true));
co_return result::success();
} catch (...) {
co_return result::current_exception();
@@ -458,25 +488,52 @@ struct GitInputScheme : InputScheme
auto gitDir = ".git";
auto result = runProgram(RunOptions {
auto result = TRY_AWAIT(runProgram(RunOptions{
.program = "git",
.args = {"-C", *root, "--git-dir", gitDir, "check-ignore", "--quiet", std::string(path.rel())},
});
.args =
{"-C",
*root,
"--git-dir",
gitDir,
"check-ignore",
"--quiet",
std::string(path.rel())},
}));
auto exitCode = WEXITSTATUS(result.first);
if (exitCode != 0) {
// The path is not `.gitignore`d, we can add the file.
runProgram("git", true,
{ "-C", *root, "--git-dir", gitDir, "add", "--intent-to-add", "--", std::string(path.rel()) });
TRY_AWAIT(runProgram(
"git",
true,
{"-C",
*root,
"--git-dir",
gitDir,
"add",
"--intent-to-add",
"--",
std::string(path.rel())}
));
if (commitMsg) {
auto [_fd, msgPath] = createTempFile("nix-msg");
AutoDelete const _delete{msgPath};
writeFile(msgPath, *commitMsg);
runProgram("git", true,
{ "-C", *root, "--git-dir", gitDir, "commit", std::string(path.rel()), "-F", msgPath }, true);
TRY_AWAIT(runProgram(
"git",
true,
{"-C",
*root,
"--git-dir",
gitDir,
"commit",
std::string(path.rel()),
"-F",
msgPath},
true
));
}
}
@@ -582,8 +639,18 @@ struct GitInputScheme : InputScheme
}
if (!input.getRev())
input.attrs.insert_or_assign("rev",
Hash::parseAny(chomp(runProgram("git", true, { "-C", actualUrl, "--git-dir", gitDir, "rev-parse", *input.getRef() })), HashType::SHA1).gitRev());
input.attrs.insert_or_assign(
"rev",
Hash::parseAny(
chomp(TRY_AWAIT(runProgram(
"git",
true,
{"-C", actualUrl, "--git-dir", gitDir, "rev-parse", *input.getRef()}
))),
HashType::SHA1
)
.gitRev()
);
repoDir = actualUrl;
} else {
@@ -620,7 +687,11 @@ struct GitInputScheme : InputScheme
PathLock cacheDirLock = TRY_AWAIT(lockPathAsync(cacheDir + ".lock"));
if (!pathExists(cacheDir)) {
runProgram("git", true, { "-c", "init.defaultBranch=" + gitInitialBranch, "init", "--bare", repoDir });
TRY_AWAIT(runProgram(
"git",
true,
{"-c", "init.defaultBranch=" + gitInitialBranch, "init", "--bare", repoDir}
));
}
std::vector<Path> gitRefFileCandidates;
@@ -638,7 +709,17 @@ struct GitInputScheme : InputScheme
repo. */
if (input.getRev()) {
try {
runProgram("git", true, { "-C", repoDir, "--git-dir", gitDir, "cat-file", "-e", input.getRev()->gitRev() });
TRY_AWAIT(runProgram(
"git",
true,
{"-C",
repoDir,
"--git-dir",
gitDir,
"cat-file",
"-e",
input.getRev()->gitRev()}
));
doFetch = false;
} catch (ExecError & e) {
if (WIFEXITED(e.status)) {
@@ -707,14 +788,21 @@ struct GitInputScheme : InputScheme
// FIXME: git stderr messes up our progress indicator, so
// we're using --quiet for now. Should process its stderr.
runProgram("git", true, {
"-C", repoDir,
"--git-dir", gitDir,
"fetch",
"--quiet",
"--force",
"--", actualUrl, fmt("%s:%s", fetchRef, fetchRef)
}, true);
TRY_AWAIT(runProgram(
"git",
true,
{"-C",
repoDir,
"--git-dir",
gitDir,
"fetch",
"--quiet",
"--force",
"--",
actualUrl,
fmt("%s:%s", fetchRef, fetchRef)},
true
));
} catch (Error & e) {
if (!pathExists(localRefFile)) throw;
printTaggedWarning(
@@ -741,7 +829,13 @@ struct GitInputScheme : InputScheme
// cache dir lock is removed at scope end; we will only use read-only operations on specific revisions in the remainder
}
bool isShallow = chomp(runProgram("git", true, { "-C", repoDir, "--git-dir", gitDir, "rev-parse", "--is-shallow-repository" })) == "true";
bool isShallow =
chomp(TRY_AWAIT(runProgram(
"git",
true,
{"-C", repoDir, "--git-dir", gitDir, "rev-parse", "--is-shallow-repository"}
)))
== "true";
if (isShallow && !shallow)
throw Error("'%s' is a shallow Git repository, but shallow repositories are only allowed when `shallow = true;` is specified.", actualUrl);
@@ -759,13 +853,13 @@ struct GitInputScheme : InputScheme
AutoDelete delTmpDir(tmpDir, true);
PathFilter filter = defaultPathFilter;
auto result = runProgram(RunOptions{
auto result = TRY_AWAIT(runProgram(RunOptions{
.program = "git",
.args =
{"-C", repoDir, "--git-dir", gitDir, "cat-file", "commit", input.getRev()->gitRev()
},
.redirections = {{.dup = STDERR_FILENO, .from = STDOUT_FILENO}},
});
}));
if (WEXITSTATUS(result.first) == 128
&& result.second.find("bad file") != std::string::npos)
{
@@ -784,18 +878,41 @@ struct GitInputScheme : InputScheme
Path tmpGitDir = createTempDir();
AutoDelete delTmpGitDir(tmpGitDir, true);
runProgram("git", true, { "-c", "init.defaultBranch=" + gitInitialBranch, "init", tmpDir, "--separate-git-dir", tmpGitDir });
TRY_AWAIT(runProgram(
"git",
true,
{"-c",
"init.defaultBranch=" + gitInitialBranch,
"init",
tmpDir,
"--separate-git-dir",
tmpGitDir}
));
{
// TODO: repoDir might lack the ref (it only checks if rev
// exists, see FIXME above) so use a big hammer and fetch
// everything to ensure we get the rev.
Activity act(*logger, lvlTalkative, actUnknown, fmt("making temporary clone of '%s'", repoDir));
runProgram("git", true, { "-C", tmpDir, "fetch", "--quiet", "--force",
"--update-head-ok", "--", repoDir, "refs/*:refs/*" }, true);
TRY_AWAIT(runProgram(
"git",
true,
{"-C",
tmpDir,
"fetch",
"--quiet",
"--force",
"--update-head-ok",
"--",
repoDir,
"refs/*:refs/*"},
true
));
}
runProgram("git", true, { "-C", tmpDir, "checkout", "--quiet", input.getRev()->gitRev() });
TRY_AWAIT(runProgram(
"git", true, {"-C", tmpDir, "checkout", "--quiet", input.getRev()->gitRev()}
));
/* Ensure that we use the correct origin for fetching
submodules. This matters for submodules with relative
@@ -805,21 +922,29 @@ struct GitInputScheme : InputScheme
/* Restore the config.bare setting we may have just
copied erroneously from the user's repo. */
runProgram("git", true, { "-C", tmpDir, "config", "core.bare", "false" });
TRY_AWAIT(runProgram("git", true, {"-C", tmpDir, "config", "core.bare", "false"}));
} else
runProgram("git", true, { "-C", tmpDir, "config", "remote.origin.url", actualUrl });
TRY_AWAIT(runProgram(
"git", true, {"-C", tmpDir, "config", "remote.origin.url", actualUrl}
));
/* As an optimisation, copy the modules directory of the
source repo if it exists. */
auto modulesPath = repoDir + "/" + gitDir + "/modules";
if (pathExists(modulesPath)) {
Activity act(*logger, lvlTalkative, actUnknown, fmt("copying submodules of '%s'", actualUrl));
runProgram("cp", true, { "-R", "--", modulesPath, tmpGitDir + "/modules" });
TRY_AWAIT(runProgram("cp", true, {"-R", "--", modulesPath, tmpGitDir + "/modules"})
);
}
{
Activity act(*logger, lvlTalkative, actUnknown, fmt("fetching submodules of '%s'", actualUrl));
runProgram("git", true, { "-C", tmpDir, "submodule", "--quiet", "update", "--init", "--recursive" }, true);
TRY_AWAIT(runProgram(
"git",
true,
{"-C", tmpDir, "submodule", "--quiet", "update", "--init", "--recursive"},
true
));
}
filter = isNotDotGitDirectory;
@@ -839,7 +964,19 @@ struct GitInputScheme : InputScheme
store->addToStoreRecursive(name, *prepareDump(tmpDir, filter), HashType::SHA256)
);
auto lastModified = std::stoull(runProgram("git", true, { "-C", repoDir, "--git-dir", gitDir, "log", "-1", "--format=%ct", "--no-show-signature", input.getRev()->gitRev() }));
auto lastModified = std::stoull(TRY_AWAIT(runProgram(
"git",
true,
{"-C",
repoDir,
"--git-dir",
gitDir,
"log",
"-1",
"--format=%ct",
"--no-show-signature",
input.getRev()->gitRev()}
)));
Attrs infoAttrs({
{"rev", input.getRev()->gitRev()},
@@ -847,8 +984,20 @@ struct GitInputScheme : InputScheme
});
if (!shallow)
infoAttrs.insert_or_assign("revCount",
std::stoull(runProgram("git", true, { "-C", repoDir, "--git-dir", gitDir, "rev-list", "--count", input.getRev()->gitRev() })));
infoAttrs.insert_or_assign(
"revCount",
std::stoull(TRY_AWAIT(runProgram(
"git",
true,
{"-C",
repoDir,
"--git-dir",
gitDir,
"rev-list",
"--count",
input.getRev()->gitRev()}
)))
);
if (!_input.getRev())
getCache()->add(
+7 -4
View File
@@ -37,7 +37,7 @@ static kj::Promise<Result<std::string>> runHg(const Strings & args)
try {
RunOptions opts = hgOptions(args);
auto res = runProgram(std::move(opts));
auto res = TRY_AWAIT(runProgram(std::move(opts)));
if (!statusOk(res.first))
throw ExecError(res.first, "hg %1%", statusToString(res.first));
@@ -300,9 +300,12 @@ struct MercurialInputScheme : InputScheme
/* If this is a commit hash that we already have, we don't
have to pull again. */
if (!(input.getRev()
&& pathExists(cacheDir)
&& runProgram(hgOptions({ "identify", "-R", cacheDir, "-r", revOrRef, "--template", "1" })).second == "1"))
if (!(input.getRev() && pathExists(cacheDir)
&& TRY_AWAIT(runProgram(hgOptions(
{"identify", "-R", cacheDir, "-r", revOrRef, "--template", "1"}
)))
.second
== "1"))
{
Activity act(*logger, lvlTalkative, actUnknown, fmt("fetching Mercurial repository '%s'", actualUrl));
+21 -10
View File
@@ -74,23 +74,27 @@ extern "C" int sandbox_init_with_parameters(const char *profile, uint64_t flags,
namespace nix {
void handleDiffHook(
uid_t uid, uid_t gid,
const Path & tryA, const Path & tryB,
const Path & drvPath, const Path & tmpDir)
{
static kj::Promise<Result<void>> handleDiffHook(
uid_t uid,
uid_t gid,
const Path & tryA,
const Path & tryB,
const Path & drvPath,
const Path & tmpDir
)
try {
auto & diffHookOpt = settings.diffHook.get();
if (diffHookOpt && settings.runDiffHook) {
auto & diffHook = *diffHookOpt;
try {
auto diffRes = runProgram(RunOptions {
auto diffRes = TRY_AWAIT(runProgram(RunOptions{
.program = diffHook,
.searchPath = true,
.args = {tryA, tryB, drvPath, tmpDir},
.uid = uid,
.gid = gid,
.chdir = "/"
});
}));
if (!statusOk(diffRes.first))
throw ExecError(diffRes.first,
"diff-hook program '%1%' %2%",
@@ -107,6 +111,9 @@ void handleDiffHook(
logError(ei);
}
}
co_return result::success();
} catch (...) {
co_return result::current_exception();
}
const Path LocalDerivationGoal::homeDir = "/homeless-shelter";
@@ -724,7 +731,7 @@ try {
auto state = stBegin;
std::string lines;
try {
runProgram(settings.preBuildHook, false, args);
TRY_AWAIT(runProgram(settings.preBuildHook, false, args));
} catch (nix::Error & e) {
e.addTrace(nullptr,
"while running pre-build-hook %s for derivation %s",
@@ -2151,10 +2158,14 @@ try {
deletePath(dst);
movePath(actualPath, dst);
handleDiffHook(
TRY_AWAIT(handleDiffHook(
buildUser ? buildUser->getUID() : getuid(),
buildUser ? buildUser->getGID() : getgid(),
finalDestPath, dst, worker.store.printStorePath(drvPath), tmpDir);
finalDestPath,
dst,
worker.store.printStorePath(drvPath),
tmpDir
));
nondeterministic.push_back(std::make_pair(worker.store.toRealPath(finalDestPath), dst));
} else
+3 -2
View File
@@ -366,8 +366,9 @@ try {
// platform-specific code in lix/libstore/platform/
try {
std::regex lsofRegex = regex::parse(R"(^n(/.*)$)");
auto lsofLines =
tokenizeString<std::vector<std::string>>(runProgram(LSOF, true, { "-n", "-w", "-F", "n" }), "\n");
auto lsofLines = tokenizeString<std::vector<std::string>>(
TRY_AWAIT(runProgram(LSOF, true, {"-n", "-w", "-F", "n"})), "\n"
);
for (const auto & line : lsofLines) {
std::smatch match;
if (std::regex_match(line, match, lsofRegex))
+16 -9
View File
@@ -243,16 +243,23 @@ StringSet Settings::getDefaultExtraPlatforms()
// machines. Note that we cant force processes from executing
// x86_64 in aarch64 environments or vice versa since they can
// always exec with their own binary preferences.
if (std::string{SYSTEM} == "aarch64-darwin"
&& runProgram(RunOptions{
.program = "arch",
.args = {"-arch", "x86_64", "/usr/bin/true"},
.redirections = {{.dup = STDERR_FILENO, .from = STDOUT_FILENO}}
}
).first
if (std::string{SYSTEM} == "aarch64-darwin") {
AutoCloseFD null(open("/dev/null", O_RDWR | O_CLOEXEC));
if (!null) {
throw Error("could not open /dev/null");
}
if (runProgram2(RunOptions{
.program = "arch",
.args = {"-arch", "x86_64", "/usr/bin/true"},
.redirections =
{{.dup = STDOUT_FILENO, .from = null.get()},
{.dup = STDERR_FILENO, .from = null.get()}}
}
).wait()
== 0)
{
extraPlatforms.insert("x86_64-darwin");
{
extraPlatforms.insert("x86_64-darwin");
}
}
#endif
+17 -8
View File
@@ -1,3 +1,4 @@
#include "async-io.hh"
#include "lix/libutil/current-process.hh"
#include "lix/libutil/environment-variables.hh"
#include "lix/libutil/finally.hh"
@@ -228,19 +229,25 @@ Pid startProcess(std::function<void()> fun, const ProcessOptions & options)
return Pid{pid};
}
std::string runProgram(Path program, bool searchPath, const Strings & args, bool isInteractive)
{
auto res = runProgram(RunOptions {.program = program, .searchPath = searchPath, .args = args, .isInteractive = isInteractive});
kj::Promise<Result<std::string>>
runProgram(Path program, bool searchPath, const Strings args, bool isInteractive)
try {
auto res = TRY_AWAIT(runProgram(RunOptions{
.program = program, .searchPath = searchPath, .args = args, .isInteractive = isInteractive
}));
if (!statusOk(res.first))
if (!statusOk(res.first)) {
throw ExecError(res.first, "program '%1%' %2%", program, statusToString(res.first));
}
return res.second;
co_return res.second;
} catch (...) {
co_return result::current_exception();
}
// Output = error code + "standard out" output stream
std::pair<int, std::string> runProgram(RunOptions && options)
{
kj::Promise<Result<std::pair<int, std::string>>> runProgram(RunOptions options)
try {
options.captureStdout = true;
int status = 0;
@@ -254,7 +261,9 @@ std::pair<int, std::string> runProgram(RunOptions && options)
status = e.status;
}
return {status, std::move(stdout)};
co_return {status, std::move(stdout)};
} catch (...) {
co_return result::current_exception();
}
RunningProgram::RunningProgram(PathView program, Pid pid, AutoCloseFD stdout)
+9 -3
View File
@@ -1,10 +1,12 @@
#pragma once
///@file
#include "lix/libutil/result.hh"
#include "lix/libutil/types.hh"
#include "lix/libutil/error.hh"
#include "lix/libutil/file-descriptor.hh"
#include <kj/async.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
@@ -69,8 +71,12 @@ Pid startProcess(std::function<void()> fun, const ProcessOptions & options = Pro
* Run a program and return its stdout in a string (i.e., like the
* shell backtick operator).
*/
std::string runProgram(Path program, bool searchPath = false,
const Strings & args = Strings(), bool isInteractive = false);
kj::Promise<Result<std::string>> runProgram(
Path program,
bool searchPath = false,
const Strings args = Strings(),
bool isInteractive = false
);
struct RunOptions
{
@@ -130,7 +136,7 @@ public:
Source * getStdout() const { return stdoutSource.get(); };
};
std::pair<int, std::string> runProgram(RunOptions && options);
kj::Promise<Result<std::pair<int, std::string>>> runProgram(RunOptions options);
RunningProgram runProgram2(const RunOptions & options);
+1 -1
View File
@@ -950,7 +950,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand
if (!changedFiles.empty() && pathExists(flakeDir + "/.git")) {
Strings args = { "-C", flakeDir, "add", "--intent-to-add", "--force", "--" };
for (auto & s : changedFiles) args.push_back(s);
runProgram("git", true, args);
aio().blockOn(runProgram("git", true, args));
}
auto welcomeText = cursor->maybeGetAttr(*evalState, "welcomeText");
if (welcomeText) {
+3 -3
View File
@@ -108,7 +108,7 @@ struct CmdUpgradeNix : MixDryRun, EvalCommand
{
Activity act(*logger, lvlInfo, actUnknown, fmt("verifying that '%s' works...", store->printStorePath(storePath)));
auto s = runProgram(newNixEnv, false, {"--version"});
auto s = aio().blockOn(runProgram(newNixEnv, false, {"--version"}));
if (s.find("Nix") == std::string::npos)
throw Error("could not verify that '%s' works", newNixEnv);
}
@@ -128,7 +128,7 @@ struct CmdUpgradeNix : MixDryRun, EvalCommand
this->profileDir,
};
printTalkative("running %s %s", newNixEnv, concatStringsSep(" ", removeArgs));
runProgram(newNixEnv, false, removeArgs);
aio().blockOn(runProgram(newNixEnv, false, removeArgs));
Strings upgradeArgs = {
"--profile",
@@ -139,7 +139,7 @@ struct CmdUpgradeNix : MixDryRun, EvalCommand
};
printTalkative("running %s %s", newNixEnv, concatStringsSep(" ", upgradeArgs));
runProgram(newNixEnv, false, upgradeArgs);
aio().blockOn(runProgram(newNixEnv, false, upgradeArgs));
} else if (pathExists(canonProfileDir + "/manifest.json")) {
this->upgradeNewStyleProfile(store, storePath);
} else {