Skip to content

Commit

Permalink
Merge pull request #491 from zong-zhe/split-client-resolver
Browse files Browse the repository at this point in the history
refactor: split resolver from client
  • Loading branch information
Peefy authored Sep 26, 2024
2 parents b4d396a + f31c717 commit af04497
Show file tree
Hide file tree
Showing 12 changed files with 124 additions and 100 deletions.
2 changes: 0 additions & 2 deletions pkg/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ type KpmClient struct {
logWriter io.Writer
// The downloader of the dependencies.
DepDownloader *downloader.DepDownloader
// The dependency resolver.
DepsResolver *DepsResolver
// credential store
credsClient *downloader.CredClient
// The home path of kpm for global configuration file and kcl package storage path.
Expand Down
58 changes: 0 additions & 58 deletions pkg/client/resolver_test.go

This file was deleted.

17 changes: 12 additions & 5 deletions pkg/client/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"kcl-lang.io/kpm/pkg/downloader"
pkg "kcl-lang.io/kpm/pkg/package"
"kcl-lang.io/kpm/pkg/resolver"
)

// UpdateOptions is the option for updating a package.
Expand Down Expand Up @@ -48,7 +49,13 @@ func (c *KpmClient) Update(options ...UpdateOption) (*pkg.KclPkg, error) {
}

