From a223eef4fcf13b19aaf6753cc19ffe14394a1a4b Mon Sep 17 00:00:00 2001 From: Hiepiscus Date: Fri, 21 Aug 2026 21:48:54 +0200 Subject: [PATCH 1/8] #2345: add Linux support for Docker Desktop with version selection --- .../devonfw/tools/ide/tool/docker/Docker.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/docker/Docker.java b/cli/src/main/java/com/devonfw/tools/ide/tool/docker/Docker.java index 46dc0d167e..b0520edf90 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/docker/Docker.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/docker/Docker.java @@ -32,6 +32,8 @@ public class Docker extends GlobalToolCommandlet { private static final Pattern DOCKER_DESKTOP_LINUX_VERSION_PATTERN = Pattern.compile("^([0-9]+(?:\\.[0-9]+){1,2})"); + private static final String EDITION_DOCKER = "docker"; + /** * The constructor. * @@ -83,6 +85,15 @@ protected List getInstallPackageManagerCommands() { VersionIdentifier configuredVersion = getConfiguredVersion(); String resolvedVersion = toolRepository.resolveVersion(this.tool, edition, configuredVersion, this).toString(); + if (EDITION_DOCKER.equals(edition)) { + return getInstallPackageManagerCommandsDockerDesktop(resolvedVersion); + } + + return getInstallPackageManagerCommandsRancherDesktop(resolvedVersion); + } + + private List getInstallPackageManagerCommandsRancherDesktop(String resolvedVersion) { + return List.of(new PackageManagerCommand(NativePackageManager.ZYPPER, List.of( "sudo zypper addrepo https://download.opensuse.org/repositories/isv:/Rancher:/stable/rpm/isv:Rancher:stable.repo", String.format("sudo zypper --no-gpg-checks install rancher-desktop=%s*", resolvedVersion))), @@ -95,6 +106,20 @@ protected List getInstallPackageManagerCommands() { String.format("sudo apt install -y --allow-downgrades rancher-desktop=%s*", resolvedVersion)))); } + private List getInstallPackageManagerCommandsDockerDesktop(String resolvedVersion) { + + return List.of(new PackageManagerCommand(NativePackageManager.APT, List.of( + "sudo install -m 0755 -d /etc/apt/keyrings", + "sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc", + "sudo chmod a+r /etc/apt/keyrings/docker.asc", + "echo \"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc]" + + " https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo \\\"$VERSION_CODENAME\\\") stable\" |" + + " sudo tee /etc/apt/sources.list.d/docker.list > /dev/null", + "sudo apt update", + "curl -fsSL https://desktop.docker.com/linux/main/amd64/docker-desktop-amd64.deb -o /tmp/docker-desktop-amd64.deb", + String.format("sudo apt install -y --allow-downgrades rancher-desktop=%s*", resolvedVersion)))); + } + @Override public VersionIdentifier getInstalledVersion() { From ff0701d234d9b72e78d932f3a5af5ab2ee1a720d Mon Sep 17 00:00:00 2001 From: Hiepiscus Date: Fri, 21 Aug 2026 21:49:50 +0200 Subject: [PATCH 2/8] #2345: fix DockerDesktopUrlUpdater --- .../url/tool/docker/DockerDesktopUrlUpdater.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/docker/DockerDesktopUrlUpdater.java b/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/docker/DockerDesktopUrlUpdater.java index 01417d03e3..70fb6c7a9a 100644 --- a/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/docker/DockerDesktopUrlUpdater.java +++ b/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/docker/DockerDesktopUrlUpdater.java @@ -1,5 +1,6 @@ package com.devonfw.tools.ide.url.tool.docker; + import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -39,17 +40,14 @@ public String getTool() { protected void addVersion(UrlVersion urlVersion) { VersionIdentifier vid = VersionIdentifier.of(urlVersion.getName()); - String version = urlVersion.getName().replaceAll("\\.", ""); - // get Code for version String body = doGetResponseBodyAsString(getVersionUrl()); - String regex = "href=#" + version - // .......1.........................................................2................. - + ".{8,12}(\r\n|\r|\n).{0,350}href=https://desktop\\.docker\\.com.*?(\\d{5,6}).*\\.exe"; + String regex = "## " + Pattern.quote(urlVersion.getName()) + + ".*?\\[Windows\\(https://desktop\\.docker\\.com/win/main/amd64/(\\d{5,6})/"; Pattern pattern = Pattern.compile(regex, Pattern.DOTALL); Matcher matcher = pattern.matcher(body); - String code; + if (matcher.find()) { - code = matcher.group(2); + String code = matcher.group(1); boolean success = doAddVersion(urlVersion, getDownloadBaseUrl() + "/win/main/amd64/" + code + "/Docker%20Desktop%20Installer.exe", WINDOWS); if (!success) { @@ -58,6 +56,7 @@ protected void addVersion(UrlVersion urlVersion) { if (WINDOWS_ONLY_VERSIONS.stream().noneMatch(i -> vid.compareVersion(i).isEqual())) { doAddVersion(urlVersion, getDownloadBaseUrl() + "/mac/main/amd64/" + code + "/Docker.dmg", MAC, X64); doAddVersion(urlVersion, getDownloadBaseUrl() + "/mac/main/arm64/" + code + "/Docker.dmg", MAC, ARM64); + doAddVersion(urlVersion, getDownloadBaseUrl() + "/linux/main/amd64/" + code + "/docker-desktop-amd64.deb", LINUX); } } } @@ -65,7 +64,7 @@ protected void addVersion(UrlVersion urlVersion) { @Override protected String getVersionUrl() { - return getVersionBaseUrl() + "/desktop/release-notes/"; + return getVersionBaseUrl() + "/desktop/release-notes.md"; } @Override From 2811b304ed47e9c12ebeb20c42e215c30a7c6e34 Mon Sep 17 00:00:00 2001 From: Hiepiscus Date: Fri, 21 Aug 2026 21:48:54 +0200 Subject: [PATCH 3/8] #2345: add Linux support for Docker Desktop with version selection --- .../devonfw/tools/ide/tool/docker/Docker.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/docker/Docker.java b/cli/src/main/java/com/devonfw/tools/ide/tool/docker/Docker.java index 5e8a071dfb..409efdff90 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/docker/Docker.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/docker/Docker.java @@ -30,6 +30,8 @@ public class Docker extends GlobalToolCommandlet { private static final Pattern DOCKER_DESKTOP_LINUX_VERSION_PATTERN = Pattern.compile("^([0-9]+(?:\\.[0-9]+){1,2})"); + private static final String EDITION_DOCKER = "docker"; + /** * The constructor. * @@ -65,6 +67,32 @@ private String detectContainerRuntime() { @Override protected List getNativePackages() { + + if (EDITION_DOCKER.equals(getConfiguredEdition())) { + return List.of( + new NativePackage( + NativePackageManager.APT, + List.of("/tmp/docker-desktop-amd64.deb"), + List.of("--allow-downgrades"), + List.of( + "sudo install -m 0755 -d /etc/apt/keyrings", + "sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc", + "sudo chmod a+r /etc/apt/keyrings/docker.asc", + "echo \"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] " + + "https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo \\\"$VERSION_CODENAME\\\") stable\" | " + + "sudo tee /etc/apt/sources.list.d/docker.list > /dev/null", + "sudo apt update", + "curl -fsSL https://desktop.docker.com/linux/main/amd64/docker-desktop-amd64.deb -o /tmp/docker-desktop-amd64.deb" + ), + List.of( + "sudo rm -f /etc/apt/sources.list.d/docker.list", + "sudo rm -f /etc/apt/keyrings/docker.asc", + "rm -f /tmp/docker-desktop-amd64.deb" + ) + ) + ); + } + return List.of( new NativePackage( NativePackageManager.ZYPPER, From 31d9c4235c29272775394131750e2d08e7155c89 Mon Sep 17 00:00:00 2001 From: Hiepiscus Date: Fri, 21 Aug 2026 21:49:50 +0200 Subject: [PATCH 4/8] #2345: fix DockerDesktopUrlUpdater --- .../url/tool/docker/DockerDesktopUrlUpdater.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/docker/DockerDesktopUrlUpdater.java b/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/docker/DockerDesktopUrlUpdater.java index 01417d03e3..70fb6c7a9a 100644 --- a/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/docker/DockerDesktopUrlUpdater.java +++ b/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/docker/DockerDesktopUrlUpdater.java @@ -1,5 +1,6 @@ package com.devonfw.tools.ide.url.tool.docker; + import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -39,17 +40,14 @@ public String getTool() { protected void addVersion(UrlVersion urlVersion) { VersionIdentifier vid = VersionIdentifier.of(urlVersion.getName()); - String version = urlVersion.getName().replaceAll("\\.", ""); - // get Code for version String body = doGetResponseBodyAsString(getVersionUrl()); - String regex = "href=#" + version - // .......1.........................................................2................. - + ".{8,12}(\r\n|\r|\n).{0,350}href=https://desktop\\.docker\\.com.*?(\\d{5,6}).*\\.exe"; + String regex = "## " + Pattern.quote(urlVersion.getName()) + + ".*?\\[Windows\\(https://desktop\\.docker\\.com/win/main/amd64/(\\d{5,6})/"; Pattern pattern = Pattern.compile(regex, Pattern.DOTALL); Matcher matcher = pattern.matcher(body); - String code; + if (matcher.find()) { - code = matcher.group(2); + String code = matcher.group(1); boolean success = doAddVersion(urlVersion, getDownloadBaseUrl() + "/win/main/amd64/" + code + "/Docker%20Desktop%20Installer.exe", WINDOWS); if (!success) { @@ -58,6 +56,7 @@ protected void addVersion(UrlVersion urlVersion) { if (WINDOWS_ONLY_VERSIONS.stream().noneMatch(i -> vid.compareVersion(i).isEqual())) { doAddVersion(urlVersion, getDownloadBaseUrl() + "/mac/main/amd64/" + code + "/Docker.dmg", MAC, X64); doAddVersion(urlVersion, getDownloadBaseUrl() + "/mac/main/arm64/" + code + "/Docker.dmg", MAC, ARM64); + doAddVersion(urlVersion, getDownloadBaseUrl() + "/linux/main/amd64/" + code + "/docker-desktop-amd64.deb", LINUX); } } } @@ -65,7 +64,7 @@ protected void addVersion(UrlVersion urlVersion) { @Override protected String getVersionUrl() { - return getVersionBaseUrl() + "/desktop/release-notes/"; + return getVersionBaseUrl() + "/desktop/release-notes.md"; } @Override From 4d1362d43d16fae6aa46423180d34177c70aa5fa Mon Sep 17 00:00:00 2001 From: Hiepiscus Date: Sat, 22 Aug 2026 10:08:26 +0200 Subject: [PATCH 5/8] #2345: remove unused imports --- .../main/java/com/devonfw/tools/ide/tool/docker/Docker.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/docker/Docker.java b/cli/src/main/java/com/devonfw/tools/ide/tool/docker/Docker.java index 3f44931d27..409efdff90 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/docker/Docker.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/docker/Docker.java @@ -1,6 +1,5 @@ package com.devonfw.tools.ide.tool.docker; -import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.regex.Pattern; @@ -14,8 +13,6 @@ import com.devonfw.tools.ide.tool.GlobalToolCommandlet; import com.devonfw.tools.ide.tool.NativePackage; import com.devonfw.tools.ide.tool.NativePackageManager; -import com.devonfw.tools.ide.tool.PackageManagerCommand; -import com.devonfw.tools.ide.tool.repository.ToolRepository; import com.devonfw.tools.ide.version.VersionIdentifier; /** From 15a7a4da3df914bb4755bea3c9dd72692e23fd11 Mon Sep 17 00:00:00 2001 From: Hiepiscus Date: Mon, 24 Aug 2026 12:42:55 +0200 Subject: [PATCH 6/8] #2345: fix regex --- .../tools/ide/url/tool/docker/DockerDesktopUrlUpdater.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/docker/DockerDesktopUrlUpdater.java b/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/docker/DockerDesktopUrlUpdater.java index 70fb6c7a9a..39a9ff871f 100644 --- a/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/docker/DockerDesktopUrlUpdater.java +++ b/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/docker/DockerDesktopUrlUpdater.java @@ -42,7 +42,7 @@ protected void addVersion(UrlVersion urlVersion) { VersionIdentifier vid = VersionIdentifier.of(urlVersion.getName()); String body = doGetResponseBodyAsString(getVersionUrl()); String regex = "## " + Pattern.quote(urlVersion.getName()) - + ".*?\\[Windows\\(https://desktop\\.docker\\.com/win/main/amd64/(\\d{5,6})/"; + + ".*?\\[Windows]\\(https://desktop\\.docker\\.com/win/main/amd64/(\\d{5,6})/"; Pattern pattern = Pattern.compile(regex, Pattern.DOTALL); Matcher matcher = pattern.matcher(body); From ad07e2aae389fac189892f257a5fdd8e01254861 Mon Sep 17 00:00:00 2001 From: Hiepiscus Date: Tue, 25 Aug 2026 09:50:27 +0200 Subject: [PATCH 7/8] #2345: Install docker-desktop from .deb --- .../devonfw/tools/ide/tool/docker/Docker.java | 46 +++++++++++++------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/docker/Docker.java b/cli/src/main/java/com/devonfw/tools/ide/tool/docker/Docker.java index 409efdff90..6c6d8f5cb2 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/docker/Docker.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/docker/Docker.java @@ -1,5 +1,6 @@ package com.devonfw.tools.ide.tool.docker; +import java.nio.file.Path; import java.util.List; import java.util.Set; import java.util.regex.Pattern; @@ -13,6 +14,8 @@ import com.devonfw.tools.ide.tool.GlobalToolCommandlet; import com.devonfw.tools.ide.tool.NativePackage; import com.devonfw.tools.ide.tool.NativePackageManager; +import com.devonfw.tools.ide.tool.PackageManagerCommand; +import com.devonfw.tools.ide.tool.repository.ToolRepository; import com.devonfw.tools.ide.version.VersionIdentifier; /** @@ -72,22 +75,12 @@ protected List getNativePackages() { return List.of( new NativePackage( NativePackageManager.APT, - List.of("/tmp/docker-desktop-amd64.deb"), + List.of("docker-desktop"), List.of("--allow-downgrades"), - List.of( - "sudo install -m 0755 -d /etc/apt/keyrings", - "sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc", - "sudo chmod a+r /etc/apt/keyrings/docker.asc", - "echo \"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] " - + "https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo \\\"$VERSION_CODENAME\\\") stable\" | " - + "sudo tee /etc/apt/sources.list.d/docker.list > /dev/null", - "sudo apt update", - "curl -fsSL https://desktop.docker.com/linux/main/amd64/docker-desktop-amd64.deb -o /tmp/docker-desktop-amd64.deb" - ), + List.of(), List.of( "sudo rm -f /etc/apt/sources.list.d/docker.list", - "sudo rm -f /etc/apt/keyrings/docker.asc", - "rm -f /tmp/docker-desktop-amd64.deb" + "sudo rm -f /etc/apt/keyrings/docker.asc" ) ) ); @@ -121,6 +114,33 @@ protected List getNativePackages() { ); } + @Override + protected List getInstallPackageManagerCommands(VersionIdentifier resolvedVersion) { + if (!EDITION_DOCKER.equals(getConfiguredEdition())) { + return super.getInstallPackageManagerCommands(resolvedVersion); + } + + ToolRepository toolRepository = this.context.getDefaultToolRepository(); + Path downloadedDeb = toolRepository.download(this.tool, EDITION_DOCKER, resolvedVersion, this); + + NativePackage dockerDesktopInstallPackage = new NativePackage( + NativePackageManager.APT, + List.of(downloadedDeb.toString()), + List.of("--allow-downgrades"), + List.of( + "sudo install -m 0755 -d /etc/apt/keyrings", + "sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc", + "sudo chmod a+r /etc/apt/keyrings/docker.asc", + "echo \"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] " + + "https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo \\\"$VERSION_CODENAME\\\") stable\" | " + + "sudo tee /etc/apt/sources.list.d/docker.list > /dev/null", + "sudo apt update" + ), + List.of() + ); + return List.of(dockerDesktopInstallPackage.install(null)); + } + @Override public boolean isExtract() { From 54cad674073a7998b22d777b6d7feea010429756 Mon Sep 17 00:00:00 2001 From: Hiepiscus Date: Thu, 3 Sep 2026 15:37:05 +0200 Subject: [PATCH 8/8] #2345: Add optional artifact paths to NativePackage --- .../devonfw/tools/ide/tool/NativePackage.java | 13 +++- .../tools/ide/tool/NativePackageManager.java | 10 ++- .../devonfw/tools/ide/tool/docker/Docker.java | 57 +++++++++------ .../tools/ide/tool/pgadmin/PgAdmin.java | 3 +- .../ide/tool/GlobalToolCommandletTest.java | 3 +- .../ide/tool/NativePackageManagerTest.java | 71 ++++++++++++++++--- .../tools/ide/tool/NativePackageTest.java | 6 +- 7 files changed, 124 insertions(+), 39 deletions(-) diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/NativePackage.java b/cli/src/main/java/com/devonfw/tools/ide/tool/NativePackage.java index 8156b97618..5d8e96b081 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/NativePackage.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/NativePackage.java @@ -13,6 +13,7 @@ public class NativePackage { private final List extraInstallOptions; private final List setupCommands; private final List cleanupCommands; + private final List optionalNativePackageArtifactPaths; /** * Creates a new {@link NativePackage} with optional fields defaulting to empty lists. @@ -24,12 +25,13 @@ public class NativePackage { * @param cleanupCommands commands to run after uninstall (optional) */ public NativePackage(NativePackageManager pm, List packages, - List extraInstallOptions, List setupCommands, List cleanupCommands) { + List extraInstallOptions, List setupCommands, List cleanupCommands, List optionalNativePackageArtifactPaths) { this.packageManager = Objects.requireNonNull(pm, "package manager must not be null"); this.packages = List.copyOf(Objects.requireNonNull(packages, "packages must not be null")); this.extraInstallOptions = extraInstallOptions != null ? List.copyOf(extraInstallOptions) : List.of(); this.setupCommands = setupCommands != null ? List.copyOf(setupCommands) : List.of(); this.cleanupCommands = cleanupCommands != null ? List.copyOf(cleanupCommands) : List.of(); + this.optionalNativePackageArtifactPaths = optionalNativePackageArtifactPaths != null ? List.copyOf(optionalNativePackageArtifactPaths) : List.of(); } /** @@ -39,7 +41,7 @@ public NativePackage(NativePackageManager pm, List packages, * @param packages the packages that need to be handled */ public NativePackage(NativePackageManager pm, List packages) { - this(pm, packages, null, null, null); + this(pm, packages, null, null, null, null); } /** @@ -88,6 +90,13 @@ public List getCleanupCommands() { return cleanupCommands; } + /** + * @return set {@link optionalNativePackageArtifactPaths}. + */ + public List getOptionalNativePackageArtifactPath() { + return optionalNativePackageArtifactPaths; + } + /** * @param version the version to pin the {@link #getPackages()} to or {@code null} to install the latest available version. * @return {@link PackageManagerCommand} for installation. diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/NativePackageManager.java b/cli/src/main/java/com/devonfw/tools/ide/tool/NativePackageManager.java index a742228c3c..1d80e87713 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/NativePackageManager.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/NativePackageManager.java @@ -128,8 +128,14 @@ public PackageManagerCommand install(NativePackage nativePackage, String version command.append(' ').append(option); } command.append(' ').append(this.installCommand); - for (String pkg : nativePackage.getPackages()) { - command.append(' ').append(getPackageSpec(pkg, version)); + if (nativePackage.getOptionalNativePackageArtifactPath().isEmpty()) { + for (String pkg : nativePackage.getPackages()) { + command.append(' ').append(getPackageSpec(pkg, version)); + } + } else { + for (String nativePackageArtifactPath : nativePackage.getOptionalNativePackageArtifactPath()) { + command.append(' ').append(nativePackageArtifactPath); + } } commands.add(command.toString()); return new PackageManagerCommand(this, commands); diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/docker/Docker.java b/cli/src/main/java/com/devonfw/tools/ide/tool/docker/Docker.java index 6c6d8f5cb2..193505fcc2 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/docker/Docker.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/docker/Docker.java @@ -15,6 +15,8 @@ import com.devonfw.tools.ide.tool.NativePackage; import com.devonfw.tools.ide.tool.NativePackageManager; import com.devonfw.tools.ide.tool.PackageManagerCommand; +import com.devonfw.tools.ide.tool.ToolInstallRequest; +import com.devonfw.tools.ide.tool.ToolInstallation; import com.devonfw.tools.ide.tool.repository.ToolRepository; import com.devonfw.tools.ide.version.VersionIdentifier; @@ -35,6 +37,8 @@ public class Docker extends GlobalToolCommandlet { private static final String EDITION_DOCKER = "docker"; + private Path downloadedDebPackageForDocker; + /** * The constructor. * @@ -72,16 +76,28 @@ private String detectContainerRuntime() { protected List getNativePackages() { if (EDITION_DOCKER.equals(getConfiguredEdition())) { + + List artifactPaths = (this.downloadedDebPackageForDocker == null) ? List.of() : List.of(this.downloadedDebPackageForDocker.toString()); + return List.of( new NativePackage( NativePackageManager.APT, List.of("docker-desktop"), List.of("--allow-downgrades"), - List.of(), + List.of( + "sudo install -m 0755 -d /etc/apt/keyrings", + "sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc", + "sudo chmod a+r /etc/apt/keyrings/docker.asc", + "echo \"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] " + + "https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo \\\"$VERSION_CODENAME\\\") stable\" | " + + "sudo tee /etc/apt/sources.list.d/docker.list > /dev/null", + "sudo apt update" + ), List.of( "sudo rm -f /etc/apt/sources.list.d/docker.list", "sudo rm -f /etc/apt/keyrings/docker.asc" - ) + ), + artifactPaths ) ); } @@ -92,6 +108,7 @@ protected List getNativePackages() { List.of("rancher-desktop"), List.of("--no-gpg-checks"), List.of("sudo zypper addrepo https://download.opensuse.org/repositories/isv:/Rancher:/stable/rpm/isv:Rancher:stable.repo"), + null, null ), new NativePackage( @@ -109,36 +126,32 @@ protected List getNativePackages() { List.of( "sudo rm -f /etc/apt/sources.list.d/isv-rancher-stable.list", "sudo rm -f /usr/share/keyrings/isv-rancher-stable-archive-keyring.gpg" - ) + ), + null ) ); } + @Override + protected ToolInstallation doInstall(ToolInstallRequest request) { + if (EDITION_DOCKER.equals(getConfiguredEdition())) { + downloadDebPackageStepAndSetPackagePath(request.getRequested().getResolvedVersion()); + } + return super.doInstall(request); + } + + private void downloadDebPackageStepAndSetPackagePath(VersionIdentifier resolvedVersion) { + ToolRepository toolRepository = this.context.getDefaultToolRepository(); + this.downloadedDebPackageForDocker = toolRepository.download(this.tool, EDITION_DOCKER, resolvedVersion, this); + } + @Override protected List getInstallPackageManagerCommands(VersionIdentifier resolvedVersion) { if (!EDITION_DOCKER.equals(getConfiguredEdition())) { return super.getInstallPackageManagerCommands(resolvedVersion); } - ToolRepository toolRepository = this.context.getDefaultToolRepository(); - Path downloadedDeb = toolRepository.download(this.tool, EDITION_DOCKER, resolvedVersion, this); - - NativePackage dockerDesktopInstallPackage = new NativePackage( - NativePackageManager.APT, - List.of(downloadedDeb.toString()), - List.of("--allow-downgrades"), - List.of( - "sudo install -m 0755 -d /etc/apt/keyrings", - "sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc", - "sudo chmod a+r /etc/apt/keyrings/docker.asc", - "echo \"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] " - + "https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo \\\"$VERSION_CODENAME\\\") stable\" | " - + "sudo tee /etc/apt/sources.list.d/docker.list > /dev/null", - "sudo apt update" - ), - List.of() - ); - return List.of(dockerDesktopInstallPackage.install(null)); + return getNativePackages().stream().map(nativePackage -> nativePackage.install(null)).toList(); } @Override diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/pgadmin/PgAdmin.java b/cli/src/main/java/com/devonfw/tools/ide/tool/pgadmin/PgAdmin.java index a07f1bce3a..4c5a0416fa 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/pgadmin/PgAdmin.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/pgadmin/PgAdmin.java @@ -40,7 +40,8 @@ protected List getNativePackages() { "sudo sh -c 'echo \"deb [signed-by=/usr/share/keyrings/packages-pgadmin-org.gpg] " + "https://ftp.postgresql.org/pub/pgadmin/pgadmin4/apt/$(lsb_release -cs) pgadmin4 main\" " + "> /etc/apt/sources.list.d/pgadmin4.list && apt update'"), - List.of("sudo rm -f /etc/apt/sources.list.d/pgadmin4.list", "sudo rm -f /usr/share/keyrings/packages-pgadmin-org.gpg") + List.of("sudo rm -f /etc/apt/sources.list.d/pgadmin4.list", "sudo rm -f /usr/share/keyrings/packages-pgadmin-org.gpg"), + null )); } diff --git a/cli/src/test/java/com/devonfw/tools/ide/tool/GlobalToolCommandletTest.java b/cli/src/test/java/com/devonfw/tools/ide/tool/GlobalToolCommandletTest.java index ede372170f..4158cab75a 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/tool/GlobalToolCommandletTest.java +++ b/cli/src/test/java/com/devonfw/tools/ide/tool/GlobalToolCommandletTest.java @@ -165,7 +165,8 @@ protected List getNativePackages() { List.of("mytool"), List.of(), List.of(), - List.of("sudo rm -f /etc/apt/sources.list.d/mytool.list")) + List.of("sudo rm -f /etc/apt/sources.list.d/mytool.list"), + List.of()) ); } diff --git a/cli/src/test/java/com/devonfw/tools/ide/tool/NativePackageManagerTest.java b/cli/src/test/java/com/devonfw/tools/ide/tool/NativePackageManagerTest.java index b57c8d8e98..78542c3958 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/tool/NativePackageManagerTest.java +++ b/cli/src/test/java/com/devonfw/tools/ide/tool/NativePackageManagerTest.java @@ -23,7 +23,8 @@ void testAptInstallCommand() { "sudo apt update"), List.of( "sudo rm -f /etc/apt/sources.list.d/example.list", - "sudo rm -f /usr/share/keyrings/example.gpg")); + "sudo rm -f /usr/share/keyrings/example.gpg"), + List.of()); var cmd = NativePackageManager.APT.install(np, "1.0.0"); @@ -47,7 +48,8 @@ void testAptUninstallCommand() { "sudo apt update"), List.of( "sudo rm -f /etc/apt/sources.list.d/example.list", - "sudo rm -f /usr/share/keyrings/example.gpg")); + "sudo rm -f /usr/share/keyrings/example.gpg"), + List.of()); var cmd = NativePackageManager.APT.uninstall(np); @@ -68,7 +70,8 @@ void testZypperInstallCommand() { "sudo zypper addrepo https://example.com/repo.repo", "sudo zypper refresh"), List.of( - "sudo zypper removerepo example-repo")); + "sudo zypper removerepo example-repo"), + List.of()); var cmd = NativePackageManager.ZYPPER.install(np, "1.0.0"); @@ -89,7 +92,8 @@ void testZypperUninstallCommand() { "sudo zypper addrepo https://example.com/repo.repo", "sudo zypper refresh"), List.of( - "sudo zypper removerepo example-repo")); + "sudo zypper removerepo example-repo"), + List.of()); var cmd = NativePackageManager.ZYPPER.uninstall(np); @@ -109,7 +113,8 @@ void testYumInstallCommand() { "sudo yum-config-manager --add-repo https://example.com/repo.repo", "sudo yum makecache"), List.of( - "sudo rm -f /etc/yum.repos.d/example.repo")); + "sudo rm -f /etc/yum.repos.d/example.repo"), + List.of()); var cmd = NativePackageManager.YUM.install(np, "1.0.0"); @@ -127,7 +132,8 @@ void testYumUninstallCommand() { List.of("pkg1"), List.of("--skip-broken"), List.of("sudo yum-config-manager --add-repo https://example.com/repo.repo", "sudo yum makecache"), - List.of("sudo rm -f /etc/yum.repos.d/example.repo")); + List.of("sudo rm -f /etc/yum.repos.d/example.repo"), + List.of()); var cmd = NativePackageManager.YUM.uninstall(np); @@ -143,7 +149,8 @@ void testDnfInstallCommand() { List.of("pkg1"), List.of("--refresh"), List.of("sudo dnf config-manager addrepo --from-repofile=https://example.com/repo.repo", "sudo dnf makecache"), - List.of("sudo rm -f /etc/yum.repos.d/example.repo")); + List.of("sudo rm -f /etc/yum.repos.d/example.repo"), + List.of()); var cmd = NativePackageManager.DNF.install(np, "1.0.0"); @@ -159,7 +166,8 @@ void testDnfUninstallCommand() { List.of("pkg1"), List.of("--refresh"), List.of("sudo dnf config-manager addrepo --from-repofile=https://example.com/repo.repo", "sudo dnf makecache"), - List.of("sudo rm -f /etc/yum.repos.d/example.repo")); + List.of("sudo rm -f /etc/yum.repos.d/example.repo"), + List.of()); var cmd = NativePackageManager.DNF.uninstall(np); @@ -192,4 +200,51 @@ void testParseVersionQueryOutputForRpmBasedPackageManager() { assertThat(NativePackageManager.YUM.parseVersionQueryOutput("1.0.0")).isEqualTo("1.0.0"); assertThat(NativePackageManager.DNF.parseVersionQueryOutput("1.0.0")).isEqualTo("1.0.0"); } + + @Test + void installUsesPackageNameAndVersionWhenNoArtifactPathConfigured() { + NativePackage nativePackage = new NativePackage(NativePackageManager.APT, List.of("docker-desktop")); + PackageManagerCommand result = NativePackageManager.APT.install(nativePackage, "1.2.3"); + + List commands = result.commands(); + String installCommand = commands.getLast(); + assertThat(installCommand).contains("apt", "install -y", "docker-desktop=1.2.3*"); + assertThat(installCommand).doesNotContain(".deb"); + } + + @Test + void installUsesArtifactPathWhenConfiguredInsteadOfPackageName() { + String debPath = "/tmp/downloads/docker-desktop-4.34.0-amd64"; + + NativePackage nativePackage = new NativePackage(NativePackageManager.APT, List.of("docker-desktop"), null, null, null, List.of(debPath)); + + PackageManagerCommand result = NativePackageManager.APT.install(nativePackage, null); + + List commands = result.commands(); + String installCommand = commands.getLast(); + assertThat(installCommand).contains(debPath); + assertThat(installCommand).doesNotContain("docker-desktop="); + } + + @Test + void installFallsBackToPackagesWhenArtifactPathListIsEmpty() { + NativePackage nativePackage = new NativePackage(NativePackageManager.APT, List.of("docker-desktop"), null, null, null, List.of()); + + PackageManagerCommand result = NativePackageManager.APT.install(nativePackage, null); + + List commands = result.commands(); + String installCommand = commands.getLast(); + assertThat(installCommand).contains("docker-desktop"); + } + + @Test + void installRejectsMismatchingPackageManager() { + NativePackage nativePackage = new NativePackage(NativePackageManager.APT, List.of("docker-desktop"), null, null, null, List.of()); + + PackageManagerCommand result = NativePackageManager.APT.install(nativePackage, null); + + List commands = result.commands(); + String installCommand = commands.getLast(); + assertThat(installCommand).contains("docker-desktop"); + } } diff --git a/cli/src/test/java/com/devonfw/tools/ide/tool/NativePackageTest.java b/cli/src/test/java/com/devonfw/tools/ide/tool/NativePackageTest.java index 3ba939304c..d679d06190 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/tool/NativePackageTest.java +++ b/cli/src/test/java/com/devonfw/tools/ide/tool/NativePackageTest.java @@ -24,7 +24,7 @@ void testOfFactoryMethod() { @Test void testConstructorWithAllFields() { - NativePackage np = new NativePackage(NativePackageManager.APT, List.of("pkg1"), List.of("--opt"), List.of("setup"), List.of("cleanup")); + NativePackage np = new NativePackage(NativePackageManager.APT, List.of("pkg1"), List.of("--opt"), List.of("setup"), List.of("cleanup"), List.of()); assertThat(np.getExtraInstallOptions()).containsExactly("--opt"); assertThat(np.getSetupCommands()).containsExactly("setup"); @@ -33,14 +33,14 @@ void testConstructorWithAllFields() { @Test void testGetPackages() { - NativePackage np = new NativePackage(NativePackageManager.APT, List.of("pkg1"), null, null, null); + NativePackage np = new NativePackage(NativePackageManager.APT, List.of("pkg1"), null, null, null, null); assertThat(np.getPackages()).containsExactly("pkg1"); } @Test void testNullSafeGetters() { - NativePackage np = new NativePackage(NativePackageManager.APT, List.of("pkg1"), null, null, null); + NativePackage np = new NativePackage(NativePackageManager.APT, List.of("pkg1"), null, null, null, null); assertThat(np.getExtraInstallOptions()).isEmpty(); assertThat(np.getSetupCommands()).isEmpty();