forked from lix-project/lix
990b5b2dcf
This replaces 'nix-env --set'. For example: $ nix build --profile /nix/var/nix/profiles/system \ ~/Misc/eelco-configurations:nixosConfigurations.vyr.config.system.build.toplevel updates the NixOS system profile from a flake. This could have been a separate command (e.g. 'nix set-profile') but 1) '--profile' is pretty similar to '--out-link'; and 2) '--profile' could be useful for other command (like 'nix dev-shell').
126 lines
3 KiB
C++
126 lines
3 KiB
C++
#include "command.hh"
|
|
#include "store-api.hh"
|
|
#include "derivations.hh"
|
|
#include "profiles.hh"
|
|
|
|
namespace nix {
|
|
|
|
Commands * RegisterCommand::commands = nullptr;
|
|
|
|
StoreCommand::StoreCommand()
|
|
{
|
|
}
|
|
|
|
ref<Store> StoreCommand::getStore()
|
|
{
|
|
if (!_store)
|
|
_store = createStore();
|
|
return ref<Store>(_store);
|
|
}
|
|
|
|
ref<Store> StoreCommand::createStore()
|
|
{
|
|
return openStore();
|
|
}
|
|
|
|
void StoreCommand::run()
|
|
{
|
|
run(getStore());
|
|
}
|
|
|
|
StorePathsCommand::StorePathsCommand(bool recursive)
|
|
: recursive(recursive)
|
|
{
|
|
if (recursive)
|
|
mkFlag()
|
|
.longName("no-recursive")
|
|
.description("apply operation to specified paths only")
|
|
.set(&this->recursive, false);
|
|
else
|
|
mkFlag()
|
|
.longName("recursive")
|
|
.shortName('r')
|
|
.description("apply operation to closure of the specified paths")
|
|
.set(&this->recursive, true);
|
|
|
|
mkFlag(0, "all", "apply operation to the entire store", &all);
|
|
}
|
|
|
|
void StorePathsCommand::run(ref<Store> store)
|
|
{
|
|
Paths storePaths;
|
|
|
|
if (all) {
|
|
if (installables.size())
|
|
throw UsageError("'--all' does not expect arguments");
|
|
for (auto & p : store->queryAllValidPaths())
|
|
storePaths.push_back(p);
|
|
}
|
|
|
|
else {
|
|
for (auto & p : toStorePaths(store, NoBuild, installables))
|
|
storePaths.push_back(p);
|
|
|
|
if (recursive) {
|
|
PathSet closure;
|
|
store->computeFSClosure(PathSet(storePaths.begin(), storePaths.end()),
|
|
closure, false, false);
|
|
storePaths = Paths(closure.begin(), closure.end());
|
|
}
|
|
}
|
|
|
|
run(store, storePaths);
|
|
}
|
|
|
|
void StorePathCommand::run(ref<Store> store)
|
|
{
|
|
auto storePaths = toStorePaths(store, NoBuild, installables);
|
|
|
|
if (storePaths.size() != 1)
|
|
throw UsageError("this command requires exactly one store path");
|
|
|
|
run(store, *storePaths.begin());
|
|
}
|
|
|
|
MixProfile::MixProfile()
|
|
{
|
|
mkFlag()
|
|
.longName("profile")
|
|
.description("profile to update")
|
|
.labels({"path"})
|
|
.dest(&profile);
|
|
}
|
|
|
|
void MixProfile::updateProfile(const Path & storePath)
|
|
{
|
|
if (!profile) return;
|
|
auto store = getStore().dynamic_pointer_cast<LocalFSStore>();
|
|
if (!store) throw Error("'--profile' is not supported for this Nix store");
|
|
switchLink(*profile,
|
|
createGeneration(
|
|
ref<LocalFSStore>(store),
|
|
*profile, storePath));
|
|
}
|
|
|
|
void MixProfile::updateProfile(const Buildables & buildables)
|
|
{
|
|
if (!profile) return;
|
|
|
|
std::optional<Path> result;
|
|
|
|
for (auto & buildable : buildables) {
|
|
for (auto & output : buildable.outputs) {
|
|
if (result)
|
|
throw Error("'--profile' requires that the arguments produce a single store path, but there are multiple");
|
|
result = output.second;
|
|
}
|
|
}
|
|
|
|
if (!result)
|
|
throw Error("'--profile' requires that the arguments produce a single store path, but there are none");
|
|
|
|
updateProfile(*result);
|
|
}
|
|
|
|
}
|