mirror of https://gitee.com/bigwinds/arangodb
added option `--console.history` to arangosh (#8328)
This commit is contained in:
parent
f437b83832
commit
6941eb941c
16
CHANGELOG
16
CHANGELOG
|
@ -1,3 +1,19 @@
|
|||
v3.4.5 (XXXX-XX-XX)
|
||||
-------------------
|
||||
|
||||
* added option `--console.history` to arangosh for controlling whether
|
||||
the command-line history should be loaded from and persisted in a file.
|
||||
|
||||
The default value for this option is `true`. Setting it to `false`
|
||||
will make arangosh not load any command-line history from the history
|
||||
file, and not store the current session's history when the shell is
|
||||
exited. The command-line history will then only be available in the
|
||||
current shell session.
|
||||
|
||||
* display the server role when connecting arangosh against a server (e.g.
|
||||
SINGLE, COORDINATOR)
|
||||
|
||||
|
||||
v3.4.4 (2019-03-08)
|
||||
-------------------
|
||||
|
||||
|
|
|
@ -1047,6 +1047,18 @@ versions on the same machine (e.g. for testing).
|
|||
Client tools
|
||||
------------
|
||||
|
||||
### Arangosh
|
||||
|
||||
Starting with ArangoDB version 3.4.5, the ArangoShell (arangosh) provides the option
|
||||
`--console.history` for controlling whether the shell's command-line history
|
||||
should be loaded from and persisted in a file.
|
||||
|
||||
The default value for this option is `true`. Setting it to `false`
|
||||
will make arangosh not load any command-line history from the history
|
||||
file, and not store the current session's history when the shell is
|
||||
exited. The command-line history will then only be available in the
|
||||
current shell session.
|
||||
|
||||
### Arangodump
|
||||
|
||||
Arangodump can now dump multiple collections in parallel. This can significantly
|
||||
|
|
|
@ -66,6 +66,10 @@ RestStatus RestVersionHandler::execute() {
|
|||
auto server = application_features::ApplicationServer::server->getFeature<ServerFeature>(
|
||||
"Server");
|
||||
result.add("mode", VPackValue(server->operationModeString()));
|
||||
auto serverState = ServerState::instance();
|
||||
if (serverState != nullptr) {
|
||||
result.add("role", VPackValue(ServerState::roleToString(serverState->getRole())));
|
||||
}
|
||||
}
|
||||
|
||||
std::string host = ServerState::instance()->getHost();
|
||||
|
|
|
@ -59,6 +59,7 @@ ConsoleFeature::ConsoleFeature(application_features::ApplicationServer& server)
|
|||
#endif
|
||||
_quiet(false),
|
||||
_colors(true),
|
||||
_useHistory(true),
|
||||
_autoComplete(true),
|
||||
_prettyPrint(true),
|
||||
_auditFile(),
|
||||
|
@ -108,6 +109,12 @@ void ConsoleFeature::collectOptions(std::shared_ptr<ProgramOptions> options) {
|
|||
options->addOption("--console.audit-file",
|
||||
"audit log file to save commands and results",
|
||||
new StringParameter(&_auditFile));
|
||||
|
||||
options->addOption("--console.history",
|
||||
"whether or not to load and persist command-line history",
|
||||
new BooleanParameter(&_useHistory))
|
||||
.setIntroducedIn(30405)
|
||||
.setIntroducedIn(30500);
|
||||
|
||||
options->addOption("--console.pager", "enable paging", new BooleanParameter(&_pager));
|
||||
|
||||
|
@ -309,13 +316,23 @@ std::string ConsoleFeature::readPassword() {
|
|||
}
|
||||
|
||||
void ConsoleFeature::printWelcomeInfo() {
|
||||
if (!_quiet && _pager) {
|
||||
std::ostringstream s;
|
||||
|
||||
s << "Using pager '" << _pagerCommand << "' for output buffering.";
|
||||
|
||||
printLine(s.str());
|
||||
if (_quiet) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::ostringstream s;
|
||||
|
||||
if (_pager) {
|
||||
s << "Using pager '" << _pagerCommand << "' for output buffering. ";
|
||||
}
|
||||
|
||||
if (_useHistory) {
|
||||
s << "Command-line history will be persisted when the shell is exited.";
|
||||
} else {
|
||||
s << "Command-line history is enabled for this session only and will *not* be persisted.";
|
||||
}
|
||||
|
||||
printLine(s.str());
|
||||
}
|
||||
|
||||
void ConsoleFeature::printByeBye() {
|
||||
|
|
|
@ -41,6 +41,7 @@ class ConsoleFeature final : public application_features::ApplicationFeature {
|
|||
bool quiet() const { return _quiet; }
|
||||
void setQuiet(bool value) { _quiet = value; }
|
||||
bool colors() const { return _colors; }
|
||||
bool useHistory() const { return _useHistory; }
|
||||
bool autoComplete() const { return _autoComplete; }
|
||||
bool prettyPrint() const { return _prettyPrint; }
|
||||
bool pager() const { return _pager; }
|
||||
|
@ -54,6 +55,7 @@ class ConsoleFeature final : public application_features::ApplicationFeature {
|
|||
#endif
|
||||
bool _quiet;
|
||||
bool _colors;
|
||||
bool _useHistory;
|
||||
bool _autoComplete;
|
||||
bool _prettyPrint;
|
||||
std::string _auditFile;
|
||||
|
|
|
@ -60,6 +60,7 @@ V8ClientConnection::V8ClientConnection()
|
|||
_lastErrorMessage(""),
|
||||
_version("arango"),
|
||||
_mode("unknown mode"),
|
||||
_role("UNKNOWN"),
|
||||
_loop(1),
|
||||
_vpackOptions(VPackOptions::Defaults) {
|
||||
_vpackOptions.buildUnindexedObjects = true;
|
||||
|
@ -123,6 +124,10 @@ void V8ClientConnection::createConnection() {
|
|||
if (mode.isString()) {
|
||||
_mode = mode.copyString();
|
||||
}
|
||||
VPackSlice role = details.get("role");
|
||||
if (role.isString()) {
|
||||
_role = role.copyString();
|
||||
}
|
||||
}
|
||||
std::string const versionString =
|
||||
VelocyPackHelper::getStringValue(body, "version", "");
|
||||
|
@ -227,7 +232,7 @@ void V8ClientConnection::reconnect(ClientFeature* client) {
|
|||
LOG_TOPIC(INFO, arangodb::Logger::FIXME)
|
||||
<< "Connected to ArangoDB "
|
||||
<< "'" << endpointSpecification() << "', "
|
||||
<< "version " << _version << " [" << _mode << "], "
|
||||
<< "version " << _version << " [" << _role << ", " << _mode << "], "
|
||||
<< "database '" << _databaseName << "', "
|
||||
<< "username: '" << client->username() << "'";
|
||||
} else {
|
||||
|
@ -353,7 +358,7 @@ static void ClientConnection_ConstructorCallback(v8::FunctionCallbackInfo<v8::Va
|
|||
LOG_TOPIC(INFO, arangodb::Logger::FIXME)
|
||||
<< "Connected to ArangoDB "
|
||||
<< "'" << v8connection->endpointSpecification() << "', "
|
||||
<< "version " << v8connection->version() << " [" << v8connection->mode() << "], "
|
||||
<< "version " << v8connection->version() << " [" << v8connection->role() << ", " << v8connection->mode() << "], "
|
||||
<< "database '" << v8connection->databaseName() << "', "
|
||||
<< "username: '" << v8connection->username() << "'";
|
||||
|
||||
|
@ -1276,6 +1281,30 @@ static void ClientConnection_getMode(v8::FunctionCallbackInfo<v8::Value> const&
|
|||
TRI_V8_TRY_CATCH_END
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief ClientConnection method "getRole"
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void ClientConnection_getRole(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
||||
TRI_V8_TRY_CATCH_BEGIN(isolate);
|
||||
v8::HandleScope scope(isolate);
|
||||
|
||||
// get the connection
|
||||
V8ClientConnection* v8connection =
|
||||
TRI_UnwrapClass<V8ClientConnection>(args.Holder(), WRAP_TYPE_CONNECTION);
|
||||
|
||||
if (v8connection == nullptr) {
|
||||
TRI_V8_THROW_EXCEPTION_INTERNAL("connection class corrupted");
|
||||
}
|
||||
|
||||
if (args.Length() != 0) {
|
||||
TRI_V8_THROW_EXCEPTION_USAGE("getRole()");
|
||||
}
|
||||
|
||||
TRI_V8_RETURN_STD_STRING(v8connection->role());
|
||||
TRI_V8_TRY_CATCH_END
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief ClientConnection method "getDatabaseName"
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1752,6 +1781,9 @@ void V8ClientConnection::initServer(v8::Isolate* isolate, v8::Local<v8::Context>
|
|||
|
||||
connection_proto->Set(isolate, "getMode",
|
||||
v8::FunctionTemplate::New(isolate, ClientConnection_getMode));
|
||||
|
||||
connection_proto->Set(isolate, "getRole",
|
||||
v8::FunctionTemplate::New(isolate, ClientConnection_getRole));
|
||||
|
||||
connection_proto->Set(isolate, "getDatabaseName",
|
||||
v8::FunctionTemplate::New(isolate, ClientConnection_getDatabaseName));
|
||||
|
|
|
@ -77,6 +77,7 @@ class V8ClientConnection {
|
|||
std::string lastErrorMessage() const { return _lastErrorMessage; }
|
||||
std::string const& version() const { return _version; }
|
||||
std::string const& mode() const { return _mode; }
|
||||
std::string const& role() const { return _role; }
|
||||
std::string endpointSpecification() const;
|
||||
|
||||
v8::Handle<v8::Value> getData(v8::Isolate* isolate, StringRef const& location,
|
||||
|
@ -145,6 +146,7 @@ class V8ClientConnection {
|
|||
std::string _lastErrorMessage;
|
||||
std::string _version;
|
||||
std::string _mode;
|
||||
std::string _role;
|
||||
|
||||
fuerte::EventLoopService _loop;
|
||||
fuerte::ConnectionBuilder _builder;
|
||||
|
|
|
@ -342,7 +342,7 @@ bool V8ShellFeature::printHello(V8ClientConnection* v8connection) {
|
|||
std::ostringstream is;
|
||||
|
||||
is << "Connected to ArangoDB '" << v8connection->endpointSpecification()
|
||||
<< "' version: " << v8connection->version() << " ["
|
||||
<< "' version: " << v8connection->version() << " [" << v8connection->role() << ", "
|
||||
<< v8connection->mode() << "], database: '" << v8connection->databaseName()
|
||||
<< "', username: '" << v8connection->username() << "'";
|
||||
|
||||
|
@ -350,7 +350,8 @@ bool V8ShellFeature::printHello(V8ClientConnection* v8connection) {
|
|||
} else {
|
||||
std::ostringstream is;
|
||||
|
||||
is << "Could not connect to endpoint '" << v8connection->endpointSpecification()
|
||||
auto client = server()->getFeature<ClientFeature>("Client");
|
||||
is << "Could not connect to endpoint '" << client->endpoint()
|
||||
<< "', database: '" << v8connection->databaseName()
|
||||
<< "', username: '" << v8connection->username() << "'";
|
||||
|
||||
|
@ -422,7 +423,7 @@ int V8ShellFeature::runShell(std::vector<std::string> const& positionals) {
|
|||
bool promptError;
|
||||
auto v8connection = setup(context, true, positionals, &promptError);
|
||||
|
||||
V8LineEditor v8LineEditor(_isolate, context, "." + _name + ".history");
|
||||
V8LineEditor v8LineEditor(_isolate, context, _console->useHistory() ? "." + _name + ".history" : "");
|
||||
|
||||
if (v8connection != nullptr) {
|
||||
v8LineEditor.setSignalFunction(
|
||||
|
|
|
@ -63,7 +63,9 @@ LinenoiseShell::LinenoiseShell(std::string const& history, Completer* completer)
|
|||
LinenoiseShell::~LinenoiseShell() { COMPLETER = nullptr; }
|
||||
|
||||
bool LinenoiseShell::open(bool) {
|
||||
linenoiseHistoryLoad(_historyFilename.c_str());
|
||||
if (!_historyFilename.empty()) {
|
||||
linenoiseHistoryLoad(_historyFilename.c_str());
|
||||
}
|
||||
_state = STATE_OPENED;
|
||||
return true;
|
||||
}
|
||||
|
@ -89,7 +91,9 @@ void LinenoiseShell::addHistory(std::string const& str) {
|
|||
}
|
||||
|
||||
bool LinenoiseShell::writeHistory() {
|
||||
linenoiseHistorySave(_historyFilename.c_str());
|
||||
if (!_historyFilename.empty()) {
|
||||
linenoiseHistorySave(_historyFilename.c_str());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -54,14 +54,18 @@ void ShellBase::sortAlternatives(std::vector<std::string>& completions) {
|
|||
ShellBase::ShellBase(std::string const& history, Completer* completer)
|
||||
: _current(), _historyFilename(), _state(STATE_NONE), _completer(completer) {
|
||||
// construct the complete history path
|
||||
std::string path(TRI_HomeDirectory());
|
||||
if (!history.empty()) {
|
||||
// note: if history is empty, we will not write any history and not
|
||||
// construct the full filename
|
||||
std::string path(TRI_HomeDirectory());
|
||||
|
||||
if (!path.empty() && path[path.size() - 1] != TRI_DIR_SEPARATOR_CHAR) {
|
||||
path.push_back(TRI_DIR_SEPARATOR_CHAR);
|
||||
if (!path.empty() && path[path.size() - 1] != TRI_DIR_SEPARATOR_CHAR) {
|
||||
path.push_back(TRI_DIR_SEPARATOR_CHAR);
|
||||
}
|
||||
path.append(history);
|
||||
|
||||
_historyFilename = path;
|
||||
}
|
||||
path.append(history);
|
||||
|
||||
_historyFilename = path;
|
||||
}
|
||||
|
||||
ShellBase::~ShellBase() { delete _completer; }
|
||||
|
|
Loading…
Reference in New Issue