Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/libcmd/include/nix/cmd/command.hh
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ void createOutLinks(const std::filesystem::path & outLink, const BuiltPaths & bu
struct MixOutLinkBase : virtual Args
{
/** Prefix for any output symlinks. Empty means do not write an output symlink. */
Path outLink;
std::filesystem::path outLink;

MixOutLinkBase(const std::string & defaultOutLink)
: outLink(defaultOutLink)
Expand Down Expand Up @@ -435,7 +435,7 @@ struct MixOutLinkByDefault : MixOutLinkBase, virtual Args
addFlag({
.longName = "no-link",
.description = "Do not create symlinks to the build results.",
.handler = {&outLink, Path("")},
.handler = {&outLink, std::filesystem::path{}},
});
}
};
Expand Down
4 changes: 2 additions & 2 deletions src/libcmd/include/nix/cmd/repl.hh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
///@file

#include "nix/expr/eval.hh"
#include "nix/util/os-string.hh"

namespace nix {

Expand All @@ -27,8 +28,7 @@ struct AbstractNixRepl
* @param programName Name of the command, e.g. `nix` or `nix-env`.
* @param args arguments to the command.
*/
using RunNix =
void(const std::string & programName, const Strings & args, const std::optional<std::string> & input);
using RunNix = void(const std::string & programName, OsStrings args, const std::optional<std::string> & input);

/**
* @param runNix Function to run the nix CLI to support various
Expand Down
21 changes: 14 additions & 7 deletions src/libcmd/repl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include "nix/util/ref.hh"
#include "nix/expr/value.hh"

#include "nix/util/os-string.hh"
#include "nix/util/processes.hh"
#include "nix/util/strings.hh"

namespace nix {
Expand Down Expand Up @@ -71,7 +73,7 @@ struct NixRepl : AbstractNixRepl, detail::ReplCompleterMixin, gc

RunNix * runNixPtr;

void runNix(const std::string & program, const Strings & args, const std::optional<std::string> & input = {});
void runNix(const std::string & program, OsStrings args, const std::optional<std::string> & input = {});

std::unique_ptr<ReplInteracter> interacter;

Expand Down Expand Up @@ -508,7 +510,12 @@ ProcessLineResult NixRepl::processLine(std::string line)

// runProgram redirects stdout to a StringSink,
// using runProgram2 to allow editors to display their UI
runProgram2(RunOptions{.program = editor, .lookupPath = true, .args = args, .isInteractive = true});
runProgram2({
.program = editor,
.lookupPath = true,
.args = toOsStrings(std::move(args)),
.isInteractive = true,
});

// Reload right after exiting the editor
state->resetFileCache();
Expand All @@ -528,7 +535,7 @@ ProcessLineResult NixRepl::processLine(std::string line)
state->callFunction(f, v, result, PosIdx());

StorePath drvPath = getDerivationPath(result);
runNix("nix-shell", {state->store->printStorePath(drvPath)});
runNix("nix-shell", toOsStrings({state->store->printStorePath(drvPath)}));
}

else if (command == ":b" || command == ":bl" || command == ":i" || command == ":sh" || command == ":log") {
Expand Down Expand Up @@ -559,15 +566,15 @@ ProcessLineResult NixRepl::processLine(std::string line)
}
}
} else if (command == ":i") {
runNix("nix-env", {"-i", drvPathRaw});
runNix("nix-env", toOsStrings({"-i", drvPathRaw}));
} else if (command == ":log") {
settings.readOnlyMode = true;
Finally roModeReset([&]() { settings.readOnlyMode = false; });
RunPager pager;
auto log = fetchBuildLog(state->store, drvPath, drvPathRaw);
logger->writeToStdout(log);
} else {
runNix("nix-shell", {drvPathRaw});
runNix("nix-shell", toOsStrings({drvPathRaw}));
}
}

Expand Down Expand Up @@ -872,10 +879,10 @@ void NixRepl::evalString(std::string s, Value & v)
state->forceValue(v, v.determinePos(noPos));
}

void NixRepl::runNix(const std::string & program, const Strings & args, const std::optional<std::string> & input)
void NixRepl::runNix(const std::string & program, OsStrings args, const std::optional<std::string> & input)
{
if (runNixPtr)
(*runNixPtr)(program, args, input);
(*runNixPtr)(program, std::move(args), input);
else
throw Error(
"Cannot run '%s' because no method of calling the Nix CLI was provided. This is a configuration problem pertaining to how this program was built. See Nix 2.25 release notes",
Expand Down
3 changes: 2 additions & 1 deletion src/libexpr/primops.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "nix/store/path-references.hh"
#include "nix/store/store-api.hh"
#include "nix/util/util.hh"
#include "nix/util/os-string.hh"
#include "nix/util/processes.hh"
#include "nix/expr/value-to-json.hh"
#include "nix/expr/value-to-xml.hh"
Expand Down Expand Up @@ -508,7 +509,7 @@ void prim_exec(EvalState & state, const PosIdx pos, Value ** args, Value & v)
.debugThrow();
}

auto output = runProgram(program, true, commandArgs);
auto output = runProgram(program, true, toOsStrings(std::move(commandArgs)));
Expr * parsed;
try {
parsed = state.parseExprFromString(std::move(output), state.rootPath(CanonPath::root));
Expand Down
8 changes: 6 additions & 2 deletions src/libfetchers/git-lfs-fetch.cc
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#include "nix/fetchers/git-lfs-fetch.hh"
#include "nix/fetchers/git-utils.hh"
#include "nix/store/filetransfer.hh"
#include "nix/util/os-string.hh"
#include "nix/util/processes.hh"
#include "nix/util/url.hh"
#include "nix/util/users.hh"
#include "nix/util/util.hh"
#include "nix/util/hash.hh"
#include "nix/store/ssh.hh"

Expand Down Expand Up @@ -73,10 +75,12 @@ static LfsApiInfo getLfsApi(const ParsedURL & url)
args.push_back(url.renderPath(/*encode=*/false));
args.push_back("download");

