Skip to content

Commit

Permalink
use component resolvers for completion
Browse files Browse the repository at this point in the history
  • Loading branch information
mandelsoft committed Dec 18, 2024
1 parent 6aea1a0 commit 4a1ab6d
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 20 deletions.
13 changes: 10 additions & 3 deletions api/ocm/internal/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,22 @@ type (
MimeType = blobaccess.MimeType
)

// VersionLookup is the interface used to resolve component versions
// in any context (especially for a ComponentAccess).
type VersionLookup interface {
ListVersions() ([]string, error)
HasVersion(vers string) (bool, error)
LookupVersion(version string) (ComponentVersionAccess, error)
}

type ComponentAccess interface {
resource.ResourceView[ComponentAccess]

GetContext() Context
GetName() string

ListVersions() ([]string, error)
LookupVersion(version string) (ComponentVersionAccess, error)
HasVersion(vers string) (bool, error)
VersionLookup

NewVersion(version string, overrides ...bool) (ComponentVersionAccess, error)
AddVersion(cv ComponentVersionAccess, overrides ...bool) error
AddVersionOpt(cv ComponentVersionAccess, opts ...AddVersionOption) error
Expand Down
64 changes: 64 additions & 0 deletions api/ocm/resolvers/forward.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package resolvers

import (
"github.com/mandelsoft/goutils/errors"
"golang.org/x/exp/maps"

"ocm.software/ocm/api/ocm/internal"
common "ocm.software/ocm/api/utils/misc"
)

type (
ContextProvider = internal.ContextProvider
RepositorySpec = internal.RepositorySpec
VersionLookup = internal.VersionLookup
ComponentVersionAccess = internal.ComponentVersionAccess
ComponentVersionResolver = internal.ComponentVersionResolver
ComponentResolver = internal.ComponentResolver
Expand All @@ -25,3 +30,62 @@ const (
func NewResolverRule(prefix string, spec RepositorySpec, prio ...int) ResolverRule {
return internal.NewResolverRule(prefix, spec, prio...)
}

// VersionResolverForComponent provides a VersionLookup for a component resolver.
// It resolves all versions provided by a component known to a ComponentResolver.
// The version set may be composed by versions of the component found in
// multiple repositories according to the result of the ComponentResolver.
func VersionResolverForComponent(name string, resolver ComponentResolver) (VersionLookup, error) {
crs := resolver.LookupComponentProviders(name)
if len(crs) == 0 {
return nil, errors.ErrNotFound(KIND_COMPONENT, name)
}

versions := map[string]ResolvedComponentProvider{}
for _, cr := range crs {
c, err := cr.LookupComponent(name)
if err != nil {
return nil, err
}
vers, err := c.ListVersions()
if err != nil {
return nil, err
}
for _, v := range vers {
if _, ok := versions[v]; !ok {
versions[v] = cr
}
}
}
return &versionResolver{name, versions}, nil
}

type versionResolver struct {
comp string
versions map[string]ResolvedComponentProvider
}

func (v *versionResolver) ListVersions() ([]string, error) {
return maps.Keys(v.versions), nil
}

func (v *versionResolver) LookupVersion(version string) (ComponentVersionAccess, error) {
p := v.versions[version]
if p == nil {
return nil, errors.ErrNotFound(KIND_COMPONENTVERSION, common.NewNameVersion(v.comp, version).String())
}
vp, err := p.LookupComponent(v.comp)
if err != nil {
return nil, err
}
return vp.LookupVersion(version)
}

func (v *versionResolver) HasVersion(vers string) (bool, error) {
cv, err := v.LookupVersion(vers)
if err != nil {
return false, err
}
defer cv.Close()
return cv != nil, nil
}
34 changes: 19 additions & 15 deletions api/ocm/resolvers/resolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,25 +42,29 @@ var _ = Describe("resolver", func() {
env.Cleanup()
})

It("lookup cv per standard resolver", func() {
// ocmlog.Context().AddRule(logging.NewConditionRule(logging.TraceLevel, accessio.ALLOC_REALM))
Context("resolver", func() {
var ctx ocm.Context

ctx := ocm.New()
BeforeEach(func() {
ctx = ocm.New()
spec := Must(ctf.NewRepositorySpec(accessobj.ACC_READONLY, ARCH, env))
ctx.AddResolverRule("ocm.software", spec, 10)
})

spec := Must(ctf.NewRepositorySpec(accessobj.ACC_READONLY, ARCH, env))
ctx.AddResolverRule("ocm.software", spec, 10)
It("lookup cv per standard resolver", func() {
cv := Must(ctx.GetResolver().LookupComponentVersion(COMPONENT, VERSION))
Close(cv)
Expect(ctx.Finalize()).To(Succeed())
})

cv := Must(ctx.GetResolver().LookupComponentVersion(COMPONENT, VERSION))
It("lookup cv per version resolver", func() {
vr := Must(resolvers.VersionResolverForComponent(COMPONENT, ctx.GetResolver().(resolvers.ComponentResolver)))
Expect(vr.ListVersions()).To(ContainElements(VERSION))

/*
err := cv.Repository().Close()
if err != nil {
defer cv.Close()
Expect(err).To(Succeed())
}
*/
Close(cv)
Expect(ctx.Finalize()).To(Succeed())
cv := Must(vr.LookupVersion(VERSION))
Close(cv)
Expect(ctx.Finalize()).To(Succeed())
})
})

It("orders resolver rules", func() {
Expand Down
18 changes: 16 additions & 2 deletions cmds/ocm/commands/ocmcmds/common/handlers/comphdlr/typehandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"ocm.software/ocm/api/ocm"
"ocm.software/ocm/api/ocm/compdesc"
metav1 "ocm.software/ocm/api/ocm/compdesc/meta/v1"
"ocm.software/ocm/api/ocm/resolvers"
common "ocm.software/ocm/api/utils/misc"
"ocm.software/ocm/api/utils/semverutils"
"ocm.software/ocm/cmds/ocm/common/output"
Expand Down Expand Up @@ -148,7 +149,7 @@ func (h *TypeHandler) filterVersions(vers []string) ([]string, error) {
}

func (h *TypeHandler) get(repo ocm.Repository, elemspec utils.ElemSpec) ([]output.Object, error) {
var component ocm.ComponentAccess
var component resolvers.VersionLookup
var result []output.Object
var err error

Expand Down Expand Up @@ -176,11 +177,25 @@ func (h *TypeHandler) get(repo ocm.Repository, elemspec utils.ElemSpec) ([]outpu
evaluated.Repository = cv.Repository()
h.session.Closer(cv)
}
} else {
// if the resolver is a component resolver, we can use it to list all available version
// cross all repositories found for the given component.
if cr, ok := h.resolver.(resolvers.ComponentResolver); ok {
cvr, err := resolvers.VersionResolverForComponent(comp.Component, cr)
if err != nil {
return nil, err
}
component = cvr
evaluated = &ocm.EvaluationResult{}
evaluated.Ref.CompSpec = comp
}
}
}
if evaluated == nil {
return nil, errors.Wrapf(err, "%s: invalid component version reference", name)
}
} else {
component = evaluated.Component
}
if evaluated.Version != nil {
result = append(result, &Object{
Expand All @@ -192,7 +207,6 @@ func (h *TypeHandler) get(repo ocm.Repository, elemspec utils.ElemSpec) ([]outpu
return result, nil
}
spec = evaluated.Ref
component = evaluated.Component
repo = evaluated.Repository
} else {
comp := ocm.CompSpec{Component: ""}
Expand Down

0 comments on commit 4a1ab6d

Please sign in to comment.