2020-05-15 15:38:10 +03:00
|
|
|
#include "command.hh"
|
|
|
|
#include "common-args.hh"
|
|
|
|
#include "shared.hh"
|
|
|
|
#include "eval.hh"
|
|
|
|
#include "flake/flake.hh"
|
|
|
|
#include "store-api.hh"
|
|
|
|
#include "fetchers.hh"
|
|
|
|
#include "registry.hh"
|
|
|
|
|
|
|
|
using namespace nix;
|
|
|
|
using namespace nix::flake;
|
|
|
|
|
2021-06-30 22:13:32 +03:00
|
|
|
|
|
|
|
class RegistryCommand: virtual Args
|
|
|
|
{
|
|
|
|
std::string registry_path;
|
|
|
|
|
|
|
|
std::shared_ptr<fetchers::Registry> registry;
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
RegistryCommand()
|
|
|
|
{
|
|
|
|
addFlag({
|
|
|
|
.longName = "registry",
|
|
|
|
.description = "The registry to operate on.",
|
|
|
|
.labels = {"registry"},
|
|
|
|
.handler = {®istry_path},
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
std::shared_ptr<fetchers::Registry> getRegistry() {
|
|
|
|
if (registry) return registry;
|
|
|
|
if (registry_path.empty()) {
|
|
|
|
registry = fetchers::getUserRegistry();
|
|
|
|
} else {
|
|
|
|
registry = fetchers::getCustomRegistry(registry_path);
|
|
|
|
}
|
|
|
|
return registry;
|
|
|
|
}
|
|
|
|
|
|
|
|
Path getRegistryPath() {
|
|
|
|
if (registry_path.empty()) {
|
|
|
|
return fetchers::getUserRegistryPath();
|
|
|
|
} else {
|
|
|
|
return registry_path;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-05-15 15:38:10 +03:00
|
|
|
struct CmdRegistryList : StoreCommand
|
|
|
|
{
|
|
|
|
std::string description() override
|
|
|
|
{
|
|
|
|
return "list available Nix flakes";
|
|
|
|
}
|
|
|
|
|
2020-12-08 23:57:14 +02:00
|
|
|
std::string doc() override
|
|
|
|
{
|
|
|
|
return
|
|
|
|
#include "registry-list.md"
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2020-05-15 15:38:10 +03:00
|
|
|
void run(nix::ref<nix::Store> store) override
|
|
|
|
{
|
|
|
|
using namespace fetchers;
|
|
|
|
|
|
|
|
auto registries = getRegistries(store);
|
|
|
|
|
|
|
|
for (auto & registry : registries) {
|
|
|
|
for (auto & entry : registry->entries) {
|
|
|
|
// FIXME: format nicely
|
2020-09-25 18:30:04 +03:00
|
|
|
logger->cout("%s %s %s",
|
2020-05-15 15:38:10 +03:00
|
|
|
registry->type == Registry::Flag ? "flags " :
|
|
|
|
registry->type == Registry::User ? "user " :
|
|
|
|
registry->type == Registry::System ? "system" :
|
|
|
|
"global",
|
2020-09-30 00:33:16 +03:00
|
|
|
entry.from.toURLString(),
|
|
|
|
entry.to.toURLString(attrsToQuery(entry.extraAttrs)));
|
2020-05-15 15:38:10 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-06-30 22:13:32 +03:00
|
|
|
struct CmdRegistryAdd : MixEvalArgs, Command, RegistryCommand
|
2020-05-15 15:38:10 +03:00
|
|
|
{
|
|
|
|
std::string fromUrl, toUrl;
|
|
|
|
|
|
|
|
std::string description() override
|
|
|
|
{
|
|
|
|
return "add/replace flake in user flake registry";
|
|
|
|
}
|
|
|
|
|
2020-12-08 23:57:14 +02:00
|
|
|
std::string doc() override
|
|
|
|
{
|
|
|
|
return
|
|
|
|
#include "registry-add.md"
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2020-05-15 15:38:10 +03:00
|
|
|
CmdRegistryAdd()
|
|
|
|
{
|
|
|
|
expectArg("from-url", &fromUrl);
|
|
|
|
expectArg("to-url", &toUrl);
|
|
|
|
}
|
|
|
|
|
|
|
|
void run() override
|
|
|
|
{
|
|
|
|
auto fromRef = parseFlakeRef(fromUrl);
|
|
|
|
auto toRef = parseFlakeRef(toUrl);
|
2021-06-30 22:13:32 +03:00
|
|
|
auto registry = getRegistry();
|
2020-05-15 15:38:10 +03:00
|
|
|
fetchers::Attrs extraAttrs;
|
|
|
|
if (toRef.subdir != "") extraAttrs["dir"] = toRef.subdir;
|
2021-06-30 22:13:32 +03:00
|
|
|
registry->remove(fromRef.input);
|
|
|
|
registry->add(fromRef.input, toRef.input, extraAttrs);
|
|
|
|
registry->write(getRegistryPath());
|
2020-05-15 15:38:10 +03:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-06-30 22:13:32 +03:00
|
|
|
struct CmdRegistryRemove : RegistryCommand, Command
|
2020-05-15 15:38:10 +03:00
|
|
|
{
|
|
|
|
std::string url;
|
|
|
|
|
|
|
|
std::string description() override
|
|
|
|
{
|
|
|
|
return "remove flake from user flake registry";
|
|
|
|
}
|
|
|
|
|
2020-12-08 23:57:14 +02:00
|
|
|
std::string doc() override
|
|
|
|
{
|
|
|
|
return
|
|
|
|
#include "registry-remove.md"
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2020-05-15 15:38:10 +03:00
|
|
|
CmdRegistryRemove()
|
|
|
|
{
|
|
|
|
expectArg("url", &url);
|
|
|
|
}
|
|
|
|
|
|
|
|
void run() override
|
|
|
|
{
|
2021-06-30 22:13:32 +03:00
|
|
|
auto registry = getRegistry();
|
|
|
|
registry->remove(parseFlakeRef(url).input);
|
|
|
|
registry->write(getRegistryPath());
|
2020-05-15 15:38:10 +03:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-06-30 22:13:32 +03:00
|
|
|
struct CmdRegistryPin : RegistryCommand, EvalCommand
|
2020-05-15 15:38:10 +03:00
|
|
|
{
|
|
|
|
std::string url;
|
|
|
|
|
|
|
|
std::string description() override
|
|
|
|
{
|
|
|
|
return "pin a flake to its current version in user flake registry";
|
|
|
|
}
|
|
|
|
|
2020-12-08 23:57:14 +02:00
|
|
|
std::string doc() override
|
|
|
|
{
|
|
|
|
return
|
|
|
|
#include "registry-pin.md"
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2020-05-15 15:38:10 +03:00
|
|
|
CmdRegistryPin()
|
|
|
|
{
|
|
|
|
expectArg("url", &url);
|
|
|
|
}
|
|
|
|
|
|
|
|
void run(nix::ref<nix::Store> store) override
|
|
|
|
{
|
2021-06-30 22:13:32 +03:00
|
|
|
auto registry = getRegistry();
|
2020-05-15 15:38:10 +03:00
|
|
|
auto ref = parseFlakeRef(url);
|
2021-06-30 22:13:32 +03:00
|
|
|
registry->remove(ref.input);
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
auto [tree, resolved] = ref.resolve(store).input.fetch(store);
|
2020-05-15 15:38:10 +03:00
|
|
|
fetchers::Attrs extraAttrs;
|
|
|
|
if (ref.subdir != "") extraAttrs["dir"] = ref.subdir;
|
2021-06-30 22:13:32 +03:00
|
|
|
registry->add(ref.input, resolved, extraAttrs);
|
|
|
|
registry->write(getRegistryPath());
|
2020-05-15 15:38:10 +03:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-08-17 18:44:52 +03:00
|
|
|
struct CmdRegistry : virtual NixMultiCommand
|
2020-05-15 15:38:10 +03:00
|
|
|
{
|
|
|
|
CmdRegistry()
|
|
|
|
: MultiCommand({
|
|
|
|
{"list", []() { return make_ref<CmdRegistryList>(); }},
|
|
|
|
{"add", []() { return make_ref<CmdRegistryAdd>(); }},
|
|
|
|
{"remove", []() { return make_ref<CmdRegistryRemove>(); }},
|
|
|
|
{"pin", []() { return make_ref<CmdRegistryPin>(); }},
|
|
|
|
})
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string description() override
|
|
|
|
{
|
|
|
|
return "manage the flake registry";
|
|
|
|
}
|
|
|
|
|
2020-12-08 23:57:14 +02:00
|
|
|
std::string doc() override
|
|
|
|
{
|
|
|
|
return
|
|
|
|
#include "registry.md"
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2020-05-15 15:38:10 +03:00
|
|
|
Category category() override { return catSecondary; }
|
|
|
|
|
|
|
|
void run() override
|
|
|
|
{
|
|
|
|
if (!command)
|
|
|
|
throw UsageError("'nix registry' requires a sub-command.");
|
|
|
|
command->second->prepare();
|
|
|
|
command->second->run();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-10-06 14:36:55 +03:00
|
|
|
static auto rCmdRegistry = registerCommand<CmdRegistry>("registry");
|