auto [status, output] = runProgram({.program = "ssh", .args = args});
auto [status, output] = runProgram({.program = "ssh", .args = toOsStrings(args)});

if (output.empty())
throw Error("git-lfs-authenticate: no output (cmd: 'ssh %s')", concatStringsSep(" ", args));
throw Error(
"git-lfs-authenticate: no output (cmd: 'ssh %s')",
concatMapStringsSep(" ", args, escapeShellArgAlways));

auto queryResp = nlohmann::json::parse(output);
auto headerIt = queryResp.find("header");
Expand Down
47 changes: 30 additions & 17 deletions src/libfetchers/git-utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "nix/fetchers/fetch-settings.hh"
#include "nix/util/base-n.hh"
#include "nix/util/finally.hh"
#include "nix/util/os-string.hh"
#include "nix/util/processes.hh"
#include "nix/util/signals.hh"
#include "nix/util/users.hh"
Expand Down Expand Up @@ -637,12 +638,24 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
// then use code that was removed in this commit (see blame)

auto dir = this->path;
Strings gitArgs{"-C", dir.string(), "--git-dir", ".", "fetch", "--progress", "--force"};
if (shallow)
append(gitArgs, {"--depth", "1"});
append(gitArgs, {std::string("--"), url, refspec});
OsStrings gitArgs = {
OS_STR("-C"),
dir.native(),
OS_STR("--git-dir"),
OS_STR("."),
OS_STR("fetch"),
OS_STR("--progress"),
OS_STR("--force"),
};
if (shallow) {
gitArgs.push_back(OS_STR("--depth"));
gitArgs.push_back(OS_STR("1"));
}
gitArgs.push_back(OS_STR("--"));
gitArgs.push_back(string_to_os_string(url));
gitArgs.push_back(string_to_os_string(refspec));

auto status = runProgram(RunOptions{.program = "git", .args = gitArgs, .isInteractive = true}).first;
auto status = runProgram({.program = "git", .args = gitArgs, .isInteractive = true}).first;

if (status > 0)
throw Error("Failed to fetch git repository '%s'", url);
Expand Down Expand Up @@ -682,18 +695,18 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
writeFile(allowedSignersFile, allowedSigners);

// Run verification command
auto [status, output] = runProgram(
RunOptions{
.program = "git",
.args =
{"-c",
"gpg.ssh.allowedSignersFile=" + allowedSignersFile,
"-C",
path.string(),
"verify-commit",
rev.gitRev()},
.mergeStderrToStdout = true,
});
auto [status, output] = runProgram({
.program = "git",
.args{
OS_STR("-c"),
string_to_os_string("gpg.ssh.allowedSignersFile=" + allowedSignersFile),
OS_STR("-C"),
path.native(),
OS_STR("verify-commit"),
string_to_os_string(rev.gitRev()),
},
.mergeStderrToStdout = true,
});

