diff --git a/CHANGELOG.md b/CHANGELOG.md index 589492ae7..60b1780d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ BUG FIXES: * core: default user variable values don't need to be strings. [GH-456] * builder/amazon-chroot: Fix errors with waitin for state change. [GH-459] +* communicator/ssh: SCP uploads now work properly when directories + contain symlinks. [GH-449] ## 0.3.8 (September 22, 2013) diff --git a/communicator/ssh/communicator.go b/communicator/ssh/communicator.go index 96de20de0..e2eea4b21 100644 --- a/communicator/ssh/communicator.go +++ b/communicator/ssh/communicator.go @@ -408,8 +408,27 @@ func scpUploadDir(root string, fs []os.FileInfo, w io.Writer, r *bufio.Reader) e for _, fi := range fs { realPath := filepath.Join(root, fi.Name()) - if !fi.IsDir() { - // It is a regular file, just upload it + // Track if this is actually a symlink to a directory. If it is + // a symlink to a file we don't do any special behavior because uploading + // a file just works. If it is a directory, we need to know so we + // treat it as such. + isSymlinkToDir := false + if fi.Mode() & os.ModeSymlink == os.ModeSymlink { + symPath, err := filepath.EvalSymlinks(realPath) + if err != nil { + return err + } + + symFi, err := os.Lstat(symPath) + if err != nil { + return err + } + + isSymlinkToDir = symFi.IsDir() + } + + if !fi.IsDir() && !isSymlinkToDir { + // It is a regular file (or symlink to a file), just upload it f, err := os.Open(realPath) if err != nil { return err