Merge pull request #2877 from NixOS/improve-flake-command

FlakeCommand improvements
This commit is contained in:
Eelco Dolstra 2019-05-22 14:08:52 +02:00 committed by GitHub
commit 3cecf3f39c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 125 additions and 92 deletions

View file

@ -482,9 +482,8 @@ ResolvedFlake resolveFlake(EvalState & state, const FlakeRef & topRef, HandleLoc
return resFlake; return resFlake;
} }
void updateLockFile(EvalState & state, const FlakeUri & flakeUri, bool recreateLockFile) void updateLockFile(EvalState & state, const FlakeRef & flakeRef, bool recreateLockFile)
{ {
FlakeRef flakeRef(flakeUri);
resolveFlake(state, flakeRef, recreateLockFile ? RecreateLockFile : UpdateLockFile); resolveFlake(state, flakeRef, recreateLockFile ? RecreateLockFile : UpdateLockFile);
} }
@ -551,10 +550,8 @@ static void prim_getFlake(EvalState & state, const Pos & pos, Value * * args, Va
static RegisterPrimOp r2("getFlake", 1, prim_getFlake); static RegisterPrimOp r2("getFlake", 1, prim_getFlake);
void gitCloneFlake (std::string flakeUri, EvalState & state, Registries registries, void gitCloneFlake(FlakeRef flakeRef, EvalState & state, Registries registries, const Path & destDir)
Path endDirectory)
{ {
FlakeRef flakeRef(flakeUri);
flakeRef = lookupFlake(state, flakeRef, registries); flakeRef = lookupFlake(state, flakeRef, registries);
std::string uri; std::string uri;
@ -576,8 +573,8 @@ void gitCloneFlake (std::string flakeUri, EvalState & state, Registries registri
} }
} }
if (endDirectory != "") if (destDir != "")
args.push_back(endDirectory); args.push_back(destDir);
runProgram("git", true, args); runProgram("git", true, args);
} }

View file

@ -64,7 +64,7 @@ typedef std::vector<std::shared_ptr<FlakeRegistry>> Registries;
Path getUserRegistryPath(); Path getUserRegistryPath();
enum HandleLockFile enum HandleLockFile : unsigned int
{ AllPure // Everything is handled 100% purely { AllPure // Everything is handled 100% purely
, TopRefUsesRegistries // The top FlakeRef uses the registries, apart from that, everything happens 100% purely , TopRefUsesRegistries // The top FlakeRef uses the registries, apart from that, everything happens 100% purely
, UpdateLockFile // Update the existing lockfile and write it to file , UpdateLockFile // Update the existing lockfile and write it to file
@ -133,7 +133,8 @@ struct ResolvedFlake
ResolvedFlake resolveFlake(EvalState &, const FlakeRef &, HandleLockFile); ResolvedFlake resolveFlake(EvalState &, const FlakeRef &, HandleLockFile);
void updateLockFile(EvalState &, const FlakeUri &, bool recreateLockFile); void updateLockFile(EvalState &, const FlakeRef & flakeRef, bool recreateLockFile);
void gitCloneFlake(FlakeRef flakeRef, EvalState &, Registries, const Path & destDir);
void gitCloneFlake (std::string flakeUri, EvalState &, Registries, Path);
} }

View file

