Skip to content

Commit

Permalink
fix: fix bugs when adding dependency without version in modspec
Browse files Browse the repository at this point in the history
Signed-off-by: zongz <[email protected]>
  • Loading branch information
zong-zhe committed Nov 4, 2024
1 parent fa23c82 commit 2437ce2
Show file tree
Hide file tree
Showing 19 changed files with 216 additions and 8 deletions.
9 changes: 9 additions & 0 deletions pkg/client/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,15 @@ func (c *KpmClient) Add(options ...AddOption) error {
// If the dependency is remote, the visitor will download it to the local.
// If the dependency is already in local cache, the visitor will not download it again.
err = visitor.Visit(fullSouce, func(depPkg *pkg.KclPkg) error {
var modSpec *downloader.ModSpec
if depSource.ModSpec.IsNil() {
modSpec = &downloader.ModSpec{
Name: depPkg.ModFile.Pkg.Name,
Version: depPkg.ModFile.Pkg.Version,
}
depSource.ModSpec = modSpec
}

dep := pkg.Dependency{
Name: depPkg.ModFile.Pkg.Name,
FullName: depPkg.GetPkgFullName(),
Expand Down
17 changes: 16 additions & 1 deletion pkg/client/add_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"kcl-lang.io/kpm/pkg/utils"
)

func testAddWithModSpec(t *testing.T) {
func TestAddWithModSpec(t *testing.T) {
tests := []struct {
name string
pkgSubPath string
Expand All @@ -32,6 +32,21 @@ func testAddWithModSpec(t *testing.T) {
pkgSubPath: filepath.Join("local", "pkg"),
sourceUrl: "../dep?mod=sub:0.0.1",
},
{
name: "TestAddOciWithEmptyVersion",
pkgSubPath: "empty_version",
sourceUrl: "oci://ghcr.io/kcl-lang/helloworld?tag=0.1.4&mod=subhelloworld",
},
{
name: "TestAddOciWithNoSpec",
pkgSubPath: "no_spec",
sourceUrl: "oci://ghcr.io/kcl-lang/helloworld?tag=0.1.4",
},
{
name: "TestAddOciWithNoTag",
pkgSubPath: "no_tag",
sourceUrl: "oci://ghcr.io/kcl-lang/helloworld",
},
}

for _, tt := range tests {
Expand Down
6 changes: 3 additions & 3 deletions pkg/client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func initTestDir(subDir string) string {
}

func TestWithGlobalLock(t *testing.T) {
test.RunTestWithGlobalLock(t, "TestUpdateWithKclMod", testUpdateWithKclMod)
test.RunTestWithGlobalLock(t, "TestUpdateWithKclMod", TestUpdateWithKclMod)
test.RunTestWithGlobalLock(t, "TestUpdateWithKclModlock", testUpdateWithKclModlock)
test.RunTestWithGlobalLock(t, "TestUpdateWithNoSumCheck", testUpdateWithNoSumCheck)
test.RunTestWithGlobalLock(t, "TestAddWithDiffVersionNoSumCheck", testAddWithDiffVersionNoSumCheck)
Expand All @@ -82,7 +82,7 @@ func TestWithGlobalLock(t *testing.T) {
test.RunTestWithGlobalLock(t, "TestDownloadGitWithPackage", testDownloadGitWithPackage)
test.RunTestWithGlobalLock(t, "TestModandLockFilesWithGitPackageDownload", testModandLockFilesWithGitPackageDownload)
test.RunTestWithGlobalLock(t, "TestDependencyGraph", testDependencyGraph)
test.RunTestWithGlobalLock(t, "testAddWithModSpec", testAddWithModSpec)
test.RunTestWithGlobalLock(t, "testAddWithModSpec", TestAddWithModSpec)
}

// TestDownloadOci test download from oci registry.
Expand Down Expand Up @@ -1077,7 +1077,7 @@ func TestGetReleasesFromSource(t *testing.T) {
assert.Equal(t, releasesVersions[:5], []string{"1.14", "1.14.1", "1.15", "1.15.1", "1.16"})
}

func testUpdateWithKclMod(t *testing.T) {
func TestUpdateWithKclMod(t *testing.T) {
kpmcli, err := NewKpmClient()
assert.Equal(t, err, nil)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "oci"
edition = "v0.10.0"
version = "0.0.1"

[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "oci"
edition = "v0.10.0"
version = "0.0.1"

[dependencies]
subhelloworld = { oci = "oci://ghcr.io/kcl-lang/helloworld", tag = "0.1.4", version = "0.0.1" }
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[dependencies]
[dependencies.subhelloworld]
name = "subhelloworld"
full_name = "subhelloworld_0.0.1"
version = "0.0.1"
reg = "ghcr.io"
repo = "kcl-lang/helloworld"
oci_tag = "0.1.4"
6 changes: 6 additions & 0 deletions pkg/client/test_data/add_with_mod_spec/no_spec/kcl.mod.bk
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "oci"
edition = "v0.10.0"
version = "0.0.1"

[dependencies]
7 changes: 7 additions & 0 deletions pkg/client/test_data/add_with_mod_spec/no_spec/kcl.mod.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "oci"
edition = "v0.10.0"
version = "0.0.1"

[dependencies]
helloworld = { oci = "oci://ghcr.io/kcl-lang/helloworld", tag = "0.1.4", version = "0.1.4" }
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[dependencies]
[dependencies.helloworld]
name = "helloworld"
full_name = "helloworld_0.1.4"
version = "0.1.4"
reg = "ghcr.io"
repo = "kcl-lang/helloworld"
oci_tag = "0.1.4"
6 changes: 6 additions & 0 deletions pkg/client/test_data/add_with_mod_spec/no_tag/kcl.mod.bk
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "oci"
edition = "v0.10.0"
version = "0.0.1"

[dependencies]
7 changes: 7 additions & 0 deletions pkg/client/test_data/add_with_mod_spec/no_tag/kcl.mod.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "oci"
edition = "v0.10.0"
version = "0.0.1"

[dependencies]
helloworld = { oci = "oci://ghcr.io/kcl-lang/helloworld", tag = "0.1.4", version = "0.1.4" }
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[dependencies]
[dependencies.helloworld]
name = "helloworld"
full_name = "helloworld_0.1.4"
version = "0.1.4"
reg = "ghcr.io"
repo = "kcl-lang/helloworld"
oci_tag = "0.1.4"
69 changes: 68 additions & 1 deletion pkg/downloader/downloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,28 @@ func NewDownloadOptions(opts ...Option) *DownloadOptions {
// Downloader is the interface for downloading a package.
type Downloader interface {
Download(opts DownloadOptions) error
// Get the latest version of the remote source
// For the git source, it will return the latest commit
// For the OCI source, it will return the latest tag
LatestVersion(opts DownloadOptions) (string, error)
}

func (d *DepDownloader) LatestVersion(opts DownloadOptions) (string, error) {
if opts.Source.Oci != nil {
if d.OciDownloader == nil {
d.OciDownloader = &OciDownloader{}
}
return d.OciDownloader.LatestVersion(opts)
}

if opts.Source.Git != nil {
if d.GitDownloader == nil {
d.GitDownloader = &GitDownloader{}
}
return d.GitDownloader.LatestVersion(opts)
}

return "", errors.New("source is nil")
}

// DepDownloader is the downloader for the package.
Expand All @@ -113,11 +135,53 @@ type DepDownloader struct {
// GitDownloader is the downloader for the git source.
type GitDownloader struct{}

func (d *GitDownloader) LatestVersion(opts DownloadOptions) (string, error) {
// TODO:supports fetch the latest commit from the git bare repo,
// after totally transfer to the new storage.
return "main", nil
}

// OciDownloader is the downloader for the OCI source.
type OciDownloader struct {
Platform string
}

func (d *OciDownloader) LatestVersion(opts DownloadOptions) (string, error) {
// download the package from the OCI registry
ociSource := opts.Source.Oci
if ociSource == nil {
return "", errors.New("oci source is nil")
}

repoPath := utils.JoinPath(ociSource.Reg, ociSource.Repo)

var cred *remoteauth.Credential
var err error
if opts.credsClient != nil {
cred, err = opts.credsClient.Credential(ociSource.Reg)
if err != nil {
return "", err
}
} else {
cred = &remoteauth.Credential{}
}

ociCli, err := oci.NewOciClientWithOpts(
oci.WithCredential(cred),
oci.WithRepoPath(repoPath),
oci.WithSettings(&opts.Settings),
oci.WithInsecureSkipTLSverify(opts.InsecureSkipTLSverify),
)

if err != nil {
return "", err
}

ociCli.PullOciOptions.Platform = d.Platform

return ociCli.TheLatestTag()
}

func NewOciDownloader(platform string) *DepDownloader {
return &DepDownloader{
OciDownloader: &OciDownloader{
Expand All @@ -143,7 +207,10 @@ func (d *DepDownloader) Download(opts DownloadOptions) error {
cacheFullPath := opts.CachePath
if ok, err := features.Enabled(features.SupportNewStorage); err == nil && !ok && opts.EnableCache {
cacheFullPath = filepath.Join(opts.CachePath, opts.Source.LocalPath())
if utils.DirExists(cacheFullPath) && utils.DirExists(filepath.Join(cacheFullPath, constants.KCL_MOD)) {
if utils.DirExists(cacheFullPath) && utils.DirExists(filepath.Join(cacheFullPath, constants.KCL_MOD)) &&
// If the version in modspec is empty, meanings the latest version is needed.
// The latest version should be requested first and the cache should be updated.
((opts.Source.ModSpec != nil && opts.Source.ModSpec.Version != "") || opts.Source.ModSpec == nil) {
// copy the cache to the local path
if cacheFullPath != opts.LocalPath {
err := copy.Copy(cacheFullPath, opts.LocalPath)
Expand Down
12 changes: 12 additions & 0 deletions pkg/downloader/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ type Oci struct {
Tag string `toml:"oci_tag,omitempty"`
}

// If the OCI source has no reference, return true.
// TODO: add digest support.
func (o *Oci) NoRef() bool {
return o.Tag == ""
}

// Git is the package source from git registry.
type Git struct {
Url string `toml:"url,omitempty"`
Expand All @@ -62,6 +68,11 @@ type Git struct {
Package string `toml:"package,omitempty"`
}

// If the git source has no reference, return true.
func (g *Git) NoRef() bool {
return g.Version == "" && g.Tag == "" && g.Branch == "" && g.Commit == ""
}

func NewSourceFromStr(sourceStr string) (*Source, error) {
source := &Source{}
err := source.FromString(sourceStr)
Expand Down Expand Up @@ -484,6 +495,7 @@ func (ps *ModSpec) FromString(registryStr string) error {
}
parts := strings.Split(registryStr, ":")
if len(parts) == 1 {
ps.Name = parts[0]
return nil
}

Expand Down
1 change: 1 addition & 0 deletions pkg/resolver/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ func (dr *DepsResolver) Resolve(options ...ResolveOption) error {
InsecureSkipTLSverify: dr.InsecureSkipTLSverify,
EnableCache: opts.EnableCache,
CachePath: cachePath,
VisitedSpace: cachePath,
}, nil
} else if source.IsLocalTarPath() || source.IsLocalTgzPath() {
return visitor.NewArchiveVisitor(pkgVisitor), nil
Expand Down
47 changes: 44 additions & 3 deletions pkg/visitor/visitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"kcl-lang.io/kpm/pkg/downloader"
"kcl-lang.io/kpm/pkg/opt"
pkg "kcl-lang.io/kpm/pkg/package"
"kcl-lang.io/kpm/pkg/reporter"
"kcl-lang.io/kpm/pkg/settings"
"kcl-lang.io/kpm/pkg/utils"
)
Expand Down Expand Up @@ -113,12 +114,50 @@ func NewRemoteVisitor(pv *PkgVisitor) *RemoteVisitor {
// It will download the remote package to a temporary directory.
// And the tmp directory will be cleaned after the visitFunc is executed.
func (rv *RemoteVisitor) Visit(s *downloader.Source, v visitFunc) error {
var err error
if !s.IsRemote() {
return fmt.Errorf("source is not remote")
}

// 1. Load the credential file.
credCli, err := downloader.LoadCredentialFile(rv.Settings.CredentialsFile)
if err != nil {
return err
}

// 2. If the version is not specified, get the latest version.
// For Oci, the latest tag
// For Git, the main branch
if (s.Oci != nil && s.Oci.NoRef()) || (s.Git != nil && s.Git.NoRef()) {
latest, err := rv.Downloader.LatestVersion(*downloader.NewDownloadOptions(
downloader.WithSource(*s),
downloader.WithLogWriter(rv.LogWriter),
downloader.WithSettings(*rv.Settings),
downloader.WithCredsClient(credCli),
downloader.WithInsecureSkipTLSverify(rv.InsecureSkipTLSverify),
))

if err != nil {
return err
}

reporter.ReportMsgTo(
fmt.Sprintf("the lastest version '%s' will be downloaded", latest),
rv.LogWriter,
)

if !s.ModSpec.IsNil() && s.ModSpec.Version == "" {
s.ModSpec.Version = latest
}

if s.Oci != nil {
s.Oci.Tag = latest
}
if s.Git != nil {
s.Git.Branch = latest
}
}
var modPath string
var err error
if len(rv.VisitedSpace) != 0 {
modPath = filepath.Join(rv.VisitedSpace, s.LocalPath())
} else {
Expand All @@ -138,7 +177,7 @@ func (rv *RemoteVisitor) Visit(s *downloader.Source, v visitFunc) error {
}
}

credCli, err := downloader.LoadCredentialFile(rv.Settings.CredentialsFile)
credCli, err = downloader.LoadCredentialFile(rv.Settings.CredentialsFile)
if err != nil {
return err
}
Expand Down Expand Up @@ -173,7 +212,9 @@ func (rv *RemoteVisitor) Visit(s *downloader.Source, v visitFunc) error {
}

if !s.ModSpec.IsNil() {
if kclPkg.ModFile.Pkg.Version != s.ModSpec.Version {
if s.ModSpec.Version == "" {
s.ModSpec.Version = kclPkg.ModFile.Pkg.Version
} else 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,
Expand Down

0 comments on commit 2437ce2

Please sign in to comment.