Fixes #3960
Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)
| ... | ... |
@@ -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, |