@ -11,8 +11,8 @@ extern std::string programPath;
struct Value; struct Value;
class Bindings; class Bindings;
class EvalState; class EvalState;
class Store; class Store;
enum HandleLockFile : unsigned int;
/* A command that require a Nix store. */ /* A command that require a Nix store. */
struct StoreCommand : virtual Command struct StoreCommand : virtual Command
@ -35,26 +35,6 @@ struct Buildable
typedef std::vector<Buildable> Buildables; typedef std::vector<Buildable> Buildables;
struct GitRepoCommand : virtual Args
{
std::string gitPath = absPath(".");
GitRepoCommand ()
{
expectArg("git-path", &gitPath, true);
}
};
struct FlakeCommand : virtual Args
{
std::string flakeUri;
FlakeCommand()
{
expectArg("flake-uri", &flakeUri);
}
};
struct Installable struct Installable
{ {
virtual std::string what() = 0; virtual std::string what() = 0;
@ -72,19 +52,33 @@ struct Installable
} }
}; };
struct SourceExprCommand : virtual Args, StoreCommand, MixEvalArgs struct EvalCommand : virtual StoreCommand, MixEvalArgs
{ {
std::optional<Path> file; ref<EvalState> getEvalState();
SourceExprCommand(); private:
std::shared_ptr<EvalState> evalState;
};
struct MixFlakeOptions : virtual Args
{
bool recreateLockFile = false; bool recreateLockFile = false;
bool saveLockFile = true; bool saveLockFile = true;
bool noRegistries = false; bool useRegistries = true;
ref<EvalState> getEvalState(); MixFlakeOptions();
HandleLockFile getLockFileMode();
};
struct SourceExprCommand : virtual Args, EvalCommand, MixFlakeOptions
{
std::optional<Path> file;
SourceExprCommand();
std::vector<std::shared_ptr<Installable>> parseInstallables( std::vector<std::shared_ptr<Installable>> parseInstallables(
ref<Store> store, std::vector<std::string> ss); ref<Store> store, std::vector<std::string> ss);
@ -96,10 +90,6 @@ struct SourceExprCommand : virtual Args, StoreCommand, MixEvalArgs
{ {
return {"defaultPackage"}; return {"defaultPackage"};
} }
private:
std::shared_ptr<EvalState> evalState;
}; };
enum RealiseMode { Build, NoBuild, DryRun }; enum RealiseMode { Build, NoBuild, DryRun };

View file

