@@ -58,3 +58,30 @@ func TestStampProvenanceFileRefusesANoteBehindASymlinkedDirectory(t *testing.T)
|
|||||||
got, _ = os.ReadFile(real)
|
got, _ = os.ReadFile(real)
|
||||||
assert.Contains(t, string(got), "written_by: x")
|
assert.Contains(t, string(got), "written_by: x")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The same through an in-brain symlinked wing and raw/rejected, which
|
||||||
|
// os.Root alone would follow.
|
||||||
|
func TestPromoteAndRejectRefuseAnInBrainSymlinkedDestinationDirectory(t *testing.T) {
|
||||||
|
brain := t.TempDir()
|
||||||
|
raw := filepath.Join(brain, "raw")
|
||||||
|
require.NoError(t, os.MkdirAll(raw, 0o755))
|
||||||
|
require.NoError(t, os.WriteFile(filepath.Join(raw, "2026-10-05-n.md"), []byte("---\ntitle: n\n---\nbody\n"), 0o644))
|
||||||
|
target := filepath.Join(brain, "archive")
|
||||||
|
require.NoError(t, os.MkdirAll(target, 0o755))
|
||||||
|
require.NoError(t, os.MkdirAll(filepath.Join(brain, "wiki"), 0o755))
|
||||||
|
require.NoError(t, os.Symlink(filepath.Join("..", "archive"), filepath.Join(brain, "wiki", "lw")))
|
||||||
|
require.NoError(t, os.Symlink(filepath.Join("..", "archive"), filepath.Join(raw, "rejected")))
|
||||||
|
|
||||||
|
_, err := api.PromoteNote(brain, api.PromoteOptions{Filename: "2026-10-05-n.md", Wing: "lw", Hall: "facts"})
|
||||||
|
assert.Error(t, err)
|
||||||
|
_, err = api.RejectNote(brain, api.RejectOptions{Filename: "2026-10-05-n.md"})
|
||||||
|
assert.Error(t, err)
|
||||||
|
ents, _ := os.ReadDir(target)
|
||||||
|
assert.Empty(t, ents, "a note was written at the in-brain link's target")
|
||||||
|
_, err = os.Stat(filepath.Join(raw, "2026-10-05-n.md"))
|
||||||
|
assert.NoError(t, err, "the raw source is kept")
|
||||||
|
|
||||||
|
require.NoError(t, os.Remove(filepath.Join(raw, "rejected")))
|
||||||
|
_, err = api.RejectNote(brain, api.RejectOptions{Filename: "2026-10-05-n.md"})
|
||||||
|
require.NoError(t, err, "positive control: reject into a real raw/rejected")
|
||||||
|
}
|
||||||
|
|||||||
@@ -493,3 +493,39 @@ func TestRemoveRefusesAPathBehindASymlinkedDirectoryAndRemovesOnlyTheLink(t *tes
|
|||||||
_, err = os.Stat(filepath.Join(dir, "wiki", "n.md"))
|
_, err = os.Stat(filepath.Join(dir, "wiki", "n.md"))
|
||||||
assert.True(t, os.IsNotExist(err))
|
assert.True(t, os.IsNotExist(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateRegular is the only write path for promote and reject: it creates
|
||||||
|
// missing parents through the root, refuses an in-brain symlinked parent and
|
||||||
|
// an unclean path, and never replaces anything already there (fs.ErrExist,
|
||||||
|
// content unchanged), including a dangling link.
|
||||||
|
func TestCreateRegularCreatesOnlyNewFilesThroughRealDirectories(t *testing.T) {
|
||||||
|
dir := t.TempDir()
|
||||||
|
require.NoError(t, os.MkdirAll(filepath.Join(dir, "raw", "keep"), 0o755))
|
||||||
|
require.NoError(t, os.MkdirAll(filepath.Join(dir, "wiki"), 0o755))
|
||||||
|
require.NoError(t, os.Symlink(filepath.Join("..", "raw"), filepath.Join(dir, "wiki", "inwing")))
|
||||||
|
require.NoError(t, os.WriteFile(filepath.Join(dir, "raw", "v.md"), []byte("untouched"), 0o644))
|
||||||
|
require.NoError(t, os.Symlink(filepath.Join("raw", "keep"), filepath.Join(dir, "indir")))
|
||||||
|
require.NoError(t, os.WriteFile(filepath.Join(dir, "wiki", "exists.md"), []byte("original"), 0o644))
|
||||||
|
require.NoError(t, os.Symlink("nowhere.md", filepath.Join(dir, "wiki", "dangling.md")))
|
||||||
|
b, err := Open(dir)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer func() { _ = b.Close() }()
|
||||||
|
|
||||||
|
assert.ErrorIs(t, b.CreateRegular("wiki/inwing/facts/n.md", []byte("x")), ErrNotRegular)
|
||||||
|
_, err = os.Stat(filepath.Join(dir, "raw", "facts"))
|
||||||
|
assert.True(t, os.IsNotExist(err), "nothing created through the in-brain link")
|
||||||
|
assert.ErrorIs(t, b.CreateRegular("indir/../v.md", []byte("x")), ErrNotRegular)
|
||||||
|
got, _ := os.ReadFile(filepath.Join(dir, "raw", "v.md"))
|
||||||
|
assert.Equal(t, "untouched", string(got))
|
||||||
|
|
||||||
|
assert.ErrorIs(t, b.CreateRegular("wiki/exists.md", []byte("x")), fs.ErrExist)
|
||||||
|
got, _ = os.ReadFile(filepath.Join(dir, "wiki", "exists.md"))
|
||||||
|
assert.Equal(t, "original", string(got))
|
||||||
|
assert.ErrorIs(t, b.CreateRegular("wiki/dangling.md", []byte("x")), fs.ErrExist)
|
||||||
|
_, err = os.Stat(filepath.Join(dir, "wiki", "nowhere.md"))
|
||||||
|
assert.True(t, os.IsNotExist(err), "nothing created at the dangling link's target")
|
||||||
|
|
||||||
|
require.NoError(t, b.CreateRegular("wiki/new/facts/n.md", []byte("one")), "positive control: create with missing parents")
|
||||||
|
got, _ = os.ReadFile(filepath.Join(dir, "wiki", "new", "facts", "n.md"))
|
||||||
|
assert.Equal(t, "one", string(got))
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user