func WriteMetadata(dir string, contents interface{}) error {
	f, err := os.Create(filepath.Join(dir, "metadata.json"))
	if err != nil {
		return err
	}
	defer f.Close()
	enc := json.NewEncoder(f)
	return enc.Encode(contents)
}
WriteMetadata writes the "metadata.json" file for a Vagrant box.
package main
import (
	"archive/tar"
	"compress/flate"
	"compress/gzip"
	"encoding/json"
	"fmt"
	"github.com/mitchellh/packer/packer"
	"io"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)
func CopyContents(dst, src string) error {
	srcF, err := os.Open(src)
	if err != nil {
		return err
	}
	defer srcF.Close()
	dstF, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer dstF.Close()
	if _, err := io.Copy(dstF, srcF); err != nil {
		return err
	}
	return nil
}
func DirToBox(dst, dir string, ui packer.Ui, level int) error {
	log.Printf("Turning dir into box: %s => %s", dir, dst)
	dstF, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer dstF.Close()
	var dstWriter io.Writer = dstF
	if level != flate.NoCompression {
		log.Printf("Compressing with gzip compression level: %d", level)
		gzipWriter, err := gzip.NewWriterLevel(dstWriter, level)
		if err != nil {
			return err
		}
		defer gzipWriter.Close()
		dstWriter = gzipWriter
	}
	tarWriter := tar.NewWriter(dstWriter)
	defer tarWriter.Close()
	tarWalk := func(path string, info os.FileInfo, prevErr error) error {
		if prevErr != nil {
			return prevErr
		}
		if info.IsDir() {
			log.Printf("Skipping directory '%s' for box '%s'", path, dst)
			return nil
		}
		log.Printf("Box add: '%s' to '%s'", path, dst)
		f, err := os.Open(path)
		if err != nil {
			return err
		}
		defer f.Close()
		header, err := tar.FileInfoHeader(info, "")
		if err != nil {
			return err
		}
		header.Name, err = filepath.Rel(dir, path)
		if err != nil {
			return err
		}
		if ui != nil {
			ui.Message(fmt.Sprintf("Compressing: %s", header.Name))
		}
		if err := tarWriter.WriteHeader(header); err != nil {
			return err
		}
		if _, err := io.Copy(tarWriter, f); err != nil {
			return err
		}
		return nil
	}
	return filepath.Walk(dir, tarWalk)
}