aboutsummaryrefslogtreecommitdiff
path: root/src/nix
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2019-11-06 10:44:21 +0100
committerEelco Dolstra <edolstra@gmail.com>2019-11-06 10:56:33 +0100
commit88c452d1603eb809358e509d5dca9c40c512cd20 (patch)
tree41d3162e57fbbd0d5e10e35eed84d4b2b5e9e936 /src/nix
parent9ff4060d2691c1a7dc2f8be65d117f43c3335714 (diff)
parent35732a95bcdc0a4b4492845205e6283fcc88fd0d (diff)
Merge remote-tracking branch 'origin/master' into flakes
Diffstat (limited to 'src/nix')
-rw-r--r--src/nix/doctor.cc67
-rw-r--r--src/nix/edit.cc40
-rw-r--r--src/nix/repl.cc30
3 files changed, 77 insertions, 60 deletions
diff --git a/src/nix/doctor.cc b/src/nix/doctor.cc
index 98260127b..5f76d0019 100644
--- a/src/nix/doctor.cc
+++ b/src/nix/doctor.cc
@@ -1,11 +1,17 @@
+#include <sstream>
+
#include "command.hh"
+#include "logging.hh"
#include "serve-protocol.hh"
#include "shared.hh"
#include "store-api.hh"
+#include "util.hh"
#include "worker-protocol.hh"
using namespace nix;
+namespace {
+
std::string formatProtocol(unsigned int proto)
{
if (proto) {
@@ -16,19 +22,30 @@ std::string formatProtocol(unsigned int proto)
return "unknown";
}
+bool checkPass(const std::string & msg) {
+ logger->log(ANSI_GREEN "[PASS] " ANSI_NORMAL + msg);
+ return true;
+}
+
+bool checkFail(const std::string & msg) {
+ logger->log(ANSI_RED "[FAIL] " ANSI_NORMAL + msg);
+ return false;
+}
+
+}
+
struct CmdDoctor : StoreCommand
{
bool success = true;
std::string description() override
{
- return "check your system for potential problems";
+ return "check your system for potential problems and print a PASS or FAIL for each check.";
}
void run(ref<Store> store) override
{
- std::cout << "Store uri: " << store->getUri() << std::endl;
- std::cout << std::endl;
+ logger->log("Running checks against store uri: " + store->getUri());
auto type = getStoreType();
@@ -51,15 +68,14 @@ struct CmdDoctor : StoreCommand
dirs.insert(dirOf(canonPath(dir + "/nix-env", true)));
if (dirs.size() != 1) {
- std::cout << "Warning: multiple versions of nix found in PATH." << std::endl;
- std::cout << std::endl;
+ std::stringstream ss;
+ ss << "Multiple versions of nix found in PATH:\n";
for (auto & dir : dirs)
- std::cout << " " << dir << std::endl;
- std::cout << std::endl;
- return false;
+ ss << " " << dir << "\n";
+ return checkFail(ss.str());
}
- return true;
+ return checkPass("PATH contains only one nix version.");
}
bool checkProfileRoots(ref<Store> store)
@@ -82,17 +98,17 @@ struct CmdDoctor : StoreCommand
}
if (!dirs.empty()) {
- std::cout << "Warning: found profiles outside of " << settings.nixStateDir << "/profiles." << std::endl;
- std::cout << "The generation this profile points to might not have a gcroot and could be" << std::endl;
- std::cout << "garbage collected, resulting in broken symlinks." << std::endl;
- std::cout << std::endl;
+ std::stringstream ss;
+ ss << "Found profiles outside of " << settings.nixStateDir << "/profiles.\n"
+ << "The generation this profile points to might not have a gcroot and could be\n"
+ << "garbage collected, resulting in broken symlinks.\n\n";
for (auto & dir : dirs)
- std::cout << " " << dir << std::endl;
- std::cout << std::endl;
- return false;
+ ss << " " << dir << "\n";
+ ss << "\n";
+ return checkFail(ss.str());
}
- return true;
+ return checkPass("All profiles are gcroots.");
}
bool checkStoreProtocol(unsigned int storeProto)
@@ -102,17 +118,16 @@ struct CmdDoctor : StoreCommand
: PROTOCOL_VERSION;
if (clientProto != storeProto) {
- std::cout << "Warning: protocol version of this client does not match the store." << std::endl;
- std::cout << "While this is not necessarily a problem it's recommended to keep the client in" << std::endl;
- std::cout << "sync with the daemon." << std::endl;
- std::cout << std::endl;
- std::cout << "Client protocol: " << formatProtocol(clientProto) << std::endl;
- std::cout << "Store protocol: " << formatProtocol(storeProto) << std::endl;
- std::cout << std::endl;
- return false;
+ std::stringstream ss;
+ ss << "Warning: protocol version of this client does not match the store.\n"
+ << "While this is not necessarily a problem it's recommended to keep the client in\n"
+ << "sync with the daemon.\n\n"
+ << "Client protocol: " << formatProtocol(clientProto) << "\n"
+ << "Store protocol: " << formatProtocol(storeProto) << "\n\n";
+ return checkFail(ss.str());
}
- return true;
+ return checkPass("Client protocol matches store protocol.");
}
};
diff --git a/src/nix/edit.cc b/src/nix/edit.cc
index 632a99d11..ca410cd1f 100644
--- a/src/nix/edit.cc
+++ b/src/nix/edit.cc
@@ -31,45 +31,17 @@ struct CmdEdit : InstallableCommand
auto v = installable->toValue(*state);
- Value * v2;
- try {
- auto dummyArgs = state->allocBindings(0);
- v2 = findAlongAttrPath(*state, "meta.position", *dummyArgs, *v);
- } catch (Error &) {
- throw Error("package '%s' has no source location information", installable->what());
- }
-
- auto pos = state->forceString(*v2);
- debug("position is %s", pos);
-
- auto colon = pos.rfind(':');
- if (colon == std::string::npos)
- throw Error("cannot parse meta.position attribute '%s'", pos);
-
- std::string filename(pos, 0, colon);
- int lineno;
- try {
- lineno = std::stoi(std::string(pos, colon + 1));
- } catch (std::invalid_argument & e) {
- throw Error("cannot parse line number '%s'", pos);
- }
-
- auto editor = getEnv("EDITOR", "cat");
-
- auto args = tokenizeString<Strings>(editor);
-
- if (editor.find("emacs") != std::string::npos ||
- editor.find("nano") != std::string::npos ||
- editor.find("vim") != std::string::npos)
- args.push_back(fmt("+%d", lineno));
-
- args.push_back(filename);
+ Pos pos = findDerivationFilename(*state, *v, installable->what());
stopProgressBar();
+ auto args = editorFor(pos);
+
execvp(args.front().c_str(), stringsToCharPtrs(args).data());
- throw SysError("cannot run editor '%s'", editor);
+ std::string command;
+ for (const auto &arg : args) command += " '" + arg + "'";
+ throw SysError("cannot run command%s", command);
}
};
diff --git a/src/nix/repl.cc b/src/nix/repl.cc
index 0fa1594cc..2b4d1a2c4 100644
--- a/src/nix/repl.cc
+++ b/src/nix/repl.cc
@@ -22,6 +22,7 @@ extern "C" {
#include "shared.hh"
#include "eval.hh"
#include "eval-inline.hh"
+#include "attr-path.hh"
#include "store-api.hh"
#include "common-eval-args.hh"
#include "get-drvs.hh"
@@ -440,6 +441,7 @@ bool NixRepl::processLine(string line)
<< " <x> = <expr> Bind expression to variable\n"
<< " :a <expr> Add attributes from resulting set to scope\n"
<< " :b <expr> Build derivation\n"
+ << " :e <expr> Open the derivation in $EDITOR\n"
<< " :i <expr> Build derivation, then install result into current profile\n"
<< " :l <path> Load Nix expression and add it to scope\n"
<< " :p <expr> Evaluate and print expression recursively\n"
@@ -466,6 +468,34 @@ bool NixRepl::processLine(string line)
reloadFiles();
}
+ else if (command == ":e" || command == ":edit") {
+ Value v;
+ evalString(arg, v);
+
+ Pos pos;
+
+ if (v.type == tPath || v.type == tString) {
+ PathSet context;
+ auto filename = state.coerceToString(noPos, v, context);
+ pos.file = state.symbols.create(filename);
+ } else if (v.type == tLambda) {
+ pos = v.lambda.fun->pos;
+ } else {
+ // assume it's a derivation
+ pos = findDerivationFilename(state, v, arg);
+ }
+
+ // Open in EDITOR
+ auto args = editorFor(pos);
+ auto editor = args.front();
+ args.pop_front();
+ runProgram(editor, args);
+
+ // Reload right after exiting the editor
+ state.resetFileCache();
+ reloadFiles();
+ }
+
else if (command == ":t") {
Value v;
evalString(arg, v);