Link VHD instead of copy where allowed by OS

No need to incur that copy I/O if we don't even change the file!
This commit is contained in:
Sander Saares 2017-08-02 14:27:22 +03:00
parent 3974976518
commit 0ebf1d0da9
2 changed files with 30 additions and 4 deletions

View File

@ -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))
}

View File

@ -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.