From ea0b7057236829fbd9b20c3075d09c388948bc1b Mon Sep 17 00:00:00 2001 From: zongz Date: Wed, 30 Oct 2024 15:03:42 +0800 Subject: [PATCH] feat: make 'run' command supports ModSpec Signed-off-by: zongz --- pkg/client/client_test.go | 37 ++++++++++++++ .../test_run_options/remote/expect_3.yaml | 1 + pkg/constants/constants.go | 1 + pkg/downloader/source.go | 51 ++++++++++++++++--- pkg/visitor/visitor.go | 13 ++++- 5 files changed, 94 insertions(+), 9 deletions(-) create mode 100644 pkg/client/test_data/test_run_options/remote/expect_3.yaml diff --git a/pkg/client/client_test.go b/pkg/client/client_test.go index 1223cca3..f974ac3d 100644 --- a/pkg/client/client_test.go +++ b/pkg/client/client_test.go @@ -1980,6 +1980,35 @@ func TestRunLocalWithArgs(t *testing.T) { } } +func TestRunRemoteWithArgsInvalid(t *testing.T) { + kpmcli, err := NewKpmClient() + assert.Equal(t, err, nil) + + logbuf := new(bytes.Buffer) + kpmcli.SetLogWriter(logbuf) + + type testCase struct { + sourceURL string + expectedLog string + expectedErrMsg string + } + + testCases := []testCase{ + { + sourceURL: "git://github.com/kcl-lang/flask-demo-kcl-manifests?commit=8308200&mod=cc:0.0.2", + expectedLog: "cloning 'https://github.com/kcl-lang/flask-demo-kcl-manifests' with commit '8308200'\n", + expectedErrMsg: "version mismatch: 0.0.1 != 0.0.2, version 0.0.2 not found", + }, + } + + for _, tc := range testCases { + _, err := kpmcli.Run(WithRunSourceUrl(tc.sourceURL)) + assert.Equal(t, err.Error(), tc.expectedErrMsg) + assert.Equal(t, logbuf.String(), tc.expectedLog) + logbuf.Reset() + } +} + func TestRunRemoteWithArgs(t *testing.T) { pkgPath := getTestDir("test_run_options") kpmcli, err := NewKpmClient() @@ -2017,6 +2046,14 @@ func TestRunRemoteWithArgs(t *testing.T) { return string(expected), err }, }, + { + sourceURL: "git://github.com/kcl-lang/flask-demo-kcl-manifests?commit=8308200&mod=cc:0.0.1", + expectedLog: "cloning 'https://github.com/kcl-lang/flask-demo-kcl-manifests' with commit '8308200'\n", + expectedYamlFn: func(pkgPath string) (string, error) { + expected, err := os.ReadFile(filepath.Join(pkgPath, "remote", "expect_3.yaml")) + return string(expected), err + }, + }, } for i, tc := range testCases { diff --git a/pkg/client/test_data/test_run_options/remote/expect_3.yaml b/pkg/client/test_data/test_run_options/remote/expect_3.yaml new file mode 100644 index 00000000..f4059255 --- /dev/null +++ b/pkg/client/test_data/test_run_options/remote/expect_3.yaml @@ -0,0 +1 @@ +The_first_kcl_program: Hello World! \ No newline at end of file diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index 44318e8c..c2637104 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -23,6 +23,7 @@ const ( GitCommit = "commit" Tag = "tag" + Mod = "mod" KCL_MOD = "kcl.mod" KCL_MOD_LOCK = "kcl.mod.lock" diff --git a/pkg/downloader/source.go b/pkg/downloader/source.go index 81a6f44c..a2996ef2 100644 --- a/pkg/downloader/source.go +++ b/pkg/downloader/source.go @@ -261,19 +261,40 @@ func (local *Local) ToFilePath() (string, error) { } func (source *Source) ToString() (string, error) { + var sourceStr string + var err error if source == nil { return "", fmt.Errorf("source is nil") } if source.Git != nil { - return source.Git.ToString() - } - if source.Oci != nil { - return source.Oci.ToString() + sourceStr, err = source.Git.ToString() + if err != nil { + return "", err + } + } else if source.Oci != nil { + sourceStr, err = source.Oci.ToString() + if err != nil { + return "", err + } + } else if source.Local != nil { + sourceStr, err = source.Local.ToString() + if err != nil { + return "", err + } } - if source.Local != nil { - return source.Local.ToString() + if source.ModSpec != nil { + url, err := url.Parse(sourceStr) + if err != nil { + return "", err + } + + q := url.Query() + q.Set(constants.Mod, source.ModSpec.ToString()) + url.RawQuery = q.Encode() + sourceStr = url.String() } - return "", fmt.Errorf("source is nil") + + return sourceStr, nil } func (git *Git) ToString() (string, error) { @@ -336,6 +357,13 @@ func (local *Local) ToString() (string, error) { return pathUrl.String(), nil } +func (mod *ModSpec) ToString() string { + if mod == nil { + return "" + } + return fmt.Sprintf("%s:%s", mod.Name, mod.Version) +} + func (source *Source) FromString(sourceStr string) error { if source == nil { return fmt.Errorf("source is nil") @@ -346,6 +374,15 @@ func (source *Source) FromString(sourceStr string) error { return err } + modSpec := sourceUrl.Query().Get(constants.Mod) + if len(modSpec) != 0 { + source.ModSpec = &ModSpec{} + err := source.ModSpec.FromString(modSpec) + if err != nil { + return err + } + } + if sourceUrl.Scheme == constants.GitScheme || sourceUrl.Scheme == constants.SshScheme { source.Git = &Git{} source.Git.FromString(sourceStr) diff --git a/pkg/visitor/visitor.go b/pkg/visitor/visitor.go index c05729e5..bea5bc00 100644 --- a/pkg/visitor/visitor.go +++ b/pkg/visitor/visitor.go @@ -140,8 +140,8 @@ func (rv *RemoteVisitor) Visit(s *downloader.Source, v visitFunc) error { return err } pkgPath := tmpDir - if s.Git != nil && len(s.Git.Package) > 0 { - pkgPath, err = utils.FindPackage(tmpDir, s.Git.Package) + if !s.ModSpec.IsNil() { + pkgPath, err = utils.FindPackage(tmpDir, s.ModSpec.Name) if err != nil { return err } @@ -155,6 +155,15 @@ func (rv *RemoteVisitor) Visit(s *downloader.Source, v visitFunc) error { return err } + if !s.ModSpec.IsNil() { + if kclPkg.ModFile.Pkg.Version != s.ModSpec.Version { + return fmt.Errorf( + "version mismatch: %s != %s, version %s not found", + kclPkg.ModFile.Pkg.Version, s.ModSpec.Version, s.ModSpec.Version, + ) + } + } + return v(kclPkg) }