• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

devonfw / IDEasy / 12429379558

20 Dec 2024 10:01AM UTC coverage: 67.345% (-0.1%) from 67.478%
12429379558

Pull #903

github

web-flow
Merge d3d2a74f1 into bc0d144fa
Pull Request #903: #898 improved feedback messages

2576 of 4174 branches covered (61.72%)

Branch coverage included in aggregate %.

6659 of 9539 relevant lines covered (69.81%)

3.07 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

70.37
cli/src/main/java/com/devonfw/tools/ide/tool/plugin/PluginBasedCommandlet.java
1
package com.devonfw.tools.ide.tool.plugin;
2

3
import java.nio.file.Files;
4
import java.nio.file.Path;
5
import java.util.Collection;
6
import java.util.List;
7
import java.util.Set;
8

9
import com.devonfw.tools.ide.cli.CliException;
10
import com.devonfw.tools.ide.common.Tag;
11
import com.devonfw.tools.ide.context.IdeContext;
12
import com.devonfw.tools.ide.io.FileAccess;
13
import com.devonfw.tools.ide.step.Step;
14
import com.devonfw.tools.ide.tool.LocalToolCommandlet;
15
import com.devonfw.tools.ide.tool.ide.IdeToolCommandlet;
16

17
/**
18
 * Base class for {@link LocalToolCommandlet}s that support plugins. It can automatically install configured plugins for the tool managed by this commandlet.
19
 */
20
public abstract class PluginBasedCommandlet extends LocalToolCommandlet {
21

22
  private ToolPlugins plugins;
23

24
  /**
25
   * The constructor.
26
   *
27
   * @param context the {@link IdeContext}.
28
   * @param tool the {@link #getName() tool name}.
29
   * @param tags the {@link #getTags() tags} classifying the tool. Should be created via {@link Set#of(Object) Set.of} method.
30
   */
31
  public PluginBasedCommandlet(IdeContext context, String tool, Set<Tag> tags) {
32

33
    super(context, tool, tags);
5✔
34
  }
1✔
35

36
  public ToolPlugins getPlugins() {
37

38
    if (this.plugins == null) {
3✔
39
      ToolPlugins toolPlugins = new ToolPlugins(this.context);
6✔
40

41
      // Load project-specific plugins
42
      Path pluginsPath = getPluginsConfigPath();
3✔
43
      loadPluginsFromDirectory(toolPlugins, pluginsPath);
4✔
44

45
      // Load user-specific plugins, this is done after loading the project-specific plugins so the user can potentially
46
      // override plugins (e.g. change active flag).
47
      Path userPluginsPath = getUserHomePluginsConfigPath();
3✔
48
      loadPluginsFromDirectory(toolPlugins, userPluginsPath);
4✔
49

50
      this.plugins = toolPlugins;
3✔
51
    }
52

53
    return this.plugins;
3✔
54
  }
55

56
  private void loadPluginsFromDirectory(ToolPlugins map, Path pluginsPath) {
57

58
    List<Path> children = this.context.getFileAccess()
5✔
59
        .listChildren(pluginsPath, p -> p.getFileName().toString().endsWith(IdeContext.EXT_PROPERTIES));
8✔
60
    for (Path child : children) {
10✔
61
      ToolPluginDescriptor descriptor = ToolPluginDescriptor.of(child, this.context, isPluginUrlNeeded());
7✔
62
      map.add(descriptor);
3✔
63
    }
1✔
64
  }
1✔
65

66
  /**
67
   * @return {@code true} if {@link ToolPluginDescriptor#url() plugin URL} property is needed, {@code false} otherwise.
68
   */
69
  protected boolean isPluginUrlNeeded() {
70

71
    return false;
2✔
72
  }
73

74
  /**
75
   * @return the {@link Path} to the folder with the plugin configuration files inside the settings.
76
   */
77
  protected Path getPluginsConfigPath() {
78

79
    return this.context.getSettingsPath().resolve(this.tool).resolve(IdeContext.FOLDER_PLUGINS);
9✔
80
  }
81

82
  private Path getUserHomePluginsConfigPath() {
83

84
    return this.context.getUserHomeIde().resolve("settings").resolve(this.tool).resolve(IdeContext.FOLDER_PLUGINS);
11✔
85
  }
86

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

92
    return this.context.getPluginsPath().resolve(this.tool);
7✔
93
  }
