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 }