diff --git a/pkg/client/client.go b/pkg/client/client.go index 5a1efdc0..d71a266e 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -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. diff --git a/pkg/client/resolver_test.go b/pkg/client/resolver_test.go deleted file mode 100644 index fa7773e5..00000000 --- a/pkg/client/resolver_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package client - -import ( - "bytes" - "fmt" - "path/filepath" - "sort" - "testing" - - "github.com/stretchr/testify/assert" - "kcl-lang.io/kpm/pkg/downloader" - pkg "kcl-lang.io/kpm/pkg/package" -) - -func TestResolver(t *testing.T) { - kpmcli, err := NewKpmClient() - if err != nil { - t.Fatal(err) - } - - resolve_path := getTestDir("test_resolve_graph") - pkgPath := filepath.Join(resolve_path, "pkg") - - pkgSource, err := downloader.NewSourceFromStr(pkgPath) - if err != nil { - t.Fatal(err) - } - - var res []string - var buf bytes.Buffer - - kpmcli.SetLogWriter(&buf) - resolver := NewDepsResolver(kpmcli) - resolver.AddResolveFunc(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), - WithResolveSource(pkgSource), - ) - - 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(), "") -} diff --git a/pkg/client/update.go b/pkg/client/update.go index 9414e992..d994561b 100644 --- a/pkg/client/update.go +++ b/pkg/client/update.go @@ -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. @@ -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. @@ -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() { @@ -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 diff --git a/pkg/mvs/mvs_test.go b/pkg/mvs/mvs_test.go index 9707a343..94a1450a 100644 --- a/pkg/mvs/mvs_test.go +++ b/pkg/mvs/mvs_test.go @@ -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) { @@ -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) diff --git a/pkg/client/resolver.go b/pkg/resolver/resolver.go similarity index 75% rename from pkg/client/resolver.go rename to pkg/resolver/resolver.go index 16304f07..c2d2bff8 100644 --- a/pkg/client/resolver.go +++ b/pkg/resolver/resolver.go @@ -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" ) @@ -41,8 +46,8 @@ 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 @@ -50,7 +55,7 @@ func WithResolveSource(source *downloader.Source) ResolveOption { } // 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 { @@ -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. @@ -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") } } @@ -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 @@ -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), ) diff --git a/pkg/resolver/resolver_test.go b/pkg/resolver/resolver_test.go new file mode 100644 index 00000000..43baae69 --- /dev/null +++ b/pkg/resolver/resolver_test.go @@ -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(), "") +} diff --git a/pkg/client/test_data/test_resolve_graph/dep1/kcl.mod b/pkg/resolver/test_data/test_resolve_graph/dep1/kcl.mod similarity index 100% rename from pkg/client/test_data/test_resolve_graph/dep1/kcl.mod rename to pkg/resolver/test_data/test_resolve_graph/dep1/kcl.mod diff --git a/pkg/client/test_data/test_resolve_graph/dep1/kcl.mod.lock b/pkg/resolver/test_data/test_resolve_graph/dep1/kcl.mod.lock similarity index 100% rename from pkg/client/test_data/test_resolve_graph/dep1/kcl.mod.lock rename to pkg/resolver/test_data/test_resolve_graph/dep1/kcl.mod.lock diff --git a/pkg/client/test_data/test_resolve_graph/dep1/main.k b/pkg/resolver/test_data/test_resolve_graph/dep1/main.k similarity index 100% rename from pkg/client/test_data/test_resolve_graph/dep1/main.k rename to pkg/resolver/test_data/test_resolve_graph/dep1/main.k diff --git a/pkg/client/test_data/test_resolve_graph/pkg/kcl.mod b/pkg/resolver/test_data/test_resolve_graph/pkg/kcl.mod similarity index 100% rename from pkg/client/test_data/test_resolve_graph/pkg/kcl.mod rename to pkg/resolver/test_data/test_resolve_graph/pkg/kcl.mod diff --git a/pkg/client/test_data/test_resolve_graph/pkg/kcl.mod.lock b/pkg/resolver/test_data/test_resolve_graph/pkg/kcl.mod.lock similarity index 100% rename from pkg/client/test_data/test_resolve_graph/pkg/kcl.mod.lock rename to pkg/resolver/test_data/test_resolve_graph/pkg/kcl.mod.lock diff --git a/pkg/client/test_data/test_resolve_graph/pkg/main.k b/pkg/resolver/test_data/test_resolve_graph/pkg/main.k similarity index 100% rename from pkg/client/test_data/test_resolve_graph/pkg/main.k rename to pkg/resolver/test_data/test_resolve_graph/pkg/main.k