github.com/tonnydourado/packer@v0.6.1-0.20140701134019-5d0cd9676a37/post-processor/vagrant/util.go (about)

     1  package vagrant
     2  
     3  import (
     4  	"archive/tar"
     5  	"compress/flate"
     6  	"compress/gzip"
     7  	"encoding/json"
     8  	"fmt"
     9  	"github.com/mitchellh/packer/packer"
    10  	"io"
    11  	"log"
    12  	"os"
    13  	"path/filepath"
    14  )
    15  
    16  // Copies a file by copying the contents of the file to another place.
    17  func CopyContents(dst, src string) error {
    18  	srcF, err := os.Open(src)
    19  	if err != nil {
    20  		return err
    21  	}
    22  	defer srcF.Close()
    23  
    24  	dstDir, _ := filepath.Split(dst)
    25  	if dstDir != "" {
    26  		err := os.MkdirAll(dstDir, os.ModePerm)
    27  		if err != nil {
    28  			return err
    29  		}
    30  	}
    31  
    32  	dstF, err := os.Create(dst)
    33  	if err != nil {
    34  		return err
    35  	}
    36  	defer dstF.Close()
    37  
    38  	if _, err := io.Copy(dstF, srcF); err != nil {
    39  		return err
    40  	}
    41  
    42  	return nil
    43  }
    44  
    45  // DirToBox takes the directory and compresses it into a Vagrant-compatible
    46  // box. This function does not perform checks to verify that dir is
    47  // actually a proper box. This is an expected precondition.
    48  func DirToBox(dst, dir string, ui packer.Ui, level int) error {
    49  	log.Printf("Turning dir into box: %s => %s", dir, dst)
    50  
    51  	// Make the containing directory, if it does not already exist
    52  	err := os.MkdirAll(filepath.Dir(dst), 0755)
    53  	if err != nil {
    54  		return err
    55  	}
    56  
    57  	dstF, err := os.Create(dst)
    58  	if err != nil {
    59  		return err
    60  	}
    61  	defer dstF.Close()
    62  
    63  	var dstWriter io.Writer = dstF
    64  	if level != flate.NoCompression {
    65  		log.Printf("Compressing with gzip compression level: %d", level)
    66  		gzipWriter, err := gzip.NewWriterLevel(dstWriter, level)
    67  		if err != nil {
    68  			return err
    69  		}
    70  		defer gzipWriter.Close()
    71  
    72  		dstWriter = gzipWriter
    73  	}
    74  
    75  	tarWriter := tar.NewWriter(dstWriter)
    76  	defer tarWriter.Close()
    77  
    78  	// This is the walk func that tars each of the files in the dir
    79  	tarWalk := func(path string, info os.FileInfo, prevErr error) error {
    80  		// If there was a prior error, return it
    81  		if prevErr != nil {
    82  			return prevErr
    83  		}
    84  
    85  		// Skip directories
    86  		if info.IsDir() {
    87  			log.Printf("Skipping directory '%s' for box '%s'", path, dst)
    88  			return nil
    89  		}
    90  
    91  		log.Printf("Box add: '%s' to '%s'", path, dst)
    92  		f, err := os.Open(path)
    93  		if err != nil {
    94  			return err
    95  		}
    96  		defer f.Close()
    97  
    98  		header, err := tar.FileInfoHeader(info, "")
    99  		if err != nil {
   100  			return err
   101  		}
   102  
   103  		// We have to set the Name explicitly because it is supposed to
   104  		// be a relative path to the root. Otherwise, the tar ends up
   105  		// being a bunch of files in the root, even if they're actually
   106  		// nested in a dir in the original "dir" param.
   107  		header.Name, err = filepath.Rel(dir, path)
   108  		if err != nil {
   109  			return err
   110  		}
   111  
   112  		if ui != nil {
   113  			ui.Message(fmt.Sprintf("Compressing: %s", header.Name))
   114  		}
   115  
   116  		if err := tarWriter.WriteHeader(header); err != nil {
   117  			return err
   118  		}
   119  
   120  		if _, err := io.Copy(tarWriter, f); err != nil {
   121  			return err
   122  		}
   123  
   124  		return nil
   125  	}
   126  
   127  	// Tar.gz everything up
   128  	return filepath.Walk(dir, tarWalk)
   129  }
   130  
   131  // WriteMetadata writes the "metadata.json" file for a Vagrant box.
   132  func WriteMetadata(dir string, contents interface{}) error {
   133  	f, err := os.Create(filepath.Join(dir, "metadata.json"))
   134  	if err != nil {
   135  		return err
   136  	}
   137  	defer f.Close()
   138  
   139  	enc := json.NewEncoder(f)
   140  	return enc.Encode(contents)
   141  }