From 78cd787622caff2c2e2bf7f9c65ace71d7b5a9c9 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Mon, 16 Dec 2024 23:32:16 -0500 Subject: [PATCH] refactor: avoid shelling out to run tar --- plugins/common/docker.go | 42 ++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/plugins/common/docker.go b/plugins/common/docker.go index 10d64b8f6..b813a0cac 100644 --- a/plugins/common/docker.go +++ b/plugins/common/docker.go @@ -1,7 +1,10 @@ package common import ( + "archive/tar" + "bytes" "fmt" + "io" "os" "strconv" "strings" @@ -132,18 +135,11 @@ func CopyFromImage(appName string, image string, source string, destination stri } // extract the contents via tar - // tar -xOf - - result, err = CallExecCommand(ExecCommandInput{ - Command: "tar", - Args: []string{"-xOf", "-"}, - Stdin: strings.NewReader(tarContents), - }) + content, err := extractTarToString(tarContents) if err != nil { return fmt.Errorf("Unable to extract contents from tar: %v", err) } - contents = result.StdoutContents() - tmpFile, err := os.CreateTemp(os.TempDir(), fmt.Sprintf("dokku-%s-%s", MustGetEnv("DOKKU_PID"), "CopyFromImage")) if err != nil { return fmt.Errorf("Cannot create temporary file: %v", err) @@ -201,6 +197,36 @@ func CopyFromImage(appName string, image string, source string, destination stri return nil } +// Function to extract tar contents and return them as a string +func extractTarToString(in string) (string, error) { + // Initialize a buffer to accumulate the extracted content + var extractedContent bytes.Buffer + + // Create a tar reader from standard input + tarReader := tar.NewReader(strings.NewReader(in)) + + // Iterate through the files in the tar archive + for { + // Read the next header (file entry) + _, err := tarReader.Next() + if err == io.EOF { + break // End of archive + } + if err != nil { + return "", fmt.Errorf("error reading tar header: %v", err) + } + + // Write the content of the current file into the buffer + _, err = io.Copy(&extractedContent, tarReader) + if err != nil { + return "", fmt.Errorf("error copying file content: %v", err) + } + } + + // Return the accumulated content as a string + return strings.TrimSpace(extractedContent.String()), nil +} + // DockerBin returns a string which contains a path to the current docker binary func DockerBin() string { dockerBin := os.Getenv("DOCKER_BIN")