github.com/supr/packer@v0.3.10-0.20131015195147-7b09e24ac3c1/post-processor/vagrant/util.go (about)

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