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 }