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  }