diff --git a/Makefile b/Makefile index da70c94a05..2eca311ca6 100644 --- a/Makefile +++ b/Makefile @@ -70,7 +70,7 @@ test-all: install-requirements .PHONY: generate generate: - @$(REPO_ROOT)/hack/generate.sh $(REPO_ROOT)/pkg... $(REPO_ROOT)/cmds/ocm/... $(REPO_ROOT)/cmds/helminstaller/... $(REPO_ROOT)/examples/... + @$(REPO_ROOT)/hack/generate.sh $(REPO_ROOT)/pkg/... $(REPO_ROOT)/cmds/ocm/... $(REPO_ROOT)/cmds/helminstaller/... $(REPO_ROOT)/examples/... .PHONY: generate-deepcopy generate-deepcopy: controller-gen diff --git a/cmds/ocm/commands/ocmcmds/common/addhdlrs/rscs/elements.go b/cmds/ocm/commands/ocmcmds/common/addhdlrs/rscs/elements.go index 51692fa2fe..18629849a3 100644 --- a/cmds/ocm/commands/ocmcmds/common/addhdlrs/rscs/elements.go +++ b/cmds/ocm/commands/ocmcmds/common/addhdlrs/rscs/elements.go @@ -130,6 +130,10 @@ type ResourceSpec struct { var _ addhdlrs.ElementSpec = (*ResourceSpec)(nil) +func (r *ResourceSpec) GetType() string { + return r.Type +} + func (r *ResourceSpec) GetRawIdentity() metav1.Identity { return r.ElementMeta.GetRawIdentity() } diff --git a/cmds/ocm/commands/ocmcmds/common/inputs/types/maven/spec.go b/cmds/ocm/commands/ocmcmds/common/inputs/types/maven/spec.go index b07c924979..dc3fe396a8 100644 --- a/cmds/ocm/commands/ocmcmds/common/inputs/types/maven/spec.go +++ b/cmds/ocm/commands/ocmcmds/common/inputs/types/maven/spec.go @@ -95,5 +95,9 @@ func (s *Spec) GetBlob(ctx inputs.Context, info inputs.InputResourceInfo) (bloba mavenblob.WithCachingFileSystem(vfsattr.Get(ctx)), ) + if s.IsPackage() { + return access, s.GAV(), err + } + return access, "", err } diff --git a/cmds/ocm/commands/ocmcmds/components/add/cmd.go b/cmds/ocm/commands/ocmcmds/components/add/cmd.go index 648babe18a..ba592a16f5 100644 --- a/cmds/ocm/commands/ocmcmds/components/add/cmd.go +++ b/cmds/ocm/commands/ocmcmds/components/add/cmd.go @@ -2,6 +2,7 @@ package add import ( "fmt" + "github.com/open-component-model/ocm/cmds/ocm/commands/ocmcmds/common/options/uploaderoption" "github.com/mandelsoft/goutils/errors" "github.com/mandelsoft/goutils/general" @@ -64,7 +65,8 @@ func NewCommand(ctx clictx.Context, names ...string) *cobra.Command { templateroption.New(""), dryrunoption.New("evaluate and print component specifications", true), lookupoption.New(), - rscbyvalueoption.New()), + rscbyvalueoption.New(), + uploaderoption.New(ctx.OCMContext())), }, utils.Names(Names, names...)...) } @@ -183,6 +185,11 @@ func (o *Command) Complete(args []string) error { return accessio.ErrInvalidFileFormat(format.String()) } + err = uploaderoption.From(o).Register(o) + if err != nil { + return err + } + return nil } diff --git a/cmds/ocm/coretests/maven/cmd_test.go b/cmds/ocm/coretests/maven/cmd_test.go new file mode 100644 index 0000000000..b94256a16e --- /dev/null +++ b/cmds/ocm/coretests/maven/cmd_test.go @@ -0,0 +1,123 @@ +package add_test + +import ( + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + . "github.com/open-component-model/ocm/cmds/ocm/testhelper" + "github.com/open-component-model/ocm/pkg/contexts/ocm" + "github.com/open-component-model/ocm/pkg/contexts/ocm/accessmethods/localblob" + mavenacc "github.com/open-component-model/ocm/pkg/contexts/ocm/accessmethods/maven" + "github.com/open-component-model/ocm/pkg/maven" + . "github.com/open-component-model/ocm/pkg/testutils" + "strings" + "time" + + "github.com/open-component-model/ocm/pkg/contexts/ocm/repositories/ctf" + "github.com/open-component-model/ocm/pkg/maven/maventest" +) + +const ( + MAVEN_CENTRAL_ADDRESS = "repo.maven.apache.org:443" + MAVEN_CENTRAL = "https://repo.maven.apache.org/maven2/" + MAVEN_GROUP_ID = "maven" + MAVEN_ARTIFACT_ID = "maven" + MAVEN_VERSION = "1.1" +) + +const ARCH = "/tmp/ctf" +const DEST_ARCH = "/tmp/ctf-dest" +const VERSION = "1.0.0" +const COMPONENT = "ocm.software/demo/test" +const OUT = "/tmp/res" + +var _ = Describe("Test Environment", func() { + var env *TestEnv + + BeforeEach(func() { + env = NewTestEnv(TestData(), maventest.TestData("/maven/testdata")) + }) + + AfterEach(func() { + env.Cleanup() + }) + + It("upload maven package from localblob during transfer", func() { + coords := maven.NewCoordinates(maventest.GROUP_ID, maventest.ARTIFACT_ID, maventest.VERSION) + Expect(env.Execute("add", "cv", "-fc", "--file", ARCH, "testdata/components.yaml")).To(Succeed()) + Expect(env.DirExists(ARCH)).To(BeTrue()) + repo := Must(ctf.Open(env, ctf.ACC_READONLY, ARCH, 0, env)) + defer Close(repo) + cv := Must(repo.LookupComponentVersion(COMPONENT, VERSION)) + defer Close(cv) + Expect(len(cv.GetDescriptor().Resources)).To(Equal(1)) + acc := Must(env.OCMContext().AccessSpecForSpec(cv.GetDescriptor().Resources[0].Access)) + Expect(acc.IsLocal(env.OCMContext())).To(BeTrue()) + Expect(acc.(*localblob.AccessSpec).ReferenceName).To(Equal(strings.Join([]string{maventest.GROUP_ID, maventest.ARTIFACT_ID, maventest.VERSION}, ":"))) + + Expect(env.Execute("transfer", "ctf", ARCH, DEST_ARCH, "--uploader", "ocm/mavenArtifact=file://localhost/mavenrepo")).To(Succeed()) + Expect(env.DirExists(DEST_ARCH)).To(BeTrue()) + Expect(env.DirExists("/mavenrepo/" + coords.GavPath())).To(BeTrue()) + mavenrepo := maven.NewFileRepository("/mavenrepo", env.FileSystem()) + Expect(mavenrepo.GavFiles(coords, nil)).To(YAMLEqual(` +sdk-modules-bom-5.7.0-random-content.json: 5 +sdk-modules-bom-5.7.0-random-content.txt: 5 +sdk-modules-bom-5.7.0-sources.jar: 5 +sdk-modules-bom-5.7.0.jar: 5 +sdk-modules-bom-5.7.0.pom: 5`)) + }) + + It("upload maven package from localblob during component composition", func() { + coords := maven.NewCoordinates(maventest.GROUP_ID, maventest.ARTIFACT_ID, maventest.VERSION) + Expect(env.Execute("add", "cv", "-fc", "--file", ARCH, "testdata/components.yaml", "--uploader", "ocm/mavenArtifact=file://localhost/mavenrepo")).To(Succeed()) + Expect(env.DirExists(ARCH)).To(BeTrue()) + repo := Must(ctf.Open(env, ctf.ACC_READONLY, ARCH, 0, env)) + defer Close(repo) + cv := Must(repo.LookupComponentVersion(COMPONENT, VERSION)) + defer Close(cv) + Expect(len(cv.GetDescriptor().Resources)).To(Equal(1)) + acc := Must(env.OCMContext().AccessSpecForSpec(cv.GetDescriptor().Resources[0].Access)) + Expect(acc.IsLocal(env.OCMContext())).To(BeFalse()) + Expect(acc.GetKind()).To(Equal(mavenacc.Type)) + Expect(acc.(*mavenacc.AccessSpec).GAV()).To(Equal(strings.Join([]string{maventest.GROUP_ID, maventest.ARTIFACT_ID, maventest.VERSION}, ":"))) + + Expect(env.DirExists("/mavenrepo/" + coords.GavPath())).To(BeTrue()) + mavenrepo := maven.NewFileRepository("/mavenrepo", env.FileSystem()) + Expect(mavenrepo.GavFiles(coords, nil)).To(YAMLEqual(` +sdk-modules-bom-5.7.0-random-content.json: 5 +sdk-modules-bom-5.7.0-random-content.txt: 5 +sdk-modules-bom-5.7.0-sources.jar: 5 +sdk-modules-bom-5.7.0.jar: 5 +sdk-modules-bom-5.7.0.pom: 5`)) + }) + + Context("maven http repository", func() { + if PingTCPServer(MAVEN_CENTRAL_ADDRESS, time.Second) == nil { + var coords *maven.Coordinates + BeforeEach(func() { + coords = maven.NewCoordinates(MAVEN_GROUP_ID, MAVEN_ARTIFACT_ID, MAVEN_VERSION) + }) + It("upload maven package from access method", func() { + Expect(env.Execute("add", "cv", "-fc", "--file", ARCH, "testdata/components2.yaml")).To(Succeed()) + Expect(env.DirExists(ARCH)).To(BeTrue()) + repo := Must(ctf.Open(env, ctf.ACC_READONLY, ARCH, 0, env)) + defer Close(repo) + cv := Must(repo.LookupComponentVersion(COMPONENT, VERSION)) + defer Close(cv) + Expect(len(cv.GetDescriptor().Resources)).To(Equal(1)) + acc := Must(env.OCMContext().AccessSpecForSpec(cv.GetDescriptor().Resources[0].Access)) + Expect(acc.IsLocal(env.OCMContext())).To(BeFalse()) + Expect(acc.(ocm.HintProvider).GetReferenceHint(cv)).To(Equal(coords.GAV())) + + Expect(env.Execute("transfer", "ctf", ARCH, DEST_ARCH, "--copy-resources", "--uploader", "ocm/mavenArtifact=file://localhost/mavenrepo")).To(Succeed()) + Expect(env.DirExists(DEST_ARCH)).To(BeTrue()) + Expect(env.DirExists("/mavenrepo/" + coords.GavPath())).To(BeTrue()) + mavenrepo := maven.NewFileRepository("/mavenrepo", env.FileSystem()) + Expect(mavenrepo.GavFiles(coords, nil)).To(YAMLEqual(` +maven-1.1-RC1.javadoc.javadoc.jar: 5 +maven-1.1-sources.jar: 5 +maven-1.1.jar: 5 +maven-1.1.pom: 5`)) + }) + } + }) +}) diff --git a/cmds/ocm/coretests/maven/suite_test.go b/cmds/ocm/coretests/maven/suite_test.go new file mode 100644 index 0000000000..7ed2c5b5ff --- /dev/null +++ b/cmds/ocm/coretests/maven/suite_test.go @@ -0,0 +1,13 @@ +package add_test + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestConfig(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "OCM add components") +} diff --git a/cmds/ocm/coretests/maven/testdata/components.yaml b/cmds/ocm/coretests/maven/testdata/components.yaml new file mode 100644 index 0000000000..b7e206e64c --- /dev/null +++ b/cmds/ocm/coretests/maven/testdata/components.yaml @@ -0,0 +1,14 @@ +components: +- name: ocm.software/demo/test + version: 1.0.0 + provider: + name: ocm.software + resources: + - name: mavenartifact + type: mavenArtifact + input: + type: maven + path: /maven/testdata/.m2/repository + groupId: "com.sap.cloud.sdk" + artifactId: "sdk-modules-bom" + version: "5.7.0" \ No newline at end of file diff --git a/cmds/ocm/coretests/maven/testdata/components2.yaml b/cmds/ocm/coretests/maven/testdata/components2.yaml new file mode 100644 index 0000000000..dabe1562b8 --- /dev/null +++ b/cmds/ocm/coretests/maven/testdata/components2.yaml @@ -0,0 +1,15 @@ +components: +- name: ocm.software/demo/test + version: 1.0.0 + provider: + name: ocm.software + resources: + - name: mavenartifact + type: mavenArtifact + version: "1.1" + access: + type: maven + repoUrl: "https://repo.maven.apache.org/maven2/" + groupId: "maven" + artifactId: "maven" + version: "1.1" \ No newline at end of file diff --git a/go.mod b/go.mod index e061189790..8278e43603 100644 --- a/go.mod +++ b/go.mod @@ -39,8 +39,8 @@ require ( github.com/klauspost/compress v1.17.8 github.com/klauspost/pgzip v1.2.6 github.com/mandelsoft/filepath v0.0.0-20240223090642-3e2777258aa3 - github.com/mandelsoft/goutils v0.0.0-20240527090454-525d51156f92 - github.com/mandelsoft/logging v0.0.0-20240326140403-99e2fb8bdce6 + github.com/mandelsoft/goutils v0.0.0-20240604075441-f06e2890eea3 + github.com/mandelsoft/logging v0.0.0-20240201091719-67180059d6bf github.com/mandelsoft/spiff v1.7.0-beta-5 github.com/mandelsoft/vfs v0.4.3 github.com/marstr/guid v1.1.0 diff --git a/go.sum b/go.sum index 0149b7f29e..b5ed0a1221 100644 --- a/go.sum +++ b/go.sum @@ -682,10 +682,10 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mandelsoft/filepath v0.0.0-20240223090642-3e2777258aa3 h1:oo9nIgnyiBgYPbcZslRT4y29siuL5EoNJ/t1tr0xEVQ= github.com/mandelsoft/filepath v0.0.0-20240223090642-3e2777258aa3/go.mod h1:LxhqC7khDoRENwooP6f/vWvia9ivj6TqLYrR39zqkN0= -github.com/mandelsoft/goutils v0.0.0-20240527090454-525d51156f92 h1:JKHpPtPpkCA7AVRv5trXmqAcncjbfkjiv4x7wGSJnEc= -github.com/mandelsoft/goutils v0.0.0-20240527090454-525d51156f92/go.mod h1:EbNqk9JceSMq7MJuALB/vlOpoD4MAGE0TenM9TR+C0o= -github.com/mandelsoft/logging v0.0.0-20240326140403-99e2fb8bdce6 h1:xLaVUuFrXqcAZJ2rGZdRHX1Qe4AvxZINJ5XAXKmL2uc= -github.com/mandelsoft/logging v0.0.0-20240326140403-99e2fb8bdce6/go.mod h1:uO460C1lIB3IOOgrbXhAlz3AKsOv4T2K6ALBn3PwuSg= +github.com/mandelsoft/goutils v0.0.0-20240604075441-f06e2890eea3 h1:jSXyDjsOuy0DUCzDUCrZS/QMJZ2we1HQfLCpb0D7cnY= +github.com/mandelsoft/goutils v0.0.0-20240604075441-f06e2890eea3/go.mod h1:EbNqk9JceSMq7MJuALB/vlOpoD4MAGE0TenM9TR+C0o= +github.com/mandelsoft/logging v0.0.0-20240201091719-67180059d6bf h1:WEmgzeArDbp6Aw34jmziMIE5ygo2zpl/atXRq3D7lSw= +github.com/mandelsoft/logging v0.0.0-20240201091719-67180059d6bf/go.mod h1:uO460C1lIB3IOOgrbXhAlz3AKsOv4T2K6ALBn3PwuSg= github.com/mandelsoft/spiff v1.7.0-beta-5 h1:3kC10nTviDQhL8diSxp7i4IC2iSiDg6KPbH1CAq7Lfw= github.com/mandelsoft/spiff v1.7.0-beta-5/go.mod h1:TwEeOPuRZxlzQBCLEyVTlHmBSruSGGNdiQ2fovVJ8ao= github.com/mandelsoft/vfs v0.4.3 h1:2UMrxQkMXkcHyuqSFhgFDupQ1fmqpKLZuu04DOHx1PA= diff --git a/pkg/blobaccess/maven/options.go b/pkg/blobaccess/maven/options.go index 8ceae8c2ea..679ad81a2d 100644 --- a/pkg/blobaccess/maven/options.go +++ b/pkg/blobaccess/maven/options.go @@ -22,10 +22,8 @@ type Options struct { CachingPath string // Credentials allows to pass credentials and certificates for the http communication Credentials credentials.Credentials - // Classifier defines the classifier of the maven file coordinates - Classifier *string - // Extension defines the extension of the maven file coordinates - Extension *string + + maven.FileCoordinates } func (o *Options) Logger(keyValuePairs ...interface{}) logging.Logger { @@ -179,7 +177,7 @@ func WithOptionalClassifier(c *string) Option { if c != nil { return WithClassifier(*c) } - return nil + return &optionutils.NoOption[*Options]{} } //////////////////////////////////////////////////////////////////////////////// @@ -198,7 +196,7 @@ func WithOptionalExtension(e *string) Option { if e != nil { return WithExtension(*e) } - return nil + return &optionutils.NoOption[*Options]{} } //////////////////////////////////////////////////////////////////////////////// diff --git a/pkg/contexts/ocm/accessmethods/maven/method.go b/pkg/contexts/ocm/accessmethods/maven/method.go index d377c884fd..71514c2b71 100644 --- a/pkg/contexts/ocm/accessmethods/maven/method.go +++ b/pkg/contexts/ocm/accessmethods/maven/method.go @@ -89,7 +89,10 @@ func (a *AccessSpec) GlobalAccessSpec(_ accspeccpi.Context) accspeccpi.AccessSpe // GetReferenceHint returns the reference hint for the Maven (mvn) artifact. func (a *AccessSpec) GetReferenceHint(_ accspeccpi.ComponentVersionAccess) string { - return a.String() + if a.IsPackage() { + return a.GAV() + } + return "" } func (_ *AccessSpec) GetType() string { diff --git a/pkg/contexts/ocm/accessmethods/maven/method_test.go b/pkg/contexts/ocm/accessmethods/maven/method_test.go index bfd7a43103..b419b3e343 100644 --- a/pkg/contexts/ocm/accessmethods/maven/method_test.go +++ b/pkg/contexts/ocm/accessmethods/maven/method_test.go @@ -60,6 +60,10 @@ var _ = Describe("local accessmethods.maven.AccessSpec tests", func() { Expect(dr.Size()).To(Equal(int64(maventest.ARTIFACT_SIZE))) Expect(dr.Digest().String()).To(Equal("SHA-256:" + maventest.ARTIFACT_DIGEST)) }) + It("test empty repoUrl", func() { + acc := me.New("", "com.sap.cloud.sdk", "sdk-modules-bom", "5.7.0") + ExpectError(acc.AccessMethod(cv)).ToNot(BeNil()) + }) It("accesses local artifact with empty classifier and with extension", func() { acc := me.New("file://"+MAVEN_PATH, "com.sap.cloud.sdk", "sdk-modules-bom", "5.7.0", me.WithClassifier(""), me.WithExtension("pom")) diff --git a/pkg/contexts/ocm/blobhandler/handlers/generic/maven/blobhandler.go b/pkg/contexts/ocm/blobhandler/handlers/generic/maven/blobhandler.go index 76dd8689bc..3e63461f56 100644 --- a/pkg/contexts/ocm/blobhandler/handlers/generic/maven/blobhandler.go +++ b/pkg/contexts/ocm/blobhandler/handlers/generic/maven/blobhandler.go @@ -60,7 +60,7 @@ func (b *artifactHandler) StoreBlob(blob cpi.BlobAccess, resourceType string, hi if err != nil { return nil, err } - if coords.Classifier != nil || coords.Extension != nil { + if !coords.IsPackage() { return nil, nil } log = log.WithValues("groupId", coords.GroupId, "artifactId", coords.ArtifactId, "version", coords.Version) diff --git a/pkg/contexts/ocm/elements/artifactblob/mavenblob/access_test.go b/pkg/contexts/ocm/elements/artifactblob/mavenblob/access_test.go index 8bf2b4fdd9..3e050eeeca 100644 --- a/pkg/contexts/ocm/elements/artifactblob/mavenblob/access_test.go +++ b/pkg/contexts/ocm/elements/artifactblob/mavenblob/access_test.go @@ -47,6 +47,7 @@ var _ = Describe("blobaccess for maven", func() { maven.WithClassifier("random-content"), maven.WithExtension("json")) a := me.ResourceAccessForMavenCoords(env.OCMContext(), Must(elements.ResourceMeta("mavenblob", resourcetypes.OCM_JSON, elements.WithLocalRelation())), repo, coords, me.WithCachingFileSystem(env.FileSystem())) + Expect(a.ReferenceHint()).To(Equal("")) b := Must(a.BlobAccess()) defer Close(b) Expect(string(Must(b.Get()))).To(Equal(`{"some": "test content"}`)) @@ -57,5 +58,15 @@ var _ = Describe("blobaccess for maven", func() { defer Close(m) Expect(string(Must(m.Get()))).To(Equal(`{"some": "test content"}`)) }) + + It("blobaccess for package", func() { + cv := composition.NewComponentVersion(env.OCMContext(), "acme.org/test", "1.0.0") + defer Close(cv) + + coords := maven.NewCoordinates("com.sap.cloud.sdk", "sdk-modules-bom", "5.7.0") + + a := me.ResourceAccessForMavenCoords(env.OCMContext(), Must(elements.ResourceMeta("mavenblob", resourcetypes.OCM_JSON, elements.WithLocalRelation())), repo, coords, me.WithCachingFileSystem(env.FileSystem())) + Expect(a.ReferenceHint()).To(Equal(coords.GAV())) + }) }) }) diff --git a/pkg/contexts/ocm/elements/artifactblob/mavenblob/options.go b/pkg/contexts/ocm/elements/artifactblob/mavenblob/options.go index 6bc448da74..55e9052f53 100644 --- a/pkg/contexts/ocm/elements/artifactblob/mavenblob/options.go +++ b/pkg/contexts/ocm/elements/artifactblob/mavenblob/options.go @@ -10,6 +10,7 @@ import ( "github.com/open-component-model/ocm/pkg/contexts/datacontext" "github.com/open-component-model/ocm/pkg/contexts/ocm/cpi" "github.com/open-component-model/ocm/pkg/contexts/ocm/elements/artifactblob/api" + "github.com/open-component-model/ocm/pkg/maven" ) type Option = optionutils.Option[*Options] @@ -40,6 +41,13 @@ func WithHint(h string) Option { return api.WrapHint[Options](h) } +func WithHintForCoords(coords *maven.Coordinates) Option { + if coords.IsPackage() { + return WithHint(coords.GAV()) + } + return optionutils.NoOption[*Options]{} +} + func WithGlobalAccess(a cpi.AccessSpec) Option { return api.WrapGlobalAccess[Options](a) } diff --git a/pkg/contexts/ocm/elements/artifactblob/mavenblob/resource.go b/pkg/contexts/ocm/elements/artifactblob/mavenblob/resource.go index c977c55ad0..162b5f8fdd 100644 --- a/pkg/contexts/ocm/elements/artifactblob/mavenblob/resource.go +++ b/pkg/contexts/ocm/elements/artifactblob/mavenblob/resource.go @@ -15,6 +15,9 @@ const TYPE = resourcetypes.MAVEN_ARTIFACT func Access[M any, P compdesc.ArtifactMetaPointer[M]](ctx ocm.Context, meta P, repo *maven.Repository, groupId, artifactId, version string, opts ...Option) cpi.ArtifactAccess[M] { eff := optionutils.EvalOptions(optionutils.WithDefaults(opts, WithCredentialContext(ctx))...) + if eff.Blob.IsPackage() && eff.Hint == "" { + eff.Hint = maven.NewCoordinates(groupId, artifactId, version).GAV() + } if meta.GetType() == "" { meta.SetType(TYPE) diff --git a/pkg/maven/access.go b/pkg/maven/access.go index 3fc972b83e..54310df693 100644 --- a/pkg/maven/access.go +++ b/pkg/maven/access.go @@ -43,7 +43,7 @@ func NewFileRepository(path string, fss ...vfs.FileSystem) *Repository { } func NewUrlRepository(repoUrl string, fss ...vfs.FileSystem) (*Repository, error) { - u, err := url.Parse(repoUrl) + u, err := url.ParseRequestURI(repoUrl) if err != nil { return nil, err } diff --git a/pkg/maven/coordinates.go b/pkg/maven/coordinates.go index fa1767ba4e..063b424b24 100644 --- a/pkg/maven/coordinates.go +++ b/pkg/maven/coordinates.go @@ -24,7 +24,7 @@ func WithOptionalClassifier(c *string) CoordinateOption { if c != nil { return WithClassifier(*c) } - return nil + return &optionutils.NoOption[*Coordinates]{} } func (o WithClassifier) ApplyTo(c *Coordinates) { @@ -37,57 +37,113 @@ func WithOptionalExtension(e *string) CoordinateOption { if e != nil { return WithExtension(*e) } - return nil + return &optionutils.NoOption[*Coordinates]{} } func (o WithExtension) ApplyTo(c *Coordinates) { c.Extension = optionutils.PointerTo(string(o)) } -// Coordinates holds the typical Maven coordinates groupId, artifactId, version. Optional also classifier and extension. -// https://maven.apache.org/ref/3.9.6/maven-core/artifact-handlers.html -type Coordinates struct { - // GroupId of the Maven artifact. - GroupId string `json:"groupId"` - // ArtifactId of the Maven artifact. - ArtifactId string `json:"artifactId"` - // Version of the Maven artifact. - Version string `json:"version"` +type FileCoordinates struct { // Classifier of the Maven artifact. Classifier *string `json:"classifier,omitempty"` // Extension of the Maven artifact. Extension *string `json:"extension,omitempty"` } -func NewCoordinates(groupId, artifactId, version string, opts ...CoordinateOption) *Coordinates { - c := &Coordinates{ - GroupId: groupId, - ArtifactId: artifactId, - Version: version, +// IsPackage returns true if the complete GAV content is addressed. +func (c *FileCoordinates) IsPackage() bool { + return c.Classifier == nil && c.Extension == nil +} + +// IsFile returns true if a dedicated single file is addressed. +func (c *FileCoordinates) IsFile() bool { + return c.Classifier != nil && c.Extension != nil +} + +// IsFileSet returns true if a file pattern is specified (and therefore, potentially multiple files are addressed). +func (c *FileCoordinates) IsFileSet() bool { + return c.IsPackage() || !c.IsFile() +} + +// MimeType returns the MIME type of the Maven Coordinates based on the file extension. +// Default is application/x-tgz. +func (c *FileCoordinates) MimeType() string { + if c.Extension != nil && c.Classifier != nil { + m := mime.TypeByExtension("." + optionutils.AsValue(c.Extension)) + if m != "" { + return m + } + return ocmmime.MIME_OCTET } - optionutils.ApplyOptions(c, opts...) - return c + return ocmmime.MIME_TGZ +} + +type PackageCoordinates struct { + // GroupId of the Maven artifact. + GroupId string `json:"groupId"` + // ArtifactId of the Maven artifact. + ArtifactId string `json:"artifactId"` + // Version of the Maven artifact. + Version string `json:"version"` } // GAV returns the GAV coordinates of the Maven Coordinates. -func (c *Coordinates) GAV() string { +func (c *PackageCoordinates) GAV() string { return c.GroupId + ":" + c.ArtifactId + ":" + c.Version } -// String returns the Coordinates as a string (GroupId:ArtifactId:Version:WithClassifier:WithExtension). -func (c *Coordinates) String() string { - return c.GroupId + ":" + c.ArtifactId + ":" + c.Version + ":" + optionutils.AsValue(c.Classifier) + ":" + optionutils.AsValue(c.Extension) +func (c *PackageCoordinates) String() string { + return c.GAV() } // GavPath returns the Maven repository path. -func (c *Coordinates) GavPath() string { +func (c *PackageCoordinates) GavPath() string { return c.GroupPath() + "/" + c.ArtifactId + "/" + c.Version } -func (c *Coordinates) GavLocation(repo *Repository) *Location { +func (c *PackageCoordinates) GavLocation(repo *Repository) *Location { return repo.AddPath(c.GavPath()) } +// GroupPath returns GroupId with `/` instead of `.`. +func (c *PackageCoordinates) GroupPath() string { + return strings.ReplaceAll(c.GroupId, ".", "/") +} + +func (c *PackageCoordinates) FileNamePrefix() string { + return c.ArtifactId + "-" + c.Version +} + +// Purl returns the Package URL of the Maven Coordinates. +func (c *PackageCoordinates) Purl() string { + return "pkg:maven/" + c.GroupId + "/" + c.ArtifactId + "@" + c.Version +} + +// Coordinates holds the typical Maven coordinates groupId, artifactId, version. Optional also classifier and extension. +// https://maven.apache.org/ref/3.9.6/maven-core/artifact-handlers.html +type Coordinates struct { + PackageCoordinates `json:",inline"` + FileCoordinates `json:",inline"` +} + +func NewCoordinates(groupId, artifactId, version string, opts ...CoordinateOption) *Coordinates { + c := &Coordinates{ + PackageCoordinates: PackageCoordinates{ + GroupId: groupId, + ArtifactId: artifactId, + Version: version, + }, + } + optionutils.ApplyOptions(c, opts...) + return c +} + +// String returns the Coordinates as a string (GroupId:ArtifactId:Version:WithClassifier:WithExtension). +func (c *Coordinates) String() string { + return c.GroupId + ":" + c.ArtifactId + ":" + c.Version + ":" + optionutils.AsValue(c.Classifier) + ":" + optionutils.AsValue(c.Extension) +} + func (c *Coordinates) FileName() string { file := c.FileNamePrefix() if optionutils.AsValue(c.Classifier) != "" { @@ -112,20 +168,6 @@ func (c *Coordinates) Location(repo *Repository) *Location { return repo.AddPath(c.FilePath()) } -// GroupPath returns GroupId with `/` instead of `.`. -func (c *Coordinates) GroupPath() string { - return strings.ReplaceAll(c.GroupId, ".", "/") -} - -func (c *Coordinates) FileNamePrefix() string { - return c.ArtifactId + "-" + c.Version -} - -// Purl returns the Package URL of the Maven Coordinates. -func (c *Coordinates) Purl() string { - return "pkg:maven/" + c.GroupId + "/" + c.ArtifactId + "@" + c.Version -} - // SetClassifierExtensionBy extracts the classifier and extension from the filename (without any path prefix). func (c *Coordinates) SetClassifierExtensionBy(filename string) error { s := strings.TrimPrefix(path.Base(filename), c.FileNamePrefix()) @@ -144,19 +186,6 @@ func (c *Coordinates) SetClassifierExtensionBy(filename string) error { return nil } -// MimeType returns the MIME type of the Maven Coordinates based on the file extension. -// Default is application/x-tgz. -func (c *Coordinates) MimeType() string { - if c.Extension != nil && c.Classifier != nil { - m := mime.TypeByExtension("." + optionutils.AsValue(c.Extension)) - if m != "" { - return m - } - return ocmmime.MIME_OCTET - } - return ocmmime.MIME_TGZ -} - // Copy creates a new Coordinates with the same values. func (c *Coordinates) Copy() *Coordinates { return generics.Pointer(*c) @@ -193,11 +222,7 @@ func Parse(serializedArtifact string) (*Coordinates, error) { if len(parts) < 3 { return nil, fmt.Errorf("invalid coordination string: %s", serializedArtifact) } - coords := &Coordinates{ - GroupId: parts[0], - ArtifactId: parts[1], - Version: parts[2], - } + coords := NewCoordinates(parts[0], parts[1], parts[2]) if len(parts) >= 4 { coords.Classifier = optionutils.PointerTo(parts[3]) } diff --git a/pkg/maven/maventest/const.go b/pkg/maven/maventest/const.go index 1e80a4db00..407ca55322 100644 --- a/pkg/maven/maventest/const.go +++ b/pkg/maven/maventest/const.go @@ -1,6 +1,10 @@ package maventest const ( + GROUP_ID = "com.sap.cloud.sdk" + ARTIFACT_ID = "sdk-modules-bom" + VERSION = "5.7.0" + ARTIFACT_SIZE = 1504 ARTIFACT_DIGEST = "dc5b38b58fd18cb0336c2e0deebeb5d2277c34312ae7024074812f34acfebc65" //nolint: gosec // yes )