Skip to content

v0.3.1

Choose a tag to compare

@clemlesne clemlesne released this 12 Mar 15:19
· 78 commits to main since this release

What's Changed

Detect ctags on more systems out of the box

  • Homebrew's ctags (which is universal-ctags) now detected correctly on macOS — no manual CTAGS_COMMAND needed
  • Three-tier detection: CTAGS_COMMAND env var → universal-ctags on PATH → ctags verified via --version
  • Clear error when CTAGS_COMMAND is set but not found on PATH

Catch more file changes from editors like vim and emacs

  • Atomic-write editors that write-to-tmp + rename now correctly trigger re-indexing, by tracking file inodes alongside mtime and size
  • State hash bumped to v5 — caches from v0.3.0 are invalidated on first run

Faster and more robust git status parsing

  • Added --no-ahead-behind to git status for faster execution
  • Defensive handling for rename/copy entries in porcelain v2 output (not expected with --no-renames, but guards against edge cases)
  • Fixed .gitignore-style exclude matching to use exact line comparison instead of substring (prevents false positives like .seek-cache-old matching .seek-cache)

Reduced memory usage for uncommitted file indexing

  • Uncommitted files are now streamed through a bounded channel instead of buffered into a single unbounded slice, keeping at most 2×parallelism files in flight
  • Non-regular files (FIFOs, sockets, devices) now skipped, preventing potential blocking reads
  • Per-file reads use pre-sized buffer from Lstat instead of os.ReadFile, saving an extra Fstat syscall per file

Lock improvements

  • Shared search lock is now non-blocking with poll timeout, preventing indefinite hangs if an indexer is stuck
  • Added jitter to lock polling backoff to prevent thundering herd, and extracted a reusable pollLock helper

Bug fixes

  • Zoekt builder Finish() is now always called even after Add errors, fixing a resource leak (ctags subprocess and open file handles)
  • formatResults trailing newline removal uses single-byte check instead of strings.TrimRight, avoiding unintended stripping of content newlines

Internal

  • fmt.Fprintf in repoStateFingerprint replaced with strings.Builder + strconv for fewer allocations
  • strings.Builder.Grow() pre-allocates fingerprint buffer
  • xxhash.WriteString replaces Write([]byte(...)) in computeStateHash, eliminating two allocations per hash
  • Zoekt builder created lazily on first file, avoiding ctags process spawning when there are no dirty files
  • Channel fully drained on error/panic paths to prevent goroutine leaks
  • Lock logic consolidated from indexer.go into lock.go

Full Changelog: v0.3.0...v0.3.1