forked from lix-project/lix
Merge remote-tracking branch 'tweag/flake-add' into flakes
This commit is contained in:
commit
42be60c6af
|
@ -12,9 +12,14 @@
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
Path getUserRegistryPath()
|
||||||
|
{
|
||||||
|
return getHome() + "/.config/nix/registry.json";
|
||||||
|
}
|
||||||
|
|
||||||
/* Read the registry or a lock file. (Currently they have an identical
|
/* Read the registry or a lock file. (Currently they have an identical
|
||||||
format. */
|
format. */
|
||||||
static std::unique_ptr<FlakeRegistry> readRegistry(const Path & path)
|
std::unique_ptr<FlakeRegistry> readRegistry(const Path & path)
|
||||||
{
|
{
|
||||||
auto registry = std::make_unique<FlakeRegistry>();
|
auto registry = std::make_unique<FlakeRegistry>();
|
||||||
|
|
||||||
|
@ -40,7 +45,7 @@ void writeRegistry(FlakeRegistry registry, Path path)
|
||||||
json["version"] = 1;
|
json["version"] = 1;
|
||||||
json["flakes"] = {};
|
json["flakes"] = {};
|
||||||
for (auto elem : registry.entries) {
|
for (auto elem : registry.entries) {
|
||||||
json["flakes"][elem.first] = elem.second.ref.to_string();
|
json["flakes"][elem.first] = { {"uri", elem.second.ref.to_string()} };
|
||||||
}
|
}
|
||||||
writeFile(path, json.dump(4)); // The '4' is the number of spaces used in the indentation in the json file.
|
writeFile(path, json.dump(4)); // The '4' is the number of spaces used in the indentation in the json file.
|
||||||
}
|
}
|
||||||
|
@ -183,8 +188,8 @@ Flake getFlake(EvalState & state, const FlakeRef & flakeRef)
|
||||||
if (std::get_if<FlakeRef::IsGitHub>(&newFlakeRef.data)) {
|
if (std::get_if<FlakeRef::IsGitHub>(&newFlakeRef.data)) {
|
||||||
FlakeSourceInfo srcInfo = fetchFlake(state, newFlakeRef);
|
FlakeSourceInfo srcInfo = fetchFlake(state, newFlakeRef);
|
||||||
if (srcInfo.rev) {
|
if (srcInfo.rev) {
|
||||||
std::string uri = flakeRef.to_string();
|
std::string uri = flakeRef.baseRef().to_string();
|
||||||
newFlakeRef = FlakeRef(uri + "/" + srcInfo.rev->to_string());
|
newFlakeRef = FlakeRef(uri + "/" + srcInfo.rev->to_string(Base16, false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,14 +14,19 @@ struct FlakeRegistry
|
||||||
{
|
{
|
||||||
FlakeRef ref;
|
FlakeRef ref;
|
||||||
Entry(const FlakeRef & flakeRef) : ref(flakeRef) {};
|
Entry(const FlakeRef & flakeRef) : ref(flakeRef) {};
|
||||||
|
Entry operator=(const Entry & entry) { return Entry(entry.ref); }
|
||||||
};
|
};
|
||||||
std::map<FlakeId, Entry> entries;
|
std::map<FlakeId, Entry> entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Path getUserRegistryPath();
|
||||||
|
|
||||||
Value * makeFlakeRegistryValue(EvalState & state);
|
Value * makeFlakeRegistryValue(EvalState & state);
|
||||||
|
|
||||||
Value * makeFlakeValue(EvalState & state, std::string flakeUri, Value & v);
|
Value * makeFlakeValue(EvalState & state, std::string flakeUri, Value & v);
|
||||||
|
|
||||||
|
std::unique_ptr<FlakeRegistry> readRegistry(const Path &);
|
||||||
|
|
||||||
void writeRegistry(FlakeRegistry, Path);
|
void writeRegistry(FlakeRegistry, Path);
|
||||||
|
|
||||||
struct Flake
|
struct Flake
|
||||||
|
|
|
@ -152,4 +152,19 @@ bool FlakeRef::isImmutable() const
|
||||||
else abort();
|
else abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FlakeRef FlakeRef::baseRef() const // Removes the ref and rev from a FlakeRef.
|
||||||
|
{
|
||||||
|
FlakeRef result(*this);
|
||||||
|
if (auto refData = std::get_if<FlakeRef::IsGitHub>(&result.data)) {
|
||||||
|
refData->ref = std::nullopt;
|
||||||
|
refData->rev = std::nullopt;
|
||||||
|
} else if (auto refData = std::get_if<FlakeRef::IsGit>(&result.data)) {
|
||||||
|
refData->ref = std::nullopt;
|
||||||
|
refData->rev = std::nullopt;
|
||||||
|
} else if (auto refData = std::get_if<FlakeRef::IsGit>(&result.data)) {
|
||||||
|
refData->ref = std::nullopt;
|
||||||
|
refData->rev = std::nullopt;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,6 +153,7 @@ struct FlakeRef
|
||||||
/* Check whether this is an "immutable" flake reference, that is,
|
/* Check whether this is an "immutable" flake reference, that is,
|
||||||
one that contains a commit hash or content hash. */
|
one that contains a commit hash or content hash. */
|
||||||
bool isImmutable() const;
|
bool isImmutable() const;
|
||||||
};
|
|
||||||
|
|
||||||
|
FlakeRef baseRef() const;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ struct GitRepoCommand : virtual Args
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FlakeCommand : virtual Args, StoreCommand, MixEvalArgs
|
struct FlakeCommand : virtual Args
|
||||||
{
|
{
|
||||||
std::string flakeUri;
|
std::string flakeUri;
|
||||||
|
|
||||||
|
|
113
src/nix/flake.cc
113
src/nix/flake.cc
|
@ -50,17 +50,12 @@ struct CmdFlakeUpdate : StoreCommand, GitRepoCommand, MixEvalArgs
|
||||||
{
|
{
|
||||||
auto evalState = std::make_shared<EvalState>(searchPath, store);
|
auto evalState = std::make_shared<EvalState>(searchPath, store);
|
||||||
|
|
||||||
if (flakeUri == "") flakeUri = absPath("./flake.nix");
|
if (gitPath == "") gitPath = absPath(".");
|
||||||
int result = updateLockFile(*evalState, flakeUri);
|
updateLockFile(*evalState, gitPath);
|
||||||
if (result == 1) {
|
|
||||||
std::cout << "You can only update local flakes, not flakes on GitHub.\n";
|
|
||||||
} else if (result == 2) {
|
|
||||||
std::cout << "You can only update local flakes, not flakes through their FlakeId.\n";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmdFlakeInfo : FlakeCommand, MixJSON
|
struct CmdFlakeInfo : FlakeCommand, MixJSON, MixEvalArgs, StoreCommand
|
||||||
{
|
{
|
||||||
std::string name() override
|
std::string name() override
|
||||||
{
|
{
|
||||||
|
@ -88,12 +83,112 @@ struct CmdFlakeInfo : FlakeCommand, MixJSON
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CmdFlakeAdd : MixEvalArgs, Command
|
||||||
|
{
|
||||||
|
std::string flakeId;
|
||||||
|
std::string flakeUri;
|
||||||
|
|
||||||
|
std::string name() override
|
||||||
|
{
|
||||||
|
return "add";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string description() override
|
||||||
|
{
|
||||||
|
return "upsert flake in user flake registry";
|
||||||
|
}
|
||||||
|
|
||||||
|
CmdFlakeAdd()
|
||||||
|
{
|
||||||
|
expectArg("flake-id", &flakeId);
|
||||||
|
expectArg("flake-uri", &flakeUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
void run() override
|
||||||
|
{
|
||||||
|
FlakeRef newFlakeRef(flakeUri);
|
||||||
|
Path userRegistryPath = getUserRegistryPath();
|
||||||
|
auto userRegistry = readRegistry(userRegistryPath);
|
||||||
|
FlakeRegistry::Entry entry(newFlakeRef);
|
||||||
|
userRegistry->entries.erase(flakeId);
|
||||||
|
userRegistry->entries.insert_or_assign(flakeId, newFlakeRef);
|
||||||
|
writeRegistry(*userRegistry, userRegistryPath);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CmdFlakeRemove : virtual Args, MixEvalArgs, Command
|
||||||
|
{
|
||||||
|
std::string flakeId;
|
||||||
|
|
||||||
|
std::string name() override
|
||||||
|
{
|
||||||
|
return "remove";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string description() override
|
||||||
|
{
|
||||||
|
return "remove flake from user flake registry";
|
||||||
|
}
|
||||||
|
|
||||||
|
CmdFlakeRemove()
|
||||||
|
{
|
||||||
|
expectArg("flake-id", &flakeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void run() override
|
||||||
|
{
|
||||||
|
Path userRegistryPath = getUserRegistryPath();
|
||||||
|
auto userRegistry = readRegistry(userRegistryPath);
|
||||||
|
userRegistry->entries.erase(flakeId);
|
||||||
|
writeRegistry(*userRegistry, userRegistryPath);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CmdFlakePin : virtual Args, StoreCommand, MixEvalArgs
|
||||||
|
{
|
||||||
|
std::string flakeId;
|
||||||
|
|
||||||
|
std::string name() override
|
||||||
|
{
|
||||||
|
return "pin";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string description() override
|
||||||
|
{
|
||||||
|
return "pin flake require in user flake registry";
|
||||||
|
}
|
||||||
|
|
||||||
|
CmdFlakePin()
|
||||||
|
{
|
||||||
|
expectArg("flake-id", &flakeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void run(nix::ref<nix::Store> store) override
|
||||||
|
{
|
||||||
|
auto evalState = std::make_shared<EvalState>(searchPath, store);
|
||||||
|
|
||||||
|
Path userRegistryPath = getUserRegistryPath();
|
||||||
|
FlakeRegistry userRegistry = *readRegistry(userRegistryPath);
|
||||||
|
auto it = userRegistry.entries.find(flakeId);
|
||||||
|
if (it != userRegistry.entries.end()) {
|
||||||
|
FlakeRef oldRef = it->second.ref;
|
||||||
|
it->second.ref = getFlake(*evalState, oldRef).ref;
|
||||||
|
// The 'ref' in 'flake' is immutable.
|
||||||
|
writeRegistry(userRegistry, userRegistryPath);
|
||||||
|
} else
|
||||||
|
throw Error("the flake identifier '%s' does not exist in the user registry", flakeId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct CmdFlake : virtual MultiCommand, virtual Command
|
struct CmdFlake : virtual MultiCommand, virtual Command
|
||||||
{
|
{
|
||||||
CmdFlake()
|
CmdFlake()
|
||||||
: MultiCommand({make_ref<CmdFlakeList>()
|
: MultiCommand({make_ref<CmdFlakeList>()
|
||||||
|
, make_ref<CmdFlakeUpdate>()
|
||||||
, make_ref<CmdFlakeInfo>()
|
, make_ref<CmdFlakeInfo>()
|
||||||
, make_ref<CmdFlakeUpdate>()})
|
, make_ref<CmdFlakeAdd>()
|
||||||
|
, make_ref<CmdFlakeRemove>()
|
||||||
|
, make_ref<CmdFlakePin>()})
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue