diff --git a/pkg/api/kpm_run.go b/pkg/api/kpm_run.go index 8f11a8e6..aa556285 100644 --- a/pkg/api/kpm_run.go +++ b/pkg/api/kpm_run.go @@ -105,6 +105,7 @@ func getAbsInputPath(pkgPath string, inputPath string) (string, error) { // RunPkgWithOpt will compile the kcl package with the compile options. func RunPkgWithOpt(opts *opt.CompileOptions) (*kcl.KCLResultList, error) { kpmcli, err := client.NewKpmClient() + kpmcli.SetNoSumCheck(opts.NoSumCheck()) if err != nil { return nil, err } @@ -140,6 +141,7 @@ func RunTarPkg(tarPath string, opts *opt.CompileOptions) (*kcl.KCLResultList, er opts.SetPkgPath(destDir) kpmcli, err := client.NewKpmClient() + kpmcli.SetNoSumCheck(opts.NoSumCheck()) if err != nil { return nil, err } @@ -157,7 +159,7 @@ func RunOciPkg(ociRef, version string, opts *opt.CompileOptions) (*kcl.KCLResult if err != nil { return nil, err } - + kpmcli.SetNoSumCheck(opts.NoSumCheck()) ociOpts, err := kpmcli.ParseOciOptionFromString(ociRef, version) if err != nil { diff --git a/pkg/api/kpm_run_test.go b/pkg/api/kpm_run_test.go index e58d1944..36899f29 100644 --- a/pkg/api/kpm_run_test.go +++ b/pkg/api/kpm_run_test.go @@ -154,3 +154,23 @@ func TestRunTarPkg(t *testing.T) { os.RemoveAll(untarPath) } } + +func TestRunWithNoSumCheck(t *testing.T) { + pkgPath := getTestDir("test_run_with_nosumcheck") + opts := opt.DefaultCompileOptions() + opts.SetPkgPath(pkgPath) + opts.SetNoSumCheck(true) + _, err := RunPkgInPath(opts) + assert.Equal(t, err, nil) + assert.Equal(t, utils.DirExists(filepath.Join(pkgPath, "kcl.mod.lock")), false) + + opts = opt.DefaultCompileOptions() + opts.SetPkgPath(pkgPath) + opts.SetNoSumCheck(false) + _, err = RunPkgInPath(opts) + assert.Equal(t, err, nil) + assert.Equal(t, utils.DirExists(filepath.Join(pkgPath, "kcl.mod.lock")), true) + defer func() { + _ = os.Remove(filepath.Join(pkgPath, "kcl.mod.lock")) + }() +} diff --git a/pkg/api/test_data/test_run_with_nosumcheck/kcl.mod b/pkg/api/test_data/test_run_with_nosumcheck/kcl.mod new file mode 100644 index 00000000..0daacdca --- /dev/null +++ b/pkg/api/test_data/test_run_with_nosumcheck/kcl.mod @@ -0,0 +1,7 @@ +[package] +name = "aaa" +edition = "0.0.1" +version = "0.0.1" + +[dependencies] +k8s = "1.27" diff --git a/pkg/api/test_data/test_run_with_nosumcheck/main.k b/pkg/api/test_data/test_run_with_nosumcheck/main.k new file mode 100644 index 00000000..fa7048e6 --- /dev/null +++ b/pkg/api/test_data/test_run_with_nosumcheck/main.k @@ -0,0 +1 @@ +The_first_kcl_program = 'Hello World!' \ No newline at end of file diff --git a/pkg/client/client.go b/pkg/client/client.go index c910fade..57948837 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -34,6 +34,8 @@ type KpmClient struct { homePath string // The settings of kpm loaded from the global configuration file. settings settings.Settings + // The flag of whether to check the checksum of the package and update kcl.mod.lock. + noSumCheck bool } // NewKpmClient will create a new kpm client with default settings. @@ -56,6 +58,16 @@ func NewKpmClient() (*KpmClient, error) { }, nil } +// SetNoSumCheck will set the 'noSumCheck' flag. +func (c *KpmClient) SetNoSumCheck(noSumCheck bool) { + c.noSumCheck = noSumCheck +} + +// GetNoSumCheck will return the 'noSumCheck' flag. +func (c *KpmClient) GetNoSumCheck() bool { + return c.noSumCheck +} + func (c *KpmClient) SetLogWriter(writer io.Writer) { c.logWriter = writer } @@ -148,6 +160,8 @@ func (c *KpmClient) ResolveDepsIntoMap(kclPkg *pkg.KclPkg) (map[string]string, e // If the package does not exist, it will re-download to the local. func (c *KpmClient) ResolvePkgDepsMetadata(kclPkg *pkg.KclPkg, update bool) error { var searchPath string + kclPkg.NoSumCheck = c.noSumCheck + if kclPkg.IsVendorMode() { // In the vendor mode, the search path is the vendor subdirectory of the current package. err := c.VendorDeps(kclPkg) @@ -193,7 +207,7 @@ func (c *KpmClient) ResolvePkgDepsMetadata(kclPkg *pkg.KclPkg, update bool) erro kclPkg.Dependencies.Deps[name] = d } } else { - if utils.DirExists(searchFullPath) && utils.CheckPackageSum(d.Sum, searchFullPath) { + if utils.DirExists(searchFullPath) && (c.GetNoSumCheck() || utils.CheckPackageSum(d.Sum, searchFullPath)) { // Find it and update the local path of the dependency. d.LocalFullPath = searchFullPath kclPkg.Dependencies.Deps[name] = d @@ -299,6 +313,8 @@ func (c *KpmClient) CompileWithOpts(opts *opt.CompileOptions) (*kcl.KCLResultLis return nil, reporter.NewErrorEvent(reporter.Bug, err, "internal bugs, please contact us to fix it.") } + c.noSumCheck = opts.NoSumCheck() + kclPkg, err := pkg.LoadKclPkg(pkgPath) if err != nil { return nil, err @@ -483,6 +499,9 @@ func (c *KpmClient) InitEmptyPkg(kclPkg *pkg.KclPkg) error { // AddDepWithOpts will add a dependency to the current kcl package. func (c *KpmClient) AddDepWithOpts(kclPkg *pkg.KclPkg, opt *opt.AddOptions) (*pkg.KclPkg, error) { + c.noSumCheck = opt.NoSumCheck + kclPkg.NoSumCheck = opt.NoSumCheck + // 1. get the name and version of the repository from the input arguments. d, err := pkg.ParseOpt(&opt.RegistryOpts) if err != nil { @@ -1006,6 +1025,29 @@ func (c *KpmClient) ParseOciOptionFromString(oci string, tag string) (*opt.OciOp return ociOpt, nil } +// dependencyExists will check whether the dependency exists in the local filesystem. +func (c *KpmClient) dependencyExists(dep *pkg.Dependency, lockDeps *pkg.Dependencies) *pkg.Dependency { + + // If the flag '--no_sum_check' is set, skip the checksum check. + if c.noSumCheck { + // If the dependent package does exist locally + if utils.DirExists(filepath.Join(c.homePath, dep.FullName)) { + return dep + } + } + + lockDep, present := lockDeps.Deps[dep.Name] + // Check if the sum of this dependency in kcl.mod.lock has been chanaged. + if !c.noSumCheck && present { + // If the dependent package does not exist locally, then method 'check' will return false. + if c.noSumCheck || check(lockDep, filepath.Join(c.homePath, dep.FullName)) { + return dep + } + } + + return nil +} + // downloadDeps will download all the dependencies of the current kcl package. func (c *KpmClient) downloadDeps(deps pkg.Dependencies, lockDeps pkg.Dependencies) (*pkg.Dependencies, error) { newDeps := pkg.Dependencies{ @@ -1018,16 +1060,12 @@ func (c *KpmClient) downloadDeps(deps pkg.Dependencies, lockDeps pkg.Dependencie return nil, errors.InvalidDependency } - lockDep, present := lockDeps.Deps[d.Name] - - // Check if the sum of this dependency in kcl.mod.lock has been chanaged. - if present { - // If the dependent package does not exist locally, then method 'check' will return false. - if check(lockDep, filepath.Join(c.homePath, d.FullName)) { - newDeps.Deps[d.Name] = lockDep - continue - } + existDep := c.dependencyExists(&d, &lockDeps) + if existDep != nil { + newDeps.Deps[d.Name] = *existDep + continue } + expectedSum := lockDeps.Deps[d.Name].Sum // Clean the cache if len(c.homePath) == 0 || len(d.FullName) == 0 { @@ -1044,7 +1082,7 @@ func (c *KpmClient) downloadDeps(deps pkg.Dependencies, lockDeps pkg.Dependencie } if !lockedDep.IsFromLocal() { - if expectedSum != "" && lockedDep.Sum != expectedSum && lockDep.FullName == d.FullName { + if !c.noSumCheck && expectedSum != "" && lockedDep.Sum != expectedSum && existDep.FullName == d.FullName { return nil, reporter.NewErrorEvent( reporter.CheckSumMismatch, errors.CheckSumMismatchError, diff --git a/pkg/client/client_test.go b/pkg/client/client_test.go index 07cd1389..cefd1385 100644 --- a/pkg/client/client_test.go +++ b/pkg/client/client_test.go @@ -778,3 +778,93 @@ func TestMetadataOffline(t *testing.T) { assert.Equal(t, err, nil) assert.Equal(t, utils.RmNewline(string(content_after_metadata)), utils.RmNewline(string(beautifulContent))) } + +func TestAddWithNoSumCheck(t *testing.T) { + pkgPath := getTestDir("test_add_no_sum_check") + err := copy.Copy(filepath.Join(pkgPath, "kcl.mod.bak"), filepath.Join(pkgPath, "kcl.mod")) + assert.Equal(t, err, nil) + + kpmcli, err := NewKpmClient() + assert.Equal(t, err, nil) + kclPkg, err := kpmcli.LoadPkgFromPath(pkgPath) + assert.Equal(t, err, nil) + + opts := opt.AddOptions{ + LocalPath: pkgPath, + RegistryOpts: opt.RegistryOptions{ + Oci: &opt.OciOptions{ + Reg: "ghcr.io", + Repo: "kcl-lang", + PkgName: "helloworld", + Tag: "0.1.0", + }, + }, + NoSumCheck: true, + } + + _, err = kpmcli.AddDepWithOpts(kclPkg, &opts) + assert.Equal(t, err, nil) + assert.Equal(t, utils.DirExists(filepath.Join(pkgPath, "kcl.mod.lock")), false) + + opts.NoSumCheck = false + _, err = kpmcli.AddDepWithOpts(kclPkg, &opts) + assert.Equal(t, err, nil) + assert.Equal(t, utils.DirExists(filepath.Join(pkgPath, "kcl.mod.lock")), true) + defer func() { + _ = os.Remove(filepath.Join(pkgPath, "kcl.mod.lock")) + _ = os.Remove(filepath.Join(pkgPath, "kcl.mod")) + }() +} + +func TestRunWithNoSumCheck(t *testing.T) { + pkgPath := getTestDir("test_run_no_sum_check") + + kpmcli, err := NewKpmClient() + assert.Equal(t, err, nil) + + opts := opt.DefaultCompileOptions() + opts.SetNoSumCheck(true) + opts.SetPkgPath(pkgPath) + + _, err = kpmcli.CompileWithOpts(opts) + assert.Equal(t, err, nil) + assert.Equal(t, utils.DirExists(filepath.Join(pkgPath, "kcl.mod.lock")), false) + + opts = opt.DefaultCompileOptions() + opts.SetPkgPath(pkgPath) + opts.SetNoSumCheck(false) + _, err = kpmcli.CompileWithOpts(opts) + assert.Equal(t, err, nil) + assert.Equal(t, utils.DirExists(filepath.Join(pkgPath, "kcl.mod.lock")), true) + + defer func() { + _ = os.Remove(filepath.Join(pkgPath, "kcl.mod.lock")) + }() +} + +func TestUpdateWithNoSumCheck(t *testing.T) { + pkgPath := getTestDir("test_update_no_sum_check") + + kpmcli, err := NewKpmClient() + assert.Equal(t, err, nil) + + kpmcli.SetNoSumCheck(true) + kclPkg, err := kpmcli.LoadPkgFromPath(pkgPath) + assert.Equal(t, err, nil) + + err = kpmcli.UpdateDeps(kclPkg) + assert.Equal(t, err, nil) + assert.Equal(t, utils.DirExists(filepath.Join(pkgPath, "kcl.mod.lock")), false) + + kpmcli.SetNoSumCheck(false) + kclPkg, err = kpmcli.LoadPkgFromPath(pkgPath) + assert.Equal(t, err, nil) + + err = kpmcli.UpdateDeps(kclPkg) + assert.Equal(t, err, nil) + assert.Equal(t, utils.DirExists(filepath.Join(pkgPath, "kcl.mod.lock")), true) + + defer func() { + _ = os.Remove(filepath.Join(pkgPath, "kcl.mod.lock")) + }() +} diff --git a/pkg/client/test_data/test_add_no_sum_check/kcl.mod.bak b/pkg/client/test_data/test_add_no_sum_check/kcl.mod.bak new file mode 100644 index 00000000..10ff4d12 --- /dev/null +++ b/pkg/client/test_data/test_add_no_sum_check/kcl.mod.bak @@ -0,0 +1,7 @@ +[package] +name = "test_add_no_sum_check" +edition = "0.0.1" +version = "0.0.1" + +[dependencies] +helloworld = "0.1.1" diff --git a/pkg/client/test_data/test_add_no_sum_check/main.k b/pkg/client/test_data/test_add_no_sum_check/main.k new file mode 100644 index 00000000..fa7048e6 --- /dev/null +++ b/pkg/client/test_data/test_add_no_sum_check/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_run_no_sum_check/kcl.mod b/pkg/client/test_data/test_run_no_sum_check/kcl.mod new file mode 100644 index 00000000..27e24ba4 --- /dev/null +++ b/pkg/client/test_data/test_run_no_sum_check/kcl.mod @@ -0,0 +1,7 @@ +[package] +name = "test_run_no_sum_check" +edition = "0.0.1" +version = "0.0.1" + +[dependencies] +helloworld = "0.1.1" diff --git a/pkg/client/test_data/test_run_no_sum_check/main.k b/pkg/client/test_data/test_run_no_sum_check/main.k new file mode 100644 index 00000000..fa7048e6 --- /dev/null +++ b/pkg/client/test_data/test_run_no_sum_check/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_update_no_sum_check/kcl.mod b/pkg/client/test_data/test_update_no_sum_check/kcl.mod new file mode 100644 index 00000000..27e24ba4 --- /dev/null +++ b/pkg/client/test_data/test_update_no_sum_check/kcl.mod @@ -0,0 +1,7 @@ +[package] +name = "test_run_no_sum_check" +edition = "0.0.1" +version = "0.0.1" + +[dependencies] +helloworld = "0.1.1" diff --git a/pkg/client/test_data/test_update_no_sum_check/main.k b/pkg/client/test_data/test_update_no_sum_check/main.k new file mode 100644 index 00000000..fa7048e6 --- /dev/null +++ b/pkg/client/test_data/test_update_no_sum_check/main.k @@ -0,0 +1 @@ +The_first_kcl_program = 'Hello World!' \ No newline at end of file diff --git a/pkg/cmd/cmd_add.go b/pkg/cmd/cmd_add.go index e5e5aa82..fdf55ff3 100644 --- a/pkg/cmd/cmd_add.go +++ b/pkg/cmd/cmd_add.go @@ -32,6 +32,10 @@ func NewAddCmd(kpmcli *client.KpmClient) *cli.Command { Name: "tag", Usage: "Git repository tag", }, + &cli.BoolFlag{ + Name: FLAG_NO_SUM_CHECK, + Usage: "do not check the checksum of the package and update kcl.mod.lock", + }, }, Action: func(c *cli.Context) error { @@ -120,6 +124,7 @@ func onlyOnceOption(c *cli.Context, name string) (*string, *reporter.KpmEvent) { // parseAddOptions will parse the user cli inputs. func parseAddOptions(c *cli.Context, kpmcli *client.KpmClient, localPath string) (*opt.AddOptions, error) { + noSumCheck := c.Bool(FLAG_NO_SUM_CHECK) // parse from 'kpm add -git https://xxx/xxx.git -tag v0.0.1'. if c.NArg() == 0 { gitOpts, err := parseGitRegistryOptions(c) @@ -132,6 +137,7 @@ func parseAddOptions(c *cli.Context, kpmcli *client.KpmClient, localPath string) return &opt.AddOptions{ LocalPath: localPath, RegistryOpts: *gitOpts, + NoSumCheck: noSumCheck, }, nil } else { localPkg, err := parseLocalPathOptions(c) @@ -144,11 +150,13 @@ func parseAddOptions(c *cli.Context, kpmcli *client.KpmClient, localPath string) return &opt.AddOptions{ LocalPath: localPath, RegistryOpts: *ociReg, + NoSumCheck: noSumCheck, }, nil } else { return &opt.AddOptions{ LocalPath: localPath, RegistryOpts: *localPkg, + NoSumCheck: noSumCheck, }, nil } } diff --git a/pkg/cmd/cmd_flags.go b/pkg/cmd/cmd_flags.go index 1f34c2f6..bf91f861 100644 --- a/pkg/cmd/cmd_flags.go +++ b/pkg/cmd/cmd_flags.go @@ -15,3 +15,4 @@ const FLAG_OVERRIDES = "overrides" const FLAG_SORT_KEYS = "sort_keys" const FLAG_QUIET = "quiet" +const FLAG_NO_SUM_CHECK = "no_sum_check" diff --git a/pkg/cmd/cmd_run.go b/pkg/cmd/cmd_run.go index 1a59f933..db3a539c 100644 --- a/pkg/cmd/cmd_run.go +++ b/pkg/cmd/cmd_run.go @@ -38,6 +38,11 @@ func NewRunCmd(kpmcli *client.KpmClient) *cli.Command { Name: FLAG_VENDOR, Usage: "run in vendor mode", }, + // --no_sum_check + &cli.BoolFlag{ + Name: FLAG_NO_SUM_CHECK, + Usage: "do not check the checksum of the package and update kcl.mod.lock", + }, // KCL arg: --setting, -Y &cli.StringSliceFlag{ @@ -87,6 +92,8 @@ func KpmRun(c *cli.Context, kpmcli *client.KpmClient) error { return err } + kpmcli.SetNoSumCheck(c.Bool(FLAG_NO_SUM_CHECK)) + defer func() { // release the lock of the package cache after the function returns. releaseErr := kpmcli.ReleasePackageCacheLock() diff --git a/pkg/cmd/cmd_update.go b/pkg/cmd/cmd_update.go index 5f7cafd2..6f004a26 100644 --- a/pkg/cmd/cmd_update.go +++ b/pkg/cmd/cmd_update.go @@ -17,6 +17,12 @@ func NewUpdateCmd(kpmcli *client.KpmClient) *cli.Command { Hidden: false, Name: "update", Usage: "Update dependencies listed in kcl.mod.lock based on kcl.mod", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: FLAG_NO_SUM_CHECK, + Usage: "do not check the checksum of the package and update kcl.mod.lock", + }, + }, Action: func(c *cli.Context) error { return KpmUpdate(c, kpmcli) }, @@ -24,6 +30,8 @@ func NewUpdateCmd(kpmcli *client.KpmClient) *cli.Command { } func KpmUpdate(c *cli.Context, kpmcli *client.KpmClient) error { + kpmcli.SetNoSumCheck(c.Bool(FLAG_NO_SUM_CHECK)) + // acquire the lock of the package cache. err := kpmcli.AcquirePackageCacheLock() if err != nil { @@ -67,12 +75,7 @@ func KpmUpdate(c *cli.Context, kpmcli *client.KpmClient) error { return err } - _, err = kpmcli.ResolveDepsMetadataInJsonStr(kclPkg, true) - if err != nil { - return err - } - - err = kclPkg.UpdateModAndLockFile() + err = kpmcli.UpdateDeps(kclPkg) if err != nil { return err } diff --git a/pkg/opt/opt.go b/pkg/opt/opt.go index 3c5944a5..f7375ba7 100644 --- a/pkg/opt/opt.go +++ b/pkg/opt/opt.go @@ -19,6 +19,7 @@ type CompileOptions struct { isVendor bool hasSettingsYaml bool entries []string + noSumCheck bool // Add a writer to control the output of the compiler. writer io.Writer *kcl.Option @@ -32,6 +33,16 @@ func DefaultCompileOptions() *CompileOptions { } } +// SetNoSumCheck will set the 'no_sum_check' flag. +func (opts *CompileOptions) SetNoSumCheck(noSumCheck bool) { + opts.noSumCheck = noSumCheck +} + +// NoSumCheck will return the 'no_sum_check' flag. +func (opts *CompileOptions) NoSumCheck() bool { + return opts.noSumCheck +} + // AddEntry will add a compile entry file to the compiler. func (opts *CompileOptions) AddEntry(entry string) { opts.entries = append(opts.entries, entry) @@ -110,6 +121,7 @@ func (opts *InitOptions) Validate() error { type AddOptions struct { LocalPath string RegistryOpts RegistryOptions + NoSumCheck bool } func (opts *AddOptions) Validate() error { diff --git a/pkg/package/package.go b/pkg/package/package.go index a20f7f9c..be5c5343 100644 --- a/pkg/package/package.go +++ b/pkg/package/package.go @@ -19,6 +19,8 @@ type KclPkg struct { // The dependencies in the current kcl package are the dependencies of kcl.mod.lock, // not the dependencies in kcl.mod. Dependencies + // The flag 'NoSumCheck' is true if the checksum of the current kcl package is not checked. + NoSumCheck bool } func NewKclPkg(opts *opt.InitOptions) KclPkg { @@ -98,9 +100,11 @@ func (kclPkg *KclPkg) UpdateModAndLockFile() error { } // Generate file kcl.mod.lock. - err = kclPkg.LockDepsVersion() - if err != nil { - return err + if !kclPkg.NoSumCheck { + err = kclPkg.LockDepsVersion() + if err != nil { + return err + } } return nil diff --git a/test/e2e/test_suites/kpm/exec_inside_pkg/run_with_with_noargs_input/test_suite.stdout b/test/e2e/test_suites/kpm/exec_inside_pkg/run_with_with_noargs_input/test_suite.stdout index c6ff3a50..934c6956 100644 --- a/test/e2e/test_suites/kpm/exec_inside_pkg/run_with_with_noargs_input/test_suite.stdout +++ b/test/e2e/test_suites/kpm/exec_inside_pkg/run_with_with_noargs_input/test_suite.stdout @@ -13,6 +13,7 @@ OPTIONS: --input value [ --input value ] a kcl file as the compile entry file --tag value the tag for oci artifact --vendor run in vendor mode (default: false) + --no_sum_check do not check the checksum of the package and update kcl.mod.lock (default: false) --setting value, -Y value [ --setting value, -Y value ] specify the input setting file --argument value, -D value [ --argument value, -D value ] specify the top-level argument --overrides value, -O value [ --overrides value, -O value ] specify the configuration override path and value