From 3d97b8b3489512dfca80b29589d624b02c346acf Mon Sep 17 00:00:00 2001 From: Bartosz Spyrko-Smietanko Date: Wed, 11 Oct 2023 11:13:03 +0100 Subject: [PATCH] Persist manifest name and add channel versions command --- pom.xml | 2 +- .../org/wildfly/prospero/cli/CliMain.java | 1 + .../org/wildfly/prospero/cli/CliMessages.java | 4 ++ .../prospero/cli/commands/ChannelCommand.java | 42 +++++++++++++++ .../prospero/cli/commands/CliConstants.java | 2 + .../main/resources/UsageMessages.properties | 2 + .../cli/commands/ChannelCommandTest.java | 9 ++++ .../prospero/actions/MetadataAction.java | 5 ++ .../prospero/api/InstallationMetadata.java | 2 +- .../spi/ProsperoInstallationManager.java | 17 ++++++ .../metadata/ManifestVersionRecord.java | 52 +++++++++++++++++-- .../metadata/ManifestVersionResolver.java | 44 ++++++++++++++-- .../metadata/ManifestVersionResolverTest.java | 51 +++++++++++++++++- 13 files changed, 223 insertions(+), 10 deletions(-) diff --git a/pom.xml b/pom.xml index 804490973..f2ff81db6 100644 --- a/pom.xml +++ b/pom.xml @@ -60,7 +60,7 @@ 3.8.10.Final 1.6.0.Final 6.4.3.Final - 1.0.1.Final + 1.0.2.Final 2.3.1.Final 5.3.0 2.0.7 diff --git a/prospero-cli/src/main/java/org/wildfly/prospero/cli/CliMain.java b/prospero-cli/src/main/java/org/wildfly/prospero/cli/CliMain.java index 2c4081be5..dfca7bbdf 100644 --- a/prospero-cli/src/main/java/org/wildfly/prospero/cli/CliMain.java +++ b/prospero-cli/src/main/java/org/wildfly/prospero/cli/CliMain.java @@ -89,6 +89,7 @@ public static CommandLine createCommandLine(CliConsole console, String[] args, A channelCmd.addSubcommand(new ChannelAddCommand(console, actionFactory)); channelCmd.addSubcommand(new ChannelRemoveCommand(console, actionFactory)); channelCmd.addSubcommand(new ChannelCommand.ChannelListCommand(console, actionFactory)); + channelCmd.addSubcommand(new ChannelCommand.ChannelVersionCommand(console, actionFactory)); channelCmd.addSubcommand(new ChannelInitializeCommand(console, actionFactory)); channelCmd.addSubcommand(new ChannelPromoteCommand(console, actionFactory)); diff --git a/prospero-cli/src/main/java/org/wildfly/prospero/cli/CliMessages.java b/prospero-cli/src/main/java/org/wildfly/prospero/cli/CliMessages.java index aba2e89f7..ee3d5657a 100644 --- a/prospero-cli/src/main/java/org/wildfly/prospero/cli/CliMessages.java +++ b/prospero-cli/src/main/java/org/wildfly/prospero/cli/CliMessages.java @@ -623,4 +623,8 @@ default String quitGenerating() { default String metadataExistsAlready(Path path, String distName) { return format(bundle.getString("prospero.update.subscribe.meta.exists"), path, distName); } + + default String serverVersionsHeader() { + return bundle.getString("prospero.channels.versions.header"); + } } diff --git a/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/ChannelCommand.java b/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/ChannelCommand.java index c443bf824..6d2a00c11 100644 --- a/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/ChannelCommand.java +++ b/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/ChannelCommand.java @@ -28,6 +28,7 @@ import org.wildfly.prospero.cli.CliMessages; import org.wildfly.prospero.cli.ReturnCodes; import org.wildfly.prospero.cli.printers.ChannelPrinter; +import org.wildfly.prospero.metadata.ManifestVersionRecord; import picocli.CommandLine; @CommandLine.Command(name = CliConstants.Commands.CHANNEL) @@ -78,5 +79,46 @@ public Integer call() throws Exception { } } + @CommandLine.Command(name = CliConstants.Commands.VERSIONS) + public static class ChannelVersionCommand extends AbstractCommand { + + protected static final String PREFIX = " * "; + @CommandLine.Option(names = CliConstants.DIR) + private Optional directory; + + public ChannelVersionCommand(CliConsole console, ActionFactory actionFactory) { + super(console, actionFactory); + } + + @Override + public Integer call() throws Exception { + final Path installationDir = determineInstallationDirectory(directory); + + console.println(CliMessages.MESSAGES.serverVersionsHeader()); + try (MetadataAction metadataAction = actionFactory.metadataActions(installationDir)) { + final ManifestVersionRecord channelVersions = metadataAction.getChannelVersions(); + for (ManifestVersionRecord.MavenManifest mavenManifest : channelVersions.getMavenManifests()) { + if (mavenManifest.getDescription() != null) { + console.println(PREFIX + mavenManifest.getDescription()); + } else { + console.println(PREFIX + buildManifestGav(mavenManifest)); + } + } + for (ManifestVersionRecord.UrlManifest urlManifest : channelVersions.getUrlManifests()) { + if (urlManifest.getDescription() != null) { + console.println(PREFIX + urlManifest.getDescription()); + } else { + console.println(PREFIX + String.format("%s [%s]", urlManifest.getUrl(), urlManifest.getHash())); + } + } + } + return ReturnCodes.SUCCESS; + } + + private static String buildManifestGav(ManifestVersionRecord.MavenManifest mavenManifest) { + return String.format("%s:%s [%s]", mavenManifest.getGroupId(), mavenManifest.getArtifactId(), mavenManifest.getVersion()); + } + } + } diff --git a/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/CliConstants.java b/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/CliConstants.java index 439520ff6..8c4c1edec 100644 --- a/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/CliConstants.java +++ b/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/CliConstants.java @@ -31,6 +31,8 @@ private CliConstants() { public static final class Commands { + protected static final String VERSIONS = "versions"; + private Commands() { } diff --git a/prospero-cli/src/main/resources/UsageMessages.properties b/prospero-cli/src/main/resources/UsageMessages.properties index 635fb964e..97b26135d 100644 --- a/prospero-cli/src/main/resources/UsageMessages.properties +++ b/prospero-cli/src/main/resources/UsageMessages.properties @@ -80,6 +80,7 @@ ${prospero.dist.name}.channel.list.usage.header = Lists the channels used by t ${prospero.dist.name}.channel.remove.usage.header = Unsubscribes the installation from a channel. ${prospero.dist.name}.channel.initialize.usage.header = Add a custom channel to be used by the server ${prospero.dist.name}.channel.promote.usage.header = Promote a bundle of artifacts to a custom repository +${prospero.dist.name}.channel.versions.usage.header = Displays currently used versions of manifests from registered channels. ${prospero.dist.name}.clone.usage.header = Exports installation details required to recreate a server. ${prospero.dist.name}.clone.export.usage.header = Exports the installation details that can be used to recreate a server. @@ -299,6 +300,7 @@ prospero.export.done=Export complete prospero.channels.list.header=Server %s is subscribed to following channels:%n prospero.channels.add.header=Subscribing %s to channel %s%n +prospero.channels.versions.header=Installed server components: prospero.channels.added=Channel '%s' added. prospero.channels.remove.header=Unsubscribing %s from channel %s%n prospero.channels.removed=Channel '%s' removed. diff --git a/prospero-cli/src/test/java/org/wildfly/prospero/cli/commands/ChannelCommandTest.java b/prospero-cli/src/test/java/org/wildfly/prospero/cli/commands/ChannelCommandTest.java index c813dfa43..d70fb5aeb 100644 --- a/prospero-cli/src/test/java/org/wildfly/prospero/cli/commands/ChannelCommandTest.java +++ b/prospero-cli/src/test/java/org/wildfly/prospero/cli/commands/ChannelCommandTest.java @@ -77,6 +77,15 @@ public void testListInvalidInstallationDir() { .getMessage())); } + @Test + public void testVersionInvalidInstallationDir() { + int exitCode = commandLine.execute(CliConstants.Commands.CHANNEL, CliConstants.Commands.VERSIONS); + + Assert.assertEquals(ReturnCodes.INVALID_ARGUMENTS, exitCode); + assertTrue(getErrorOutput().contains(CliMessages.MESSAGES.invalidInstallationDir(ChannelCommand.currentDir()) + .getMessage())); + } + @Test public void testAddEmptyRepository() { int exitCode = commandLine.execute(CliConstants.Commands.CHANNEL, CliConstants.Commands.ADD, diff --git a/prospero-common/src/main/java/org/wildfly/prospero/actions/MetadataAction.java b/prospero-common/src/main/java/org/wildfly/prospero/actions/MetadataAction.java index 2dffe07b8..058acae8b 100644 --- a/prospero-common/src/main/java/org/wildfly/prospero/actions/MetadataAction.java +++ b/prospero-common/src/main/java/org/wildfly/prospero/actions/MetadataAction.java @@ -26,6 +26,7 @@ import org.wildfly.prospero.ProsperoLogger; import org.wildfly.prospero.api.InstallationMetadata; import org.wildfly.prospero.api.exceptions.MetadataException; +import org.wildfly.prospero.metadata.ManifestVersionRecord; import org.wildfly.prospero.model.ProsperoConfig; /** @@ -90,6 +91,10 @@ public List getChannels() throws MetadataException { return new ArrayList<>(installationMetadata.getProsperoConfig().getChannels()); } + public ManifestVersionRecord getChannelVersions() { + return installationMetadata.getManifestVersions().orElse(new ManifestVersionRecord()); + } + @Override public void close() { this.installationMetadata.close(); diff --git a/prospero-common/src/main/java/org/wildfly/prospero/api/InstallationMetadata.java b/prospero-common/src/main/java/org/wildfly/prospero/api/InstallationMetadata.java index 540624eef..4a8f5daa9 100644 --- a/prospero-common/src/main/java/org/wildfly/prospero/api/InstallationMetadata.java +++ b/prospero-common/src/main/java/org/wildfly/prospero/api/InstallationMetadata.java @@ -394,7 +394,7 @@ public void updateProsperoConfig(ProsperoConfig config) throws MetadataException gitStorage.recordConfigChange(); } - public Optional getManifestVersions() throws IOException { + public Optional getManifestVersions() { return manifestVersion; } diff --git a/prospero-common/src/main/java/org/wildfly/prospero/spi/ProsperoInstallationManager.java b/prospero-common/src/main/java/org/wildfly/prospero/spi/ProsperoInstallationManager.java index e1e644257..b528f8931 100644 --- a/prospero-common/src/main/java/org/wildfly/prospero/spi/ProsperoInstallationManager.java +++ b/prospero-common/src/main/java/org/wildfly/prospero/spi/ProsperoInstallationManager.java @@ -9,6 +9,7 @@ import org.wildfly.installationmanager.ChannelChange; import org.wildfly.installationmanager.HistoryResult; import org.wildfly.installationmanager.InstallationChanges; +import org.wildfly.installationmanager.ManifestVersion; import org.wildfly.installationmanager.MavenOptions; import org.wildfly.installationmanager.OperationNotAvailableException; import org.wildfly.installationmanager.Repository; @@ -21,6 +22,7 @@ import org.wildfly.prospero.actions.UpdateAction; import org.wildfly.prospero.api.MavenOptions.Builder; import org.wildfly.prospero.galleon.GalleonCallbackAdapter; +import org.wildfly.prospero.metadata.ManifestVersionRecord; import org.wildfly.prospero.spi.internal.CliProvider; import org.wildfly.prospero.api.SavedState; import org.wildfly.prospero.api.exceptions.MetadataException; @@ -41,6 +43,7 @@ import java.util.ServiceLoader; import java.util.function.Function; import java.util.stream.Collectors; +import java.util.stream.Stream; public class ProsperoInstallationManager implements InstallationManager { @@ -215,6 +218,20 @@ public String generateApplyRevertCommand(Path scriptHome, Path candidatePath, Os return escape(scriptHome.resolve(cliProvider.getScriptName(shell))) + " " + cliProvider.getApplyRevertCommand(installationDir, candidatePath); } + @Override + public Collection getInstalledVersions() throws MetadataException { + try (MetadataAction metadataAction = actionFactory.getMetadataAction()) { + final ManifestVersionRecord versionRecord = metadataAction.getChannelVersions(); + return Stream.concat( + versionRecord.getMavenManifests().stream() + .map(m->new ManifestVersion(m.getGroupId()+":"+m.getArtifactId(), m.getDescription(), m.getVersion(), ManifestVersion.Type.MAVEN)), + versionRecord.getUrlManifests().stream() + .map(m->new ManifestVersion(m.getUrl(), m.getDescription(), m.getHash(), ManifestVersion.Type.URL)) + ) + .collect(Collectors.toList()); + } + } + private String escape(Path absolutePath) { return "\"" + absolutePath.toString() + "\""; } diff --git a/prospero-metadata/src/main/java/org/wildfly/prospero/metadata/ManifestVersionRecord.java b/prospero-metadata/src/main/java/org/wildfly/prospero/metadata/ManifestVersionRecord.java index 71a7fa8ff..c97c6192d 100644 --- a/prospero-metadata/src/main/java/org/wildfly/prospero/metadata/ManifestVersionRecord.java +++ b/prospero-metadata/src/main/java/org/wildfly/prospero/metadata/ManifestVersionRecord.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.ObjectMapper; @@ -33,19 +34,32 @@ import java.util.List; import java.util.Optional; +@JsonIgnoreProperties(ignoreUnknown = true) public class ManifestVersionRecord { + @JsonIgnoreProperties(ignoreUnknown = true) public static class MavenManifest { + private final String description; private String groupId; private String artifactId; private String version; + + @Deprecated + public MavenManifest(String groupId, + String artifactId, + String version) { + this(groupId, artifactId, version, null); + } + public MavenManifest(@JsonProperty("groupId") String groupId, @JsonProperty("artifactId") String artifactId, - @JsonProperty("version") String version) { + @JsonProperty("version") String version, + @JsonProperty(value = "description", required = false) String description) { this.groupId = groupId; this.artifactId = artifactId; this.version = version; + this.description = description; } public String getGroupId() { @@ -59,6 +73,12 @@ public String getArtifactId() { public String getVersion() { return version; } + + @JsonInclude(JsonInclude.Include.NON_NULL) + public String getDescription() { + return description; + } + @JsonIgnore public String getSummary() { return String.format("[%s:%s::%s]", groupId, artifactId, version); @@ -66,13 +86,24 @@ public String getSummary() { } + @JsonIgnoreProperties(ignoreUnknown = true) public static class UrlManifest { private String url; private String hash; - public UrlManifest(@JsonProperty("url") String url, @JsonProperty("hash") String hash) { + private String description; + + @Deprecated + public UrlManifest(String url, String hash) { + this.url = url; + this.hash = hash; + this.description = null; + } + + public UrlManifest(@JsonProperty("url") String url, @JsonProperty("hash") String hash, @JsonProperty("description") String description) { this.url = url; this.hash = hash; + this.description = description; } public String getUrl() { @@ -83,6 +114,11 @@ public String getHash() { return hash; } + @JsonInclude(JsonInclude.Include.NON_NULL) + public String getDescription() { + return description; + } + @JsonIgnore public String getSummary() { return String.format("[%s::%s]", url, hash); @@ -90,6 +126,7 @@ public String getSummary() { } + @JsonIgnoreProperties(ignoreUnknown = true) public static class NoManifest { private List repos; @@ -114,21 +151,26 @@ public String getSummary() { } } + + private String schemaVersion; private List mavenManifests = new ArrayList<>(); private List urlManifests = new ArrayList<>(); private List noManifests = new ArrayList<>(); @JsonCreator - public ManifestVersionRecord(@JsonProperty("maven") List mavenManifests, + public ManifestVersionRecord(@JsonProperty("schemaVersion") String schemaVersion, + @JsonProperty("maven") List mavenManifests, @JsonProperty("url") List urlManifests, @JsonProperty("open") List noManifests) { + this.schemaVersion = schemaVersion; this.mavenManifests = mavenManifests==null?Collections.emptyList():mavenManifests; this.urlManifests = urlManifests==null?Collections.emptyList():urlManifests; this.noManifests = noManifests==null?Collections.emptyList():noManifests; } public ManifestVersionRecord() { + this.schemaVersion = "1.0.0"; } @JsonProperty("maven") @@ -149,6 +191,10 @@ public List getOpenManifests() { return noManifests; } + public String getSchemaVersion() { + return schemaVersion; + } + public void addManifest(MavenManifest manifest) { mavenManifests.add(manifest); } diff --git a/prospero-metadata/src/main/java/org/wildfly/prospero/metadata/ManifestVersionResolver.java b/prospero-metadata/src/main/java/org/wildfly/prospero/metadata/ManifestVersionResolver.java index ec5483ad6..38e927c03 100644 --- a/prospero-metadata/src/main/java/org/wildfly/prospero/metadata/ManifestVersionResolver.java +++ b/prospero-metadata/src/main/java/org/wildfly/prospero/metadata/ManifestVersionResolver.java @@ -22,8 +22,11 @@ import org.eclipse.aether.RepositorySystem; import org.eclipse.aether.repository.LocalRepository; import org.jboss.galleon.util.HashUtils; +import org.jboss.logging.Logger; import org.wildfly.channel.Channel; +import org.wildfly.channel.ChannelManifest; import org.wildfly.channel.ChannelManifestCoordinate; +import org.wildfly.channel.ChannelManifestMapper; import org.wildfly.channel.Repository; import org.wildfly.channel.maven.VersionResolverFactory; import org.wildfly.channel.spi.MavenVersionsResolver; @@ -48,6 +51,7 @@ * for open manifests it's list of repositories + strategy. */ public class ManifestVersionResolver { + private static final Logger LOG = Logger.getLogger(ManifestVersionResolver.class.getName()); private final VersionResolverFactory resolverFactory; @@ -89,19 +93,53 @@ public ManifestVersionRecord getCurrentVersions(List channels) throws I } else if (manifestCoordinate.getUrl() != null) { final String content = read(manifestCoordinate.getUrl()); final String hashCode = HashUtils.hash(content); - manifestVersionRecord.addManifest(new ManifestVersionRecord.UrlManifest(manifestCoordinate.getUrl().toExternalForm(), hashCode)); + final ChannelManifest manifest = ChannelManifestMapper.from(manifestCoordinate.getUrl()); + manifestVersionRecord.addManifest(new ManifestVersionRecord.UrlManifest(manifestCoordinate.getUrl().toExternalForm(), hashCode, manifest.getName())); } else if (manifestCoordinate.getVersion() != null) { - manifestVersionRecord.addManifest(new ManifestVersionRecord.MavenManifest(manifestCoordinate.getGroupId(), manifestCoordinate.getArtifactId(), manifestCoordinate.getVersion())); + final String description = getManifestDescription(manifestCoordinate, resolverFactory.create(channel.getRepositories())); + manifestVersionRecord.addManifest(new ManifestVersionRecord.MavenManifest( + manifestCoordinate.getGroupId(), + manifestCoordinate.getArtifactId(), + manifestCoordinate.getVersion(), + description)); } else { final MavenVersionsResolver mavenVersionsResolver = resolverFactory.create(channel.getRepositories()); final Optional latestVersion = VersionMatcher.getLatestVersion(mavenVersionsResolver.getAllVersions(manifestCoordinate.getGroupId(), manifestCoordinate.getArtifactId(), manifestCoordinate.getExtension(), manifestCoordinate.getClassifier())); - manifestVersionRecord.addManifest(new ManifestVersionRecord.MavenManifest(manifestCoordinate.getGroupId(), manifestCoordinate.getArtifactId(), latestVersion.get())); + if (latestVersion.isPresent()) { + final String description = getManifestDescription(new ChannelManifestCoordinate( + manifestCoordinate.getGroupId(), manifestCoordinate.getArtifactId(), latestVersion.get() + ), mavenVersionsResolver); + manifestVersionRecord.addManifest(new ManifestVersionRecord.MavenManifest( + manifestCoordinate.getGroupId(), + manifestCoordinate.getArtifactId(), + latestVersion.get(), + description)); + } else { + LOG.warn("Unable to determine version of manifest used: " + manifestCoordinate); + manifestVersionRecord.addManifest(new ManifestVersionRecord.MavenManifest( + manifestCoordinate.getGroupId(), + manifestCoordinate.getArtifactId(), + "", + null)); + } } } return manifestVersionRecord; } + private String getManifestDescription(ChannelManifestCoordinate manifestCoordinate, MavenVersionsResolver mavenVersionsResolver) { + final List urls = mavenVersionsResolver.resolveChannelMetadata(List.of(manifestCoordinate)); + final String description; + if (!urls.isEmpty()) { + final ChannelManifest manifest = ChannelManifestMapper.from(urls.get(0)); + description = manifest.getName(); + } else { + description = null; + } + return description; + } + private String read(URL url) throws IOException { try(InputStream inputStream = url.openStream(); OutputStream outputStream = new ByteArrayOutputStream()) { diff --git a/prospero-metadata/src/test/java/org/wildfly/prospero/metadata/ManifestVersionResolverTest.java b/prospero-metadata/src/test/java/org/wildfly/prospero/metadata/ManifestVersionResolverTest.java index df848d67b..d2ed097b2 100644 --- a/prospero-metadata/src/test/java/org/wildfly/prospero/metadata/ManifestVersionResolverTest.java +++ b/prospero-metadata/src/test/java/org/wildfly/prospero/metadata/ManifestVersionResolverTest.java @@ -18,6 +18,7 @@ package org.wildfly.prospero.metadata; import org.jboss.galleon.util.HashUtils; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -25,12 +26,16 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.wildfly.channel.Channel; +import org.wildfly.channel.ChannelManifest; import org.wildfly.channel.ChannelManifestCoordinate; +import org.wildfly.channel.ChannelManifestMapper; import org.wildfly.channel.Repository; import org.wildfly.channel.maven.VersionResolverFactory; import org.wildfly.channel.spi.MavenVersionsResolver; +import java.io.File; import java.net.URL; +import java.nio.file.Files; import java.nio.file.Path; import java.util.Collections; import java.util.List; @@ -50,13 +55,23 @@ public class ManifestVersionResolverTest { @Rule public TemporaryFolder temp = new TemporaryFolder(); + @Before + public void setUp() { + when(factory.create(any())).thenReturn(mavenResolver); + } + @Test public void getVersionOfLatestMavenManifest() throws Exception { final ManifestVersionResolver resolver = new ManifestVersionResolver(factory); - when(factory.create(any())).thenReturn(mavenResolver); + final File manifestFile = temp.newFile(); + final URL url = manifestFile.toURI().toURL(); + Files.writeString(manifestFile.toPath(), ChannelManifestMapper.toYaml(new ChannelManifest("test", null, null, Collections.emptyList()))); + when(mavenResolver.getAllVersions("org.test", "test", "yaml", "manifest")) .thenReturn(Set.of("1.0.0", "1.0.1")); + when(mavenResolver.resolveChannelMetadata(any())) + .thenReturn(List.of(url)); final Channel channel = new Channel("test", "", null, Collections.emptyList(), new ChannelManifestCoordinate("org.test", "test"), null, null); @@ -65,6 +80,9 @@ public void getVersionOfLatestMavenManifest() throws Exception { assertThat(currentVersions.getMavenManifests()) .map(ManifestVersionRecord.MavenManifest::getVersion) .containsExactly("1.0.1"); + assertThat(currentVersions.getMavenManifests()) + .map(ManifestVersionRecord.MavenManifest::getDescription) + .containsExactly("test"); assertThat(currentVersions.getOpenManifests()).isEmpty(); assertThat(currentVersions.getUrlManifests()).isEmpty(); } @@ -84,11 +102,37 @@ public void getHardcodedVersionOfManifestIfPresent() throws Exception { assertThat(currentVersions.getUrlManifests()).isEmpty(); } + @Test + public void emptyVersionIfLatestVersionCannotBeFound() throws Exception { + final ManifestVersionResolver resolver = new ManifestVersionResolver(factory); + + when(mavenResolver.getAllVersions("org.test", "test", "yaml", "manifest")) + .thenReturn(Collections.emptySet()); + + final Channel channel = new Channel("test", "", null, Collections.emptyList(), + new ChannelManifestCoordinate("org.test", "test"), null, null); + final ManifestVersionRecord currentVersions = resolver.getCurrentVersions(List.of(channel)); + + assertThat(currentVersions.getMavenManifests()) + .map(ManifestVersionRecord.MavenManifest::getVersion) + .containsExactly(""); + assertThat(currentVersions.getMavenManifests()) + .map(ManifestVersionRecord.MavenManifest::getGroupId) + .containsExactly("org.test"); + assertThat(currentVersions.getMavenManifests()) + .map(ManifestVersionRecord.MavenManifest::getArtifactId) + .containsExactly("test"); + assertThat(currentVersions.getOpenManifests()).isEmpty(); + assertThat(currentVersions.getUrlManifests()).isEmpty(); + } + @Test public void getUrlAndHashOfManifest() throws Exception { final ManifestVersionResolver resolver = new ManifestVersionResolver(factory); - final URL url = temp.newFile().toURI().toURL(); + final File manifestFile = temp.newFile(); + final URL url = manifestFile.toURI().toURL(); + Files.writeString(manifestFile.toPath(), ChannelManifestMapper.toYaml(new ChannelManifest("test", null, null, Collections.emptyList()))); final Channel channel = new Channel("test", "", null, Collections.emptyList(), new ChannelManifestCoordinate(url), null, null); final ManifestVersionRecord currentVersions = resolver.getCurrentVersions(List.of(channel)); @@ -101,6 +145,9 @@ public void getUrlAndHashOfManifest() throws Exception { assertThat(currentVersions.getUrlManifests()) .map(ManifestVersionRecord.UrlManifest::getHash) .containsExactly(HashUtils.hashFile(Path.of(url.toURI()))); + assertThat(currentVersions.getUrlManifests()) + .map(ManifestVersionRecord.UrlManifest::getDescription) + .containsExactly("test"); } @Test