Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#142 and #94: Plugin based commandlet feature and PluginBasedCommandlet #153

Closed
wants to merge 12 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ jobs:
- name: Build project with Maven
run: mvn -B -ntp -Dstyle.color=always install
- name: Coveralls GitHub Action
uses: coverallsapp/[email protected]
uses: coverallsapp/[email protected]
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ jobs:
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
run: mvn --settings .mvn/settings.xml -DskipTests=true -Darchetype.test.skip=true -Dmaven.install.skip=true -Dstyle.color=always -B -ntp deploy
- name: Coveralls GitHub Action
uses: coverallsapp/[email protected]
uses: coverallsapp/[email protected]
1 change: 0 additions & 1 deletion README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ image:https://img.shields.io/github/license/devonfw/IDEasy.svg?label=License["Ap
image:https://img.shields.io/maven-central/v/com.devonfw.tools.ide/ide-cli.svg?label=Maven%20Central["Maven Central",link=https://search.maven.org/search?q=g:com.devonfw.tools.ide]
image:https://github.com/devonfw/IDEasy/actions/workflows/build.yml/badge.svg["Build Status",link="https://github.com/devonfw/IDEasy/actions/workflows/build.yml"]
image:https://github.com/devonfw/IDEasy/actions/workflows/update-urls.yml/badge.svg["Update URLS Status",link="https://github.com/devonfw/IDEasy/actions/workflows/update-urls.yml"]
image:https://coveralls.io/repos/github/devonfw/IDEasy/badge.svg?branch=main["Coverage Status",link="https://coveralls.io/github/devonfw/IDEasy?branch=main"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please keep this badge added by Moritz for the coverage.


