From 5eb97908c22112ded02efc38a1d97af3a05d04f9 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 25 Aug 2013 20:47:10 -0700 Subject: [PATCH] communicator/ssh: Trailing slash won't create destination dir --- communicator/ssh/communicator.go | 82 +++++++++++++++++++------------- packer/communicator.go | 5 ++ 2 files changed, 54 insertions(+), 33 deletions(-) diff --git a/communicator/ssh/communicator.go b/communicator/ssh/communicator.go index ec9a40724..35ff8f0ca 100644 --- a/communicator/ssh/communicator.go +++ b/communicator/ssh/communicator.go @@ -113,19 +113,30 @@ func (c *comm) Upload(path string, input io.Reader) error { } func (c *comm) UploadDir(dst string, src string, excl []string) error { - f, err := os.Open(src) - if err != nil { - return err - } - defer f.Close() - - entries, err := f.Readdir(-1) - if err != nil { - return err - } - + log.Printf("Upload dir '%s' to '%s'", src, dst) scpFunc := func(w io.Writer, r *bufio.Reader) error { - return scpUploadDir(src, entries, w, r) + uploadEntries := func() error { + f, err := os.Open(src) + if err != nil { + return err + } + defer f.Close() + + entries, err := f.Readdir(-1) + if err != nil { + return err + } + + return scpUploadDir(src, entries, w, r) + } + + if src[len(src)-1] != '/' { + log.Printf("No trailing slash, creating the source directory name") + return scpUploadDirProtocol(filepath.Base(src), w, r, uploadEntries) + } else { + // Trailing slash, so only upload the contents + return uploadEntries() + } } return c.scpSession("scp -rvt "+dst, scpFunc) @@ -311,6 +322,26 @@ func scpUploadFile(dst string, src io.Reader, w io.Writer, r *bufio.Reader) erro return nil } +func scpUploadDirProtocol(name string, w io.Writer, r *bufio.Reader, f func() error) error { + log.Printf("SCP: starting directory upload: %s", name) + fmt.Fprintln(w, "D0755 0", name) + err := checkSCPStatus(r) + if err != nil { + return err + } + + if err := f(); err != nil { + return err + } + + fmt.Fprintln(w, "E") + if err != nil { + return err + } + + return nil +} + func scpUploadDir(root string, fs []os.FileInfo, w io.Writer, r *bufio.Reader) error { for _, fi := range fs { realPath := filepath.Join(root, fi.Name()) @@ -335,21 +366,11 @@ func scpUploadDir(root string, fs []os.FileInfo, w io.Writer, r *bufio.Reader) e } // It is a directory, recursively upload - log.Printf("SCP: starting directory upload: %s", fi.Name()) - fmt.Fprintln(w, "D0755 0", fi.Name()) - err := checkSCPStatus(r) - if err != nil { - return err - } - - f, err := os.Open(realPath) - if err != nil { - return err - } - - // Execute this in a function just so that we have easy "defer" - // available because laziness. - err = func() error { + err := scpUploadDirProtocol(fi.Name(), w, r, func() error { + f, err := os.Open(realPath) + if err != nil { + return err + } defer f.Close() entries, err := f.Readdir(-1) @@ -358,12 +379,7 @@ func scpUploadDir(root string, fs []os.FileInfo, w io.Writer, r *bufio.Reader) e } return scpUploadDir(realPath, entries, w, r) - }() - if err != nil { - return err - } - - fmt.Fprintln(w, "E") + }) if err != nil { return err } diff --git a/packer/communicator.go b/packer/communicator.go index 00df95811..236d34633 100644 --- a/packer/communicator.go +++ b/packer/communicator.go @@ -62,6 +62,11 @@ type Communicator interface { // UploadDir uploads the contents of a directory recursively to // the remote path. It also takes an optional slice of paths to // ignore when uploading. + // + // The folder name of the source folder should be created unless there + // is a trailing slash on the source "/". For example: "/tmp/src" as + // the source will create a "src" directory in the destination unless + // a trailing slash is added. This is identical behavior to rsync(1). UploadDir(string, string, []string) error // Download downloads a file from the machine from the given remote path