diff --git a/internal/artifacts/manifest.go b/internal/artifacts/manifest.go index 9b74df6f1..5b7000d32 100644 --- a/internal/artifacts/manifest.go +++ b/internal/artifacts/manifest.go @@ -63,9 +63,45 @@ func setManifestDesc(source dir.ISourceModule, ep dir.ITargetArtifacts, targetPa } entries = append(entries, resourcesEntries...) + // Module entries that point to the same path should be merged in the manifest + entries = mergeDuplicateEntries(entries) + return genManifest(ep.GetManifestPath(), entries) } +func mergeDuplicateEntries(entries []entry) []entry { + // Several MTA-Module entries can point to the same path. In that case, their names should in the same entry, comma-separated. + mergedEntries := make([]entry, 0) + modules := make(map[string]entry) + // To keep a consistent sort order for the map entries we must keep another data structure (slice of keys by order of addition here) + pathsOrder := make([]string, 0) + + // Add module entries to modules. Add non-module entries to mergedEntries. + for index, entry := range entries { + if entry.EntryType == moduleEntry { + if existing, ok := modules[entry.EntryPath]; ok { + existing.EntryName += ", " + entry.EntryName + modules[entry.EntryPath] = existing + } else { + modules[entry.EntryPath] = entries[index] + pathsOrder = append(pathsOrder, entry.EntryPath) + } + } else { + mergedEntries = append(mergedEntries, entry) + } + } + + // Sort module entries by order of insertion + moduleEntries := make([]entry, 0) + for _, path := range pathsOrder { + moduleEntries = append(moduleEntries, modules[path]) + } + + // Add the module entries first to the merged entries + mergedEntries = append(moduleEntries, mergedEntries...) + return mergedEntries +} + func addModuleEntry(entries []entry, module *mta.Module, contentType, modulePath string) []entry { result := entries diff --git a/internal/artifacts/manifest_test.go b/internal/artifacts/manifest_test.go index 3dfaf4c6c..25d7f2857 100644 --- a/internal/artifacts/manifest_test.go +++ b/internal/artifacts/manifest_test.go @@ -2,20 +2,21 @@ package artifacts import ( "fmt" - "github.com/SAP/cloud-mta-build-tool/internal/buildops" "os" + "strings" "text/template" - "github.com/SAP/cloud-mta/mta" . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/extensions/table" . "github.com/onsi/gomega" "github.com/pkg/errors" "github.com/SAP/cloud-mta-build-tool/internal/archive" + "github.com/SAP/cloud-mta-build-tool/internal/buildops" "github.com/SAP/cloud-mta-build-tool/internal/commands" "github.com/SAP/cloud-mta-build-tool/internal/conttype" "github.com/SAP/cloud-mta-build-tool/internal/version" - "strings" + "github.com/SAP/cloud-mta/mta" ) var _ = Describe("manifest", func() { @@ -336,6 +337,50 @@ bad config }) }) + + DescribeTable("mergeDuplicateEntries", func(entries []entry, expected []entry) { + actual := mergeDuplicateEntries(entries) + Ω(actual).Should(Equal(expected)) + }, + Entry("returns non-module entries unchanged", []entry{ + {EntryName: "e1", EntryPath: "a", EntryType: resourceEntry, ContentType: "t"}, + {EntryName: "e2", EntryPath: "a", EntryType: requiredEntry, ContentType: "t"}, + {EntryName: "e3", EntryPath: "b", EntryType: resourceEntry, ContentType: "t"}, + {EntryName: "e4", EntryPath: "b", EntryType: resourceEntry, ContentType: "t"}, + }, []entry{ + {EntryName: "e1", EntryPath: "a", EntryType: resourceEntry, ContentType: "t"}, + {EntryName: "e2", EntryPath: "a", EntryType: requiredEntry, ContentType: "t"}, + {EntryName: "e3", EntryPath: "b", EntryType: resourceEntry, ContentType: "t"}, + {EntryName: "e4", EntryPath: "b", EntryType: resourceEntry, ContentType: "t"}, + }, + ), + Entry("merges module entries with the same path and keeps the modules order", []entry{ + {EntryName: "e1", EntryPath: "a", EntryType: moduleEntry, ContentType: "t1"}, + {EntryName: "e2", EntryPath: "a", EntryType: moduleEntry, ContentType: "t2"}, + {EntryName: "e3", EntryPath: "a", EntryType: moduleEntry, ContentType: "t3"}, + {EntryName: "e4", EntryPath: "b", EntryType: moduleEntry, ContentType: "t4"}, + {EntryName: "e5", EntryPath: "b", EntryType: moduleEntry, ContentType: "t5"}, + {EntryName: "e6", EntryPath: "c", EntryType: moduleEntry, ContentType: "t6"}, + }, []entry{ + {EntryName: "e1, e2, e3", EntryPath: "a", EntryType: moduleEntry, ContentType: "t1"}, + {EntryName: "e4, e5", EntryPath: "b", EntryType: moduleEntry, ContentType: "t4"}, + {EntryName: "e6", EntryPath: "c", EntryType: moduleEntry, ContentType: "t6"}, + }, + ), + Entry("merges module entries and keeps non-module entries unchanged at the end", []entry{ + {EntryName: "e1", EntryPath: "a", EntryType: resourceEntry, ContentType: "t1"}, + {EntryName: "e2", EntryPath: "a", EntryType: moduleEntry, ContentType: "t2"}, + {EntryName: "e3", EntryPath: "a", EntryType: moduleEntry, ContentType: "t3"}, + {EntryName: "e4", EntryPath: "b", EntryType: moduleEntry, ContentType: "t4"}, + {EntryName: "e5", EntryPath: "b", EntryType: requiredEntry, ContentType: "t5"}, + }, []entry{ + {EntryName: "e2, e3", EntryPath: "a", EntryType: moduleEntry, ContentType: "t2"}, + {EntryName: "e4", EntryPath: "b", EntryType: moduleEntry, ContentType: "t4"}, + {EntryName: "e1", EntryPath: "a", EntryType: resourceEntry, ContentType: "t1"}, + {EntryName: "e5", EntryPath: "b", EntryType: requiredEntry, ContentType: "t5"}, + }, + ), + ) }) type testWriter struct { diff --git a/internal/artifacts/testdata/assembly/golden.mf b/internal/artifacts/testdata/assembly/golden.mf index f57620e9e..26e024410 100644 --- a/internal/artifacts/testdata/assembly/golden.mf +++ b/internal/artifacts/testdata/assembly/golden.mf @@ -2,7 +2,7 @@ manifest-Version: 1.0 Created-By: SAP Application Archive Builder {{cli_version}} Name: folder-with-archive/data.jar -MTA-Module: m1 +MTA-Module: m1, m12 Content-Type: application/zip Name: data.zip @@ -30,7 +30,7 @@ MTA-Module: m9 Content-Type: text/directory Name: folder2 -MTA-Module: m10 +MTA-Module: m10, m11 Content-Type: text/directory Name: META-INF/mtad.yaml diff --git a/internal/artifacts/testdata/assembly/mtad.yaml b/internal/artifacts/testdata/assembly/mtad.yaml index 0c3fa1788..61cf759b1 100644 --- a/internal/artifacts/testdata/assembly/mtad.yaml +++ b/internal/artifacts/testdata/assembly/mtad.yaml @@ -42,4 +42,12 @@ modules: path: folder1/folder11 - name: m10 type: javascript.nodejs - path: folder2 \ No newline at end of file + path: folder2 +# path is to the same folder as another module + - name: m11 + type: java + path: folder2 +# path is to the same file as another file + - name: m12 + type: javascript.nodejs + path: folder-with-archive/data.jar \ No newline at end of file