Per-project custom repositories through required plugins

This commit is contained in:
Ivan Chirkov
2016-01-14 20:49:46 +01:00
parent 4d7d54daa6
commit 87ee55555a
6 changed files with 48 additions and 9 deletions
@@ -40,7 +40,7 @@ internal class DefaultProjectStoreTest {
private val tempDirManager = TemporaryDirectory()
private val requiredPlugins = listOf<ProjectExternalDependency>(DependencyOnPlugin("fake", "0", "1"))
private val requiredPlugins = listOf<ProjectExternalDependency>(DependencyOnPlugin("fake", "0", "1", "alpha"))
private val ruleChain = RuleChain(
tempDirManager,
@@ -31,11 +31,13 @@ public class DependencyOnPlugin implements ProjectExternalDependency, Comparable
private final String myPluginId;
private final String myMinVersion;
private final String myMaxVersion;
private final String myChannel;
public DependencyOnPlugin(@NotNull String pluginId, @Nullable String minVersion, @Nullable String maxVersion) {
public DependencyOnPlugin(@NotNull String pluginId, @Nullable String minVersion, @Nullable String maxVersion, @Nullable String channel) {
myPluginId = pluginId;
myMinVersion = minVersion;
myMaxVersion = maxVersion;
myChannel = channel;
}
public String getPluginId() {
@@ -50,6 +52,10 @@ public class DependencyOnPlugin implements ProjectExternalDependency, Comparable
return myMaxVersion;
}
public String getChannel() {
return myChannel;
}
@Override
public boolean equals(Object o) {
@@ -60,12 +66,13 @@ public class DependencyOnPlugin implements ProjectExternalDependency, Comparable
return myPluginId.equals(plugin.myPluginId)
&& Comparing.equal(myMinVersion, plugin.myMinVersion)
&& Comparing.equal(myMaxVersion, plugin.myMaxVersion);
&& Comparing.equal(myMaxVersion, plugin.myMaxVersion)
&& Comparing.equal(myChannel, plugin.myChannel);
}
@Override
public int hashCode() {
return 31 * (31 * myPluginId.hashCode() + Comparing.hashcode(myMinVersion)) + Comparing.hashcode(myMaxVersion);
return 31 * (31 * (31 * myPluginId.hashCode() + Comparing.hashcode(myMinVersion)) + Comparing.hashcode(myMaxVersion)) + Comparing.hashcode(myChannel);
}
@Override
@@ -26,6 +26,7 @@ import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupActivity;
import com.intellij.openapi.updateSettings.impl.UpdateSettings;
import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.PluginsAdvertiser;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.text.VersionComparatorUtil;
@@ -42,6 +43,7 @@ import java.util.Set;
*/
public class CheckRequiredPluginsActivity implements StartupActivity, DumbAware {
private static final NotificationGroup NOTIFICATION_GROUP = new NotificationGroup("Required Plugins", NotificationDisplayType.BALLOON, true);
public static final String PLUGINS_HOST = "https://plugins.jetbrains.com";
@Override
public void runActivity(@NotNull final Project project) {
@@ -53,11 +55,20 @@ public class CheckRequiredPluginsActivity implements StartupActivity, DumbAware
List<DependencyOnPlugin> dependencies = ExternalDependenciesManager.getInstance(project).getDependencies(DependencyOnPlugin.class);
if (dependencies.isEmpty()) return;
List<String> customRepositories = UpdateSettings.getInstance().getStoredPluginHosts();
final List<String> errorMessages = new ArrayList<String>();
final List<String> missingCustomRepositories = new ArrayList<String>();
final List<IdeaPluginDescriptor> disabled = new ArrayList<IdeaPluginDescriptor>();
final List<PluginId> notInstalled = new ArrayList<PluginId>();
for (DependencyOnPlugin dependency : dependencies) {
PluginId pluginId = PluginId.getId(dependency.getPluginId());
String channel = dependency.getChannel();
String customRepository = getCustomRepository(pluginId, channel);
if (!StringUtil.isEmpty(channel) && customRepositoryNotSpecified(customRepositories, customRepository)) {
errorMessages.add("Custom repository '" + customRepository + "' required for '" + project.getName() + "' project isn't installed.");
missingCustomRepositories.add(customRepository);
}
IdeaPluginDescriptor plugin = PluginManager.getPlugin(pluginId);
if (plugin == null) {
errorMessages.add("Plugin '" + dependency.getPluginId() + "' required for '" + project.getName() + "' project isn't installed.");
@@ -80,7 +91,10 @@ public class CheckRequiredPluginsActivity implements StartupActivity, DumbAware
}
if (!errorMessages.isEmpty()) {
if (!disabled.isEmpty() && notInstalled.isEmpty()) {
if (!missingCustomRepositories.isEmpty()) {
errorMessages.add("<a href=\"addRepositories\">Add custom repositories and install required plugins</a>");
}
else if (!disabled.isEmpty() && notInstalled.isEmpty()) {
String plugins = disabled.size() == 1 ? disabled.get(0).getName() : "required plugins";
errorMessages.add("<a href=\"enable\">Enable " + plugins + "</a>");
}
@@ -94,6 +108,9 @@ public class CheckRequiredPluginsActivity implements StartupActivity, DumbAware
public void hyperlinkUpdate(@NotNull final Notification notification,
@NotNull HyperlinkEvent event) {
if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
if ("addRepositories".equals(event.getDescription())) {
UpdateSettings.getInstance().getStoredPluginHosts().addAll(missingCustomRepositories);
}
if ("enable".equals(event.getDescription())) {
notification.expire();
for (IdeaPluginDescriptor descriptor : disabled) {
@@ -101,7 +118,7 @@ public class CheckRequiredPluginsActivity implements StartupActivity, DumbAware
}
PluginManagerMain.notifyPluginsUpdated(project);
}
else {
else if ("install".equals(event.getDescription()) || "addRepositories".equals(event.getDescription())) {
Set<String> pluginIds = new HashSet<String>();
for (IdeaPluginDescriptor descriptor : disabled) {
pluginIds.add(descriptor.getPluginId().getIdString());
@@ -121,4 +138,12 @@ public class CheckRequiredPluginsActivity implements StartupActivity, DumbAware
}).notify(project);
}
}
private static boolean customRepositoryNotSpecified(List<String> repositories, String customRepository) {
return !repositories.contains(customRepository);
}
private static String getCustomRepository(PluginId id, String channel) {
return String.format(PLUGINS_HOST + "/plugins/%s/%s", channel, id);
}
}
@@ -31,6 +31,7 @@ class DependencyOnPluginState {
myId = dependency.getPluginId();
myMinVersion = dependency.getMinVersion();
myMaxVersion = dependency.getMaxVersion();
myChannel = dependency.getChannel();
}
@Attribute("id")
@@ -39,4 +40,6 @@ class DependencyOnPluginState {
public String myMinVersion;
@Attribute("max-version")
public String myMaxVersion;
@Attribute("channel")
public String myChannel;
}
@@ -117,7 +117,7 @@ public class ExternalDependenciesConfigurable implements SearchableConfigurable,
.setAddAction(new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
replaceDependency(new DependencyOnPlugin("", null, null), dependenciesList);
replaceDependency(new DependencyOnPlugin("", null, null, null), dependenciesList);
}
})
.setEditAction(new AnActionButtonRunnable() {
@@ -198,14 +198,17 @@ public class ExternalDependenciesConfigurable implements SearchableConfigurable,
final JBTextField minVersionField = new JBTextField(StringUtil.notNullize(original.getMinVersion()));
final JBTextField maxVersionField = new JBTextField(StringUtil.notNullize(original.getMaxVersion()));
final JBTextField channelField = new JBTextField(StringUtil.notNullize(original.getChannel()));
minVersionField.getEmptyText().setText("<any>");
minVersionField.setColumns(10);
maxVersionField.getEmptyText().setText("<any>");
maxVersionField.setColumns(10);
channelField.setColumns(10);
JPanel panel = FormBuilder.createFormBuilder()
.addLabeledComponent("Plugin:", pluginChooser)
.addLabeledComponent("Minimum version:", minVersionField)
.addLabeledComponent("Maximum version:", maxVersionField)
.addLabeledComponent("Channel:", channelField)
.getPanel();
final DialogBuilder dialogBuilder = new DialogBuilder(parent).title("Required Plugin").centerPanel(panel);
dialogBuilder.setPreferredFocusComponent(pluginChooser);
@@ -218,7 +221,8 @@ public class ExternalDependenciesConfigurable implements SearchableConfigurable,
if (dialogBuilder.show() == DialogWrapper.OK_EXIT_CODE) {
return new DependencyOnPlugin(((String)pluginChooser.getSelectedItem()),
StringUtil.nullize(minVersionField.getText().trim()),
StringUtil.nullize(maxVersionField.getText().trim()));
StringUtil.nullize(maxVersionField.getText().trim()),
StringUtil.nullize(channelField.getText().trim()));
}
return null;
}
@@ -96,7 +96,7 @@ public class ExternalDependenciesManagerImpl extends ExternalDependenciesManager
ArrayList<ProjectExternalDependency> oldDependencies = new ArrayList<ProjectExternalDependency>(myDependencies);
myDependencies.clear();
for (DependencyOnPluginState dependency : state.myDependencies) {
myDependencies.add(new DependencyOnPlugin(dependency.myId, dependency.myMinVersion, dependency.myMaxVersion));
myDependencies.add(new DependencyOnPlugin(dependency.myId, dependency.myMinVersion, dependency.myMaxVersion, dependency.myChannel));
}
if (!oldDependencies.equals(myDependencies) && !myDependencies.isEmpty()) {
StartupManager.getInstance(myProject).runWhenProjectIsInitialized(new DumbAwareRunnable() {