diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index 4de183f7..d053a25b 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -71,8 +71,11 @@ jobs: libbz2-dev libcurl4-openssl-dev libreadline-dev + pipx tshark zlib1g-dev + - name: Install python packages + run: pipx install check-jsonschema - name: autogen run: ./autogen.sh - name: configure diff --git a/configure.ac b/configure.ac index 4387a5cb..1446eb82 100644 --- a/configure.ac +++ b/configure.ac @@ -56,6 +56,7 @@ AC_PATH_PROG(RE2C_CMD, [re2c]) AM_CONDITIONAL(HAVE_RE2C, test x"$RE2C_CMD" != x"") AC_PATH_PROG(XZ_CMD, [xz]) AC_PATH_PROG(TSHARK_CMD, [tshark]) +AC_PATH_PROG(CHECK_JSONSCHEMA, [check-jsonschema]) AC_CHECK_SIZEOF(off_t) AC_CHECK_SIZEOF(size_t) @@ -310,6 +311,7 @@ AM_CONDITIONAL(HAVE_CARGO, test x"$CARGO_CMD" != x"") AM_CONDITIONAL(USE_INCLUDED_YAJL, test $HAVE_LOCAL_YAJL -eq 0) AM_CONDITIONAL(HAVE_LIBCURL, test x"$LIBCURL" != x"") AM_CONDITIONAL([CROSS_COMPILING], [ test x"$cross_compiling" != x"no" ]) +AM_CONDITIONAL(HAVE_CHECK_JSONSCHEMA, test x"$CHECK_JSONSCHEMA" != x"") AS_VAR_SET(USER_CXXFLAGS, ["$CXXFLAGS"]) AC_SUBST(USER_CXXFLAGS) diff --git a/docs/schemas/config-v1.schema.json b/docs/schemas/config-v1.schema.json index 1c021567..d4897131 100644 --- a/docs/schemas/config-v1.schema.json +++ b/docs/schemas/config-v1.schema.json @@ -140,7 +140,7 @@ "title": "/tuning/remote/ssh/options", "type": "object", "patternProperties": { - "(\\w+)": { + "^(\\w+)$": { "title": "/tuning/remote/ssh/options/", "description": "Set an option to be passed to the SSH command", "type": "string" @@ -153,7 +153,7 @@ "title": "/tuning/remote/ssh/config", "type": "object", "patternProperties": { - "(\\w+)": { + "^(\\w+)$": { "title": "/tuning/remote/ssh/config/", "description": "Set an SSH configuration value", "type": "string" @@ -177,7 +177,7 @@ "title": "/tuning/clipboard/impls", "type": "object", "patternProperties": { - "([\\w\\-]+)": { + "^([\\w\\-]+)$": { "description": "Clipboard implementation", "title": "/tuning/clipboard/impls/", "type": "object", @@ -214,7 +214,7 @@ "title": "/tuning/url-scheme", "type": "object", "patternProperties": { - "([a-z][\\w\\-\\+\\.]+)": { + "^([a-z][\\w\\-\\+\\.]+)$": { "description": "Definition of a custom URL scheme", "title": "/tuning/url-scheme/", "type": "object", @@ -272,7 +272,7 @@ "title": "/ui/theme-defs", "type": "object", "patternProperties": { - "([\\w\\-]+)": { + "^([\\w\\-]+)$": { "description": "Theme definitions", "title": "/ui/theme-defs/", "type": "object", @@ -282,7 +282,7 @@ "title": "/ui/theme-defs//vars", "type": "object", "patternProperties": { - "(\\w+)": { + "^(\\w+)$": { "title": "/ui/theme-defs//vars/", "description": "A theme variable definition", "type": "string" @@ -694,7 +694,7 @@ "title": "/ui/theme-defs//log-level-styles", "type": "object", "patternProperties": { - "(trace|debug5|debug4|debug3|debug2|debug|info|stats|notice|warning|error|critical|fatal|invalid)": { + "^(trace|debug5|debug4|debug3|debug2|debug|info|stats|notice|warning|error|critical|fatal|invalid)$": { "title": "/ui/theme-defs//log-level-styles/", "$ref": "#/definitions/style" } @@ -706,7 +706,7 @@ "title": "/ui/theme-defs//highlights", "type": "object", "patternProperties": { - "([\\w\\-]+)": { + "^([\\w\\-]+)$": { "title": "/ui/theme-defs//highlights/", "type": "object", "properties": { @@ -758,12 +758,12 @@ "title": "/ui/keymap-defs", "type": "object", "patternProperties": { - "([\\w\\-]+)": { + "^([\\w\\-]+)$": { "description": "The keymap definitions", "title": "/ui/keymap-defs/", "type": "object", "patternProperties": { - "((?:x[0-9a-f]{2})+)": { + "^((?:x[0-9a-f]{2})+)$": { "description": "Map of key codes to commands to execute. The field names are the keys to be mapped using as a hexadecimal representation of the UTF-8 encoding. Each byte of the UTF-8 should start with an 'x' followed by the hexadecimal representation of the byte.", "title": "/ui/keymap-defs//", "type": "object", @@ -817,7 +817,7 @@ "title": "/log/watch-expressions", "type": "object", "patternProperties": { - "([\\w\\.\\-]+)": { + "^([\\w\\.\\-]+)$": { "description": "A log message watch expression", "title": "/log/watch-expressions/", "type": "object", @@ -842,7 +842,7 @@ "title": "/log/annotations", "type": "object", "patternProperties": { - "([\\w\\.\\-]+)": { + "^([\\w\\.\\-]+)$": { "title": "/log/annotations/", "type": "object", "properties": { @@ -877,7 +877,7 @@ "title": "/global", "type": "object", "patternProperties": { - "(\\w+)": { + "^(\\w+)$": { "title": "/global/", "description": "A global variable definition. Global variables can be referenced in scripts, SQL statements, or commands.", "type": "string" diff --git a/docs/schemas/event-log-msg-detected-v1.schema.json b/docs/schemas/event-log-msg-detected-v1.schema.json index 30ec3a23..a82b01f4 100644 --- a/docs/schemas/event-log-msg-detected-v1.schema.json +++ b/docs/schemas/event-log-msg-detected-v1.schema.json @@ -41,7 +41,7 @@ "title": "/values", "type": "object", "patternProperties": { - "([\\w\\-]+)": { + "^([\\w\\-]+)$": { "title": "/values/", "type": [ "boolean", diff --git a/docs/schemas/format-v1.schema.json b/docs/schemas/format-v1.schema.json index d3e08272..7d01ab07 100644 --- a/docs/schemas/format-v1.schema.json +++ b/docs/schemas/format-v1.schema.json @@ -10,7 +10,7 @@ } }, "patternProperties": { - "(\\w+)": { + "^(\\w+)$": { "description": "The definition of a log file format.", "title": "/", "type": "object", @@ -20,7 +20,7 @@ "title": "//regex", "type": "object", "patternProperties": { - "([^/]+)": { + "^(.+)$": { "description": "The set of patterns used to match log messages", "title": "//regex/", "type": "object", @@ -95,7 +95,7 @@ "title": "//converter/header/expr", "type": "object", "patternProperties": { - "(\\w+)": { + "^(\\w+)$": { "title": "//converter/header/expr/", "description": "SQLite expression", "type": "string" @@ -214,7 +214,7 @@ "title": "//opid/description", "type": "object", "patternProperties": { - "([\\w\\.\\-]+)": { + "^([\\w\\.\\-]+)$": { "description": "A type of description for this operation", "title": "//opid/description/", "type": "object", @@ -266,7 +266,7 @@ "title": "//opid/sub-description", "type": "object", "patternProperties": { - "([\\w\\.\\-]+)": { + "^([\\w\\.\\-]+)$": { "description": "A type of description for this sub-operation", "title": "//opid/sub-description/", "type": "object", @@ -326,7 +326,7 @@ "title": "//level", "type": "object", "patternProperties": { - "(trace|debug[2345]?|info|stats|notice|warning|error|critical|fatal)": { + "^(trace|debug[2345]?|info|stats|notice|warning|error|critical|fatal)$": { "title": "//level/", "description": "The regular expression used to match the log text for this level. For JSON logs with numeric levels, this should be the number for the corresponding level.", "type": [ @@ -342,7 +342,7 @@ "title": "//value", "type": "object", "patternProperties": { - "([^/]+)": { + "^(.+)$": { "description": "The set of values captured by the log message patterns", "title": "//value/", "type": "object", @@ -382,7 +382,7 @@ "title": "//value//unit/scaling-factor", "type": "object", "patternProperties": { - "([^/]+)": { + "^(.+)$": { "title": "//value//unit/scaling-factor/", "type": "object", "properties": { @@ -455,7 +455,7 @@ "title": "//tags", "type": "object", "patternProperties": { - "([\\w:;\\._\\-]+)": { + "^([\\w:;\\._\\-]+)$": { "description": "The name of the tag to apply", "title": "//tags/", "type": "object", @@ -523,7 +523,7 @@ "title": "//partitions", "type": "object", "patternProperties": { - "([\\w:;\\._\\-]+)": { + "^([\\w:;\\._\\-]+)$": { "description": "The type of partition to apply", "title": "//partitions/", "type": "object", @@ -590,7 +590,7 @@ "title": "//action", "type": "object", "patternProperties": { - "(\\w+)": { + "^(\\w+)$": { "title": "//action/", "type": [ "string", @@ -751,7 +751,7 @@ "title": "//search-table", "type": "object", "patternProperties": { - "(\\w+)": { + "^(\\w+)$": { "description": "The set of search tables to be automatically defined", "title": "//search-table/", "type": "object", @@ -797,7 +797,7 @@ "title": "//highlights", "type": "object", "patternProperties": { - "([^/]+)": { + "^(.+)$": { "description": "The definition of a highlight", "title": "//highlights/", "type": "object", diff --git a/src/Makefile.am b/src/Makefile.am index f10577bb..b4d004af 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -612,5 +612,11 @@ else all-local: $(LNAV_BUILT_FILES) $(RUST_DEPS) endif +check-local: +if HAVE_CHECK_JSONSCHEMA + $(CHECK_JSONSCHEMA) --schemafile $(top_srcdir)/docs/schemas/format-v1.schema.json $(FORMAT_FILES) + $(CHECK_JSONSCHEMA) --schemafile $(top_srcdir)/docs/schemas/config-v1.schema.json $(CONFIG_FILES) +endif + install-exec-hook: bash $(srcdir)/alpha-release.sh diff --git a/src/lnav.cc b/src/lnav.cc index b4a292e2..b4d8b01e 100644 --- a/src/lnav.cc +++ b/src/lnav.cc @@ -3296,8 +3296,11 @@ SELECT tbl_name FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE%' { rescan_files(true); gather_pipers(); - rebuild_indexes(ui_clock::now() + 10ms); - if (lnav_data.ld_child_pollers.empty()) { + auto rebuild_res = rebuild_indexes(ui_clock::now() + 15ms); + if (rebuild_res.rir_completed + && lnav_data.ld_child_pollers.empty()) + { + rebuild_indexes_repeatedly(); if (lnav_data.ld_active_files.fc_files.empty() || lnav_data.ld_active_files.fc_files[0]->size() < 24) { diff --git a/src/yajlpp/yajlpp.cc b/src/yajlpp/yajlpp.cc index 45183e29..0fc00014 100644 --- a/src/yajlpp/yajlpp.cc +++ b/src/yajlpp/yajlpp.cc @@ -1529,6 +1529,7 @@ json_path_container::gen_schema(yajlpp_gen_context& ygc) const void json_path_container::gen_properties(yajlpp_gen_context& ygc) const { + static const auto FWD_SLASH = lnav::pcre2pp::code::from_const(R"(\[\^/\])"); auto pattern_count = count_if( this->jpc_children.begin(), this->jpc_children.end(), [](auto& jph) { return jph.jph_is_pattern_property; @@ -1558,7 +1559,10 @@ json_path_container::gen_properties(yajlpp_gen_context& ygc) const if (!child_handler.jph_is_pattern_property) { continue; } - properties.gen(child_handler.jph_property); + + auto pattern = child_handler.jph_property; + pattern = FWD_SLASH.replace(pattern, "."); + properties.gen(fmt::format(FMT_STRING("^{}$"), pattern)); child_handler.gen_schema(ygc); } }