MCPcopy
hub / github.com/opentofu/opentofu / getWithGoGetter

Method getWithGoGetter

internal/getmodules/getter.go:159–218  ·  view source on GitHub ↗

getWithGoGetter fetches the package at the given address into the given target directory. The given address must already be in normalized form (using NormalizePackageAddress) or else the behavior is undefined. This function deals only in entire packages, so it's always the caller's responsibility t

(ctx context.Context, instPath, packageAddr string)

Source from the content-addressed store, hash-verified

157// reasonable way to improve these error messages at this layer because
158// the underlying errors are not separately recognizable.
159func (g *reusingGetter) getWithGoGetter(ctx context.Context, instPath, packageAddr string) error {
160 var err error
161
162 // For now we hold the "previousInstalls" mutex throughout our entire work here
163 // since we don't currently try to use a single getter concurrently anyway.
164 // If we _do_ want to enable more concurrency in future then we'll need a
165 // more interesting strategy to make sure that only concurrent attempts to
166 // install the _same_ package get serialized, but we'll wait until we have
167 // that need before we introduce that complexity.
168 //
169 // NOTE WELL: [getter.Client.Get] modifies internal state inside each of the
170 // getters passed in [getter.Client.Getters] before calling into them, so
171 // it is _not_ safe to reuse the same getter instances across multiple
172 // concurrent calls. If we want to make this work concurrently in future
173 // then we'll need to instead instantiate the getters on demand for each
174 // request.
175 g.previousInstallsMu.Lock()
176 defer g.previousInstallsMu.Unlock()
177 if g.previousInstalls == nil {
178 g.previousInstalls = make(map[string]string)
179 }
180
181 if prevDir, exists := g.previousInstalls[packageAddr]; exists {
182 log.Printf("[TRACE] getmodules: copying previous install of %q from %s to %s", packageAddr, prevDir, instPath)
183 err := os.Mkdir(instPath, os.ModePerm)
184 if err != nil {
185 return fmt.Errorf("failed to create directory %s: %w", instPath, err)
186 }
187 err = copy.CopyDir(instPath, prevDir)
188 if err != nil {
189 return fmt.Errorf("failed to copy from %s to %s: %w", prevDir, instPath, err)
190 }
191 } else {
192 log.Printf("[TRACE] getmodules: fetching %q to %q", packageAddr, instPath)
193 client := getter.Client{
194 Src: packageAddr,
195 Dst: instPath,
196 Pwd: instPath,
197
198 Mode: getter.ClientModeDir,
199
200 Detectors: goGetterNoDetectors, // our caller should've already done detection
201 Decompressors: goGetterDecompressors,
202 Getters: g.getters,
203 Ctx: ctx,
204 }
205 err = client.Get()
206 if err != nil {
207 return err
208 }
209 // Remember where we installed this so we might reuse this directory
210 // on subsequent calls to avoid re-downloading.
211 g.previousInstalls[packageAddr] = instPath
212 }
213
214 // If we get down here then we've either downloaded the package or
215 // copied a previous tree we downloaded, and so either way we should
216 // have got the full module package structure written into instPath.

Callers 1

FetchPackageMethod · 0.80

Calls 6

GetMethod · 0.95
CopyDirFunction · 0.92
PrintfMethod · 0.80
MkdirMethod · 0.80
LockMethod · 0.65
UnlockMethod · 0.65

Tested by

no test coverage detected