github.com/juju/charm/v11@v11.2.0/bundlearchive.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the LGPLv3, see LICENCE file for details. 3 4 package charm 5 6 import ( 7 "bytes" 8 "io" 9 "io/ioutil" 10 11 ziputil "github.com/juju/utils/v3/zip" 12 ) 13 14 type BundleArchive struct { 15 zopen zipOpener 16 17 Path string 18 data *BundleData 19 readMe string 20 21 containsOverlays bool 22 } 23 24 // ReadBundleArchive reads a bundle archive from the given file path. 25 func ReadBundleArchive(path string) (*BundleArchive, error) { 26 a, err := readBundleArchive(newZipOpenerFromPath(path)) 27 if err != nil { 28 return nil, err 29 } 30 a.Path = path 31 return a, nil 32 } 33 34 // ReadBundleArchiveBytes reads a bundle archive from the given byte 35 // slice. 36 func ReadBundleArchiveBytes(data []byte) (*BundleArchive, error) { 37 zopener := newZipOpenerFromReader(bytes.NewReader(data), int64(len(data))) 38 return readBundleArchive(zopener) 39 } 40 41 // ReadBundleArchiveFromReader returns a BundleArchive that uses 42 // r to read the bundle. The given size must hold the number 43 // of available bytes in the file. 44 // 45 // Note that the caller is responsible for closing r - methods on 46 // the returned BundleArchive may fail after that. 47 func ReadBundleArchiveFromReader(r io.ReaderAt, size int64) (*BundleArchive, error) { 48 return readBundleArchive(newZipOpenerFromReader(r, size)) 49 } 50 51 func readBundleArchive(zopen zipOpener) (*BundleArchive, error) { 52 a := &BundleArchive{ 53 zopen: zopen, 54 } 55 zipr, err := zopen.openZip() 56 if err != nil { 57 return nil, err 58 } 59 defer zipr.Close() 60 reader, err := zipOpenFile(zipr, "bundle.yaml") 61 if err != nil { 62 return nil, err 63 } 64 a.data, a.containsOverlays, err = readBaseFromMultidocBundle(reader) 65 reader.Close() 66 if err != nil { 67 return nil, err 68 } 69 reader, err = zipOpenFile(zipr, "README.md") 70 if err != nil { 71 return nil, err 72 } 73 readMe, err := ioutil.ReadAll(reader) 74 if err != nil { 75 return nil, err 76 } 77 a.readMe = string(readMe) 78 return a, nil 79 } 80 81 // Data implements Bundle.Data. 82 func (a *BundleArchive) Data() *BundleData { 83 return a.data 84 } 85 86 // ReadMe implements Bundle.ReadMe. 87 func (a *BundleArchive) ReadMe() string { 88 return a.readMe 89 } 90 91 // ContainsOverlays implements Bundle.ReadMe. 92 func (a *BundleArchive) ContainsOverlays() bool { 93 return a.containsOverlays 94 } 95 96 // ExpandTo expands the bundle archive into dir, creating it if necessary. 97 // If any errors occur during the expansion procedure, the process will 98 // abort. 99 func (a *BundleArchive) ExpandTo(dir string) error { 100 zipr, err := a.zopen.openZip() 101 if err != nil { 102 return err 103 } 104 defer zipr.Close() 105 return ziputil.ExtractAll(zipr.Reader, dir) 106 }