Files
steampipe/pkg/modinstaller/install_data.go

121 lines
4.8 KiB
Go

package modinstaller
import (
"fmt"
"github.com/Masterminds/semver/v3"
"github.com/turbot/steampipe/pkg/steampipeconfig/modconfig"
"github.com/turbot/steampipe/pkg/steampipeconfig/versionmap"
"github.com/turbot/steampipe/pkg/versionhelpers"
"github.com/xlab/treeprint"
)
type InstallData struct {
// record of the full dependency tree
Lock *versionmap.WorkspaceLock
NewLock *versionmap.WorkspaceLock
// ALL the available versions for each dependency mod(we populate this in a lazy fashion)
allAvailable versionmap.VersionListMap
// list of dependencies installed by recent install operation
Installed versionmap.DependencyVersionMap
// list of dependencies which have been upgraded
Upgraded versionmap.DependencyVersionMap
// list of dependencies which have been downgraded
Downgraded versionmap.DependencyVersionMap
// list of dependencies which have been uninstalled
Uninstalled versionmap.DependencyVersionMap
WorkspaceMod *modconfig.Mod
}
func NewInstallData(workspaceLock *versionmap.WorkspaceLock, workspaceMod *modconfig.Mod) *InstallData {
return &InstallData{
Lock: workspaceLock,
WorkspaceMod: workspaceMod,
NewLock: versionmap.EmptyWorkspaceLock(workspaceLock),
allAvailable: make(versionmap.VersionListMap),
Installed: make(versionmap.DependencyVersionMap),
Upgraded: make(versionmap.DependencyVersionMap),
Downgraded: make(versionmap.DependencyVersionMap),
Uninstalled: make(versionmap.DependencyVersionMap),
}
}
// GetAvailableUpdates returns a map of all installed mods which are not in the lock file
func (d *InstallData) GetAvailableUpdates() (versionmap.DependencyVersionMap, error) {
res := make(versionmap.DependencyVersionMap)
for parent, deps := range d.Lock.InstallCache {
for name, resolvedConstraint := range deps {
includePrerelease := resolvedConstraint.IsPrerelease()
availableVersions, err := d.getAvailableModVersions(name, includePrerelease)
if err != nil {
return nil, err
}
constraint, _ := versionhelpers.NewConstraint(resolvedConstraint.Constraint)
var latestVersion = getVersionSatisfyingConstraint(constraint, availableVersions)
if latestVersion.GreaterThan(resolvedConstraint.Version) {
res.Add(name, resolvedConstraint.Alias, latestVersion, constraint.Original, parent)
}
}
}
return res, nil
}
// onModInstalled is called when a dependency is satisfied by installing a mod version
func (d *InstallData) onModInstalled(dependency *ResolvedModRef, modDef *modconfig.Mod, parent *modconfig.Mod) {
parentPath := parent.GetInstallCacheKey()
// get the constraint from the parent (it must be there)
modVersionConstraint := parent.Require.GetModDependency(dependency.Name).Constraint.Original
// update lock
d.NewLock.InstallCache.Add(dependency.Name, modDef.ShortName, modDef.Version, modVersionConstraint, parentPath)
}
// addExisting is called when a dependency is satisfied by a mod which is already installed
func (d *InstallData) addExisting(dependencyName string, existingDep *modconfig.Mod, constraint *versionhelpers.Constraints, parent *modconfig.Mod) {
// update lock
parentPath := parent.GetInstallCacheKey()
d.NewLock.InstallCache.Add(dependencyName, existingDep.ShortName, existingDep.Version, constraint.Original, parentPath)
}
// retrieve all available mod versions from our cache, or from Git if not yet cached
func (d *InstallData) getAvailableModVersions(modName string, includePrerelease bool) ([]*semver.Version, error) {
// have we already loaded the versions for this mod
availableVersions, ok := d.allAvailable[modName]
if ok {
return availableVersions, nil
}
// so we have not cached this yet - retrieve from Git
var err error
availableVersions, err = getTagVersionsFromGit(getGitUrl(modName), includePrerelease)
if err != nil {
return nil, fmt.Errorf("could not retrieve version data from Git URL '%s'", modName)
}
// update our cache
d.allAvailable[modName] = availableVersions
return availableVersions, nil
}
// update the lock with the NewLock and dtermine if any mods have been uninstalled
func (d *InstallData) onInstallComplete() {
d.Installed = d.NewLock.InstallCache.GetMissingFromOther(d.Lock.InstallCache)
d.Uninstalled = d.Lock.InstallCache.GetMissingFromOther(d.NewLock.InstallCache)
d.Upgraded = d.Lock.InstallCache.GetUpgradedInOther(d.NewLock.InstallCache)
d.Downgraded = d.Lock.InstallCache.GetDowngradedInOther(d.NewLock.InstallCache)
d.Lock = d.NewLock
}
func (d *InstallData) GetUpdatedTree() treeprint.Tree {
return d.Upgraded.GetDependencyTree(d.WorkspaceMod.GetInstallCacheKey())
}
func (d *InstallData) GetInstalledTree() treeprint.Tree {
return d.Installed.GetDependencyTree(d.WorkspaceMod.GetInstallCacheKey())
}
func (d *InstallData) GetUninstalledTree() treeprint.Tree {
return d.Uninstalled.GetDependencyTree(d.WorkspaceMod.GetInstallCacheKey())
}