-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into feature/56-implement-autocompletion
- Loading branch information
Showing
22 changed files
with
381 additions
and
257 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
74 changes: 74 additions & 0 deletions
74
cli/src/main/java/com/devonfw/tools/ide/tool/GlobalToolCommandlet.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package com.devonfw.tools.ide.tool; | ||
|
||
import com.devonfw.tools.ide.context.IdeContext; | ||
import com.devonfw.tools.ide.io.FileAccess; | ||
import com.devonfw.tools.ide.process.ProcessContext; | ||
import com.devonfw.tools.ide.process.ProcessErrorHandling; | ||
import com.devonfw.tools.ide.repo.ToolRepository; | ||
import com.devonfw.tools.ide.version.VersionIdentifier; | ||
|
||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.util.Set; | ||
|
||
/** | ||
* {@link ToolCommandlet} that is installed globally. | ||
*/ | ||
public abstract class GlobalToolCommandlet extends ToolCommandlet { | ||
|
||
/** | ||
* The constructor. | ||
* | ||
* @param context the {@link IdeContext}. | ||
* @param tool the {@link #getName() tool name}. | ||
* @param tags the {@link #getTags() tags} classifying the tool. Should be created via {@link Set#of(Object) Set.of} | ||
* method. | ||
*/ | ||
public GlobalToolCommandlet(IdeContext context, String tool, Set<String> tags) { | ||
|
||
super(context, tool, tags); | ||
} | ||
|
||
@Override | ||
protected boolean isExtract() { | ||
// for global tools we usually download installers and do not want to extract them (e.g. installer.msi file shall not be extracted) | ||
return false; | ||
} | ||
|
||
@Override | ||
protected boolean doInstall(boolean silent) { | ||
|
||
Path binaryPath = this.context.getPath().findBinary(Path.of(getBinaryName())); | ||
//if force mode is enabled, go through with the installation even if the tool is already installed | ||
if (binaryPath != null && Files.exists(binaryPath) && !this.context.isForceMode()) { | ||
this.context.debug("{} is already installed at {}", this.tool, binaryPath); | ||
return false; | ||
} | ||
String edition = getEdition(); | ||
ToolRepository toolRepository = this.context.getDefaultToolRepository(); | ||
VersionIdentifier configuredVersion = getConfiguredVersion(); | ||
VersionIdentifier resolvedVersion = toolRepository.resolveVersion(this.tool, edition, configuredVersion); | ||
// download and install the global tool | ||
FileAccess fileAccess = this.context.getFileAccess(); | ||
Path target = toolRepository.download(this.tool, edition, resolvedVersion); | ||
Path tmpDir = fileAccess.createTempDir(getName()); | ||
Path downloadBinaryPath = tmpDir.resolve(target.getFileName()); | ||
extract(target, downloadBinaryPath); | ||
if (isExtract()) { | ||
downloadBinaryPath = fileAccess.findFirst(downloadBinaryPath, Files::isExecutable, false); | ||
} | ||
ProcessContext pc = this.context.newProcess().errorHandling(ProcessErrorHandling.WARNING).executable(downloadBinaryPath); | ||
int exitCode = pc.run(); | ||
fileAccess.delete(tmpDir); | ||
fileAccess.delete(target); | ||
if (exitCode == 0) { | ||
this.context.success("Successfully installed {} in version {}", this.tool, resolvedVersion); | ||
} else { | ||
this.context.warning("{} in version {} was not successfully installed", this.tool, resolvedVersion); | ||
return false; | ||
} | ||
postInstall(); | ||
return true; | ||
} | ||
|
||
} |
185 changes: 185 additions & 0 deletions
185
cli/src/main/java/com/devonfw/tools/ide/tool/LocalToolCommandlet.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
package com.devonfw.tools.ide.tool; | ||
|
||
import com.devonfw.tools.ide.commandlet.Commandlet; | ||
import com.devonfw.tools.ide.context.IdeContext; | ||
import com.devonfw.tools.ide.io.FileAccess; | ||
import com.devonfw.tools.ide.io.FileCopyMode; | ||
import com.devonfw.tools.ide.log.IdeLogLevel; | ||
import com.devonfw.tools.ide.repo.ToolRepository; | ||
import com.devonfw.tools.ide.version.VersionIdentifier; | ||
|
||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.nio.file.StandardOpenOption; | ||
import java.util.Set; | ||
|
||
/** | ||
* {@link ToolCommandlet} that is installed locally into the IDE. | ||
*/ | ||
public abstract class LocalToolCommandlet extends ToolCommandlet { | ||
|
||
/** | ||
* The constructor. | ||
* | ||
* @param context the {@link IdeContext}. | ||
* @param tool the {@link #getName() tool name}. | ||
* @param tags the {@link #getTags() tags} classifying the tool. Should be created via {@link Set#of(Object) Set.of} | ||
* method. | ||
*/ | ||
public LocalToolCommandlet(IdeContext context, String tool, Set<String> tags) { | ||
|
||
super(context, tool, tags); | ||
} | ||
|
||
|
||
/** | ||
* @return the {@link Path} where the tool is located (installed). | ||
*/ | ||
public Path getToolPath() { | ||
|
||
return this.context.getSoftwarePath().resolve(getName()); | ||
} | ||
|
||
/** | ||
* @return the {@link Path} where the executables of the tool can be found. Typically a "bin" folder inside | ||
* {@link #getToolPath() tool path}. | ||
*/ | ||
public Path getToolBinPath() { | ||
|
||
Path toolPath = getToolPath(); | ||
Path binPath = this.context.getFileAccess().findFirst(toolPath, path -> path.getFileName().toString().equals("bin"), | ||
false); | ||
if ((binPath != null) && Files.isDirectory(binPath)) { | ||
return binPath; | ||
} | ||
return toolPath; | ||
} | ||
|
||
@Override | ||
protected boolean doInstall(boolean silent) { | ||
|
||
VersionIdentifier configuredVersion = getConfiguredVersion(); | ||
// install configured version of our tool in the software repository if not already installed | ||
ToolInstallation installation = installInRepo(configuredVersion); | ||
|
||
// check if we already have this version installed (linked) locally in IDE_HOME/software | ||
VersionIdentifier installedVersion = getInstalledVersion(); | ||
VersionIdentifier resolvedVersion = installation.resolvedVersion(); | ||
if (isInstalledVersion(resolvedVersion, installedVersion, silent)) { | ||
return false; | ||
} | ||
// we need to link the version or update the link. | ||
Path toolPath = getToolPath(); | ||
FileAccess fileAccess = this.context.getFileAccess(); | ||
if (Files.exists(toolPath)) { | ||
fileAccess.backup(toolPath); | ||
} | ||
fileAccess.symlink(installation.linkDir(), toolPath); | ||
this.context.getPath().setPath(this.tool, installation.binDir()); | ||
if (installedVersion == null) { | ||
this.context.success("Successfully installed {} in version {}", this.tool, resolvedVersion); | ||
} else { | ||
this.context.success("Successfully installed {} in version {} replacing previous version {]", this.tool, | ||
resolvedVersion, installedVersion); | ||
} | ||
postInstall(); | ||
return true; | ||
} | ||
|
||
/** | ||
* Performs the installation of the {@link #getName() tool} managed by this {@link Commandlet} only in the central | ||
* software repository without touching the IDE installation. | ||
* | ||
* @param version the {@link VersionIdentifier} requested to be installed. May also be a | ||
* {@link VersionIdentifier#isPattern() version pattern}. | ||
* @return the {@link ToolInstallation} in the central software repository matching the given {@code version}. | ||
*/ | ||
public ToolInstallation installInRepo(VersionIdentifier version) { | ||
|
||
return installInRepo(version, getEdition()); | ||
} | ||
|
||
/** | ||
* Performs the installation of the {@link #getName() tool} managed by this {@link Commandlet} only in the central | ||
* software repository without touching the IDE installation. | ||
* | ||
* @param version the {@link VersionIdentifier} requested to be installed. May also be a | ||
* {@link VersionIdentifier#isPattern() version pattern}. | ||
* @param edition the specific edition to install. | ||
* @return the {@link ToolInstallation} in the central software repository matching the given {@code version}. | ||
*/ | ||
public ToolInstallation installInRepo(VersionIdentifier version, String edition) { | ||
|
||
return installInRepo(version, edition, this.context.getDefaultToolRepository()); | ||
} | ||
|
||
/** | ||
* Performs the installation of the {@link #getName() tool} managed by this {@link Commandlet} only in the central | ||
* software repository without touching the IDE installation. | ||
* | ||
* @param version the {@link VersionIdentifier} requested to be installed. May also be a | ||
* {@link VersionIdentifier#isPattern() version pattern}. | ||
* @param edition the specific edition to install. | ||
* @param toolRepository the {@link ToolRepository} to use. | ||
* @return the {@link ToolInstallation} in the central software repository matching the given {@code version}. | ||
*/ | ||
public ToolInstallation installInRepo(VersionIdentifier version, String edition, ToolRepository toolRepository) { | ||
|
||
VersionIdentifier resolvedVersion = toolRepository.resolveVersion(this.tool, edition, version); | ||
Path toolPath = this.context.getSoftwareRepositoryPath().resolve(toolRepository.getId()).resolve(this.tool) | ||
.resolve(edition).resolve(resolvedVersion.toString()); | ||
Path toolVersionFile = toolPath.resolve(IdeContext.FILE_SOFTWARE_VERSION); | ||
FileAccess fileAccess = this.context.getFileAccess(); | ||
if (Files.isDirectory(toolPath)) { | ||
if (Files.exists(toolVersionFile)) { | ||
this.context.debug("Version {} of tool {} is already installed at {}", resolvedVersion, | ||
getToolWithEdition(this.tool, edition), toolPath); | ||
return createToolInstallation(toolPath, resolvedVersion, toolVersionFile); | ||
} | ||
this.context.warning("Deleting corrupted installation at {}", toolPath); | ||
fileAccess.delete(toolPath); | ||
} | ||
Path target = toolRepository.download(this.tool, edition, resolvedVersion); | ||
fileAccess.mkdirs(toolPath.getParent()); | ||
extract(target, toolPath); | ||
try { | ||
Files.writeString(toolVersionFile, resolvedVersion.toString(), StandardOpenOption.CREATE_NEW); | ||
} catch (IOException e) { | ||
throw new IllegalStateException("Failed to write version file " + toolVersionFile, e); | ||
} | ||
return createToolInstallation(toolPath, resolvedVersion, toolVersionFile); | ||
} | ||
|
||
private ToolInstallation createToolInstallation(Path rootDir, VersionIdentifier resolvedVersion, | ||
Path toolVersionFile) { | ||
|
||
Path linkDir = getMacOsHelper().findLinkDir(rootDir); | ||
Path binDir = linkDir; | ||
Path binFolder = binDir.resolve(IdeContext.FOLDER_BIN); | ||
if (Files.isDirectory(binFolder)) { | ||
binDir = binFolder; | ||
} | ||
if (linkDir != rootDir) { | ||
assert (!linkDir.equals(rootDir)); | ||
this.context.getFileAccess().copy(toolVersionFile, linkDir, FileCopyMode.COPY_FILE_OVERRIDE); | ||
} | ||
return new ToolInstallation(rootDir, linkDir, binDir, resolvedVersion); | ||
} | ||
|
||
private boolean isInstalledVersion(VersionIdentifier expectedVersion, VersionIdentifier installedVersion, | ||
boolean silent) { | ||
|
||
if (expectedVersion.equals(installedVersion)) { | ||
IdeLogLevel level = IdeLogLevel.INFO; | ||
if (silent) { | ||
level = IdeLogLevel.DEBUG; | ||
} | ||
this.context.level(level).log("Version {} of tool {} is already installed", installedVersion, | ||
getToolWithEdition()); | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
} |
Oops, something went wrong.