v0.49.9
[0.49.9] — 2026-08-18
Line anchors now work in files with CRLF endings, and the path-prefix filter works on paths containing an underscore. Both failures were silent: the tool returned zero, indistinguishable from an honest "nothing found".
Context. Findings H-1, H-2, H-5, H-6 of the storage audit.
Fixed
- The end-of-line anchor found nothing in files with CRLF. The same expression was applied to two different representations of the text: the pre-filter to the whole text, where a line ends with carriage return plus line feed, and the line-by-line scan to lines with the carriage return already stripped. In multi-line mode
$matches right before the line feed, and a carriage return sat there — so the file was discarded whole before the scan began.grep_code,grep_textandgrep_bodywere all affected. Line endings are now normalised before the expression is applied — in the shared content-scanning path and in the SQLREGEXPfunction; the copy is made only when a carriage return is actually present. - The path-prefix filter missed paths with an underscore or a percent sign. Pattern-matching special characters were escaped with a backslash, but the query had no
ESCAPEclause, so SQLite treated the backslash as an ordinary character and looked for a path literally containing it. There were never any matches: apath_prefixwith an underscore — the norm for directories likedaemon_coreand for 1C external-processing names — silently returned an empty list. The escaping did not merely fail to help, it created the defect. - Schema migrations were not applied on every database-opening path. The set of migrations was listed twice — when creating a database and when loading an existing one into memory — and the second list lagged behind: the content-table migrations never made it there. A database from an older binary opened this way stayed without them, and the first content write failed with "no such table". The chain now lives in one function called by both paths; that path also explicitly enables foreign keys and sets the cache size, which it lacked entirely.
- A line longer than the soft limit made a file unreadable. Line collection stopped as soon as one did not fit the budget; when the very first line exceeded it (minified js/css/json — the whole file on one line), empty content went out with a truncation flag. The file could not be read whole or by range — there is only one line. Its beginning is now returned, cut on a character boundary.
Testing
- Unit tests:
cargo test --workspace— 672 passed, 0 failed (was 667; five new ones: anchors on content with CRLF specifically, for code and for bodies; a prefix with an underscore and with a percent sign; the full migration chain on a database whose content tables were dropped; a long line whole and by range). - Live check on Windows (repository with CRLF endings):
grep_codefor^use std::sync::Arc;$— 1 match,grep_bodyfor^\s+Ok\(\(\)\)$— 30,grep_textfor^# Changelog$— 1; before the fix all three returned zero. Prefixcrates/code-index-core/src/daemon_core/— 13 files, exactly as many as the same directory by pattern; before the fix — zero. - Checking the check: the long-line test was run with the fix disabled and failed — so it catches this defect rather than passing incidentally.
- Live check through federation (remote node, a repository holding a 1C configuration): a prefix for a directory whose name contains an underscore — 14 files against the previous zero, exactly as many as the same directory by pattern; on a repository with LF endings anchor search is unchanged, so normalisation broke nothing. The previous release's fixes were confirmed here too: the listing is capped and carries the total, path-scoped search returns 10 records with the incompleteness marker.
- What was NOT verified live: the migration-chain divergence. All eight working databases are already migrated, so the defect is dormant — it can only be reproduced on an artificial database, which the unit test does.
Compatibility
- No reindexing required: the changes live in the read path and in database opening. Search behaviour changes only where it previously returned a silent zero.
Russian version of the changelog: CHANGELOG.md.
Full Changelog: v0.49.8...v0.49.9