This is an automated email from the ASF dual-hosted git repository. astefanutti pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit 34956df3c99cb0d86f11483dc881596940fb1178 Author: Antonin Stefanutti <[email protected]> AuthorDate: Thu Jul 29 11:36:41 2021 +0200 chore(s2i): Use tar.gz archive to preserve file permissions --- pkg/builder/s2i.go | 72 +++++++++++++++++++++++++++++++++++++++++++++++++---- pkg/util/zip/zip.go | 64 ----------------------------------------------- 2 files changed, 67 insertions(+), 69 deletions(-) diff --git a/pkg/builder/s2i.go b/pkg/builder/s2i.go index 428901a..6ce99b6 100644 --- a/pkg/builder/s2i.go +++ b/pkg/builder/s2i.go @@ -18,10 +18,16 @@ limitations under the License. package builder import ( + "archive/tar" + "compress/gzip" "context" + "fmt" + "io" "io/ioutil" "os" "path" + "path/filepath" + "strings" "time" "github.com/pkg/errors" @@ -42,7 +48,6 @@ import ( "github.com/apache/camel-k/pkg/client" "github.com/apache/camel-k/pkg/util/kubernetes/customclient" "github.com/apache/camel-k/pkg/util/log" - "github.com/apache/camel-k/pkg/util/zip" ) type s2iTask struct { @@ -140,7 +145,7 @@ func (t *s2iTask) Do(ctx context.Context) v1.BuildStatus { if err != nil { return status.Failed(err) } - archive := path.Join(tmpDir, "archive.zip") + archive := path.Join(tmpDir, "archive.tar.gz") defer os.RemoveAll(tmpDir) contextDir := t.task.ContextDir @@ -156,14 +161,19 @@ func (t *s2iTask) Do(ctx context.Context) v1.BuildStatus { contextDir = path.Join(pwd, ContextDir) } - err = zip.Directory(contextDir, archive) + archiveFile, err := os.Create(archive) if err != nil { - return status.Failed(errors.Wrap(err, "cannot zip context directory")) + return status.Failed(errors.Wrap(err, "cannot create tar archive")) + } + + err = tarDir(contextDir, archiveFile) + if err != nil { + return status.Failed(errors.Wrap(err, "cannot tar context directory")) } resource, err := ioutil.ReadFile(archive) if err != nil { - return status.Failed(errors.Wrap(err, "cannot fully read zip file "+archive)) + return status.Failed(errors.Wrap(err, "cannot read tar file "+archive)) } restClient, err := customclient.GetClientFor(t.c, "build.openshift.io", "v1") @@ -275,3 +285,55 @@ func (t *s2iTask) cancelBuild(ctx context.Context, build *buildv1.Build) error { *build = *target return nil } + +func tarDir(src string, writers ...io.Writer) error { + // ensure the src actually exists before trying to tar it + if _, err := os.Stat(src); err != nil { + return fmt.Errorf("unable to tar files - %v", err.Error()) + } + + mw := io.MultiWriter(writers...) + + gzw := gzip.NewWriter(mw) + defer gzw.Close() + + tw := tar.NewWriter(gzw) + defer tw.Close() + + return filepath.Walk(src, func(file string, fi os.FileInfo, err error) error { + if err != nil { + return err + } + + if !fi.Mode().IsRegular() { + return nil + } + + header, err := tar.FileInfoHeader(fi, fi.Name()) + if err != nil { + return err + } + + // update the name to correctly reflect the desired destination when un-taring + header.Name = strings.TrimPrefix(strings.Replace(file, src, "", -1), string(filepath.Separator)) + + if err := tw.WriteHeader(header); err != nil { + return err + } + + f, err := os.Open(file) + if err != nil { + return err + } + + if _, err := io.Copy(tw, f); err != nil { + return err + } + + // manually close here after each file operation; deferring would cause each file close + // to wait until all operations have completed. + f.Close() + + return nil + }) +} diff --git a/pkg/util/zip/zip.go b/pkg/util/zip/zip.go deleted file mode 100644 index a5f59de..0000000 --- a/pkg/util/zip/zip.go +++ /dev/null @@ -1,64 +0,0 @@ -/* -Licensed to the Apache Software Foundation (ASF) under one or more -contributor license agreements. See the NOTICE file distributed with -this work for additional information regarding copyright ownership. -The ASF licenses this file to You under the Apache License, Version 2.0 -(the "License"); you may not use this file except in compliance with -the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package zip - -import ( - "archive/zip" - "io" - "os" - "path/filepath" - "strings" -) - -func Directory(pathToZip, destinationPath string) error { - destinationFile, err := os.Create(destinationPath) - if err != nil { - return err - } - myZip := zip.NewWriter(destinationFile) - err = filepath.Walk(pathToZip, func(filePath string, info os.FileInfo, err error) error { - if info.IsDir() { - return nil - } - if err != nil { - return err - } - relPath := strings.TrimPrefix(filePath, pathToZip) - zipFile, err := myZip.Create(relPath) - if err != nil { - return err - } - fsFile, err := os.Open(filePath) - if err != nil { - return err - } - _, err = io.Copy(zipFile, fsFile) - if err != nil { - return err - } - return nil - }) - if err != nil { - return err - } - err = myZip.Close() - if err != nil { - return err - } - return nil -}