// Create a new dependency resolver
resolver := NewDepsResolver(c)
depResolver := resolver.DepsResolver{
DefaultCachePath: c.homePath,
InsecureSkipTLSverify: c.insecureSkipTLSverify,
Downloader: c.DepDownloader,
Settings: &c.settings,
LogWriter: c.logWriter,
}
// ResolveFunc is the function for resolving each dependency when traversing the dependency graph.
resolverFunc := func(dep *pkg.Dependency, parentPkg *pkg.KclPkg) error {
// Check if the dependency exists in the mod file.
Expand Down Expand Up @@ -77,7 +84,7 @@ func (c *KpmClient) Update(options ...UpdateOption) (*pkg.KclPkg, error) {

return nil
}
resolver.AddResolveFunc(resolverFunc)
depResolver.ResolveFuncs = append(depResolver.ResolveFuncs, resolverFunc)

// Iterate all the dependencies of the package in kcl.mod and resolve each dependency.
for _, depName := range modDeps.Keys() {
Expand All @@ -99,9 +106,9 @@ func (c *KpmClient) Update(options ...UpdateOption) (*pkg.KclPkg, error) {
depSource = &dep.Source
}

err := resolver.Resolve(
WithEnableCache(true),
WithResolveSource(depSource),
err := depResolver.Resolve(
resolver.WithEnableCache(true),
resolver.WithSource(depSource),
)
if err != nil {
return nil, err
Expand Down
4 changes: 2 additions & 2 deletions pkg/mvs/mvs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func TestUpgradeToLatest(t *testing.T) {

upgrade, err := reqs.Upgrade(module.Version{Path: "k8s", Version: "1.27"})
assert.Equal(t, err, nil)
assert.Equal(t, upgrade, module.Version{Path: "k8s", Version: "1.31"})
assert.Equal(t, upgrade, module.Version{Path: "k8s", Version: "1.31.1"})
}

func TestUpgradeAllToLatest(t *testing.T) {
Expand Down Expand Up @@ -147,7 +147,7 @@ func TestUpgradeAllToLatest(t *testing.T) {
{Path: "argo-cd-order", Version: "0.2.0"},
{Path: "helloworld", Version: "0.1.2"},
{Path: "json_merge_patch", Version: "0.1.1"},
{Path: "k8s", Version: "1.31"},
{Path: "k8s", Version: "1.31.1"},
{Path: "podinfo", Version: "0.1.1"},
}
assert.Equal(t, upgrade, expectedReqs)
Expand Down
74 changes: 41 additions & 33 deletions pkg/client/resolver.go → pkg/resolver/resolver.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package client
package resolver

import (
"fmt"
"io"
"path/filepath"

"kcl-lang.io/kpm/pkg/constants"
"kcl-lang.io/kpm/pkg/downloader"
pkg "kcl-lang.io/kpm/pkg/package"
"kcl-lang.io/kpm/pkg/settings"
"kcl-lang.io/kpm/pkg/utils"
"kcl-lang.io/kpm/pkg/visitor"
)

Expand Down Expand Up @@ -41,16 +46,16 @@ func WithCachePath(cachePath string) ResolveOption {
}
}

// WithResolveSource sets the source of the package to be resolved.
func WithResolveSource(source *downloader.Source) ResolveOption {
// WithSource sets the source of the package to be resolved.
func WithSource(source *downloader.Source) ResolveOption {
return func(opts *ResolveOptions) error {
opts.Source = source
return nil
}
}

// WithResolveSourceUrl sets the source of the package to be resolved by the source url.
func WithResolveSourceUrl(sourceUrl string) ResolveOption {
func WithSourceUrl(sourceUrl string) ResolveOption {
return func(opts *ResolveOptions) error {
source, err := downloader.NewSourceFromStr(sourceUrl)
if err != nil {
Expand All @@ -63,25 +68,12 @@ func WithResolveSourceUrl(sourceUrl string) ResolveOption {

// DepsResolver is the resolver for resolving dependencies.
type DepsResolver struct {
kpmClient *KpmClient
resolveFuncs []resolveFunc
}

// NewDepsResolver creates a new DepsResolver.
func NewDepsResolver(kpmClient *KpmClient) *DepsResolver {
return &DepsResolver{
kpmClient: kpmClient,
resolveFuncs: []resolveFunc{},
}
}

// AddResolveFunc adds a resolve function to the DepsResolver.
func (dr *DepsResolver) AddResolveFunc(rf resolveFunc) {
if dr.resolveFuncs == nil {
dr.resolveFuncs = []resolveFunc{}
}

dr.resolveFuncs = append(dr.resolveFuncs, rf)
DefaultCachePath string
InsecureSkipTLSverify bool
Downloader downloader.Downloader
Settings *settings.Settings
LogWriter io.Writer
ResolveFuncs []resolveFunc
}

// Resolve resolves the dependencies of the package.
Expand All @@ -97,25 +89,41 @@ func (dr *DepsResolver) Resolve(options ...ResolveOption) error {
// For remote source, it will use the RemoteVisitor and enable the cache.
// For local source, it will use the PkgVisitor.
visitorSelectorFunc := func(source *downloader.Source) (visitor.Visitor, error) {
pkgVisitor := &visitor.PkgVisitor{
Settings: dr.Settings,
LogWriter: dr.LogWriter,
}

if source.IsRemote() {
var cachePath string
if opts.CachePath != "" {
cachePath = opts.CachePath
} else {
cachePath = dr.kpmClient.homePath
cachePath = dr.DefaultCachePath
}

return &visitor.RemoteVisitor{
PkgVisitor: &visitor.PkgVisitor{
Settings: &dr.kpmClient.settings,
LogWriter: dr.kpmClient.logWriter,
},
Downloader: dr.kpmClient.DepDownloader,
InsecureSkipTLSverify: dr.kpmClient.insecureSkipTLSverify,
PkgVisitor: pkgVisitor,
Downloader: dr.Downloader,
InsecureSkipTLSverify: dr.InsecureSkipTLSverify,
EnableCache: opts.EnableCache,
CachePath: cachePath,
}, nil
} else if source.IsLocalTarPath() || source.IsLocalTgzPath() {
return visitor.NewArchiveVisitor(pkgVisitor), nil
} else if source.IsLocalPath() {
rootPath, err := source.FindRootPath()
if err != nil {
return nil, err
}
kclmodpath := filepath.Join(rootPath, constants.KCL_MOD)
if utils.DirExists(kclmodpath) {
return pkgVisitor, nil
} else {
return visitor.NewVirtualPkgVisitor(pkgVisitor), nil
}
} else {
return NewVisitor(*source, dr.kpmClient), nil
return nil, fmt.Errorf("unsupported source")
}
}

Expand Down Expand Up @@ -151,7 +159,7 @@ func (dr *DepsResolver) Resolve(options ...ResolveOption) error {
// Visit this dependency and current package as the parent package.
err = visitor.Visit(&depSource,
func(childPkg *pkg.KclPkg) error {
for _, resolveFunc := range dr.resolveFuncs {
for _, resolveFunc := range dr.ResolveFuncs {
err := resolveFunc(&dep, kclPkg)
if err != nil {
return err
Expand All @@ -167,7 +175,7 @@ func (dr *DepsResolver) Resolve(options ...ResolveOption) error {

// Recursively resolve the dependencies of the dependency.
err = dr.Resolve(
WithResolveSource(&depSource),
WithSource(&depSource),
WithEnableCache(opts.EnableCache),
WithCachePath(opts.CachePath),
)
Expand Down
69 changes: 69 additions & 0 deletions pkg/resolver/resolver_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package resolver

import (
"bytes"
"fmt"
"os"
"path/filepath"
"sort"
"testing"

"github.com/stretchr/testify/assert"
"kcl-lang.io/kpm/pkg/downloader"
"kcl-lang.io/kpm/pkg/env"
pkg "kcl-lang.io/kpm/pkg/package"
"kcl-lang.io/kpm/pkg/settings"
)

const testDataDir = "test_data"

func getTestDir(subDir string) string {
pwd, _ := os.Getwd()
testDir := filepath.Join(pwd, testDataDir)
testDir = filepath.Join(testDir, subDir)

return testDir
}

func TestResolver(t *testing.T) {
resolve_path := getTestDir("test_resolve_graph")
pkgPath := filepath.Join(resolve_path, "pkg")
defaultCachePath, err := env.GetAbsPkgPath()
if err != nil {
t.Fatal(err)
}

var res []string
var buf bytes.Buffer

resolver := DepsResolver{
Downloader: &downloader.DepDownloader{},
Settings: settings.GetSettings(),
LogWriter: &buf,
DefaultCachePath: defaultCachePath,
ResolveFuncs: []resolveFunc{func(dep *pkg.Dependency, parentPkg *pkg.KclPkg) error {
res = append(res, fmt.Sprintf("%s -> %s", parentPkg.GetPkgName(), dep.Name))
return nil
}},
}

err = resolver.Resolve(
WithEnableCache(true),
WithSourceUrl(pkgPath),
)

if err != nil {
t.Fatal(err)
}

expected := []string{
"dep1 -> helloworld",
"pkg -> dep1",
"pkg -> helloworld",
}

sort.Strings(res)
assert.Equal(t, len(res), 3)
assert.Equal(t, res, expected)
assert.Equal(t, buf.String(), "")
}

0 comments on commit af04497

Please sign in to comment.