@ -10,7 +10,38 @@
using namespace nix; using namespace nix;
struct CmdFlakeList : StoreCommand, MixEvalArgs class FlakeCommand : virtual Args, public EvalCommand, public MixFlakeOptions
{
std::string flakeUri = ".";
public:
FlakeCommand()
{
expectArg("flake-uri", &flakeUri, true);
}
FlakeRef getFlakeRef()
{
if (flakeUri.find('/') != std::string::npos || flakeUri == ".")
return FlakeRef(flakeUri, true);
else
return FlakeRef(flakeUri);
}
Flake getFlake()
{
auto evalState = getEvalState();
return nix::getFlake(*evalState, getFlakeRef(), useRegistries);
}
ResolvedFlake resolveFlake()
{
return nix::resolveFlake(*getEvalState(), getFlakeRef(), getLockFileMode());
}
};
struct CmdFlakeList : EvalCommand
{ {
std::string name() override std::string name() override
{ {
@ -24,9 +55,7 @@ struct CmdFlakeList : StoreCommand, MixEvalArgs
void run(nix::ref<nix::Store> store) override void run(nix::ref<nix::Store> store) override
{ {
auto evalState = std::make_shared<EvalState>(searchPath, store); auto registries = getEvalState()->getFlakeRegistries();
auto registries = evalState->getFlakeRegistries();
stopProgressBar(); stopProgressBar();
@ -41,7 +70,7 @@ struct CmdFlakeList : StoreCommand, MixEvalArgs
} }
}; };
void printFlakeInfo(Flake & flake, bool json) { void printFlakeInfo(const Flake & flake, bool json) {
if (json) { if (json) {
nlohmann::json j; nlohmann::json j;
j["id"] = flake.id; j["id"] = flake.id;
@ -60,7 +89,7 @@ void printFlakeInfo(Flake & flake, bool json) {
std::cout << "URI: " << flake.resolvedRef.to_string() << "\n"; std::cout << "URI: " << flake.resolvedRef.to_string() << "\n";
std::cout << "Description: " << flake.description << "\n"; std::cout << "Description: " << flake.description << "\n";
if (flake.resolvedRef.ref) if (flake.resolvedRef.ref)
std::cout << "Branch: " << *flake.resolvedRef.ref; std::cout << "Branch: " << *flake.resolvedRef.ref << "\n";
if (flake.resolvedRef.rev) if (flake.resolvedRef.rev)
std::cout << "Revision: " << flake.resolvedRef.rev->to_string(Base16, false) << "\n"; std::cout << "Revision: " << flake.resolvedRef.rev->to_string(Base16, false) << "\n";
if (flake.revCount) if (flake.revCount)
@ -69,7 +98,7 @@ void printFlakeInfo(Flake & flake, bool json) {
} }
} }
void printNonFlakeInfo(NonFlake & nonFlake, bool json) { void printNonFlakeInfo(const NonFlake & nonFlake, bool json) {
if (json) { if (json) {
nlohmann::json j; nlohmann::json j;
j["id"] = nonFlake.alias; j["id"] = nonFlake.alias;
@ -95,7 +124,8 @@ void printNonFlakeInfo(NonFlake & nonFlake, bool json) {
} }
} }
struct CmdFlakeDeps : FlakeCommand, MixJSON, StoreCommand, MixEvalArgs // FIXME: merge info CmdFlakeInfo?
struct CmdFlakeDeps : FlakeCommand, MixJSON
{ {
std::string name() override std::string name() override
{ {
@ -109,30 +139,28 @@ struct CmdFlakeDeps : FlakeCommand, MixJSON, StoreCommand, MixEvalArgs
void run(nix::ref<nix::Store> store) override void run(nix::ref<nix::Store> store) override
{ {
auto evalState = std::make_shared<EvalState>(searchPath, store); auto evalState = getEvalState();
evalState->addRegistryOverrides(registryOverrides); evalState->addRegistryOverrides(registryOverrides);
FlakeRef flakeRef(flakeUri);
ResolvedFlake resFlake = resolveFlake(*evalState, flakeRef, UpdateLockFile);
std::queue<ResolvedFlake> todo; std::queue<ResolvedFlake> todo;
todo.push(resFlake); todo.push(resolveFlake());
while (!todo.empty()) { while (!todo.empty()) {
resFlake = todo.front(); auto resFlake = std::move(todo.front());
todo.pop(); todo.pop();
for (NonFlake & nonFlake : resFlake.nonFlakeDeps) for (auto & nonFlake : resFlake.nonFlakeDeps)
printNonFlakeInfo(nonFlake, json); printNonFlakeInfo(nonFlake, json);
for (auto info : resFlake.flakeDeps) for (auto & info : resFlake.flakeDeps) {
printFlakeInfo(info.second.flake, json);
todo.push(info.second); todo.push(info.second);
}
} }
} }
}; };
struct CmdFlakeUpdate : StoreCommand, FlakeCommand, MixEvalArgs struct CmdFlakeUpdate : FlakeCommand
{ {
std::string name() override std::string name() override
{ {
@ -146,14 +174,18 @@ struct CmdFlakeUpdate : StoreCommand, FlakeCommand, MixEvalArgs
void run(nix::ref<nix::Store> store) override void run(nix::ref<nix::Store> store) override
{ {
auto evalState = std::make_shared<EvalState>(searchPath, store); auto evalState = getEvalState();
bool recreateLockFile = true; auto flakeRef = getFlakeRef();
updateLockFile(*evalState, flakeUri, recreateLockFile);
if (std::get_if<FlakeRef::IsPath>(&flakeRef.data))
updateLockFile(*evalState, flakeRef, true);
else
throw Error("cannot update lockfile of flake '%s'", flakeRef);
} }
}; };
struct CmdFlakeInfo : FlakeCommand, MixJSON, MixEvalArgs, StoreCommand struct CmdFlakeInfo : FlakeCommand, MixJSON
{ {
std::string name() override std::string name() override
{ {
@ -169,8 +201,7 @@ struct CmdFlakeInfo : FlakeCommand, MixJSON, MixEvalArgs, StoreCommand
void run(nix::ref<nix::Store> store) override void run(nix::ref<nix::Store> store) override
{ {
auto evalState = std::make_shared<EvalState>(searchPath, store); auto flake = getFlake();
Flake flake = getFlake(*evalState, FlakeRef(flakeUri), true);
printFlakeInfo(flake, json); printFlakeInfo(flake, json);
} }
}; };
@ -235,7 +266,7 @@ struct CmdFlakeRemove : virtual Args, MixEvalArgs, Command
} }
}; };
struct CmdFlakePin : virtual Args, StoreCommand, MixEvalArgs struct CmdFlakePin : virtual Args, EvalCommand
{ {
FlakeUri alias; FlakeUri alias;
@ -256,7 +287,7 @@ struct CmdFlakePin : virtual Args, StoreCommand, MixEvalArgs
void run(nix::ref<nix::Store> store) override void run(nix::ref<nix::Store> store) override
{ {
auto evalState = std::make_shared<EvalState>(searchPath, store); auto evalState = getEvalState();
Path userRegistryPath = getUserRegistryPath(); Path userRegistryPath = getUserRegistryPath();
FlakeRegistry userRegistry = *readRegistry(userRegistryPath); FlakeRegistry userRegistry = *readRegistry(userRegistryPath);
@ -307,9 +338,9 @@ struct CmdFlakeInit : virtual Args, Command
} }
}; };
struct CmdFlakeClone : StoreCommand, FlakeCommand, MixEvalArgs struct CmdFlakeClone : FlakeCommand
{ {
Path endDirectory = ""; Path destDir;
std::string name() override std::string name() override
{ {
@ -323,15 +354,15 @@ struct CmdFlakeClone : StoreCommand, FlakeCommand, MixEvalArgs
CmdFlakeClone() CmdFlakeClone()
{ {
expectArg("end-dir", &endDirectory, true); expectArg("dest-dir", &destDir, true);
} }
void run(nix::ref<nix::Store> store) override void run(nix::ref<nix::Store> store) override
{ {
auto evalState = std::make_shared<EvalState>(searchPath, store); auto evalState = getEvalState();
Registries registries = evalState->getFlakeRegistries(); Registries registries = evalState->getFlakeRegistries();
gitCloneFlake(flakeUri, *evalState, registries, endDirectory); gitCloneFlake(getFlakeRef().to_string(), *evalState, registries, destDir);
} }
}; };

View file

@ -13,6 +13,34 @@
namespace nix { namespace nix {
MixFlakeOptions::MixFlakeOptions()
{
mkFlag()
.longName("recreate-lock-file")
.description("recreate lock file from scratch")
.set(&recreateLockFile, true);
mkFlag()
.longName("no-save-lock-file")
.description("do not save the newly generated lock file")
.set(&saveLockFile, false);
mkFlag()
.longName("no-registries")
.description("don't use flake registries")
.set(&useRegistries, false);
}
HandleLockFile MixFlakeOptions::getLockFileMode()
{
return
useRegistries
? recreateLockFile
? (saveLockFile ? RecreateLockFile : UseNewLockFile)
: (saveLockFile ? UpdateLockFile : UseUpdatedLockFile)
: AllPure;
}
SourceExprCommand::SourceExprCommand() SourceExprCommand::SourceExprCommand()
{ {
mkFlag() mkFlag()
@ -21,24 +49,9 @@ SourceExprCommand::SourceExprCommand()
.label("file") .label("file")
.description("evaluate a set of attributes from FILE (deprecated)") .description("evaluate a set of attributes from FILE (deprecated)")
.dest(&file); .dest(&file);
mkFlag()
.longName("recreate-lock-file")
.description("recreate lock file from scratch")
.set(&recreateLockFile, true);
mkFlag()
.longName("dont-save-lock-file")
.description("save the newly generated lock file")
.set(&saveLockFile, false);
mkFlag()
.longName("no-registries")
.description("don't use flake registries")
.set(&noRegistries, true);
} }
ref<EvalState> SourceExprCommand::getEvalState() ref<EvalState> EvalCommand::getEvalState()
{ {
if (!evalState) if (!evalState)
evalState = std::make_shared<EvalState>(searchPath, getStore()); evalState = std::make_shared<EvalState>(searchPath, getStore());
@ -169,11 +182,7 @@ struct InstallableFlake : InstallableValue
{ {
auto vFlake = state.allocValue(); auto vFlake = state.allocValue();
HandleLockFile handle = cmd.noRegistries ? AllPure : makeFlakeValue(state, flakeRef, cmd.getLockFileMode(), *vFlake);
cmd.recreateLockFile ?
(cmd.saveLockFile ? RecreateLockFile : UseNewLockFile)
: (cmd.saveLockFile ? UpdateLockFile : UseUpdatedLockFile);
makeFlakeValue(state, flakeRef, handle, *vFlake);
auto vProvides = (*vFlake->attrs->get(state.symbols.create("provides")))->value; auto vProvides = (*vFlake->attrs->get(state.symbols.create("provides")))->value;

View file

@ -104,6 +104,11 @@ EOF
# Test 'nix flake info'. # Test 'nix flake info'.
nix flake info --flake-registry $registry flake1 | grep -q 'ID: *flake1' nix flake info --flake-registry $registry flake1 | grep -q 'ID: *flake1'
# Test 'nix flake info' on a local flake.
(cd $flake1Dir && nix flake info) | grep -q 'ID: *flake1'
(cd $flake1Dir && nix flake info .) | grep -q 'ID: *flake1'
nix flake info $flake1Dir | grep -q 'ID: *flake1'
# Test 'nix flake info --json'. # Test 'nix flake info --json'.
json=$(nix flake info --flake-registry $registry flake1 --json | jq .) json=$(nix flake info --flake-registry $registry flake1 --json | jq .)
[[ $(echo "$json" | jq -r .description) = 'Bla bla' ]] [[ $(echo "$json" | jq -r .description) = 'Bla bla' ]]