1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-12-03 07:31:00 +01:00

Merge remote-tracking branch 'origin/2.29-maintenance' into detsys-main

This commit is contained in:
Eelco Dolstra 2025-05-16 12:48:44 +02:00
commit c20642ac7b
354 changed files with 6768 additions and 3808 deletions

View file

@ -3,7 +3,7 @@
#include "nix/cmd/command.hh"
#include "nix/cmd/markdown.hh"
#include "nix/store/store-api.hh"
#include "nix/store/store-open.hh"
#include "nix/store/local-fs-store.hh"
#include "nix/store/derivations.hh"
#include "nix/expr/nixexpr.hh"
@ -14,12 +14,10 @@
namespace nix {
RegisterCommand::Commands * RegisterCommand::commands = nullptr;
nix::Commands RegisterCommand::getCommandsFor(const std::vector<std::string> & prefix)
{
nix::Commands res;
for (auto & [name, command] : *RegisterCommand::commands)
for (auto & [name, command] : RegisterCommand::commands())
if (name.size() == prefix.size() + 1) {
bool equal = true;
for (size_t i = 0; i < prefix.size(); ++i)
@ -40,7 +38,7 @@ nlohmann::json NixMultiCommand::toJSON()
void NixMultiCommand::run()
{
if (!command) {
std::set<std::string> subCommandTextLines;
StringSet subCommandTextLines;
for (auto & [name, _] : commands)
subCommandTextLines.insert(fmt("- `%s`", name));
std::string markdownError =
@ -397,4 +395,11 @@ void createOutLinks(const std::filesystem::path & outLink, const BuiltPaths & bu
}
}
void MixOutLinkBase::createOutLinksMaybe(const std::vector<BuiltPathWithResult> & buildables, ref<Store> & store)
{
if (outLink != "")
if (auto store2 = store.dynamic_pointer_cast<LocalFSStore>())
createOutLinks(outLink, toBuiltPaths(buildables), *store2);
}
}

View file

@ -9,7 +9,7 @@
#include "nix/fetchers/registry.hh"
#include "nix/flake/flakeref.hh"
#include "nix/flake/settings.hh"
#include "nix/store/store-api.hh"
#include "nix/store/store-open.hh"
#include "nix/cmd/command.hh"
#include "nix/fetchers/tarball.hh"
#include "nix/fetchers/fetch-to-store.hh"
@ -18,7 +18,6 @@
namespace nix {
namespace fs { using namespace std::filesystem; }
fetchers::Settings fetchSettings;
@ -122,8 +121,8 @@ MixEvalArgs::MixEvalArgs()
.category = category,
.labels = {"original-ref", "resolved-ref"},
.handler = {[&](std::string _from, std::string _to) {
auto from = parseFlakeRef(fetchSettings, _from, fs::current_path().string());
auto to = parseFlakeRef(fetchSettings, _to, fs::current_path().string());
auto from = parseFlakeRef(fetchSettings, _from, std::filesystem::current_path().string());
auto to = parseFlakeRef(fetchSettings, _to, std::filesystem::current_path().string());
fetchers::Attrs extraAttrs;
if (to.subdir != "") extraAttrs["dir"] = to.subdir;
fetchers::overrideRegistry(from.input, to.input, extraAttrs);

View file

@ -18,7 +18,7 @@ extern char ** savedArgv;
class EvalState;
struct Pos;
class Store;
class LocalFSStore;
struct LocalFSStore;
static constexpr Command::Category catHelp = -1;
static constexpr Command::Category catSecondary = 100;
@ -287,13 +287,16 @@ struct StorePathCommand : public StorePathsCommand
struct RegisterCommand
{
typedef std::map<std::vector<std::string>, std::function<ref<Command>()>> Commands;
static Commands * commands;
static Commands & commands()
{
static Commands commands;
return commands;
}
RegisterCommand(std::vector<std::string> && name, std::function<ref<Command>()> command)
{
if (!commands)
commands = new Commands;
commands->emplace(name, command);
commands().emplace(name, command);
}
static nix::Commands getCommandsFor(const std::vector<std::string> & prefix);
@ -365,7 +368,7 @@ void completeFlakeRefWithFragment(
const Strings & defaultFlakeAttrPaths,
std::string_view prefix);
std::string showVersions(const std::set<std::string> & versions);
std::string showVersions(const StringSet & versions);
void printClosureDiff(
ref<Store> store, const StorePath & beforePath, const StorePath & afterPath, std::string_view indent);
@ -376,4 +379,41 @@ void printClosureDiff(
*/
void createOutLinks(const std::filesystem::path & outLink, const BuiltPaths & buildables, LocalFSStore & store);
}
/** `outLink` parameter, `createOutLinksMaybe` method. See `MixOutLinkByDefault`. */
struct MixOutLinkBase : virtual Args
{
/** Prefix for any output symlinks. Empty means do not write an output symlink. */
Path outLink;
MixOutLinkBase(const std::string & defaultOutLink)
: outLink(defaultOutLink)
{
}
void createOutLinksMaybe(const std::vector<BuiltPathWithResult> & buildables, ref<Store> & store);
};
/** `--out-link`, `--no-link`, `createOutLinksMaybe` */
struct MixOutLinkByDefault : MixOutLinkBase, virtual Args
{
MixOutLinkByDefault()
: MixOutLinkBase("result")
{
addFlag({
.longName = "out-link",
.shortName = 'o',
.description = "Use *path* as prefix for the symlinks to the build results. It defaults to `result`.",
.labels = {"path"},
.handler = {&outLink},
.completer = completePath,
});
addFlag({
.longName = "no-link",
.description = "Do not create symlinks to the build results.",
.handler = {&outLink, Path("")},
});
}
};
} // namespace nix

View file

@ -21,6 +21,7 @@ struct App
struct UnresolvedApp
{
App unresolved;
std::vector<BuiltPathWithResult> build(ref<Store> evalStore, ref<Store> store);
App resolve(ref<Store> evalStore, ref<Store> store);
};

View file

@ -12,12 +12,15 @@ typedef std::function<void(int, char * *)> MainFunction;
struct RegisterLegacyCommand
{
typedef std::map<std::string, MainFunction> Commands;
static Commands * commands;
static Commands & commands() {
static Commands commands;
return commands;
}
RegisterLegacyCommand(const std::string & name, MainFunction fun)
{
if (!commands) commands = new Commands;
(*commands)[name] = fun;
commands()[name] = fun;
}
};

View file

@ -72,7 +72,7 @@ DerivedPathsWithInfo InstallableAttrPath::toDerivedPaths()
auto newOutputs = std::visit(overloaded {
[&](const ExtendedOutputsSpec::Default & d) -> OutputsSpec {
std::set<std::string> outputsToInstall;
StringSet outputsToInstall;
for (auto & output : packageInfo.queryOutputs(false, true))
outputsToInstall.insert(output.first);
if (outputsToInstall.empty())

View file

@ -117,7 +117,7 @@ DerivedPathsWithInfo InstallableFlake::toDerivedPaths()
.drvPath = makeConstantStorePathRef(std::move(drvPath)),
.outputs = std::visit(overloaded {
[&](const ExtendedOutputsSpec::Default & d) -> OutputsSpec {
std::set<std::string> outputsToInstall;
StringSet outputsToInstall;
if (auto aOutputSpecified = attr->maybeGetAttr(state->sOutputSpecified)) {
if (aOutputSpecified->getBool()) {
if (auto aOutputName = attr->maybeGetAttr("outputName"))

View file

@ -31,8 +31,6 @@
namespace nix {
namespace fs { using namespace std::filesystem; }
void completeFlakeInputAttrPath(
AddCompletions & completions,
ref<EvalState> evalState,
@ -343,7 +341,7 @@ void completeFlakeRefWithFragment(
auto flakeRefS = std::string(prefix.substr(0, hash));
// TODO: ideally this would use the command base directory instead of assuming ".".
auto flakeRef = parseFlakeRef(fetchSettings, expandTilde(flakeRefS), fs::current_path().string());
auto flakeRef = parseFlakeRef(fetchSettings, expandTilde(flakeRefS), std::filesystem::current_path().string());
auto evalCache = openEvalCache(*evalState,
std::make_shared<flake::LockedFlake>(lockFlake(
@ -488,7 +486,11 @@ Installables SourceExprCommand::parseInstallables(
throw UsageError("'--file' and '--expr' are exclusive");
// FIXME: backward compatibility hack
if (file) evalSettings.pureEval = false;
if (file) {
if (evalSettings.pureEval && evalSettings.pureEval.overridden)
throw UsageError("'--file' is not compatible with '--pure-eval'");
evalSettings.pureEval = false;
}
auto state = getEvalState();
auto vFile = state->allocValue();

View file

@ -1,7 +0,0 @@
#include "nix/cmd/legacy.hh"
namespace nix {
RegisterLegacyCommand::Commands * RegisterLegacyCommand::commands = 0;
}

View file

@ -71,7 +71,6 @@ sources = files(
'installable-flake.cc',
'installable-value.cc',
'installables.cc',
'legacy.cc',
'markdown.cc',
'misc-store-flags.cc',
'network-proxy.cc',

View file

@ -135,7 +135,7 @@ static constexpr const char * promptForType(ReplPromptType promptType)
case ReplPromptType::ReplPrompt:
return "nix-repl> ";
case ReplPromptType::ContinuationPrompt:
return " ";
return " > "; // 9 spaces + >
}
assert(false);
}

View file

@ -12,7 +12,7 @@
#include "nix/expr/eval-settings.hh"
#include "nix/expr/attr-path.hh"
#include "nix/util/signals.hh"
#include "nix/store/store-api.hh"
#include "nix/store/store-open.hh"
#include "nix/store/log-store.hh"
#include "nix/cmd/common-eval-args.hh"
#include "nix/expr/get-drvs.hh"
@ -61,7 +61,10 @@ struct NixRepl
{
size_t debugTraceIndex;
// Arguments passed to :load, saved so they can be reloaded with :reload
Strings loadedFiles;
// Arguments passed to :load-flake, saved so they can be reloaded with :reload
Strings loadedFlakes;
std::function<AnnotatedValues()> getValues;
const static int envSize = 32768;
@ -90,7 +93,8 @@ struct NixRepl
void loadFile(const Path & path);
void loadFlake(const std::string & flakeRef);
void loadFiles();
void reloadFiles();
void loadFlakes();
void reloadFilesAndFlakes();
void addAttrsToScope(Value & attrs);
void addVarToScope(const Symbol name, Value & v);
Expr * parseString(std::string s);
@ -244,14 +248,13 @@ StringSet NixRepl::completePrefix(const std::string & prefix)
try {
auto dir = std::string(cur, 0, slash);
auto prefix2 = std::string(cur, slash + 1);
for (auto & entry : std::filesystem::directory_iterator{dir == "" ? "/" : dir}) {
for (auto & entry : DirectoryIterator{dir == "" ? "/" : dir}) {
checkInterrupt();
auto name = entry.path().filename().string();
if (name[0] != '.' && hasPrefix(name, prefix2))
completions.insert(prev + entry.path().string());
}
} catch (Error &) {
} catch (std::filesystem::filesystem_error &) {
}
} else if ((dot = cur.rfind('.')) == std::string::npos) {
/* This is a variable name; look it up in the current scope. */
@ -467,7 +470,7 @@ ProcessLineResult NixRepl::processLine(std::string line)
else if (command == ":r" || command == ":reload") {
state->resetFileCache();
reloadFiles();
reloadFilesAndFlakes();
}
else if (command == ":e" || command == ":edit") {
@ -502,7 +505,7 @@ ProcessLineResult NixRepl::processLine(std::string line)
// Reload right after exiting the editor
state->resetFileCache();
reloadFiles();
reloadFilesAndFlakes();
}
else if (command == ":t") {
@ -717,6 +720,9 @@ void NixRepl::loadFlake(const std::string & flakeRefS)
if (flakeRefS.empty())
throw Error("cannot use ':load-flake' without a path specified. (Use '.' for the current working directory.)");
loadedFlakes.remove(flakeRefS);
loadedFlakes.push_back(flakeRefS);
std::filesystem::path cwd;
try {
cwd = std::filesystem::current_path();
@ -755,11 +761,12 @@ void NixRepl::initEnv()
}
void NixRepl::reloadFiles()
void NixRepl::reloadFilesAndFlakes()
{
initEnv();
loadFiles();
loadFlakes();
}
@ -780,6 +787,18 @@ void NixRepl::loadFiles()
}
void NixRepl::loadFlakes()
{
Strings old = loadedFlakes;
loadedFlakes.clear();
for (auto & i : old) {
notice("Loading flake '%1%'...", i);
loadFlake(i);
}
}
void NixRepl::addAttrsToScope(Value & attrs)
{
state->forceAttrs(attrs, [&]() { return attrs.determinePos(noPos); }, "while evaluating an attribute set to be merged in the global scope");