Merge remote-tracking branch 'tweag/flake-add' into flakes

This commit is contained in:
Eelco Dolstra 2019-03-26 12:35:27 +01:00
commit 42be60c6af
6 changed files with 136 additions and 15 deletions

View file

@ -12,9 +12,14 @@
namespace nix {
Path getUserRegistryPath()
{
return getHome() + "/.config/nix/registry.json";
}
/* Read the registry or a lock file. (Currently they have an identical
format. */
static std::unique_ptr<FlakeRegistry> readRegistry(const Path & path)
std::unique_ptr<FlakeRegistry> readRegistry(const Path & path)
{
auto registry = std::make_unique<FlakeRegistry>();
@ -40,7 +45,7 @@ void writeRegistry(FlakeRegistry registry, Path path)
json["version"] = 1;
json["flakes"] = {};
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.
}
@ -183,8 +188,8 @@ Flake getFlake(EvalState & state, const FlakeRef & flakeRef)
if (std::get_if<FlakeRef::IsGitHub>(&newFlakeRef.data)) {
FlakeSourceInfo srcInfo = fetchFlake(state, newFlakeRef);
if (srcInfo.rev) {
std::string uri = flakeRef.to_string();
newFlakeRef = FlakeRef(uri + "/" + srcInfo.rev->to_string());
std::string uri = flakeRef.baseRef().to_string();
newFlakeRef = FlakeRef(uri + "/" + srcInfo.rev->to_string(Base16, false));
}
}

View file

@ -14,14 +14,19 @@ struct FlakeRegistry
{
FlakeRef ref;
Entry(const FlakeRef & flakeRef) : ref(flakeRef) {};
Entry operator=(const Entry & entry) { return Entry(entry.ref); }
};
std::map<FlakeId, Entry> entries;
};
Path getUserRegistryPath();
Value * makeFlakeRegistryValue(EvalState & state);
Value * makeFlakeValue(EvalState & state, std::string flakeUri, Value & v);
std::unique_ptr<FlakeRegistry> readRegistry(const Path &);
void writeRegistry(FlakeRegistry, Path);
struct Flake

View file

@ -152,4 +152,19 @@ bool FlakeRef::isImmutable() const
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;
}
}

View file

@ -153,6 +153,7 @@ struct FlakeRef
/* Check whether this is an "immutable" flake reference, that is,
one that contains a commit hash or content hash. */
bool isImmutable() const;
};
FlakeRef baseRef() const;
};
}

View file

@ -44,7 +44,7 @@ struct GitRepoCommand : virtual Args
}
};
struct FlakeCommand : virtual Args, StoreCommand, MixEvalArgs
struct FlakeCommand : virtual Args
{
std::string flakeUri;

View file

@ -50,17 +50,12 @@ struct CmdFlakeUpdate : StoreCommand, GitRepoCommand, MixEvalArgs
{
auto evalState = std::make_shared<EvalState>(searchPath, store);
if (flakeUri == "") flakeUri = absPath("./flake.nix");
int result = updateLockFile(*evalState, flakeUri);
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";
}
if (gitPath == "") gitPath = absPath(".");
updateLockFile(*evalState, gitPath);
}
};
struct CmdFlakeInfo : FlakeCommand, MixJSON
struct CmdFlakeInfo : FlakeCommand, MixJSON, MixEvalArgs, StoreCommand
{
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
{
CmdFlake()
: MultiCommand({make_ref<CmdFlakeList>()
, make_ref<CmdFlakeUpdate>()
, make_ref<CmdFlakeInfo>()
, make_ref<CmdFlakeUpdate>()})
, make_ref<CmdFlakeAdd>()
, make_ref<CmdFlakeRemove>()
, make_ref<CmdFlakePin>()})
{
}