From 014111286e250811e7b07894b3471290fccb5fce Mon Sep 17 00:00:00 2001 From: Dmitry Kandalov Date: Sat, 21 Sep 2024 21:51:08 +0100 Subject: [PATCH] combined AddPluginFromGistOrGitAction action (removed AddPluginFromGitAction and related classes) --- resources/META-INF/github-integration.xml | 2 +- .../actions/gist/AddPluginFromGistAction.kt | 81 ---- .../gist/AddPluginFromGistOrGitAction.kt | 137 +++++++ .../actions/git/AddPluginFromGitAction.kt | 120 ------ .../com/intellij/dvcs/ui/CloneDvcsDialog.form | 88 ----- .../com/intellij/dvcs/ui/CloneDvcsDialog.java | 350 ------------------ .../implementation/actions/git/git-actions.kt | 8 +- .../toolwindow/NewElementPopupAction.kt | 6 +- .../actions/toolwindow/PluginToolWindow.kt | 6 +- 9 files changed, 145 insertions(+), 653 deletions(-) delete mode 100644 src/main/liveplugin/implementation/actions/gist/AddPluginFromGistAction.kt create mode 100644 src/main/liveplugin/implementation/actions/gist/AddPluginFromGistOrGitAction.kt delete mode 100644 src/main/liveplugin/implementation/actions/git/AddPluginFromGitAction.kt delete mode 100644 src/main/liveplugin/implementation/actions/git/com/intellij/dvcs/ui/CloneDvcsDialog.form delete mode 100644 src/main/liveplugin/implementation/actions/git/com/intellij/dvcs/ui/CloneDvcsDialog.java diff --git a/resources/META-INF/github-integration.xml b/resources/META-INF/github-integration.xml index ecf377f7..b9ed0c8d 100644 --- a/resources/META-INF/github-integration.xml +++ b/resources/META-INF/github-integration.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/src/main/liveplugin/implementation/actions/gist/AddPluginFromGistAction.kt b/src/main/liveplugin/implementation/actions/gist/AddPluginFromGistAction.kt deleted file mode 100644 index e193391f..00000000 --- a/src/main/liveplugin/implementation/actions/gist/AddPluginFromGistAction.kt +++ /dev/null @@ -1,81 +0,0 @@ -package liveplugin.implementation.actions.gist - -import com.intellij.icons.AllIcons -import com.intellij.openapi.actionSystem.AnAction -import com.intellij.openapi.actionSystem.AnActionEvent -import com.intellij.openapi.progress.ProgressIndicator -import com.intellij.openapi.progress.Task -import com.intellij.openapi.project.DumbAware -import com.intellij.openapi.project.Project -import com.intellij.util.net.JdkProxyProvider -import liveplugin.implementation.LivePluginPaths.livePluginsPath -import liveplugin.implementation.actions.gist.GistApi.FailedRequest -import liveplugin.implementation.actions.gist.GistApi.Gist -import liveplugin.implementation.actions.isNewPluginNameValidator -import liveplugin.implementation.common.IdeUtil.runLaterOnEdt -import liveplugin.implementation.common.IdeUtil.showError -import liveplugin.implementation.common.IdeUtil.showInputDialog -import liveplugin.implementation.common.createFile -import liveplugin.implementation.common.inputValidator -import java.io.IOException -import java.net.URI - -class AddPluginFromGistAction : AnAction("Copy from Gist", "Copy from Gist", AllIcons.Vcs.Vendors.Github), DumbAware { - - override fun actionPerformed(event: AnActionEvent) { - val project = event.project - val gistUrl = project.showInputDialog( - message = "Enter Gist URL:", - dialogTitle, - inputValidator { if (extractGistIdFrom(it) == null) "Couldn't parse Gist URL" else null } - ) ?: return - - fetchGist( - gistUrl, - project, - onSuccess = { gist -> - val newPluginId = project.showInputDialog(message = "Enter new plugin name:", dialogTitle, isNewPluginNameValidator, gist.description) - if (newPluginId != null) { - try { - gist.files.forEach { (filename, file) -> - createFile("$livePluginsPath/$newPluginId", filename, file.content) - } - } catch (e: IOException) { - project.showError("Error adding plugin \"$newPluginId\": ${e.message}", e) - } - } - }, - onFailure = { e -> - project.showError("Failed to fetch Gist: ${e.message}", e) - } - ) - } - - private fun fetchGist( - gistUrl: String, - project: Project?, - onSuccess: (Gist) -> Unit, - onFailure: (FailedRequest) -> Unit - ) { - object : Task.Backgroundable(project, "Fetching gist…", true, ALWAYS_BACKGROUND) { - override fun run(indicator: ProgressIndicator) { - try { - val proxy = JdkProxyProvider.getInstance().proxySelector.select(URI("https://api.github.com/gists")).firstOrNull() - val gist = GistApiHttp(proxy).getGist(extractGistIdFrom(gistUrl)!!) - runLaterOnEdt { onSuccess(gist) } - } catch (e: FailedRequest) { - runLaterOnEdt { onFailure(e) } - } - } - }.queue() - } - - private companion object { - private const val dialogTitle = "Copy Plugin From Gist" - - private fun extractGistIdFrom(gistUrl: String): String? { - val i = gistUrl.lastIndexOf('/') - return if (i == -1) null else gistUrl.substring(i + 1) - } - } -} diff --git a/src/main/liveplugin/implementation/actions/gist/AddPluginFromGistOrGitAction.kt b/src/main/liveplugin/implementation/actions/gist/AddPluginFromGistOrGitAction.kt new file mode 100644 index 00000000..3842b145 --- /dev/null +++ b/src/main/liveplugin/implementation/actions/gist/AddPluginFromGistOrGitAction.kt @@ -0,0 +1,137 @@ +package liveplugin.implementation.actions.gist + +import com.intellij.icons.AllIcons +import com.intellij.openapi.actionSystem.AnAction +import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.components.service +import com.intellij.openapi.diagnostic.Logger +import com.intellij.openapi.progress.ProgressIndicator +import com.intellij.openapi.progress.Task +import com.intellij.openapi.project.DumbAware +import com.intellij.openapi.project.Project +import com.intellij.openapi.vcs.CheckoutProvider +import com.intellij.openapi.vcs.VcsKey +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.vfs.newvfs.RefreshQueue +import com.intellij.util.net.JdkProxyProvider +import git4idea.checkout.GitCheckoutProvider +import git4idea.commands.Git +import liveplugin.implementation.LivePluginPaths.livePluginsPath +import liveplugin.implementation.actions.gist.GistApi.FailedRequest +import liveplugin.implementation.actions.gist.GistApi.Gist +import liveplugin.implementation.actions.git.isGitHubPluginAvailable +import liveplugin.implementation.actions.isNewPluginNameValidator +import liveplugin.implementation.common.IdeUtil.runLaterOnEdt +import liveplugin.implementation.common.IdeUtil.showError +import liveplugin.implementation.common.IdeUtil.showInputDialog +import liveplugin.implementation.common.createFile +import liveplugin.implementation.common.inputValidator +import java.io.File +import java.io.IOException +import java.net.URI + +class AddPluginFromGistOrGitAction : AnAction("Copy from Gist/Git", "Copy from Gist/Git", AllIcons.Vcs.Vendors.Github), DumbAware { + + override fun actionPerformed(event: AnActionEvent) { + val project = event.project ?: return + val url = project.showInputDialog( + message = "Enter Gist/Git URL:", + title = dialogTitle, + inputValidator = inputValidator { if (extractIdFrom(it) == null) "Invalid Gist/Git URL" else null } + ) ?: return + + if (url.lowercase().startsWith("https://gist.")) { + fetchGist( + url, + project, + onSuccess = { gist -> + val newPluginId = project.showInputDialog( + message = "Enter new plugin name:", + title = dialogTitle, + inputValidator = isNewPluginNameValidator, + initialValue = gist.description + ) + if (newPluginId != null) { + try { + gist.files.forEach { (filename, file) -> + createFile("$livePluginsPath/$newPluginId", filename, file.content) + } + } catch (e: IOException) { + project.showError("Error adding plugin \"$newPluginId\": ${e.message}", e) + } + } + }, + onFailure = { e -> + project.showError("Failed to fetch Gist: ${e.message}", e) + } + ) + } else if (isGitHubPluginAvailable) { + val newPluginId = project.showInputDialog( + message = "Enter new plugin name:", + title = dialogTitle, + inputValidator = isNewPluginNameValidator, + initialValue = url.takeLastWhile { it != '/' } + ) ?: return + + val gitService = service() + val destinationFolder = livePluginsPath.toVirtualFile() ?: return + GitCheckoutProvider.clone( + /* project = */ project, + /* git = */ gitService, + /* listener = */ GitCheckoutListener(destinationFolder, newPluginId), + /* destinationParent = */ destinationFolder, + /* sourceRepositoryURL = */ url, + /* directoryName = */ newPluginId, + /* parentDirectory = */ destinationFolder.path + ) + } else { + project.showError("Cannot clone project without GitHub plugin.") + } + } + + private fun fetchGist( + gistUrl: String, + project: Project?, + onSuccess: (Gist) -> Unit, + onFailure: (FailedRequest) -> Unit + ) { + object : Task.Backgroundable(project, "Fetching gist…", true, ALWAYS_BACKGROUND) { + override fun run(indicator: ProgressIndicator) { + try { + val proxy = JdkProxyProvider.getInstance().proxySelector.select(URI("https://api.github.com/gists")).firstOrNull() + val gist = GistApiHttp(proxy).getGist(extractIdFrom(gistUrl)!!) + runLaterOnEdt { onSuccess(gist) } + } catch (e: FailedRequest) { + runLaterOnEdt { onFailure(e) } + } + } + }.queue() + } + + private class GitCheckoutListener( + private val destinationFolder: VirtualFile, + private val pluginName: String + ): CheckoutProvider.Listener { + private val logger = Logger.getInstance(GitCheckoutListener::class.java) + + override fun directoryCheckedOut(directory: File, vcs: VcsKey) {} + + override fun checkoutCompleted() { + val finishRunnable = Runnable { + val clonedFolder = destinationFolder.findChild(pluginName) + if (clonedFolder == null) logger.error("Couldn't find virtual file for checked out plugin: $pluginName") + } + val pluginsRoot = livePluginsPath.toVirtualFile() ?: return + RefreshQueue.getInstance().refresh(false, true, finishRunnable, pluginsRoot) + } + } + + private companion object { + private const val dialogTitle = "Copy Plugin From Gist/Git" + + private fun extractIdFrom(gistOrGitUrl: String): String? { + val i = gistOrGitUrl.lastIndexOf('/') + return if (i == -1) null else gistOrGitUrl.substring(i + 1) + } + } +} diff --git a/src/main/liveplugin/implementation/actions/git/AddPluginFromGitAction.kt b/src/main/liveplugin/implementation/actions/git/AddPluginFromGitAction.kt deleted file mode 100644 index 6235c29d..00000000 --- a/src/main/liveplugin/implementation/actions/git/AddPluginFromGitAction.kt +++ /dev/null @@ -1,120 +0,0 @@ -package liveplugin.implementation.actions.git - -import com.intellij.icons.AllIcons -import com.intellij.openapi.actionSystem.AnAction -import com.intellij.openapi.actionSystem.AnActionEvent -import com.intellij.openapi.application.runWriteAction -import com.intellij.openapi.components.service -import com.intellij.openapi.diagnostic.Logger -import com.intellij.openapi.project.DumbAware -import com.intellij.openapi.project.Project -import com.intellij.openapi.util.Ref -import com.intellij.openapi.vcs.CheckoutProvider -import com.intellij.openapi.vcs.VcsKey -import com.intellij.openapi.vfs.LocalFileSystem -import com.intellij.openapi.vfs.VirtualFile -import com.intellij.openapi.vfs.VirtualFileManager -import com.intellij.openapi.vfs.newvfs.NewVirtualFile -import com.intellij.openapi.vfs.newvfs.RefreshQueue -import git4idea.GitUtil -import git4idea.GitVcs -import git4idea.checkout.GitCheckoutProvider -import git4idea.commands.Git -import git4idea.remote.GitRememberedInputs -import liveplugin.implementation.LivePluginPaths -import liveplugin.implementation.actions.git.com.intellij.dvcs.ui.CloneDvcsDialog -import java.io.File - -/** - * Partially copied from org.jetbrains.plugins.github.GithubCheckoutProvider (became com.intellij.dvcs.ui.CloneDvcsDialog in IJ13) - */ -class AddPluginFromGitAction: AnAction("Clone from Git", "Clone from Git", AllIcons.Vcs.Vendors.Github), DumbAware { - - override fun actionPerformed(event: AnActionEvent) { - val project = event.project ?: return - - val dialog = GitCloneDialog(project) - dialog.show() - if (!dialog.isOK) return - dialog.rememberSettings() - - val destinationFolder = dialog.parentDirectory.refreshAndFindFileByUrl() ?: return - val gitService = service() - - GitCheckoutProvider.clone( - project, - gitService, - MyCheckoutListener(destinationFolder, dialog.directoryName), - destinationFolder, - dialog.sourceRepositoryURL, - dialog.directoryName, - dialog.parentDirectory - ) - } - - private fun String.refreshAndFindFileByUrl(): VirtualFile? = - VirtualFileManager.getInstance().refreshAndFindFileByUrl("file:///$this") - - private class MyCheckoutListener( - private val destinationFolder: VirtualFile, - private val pluginName: String - ): CheckoutProvider.Listener { - - /** - * Copied from [com.intellij.openapi.vcs.checkout.CompositeCheckoutListener] - */ - private fun refreshVFS(directory: File): VirtualFile { - val result = Ref() - runWriteAction { - val lfs = LocalFileSystem.getInstance() - val vDir = lfs.refreshAndFindFileByIoFile(directory) - result.set(vDir) - if (vDir != null) { - val watchRequest = lfs.addRootToWatch(vDir.path, true) - (vDir as NewVirtualFile).markDirtyRecursively() - vDir.refresh(false, true) - if (watchRequest != null) { - lfs.removeWatchedRoot(watchRequest) - } - } - } - return result.get() - } - - override fun directoryCheckedOut(directory: File, vcs: VcsKey) { - refreshVFS(directory) - } - - override fun checkoutCompleted() { - val finishRunnable = Runnable { - val clonedFolder = destinationFolder.findChild(pluginName) - if (clonedFolder == null) { - logger.error("Couldn't find virtual file for checked out plugin: $pluginName") - return@Runnable - } - } - val pluginsRoot = LivePluginPaths.livePluginsPath.toVirtualFile() ?: return - RefreshQueue.getInstance().refresh(false, true, finishRunnable, pluginsRoot) - } - } - - companion object { - private val logger = Logger.getInstance(AddPluginFromGitAction::class.java) - } -} - -private class GitCloneDialog(project: Project): CloneDvcsDialog(project, GitVcs.NAME, GitUtil.DOT_GIT, null) { - - private val myGit = service() - - override fun test(url: String): TestResult { - val result = myGit.lsRemote(myProject, File("."), url) - return if (result.success()) TestResult.SUCCESS else TestResult(result.errorOutputAsJoinedString) - } - - override fun getRememberedInputs() = GitRememberedInputs.getInstance() - - override fun getDimensionServiceKey() = "GitCloneDialog" - - override fun getHelpId() = "reference.VersionControl.Git.CloneRepository" -} \ No newline at end of file diff --git a/src/main/liveplugin/implementation/actions/git/com/intellij/dvcs/ui/CloneDvcsDialog.form b/src/main/liveplugin/implementation/actions/git/com/intellij/dvcs/ui/CloneDvcsDialog.form deleted file mode 100644 index 2e003bf2..00000000 --- a/src/main/liveplugin/implementation/actions/git/com/intellij/dvcs/ui/CloneDvcsDialog.form +++ /dev/null @@ -1,88 +0,0 @@ - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/main/liveplugin/implementation/actions/git/com/intellij/dvcs/ui/CloneDvcsDialog.java b/src/main/liveplugin/implementation/actions/git/com/intellij/dvcs/ui/CloneDvcsDialog.java deleted file mode 100644 index e37d6676..00000000 --- a/src/main/liveplugin/implementation/actions/git/com/intellij/dvcs/ui/CloneDvcsDialog.java +++ /dev/null @@ -1,350 +0,0 @@ -package liveplugin.implementation.actions.git.com.intellij.dvcs.ui; - -import com.intellij.dvcs.DvcsRememberedInputs; -import com.intellij.dvcs.ui.DvcsBundle; -import com.intellij.ide.FrameStateListener; -import com.intellij.openapi.fileChooser.FileChooserDescriptor; -import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; -import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectUtil; -import com.intellij.openapi.ui.*; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.ui.DocumentAdapter; -import com.intellij.ui.EditorComboBox; -import com.intellij.util.ArrayUtil; -import liveplugin.implementation.LivePluginPaths; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import javax.swing.*; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import java.io.File; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.regex.Pattern; - -/** - * TODO check if existing clone dialog can be reused or fork the code again - *

- * This is a fork of com.intellij.dvcs.ui.CloneDvcsDialog. - * The reason for fork is to disable "parent directory" and "directory name" text fields. - */ -public abstract class CloneDvcsDialog extends DialogWrapper { - /** - * The pattern for SSH URL-s in form [user@]host:path - */ - private static final Pattern SSH_URL_PATTERN; - - static { - // TODO make real URL pattern - @NonNls final String ch = "[\\p{ASCII}&&[\\p{Graph}]&&[^@:/]]"; - @NonNls final String host = ch + "+(?:\\." + ch + "+)*"; - @NonNls final String path = "/?" + ch + "+(?:/" + ch + "+)*/?"; - @NonNls final String all = "(?:" + ch + "+@)?" + host + ":" + path; - SSH_URL_PATTERN = Pattern.compile(all); - } - - private JPanel myRootPanel; - private EditorComboBox myRepositoryURL; - private TextFieldWithBrowseButton myParentDirectory; - private JButton myTestButton; // test repository - private JTextField myDirectoryName; - private JLabel myRepositoryUrlLabel; - - @NotNull private String myTestURL; // the repository URL at the time of the last test - @Nullable private Boolean myTestResult; // the test result of the last test or null if not tested - @NotNull private String myDefaultDirectoryName = ""; - @NotNull protected final Project myProject; - @NotNull protected final String myVcsDirectoryName; - @Nullable private final String myDefaultRepoUrl; - - public CloneDvcsDialog(@NotNull Project project, @NotNull String displayName, @NotNull String vcsDirectoryName) { - this(project, displayName, vcsDirectoryName, null); - } - - public CloneDvcsDialog(@NotNull Project project, @NotNull String displayName, @NotNull String vcsDirectoryName, @Nullable String defaultUrl) { - super(project, true); - myDefaultRepoUrl = defaultUrl; - myProject = project; - myVcsDirectoryName = vcsDirectoryName; - init(); - initListeners(); - setTitle(DvcsBundle.message("clone.title")); - myRepositoryUrlLabel.setText("Clone Repository URL"); // FORK DIFF - myRepositoryUrlLabel.setDisplayedMnemonic('R'); - setOKButtonText(DvcsBundle.message("clone.button")); - - project.getMessageBus().connect(getDisposable()).subscribe(FrameStateListener.TOPIC, new FrameStateListener() { - @Override - public void onFrameActivated() { - updateButtons(); - } - }); - } - - @Override - protected void doOKAction() { - File parent = new File(getParentDirectory()); - if (parent.exists() && parent.isDirectory() && parent.canWrite() || parent.mkdirs()) { - super.doOKAction(); - return; - } - setErrorText("Couldn't create " + parent + "
Check your access rights"); - setOKActionEnabled(false); - } - - @NotNull - public String getSourceRepositoryURL() { - return getCurrentUrlText(); - } - - public String getParentDirectory() { - return myParentDirectory.getText(); - } - - public String getDirectoryName() { - return myDirectoryName.getText(); - } - - /** - * Init components - */ - private void initListeners() { - FileChooserDescriptor fcd = FileChooserDescriptorFactory.createSingleFolderDescriptor(); - fcd.setShowFileSystemRoots(true); - fcd.setTitle(DvcsBundle.message("clone.destination.directory.browser.title")); - fcd.setDescription(DvcsBundle.message("clone.destination.directory.browser.description")); - fcd.setHideIgnored(false); - myParentDirectory.addActionListener( - new ComponentWithBrowseButton.BrowseFolderActionListener<>(fcd.getTitle(), fcd.getDescription(), myParentDirectory, - myProject, fcd, TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT) { - @Override - protected VirtualFile getInitialFile() { - return ProjectUtil.guessProjectDir(myProject); - } - } - ); - - final DocumentListener updateOkButtonListener = new DocumentAdapter() { - @Override - protected void textChanged(@NotNull DocumentEvent e) { - updateButtons(); - } - }; - myParentDirectory.getChildComponent().getDocument().addDocumentListener(updateOkButtonListener); - // FORK DIFF ↓↓↓ -// String parentDir = getRememberedInputs().getCloneParentDir(); -// if (StringUtil.isEmptyOrSpaces(parentDir)) { -// parentDir = ProjectUtil.getBaseDir(); -// } - //noinspection ConstantIfStatement - myParentDirectory.setText(LivePluginPaths.livePluginsPath.getValue()); - // FORK DIFF ↑↑↑ - - myDirectoryName.getDocument().addDocumentListener(updateOkButtonListener); - - myTestButton.addActionListener(e -> test()); - - setOKActionEnabled(false); - myTestButton.setEnabled(false); - } - - private void test() { - myTestURL = getCurrentUrlText(); - TestResult testResult = ProgressManager.getInstance().runProcessWithProgressSynchronously( - () -> test(myTestURL), DvcsBundle.message("clone.testing", myTestURL), true, myProject); - if (testResult.isSuccess()) { - Messages.showInfoMessage(myTestButton, DvcsBundle.message("clone.test.success.message", myTestURL), - DvcsBundle.message("clone.repository.url.test.label")); - myTestResult = Boolean.TRUE; - } else { - Messages.showErrorDialog(myProject, Objects.requireNonNull(testResult.getError()), "Repository Test Failed"); - myTestResult = Boolean.FALSE; - } - updateButtons(); - } - - @NotNull - protected abstract TestResult test(@NotNull String url); - - @NotNull - protected abstract DvcsRememberedInputs getRememberedInputs(); - - /** - * Check fields and display error in the wrapper if there is a problem - */ - private void updateButtons() { - if (!checkRepositoryURL()) { - return; - } - if (!checkDestination()) { - return; - } - setErrorText(null); - setOKActionEnabled(true); - } - - /** - * Check destination directory and set appropriate error text if there are problems - * - * @return true if destination components are OK. - */ - private boolean checkDestination() { - if (myParentDirectory.getText().isEmpty() || myDirectoryName.getText().isEmpty()) { - setErrorText(null); - setOKActionEnabled(false); - return false; - } - File file = new File(myParentDirectory.getText(), myDirectoryName.getText()); - if (file.exists() && (!file.isDirectory()) || !ArrayUtil.isEmpty(file.list())) { - setErrorText(DvcsBundle.message("clone.destination.exists.error", file)); - setOKActionEnabled(false); - return false; - } - return true; - } - - /** - * Check repository URL and set appropriate error text if there are problems - * - * @return true if repository URL is OK. - */ - private boolean checkRepositoryURL() { - String repository = getCurrentUrlText(); - if (repository.isEmpty()) { - setErrorText(null); - setOKActionEnabled(false); - return false; - } - if (myTestResult != null && repository.equals(myTestURL)) { - if (!myTestResult) { - setErrorText("Repository test has failed."); - setOKActionEnabled(false); - return false; - } else { - return true; - } - } - try { - if (new URI(repository).isAbsolute()) { - return true; - } - } catch (URISyntaxException urlExp) { - // do nothing - } - // check if ssh url pattern - if (SSH_URL_PATTERN.matcher(repository).matches()) { - return true; - } - try { - File file = new File(repository); - if (file.exists()) { - if (!file.isDirectory()) { - setErrorText("Repository URL is not a directory."); - setOKActionEnabled(false); - } - return true; - } - } catch (Exception fileExp) { - // do nothing - } - setErrorText("Repository URL is a malformed URL or non-existent directory."); - setOKActionEnabled(false); - return false; - } - - @NotNull - private String getCurrentUrlText() { - return FileUtil.expandUserHome(myRepositoryURL.getText().trim()); - } - - private void createUIComponents() { - myRepositoryURL = new EditorComboBox(""); - final DvcsRememberedInputs rememberedInputs = getRememberedInputs(); - List urls = new ArrayList<>(rememberedInputs.getVisitedUrls()); - if (myDefaultRepoUrl != null) { - urls.addFirst(myDefaultRepoUrl); - } - myRepositoryURL.setHistory(ArrayUtil.toObjectArray(urls, String.class)); - myRepositoryURL.addDocumentListener(new com.intellij.openapi.editor.event.DocumentListener() { - @Override - public void documentChanged(@NotNull com.intellij.openapi.editor.event.DocumentEvent e) { - // enable test button only if something is entered in repository URL - final String url = getCurrentUrlText(); - myTestButton.setEnabled(!url.isEmpty()); - if (myDefaultDirectoryName.equals(myDirectoryName.getText()) || myDirectoryName.getText().isEmpty()) { - // modify field if it was unmodified or blank - myDefaultDirectoryName = defaultDirectoryName(url, myVcsDirectoryName); - myDirectoryName.setText(myDefaultDirectoryName); - } - updateButtons(); - } - }); - } - - public void rememberSettings() { - final DvcsRememberedInputs rememberedInputs = getRememberedInputs(); - rememberedInputs.addUrl(getSourceRepositoryURL()); - rememberedInputs.setCloneParentDir(getParentDirectory()); - } - - /** - * Get default name for checked out directory - * - * @param url an URL to checkout - * @return a default repository name - */ - @NotNull - private static String defaultDirectoryName(@NotNull final String url, @NotNull final String vcsDirName) { - String nonSystemName; - if (url.endsWith("/" + vcsDirName) || url.endsWith(File.separator + vcsDirName)) { - nonSystemName = url.substring(0, url.length() - vcsDirName.length() - 1); - } else { - if (url.endsWith(vcsDirName)) { - nonSystemName = url.substring(0, url.length() - vcsDirName.length()); - } else { - nonSystemName = url; - } - } - int i = nonSystemName.lastIndexOf('/'); - if (i == -1 && File.separatorChar != '/') { - i = nonSystemName.lastIndexOf(File.separatorChar); - } - return i >= 0 ? nonSystemName.substring(i + 1) : ""; - } - - @Nullable - @Override - public JComponent getPreferredFocusedComponent() { - return myRepositoryURL; - } - - protected JComponent createCenterPanel() { - return myRootPanel; - } - - protected static class TestResult { - @NotNull public static final TestResult SUCCESS = new TestResult(null); - @Nullable private final String myErrorMessage; - - public TestResult(@Nullable String errorMessage) { - myErrorMessage = errorMessage; - } - - boolean isSuccess() { - return myErrorMessage == null; - } - - @Nullable - public String getError() { - return myErrorMessage; - } - } -} diff --git a/src/main/liveplugin/implementation/actions/git/git-actions.kt b/src/main/liveplugin/implementation/actions/git/git-actions.kt index 23550ec5..ffb43f2f 100644 --- a/src/main/liveplugin/implementation/actions/git/git-actions.kt +++ b/src/main/liveplugin/implementation/actions/git/git-actions.kt @@ -8,16 +8,14 @@ import com.intellij.openapi.project.DumbAware import liveplugin.implementation.actions.gist.SharePluginAsGistAction import kotlin.reflect.KMutableProperty0 -var addFromGitHubAction: AnAction? = null -class AddPluginFromGitHubDelegateAction: DelegateAction(::addFromGitHubAction) - var shareAsGistAction: AnAction? = null class SharePluginAsGistDelegateAction: DelegateAction(::shareAsGistAction) +var isGitHubPluginAvailable = false -class GitDependentAppComponent : AppLifecycleListener { +class GitHubPluginDependencyAppComponent : AppLifecycleListener { override fun appFrameCreated(commandLineArgs: MutableList) { - addFromGitHubAction = AddPluginFromGitAction() shareAsGistAction = SharePluginAsGistAction() + isGitHubPluginAvailable = true } } diff --git a/src/main/liveplugin/implementation/actions/toolwindow/NewElementPopupAction.kt b/src/main/liveplugin/implementation/actions/toolwindow/NewElementPopupAction.kt index 47bbeff5..d94c0f78 100644 --- a/src/main/liveplugin/implementation/actions/toolwindow/NewElementPopupAction.kt +++ b/src/main/liveplugin/implementation/actions/toolwindow/NewElementPopupAction.kt @@ -13,8 +13,7 @@ import liveplugin.implementation.actions.AddGroovyExamplesActionGroup import liveplugin.implementation.actions.AddKotlinExamplesActionGroup import liveplugin.implementation.actions.AddNewGroovyPluginAction import liveplugin.implementation.actions.AddNewKotlinPluginAction -import liveplugin.implementation.actions.gist.AddPluginFromGistAction -import liveplugin.implementation.actions.git.AddPluginFromGitHubDelegateAction +import liveplugin.implementation.actions.gist.AddPluginFromGistOrGitAction import liveplugin.implementation.common.Icons.newFolderIcon import liveplugin.implementation.common.IdeUtil.groovyFileType import liveplugin.implementation.common.IdeUtil.kotlinFileType @@ -60,8 +59,7 @@ class NewElementPopupAction: AnAction(), DumbAware, PopupAction { Separator.getInstance(), AddNewKotlinPluginAction(), AddNewGroovyPluginAction(), - AddPluginFromGistAction(), - AddPluginFromGitHubDelegateAction(), + AddPluginFromGistOrGitAction(), AddKotlinExamplesActionGroup(), AddGroovyExamplesActionGroup(), ) diff --git a/src/main/liveplugin/implementation/actions/toolwindow/PluginToolWindow.kt b/src/main/liveplugin/implementation/actions/toolwindow/PluginToolWindow.kt index 721ea793..6e2a3426 100644 --- a/src/main/liveplugin/implementation/actions/toolwindow/PluginToolWindow.kt +++ b/src/main/liveplugin/implementation/actions/toolwindow/PluginToolWindow.kt @@ -32,8 +32,7 @@ import com.intellij.util.EditSourceOnEnterKeyHandler import com.intellij.util.ui.tree.TreeUtil import liveplugin.implementation.LivePluginPaths.livePluginsPath import liveplugin.implementation.actions.* -import liveplugin.implementation.actions.gist.AddPluginFromGistAction -import liveplugin.implementation.actions.git.AddPluginFromGitHubDelegateAction +import liveplugin.implementation.actions.gist.AddPluginFromGistOrGitAction import liveplugin.implementation.actions.git.SharePluginAsGistDelegateAction import liveplugin.implementation.actions.settings.AddLivePluginAndIdeJarsAsDependencies import liveplugin.implementation.actions.settings.RunPluginsOnIDEStartAction @@ -82,8 +81,7 @@ private class PluginToolWindow(project: Project) { add(DefaultActionGroup("Add Plugin", true).apply { add(AddNewKotlinPluginAction()) add(AddNewGroovyPluginAction()) - add(AddPluginFromGistAction()) - add(AddPluginFromGitHubDelegateAction()) + add(AddPluginFromGistOrGitAction()) add(AddKotlinExamplesActionGroup()) add(AddGroovyExamplesActionGroup()) }.with(addPluginIcon))