From e7cabd4603bb5269a8c4380075782f58adb220ae Mon Sep 17 00:00:00 2001 From: Constantine Plotnikov Date: Mon, 2 Nov 2009 23:04:34 +0300 Subject: [PATCH] git4idea: refactored rebase editor service to support other types of rebase editors --- .../GitAbstractRebaseResumeAction.java | 4 +- .../git4idea/actions/GitRebaseActionBase.java | 11 +- .../GitInteractiveRebaseEditorHandler.java | 155 ++++++++++++++++++ .../rebase/GitRebaseEditorHandler.java | 135 +-------------- .../rebase/GitRebaseEditorService.java | 43 +++-- 5 files changed, 191 insertions(+), 157 deletions(-) create mode 100644 plugins/git4idea/src/git4idea/rebase/GitInteractiveRebaseEditorHandler.java diff --git a/plugins/git4idea/src/git4idea/actions/GitAbstractRebaseResumeAction.java b/plugins/git4idea/src/git4idea/actions/GitAbstractRebaseResumeAction.java index 6f2ffc1b6fd8..588dc50c3b07 100644 --- a/plugins/git4idea/src/git4idea/actions/GitAbstractRebaseResumeAction.java +++ b/plugins/git4idea/src/git4idea/actions/GitAbstractRebaseResumeAction.java @@ -21,9 +21,9 @@ import com.intellij.openapi.vfs.VirtualFile; import git4idea.commands.GitHandler; import git4idea.commands.GitLineHandler; import git4idea.i18n.GitBundle; +import git4idea.rebase.GitInteractiveRebaseEditorHandler; import git4idea.rebase.GitRebaseActionDialog; import git4idea.rebase.GitRebaseUtils; -import git4idea.rebase.GitRebaseEditorHandler; import org.jetbrains.annotations.NonNls; import java.util.Iterator; @@ -70,7 +70,7 @@ public abstract class GitAbstractRebaseResumeAction extends GitRebaseActionBase * {@inheritDoc} */ @Override - protected void configureEditor(GitRebaseEditorHandler editor) { + protected void configureEditor(GitInteractiveRebaseEditorHandler editor) { editor.setRebaseEditorShown(); } diff --git a/plugins/git4idea/src/git4idea/actions/GitRebaseActionBase.java b/plugins/git4idea/src/git4idea/actions/GitRebaseActionBase.java index e69c9861eef0..530df73b7f15 100644 --- a/plugins/git4idea/src/git4idea/actions/GitRebaseActionBase.java +++ b/plugins/git4idea/src/git4idea/actions/GitRebaseActionBase.java @@ -19,12 +19,10 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; -import git4idea.commands.GitHandler; import git4idea.commands.GitHandlerUtil; import git4idea.commands.GitLineHandler; import git4idea.i18n.GitBundle; -import git4idea.rebase.GitRebaseEditorHandler; -import git4idea.rebase.GitRebaseEditorMain; +import git4idea.rebase.GitInteractiveRebaseEditorHandler; import git4idea.rebase.GitRebaseEditorService; import git4idea.rebase.GitRebaseLineListener; import org.jetbrains.annotations.NotNull; @@ -51,14 +49,13 @@ public abstract class GitRebaseActionBase extends GitRepositoryAction { } final VirtualFile root = h.workingDirectoryFile(); GitRebaseEditorService service = GitRebaseEditorService.getInstance(); - GitRebaseEditorHandler editor = service.getHandler(project, root); + GitInteractiveRebaseEditorHandler editor = new GitInteractiveRebaseEditorHandler(service, project, root); GitRebaseLineListener resultListener = new GitRebaseLineListener(); h.addLineListener(resultListener); configureEditor(editor); affectedRoots.add(root); try { - h.setEnvironment(GitHandler.GIT_EDITOR_ENV, service.getEditorCommand()); - h.setEnvironment(GitRebaseEditorMain.IDEA_REBASE_HANDER_NO, Integer.toString(editor.getHandlerNo())); + service.configureHandler(h, editor.getHandlerNo()); GitHandlerUtil.doSynchronously(h, GitBundle.getString("rebasing.title"), h.printableCommandLine()); } finally { @@ -105,7 +102,7 @@ public abstract class GitRebaseActionBase extends GitRepositoryAction { * * @param editor the editor to configure */ - protected void configureEditor(GitRebaseEditorHandler editor) { + protected void configureEditor(GitInteractiveRebaseEditorHandler editor) { } /** diff --git a/plugins/git4idea/src/git4idea/rebase/GitInteractiveRebaseEditorHandler.java b/plugins/git4idea/src/git4idea/rebase/GitInteractiveRebaseEditorHandler.java new file mode 100644 index 000000000000..4850282d1383 --- /dev/null +++ b/plugins/git4idea/src/git4idea/rebase/GitInteractiveRebaseEditorHandler.java @@ -0,0 +1,155 @@ +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package git4idea.rebase; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Ref; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.ui.UIUtil; + +import java.io.Closeable; + +/** + * The handler for rebase editor request. The handler shows {@link git4idea.rebase.GitRebaseEditor} + * dialog with the specified file. If user accepts the changes, it saves file and returns 0, + * otherwise it just returns error code. + */ +public class GitInteractiveRebaseEditorHandler implements Closeable, GitRebaseEditorHandler { + /** + * The logger + */ + private final static Logger LOG = Logger.getInstance(GitInteractiveRebaseEditorHandler.class.getName()); + /** + * The service object that has created this handler + */ + private final GitRebaseEditorService myService; + /** + * The context project + */ + private final Project myProject; + /** + * The git repository root + */ + private final VirtualFile myRoot; + /** + * The handler number + */ + private int myHandlerNo; + /** + * If true, the handler has been closed + */ + private boolean myIsClosed; + /** + * Set to true after rebase editor was shown + */ + protected boolean myRebaseEditorShown = false; + + /** + * The constructor from fields that is expected to be + * accessed only from {@link git4idea.rebase.GitRebaseEditorService}. + * + * @param service the service object that has created this handler + * @param project the context project + * @param root the git repository root + */ + public GitInteractiveRebaseEditorHandler(final GitRebaseEditorService service, final Project project, final VirtualFile root) { + myService = service; + myProject = project; + myRoot = root; + myHandlerNo = service.registerHandler(this); + } + + /** + * Edit commits request + * + * @param path the path to editing + * @return the exit code to be returned from editor + */ + public int editCommits(final String path) { + ensureOpen(); + final Ref isSuccess = new Ref(); + UIUtil.invokeAndWaitIfNeeded(new Runnable() { + public void run() { + try { + if (myRebaseEditorShown) { + GitRebaseUnstructuredEditor editor = new GitRebaseUnstructuredEditor(myProject, myRoot, path); + editor.show(); + if (editor.isOK()) { + editor.save(); + isSuccess.set(true); + return; + } + else { + isSuccess.set(false); + } + } + else { + setRebaseEditorShown(); + GitRebaseEditor editor = new GitRebaseEditor(myProject, myRoot, path); + editor.show(); + if (editor.isOK()) { + editor.save(); + isSuccess.set(true); + return; + } + else { + editor.cancel(); + isSuccess.set(true); + } + } + } + catch (Exception e) { + LOG.error("Failed to edit the git rebase file: " + path, e); + } + isSuccess.set(false); + } + }); + return (isSuccess.isNull() || !isSuccess.get().booleanValue()) ? GitRebaseEditorMain.ERROR_EXIT_CODE : 0; + } + + /** + * This method is invoked to indicate that this editor will be invoked in the rebase continuation action. + */ + public void setRebaseEditorShown() { + myRebaseEditorShown = true; + } + + /** + * Check that handler has not yet been closed + */ + private void ensureOpen() { + if (myIsClosed) { + throw new IllegalStateException("The handler was already closed"); + } + } + + /** + * Stop using the handler + */ + public void close() { + ensureOpen(); + myIsClosed = true; + myService.unregisterHandler(myHandlerNo); + } + + /** + * @return the handler number + */ + public int getHandlerNo() { + return myHandlerNo; + } +} diff --git a/plugins/git4idea/src/git4idea/rebase/GitRebaseEditorHandler.java b/plugins/git4idea/src/git4idea/rebase/GitRebaseEditorHandler.java index 9a75576af853..f280b437cbfa 100644 --- a/plugins/git4idea/src/git4idea/rebase/GitRebaseEditorHandler.java +++ b/plugins/git4idea/src/git4idea/rebase/GitRebaseEditorHandler.java @@ -15,142 +15,15 @@ */ package git4idea.rebase; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Ref; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.ui.UIUtil; - -import java.io.Closeable; - /** - * The handler for rebase editor request. The handler shows {@link git4idea.rebase.GitRebaseEditor} - * dialog with the specified file. If user accepts the changes, it saves file and returns 0, - * otherwise it just returns error code. + * The interface */ -public class GitRebaseEditorHandler implements Closeable { - /** - * The logger - */ - private final static Logger LOG = Logger.getInstance(GitRebaseEditorHandler.class.getName()); - /** - * The service object that has created this handler - */ - private final GitRebaseEditorService myService; - /** - * The context project - */ - private final Project myProject; - /** - * The git repository root - */ - private final VirtualFile myRoot; - /** - * The handler number - */ - private final int myHandlerNo; - /** - * If true, the handler has been closed - */ - private boolean myIsClosed; - /** - * Set to true after rebase edior was shown - */ - private boolean myRebaseEditorShown = false; - - /** - * The constructor from fields that is expected to be - * accessed only from {@link git4idea.rebase.GitRebaseEditorService}. - * - * @param service the service object that has created this handler - * @param project the context project - * @param root the git repository root - * @param handlerNo the handler no for this editor - */ - GitRebaseEditorHandler(final GitRebaseEditorService service, final Project project, final VirtualFile root, final int handlerNo) { - myService = service; - myProject = project; - myRoot = root; - myHandlerNo = handlerNo; - } - +public interface GitRebaseEditorHandler { /** * Edit commits request * - * @param path the path to eding + * @param path the path to editing * @return the exit code to be returned from editor */ - public int editCommits(final String path) { - ensureOpen(); - final Ref isSuccess = new Ref(); - UIUtil.invokeAndWaitIfNeeded(new Runnable() { - public void run() { - try { - if (myRebaseEditorShown) { - GitRebaseUnstructuredEditor editor = new GitRebaseUnstructuredEditor(myProject, myRoot, path); - editor.show(); - if (editor.isOK()) { - editor.save(); - isSuccess.set(true); - return; - } - else { - isSuccess.set(false); - } - } - else { - setRebaseEditorShown(); - GitRebaseEditor editor = new GitRebaseEditor(myProject, myRoot, path); - editor.show(); - if (editor.isOK()) { - editor.save(); - isSuccess.set(true); - return; - } - else { - editor.cancel(); - isSuccess.set(true); - } - } - } - catch (Exception e) { - LOG.error("Failed to edit the git rebase file: " + path, e); - } - isSuccess.set(false); - } - }); - return (isSuccess.isNull() || !isSuccess.get().booleanValue()) ? GitRebaseEditorMain.ERROR_EXIT_CODE : 0; - } - - /** - * This method is invoked to indicate that this editor will be invoked in the rebase continuation action. - */ - public void setRebaseEditorShown() { - myRebaseEditorShown = true; - } - - /** - * Check that handler has not yet been closed - */ - private void ensureOpen() { - if (myIsClosed) { - throw new IllegalStateException("The handler was already closed"); - } - } - - /** - * Stop using the handler - */ - public void close() { - ensureOpen(); - myIsClosed = true; - myService.unregisterHandler(myHandlerNo); - } - - /** - * @return the handler number - */ - public int getHandlerNo() { - return myHandlerNo; - } + int editCommits(String path); } diff --git a/plugins/git4idea/src/git4idea/rebase/GitRebaseEditorService.java b/plugins/git4idea/src/git4idea/rebase/GitRebaseEditorService.java index 45628f74a3d1..cc46f744b7f0 100644 --- a/plugins/git4idea/src/git4idea/rebase/GitRebaseEditorService.java +++ b/plugins/git4idea/src/git4idea/rebase/GitRebaseEditorService.java @@ -18,9 +18,8 @@ package git4idea.rebase; import com.intellij.ide.XmlRpcServer; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.components.ServiceManager; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; +import git4idea.commands.GitHandler; +import git4idea.commands.GitLineHandler; import git4idea.commands.ScriptGenerator; import gnu.trove.THashMap; import org.apache.commons.codec.DecoderException; @@ -35,11 +34,6 @@ import java.util.Random; * The service that generates editor script for */ public class GitRebaseEditorService implements ApplicationComponent { - /** - * the logger - */ - private static final Logger LOG = Logger.getInstance(GitRebaseEditorService.class.getName()); - /** * The editor command that is set to env variable */ @@ -65,7 +59,7 @@ public class GitRebaseEditorService implements ApplicationComponent { */ private final static Random oursRandom = new Random(); /** - * If true, the component has been intialized + * If true, the component has been initialized */ private boolean myInitialized = false; /** @@ -138,24 +132,27 @@ public class GitRebaseEditorService implements ApplicationComponent { } /** - * @return the handler instance + * Register the handler in the service + * + * @param handler the handler to register + * @return the handler identifier */ - public GitRebaseEditorHandler getHandler(Project project, VirtualFile root) { + public int registerHandler(GitRebaseEditorHandler handler) { initComponent(); - GitRebaseEditorHandler rc = null; + Integer rc = null; synchronized (myHandlersLock) { for (int i = Integer.MAX_VALUE; i > 0; i--) { int code = Math.abs(oursRandom.nextInt()); // note that code might still be negative at this point if it is Integer.MIN_VALUE. if (code > 0 && !myHandlers.containsKey(code)) { - rc = new GitRebaseEditorHandler(this, project, root, code); + rc = code; break; } } if (rc == null) { throw new IllegalStateException("There is a problem with random number allocation"); } - myHandlers.put(rc.getHandlerNo(), rc); + myHandlers.put(rc, handler); } return rc; } @@ -166,7 +163,7 @@ public class GitRebaseEditorService implements ApplicationComponent { * * @param handlerNo the handler number. */ - void unregisterHandler(final int handlerNo) { + public void unregisterHandler(final int handlerNo) { synchronized (myHandlersLock) { if (myHandlers.remove(handlerNo) == null) { throw new IllegalStateException("The handler " + handlerNo + " has been already remoted"); @@ -175,7 +172,7 @@ public class GitRebaseEditorService implements ApplicationComponent { } /** - * Unregister handler + * Get handler * * @param handlerNo the handler number. */ @@ -184,12 +181,23 @@ public class GitRebaseEditorService implements ApplicationComponent { synchronized (myHandlersLock) { GitRebaseEditorHandler h = myHandlers.get(handlerNo); if (h == null) { - throw new IllegalStateException("The handler " + handlerNo + " has been already remoted"); + throw new IllegalStateException("The handler " + handlerNo + " is not registered"); } return h; } } + /** + * Configure handler with editor + * + * @param h the handler to configure + * @param editorNo the editor number + */ + public void configureHandler(GitLineHandler h, int editorNo) { + h.setEnvironment(GitHandler.GIT_EDITOR_ENV, getEditorCommand()); + h.setEnvironment(GitRebaseEditorMain.IDEA_REBASE_HANDER_NO, Integer.toString(editorNo)); + } + /** * The internal xml rcp handler @@ -202,6 +210,7 @@ public class GitRebaseEditorService implements ApplicationComponent { * @param path the path to edit * @return exit code */ + @SuppressWarnings({"UnusedDeclaration"}) public int editCommits(int handlerNo, String path) { return getHandler(handlerNo).editCommits(path); }