@@ -21,6 +21,7 @@ import (
2121 configMediator "github.com/ActiveState/cli/internal/mediators/config"
2222 "github.com/ActiveState/cli/internal/sliceutils"
2323 "github.com/ActiveState/cli/internal/smartlink"
24+ "github.com/ActiveState/cli/pkg/buildplan"
2425)
2526
2627const (
@@ -52,6 +53,11 @@ type artifactInfo struct {
5253 Size int64 `json:"size"`
5354 LastAccessTime int64 `json:"lastAccessTime"`
5455
56+ // These fields are used by ecosystems during Add/Remove/Apply.
57+ Namespace string `json:"namespace,omitempty"`
58+ Name string `json:"name,omitempty"`
59+ Version string `json:"version,omitempty"`
60+
5561 id strfmt.UUID // for convenience when removing stale artifacts; should NOT have json tag
5662}
5763
@@ -148,9 +154,19 @@ func (d *depot) SetCacheSize(mb int) {
148154 d .cacheSize = int64 (mb ) * MB
149155}
150156
151- func (d * depot ) Exists (id strfmt.UUID ) bool {
152- _ , ok := d .artifacts [id ]
153- return ok
157+ // Exists returns whether or not an artifact ID exists in the depot, along with any known metadata
158+ // associated with that artifact ID.
159+ // Existence is merely whether a directory with the name of the given ID exists on the filesystem.
160+ // Artifact metadata comes from the depot's cache, and may not exist for installed artifacts that
161+ // predate the cache.
162+ func (d * depot ) Exists (id strfmt.UUID ) (bool , * artifactInfo ) {
163+ if _ , ok := d .artifacts [id ]; ok {
164+ if artifact , exists := d .config .Cache [id ]; exists {
165+ return true , artifact
166+ }
167+ return true , nil
168+ }
169+ return false , nil
154170}
155171
156172func (d * depot ) Path (id strfmt.UUID ) string {
@@ -174,84 +190,80 @@ func (d *depot) Put(id strfmt.UUID) error {
174190}
175191
176192// DeployViaLink will take an artifact from the depot and link it to the target path.
177- func (d * depot ) DeployViaLink (id strfmt.UUID , relativeSrc , absoluteDest string ) error {
193+ // It should return deployment info to be used for tracking the artifact.
194+ func (d * depot ) DeployViaLink (id strfmt.UUID , relativeSrc , absoluteDest string ) (* deployment , error ) {
178195 d .fsMutex .Lock ()
179196 defer d .fsMutex .Unlock ()
180197
181- if ! d .Exists (id ) {
182- return errs .New ("artifact not found in depot" )
198+ if exists , _ := d .Exists (id ); ! exists {
199+ return nil , errs .New ("artifact not found in depot" )
183200 }
184201
185202 if err := d .validateVolume (absoluteDest ); err != nil {
186- return errs .Wrap (err , "volume validation failed" )
203+ return nil , errs .Wrap (err , "volume validation failed" )
187204 }
188205
189206 // Collect artifact meta info
190207 var err error
191208 absoluteDest , err = fileutils .ResolvePath (absoluteDest )
192209 if err != nil {
193- return errs .Wrap (err , "failed to resolve path" )
210+ return nil , errs .Wrap (err , "failed to resolve path" )
194211 }
195212
196213 if err := fileutils .MkdirUnlessExists (absoluteDest ); err != nil {
197- return errs .Wrap (err , "failed to create path" )
214+ return nil , errs .Wrap (err , "failed to create path" )
198215 }
199216
200217 absoluteSrc := filepath .Join (d .Path (id ), relativeSrc )
201218 if ! fileutils .DirExists (absoluteSrc ) {
202- return errs .New ("artifact src does not exist: %s" , absoluteSrc )
219+ return nil , errs .New ("artifact src does not exist: %s" , absoluteSrc )
203220 }
204221
205222 // Copy or link the artifact files, depending on whether the artifact in question relies on file transformations
206223 if err := smartlink .LinkContents (absoluteSrc , absoluteDest ); err != nil {
207- return errs .Wrap (err , "failed to link artifact" )
224+ return nil , errs .Wrap (err , "failed to link artifact" )
208225 }
209226
210227 files , err := fileutils .ListDir (absoluteSrc , false )
211228 if err != nil {
212- return errs .Wrap (err , "failed to list files" )
229+ return nil , errs .Wrap (err , "failed to list files" )
213230 }
214231
215- // Record deployment to config
216- err = d .Track (id , & deployment {
232+ return & deployment {
217233 Type : deploymentTypeLink ,
218234 Path : absoluteDest ,
219235 Files : files .RelativePaths (),
220236 RelativeSrc : relativeSrc ,
221- })
222- if err != nil {
223- return errs .Wrap (err , "Could not record artifact use" )
224- }
225-
226- return nil
237+ }, nil
227238}
228239
229240// DeployViaCopy will take an artifact from the depot and copy it to the target path.
230- func (d * depot ) DeployViaCopy (id strfmt.UUID , relativeSrc , absoluteDest string ) error {
241+ // It should return deployment info to be used for tracking the artifact.
242+ func (d * depot ) DeployViaCopy (id strfmt.UUID , relativeSrc , absoluteDest string ) (* deployment , error ) {
231243 d .fsMutex .Lock ()
232244 defer d .fsMutex .Unlock ()
233245
234- if ! d .Exists (id ) {
235- return errs .New ("artifact not found in depot" )
246+ if exists , _ := d .Exists (id ); ! exists {
247+ return nil , errs .New ("artifact not found in depot" )
236248 }
237249
238250 var err error
239251 absoluteDest , err = fileutils .ResolvePath (absoluteDest )
240252 if err != nil {
241- return errs .Wrap (err , "failed to resolve path" )
253+ return nil , errs .Wrap (err , "failed to resolve path" )
242254 }
243255
244256 if err := d .validateVolume (absoluteDest ); err != nil {
245- return errs .Wrap (err , "volume validation failed" )
257+ return nil , errs .Wrap (err , "volume validation failed" )
246258 }
247259
248260 if err := fileutils .MkdirUnlessExists (absoluteDest ); err != nil {
249- return errs .Wrap (err , "failed to create path" )
261+ return nil , errs .Wrap (err , "failed to create path" )
250262 }
251263
252264 absoluteSrc := filepath .Join (d .Path (id ), relativeSrc )
253265 if ! fileutils .DirExists (absoluteSrc ) {
254- return errs .New ("artifact src does not exist: %s" , absoluteSrc )
266+ return nil , errs .New ("artifact src does not exist: %s" , absoluteSrc )
255267 }
256268
257269 // Copy or link the artifact files, depending on whether the artifact in question relies on file transformations
@@ -260,36 +272,30 @@ func (d *depot) DeployViaCopy(id strfmt.UUID, relativeSrc, absoluteDest string)
260272 if errors .As (err , & errExist ) {
261273 logging .Warning ("Skipping files that already exist: " + errs .JoinMessage (errExist ))
262274 } else {
263- return errs .Wrap (err , "failed to copy artifact" )
275+ return nil , errs .Wrap (err , "failed to copy artifact" )
264276 }
265277 }
266278
267279 files , err := fileutils .ListDir (absoluteSrc , false )
268280 if err != nil {
269- return errs .Wrap (err , "failed to list files" )
281+ return nil , errs .Wrap (err , "failed to list files" )
270282 }
271283
272- // Record deployment to config
273- err = d .Track (id , & deployment {
284+ return & deployment {
274285 Type : deploymentTypeCopy ,
275286 Path : absoluteDest ,
276287 Files : files .RelativePaths (),
277288 RelativeSrc : relativeSrc ,
278- })
279- if err != nil {
280- return errs .Wrap (err , "Could not record artifact use" )
281- }
282-
283- return nil
289+ }, nil
284290}
285291
286292// Track will record an artifact deployment.
287- // This is automatically called by `DeployVia*()` functions.
288- // This should be called for ecosystems that handle installation of artifacts.
289- func (d * depot ) Track (id strfmt.UUID , deploy * deployment ) error {
293+ func (d * depot ) Track (artifact * buildplan.Artifact , deploy * deployment ) error {
290294 d .mapMutex .Lock ()
291295 defer d .mapMutex .Unlock ()
292296
297+ id := artifact .ArtifactID
298+
293299 // Record deployment of this artifact.
294300 if _ , ok := d .config .Deployments [id ]; ! ok {
295301 d .config .Deployments [id ] = []deployment {}
@@ -308,6 +314,21 @@ func (d *depot) Track(id strfmt.UUID, deploy *deployment) error {
308314 }
309315 d .config .Cache [id ].InUse = true
310316 d .config .Cache [id ].LastAccessTime = time .Now ().Unix ()
317+
318+ // For dynamically imported artifacts, also include artifact metadata.
319+ if artifact != nil {
320+ d .config .Cache [id ].Namespace = artifact .Ingredients [0 ].Namespace
321+ d .config .Cache [id ].Name = artifact .Name ()
322+ d .config .Cache [id ].Version = artifact .Version ()
323+ }
324+
325+ return nil
326+ }
327+
328+ func (d * depot ) Deployments (id strfmt.UUID ) []deployment {
329+ if deployments , ok := d .config .Deployments [id ]; ok {
330+ return deployments
331+ }
311332 return nil
312333}
313334
@@ -317,16 +338,16 @@ func (d *depot) Track(id strfmt.UUID, deploy *deployment) error {
317338// This is automatically called by the `Undeploy()` function.
318339// This should be called for ecosystems that handle uninstallation of artifacts.
319340func (d * depot ) Untrack (id strfmt.UUID , path string ) {
320- if _ , ok := d .config .Deployments [id ]; ok {
321- d .config .Deployments [id ] = sliceutils .Filter (d . config . Deployments [ id ] , func (d deployment ) bool { return d .Path != path })
341+ if deployments , ok := d .config .Deployments [id ]; ok {
342+ d .config .Deployments [id ] = sliceutils .Filter (deployments , func (d deployment ) bool { return d .Path != path })
322343 }
323344}
324345
325346func (d * depot ) Undeploy (id strfmt.UUID , relativeSrc , path string ) error {
326347 d .fsMutex .Lock ()
327348 defer d .fsMutex .Unlock ()
328349
329- if ! d .Exists (id ) {
350+ if exists , _ := d .Exists (id ); ! exists {
330351 return errs .New ("artifact not found in depot" )
331352 }
332353
@@ -341,7 +362,10 @@ func (d *depot) Undeploy(id strfmt.UUID, relativeSrc, path string) error {
341362 if ! ok {
342363 return errs .New ("deployment for %s not found in depot" , id )
343364 }
344- deployments = sliceutils .Filter (deployments , func (d deployment ) bool { return d .Path == path })
365+ deployments = sliceutils .Filter (deployments , func (d deployment ) bool {
366+ equal , _ := fileutils .PathsEqual (d .Path , path )
367+ return equal
368+ })
345369 if len (deployments ) != 1 {
346370 return errs .New ("no deployment found for %s in depot" , path )
347371 }
@@ -445,10 +469,12 @@ func (d *depot) Save() error {
445469 for id := range d .artifacts {
446470 if deployments , ok := d .config .Deployments [id ]; ! ok || len (deployments ) == 0 {
447471 if _ , exists := d .config .Cache [id ]; ! exists {
448- err := d .Track (id , nil ) // create cache entry for previously used artifact
472+ // Create cache entry for previously used artifact.
473+ size , err := fileutils .GetDirSize (d .Path (id ))
449474 if err != nil {
450- return errs .Wrap (err , "Could not update depot cache with previously used artifact " )
475+ return errs .Wrap (err , "Could not get artifact size on disk " )
451476 }
477+ d .config .Cache [id ] = & artifactInfo {Size : size , id : id }
452478 }
453479 d .config .Cache [id ].InUse = false
454480 logging .Debug ("Artifact '%s' is no longer in use" , id .String ())
0 commit comments