github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/testcharms/repo/repo.go (about)

     1  // Copyright 2023 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package repo
     5  
     6  // File moved from github.com/juju/charmrepo/v7/testing/charm.go
     7  // Attempting to remove use of the charmrepo package from juju
     8  // with the removal of charmstore support.
     9  
    10  import (
    11  	"fmt"
    12  	"os"
    13  	"path/filepath"
    14  	"runtime"
    15  
    16  	"github.com/juju/charm/v12"
    17  	"github.com/juju/utils/v3/fs"
    18  )
    19  
    20  func check(err error) {
    21  	if err != nil {
    22  		panic(err)
    23  	}
    24  }
    25  
    26  // NewRepo returns a new testing charm repository rooted at the given
    27  // path, relative to the package directory of the calling package, using
    28  // defaultSeries as the default series.
    29  func NewRepo(path, defaultSeries string) *CharmRepo {
    30  	// Find the repo directory. This is only OK to do
    31  	// because this is running in a test context
    32  	// so we know the source is available.
    33  	_, file, _, ok := runtime.Caller(1)
    34  	if !ok {
    35  		panic("cannot get caller")
    36  	}
    37  	r := &CharmRepo{
    38  		path:          filepath.Join(filepath.Dir(file), path),
    39  		defaultSeries: defaultSeries,
    40  	}
    41  	_, err := os.Stat(r.path)
    42  	if err != nil {
    43  		panic(fmt.Errorf("cannot read repository found at %q: %v", r.path, err))
    44  	}
    45  	return r
    46  }
    47  
    48  // CharmRepo represents a charm repository used for testing.
    49  type CharmRepo struct {
    50  	path          string
    51  	defaultSeries string
    52  }
    53  
    54  func (r *CharmRepo) Path() string {
    55  	return r.path
    56  }
    57  
    58  func clone(dst, src string) string {
    59  	dst = filepath.Join(dst, filepath.Base(src))
    60  	check(fs.Copy(src, dst))
    61  	return dst
    62  }
    63  
    64  // BundleDirPath returns the path to a bundle directory with the given name in the
    65  // default series
    66  func (r *CharmRepo) BundleDirPath(name string) string {
    67  	return filepath.Join(r.Path(), "bundle", name)
    68  }
    69  
    70  // BundleDir returns the actual charm.BundleDir named name.
    71  func (r *CharmRepo) BundleDir(name string) *charm.BundleDir {
    72  	b, err := charm.ReadBundleDir(r.BundleDirPath(name))
    73  	check(err)
    74  	return b
    75  }
    76  
    77  // CharmDirPath returns the path to a charm directory with the given name in the
    78  // default series
    79  func (r *CharmRepo) CharmDirPath(name string) string {
    80  	return filepath.Join(r.Path(), r.defaultSeries, name)
    81  }
    82  
    83  // CharmDir returns the actual charm.CharmDir named name.
    84  func (r *CharmRepo) CharmDir(name string) *charm.CharmDir {
    85  	ch, err := charm.ReadCharmDir(r.CharmDirPath(name))
    86  	check(err)
    87  	return ch
    88  }
    89  
    90  // ClonedDirPath returns the path to a new copy of the default charm directory
    91  // named name.
    92  func (r *CharmRepo) ClonedDirPath(dst, name string) string {
    93  	return clone(dst, r.CharmDirPath(name))
    94  }
    95  
    96  // ClonedDirPath returns the path to a new copy of the default bundle directory
    97  // named name.
    98  func (r *CharmRepo) ClonedBundleDirPath(dst, name string) string {
    99  	return clone(dst, r.BundleDirPath(name))
   100  }
   101  
   102  // RenamedClonedDirPath returns the path to a new copy of the default
   103  // charm directory named name, renamed to newName.
   104  func (r *CharmRepo) RenamedClonedDirPath(dst, name, newName string) string {
   105  	dstPath := filepath.Join(dst, newName)
   106  	err := fs.Copy(r.CharmDirPath(name), dstPath)
   107  	check(err)
   108  	return dstPath
   109  }
   110  
   111  // ClonedDir returns an actual charm.CharmDir based on a new copy of the charm directory
   112  // named name, in the directory dst.
   113  func (r *CharmRepo) ClonedDir(dst, name string) *charm.CharmDir {
   114  	ch, err := charm.ReadCharmDir(r.ClonedDirPath(dst, name))
   115  	check(err)
   116  	return ch
   117  }
   118  
   119  // ClonedURL makes a copy of the charm directory. It will create a directory
   120  // with the series name if it does not exist, and then clone the charm named
   121  // name into that directory. The return value is a URL pointing at the local
   122  // charm.
   123  func (r *CharmRepo) ClonedURL(dst, series, name string) *charm.URL {
   124  	dst = filepath.Join(dst, series)
   125  	if err := os.MkdirAll(dst, os.FileMode(0777)); err != nil {
   126  		panic(fmt.Errorf("cannot make destination directory: %v", err))
   127  	}
   128  	clone(dst, r.CharmDirPath(name))
   129  	return &charm.URL{
   130  		Schema:   "local",
   131  		Name:     name,
   132  		Revision: -1,
   133  		Series:   series,
   134  	}
   135  }
   136  
   137  // CharmArchivePath returns the path to a new charm archive file
   138  // in the directory dst, created from the charm directory named name.
   139  func (r *CharmRepo) CharmArchivePath(dst, name string) string {
   140  	dir := r.CharmDir(name)
   141  	path := filepath.Join(dst, "archive.charm")
   142  	file, err := os.Create(path)
   143  	check(err)
   144  	defer func() { _ = file.Close() }()
   145  	check(dir.ArchiveTo(file))
   146  	return path
   147  }
   148  
   149  // BundleArchivePath returns the path to a new bundle archive file
   150  // in the directory dst, created from the bundle directory named name.
   151  func (r *CharmRepo) BundleArchivePath(dst, name string) string {
   152  	dir := r.BundleDir(name)
   153  	path := filepath.Join(dst, "archive.bundle")
   154  	file, err := os.Create(path)
   155  	check(err)
   156  	defer func() { _ = file.Close() }()
   157  	check(dir.ArchiveTo(file))
   158  	return path
   159  }
   160  
   161  // CharmArchive returns an actual charm.CharmArchive created from a new
   162  // charm archive file created from the charm directory named name, in
   163  // the directory dst.
   164  func (r *CharmRepo) CharmArchive(dst, name string) *charm.CharmArchive {
   165  	ch, err := charm.ReadCharmArchive(r.CharmArchivePath(dst, name))
   166  	check(err)
   167  	return ch
   168  }
   169  
   170  // BundleArchive returns an actual charm.BundleArchive created from a new
   171  // bundle archive file created from the bundle directory named name, in
   172  // the directory dst.
   173  func (r *CharmRepo) BundleArchive(dst, name string) *charm.BundleArchive {
   174  	b, err := charm.ReadBundleArchive(r.BundleArchivePath(dst, name))
   175  	check(err)
   176  	return b
   177  }