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 }