From 18ca0160fc45b9904605efa2f0427b4f74fa21e9 Mon Sep 17 00:00:00 2001 From: Suleiman Dibirov Date: Sun, 6 Oct 2024 18:28:10 +0300 Subject: [PATCH] updated hash.go and tar.go Signed-off-by: Suleiman Dibirov --- pkg/compose/hash.go | 74 ++++++--------------------------------------- pkg/utils/tar.go | 58 +++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 65 deletions(-) diff --git a/pkg/compose/hash.go b/pkg/compose/hash.go index e10502785cd..aeb2bb6d310 100644 --- a/pkg/compose/hash.go +++ b/pkg/compose/hash.go @@ -20,12 +20,10 @@ import ( "bytes" "encoding/json" "fmt" - "os" - "path/filepath" + "github.com/docker/compose/v2/pkg/utils" "time" "github.com/compose-spec/compose-go/v2/types" - "github.com/docker/compose/v2/pkg/utils" "github.com/opencontainers/go-digest" ) @@ -88,10 +86,13 @@ func createTarForConfig( ) (*bytes.Buffer, error) { // fixed time to ensure the tarball is deterministic modTime := time.Unix(0, 0) - content := make([]byte, 0) + + if serviceConfig.Target == "" { + serviceConfig.Target = "/" + serviceConfig.Source + } if file.Content != "" { - content = []byte(file.Content) + return bytes.NewBuffer([]byte(file.Content)), nil } else if file.Environment != "" { env, ok := project.Environment[file.Environment] if !ok { @@ -101,67 +102,10 @@ func createTarForConfig( file.Name, ) } - content = []byte(env) + return bytes.NewBuffer([]byte(env)), nil } else if file.File != "" { - var err error - content, err = readPathContent(file.File) - - if err != nil { - return nil, err - } - } - - if len(content) == 0 { - return nil, fmt.Errorf("config %q is empty", file.Name) - } - - if serviceConfig.Target == "" { - serviceConfig.Target = "/" + serviceConfig.Source - } - - b, err := utils.CreateTar(content, serviceConfig, modTime) - if err != nil { - return nil, err - } - - return &b, nil -} - -func readPathContent(path string) ([]byte, error) { - content := make([]byte, 0) - - // Check if the path is a directory - info, err := os.Stat(path) - if err != nil { - return nil, fmt.Errorf("error accessing path %q: %v", path, err) - } - - if info.IsDir() { - // If it's a directory, read all files and concatenate their contents - err = filepath.Walk(path, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if !info.IsDir() { - fileContent, err := os.ReadFile(path) - if err != nil { - return err - } - content = append(content, fileContent...) - } - return nil - }) - if err != nil { - return nil, fmt.Errorf("error reading directory %q: %v", path, err) - } - } else { - // If it's a file, read its content - fileContent, err := os.ReadFile(path) - if err != nil { - return nil, fmt.Errorf("error reading file %q: %v", path, err) - } - content = fileContent + return utils.CreateTarByPath(file.File, modTime) } - return content, nil + return nil, fmt.Errorf("config %q is empty", file.Name) } diff --git a/pkg/utils/tar.go b/pkg/utils/tar.go index 49305f52e80..de262d88479 100644 --- a/pkg/utils/tar.go +++ b/pkg/utils/tar.go @@ -19,6 +19,9 @@ package utils import ( "archive/tar" "bytes" + "io" + "os" + "path/filepath" "strconv" "time" @@ -68,3 +71,58 @@ func CreateTar(content []byte, config types.FileReferenceConfig, modTime time.Ti err = tarWriter.Close() return b, err } + +func CreateTarByPath(path string, modTime time.Time) (*bytes.Buffer, error) { + b := new(bytes.Buffer) + tw := tar.NewWriter(b) + defer tw.Close() + + // Walk the directory or file tree at the given path + err := filepath.Walk(path, func(file string, fi os.FileInfo, err error) error { + if err != nil { + return err + } + + // Create tar header + header, err := tar.FileInfoHeader(fi, fi.Name()) + if err != nil { + return err + } + + // Preserve folder structure by using relative paths + header.Name, err = filepath.Rel(filepath.Dir(path), file) + if err != nil { + return err + } + + // Set custom modification time + header.ModTime = modTime + + // Write header to the tarball + if err := tw.WriteHeader(header); err != nil { + return err + } + + // If it's a directory, we don't need to write file content + if fi.Mode().IsRegular() { + // Open the file and write its contents + f, err := os.Open(file) + if err != nil { + return err + } + defer f.Close() + + if _, err := io.Copy(tw, f); err != nil { + return err + } + } + + return nil + }) + + if err != nil { + return nil, err + } + + return b, nil +}