fix(brainfs): refuse a symlinked walk root (#157)
Review round 1 on PR #166: fs.WalkDir stats its root with a follow, and os.Root allows a symlink that stays inside the brain, so knowledge -> . aliased raw/, sessions/ and root files into the embeddings (and a wiki/<w> -> .. root into search results). On main, filepath.WalkDir Lstat'ed the root and did not descend. - WalkRegular Lstats its root and requires a real directory; anything else goes to onErr as ErrNotRegular and nothing is yielded. - Sync skips a missing scan root via bfs.Lstat before walking, and every other walk error, including a symlinked root, aborts before the delete pass. This removes the unpinned rel == sub special case. - Search warns and skips a symlinked root (new test). - Test renamed to TestSyncRefusesSymlinkedNotesAndSurvivesSwapRaces. - wrapAfterStat comment: brainfs tests must not use t.Parallel. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -103,11 +103,13 @@ func Sync(ctx context.Context, brainDir string, store Store, embedder Embedder)
|
||||
defer func() { _ = bfs.Close() }()
|
||||
|
||||
for _, sub := range scanDirs {
|
||||
if _, err := bfs.Lstat(sub); errors.Is(err, fs.ErrNotExist) {
|
||||
continue
|
||||
}
|
||||
// Any other walk error, including a scan root that is a symlink,
|
||||
// aborts the run below.
|
||||
var walkErr error
|
||||
onErr := func(rel string, err error) {
|
||||
if rel == sub && errors.Is(err, fs.ErrNotExist) {
|
||||
return
|
||||
}
|
||||
if walkErr == nil {
|
||||
walkErr = fmt.Errorf("%s: %w", rel, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user