go-ruby-find

Ruby's Find traversal algorithm in pure Go โ€” MRI-compatible, no cgo.

pure Go ยท zero cgo Find.find traversal depth-first walk byte-wise sort Find.prune injected Lister Dir / File host-side MRI-faithful 100% coverage 6 arches
Documentation GitHub
Documentation (MkDocs Material + mike) License: BSD-3-Clause Go 1.26.4+ Coverage 100%

go-ruby-find is a pure-Go (no cgo) reimplementation of the traversal algorithm of Ruby's Find module (require "find") โ€” the deterministic, interpreter-independent core of MRI 4.0.5's lib/find.rb. It drives Find.find's exact top-down visit order and the Find.prune control flow over an injected directory lister, so the real filesystem access โ€” Dir.children, File.lstat/File.directory? โ€” stays host-side while the order, the byte-wise sort, the prune throw/catch and the error pass-through behaviour live here as portable Go. Each start path is yielded first, then a depth-first walk of its contents with children sorted ascending byte-wise; Find.prune maps to returning find.ErrPrune from the yield callback. It is the Find backend for go-embedded-ruby, bound by rbgo just like go-ruby-regexp and go-ruby-erb โ€” differential-tested against MRI, 100% coverage, CI green across 6 arches and 3 OSes.

Traversal engine ready

Walk(roots, lister, yield, ignoreError) drives MRI Find.find’s traversal: each start path is yielded first, then a depth-first walk of its contents over an injected directory lister.

MRI visit order ready

A directory’s children are listed, sorted ascending byte-wise (MRI’s String#<=>), reversed and unshifted onto a FIFO queue โ€” giving MRI’s exact depth-first, ascending-sorted order.

Find.prune control flow ready

Returning find.ErrPrune from the yield callback prunes the current path โ€” already yielded, but if a directory, not descended into โ€” the engine’s analogue of throw :prune.

The Lister seam ready

Walk performs no I/O: the host injects Exist / IsDir / Children (Ruby File.exist? / File.lstat / Dir.children). WalkJoin accepts a custom path joiner. Dir/File stay host-side.

Error semantics ready

A missing start path returns *MissingPathError before any yield (MRI’s Errno::ENOENT); a per-entry IsDir/Children failure mid-walk is swallowed when ignoreError is true (MRI’s default) and propagated otherwise.

Differential oracle & coverage ready

The visit order is diffed against ruby -rfind over real temp trees on the non-Windows lanes; the deterministic in-memory tests reach 100% coverage with no ruby present, gofmt + go vet clean, green across all six 64-bit Go arches and three OSes.

A faithful port of Ruby's Find traversal in pure Go, cgo disabled, so it cross-compiles and embeds anywhere. It owns the depth-first walk, the byte-wise child sort, the Find.prune semantics and the swallow-or-propagate error policy; all filesystem access is injected through a small Lister the host binds to Dir.children and File.lstat. Validated differentially against the system ruby -rfind โ€” the visit order diffed over real temp trees. It is a standalone, reusable module, and the Find backend for the sibling org github.com/go-embedded-ruby.