diff --git a/pkg/lib/filesystem/local-storage.go b/pkg/lib/filesystem/local-storage.go index f6682884..14a893f5 100644 --- a/pkg/lib/filesystem/local-storage.go +++ b/pkg/lib/filesystem/local-storage.go @@ -241,6 +241,7 @@ func saveContentLayer(ctx context.Context, localRepo local.LocalRepo, path strin // TODO: Add support for ModelPack's "raw" layer type return ocispec.DescriptorEmptyJSON, nil, fmt.Errorf("Only tar-formatted layers are currently supported") } + tempPath, desc, info, err := packLayerToTar(path, mediaType, ignore) if err != nil { return ocispec.DescriptorEmptyJSON, nil, err diff --git a/pkg/lib/filesystem/tar.go b/pkg/lib/filesystem/tar.go index 06a13c17..db8f5b17 100644 --- a/pkg/lib/filesystem/tar.go +++ b/pkg/lib/filesystem/tar.go @@ -22,6 +22,7 @@ import ( "errors" "fmt" "io" + "io/fs" "os" "path/filepath" "strings" @@ -31,6 +32,7 @@ import ( "github.com/kitops-ml/kitops/pkg/lib/constants/mediatype" "github.com/kitops-ml/kitops/pkg/lib/filesystem/cache" "github.com/kitops-ml/kitops/pkg/lib/filesystem/ignore" + "github.com/kitops-ml/kitops/pkg/lib/kitfile/generate" "github.com/kitops-ml/kitops/pkg/output" "github.com/opencontainers/go-digest" @@ -158,7 +160,7 @@ func writeLayerToTar(basePath string, ignore ignore.Paths, tarWriter *output.Pro return true } - err = filepath.Walk(".", func(file string, fi os.FileInfo, err error) error { + err = filepath.WalkDir(".", func(file string, d fs.DirEntry, err error) error { if err != nil { return err } @@ -166,17 +168,30 @@ func writeLayerToTar(basePath string, ignore ignore.Paths, tarWriter *output.Pro return nil } // Skip anything that's not a regular file or directory - if !fi.Mode().IsRegular() && !fi.Mode().IsDir() { + if !d.Type().IsRegular() && !d.IsDir() { return nil } // Since we're walking from the context directory, we want to skip irrelevant files (e.g. sibling directories) if !sameDirTree(basePath, file) { - if fi.IsDir() { + if d.IsDir() { return filepath.SkipDir } return nil } + if generate.ShouldIgnoreFile(d.Name()) { + plog.Debugf("Skipping file %s: OS-specific file", file) + if d.IsDir() { + return filepath.SkipDir + } + return nil + } + + fi, err := d.Info() + if err != nil { + return fmt.Errorf("failed to read file info for %s: %w", file, err) + } + // Check if file should be ignored by the ignorefile/other Kitfile layers if shouldIgnore, err := ignore.Matches(file, basePath); err != nil { return fmt.Errorf("failed to match %s against ignore file: %w", file, err) diff --git a/pkg/lib/kitfile/generate/filesystem.go b/pkg/lib/kitfile/generate/filesystem.go index da877275..2ec18110 100644 --- a/pkg/lib/kitfile/generate/filesystem.go +++ b/pkg/lib/kitfile/generate/filesystem.go @@ -20,8 +20,37 @@ import ( "fmt" "os" "path/filepath" + "strings" ) +// OsSpecificFiles contains filenames that are auto-generated by operating systems +// and should be ignored by KitOps when scanning the filesystem. +var OsSpecificFiles = []string{ + ".DS_Store", // macOS + ".AppleDouble", // macOS + ".LSOverride", // macOS + ".Spotlight-V100", // macOS + ".Trashes", // macOS + "Thumbs.db", // Windows + "desktop.ini", // Windows + "$RECYCLE.BIN", // Windows + "ehthumbs.db", // Windows +} + +// ShouldIgnoreFile returns true if the file should be ignored. +// This helper is exported so other packages (for example packing logic) +// can reuse the same OS-file filtering logic. +func ShouldIgnoreFile(name string) bool { + // Ignore known OS-specific metadata files + for _, osFile := range OsSpecificFiles { + if strings.EqualFold(name, osFile) { + return true + } + } + + return false +} + type DirectoryListing struct { Name string Path string @@ -52,6 +81,10 @@ func genDirListingFromPath(curDir, contextDir string) (*DirectoryListing, error) return nil, fmt.Errorf("failed to read directory %s: %w", fullPath, err) } for _, dirEntry := range ds { + // Skip OS-specific files that should not be included in the Kitfile + if ShouldIgnoreFile(dirEntry.Name()) { + continue + } relPath := filepath.Join(curDir, dirEntry.Name()) fullPath := filepath.Join(contextDir, relPath) t := dirEntry.Type()