void installOrUpdatePlugin(@Nullable JComponent parentComponent,
                             @NotNull IdeaPluginDescriptor descriptor,
                             @Nullable IdeaPluginDescriptor updateDescriptor,
                             @NotNull ModalityState modalityState) {
    boolean isUpdate = updateDescriptor != null;
    IdeaPluginDescriptor actionDescriptor = isUpdate ? updateDescriptor : descriptor;
    if (!PluginManagerMain.checkThirdPartyPluginsAllowed(List.of(actionDescriptor))) {
      return;
    }

    if (myInstallSource != null) {
      String pluginId = descriptor.getPluginId().getIdString();
      myInstallSource.logInstallPlugins(Collections.singletonList(pluginId));
    }

    if (descriptor instanceof PluginNode node) {
      FUSEventSource installSource = node.getInstallSource();
      if (installSource != null) {
        installSource.logInstallPlugins(List.of(descriptor.getPluginId().getIdString()));
      }
    }

    Ref<Boolean> allowInstallWithoutRestart = Ref.create(true);
    if (isUpdate) {
      IdeaPluginDescriptorImpl installedPluginDescriptor = (IdeaPluginDescriptorImpl)descriptor;
      if (installedPluginDescriptor.isBundled()) {
        allowInstallWithoutRestart.set(
          DynamicPlugins.allowLoadUnloadWithoutRestart(installedPluginDescriptor) &&
          DynamicPlugins.allowLoadUnloadSynchronously(installedPluginDescriptor) &&
          PluginInstaller.unloadDynamicPlugin(parentComponent, installedPluginDescriptor, true));
      }
      else if (!DynamicPlugins.allowLoadUnloadWithoutRestart(installedPluginDescriptor)) {
        allowInstallWithoutRestart.set(false);
      }
      else if (!installedPluginDescriptor.isEnabled()) {
        try {
          FileUtil.delete(installedPluginDescriptor.getPluginPath());
        }
        catch (IOException e) {
          LOG.debug(e);
        }
      }
      else if (DynamicPlugins.allowLoadUnloadSynchronously(installedPluginDescriptor)) {
        allowInstallWithoutRestart.set(PluginInstaller.uninstallDynamicPlugin(parentComponent,
                                                                              installedPluginDescriptor,
                                                                              true));
      }
      else {
        performUninstall(installedPluginDescriptor);
      }
    }

    ProgressManager.getInstance()
      .runProcessWithProgressAsynchronously(new Task.Backgroundable(getProject(),
                                                                    parentComponent,
                                                                    IdeBundle.message("progress.title.loading.plugin.details"),
                                                                    true,
                                                                    null) {
        @Override
        public void run(@NotNull ProgressIndicator indicator) {
          PluginNode pluginNode = toPluginNode(actionDescriptor, indicator);
          if (pluginNode == null) {
            return;
          }

          List<PluginNode> pluginsToInstall = List.of(pluginNode);
          ApplicationManager.getApplication().invokeAndWait(() -> {
            PluginManagerMain.suggestToEnableInstalledDependantPlugins(MyPluginModel.this,
                                                                       pluginsToInstall);
          }, modalityState);


          InstallPluginInfo info = new InstallPluginInfo((BgProgressIndicator)indicator,
                                                         descriptor,
                                                         MyPluginModel.this,
                                                         !isUpdate);
          ApplicationManager.getApplication().invokeLater(() -> prepareToInstall(info), modalityState);

          PluginInstallOperation operation = new PluginInstallOperation(pluginsToInstall,
                                                                        getCustomRepoPlugins(),
                                                                        MyPluginModel.this,
                                                                        indicator);
          operation.setAllowInstallWithoutRestart(allowInstallWithoutRestart.get());

          runInstallOperation(operation, info, modalityState);
        }

        private static @Nullable PluginNode toPluginNode(@NotNull IdeaPluginDescriptor descriptor, @NotNull ProgressIndicator indicator) {
          if (descriptor instanceof PluginNode pluginNode) {
            return pluginNode.detailsLoaded() ?
                   pluginNode :
                   MarketplaceRequests.getInstance().loadPluginDetails(pluginNode, indicator);
          }
          else {
            PluginNode pluginNode = new PluginNode(descriptor.getPluginId(),
                                                   descriptor.getName(),
                                                   "-1");
            pluginNode.setDependencies(descriptor.getDependencies());
            pluginNode.setRepositoryName(PluginInstaller.UNKNOWN_HOST_MARKER);
            return pluginNode;
          }
        }
      }, new BgProgressIndicator());
  }
void installOrUpdatePlugin(@Nullable JComponent parentComponent,
                             @NotNull IdeaPluginDescriptor descriptor,
                             @Nullable IdeaPluginDescriptor updateDescriptor,
                             @NotNull ModalityState modalityState)