aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/build-remote/build-remote.cc2
-rw-r--r--src/libcmd/command.cc6
-rw-r--r--src/libcmd/command.hh58
-rw-r--r--src/libcmd/installable-flake.cc3
-rw-r--r--src/libcmd/installables.cc92
-rw-r--r--src/libcmd/installables.hh19
-rw-r--r--src/libexpr/eval.cc4
-rw-r--r--src/libexpr/parser.y4
-rw-r--r--src/libexpr/primops/fetchTree.cc54
-rw-r--r--src/libexpr/tests/primops.cc4
-rw-r--r--src/libexpr/value-to-xml.cc8
-rw-r--r--src/libfetchers/git.cc2
-rw-r--r--src/libmain/progress-bar.cc6
-rw-r--r--src/libmain/shared.cc16
-rw-r--r--src/libstore/build/derivation-goal.cc2
-rw-r--r--src/libstore/build/drv-output-substitution-goal.cc23
-rw-r--r--src/libstore/build/drv-output-substitution-goal.hh12
-rw-r--r--src/libstore/build/goal.cc4
-rw-r--r--src/libstore/build/goal.hh2
-rw-r--r--src/libstore/build/hook-instance.cc2
-rw-r--r--src/libstore/build/local-derivation-goal.cc98
-rw-r--r--src/libstore/build/local-derivation-goal.hh7
-rw-r--r--src/libstore/daemon.cc4
-rw-r--r--src/libstore/export-import.cc4
-rw-r--r--src/libstore/filetransfer.cc4
-rw-r--r--src/libstore/gc.cc53
-rw-r--r--src/libstore/globals.cc14
-rw-r--r--src/libstore/local-store.cc6
-rw-r--r--src/libstore/optimise-store.cc17
-rw-r--r--src/libstore/pathlocks.cc8
-rw-r--r--src/libstore/profiles.cc4
-rw-r--r--src/libstore/references.cc3
-rw-r--r--src/libstore/s3-binary-cache-store.cc12
-rw-r--r--src/libstore/store-api.cc14
-rw-r--r--src/libutil/archive.cc4
-rw-r--r--src/libutil/args.hh1
-rw-r--r--src/libutil/filesystem.cc4
-rw-r--r--src/libutil/fmt.hh15
-rw-r--r--src/libutil/logging.cc8
-rw-r--r--src/libutil/logging.hh6
-rw-r--r--src/libutil/serialise.cc4
-rw-r--r--src/libutil/util.cc21
-rw-r--r--src/libutil/util.hh8
-rw-r--r--src/nix-build/nix-build.cc4
-rw-r--r--src/nix-collect-garbage/nix-collect-garbage.cc5
-rwxr-xr-xsrc/nix-copy-closure/nix-copy-closure.cc2
-rw-r--r--src/nix-env/nix-env.cc22
-rw-r--r--src/nix-env/user-env.cc4
-rw-r--r--src/nix-store/nix-store.cc15
-rw-r--r--src/nix/app.cc4
-rw-r--r--src/nix/build.cc2
-rw-r--r--src/nix/build.md2
-rw-r--r--src/nix/bundle.cc2
-rw-r--r--src/nix/bundle.md2
-rw-r--r--src/nix/copy.cc2
-rw-r--r--src/nix/daemon.cc6
-rw-r--r--src/nix/develop.cc21
-rw-r--r--src/nix/develop.md2
-rw-r--r--src/nix/doctor.cc2
-rw-r--r--src/nix/edit.cc2
-rw-r--r--src/nix/eval.cc2
-rw-r--r--src/nix/eval.md2
-rw-r--r--src/nix/flake.cc1
-rw-r--r--src/nix/flake.md4
-rw-r--r--src/nix/hash.cc39
-rw-r--r--src/nix/log.cc2
-rw-r--r--src/nix/log.md3
-rw-r--r--src/nix/main.cc1
-rw-r--r--src/nix/make-content-addressed.cc1
-rw-r--r--src/nix/make-content-addressed.md4
-rw-r--r--src/nix/nar.cc1
-rw-r--r--src/nix/nix.md168
-rw-r--r--src/nix/path-info.md2
-rw-r--r--src/nix/print-dev-env.md2
-rw-r--r--src/nix/profile-install.md2
-rw-r--r--src/nix/profile.cc15
-rw-r--r--src/nix/realisation.cc1
-rw-r--r--src/nix/registry.cc1
-rw-r--r--src/nix/repl.cc41
-rw-r--r--src/nix/run.cc4
-rw-r--r--src/nix/run.md2
-rw-r--r--src/nix/search.cc2
-rw-r--r--src/nix/search.md6
-rw-r--r--src/nix/shell.md2
-rw-r--r--src/nix/show-derivation.cc2
-rw-r--r--src/nix/show-derivation.md2
-rw-r--r--src/nix/sigs.cc3
-rw-r--r--src/nix/store-copy-log.cc2
-rw-r--r--src/nix/store-delete.cc2
-rw-r--r--src/nix/store-delete.md2
-rw-r--r--src/nix/store-dump-path.md2
-rw-r--r--src/nix/store-repair.cc2
-rw-r--r--src/nix/store-repair.md2
-rw-r--r--src/nix/store.cc1
-rw-r--r--src/nix/verify.md2
-rw-r--r--src/resolve-system-dependencies/resolve-system-dependencies.cc8
96 files changed, 578 insertions, 501 deletions
diff --git a/src/build-remote/build-remote.cc b/src/build-remote/build-remote.cc
index 174435e7c..63e3e3fa9 100644
--- a/src/build-remote/build-remote.cc
+++ b/src/build-remote/build-remote.cc
@@ -219,7 +219,7 @@ static int main_build_remote(int argc, char * * argv)
% concatStringsSep<StringSet>(", ", m.supportedFeatures)
% concatStringsSep<StringSet>(", ", m.mandatoryFeatures);
- printMsg(couldBuildLocally ? lvlChatty : lvlWarn, error);
+ printMsg(couldBuildLocally ? lvlChatty : lvlWarn, error.str());
std::cerr << "# decline\n";
}
diff --git a/src/libcmd/command.cc b/src/libcmd/command.cc
index ab51c229d..bedf11e2c 100644
--- a/src/libcmd/command.cc
+++ b/src/libcmd/command.cc
@@ -165,7 +165,7 @@ BuiltPathsCommand::BuiltPathsCommand(bool recursive)
});
}
-void BuiltPathsCommand::run(ref<Store> store)
+void BuiltPathsCommand::run(ref<Store> store, Installables && installables)
{
BuiltPaths paths;
if (all) {
@@ -211,7 +211,7 @@ void StorePathsCommand::run(ref<Store> store, BuiltPaths && paths)
run(store, std::move(sorted));
}
-void StorePathCommand::run(ref<Store> store, std::vector<StorePath> && storePaths)
+void StorePathCommand::run(ref<Store> store, StorePaths && storePaths)
{
if (storePaths.size() != 1)
throw UsageError("this command requires exactly one store path");
@@ -246,7 +246,7 @@ void MixProfile::updateProfile(const BuiltPaths & buildables)
{
if (!profile) return;
- std::vector<StorePath> result;
+ StorePaths result;
for (auto & buildable : buildables) {
std::visit(overloaded {
diff --git a/src/libcmd/command.hh b/src/libcmd/command.hh
index b6d554aab..874ca3249 100644
--- a/src/libcmd/command.hh
+++ b/src/libcmd/command.hh
@@ -22,13 +22,16 @@ static constexpr Command::Category catSecondary = 100;
static constexpr Command::Category catUtility = 101;
static constexpr Command::Category catNixInstallation = 102;
-static constexpr auto installablesCategory = "Options that change the interpretation of installables";
+static constexpr auto installablesCategory = "Options that change the interpretation of [installables](@docroot@/command-ref/new-cli/nix.md#installables)";
struct NixMultiCommand : virtual MultiCommand, virtual Command
{
nlohmann::json toJSON() override;
};
+// For the overloaded run methods
+#pragma GCC diagnostic ignored "-Woverloaded-virtual"
+
/* A command that requires a Nix store. */
struct StoreCommand : virtual Command
{
@@ -97,10 +100,10 @@ struct SourceExprCommand : virtual Args, MixFlakeOptions
SourceExprCommand();
- std::vector<std::shared_ptr<Installable>> parseInstallables(
+ Installables parseInstallables(
ref<Store> store, std::vector<std::string> ss);
- std::shared_ptr<Installable> parseInstallable(
+ ref<Installable> parseInstallable(
ref<Store> store, const std::string & installable);
virtual Strings getDefaultFlakeAttrPaths();
@@ -115,34 +118,43 @@ struct MixReadOnlyOption : virtual Args
MixReadOnlyOption();
};
-/* A command that operates on a list of "installables", which can be
- store paths, attribute paths, Nix expressions, etc. */
-struct InstallablesCommand : virtual Args, SourceExprCommand
+/* Like InstallablesCommand but the installables are not loaded */
+struct RawInstallablesCommand : virtual Args, SourceExprCommand
{
- std::vector<std::shared_ptr<Installable>> installables;
+ RawInstallablesCommand();
- InstallablesCommand();
+ virtual void run(ref<Store> store, std::vector<std::string> && rawInstallables) = 0;
+
+ void run(ref<Store> store) override;
- void prepare() override;
- Installables load();
+ // FIXME make const after CmdRepl's override is fixed up
+ virtual void applyDefaultInstallables(std::vector<std::string> & rawInstallables);
- virtual bool useDefaultInstallables() { return true; }
+ bool readFromStdIn = false;
std::vector<std::string> getFlakesForCompletion() override;
-protected:
+private:
- std::vector<std::string> _installables;
+ std::vector<std::string> rawInstallables;
+};
+/* A command that operates on a list of "installables", which can be
+ store paths, attribute paths, Nix expressions, etc. */
+struct InstallablesCommand : RawInstallablesCommand
+{
+ virtual void run(ref<Store> store, Installables && installables) = 0;
+
+ void run(ref<Store> store, std::vector<std::string> && rawInstallables) override;
};
/* A command that operates on exactly one "installable" */
struct InstallableCommand : virtual Args, SourceExprCommand
{
- std::shared_ptr<Installable> installable;
-
InstallableCommand();
- void prepare() override;
+ virtual void run(ref<Store> store, ref<Installable> installable) = 0;
+
+ void run(ref<Store> store) override;
std::vector<std::string> getFlakesForCompletion() override
{
@@ -177,22 +189,18 @@ public:
BuiltPathsCommand(bool recursive = false);
- using StoreCommand::run;
-
virtual void run(ref<Store> store, BuiltPaths && paths) = 0;
- void run(ref<Store> store) override;
+ void run(ref<Store> store, Installables && installables) override;
- bool useDefaultInstallables() override { return !all; }
+ void applyDefaultInstallables(std::vector<std::string> & rawInstallables) override;
};
struct StorePathsCommand : public BuiltPathsCommand
{
StorePathsCommand(bool recursive = false);
- using BuiltPathsCommand::run;
-
- virtual void run(ref<Store> store, std::vector<StorePath> && storePaths) = 0;
+ virtual void run(ref<Store> store, StorePaths && storePaths) = 0;
void run(ref<Store> store, BuiltPaths && paths) override;
};
@@ -200,11 +208,9 @@ struct StorePathsCommand : public BuiltPathsCommand
/* A command that operates on exactly one store path. */
struct StorePathCommand : public StorePathsCommand
{
- using StorePathsCommand::run;
-
virtual void run(ref<Store> store, const StorePath & storePath) = 0;
- void run(ref<Store> store, std::vector<StorePath> && storePaths) override;
+ void run(ref<Store> store, StorePaths && storePaths) override;
};
/* A helper class for registering commands globally. */
diff --git a/src/libcmd/installable-flake.cc b/src/libcmd/installable-flake.cc
index 60a97deaf..7b0cc376d 100644
--- a/src/libcmd/installable-flake.cc
+++ b/src/libcmd/installable-flake.cc
@@ -178,8 +178,7 @@ std::pair<Value *, PosIdx> InstallableFlake::toValue(EvalState & state)
std::vector<ref<eval_cache::AttrCursor>>
InstallableFlake::getCursors(EvalState & state)
{
- auto evalCache = openEvalCache(state,
- std::make_shared<flake::LockedFlake>(lockFlake(state, flakeRef, lockFlags)));
+ auto evalCache = openEvalCache(state, getLockedFlake());
auto root = evalCache->getRoot();
diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc
index 90f001902..5cbf26b88 100644
--- a/src/libcmd/installables.cc
+++ b/src/libcmd/installables.cc
@@ -153,7 +153,7 @@ SourceExprCommand::SourceExprCommand()
.longName = "file",
.shortName = 'f',
.description =
- "Interpret installables as attribute paths relative to the Nix expression stored in *file*. "
+ "Interpret [*installables*](@docroot@/command-ref/new-cli/nix.md#installables) as attribute paths relative to the Nix expression stored in *file*. "
"If *file* is the character -, then a Nix expression will be read from standard input. "
"Implies `--impure`.",
.category = installablesCategory,
@@ -164,7 +164,7 @@ SourceExprCommand::SourceExprCommand()
addFlag({
.longName = "expr",
- .description = "Interpret installables as attribute paths relative to the Nix expression *expr*.",
+ .description = "Interpret [*installables*](@docroot@/command-ref/new-cli/nix.md#installables) as attribute paths relative to the Nix expression *expr*.",
.category = installablesCategory,
.labels = {"expr"},
.handler = {&expr}
@@ -422,10 +422,10 @@ ref<eval_cache::EvalCache> openEvalCache(
});
}
-std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
+Installables SourceExprCommand::parseInstallables(
ref<Store> store, std::vector<std::string> ss)
{
- std::vector<std::shared_ptr<Installable>> result;
+ Installables result;
if (file || expr) {
if (file && expr)
@@ -451,7 +451,7 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
for (auto & s : ss) {
auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse(s);
result.push_back(
- std::make_shared<InstallableAttrPath>(
+ make_ref<InstallableAttrPath>(
InstallableAttrPath::parse(
state, *this, vFile, prefix, extendedOutputsSpec)));
}
@@ -468,7 +468,7 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
if (prefix.find('/') != std::string::npos) {
try {
- result.push_back(std::make_shared<InstallableDerivedPath>(
+ result.push_back(make_ref<InstallableDerivedPath>(
InstallableDerivedPath::parse(store, prefix, extendedOutputsSpec)));
continue;
} catch (BadStorePath &) {
@@ -480,7 +480,7 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
try {
auto [flakeRef, fragment] = parseFlakeRefWithFragment(std::string { prefix }, absPath("."));
- result.push_back(std::make_shared<InstallableFlake>(
+ result.push_back(make_ref<InstallableFlake>(
this,
getEvalState(),
std::move(flakeRef),
@@ -501,7 +501,7 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
return result;
}
-std::shared_ptr<Installable> SourceExprCommand::parseInstallable(
+ref<Installable> SourceExprCommand::parseInstallable(
ref<Store> store, const std::string & installable)
{
auto installables = parseInstallables(store, {installable});
@@ -513,7 +513,7 @@ std::vector<BuiltPathWithResult> Installable::build(
ref<Store> evalStore,
ref<Store> store,
Realise mode,
- const std::vector<std::shared_ptr<Installable>> & installables,
+ const Installables & installables,
BuildMode bMode)
{
std::vector<BuiltPathWithResult> res;
@@ -522,11 +522,11 @@ std::vector<BuiltPathWithResult> Installable::build(
return res;
}
-std::vector<std::pair<std::shared_ptr<Installable>, BuiltPathWithResult>> Installable::build2(
+std::vector<std::pair<ref<Installable>, BuiltPathWithResult>> Installable::build2(
ref<Store> evalStore,
ref<Store> store,
Realise mode,
- const std::vector<std::shared_ptr<Installable>> & installables,
+ const Installables & installables,
BuildMode bMode)
{
if (mode == Realise::Nothing)
@@ -535,7 +535,7 @@ std::vector<std::pair<std::shared_ptr<Installable>, BuiltPathWithResult>> Instal
struct Aux
{
ExtraPathInfo info;
- std::shared_ptr<Installable> installable;
+ ref<Installable> installable;
};
std::vector<DerivedPath> pathsToBuild;
@@ -548,7 +548,7 @@ std::vector<std::pair<std::shared_ptr<Installable>, BuiltPathWithResult>> Instal
}
}
- std::vector<std::pair<std::shared_ptr<Installable>, BuiltPathWithResult>> res;
+ std::vector<std::pair<ref<Installable>, BuiltPathWithResult>> res;
switch (mode) {
@@ -620,7 +620,7 @@ BuiltPaths Installable::toBuiltPaths(
ref<Store> store,
Realise mode,
OperateOn operateOn,
- const std::vector<std::shared_ptr<Installable>> & installables)
+ const Installables & installables)
{
if (operateOn == OperateOn::Output) {
BuiltPaths res;
@@ -642,7 +642,7 @@ StorePathSet Installable::toStorePaths(
ref<Store> evalStore,
ref<Store> store,
Realise mode, OperateOn operateOn,
- const std::vector<std::shared_ptr<Installable>> & installables)
+ const Installables & installables)
{
StorePathSet outPaths;
for (auto & path : toBuiltPaths(evalStore, store, mode, operateOn, installables)) {
@@ -656,7 +656,7 @@ StorePath Installable::toStorePath(
ref<Store> evalStore,
ref<Store> store,
Realise mode, OperateOn operateOn,
- std::shared_ptr<Installable> installable)
+ ref<Installable> installable)
{
auto paths = toStorePaths(evalStore, store, mode, operateOn, {installable});
@@ -668,7 +668,7 @@ StorePath Installable::toStorePath(
StorePathSet Installable::toDerivations(
ref<Store> store,
- const std::vector<std::shared_ptr<Installable>> & installables,
+ const Installables & installables,
bool useDeriver)
{
StorePathSet drvPaths;
@@ -692,36 +692,55 @@ StorePathSet Installable::toDerivations(
return drvPaths;
}
-InstallablesCommand::InstallablesCommand()
+RawInstallablesCommand::RawInstallablesCommand()
{
+ addFlag({
+ .longName = "stdin",
+ .description = "Read installables from the standard input.",
+ .handler = {&readFromStdIn, true}
+ });
+
expectArgs({
.label = "installables",
- .handler = {&_installables},
+ .handler = {&rawInstallables},
.completer = {[&](size_t, std::string_view prefix) {
completeInstallable(prefix);
}}
});
}
-void InstallablesCommand::prepare()
+void RawInstallablesCommand::applyDefaultInstallables(std::vector<std::string> & rawInstallables)
{
- installables = load();
+ if (rawInstallables.empty()) {
+ // FIXME: commands like "nix profile install" should not have a
+ // default, probably.
+ rawInstallables.push_back(".");
+ }
}
-Installables InstallablesCommand::load()
+void RawInstallablesCommand::run(ref<Store> store)
{
- if (_installables.empty() && useDefaultInstallables())
- // FIXME: commands like "nix profile install" should not have a
- // default, probably.
- _installables.push_back(".");
- return parseInstallables(getStore(), _installables);
+ if (readFromStdIn && !isatty(STDIN_FILENO)) {
+ std::string word;
+ while (std::cin >> word) {
+ rawInstallables.emplace_back(std::move(word));
+ }
+ }
+
+ applyDefaultInstallables(rawInstallables);
+ run(store, std::move(rawInstallables));
+}
+
+std::vector<std::string> RawInstallablesCommand::getFlakesForCompletion()
+{
+ applyDefaultInstallables(rawInstallables);
+ return rawInstallables;
}
-std::vector<std::string> InstallablesCommand::getFlakesForCompletion()
+void InstallablesCommand::run(ref<Store> store, std::vector<std::string> && rawInstallables)
{
- if (_installables.empty() && useDefaultInstallables())
- return {"."};
- return _installables;
+ auto installables = parseInstallables(store, rawInstallables);
+ run(store, std::move(installables));
}
InstallableCommand::InstallableCommand()
@@ -737,9 +756,16 @@ InstallableCommand::InstallableCommand()
});
}
-void InstallableCommand::prepare()
+void InstallableCommand::run(ref<Store> store)
+{
+ auto installable = parseInstallable(store, _installable);
+ run(store, std::move(installable));
+}
+
+void BuiltPathsCommand::applyDefaultInstallables(std::vector<std::string> & rawInstallables)
{
- installable = parseInstallable(getStore(), _installable);
+ if (rawInstallables.empty() && !all)
+ rawInstallables.push_back(".");
}
}
diff --git a/src/libcmd/installables.hh b/src/libcmd/installables.hh
index be77fdc81..6c2922d89 100644
--- a/src/libcmd/installables.hh
+++ b/src/libcmd/installables.hh
@@ -79,6 +79,9 @@ struct BuiltPathWithResult
typedef std::vector<DerivedPathWithInfo> DerivedPathsWithInfo;
+struct Installable;
+typedef std::vector<ref<Installable>> Installables;
+
struct Installable
{
virtual ~Installable() { }
@@ -122,14 +125,14 @@ struct Installable
ref<Store> evalStore,
ref<Store> store,
Realise mode,
- const std::vector<std::shared_ptr<Installable>> & installables,
+ const Installables & installables,
BuildMode bMode = bmNormal);
- static std::vector<std::pair<std::shared_ptr<Installable>, BuiltPathWithResult>> build2(
+ static std::vector<std::pair<ref<Installable>, BuiltPathWithResult>> build2(
ref<Store> evalStore,
ref<Store> store,
Realise mode,
- const std::vector<std::shared_ptr<Installable>> & installables,
+ const Installables & installables,
BuildMode bMode = bmNormal);
static std::set<StorePath> toStorePaths(
@@ -137,18 +140,18 @@ struct Installable
ref<Store> store,
Realise mode,
OperateOn operateOn,
- const std::vector<std::shared_ptr<Installable>> & installables);
+ const Installables & installables);
static StorePath toStorePath(
ref<Store> evalStore,
ref<Store> store,
Realise mode,
OperateOn operateOn,
- std::shared_ptr<Installable> installable);
+ ref<Installable> installable);
static std::set<StorePath> toDerivations(
ref<Store> store,
- const std::vector<std::shared_ptr<Installable>> & installables,
+ const Installables & installables,
bool useDeriver = false);
static BuiltPaths toBuiltPaths(
@@ -156,9 +159,7 @@ struct Installable
ref<Store> store,
Realise mode,
OperateOn operateOn,
- const std::vector<std::shared_ptr<Installable>> & installables);
+ const Installables & installables);
};
-typedef std::vector<std::shared_ptr<Installable>> Installables;
-
}
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 21fc4d0fe..2721b6733 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -368,7 +368,7 @@ void initGC()
size = (pageSize * pages) / 4; // 25% of RAM
if (size > maxSize) size = maxSize;
#endif
- debug(format("setting initial heap size to %1% bytes") % size);
+ debug("setting initial heap size to %1% bytes", size);
GC_expand_hp(size);
}
@@ -609,7 +609,7 @@ Path EvalState::checkSourcePath(const Path & path_)
}
/* Resolve symlinks. */
- debug(format("checking access to '%s'") % abspath);
+ debug("checking access to '%s'", abspath);
Path path = canonPath(abspath, true);
for (auto & i : *allowedPaths) {
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index dec5818fc..0f75ed9a0 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -732,7 +732,7 @@ Expr * EvalState::parseExprFromString(std::string s, const Path & basePath)
Expr * EvalState::parseStdin()
{
- //Activity act(*logger, lvlTalkative, format("parsing standard input"));
+ //Activity act(*logger, lvlTalkative, "parsing standard input");
auto buffer = drainFD(0);
// drainFD should have left some extra space for terminators
buffer.append("\0\0", 2);
@@ -835,7 +835,7 @@ std::pair<bool, std::string> EvalState::resolveSearchPathElem(const SearchPathEl
}
}
- debug(format("resolved search path element '%s' to '%s'") % elem.second % res.second);
+ debug("resolved search path element '%s' to '%s'", elem.second, res.second);
searchPathResolved[elem.second] = res;
return res;
diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc
index c9faf3ffb..fd51dfb90 100644
--- a/src/libexpr/primops/fetchTree.cc
+++ b/src/libexpr/primops/fetchTree.cc
@@ -353,36 +353,44 @@ static RegisterPrimOp primop_fetchGit({
of the repo at that URL is fetched. Otherwise, it can be an
attribute with the following attributes (all except `url` optional):
- - url\
- The URL of the repo.
+ - `url`
- - name\
- The name of the directory the repo should be exported to in the
- store. Defaults to the basename of the URL.
+ The URL of the repo.
- - rev\
- The git revision to fetch. Defaults to the tip of `ref`.
+ - `name` (default: *basename of the URL*)
- - ref\
- The git ref to look for the requested revision under. This is
- often a branch or tag name. Defaults to `HEAD`.
+ The name of the directory the repo should be exported to in the store.
- By default, the `ref` value is prefixed with `refs/heads/`. As
- of Nix 2.3.0 Nix will not prefix `refs/heads/` if `ref` starts
- with `refs/`.
+ - `rev` (default: *the tip of `ref`*)
- - submodules\
- A Boolean parameter that specifies whether submodules should be
- checked out. Defaults to `false`.
+ The [Git revision] to fetch.
+ This is typically a commit hash.
- - shallow\
- A Boolean parameter that specifies whether fetching a shallow clone
- is allowed. Defaults to `false`.
+ [Git revision]: https://git-scm.com/docs/git-rev-parse#_specifying_revisions
- - allRefs\
- Whether to fetch all refs of the repository. With this argument being
- true, it's possible to load a `rev` from *any* `ref` (by default only
- `rev`s from the specified `ref` are supported).
+ - `ref` (default: `HEAD`)
+
+ The [Git reference] under which to look for the requested revision.
+ This is often a branch or tag name.
+
+ [Git reference]: https://git-scm.com/book/en/v2/Git-Internals-Git-References
+
+ By default, the `ref` value is prefixed with `refs/heads/`.
+ As of 2.3.0, Nix will not prefix `refs/heads/` if `ref` starts with `refs/`.
+
+ - `submodules` (default: `false`)
+
+ A Boolean parameter that specifies whether submodules should be checked out.
+
+ - `shallow` (default: `false`)
+
+ A Boolean parameter that specifies whether fetching a shallow clone is allowed.
+
+ - `allRefs`
+
+ Whether to fetch all references of the repository.
+ With this argument being true, it's possible to load a `rev` from *any* `ref`
+ (by default only `rev`s from the specified `ref` are supported).
Here are some examples of how to use `fetchGit`.
diff --git a/src/libexpr/tests/primops.cc b/src/libexpr/tests/primops.cc
index e1d3ac503..ce3b5d11f 100644
--- a/src/libexpr/tests/primops.cc
+++ b/src/libexpr/tests/primops.cc
@@ -15,8 +15,8 @@ namespace nix {
return oss.str();
}
- void log(Verbosity lvl, const FormatOrString & fs) override {
- oss << fs.s << std::endl;
+ void log(Verbosity lvl, std::string_view s) override {
+ oss << s << std::endl;
}
void logEI(const ErrorInfo & ei) override {
diff --git a/src/libexpr/value-to-xml.cc b/src/libexpr/value-to-xml.cc
index 3f6222768..341c8922f 100644
--- a/src/libexpr/value-to-xml.cc
+++ b/src/libexpr/value-to-xml.cc
@@ -26,8 +26,8 @@ static void posToXML(EvalState & state, XMLAttrs & xmlAttrs, const Pos & pos)
{
if (auto path = std::get_if<Path>(&pos.origin))
xmlAttrs["path"] = *path;
- xmlAttrs["line"] = (format("%1%") % pos.line).str();
- xmlAttrs["column"] = (format("%1%") % pos.column).str();
+ xmlAttrs["line"] = fmt("%1%", pos.line);
+ xmlAttrs["column"] = fmt("%1%", pos.column);
}
@@ -64,7 +64,7 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
switch (v.type()) {
case nInt:
- doc.writeEmptyElement("int", singletonAttrs("value", (format("%1%") % v.integer).str()));
+ doc.writeEmptyElement("int", singletonAttrs("value", fmt("%1%", v.integer)));
break;
case nBool:
@@ -156,7 +156,7 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
break;
case nFloat:
- doc.writeEmptyElement("float", singletonAttrs("value", (format("%1%") % v.fpoint).str()));
+ doc.writeEmptyElement("float", singletonAttrs("value", fmt("%1%", v.fpoint)));
break;
case nThunk:
diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc
index 309a143f5..1da8c9609 100644
--- a/src/libfetchers/git.cc
+++ b/src/libfetchers/git.cc
@@ -266,7 +266,7 @@ struct GitInputScheme : InputScheme
for (auto & [name, value] : url.query) {
if (name == "rev" || name == "ref")
attrs.emplace(name, value);
- else if (name == "shallow" || name == "submodules")
+ else if (name == "shallow" || name == "submodules" || name == "allRefs")
attrs.emplace(name, Explicit<bool> { value == "1" });
else
url2.query.emplace(name, value);
diff --git a/src/libmain/progress-bar.cc b/src/libmain/progress-bar.cc
index e9205a5e5..024259584 100644
--- a/src/libmain/progress-bar.cc
+++ b/src/libmain/progress-bar.cc
@@ -125,11 +125,11 @@ public:
return printBuildLogs;
}
- void log(Verbosity lvl, const FormatOrString & fs) override
+ void log(Verbosity lvl, std::string_view s) override
{
if (lvl > verbosity) return;
auto state(state_.lock());
- log(*state, lvl, fs.s);
+ log(*state, lvl, s);
}
void logEI(const ErrorInfo & ei) override
@@ -142,7 +142,7 @@ public:
log(*state, ei.level, oss.str());
}
- void log(State & state, Verbosity lvl, const std::string & s)
+ void log(State & state, Verbosity lvl, std::string_view s)
{
if (state.active) {
writeToStderr("\r\e[K" + filterANSIEscapes(s, !isTTY) + ANSI_NORMAL "\n");
diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc
index d4871a8e2..37664c065 100644
--- a/src/libmain/shared.cc
+++ b/src/libmain/shared.cc
@@ -84,8 +84,18 @@ void printMissing(ref<Store> store, const StorePathSet & willBuild,
downloadSizeMiB,
narSizeMiB);
}
- for (auto & i : willSubstitute)
- printMsg(lvl, " %s", store->printStorePath(i));
+ std::vector<const StorePath *> willSubstituteSorted = {};
+ std::for_each(willSubstitute.begin(), willSubstitute.end(),
+ [&](const StorePath &p) { willSubstituteSorted.push_back(&p); });
+ std::sort(willSubstituteSorted.begin(), willSubstituteSorted.end(),
+ [](const StorePath *lhs, const StorePath *rhs) {
+ if (lhs->name() == rhs->name())
+ return lhs->to_string() < rhs->to_string();
+ else
+ return lhs->name() < rhs->name();
+ });
+ for (auto p : willSubstituteSorted)
+ printMsg(lvl, " %s", store->printStorePath(*p));
}
if (!unknown.empty()) {
@@ -347,7 +357,7 @@ void parseCmdLine(const std::string & programName, const Strings & args,
void printVersion(const std::string & programName)
{
- std::cout << format("%1% (Nix) %2%") % programName % nixVersion << std::endl;
+ std::cout << fmt("%1% (Nix) %2%", programName, nixVersion) << std::endl;
if (verbosity > lvlInfo) {
Strings cfg;
#if HAVE_BOEHMGC
diff --git a/src/libstore/build/derivation-goal.cc b/src/libstore/build/derivation-goal.cc
index 2021d0023..38b73d531 100644
--- a/src/libstore/build/derivation-goal.cc
+++ b/src/libstore/build/derivation-goal.cc
@@ -732,7 +732,7 @@ void replaceValidPath(const Path & storePath, const Path & tmpPath)
tmpPath (the replacement), so we have to move it out of the
way first. We'd better not be interrupted here, because if
we're repairing (say) Glibc, we end up with a broken system. */
- Path oldPath = (format("%1%.old-%2%-%3%") % storePath % getpid() % random()).str();
+ Path oldPath = fmt("%1%.old-%2%-%3%", storePath, getpid(), random());
if (pathExists(storePath))
movePath(storePath, oldPath);
diff --git a/src/libstore/build/drv-output-substitution-goal.cc b/src/libstore/build/drv-output-substitution-goal.cc
index b7f7b5ab1..b30957c84 100644
--- a/src/libstore/build/drv-output-substitution-goal.cc
+++ b/src/libstore/build/drv-output-substitution-goal.cc
@@ -61,20 +61,25 @@ void DrvOutputSubstitutionGoal::tryNext()
// FIXME: Make async
// outputInfo = sub->queryRealisation(id);
- outPipe.create();
- promise = decltype(promise)();
+
+ /* The callback of the curl download below can outlive `this` (if
+ some other error occurs), so it must not touch `this`. So put
+ the shared state in a separate refcounted object. */
+ downloadState = std::make_shared<DownloadState>();
+ downloadState->outPipe.create();
sub->queryRealisation(
- id, { [&](std::future<std::shared_ptr<const Realisation>> res) {
+ id,
+ { [downloadState(downloadState)](std::future<std::shared_ptr<const Realisation>> res) {
try {
- Finally updateStats([this]() { outPipe.writeSide.close(); });
- promise.set_value(res.get());
+ Finally updateStats([&]() { downloadState->outPipe.writeSide.close(); });
+ downloadState->promise.set_value(res.get());
} catch (...) {
- promise.set_exception(std::current_exception());
+ downloadState->promise.set_exception(std::current_exception());
}
} });
- worker.childStarted(shared_from_this(), {outPipe.readSide.get()}, true, false);
+ worker.childStarted(shared_from_this(), {downloadState->outPipe.readSide.get()}, true, false);
state = &DrvOutputSubstitutionGoal::realisationFetched;
}
@@ -84,7 +89,7 @@ void DrvOutputSubstitutionGoal::realisationFetched()
worker.childTerminated(this);
try {
- outputInfo = promise.get_future().get();
+ outputInfo = downloadState->promise.get_future().get();
} catch (std::exception & e) {
printError(e.what());
substituterFailed = true;
@@ -155,7 +160,7 @@ void DrvOutputSubstitutionGoal::work()
void DrvOutputSubstitutionGoal::handleEOF(int fd)
{
- if (fd == outPipe.readSide.get()) worker.wakeUp(shared_from_this());
+ if (fd == downloadState->outPipe.readSide.get()) worker.wakeUp(shared_from_this());
}
diff --git a/src/libstore/build/drv-output-substitution-goal.hh b/src/libstore/build/drv-output-substitution-goal.hh
index 948dbda8f..e4b044790 100644
--- a/src/libstore/build/drv-output-substitution-goal.hh
+++ b/src/libstore/build/drv-output-substitution-goal.hh
@@ -16,7 +16,7 @@ class Worker;
// 2. Substitute the corresponding output path
// 3. Register the output info
class DrvOutputSubstitutionGoal : public Goal {
-private:
+
// The drv output we're trying to substitue
DrvOutput id;
@@ -30,9 +30,13 @@ private:
/* The current substituter. */
std::shared_ptr<Store> sub;
- Pipe outPipe;
- std::thread thr;
- std::promise<std::shared_ptr<const Realisation>> promise;
+ struct DownloadState
+ {
+ Pipe outPipe;
+ std::promise<std::shared_ptr<const Realisation>> promise;
+ };
+
+ std::shared_ptr<DownloadState> downloadState;
/* Whether a substituter failed. */
bool substituterFailed = false;
diff --git a/src/libstore/build/goal.cc b/src/libstore/build/goal.cc
index 58e805f55..d59b94797 100644
--- a/src/libstore/build/goal.cc
+++ b/src/libstore/build/goal.cc
@@ -78,9 +78,9 @@ void Goal::amDone(ExitCode result, std::optional<Error> ex)
}
-void Goal::trace(const FormatOrString & fs)
+void Goal::trace(std::string_view s)
{
- debug("%1%: %2%", name, fs.s);
+ debug("%1%: %2%", name, s);
}
}
diff --git a/src/libstore/build/goal.hh b/src/libstore/build/goal.hh
index 35121c5d9..776eb86bc 100644
--- a/src/libstore/build/goal.hh
+++ b/src/libstore/build/goal.hh
@@ -88,7 +88,7 @@ struct Goal : public std::enable_shared_from_this<Goal>
abort();
}
- void trace(const FormatOrString & fs);
+ void trace(std::string_view s);
std::string getName()
{
diff --git a/src/libstore/build/hook-instance.cc b/src/libstore/build/hook-instance.cc
index cb58a1f02..ea2ae210e 100644
--- a/src/libstore/build/hook-instance.cc
+++ b/src/libstore/build/hook-instance.cc
@@ -35,7 +35,7 @@ HookInstance::HookInstance()
/* Fork the hook. */
pid = startProcess([&]() {
- commonChildInit(fromHook);
+ commonChildInit(fromHook.writeSide.get());
if (chdir("/") == -1) throw SysError("changing into /");
diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc
index a961d8eed..521117c68 100644
--- a/src/libstore/build/local-derivation-goal.cc
+++ b/src/libstore/build/local-derivation-goal.cc
@@ -292,7 +292,7 @@ void LocalDerivationGoal::closeReadPipes()
if (hook) {
DerivationGoal::closeReadPipes();
} else
- builderOut.readSide = -1;
+ builderOut.close();
}
@@ -650,7 +650,7 @@ void LocalDerivationGoal::startBuilder()
/* Clean up the chroot directory automatically. */
autoDelChroot = std::make_shared<AutoDelete>(chrootRootDir);
- printMsg(lvlChatty, format("setting up chroot environment in '%1%'") % chrootRootDir);
+ printMsg(lvlChatty, "setting up chroot environment in '%1%'", chrootRootDir);
// FIXME: make this 0700
if (mkdir(chrootRootDir.c_str(), buildUser && buildUser->getUIDCount() != 1 ? 0755 : 0750) == -1)
@@ -753,8 +753,7 @@ void LocalDerivationGoal::startBuilder()
throw Error("home directory '%1%' exists; please remove it to assure purity of builds without sandboxing", homeDir);
if (useChroot && settings.preBuildHook != "" && dynamic_cast<Derivation *>(drv.get())) {
- printMsg(lvlChatty, format("executing pre-build hook '%1%'")
- % settings.preBuildHook);
+ printMsg(lvlChatty, "executing pre-build hook '%1%'", settings.preBuildHook);
auto args = useChroot ? Strings({worker.store.printStorePath(drvPath), chrootRootDir}) :
Strings({ worker.store.printStorePath(drvPath) });
enum BuildHookState {
@@ -803,15 +802,13 @@ void LocalDerivationGoal::startBuilder()
/* Create the log file. */
Path logFile = openLogFile();
- /* Create a pipe to get the output of the builder. */
- //builderOut.create();
-
- builderOut.readSide = posix_openpt(O_RDWR | O_NOCTTY);
- if (!builderOut.readSide)
+ /* Create a pseudoterminal to get the output of the builder. */
+ builderOut = posix_openpt(O_RDWR | O_NOCTTY);
+ if (!builderOut)
throw SysError("opening pseudoterminal master");
// FIXME: not thread-safe, use ptsname_r
- std::string slaveName(ptsname(builderOut.readSide.get()));
+ std::string slaveName = ptsname(builderOut.get());
if (buildUser) {
if (chmod(slaveName.c_str(), 0600))
@@ -822,35 +819,14 @@ void LocalDerivationGoal::startBuilder()
}
#if __APPLE__
else {
- if (grantpt(builderOut.readSide.get()))
+ if (grantpt(builderOut.get()))
throw SysError("granting access to pseudoterminal slave");
}
#endif
- #if 0
- // Mount the pt in the sandbox so that the "tty" command works.
- // FIXME: this doesn't work with the new devpts in the sandbox.
- if (useChroot)
- dirsInChroot[slaveName] = {slaveName, false};
- #endif
-
- if (unlockpt(builderOut.readSide.get()))
+ if (unlockpt(builderOut.get()))
throw SysError("unlocking pseudoterminal");
- builderOut.writeSide = open(slaveName.c_str(), O_RDWR | O_NOCTTY);
- if (!builderOut.writeSide)
- throw SysError("opening pseudoterminal slave");
-
- // Put the pt into raw mode to prevent \n -> \r\n translation.
- struct termios term;
- if (tcgetattr(builderOut.writeSide.get(), &term))
- throw SysError("getting pseudoterminal attributes");
-
- cfmakeraw(&term);
-
- if (tcsetattr(builderOut.writeSide.get(), TCSANOW, &term))
- throw SysError("putting pseudoterminal into raw mode");
-
buildResult.startTime = time(0);
/* Fork a child to build the package. */
@@ -898,7 +874,11 @@ void LocalDerivationGoal::startBuilder()
usingUserNamespace = userNamespacesSupported();
+ Pipe sendPid;
+ sendPid.create();
+
Pid helper = startProcess([&]() {
+ sendPid.readSide.close();
/* Drop additional groups here because we can't do it
after we've created the new user namespace. FIXME:
@@ -918,13 +898,14 @@ void LocalDerivationGoal::startBuilder()
if (usingUserNamespace)
options.cloneFlags |= CLONE_NEWUSER;
- pid_t child = startProcess([&]() { runChild(); }, options);
+ pid_t child = startProcess([&]() { runChild(slaveName); }, options);
- writeFull(builderOut.writeSide.get(),
- fmt("%d %d\n", usingUserNamespace, child));
+ writeFull(sendPid.writeSide.get(), fmt("%d\n", child));
_exit(0);
});
+ sendPid.writeSide.close();
+
if (helper.wait() != 0)
throw Error("unable to start build process");
@@ -936,10 +917,9 @@ void LocalDerivationGoal::startBuilder()
userNamespaceSync.writeSide = -1;
});
- auto ss = tokenizeString<std::vector<std::string>>(readLine(builderOut.readSide.get()));
- assert(ss.size() == 2);
- usingUserNamespace = ss[0] == "1";
- pid = string2Int<pid_t>(ss[1]).value();
+ auto ss = tokenizeString<std::vector<std::string>>(readLine(sendPid.readSide.get()));
+ assert(ss.size() == 1);
+ pid = string2Int<pid_t>(ss[0]).value();
if (usingUserNamespace) {
/* Set the UID/GID mapping of the builder's user namespace
@@ -994,21 +974,20 @@ void LocalDerivationGoal::startBuilder()
#endif
{
pid = startProcess([&]() {
- runChild();
+ runChild(slaveName);
});
}
/* parent */
pid.setSeparatePG(true);
- builderOut.writeSide = -1;
- worker.childStarted(shared_from_this(), {builderOut.readSide.get()}, true, true);
+ worker.childStarted(shared_from_this(), {builderOut.get()}, true, true);
/* Check if setting up the build environment failed. */
std::vector<std::string> msgs;
while (true) {
std::string msg = [&]() {
try {
- return readLine(builderOut.readSide.get());
+ return readLine(builderOut.get());
} catch (Error & e) {
auto status = pid.wait();
e.addTrace({}, "while waiting for the build environment for '%s' to initialize (%s, previous messages: %s)",
@@ -1020,7 +999,7 @@ void LocalDerivationGoal::startBuilder()
}();
if (msg.substr(0, 1) == "\2") break;
if (msg.substr(0, 1) == "\1") {
- FdSource source(builderOut.readSide.get());
+ FdSource source(builderOut.get());
auto ex = readError(source);
ex.addTrace({}, "while setting up the build environment");
throw ex;
@@ -1104,7 +1083,7 @@ void LocalDerivationGoal::initEnv()
env["NIX_STORE"] = worker.store.storeDir;
/* The maximum number of cores to utilize for parallel building. */
- env["NIX_BUILD_CORES"] = (format("%d") % settings.buildCores).str();
+ env["NIX_BUILD_CORES"] = fmt("%d", settings.buildCores);
initTmpDir();
@@ -1155,10 +1134,10 @@ void LocalDerivationGoal::writeStructuredAttrs()
writeFile(tmpDir + "/.attrs.sh", rewriteStrings(jsonSh, inputRewrites));
chownToBuilder(tmpDir + "/.attrs.sh");
- env["NIX_ATTRS_SH_FILE"] = tmpDir + "/.attrs.sh";
+ env["NIX_ATTRS_SH_FILE"] = tmpDirInSandbox + "/.attrs.sh";
writeFile(tmpDir + "/.attrs.json", rewriteStrings(json.dump(), inputRewrites));
chownToBuilder(tmpDir + "/.attrs.json");
- env["NIX_ATTRS_JSON_FILE"] = tmpDir + "/.attrs.json";
+ env["NIX_ATTRS_JSON_FILE"] = tmpDirInSandbox + "/.attrs.json";
}
}
@@ -1641,7 +1620,7 @@ void setupSeccomp()
}
-void LocalDerivationGoal::runChild()
+void LocalDerivationGoal::runChild(const Path & slaveName)
{
/* Warning: in the child we should absolutely not make any SQLite
calls! */
@@ -1650,7 +1629,22 @@ void LocalDerivationGoal::runChild()
try { /* child */
- commonChildInit(builderOut);
+ /* Open the slave side of the pseudoterminal. */
+ AutoCloseFD builderOut = open(slaveName.c_str(), O_RDWR | O_NOCTTY);
+ if (!builderOut)
+ throw SysError("opening pseudoterminal slave");
+
+ // Put the pt into raw mode to prevent \n -> \r\n translation.
+ struct termios term;
+ if (tcgetattr(builderOut.get(), &term))
+ throw SysError("getting pseudoterminal attributes");
+
+ cfmakeraw(&term);
+
+ if (tcsetattr(builderOut.get(), TCSANOW, &term))
+ throw SysError("putting pseudoterminal into raw mode");
+
+ commonChildInit(builderOut.get());
try {
setupSeccomp();
@@ -2063,7 +2057,7 @@ void LocalDerivationGoal::runChild()
/* The tmpDir in scope points at the temporary build directory for our derivation. Some packages try different mechanisms
to find temporary directories, so we want to open up a broader place for them to dump their files, if needed. */
- Path globalTmpDir = canonPath(getEnv("TMPDIR").value_or("/tmp"), true);
+ Path globalTmpDir = canonPath(getEnvNonEmpty("TMPDIR").value_or("/tmp"), true);
/* They don't like trailing slashes on subpath directives */
if (globalTmpDir.back() == '/') globalTmpDir.pop_back();
@@ -2892,7 +2886,7 @@ void LocalDerivationGoal::deleteTmpDir(bool force)
bool LocalDerivationGoal::isReadDesc(int fd)
{
return (hook && DerivationGoal::isReadDesc(fd)) ||
- (!hook && fd == builderOut.readSide.get());
+ (!hook && fd == builderOut.get());
}
diff --git a/src/libstore/build/local-derivation-goal.hh b/src/libstore/build/local-derivation-goal.hh
index 34c4e9187..4d2f1ac28 100644
--- a/src/libstore/build/local-derivation-goal.hh
+++ b/src/libstore/build/local-derivation-goal.hh
@@ -24,8 +24,9 @@ struct LocalDerivationGoal : public DerivationGoal
/* The path of the temporary directory in the sandbox. */
Path tmpDirInSandbox;
- /* Pipe for the builder's standard output/error. */
- Pipe builderOut;
+ /* Master side of the pseudoterminal used for the builder's
+ standard output/error. */
+ AutoCloseFD builderOut;
/* Pipe for synchronising updates to the builder namespaces. */
Pipe userNamespaceSync;
@@ -168,7 +169,7 @@ struct LocalDerivationGoal : public DerivationGoal
int getChildStatus() override;
/* Run the builder's process. */
- void runChild();
+ void runChild(const std::string & slaveName);
/* Check that the derivation outputs all exist and register them
as valid. */
diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc
index 5e6fd011f..7f8b0f905 100644
--- a/src/libstore/daemon.cc
+++ b/src/libstore/daemon.cc
@@ -67,12 +67,12 @@ struct TunnelLogger : public Logger
state->pendingMsgs.push_back(s);
}
- void log(Verbosity lvl, const FormatOrString & fs) override
+ void log(Verbosity lvl, std::string_view s) override
{
if (lvl > verbosity) return;
StringSink buf;
- buf << STDERR_NEXT << (fs.s + "\n");
+ buf << STDERR_NEXT << (s + "\n");
enqueueMsg(buf.s);
}
diff --git a/src/libstore/export-import.cc b/src/libstore/export-import.cc
index 9875da909..4eb838b68 100644
--- a/src/libstore/export-import.cc
+++ b/src/libstore/export-import.cc
@@ -16,7 +16,7 @@ void Store::exportPaths(const StorePathSet & paths, Sink & sink)
//logger->incExpected(doneLabel, sorted.size());
for (auto & path : sorted) {
- //Activity act(*logger, lvlInfo, format("exporting path '%s'") % path);
+ //Activity act(*logger, lvlInfo, "exporting path '%s'", path);
sink << 1;
exportPath(path, sink);
//logger->incProgress(doneLabel);
@@ -71,7 +71,7 @@ StorePaths Store::importPaths(Source & source, CheckSigsFlag checkSigs)
auto path = parseStorePath(readString(source));
- //Activity act(*logger, lvlInfo, format("importing path '%s'") % info.path);
+ //Activity act(*logger, lvlInfo, "importing path '%s'", info.path);
auto references = worker_proto::read(*this, source, Phantom<StorePathSet> {});
auto deriver = readString(source);
diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc
index 6a4778d1f..b5fe7c03b 100644
--- a/src/libstore/filetransfer.cc
+++ b/src/libstore/filetransfer.cc
@@ -185,7 +185,7 @@ struct curlFileTransfer : public FileTransfer
{
size_t realSize = size * nmemb;
std::string line((char *) contents, realSize);
- printMsg(lvlVomit, format("got header for '%s': %s") % request.uri % trim(line));
+ printMsg(lvlVomit, "got header for '%s': %s", request.uri, trim(line));
static std::regex statusLine("HTTP/[^ ]+ +[0-9]+(.*)", std::regex::extended | std::regex::icase);
std::smatch match;
if (std::regex_match(line, match, statusLine)) {
@@ -209,7 +209,7 @@ struct curlFileTransfer : public FileTransfer
long httpStatus = 0;
curl_easy_getinfo(req, CURLINFO_RESPONSE_CODE, &httpStatus);
if (result.etag == request.expectedETag && httpStatus == 200) {
- debug(format("shutting down on 200 HTTP response with expected ETag"));
+ debug("shutting down on 200 HTTP response with expected ETag");
return 0;
}
} else if (name == "content-encoding")
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index 996f26a95..0038ec802 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -34,8 +34,7 @@ static void makeSymlink(const Path & link, const Path & target)
createDirs(dirOf(link));
/* Create the new symlink. */
- Path tempLink = (format("%1%.tmp-%2%-%3%")
- % link % getpid() % random()).str();
+ Path tempLink = fmt("%1%.tmp-%2%-%3%", link, getpid(), random());
createSymlink(target, tempLink);
/* Atomically replace the old one. */
@@ -197,7 +196,7 @@ void LocalStore::findTempRoots(Roots & tempRoots, bool censor)
pid_t pid = std::stoi(i.name);
- debug(format("reading temporary root file '%1%'") % path);
+ debug("reading temporary root file '%1%'", path);
AutoCloseFD fd(open(path.c_str(), O_CLOEXEC | O_RDWR, 0666));
if (!fd) {
/* It's okay if the file has disappeared. */
@@ -263,7 +262,7 @@ void LocalStore::findRoots(const Path & path, unsigned char type, Roots & roots)
target = absPath(target, dirOf(path));
if (!pathExists(target)) {
if (isInDir(path, stateDir + "/" + gcRootsDir + "/auto")) {
- printInfo(format("removing stale link from '%1%' to '%2%'") % path % target);
+ printInfo("removing stale link from '%1%' to '%2%'", path, target);
unlink(path.c_str());
}
} else {
@@ -372,29 +371,29 @@ void LocalStore::findRuntimeRoots(Roots & roots, bool censor)
while (errno = 0, ent = readdir(procDir.get())) {
checkInterrupt();
if (std::regex_match(ent->d_name, digitsRegex)) {
- readProcLink(fmt("/proc/%s/exe" ,ent->d_name), unchecked);
- readProcLink(fmt("/proc/%s/cwd", ent->d_name), unchecked);
-
- auto fdStr = fmt("/proc/%s/fd", ent->d_name);
- auto fdDir = AutoCloseDir(opendir(fdStr.c_str()));
- if (!fdDir) {
- if (errno == ENOENT || errno == EACCES)
- continue;
- throw SysError("opening %1%", fdStr);
- }
- struct dirent * fd_ent;
- while (errno = 0, fd_ent = readdir(fdDir.get())) {
- if (fd_ent->d_name[0] != '.')
- readProcLink(fmt("%s/%s", fdStr, fd_ent->d_name), unchecked);
- }
- if (errno) {
- if (errno == ESRCH)
- continue;
- throw SysError("iterating /proc/%1%/fd", ent->d_name);
- }
- fdDir.reset();
-
try {
+ readProcLink(fmt("/proc/%s/exe" ,ent->d_name), unchecked);
+ readProcLink(fmt("/proc/%s/cwd", ent->d_name), unchecked);
+
+ auto fdStr = fmt("/proc/%s/fd", ent->d_name);
+ auto fdDir = AutoCloseDir(opendir(fdStr.c_str()));
+ if (!fdDir) {
+ if (errno == ENOENT || errno == EACCES)
+ continue;
+ throw SysError("opening %1%", fdStr);
+ }
+ struct dirent * fd_ent;
+ while (errno = 0, fd_ent = readdir(fdDir.get())) {
+ if (fd_ent->d_name[0] != '.')
+ readProcLink(fmt("%s/%s", fdStr, fd_ent->d_name), unchecked);
+ }
+ if (errno) {
+ if (errno == ESRCH)
+ continue;
+ throw SysError("iterating /proc/%1%/fd", ent->d_name);
+ }
+ fdDir.reset();
+
auto mapFile = fmt("/proc/%s/maps", ent->d_name);
auto mapLines = tokenizeString<std::vector<std::string>>(readFile(mapFile), "\n");
for (const auto & line : mapLines) {
@@ -863,7 +862,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
continue;
}
- printMsg(lvlTalkative, format("deleting unused link '%1%'") % path);
+ printMsg(lvlTalkative, "deleting unused link '%1%'", path);
if (unlink(path.c_str()) == -1)
throw SysError("deleting '%1%'", path);
diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc
index 8e33a3dec..fae79c1a0 100644
--- a/src/libstore/globals.cc
+++ b/src/libstore/globals.cc
@@ -30,15 +30,15 @@ static GlobalConfig::Register rSettings(&settings);
Settings::Settings()
: nixPrefix(NIX_PREFIX)
- , nixStore(canonPath(getEnv("NIX_STORE_DIR").value_or(getEnv("NIX_STORE").value_or(NIX_STORE_DIR))))
- , nixDataDir(canonPath(getEnv("NIX_DATA_DIR").value_or(NIX_DATA_DIR)))
- , nixLogDir(canonPath(getEnv("NIX_LOG_DIR").value_or(NIX_LOG_DIR)))
- , nixStateDir(canonPath(getEnv("NIX_STATE_DIR").value_or(NIX_STATE_DIR)))
- , nixConfDir(canonPath(getEnv("NIX_CONF_DIR").value_or(NIX_CONF_DIR)))
+ , nixStore(canonPath(getEnvNonEmpty("NIX_STORE_DIR").value_or(getEnvNonEmpty("NIX_STORE").value_or(NIX_STORE_DIR))))
+ , nixDataDir(canonPath(getEnvNonEmpty("NIX_DATA_DIR").value_or(NIX_DATA_DIR)))
+ , nixLogDir(canonPath(getEnvNonEmpty("NIX_LOG_DIR").value_or(NIX_LOG_DIR)))
+ , nixStateDir(canonPath(getEnvNonEmpty("NIX_STATE_DIR").value_or(NIX_STATE_DIR)))
+ , nixConfDir(canonPath(getEnvNonEmpty("NIX_CONF_DIR").value_or(NIX_CONF_DIR)))
, nixUserConfFiles(getUserConfigFiles())
- , nixBinDir(canonPath(getEnv("NIX_BIN_DIR").value_or(NIX_BIN_DIR)))
+ , nixBinDir(canonPath(getEnvNonEmpty("NIX_BIN_DIR").value_or(NIX_BIN_DIR)))
, nixManDir(canonPath(NIX_MAN_DIR))
- , nixDaemonSocketFile(canonPath(getEnv("NIX_DAEMON_SOCKET_PATH").value_or(nixStateDir + DEFAULT_SOCKET_PATH)))
+ , nixDaemonSocketFile(canonPath(getEnvNonEmpty("NIX_DAEMON_SOCKET_PATH").value_or(nixStateDir + DEFAULT_SOCKET_PATH)))
{
buildUsersGroup = getuid() == 0 ? "nixbld" : "";
lockCPU = getEnv("NIX_AFFINITY_HACK") == "1";
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index 82edaa9bf..c9a466ee8 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -280,7 +280,7 @@ LocalStore::LocalStore(const Params & params)
else if (curSchema == 0) { /* new store */
curSchema = nixSchemaVersion;
openDB(*state, true);
- writeFile(schemaPath, (format("%1%") % nixSchemaVersion).str(), 0666, true);
+ writeFile(schemaPath, fmt("%1%", nixSchemaVersion), 0666, true);
}
else if (curSchema < nixSchemaVersion) {
@@ -329,7 +329,7 @@ LocalStore::LocalStore(const Params & params)
txn.commit();
}
- writeFile(schemaPath, (format("%1%") % nixSchemaVersion).str(), 0666, true);
+ writeFile(schemaPath, fmt("%1%", nixSchemaVersion), 0666, true);
lockFile(globalLock.get(), ltRead, true);
}
@@ -1560,7 +1560,7 @@ void LocalStore::invalidatePathChecked(const StorePath & path)
bool LocalStore::verifyStore(bool checkContents, RepairFlag repair)
{
- printInfo(format("reading the Nix store..."));
+ printInfo("reading the Nix store...");
bool errors = false;
diff --git a/src/libstore/optimise-store.cc b/src/libstore/optimise-store.cc
index 4d2781180..4a79cf4a1 100644
--- a/src/libstore/optimise-store.cc
+++ b/src/libstore/optimise-store.cc
@@ -55,7 +55,7 @@ LocalStore::InodeHash LocalStore::loadInodeHash()
}
if (errno) throw SysError("reading directory '%1%'", linksDir);
- printMsg(lvlTalkative, format("loaded %1% hash inodes") % inodeHash.size());
+ printMsg(lvlTalkative, "loaded %1% hash inodes", inodeHash.size());
return inodeHash;
}
@@ -73,7 +73,7 @@ Strings LocalStore::readDirectoryIgnoringInodes(const Path & path, const InodeHa
checkInterrupt();
if (inodeHash.count(dirent->d_ino)) {
- debug(format("'%1%' is already linked") % dirent->d_name);
+ debug("'%1%' is already linked", dirent->d_name);
continue;
}
@@ -102,7 +102,7 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats,
if (std::regex_search(path, std::regex("\\.app/Contents/.+$")))
{
- debug(format("'%1%' is not allowed to be linked in macOS") % path);
+ debug("'%1%' is not allowed to be linked in macOS", path);
return;
}
#endif
@@ -146,7 +146,7 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats,
contents of the symlink (i.e. the result of readlink()), not
the contents of the target (which may not even exist). */
Hash hash = hashPath(htSHA256, path).first;
- debug(format("'%1%' has hash '%2%'") % path % hash.to_string(Base32, true));
+ debug("'%1%' has hash '%2%'", path, hash.to_string(Base32, true));
/* Check if this is a known hash. */
Path linkPath = linksDir + "/" + hash.to_string(Base32, false);
@@ -196,11 +196,11 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats,
auto stLink = lstat(linkPath);
if (st.st_ino == stLink.st_ino) {
- debug(format("'%1%' is already linked to '%2%'") % path % linkPath);
+ debug("'%1%' is already linked to '%2%'", path, linkPath);
return;
}
- printMsg(lvlTalkative, format("linking '%1%' to '%2%'") % path % linkPath);
+ printMsg(lvlTalkative, "linking '%1%' to '%2%'", path, linkPath);
/* Make the containing directory writable, but only if it's not
the store itself (we don't want or need to mess with its
@@ -213,8 +213,7 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats,
its timestamp back to 0. */
MakeReadOnly makeReadOnly(mustToggle ? dirOfPath : "");
- Path tempLink = (format("%1%/.tmp-link-%2%-%3%")
- % realStoreDir % getpid() % random()).str();
+ Path tempLink = fmt("%1%/.tmp-link-%2%-%3%", realStoreDir, getpid(), random());
if (link(linkPath.c_str(), tempLink.c_str()) == -1) {
if (errno == EMLINK) {
@@ -222,7 +221,7 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats,
systems). This is likely to happen with empty files.
Just shrug and ignore. */
if (st.st_size)
- printInfo(format("'%1%' has maximum number of links") % linkPath);
+ printInfo("'%1%' has maximum number of links", linkPath);
return;
}
throw SysError("cannot link '%1%' to '%2%'", tempLink, linkPath);
diff --git a/src/libstore/pathlocks.cc b/src/libstore/pathlocks.cc
index 42023cd0a..adc763e6a 100644
--- a/src/libstore/pathlocks.cc
+++ b/src/libstore/pathlocks.cc
@@ -96,7 +96,7 @@ bool PathLocks::lockPaths(const PathSet & paths,
checkInterrupt();
Path lockPath = path + ".lock";
- debug(format("locking path '%1%'") % path);
+ debug("locking path '%1%'", path);
AutoCloseFD fd;
@@ -118,7 +118,7 @@ bool PathLocks::lockPaths(const PathSet & paths,
}
}
- debug(format("lock acquired on '%1%'") % lockPath);
+ debug("lock acquired on '%1%'", lockPath);
/* Check that the lock file hasn't become stale (i.e.,
hasn't been unlinked). */
@@ -130,7 +130,7 @@ bool PathLocks::lockPaths(const PathSet & paths,
a lock on a deleted file. This means that other
processes may create and acquire a lock on
`lockPath', and proceed. So we must retry. */
- debug(format("open lock file '%1%' has become stale") % lockPath);
+ debug("open lock file '%1%' has become stale", lockPath);
else
break;
}
@@ -163,7 +163,7 @@ void PathLocks::unlock()
"error (ignored): cannot close lock file on '%1%'",
i.second);
- debug(format("lock released on '%1%'") % i.second);
+ debug("lock released on '%1%'", i.second);
}
fds.clear();
diff --git a/src/libstore/profiles.cc b/src/libstore/profiles.cc
index c551c5f3e..179161ff7 100644
--- a/src/libstore/profiles.cc
+++ b/src/libstore/profiles.cc
@@ -64,7 +64,7 @@ std::pair<Generations, std::optional<GenerationNumber>> findGenerations(Path pro
static void makeName(const Path & profile, GenerationNumber num,
Path & outLink)
{
- Path prefix = (format("%1%-%2%") % profile % num).str();
+ Path prefix = fmt("%1%-%2%", profile, num);
outLink = prefix + "-link";
}
@@ -269,7 +269,7 @@ void switchGeneration(
void lockProfile(PathLocks & lock, const Path & profile)
{
- lock.lockPaths({profile}, (format("waiting for lock on profile '%1%'") % profile).str());
+ lock.lockPaths({profile}, fmt("waiting for lock on profile '%1%'", profile));
lock.setDeletion(true);
}
diff --git a/src/libstore/references.cc b/src/libstore/references.cc
index 3bb297fc8..345f4528b 100644
--- a/src/libstore/references.cc
+++ b/src/libstore/references.cc
@@ -39,8 +39,7 @@ static void search(
if (!match) continue;
std::string ref(s.substr(i, refLength));
if (hashes.erase(ref)) {
- debug(format("found reference to '%1%' at offset '%2%'")
- % ref % i);
+ debug("found reference to '%1%' at offset '%2%'", ref, i);
seen.insert(ref);
}
++i;
diff --git a/src/libstore/s3-binary-cache-store.cc b/src/libstore/s3-binary-cache-store.cc
index 8d76eee99..8006bd733 100644
--- a/src/libstore/s3-binary-cache-store.cc
+++ b/src/libstore/s3-binary-cache-store.cc
@@ -40,12 +40,12 @@ struct S3Error : public Error
/* Helper: given an Outcome<R, E>, return R in case of success, or
throw an exception in case of an error. */
template<typename R, typename E>
-R && checkAws(const FormatOrString & fs, Aws::Utils::Outcome<R, E> && outcome)
+R && checkAws(std::string_view s, Aws::Utils::Outcome<R, E> && outcome)
{
if (!outcome.IsSuccess())
throw S3Error(
outcome.GetError().GetErrorType(),
- fs.s + ": " + outcome.GetError().GetMessage());
+ s + ": " + outcome.GetError().GetMessage());
return outcome.GetResultWithOwnership();
}
@@ -430,9 +430,9 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
std::string marker;
do {
- debug(format("listing bucket 's3://%s' from key '%s'...") % bucketName % marker);
+ debug("listing bucket 's3://%s' from key '%s'...", bucketName, marker);
- auto res = checkAws(format("AWS error listing bucket '%s'") % bucketName,
+ auto res = checkAws(fmt("AWS error listing bucket '%s'", bucketName),
s3Helper.client->ListObjects(
Aws::S3::Model::ListObjectsRequest()
.WithBucket(bucketName)
@@ -441,8 +441,8 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
auto & contents = res.GetContents();
- debug(format("got %d keys, next marker '%s'")
- % contents.size() % res.GetNextMarker());
+ debug("got %d keys, next marker '%s'",
+ contents.size(), res.GetNextMarker());
for (auto object : contents) {
auto & key = object.GetKey();
diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc
index f32c2d30c..19b0a7f5f 100644
--- a/src/libstore/store-api.cc
+++ b/src/libstore/store-api.cc
@@ -790,13 +790,13 @@ std::string Store::makeValidityRegistration(const StorePathSet & paths,
if (showHash) {
s += info->narHash.to_string(Base16, false) + "\n";
- s += (format("%1%\n") % info->narSize).str();
+ s += fmt("%1%\n", info->narSize);
}
auto deriver = showDerivers && info->deriver ? printStorePath(*info->deriver) : "";
s += deriver + "\n";
- s += (format("%1%\n") % info->references.size()).str();
+ s += fmt("%1%\n", info->references.size());
for (auto & j : info->references)
s += printStorePath(j) + "\n";
@@ -1101,6 +1101,8 @@ std::map<StorePath, StorePath> copyPaths(
return storePathForDst;
};
+ uint64_t total = 0;
+
for (auto & missingPath : sortedMissing) {
auto info = srcStore.queryPathInfo(missingPath);
@@ -1121,7 +1123,13 @@ std::map<StorePath, StorePath> copyPaths(
{storePathS, srcUri, dstUri});
PushActivity pact(act.id);
- srcStore.narFromPath(missingPath, sink);
+ LambdaSink progressSink([&](std::string_view data) {
+ total += data.size();
+ act.progress(total, info->narSize);
+ });
+ TeeSink tee { sink, progressSink };
+
+ srcStore.narFromPath(missingPath, tee);
});
pathsToCopy.push_back(std::pair{infoForDst, std::move(source)});
}
diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc
index 0e2b9d12c..268a798d9 100644
--- a/src/libutil/archive.cc
+++ b/src/libutil/archive.cc
@@ -87,7 +87,7 @@ static time_t dump(const Path & path, Sink & sink, PathFilter & filter)
std::string name(i.name);
size_t pos = i.name.find(caseHackSuffix);
if (pos != std::string::npos) {
- debug(format("removing case hack suffix from '%1%'") % (path + "/" + i.name));
+ debug("removing case hack suffix from '%1%'", path + "/" + i.name);
name.erase(pos);
}
if (!unhacked.emplace(name, i.name).second)
@@ -262,7 +262,7 @@ static void parse(ParseSink & sink, Source & source, const Path & path)
if (archiveSettings.useCaseHack) {
auto i = names.find(name);
if (i != names.end()) {
- debug(format("case collision between '%1%' and '%2%'") % i->first % name);
+ debug("case collision between '%1%' and '%2%'", i->first, name);
name += caseHackSuffix;
name += std::to_string(++i->second);
} else
diff --git a/src/libutil/args.hh b/src/libutil/args.hh
index 84866f12b..7211ee307 100644
--- a/src/libutil/args.hh
+++ b/src/libutil/args.hh
@@ -198,7 +198,6 @@ struct Command : virtual public Args
virtual ~Command() { }
- virtual void prepare() { };
virtual void run() = 0;
typedef int Category;
diff --git a/src/libutil/filesystem.cc b/src/libutil/filesystem.cc
index 3a732cff8..56be76ecc 100644
--- a/src/libutil/filesystem.cc
+++ b/src/libutil/filesystem.cc
@@ -15,9 +15,9 @@ static Path tempName(Path tmpRoot, const Path & prefix, bool includePid,
{
tmpRoot = canonPath(tmpRoot.empty() ? getEnv("TMPDIR").value_or("/tmp") : tmpRoot, true);
if (includePid)
- return (format("%1%/%2%-%3%-%4%") % tmpRoot % prefix % getpid() % counter++).str();
+ return fmt("%1%/%2%-%3%-%4%", tmpRoot, prefix, getpid(), counter++);
else
- return (format("%1%/%2%-%3%") % tmpRoot % prefix % counter++).str();
+ return fmt("%1%/%2%-%3%", tmpRoot, prefix, counter++);
}
Path createTempDir(const Path & tmpRoot, const Path & prefix,
diff --git a/src/libutil/fmt.hh b/src/libutil/fmt.hh
index e879fd3b8..e11426b88 100644
--- a/src/libutil/fmt.hh
+++ b/src/libutil/fmt.hh
@@ -17,16 +17,6 @@ using boost::format;
struct nop { template<typename... T> nop(T...) {} };
-struct FormatOrString
-{
- std::string s;
- FormatOrString(std::string s) : s(std::move(s)) { };
- template<class F>
- FormatOrString(const F & f) : s(f.str()) { };
- FormatOrString(const char * s) : s(s) { };
-};
-
-
/* A helper for formatting strings. ‘fmt(format, a_0, ..., a_n)’ is
equivalent to ‘boost::format(format) % a_0 % ... %
... a_n’. However, ‘fmt(s)’ is equivalent to ‘s’ (so no %-expansion
@@ -53,11 +43,6 @@ inline std::string fmt(const char * s)
return s;
}
-inline std::string fmt(const FormatOrString & fs)
-{
- return fs.s;
-}
-
template<typename... Args>
inline std::string fmt(const std::string & fs, const Args & ... args)
{
diff --git a/src/libutil/logging.cc b/src/libutil/logging.cc
index 56bdaf87a..7cac75ce1 100644
--- a/src/libutil/logging.cc
+++ b/src/libutil/logging.cc
@@ -54,7 +54,7 @@ public:
return printBuildLogs;
}
- void log(Verbosity lvl, const FormatOrString & fs) override
+ void log(Verbosity lvl, std::string_view s) override
{
if (lvl > verbosity) return;
@@ -72,7 +72,7 @@ public:
prefix = std::string("<") + c + ">";
}
- writeToStderr(prefix + filterANSIEscapes(fs.s, !tty) + "\n");
+ writeToStderr(prefix + filterANSIEscapes(s, !tty) + "\n");
}
void logEI(const ErrorInfo & ei) override
@@ -174,12 +174,12 @@ struct JSONLogger : Logger {
prevLogger.log(lvlError, "@nix " + json.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace));
}
- void log(Verbosity lvl, const FormatOrString & fs) override
+ void log(Verbosity lvl, std::string_view s) override
{
nlohmann::json json;
json["action"] = "msg";
json["level"] = lvl;
- json["msg"] = fs.s;
+ json["msg"] = s;
write(json);
}
diff --git a/src/libutil/logging.hh b/src/libutil/logging.hh
index a68edd15a..59a707eef 100644
--- a/src/libutil/logging.hh
+++ b/src/libutil/logging.hh
@@ -75,11 +75,11 @@ public:
// Whether the logger prints the whole build log
virtual bool isVerbose() { return false; }
- virtual void log(Verbosity lvl, const FormatOrString & fs) = 0;
+ virtual void log(Verbosity lvl, std::string_view s) = 0;
- void log(const FormatOrString & fs)
+ void log(std::string_view s)
{
- log(lvlInfo, fs);
+ log(lvlInfo, s);
}
virtual void logEI(const ErrorInfo & ei) = 0;
diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc
index c653db9d0..7476e6f6c 100644
--- a/src/libutil/serialise.cc
+++ b/src/libutil/serialise.cc
@@ -415,7 +415,7 @@ Error readError(Source & source)
auto msg = readString(source);
ErrorInfo info {
.level = level,
- .msg = hintformat(std::move(format("%s") % msg)),
+ .msg = hintformat(fmt("%s", msg)),
};
auto havePos = readNum<size_t>(source);
assert(havePos == 0);
@@ -424,7 +424,7 @@ Error readError(Source & source)
havePos = readNum<size_t>(source);
assert(havePos == 0);
info.traces.push_back(Trace {
- .hint = hintformat(std::move(format("%s") % readString(source)))
+ .hint = hintformat(fmt("%s", readString(source)))
});
}
return Error(std::move(info));
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 885bae69c..c605a33e6 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -54,6 +54,11 @@ std::optional<std::string> getEnv(const std::string & key)
return std::string(value);
}
+std::optional<std::string> getEnvNonEmpty(const std::string & key) {
+ auto value = getEnv(key);
+ if (value == "") return {};
+ return value;
+}
std::map<std::string, std::string> getEnv()
{
@@ -523,7 +528,7 @@ void deletePath(const Path & path)
void deletePath(const Path & path, uint64_t & bytesFreed)
{
- //Activity act(*logger, lvlDebug, format("recursively deleting path '%1%'") % path);
+ //Activity act(*logger, lvlDebug, "recursively deleting path '%1%'", path);
bytesFreed = 0;
_deletePath(path, bytesFreed);
}
@@ -1065,12 +1070,14 @@ static pid_t doFork(bool allowVfork, std::function<void()> fun)
}
+#if __linux__
static int childEntry(void * arg)
{
auto main = (std::function<void()> *) arg;
(*main)();
return 1;
}
+#endif
pid_t startProcess(std::function<void()> fun, const ProcessOptions & options)
@@ -1394,14 +1401,14 @@ std::string statusToString(int status)
{
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
if (WIFEXITED(status))
- return (format("failed with exit code %1%") % WEXITSTATUS(status)).str();
+ return fmt("failed with exit code %1%", WEXITSTATUS(status));
else if (WIFSIGNALED(status)) {
int sig = WTERMSIG(status);
#if HAVE_STRSIGNAL
const char * description = strsignal(sig);
- return (format("failed due to signal %1% (%2%)") % sig % description).str();
+ return fmt("failed due to signal %1% (%2%)", sig, description);
#else
- return (format("failed due to signal %1%") % sig).str();
+ return fmt("failed due to signal %1%", sig);
#endif
}
else
@@ -1470,7 +1477,7 @@ bool shouldANSI()
&& !getEnv("NO_COLOR").has_value();
}
-std::string filterANSIEscapes(const std::string & s, bool filterAll, unsigned int width)
+std::string filterANSIEscapes(std::string_view s, bool filterAll, unsigned int width)
{
std::string t, e;
size_t w = 0;
@@ -1961,7 +1968,7 @@ std::string showBytes(uint64_t bytes)
// FIXME: move to libstore/build
-void commonChildInit(Pipe & logPipe)
+void commonChildInit(int stderrFd)
{
logger = makeSimpleLogger();
@@ -1976,7 +1983,7 @@ void commonChildInit(Pipe & logPipe)
throw SysError("creating a new session");
/* Dup the write side of the logger pipe into stderr. */
- if (dup2(logPipe.writeSide.get(), STDERR_FILENO) == -1)
+ if (dup2(stderrFd, STDERR_FILENO) == -1)
throw SysError("cannot pipe standard error into log file");
/* Dup stderr to stdout. */
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index b5625ecef..52ca36fd1 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -39,6 +39,10 @@ extern const std::string nativeSystem;
/* Return an environment variable. */
std::optional<std::string> getEnv(const std::string & key);
+/* Return a non empty environment variable. Returns nullopt if the env
+variable is set to "" */
+std::optional<std::string> getEnvNonEmpty(const std::string & key);
+
/* Get the entire environment. */
std::map<std::string, std::string> getEnv();
@@ -569,7 +573,7 @@ bool shouldANSI();
some escape sequences (such as colour setting) are copied but not
included in the character count. Also, tabs are expanded to
spaces. */
-std::string filterANSIEscapes(const std::string & s,
+std::string filterANSIEscapes(std::string_view s,
bool filterAll = false,
unsigned int width = std::numeric_limits<unsigned int>::max());
@@ -700,7 +704,7 @@ typedef std::function<bool(const Path & path)> PathFilter;
extern PathFilter defaultPathFilter;
/* Common initialisation performed in child processes. */
-void commonChildInit(Pipe & logPipe);
+void commonChildInit(int stderrFd);
/* Create a Unix domain socket. */
AutoCloseFD createUnixDomainSocket();
diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc
index da76c2ace..a4b3b1f96 100644
--- a/src/nix-build/nix-build.cc
+++ b/src/nix-build/nix-build.cc
@@ -219,9 +219,9 @@ static void main_nix_build(int argc, char * * argv)
// read the shebang to understand which packages to read from. Since
// this is handled via nix-shell -p, we wrap our ruby script execution
// in ruby -e 'load' which ignores the shebangs.
- envCommand = (format("exec %1% %2% -e 'load(ARGV.shift)' -- %3% %4%") % execArgs % interpreter % shellEscape(script) % joined.str()).str();
+ envCommand = fmt("exec %1% %2% -e 'load(ARGV.shift)' -- %3% %4%", execArgs, interpreter, shellEscape(script), joined.str());
} else {
- envCommand = (format("exec %1% %2% %3% %4%") % execArgs % interpreter % shellEscape(script) % joined.str()).str();
+ envCommand = fmt("exec %1% %2% %3% %4%", execArgs, interpreter, shellEscape(script), joined.str());
}
}
diff --git a/src/nix-collect-garbage/nix-collect-garbage.cc b/src/nix-collect-garbage/nix-collect-garbage.cc
index e413faffe..3cc57af4e 100644
--- a/src/nix-collect-garbage/nix-collect-garbage.cc
+++ b/src/nix-collect-garbage/nix-collect-garbage.cc
@@ -40,7 +40,7 @@ void removeOldGenerations(std::string dir)
throw;
}
if (link.find("link") != std::string::npos) {
- printInfo(format("removing old generations of profile %1%") % path);
+ printInfo("removing old generations of profile %s", path);
if (deleteOlderThan != "")
deleteGenerationsOlderThan(path, deleteOlderThan, dryRun);
else
@@ -77,8 +77,7 @@ static int main_nix_collect_garbage(int argc, char * * argv)
return true;
});
- auto profilesDir = settings.nixStateDir + "/profiles";
- if (removeOld) removeOldGenerations(profilesDir);
+ if (removeOld) removeOldGenerations(profilesDir());
// Run the actual garbage collector.
if (!dryRun) {
diff --git a/src/nix-copy-closure/nix-copy-closure.cc b/src/nix-copy-closure/nix-copy-closure.cc
index 841d50fd3..7f2bb93b6 100755
--- a/src/nix-copy-closure/nix-copy-closure.cc
+++ b/src/nix-copy-closure/nix-copy-closure.cc
@@ -22,7 +22,7 @@ static int main_nix_copy_closure(int argc, char ** argv)
printVersion("nix-copy-closure");
else if (*arg == "--gzip" || *arg == "--bzip2" || *arg == "--xz") {
if (*arg != "--gzip")
- printMsg(lvlError, format("Warning: '%1%' is not implemented, falling back to gzip") % *arg);
+ warn("'%1%' is not implemented, falling back to gzip", *arg);
gzip = true;
} else if (*arg == "--from")
toMode = false;
diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc
index 0daf374de..3a012638b 100644
--- a/src/nix-env/nix-env.cc
+++ b/src/nix-env/nix-env.cc
@@ -500,7 +500,7 @@ static bool keep(DrvInfo & drv)
static void installDerivations(Globals & globals,
const Strings & args, const Path & profile)
{
- debug(format("installing derivations"));
+ debug("installing derivations");
/* Get the set of user environment elements to be installed. */
DrvInfos newElems, newElemsTmp;
@@ -579,7 +579,7 @@ typedef enum { utLt, utLeq, utEq, utAlways } UpgradeType;
static void upgradeDerivations(Globals & globals,
const Strings & args, UpgradeType upgradeType)
{
- debug(format("upgrading derivations"));
+ debug("upgrading derivations");
/* Upgrade works as follows: we take all currently installed
derivations, and for any derivation matching any selector, look
@@ -768,7 +768,7 @@ static void opSet(Globals & globals, Strings opFlags, Strings opArgs)
if (globals.dryRun) return;
globals.state->store->buildPaths(paths, globals.state->repair ? bmRepair : bmNormal);
- debug(format("switching to new user environment"));
+ debug("switching to new user environment");
Path generation = createGeneration(
ref<LocalFSStore>(store2),
globals.profile,
@@ -1093,7 +1093,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
try {
if (i.hasFailed()) continue;
- //Activity act(*logger, lvlDebug, format("outputting query result '%1%'") % i.attrPath);
+ //Activity act(*logger, lvlDebug, "outputting query result '%1%'", i.attrPath);
if (globals.prebuiltOnly &&
!validPaths.count(i.queryOutPath()) &&
@@ -1229,11 +1229,11 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
xml.writeEmptyElement("meta", attrs2);
} else if (v->type() == nInt) {
attrs2["type"] = "int";
- attrs2["value"] = (format("%1%") % v->integer).str();
+ attrs2["value"] = fmt("%1%", v->integer);
xml.writeEmptyElement("meta", attrs2);
} else if (v->type() == nFloat) {
attrs2["type"] = "float";
- attrs2["value"] = (format("%1%") % v->fpoint).str();
+ attrs2["value"] = fmt("%1%", v->fpoint);
xml.writeEmptyElement("meta", attrs2);
} else if (v->type() == nBool) {
attrs2["type"] = "bool";
@@ -1337,11 +1337,11 @@ static void opListGenerations(Globals & globals, Strings opFlags, Strings opArgs
for (auto & i : gens) {
tm t;
if (!localtime_r(&i.creationTime, &t)) throw Error("cannot convert time");
- cout << format("%|4| %|4|-%|02|-%|02| %|02|:%|02|:%|02| %||\n")
- % i.number
- % (t.tm_year + 1900) % (t.tm_mon + 1) % t.tm_mday
- % t.tm_hour % t.tm_min % t.tm_sec
- % (i.number == curGen ? "(current)" : "");
+ logger->cout("%|4| %|4|-%|02|-%|02| %|02|:%|02|:%|02| %||",
+ i.number,
+ t.tm_year + 1900, t.tm_mon + 1, t.tm_mday,
+ t.tm_hour, t.tm_min, t.tm_sec,
+ i.number == curGen ? "(current)" : "");
}
}
diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc
index cad7f9c88..745e9e174 100644
--- a/src/nix-env/user-env.cc
+++ b/src/nix-env/user-env.cc
@@ -41,7 +41,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
if (auto drvPath = i.queryDrvPath())
drvsToBuild.push_back({*drvPath});
- debug(format("building user environment dependencies"));
+ debug("building user environment dependencies");
state.store->buildPaths(
toDerivedPaths(drvsToBuild),
state.repair ? bmRepair : bmNormal);
@@ -159,7 +159,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
return false;
}
- debug(format("switching to new user environment"));
+ debug("switching to new user environment");
Path generation = createGeneration(ref<LocalFSStore>(store2), profile, topLevelOut);
switchLink(profile, generation);
}
diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc
index 3bbefedbe..54479489f 100644
--- a/src/nix-store/nix-store.cc
+++ b/src/nix-store/nix-store.cc
@@ -72,11 +72,13 @@ static PathSet realisePath(StorePathWithOutputs path, bool build = true)
Derivation drv = store->derivationFromPath(path.path);
rootNr++;
+ /* FIXME: Encode this empty special case explicitly in the type. */
if (path.outputs.empty())
for (auto & i : drv.outputs) path.outputs.insert(i.first);
PathSet outputs;
for (auto & j : path.outputs) {
+ /* Match outputs of a store path with outputs of the derivation that produces it. */
DerivationOutputs::iterator i = drv.outputs.find(j);
if (i == drv.outputs.end())
throw Error("derivation '%s' does not have an output named '%s'",
@@ -141,6 +143,7 @@ static void opRealise(Strings opFlags, Strings opArgs)
toDerivedPaths(paths),
willBuild, willSubstitute, unknown, downloadSize, narSize);
+ /* Filter out unknown paths from `paths`. */
if (ignoreUnknown) {
std::vector<StorePathWithOutputs> paths2;
for (auto & i : paths)
@@ -457,7 +460,7 @@ static void opPrintEnv(Strings opFlags, Strings opArgs)
/* Print each environment variable in the derivation in a format
* that can be sourced by the shell. */
for (auto & i : drv.env)
- cout << format("export %1%; %1%=%2%\n") % i.first % shellEscape(i.second);
+ logger->cout("export %1%; %1%=%2%\n", i.first, shellEscape(i.second));
/* Also output the arguments. This doesn't preserve whitespace in
arguments. */
@@ -1020,6 +1023,7 @@ static int main_nix_store(int argc, char * * argv)
{
Strings opFlags, opArgs;
Operation op = 0;
+ bool readFromStdIn = false;
parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) {
Operation oldOp = op;
@@ -1078,6 +1082,8 @@ static int main_nix_store(int argc, char * * argv)
op = opGenerateBinaryCacheKey;
else if (*arg == "--add-root")
gcRoot = absPath(getArg(*arg, arg, end));
+ else if (*arg == "--stdin" && !isatty(STDIN_FILENO))
+ readFromStdIn = true;
else if (*arg == "--indirect")
;
else if (*arg == "--no-output")
@@ -1090,6 +1096,13 @@ static int main_nix_store(int argc, char * * argv)
else
opArgs.push_back(*arg);
+ if (readFromStdIn && op != opImport && op != opRestore && op != opServe) {
+ std::string word;
+ while (std::cin >> word) {
+ opArgs.emplace_back(std::move(word));
+ };
+ }
+
if (oldOp && oldOp != op)
throw UsageError("only one operation may be specified");
diff --git a/src/nix/app.cc b/src/nix/app.cc
index 5cd65136f..bfd75e278 100644
--- a/src/nix/app.cc
+++ b/src/nix/app.cc
@@ -119,11 +119,11 @@ App UnresolvedApp::resolve(ref<Store> evalStore, ref<Store> store)
{
auto res = unresolved;
- std::vector<std::shared_ptr<Installable>> installableContext;
+ Installables installableContext;
for (auto & ctxElt : unresolved.context)
installableContext.push_back(
- std::make_shared<InstallableDerivedPath>(store, DerivedPath { ctxElt }));
+ make_ref<InstallableDerivedPath>(store, DerivedPath { ctxElt }));
auto builtContext = Installable::build(evalStore, store, Realise::Outputs, installableContext);
res.program = resolveString(*store, unresolved.program, builtContext);
diff --git a/src/nix/build.cc b/src/nix/build.cc
index 7240f402b..bca20e97c 100644
--- a/src/nix/build.cc
+++ b/src/nix/build.cc
@@ -112,7 +112,7 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile
;
}
- void run(ref<Store> store) override
+ void run(ref<Store> store, Installables && installables) override
{
if (dryRun) {
std::vector<DerivedPath> pathsToBuild;
diff --git a/src/nix/build.md b/src/nix/build.md
index 6a79f308c..ee414dc86 100644
--- a/src/nix/build.md
+++ b/src/nix/build.md
@@ -82,7 +82,7 @@ R""(
# Description
-`nix build` builds the specified *installables*. Installables that
+`nix build` builds the specified *installables*. [Installables](./nix.md#installables) that
resolve to derivations are built (or substituted if possible). Store
path installables are substituted.
diff --git a/src/nix/bundle.cc b/src/nix/bundle.cc
index dcf9a6f2d..973bbd423 100644
--- a/src/nix/bundle.cc
+++ b/src/nix/bundle.cc
@@ -70,7 +70,7 @@ struct CmdBundle : InstallableCommand
return res;
}
- void run(ref<Store> store) override
+ void run(ref<Store> store, ref<Installable> installable) override
{
auto evalState = getEvalState();
diff --git a/src/nix/bundle.md b/src/nix/bundle.md
index a18161a3c..89458aaaa 100644
--- a/src/nix/bundle.md
+++ b/src/nix/bundle.md
@@ -29,7 +29,7 @@ R""(
# Description
-`nix bundle`, by default, packs the closure of the *installable* into a single
+`nix bundle`, by default, packs the closure of the [*installable*](./nix.md#installables) into a single
self-extracting executable. See the [`bundlers`
homepage](https://github.com/NixOS/bundlers) for more details.
diff --git a/src/nix/copy.cc b/src/nix/copy.cc
index 8730a9a5c..151d28277 100644
--- a/src/nix/copy.cc
+++ b/src/nix/copy.cc
@@ -10,8 +10,6 @@ struct CmdCopy : virtual CopyCommand, virtual BuiltPathsCommand
SubstituteFlag substitute = NoSubstitute;
- using BuiltPathsCommand::run;
-
CmdCopy()
: BuiltPathsCommand(true)
{
diff --git a/src/nix/daemon.cc b/src/nix/daemon.cc
index a22bccba1..7e4a7ba86 100644
--- a/src/nix/daemon.cc
+++ b/src/nix/daemon.cc
@@ -249,9 +249,9 @@ static void daemonLoop()
if ((!trusted && !matchUser(user, group, allowedUsers)) || group == settings.buildUsersGroup)
throw Error("user '%1%' is not allowed to connect to the Nix daemon", user);
- printInfo(format((std::string) "accepted connection from pid %1%, user %2%" + (trusted ? " (trusted)" : ""))
- % (peer.pidKnown ? std::to_string(peer.pid) : "<unknown>")
- % (peer.uidKnown ? user : "<unknown>"));
+ printInfo((std::string) "accepted connection from pid %1%, user %2%" + (trusted ? " (trusted)" : ""),
+ peer.pidKnown ? std::to_string(peer.pid) : "<unknown>",
+ peer.uidKnown ? user : "<unknown>");
// Fork a child to handle the connection.
ProcessOptions options;
diff --git a/src/nix/develop.cc b/src/nix/develop.cc
index 9d07a7a85..f06ade008 100644
--- a/src/nix/develop.cc
+++ b/src/nix/develop.cc
@@ -313,7 +313,7 @@ struct Common : InstallableCommand, MixProfile
buildEnvironment.toBash(out, ignoreVars);
for (auto & var : savedVars)
- out << fmt("%s=\"$%s:$nix_saved_%s\"\n", var, var, var);
+ out << fmt("%s=\"$%s${nix_saved_%s:+:$nix_saved_%s}\"\n", var, var, var, var);
out << "export NIX_BUILD_TOP=\"$(mktemp -d -t nix-shell.XXXXXX)\"\n";
for (auto & i : {"TMP", "TMPDIR", "TEMP", "TEMPDIR"})
@@ -374,7 +374,7 @@ struct Common : InstallableCommand, MixProfile
return res;
}
- StorePath getShellOutPath(ref<Store> store)
+ StorePath getShellOutPath(ref<Store> store, ref<Installable> installable)
{
auto path = installable->getStorePath();
if (path && hasSuffix(path->to_string(), "-env"))
@@ -392,9 +392,10 @@ struct Common : InstallableCommand, MixProfile
}
}
- std::pair<BuildEnvironment, std::string> getBuildEnvironment(ref<Store> store)
+ std::pair<BuildEnvironment, std::string>
+ getBuildEnvironment(ref<Store> store, ref<Installable> installable)
{
- auto shellOutPath = getShellOutPath(store);
+ auto shellOutPath = getShellOutPath(store, installable);
auto strPath = store->printStorePath(shellOutPath);
@@ -480,9 +481,9 @@ struct CmdDevelop : Common, MixEnvironment
;
}
- void run(ref<Store> store) override
+ void run(ref<Store> store, ref<Installable> installable) override
{
- auto [buildEnvironment, gcroot] = getBuildEnvironment(store);
+ auto [buildEnvironment, gcroot] = getBuildEnvironment(store, installable);
auto [rcFileFd, rcFilePath] = createTempFile("nix-shell");
@@ -537,7 +538,7 @@ struct CmdDevelop : Common, MixEnvironment
nixpkgsLockFlags.inputOverrides = {};
nixpkgsLockFlags.inputUpdates = {};
- auto bashInstallable = std::make_shared<InstallableFlake>(
+ auto bashInstallable = make_ref<InstallableFlake>(
this,
state,
installable->nixpkgsFlakeRef(),
@@ -573,7 +574,7 @@ struct CmdDevelop : Common, MixEnvironment
// Need to chdir since phases assume in flake directory
if (phase) {
// chdir if installable is a flake of type git+file or path
- auto installableFlake = std::dynamic_pointer_cast<InstallableFlake>(installable);
+ auto installableFlake = installable.dynamic_pointer_cast<InstallableFlake>();
if (installableFlake) {
auto sourcePath = installableFlake->getLockedFlake()->flake.resolvedRef.input.getSourcePath();
if (sourcePath) {
@@ -604,9 +605,9 @@ struct CmdPrintDevEnv : Common, MixJSON
Category category() override { return catUtility; }
- void run(ref<Store> store) override
+ void run(ref<Store> store, ref<Installable> installable) override
{
- auto buildEnvironment = getBuildEnvironment(store).first;
+ auto buildEnvironment = getBuildEnvironment(store, installable).first;
stopProgressBar();
diff --git a/src/nix/develop.md b/src/nix/develop.md
index 4e8542d1b..c49b39669 100644
--- a/src/nix/develop.md
+++ b/src/nix/develop.md
@@ -76,7 +76,7 @@ R""(
`nix develop` starts a `bash` shell that provides an interactive build
environment nearly identical to what Nix would use to build
-*installable*. Inside this shell, environment variables and shell
+[*installable*](./nix.md#installables). Inside this shell, environment variables and shell
functions are set up so that you can interactively and incrementally
build your package.
diff --git a/src/nix/doctor.cc b/src/nix/doctor.cc
index ea87e3d87..7da4549a1 100644
--- a/src/nix/doctor.cc
+++ b/src/nix/doctor.cc
@@ -18,7 +18,7 @@ std::string formatProtocol(unsigned int proto)
if (proto) {
auto major = GET_PROTOCOL_MAJOR(proto) >> 8;
auto minor = GET_PROTOCOL_MINOR(proto);
- return (format("%1%.%2%") % major % minor).str();
+ return fmt("%1%.%2%", major, minor);
}
return "unknown";
}
diff --git a/src/nix/edit.cc b/src/nix/edit.cc
index dfe75fbdf..c46c1c23c 100644
--- a/src/nix/edit.cc
+++ b/src/nix/edit.cc
@@ -25,7 +25,7 @@ struct CmdEdit : InstallableCommand
Category category() override { return catSecondary; }
- void run(ref<Store> store) override
+ void run(ref<Store> store, ref<Installable> installable) override
{
auto state = getEvalState();
diff --git a/src/nix/eval.cc b/src/nix/eval.cc
index 209fd3ed2..6c2b60427 100644
--- a/src/nix/eval.cc
+++ b/src/nix/eval.cc
@@ -54,7 +54,7 @@ struct CmdEval : MixJSON, InstallableCommand, MixReadOnlyOption
Category category() override { return catSecondary; }
- void run(ref<Store> store) override
+ void run(ref<Store> store, ref<Installable> installable) override
{
if (raw && json)
throw UsageError("--raw and --json are mutually exclusive");
diff --git a/src/nix/eval.md b/src/nix/eval.md
index 61334cde1..3b510737a 100644
--- a/src/nix/eval.md
+++ b/src/nix/eval.md
@@ -50,7 +50,7 @@ R""(
# Description
-This command evaluates the Nix expression *installable* and prints the
+This command evaluates the given Nix expression and prints the
result on standard output.
# Output format
diff --git a/src/nix/flake.cc b/src/nix/flake.cc
index 3fe093fc7..0a6616396 100644
--- a/src/nix/flake.cc
+++ b/src/nix/flake.cc
@@ -1329,7 +1329,6 @@ struct CmdFlake : NixMultiCommand
if (!command)
throw UsageError("'nix flake' requires a sub-command.");
settings.requireExperimentalFeature(Xp::Flakes);
- command->second->prepare();
command->second->run();
}
};
diff --git a/src/nix/flake.md b/src/nix/flake.md
index 810e9ebea..9073d0c3b 100644
--- a/src/nix/flake.md
+++ b/src/nix/flake.md
@@ -275,8 +275,8 @@ Currently the `type` attribute can be one of the following:
# Flake format
As an example, here is a simple `flake.nix` that depends on the
-Nixpkgs flake and provides a single package (i.e. an installable
-derivation):
+Nixpkgs flake and provides a single package (i.e. an
+[installable](./nix.md#installables) derivation):
```nix
{
diff --git a/src/nix/hash.cc b/src/nix/hash.cc
index 60d9593a7..9feca9345 100644
--- a/src/nix/hash.cc
+++ b/src/nix/hash.cc
@@ -151,7 +151,6 @@ struct CmdHash : NixMultiCommand
{
if (!command)
throw UsageError("'nix hash' requires a sub-command.");
- command->second->prepare();
command->second->run();
}
};
@@ -161,11 +160,11 @@ static auto rCmdHash = registerCommand<CmdHash>("hash");
/* Legacy nix-hash command. */
static int compatNixHash(int argc, char * * argv)
{
- HashType ht = htMD5;
+ std::optional<HashType> ht;
bool flat = false;
- bool base32 = false;
+ Base base = Base16;
bool truncate = false;
- enum { opHash, opTo32, opTo16 } op = opHash;
+ enum { opHash, opTo } op = opHash;
std::vector<std::string> ss;
parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) {
@@ -174,14 +173,31 @@ static int compatNixHash(int argc, char * * argv)
else if (*arg == "--version")
printVersion("nix-hash");
else if (*arg == "--flat") flat = true;
- else if (*arg == "--base32") base32 = true;
+ else if (*arg == "--base16") base = Base16;
+ else if (*arg == "--base32") base = Base32;
+ else if (*arg == "--base64") base = Base64;
+ else if (*arg == "--sri") base = SRI;
else if (*arg == "--truncate") truncate = true;
else if (*arg == "--type") {
std::string s = getArg(*arg, arg, end);
ht = parseHashType(s);
}
- else if (*arg == "--to-base16") op = opTo16;
- else if (*arg == "--to-base32") op = opTo32;
+ else if (*arg == "--to-base16") {
+ op = opTo;
+ base = Base16;
+ }
+ else if (*arg == "--to-base32") {
+ op = opTo;
+ base = Base32;
+ }
+ else if (*arg == "--to-base64") {
+ op = opTo;
+ base = Base64;
+ }
+ else if (*arg == "--to-sri") {
+ op = opTo;
+ base = SRI;
+ }
else if (*arg != "" && arg->at(0) == '-')
return false;
else
@@ -191,17 +207,18 @@ static int compatNixHash(int argc, char * * argv)
if (op == opHash) {
CmdHashBase cmd(flat ? FileIngestionMethod::Flat : FileIngestionMethod::Recursive);
- cmd.ht = ht;
- cmd.base = base32 ? Base32 : Base16;
+ if (!ht.has_value()) ht = htMD5;
+ cmd.ht = ht.value();
+ cmd.base = base;
cmd.truncate = truncate;
cmd.paths = ss;
cmd.run();
}
else {
- CmdToBase cmd(op == opTo32 ? Base32 : Base16);
+ CmdToBase cmd(base);
cmd.args = ss;
- cmd.ht = ht;
+ if (ht.has_value()) cmd.ht = ht;
cmd.run();
}
diff --git a/src/nix/log.cc b/src/nix/log.cc
index 0c9f778f0..aaf829764 100644
--- a/src/nix/log.cc
+++ b/src/nix/log.cc
@@ -23,7 +23,7 @@ struct CmdLog : InstallableCommand
Category category() override { return catSecondary; }
- void run(ref<Store> store) override
+ void run(ref<Store> store, ref<Installable> installable) override
{
settings.readOnlyMode = true;
diff --git a/src/nix/log.md b/src/nix/log.md
index 1c76226a3..01e9801df 100644
--- a/src/nix/log.md
+++ b/src/nix/log.md
@@ -22,8 +22,7 @@ R""(
# Description
-This command prints the log of a previous build of the derivation
-*installable* on standard output.
+This command prints the log of a previous build of the [*installable*](./nix.md#installables) on standard output.
Nix looks for build logs in two places:
diff --git a/src/nix/main.cc b/src/nix/main.cc
index 53bf649d4..7b715f281 100644
--- a/src/nix/main.cc
+++ b/src/nix/main.cc
@@ -394,7 +394,6 @@ void mainWrapped(int argc, char * * argv)
if (args.command->second->forceImpureByDefault() && !evalSettings.pureEval.overridden) {
evalSettings.pureEval = false;
}
- args.command->second->prepare();
args.command->second->run();
}
diff --git a/src/nix/make-content-addressed.cc b/src/nix/make-content-addressed.cc
index 6693c55ac..d9c988a9f 100644
--- a/src/nix/make-content-addressed.cc
+++ b/src/nix/make-content-addressed.cc
@@ -28,7 +28,6 @@ struct CmdMakeContentAddressed : virtual CopyCommand, virtual StorePathsCommand,
;
}
- using StorePathsCommand::run;
void run(ref<Store> srcStore, StorePaths && storePaths) override
{
auto dstStore = dstUri.empty() ? openStore() : openStore(dstUri);
diff --git a/src/nix/make-content-addressed.md b/src/nix/make-content-addressed.md
index 32eecc880..b1f7da525 100644
--- a/src/nix/make-content-addressed.md
+++ b/src/nix/make-content-addressed.md
@@ -35,7 +35,9 @@ R""(
# Description
This command converts the closure of the store paths specified by
-*installables* to content-addressed form. Nix store paths are usually
+[*installables*](./nix.md#installables) to content-addressed form.
+
+Nix store paths are usually
*input-addressed*, meaning that the hash part of the store path is
computed from the contents of the derivation (i.e., the build-time
dependency graph). Input-addressed paths need to be signed by a
diff --git a/src/nix/nar.cc b/src/nix/nar.cc
index dbb043d9b..9815410cf 100644
--- a/src/nix/nar.cc
+++ b/src/nix/nar.cc
@@ -25,7 +25,6 @@ struct CmdNar : NixMultiCommand
{
if (!command)
throw UsageError("'nix nar' requires a sub-command.");
- command->second->prepare();
command->second->run();
}
};
diff --git a/src/nix/nix.md b/src/nix/nix.md
index db60c59ff..0a90fa6c9 100644
--- a/src/nix/nix.md
+++ b/src/nix/nix.md
@@ -48,102 +48,112 @@ manual](https://nixos.org/manual/nix/stable/).
# Installables
-Many `nix` subcommands operate on one or more *installables*. These are
-command line arguments that represent something that can be built in
-the Nix store. Here are the recognised types of installables:
-
-* **Flake output attributes**: `nixpkgs#hello`
-
- These have the form *flakeref*[`#`*attrpath*], where *flakeref* is a
- flake reference and *attrpath* is an optional attribute path. For
- more information on flakes, see [the `nix flake` manual
- page](./nix3-flake.md). Flake references are most commonly a flake
- identifier in the flake registry (e.g. `nixpkgs`), or a raw path
- (e.g. `/path/to/my-flake` or `.` or `../foo`), or a full URL
- (e.g. `github:nixos/nixpkgs` or `path:.`)
-
- When the flake reference is a raw path (a path without any URL
- scheme), it is interpreted as a `path:` or `git+file:` url in the following
- way:
-
- - If the path is within a Git repository, then the url will be of the form
- `git+file://[GIT_REPO_ROOT]?dir=[RELATIVE_FLAKE_DIR_PATH]`
- where `GIT_REPO_ROOT` is the path to the root of the git repository,
- and `RELATIVE_FLAKE_DIR_PATH` is the path (relative to the directory
- root) of the closest parent of the given path that contains a `flake.nix` within
- the git repository.
- If no such directory exists, then Nix will error-out.
-
- Note that the search will only include files indexed by git. In particular, files
- which are matched by `.gitignore` or have never been `git add`-ed will not be
- available in the flake. If this is undesirable, specify `path:<directory>` explicitly;
-
- For example, if `/foo/bar` is a git repository with the following structure:
- ```
- .
- └── baz
- ├── blah
- │  └── file.txt
- └── flake.nix
- ```
+Many `nix` subcommands operate on one or more *installables*.
+These are command line arguments that represent something that can be realised in the Nix store.
- Then `/foo/bar/baz/blah` will resolve to `git+file:///foo/bar?dir=baz`
+The following types of installable are supported by most commands:
- - If the supplied path is not a git repository, then the url will have the form
- `path:FLAKE_DIR_PATH` where `FLAKE_DIR_PATH` is the closest parent
- of the supplied path that contains a `flake.nix` file (within the same file-system).
- If no such directory exists, then Nix will error-out.
-
- For example, if `/foo/bar/flake.nix` exists, then `/foo/bar/baz/` will resolve to
- `path:/foo/bar`
+- [Flake output attribute](#flake-output-attribute)
+- [Store path](#store-path)
+- [Nix file](#nix-file), optionally qualified by an attribute path
+- [Nix expression](#nix-expression), optionally qualified by an attribute path
- If *attrpath* is omitted, Nix tries some default values; for most
- subcommands, the default is `packages.`*system*`.default`
- (e.g. `packages.x86_64-linux.default`), but some subcommands have
- other defaults. If *attrpath* *is* specified, *attrpath* is
- interpreted as relative to one or more prefixes; for most
- subcommands, these are `packages.`*system*,
- `legacyPackages.*system*` and the empty prefix. Thus, on
- `x86_64-linux` `nix build nixpkgs#hello` will try to build the
- attributes `packages.x86_64-linux.hello`,
- `legacyPackages.x86_64-linux.hello` and `hello`.
+For most commands, if no installable is specified, `.` as assumed.
+That is, Nix will operate on the default flake output attribute of the flake in the current directory.
-* **Store paths**: `/nix/store/v5sv61sszx301i0x6xysaqzla09nksnd-hello-2.10`
+### Flake output attribute
- These are paths inside the Nix store, or symlinks that resolve to a
- path in the Nix store.
+Example: `nixpkgs#hello`
-* **Store derivations**: `/nix/store/p7gp6lxdg32h4ka1q398wd9r2zkbbz2v-hello-2.10.drv`
+These have the form *flakeref*[`#`*attrpath*], where *flakeref* is a
+[flake reference](./nix3-flake.md#flake-references) and *attrpath* is an optional attribute path. For
+more information on flakes, see [the `nix flake` manual
+page](./nix3-flake.md). Flake references are most commonly a flake
+identifier in the flake registry (e.g. `nixpkgs`), or a raw path
+(e.g. `/path/to/my-flake` or `.` or `../foo`), or a full URL
+(e.g. `github:nixos/nixpkgs` or `path:.`)
- By default, if you pass a [store derivation] path to a `nix` subcommand, the command will operate on the [output path]s of the derivation.
+When the flake reference is a raw path (a path without any URL
+scheme), it is interpreted as a `path:` or `git+file:` url in the following
+way:
- [output path]: ../../glossary.md#gloss-output-path
+- If the path is within a Git repository, then the url will be of the form
+ `git+file://[GIT_REPO_ROOT]?dir=[RELATIVE_FLAKE_DIR_PATH]`
+ where `GIT_REPO_ROOT` is the path to the root of the git repository,
+ and `RELATIVE_FLAKE_DIR_PATH` is the path (relative to the directory
+ root) of the closest parent of the given path that contains a `flake.nix` within
+ the git repository.
+ If no such directory exists, then Nix will error-out.
- For example, `nix path-info` prints information about the output paths:
+ Note that the search will only include files indexed by git. In particular, files
+ which are matched by `.gitignore` or have never been `git add`-ed will not be
+ available in the flake. If this is undesirable, specify `path:<directory>` explicitly;
- ```console
- # nix path-info --json /nix/store/p7gp6lxdg32h4ka1q398wd9r2zkbbz2v-hello-2.10.drv
- [{"path":"/nix/store/v5sv61sszx301i0x6xysaqzla09nksnd-hello-2.10",…}]
+ For example, if `/foo/bar` is a git repository with the following structure:
+ ```
+ .
+ └── baz
+ ├── blah
+ │  └── file.txt
+ └── flake.nix
```
- If you want to operate on the store derivation itself, pass the
- `--derivation` flag.
+ Then `/foo/bar/baz/blah` will resolve to `git+file:///foo/bar?dir=baz`
+
+- If the supplied path is not a git repository, then the url will have the form
+ `path:FLAKE_DIR_PATH` where `FLAKE_DIR_PATH` is the closest parent
+ of the supplied path that contains a `flake.nix` file (within the same file-system).
+ If no such directory exists, then Nix will error-out.
+
+ For example, if `/foo/bar/flake.nix` exists, then `/foo/bar/baz/` will resolve to
+ `path:/foo/bar`
+
+If *attrpath* is omitted, Nix tries some default values; for most
+subcommands, the default is `packages.`*system*`.default`
+(e.g. `packages.x86_64-linux.default`), but some subcommands have
+other defaults. If *attrpath* *is* specified, *attrpath* is
+interpreted as relative to one or more prefixes; for most
+subcommands, these are `packages.`*system*,
+`legacyPackages.*system*` and the empty prefix. Thus, on
+`x86_64-linux` `nix build nixpkgs#hello` will try to build the
+attributes `packages.x86_64-linux.hello`,
+`legacyPackages.x86_64-linux.hello` and `hello`.
+
+### Store path
+
+Example: `/nix/store/v5sv61sszx301i0x6xysaqzla09nksnd-hello-2.10`
+
+These are paths inside the Nix store, or symlinks that resolve to a path in the Nix store.
+
+A [store derivation] is also addressed by store path.
+
+Example: `/nix/store/p7gp6lxdg32h4ka1q398wd9r2zkbbz2v-hello-2.10.drv`
+
+If you want to refer to an output path of that store derivation, add the output name preceded by a caret (`^`).
+
+Example: `/nix/store/p7gp6lxdg32h4ka1q398wd9r2zkbbz2v-hello-2.10.drv^out`
+
+All outputs can be referred to at once with the special syntax `^*`.
+
+Example: `/nix/store/p7gp6lxdg32h4ka1q398wd9r2zkbbz2v-hello-2.10.drv^*`
+
+### Nix file
+
+Example: `--file /path/to/nixpkgs hello`
-* **Nix attributes**: `--file /path/to/nixpkgs hello`
+When the option `-f` / `--file` *path* \[*attrpath*...\] is given, installables are interpreted as the value of the expression in the Nix file at *path*.
+If attribute paths are provided, commands will operate on the corresponding values accessible at these paths.
+The Nix expression in that file, or any selected attribute, must evaluate to a derivation.
- When the `-f` / `--file` *path* option is given, installables are
- interpreted as attribute paths referencing a value returned by
- evaluating the Nix file *path*.
+### Nix expression
-* **Nix expressions**: `--expr '(import <nixpkgs> {}).hello.overrideDerivation (prev: { name = "my-hello"; })'`.
+Example: `--expr 'import <nixpkgs> {}' hello`
- When the `--expr` option is given, all installables are interpreted
- as Nix expressions. You may need to specify `--impure` if the
- expression references impure inputs (such as `<nixpkgs>`).
+When the option `--expr` *expression* \[*attrpath*...\] is given, installables are interpreted as the value of the of the Nix expression.
+If attribute paths are provided, commands will operate on the corresponding values accessible at these paths.
+The Nix expression, or any selected attribute, must evaluate to a derivation.
-For most commands, if no installable is specified, the default is `.`,
-i.e. Nix will operate on the default flake output attribute of the
-flake in the current directory.
+You may need to specify `--impure` if the expression references impure inputs (such as `<nixpkgs>`).
## Derivation output selection
diff --git a/src/nix/path-info.md b/src/nix/path-info.md
index b30898ac0..6ad23a02e 100644
--- a/src/nix/path-info.md
+++ b/src/nix/path-info.md
@@ -80,7 +80,7 @@ R""(
# Description
This command shows information about the store paths produced by
-*installables*, or about all paths in the store if you pass `--all`.
+[*installables*](./nix.md#installables), or about all paths in the store if you pass `--all`.
By default, this command only prints the store paths. You can get
additional information by passing flags such as `--closure-size`,
diff --git a/src/nix/print-dev-env.md b/src/nix/print-dev-env.md
index 2aad491de..a8ce9d36a 100644
--- a/src/nix/print-dev-env.md
+++ b/src/nix/print-dev-env.md
@@ -40,7 +40,7 @@ R""(
This command prints a shell script that can be sourced by `bash` and
that sets the variables and shell functions defined by the build
-process of *installable*. This allows you to get a similar build
+process of [*installable*](./nix.md#installables). This allows you to get a similar build
environment in your current shell rather than in a subshell (as with
`nix develop`).
diff --git a/src/nix/profile-install.md b/src/nix/profile-install.md
index aed414963..4c0f82c09 100644
--- a/src/nix/profile-install.md
+++ b/src/nix/profile-install.md
@@ -29,6 +29,6 @@ R""(
# Description
-This command adds *installables* to a Nix profile.
+This command adds [*installables*](./nix.md#installables) to a Nix profile.
)""
diff --git a/src/nix/profile.cc b/src/nix/profile.cc
index eef33b3d9..d72dd1a13 100644
--- a/src/nix/profile.cc
+++ b/src/nix/profile.cc
@@ -256,11 +256,11 @@ struct ProfileManifest
static std::map<Installable *, std::pair<BuiltPaths, ExtraPathInfo>>
builtPathsPerInstallable(
- const std::vector<std::pair<std::shared_ptr<Installable>, BuiltPathWithResult>> & builtPaths)
+ const std::vector<std::pair<ref<Installable>, BuiltPathWithResult>> & builtPaths)
{
std::map<Installable *, std::pair<BuiltPaths, ExtraPathInfo>> res;
for (auto & [installable, builtPath] : builtPaths) {
- auto & r = res[installable.get()];
+ auto & r = res[&*installable];
/* Note that there could be conflicting info
(e.g. meta.priority fields) if the installable returned
multiple derivations. So pick one arbitrarily. FIXME:
@@ -296,7 +296,7 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
;
}
- void run(ref<Store> store) override
+ void run(ref<Store> store, Installables && installables) override
{
ProfileManifest manifest(*getEvalState(), *profile);
@@ -307,7 +307,7 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
for (auto & installable : installables) {
ProfileElement element;
- auto & [res, info] = builtPaths[installable.get()];
+ auto & [res, info] = builtPaths[&*installable];
if (info.originalRef && info.resolvedRef && info.attrPath && info.extendedOutputsSpec) {
element.source = ProfileElementSource {
@@ -513,7 +513,7 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf
auto matchers = getMatchers(store);
- std::vector<std::shared_ptr<Installable>> installables;
+ Installables installables;
std::vector<size_t> indices;
auto upgradedCount = 0;
@@ -529,7 +529,7 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf
Activity act(*logger, lvlChatty, actUnknown,
fmt("checking '%s' for updates", element.source->attrPath));
- auto installable = std::make_shared<InstallableFlake>(
+ auto installable = make_ref<InstallableFlake>(
this,
getEvalState(),
FlakeRef(element.source->originalRef),
@@ -582,7 +582,7 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf
for (size_t i = 0; i < installables.size(); ++i) {
auto & installable = installables.at(i);
auto & element = manifest.elements[indices.at(i)];
- element.updateStorePaths(getEvalStore(), store, builtPaths[installable.get()].first);
+ element.updateStorePaths(getEvalStore(), store, builtPaths[&*installable].first);
}
updateProfile(manifest.build(store));
@@ -798,7 +798,6 @@ struct CmdProfile : NixMultiCommand
{
if (!command)
throw UsageError("'nix profile' requires a sub-command.");
- command->second->prepare();
command->second->run();
}
};
diff --git a/src/nix/realisation.cc b/src/nix/realisation.cc
index 0d3466515..13db80282 100644
--- a/src/nix/realisation.cc
+++ b/src/nix/realisation.cc
@@ -21,7 +21,6 @@ struct CmdRealisation : virtual NixMultiCommand
{
if (!command)
throw UsageError("'nix realisation' requires a sub-command.");
- command->second->prepare();
command->second->run();
}
};
diff --git a/src/nix/registry.cc b/src/nix/registry.cc
index b5bdfba95..1f4f820ac 100644
--- a/src/nix/registry.cc
+++ b/src/nix/registry.cc
@@ -227,7 +227,6 @@ struct CmdRegistry : virtual NixMultiCommand
settings.requireExperimentalFeature(Xp::Flakes);
if (!command)
throw UsageError("'nix registry' requires a sub-command.");
- command->second->prepare();
command->second->run();
}
};
diff --git a/src/nix/repl.cc b/src/nix/repl.cc
index 679bdea77..51d3074b4 100644
--- a/src/nix/repl.cc
+++ b/src/nix/repl.cc
@@ -5,26 +5,12 @@
namespace nix {
-struct CmdRepl : InstallablesCommand
+struct CmdRepl : RawInstallablesCommand
{
CmdRepl() {
evalSettings.pureEval = false;
}
- void prepare() override
- {
- if (!settings.isExperimentalFeatureEnabled(Xp::ReplFlake) && !(file) && this->_installables.size() >= 1) {
- warn("future versions of Nix will require using `--file` to load a file");
- if (this->_installables.size() > 1)
- warn("more than one input file is not currently supported");
- auto filePath = this->_installables[0].data();
- file = std::optional(filePath);
- _installables.front() = _installables.back();
- _installables.pop_back();
- }
- installables = InstallablesCommand::load();
- }
-
std::vector<std::string> files;
Strings getDefaultFlakeAttrPaths() override
@@ -32,11 +18,6 @@ struct CmdRepl : InstallablesCommand
return {""};
}
- bool useDefaultInstallables() override
- {
- return file.has_value() or expr.has_value();
- }
-
bool forceImpureByDefault() override
{
return true;
@@ -54,11 +35,27 @@ struct CmdRepl : InstallablesCommand
;
}
- void run(ref<Store> store) override
+ void applyDefaultInstallables(std::vector<std::string> & rawInstallables) override
+ {
+ if (!settings.isExperimentalFeatureEnabled(Xp::ReplFlake) && !(file) && rawInstallables.size() >= 1) {
+ warn("future versions of Nix will require using `--file` to load a file");
+ if (rawInstallables.size() > 1)
+ warn("more than one input file is not currently supported");
+ auto filePath = rawInstallables[0].data();
+ file = std::optional(filePath);
+ rawInstallables.front() = rawInstallables.back();
+ rawInstallables.pop_back();
+ }
+ if (rawInstallables.empty() && (file.has_value() || expr.has_value())) {
+ rawInstallables.push_back(".");
+ }
+ }
+
+ void run(ref<Store> store, std::vector<std::string> && rawInstallables) override
{
auto state = getEvalState();
auto getValues = [&]()->AbstractNixRepl::AnnotatedValues{
- auto installables = load();
+ auto installables = parseInstallables(store, rawInstallables);
AbstractNixRepl::AnnotatedValues values;
for (auto & installable: installables){
auto what = installable->what();
diff --git a/src/nix/run.cc b/src/nix/run.cc
index 6fca68047..56605d9d5 100644
--- a/src/nix/run.cc
+++ b/src/nix/run.cc
@@ -97,7 +97,7 @@ struct CmdShell : InstallablesCommand, MixEnvironment
;
}
- void run(ref<Store> store) override
+ void run(ref<Store> store, Installables && installables) override
{
auto outPaths = Installable::toStorePaths(getEvalStore(), store, Realise::Outputs, OperateOn::Output, installables);
@@ -183,7 +183,7 @@ struct CmdRun : InstallableCommand
return res;
}
- void run(ref<Store> store) override
+ void run(ref<Store> store, ref<Installable> installable) override
{
auto state = getEvalState();
diff --git a/src/nix/run.md b/src/nix/run.md
index a0f362076..250ea65aa 100644
--- a/src/nix/run.md
+++ b/src/nix/run.md
@@ -35,7 +35,7 @@ R""(
# Description
-`nix run` builds and runs *installable*, which must evaluate to an
+`nix run` builds and runs [*installable*](./nix.md#installables), which must evaluate to an
*app* or a regular Nix derivation.
If *installable* evaluates to an *app* (see below), it executes the
diff --git a/src/nix/search.cc b/src/nix/search.cc
index 2e38f7e4b..994ec44c2 100644
--- a/src/nix/search.cc
+++ b/src/nix/search.cc
@@ -61,7 +61,7 @@ struct CmdSearch : InstallableCommand, MixJSON
};
}
- void run(ref<Store> store) override
+ void run(ref<Store> store, ref<Installable> installable) override
{
settings.readOnlyMode = true;
evalSettings.enableImportFromDerivation.setDefault(false);
diff --git a/src/nix/search.md b/src/nix/search.md
index 5a5b5ae05..4caa90654 100644
--- a/src/nix/search.md
+++ b/src/nix/search.md
@@ -62,10 +62,10 @@ R""(
# Description
-`nix search` searches *installable* (which must be evaluatable, e.g. a
-flake) for packages whose name or description matches all of the
+`nix search` searches [*installable*](./nix.md#installables) (which can be evaluated, that is, a
+flake or Nix expression, but not a store path or store derivation path) for packages whose name or description matches all of the
regular expressions *regex*. For each matching package, It prints the
-full attribute name (from the root of the installable), the version
+full attribute name (from the root of the [installable](./nix.md#installables)), the version
and the `meta.description` field, highlighting the substrings that
were matched by the regular expressions. If no regular expressions are
specified, all packages are shown.
diff --git a/src/nix/shell.md b/src/nix/shell.md
index 9fa1031f5..13a389103 100644
--- a/src/nix/shell.md
+++ b/src/nix/shell.md
@@ -48,7 +48,7 @@ R""(
# Description
`nix shell` runs a command in an environment in which the `$PATH` variable
-provides the specified *installables*. If no command is specified, it starts the
+provides the specified [*installables*](./nix.md#installable). If no command is specified, it starts the
default shell of your user account specified by `$SHELL`.
)""
diff --git a/src/nix/show-derivation.cc b/src/nix/show-derivation.cc
index 520e8b1ce..4a406ae08 100644
--- a/src/nix/show-derivation.cc
+++ b/src/nix/show-derivation.cc
@@ -39,7 +39,7 @@ struct CmdShowDerivation : InstallablesCommand
Category category() override { return catUtility; }
- void run(ref<Store> store) override
+ void run(ref<Store> store, Installables && installables) override
{
auto drvPaths = Installable::toDerivations(store, installables, true);
diff --git a/src/nix/show-derivation.md b/src/nix/show-derivation.md
index 2cd93aa62..1d37c6f5a 100644
--- a/src/nix/show-derivation.md
+++ b/src/nix/show-derivation.md
@@ -39,7 +39,7 @@ R""(
# Description
This command prints on standard output a JSON representation of the
-[store derivation]s to which *installables* evaluate. Store derivations
+[store derivation]s to which [*installables*](./nix.md#installables) evaluate. Store derivations
are used internally by Nix. They are store paths with extension `.drv`
that represent the build-time dependency graph to which a Nix
expression evaluates.
diff --git a/src/nix/sigs.cc b/src/nix/sigs.cc
index ee27e3725..45cd2e1a6 100644
--- a/src/nix/sigs.cc
+++ b/src/nix/sigs.cc
@@ -45,7 +45,7 @@ struct CmdCopySigs : StorePathsCommand
//logger->setExpected(doneLabel, storePaths.size());
auto doPath = [&](const Path & storePathS) {
- //Activity act(*logger, lvlInfo, format("getting signatures for '%s'") % storePath);
+ //Activity act(*logger, lvlInfo, "getting signatures for '%s'", storePath);
checkInterrupt();
@@ -219,7 +219,6 @@ struct CmdKey : NixMultiCommand
{
if (!command)
throw UsageError("'nix key' requires a sub-command.");
- command->second->prepare();
command->second->run();
}
};
diff --git a/src/nix/store-copy-log.cc b/src/nix/store-copy-log.cc
index d5fab5f2f..1dda8c0b8 100644
--- a/src/nix/store-copy-log.cc
+++ b/src/nix/store-copy-log.cc
@@ -26,7 +26,7 @@ struct CmdCopyLog : virtual CopyCommand, virtual InstallablesCommand
Category category() override { return catUtility; }
- void run(ref<Store> srcStore) override
+ void run(ref<Store> srcStore, Installables && installables) override
{
auto & srcLogStore = require<LogStore>(*srcStore);
diff --git a/src/nix/store-delete.cc b/src/nix/store-delete.cc
index ca43f1530..6719227df 100644
--- a/src/nix/store-delete.cc
+++ b/src/nix/store-delete.cc
@@ -32,7 +32,7 @@ struct CmdStoreDelete : StorePathsCommand
;
}
- void run(ref<Store> store, std::vector<StorePath> && storePaths) override
+ void run(ref<Store> store, StorePaths && storePaths) override
{
auto & gcStore = require<GcStore>(*store);
diff --git a/src/nix/store-delete.md b/src/nix/store-delete.md
index db535f87c..431bc5f5e 100644
--- a/src/nix/store-delete.md
+++ b/src/nix/store-delete.md
@@ -10,7 +10,7 @@ R""(
# Description
-This command deletes the store paths specified by *installables*. ,
+This command deletes the store paths specified by [*installables*](./nix.md#installables),
but only if it is safe to do so; that is, when the path is not
reachable from a root of the garbage collector. This means that you
can only delete paths that would also be deleted by `nix store
diff --git a/src/nix/store-dump-path.md b/src/nix/store-dump-path.md
index 4ef563526..56e2174b6 100644
--- a/src/nix/store-dump-path.md
+++ b/src/nix/store-dump-path.md
@@ -18,6 +18,6 @@ R""(
# Description
This command generates a NAR file containing the serialisation of the
-store path *installable*. The NAR is written to standard output.
+store path [*installable*](./nix.md#installables). The NAR is written to standard output.
)""
diff --git a/src/nix/store-repair.cc b/src/nix/store-repair.cc
index 8fcb3639a..895e39685 100644
--- a/src/nix/store-repair.cc
+++ b/src/nix/store-repair.cc
@@ -17,7 +17,7 @@ struct CmdStoreRepair : StorePathsCommand
;
}
- void run(ref<Store> store, std::vector<StorePath> && storePaths) override
+ void run(ref<Store> store, StorePaths && storePaths) override
{
for (auto & path : storePaths)
store->repairPath(path);
diff --git a/src/nix/store-repair.md b/src/nix/store-repair.md
index 92d2205a9..180c577ac 100644
--- a/src/nix/store-repair.md
+++ b/src/nix/store-repair.md
@@ -17,7 +17,7 @@ R""(
# Description
This command attempts to "repair" the store paths specified by
-*installables* by redownloading them using the available
+[*installables*](./nix.md#installables) by redownloading them using the available
substituters. If no substitutes are available, then repair is not
possible.
diff --git a/src/nix/store.cc b/src/nix/store.cc
index 44e53c7c7..2879e03b3 100644
--- a/src/nix/store.cc
+++ b/src/nix/store.cc
@@ -18,7 +18,6 @@ struct CmdStore : virtual NixMultiCommand
{
if (!command)
throw UsageError("'nix store' requires a sub-command.");
- command->second->prepare();
command->second->run();
}
};
diff --git a/src/nix/verify.md b/src/nix/verify.md
index 1c43792e7..cc1122c02 100644
--- a/src/nix/verify.md
+++ b/src/nix/verify.md
@@ -24,7 +24,7 @@ R""(
# Description
-This command verifies the integrity of the store paths *installables*,
+This command verifies the integrity of the store paths [*installables*](./nix.md#installables),
or, if `--all` is given, the entire Nix store. For each path, it
checks that
diff --git a/src/resolve-system-dependencies/resolve-system-dependencies.cc b/src/resolve-system-dependencies/resolve-system-dependencies.cc
index c6023eb03..4ea268d24 100644
--- a/src/resolve-system-dependencies/resolve-system-dependencies.cc
+++ b/src/resolve-system-dependencies/resolve-system-dependencies.cc
@@ -157,13 +157,9 @@ int main(int argc, char ** argv)
uname(&_uname);
- auto cacheParentDir = (format("%1%/dependency-maps") % settings.nixStateDir).str();
+ auto cacheParentDir = fmt("%1%/dependency-maps", settings.nixStateDir);
- cacheDir = (format("%1%/%2%-%3%-%4%")
- % cacheParentDir
- % _uname.machine
- % _uname.sysname
- % _uname.release).str();
+ cacheDir = fmt("%1%/%2%-%3%-%4%", cacheParentDir, _uname.machine, _uname.sysname, _uname.release);
mkdir(cacheParentDir.c_str(), 0755);
mkdir(cacheDir.c_str(), 0755);