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

devonfw / IDEasy / 11019972842

24 Sep 2024 06:42PM UTC coverage: 66.107% (+0.2%) from 65.911%
11019972842

Pull #538

github

web-flow
Merge 83a22b241 into 3ddcdd758
Pull Request #538: #37: Tool commandlet for visual studio code

2317 of 3850 branches covered (60.18%)

Branch coverage included in aggregate %.

6105 of 8890 relevant lines covered (68.67%)

3.03 hits per line

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

73.91
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.tool.LocalToolCommandlet;
14
import com.devonfw.tools.ide.tool.ide.IdeToolCommandlet;
15

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

21
  private PluginMaps pluginsMap;
22

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

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

35
  public PluginMaps getPluginsMap() {
36

37
    if (this.pluginsMap == null) {
3✔
38
      PluginMaps map = new PluginMaps(this.context);
6✔
39

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

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

49
      this.pluginsMap = map;
3✔
50
    }
51

52
    return this.pluginsMap;
3✔
53
  }
54

55
  private void loadPluginsFromDirectory(PluginMaps map, Path pluginsPath) {
56

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

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

70
    return false;
2✔
71
  }
72

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

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

81
  private Path getUserHomePluginsConfigPath() {
82

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

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

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

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

99
  /**
100
   * @param plugin the {@link PluginDescriptor} to uninstall.
101
   */
102
  public void uninstallPlugin(PluginDescriptor plugin) {
103

104
    Path pluginsPath = getPluginsInstallationPath();
3✔
105
    if (!Files.isDirectory(pluginsPath)) {
5!
106
      this.context.debug("Omitting to uninstall plugin {} ({}) as plugins folder does not exist at {}",
×
107
          plugin.getName(), plugin.getId(), pluginsPath);
×
108
      return;
×
109
    }
110
    FileAccess fileAccess = this.context.getFileAccess();
4✔
111
    Path match = fileAccess.findFirst(pluginsPath, p -> p.getFileName().toString().startsWith(plugin.getId()), false);
14✔
112
    if (match == null) {
2!
113
      this.context.debug("Omitting to uninstall plugin {} ({}) as plugins folder does not contain a match at {}",
×
114
          plugin.getName(), plugin.getId(), pluginsPath);
×
115
      return;
×
116
    }
117
    fileAccess.delete(match);
3✔
118
  }
1✔
119

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

126
    if (key == null) {
×
127
      return null;
×
128
    }
129
    if (key.endsWith(IdeContext.EXT_PROPERTIES)) {
×
130
      key = key.substring(0, key.length() - IdeContext.EXT_PROPERTIES.length());
×
131
    }
132

133
    PluginMaps pluginMaps = getPluginsMap();
×
134
    PluginDescriptor pluginDescriptor = pluginMaps.getByName(key);
×
135
    if (pluginDescriptor == null) {
×
136
      throw new CliException(
×
137
          "Could not find plugin " + key + " at " + getPluginsConfigPath().resolve(key) + ".properties");
×
138
    }
139
    return pluginDescriptor;
×
140
  }
141

142

143
  @Override
144
  protected boolean doInstall(boolean silent) {
145

146
    boolean newlyInstalled = super.doInstall(silent);
4✔
147
    // post installation...
148
    boolean installPlugins = newlyInstalled;
2✔
149
    Path pluginsInstallationPath = getPluginsInstallationPath();
3✔
150
    if (newlyInstalled) {
2✔
151
      this.context.getFileAccess().delete(pluginsInstallationPath);
6✔
152
    } else if (!Files.isDirectory(pluginsInstallationPath)) {
5✔
153
      installPlugins = true;
2✔
154
    }
155
    createExtensionFolder();
2✔
156
    if (installPlugins) {
2✔
157
      PluginMaps pluginMaps = getPluginsMap();
3✔
158
      Collection<PluginDescriptor> plugins = pluginMaps.getPlugins();
3✔
159
      installPlugins(plugins);
3✔
160
    }
161
    return newlyInstalled;
2✔
162
  }
163

164
  private void createExtensionFolder() {
165
    Path extensionFolder = this.context.getIdeHome().resolve("plugins").resolve(this.tool);
9✔
166
    this.context.getFileAccess().mkdirs(extensionFolder);
5✔
167
  }
1✔
168

169
  /**
170
   * Method to install active plugins or to handle install for inactive plugins
171
   *
172
   * @param plugins as {@link Collection} of plugins to install.
173
   */
174
  protected void installPlugins(Collection<PluginDescriptor> plugins) {
175
    for (PluginDescriptor plugin : plugins) {
10✔
176
      if (plugin.isActive()) {
3✔
177
        installPlugin(plugin);
4✔
178
      } else {
179
        handleInstall4InactivePlugin(plugin);
3✔
180
      }
181
    }
1✔
182
  }
1✔
183

184
  /**
185
   * @param plugin the in{@link PluginDescriptor#isActive() active} {@link PluginDescriptor} that is skipped for regular plugin installation.
186
   */
187
  protected void handleInstall4InactivePlugin(PluginDescriptor plugin) {
188

189
    this.context.debug("Omitting installation of inactive plugin {} ({}).", plugin.getName(), plugin.getId());
16✔
190
  }
1✔
191
}
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