toc::[]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -667,9 +667,8 @@ public <O> O question(String question, O... options) {
assert (options.length >= 2);
interaction(question);
Map<String, O> mapping = new HashMap<>(options.length);
int i = 0;
int i = 1;
for (O option : options) {
i++;
String key = "" + option;
addMapping(mapping, key, option);
String numericKey = Integer.toString(i);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
package com.devonfw.tools.ide.tool;

import com.devonfw.tools.ide.common.Tag;
import com.devonfw.tools.ide.cli.CliException;
import com.devonfw.tools.ide.context.IdeContext;
import com.devonfw.tools.ide.io.FileAccess;
import com.devonfw.tools.ide.tool.ide.IdeToolCommandlet;
import com.devonfw.tools.ide.tool.ide.PluginDescriptor;
import com.devonfw.tools.ide.tool.ide.PluginDescriptorImpl;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

your IDE settings are outdated/incorrect. Star-Imports are discouraged. According to our IDE settings this should also be auto-configured correctly for Intellij (maybe ask @jan-vcapgemini if it is not working for you) and for Eclipse it was correct from the beginning.

import java.util.stream.Stream;

public abstract class PluginBasedCommandlet extends LocalToolCommandlet {

private Map<String, PluginDescriptor> pluginsMap;

private Collection<PluginDescriptor> configuredPlugins;

/**
* 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 PluginBasedCommandlet(IdeContext context, String tool, Set<Tag> tags) {

super(context, tool, tags);
}


protected Map<String, PluginDescriptor> getPluginsMap() {

if (this.pluginsMap == null) {
Map<String, PluginDescriptor> map = new HashMap<>();

// Load project-specific plugins
Path pluginsPath = getPluginsConfigPath();
loadPluginsFromDirectory(map, pluginsPath);

// Load user-specific plugins
Path userPluginsPath = getUserHomePluginsConfigPath();
loadPluginsFromDirectory(map, userPluginsPath);

this.pluginsMap = map;
}

return this.pluginsMap;
}

private void loadPluginsFromDirectory(Map<String, PluginDescriptor> map, Path pluginsPath) {
if (Files.isDirectory(pluginsPath)) {
try (Stream<Path> childStream = Files.list(pluginsPath)) {
Iterator<Path> iterator = childStream.iterator();
while (iterator.hasNext()) {
Path child = iterator.next();
String filename = child.getFileName().toString();
if (filename.endsWith(IdeContext.EXT_PROPERTIES) && Files.exists(child)) {
PluginDescriptor descriptor = PluginDescriptorImpl.of(child, this.context, isPluginUrlNeeded());

// Priority to user-specific plugins
map.put(descriptor.getName(), descriptor);
}
}
} catch (IOException e) {
throw new IllegalStateException("Failed to list children of directory " + pluginsPath, e);
}
}
}

/**
* @return {@code true} if {@link PluginDescriptor#getUrl() plugin URL} property is needed, {@code false} otherwise.
*/
protected boolean isPluginUrlNeeded() {

return false;
}

protected Path getPluginsConfigPath() {

return this.context.getSettingsPath().resolve(this.tool).resolve(IdeContext.FOLDER_PLUGINS);
}

private Path getUserHomePluginsConfigPath() {

return context.getUserHome().resolve(Paths.get(".ide", "settings", this.tool, IdeContext.FOLDER_PLUGINS));
}


/**
* @return the immutable {@link Collection} of {@link PluginDescriptor}s configured for this IDE tool.
*/
public Collection<PluginDescriptor> getConfiguredPlugins() {

if (this.configuredPlugins == null) {
this.configuredPlugins = Collections.unmodifiableCollection(getPluginsMap().values());
}
return this.configuredPlugins;
}

/**
* @return the {@link Path} where the plugins of this {@link IdeToolCommandlet} shall be installed.
*/
public Path getPluginsInstallationPath() {

return this.context.getPluginsPath().resolve(this.tool);
}

/**
* @param plugin the {@link PluginDescriptor} to install.
*/
public abstract void installPlugin(PluginDescriptor plugin);

/**
* @param plugin the {@link PluginDescriptor} to uninstall.
*/
public void uninstallPlugin(PluginDescriptor plugin) {

Path pluginsPath = getPluginsInstallationPath();
if (!Files.isDirectory(pluginsPath)) {
this.context.debug("Omitting to uninstall plugin {} ({}) as plugins folder does not exist at {}",
plugin.getName(), plugin.getId(), pluginsPath);
return;
}
FileAccess fileAccess = this.context.getFileAccess();
Path match = fileAccess.findFirst(pluginsPath, p -> p.getFileName().toString().startsWith(plugin.getId()), false);
if (match == null) {
this.context.debug("Omitting to uninstall plugin {} ({}) as plugins folder does not contain a match at {}",
plugin.getName(), plugin.getId(), pluginsPath);
return;
}
fileAccess.delete(match);
}

/**
* @param key the filename of the properties file configuring the requested plugin (typically excluding the
* ".properties" extension).
* @return the {@link PluginDescriptor} for the given {@code key}.
*/
public PluginDescriptor getPlugin(String key) {

if (key == null) {
return null;
}
if (key.endsWith(IdeContext.EXT_PROPERTIES)) {
key = key.substring(0, key.length() - IdeContext.EXT_PROPERTIES.length());
}
PluginDescriptor pluginDescriptor = getPluginsMap().get(key);
if (pluginDescriptor == null) {
throw new CliException(
"Could not find plugin " + key + " at " + getPluginsConfigPath().resolve(key) + ".properties");
}
return pluginDescriptor;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,21 @@
import com.devonfw.tools.ide.common.Tag;
import com.devonfw.tools.ide.context.IdeContext;
import com.devonfw.tools.ide.io.FileAccess;
import com.devonfw.tools.ide.tool.LocalToolCommandlet;
import com.devonfw.tools.ide.tool.PluginBasedCommandlet;
import com.devonfw.tools.ide.tool.ToolCommandlet;
import com.devonfw.tools.ide.tool.eclipse.Eclipse;
import com.devonfw.tools.ide.tool.intellij.Intellij;
import com.devonfw.tools.ide.tool.vscode.Vscode;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Set;

/**
* {@link ToolCommandlet} for an IDE (integrated development environment) such as {@link Eclipse}, {@link Vscode}, or
* {@link Intellij}.
*/
public abstract class IdeToolCommandlet extends LocalToolCommandlet {

private Map<String, PluginDescriptor> pluginsMap;

private Collection<PluginDescriptor> configuredPlugins;
public abstract class IdeToolCommandlet extends PluginBasedCommandlet {

/**
* The constructor.
Expand All @@ -55,85 +55,6 @@ private boolean hasIde(Set<Tag> tags) {
throw new IllegalStateException("Tags of IdeTool hat to be connected with tag IDE: " + tags);
}

private Map<String, PluginDescriptor> getPluginsMap() {

if (this.pluginsMap == null) {
Map<String, PluginDescriptor> map = new HashMap<>();
Path pluginsPath = getPluginsConfigPath();
if (Files.isDirectory(pluginsPath)) {
try (Stream<Path> childStream = Files.list(pluginsPath)) {
Iterator<Path> iterator = childStream.iterator();
while (iterator.hasNext()) {
Path child = iterator.next();
String filename = child.getFileName().toString();
if (filename.endsWith(IdeContext.EXT_PROPERTIES) && Files.exists(child)) {
PluginDescriptor descriptor = PluginDescriptorImpl.of(child, this.context, isPluginUrlNeeded());
map.put(descriptor.getName(), descriptor);
}
}
} catch (IOException e) {
throw new IllegalStateException("Failed to list children of directory " + pluginsPath, e);
}
}
this.pluginsMap = map;
}
return this.pluginsMap;
}

private Path getPluginsConfigPath() {

return this.context.getSettingsPath().resolve(this.tool).resolve(IdeContext.FOLDER_PLUGINS);
}

/**
* @return {@code true} if {@link PluginDescriptor#getUrl() plugin URL} property is needed, {@code false} otherwise.
*/
protected boolean isPluginUrlNeeded() {

return false;
}

/**
* @return the immutable {@link Collection} of {@link PluginDescriptor}s configured for this IDE tool.
*/
public Collection<PluginDescriptor> getConfiguredPlugins() {

if (this.configuredPlugins == null) {
this.configuredPlugins = Collections.unmodifiableCollection(getPluginsMap().values());
}
return this.configuredPlugins;
}

/**
* @return the {@link Path} where the plugins of this {@link IdeToolCommandlet} shall be installed.
*/
public Path getPluginsInstallationPath() {

// TODO add edition???
return this.context.getPluginsPath().resolve(this.tool);
}

/**
* @param key the filename of the properties file configuring the requested plugin (typically excluding the
* ".properties" extension).
* @return the {@link PluginDescriptor} for the given {@code key}.
*/
public PluginDescriptor getPlugin(String key) {

if (key == null) {
return null;
}
if (key.endsWith(IdeContext.EXT_PROPERTIES)) {
key = key.substring(0, key.length() - IdeContext.EXT_PROPERTIES.length());
}
PluginDescriptor pluginDescriptor = getPluginsMap().get(key);
if (pluginDescriptor == null) {
throw new CliException(
"Could not find plugin " + key + " at " + getPluginsConfigPath().resolve(key) + ".properties");
}
return pluginDescriptor;
}

@Override
protected boolean doInstall(boolean silent) {

Expand Down Expand Up @@ -167,32 +88,6 @@ protected void handleInstall4InactivePlugin(PluginDescriptor plugin) {
this.context.debug("Omitting installation of inactive plugin {} ({}).", plugin.getName(), plugin.getId());
}

/**
* @param plugin the {@link PluginDescriptor} to install.
*/
public abstract void installPlugin(PluginDescriptor plugin);

/**
* @param plugin the {@link PluginDescriptor} to uninstall.
*/
public void uninstallPlugin(PluginDescriptor plugin) {

Path pluginsPath = getPluginsInstallationPath();
if (!Files.isDirectory(pluginsPath)) {
this.context.debug("Omitting to uninstall plugin {} ({}) as plugins folder does not exist at {}",
plugin.getName(), plugin.getId(), pluginsPath);
return;
}
FileAccess fileAccess = this.context.getFileAccess();
Path match = fileAccess.findFirst(pluginsPath, p -> p.getFileName().toString().startsWith(plugin.getId()), false);
if (match == null) {
this.context.debug("Omitting to uninstall plugin {} ({}) as plugins folder does not contain a match at {}",
plugin.getName(), plugin.getId(), pluginsPath);
return;
}
fileAccess.delete(match);
}

@Override
public void run() {

Expand Down

This file was deleted.

Loading
Loading