Browse code

Fix add hang when dest is .

Fixes #3960
Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)

Michael Crosby authored on 2014/05/23 09:03:00
Showing 1 changed files
... ...
@@ -415,17 +415,18 @@ func (b *buildFile) addContext(container *daemon.Container, orig, dest string, r
415 415
 	}
416 416
 
417 417
 	// Preserve the trailing '/'
418
-	if strings.HasSuffix(dest, "/") {
418
+	if strings.HasSuffix(dest, "/") || dest == "." {
419 419
 		destPath = destPath + "/"
420 420
 	}
421
+
421 422
 	destStat, err := os.Stat(destPath)
422 423
 	if err != nil {
423
-		if os.IsNotExist(err) {
424
-			destExists = false
425
-		} else {
424
+		if !os.IsNotExist(err) {
426 425
 			return err
427 426
 		}
427
+		destExists = false
428 428
 	}
429
+
429 430
 	fi, err := os.Stat(origPath)
430 431
 	if err != nil {
431 432
 		if os.IsNotExist(err) {
... ...
@@ -434,57 +435,29 @@ func (b *buildFile) addContext(container *daemon.Container, orig, dest string, r
434 434
 		return err
435 435
 	}
436 436
 
437
-	fixPermsR := func(destPath string, uid, gid int) error {
438
-		return filepath.Walk(destPath, func(path string, info os.FileInfo, err error) error {
439
-			if err := os.Lchown(path, uid, gid); err != nil && !os.IsNotExist(err) {
440
-				return err
441
-			}
442
-			return nil
443
-		})
444
-	}
445
-
446 437
 	if fi.IsDir() {
447
-		if err := archive.CopyWithTar(origPath, destPath); err != nil {
448
-			return err
449
-		}
450
-		if destExists {
451
-			files, err := ioutil.ReadDir(origPath)
452
-			if err != nil {
453
-				return err
454
-			}
455
-			for _, file := range files {
456
-				if err := fixPermsR(filepath.Join(destPath, file.Name()), 0, 0); err != nil {
457
-					return err
458
-				}
459
-			}
460
-		} else {
461
-			if err := fixPermsR(destPath, 0, 0); err != nil {
462
-				return err
463
-			}
464
-		}
465
-		return nil
466
-	}
467
-
468
-	// First try to unpack the source as an archive
469
-	// to support the untar feature we need to clean up the path a little bit
470
-	// because tar is very forgiving.  First we need to strip off the archive's
471
-	// filename from the path but this is only added if it does not end in / .
472
-	tarDest := destPath
473
-	if strings.HasSuffix(tarDest, "/") {
474
-		tarDest = filepath.Dir(destPath)
438
+		return copyAsDirectory(origPath, destPath, destExists)
475 439
 	}
476 440
 
477 441
 	// If we are adding a remote file, do not try to untar it
478 442
 	if !remote {
443
+		// First try to unpack the source as an archive
444
+		// to support the untar feature we need to clean up the path a little bit
445
+		// because tar is very forgiving.  First we need to strip off the archive's
446
+		// filename from the path but this is only added if it does not end in / .
447
+		tarDest := destPath
448
+		if strings.HasSuffix(tarDest, "/") {
449
+			tarDest = filepath.Dir(destPath)
450
+		}
451
+
479 452
 		// try to successfully untar the orig
480 453
 		if err := archive.UntarPath(origPath, tarDest); err == nil {
481 454
 			return nil
455
+		} else if err != io.EOF {
456
+			utils.Debugf("Couldn't untar %s to %s: %s", origPath, tarDest, err)
482 457
 		}
483
-		utils.Debugf("Couldn't untar %s to %s: %s", origPath, destPath, err)
484 458
 	}
485 459
 
486
-	// If that fails, just copy it as a regular file
487
-	// but do not use all the magic path handling for the tar path
488 460
 	if err := os.MkdirAll(path.Dir(destPath), 0755); err != nil {
489 461
 		return err
490 462
 	}
... ...
@@ -497,10 +470,7 @@ func (b *buildFile) addContext(container *daemon.Container, orig, dest string, r
497 497
 		resPath = path.Join(destPath, path.Base(origPath))
498 498
 	}
499 499
 
500
-	if err := fixPermsR(resPath, 0, 0); err != nil {
501
-		return err
502
-	}
503
-	return nil
500
+	return fixPermissions(resPath, 0, 0)
504 501
 }
505 502
 
506 503
 func (b *buildFile) CmdAdd(args string) error {
... ...
@@ -873,6 +843,37 @@ func stripComments(raw []byte) string {
873 873
 	return strings.Join(out, "\n")
874 874
 }
875 875
 
876
+func copyAsDirectory(source, destination string, destinationExists bool) error {
877
+	if err := archive.CopyWithTar(source, destination); err != nil {
878
+		return err
879
+	}
880
+
881
+	if destinationExists {
882
+		files, err := ioutil.ReadDir(source)
883
+		if err != nil {
884
+			return err
885
+		}
886
+
887
+		for _, file := range files {
888
+			if err := fixPermissions(filepath.Join(destination, file.Name()), 0, 0); err != nil {
889
+				return err
890
+			}
891
+		}
892
+		return nil
893
+	}
894
+
895
+	return fixPermissions(destination, 0, 0)
896
+}
897
+
898
+func fixPermissions(destination string, uid, gid int) error {
899
+	return filepath.Walk(destination, func(path string, info os.FileInfo, err error) error {
900
+		if err := os.Lchown(path, uid, gid); err != nil && !os.IsNotExist(err) {
901
+			return err
902
+		}
903
+		return nil
904
+	})
905
+}
906
+
876 907
 func NewBuildFile(srv *Server, outStream, errStream io.Writer, verbose, utilizeCache, rm bool, forceRm bool, outOld io.Writer, sf *utils.StreamFormatter, auth *registry.AuthConfig, authConfigFile *registry.ConfigFile) BuildFile {
877 908
 	return &buildFile{
878 909
 		daemon:        srv.daemon,