Default the manifest to index.mf and keep it out of its own listing (closes #100)
check / check (push) Failing after 1s
check / check (push) Failing after 1s
mfer gen now writes index.mf instead of .index.mf, the name fetch requests and the README calls the standard filename. Given a directory, check, freshen, list and export look only for index.mf; .index.mf is no longer recognized. Because index.mf is not hidden, gen and freshen now leave out of their own listing both the manifest they write and a temp file an interrupted run left beside it, by file identity (os.SameFile), so each is recognized however its path is spelled, while an ordinary file of the same name elsewhere in the tree is still listed. Model: opus-5-5
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -29,7 +30,7 @@ func (s stubFileInfo) IsDir() bool { return false }
|
||||
func (s stubFileInfo) Sys() any { return nil }
|
||||
|
||||
// setupFreshenDir populates /testdir with two files, scans it, and
|
||||
// writes the resulting manifest to /testdir/.index.mf.
|
||||
// writes the resulting manifest to /testdir/index.mf.
|
||||
func setupFreshenDir(t *testing.T, fs afero.Fs) {
|
||||
t.Helper()
|
||||
|
||||
@@ -48,7 +49,7 @@ func setupFreshenDir(t *testing.T, fs afero.Fs) {
|
||||
|
||||
// Write manifest to filesystem
|
||||
require.NoError(t,
|
||||
afero.WriteFile(fs, "/testdir/.index.mf", manifestBuf.Bytes(), 0o644))
|
||||
afero.WriteFile(fs, "/testdir/index.mf", manifestBuf.Bytes(), 0o644))
|
||||
}
|
||||
|
||||
func TestFreshenUnchanged(t *testing.T) {
|
||||
@@ -59,7 +60,7 @@ func TestFreshenUnchanged(t *testing.T) {
|
||||
|
||||
// Parse manifest to verify
|
||||
manifest, err := mfer.NewManifestFromFile(&mfer.ManifestFromFileOptions{
|
||||
Path: "/testdir/.index.mf",
|
||||
Path: "/testdir/index.mf",
|
||||
Fs: fs,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -74,7 +75,7 @@ func TestFreshenWithChanges(t *testing.T) {
|
||||
|
||||
// Verify initial manifest has 2 files
|
||||
manifest, err := mfer.NewManifestFromFile(&mfer.ManifestFromFileOptions{
|
||||
Path: "/testdir/.index.mf",
|
||||
Path: "/testdir/index.mf",
|
||||
Fs: fs,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -101,6 +102,64 @@ func TestFreshenWithChanges(t *testing.T) {
|
||||
assert.Equal(t, "modified content2", string(content))
|
||||
}
|
||||
|
||||
// TestFreshenLeavesManifestOutOfListing freshens a manifest kept in a
|
||||
// subdirectory of the tree it lists: the manifest is not listed, while an
|
||||
// ordinary file of the same name at the top of the tree is. The manifest
|
||||
// is recognized by file identity, which needs the real filesystem.
|
||||
func TestFreshenLeavesManifestOutOfListing(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
root := t.TempDir()
|
||||
manifestPath := filepath.Join(root, "sub", "listing.mf")
|
||||
|
||||
fs := afero.NewOsFs()
|
||||
require.NoError(t, fs.MkdirAll(filepath.Join(root, "sub"), 0o750))
|
||||
writeTestFile(t, fs, filepath.Join(root, testFileTxt), "hello")
|
||||
writeTestFile(t, fs, filepath.Join(root, "listing.mf"), "an ordinary file")
|
||||
|
||||
opts := testOpts([]string{testApp, cmdGenerate, "-q", "-o", manifestPath, root}, fs)
|
||||
require.Equal(t, 0, runCLI(opts), "stderr: %s", testStderr(t, opts))
|
||||
|
||||
// A new file gives freshen something to write.
|
||||
writeTestFile(t, fs, filepath.Join(root, "added.txt"), "added")
|
||||
|
||||
opts = testOpts([]string{
|
||||
testApp, "freshen", "-q", testFlagBase, root, manifestPath,
|
||||
}, fs)
|
||||
require.Equal(t, 0, runCLI(opts), "stderr: %s", testStderr(t, opts))
|
||||
|
||||
assert.ElementsMatch(t, []string{testFileTxt, "listing.mf", "added.txt"},
|
||||
manifestPaths(t, fs, manifestPath))
|
||||
}
|
||||
|
||||
// TestFreshenLeavesLeftoverTempFileOutOfListing freshens a manifest where
|
||||
// an interrupted run left its temp file, index.mf.tmp, beside it: the
|
||||
// leftover is not listed.
|
||||
func TestFreshenLeavesLeftoverTempFileOutOfListing(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
root := t.TempDir()
|
||||
manifestPath := filepath.Join(root, "index.mf")
|
||||
|
||||
fs := afero.NewOsFs()
|
||||
writeTestFile(t, fs, filepath.Join(root, testFileTxt), "hello")
|
||||
|
||||
opts := testOpts([]string{testApp, cmdGenerate, "-q", "-o", manifestPath, root}, fs)
|
||||
require.Equal(t, 0, runCLI(opts), "stderr: %s", testStderr(t, opts))
|
||||
|
||||
writeTestFile(t, fs, manifestPath+".tmp", "part of a manifest")
|
||||
// A new file gives freshen something to write.
|
||||
writeTestFile(t, fs, filepath.Join(root, "added.txt"), "added")
|
||||
|
||||
opts = testOpts([]string{
|
||||
testApp, "freshen", "-q", testFlagBase, root, manifestPath,
|
||||
}, fs)
|
||||
require.Equal(t, 0, runCLI(opts), "stderr: %s", testStderr(t, opts))
|
||||
|
||||
assert.ElementsMatch(t, []string{testFileTxt, "added.txt"},
|
||||
manifestPaths(t, fs, manifestPath))
|
||||
}
|
||||
|
||||
// TestFreshenRecordEntryMtimePresence pins the behavior of recordEntry
|
||||
// with respect to MFFilePath.Mtime, which is a message pointer with
|
||||
// proto3 field presence and may legitimately be absent.
|
||||
|
||||
Reference in New Issue
Block a user