1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-07-07 01:51:47 +02:00

Merge remote-tracking branch 'origin/master' into flakes

This commit is contained in:
Eelco Dolstra 2019-11-06 10:44:21 +01:00
commit 88c452d160
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
17 changed files with 155 additions and 83 deletions

View file

@ -93,4 +93,36 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath,
}
Pos findDerivationFilename(EvalState & state, Value & v, std::string what)
{
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", what);
}
// FIXME: is it possible to extract the Pos object instead of doing this
// toString + parsing?
auto pos = state.forceString(*v2);
auto colon = pos.rfind(':');
if (colon == std::string::npos)
throw Error("cannot parse meta.position attribute '%s'", pos);
std::string filename(pos, 0, colon);
unsigned int lineno;
try {
lineno = std::stoi(std::string(pos, colon + 1));
} catch (std::invalid_argument & e) {
throw Error("cannot parse line number '%s'", pos);
}
Symbol file = state.symbols.create(filename);
return { file, lineno, 0 };
}
}

View file

@ -12,4 +12,7 @@ MakeError(AttrPathNotFound, Error);
Value * findAlongAttrPath(EvalState & state, const string & attrPath,
Bindings & autoArgs, Value & vIn);
/* Heuristic to find the filename and lineno or a nix value. */
Pos findDerivationFilename(EvalState & state, Value & v, std::string what);
}

View file

@ -178,6 +178,19 @@ Strings argvToStrings(int argc, char * * argv)
return args;
}
Strings editorFor(Pos pos)
{
auto editor = getEnv("EDITOR", "cat");
auto args = tokenizeString<Strings>(editor);
if (pos.line > 0 && (
editor.find("emacs") != std::string::npos ||
editor.find("nano") != std::string::npos ||
editor.find("vim") != std::string::npos))
args.push_back(fmt("+%d", pos.line));
args.push_back(pos.file);
return args;
}
std::string renderLabels(const Strings & labels)
{
std::string res;

View file

@ -5,6 +5,7 @@
#include <memory>
#include "util.hh"
#include "nixexpr.hh"
namespace nix {
@ -241,6 +242,9 @@ public:
Strings argvToStrings(int argc, char * * argv);
/* Helper function to generate args that invoke $EDITOR on filename:lineno */
Strings editorFor(Pos pos);
/* Helper function for rendering argument labels. */
std::string renderLabels(const Strings & labels);

View file

@ -1572,7 +1572,11 @@ std::unique_ptr<InterruptCallback> createInterruptCallback(std::function<void()>
AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode)
{
AutoCloseFD fdSocket = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
AutoCloseFD fdSocket = socket(PF_UNIX, SOCK_STREAM
#ifdef SOCK_CLOEXEC
| SOCK_CLOEXEC
#endif
, 0);
if (!fdSocket)
throw SysError("cannot create Unix domain socket");

View file

@ -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.");
}
};

View file

@ -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);
}
};

View file

@ -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);