diff options
Diffstat (limited to 'src/libcmd')
-rw-r--r-- | src/libcmd/installable-flake.cc | 9 | ||||
-rw-r--r-- | src/libcmd/repl-interacter.cc | 33 | ||||
-rw-r--r-- | src/libcmd/repl-interacter.hh | 5 | ||||
-rw-r--r-- | src/libcmd/repl.cc | 11 |
4 files changed, 54 insertions, 4 deletions
diff --git a/src/libcmd/installable-flake.cc b/src/libcmd/installable-flake.cc index 615f70945..46bdd411b 100644 --- a/src/libcmd/installable-flake.cc +++ b/src/libcmd/installable-flake.cc @@ -105,9 +105,14 @@ DerivedPathsWithInfo InstallableFlake::toDerivedPaths() fmt("while evaluating the flake output attribute '%s'", attrPath))) { return { *derivedPathWithInfo }; + } else { + throw Error( + "expected flake output attribute '%s' to be a derivation or path but found %s: %s", + attrPath, + showType(v), + ValuePrinter(*this->state, v, errorPrintOptions) + ); } - else - throw Error("flake output attribute '%s' is not a derivation or path", attrPath); } auto drvPath = attr->forceDerivation(); diff --git a/src/libcmd/repl-interacter.cc b/src/libcmd/repl-interacter.cc index 829383add..41589cda1 100644 --- a/src/libcmd/repl-interacter.cc +++ b/src/libcmd/repl-interacter.cc @@ -1,6 +1,8 @@ #include <cstdio> #include <iostream> #include <string> +#include <string_view> +#include <cerrno> #ifdef READLINE #include <readline/history.h> @@ -175,14 +177,43 @@ bool ReadlineLikeInteracter::getLine(std::string & input, ReplPromptType promptT if (!s) return false; + + this->writeHistory(); input += s; input += '\n'; return true; } +void ReadlineLikeInteracter::writeHistory() +{ + int ret = write_history(historyFile.c_str()); + int writeHistErr = errno; + + if (ret == 0) { + return; + } + + // If the open fails, editline returns EOF. If the close fails, editline + // forwards the return value of fclose(), which is EOF on error. + // readline however, returns the errno. + // So if we didn't get exactly EOF, then consider the return value the error + // code; otherwise use the errno we saved above. + // https://github.com/troglobit/editline/issues/66 + if (ret != EOF) { + writeHistErr = ret; + } + + // In any of these cases, we should explicitly ignore the error, but log + // them so the user isn't confused why their history is getting eaten. + + std::string_view const errMsg(std::strerror(writeHistErr)); + warn("ignoring error writing repl history to %s: %s", this->historyFile, errMsg); + +} + ReadlineLikeInteracter::~ReadlineLikeInteracter() { - write_history(historyFile.c_str()); + this->writeHistory(); } AutomationInteracter::Guard AutomationInteracter::init(detail::ReplCompleterMixin *) diff --git a/src/libcmd/repl-interacter.hh b/src/libcmd/repl-interacter.hh index c31b1a1e6..8f815fceb 100644 --- a/src/libcmd/repl-interacter.hh +++ b/src/libcmd/repl-interacter.hh @@ -42,6 +42,11 @@ public: } virtual Guard init(detail::ReplCompleterMixin * repl) override; virtual bool getLine(std::string & input, ReplPromptType promptType) override; + /** Writes the current history to the history file. + * + * This function logs but ignores errors from readline's write_history(). + */ + virtual void writeHistory(); virtual ~ReadlineLikeInteracter() override; }; diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc index 525c25560..46b6d57ed 100644 --- a/src/libcmd/repl.cc +++ b/src/libcmd/repl.cc @@ -90,7 +90,8 @@ struct NixRepl Strings loadedFiles; std::function<AnnotatedValues()> getValues; - const static int envSize = 32768; + // Uses 8MiB of memory. It's fine. + const static int envSize = 1 << 20; std::shared_ptr<StaticEnv> staticEnv; Env * env; int displ; @@ -375,6 +376,9 @@ StringSet NixRepl::completePrefix(const std::string & prefix) // Quietly ignore evaluation errors. } catch (BadURL & e) { // Quietly ignore BadURL flake-related errors. + } catch (SysError & e) { + // Quietly ignore system errors which can for example be raised by + // a non-existent file being `import`-ed. } } @@ -854,6 +858,11 @@ void NixRepl::loadReplOverlays() replInitFilesFunction->determinePos(noPos) ); + // n.b. this does in fact load the stuff into the environment twice (once + // from the superset of the environment returned by repl-overlays and once + // from the thing itself), but it's not fixable because clearEnv here could + // lead to dangling references to the old environment in thunks. + // https://git.lix.systems/lix-project/lix/issues/337#issuecomment-3745 addAttrsToScope(newAttrs); } |