aboutsummaryrefslogtreecommitdiff
path: root/src/nix
diff options
context:
space:
mode:
authorBen Burdette <bburdette@protonmail.com>2022-04-07 13:42:01 -0600
committerBen Burdette <bburdette@protonmail.com>2022-04-07 13:42:01 -0600
commit1a93ac8133381eb692416c4e46b1706faa5cd89f (patch)
tree9a559f977ad6213c055099f6f2ab6be96f0c551b /src/nix
parentd2ec9b4e15718e42720787140d7825dcbfd73249 (diff)
parent8b1e328d5d0ae7d3a4a8f6012ec065b59674ed4a (diff)
Merge remote-tracking branch 'upstream/master' into upstream-merge
Diffstat (limited to 'src/nix')
-rw-r--r--src/nix/app.cc5
-rw-r--r--src/nix/build.cc19
-rw-r--r--src/nix/bundle.cc34
-rw-r--r--src/nix/bundle.md14
-rw-r--r--src/nix/daemon.cc16
-rw-r--r--src/nix/develop.cc32
-rw-r--r--src/nix/develop.md4
-rw-r--r--src/nix/diff-closures.cc4
-rw-r--r--src/nix/doctor.cc4
-rw-r--r--src/nix/edit.md6
-rw-r--r--src/nix/flake-init.md22
-rw-r--r--src/nix/flake-show.md11
-rw-r--r--src/nix/flake.cc47
-rw-r--r--src/nix/flake.md34
-rw-r--r--src/nix/hash.cc2
-rw-r--r--src/nix/log.cc14
-rw-r--r--src/nix/main.cc3
-rw-r--r--src/nix/make-content-addressable.cc102
-rw-r--r--src/nix/make-content-addressed.cc55
-rw-r--r--src/nix/make-content-addressed.md (renamed from src/nix/make-content-addressable.md)4
-rw-r--r--src/nix/nix.md6
-rw-r--r--src/nix/path-info.cc2
-rw-r--r--src/nix/prefetch.cc14
-rw-r--r--src/nix/profile-list.md2
-rw-r--r--src/nix/profile.cc188
-rw-r--r--src/nix/profile.md8
-rw-r--r--src/nix/run.cc15
-rw-r--r--src/nix/run.md6
-rw-r--r--src/nix/show-derivation.cc16
-rw-r--r--src/nix/store-copy-log.cc9
-rw-r--r--src/nix/store-delete.cc6
-rw-r--r--src/nix/store-gc.cc6
-rw-r--r--src/nix/why-depends.cc29
33 files changed, 442 insertions, 297 deletions
diff --git a/src/nix/app.cc b/src/nix/app.cc
index e104cc9c1..803d028f0 100644
--- a/src/nix/app.cc
+++ b/src/nix/app.cc
@@ -4,6 +4,7 @@
#include "eval-cache.hh"
#include "names.hh"
#include "command.hh"
+#include "derivations.hh"
namespace nix {
@@ -70,7 +71,7 @@ UnresolvedApp Installable::toApp(EvalState & state)
std::vector<StorePathWithOutputs> context2;
for (auto & [path, name] : context)
- context2.push_back({state.store->parseStorePath(path), {name}});
+ context2.push_back({path, {name}});
return UnresolvedApp{App {
.context = std::move(context2),
@@ -114,7 +115,7 @@ App UnresolvedApp::resolve(ref<Store> evalStore, ref<Store> store)
installableContext.push_back(
std::make_shared<InstallableDerivedPath>(store, ctxElt.toDerivedPath()));
- auto builtContext = build(evalStore, store, Realise::Outputs, installableContext);
+ auto builtContext = Installable::build(evalStore, store, Realise::Outputs, installableContext);
res.program = resolveString(*store, unresolved.program, builtContext);
if (!store->isInStore(res.program))
throw Error("app program '%s' is not in the Nix store", res.program);
diff --git a/src/nix/build.cc b/src/nix/build.cc
index 6e31757a2..840c7ca38 100644
--- a/src/nix/build.cc
+++ b/src/nix/build.cc
@@ -52,15 +52,26 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile
void run(ref<Store> store) override
{
- auto buildables = build(
+ if (dryRun) {
+ std::vector<DerivedPath> pathsToBuild;
+
+ for (auto & i : installables) {
+ auto b = i->toDerivedPaths();
+ pathsToBuild.insert(pathsToBuild.end(), b.begin(), b.end());
+ }
+ printMissing(store, pathsToBuild, lvlError);
+ if (json)
+ logger->cout("%s", derivedPathsToJSON(pathsToBuild, store).dump());
+ return;
+ }
+
+ auto buildables = Installable::build(
getEvalStore(), store,
- dryRun ? Realise::Derivation : Realise::Outputs,
+ Realise::Outputs,
installables, buildMode);
if (json) logger->cout("%s", derivedPathsWithHintsToJSON(buildables, store).dump());
- if (dryRun) return;
-
if (outLink != "")
if (auto store2 = store.dynamic_pointer_cast<LocalFSStore>())
for (const auto & [_i, buildable] : enumerate(buildables)) {
diff --git a/src/nix/bundle.cc b/src/nix/bundle.cc
index 113ceca33..81fb8464a 100644
--- a/src/nix/bundle.cc
+++ b/src/nix/bundle.cc
@@ -9,7 +9,7 @@ using namespace nix;
struct CmdBundle : InstallableCommand
{
- std::string bundler = "github:matthewbauer/nix-bundle";
+ std::string bundler = "github:NixOS/bundlers";
std::optional<Path> outLink;
CmdBundle()
@@ -49,9 +49,11 @@ struct CmdBundle : InstallableCommand
Category category() override { return catSecondary; }
+ // FIXME: cut&paste from CmdRun.
Strings getDefaultFlakeAttrPaths() override
{
Strings res{
+ "apps." + settings.thisSystem.get() + ".default",
"defaultApp." + settings.thisSystem.get()
};
for (auto & s : SourceExprCommand::getDefaultFlakeAttrPaths())
@@ -61,10 +63,7 @@ struct CmdBundle : InstallableCommand
Strings getDefaultFlakeAttrPathPrefixes() override
{
- Strings res{
- "apps." + settings.thisSystem.get() + "."
-
- };
+ Strings res{"apps." + settings.thisSystem.get() + "."};
for (auto & s : SourceExprCommand::getDefaultFlakeAttrPathPrefixes())
res.push_back(s);
return res;
@@ -74,21 +73,18 @@ struct CmdBundle : InstallableCommand
{
auto evalState = getEvalState();
- auto [progFlakeRef, progName] = parseFlakeRefWithFragment(installable->what(), absPath("."));
- const flake::LockFlags lockFlagsProg{ .writeLockFile = false };
- auto programInstallable = InstallableFlake(this,
- evalState, std::move(progFlakeRef),
- Strings{progName == "" ? "defaultApp" : progName},
- Strings(this->getDefaultFlakeAttrPathPrefixes()),
- lockFlagsProg);
- auto val = programInstallable.toValue(*evalState).first;
+ auto val = installable->toValue(*evalState).first;
auto [bundlerFlakeRef, bundlerName] = parseFlakeRefWithFragment(bundler, absPath("."));
const flake::LockFlags lockFlags{ .writeLockFile = false };
- auto bundler = InstallableFlake(this,
- evalState, std::move(bundlerFlakeRef),
- Strings{bundlerName == "" ? "defaultBundler." + settings.thisSystem.get() : settings.thisSystem.get() + "." + bundlerName, bundlerName},
- Strings({"","bundlers."}), lockFlags);
+ InstallableFlake bundler{this,
+ evalState, std::move(bundlerFlakeRef), bundlerName,
+ {"bundlers." + settings.thisSystem.get() + ".default",
+ "defaultBundler." + settings.thisSystem.get()
+ },
+ {"bundlers." + settings.thisSystem.get() + "."},
+ lockFlags
+ };
auto vRes = evalState->allocValue();
evalState->callFunction(*bundler.toValue(*evalState).first, *val, *vRes, noPos);
@@ -101,13 +97,13 @@ struct CmdBundle : InstallableCommand
throw Error("the bundler '%s' does not produce a derivation", bundler.what());
PathSet context2;
- StorePath drvPath = store->parseStorePath(evalState->coerceToPath(*attr1->pos, *attr1->value, context2));
+ auto drvPath = evalState->coerceToStorePath(*attr1->pos, *attr1->value, context2);
auto attr2 = vRes->attrs->get(evalState->sOutPath);
if (!attr2)
throw Error("the bundler '%s' does not produce a derivation", bundler.what());
- StorePath outPath = store->parseStorePath(evalState->coerceToPath(*attr2->pos, *attr2->value, context2));
+ auto outPath = evalState->coerceToStorePath(*attr2->pos, *attr2->value, context2);
store->buildPaths({ DerivedPath::Built { drvPath } });
diff --git a/src/nix/bundle.md b/src/nix/bundle.md
index a5186a996..2bb70711f 100644
--- a/src/nix/bundle.md
+++ b/src/nix/bundle.md
@@ -42,24 +42,26 @@ homepage](https://github.com/NixOS/bundlers) for more details.
If no flake output attribute is given, `nix bundle` tries the following
flake output attributes:
-* `defaultBundler.<system>`
+* `bundlers.<system>.default`
If an attribute *name* is given, `nix run` tries the following flake
output attributes:
-* `bundler.<system>.<name>`
+* `bundlers.<system>.<name>`
# Bundlers
A bundler is specified by a flake output attribute named
-`bundlers.<system>.<name>` or `defaultBundler.<system>`. It looks like this:
+`bundlers.<system>.<name>`. It looks like this:
```nix
-bundlers.x86_64-linux.identity = drv: drv;
+bundlers.x86_64-linux = rec {
+ identity = drv: drv;
-bundlers.x86_64-linux.blender_2_79 = drv: self.packages.x86_64-linux.blender_2_79;
+ blender_2_79 = drv: self.packages.x86_64-linux.blender_2_79;
-defaultBundler.x86_64-linux = drv: drv;
+ default = identity;
+};
```
A bundler must be a function that accepts an arbitrary value (typically a
diff --git a/src/nix/daemon.cc b/src/nix/daemon.cc
index 6a40a0bd3..940923d3b 100644
--- a/src/nix/daemon.cc
+++ b/src/nix/daemon.cc
@@ -76,7 +76,7 @@ static void setSigChldAction(bool autoReap)
}
-bool matchUser(const string & user, const string & group, const Strings & users)
+bool matchUser(const std::string & user, const std::string & group, const Strings & users)
{
if (find(users.begin(), users.end(), "*") != users.end())
return true;
@@ -85,12 +85,12 @@ bool matchUser(const string & user, const string & group, const Strings & users)
return true;
for (auto & i : users)
- if (string(i, 0, 1) == "@") {
- if (group == string(i, 1)) return true;
+ if (i.substr(0, 1) == "@") {
+ if (group == i.substr(1)) return true;
struct group * gr = getgrnam(i.c_str() + 1);
if (!gr) continue;
for (char * * mem = gr->gr_mem; *mem; mem++)
- if (user == string(*mem)) return true;
+ if (user == std::string(*mem)) return true;
}
return false;
@@ -198,10 +198,10 @@ static void daemonLoop()
PeerInfo peer = getPeerInfo(remote.get());
struct passwd * pw = peer.uidKnown ? getpwuid(peer.uid) : 0;
- string user = pw ? pw->pw_name : std::to_string(peer.uid);
+ std::string user = pw ? pw->pw_name : std::to_string(peer.uid);
struct group * gr = peer.gidKnown ? getgrgid(peer.gid) : 0;
- string group = gr ? gr->gr_name : std::to_string(peer.gid);
+ std::string group = gr ? gr->gr_name : std::to_string(peer.gid);
Strings trustedUsers = settings.trustedUsers;
Strings allowedUsers = settings.allowedUsers;
@@ -212,7 +212,7 @@ 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((string) "accepted connection from pid %1%, user %2%" + (trusted ? " (trusted)" : ""))
+ 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>"));
@@ -234,7 +234,7 @@ static void daemonLoop()
// For debugging, stuff the pid into argv[1].
if (peer.pidKnown && savedArgv[1]) {
- string processName = std::to_string(peer.pid);
+ auto processName = std::to_string(peer.pid);
strncpy(savedArgv[1], processName.c_str(), strlen(savedArgv[1]));
}
diff --git a/src/nix/develop.cc b/src/nix/develop.cc
index 42e13436a..7fc74d34e 100644
--- a/src/nix/develop.cc
+++ b/src/nix/develop.cc
@@ -196,21 +196,22 @@ static StorePath getDerivationEnvironment(ref<Store> store, ref<Store> evalStore
drv.inputSrcs.insert(std::move(getEnvShPath));
if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations)) {
for (auto & output : drv.outputs) {
- output.second = {
- .output = DerivationOutputDeferred{},
- };
+ output.second = DerivationOutput::Deferred {},
drv.env[output.first] = hashPlaceholder(output.first);
}
} else {
for (auto & output : drv.outputs) {
- output.second = { .output = DerivationOutputInputAddressed { .path = StorePath::dummy } };
+ output.second = DerivationOutput::Deferred { };
drv.env[output.first] = "";
}
- Hash h = std::get<0>(hashDerivationModulo(*evalStore, drv, true));
+ auto hashesModulo = hashDerivationModulo(*evalStore, drv, true);
for (auto & output : drv.outputs) {
+ Hash h = hashesModulo.hashes.at(output.first);
auto outPath = store->makeOutputPath(output.first, h, drv.name);
- output.second = { .output = DerivationOutputInputAddressed { .path = outPath } };
+ output.second = DerivationOutput::InputAddressed {
+ .path = outPath,
+ };
drv.env[output.first] = store->printStorePath(outPath);
}
}
@@ -307,7 +308,7 @@ struct Common : InstallableCommand, MixProfile
for (auto & [installable_, dir_] : redirects) {
auto dir = absPath(dir_);
auto installable = parseInstallable(store, installable_);
- auto builtPaths = toStorePaths(
+ auto builtPaths = Installable::toStorePaths(
getEvalStore(), store, Realise::Nothing, OperateOn::Output, {installable});
for (auto & path: builtPaths) {
auto from = store->printStorePath(path);
@@ -325,8 +326,15 @@ struct Common : InstallableCommand, MixProfile
Strings getDefaultFlakeAttrPaths() override
{
- return {"devShell." + settings.thisSystem.get(), "defaultPackage." + settings.thisSystem.get()};
+ Strings paths{
+ "devShells." + settings.thisSystem.get() + ".default",
+ "devShell." + settings.thisSystem.get(),
+ };
+ for (auto & p : SourceExprCommand::getDefaultFlakeAttrPaths())
+ paths.push_back(p);
+ return paths;
}
+
Strings getDefaultFlakeAttrPathPrefixes() override
{
auto res = SourceExprCommand::getDefaultFlakeAttrPathPrefixes();
@@ -340,7 +348,7 @@ struct Common : InstallableCommand, MixProfile
if (path && hasSuffix(path->to_string(), "-env"))
return *path;
else {
- auto drvs = toDerivations(store, {installable});
+ auto drvs = Installable::toDerivations(store, {installable});
if (drvs.size() != 1)
throw Error("'%s' needs to evaluate to a single derivation, but it evaluated to %d derivations",
@@ -498,12 +506,14 @@ struct CmdDevelop : Common, MixEnvironment
this,
state,
installable->nixpkgsFlakeRef(),
- Strings{"bashInteractive"},
+ "bashInteractive",
+ Strings{},
Strings{"legacyPackages." + settings.thisSystem.get() + "."},
nixpkgsLockFlags);
shell = store->printStorePath(
- toStorePath(getEvalStore(), store, Realise::Outputs, OperateOn::Output, bashInstallable)) + "/bin/bash";
+ Installable::toStorePath(getEvalStore(), store, Realise::Outputs, OperateOn::Output, bashInstallable))
+ + "/bin/bash";
} catch (Error &) {
ignoreException();
}
diff --git a/src/nix/develop.md b/src/nix/develop.md
index 3e7e339d5..8bcff66c9 100644
--- a/src/nix/develop.md
+++ b/src/nix/develop.md
@@ -88,9 +88,9 @@ the flake's `nixConfig` attribute.
If no flake output attribute is given, `nix develop` tries the following
flake output attributes:
-* `devShell.<system>`
+* `devShells.<system>.default`
-* `defaultPackage.<system>`
+* `packages.<system>.default`
If a flake output *name* is given, `nix develop` tries the following flake
output attributes:
diff --git a/src/nix/diff-closures.cc b/src/nix/diff-closures.cc
index 734c41e0e..0621d662c 100644
--- a/src/nix/diff-closures.cc
+++ b/src/nix/diff-closures.cc
@@ -131,9 +131,9 @@ struct CmdDiffClosures : SourceExprCommand
void run(ref<Store> store) override
{
auto before = parseInstallable(store, _before);
- auto beforePath = toStorePath(getEvalStore(), store, Realise::Outputs, operateOn, before);
+ auto beforePath = Installable::toStorePath(getEvalStore(), store, Realise::Outputs, operateOn, before);
auto after = parseInstallable(store, _after);
- auto afterPath = toStorePath(getEvalStore(), store, Realise::Outputs, operateOn, after);
+ auto afterPath = Installable::toStorePath(getEvalStore(), store, Realise::Outputs, operateOn, after);
printClosureDiff(store, beforePath, afterPath, "");
}
};
diff --git a/src/nix/doctor.cc b/src/nix/doctor.cc
index 4f3003448..ea87e3d87 100644
--- a/src/nix/doctor.cc
+++ b/src/nix/doctor.cc
@@ -24,12 +24,12 @@ std::string formatProtocol(unsigned int proto)
}
bool checkPass(const std::string & msg) {
- logger->log(ANSI_GREEN "[PASS] " ANSI_NORMAL + msg);
+ notice(ANSI_GREEN "[PASS] " ANSI_NORMAL + msg);
return true;
}
bool checkFail(const std::string & msg) {
- logger->log(ANSI_RED "[FAIL] " ANSI_NORMAL + msg);
+ notice(ANSI_RED "[FAIL] " ANSI_NORMAL + msg);
return false;
}
diff --git a/src/nix/edit.md b/src/nix/edit.md
index 80563d06b..89bd09abf 100644
--- a/src/nix/edit.md
+++ b/src/nix/edit.md
@@ -24,8 +24,8 @@ this attribute to the location of the definition of the
`meta.description`, `version` or `name` derivation attributes.
The editor to invoke is specified by the `EDITOR` environment
-variable. It defaults to `cat`. If the editor is `emacs`, `nano` or
-`vim`, it is passed the line number of the derivation using the
-argument `+<lineno>`.
+variable. It defaults to `cat`. If the editor is `emacs`, `nano`,
+`vim` or `kak`, it is passed the line number of the derivation using
+the argument `+<lineno>`.
)""
diff --git a/src/nix/flake-init.md b/src/nix/flake-init.md
index 890038016..fc1f4f805 100644
--- a/src/nix/flake-init.md
+++ b/src/nix/flake-init.md
@@ -24,19 +24,23 @@ R""(
This command creates a flake in the current directory by copying the
files of a template. It will not overwrite existing files. The default
-template is `templates#defaultTemplate`, but this can be overridden
+template is `templates#templates.default`, but this can be overridden
using `-t`.
# Template definitions
-A flake can declare templates through its `templates` and
-`defaultTemplate` output attributes. A template has two attributes:
+A flake can declare templates through its `templates` output
+attribute. A template has two attributes:
* `description`: A one-line description of the template, in CommonMark
syntax.
* `path`: The path of the directory to be copied.
+* `welcomeText`: A block of markdown text to display when a user initializes a
+ new flake based on this template.
+
+
Here is an example:
```
@@ -45,9 +49,19 @@ outputs = { self }: {
templates.rust = {
path = ./rust;
description = "A simple Rust/Cargo project";
+ welcomeText = ''
+ # Simple Rust/Cargo Template
+ ## Intended usage
+ The intended usage of this flake is...
+
+ ## More info
+ - [Rust language](https://www.rust-lang.org/)
+ - [Rust on the NixOS Wiki](https://nixos.wiki/wiki/Rust)
+ - ...
+ '';
};
- templates.defaultTemplate = self.templates.rust;
+ templates.default = self.templates.rust;
}
```
diff --git a/src/nix/flake-show.md b/src/nix/flake-show.md
index e484cf47e..f3b74285d 100644
--- a/src/nix/flake-show.md
+++ b/src/nix/flake-show.md
@@ -13,10 +13,13 @@ R""(
│ │ └───build: derivation 'patchelf-0.12.20201207.f34751b'
│ └───x86_64-linux
│ └───build: derivation 'patchelf-0.12.20201207.f34751b'
- ├───defaultPackage
- │ ├───aarch64-linux: package 'patchelf-0.12.20201207.f34751b'
- │ ├───i686-linux: package 'patchelf-0.12.20201207.f34751b'
- │ └───x86_64-linux: package 'patchelf-0.12.20201207.f34751b'
+ ├───packages
+ │ ├───aarch64-linux
+ │ │ └───default: package 'patchelf-0.12.20201207.f34751b'
+ │ ├───i686-linux
+ │ │ └───default: package 'patchelf-0.12.20201207.f34751b'
+ │ └───x86_64-linux
+ │ └───default: package 'patchelf-0.12.20201207.f34751b'
├───hydraJobs
│ ├───build
│ │ ├───aarch64-linux: derivation 'patchelf-0.12.20201207.f34751b'
diff --git a/src/nix/flake.cc b/src/nix/flake.cc
index 4bc79820c..a876bb3af 100644
--- a/src/nix/flake.cc
+++ b/src/nix/flake.cc
@@ -13,6 +13,7 @@
#include "registry.hh"
#include "json.hh"
#include "eval-cache.hh"
+#include "markdown.hh"
#include <nlohmann/json.hpp>
#include <queue>
@@ -326,7 +327,7 @@ struct CmdFlakeCheck : FlakeCommand
if (!drvInfo)
throw Error("flake attribute '%s' is not a derivation", attrPath);
// FIXME: check meta attributes
- return std::make_optional(store->parseStorePath(drvInfo->queryDrvPath()));
+ return drvInfo->queryDrvPath();
} catch (Error & e) {
e.addTrace(pos, hintfmt("while checking the derivation '%s'", attrPath));
reportError(e);
@@ -462,7 +463,7 @@ struct CmdFlakeCheck : FlakeCommand
for (auto & attr : *v.attrs) {
std::string name(attr.name);
- if (name != "path" && name != "description")
+ if (name != "path" && name != "description" && name != "welcomeText")
throw Error("template '%s' has unsupported attribute '%s'", attrPath, name);
}
} catch (Error & e) {
@@ -500,6 +501,18 @@ struct CmdFlakeCheck : FlakeCommand
state->forceValue(vOutput, pos);
+ std::string_view replacement =
+ name == "defaultPackage" ? "packages.<system>.default" :
+ name == "defaultApps" ? "apps.<system>.default" :
+ name == "defaultTemplate" ? "templates.default" :
+ name == "defaultBundler" ? "bundlers.<system>.default" :
+ name == "overlay" ? "overlays.default" :
+ name == "devShell" ? "devShells.<system>.default" :
+ name == "nixosModule" ? "nixosModules.default" :
+ "";
+ if (replacement != "")
+ warn("flake output attribute '%s' is deprecated; use '%s' instead", name, replacement);
+
if (name == "checks") {
state->forceAttrs(vOutput, pos);
for (auto & attr : *vOutput.attrs) {
@@ -649,12 +662,14 @@ struct CmdFlakeCheck : FlakeCommand
}
};
+static Strings defaultTemplateAttrPathsPrefixes{"templates."};
+static Strings defaultTemplateAttrPaths = {"templates.default", "defaultTemplate"};
+
struct CmdFlakeInitCommon : virtual Args, EvalCommand
{
std::string templateUrl = "templates";
Path destDir;
- const Strings attrsPathPrefixes{"templates."};
const LockFlags lockFlags{ .writeLockFile = false };
CmdFlakeInitCommon()
@@ -669,8 +684,8 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand
completeFlakeRefWithFragment(
getEvalState(),
lockFlags,
- attrsPathPrefixes,
- {"defaultTemplate"},
+ defaultTemplateAttrPathsPrefixes,
+ defaultTemplateAttrPaths,
prefix);
}}
});
@@ -685,15 +700,21 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand
auto [templateFlakeRef, templateName] = parseFlakeRefWithFragment(templateUrl, absPath("."));
auto installable = InstallableFlake(nullptr,
- evalState, std::move(templateFlakeRef),
- Strings{templateName == "" ? "defaultTemplate" : templateName},
- Strings(attrsPathPrefixes), lockFlags);
+ evalState, std::move(templateFlakeRef), templateName,
+ defaultTemplateAttrPaths,
+ defaultTemplateAttrPathsPrefixes,
+ lockFlags);
auto [cursor, attrPath] = installable.getCursor(*evalState);
- auto templateDir = cursor->getAttr("path")->getString();
+ auto templateDirAttr = cursor->getAttr("path");
+ auto templateDir = templateDirAttr->getString();
- assert(store->isInStore(templateDir));
+ if (!store->isInStore(templateDir))
+ throw TypeError(
+ "'%s' was not found in the Nix store\n"
+ "If you've set '%s' to a string, try using a path instead.",
+ templateDir, templateDirAttr->getAttrPathStr());
std::vector<Path> files;
@@ -728,6 +749,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand
else
throw Error("file '%s' has unsupported type", from2);
files.push_back(to2);
+ notice("wrote: %s", to2);
}
};
@@ -738,6 +760,11 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand
for (auto & s : files) args.push_back(s);
runProgram("git", true, args);
}
+ auto welcomeText = cursor->maybeGetAttr("welcomeText");
+ if (welcomeText) {
+ notice("\n");
+ notice(renderMarkdownToTerminal(welcomeText->getString()));
+ }
}
};
diff --git a/src/nix/flake.md b/src/nix/flake.md
index accddd436..d59915eeb 100644
--- a/src/nix/flake.md
+++ b/src/nix/flake.md
@@ -209,6 +209,38 @@ Currently the `type` attribute can be one of the following:
* `github:edolstra/dwarffs/unstable`
* `github:edolstra/dwarffs/d3f2baba8f425779026c6ec04021b2e927f61e31`
+* `sourcehut`: Similar to `github`, is a more efficient way to fetch
+ SourceHut repositories. The following attributes are required:
+
+ * `owner`: The owner of the repository (including leading `~`).
+
+ * `repo`: The name of the repository.
+
+ Like `github`, these are downloaded as tarball archives.
+
+ The URL syntax for `sourcehut` flakes is:
+
+ `sourcehut:<owner>/<repo>(/<rev-or-ref>)?(\?<params>)?`
+
+ `<rev-or-ref>` works the same as `github`. Either a branch or tag name
+ (`ref`), or a commit hash (`rev`) can be specified.
+
+ Since SourceHut allows for self-hosting, you can specify `host` as
+ a parameter, to point to any instances other than `git.sr.ht`.
+
+ Currently, `ref` name resolution only works for Git repositories.
+ You can refer to Mercurial repositories by simply changing `host` to
+ `hg.sr.ht` (or any other Mercurial instance). With the caveat
+ that you must explicitly specify a commit hash (`rev`).
+
+ Some examples:
+
+ * `sourcehut:~misterio/nix-colors`
+ * `sourcehut:~misterio/nix-colors/main`
+ * `sourcehut:~misterio/nix-colors?host=git.example.org`
+ * `sourcehut:~misterio/nix-colors/182b4b8709b8ffe4e9774a4c5d6877bf6bb9a21c`
+ * `sourcehut:~misterio/nix-colors/21c1a380a6915d890d408e9f22203436a35bb2de?host=hg.sr.ht`
+
* `indirect`: Indirections through the flake registry. These have the
form
@@ -236,7 +268,7 @@ derivation):
outputs = { self, nixpkgs }: {
- defaultPackage.x86_64-linux =
+ packages.x86_64-linux.default =
# Notice the reference to nixpkgs here.
with import nixpkgs { system = "x86_64-linux"; };
stdenv.mkDerivation {
diff --git a/src/nix/hash.cc b/src/nix/hash.cc
index 4535e4ab0..60d9593a7 100644
--- a/src/nix/hash.cc
+++ b/src/nix/hash.cc
@@ -177,7 +177,7 @@ static int compatNixHash(int argc, char * * argv)
else if (*arg == "--base32") base32 = true;
else if (*arg == "--truncate") truncate = true;
else if (*arg == "--type") {
- string s = getArg(*arg, arg, end);
+ std::string s = getArg(*arg, arg, end);
ht = parseHashType(s);
}
else if (*arg == "--to-base16") op = opTo16;
diff --git a/src/nix/log.cc b/src/nix/log.cc
index fd3c1d787..72d02ef11 100644
--- a/src/nix/log.cc
+++ b/src/nix/log.cc
@@ -2,6 +2,7 @@
#include "common-args.hh"
#include "shared.hh"
#include "store-api.hh"
+#include "log-store.hh"
#include "progress-bar.hh"
using namespace nix;
@@ -34,17 +35,24 @@ struct CmdLog : InstallableCommand
RunPager pager;
for (auto & sub : subs) {
+ auto * logSubP = dynamic_cast<LogStore *>(&*sub);
+ if (!logSubP) {
+ printInfo("Skipped '%s' which does not support retrieving build logs", sub->getUri());
+ continue;
+ }
+ auto & logSub = *logSubP;
+
auto log = std::visit(overloaded {
[&](const DerivedPath::Opaque & bo) {
- return sub->getBuildLog(bo.path);
+ return logSub.getBuildLog(bo.path);
},
[&](const DerivedPath::Built & bfd) {
- return sub->getBuildLog(bfd.drvPath);
+ return logSub.getBuildLog(bfd.drvPath);
},
}, b.raw());
if (!log) continue;
stopProgressBar();
- printInfo("got build log for '%s' from '%s'", installable->what(), sub->getUri());
+ printInfo("got build log for '%s' from '%s'", installable->what(), logSub.getUri());
std::cout << *log;
return;
}
diff --git a/src/nix/main.cc b/src/nix/main.cc
index b923f2535..6198681e7 100644
--- a/src/nix/main.cc
+++ b/src/nix/main.cc
@@ -117,7 +117,7 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs
{"hash-path", {"hash", "path"}},
{"ls-nar", {"nar", "ls"}},
{"ls-store", {"store", "ls"}},
- {"make-content-addressable", {"store", "make-content-addressable"}},
+ {"make-content-addressable", {"store", "make-content-addressed"}},
{"optimise-store", {"store", "optimise"}},
{"ping-store", {"store", "ping"}},
{"sign-paths", {"store", "sign"}},
@@ -289,6 +289,7 @@ void mainWrapped(int argc, char * * argv)
}
if (argc == 2 && std::string(argv[1]) == "__dump-builtins") {
+ settings.experimentalFeatures = {Xp::Flakes, Xp::FetchClosure};
evalSettings.pureEval = false;
EvalState state({}, openStore("dummy://"));
auto res = nlohmann::json::object();
diff --git a/src/nix/make-content-addressable.cc b/src/nix/make-content-addressable.cc
deleted file mode 100644
index 2e75a3b61..000000000
--- a/src/nix/make-content-addressable.cc
+++ /dev/null
@@ -1,102 +0,0 @@
-#include "command.hh"
-#include "store-api.hh"
-#include "references.hh"
-#include "common-args.hh"
-#include "json.hh"
-
-using namespace nix;
-
-struct CmdMakeContentAddressable : StorePathsCommand, MixJSON
-{
- CmdMakeContentAddressable()
- {
- realiseMode = Realise::Outputs;
- }
-
- std::string description() override
- {
- return "rewrite a path or closure to content-addressed form";
- }
-
- std::string doc() override
- {
- return
- #include "make-content-addressable.md"
- ;
- }
-
- void run(ref<Store> store, StorePaths && storePaths) override
- {
- auto paths = store->topoSortPaths(StorePathSet(storePaths.begin(), storePaths.end()));
-
- std::reverse(paths.begin(), paths.end());
-
- std::map<StorePath, StorePath> remappings;
-
- auto jsonRoot = json ? std::make_unique<JSONObject>(std::cout) : nullptr;
- auto jsonRewrites = json ? std::make_unique<JSONObject>(jsonRoot->object("rewrites")) : nullptr;
-
- for (auto & path : paths) {
- auto pathS = store->printStorePath(path);
- auto oldInfo = store->queryPathInfo(path);
- std::string oldHashPart(path.hashPart());
-
- StringSink sink;
- store->narFromPath(path, sink);
-
- StringMap rewrites;
-
- StorePathSet references;
- bool hasSelfReference = false;
- for (auto & ref : oldInfo->references) {
- if (ref == path)
- hasSelfReference = true;
- else {
- auto i = remappings.find(ref);
- auto replacement = i != remappings.end() ? i->second : ref;
- // FIXME: warn about unremapped paths?
- if (replacement != ref)
- rewrites.insert_or_assign(store->printStorePath(ref), store->printStorePath(replacement));
- references.insert(std::move(replacement));
- }
- }
-
- sink.s = rewriteStrings(sink.s, rewrites);
-
- HashModuloSink hashModuloSink(htSHA256, oldHashPart);
- hashModuloSink(sink.s);
-
- auto narHash = hashModuloSink.finish().first;
-
- ValidPathInfo info {
- store->makeFixedOutputPath(FileIngestionMethod::Recursive, narHash, path.name(), references, hasSelfReference),
- narHash,
- };
- info.references = std::move(references);
- if (hasSelfReference) info.references.insert(info.path);
- info.narSize = sink.s.size();
- info.ca = FixedOutputHash {
- .method = FileIngestionMethod::Recursive,
- .hash = info.narHash,
- };
-
- if (!json)
- notice("rewrote '%s' to '%s'", pathS, store->printStorePath(info.path));
-
- auto source = sinkToSource([&](Sink & nextSink) {
- RewritingSink rsink2(oldHashPart, std::string(info.path.hashPart()), nextSink);
- rsink2(sink.s);
- rsink2.flush();
- });
-
- store->addToStore(info, *source);
-
- if (json)
- jsonRewrites->attr(store->printStorePath(path), store->printStorePath(info.path));
-
- remappings.insert_or_assign(std::move(path), std::move(info.path));
- }
- }
-};
-
-static auto rCmdMakeContentAddressable = registerCommand2<CmdMakeContentAddressable>({"store", "make-content-addressable"});
diff --git a/src/nix/make-content-addressed.cc b/src/nix/make-content-addressed.cc
new file mode 100644
index 000000000..34860c38f
--- /dev/null
+++ b/src/nix/make-content-addressed.cc
@@ -0,0 +1,55 @@
+#include "command.hh"
+#include "store-api.hh"
+#include "make-content-addressed.hh"
+#include "common-args.hh"
+#include "json.hh"
+
+using namespace nix;
+
+struct CmdMakeContentAddressed : virtual CopyCommand, virtual StorePathsCommand, MixJSON
+{
+ CmdMakeContentAddressed()
+ {
+ realiseMode = Realise::Outputs;
+ }
+
+ std::string description() override
+ {
+ return "rewrite a path or closure to content-addressed form";
+ }
+
+ std::string doc() override
+ {
+ return
+ #include "make-content-addressed.md"
+ ;
+ }
+
+ void run(ref<Store> srcStore, StorePaths && storePaths) override
+ {
+ auto dstStore = dstUri.empty() ? openStore() : openStore(dstUri);
+
+ auto remappings = makeContentAddressed(*srcStore, *dstStore,
+ StorePathSet(storePaths.begin(), storePaths.end()));
+
+ if (json) {
+ JSONObject jsonRoot(std::cout);
+ JSONObject jsonRewrites(jsonRoot.object("rewrites"));
+ for (auto & path : storePaths) {
+ auto i = remappings.find(path);
+ assert(i != remappings.end());
+ jsonRewrites.attr(srcStore->printStorePath(path), srcStore->printStorePath(i->second));
+ }
+ } else {
+ for (auto & path : storePaths) {
+ auto i = remappings.find(path);
+ assert(i != remappings.end());
+ notice("rewrote '%s' to '%s'",
+ srcStore->printStorePath(path),
+ srcStore->printStorePath(i->second));
+ }
+ }
+ }
+};
+
+static auto rCmdMakeContentAddressed = registerCommand2<CmdMakeContentAddressed>({"store", "make-content-addressed"});
diff --git a/src/nix/make-content-addressable.md b/src/nix/make-content-addressed.md
index 3dd847edc..215683e6d 100644
--- a/src/nix/make-content-addressable.md
+++ b/src/nix/make-content-addressed.md
@@ -5,7 +5,7 @@ R""(
* Create a content-addressed representation of the closure of GNU Hello:
```console
- # nix store make-content-addressable -r nixpkgs#hello
+ # nix store make-content-addressed nixpkgs#hello
rewrote '/nix/store/v5sv61sszx301i0x6xysaqzla09nksnd-hello-2.10' to '/nix/store/5skmmcb9svys5lj3kbsrjg7vf2irid63-hello-2.10'
```
@@ -29,7 +29,7 @@ R""(
system closure:
```console
- # nix store make-content-addressable -r /run/current-system
+ # nix store make-content-addressed /run/current-system
```
# Description
diff --git a/src/nix/nix.md b/src/nix/nix.md
index 1dc59362d..0dacadee6 100644
--- a/src/nix/nix.md
+++ b/src/nix/nix.md
@@ -97,11 +97,9 @@ the Nix store. Here are the recognised types of installables:
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 `defaultPackage.`*system*
- (e.g. `defaultPackage.x86_64-linux`), but some subcommands have
+ 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*,
diff --git a/src/nix/path-info.cc b/src/nix/path-info.cc
index 3743d7504..d690fe594 100644
--- a/src/nix/path-info.cc
+++ b/src/nix/path-info.cc
@@ -97,7 +97,7 @@ struct CmdPathInfo : StorePathsCommand, MixJSON
for (auto & storePath : storePaths) {
auto info = store->queryPathInfo(storePath);
- auto storePathS = store->printStorePath(storePath);
+ auto storePathS = store->printStorePath(info->path);
std::cout << storePathS;
diff --git a/src/nix/prefetch.cc b/src/nix/prefetch.cc
index 094d2a519..f2dd44ba4 100644
--- a/src/nix/prefetch.cc
+++ b/src/nix/prefetch.cc
@@ -16,7 +16,7 @@ using namespace nix;
/* If ‘url’ starts with ‘mirror://’, then resolve it using the list of
mirrors defined in Nixpkgs. */
-string resolveMirrorUrl(EvalState & state, string url)
+std::string resolveMirrorUrl(EvalState & state, const std::string & url)
{
if (url.substr(0, 9) != "mirror://") return url;
@@ -38,8 +38,8 @@ string resolveMirrorUrl(EvalState & state, string url)
if (mirrorList->value->listSize() < 1)
throw Error("mirror URL '%s' did not expand to anything", url);
- string mirror(state.forceString(*mirrorList->value->listElems()[0]));
- return mirror + (hasSuffix(mirror, "/") ? "" : "/") + string(s, p + 1);
+ std::string mirror(state.forceString(*mirrorList->value->listElems()[0]));
+ return mirror + (hasSuffix(mirror, "/") ? "" : "/") + s.substr(p + 1);
}
std::tuple<StorePath, Hash> prefetchFile(
@@ -128,10 +128,10 @@ static int main_nix_prefetch_url(int argc, char * * argv)
{
{
HashType ht = htSHA256;
- std::vector<string> args;
+ std::vector<std::string> args;
bool printPath = getEnv("PRINT_PATH") == "1";
bool fromExpr = false;
- string attrPath;
+ std::string attrPath;
bool unpack = false;
bool executable = false;
std::optional<std::string> name;
@@ -147,7 +147,7 @@ static int main_nix_prefetch_url(int argc, char * * argv)
else if (*arg == "--version")
printVersion("nix-prefetch-url");
else if (*arg == "--type") {
- string s = getArg(*arg, arg, end);
+ auto s = getArg(*arg, arg, end);
ht = parseHashType(s);
}
else if (*arg == "--print-path")
@@ -186,7 +186,7 @@ static int main_nix_prefetch_url(int argc, char * * argv)
/* If -A is given, get the URL from the specified Nix
expression. */
- string url;
+ std::string url;
if (!fromExpr) {
if (args.empty())
throw UsageError("you must specify a URL");
diff --git a/src/nix/profile-list.md b/src/nix/profile-list.md
index 5c29c0b02..bdab9a208 100644
--- a/src/nix/profile-list.md
+++ b/src/nix/profile-list.md
@@ -8,7 +8,7 @@ R""(
# nix profile list
0 flake:nixpkgs#legacyPackages.x86_64-linux.spotify github:NixOS/nixpkgs/c23db78bbd474c4d0c5c3c551877523b4a50db06#legacyPackages.x86_64-linux.spotify /nix/store/akpdsid105phbbvknjsdh7hl4v3fhjkr-spotify-1.1.46.916.g416cacf1
1 flake:nixpkgs#legacyPackages.x86_64-linux.zoom-us github:NixOS/nixpkgs/c23db78bbd474c4d0c5c3c551877523b4a50db06#legacyPackages.x86_64-linux.zoom-us /nix/store/89pmjmbih5qpi7accgacd17ybpgp4xfm-zoom-us-5.4.53350.1027
- 2 flake:blender-bin#defaultPackage.x86_64-linux github:edolstra/nix-warez/d09d7eea893dcb162e89bc67f6dc1ced14abfc27?dir=blender#defaultPackage.x86_64-linux /nix/store/zfgralhqjnam662kqsgq6isjw8lhrflz-blender-bin-2.91.0
+ 2 flake:blender-bin#packages.x86_64-linux.default github:edolstra/nix-warez/d09d7eea893dcb162e89bc67f6dc1ced14abfc27?dir=blender#packages.x86_64-linux.default /nix/store/zfgralhqjnam662kqsgq6isjw8lhrflz-blender-bin-2.91.0
```
# Description
diff --git a/src/nix/profile.cc b/src/nix/profile.cc
index 9b7c999af..b151e48d6 100644
--- a/src/nix/profile.cc
+++ b/src/nix/profile.cc
@@ -61,6 +61,26 @@ struct ProfileElement
{
return std::tuple(describe(), storePaths) < std::tuple(other.describe(), other.storePaths);
}
+
+ void updateStorePaths(
+ ref<Store> evalStore,
+ ref<Store> store,
+ const BuiltPaths & builtPaths)
+ {
+ // FIXME: respect meta.outputsToInstall
+ storePaths.clear();
+ for (auto & buildable : builtPaths) {
+ std::visit(overloaded {
+ [&](const BuiltPath::Opaque & bo) {
+ storePaths.insert(bo.path);
+ },
+ [&](const BuiltPath::Built & bfd) {
+ for (auto & output : bfd.outputs)
+ storePaths.insert(output.second);
+ },
+ }, buildable.raw());
+ }
+ }
};
struct ProfileManifest
@@ -77,18 +97,30 @@ struct ProfileManifest
auto json = nlohmann::json::parse(readFile(manifestPath));
auto version = json.value("version", 0);
- if (version != 1)
- throw Error("profile manifest '%s' has unsupported version %d", manifestPath, version);
+ std::string sUrl;
+ std::string sOriginalUrl;
+ switch(version){
+ case 1:
+ sUrl = "uri";
+ sOriginalUrl = "originalUri";
+ break;
+ case 2:
+ sUrl = "url";
+ sOriginalUrl = "originalUrl";
+ break;
+ default:
+ throw Error("profile manifest '%s' has unsupported version %d", manifestPath, version);
+ }
for (auto & e : json["elements"]) {
ProfileElement element;
for (auto & p : e["storePaths"])
element.storePaths.insert(state.store->parseStorePath((std::string) p));
element.active = e["active"];
- if (e.value("uri", "") != "") {
+ if (e.value(sUrl,"") != "") {
element.source = ProfileElementSource{
- parseFlakeRef(e["originalUri"]),
- parseFlakeRef(e["uri"]),
+ parseFlakeRef(e[sOriginalUrl]),
+ parseFlakeRef(e[sUrl]),
e["attrPath"]
};
}
@@ -105,7 +137,7 @@ struct ProfileManifest
for (auto & drvInfo : drvInfos) {
ProfileElement element;
- element.storePaths = {state.store->parseStorePath(drvInfo.queryOutPath())};
+ element.storePaths = {drvInfo.queryOutPath()};
elements.emplace_back(std::move(element));
}
}
@@ -122,14 +154,14 @@ struct ProfileManifest
obj["storePaths"] = paths;
obj["active"] = element.active;
if (element.source) {
- obj["originalUri"] = element.source->originalRef.to_string();
- obj["uri"] = element.source->resolvedRef.to_string();
+ obj["originalUrl"] = element.source->originalRef.to_string();
+ obj["url"] = element.source->resolvedRef.to_string();
obj["attrPath"] = element.source->attrPath;
}
array.push_back(obj);
}
nlohmann::json json;
- json["version"] = 1;
+ json["version"] = 2;
json["elements"] = array;
return json.dump();
}
@@ -214,6 +246,16 @@ struct ProfileManifest
}
};
+static std::map<Installable *, BuiltPaths>
+builtPathsPerInstallable(
+ const std::vector<std::pair<std::shared_ptr<Installable>, BuiltPath>> & builtPaths)
+{
+ std::map<Installable *, BuiltPaths> res;
+ for (auto & [installable, builtPath] : builtPaths)
+ res[installable.get()].push_back(builtPath);
+ return res;
+}
+
struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
{
std::string description() override
@@ -232,54 +274,28 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
{
ProfileManifest manifest(*getEvalState(), *profile);
- std::vector<DerivedPath> pathsToBuild;
+ auto builtPaths = builtPathsPerInstallable(
+ Installable::build2(
+ getEvalStore(), store, Realise::Outputs, installables, bmNormal));
for (auto & installable : installables) {
+ ProfileElement element;
+
if (auto installable2 = std::dynamic_pointer_cast<InstallableFlake>(installable)) {
+ // FIXME: make build() return this?
auto [attrPath, resolvedRef, drv] = installable2->toDerivation();
-
- ProfileElement element;
- if (!drv.outPath)
- throw UnimplementedError("CA derivations are not yet supported by 'nix profile'");
- element.storePaths = {*drv.outPath}; // FIXME
element.source = ProfileElementSource{
installable2->flakeRef,
resolvedRef,
attrPath,
};
+ }
- pathsToBuild.push_back(DerivedPath::Built{drv.drvPath, StringSet{drv.outputName}});
+ element.updateStorePaths(getEvalStore(), store, builtPaths[installable.get()]);
- manifest.elements.emplace_back(std::move(element));
- } else {
- auto buildables = build(getEvalStore(), store, Realise::Outputs, {installable}, bmNormal);
-
- for (auto & buildable : buildables) {
- ProfileElement element;
-
- std::visit(overloaded {
- [&](const BuiltPath::Opaque & bo) {
- pathsToBuild.push_back(bo);
- element.storePaths.insert(bo.path);
- },
- [&](const BuiltPath::Built & bfd) {
- // TODO: Why are we querying if we know the output
- // names already? Is it just to figure out what the
- // default one is?
- for (auto & output : store->queryDerivationOutputMap(bfd.drvPath)) {
- pathsToBuild.push_back(DerivedPath::Built{bfd.drvPath, {output.first}});
- element.storePaths.insert(output.second);
- }
- },
- }, buildable.raw());
-
- manifest.elements.emplace_back(std::move(element));
- }
- }
+ manifest.elements.push_back(std::move(element));
}
- store->buildPaths(pathsToBuild);
-
updateProfile(manifest.build(store));
}
};
@@ -295,7 +311,11 @@ public:
expectArgs("elements", &_matchers);
}
- typedef std::variant<size_t, Path, std::regex> Matcher;
+ struct RegexPattern {
+ std::string pattern;
+ std::regex reg;
+ };
+ typedef std::variant<size_t, Path, RegexPattern> Matcher;
std::vector<Matcher> getMatchers(ref<Store> store)
{
@@ -307,7 +327,7 @@ public:
else if (store->isStorePath(s))
res.push_back(s);
else
- res.push_back(std::regex(s, std::regex::extended | std::regex::icase));
+ res.push_back(RegexPattern{s,std::regex(s, std::regex::extended | std::regex::icase)});
}
return res;
@@ -320,9 +340,9 @@ public:
if (*n == pos) return true;
} else if (auto path = std::get_if<Path>(&matcher)) {
if (element.storePaths.count(store.parseStorePath(*path))) return true;
- } else if (auto regex = std::get_if<std::regex>(&matcher)) {
+ } else if (auto regex = std::get_if<RegexPattern>(&matcher)) {
if (element.source
- && std::regex_match(element.source->attrPath, *regex))
+ && std::regex_match(element.source->attrPath, regex->reg))
return true;
}
}
@@ -355,16 +375,30 @@ struct CmdProfileRemove : virtual EvalCommand, MixDefaultProfile, MixProfileElem
for (size_t i = 0; i < oldManifest.elements.size(); ++i) {
auto & element(oldManifest.elements[i]);
- if (!matches(*store, element, i, matchers))
+ if (!matches(*store, element, i, matchers)) {
newManifest.elements.push_back(std::move(element));
+ } else {
+ notice("removing '%s'", element.describe());
+ }
}
- // FIXME: warn about unused matchers?
-
+ auto removedCount = oldManifest.elements.size() - newManifest.elements.size();
printInfo("removed %d packages, kept %d packages",
- oldManifest.elements.size() - newManifest.elements.size(),
+ removedCount,
newManifest.elements.size());
+ if (removedCount == 0) {
+ for (auto matcher: matchers) {
+ if (const size_t * index = std::get_if<size_t>(&matcher)){
+ warn("'%d' is not a valid index", *index);
+ } else if (const Path * path = std::get_if<Path>(&matcher)){
+ warn("'%s' does not match any paths", *path);
+ } else if (const RegexPattern * regex = std::get_if<RegexPattern>(&matcher)){
+ warn("'%s' does not match any packages", regex->pattern);
+ }
+ }
+ warn ("Use 'nix profile list' to see the current profile.");
+ }
updateProfile(newManifest.build(store));
}
};
@@ -389,47 +423,71 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf
auto matchers = getMatchers(store);
- // FIXME: code duplication
- std::vector<DerivedPath> pathsToBuild;
+ std::vector<std::shared_ptr<Installable>> installables;
+ std::vector<size_t> indices;
+
+ auto upgradedCount = 0;
for (size_t i = 0; i < manifest.elements.size(); ++i) {
auto & element(manifest.elements[i]);
if (element.source
- && !element.source->originalRef.input.isImmutable()
+ && !element.source->originalRef.input.isLocked()
&& matches(*store, element, i, matchers))
{
+ upgradedCount++;
+
Activity act(*logger, lvlChatty, actUnknown,
fmt("checking '%s' for updates", element.source->attrPath));
- InstallableFlake installable(
+ auto installable = std::make_shared<InstallableFlake>(
this,
getEvalState(),
FlakeRef(element.source->originalRef),
- {element.source->attrPath},
- {},
+ "",
+ Strings{element.source->attrPath},
+ Strings{},
lockFlags);
- auto [attrPath, resolvedRef, drv] = installable.toDerivation();
+ auto [attrPath, resolvedRef, drv] = installable->toDerivation();
if (element.source->resolvedRef == resolvedRef) continue;
printInfo("upgrading '%s' from flake '%s' to '%s'",
element.source->attrPath, element.source->resolvedRef, resolvedRef);
- if (!drv.outPath)
- throw UnimplementedError("CA derivations are not yet supported by 'nix profile'");
- element.storePaths = {*drv.outPath}; // FIXME
element.source = ProfileElementSource{
- installable.flakeRef,
+ installable->flakeRef,
resolvedRef,
attrPath,
};
- pathsToBuild.push_back(DerivedPath::Built{drv.drvPath, {drv.outputName}});
+ installables.push_back(installable);
+ indices.push_back(i);
}
}
- store->buildPaths(pathsToBuild);
+ if (upgradedCount == 0) {
+ for (auto & matcher : matchers) {
+ if (const size_t * index = std::get_if<size_t>(&matcher)){
+ warn("'%d' is not a valid index", *index);
+ } else if (const Path * path = std::get_if<Path>(&matcher)){
+ warn("'%s' does not match any paths", *path);
+ } else if (const RegexPattern * regex = std::get_if<RegexPattern>(&matcher)){
+ warn("'%s' does not match any packages", regex->pattern);
+ }
+ }
+ warn ("Use 'nix profile list' to see the current profile.");
+ }
+
+ auto builtPaths = builtPathsPerInstallable(
+ Installable::build2(
+ getEvalStore(), store, Realise::Outputs, installables, bmNormal));
+
+ 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()]);
+ }
updateProfile(manifest.build(store));
}
diff --git a/src/nix/profile.md b/src/nix/profile.md
index d3ddcd3d1..8dade051d 100644
--- a/src/nix/profile.md
+++ b/src/nix/profile.md
@@ -70,7 +70,7 @@ are installed in this version of the profile. It looks like this:
{
"active": true,
"attrPath": "legacyPackages.x86_64-linux.zoom-us",
- "originalUri": "flake:nixpkgs",
+ "originalUrl": "flake:nixpkgs",
"storePaths": [
"/nix/store/wbhg2ga8f3h87s9h5k0slxk0m81m4cxl-zoom-us-5.3.469451.0927"
],
@@ -84,11 +84,11 @@ are installed in this version of the profile. It looks like this:
Each object in the array `elements` denotes an installed package and
has the following fields:
-* `originalUri`: The [flake reference](./nix3-flake.md) specified by
+* `originalUrl`: The [flake reference](./nix3-flake.md) specified by
the user at the time of installation (e.g. `nixpkgs`). This is also
the flake reference that will be used by `nix profile upgrade`.
-* `uri`: The immutable flake reference to which `originalUri`
+* `uri`: The immutable flake reference to which `originalUrl`
resolved.
* `attrPath`: The flake output attribute that provided this
@@ -96,7 +96,7 @@ has the following fields:
user specified, but the one resulting from applying the default
attribute paths and prefixes; for instance, `hello` might resolve to
`packages.x86_64-linux.hello` and the empty string to
- `defaultPackage.x86_64-linux`.
+ `packages.x86_64-linux.default`.
* `storePath`: The paths in the Nix store containing the package.
diff --git a/src/nix/run.cc b/src/nix/run.cc
index bae64ed39..25a8fa8d3 100644
--- a/src/nix/run.cc
+++ b/src/nix/run.cc
@@ -38,9 +38,12 @@ void runProgramInStore(ref<Store> store,
unshare(CLONE_NEWUSER) doesn't work in a multithreaded program
(which "nix" is), so we exec() a single-threaded helper program
(chrootHelper() below) to do the work. */
- auto store2 = store.dynamic_pointer_cast<LocalStore>();
+ auto store2 = store.dynamic_pointer_cast<LocalFSStore>();
- if (store2 && store->storeDir != store2->getRealStoreDir()) {
+ if (!store2)
+ throw Error("store '%s' is not a local store so it does not support command execution", store->getUri());
+
+ if (store->storeDir != store2->getRealStoreDir()) {
Strings helperArgs = { chrootHelperName, store->storeDir, store2->getRealStoreDir(), program };
for (auto & arg : args) helperArgs.push_back(arg);
@@ -91,7 +94,7 @@ struct CmdShell : InstallablesCommand, MixEnvironment
void run(ref<Store> store) override
{
- auto outPaths = toStorePaths(getEvalStore(), store, Realise::Outputs, OperateOn::Output, installables);
+ auto outPaths = Installable::toStorePaths(getEvalStore(), store, Realise::Outputs, OperateOn::Output, installables);
auto accessor = store->getFSAccessor();
@@ -158,7 +161,10 @@ struct CmdRun : InstallableCommand
Strings getDefaultFlakeAttrPaths() override
{
- Strings res{"defaultApp." + settings.thisSystem.get()};
+ Strings res{
+ "apps." + settings.thisSystem.get() + ".default",
+ "defaultApp." + settings.thisSystem.get(),
+ };
for (auto & s : SourceExprCommand::getDefaultFlakeAttrPaths())
res.push_back(s);
return res;
@@ -176,6 +182,7 @@ struct CmdRun : InstallableCommand
{
auto state = getEvalState();
+ lockFlags.applyNixConfig = true;
auto app = installable->toApp(*state).resolve(getEvalStore(), store);
Strings allArgs{app.program};
diff --git a/src/nix/run.md b/src/nix/run.md
index cd3b978c0..a0f362076 100644
--- a/src/nix/run.md
+++ b/src/nix/run.md
@@ -58,9 +58,9 @@ For instance, if `name` is set to `hello-1.10`, `nix run` will run
If no flake output attribute is given, `nix run` tries the following
flake output attributes:
-* `defaultApp.<system>`
+* `apps.<system>.default`
-* `defaultPackage.<system>`
+* `packages.<system>.default`
If an attribute *name* is given, `nix run` tries the following flake
output attributes:
@@ -74,7 +74,7 @@ output attributes:
# Apps
An app is specified by a flake output attribute named
-`apps.<system>.<name>` or `defaultApp.<system>`. It looks like this:
+`apps.<system>.<name>`. It looks like this:
```nix
apps.x86_64-linux.blender_2_79 = {
diff --git a/src/nix/show-derivation.cc b/src/nix/show-derivation.cc
index c614be68d..fb46b4dbf 100644
--- a/src/nix/show-derivation.cc
+++ b/src/nix/show-derivation.cc
@@ -40,7 +40,7 @@ struct CmdShowDerivation : InstallablesCommand
void run(ref<Store> store) override
{
- auto drvPaths = toDerivations(store, installables, true);
+ auto drvPaths = Installable::toDerivations(store, installables, true);
if (recursive) {
StorePathSet closure;
@@ -65,19 +65,23 @@ struct CmdShowDerivation : InstallablesCommand
auto & outputName = _outputName; // work around clang bug
auto outputObj { outputsObj.object(outputName) };
std::visit(overloaded {
- [&](const DerivationOutputInputAddressed & doi) {
+ [&](const DerivationOutput::InputAddressed & doi) {
outputObj.attr("path", store->printStorePath(doi.path));
},
- [&](const DerivationOutputCAFixed & dof) {
+ [&](const DerivationOutput::CAFixed & dof) {
outputObj.attr("path", store->printStorePath(dof.path(*store, drv.name, outputName)));
outputObj.attr("hashAlgo", dof.hash.printMethodAlgo());
outputObj.attr("hash", dof.hash.hash.to_string(Base16, false));
},
- [&](const DerivationOutputCAFloating & dof) {
+ [&](const DerivationOutput::CAFloating & dof) {
outputObj.attr("hashAlgo", makeFileIngestionPrefix(dof.method) + printHashType(dof.hashType));
},
- [&](const DerivationOutputDeferred &) {},
- }, output.output);
+ [&](const DerivationOutput::Deferred &) {},
+ [&](const DerivationOutput::Impure & doi) {
+ outputObj.attr("hashAlgo", makeFileIngestionPrefix(doi.method) + printHashType(doi.hashType));
+ outputObj.attr("impure", true);
+ },
+ }, output.raw());
}
}
diff --git a/src/nix/store-copy-log.cc b/src/nix/store-copy-log.cc
index 079cd6b3e..2e288f743 100644
--- a/src/nix/store-copy-log.cc
+++ b/src/nix/store-copy-log.cc
@@ -1,6 +1,8 @@
#include "command.hh"
#include "shared.hh"
#include "store-api.hh"
+#include "store-cast.hh"
+#include "log-store.hh"
#include "sync.hh"
#include "thread-pool.hh"
@@ -26,7 +28,10 @@ struct CmdCopyLog : virtual CopyCommand, virtual InstallablesCommand
void run(ref<Store> srcStore) override
{
+ auto & srcLogStore = require<LogStore>(*srcStore);
+
auto dstStore = getDstStore();
+ auto & dstLogStore = require<LogStore>(*dstStore);
StorePathSet drvPaths;
@@ -35,8 +40,8 @@ struct CmdCopyLog : virtual CopyCommand, virtual InstallablesCommand
drvPaths.insert(drvPath);
for (auto & drvPath : drvPaths) {
- if (auto log = srcStore->getBuildLog(drvPath))
- dstStore->addBuildLog(drvPath, *log);
+ if (auto log = srcLogStore.getBuildLog(drvPath))
+ dstLogStore.addBuildLog(drvPath, *log);
else
throw Error("build log for '%s' is not available", srcStore->printStorePath(drvPath));
}
diff --git a/src/nix/store-delete.cc b/src/nix/store-delete.cc
index e4a3cb554..ca43f1530 100644
--- a/src/nix/store-delete.cc
+++ b/src/nix/store-delete.cc
@@ -2,6 +2,8 @@
#include "common-args.hh"
#include "shared.hh"
#include "store-api.hh"
+#include "store-cast.hh"
+#include "gc-store.hh"
using namespace nix;
@@ -32,12 +34,14 @@ struct CmdStoreDelete : StorePathsCommand
void run(ref<Store> store, std::vector<StorePath> && storePaths) override
{
+ auto & gcStore = require<GcStore>(*store);
+
for (auto & path : storePaths)
options.pathsToDelete.insert(path);
GCResults results;
PrintFreed freed(true, results);
- store->collectGarbage(options, results);
+ gcStore.collectGarbage(options, results);
}
};
diff --git a/src/nix/store-gc.cc b/src/nix/store-gc.cc
index a2d74066e..8b9b5d164 100644
--- a/src/nix/store-gc.cc
+++ b/src/nix/store-gc.cc
@@ -2,6 +2,8 @@
#include "common-args.hh"
#include "shared.hh"
#include "store-api.hh"
+#include "store-cast.hh"
+#include "gc-store.hh"
using namespace nix;
@@ -33,10 +35,12 @@ struct CmdStoreGC : StoreCommand, MixDryRun
void run(ref<Store> store) override
{
+ auto & gcStore = require<GcStore>(*store);
+
options.action = dryRun ? GCOptions::gcReturnDead : GCOptions::gcDeleteDead;
GCResults results;
PrintFreed freed(options.action == GCOptions::gcDeleteDead, results);
- store->collectGarbage(options, results);
+ gcStore.collectGarbage(options, results);
}
};
diff --git a/src/nix/why-depends.cc b/src/nix/why-depends.cc
index 657df30d7..1d9ab28ba 100644
--- a/src/nix/why-depends.cc
+++ b/src/nix/why-depends.cc
@@ -82,9 +82,9 @@ struct CmdWhyDepends : SourceExprCommand
void run(ref<Store> store) override
{
auto package = parseInstallable(store, _package);
- auto packagePath = toStorePath(getEvalStore(), store, Realise::Outputs, operateOn, package);
+ auto packagePath = Installable::toStorePath(getEvalStore(), store, Realise::Outputs, operateOn, package);
auto dependency = parseInstallable(store, _dependency);
- auto dependencyPath = toStorePath(getEvalStore(), store, Realise::Derivation, operateOn, dependency);
+ auto dependencyPath = Installable::toStorePath(getEvalStore(), store, Realise::Derivation, operateOn, dependency);
auto dependencyPathHash = dependencyPath.hashPart();
StorePathSet closure;
@@ -157,11 +157,11 @@ struct CmdWhyDepends : SourceExprCommand
closure (i.e., that have a non-infinite distance to
'dependency'). Print every edge on a path between `package`
and `dependency`. */
- std::function<void(Node &, const string &, const string &)> printNode;
+ std::function<void(Node &, const std::string &, const std::string &)> printNode;
struct BailOut { };
- printNode = [&](Node & node, const string & firstPad, const string & tailPad) {
+ printNode = [&](Node & node, const std::string & firstPad, const std::string & tailPad) {
auto pathS = store->printStorePath(node.path);
assert(node.dist != inf);
@@ -171,12 +171,6 @@ struct CmdWhyDepends : SourceExprCommand
node.visited ? "\e[38;5;244m" : "",
firstPad != "" ? "→ " : "",
pathS);
- } else {
- logger->cout("%s%s%s%s" ANSI_NORMAL,
- firstPad,
- node.visited ? "\e[38;5;244m" : "",
- firstPad != "" ? treeLast : "",
- pathS);
}
if (node.path == dependencyPath && !all
@@ -184,7 +178,7 @@ struct CmdWhyDepends : SourceExprCommand
throw BailOut();
if (node.visited) return;
- node.visited = true;
+ if (precise) node.visited = true;
/* Sort the references by distance to `dependency` to
ensure that the shortest path is printed first. */
@@ -267,6 +261,16 @@ struct CmdWhyDepends : SourceExprCommand
if (!all) break;
}
+ if (!precise) {
+ auto pathS = store->printStorePath(ref.second->path);
+ logger->cout("%s%s%s%s" ANSI_NORMAL,
+ firstPad,
+ ref.second->visited ? "\e[38;5;244m" : "",
+ last ? treeLast : treeConn,
+ pathS);
+ node.visited = true;
+ }
+
printNode(*ref.second,
tailPad + (last ? treeNull : treeLine),
tailPad + (last ? treeNull : treeLine));
@@ -275,6 +279,9 @@ struct CmdWhyDepends : SourceExprCommand
RunPager pager;
try {
+ if (!precise) {
+ logger->cout("%s", store->printStorePath(graph.at(packagePath).path));
+ }
printNode(graph.at(packagePath), "", "");
} catch (BailOut & ) { }
}