Przeglądaj źródła

Merge pull request #3510 from creack/hotfix-add_caching

Hotfix add caching
Guillaume J. Charmes 11 lat temu
rodzic
commit
772765c404
3 zmienionych plików z 47 dodań i 18 usunięć
  1. 25 13
      buildfile.go
  2. 20 0
      integration/buildfile_test.go
  3. 2 5
      utils/utils.go

+ 25 - 13
buildfile.go

@@ -353,8 +353,9 @@ func (b *buildFile) CmdAdd(args string) error {
 
 	// FIXME: do we really need this?
 	var (
-		origPath = orig
-		destPath = dest
+		origPath   = orig
+		destPath   = dest
+		remoteHash string
 	)
 
 	if utils.IsURL(orig) {
@@ -373,11 +374,20 @@ func (b *buildFile) CmdAdd(args string) error {
 		}
 		defer os.RemoveAll(tmpDirName)
 		if _, err = io.Copy(tmpFile, resp.Body); err != nil {
+			tmpFile.Close()
 			return err
 		}
 		origPath = path.Join(filepath.Base(tmpDirName), filepath.Base(tmpFileName))
 		tmpFile.Close()
 
+		// Process the checksum
+		r, err := archive.Tar(tmpFileName, archive.Uncompressed)
+		if err != nil {
+			return err
+		}
+		tarSum := utils.TarSum{Reader: r, DisableCompression: true}
+		remoteHash = tarSum.Sum(nil)
+
 		// If the destination is a directory, figure out the filename.
 		if strings.HasSuffix(dest, "/") {
 			u, err := url.Parse(orig)
@@ -408,20 +418,16 @@ func (b *buildFile) CmdAdd(args string) error {
 			sums = b.context.GetSums()
 		)
 
-		// Has tarsum strips the '.' and './', we put it back for comparaison.
-		for file, sum := range sums {
-			if len(file) == 0 || file[0] != '.' && file[0] != '/' {
-				delete(sums, file)
-				sums["./"+file] = sum
-			}
-		}
-
-		if fi, err := os.Stat(path.Join(b.contextPath, origPath)); err != nil {
+		if remoteHash != "" {
+			hash = remoteHash
+		} else if fi, err := os.Stat(path.Join(b.contextPath, origPath)); err != nil {
 			return err
 		} else if fi.IsDir() {
 			var subfiles []string
 			for file, sum := range sums {
-				if strings.HasPrefix(file, origPath) {
+				absFile := path.Join(b.contextPath, file)
+				absOrigPath := path.Join(b.contextPath, origPath)
+				if strings.HasPrefix(absFile, absOrigPath) {
 					subfiles = append(subfiles, sum)
 				}
 			}
@@ -430,7 +436,13 @@ func (b *buildFile) CmdAdd(args string) error {
 			hasher.Write([]byte(strings.Join(subfiles, ",")))
 			hash = "dir:" + hex.EncodeToString(hasher.Sum(nil))
 		} else {
-			hash = "file:" + sums[origPath]
+			if origPath[0] == '/' && len(origPath) > 1 {
+				origPath = origPath[1:]
+			}
+			origPath = strings.TrimPrefix(origPath, "./")
+			if h, ok := sums[origPath]; ok {
+				hash = "file:" + h
+			}
 		}
 		b.config.Cmd = []string{"/bin/sh", "-c", fmt.Sprintf("#(nop) ADD %s in %s", hash, dest)}
 		hit, err := b.probeCache()

+ 20 - 0
integration/buildfile_test.go

@@ -592,6 +592,26 @@ func TestBuildADDLocalFileWithoutCache(t *testing.T) {
 	checkCacheBehavior(t, template, false)
 }
 
+func TestBuildADDCurrentDirectoryWithCache(t *testing.T) {
+	template := testContextTemplate{`
+        from {IMAGE}
+        maintainer dockerio
+        add . /usr/lib/bla
+        `,
+		nil, nil}
+	checkCacheBehavior(t, template, true)
+}
+
+func TestBuildADDCurrentDirectoryWithoutCache(t *testing.T) {
+	template := testContextTemplate{`
+        from {IMAGE}
+        maintainer dockerio
+        add . /usr/lib/bla
+        `,
+		nil, nil}
+	checkCacheBehavior(t, template, false)
+}
+
 func TestBuildADDRemoteFileWithCache(t *testing.T) {
 	template := testContextTemplate{`
         from {IMAGE}

+ 2 - 5
utils/utils.go

@@ -6,7 +6,6 @@ import (
 	"crypto/sha256"
 	"encoding/hex"
 	"encoding/json"
-	"errors"
 	"fmt"
 	"index/suffixarray"
 	"io"
@@ -46,14 +45,12 @@ func Go(f func() error) chan error {
 }
 
 // Request a given URL and return an io.Reader
-func Download(url string) (*http.Response, error) {
-	var resp *http.Response
-	var err error
+func Download(url string) (resp *http.Response, err error) {
 	if resp, err = http.Get(url); err != nil {
 		return nil, err
 	}
 	if resp.StatusCode >= 400 {
-		return nil, errors.New("Got HTTP status code >= 400: " + resp.Status)
+		return nil, fmt.Errorf("Got HTTP status code >= 400: %s", resp.Status)
 	}
 	return resp, nil
 }