diff --git a/post-processor/vagrant/hyperv.go b/post-processor/vagrant/hyperv.go index cf71820e9..14486738b 100644 --- a/post-processor/vagrant/hyperv.go +++ b/post-processor/vagrant/hyperv.go @@ -2,10 +2,11 @@ package vagrant import ( "fmt" - "github.com/hashicorp/packer/packer" "os" "path/filepath" "strings" + + "github.com/hashicorp/packer/packer" ) type HypervProvider struct{} @@ -55,10 +56,18 @@ func (p *HypervProvider) Process(ui packer.Ui, artifact packer.Artifact, dir str dstPath := filepath.Join(dstDir, filepath.Base(path)) - if err = CopyContents(dstPath, path); err != nil { - ui.Message(fmt.Sprintf("err in copying: %s to %s", path, dstPath)) - return + // We prefer to link the files where possible because they are often very huge. + // Some filesystem configurations do not allow hardlinks. As the possibilities + // of mounting different devices in different paths are flexible, we just try to + // link the file and copy if the link fails, thereby automatically optimizing with a safe fallback. + if err = LinkFile(dstPath, path); err != nil { + // ui.Message(fmt.Sprintf("err in linking: %s to %s", path, dstPath)) + if err = CopyContents(dstPath, path); err != nil { + ui.Message(fmt.Sprintf("err in copying: %s to %s", path, dstPath)) + return + } } + ui.Message(fmt.Sprintf("Copyed %s to %s", path, dstPath)) } diff --git a/post-processor/vagrant/util.go b/post-processor/vagrant/util.go index bc154d640..8c6e09b50 100644 --- a/post-processor/vagrant/util.go +++ b/post-processor/vagrant/util.go @@ -51,6 +51,23 @@ func CopyContents(dst, src string) error { return nil } +// Creates a (hard) link to a file, ensuring that all parent directories also exist. +func LinkFile(dst, src string) error { + dstDir, _ := filepath.Split(dst) + if dstDir != "" { + err := os.MkdirAll(dstDir, os.ModePerm) + if err != nil { + return err + } + } + + if err := os.Link(src, dst); err != nil { + return err + } + + return nil +} + // DirToBox takes the directory and compresses it into a Vagrant-compatible // box. This function does not perform checks to verify that dir is // actually a proper box. This is an expected precondition.