/* Evaluate result through status code and checking if public
key fingerprints appear on stderr. This is necessary
Expand Down
90 changes: 55 additions & 35 deletions src/libfetchers/git.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "nix/store/store-api.hh"
#include "nix/util/url-parts.hh"
#include "nix/store/pathlocks.hh"
#include "nix/util/os-string.hh"
#include "nix/util/processes.hh"
#include "nix/util/git.hh"
#include "nix/fetchers/git-utils.hh"
Expand Down Expand Up @@ -62,7 +63,7 @@ std::optional<std::string> readHead(const std::filesystem::path & path)
RunOptions{
.program = "git",
// FIXME: use 'HEAD' to avoid returning all refs
.args = {"ls-remote", "--symref", path.string()},
.args = {OS_STR("ls-remote"), OS_STR("--symref"), path.native()},
.isInteractive = true,
});
if (status != 0)
Expand All @@ -89,7 +90,19 @@ bool storeCachedHead(const std::string & actualUrl, bool shallow, const std::str
{
std::filesystem::path cacheDir = getCachePath(actualUrl, shallow);
try {
runProgram("git", true, {"-C", cacheDir.string(), "--git-dir", ".", "symbolic-ref", "--", "HEAD", headRef});
runProgram(
"git",
true,
{
OS_STR("-C"),
cacheDir.native(),
OS_STR("--git-dir"),
OS_STR("."),
OS_STR("symbolic-ref"),
OS_STR("--"),
OS_STR("HEAD"),
string_to_os_string(headRef),
});
} catch (ExecError & e) {
if (
#ifndef WIN32 // TODO abstract over exit status handling on Windows
Expand Down Expand Up @@ -439,19 +452,19 @@ struct GitInputScheme : InputScheme
{
auto repoInfo = getRepoInfo(input);

Strings args = {"clone"};
OsStrings args = {OS_STR("clone")};

args.push_back(repoInfo.locationToArg());
args.push_back(string_to_os_string(repoInfo.locationToArg()));

if (auto ref = input.getRef()) {
args.push_back("--branch");
args.push_back(*ref);
args.push_back(OS_STR("--branch"));
args.push_back(string_to_os_string(*ref));
}

if (input.getRev())
throw UnimplementedError("cloning a specific revision is not implemented");

args.push_back(destDir.string());
args.push_back(destDir.native());

runProgram("git", true, args, {}, true);
}
Expand All @@ -478,14 +491,15 @@ struct GitInputScheme : InputScheme
auto result = runProgram(
RunOptions{
.program = "git",
.args =
{"-C",
repoPath->string(),
"--git-dir",
repoInfo.gitDir,
"check-ignore",
"--quiet",
std::string(path.rel())},
.args{
OS_STR("-C"),
repoPath->native(),
OS_STR("--git-dir"),
string_to_os_string(repoInfo.gitDir),
OS_STR("check-ignore"),
OS_STR("--quiet"),
string_to_os_string(std::string(path.rel())),
},
});
auto exitCode =
#ifndef WIN32 // TODO abstract over exit status handling on Windows
Expand All @@ -500,29 +514,33 @@ struct GitInputScheme : InputScheme
runProgram(
"git",
true,
{"-C",
repoPath->string(),
"--git-dir",
repoInfo.gitDir,
"add",
"--intent-to-add",
"--",
std::string(path.rel())});
{
OS_STR("-C"),
repoPath->native(),
OS_STR("--git-dir"),
string_to_os_string(repoInfo.gitDir),
OS_STR("add"),
OS_STR("--intent-to-add"),
OS_STR("--"),
string_to_os_string(std::string(path.rel())),
});

if (commitMsg) {
// Pause the logger to allow for user input (such as a gpg passphrase) in `git commit`
auto suspension = logger->suspend();
runProgram(
"git",
true,
{"-C",
repoPath->string(),
"--git-dir",
repoInfo.gitDir,
"commit",
std::string(path.rel()),
"-F",
"-"},
{
OS_STR("-C"),
repoPath->native(),
OS_STR("--git-dir"),
string_to_os_string(repoInfo.gitDir),
OS_STR("commit"),
string_to_os_string(std::string(path.rel())),
OS_STR("-F"),
OS_STR("-"),
},
*commitMsg);
}
}
Expand Down Expand Up @@ -627,10 +645,12 @@ struct GitInputScheme : InputScheme
//
// See: https://discourse.nixos.org/t/57783 and #9708
//
if (url.scheme == "file" && !forceHttp && !isBareRepository(renderUrlPathEnsureLegal(url.path))) {
auto path = renderUrlPathEnsureLegal(url.path);
auto maybeUrlFsPathForFileUrl =
url.scheme == "file" ? std::make_optional(urlPathToPath(url.path)) : std::nullopt;
if (maybeUrlFsPathForFileUrl && !forceHttp && !isBareRepository(maybeUrlFsPathForFileUrl->string())) {
auto & path = *maybeUrlFsPathForFileUrl;

if (!isAbsolute(path)) {
if (!path.is_absolute()) {
warn(
"Fetching Git repository '%s', which uses a path relative to the current directory. "
"This is not supported and will stop working in a future release. "
Expand All @@ -640,7 +660,7 @@ struct GitInputScheme : InputScheme

repoInfo.location = std::filesystem::absolute(path);
} else {
if (url.scheme == "file")
if (maybeUrlFsPathForFileUrl)
/* Query parameters are meaningless for file://, but
Git interprets them as part of the file name. So get
rid of them. */
Expand Down
Loading
Loading