github.com/cloudfoundry-attic/ltc@v0.0.0-20151123212628-098adc7919fc/droplet_runner/command_factory/zipper/zipper.go (about) 1 package zipper 2 3 import ( 4 "archive/zip" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "os" 9 "path/filepath" 10 "strings" 11 12 "github.com/cloudfoundry-incubator/ltc/droplet_runner/command_factory/cf_ignore" 13 ) 14 15 //go:generate counterfeiter -o fake_zipper/fake_zipper.go . Zipper 16 type Zipper interface { 17 Zip(srcDir string, cfIgnore cf_ignore.CFIgnore) (string, error) 18 IsZipFile(path string) bool 19 Unzip(srcZip string, destDir string) error 20 } 21 22 type DropletArtifactZipper struct{} 23 24 func (zipper *DropletArtifactZipper) Zip(srcDir string, cfIgnore cf_ignore.CFIgnore) (string, error) { 25 tmpPath, err := ioutil.TempDir(os.TempDir(), "droplet-artifact-zipper") 26 if err != nil { 27 return "", err 28 } 29 30 fileWriter, err := os.OpenFile(filepath.Join(tmpPath, "artifact.zip"), os.O_CREATE|os.O_WRONLY, 0600) 31 if err != nil { 32 return "", err 33 } 34 defer fileWriter.Close() 35 36 zipWriter := zip.NewWriter(fileWriter) 37 defer zipWriter.Close() 38 39 contentsFileInfo, err := os.Stat(srcDir) 40 if err != nil { 41 return "", err 42 } 43 44 if !contentsFileInfo.IsDir() { 45 return "", fmt.Errorf("%s must be a directory", srcDir) 46 } 47 48 if ignoreFile, err := os.Open(filepath.Join(srcDir, ".cfignore")); err == nil { 49 defer ignoreFile.Close() 50 51 if err := cfIgnore.Parse(ignoreFile); err != nil { 52 return "", err 53 } 54 } 55 56 err = filepath.Walk(srcDir, func(fullPath string, info os.FileInfo, err error) error { 57 if err != nil { 58 return err 59 } 60 61 relativePath, err := filepath.Rel(srcDir, fullPath) 62 if err != nil { 63 return err 64 } 65 66 if cfIgnore.ShouldIgnore(relativePath) { 67 return nil 68 } 69 70 if relativePath == fileWriter.Name() || relativePath == "." || relativePath == ".." { 71 return nil 72 } 73 74 if h, err := zip.FileInfoHeader(info); err == nil { 75 h.Name = filepath.ToSlash(relativePath) 76 77 if info.IsDir() { 78 h.Name = h.Name + "/" 79 } 80 81 h.SetMode(info.Mode()) 82 83 writer, err := zipWriter.CreateHeader(h) 84 if err != nil { 85 return err 86 } 87 88 if info.IsDir() { 89 return nil 90 } 91 92 li, err := os.Lstat(fullPath) 93 if err != nil { 94 return err 95 } 96 97 if li.Mode()&os.ModeSymlink == os.ModeSymlink { 98 dest, err := os.Readlink(fullPath) 99 if err != nil { 100 return err 101 } 102 if _, err := io.Copy(writer, strings.NewReader(dest)); err != nil { 103 return err 104 } 105 } else { 106 fr, err := os.Open(fullPath) 107 if err != nil { 108 return err 109 } 110 defer fr.Close() 111 if _, err := io.Copy(writer, fr); err != nil { 112 return err 113 } 114 } 115 } 116 117 return nil 118 }) 119 120 return fileWriter.Name(), err 121 } 122 123 func (zipper *DropletArtifactZipper) IsZipFile(path string) bool { 124 reader, err := zip.OpenReader(path) 125 if err != nil { 126 return false 127 } else { 128 reader.Close() 129 return true 130 } 131 } 132 133 func (zipper *DropletArtifactZipper) Unzip(srcZip string, destDir string) error { 134 reader, err := zip.OpenReader(srcZip) 135 if err != nil { 136 return err 137 } 138 defer reader.Close() 139 140 for _, f := range reader.File { 141 err := func() error { 142 fileReader, err := f.Open() 143 if err != nil { 144 return err 145 } 146 defer fileReader.Close() 147 148 fileInfo := f.FileHeader.FileInfo() 149 150 if fileInfo.IsDir() { 151 return nil 152 } 153 154 if err := os.MkdirAll(filepath.Dir(filepath.Join(destDir, f.FileHeader.Name)), os.ModeDir|os.ModePerm); err != nil { 155 return err 156 } 157 158 fileWriter, err := os.OpenFile(filepath.Join(destDir, f.FileHeader.Name), os.O_CREATE|os.O_WRONLY, f.FileHeader.Mode()) 159 if err != nil { 160 return err 161 } 162 defer fileWriter.Close() 163 164 _, err = io.Copy(fileWriter, fileReader) 165 if err != nil { 166 return err 167 } 168 169 return nil 170 }() 171 172 if err != nil { 173 return err 174 } 175 } 176 177 return nil 178 }