Fix FindExtraFiles reporting manifest file and dotfiles as extra (closes #16)
FindExtraFiles now skips hidden files/directories (dotfiles) and the manifest file itself when walking the filesystem. The manifest's relative path is computed at Checker construction time.
This commit is contained in:
parent
377fdfb503
commit
7c91f43d76
@ -70,6 +70,8 @@ type Checker struct {
|
||||
fs afero.Fs
|
||||
// manifestPaths is a set of paths in the manifest for quick lookup
|
||||
manifestPaths map[RelFilePath]struct{}
|
||||
// manifestRelPath is the relative path of the manifest file from basePath (for exclusion)
|
||||
manifestRelPath RelFilePath
|
||||
// signature info from the manifest
|
||||
signature []byte
|
||||
signer []byte
|
||||
@ -100,14 +102,25 @@ func NewChecker(manifestPath string, basePath string, fs afero.Fs) (*Checker, er
|
||||
manifestPaths[RelFilePath(f.Path)] = struct{}{}
|
||||
}
|
||||
|
||||
// Compute manifest's relative path from basePath for exclusion in FindExtraFiles
|
||||
absManifest, err := filepath.Abs(manifestPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
manifestRel, err := filepath.Rel(abs, absManifest)
|
||||
if err != nil {
|
||||
manifestRel = ""
|
||||
}
|
||||
|
||||
return &Checker{
|
||||
basePath: AbsFilePath(abs),
|
||||
files: files,
|
||||
fs: fs,
|
||||
manifestPaths: manifestPaths,
|
||||
signature: m.pbOuter.Signature,
|
||||
signer: m.pbOuter.Signer,
|
||||
signingPubKey: m.pbOuter.SigningPubKey,
|
||||
basePath: AbsFilePath(abs),
|
||||
files: files,
|
||||
fs: fs,
|
||||
manifestPaths: manifestPaths,
|
||||
manifestRelPath: RelFilePath(manifestRel),
|
||||
signature: m.pbOuter.Signature,
|
||||
signer: m.pbOuter.Signer,
|
||||
signingPubKey: m.pbOuter.SigningPubKey,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -288,18 +301,32 @@ func (c *Checker) FindExtraFiles(ctx context.Context, results chan<- Result) err
|
||||
default:
|
||||
}
|
||||
|
||||
// Skip directories
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get relative path
|
||||
rel, err := filepath.Rel(string(c.basePath), path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Skip hidden files and directories (dotfiles)
|
||||
if IsHiddenPath(filepath.ToSlash(rel)) {
|
||||
if info.IsDir() {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Skip directories
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
relPath := RelFilePath(rel)
|
||||
|
||||
// Skip the manifest file itself
|
||||
if relPath == c.manifestRelPath {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check if path is in manifest
|
||||
if _, exists := c.manifestPaths[relPath]; !exists {
|
||||
if results != nil {
|
||||
|
||||
@ -414,6 +414,61 @@ func TestCheckMissingFileDetectedWithoutFallback(t *testing.T) {
|
||||
assert.Equal(t, 0, statusCounts[StatusError], "no files should be ERROR")
|
||||
}
|
||||
|
||||
func TestFindExtraFilesSkipsDotfiles(t *testing.T) {
|
||||
// Regression test for #16: FindExtraFiles should not report dotfiles
|
||||
// or the manifest file itself as extra files.
|
||||
fs := afero.NewMemMapFs()
|
||||
files := map[string][]byte{
|
||||
"file1.txt": []byte("in manifest"),
|
||||
}
|
||||
createTestManifest(t, fs, "/data/.index.mf", files)
|
||||
createFilesOnDisk(t, fs, "/data", files)
|
||||
|
||||
// Add dotfiles and manifest file on disk
|
||||
require.NoError(t, afero.WriteFile(fs, "/data/.hidden", []byte("dotfile"), 0o644))
|
||||
require.NoError(t, fs.MkdirAll("/data/.git", 0o755))
|
||||
require.NoError(t, afero.WriteFile(fs, "/data/.git/config", []byte("git config"), 0o644))
|
||||
|
||||
chk, err := NewChecker("/data/.index.mf", "/data", fs)
|
||||
require.NoError(t, err)
|
||||
|
||||
results := make(chan Result, 10)
|
||||
err = chk.FindExtraFiles(context.Background(), results)
|
||||
require.NoError(t, err)
|
||||
|
||||
var extras []Result
|
||||
for r := range results {
|
||||
extras = append(extras, r)
|
||||
}
|
||||
|
||||
// Should report NO extra files — dotfiles and manifest should be skipped
|
||||
assert.Empty(t, extras, "FindExtraFiles should not report dotfiles or manifest file as extra; got: %v", extras)
|
||||
}
|
||||
|
||||
func TestFindExtraFilesSkipsManifestFile(t *testing.T) {
|
||||
// The manifest file itself should never be reported as extra
|
||||
fs := afero.NewMemMapFs()
|
||||
files := map[string][]byte{
|
||||
"file1.txt": []byte("content"),
|
||||
}
|
||||
createTestManifest(t, fs, "/data/index.mf", files)
|
||||
createFilesOnDisk(t, fs, "/data", files)
|
||||
|
||||
chk, err := NewChecker("/data/index.mf", "/data", fs)
|
||||
require.NoError(t, err)
|
||||
|
||||
results := make(chan Result, 10)
|
||||
err = chk.FindExtraFiles(context.Background(), results)
|
||||
require.NoError(t, err)
|
||||
|
||||
var extras []Result
|
||||
for r := range results {
|
||||
extras = append(extras, r)
|
||||
}
|
||||
|
||||
assert.Empty(t, extras, "manifest file should not be reported as extra; got: %v", extras)
|
||||
}
|
||||
|
||||
func TestCheckEmptyManifest(t *testing.T) {
|
||||
fs := afero.NewMemMapFs()
|
||||
// Create manifest with no files
|
||||
|
||||
Loading…
Reference in New Issue
Block a user