94

95
  @Override
96
  protected void postInstall(boolean newlyInstalled) {
97

98
    super.postInstall(newlyInstalled);
3✔
99
    if (newlyInstalled) {
2✔
100
      Path pluginsInstallationPath = getPluginsInstallationPath();
3✔
101
      FileAccess fileAccess = this.context.getFileAccess();
4✔
102
      fileAccess.delete(pluginsInstallationPath);
3✔
103
      fileAccess.mkdirs(pluginsInstallationPath);
3✔
104
      installPlugins(getPlugins().getPlugins());
5✔
105
    }
106
    // else ? check all plugins are installed, retry failed plugin installations ?
107
  }
1✔
108

109
  /**
110
   * Method to install active plugins or to handle install for inactive plugins
111
   *
112
   * @param plugins as {@link Collection} of plugins to install.
113
   */
114
  protected void installPlugins(Collection<ToolPluginDescriptor> plugins) {
115
    for (ToolPluginDescriptor plugin : plugins) {
10✔
116
      if (plugin.active()) {
3✔
117
        try (Step step = this.context.newStep("Install plugin " + plugin.name())) {
8✔
118
          installPlugin(plugin, step);
4✔
119
        }
120
      } else {
121
        handleInstall4InactivePlugin(plugin);
3✔
122
      }
123
    }
1✔
124
  }
1✔
125

126
  /**
127
   * @param plugin the {@link ToolPluginDescriptor} to install.
128
   * @param step the {@link Step} for the plugin installation.
129
   */
130
  public abstract void installPlugin(ToolPluginDescriptor plugin, Step step);
131

132
  /**
133
   * @param plugin the {@link ToolPluginDescriptor} to uninstall.
134
   * @return 0 if the uninstallation was successfull and 1 if it failed
135
   */
136
  public int uninstallPlugin(ToolPluginDescriptor plugin) {
137

138
    Path pluginsPath = getPluginsInstallationPath();
3✔
139
    if (!Files.isDirectory(pluginsPath)) {
5!
140
      this.context.debug("Omitting to uninstall plugin {} ({}) as plugins folder does not exist at {}",
×
141
          plugin.name(), plugin.id(), pluginsPath);
×
142
      return 1;
×
143
    }
144
    FileAccess fileAccess = this.context.getFileAccess();
4✔
145
    Path match = fileAccess.findFirst(pluginsPath, p -> p.getFileName().toString().startsWith(plugin.id()), false);
14✔
146
    if (match == null) {
2!
147
      this.context.debug("Omitting to uninstall plugin {} ({}) as plugins folder does not contain a match at {}",
×
148
          plugin.name(), plugin.id(), pluginsPath);
×
149
      return 1;
×
150
    }
151
    fileAccess.delete(match);
3✔
152
    return 0;
2✔
153
  }
154

155
  /**
156
   * @param key the filename of the properties file configuring the requested plugin (typically excluding the ".properties" extension).
157
   * @return the {@link ToolPluginDescriptor} for the given {@code key}.
158
   */
159
  public ToolPluginDescriptor getPlugin(String key) {
160

161
    if (key == null) {
×
162
      return null;
×
163
    }
164
    if (key.endsWith(IdeContext.EXT_PROPERTIES)) {
×
165
      key = key.substring(0, key.length() - IdeContext.EXT_PROPERTIES.length());
×
166
    }
167

168
    ToolPlugins toolPlugins = getPlugins();
×
169
    ToolPluginDescriptor pluginDescriptor = toolPlugins.getByName(key);
×
170
    if (pluginDescriptor == null) {
×
171
      throw new CliException(
×
172
          "Could not find plugin " + key + " at " + getPluginsConfigPath().resolve(key) + ".properties");
×
173
    }
174
    return pluginDescriptor;
×
175
  }
176

177
  /**
178
   * @param plugin the in{@link ToolPluginDescriptor#active() active} {@link ToolPluginDescriptor} that is skipped for regular plugin installation.
179
   */
180
  protected void handleInstall4InactivePlugin(ToolPluginDescriptor plugin) {
181

182
    this.context.debug("Omitting installation of inactive plugin {} ({}).", plugin.name(), plugin.id());
16✔
183
  }
1✔
184
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc