Unify and clarify interactive and --exec command error and parse error handling.
Previously, interactive execution and --exec used two models for how a failed command would impact other commands in the execution. As an example, consider: fdb> set foo bar ; set bar f\00 ; set baz foo In interactive mode, this had the effect of {foo=bar, baz=foo}. In --exec mode, this had the effect of {foo=bar}. With this change, both now have the effect of {foo=bar}. This is achieved by prefixing the last parsed command, which is the one that had the error, with a fake "parse_error" token. The execution of this would now look like: ERROR: malformed escape sequence >>> set foo bar ERROR: Command failed to completely parse. ERROR: Not running partial or malformed command: set bar Which indicates how much execution occurred and where it halted, identically in both modes of execution.
This commit is contained in:
parent
d78b29625c
commit
0c7fd0a23d
|
@ -2217,33 +2217,45 @@ ACTOR Future<int> cli(CLIOptions opt, LineNoise* plinenoise) {
|
|||
state UID randomID = g_random->randomUniqueID();
|
||||
TraceEvent(SevInfo, "CLICommandLog", randomID).detail("command", printable(StringRef(line)));
|
||||
|
||||
bool err, partial;
|
||||
state std::vector<std::vector<StringRef>> parsed = parseLine(line, err, partial);
|
||||
if (err) {
|
||||
LogCommand(line, randomID, "ERROR: malformed escape sequence");
|
||||
is_error = true;
|
||||
bool malformed, partial;
|
||||
state std::vector<std::vector<StringRef>> parsed = parseLine(line, malformed, partial);
|
||||
if (malformed) LogCommand(line, randomID, "ERROR: malformed escape sequence");
|
||||
if (partial) LogCommand(line, randomID, "ERROR: unterminated quote");
|
||||
if (malformed || partial) {
|
||||
if (parsed.size() > 0) {
|
||||
// Denote via a special token that the command was a parse failure.
|
||||
auto& last_command = parsed.back();
|
||||
last_command.insert(last_command.begin(), StringRef((const uint8_t*)"parse_error", strlen("parse_error")));
|
||||
}
|
||||
if (partial) {
|
||||
LogCommand(line, randomID, "ERROR: unterminated quote");
|
||||
is_error = true;
|
||||
}
|
||||
|
||||
state bool multi = parsed.size() > 1;
|
||||
is_error = false;
|
||||
|
||||
state std::vector<std::vector<StringRef>>::iterator iter;
|
||||
for (iter = parsed.begin(); iter != parsed.end(); ++iter) {
|
||||
state std::vector<StringRef> tokens = *iter;
|
||||
|
||||
if (opt.exec.present() && is_error) {
|
||||
if (is_error) {
|
||||
printf("WARNING: the previous command failed, the remaining commands will not be executed.\n");
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
|
||||
is_error = false;
|
||||
|
||||
if (!tokens.size())
|
||||
continue;
|
||||
|
||||
if (tokencmp(tokens[0], "parse_error")) {
|
||||
printf("ERROR: Command failed to completely parse.\n");
|
||||
if (tokens.size() > 1) {
|
||||
printf("ERROR: Not running partial or malformed command:");
|
||||
for (auto t = tokens.begin() + 1; t != tokens.end(); ++t)
|
||||
printf(" %s", formatStringRef(*t, true).c_str());
|
||||
printf("\n");
|
||||
}
|
||||
is_error = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (multi) {
|
||||
printf(">>>");
|
||||
for (auto t = tokens.begin(); t != tokens.end(); ++t)
|
||||
|
|
Loading…
Reference in New Issue