mirror of https://github.com/tstack/lnav.git
[session] allow the name
This commit is contained in:
parent
138a506b1a
commit
3da3ec799a
10
NEWS
10
NEWS
|
@ -9,8 +9,18 @@ lnav v0.8.6:
|
|||
and unpaused by pressing it again. The bottom status bar will display
|
||||
'Paused' in the right corner while paused.
|
||||
* CMake is now a supported way to build.
|
||||
* When viewing data from the standard-input, a symbolic name can now be
|
||||
assigned to the view by doing an UPDATE to the filepath column of the
|
||||
lnav_file table. For example, to assign the name "journald", the
|
||||
following SQL statement can be executed in lnav:
|
||||
;UPDATE lnav_file SET filepath='journald' WHERE filepath='stdin'
|
||||
The symbolic name will be used when saving and loading session
|
||||
information. A "rename-stdin" lnav script has also been added as a
|
||||
convenience to perform this operation.
|
||||
* The size of the terminal can be accessed in SQL using the $LINES and
|
||||
$COLS variables.
|
||||
* The raise_error(msg) SQL function has been added to make it easier to
|
||||
raise an error in an lnav script to stop execution and notify the user.
|
||||
|
||||
Interface Changes:
|
||||
* Data piped into lnav is no longer dumped to the console after exit.
|
||||
|
|
|
@ -194,6 +194,15 @@ The following functions can be used to access **lnav**'s internal state:
|
|||
* log_top_datetime() - Return the timestamp of the line at the top of the log
|
||||
view.
|
||||
|
||||
Miscellaneous
|
||||
---------------
|
||||
|
||||
Miscellaneous functions:
|
||||
|
||||
* raise_error(msg) - Raises an error with the given message when executed.
|
||||
This function can be useful to raise errors in **lnav** scripts, for example,
|
||||
when checking arguments.
|
||||
|
||||
.. _collators:
|
||||
|
||||
Collators
|
||||
|
|
|
@ -55,7 +55,9 @@ following columns are available in this table:
|
|||
|
||||
:device: The device the file is stored on.
|
||||
:inode: The inode for the file on the device.
|
||||
:filepath: The absolute path to the file.
|
||||
:filepath: If this is a real file, it will be the absolute path. Otherwise,
|
||||
it is a symbolic name. If it is a symbolic name, it can be UPDATEd so that
|
||||
this file will be considered when saving and loading session information.
|
||||
:format: The log file format for the file.
|
||||
:lines: The number of lines in the file.
|
||||
:time_offset: The millisecond offset for timestamps. This column can be
|
||||
|
|
|
@ -37,6 +37,7 @@ BUILTIN_LNAVSCRIPTS = \
|
|||
$(srcdir)/scripts/dhclient-summary.lnav \
|
||||
$(srcdir)/scripts/lnav-pop-view.lnav \
|
||||
$(srcdir)/scripts/partition-by-boot.lnav \
|
||||
$(srcdir)/scripts/rename-stdin.lnav \
|
||||
$(srcdir)/scripts/search-for.lnav \
|
||||
$()
|
||||
|
||||
|
@ -165,6 +166,7 @@ dist_noinst_DATA = \
|
|||
scripts/dump-pid.sh \
|
||||
scripts/lnav-pop-view.lnav \
|
||||
scripts/partition-by-boot.lnav \
|
||||
scripts/rename-stdin.lnav \
|
||||
scripts/search-for.lnav \
|
||||
themes/default-theme.json \
|
||||
themes/eldar.json \
|
||||
|
|
|
@ -62,4 +62,14 @@ auto operator|(T&& t, F f) -> decltype(detail::void_or_nullopt<decltype(f(std::f
|
|||
else return detail::void_or_nullopt<return_type>();
|
||||
}
|
||||
|
||||
template< class T >
|
||||
optional_constexpr nonstd::optional< typename std::decay<T>::type > make_optional_from_nullable( T && v )
|
||||
{
|
||||
if (v != nullptr) {
|
||||
return nonstd::optional<typename std::decay<T>::type>(
|
||||
std::forward<T>(v));
|
||||
}
|
||||
return nonstd::nullopt;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -59,7 +59,7 @@ int sql_progress(const struct log_cursor &lc)
|
|||
size_t total = lnav_data.ld_log_source.text_line_count();
|
||||
off_t off = lc.lc_curr_line;
|
||||
|
||||
if (lnav_data.ld_window == NULL) {
|
||||
if (lnav_data.ld_window == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -78,33 +78,44 @@ int sql_progress(const struct log_cursor &lc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
string execute_from_file(exec_context &ec, const filesystem::path &path, int line_number, char mode, const string &cmdline);
|
||||
void sql_progress_finished()
|
||||
{
|
||||
if (lnav_data.ld_window == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
string execute_command(exec_context &ec, const string &cmdline)
|
||||
lnav_data.ld_bottom_source.update_loading(0, 0);
|
||||
lnav_data.ld_top_source.update_time();
|
||||
lnav_data.ld_status[LNS_TOP].do_update();
|
||||
lnav_data.ld_status[LNS_BOTTOM].do_update();
|
||||
lnav_data.ld_views[LNV_DB].redo_search();
|
||||
}
|
||||
|
||||
Result<string, string> execute_from_file(exec_context &ec, const filesystem::path &path, int line_number, char mode, const string &cmdline);
|
||||
|
||||
Result<string, string> execute_command(exec_context &ec, const string &cmdline)
|
||||
{
|
||||
vector<string> args;
|
||||
string msg;
|
||||
|
||||
log_info("Executing: %s", cmdline.c_str());
|
||||
|
||||
split_ws(cmdline, args);
|
||||
|
||||
if (args.size() > 0) {
|
||||
if (!args.empty()) {
|
||||
readline_context::command_map_t::iterator iter;
|
||||
|
||||
if ((iter = lnav_commands.find(args[0])) ==
|
||||
lnav_commands.end()) {
|
||||
msg = ec.get_error_prefix() + "unknown command - " + args[0];
|
||||
if ((iter = lnav_commands.find(args[0])) == lnav_commands.end()) {
|
||||
return ec.make_error("unknown command - {}", args[0]);
|
||||
}
|
||||
else {
|
||||
msg = iter->second->c_func(ec, cmdline, args);
|
||||
return iter->second->c_func(ec, cmdline, args);
|
||||
}
|
||||
}
|
||||
|
||||
return msg;
|
||||
return ec.make_error("no command to execute");
|
||||
}
|
||||
|
||||
string execute_sql(exec_context &ec, const string &sql, string &alt_msg)
|
||||
Result<string, string> execute_sql(exec_context &ec, const string &sql, string &alt_msg)
|
||||
{
|
||||
db_label_source &dls = lnav_data.ld_db_row_source;
|
||||
auto_mem<sqlite3_stmt> stmt(sqlite3_finalize);
|
||||
|
@ -123,7 +134,7 @@ string execute_sql(exec_context &ec, const string &sql, string &alt_msg)
|
|||
ensure_view(&lnav_data.ld_views[LNV_SCHEMA]);
|
||||
|
||||
lnav_data.ld_mode = LNM_PAGING;
|
||||
return "";
|
||||
return Ok(string());
|
||||
}
|
||||
else if (stmt_str == ".msgformats") {
|
||||
stmt_str = MSG_FORMAT_STMT;
|
||||
|
@ -133,6 +144,7 @@ string execute_sql(exec_context &ec, const string &sql, string &alt_msg)
|
|||
|
||||
pair<string, int> source = ec.ec_source.top();
|
||||
sql_progress_guard progress_guard(sql_progress,
|
||||
sql_progress_finished,
|
||||
source.first,
|
||||
source.second);
|
||||
gettimeofday(&start_tv, NULL);
|
||||
|
@ -144,12 +156,12 @@ string execute_sql(exec_context &ec, const string &sql, string &alt_msg)
|
|||
if (retcode != SQLITE_OK) {
|
||||
const char *errmsg = sqlite3_errmsg(lnav_data.ld_db);
|
||||
|
||||
retval = ec.get_error_prefix() + string(errmsg);
|
||||
alt_msg = "";
|
||||
return ec.make_error("{}", errmsg);
|
||||
}
|
||||
else if (stmt == NULL) {
|
||||
retval = "";
|
||||
alt_msg = "";
|
||||
return ec.make_error("No statement given");
|
||||
}
|
||||
else {
|
||||
bool done = false;
|
||||
|
@ -253,24 +265,23 @@ string execute_sql(exec_context &ec, const string &sql, string &alt_msg)
|
|||
retcode = sqlite3_step(stmt.in());
|
||||
|
||||
switch (retcode) {
|
||||
case SQLITE_OK:
|
||||
case SQLITE_DONE:
|
||||
done = true;
|
||||
break;
|
||||
case SQLITE_OK:
|
||||
case SQLITE_DONE:
|
||||
done = true;
|
||||
break;
|
||||
|
||||
case SQLITE_ROW:
|
||||
ec.ec_sql_callback(ec, stmt.in());
|
||||
break;
|
||||
case SQLITE_ROW:
|
||||
ec.ec_sql_callback(ec, stmt.in());
|
||||
break;
|
||||
|
||||
default: {
|
||||
const char *errmsg;
|
||||
default: {
|
||||
const char *errmsg;
|
||||
|
||||
log_error("sqlite3_step error code: %d", retcode);
|
||||
errmsg = sqlite3_errmsg(lnav_data.ld_db);
|
||||
retval = ec.get_error_prefix() + string(errmsg);
|
||||
done = true;
|
||||
}
|
||||
break;
|
||||
log_error("sqlite3_step error code: %d", retcode);
|
||||
errmsg = sqlite3_errmsg(lnav_data.ld_db);
|
||||
return ec.make_error("{}", errmsg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -371,16 +382,10 @@ string execute_sql(exec_context &ec, const string &sql, string &alt_msg)
|
|||
#endif
|
||||
}
|
||||
|
||||
if (!(lnav_data.ld_flags & LNF_HEADLESS)) {
|
||||
lnav_data.ld_bottom_source.update_loading(0, 0);
|
||||
lnav_data.ld_status[LNS_BOTTOM].do_update();
|
||||
lnav_data.ld_views[LNV_DB].redo_search();
|
||||
}
|
||||
|
||||
return retval;
|
||||
return Ok(retval);
|
||||
}
|
||||
|
||||
static string execute_file_contents(exec_context &ec, const filesystem::path &path, bool multiline)
|
||||
static Result<string, string> execute_file_contents(exec_context &ec, const filesystem::path &path, bool multiline)
|
||||
{
|
||||
static filesystem::path stdin_path("-");
|
||||
static filesystem::path dev_stdin_path("/dev/stdin");
|
||||
|
@ -390,12 +395,12 @@ static string execute_file_contents(exec_context &ec, const filesystem::path &pa
|
|||
|
||||
if (path == stdin_path || path == dev_stdin_path) {
|
||||
if (isatty(STDIN_FILENO)) {
|
||||
return "error: stdin has already been consumed";
|
||||
return ec.make_error("stdin has already been consumed");
|
||||
}
|
||||
file = stdin;
|
||||
}
|
||||
else if ((file = fopen(path.str().c_str(), "r")) == nullptr) {
|
||||
return ec.get_error_prefix() + "unable to open file";
|
||||
return ec.make_error("unable to open file");
|
||||
}
|
||||
|
||||
int line_number = 0, starting_line_number = 0;
|
||||
|
@ -423,7 +428,7 @@ static string execute_file_contents(exec_context &ec, const filesystem::path &pa
|
|||
case ';':
|
||||
case '|':
|
||||
if (mode) {
|
||||
retval = execute_from_file(ec, path, starting_line_number, mode, trim(cmdline));
|
||||
retval = TRY(execute_from_file(ec, path, starting_line_number, mode, trim(cmdline)));
|
||||
}
|
||||
|
||||
starting_line_number = line_number;
|
||||
|
@ -435,7 +440,7 @@ static string execute_file_contents(exec_context &ec, const filesystem::path &pa
|
|||
cmdline += line;
|
||||
}
|
||||
else {
|
||||
retval = execute_from_file(ec, path, line_number, ':', line);
|
||||
retval = TRY(execute_from_file(ec, path, line_number, ':', line));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -443,7 +448,7 @@ static string execute_file_contents(exec_context &ec, const filesystem::path &pa
|
|||
}
|
||||
|
||||
if (mode) {
|
||||
retval = execute_from_file(ec, path, starting_line_number, mode, trim(cmdline));
|
||||
retval = TRY(execute_from_file(ec, path, starting_line_number, mode, trim(cmdline)));
|
||||
}
|
||||
|
||||
if (file == stdin) {
|
||||
|
@ -456,113 +461,110 @@ static string execute_file_contents(exec_context &ec, const filesystem::path &pa
|
|||
ec.ec_output_stack.pop_back();
|
||||
ec.ec_path_stack.pop_back();
|
||||
|
||||
return retval;
|
||||
return Ok(retval);
|
||||
}
|
||||
|
||||
string execute_file(exec_context &ec, const string &path_and_args, bool multiline)
|
||||
Result<string, string> execute_file(exec_context &ec, const string &path_and_args, bool multiline)
|
||||
{
|
||||
map<string, vector<script_metadata> > scripts;
|
||||
map<string, vector<script_metadata> >::iterator iter;
|
||||
vector<string> split_args;
|
||||
string msg, retval;
|
||||
string retval, msg;
|
||||
shlex lexer(path_and_args);
|
||||
|
||||
log_info("Executing file: %s", path_and_args.c_str());
|
||||
|
||||
if (!lexer.split(split_args, ec.ec_local_vars.top())) {
|
||||
retval = ec.get_error_prefix() + "unable to parse path";
|
||||
return ec.make_error("unable to parse path");
|
||||
}
|
||||
else if (split_args.empty()) {
|
||||
retval = ec.get_error_prefix() + "no script specified";
|
||||
if (split_args.empty()) {
|
||||
return ec.make_error("no script specified");
|
||||
}
|
||||
else {
|
||||
ec.ec_local_vars.push({});
|
||||
|
||||
auto script_name = split_args[0];
|
||||
map<string, string> &vars = ec.ec_local_vars.top();
|
||||
char env_arg_name[32];
|
||||
string star, result, open_error = "file not found";
|
||||
ec.ec_local_vars.push({});
|
||||
|
||||
add_ansi_vars(vars);
|
||||
auto script_name = split_args[0];
|
||||
map<string, string> &vars = ec.ec_local_vars.top();
|
||||
char env_arg_name[32];
|
||||
string star, open_error = "file not found";
|
||||
|
||||
snprintf(env_arg_name, sizeof(env_arg_name), "%d", (int) split_args.size() - 1);
|
||||
add_ansi_vars(vars);
|
||||
|
||||
vars["#"] = env_arg_name;
|
||||
for (size_t lpc = 0; lpc < split_args.size(); lpc++) {
|
||||
snprintf(env_arg_name, sizeof(env_arg_name), "%lu", lpc);
|
||||
vars[env_arg_name] = split_args[lpc];
|
||||
snprintf(env_arg_name, sizeof(env_arg_name), "%d",
|
||||
(int) split_args.size() - 1);
|
||||
|
||||
vars["#"] = env_arg_name;
|
||||
for (size_t lpc = 0; lpc < split_args.size(); lpc++) {
|
||||
snprintf(env_arg_name, sizeof(env_arg_name), "%lu", lpc);
|
||||
vars[env_arg_name] = split_args[lpc];
|
||||
}
|
||||
for (size_t lpc = 1; lpc < split_args.size(); lpc++) {
|
||||
if (lpc > 1) {
|
||||
star.append(" ");
|
||||
}
|
||||
for (size_t lpc = 1; lpc < split_args.size(); lpc++) {
|
||||
if (lpc > 1) {
|
||||
star.append(" ");
|
||||
}
|
||||
star.append(split_args[lpc]);
|
||||
}
|
||||
vars["__all__"] = star;
|
||||
star.append(split_args[lpc]);
|
||||
}
|
||||
vars["__all__"] = star;
|
||||
|
||||
vector<script_metadata> paths_to_exec;
|
||||
map<string, const char *>::iterator internal_iter;
|
||||
vector<script_metadata> paths_to_exec;
|
||||
map<string, const char *>::iterator internal_iter;
|
||||
|
||||
find_format_scripts(lnav_data.ld_config_paths, scripts);
|
||||
if ((iter = scripts.find(script_name)) != scripts.end()) {
|
||||
paths_to_exec = iter->second;
|
||||
find_format_scripts(lnav_data.ld_config_paths, scripts);
|
||||
if ((iter = scripts.find(script_name)) != scripts.end()) {
|
||||
paths_to_exec = iter->second;
|
||||
}
|
||||
if (script_name == "-" || script_name == "/dev/stdin") {
|
||||
paths_to_exec.push_back({script_name});
|
||||
} else if (access(script_name.c_str(), R_OK) == 0) {
|
||||
struct script_metadata meta;
|
||||
|
||||
meta.sm_path = script_name;
|
||||
extract_metadata_from_file(meta);
|
||||
paths_to_exec.push_back(meta);
|
||||
} else if (errno != ENOENT) {
|
||||
open_error = strerror(errno);
|
||||
} else {
|
||||
auto script_path = filesystem::path(script_name);
|
||||
|
||||
if (!script_path.is_absolute()) {
|
||||
script_path = ec.ec_path_stack.back() / script_path;
|
||||
}
|
||||
if (script_name == "-" || script_name == "/dev/stdin") {
|
||||
paths_to_exec.push_back({script_name});
|
||||
}
|
||||
else if (access(script_name.c_str(), R_OK) == 0) {
|
||||
|
||||
if (script_path.is_file()) {
|
||||
struct script_metadata meta;
|
||||
|
||||
meta.sm_path = script_name;
|
||||
meta.sm_path = script_path;
|
||||
extract_metadata_from_file(meta);
|
||||
paths_to_exec.push_back(meta);
|
||||
}
|
||||
else if (errno != ENOENT) {
|
||||
} else if (errno != ENOENT) {
|
||||
open_error = strerror(errno);
|
||||
}
|
||||
else {
|
||||
auto script_path = filesystem::path(script_name);
|
||||
|
||||
if (!script_path.is_absolute()) {
|
||||
script_path = ec.ec_path_stack.back() / script_path;
|
||||
}
|
||||
|
||||
if (script_path.is_file()) {
|
||||
struct script_metadata meta;
|
||||
|
||||
meta.sm_path = script_path;
|
||||
extract_metadata_from_file(meta);
|
||||
paths_to_exec.push_back(meta);
|
||||
}
|
||||
else if (errno != ENOENT) {
|
||||
open_error = strerror(errno);
|
||||
}
|
||||
}
|
||||
|
||||
if (!paths_to_exec.empty()) {
|
||||
for (auto &path_iter : paths_to_exec) {
|
||||
result = execute_file_contents(ec, path_iter.sm_path, multiline);
|
||||
}
|
||||
retval = result;
|
||||
}
|
||||
else {
|
||||
retval = ec.get_error_prefix()
|
||||
+ "unknown script -- " + script_name + " -- " + open_error;
|
||||
}
|
||||
ec.ec_local_vars.pop();
|
||||
}
|
||||
|
||||
return retval;
|
||||
if (!paths_to_exec.empty()) {
|
||||
for (auto &path_iter : paths_to_exec) {
|
||||
retval = TRY(
|
||||
execute_file_contents(ec, path_iter.sm_path, multiline));
|
||||
}
|
||||
}
|
||||
ec.ec_local_vars.pop();
|
||||
|
||||
if (paths_to_exec.empty()) {
|
||||
return ec.make_error("unknown script -- {} -- {}",
|
||||
script_name, open_error);
|
||||
}
|
||||
|
||||
return Ok(retval);
|
||||
}
|
||||
|
||||
string execute_from_file(exec_context &ec, const filesystem::path &path, int line_number, char mode, const string &cmdline)
|
||||
Result<string, string> execute_from_file(exec_context &ec, const filesystem::path &path, int line_number, char mode, const string &cmdline)
|
||||
{
|
||||
string retval, alt_msg;
|
||||
auto _sg = ec.enter_source(path.str(), line_number);
|
||||
|
||||
ec.ec_source.emplace(path.str(), line_number);
|
||||
switch (mode) {
|
||||
case ':':
|
||||
retval = execute_command(ec, cmdline);
|
||||
retval = TRY(execute_command(ec, cmdline));
|
||||
break;
|
||||
case '/':
|
||||
lnav_data.ld_view_stack.top() | [cmdline] (auto tc) {
|
||||
|
@ -571,36 +573,35 @@ string execute_from_file(exec_context &ec, const filesystem::path &path, int lin
|
|||
break;
|
||||
case ';':
|
||||
setup_logline_table(ec);
|
||||
retval = execute_sql(ec, cmdline, alt_msg);
|
||||
retval = TRY(execute_sql(ec, cmdline, alt_msg));
|
||||
break;
|
||||
case '|':
|
||||
retval = execute_file(ec, cmdline);
|
||||
retval = TRY(execute_file(ec, cmdline));
|
||||
break;
|
||||
default:
|
||||
retval = execute_command(ec, cmdline);
|
||||
retval = TRY(execute_command(ec, cmdline));
|
||||
break;
|
||||
}
|
||||
|
||||
rescan_files();
|
||||
rebuild_indexes();
|
||||
|
||||
log_info("%s:%d:execute result -- %s",
|
||||
path.str().c_str(),
|
||||
line_number,
|
||||
retval.c_str());
|
||||
|
||||
ec.ec_source.pop();
|
||||
|
||||
return retval;
|
||||
return Ok(retval);
|
||||
}
|
||||
|
||||
string execute_any(exec_context &ec, const string &cmdline_with_mode)
|
||||
Result<string, string> execute_any(exec_context &ec, const string &cmdline_with_mode)
|
||||
{
|
||||
string retval, alt_msg, cmdline = cmdline_with_mode.substr(1);
|
||||
auto _cleanup = finally([] {
|
||||
rescan_files();
|
||||
rebuild_indexes();
|
||||
});
|
||||
|
||||
switch (cmdline_with_mode[0]) {
|
||||
case ':':
|
||||
retval = execute_command(ec, cmdline);
|
||||
retval = TRY(execute_command(ec, cmdline));
|
||||
break;
|
||||
case '/':
|
||||
lnav_data.ld_view_stack.top() | [cmdline] (auto tc) {
|
||||
|
@ -609,24 +610,21 @@ string execute_any(exec_context &ec, const string &cmdline_with_mode)
|
|||
break;
|
||||
case ';':
|
||||
setup_logline_table(ec);
|
||||
retval = execute_sql(ec, cmdline, alt_msg);
|
||||
retval = TRY(execute_sql(ec, cmdline, alt_msg));
|
||||
break;
|
||||
case '|': {
|
||||
retval = execute_file(ec, cmdline);
|
||||
retval = TRY(execute_file(ec, cmdline));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
retval = execute_command(ec, cmdline);
|
||||
retval = TRY(execute_command(ec, cmdline));
|
||||
break;
|
||||
}
|
||||
|
||||
rescan_files();
|
||||
rebuild_indexes();
|
||||
|
||||
return retval;
|
||||
return Ok(retval);
|
||||
}
|
||||
|
||||
void execute_init_commands(exec_context &ec, vector<pair<string, string> > &msgs)
|
||||
void execute_init_commands(exec_context &ec, vector<pair<Result<string, string>, string> > &msgs)
|
||||
{
|
||||
if (lnav_data.ld_cmd_init_done) {
|
||||
return;
|
||||
|
@ -637,14 +635,14 @@ void execute_init_commands(exec_context &ec, vector<pair<string, string> > &msgs
|
|||
|
||||
log_info("Executing initial commands");
|
||||
for (auto &cmd : lnav_data.ld_commands) {
|
||||
string msg, alt_msg;
|
||||
string alt_msg;
|
||||
|
||||
wait_for_children();
|
||||
|
||||
ec.ec_source.emplace("command-option", option_index++);
|
||||
switch (cmd.at(0)) {
|
||||
case ':':
|
||||
msg = execute_command(ec, cmd.substr(1));
|
||||
msgs.emplace_back(execute_command(ec, cmd.substr(1)), alt_msg);
|
||||
break;
|
||||
case '/':
|
||||
lnav_data.ld_view_stack.top() | [cmd] (auto tc) {
|
||||
|
@ -653,15 +651,13 @@ void execute_init_commands(exec_context &ec, vector<pair<string, string> > &msgs
|
|||
break;
|
||||
case ';':
|
||||
setup_logline_table(ec);
|
||||
msg = execute_sql(ec, cmd.substr(1), alt_msg);
|
||||
msgs.emplace_back(execute_sql(ec, cmd.substr(1), alt_msg), alt_msg);
|
||||
break;
|
||||
case '|':
|
||||
msg = execute_file(ec, cmd.substr(1));
|
||||
msgs.emplace_back(execute_file(ec, cmd.substr(1)), alt_msg);
|
||||
break;
|
||||
}
|
||||
|
||||
msgs.emplace_back(msg, alt_msg);
|
||||
|
||||
rescan_files();
|
||||
rebuild_indexes();
|
||||
|
||||
|
@ -794,6 +790,7 @@ future<string> pipe_callback(exec_context &ec, const string &cmdline, auto_fd &f
|
|||
cmdline.c_str());
|
||||
lnav_data.ld_file_names[desc]
|
||||
.with_fd(pp->get_fd())
|
||||
.with_include_in_session(false)
|
||||
.with_detect_format(false);
|
||||
lnav_data.ld_files_to_front.emplace_back(desc, 0);
|
||||
if (lnav_data.ld_rl_view != nullptr) {
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <future>
|
||||
#include <string>
|
||||
|
||||
#include "fmt/format.h"
|
||||
#include "optional.hpp"
|
||||
#include "auto_fd.hh"
|
||||
#include "attr_line.hh"
|
||||
|
@ -69,7 +70,14 @@ struct exec_context {
|
|||
|
||||
std::pair<std::string, int> source = this->ec_source.top();
|
||||
|
||||
return "error:" + source.first + ":" + std::to_string(source.second) + ":";
|
||||
return fmt::format("{}:{}: error: ", source.first, source.second);
|
||||
}
|
||||
|
||||
template<typename ...Args>
|
||||
Result<std::string, std::string> make_error(
|
||||
fmt::string_view format_str, const Args& ...args) {
|
||||
return Err(this->get_error_prefix() +
|
||||
fmt::vformat(format_str, fmt::make_format_args(args...)));
|
||||
}
|
||||
|
||||
nonstd::optional<FILE *> get_output() {
|
||||
|
@ -84,6 +92,23 @@ struct exec_context {
|
|||
return nonstd::nullopt;
|
||||
}
|
||||
|
||||
struct source_guard {
|
||||
source_guard(exec_context &context) : sg_context(context) {
|
||||
|
||||
}
|
||||
|
||||
~source_guard() {
|
||||
this->sg_context.ec_source.pop();
|
||||
}
|
||||
|
||||
exec_context &sg_context;
|
||||
};
|
||||
|
||||
source_guard enter_source(const std::string path, int line_number) {
|
||||
this->ec_source.emplace(path, line_number);
|
||||
return source_guard(*this);
|
||||
}
|
||||
|
||||
vis_line_t ec_top_line;
|
||||
bool ec_dry_run;
|
||||
|
||||
|
@ -101,18 +126,23 @@ struct exec_context {
|
|||
pipe_callback_t ec_pipe_callback;
|
||||
};
|
||||
|
||||
std::string execute_command(exec_context &ec, const std::string &cmdline);
|
||||
Result<std::string, std::string> execute_command(exec_context &ec, const std::string &cmdline);
|
||||
|
||||
std::string execute_sql(exec_context &ec, const std::string &sql, std::string &alt_msg);
|
||||
std::string execute_file(exec_context &ec, const std::string &path_and_args, bool multiline = true);
|
||||
std::string execute_any(exec_context &ec, const std::string &cmdline);
|
||||
void execute_init_commands(exec_context &ec, std::vector<std::pair<std::string, std::string> > &msgs);
|
||||
Result<std::string, std::string> execute_sql(exec_context &ec, const std::string &sql, std::string &alt_msg);
|
||||
Result<std::string, std::string> execute_file(exec_context &ec, const std::string &path_and_args, bool multiline = true);
|
||||
Result<std::string, std::string> execute_any(exec_context &ec, const std::string &cmdline);
|
||||
void execute_init_commands(exec_context &ec, std::vector<std::pair<Result<std::string, std::string>, std::string> > &msgs);
|
||||
|
||||
int sql_callback(exec_context &ec, sqlite3_stmt *stmt);
|
||||
std::future<std::string> pipe_callback(
|
||||
exec_context &ec, const std::string &cmdline, auto_fd &fd);
|
||||
|
||||
inline Result<std::string, std::string> err_to_ok(const std::string msg) {
|
||||
return Ok(msg);
|
||||
}
|
||||
|
||||
int sql_progress(const struct log_cursor &lc);
|
||||
void sql_progress_finished();
|
||||
|
||||
void add_global_vars(exec_context &ec);
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "base/lnav_log.hh"
|
||||
#include "sql_util.hh"
|
||||
#include "file_vtab.hh"
|
||||
#include "session_data.hh"
|
||||
#include "vtab_module.hh"
|
||||
|
||||
using namespace std;
|
||||
|
@ -128,7 +129,7 @@ CREATE TABLE lnav_file (
|
|||
sqlite3_int64 &rowid,
|
||||
int64_t device,
|
||||
int64_t inode,
|
||||
const char *path,
|
||||
std::string path,
|
||||
const char *format,
|
||||
int64_t lines,
|
||||
int64_t time_offset) {
|
||||
|
@ -140,6 +141,29 @@ CREATE TABLE lnav_file (
|
|||
|
||||
lf->adjust_content_time(0, tv, true);
|
||||
|
||||
if (path != lf->get_filename()) {
|
||||
if (lf->is_valid_filename()) {
|
||||
throw sqlite_func_error(
|
||||
"real file paths cannot be updated, only symbolic ones");
|
||||
}
|
||||
|
||||
auto iter = lnav_data.ld_file_names.find(lf->get_filename());
|
||||
|
||||
if (iter != lnav_data.ld_file_names.end()) {
|
||||
auto loo = iter->second;
|
||||
|
||||
lnav_data.ld_file_names.erase(iter);
|
||||
|
||||
loo.loo_include_in_session = true;
|
||||
lnav_data.ld_file_names[path] = loo;
|
||||
lf->set_filename(path);
|
||||
|
||||
init_session();
|
||||
load_session();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return SQLITE_OK;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -136,7 +136,7 @@ string sql_readlink(const char *path)
|
|||
struct stat st;
|
||||
|
||||
if (lstat(path, &st) == -1) {
|
||||
throw sqlite_func_error("unable to stat path: %s -- %s", path, strerror(errno));
|
||||
throw sqlite_func_error("unable to stat path: {} -- {}", path, strerror(errno));
|
||||
}
|
||||
|
||||
char buf[st.st_size];
|
||||
|
@ -147,7 +147,7 @@ string sql_readlink(const char *path)
|
|||
if (errno == EINVAL) {
|
||||
return path;
|
||||
}
|
||||
throw sqlite_func_error("unable to read link: %s -- %s", path, strerror(errno));
|
||||
throw sqlite_func_error("unable to read link: {} -- {}", path, strerror(errno));
|
||||
}
|
||||
|
||||
return string(buf, rc);
|
||||
|
@ -159,7 +159,7 @@ string sql_realpath(const char *path)
|
|||
char resolved_path[PATH_MAX];
|
||||
|
||||
if (realpath(path, resolved_path) == NULL) {
|
||||
throw sqlite_func_error("Could not get real path for %s -- %s",
|
||||
throw sqlite_func_error("Could not get real path for {} -- {}",
|
||||
path, strerror(errno));
|
||||
}
|
||||
|
||||
|
|
|
@ -140,7 +140,6 @@ bool handle_keyseq(const char *keyseq)
|
|||
vector<logline_value> values;
|
||||
exec_context ec(&values, key_sql_callback, pipe_callback);
|
||||
auto &var_stack = ec.ec_local_vars;
|
||||
string result;
|
||||
|
||||
ec.ec_global_vars = lnav_data.ld_exec_context.ec_global_vars;
|
||||
var_stack.push(map<string, string>());
|
||||
|
@ -149,8 +148,8 @@ bool handle_keyseq(const char *keyseq)
|
|||
const auto &kc = iter->second;
|
||||
|
||||
log_debug("executing key sequence x%02x: %s", keyseq, kc.kc_cmd.c_str());
|
||||
result = execute_any(ec, kc.kc_cmd);
|
||||
lnav_data.ld_rl_view->set_value(result);
|
||||
auto result = execute_any(ec, kc.kc_cmd);
|
||||
lnav_data.ld_rl_view->set_value(result.orElse(err_to_ok).unwrap());
|
||||
|
||||
if (!kc.kc_alt_msg.empty()) {
|
||||
shlex lexer(kc.kc_alt_msg);
|
||||
|
|
40
src/lnav.cc
40
src/lnav.cc
|
@ -132,7 +132,6 @@
|
|||
#include <curl/curl.h>
|
||||
#endif
|
||||
|
||||
#include "papertrail_proc.hh"
|
||||
#include "yajlpp/yajlpp.hh"
|
||||
#include "readline_callbacks.hh"
|
||||
#include "command_executor.hh"
|
||||
|
@ -1675,7 +1674,7 @@ static void looper()
|
|||
|
||||
if (!session_loaded) {
|
||||
load_session();
|
||||
if (!lnav_data.ld_session_file_names.empty()) {
|
||||
if (lnav_data.ld_session_save_time) {
|
||||
std::string ago;
|
||||
|
||||
ago = time_ago(lnav_data.ld_session_save_time);
|
||||
|
@ -1685,15 +1684,16 @@ static void looper()
|
|||
(ANSI_NORM "; press Ctrl-R to reset session"));
|
||||
}
|
||||
|
||||
vector<pair<string, string> > msgs;
|
||||
vector<pair<Result<string, string>, string>> cmd_results;
|
||||
|
||||
execute_init_commands(ec, msgs);
|
||||
execute_init_commands(ec, cmd_results);
|
||||
|
||||
if (!msgs.empty()) {
|
||||
pair<string, string> last_msg = msgs.back();
|
||||
if (!cmd_results.empty()) {
|
||||
auto last_cmd_result = cmd_results.back();
|
||||
|
||||
lnav_data.ld_rl_view->set_value(last_msg.first);
|
||||
lnav_data.ld_rl_view->set_alt_value(last_msg.second);
|
||||
lnav_data.ld_rl_view->set_value(
|
||||
last_cmd_result.first.orElse(err_to_ok).unwrap());
|
||||
lnav_data.ld_rl_view->set_alt_value(last_cmd_result.second);
|
||||
}
|
||||
|
||||
session_loaded = true;
|
||||
|
@ -2403,7 +2403,8 @@ int main(int argc, char *argv[])
|
|||
stdin_reader = make_shared<piper_proc>(
|
||||
STDIN_FILENO, lnav_data.ld_flags & LNF_TIMESTAMP, stdin_out_fd);
|
||||
lnav_data.ld_file_names["stdin"]
|
||||
.with_fd(stdin_out_fd);
|
||||
.with_fd(stdin_out_fd)
|
||||
.with_include_in_session(false);
|
||||
if (dup2(STDOUT_FILENO, STDIN_FILENO) == -1) {
|
||||
perror("cannot dup stdout to stdin");
|
||||
}
|
||||
|
@ -2457,8 +2458,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
if (lnav_data.ld_flags & LNF_HEADLESS) {
|
||||
std::vector<pair<string, string> > msgs;
|
||||
std::vector<pair<string, string> >::iterator msg_iter;
|
||||
std::vector<pair<Result<string, string>, string>> cmd_results;
|
||||
textview_curses *log_tc, *text_tc, *tc;
|
||||
bool found_error = false;
|
||||
|
||||
|
@ -2483,21 +2483,19 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
log_info("Executing initial commands");
|
||||
execute_init_commands(lnav_data.ld_exec_context, msgs);
|
||||
execute_init_commands(lnav_data.ld_exec_context, cmd_results);
|
||||
wait_for_pipers();
|
||||
lnav_data.ld_curl_looper.process_all();
|
||||
rebuild_indexes();
|
||||
|
||||
for (msg_iter = msgs.begin();
|
||||
msg_iter != msgs.end();
|
||||
++msg_iter) {
|
||||
if (strncmp("error:", msg_iter->first.c_str(), 6) == 0) {
|
||||
fprintf(stderr, "%s\n", msg_iter->first.c_str());
|
||||
for (auto &pair : cmd_results) {
|
||||
if (pair.first.isErr()) {
|
||||
fprintf(stderr, "%s\n", pair.first.unwrapErr().c_str());
|
||||
found_error = true;
|
||||
}
|
||||
else if (startswith(msg_iter->first, "info:") &&
|
||||
else if (startswith(pair.first.unwrap(), "info:") &&
|
||||
lnav_data.ld_flags & LNF_VERBOSE) {
|
||||
printf("%s\n", msg_iter->first.c_str());
|
||||
printf("%s\n", pair.first.unwrap().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2578,10 +2576,6 @@ int main(int argc, char *argv[])
|
|||
|
||||
init_session();
|
||||
|
||||
log_info(" session_id=%s", lnav_data.ld_session_id.c_str());
|
||||
|
||||
scan_sessions();
|
||||
|
||||
guard_termios gt(STDIN_FILENO);
|
||||
auto_fd::pipe(errpipe);
|
||||
|
||||
|
|
|
@ -214,12 +214,10 @@ struct key_repeat_history {
|
|||
};
|
||||
|
||||
struct _lnav_data {
|
||||
std::string ld_session_id;
|
||||
std::map<std::string, std::list<session_pair_t>> ld_session_id;
|
||||
time_t ld_session_time;
|
||||
time_t ld_session_load_time;
|
||||
time_t ld_session_save_time;
|
||||
std::list<session_pair_t> ld_session_file_names;
|
||||
int ld_session_file_index;
|
||||
const char * ld_program_name;
|
||||
const char * ld_debug_log_name;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -513,4 +513,17 @@ inline int openp(const filesystem::path &path, int flags, mode_t mode) {
|
|||
Result<std::pair<filesystem::path, int>, std::string>
|
||||
open_temp_file(const filesystem::path &pattern);
|
||||
|
||||
template<typename A>
|
||||
struct final_action { // slightly simplified
|
||||
A act;
|
||||
final_action(A a) :act{a} {}
|
||||
~final_action() { act(); }
|
||||
};
|
||||
|
||||
template<typename A>
|
||||
final_action<A> finally(A act) // deduce action type
|
||||
{
|
||||
return final_action<A>{act};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -898,11 +898,12 @@ void external_log_format::rewrite(exec_context &ec,
|
|||
continue;
|
||||
}
|
||||
|
||||
ec.ec_source.emplace(this->elf_name.to_string() +
|
||||
":" +
|
||||
vd_iter->first.to_string(),
|
||||
1);
|
||||
string field_value = execute_any(ec, vd.vd_rewriter);
|
||||
auto _sg = ec.enter_source(this->elf_name.to_string() +
|
||||
":" +
|
||||
vd_iter->first.to_string(),
|
||||
1);
|
||||
string field_value = execute_any(ec, vd.vd_rewriter)
|
||||
.orElse(err_to_ok).unwrap();
|
||||
struct line_range adj_origin = iter->origin_in_full_msg(
|
||||
value_out.c_str(), value_out.length());
|
||||
|
||||
|
|
|
@ -194,9 +194,11 @@ protected:
|
|||
};
|
||||
|
||||
typedef int (*sql_progress_callback_t)(const log_cursor &lc);
|
||||
typedef void (*sql_progress_finished_callback_t)();
|
||||
|
||||
extern struct _log_vtab_data {
|
||||
sql_progress_callback_t lvd_progress;
|
||||
sql_progress_finished_callback_t lvd_finished;
|
||||
std::string lvd_source;
|
||||
int lvd_line_number{0};
|
||||
} log_vtab_data;
|
||||
|
@ -204,15 +206,21 @@ extern struct _log_vtab_data {
|
|||
class sql_progress_guard {
|
||||
public:
|
||||
sql_progress_guard(sql_progress_callback_t cb,
|
||||
sql_progress_finished_callback_t fcb,
|
||||
const std::string &source,
|
||||
int line_number) {
|
||||
log_vtab_data.lvd_progress = cb;
|
||||
log_vtab_data.lvd_finished = fcb;
|
||||
log_vtab_data.lvd_source = source;
|
||||
log_vtab_data.lvd_line_number = line_number;
|
||||
};
|
||||
|
||||
~sql_progress_guard() {
|
||||
log_vtab_data.lvd_progress = NULL;
|
||||
if (log_vtab_data.lvd_finished) {
|
||||
log_vtab_data.lvd_finished();
|
||||
}
|
||||
log_vtab_data.lvd_progress = nullptr;
|
||||
log_vtab_data.lvd_finished = nullptr;
|
||||
log_vtab_data.lvd_source.clear();
|
||||
log_vtab_data.lvd_line_number = 0;
|
||||
};
|
||||
|
|
|
@ -90,8 +90,15 @@ struct logfile_open_options {
|
|||
return *this;
|
||||
};
|
||||
|
||||
logfile_open_options &with_include_in_session(bool val) {
|
||||
this->loo_include_in_session = val;
|
||||
|
||||
return *this;
|
||||
};
|
||||
|
||||
auto_fd loo_fd;
|
||||
bool loo_detect_format;
|
||||
bool loo_include_in_session{true};
|
||||
};
|
||||
|
||||
struct logfile_activity {
|
||||
|
|
|
@ -294,7 +294,8 @@ static void rl_search_internal(void *dummy, readline_curses *rc, bool complete =
|
|||
|
||||
lnav_data.ld_preview_status_source.get_description().clear();
|
||||
lnav_data.ld_preview_source.clear();
|
||||
string result = execute_command(lnav_data.ld_exec_context, rc->get_value());
|
||||
string result = execute_command(lnav_data.ld_exec_context, rc->get_value())
|
||||
.orElse(err_to_ok).unwrap();
|
||||
|
||||
if (result.empty()) {
|
||||
lnav_data.ld_bottom_source.set_prompt(LNAV_CMD_PROMPT);
|
||||
|
@ -548,7 +549,8 @@ void rl_callback(void *dummy, readline_curses *rc)
|
|||
|
||||
case LNM_COMMAND:
|
||||
rc->set_alt_value("");
|
||||
rc->set_value(execute_command(ec, rc->get_value()));
|
||||
rc->set_value(execute_command(ec, rc->get_value())
|
||||
.orElse(err_to_ok).unwrap());
|
||||
break;
|
||||
|
||||
case LNM_SEARCH:
|
||||
|
@ -577,7 +579,8 @@ void rl_callback(void *dummy, readline_curses *rc)
|
|||
break;
|
||||
|
||||
case LNM_SQL: {
|
||||
string result = execute_sql(ec, rc->get_value(), alt_msg);
|
||||
string result = execute_sql(ec, rc->get_value(), alt_msg)
|
||||
.orElse(err_to_ok).unwrap();
|
||||
db_label_source &dls = lnav_data.ld_db_row_source;
|
||||
|
||||
if (!result.empty()) {
|
||||
|
@ -608,7 +611,8 @@ void rl_callback(void *dummy, readline_curses *rc)
|
|||
string path_and_args = rc->get_value();
|
||||
|
||||
ec.ec_output_stack.back() = tmpout.in();
|
||||
string result = execute_file(ec, path_and_args);
|
||||
string result = execute_file(ec, path_and_args)
|
||||
.orElse(err_to_ok).unwrap();
|
||||
string::size_type lf_index = result.find('\n');
|
||||
if (lf_index != string::npos) {
|
||||
result = result.substr(0, lf_index);
|
||||
|
@ -628,6 +632,7 @@ void rl_callback(void *dummy, readline_curses *rc)
|
|||
timestamp);
|
||||
lnav_data.ld_file_names[desc]
|
||||
.with_fd(fd_copy)
|
||||
.with_include_in_session(false)
|
||||
.with_detect_format(false);
|
||||
lnav_data.ld_files_to_front.emplace_back(desc, 0);
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
|
||||
#include "base/result.h"
|
||||
#include "auto_fd.hh"
|
||||
#include "vt52_curses.hh"
|
||||
#include "log_format.hh"
|
||||
|
@ -69,7 +70,7 @@ extern exec_context INIT_EXEC_CONTEXT;
|
|||
*/
|
||||
class readline_context {
|
||||
public:
|
||||
typedef std::string (*command_func_t)(exec_context &ec,
|
||||
typedef Result<std::string, std::string> (*command_func_t)(exec_context &ec,
|
||||
std::string cmdline, std::vector<std::string> &args);
|
||||
typedef std::string (*prompt_func_t)(exec_context &ec,
|
||||
const std::string &cmdline);
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
#
|
||||
# @synopsis: rename-stdin <name>
|
||||
# @description: Give a symbolic name to the standard-input file
|
||||
#
|
||||
|
||||
;SELECT raise_error('expecting the new name for stdin as the first argument') WHERE $1 IS NULL
|
||||
;SELECT raise_error('no data was redirected to lnav''s standard-input')
|
||||
WHERE (SELECT count(1) FROM lnav_file WHERE filepath='stdin') = 0
|
||||
|
||||
;UPDATE lnav_file SET filepath=$1 WHERE filepath='stdin'
|
||||
|
||||
;SELECT 'info: renamed stdin to ' || $1 AS msg
|
|
@ -289,57 +289,59 @@ static void cleanup_session_data()
|
|||
}
|
||||
|
||||
void init_session()
|
||||
{
|
||||
lnav_data.ld_session_time = time(nullptr);
|
||||
lnav_data.ld_session_id.clear();
|
||||
}
|
||||
|
||||
static nonstd::optional<std::string> compute_session_id()
|
||||
{
|
||||
byte_array<2, uint64> hash;
|
||||
SpookyHash context;
|
||||
|
||||
lnav_data.ld_session_time = time(nullptr);
|
||||
bool has_files = false;
|
||||
|
||||
context.Init(0, 0);
|
||||
hash_updater updater(&context);
|
||||
for (auto &ld_file_name : lnav_data.ld_file_names) {
|
||||
if (!ld_file_name.second.loo_include_in_session) {
|
||||
continue;
|
||||
}
|
||||
has_files = true;
|
||||
updater(ld_file_name.first);
|
||||
}
|
||||
if (!has_files) {
|
||||
return nonstd::nullopt;
|
||||
}
|
||||
context.Final(hash.out(0), hash.out(1));
|
||||
|
||||
lnav_data.ld_session_id = hash.to_string();
|
||||
|
||||
log_info("init_session: time=%d; id=%s", lnav_data.ld_session_time,
|
||||
lnav_data.ld_session_id.c_str());
|
||||
return hash.to_string();
|
||||
}
|
||||
|
||||
void scan_sessions()
|
||||
nonstd::optional<session_pair_t> scan_sessions()
|
||||
{
|
||||
std::list<session_pair_t> &session_file_names =
|
||||
lnav_data.ld_session_file_names;
|
||||
|
||||
static_root_mem<glob_t, globfree> view_info_list;
|
||||
std::list<session_pair_t>::iterator iter;
|
||||
char view_info_pattern_base[128];
|
||||
string old_session_name;
|
||||
int index;
|
||||
static_root_mem<glob_t, globfree> view_info_list;
|
||||
char view_info_pattern_base[128];
|
||||
|
||||
cleanup_session_data();
|
||||
|
||||
if (lnav_data.ld_session_file_index >= 0 &&
|
||||
lnav_data.ld_session_file_index < (int)session_file_names.size()) {
|
||||
iter = session_file_names.begin();
|
||||
|
||||
advance(iter, lnav_data.ld_session_file_index);
|
||||
old_session_name = iter->second;
|
||||
const auto session_id = compute_session_id();
|
||||
if (!session_id) {
|
||||
return nonstd::nullopt;
|
||||
}
|
||||
std::list<session_pair_t> &session_file_names =
|
||||
lnav_data.ld_session_id[session_id.value()];
|
||||
|
||||
session_file_names.clear();
|
||||
|
||||
snprintf(view_info_pattern_base, sizeof(view_info_pattern_base),
|
||||
"view-info-%s.*.json",
|
||||
lnav_data.ld_session_id.c_str());
|
||||
session_id.value().c_str());
|
||||
auto view_info_pattern = dotlnav_path() / view_info_pattern_base;
|
||||
if (glob(view_info_pattern.str().c_str(), 0, nullptr,
|
||||
view_info_list.inout()) == 0) {
|
||||
for (size_t lpc = 0; lpc < view_info_list->gl_pathc; lpc++) {
|
||||
const char *path = view_info_list->gl_pathv[lpc];
|
||||
int timestamp, ppid, rc;
|
||||
int timestamp, ppid, rc;
|
||||
const char *base;
|
||||
|
||||
base = strrchr(path, '/');
|
||||
|
@ -374,16 +376,11 @@ void scan_sessions()
|
|||
session_file_names.pop_front();
|
||||
}
|
||||
|
||||
lnav_data.ld_session_file_index = ((int)session_file_names.size()) - 1;
|
||||
|
||||
for (index = 0, iter = session_file_names.begin();
|
||||
iter != session_file_names.end();
|
||||
index++, ++iter) {
|
||||
if (iter->second == old_session_name) {
|
||||
lnav_data.ld_session_file_index = index;
|
||||
break;
|
||||
}
|
||||
if (session_file_names.empty()) {
|
||||
return nonstd::nullopt;
|
||||
}
|
||||
|
||||
return nonstd::make_optional(session_file_names.back());
|
||||
}
|
||||
|
||||
static void load_time_bookmarks()
|
||||
|
@ -832,40 +829,35 @@ static struct json_path_handler view_info_handlers[] = {
|
|||
|
||||
void load_session()
|
||||
{
|
||||
std::list<session_pair_t>::iterator sess_iter;
|
||||
yajl_handle handle;
|
||||
auto_fd fd;
|
||||
|
||||
if (lnav_data.ld_session_file_names.empty()) {
|
||||
load_time_bookmarks();
|
||||
return;
|
||||
}
|
||||
|
||||
sess_iter = lnav_data.ld_session_file_names.begin();
|
||||
advance(sess_iter, lnav_data.ld_session_file_index);
|
||||
lnav_data.ld_session_load_time = sess_iter->first.second;
|
||||
lnav_data.ld_session_save_time = sess_iter->first.second;
|
||||
string &view_info_name = sess_iter->second;
|
||||
|
||||
yajlpp_parse_context ypc(view_info_name, view_info_handlers);
|
||||
handle = yajl_alloc(&ypc.ypc_callbacks, nullptr, &ypc);
|
||||
|
||||
load_time_bookmarks();
|
||||
scan_sessions() | [](const auto pair) {
|
||||
yajl_handle handle;
|
||||
auto_fd fd;
|
||||
|
||||
if ((fd = open(view_info_name.c_str(), O_RDONLY)) < 0) {
|
||||
perror("cannot open session file");
|
||||
}
|
||||
else {
|
||||
unsigned char buffer[1024];
|
||||
ssize_t rc;
|
||||
lnav_data.ld_session_load_time = pair.first.second;
|
||||
lnav_data.ld_session_save_time = pair.first.second;
|
||||
const string &view_info_name = pair.second;
|
||||
|
||||
log_info("loading session file: %s", view_info_name.c_str());
|
||||
while ((rc = read(fd, buffer, sizeof(buffer))) > 0) {
|
||||
yajl_parse(handle, buffer, rc);
|
||||
yajlpp_parse_context ypc(view_info_name, view_info_handlers);
|
||||
handle = yajl_alloc(&ypc.ypc_callbacks, nullptr, &ypc);
|
||||
|
||||
load_time_bookmarks();
|
||||
|
||||
if ((fd = open(view_info_name.c_str(), O_RDONLY)) < 0) {
|
||||
perror("cannot open session file");
|
||||
}
|
||||
yajl_complete_parse(handle);
|
||||
}
|
||||
yajl_free(handle);
|
||||
else {
|
||||
unsigned char buffer[1024];
|
||||
ssize_t rc;
|
||||
|
||||
log_info("loading session file: %s", view_info_name.c_str());
|
||||
while ((rc = read(fd, buffer, sizeof(buffer))) > 0) {
|
||||
yajl_parse(handle, buffer, rc);
|
||||
}
|
||||
yajl_complete_parse(handle);
|
||||
}
|
||||
yajl_free(handle);
|
||||
};
|
||||
}
|
||||
|
||||
static void yajl_writer(void *context, const char *str, size_t len)
|
||||
|
@ -1215,19 +1207,19 @@ static void save_time_bookmarks()
|
|||
}
|
||||
}
|
||||
|
||||
void save_session()
|
||||
static void save_session_with_id(const std::string session_id)
|
||||
{
|
||||
auto_mem<FILE> file(fclose);
|
||||
yajl_gen handle = nullptr;
|
||||
|
||||
save_time_bookmarks();
|
||||
yajl_gen handle = nullptr;
|
||||
|
||||
/* TODO: save the last search query */
|
||||
|
||||
log_info("saving session with id: %s", session_id.c_str());
|
||||
|
||||
char view_base_name[256];
|
||||
snprintf(view_base_name, sizeof(view_base_name),
|
||||
"view-info-%s.ts%ld.ppid%d.json",
|
||||
lnav_data.ld_session_id.c_str(),
|
||||
session_id.c_str(),
|
||||
lnav_data.ld_session_time,
|
||||
getppid());
|
||||
|
||||
|
@ -1384,12 +1376,27 @@ void save_session()
|
|||
}
|
||||
}
|
||||
|
||||
void save_session()
|
||||
{
|
||||
save_time_bookmarks();
|
||||
|
||||
const auto opt_session_id = compute_session_id();
|
||||
opt_session_id | [](auto &session_id) {
|
||||
save_session_with_id(session_id);
|
||||
};
|
||||
for (const auto pair : lnav_data.ld_session_id) {
|
||||
if (opt_session_id && pair.first == opt_session_id.value()) {
|
||||
continue;
|
||||
}
|
||||
save_session_with_id(pair.first);
|
||||
}
|
||||
}
|
||||
|
||||
void reset_session()
|
||||
{
|
||||
log_info("reset session: time=%d", lnav_data.ld_session_time);
|
||||
|
||||
save_session();
|
||||
scan_sessions();
|
||||
|
||||
lnav_data.ld_session_time = time(nullptr);
|
||||
|
||||
|
|
|
@ -32,10 +32,9 @@
|
|||
#ifndef _session_data_hh
|
||||
#define _session_data_hh
|
||||
|
||||
void init_session(void);
|
||||
void load_session(void);
|
||||
void save_session(void);
|
||||
void reset_session(void);
|
||||
void scan_sessions(void);
|
||||
void init_session();
|
||||
void load_session();
|
||||
void save_session();
|
||||
void reset_session();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -47,6 +47,11 @@ struct FuncDef {
|
|||
uint8_t needCollSeq;
|
||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
|
||||
help_text fd_help;
|
||||
|
||||
FuncDef &with_flags(int flags) {
|
||||
this->eTextRep = flags;
|
||||
return *this;
|
||||
};
|
||||
};
|
||||
|
||||
struct FuncDefAgg {
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
#include <exception>
|
||||
|
||||
#include "sqlite3.h"
|
||||
|
||||
|
@ -56,10 +57,15 @@ static std::string sql_log_top_datetime()
|
|||
return buffer;
|
||||
}
|
||||
|
||||
static int64_t sql_error(const std::string str)
|
||||
{
|
||||
throw sqlite_func_error("{}", str);
|
||||
}
|
||||
|
||||
int state_extension_functions(struct FuncDef **basic_funcs,
|
||||
struct FuncDefAgg **agg_funcs)
|
||||
{
|
||||
static struct FuncDef datetime_funcs[] = {
|
||||
static struct FuncDef state_funcs[] = {
|
||||
sqlite_func_adapter<decltype(&sql_log_top_line), sql_log_top_line>::builder(
|
||||
help_text("log_top_line",
|
||||
"Return the line number at the top of the log view.")
|
||||
|
@ -72,10 +78,17 @@ int state_extension_functions(struct FuncDef **basic_funcs,
|
|||
.sql_function()
|
||||
),
|
||||
|
||||
sqlite_func_adapter<decltype(&sql_error), sql_error>::builder(
|
||||
help_text("raise_error",
|
||||
"Raises an error with the given message when executed")
|
||||
.sql_function()
|
||||
.with_parameter({"msg", "The error message"})
|
||||
).with_flags(SQLITE_UTF8),
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
*basic_funcs = datetime_funcs;
|
||||
*basic_funcs = state_funcs;
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ static string timeslice(const char *time_in, nonstd::optional<const char *> slic
|
|||
dts.set_base_time(now);
|
||||
|
||||
if (!rt.parse(slice_in, strlen(slice_in), pe)) {
|
||||
throw sqlite_func_error("unable to parse time slice value");
|
||||
throw sqlite_func_error("unable to parse time slice value -- {}", slice_in);
|
||||
}
|
||||
|
||||
if (rt.empty()) {
|
||||
|
@ -73,7 +73,7 @@ static string timeslice(const char *time_in, nonstd::optional<const char *> slic
|
|||
struct timeval tv;
|
||||
|
||||
if (dts.scan(time_in, strlen(time_in), NULL, &tm, tv) == NULL) {
|
||||
throw sqlite_func_error("unable to parse time value");
|
||||
throw sqlite_func_error("unable to parse time value -- {}", time_in);
|
||||
}
|
||||
|
||||
int64_t us = tv.tv_sec * 1000000LL + tv.tv_usec, remainder;
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "auto_mem.hh"
|
||||
#include "yajl/api/yajl_gen.h"
|
||||
#include "mapbox/variant.hpp"
|
||||
#include "fmt/format.h"
|
||||
|
||||
#include "sqlite-extension-func.hh"
|
||||
|
||||
|
@ -56,22 +57,17 @@ struct from_sqlite_conversion_error : std::exception {
|
|||
};
|
||||
|
||||
struct sqlite_func_error : std::exception {
|
||||
sqlite_func_error(const char *fmt, ...) {
|
||||
char buffer[1024];
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
vsnprintf(buffer, sizeof(buffer), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
this->e_what = buffer;
|
||||
};
|
||||
template<typename ...Args>
|
||||
sqlite_func_error(
|
||||
fmt::string_view format_str, const Args& ...args) :
|
||||
e_what(fmt::vformat(format_str, fmt::make_format_args(args...))) {
|
||||
}
|
||||
|
||||
const char *what() const noexcept {
|
||||
return this->e_what.c_str();
|
||||
}
|
||||
|
||||
std::string e_what;
|
||||
const std::string e_what;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
@ -129,8 +125,8 @@ struct from_sqlite<const char *> {
|
|||
};
|
||||
|
||||
template<>
|
||||
struct from_sqlite<const std::string &> {
|
||||
inline const std::string operator()(int argc, sqlite3_value **val, int argi) {
|
||||
struct from_sqlite<std::string> {
|
||||
inline std::string operator()(int argc, sqlite3_value **val, int argi) {
|
||||
return std::string((const char *) sqlite3_value_text(val[argi]));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -9,6 +9,7 @@ RM_V_0 = @echo " RM " $@;
|
|||
AM_CPPFLAGS = \
|
||||
-Wall \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/fmtlib \
|
||||
$(READLINE_CFLAGS) \
|
||||
$(SQLITE3_CFLAGS)
|
||||
|
||||
|
|
|
@ -1601,6 +1601,12 @@ Examples
|
|||
|
||||
|
||||
|
||||
Synopsis
|
||||
raise_error(msg) -- Raises an error with the given message when executed
|
||||
Parameter
|
||||
msg The error message
|
||||
|
||||
|
||||
Synopsis
|
||||
random() -- Returns a pseudo-random integer between -9223372036854775808 and
|
||||
+9223372036854775807.
|
||||
|
|
|
@ -48,7 +48,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "hide-fields with unknown" <<EOF
|
||||
error: unknown field(s) -- foobar
|
||||
command-option:1: error: unknown field(s) -- foobar
|
||||
EOF
|
||||
|
||||
run_test ${lnav_test} -n \
|
||||
|
@ -83,7 +83,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "config bad option" <<EOF
|
||||
error: unknown configuration option -- /bad/option
|
||||
command-option:1: error: unknown configuration option -- /bad/option
|
||||
EOF
|
||||
|
||||
check_output "config bad option" <<EOF
|
||||
|
@ -149,7 +149,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "include nonexistent" <<EOF
|
||||
error:command-option:1:unknown script -- nonexistent.lnav -- file not found
|
||||
command-option:1: error: unknown script -- nonexistent.lnav -- file not found
|
||||
EOF
|
||||
|
||||
|
||||
|
@ -231,7 +231,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "goto invalid is working" <<EOF
|
||||
error: expecting line number/percentage, timestamp, or relative time
|
||||
command-option:1: error: expecting line number/percentage, timestamp, or relative time
|
||||
EOF
|
||||
|
||||
check_output "goto invalid is not working" <<EOF
|
||||
|
@ -276,7 +276,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "goto invalid is not working" <<EOF
|
||||
error: unknown bookmark type
|
||||
command-option:2: error: unknown bookmark type
|
||||
EOF
|
||||
|
||||
check_output "invalid mark-type is working" <<EOF
|
||||
|
@ -426,7 +426,7 @@ run_test eval ${lnav_test} -d /tmp/lnav.err -n \
|
|||
$TOO_MANY_FILTERS \
|
||||
${test_dir}/logfile_filter.0
|
||||
check_error_output "able to create too many filters?" <<EOF
|
||||
error: filter limit reached, try combining filters with a pipe symbol (e.g. foo|bar)
|
||||
command-option:33: error: filter limit reached, try combining filters with a pipe symbol (e.g. foo|bar)
|
||||
EOF
|
||||
|
||||
|
||||
|
@ -444,7 +444,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "double close works" <<EOF
|
||||
error: no log files loaded
|
||||
command-option:2: error: no log files loaded
|
||||
EOF
|
||||
|
||||
check_output "double close is working" <<EOF
|
||||
|
@ -469,7 +469,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "open non-existent is working" <<EOF
|
||||
error: cannot stat file: /non-existent -- No such file or directory
|
||||
command-option:2: error: cannot stat file: /non-existent -- No such file or directory
|
||||
EOF
|
||||
|
||||
check_output "open non-existent is not working" <<EOF
|
||||
|
@ -584,7 +584,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "We managed to bypass LNAVSECURE mode" <<EOF
|
||||
error: write-json-to -- unavailable in secure mode
|
||||
command-option:2: error: write-json-to -- unavailable in secure mode
|
||||
EOF
|
||||
unset LNAVSECURE
|
||||
|
||||
|
@ -783,7 +783,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "clear-highlight did not report an error?" <<EOF
|
||||
error: highlight does not exist
|
||||
command-option:1: error: highlight does not exist -- foobar
|
||||
EOF
|
||||
|
||||
run_test ${lnav_test} -n \
|
||||
|
@ -878,7 +878,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "bad zoom level is not rejected?" <<EOF
|
||||
error: invalid zoom level -- bad
|
||||
command-option:1: error: invalid zoom level -- bad
|
||||
EOF
|
||||
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "updating log_tags is not working?" <<EOF
|
||||
error:command-option:1:command-option:line 1
|
||||
command-option:1: error: command-option:line 1
|
||||
unexpected JSON value
|
||||
accepted paths --
|
||||
# <tag> -- A tag for the log line
|
||||
|
@ -134,7 +134,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "updating log_tags is not working?" <<EOF
|
||||
error:command-option:1:Value does not match pattern: ^#[^\s]+$
|
||||
command-option:1: error: Value does not match pattern: ^#[^\s]+$
|
||||
EOF
|
||||
|
||||
run_test ${lnav_test} -n \
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
lnav_test="${top_builddir}/src/lnav-test"
|
||||
|
||||
export HOME="./sessions"
|
||||
rm -rf "./sessions"
|
||||
mkdir -p $HOME
|
||||
|
||||
run_test ${lnav_test} -nq \
|
||||
|
@ -71,7 +72,7 @@ EOF
|
|||
|
||||
rm -rf ./sessions
|
||||
mkdir -p $HOME
|
||||
run_test ${lnav_test} -nq \
|
||||
run_test ${lnav_test} -nq -d /tmp/lnav.err \
|
||||
-c ":hide-fields c_ip" \
|
||||
-c ":save-session" \
|
||||
${test_dir}/logfile_access_log.0
|
||||
|
|
|
@ -2,6 +2,39 @@
|
|||
|
||||
lnav_test="${top_builddir}/src/lnav-test"
|
||||
|
||||
run_test ${lnav_test} -n \
|
||||
-c ";UPDATE lnav_file SET filepath='foo' WHERE endswith(filepath, '_log.0')" \
|
||||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "able to change a real file's path?" <<EOF
|
||||
command-option:1: error: real file paths cannot be updated, only symbolic ones
|
||||
EOF
|
||||
|
||||
run_test ${lnav_test} -n \
|
||||
-c "|rename-stdin" \
|
||||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "rename-stdin works without an argument?" <<EOF
|
||||
../test/.lnav/formats/default/rename-stdin.lnav:6: error: expecting the new name for stdin as the first argument
|
||||
EOF
|
||||
|
||||
run_test ${lnav_test} -n \
|
||||
-c "|rename-stdin foo" \
|
||||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "rename-stdin when there is no stdin file?" <<EOF
|
||||
../test/.lnav/formats/default/rename-stdin.lnav:7: error: no data was redirected to lnav's standard-input
|
||||
EOF
|
||||
|
||||
echo 'Hello, World!' | run_test ${lnav_test} -n \
|
||||
-c "|rename-stdin foo" \
|
||||
-c ";SELECT filepath FROM lnav_file"
|
||||
|
||||
check_output "rename of stdin did not work?" <<EOF
|
||||
filepath
|
||||
foo
|
||||
EOF
|
||||
|
||||
run_test ${lnav_test} -n \
|
||||
-c ";SELECT basename(filepath),format,lines,time_offset FROM lnav_file LIMIT 2" \
|
||||
-c ":write-csv-to -" \
|
||||
|
@ -31,7 +64,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "inserted filter with an empty pattern?" <<EOF
|
||||
error:command-option:1:Expecting an non-empty pattern for column number 4
|
||||
command-option:1: error: Expecting an non-empty pattern for column number 4
|
||||
EOF
|
||||
|
||||
run_test ${lnav_test} -n \
|
||||
|
@ -39,7 +72,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "inserted filter with an empty pattern?" <<EOF
|
||||
error:command-option:1:Expecting an lnav view name for column number 0
|
||||
command-option:1: error: Expecting an lnav view name for column number 0
|
||||
EOF
|
||||
|
||||
run_test ${lnav_test} -n \
|
||||
|
@ -47,7 +80,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "inserted filter with an invalid filter type?" <<EOF
|
||||
error:command-option:1:Expecting an filter type for column number 3
|
||||
command-option:1: error: Expecting an filter type for column number 3
|
||||
EOF
|
||||
|
||||
run_test ${lnav_test} -n \
|
||||
|
@ -216,7 +249,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "spectrogram worked without log_time?" <<EOF
|
||||
error: no 'log_time' column found or not in ascending order, unable to create spectrogram
|
||||
command-option:2: error: no 'log_time' column found or not in ascending order, unable to create spectrogram
|
||||
EOF
|
||||
|
||||
run_test ${lnav_test} -n \
|
||||
|
@ -225,7 +258,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "spectrogram worked with bad column?" <<EOF
|
||||
error: unknown column -- sc_byes
|
||||
command-option:2: error: unknown column -- sc_byes
|
||||
EOF
|
||||
|
||||
run_test ${lnav_test} -n \
|
||||
|
@ -234,7 +267,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "spectrogram worked with non-numeric column?" <<EOF
|
||||
error: column is not numeric -- c_ip
|
||||
command-option:2: error: column is not numeric -- c_ip
|
||||
EOF
|
||||
|
||||
run_test ${lnav_test} -n \
|
||||
|
@ -243,7 +276,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "spectrogram worked with unordered log_time?" <<EOF
|
||||
error: no 'log_time' column found or not in ascending order, unable to create spectrogram
|
||||
command-option:2: error: no 'log_time' column found or not in ascending order, unable to create spectrogram
|
||||
EOF
|
||||
|
||||
cp ${srcdir}/logfile_syslog_with_mixed_times.0 logfile_syslog_with_mixed_times.0
|
||||
|
@ -485,7 +518,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "insert into environ table works" <<EOF
|
||||
error:command-option:1:A non-empty name and value must be provided when inserting an environment variable
|
||||
command-option:1: error: A non-empty name and value must be provided when inserting an environment variable
|
||||
EOF
|
||||
|
||||
check_output "insert into environ table works" <<EOF
|
||||
|
@ -497,7 +530,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "insert into environ table works" <<EOF
|
||||
error:command-option:1:A non-empty name and value must be provided when inserting an environment variable
|
||||
command-option:1: error: A non-empty name and value must be provided when inserting an environment variable
|
||||
EOF
|
||||
|
||||
check_output "insert into environ table works" <<EOF
|
||||
|
@ -509,7 +542,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "insert into environ table works" <<EOF
|
||||
error:command-option:1:A non-empty name and value must be provided when inserting an environment variable
|
||||
command-option:1: error: A non-empty name and value must be provided when inserting an environment variable
|
||||
EOF
|
||||
|
||||
check_output "insert into environ table works" <<EOF
|
||||
|
@ -521,7 +554,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "insert into environ table works" <<EOF
|
||||
error:command-option:1:Environment variable names cannot contain an equals sign (=)
|
||||
command-option:1: error: Environment variable names cannot contain an equals sign (=)
|
||||
EOF
|
||||
|
||||
check_output "insert into environ table works" <<EOF
|
||||
|
@ -533,7 +566,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "insert into environ table works" <<EOF
|
||||
error:command-option:1:An environment variable with the name 'SQL_ENV_VALUE' already exists
|
||||
command-option:1: error: An environment variable with the name 'SQL_ENV_VALUE' already exists
|
||||
EOF
|
||||
|
||||
check_output "insert into environ table works" <<EOF
|
||||
|
@ -656,7 +689,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "updating lnav_views.top_time with a bad time works?" <<EOF
|
||||
error:command-option:1:Invalid time: bad-time
|
||||
command-option:1: error: Invalid time: bad-time
|
||||
EOF
|
||||
|
||||
|
||||
|
@ -721,7 +754,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "errors are not reported" <<EOF
|
||||
error:command-option:1:no such table: nonexistent_table
|
||||
command-option:1: error: no such table: nonexistent_table
|
||||
EOF
|
||||
|
||||
check_output "errors are not reported" <<EOF
|
||||
|
@ -733,7 +766,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_error_output "errors are not reported" <<EOF
|
||||
error:command-option:1:attempt to write a readonly database
|
||||
command-option:1: error: attempt to write a readonly database
|
||||
EOF
|
||||
|
||||
check_output "errors are not reported" <<EOF
|
||||
|
@ -945,7 +978,7 @@ run_test ${lnav_test} -n \
|
|||
empty
|
||||
|
||||
check_error_output "LNAVSECURE mode bypassed" <<EOF
|
||||
error:command-option:1:not authorized
|
||||
command-option:1: error: not authorized
|
||||
EOF
|
||||
|
||||
run_test ${lnav_test} -n \
|
||||
|
@ -953,7 +986,7 @@ run_test ${lnav_test} -n \
|
|||
empty
|
||||
|
||||
check_error_output "LNAVSECURE mode bypassed (':' adorned)" <<EOF
|
||||
error:command-option:1:not authorized
|
||||
command-option:1: error: not authorized
|
||||
EOF
|
||||
|
||||
run_test ${lnav_test} -n \
|
||||
|
@ -961,7 +994,7 @@ run_test ${lnav_test} -n \
|
|||
empty
|
||||
|
||||
check_error_output "LNAVSECURE mode bypassed (filepath)" <<EOF
|
||||
error:command-option:1:not authorized
|
||||
command-option:1: error: not authorized
|
||||
EOF
|
||||
|
||||
run_test ${lnav_test} -n \
|
||||
|
@ -969,7 +1002,7 @@ run_test ${lnav_test} -n \
|
|||
empty
|
||||
|
||||
check_error_output "LNAVSECURE mode bypassed (URI)" <<EOF
|
||||
error:command-option:1:not authorized
|
||||
command-option:1: error: not authorized
|
||||
EOF
|
||||
|
||||
unset LNAVSECURE
|
||||
|
@ -1065,7 +1098,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_multiline.0
|
||||
|
||||
check_error_output "able to delete unknown table?" <<EOF
|
||||
error: unknown search table -- search_test1
|
||||
command-option:1: error: unknown search table -- search_test1
|
||||
EOF
|
||||
|
||||
run_test ${lnav_test} -n \
|
||||
|
@ -1074,7 +1107,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_multiline.0
|
||||
|
||||
check_error_output "able to delete logline table?" <<EOF
|
||||
error: unknown search table -- search_test1
|
||||
command-option:2: error: unknown search table -- search_test1
|
||||
EOF
|
||||
|
||||
run_test ${lnav_test} -n \
|
||||
|
@ -1082,7 +1115,7 @@ run_test ${lnav_test} -n \
|
|||
${test_dir}/logfile_multiline.0
|
||||
|
||||
check_error_output "able to create table with a bad regex?" <<EOF
|
||||
error: missing )
|
||||
command-option:1: error: missing )
|
||||
EOF
|
||||
|
||||
NULL_GRAPH_SELECT_1=$(cat <<EOF
|
||||
|
|
Loading…
Reference in New Issue