From d7127c21b112baf186a1ec8760e7163889ad8440 Mon Sep 17 00:00:00 2001 From: zongz Date: Fri, 29 Nov 2024 16:06:17 +0800 Subject: [PATCH 1/3] feat: add API for checker and support mod checking in update Signed-off-by: zongz --- pkg/checker/checker.go | 69 ++++++---- pkg/checker/checker_test.go | 78 +++-------- pkg/client/check.go | 57 +++++++++ pkg/client/check_test.go | 121 ++++++++++++++++++ pkg/client/client.go | 10 +- pkg/client/client_test.go | 4 +- .../test_mod_check/name_failed/kcl.mod | 7 + .../test_mod_check/name_failed/kcl.mod.lock | 9 ++ .../test_mod_check/name_failed/main.k | 1 + .../test_data/test_mod_check/pass/kcl.mod | 7 + .../test_mod_check/pass/kcl.mod.lock | 9 ++ .../test_data/test_mod_check/pass/main.k | 1 + .../test_data/test_mod_check/sum/kcl.mod | 7 + .../test_data/test_mod_check/sum/kcl.mod.lock | 9 ++ .../test_data/test_mod_check/sum/main.k | 1 + .../test_mod_check/version_failed/kcl.mod | 7 + .../version_failed/kcl.mod.lock | 9 ++ .../test_mod_check/version_failed/main.k | 1 + pkg/client/update.go | 19 +++ pkg/features/features.go | 6 +- 20 files changed, 335 insertions(+), 97 deletions(-) create mode 100644 pkg/client/check.go create mode 100644 pkg/client/check_test.go create mode 100644 pkg/client/test_data/test_mod_check/name_failed/kcl.mod create mode 100644 pkg/client/test_data/test_mod_check/name_failed/kcl.mod.lock create mode 100644 pkg/client/test_data/test_mod_check/name_failed/main.k create mode 100644 pkg/client/test_data/test_mod_check/pass/kcl.mod create mode 100644 pkg/client/test_data/test_mod_check/pass/kcl.mod.lock create mode 100644 pkg/client/test_data/test_mod_check/pass/main.k create mode 100644 pkg/client/test_data/test_mod_check/sum/kcl.mod create mode 100644 pkg/client/test_data/test_mod_check/sum/kcl.mod.lock create mode 100644 pkg/client/test_data/test_mod_check/sum/main.k create mode 100644 pkg/client/test_data/test_mod_check/version_failed/kcl.mod create mode 100644 pkg/client/test_data/test_mod_check/version_failed/kcl.mod.lock create mode 100644 pkg/client/test_data/test_mod_check/version_failed/main.k diff --git a/pkg/checker/checker.go b/pkg/checker/checker.go index 2004dbdb..98c63190 100644 --- a/pkg/checker/checker.go +++ b/pkg/checker/checker.go @@ -25,40 +25,57 @@ type Checker interface { Check(pkg.KclPkg) error } -// DepChecker is responsible for running multiple checkers on a package's dependencies. -type DepChecker struct { +// ModChecker is responsible for running multiple checkers on a KCL module. +type ModChecker struct { checkers []Checker } -// DepCheckerOption configures how we set up DepChecker. -type DepCheckerOption func(*DepChecker) +// ModCheckerOption configures how we set up ModChecker. +type ModCheckerOption func(*ModChecker) -// NewDepChecker creates a new DepChecker with options. -func NewDepChecker(options ...DepCheckerOption) *DepChecker { - depChecker := &DepChecker{} +// NewModChecker creates a new ModChecker with options. +func NewModChecker(options ...ModCheckerOption) *ModChecker { + ModChecker := &ModChecker{} for _, opt := range options { - opt(depChecker) + opt(ModChecker) } - return depChecker + return ModChecker } -// WithChecker adds a single Checker to DepChecker. -func WithChecker(checker Checker) DepCheckerOption { - return func(c *DepChecker) { +// WithChecker adds a single Checker to ModChecker. +func WithChecker(checker Checker) ModCheckerOption { + return func(c *ModChecker) { + if c.checkers == nil { + c.checkers = []Checker{} + } c.checkers = append(c.checkers, checker) } } -// WithCheckers adds multiple Checkers to DepChecker. -func WithCheckers(checkers ...Checker) DepCheckerOption { - return func(c *DepChecker) { +// WithCheckers adds multiple Checkers to ModChecker. +func WithCheckers(checkers ...Checker) ModCheckerOption { + return func(c *ModChecker) { + if c.checkers == nil { + c.checkers = []Checker{} + } c.checkers = append(c.checkers, checkers...) } } +func (mc *ModChecker) AddChecker(checker Checker) { + mc.checkers = append(mc.checkers, checker) +} + +func (mc *ModChecker) CheckersSize() int { + if mc.checkers == nil { + return 0 + } + return len(mc.checkers) +} + // Check runs all individual checks for a kclPkg. -func (dc *DepChecker) Check(kclPkg pkg.KclPkg) error { - for _, checker := range dc.checkers { +func (mc *ModChecker) Check(kclPkg pkg.KclPkg) error { + for _, checker := range mc.checkers { if err := checker.Check(kclPkg); err != nil { return err } @@ -75,11 +92,8 @@ func NewIdentChecker() *IdentChecker { } func (ic *IdentChecker) Check(kclPkg pkg.KclPkg) error { - for _, key := range kclPkg.Dependencies.Deps.Keys() { - dep, _ := kclPkg.Dependencies.Deps.Get(key) - if !isValidDependencyName(dep.Name) { - return fmt.Errorf("invalid dependency name: %s", dep.Name) - } + if !isValidDependencyName(kclPkg.ModFile.Pkg.Name) { + return fmt.Errorf("invalid name: %s", kclPkg.ModFile.Pkg.Name) } return nil } @@ -93,12 +107,11 @@ func NewVersionChecker() *VersionChecker { } func (vc *VersionChecker) Check(kclPkg pkg.KclPkg) error { - for _, key := range kclPkg.Dependencies.Deps.Keys() { - dep, _ := kclPkg.Dependencies.Deps.Get(key) - if !isValidDependencyVersion(dep.Version) { - return fmt.Errorf("invalid dependency version: %s for %s", dep.Version, dep.Name) - } + if !isValidDependencyVersion(kclPkg.ModFile.Pkg.Version) { + return fmt.Errorf("invalid version: %s for %s", + kclPkg.ModFile.Pkg.Version, kclPkg.ModFile.Pkg.Name) } + return nil } @@ -147,7 +160,7 @@ func (sc *SumChecker) Check(kclPkg pkg.KclPkg) error { // isValidDependencyName checks whether the given dependency name is valid. func isValidDependencyName(name string) bool { - validNamePattern := `^[a-zA-Z][a-zA-Z0-9_\-\.]*[a-zA-Z0-9_]$` + validNamePattern := `^[a-z][a-z0-9_]*(?:-[a-z0-9_]+)*$` regex := regexp.MustCompile(validNamePattern) return regex.MatchString(name) } diff --git a/pkg/checker/checker_test.go b/pkg/checker/checker_test.go index 2b49fead..7dbf021b 100644 --- a/pkg/checker/checker_test.go +++ b/pkg/checker/checker_test.go @@ -14,8 +14,8 @@ import ( "kcl-lang.io/kpm/pkg/settings" ) -func TestDepCheckerCheck(t *testing.T) { - depChecker := NewDepChecker(WithCheckers(NewIdentChecker(), NewVersionChecker(), NewSumChecker())) +func TestModCheckerCheck(t *testing.T) { + ModChecker := NewModChecker(WithCheckers(NewIdentChecker(), NewVersionChecker(), NewSumChecker())) deps1 := orderedmap.NewOrderedMap[string, pkg.Dependency]() deps1.Set("kcl1", pkg.Dependency{ @@ -31,22 +31,6 @@ func TestDepCheckerCheck(t *testing.T) { Sum: "no-sum-check-enabled", }) - deps2 := orderedmap.NewOrderedMap[string, pkg.Dependency]() - deps2.Set("kcl1", pkg.Dependency{ - Name: ".kcl1", - FullName: "kcl1", - Version: "0.0.1", - Sum: "", - }) - - deps3 := orderedmap.NewOrderedMap[string, pkg.Dependency]() - deps3.Set("kcl1", pkg.Dependency{ - Name: "kcl1", - FullName: "kcl1", - Version: "1.0.0-alpha#", - Sum: "", - }) - tests := []struct { name string KclPkg pkg.KclPkg @@ -56,6 +40,10 @@ func TestDepCheckerCheck(t *testing.T) { name: "valid kcl package - with no sum check enabled", KclPkg: pkg.KclPkg{ ModFile: pkg.ModFile{ + Pkg: pkg.Package{ + Name: "testmod", + Version: "0.0.1", + }, HomePath: "path/to/modfile", }, HomePath: "path/to/kcl/pkg", @@ -66,40 +54,12 @@ func TestDepCheckerCheck(t *testing.T) { }, wantErr: false, }, - { - name: "Invalid kcl package - invalid dependency name", - KclPkg: pkg.KclPkg{ - ModFile: pkg.ModFile{ - HomePath: "path/to/modfile", - }, - HomePath: "path/to/kcl/pkg", - Dependencies: pkg.Dependencies{ - Deps: deps2, - }, - NoSumCheck: false, - }, - wantErr: true, - }, - { - name: "Invalid kcl package - invalid dependency version", - KclPkg: pkg.KclPkg{ - ModFile: pkg.ModFile{ - HomePath: "path/to/modfile", - }, - HomePath: "path/to/kcl/pkg", - Dependencies: pkg.Dependencies{ - Deps: deps3, - }, - NoSumCheck: false, - }, - wantErr: true, - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - gotErr := depChecker.Check(tt.KclPkg) + gotErr := ModChecker.Check(tt.KclPkg) if (gotErr != nil) != tt.wantErr { - t.Errorf("depChecker.Check(%v) = %v, want error %v", tt.KclPkg, gotErr, tt.wantErr) + t.Errorf("ModChecker.Check(%v) = %v, want error %v", tt.KclPkg, gotErr, tt.wantErr) } }) } @@ -112,12 +72,12 @@ func TestIsValidDependencyName(t *testing.T) { want bool }{ {"Empty Name", "", false}, - {"Valid Name - Simple", "myDependency", true}, + {"Valid Name - Simple", "myDependency", false}, {"Valid Name - With Underscore", "my_dependency", true}, {"Valid Name - With Hyphen", "my-dependency", true}, - {"Valid Name - With Dot", "my.dependency", true}, - {"Valid Name - Mixed Case", "MyDependency", true}, - {"Valid Name - Long Name", "My_Very-Long.Dependency", true}, + {"Valid Name - With Dot", "my.dependency", false}, + {"Valid Name - Mixed Case", "MyDependency", false}, + {"Valid Name - Long Name", "My_Very-Long.Dependency", false}, {"Contains Number", "depend3ncy", true}, {"Starts with Special Character", "-dependency", false}, {"Starts and Ends with Dot", ".dependency.", false}, @@ -184,9 +144,9 @@ func getTestSettings() (*settings.Settings, error) { return settings, nil } -func TestDepCheckerCheck_WithTrustedSum(t *testing.T) { +func TestModCheckerCheck_WithTrustedSum(t *testing.T) { if runtime.GOOS == "windows" { - t.Skip("Skipping TestDepCheckerCheck_WithTrustedSum test on Windows") + t.Skip("Skipping TestModCheckerCheck_WithTrustedSum test on Windows") } // Start the local Docker registry required for testing @@ -197,12 +157,12 @@ func TestDepCheckerCheck_WithTrustedSum(t *testing.T) { err = mock.PushTestPkgToRegistry() assert.Equal(t, err, nil) - // Initialize settings for use with the DepChecker + // Initialize settings for use with the ModChecker settings, err := getTestSettings() assert.Equal(t, err, nil) - // Initialize the DepChecker with required checkers - depChecker := NewDepChecker(WithCheckers(NewIdentChecker(), NewVersionChecker(), NewSumChecker(WithSettings(*settings)))) + // Initialize the ModChecker with required checkers + ModChecker := NewModChecker(WithCheckers(NewIdentChecker(), NewVersionChecker(), NewSumChecker(WithSettings(*settings)))) deps1 := orderedmap.NewOrderedMap[string, pkg.Dependency]() deps1.Set("kcl1", pkg.Dependency{ @@ -285,9 +245,9 @@ func TestDepCheckerCheck_WithTrustedSum(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - gotErr := depChecker.Check(tt.KclPkg) + gotErr := ModChecker.Check(tt.KclPkg) if (gotErr != nil) != tt.wantErr { - t.Errorf("depChecker.Check(%v) = %v, want error %v", tt.KclPkg, gotErr, tt.wantErr) + t.Errorf("ModChecker.Check(%v) = %v, want error %v", tt.KclPkg, gotErr, tt.wantErr) } }) } diff --git a/pkg/client/check.go b/pkg/client/check.go new file mode 100644 index 00000000..3cb45c54 --- /dev/null +++ b/pkg/client/check.go @@ -0,0 +1,57 @@ +package client + +import ( + "fmt" + + "kcl-lang.io/kpm/pkg/checker" + pkg "kcl-lang.io/kpm/pkg/package" +) + +type CheckOptions struct { + KclMod *pkg.KclPkg +} + +type CheckOption func(*CheckOptions) error + +func WithCheckKclMod(kclMod *pkg.KclPkg) CheckOption { + return func(opts *CheckOptions) error { + if kclMod == nil { + return fmt.Errorf("kclMod cannot be nil") + } + opts.KclMod = kclMod + return nil + } +} + +func (c *KpmClient) Check(options ...CheckOption) error { + opts := &CheckOptions{} + for _, option := range options { + if err := option(opts); err != nil { + return err + } + } + + kmod := opts.KclMod + if kmod == nil { + return fmt.Errorf("kclMod cannot be nil") + } + + // Init the ModChecker, name and version checkers are required. + if c.ModChecker == nil || c.ModChecker.CheckersSize() == 0 { + c.ModChecker = checker.NewModChecker( + checker.WithCheckers( + checker.NewIdentChecker(), + checker.NewVersionChecker(), + checker.NewSumChecker(), + ), + ) + } + + // Check the module and the dependencies + err := c.ModChecker.Check(*kmod) + if err != nil { + return err + } + + return err +} diff --git a/pkg/client/check_test.go b/pkg/client/check_test.go new file mode 100644 index 00000000..b65a4c0d --- /dev/null +++ b/pkg/client/check_test.go @@ -0,0 +1,121 @@ +package client + +import ( + "path/filepath" + "testing" + + "gotest.tools/v3/assert" + pkg "kcl-lang.io/kpm/pkg/package" +) + +func TestModCheckPass(t *testing.T) { + testModCheckPass := func(t *testing.T, kpmcli *KpmClient) { + testDir := filepath.Join(getTestDir("test_mod_check"), "pass") + kmod, err := pkg.LoadKclPkgWithOpts( + pkg.WithPath(testDir), + ) + + if err != nil { + t.Fatalf("failed to load kcl package: %v", err) + } + + err = kpmcli.Check( + WithCheckKclMod(kmod), + ) + + if err != nil { + t.Fatalf("failed to check kcl package: %v", err) + } + } + RunTestWithGlobalLockAndKpmCli(t, "test_mod_check_pass", testModCheckPass) +} + +func TestModCheckNameFailed(t *testing.T) { + testModCheckNameFailed := func(t *testing.T, kpmcli *KpmClient) { + testDir := filepath.Join(getTestDir("test_mod_check"), "name_failed") + kmod, err := pkg.LoadKclPkgWithOpts( + pkg.WithPath(testDir), + ) + + if err != nil { + t.Fatalf("failed to load kcl package: %v", err) + } + + err = kpmcli.Check( + WithCheckKclMod(kmod), + ) + + assert.Equal(t, err.Error(), "invalid name: invalid/mod/name") + } + RunTestWithGlobalLockAndKpmCli(t, "test_mod_check_name_failed", testModCheckNameFailed) +} + +func TestModCheckVersionFailed(t *testing.T) { + testModCheckVersionFailed := func(t *testing.T, kpmcli *KpmClient) { + testDir := filepath.Join(getTestDir("test_mod_check"), "version_failed") + kmod, err := pkg.LoadKclPkgWithOpts( + pkg.WithPath(testDir), + ) + if err != nil { + t.Fatalf("failed to load kcl package: %v", err) + } + + err = kpmcli.Check( + WithCheckKclMod(kmod), + ) + + assert.Equal(t, err.Error(), "invalid version: invalid_version for version_failed") + } + RunTestWithGlobalLockAndKpmCli(t, "test_mod_check_version_failed", testModCheckVersionFailed) +} + +func TestCheckDepSumPass(t *testing.T) { + testDepSumFunc := func(t *testing.T, kpmcli *KpmClient) { + pkgDir := filepath.Join(getTestDir("test_mod_check"), "sum") + + kmod, err := pkg.LoadKclPkgWithOpts( + pkg.WithPath(pkgDir), + ) + + if err != nil { + t.Fatalf("failed to load kcl package: %v", err) + } + + err = kpmcli.Check( + WithCheckKclMod(kmod), + ) + if err != nil { + t.Fatalf("failed to check kcl package: %v", err) + } + } + + RunTestWithGlobalLockAndKpmCli(t, "TestCheckDepSumPass", testDepSumFunc) +} + +func TestCheckDepSumFailed(t *testing.T) { + testDepSumFunc := func(t *testing.T, kpmcli *KpmClient) { + pkgDir := filepath.Join(getTestDir("test_mod_check"), "sum") + + kmod, err := pkg.LoadKclPkgWithOpts( + pkg.WithPath(pkgDir), + ) + + if err != nil { + t.Fatalf("failed to load kcl package: %v", err) + } + + dep := kmod.Dependencies.Deps.GetOrDefault("helloworld", pkg.TestPkgDependency) + dep.Sum = "invalid_sum" + ok := kmod.Dependencies.Deps.Set("helloworld", dep) + assert.Assert(t, !ok) + + err = kpmcli.Check( + WithCheckKclMod(kmod), + ) + + assert.Equal(t, err.Error(), "checksum verification failed for 'helloworld': "+ + "expected '9J9HOMhdypaDYf0J7PqtpGTdlkbxkN0HFEYhosHhf4U=', got 'invalid_sum'") + } + + RunTestWithGlobalLockAndKpmCli(t, "TestCheckDepSumFailed", testDepSumFunc) +} diff --git a/pkg/client/client.go b/pkg/client/client.go index 41b20f5f..16efbd07 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -49,7 +49,7 @@ type KpmClient struct { // The settings of kpm loaded from the global configuration file. settings settings.Settings // The checker to validate dependencies - DepChecker *checker.DepChecker + ModChecker *checker.ModChecker // The flag of whether to check the checksum of the package and update kcl.mod.lock. noSumCheck bool // The flag of whether to skip the verification of TLS. @@ -69,7 +69,7 @@ func NewKpmClient() (*KpmClient, error) { return nil, err } - depChecker := checker.NewDepChecker( + ModChecker := checker.NewModChecker( checker.WithCheckers(checker.NewIdentChecker(), checker.NewVersionChecker(), checker.NewSumChecker( checker.WithSettings(*settings))), ) @@ -78,7 +78,7 @@ func NewKpmClient() (*KpmClient, error) { logWriter: os.Stdout, settings: *settings, homePath: homePath, - DepChecker: depChecker, + ModChecker: ModChecker, DepDownloader: &downloader.DepDownloader{}, }, nil } @@ -947,7 +947,7 @@ func (c *KpmClient) Download(dep *pkg.Dependency, homePath, localPath string) (* } func (c *KpmClient) ValidateDependency(dep *pkg.Dependency) error { - if ok, err := features.Enabled(features.SupportCheckSum); err == nil && ok { + if ok, err := features.Enabled(features.SupportModCheck); err == nil && ok { tmpKclPkg := pkg.KclPkg{ HomePath: dep.LocalFullPath, Dependencies: pkg.Dependencies{Deps: func() *orderedmap.OrderedMap[string, pkg.Dependency] { @@ -958,7 +958,7 @@ func (c *KpmClient) ValidateDependency(dep *pkg.Dependency) error { NoSumCheck: c.GetNoSumCheck(), } - if err := c.DepChecker.Check(tmpKclPkg); err != nil { + if err := c.ModChecker.Check(tmpKclPkg); err != nil { return reporter.NewErrorEvent(reporter.InvalidKclPkg, err, fmt.Sprintf("%s package does not match the original kcl package", dep.FullName)) } } diff --git a/pkg/client/client_test.go b/pkg/client/client_test.go index 1de90bea..40409a19 100644 --- a/pkg/client/client_test.go +++ b/pkg/client/client_test.go @@ -2266,8 +2266,8 @@ func testPushWithInsecureSkipTLSverify(t *testing.T) { } func TestValidateDependency(t *testing.T) { - features.Enable(features.SupportCheckSum) - defer features.Disable(features.SupportCheckSum) + features.Enable(features.SupportModCheck) + defer features.Disable(features.SupportModCheck) kpmcli, err := NewKpmClient() assert.Equal(t, err, nil) diff --git a/pkg/client/test_data/test_mod_check/name_failed/kcl.mod b/pkg/client/test_data/test_mod_check/name_failed/kcl.mod new file mode 100644 index 00000000..8d860dec --- /dev/null +++ b/pkg/client/test_data/test_mod_check/name_failed/kcl.mod @@ -0,0 +1,7 @@ +[package] +name = "invalid/mod/name" +edition = "v0.10.0" +version = "0.0.1" + +[dependencies] +helloworld = "0.1.4" diff --git a/pkg/client/test_data/test_mod_check/name_failed/kcl.mod.lock b/pkg/client/test_data/test_mod_check/name_failed/kcl.mod.lock new file mode 100644 index 00000000..52056478 --- /dev/null +++ b/pkg/client/test_data/test_mod_check/name_failed/kcl.mod.lock @@ -0,0 +1,9 @@ +[dependencies] + [dependencies.helloworld] + name = "helloworld" + full_name = "helloworld_0.1.4" + version = "0.1.4" + sum = "9J9HOMhdypaDYf0J7PqtpGTdlkbxkN0HFEYhosHhf4U=" + reg = "ghcr.io" + repo = "kcl-lang/helloworld" + oci_tag = "0.1.4" diff --git a/pkg/client/test_data/test_mod_check/name_failed/main.k b/pkg/client/test_data/test_mod_check/name_failed/main.k new file mode 100644 index 00000000..fa7048e6 --- /dev/null +++ b/pkg/client/test_data/test_mod_check/name_failed/main.k @@ -0,0 +1 @@ +The_first_kcl_program = 'Hello World!' \ No newline at end of file diff --git a/pkg/client/test_data/test_mod_check/pass/kcl.mod b/pkg/client/test_data/test_mod_check/pass/kcl.mod new file mode 100644 index 00000000..67d51384 --- /dev/null +++ b/pkg/client/test_data/test_mod_check/pass/kcl.mod @@ -0,0 +1,7 @@ +[package] +name = "test_mod_check" +edition = "v0.10.0" +version = "0.0.1" + +[dependencies] +helloworld = "0.1.4" diff --git a/pkg/client/test_data/test_mod_check/pass/kcl.mod.lock b/pkg/client/test_data/test_mod_check/pass/kcl.mod.lock new file mode 100644 index 00000000..52056478 --- /dev/null +++ b/pkg/client/test_data/test_mod_check/pass/kcl.mod.lock @@ -0,0 +1,9 @@ +[dependencies] + [dependencies.helloworld] + name = "helloworld" + full_name = "helloworld_0.1.4" + version = "0.1.4" + sum = "9J9HOMhdypaDYf0J7PqtpGTdlkbxkN0HFEYhosHhf4U=" + reg = "ghcr.io" + repo = "kcl-lang/helloworld" + oci_tag = "0.1.4" diff --git a/pkg/client/test_data/test_mod_check/pass/main.k b/pkg/client/test_data/test_mod_check/pass/main.k new file mode 100644 index 00000000..fa7048e6 --- /dev/null +++ b/pkg/client/test_data/test_mod_check/pass/main.k @@ -0,0 +1 @@ +The_first_kcl_program = 'Hello World!' \ No newline at end of file diff --git a/pkg/client/test_data/test_mod_check/sum/kcl.mod b/pkg/client/test_data/test_mod_check/sum/kcl.mod new file mode 100644 index 00000000..67d51384 --- /dev/null +++ b/pkg/client/test_data/test_mod_check/sum/kcl.mod @@ -0,0 +1,7 @@ +[package] +name = "test_mod_check" +edition = "v0.10.0" +version = "0.0.1" + +[dependencies] +helloworld = "0.1.4" diff --git a/pkg/client/test_data/test_mod_check/sum/kcl.mod.lock b/pkg/client/test_data/test_mod_check/sum/kcl.mod.lock new file mode 100644 index 00000000..52056478 --- /dev/null +++ b/pkg/client/test_data/test_mod_check/sum/kcl.mod.lock @@ -0,0 +1,9 @@ +[dependencies] + [dependencies.helloworld] + name = "helloworld" + full_name = "helloworld_0.1.4" + version = "0.1.4" + sum = "9J9HOMhdypaDYf0J7PqtpGTdlkbxkN0HFEYhosHhf4U=" + reg = "ghcr.io" + repo = "kcl-lang/helloworld" + oci_tag = "0.1.4" diff --git a/pkg/client/test_data/test_mod_check/sum/main.k b/pkg/client/test_data/test_mod_check/sum/main.k new file mode 100644 index 00000000..fa7048e6 --- /dev/null +++ b/pkg/client/test_data/test_mod_check/sum/main.k @@ -0,0 +1 @@ +The_first_kcl_program = 'Hello World!' \ No newline at end of file diff --git a/pkg/client/test_data/test_mod_check/version_failed/kcl.mod b/pkg/client/test_data/test_mod_check/version_failed/kcl.mod new file mode 100644 index 00000000..cbf53be6 --- /dev/null +++ b/pkg/client/test_data/test_mod_check/version_failed/kcl.mod @@ -0,0 +1,7 @@ +[package] +name = "version_failed" +edition = "v0.10.0" +version = "invalid_version" + +[dependencies] +helloworld = "0.1.4" diff --git a/pkg/client/test_data/test_mod_check/version_failed/kcl.mod.lock b/pkg/client/test_data/test_mod_check/version_failed/kcl.mod.lock new file mode 100644 index 00000000..52056478 --- /dev/null +++ b/pkg/client/test_data/test_mod_check/version_failed/kcl.mod.lock @@ -0,0 +1,9 @@ +[dependencies] + [dependencies.helloworld] + name = "helloworld" + full_name = "helloworld_0.1.4" + version = "0.1.4" + sum = "9J9HOMhdypaDYf0J7PqtpGTdlkbxkN0HFEYhosHhf4U=" + reg = "ghcr.io" + repo = "kcl-lang/helloworld" + oci_tag = "0.1.4" diff --git a/pkg/client/test_data/test_mod_check/version_failed/main.k b/pkg/client/test_data/test_mod_check/version_failed/main.k new file mode 100644 index 00000000..fa7048e6 --- /dev/null +++ b/pkg/client/test_data/test_mod_check/version_failed/main.k @@ -0,0 +1 @@ +The_first_kcl_program = 'Hello World!' \ No newline at end of file diff --git a/pkg/client/update.go b/pkg/client/update.go index acbb0c09..b20a3a92 100644 --- a/pkg/client/update.go +++ b/pkg/client/update.go @@ -3,6 +3,8 @@ package client import ( "fmt" + "kcl-lang.io/kpm/pkg/checker" + "kcl-lang.io/kpm/pkg/features" pkg "kcl-lang.io/kpm/pkg/package" "kcl-lang.io/kpm/pkg/resolver" ) @@ -46,6 +48,23 @@ func (c *KpmClient) Update(options ...UpdateOption) (*pkg.KclPkg, error) { return nil, fmt.Errorf("kcl package is nil") } + if ok, err := features.Enabled(features.SupportModCheck); err == nil && ok && c.noSumCheck { + c.ModChecker = checker.NewModChecker( + checker.WithCheckers( + checker.NewIdentChecker(), + checker.NewVersionChecker(), + checker.NewSumChecker(), + ), + ) + + err := c.Check( + WithCheckKclMod(kMod), + ) + if err != nil { + return nil, err + } + } + kMod.NoSumCheck = c.noSumCheck modDeps := kMod.ModFile.Dependencies.Deps diff --git a/pkg/features/features.go b/pkg/features/features.go index 95d4dbbf..20f36ce3 100644 --- a/pkg/features/features.go +++ b/pkg/features/features.go @@ -13,15 +13,15 @@ const ( SupportMVS = "SupportMVS" // SupportNewStorage is the feature gate for enabling the support for the new storage structure. SupportNewStorage = "SupportNewStorage" - // SupportCheckSum is the feature gate for enabling the support for the checksum verification. - SupportCheckSum = "SupportCheckSum" + // SupportModCheck is the feature gate for enabling the support for the checksum verification. + SupportModCheck = "SupportModCheck" ) var ( features = map[string]bool{ SupportMVS: false, SupportNewStorage: false, - SupportCheckSum: false, + SupportModCheck: false, } mu sync.Mutex ) From 5586463229554b1ab4bf177664484c67dae44468 Mon Sep 17 00:00:00 2001 From: zongz Date: Fri, 29 Nov 2024 16:13:38 +0800 Subject: [PATCH 2/3] fix: fix test cases Signed-off-by: zongz --- pkg/checker/checker_test.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pkg/checker/checker_test.go b/pkg/checker/checker_test.go index 7dbf021b..56e51281 100644 --- a/pkg/checker/checker_test.go +++ b/pkg/checker/checker_test.go @@ -203,6 +203,10 @@ func TestModCheckerCheck_WithTrustedSum(t *testing.T) { name: "valid kcl package - with sum check", KclPkg: pkg.KclPkg{ ModFile: pkg.ModFile{ + Pkg: pkg.Package{ + Name: "testmod", + Version: "0.0.1", + }, HomePath: "path/to/modfile", }, HomePath: "path/to/kcl/pkg", @@ -217,6 +221,10 @@ func TestModCheckerCheck_WithTrustedSum(t *testing.T) { name: "valid kcl package - with no sum check enabled", KclPkg: pkg.KclPkg{ ModFile: pkg.ModFile{ + Pkg: pkg.Package{ + Name: "testmod", + Version: "0.0.1", + }, HomePath: "path/to/modfile", }, HomePath: "path/to/kcl/pkg", @@ -231,6 +239,10 @@ func TestModCheckerCheck_WithTrustedSum(t *testing.T) { name: "Invalid kcl package - with no sum check disabled - checksum mismatches", KclPkg: pkg.KclPkg{ ModFile: pkg.ModFile{ + Pkg: pkg.Package{ + Name: "testmod", + Version: "0.0.1", + }, HomePath: "path/to/modfile", }, HomePath: "path/to/kcl/pkg", From ade848daba63804cbe9a2bee87dedc4ce1b4e047 Mon Sep 17 00:00:00 2001 From: zongz Date: Fri, 29 Nov 2024 16:21:01 +0800 Subject: [PATCH 3/3] fix: fix test cases Signed-off-by: zongz --- pkg/client/client.go | 20 -------------------- pkg/client/client_test.go | 1 + pkg/client/deperated.go | 29 +++++++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/pkg/client/client.go b/pkg/client/client.go index 16efbd07..57994f9d 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -946,26 +946,6 @@ func (c *KpmClient) Download(dep *pkg.Dependency, homePath, localPath string) (* return dep, nil } -func (c *KpmClient) ValidateDependency(dep *pkg.Dependency) error { - if ok, err := features.Enabled(features.SupportModCheck); err == nil && ok { - tmpKclPkg := pkg.KclPkg{ - HomePath: dep.LocalFullPath, - Dependencies: pkg.Dependencies{Deps: func() *orderedmap.OrderedMap[string, pkg.Dependency] { - m := orderedmap.NewOrderedMap[string, pkg.Dependency]() - m.Set(dep.Name, *dep) - return m - }()}, - NoSumCheck: c.GetNoSumCheck(), - } - - if err := c.ModChecker.Check(tmpKclPkg); err != nil { - return reporter.NewErrorEvent(reporter.InvalidKclPkg, err, fmt.Sprintf("%s package does not match the original kcl package", dep.FullName)) - } - } - - return nil -} - // DownloadFromGit will download the dependency from the git repository. func (c *KpmClient) DownloadFromGit(dep *downloader.Git, localPath string) (string, error) { var msg string diff --git a/pkg/client/client_test.go b/pkg/client/client_test.go index 40409a19..6d082329 100644 --- a/pkg/client/client_test.go +++ b/pkg/client/client_test.go @@ -2287,6 +2287,7 @@ func TestValidateDependency(t *testing.T) { }, } err = kpmcli.ValidateDependency(&dep1) + fmt.Printf("err: %v\n", err) assert.Equal(t, err, nil) dep2 := pkg.Dependency{ diff --git a/pkg/client/deperated.go b/pkg/client/deperated.go index 20b4ba26..0265ee9e 100644 --- a/pkg/client/deperated.go +++ b/pkg/client/deperated.go @@ -6,8 +6,10 @@ import ( "os" "path/filepath" + "github.com/elliotchance/orderedmap/v2" "kcl-lang.io/kcl-go/pkg/kcl" "kcl-lang.io/kpm/pkg/downloader" + "kcl-lang.io/kpm/pkg/features" "kcl-lang.io/kpm/pkg/git" "kcl-lang.io/kpm/pkg/oci" "kcl-lang.io/kpm/pkg/opt" @@ -16,6 +18,33 @@ import ( "kcl-lang.io/kpm/pkg/utils" ) +// Deprecated: ValidateDependency is deprecated, use `Check` replaced. +func (c *KpmClient) ValidateDependency(dep *pkg.Dependency) error { + if ok, err := features.Enabled(features.SupportModCheck); err == nil && ok { + tmpKclPkg := pkg.KclPkg{ + ModFile: pkg.ModFile{ + Pkg: pkg.Package{ + Name: dep.Name, + Version: dep.Version, + }, + }, + HomePath: dep.LocalFullPath, + Dependencies: pkg.Dependencies{Deps: func() *orderedmap.OrderedMap[string, pkg.Dependency] { + m := orderedmap.NewOrderedMap[string, pkg.Dependency]() + m.Set(dep.Name, *dep) + return m + }()}, + NoSumCheck: c.GetNoSumCheck(), + } + + if err := c.ModChecker.Check(tmpKclPkg); err != nil { + return reporter.NewErrorEvent(reporter.InvalidKclPkg, err, fmt.Sprintf("%s package does not match the original kcl package", dep.FullName)) + } + } + + return nil +} + // CompileWithOpts will compile the kcl program with the compile options. // Deprecated: Use `Run` instead. func (c *KpmClient) CompileWithOpts(opts *opt.CompileOptions) (*kcl.KCLResultList, error) {