From 2ceb1146078f900a686019398a94d113943beeb9 Mon Sep 17 00:00:00 2001 From: John Howard Date: Sun, 12 Jul 2015 09:05:10 -0700 Subject: [PATCH] Windows: Fix builder Signed-off-by: John Howard --- builder/internals.go | 56 ++++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/builder/internals.go b/builder/internals.go index 0ec75143a3..bf085d4ff3 100644 --- a/builder/internals.go +++ b/builder/internals.go @@ -139,7 +139,8 @@ func (b *Builder) runContextCommand(args []string, allowRemote bool, allowDecomp return fmt.Errorf("Invalid %s format - at least two arguments required", cmdName) } - dest := args[len(args)-1] // last one is always the dest + // Work in daemon-specific filepath semantics + dest := filepath.FromSlash(args[len(args)-1]) // last one is always the dest copyInfos := []*copyInfo{} @@ -174,8 +175,7 @@ func (b *Builder) runContextCommand(args []string, allowRemote bool, allowDecomp if len(copyInfos) == 0 { return fmt.Errorf("No source files were specified") } - - if len(copyInfos) > 1 && !strings.HasSuffix(dest, "/") { + if len(copyInfos) > 1 && !strings.HasSuffix(dest, string(os.PathSeparator)) { return fmt.Errorf("When using %s with more than one source file, the destination must be a directory and end with a /", cmdName) } @@ -250,25 +250,37 @@ func (b *Builder) runContextCommand(args []string, allowRemote bool, allowDecomp func calcCopyInfo(b *Builder, cmdName string, cInfos *[]*copyInfo, origPath string, destPath string, allowRemote bool, allowDecompression bool, allowWildcards bool) error { - if origPath != "" && origPath[0] == '/' && len(origPath) > 1 { + // Work in daemon-specific OS filepath semantics. However, we save + // the the origPath passed in here, as it might also be a URL which + // we need to check for in this function. + passedInOrigPath := origPath + origPath = filepath.FromSlash(origPath) + destPath = filepath.FromSlash(destPath) + + if origPath != "" && origPath[0] == os.PathSeparator && len(origPath) > 1 { origPath = origPath[1:] } - origPath = strings.TrimPrefix(origPath, "./") + origPath = strings.TrimPrefix(origPath, "."+string(os.PathSeparator)) // Twiddle the destPath when its a relative path - meaning, make it // relative to the WORKINGDIR if !filepath.IsAbs(destPath) { - hasSlash := strings.HasSuffix(destPath, "/") - destPath = filepath.Join("/", b.Config.WorkingDir, destPath) + hasSlash := strings.HasSuffix(destPath, string(os.PathSeparator)) + destPath = filepath.Join(string(os.PathSeparator), filepath.FromSlash(b.Config.WorkingDir), destPath) // Make sure we preserve any trailing slash if hasSlash { - destPath += "/" + destPath += string(os.PathSeparator) } } // In the remote/URL case, download it and gen its hashcode - if urlutil.IsURL(origPath) { + if urlutil.IsURL(passedInOrigPath) { + + // As it's a URL, we go back to processing on what was passed in + // to this function + origPath = passedInOrigPath + if !allowRemote { return fmt.Errorf("Source can't be a URL for %s", cmdName) } @@ -337,16 +349,16 @@ func calcCopyInfo(b *Builder, cmdName string, cInfos *[]*copyInfo, origPath stri ci.origPath = filepath.Join(filepath.Base(tmpDirName), filepath.Base(tmpFileName)) // If the destination is a directory, figure out the filename. - if strings.HasSuffix(ci.destPath, "/") { + if strings.HasSuffix(ci.destPath, string(os.PathSeparator)) { u, err := url.Parse(origPath) if err != nil { return err } path := u.Path - if strings.HasSuffix(path, "/") { + if strings.HasSuffix(path, string(os.PathSeparator)) { path = path[:len(path)-1] } - parts := strings.Split(path, "/") + parts := strings.Split(path, string(os.PathSeparator)) filename := parts[len(parts)-1] if filename == "" { return fmt.Errorf("cannot determine filename from url: %s", u) @@ -421,11 +433,11 @@ func calcCopyInfo(b *Builder, cmdName string, cInfos *[]*copyInfo, origPath stri // Add a trailing / to make sure we only pick up nested files under // the dir and not sibling files of the dir that just happen to // start with the same chars - if !strings.HasSuffix(absOrigPath, "/") { - absOrigPath += "/" + if !strings.HasSuffix(absOrigPath, string(os.PathSeparator)) { + absOrigPath += string(os.PathSeparator) } - // Need path w/o / too to find matching dir w/o trailing / + // Need path w/o slash too to find matching dir w/o trailing slash absOrigPathNoSlash := absOrigPath[:len(absOrigPath)-1] for _, fileInfo := range b.context.GetSums() { @@ -689,19 +701,23 @@ func (b *Builder) addContext(container *daemon.Container, orig, dest string, dec destPath string ) + // Work in daemon-local OS specific file paths + dest = filepath.FromSlash(dest) + destPath, err = container.GetResourcePath(dest) if err != nil { return err } - // Preserve the trailing '/' - if strings.HasSuffix(dest, "/") || dest == "." { - destPath = destPath + "/" + // Preserve the trailing slash + if strings.HasSuffix(dest, string(os.PathSeparator)) || dest == "." { + destPath = destPath + string(os.PathSeparator) } destStat, err := os.Stat(destPath) if err != nil { if !os.IsNotExist(err) { + logrus.Errorf("Error performing os.Stat on %s. %s", destPath, err) return err } destExists = false @@ -724,9 +740,9 @@ func (b *Builder) addContext(container *daemon.Container, orig, dest string, dec // First try to unpack the source as an archive // to support the untar feature we need to clean up the path a little bit // because tar is very forgiving. First we need to strip off the archive's - // filename from the path but this is only added if it does not end in / . + // filename from the path but this is only added if it does not end in slash tarDest := destPath - if strings.HasSuffix(tarDest, "/") { + if strings.HasSuffix(tarDest, string(os.PathSeparator)) { tarDest = filepath.Dir(destPath) }