github.com/sneal/packer@v0.5.2/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 dstF, err := os.Create(dst) 25 if err != nil { 26 return err 27 } 28 defer dstF.Close() 29 30 if _, err := io.Copy(dstF, srcF); err != nil { 31 return err 32 } 33 34 return nil 35 } 36 37 // DirToBox takes the directory and compresses it into a Vagrant-compatible 38 // box. This function does not perform checks to verify that dir is 39 // actually a proper box. This is an expected precondition. 40 func DirToBox(dst, dir string, ui packer.Ui, level int) error { 41 log.Printf("Turning dir into box: %s => %s", dir, dst) 42 dstF, err := os.Create(dst) 43 if err != nil { 44 return err 45 } 46 defer dstF.Close() 47 48 var dstWriter io.Writer = dstF 49 if level != flate.NoCompression { 50 log.Printf("Compressing with gzip compression level: %d", level) 51 gzipWriter, err := gzip.NewWriterLevel(dstWriter, level) 52 if err != nil { 53 return err 54 } 55 defer gzipWriter.Close() 56 57 dstWriter = gzipWriter 58 } 59 60 tarWriter := tar.NewWriter(dstWriter) 61 defer tarWriter.Close() 62 63 // This is the walk func that tars each of the files in the dir 64 tarWalk := func(path string, info os.FileInfo, prevErr error) error { 65 // If there was a prior error, return it 66 if prevErr != nil { 67 return prevErr 68 } 69 70 // Skip directories 71 if info.IsDir() { 72 log.Printf("Skipping directory '%s' for box '%s'", path, dst) 73 return nil 74 } 75 76 log.Printf("Box add: '%s' to '%s'", path, dst) 77 f, err := os.Open(path) 78 if err != nil { 79 return err 80 } 81 defer f.Close() 82 83 header, err := tar.FileInfoHeader(info, "") 84 if err != nil { 85 return err 86 } 87 88 // We have to set the Name explicitly because it is supposed to 89 // be a relative path to the root. Otherwise, the tar ends up 90 // being a bunch of files in the root, even if they're actually 91 // nested in a dir in the original "dir" param. 92 header.Name, err = filepath.Rel(dir, path) 93 if err != nil { 94 return err 95 } 96 97 if ui != nil { 98 ui.Message(fmt.Sprintf("Compressing: %s", header.Name)) 99 } 100 101 if err := tarWriter.WriteHeader(header); err != nil { 102 return err 103 } 104 105 if _, err := io.Copy(tarWriter, f); err != nil { 106 return err 107 } 108 109 return nil 110 } 111 112 // Tar.gz everything up 113 return filepath.Walk(dir, tarWalk) 114 } 115 116 // WriteMetadata writes the "metadata.json" file for a Vagrant box. 117 func WriteMetadata(dir string, contents interface{}) error { 118 f, err := os.Create(filepath.Join(dir, "metadata.json")) 119 if err != nil { 120 return err 121 } 122 defer f.Close() 123 124 enc := json.NewEncoder(f) 125 return enc.Encode(contents) 126 }