mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -20,12 +20,13 @@ import com.intellij.execution.configurations.RemoteConnection;
|
||||
import com.intellij.execution.configurations.RunProfile;
|
||||
import com.intellij.execution.configurations.RunProfileState;
|
||||
import com.intellij.execution.runners.ExecutionEnvironment;
|
||||
import com.intellij.execution.runners.RestartAction;
|
||||
import com.intellij.execution.ui.RunContentDescriptor;
|
||||
import com.intellij.execution.ui.actions.CloseAction;
|
||||
import com.intellij.ide.actions.ContextHelpAction;
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.Constraints;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import com.intellij.openapi.actionSystem.IdeActions;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -62,9 +63,7 @@ public class DefaultDebugUIEnvironment implements DebugUIEnvironment {
|
||||
@Override
|
||||
public void initActions(RunContentDescriptor content, DefaultActionGroup actionGroup) {
|
||||
Executor executor = myExecutionEnvironment.getExecutor();
|
||||
RestartAction restartAction = new RestartAction(content, myExecutionEnvironment);
|
||||
actionGroup.add(restartAction, Constraints.FIRST);
|
||||
restartAction.registerShortcut(content.getComponent());
|
||||
actionGroup.add(ActionManager.getInstance().getAction(IdeActions.ACTION_RERUN), Constraints.FIRST);
|
||||
|
||||
actionGroup.add(new CloseAction(executor, content, myExecutionEnvironment.getProject()));
|
||||
actionGroup.add(new ContextHelpAction(executor.getHelpId()));
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.NullableComputable;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.FilenameIndex;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
@@ -139,6 +140,19 @@ public class PositionManagerImpl implements PositionManager {
|
||||
lineNumber = -1;
|
||||
}
|
||||
|
||||
if (psiFile instanceof PsiCompiledElement && lineNumber > -1) {
|
||||
VirtualFile file = psiFile.getVirtualFile();
|
||||
if (file != null) {
|
||||
int[] data = file.getUserData(LINE_NUMBERS_MAPPING_KEY);
|
||||
if (data != null) {
|
||||
int line = mapLine(lineNumber+1, data);
|
||||
if (line > -1) {
|
||||
return SourcePosition.createFromLine(psiFile, line-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (psiFile instanceof PsiCompiledElement || lineNumber < 0) {
|
||||
final String methodSignature = location.method().signature();
|
||||
if (methodSignature == null) {
|
||||
@@ -165,6 +179,15 @@ public class PositionManagerImpl implements PositionManager {
|
||||
return SourcePosition.createFromLine(psiFile, lineNumber);
|
||||
}
|
||||
|
||||
private static int mapLine(int line, int[] mapping) {
|
||||
for (int i = 0; i < mapping.length; i+=2) {
|
||||
if (mapping[i] == line) {
|
||||
return mapping[i+1];
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PsiFile getPsiFileByLocation(final Project project, final Location location) {
|
||||
if (location == null) {
|
||||
|
||||
@@ -136,7 +136,7 @@ public class ImportModuleAction extends AnAction {
|
||||
});
|
||||
StringBuilder builder = new StringBuilder("<html>Select ");
|
||||
boolean first = true;
|
||||
if (list.size() > 1) {
|
||||
if (list.size() > 0) {
|
||||
for (ProjectImportProvider provider : list) {
|
||||
String sample = provider.getFileSample();
|
||||
if (sample != null) {
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.projectView;
|
||||
|
||||
import com.intellij.ide.projectView.ProjectView;
|
||||
import com.intellij.ide.projectView.impl.AbstractProjectViewPSIPane;
|
||||
import com.intellij.ide.projectView.impl.ProjectViewImpl;
|
||||
import com.intellij.openapi.ui.Queryable;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.testFramework.PlatformTestUtil;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
|
||||
public class ProjectTreeSortingTest extends BaseProjectViewTestCase {
|
||||
private ProjectView myProjectView;
|
||||
private AbstractProjectViewPSIPane myPane;
|
||||
private boolean myOriginalSortByType;
|
||||
private boolean myOriginalFoldersAlwaysOnTop;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
myPane = new TestProjectViewPSIPane(myProject, myStructure, 9);
|
||||
myPane.createComponent();
|
||||
Disposer.register(myStructure, myPane);
|
||||
|
||||
myProjectView = ProjectView.getInstance(myProject);
|
||||
myProjectView.addProjectPane(myPane);
|
||||
myOriginalSortByType = myProjectView.isSortByType(myPane.getId());
|
||||
myOriginalFoldersAlwaysOnTop = ((ProjectViewImpl)myProjectView).isFoldersAlwaysOnTop();
|
||||
|
||||
TreeUtil.expand(myPane.getTree(), 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
myProjectView.setSortByType(myPane.getId(), myOriginalSortByType);
|
||||
((ProjectViewImpl)myProjectView).setFoldersAlwaysOnTop(myOriginalFoldersAlwaysOnTop);
|
||||
myProjectView.removeProjectPane(myPane);
|
||||
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
public void testSortByName() throws Exception {
|
||||
myProjectView.setSortByType(myPane.getId(), false);
|
||||
assertTree("-sortByName\n" +
|
||||
" a.java\n" +
|
||||
" a-a.java\n" +
|
||||
" a-b.java\n" +
|
||||
" ab.java\n" +
|
||||
" b.java\n");
|
||||
}
|
||||
|
||||
public void testSortByType() throws Exception {
|
||||
myProjectView.setSortByType(myPane.getId(), false);
|
||||
assertTree("-sortByType\n" +
|
||||
" a.java\n" +
|
||||
" a.txt\n" +
|
||||
" b.java\n" +
|
||||
" b.txt\n");
|
||||
|
||||
myProjectView.setSortByType(myPane.getId(), true);
|
||||
assertTree("-sortByType\n" +
|
||||
" a.java\n" +
|
||||
" b.java\n" +
|
||||
" a.txt\n" +
|
||||
" b.txt\n");
|
||||
}
|
||||
|
||||
public void testFoldersOnTop() throws Exception {
|
||||
// first, check with 'sort by type' disabled
|
||||
myProjectView.setSortByType(myPane.getId(), false);
|
||||
|
||||
((ProjectViewImpl)myProjectView).setFoldersAlwaysOnTop(true);
|
||||
assertTree("-foldersOnTop\n" +
|
||||
" +b.java\n" +
|
||||
" +b.txt\n" +
|
||||
" a.java\n" +
|
||||
" a.txt\n" +
|
||||
" c.java\n" +
|
||||
" c.txt\n");
|
||||
|
||||
((ProjectViewImpl)myProjectView).setFoldersAlwaysOnTop(false);
|
||||
assertTree("-foldersOnTop\n" +
|
||||
" a.java\n" +
|
||||
" a.txt\n" +
|
||||
" +b.java\n" +
|
||||
" +b.txt\n" +
|
||||
" c.java\n" +
|
||||
" c.txt\n");
|
||||
|
||||
// now let's check the behavior, when sortByType is enabled
|
||||
myProjectView.setSortByType(myPane.getId(), true);
|
||||
|
||||
((ProjectViewImpl)myProjectView).setFoldersAlwaysOnTop(true);
|
||||
assertTree("-foldersOnTop\n" +
|
||||
" +b.java\n" +
|
||||
" +b.txt\n" +
|
||||
" a.java\n" +
|
||||
" c.java\n" +
|
||||
" a.txt\n" +
|
||||
" c.txt\n");
|
||||
|
||||
((ProjectViewImpl)myProjectView).setFoldersAlwaysOnTop(false);
|
||||
assertTree("-foldersOnTop\n" +
|
||||
" a.java\n" +
|
||||
" c.java\n" +
|
||||
" a.txt\n" +
|
||||
" c.txt\n" +
|
||||
" +b.java\n" +
|
||||
" +b.txt\n");
|
||||
}
|
||||
|
||||
public void testSortByTypeBetweenFilesAndFolders() throws Exception {
|
||||
((ProjectViewImpl)myProjectView).setFoldersAlwaysOnTop(false);
|
||||
myProjectView.setSortByType(myPane.getId(), false);
|
||||
assertTree("-sortByTypeBetweenFilesAndFolders\n" +
|
||||
" a.java\n" +
|
||||
" +a.java_folder\n" +
|
||||
" a.txt\n" +
|
||||
" +a_folder\n" +
|
||||
" b.java\n" +
|
||||
" +b.java_folder\n" +
|
||||
" b.txt\n" +
|
||||
" +b_folder\n");
|
||||
|
||||
myProjectView.setSortByType(myPane.getId(), true);
|
||||
assertTree("-sortByTypeBetweenFilesAndFolders\n" +
|
||||
" a.java\n" +
|
||||
" b.java\n" +
|
||||
" a.txt\n" +
|
||||
" b.txt\n" +
|
||||
" +a.java_folder\n" +
|
||||
" +a_folder\n" +
|
||||
" +b.java_folder\n" +
|
||||
" +b_folder\n");
|
||||
}
|
||||
|
||||
private void assertTree(String expected) {
|
||||
DefaultMutableTreeNode element = myPane.getTreeBuilder().getNodeForElement(getContentDirectory());
|
||||
assertNotNull("Element for " + getContentDirectory() + " not found", element);
|
||||
assertEquals(expected, PlatformTestUtil.print(myPane.getTree(), element, new Queryable.PrintInfo(), false));
|
||||
}
|
||||
}
|
||||
@@ -129,16 +129,28 @@ public class Main {
|
||||
// always delete previous patch copy
|
||||
File patchCopy = new File(tempDir, patchFileName + "_copy");
|
||||
File log4jCopy = new File(tempDir, "log4j.jar." + platform + "_copy");
|
||||
if (!FileUtilRt.delete(patchCopy) || !FileUtilRt.delete(log4jCopy)) {
|
||||
File jnaUtilsCopy = new File(tempDir, "jna-utils.jar." + platform + "_copy");
|
||||
File jnaCopy = new File(tempDir, "jna.jar." + platform + "_copy");
|
||||
if (!FileUtilRt.delete(patchCopy) || !FileUtilRt.delete(log4jCopy) || !FileUtilRt.delete(jnaUtilsCopy) || !FileUtilRt.delete(jnaCopy)) {
|
||||
throw new IOException("Cannot delete temporary files in " + tempDir);
|
||||
}
|
||||
|
||||
File patch = new File(tempDir, patchFileName);
|
||||
if (!patch.exists()) return;
|
||||
|
||||
File log4j = new File(PathManager.getLibPath(), "log4j.jar");
|
||||
if (!log4j.exists()) throw new IOException("Log4J missing: " + log4j);
|
||||
if (!log4j.exists()) throw new IOException("Log4J is missing: " + log4j);
|
||||
|
||||
File jnaUtils = new File(PathManager.getLibPath(), "jna-utils.jar");
|
||||
if (!jnaUtils.exists()) throw new IOException("jna-utils.jar is missing: " + jnaUtils);
|
||||
|
||||
File jna = new File(PathManager.getLibPath(), "jna.jar");
|
||||
if (!jna.exists()) throw new IOException("jna is missing: " + jna);
|
||||
|
||||
copyFile(patch, patchCopy, true);
|
||||
copyFile(log4j, log4jCopy, false);
|
||||
copyFile(jna, jnaCopy, false);
|
||||
copyFile(jnaUtils, jnaUtilsCopy, false);
|
||||
|
||||
int status = 0;
|
||||
if (Restarter.isSupported()) {
|
||||
@@ -154,7 +166,7 @@ public class Main {
|
||||
System.getProperty("java.home") + "/bin/java",
|
||||
"-Xmx500m",
|
||||
"-classpath",
|
||||
patchCopy.getPath() + File.pathSeparator + log4jCopy.getPath(),
|
||||
patchCopy.getPath() + File.pathSeparator + log4jCopy.getPath() + File.pathSeparator + jnaCopy.getPath() + File.pathSeparator + jnaUtilsCopy.getPath(),
|
||||
"-Djava.io.tmpdir=" + tempDir,
|
||||
"-Didea.updater.log=" + PathManager.getLogPath(),
|
||||
"-Dswing.defaultlaf=" + UIManager.getSystemLookAndFeelClassName(),
|
||||
|
||||
@@ -31,7 +31,9 @@ import com.intellij.psi.meta.PsiMetaOwner;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.util.TimeoutUtil;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -536,4 +538,14 @@ public class PsiUtilCore {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Contract("null -> null;!null -> !null")
|
||||
public static IElementType getElementType(@Nullable ASTNode node) {
|
||||
return node == null ? null : node.getElementType();
|
||||
}
|
||||
|
||||
@Contract("null -> null;!null -> !null")
|
||||
public static IElementType getElementType(@Nullable PsiElement element) {
|
||||
return element == null ? null : getElementType(element.getNode());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.dvcs.push.ui;
|
||||
import com.intellij.dvcs.DvcsUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.changes.issueLinks.IssueLinkHtmlRenderer;
|
||||
import com.intellij.openapi.vcs.changes.issueLinks.IssueLinkRenderer;
|
||||
import com.intellij.ui.ColoredTreeCellRenderer;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.vcs.log.VcsFullCommitDetails;
|
||||
@@ -41,8 +42,9 @@ public class CommitNode extends DefaultMutableTreeNode implements CustomRendered
|
||||
|
||||
@Override
|
||||
public void render(@NotNull ColoredTreeCellRenderer renderer) {
|
||||
String subject = getUserObject().getSubject();
|
||||
renderer.append(subject, SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
new IssueLinkRenderer(myProject, renderer).appendTextWithLinks(getUserObject().getSubject(),
|
||||
new SimpleTextAttributes(SimpleTextAttributes.STYLE_SMALLER,
|
||||
renderer.getForeground()));
|
||||
}
|
||||
|
||||
public String getTooltip() {
|
||||
|
||||
@@ -15,13 +15,11 @@
|
||||
*/
|
||||
package com.intellij.dvcs.push.ui;
|
||||
|
||||
import com.intellij.dvcs.push.PushTargetPanel;
|
||||
import com.intellij.openapi.vcs.changes.issueLinks.LinkMouseListenerBase;
|
||||
import com.intellij.ui.CheckboxTree;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
public class VcsBranchEditorListener extends LinkMouseListenerBase {
|
||||
@@ -31,18 +29,6 @@ public class VcsBranchEditorListener extends LinkMouseListenerBase {
|
||||
myRenderer = renderer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
Component component = (Component)e.getSource();
|
||||
Object tag = getTagAt(e);
|
||||
if (tag instanceof PushTargetPanel || tag instanceof TextWithLinkNode || tag instanceof ExtraEditControl) {
|
||||
component.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||
}
|
||||
else {
|
||||
component.setCursor(Cursor.getDefaultCursor());
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected Object getTagAt(@NotNull final MouseEvent e) {
|
||||
|
||||
+4
-2
@@ -512,7 +512,7 @@ public class CommentByLineCommentHandler extends MultiCaretCodeInsightActionHand
|
||||
if (startOffset == endOffset) {
|
||||
return;
|
||||
}
|
||||
RangeMarker marker = block.editor.getDocument().createRangeMarker(startOffset, endOffset);
|
||||
RangeMarker marker = endOffset > startOffset ? block.editor.getDocument().createRangeMarker(startOffset, endOffset) : null;
|
||||
String prefix = commenter.getLineCommentPrefix();
|
||||
if (prefix != null) {
|
||||
CharSequence chars = document.getCharsSequence();
|
||||
@@ -581,7 +581,9 @@ public class CommentByLineCommentHandler extends MultiCaretCodeInsightActionHand
|
||||
for (int i = prefixes.size() - 1; i >= 0; i--) {
|
||||
uncommentRange(document, startOffset + prefixes.get(i), Math.min(startOffset + suffixes.get(i) + suffix.length(), endOffset), commenter);
|
||||
}
|
||||
CommentByBlockCommentHandler.processDocument(document, marker, commenter, false);
|
||||
if (marker != null) {
|
||||
CommentByBlockCommentHandler.processDocument(document, marker, commenter, false);
|
||||
}
|
||||
}
|
||||
|
||||
private static void commentLine(Block block, int line, int offset) {
|
||||
|
||||
+37
-12
@@ -56,6 +56,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.xmlpull.v1.XmlPullParserFactory;
|
||||
import org.xmlpull.v1.XmlSerializer;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.io.*;
|
||||
import java.util.List;
|
||||
@@ -75,6 +76,7 @@ public class ConsoleHistoryController {
|
||||
private final AnAction myHistoryPrev = new MyAction(false);
|
||||
private final AnAction myBrowseHistory = new MyBrowseAction();
|
||||
private boolean myMultiline;
|
||||
private boolean isStandardUpDownUsed = false;
|
||||
private final ModelHelper myHelper;
|
||||
private long myLastSaveStamp;
|
||||
|
||||
@@ -115,6 +117,7 @@ public class ConsoleHistoryController {
|
||||
loadHistory(myHelper.getId());
|
||||
}
|
||||
configureActions();
|
||||
isStandardUpDownUsed = checkIfStandardUpDownUsed();
|
||||
myLastSaveStamp = getCurrentTimeStamp();
|
||||
}
|
||||
|
||||
@@ -122,21 +125,18 @@ public class ConsoleHistoryController {
|
||||
return getModel().getModificationCount() + myConsole.getEditorDocument().getModificationStamp();
|
||||
}
|
||||
|
||||
private void configureActions() {
|
||||
private boolean checkIfStandardUpDownUsed() {
|
||||
return isShortcutSetsIntersect(myHistoryNext.getShortcutSet(), getShortcutUpDown(true))
|
||||
|| isShortcutSetsIntersect(myHistoryPrev.getShortcutSet(), getShortcutUpDown(false));
|
||||
}
|
||||
|
||||
protected void configureActions() {
|
||||
EmptyAction.setupAction(myHistoryNext, "Console.History.Next", null);
|
||||
EmptyAction.setupAction(myHistoryPrev, "Console.History.Previous", null);
|
||||
EmptyAction.setupAction(myBrowseHistory, "Console.History.Browse", null);
|
||||
if (!myMultiline) {
|
||||
AnAction up = ActionManager.getInstance().getActionOrStub(IdeActions.ACTION_EDITOR_MOVE_CARET_UP);
|
||||
AnAction down = ActionManager.getInstance().getActionOrStub(IdeActions.ACTION_EDITOR_MOVE_CARET_DOWN);
|
||||
if (up != null && down != null) {
|
||||
myHistoryNext.registerCustomShortcutSet(up.getShortcutSet(), null);
|
||||
myHistoryPrev.registerCustomShortcutSet(down.getShortcutSet(), null);
|
||||
}
|
||||
else {
|
||||
myHistoryNext.registerCustomShortcutSet(KeyEvent.VK_UP, 0, null);
|
||||
myHistoryPrev.registerCustomShortcutSet(KeyEvent.VK_DOWN, 0, null);
|
||||
}
|
||||
myHistoryNext.registerCustomShortcutSet(getShortcutUpDown(true), null);
|
||||
myHistoryPrev.registerCustomShortcutSet(getShortcutUpDown(false), null);
|
||||
}
|
||||
myHistoryNext.registerCustomShortcutSet(myHistoryNext.getShortcutSet(), myConsole.getCurrentEditor().getComponent());
|
||||
myHistoryPrev.registerCustomShortcutSet(myHistoryPrev.getShortcutSet(), myConsole.getCurrentEditor().getComponent());
|
||||
@@ -263,7 +263,7 @@ public class ConsoleHistoryController {
|
||||
@Override
|
||||
public void update(final AnActionEvent e) {
|
||||
super.update(e);
|
||||
e.getPresentation().setEnabled(myMultiline || canMoveInEditor(myNext));
|
||||
e.getPresentation().setEnabled(!isStandardUpDownUsed || canMoveInEditor(myNext));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -505,4 +505,29 @@ public class ConsoleHistoryController {
|
||||
out.endTag(null, tag);
|
||||
}
|
||||
}
|
||||
|
||||
private static ShortcutSet getShortcutUpDown(boolean isUp) {
|
||||
AnAction action = ActionManager.getInstance().getActionOrStub(isUp ?
|
||||
IdeActions.ACTION_EDITOR_MOVE_CARET_UP :
|
||||
IdeActions.ACTION_EDITOR_MOVE_CARET_DOWN);
|
||||
if (action != null) {
|
||||
return action.getShortcutSet();
|
||||
}
|
||||
return new CustomShortcutSet(KeyStroke.getKeyStroke(isUp ? KeyEvent.VK_UP : KeyEvent.VK_DOWN, 0));
|
||||
}
|
||||
|
||||
private static boolean isShortcutSetsIntersect(ShortcutSet set1, ShortcutSet set2) {
|
||||
final Shortcut[] shortcuts1 = set1.getShortcuts();
|
||||
final Shortcut[] shortcuts2 = set2.getShortcuts();
|
||||
|
||||
for (Shortcut s1 : shortcuts1) {
|
||||
for (Shortcut s2 : shortcuts2) {
|
||||
if (s1.equals(s2)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-24
@@ -253,31 +253,8 @@ public abstract class AbstractConsoleRunnerWithHistory<T extends LanguageConsole
|
||||
consoleExecuteActionHandler);
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
@Deprecated
|
||||
/**
|
||||
* @deprecated to remove in IDEA 14
|
||||
*/
|
||||
public static AnAction createConsoleExecAction(LanguageConsoleImpl languageConsole,
|
||||
ProcessHandler processHandler,
|
||||
@SuppressWarnings("deprecation") ConsoleExecuteActionHandler consoleExecuteActionHandler) {
|
||||
return ConsoleExecuteAction.createAction(languageConsole, consoleExecuteActionHandler);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected ProcessBackedConsoleExecuteActionHandler createExecuteActionHandler() {
|
||||
//noinspection deprecation
|
||||
return createConsoleExecuteActionHandler();
|
||||
}
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration", "deprecation"})
|
||||
@Deprecated
|
||||
/**
|
||||
* @deprecated to remove in IDEA 14
|
||||
*/
|
||||
protected ConsoleExecuteActionHandler createConsoleExecuteActionHandler() {
|
||||
throw new AbstractMethodError();
|
||||
}
|
||||
protected abstract ProcessBackedConsoleExecuteActionHandler createExecuteActionHandler();
|
||||
|
||||
public T getConsoleView() {
|
||||
return myConsoleView;
|
||||
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
package com.intellij.execution.runners;
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* @deprecated to remove in IDEA 15
|
||||
*/
|
||||
public abstract class BaseConsoleExecuteActionHandler extends com.intellij.execution.console.BaseConsoleExecuteActionHandler {
|
||||
public BaseConsoleExecuteActionHandler(boolean preserveMarkup) {
|
||||
super(preserveMarkup);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 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.
|
||||
@@ -26,26 +26,12 @@ import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.LangDataKeys;
|
||||
import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Roman.Chernyatchik
|
||||
*/
|
||||
class FakeRerunAction extends AnAction implements DumbAware {
|
||||
@SuppressWarnings("deprecation")
|
||||
static final List<RestartAction> registry = ContainerUtil.createLockFreeCopyOnWriteList();
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent event) {
|
||||
public void update(@NotNull AnActionEvent event) {
|
||||
Presentation presentation = event.getPresentation();
|
||||
ExecutionEnvironment environment = getEnvironment(event);
|
||||
if (environment != null) {
|
||||
@@ -55,22 +41,14 @@ class FakeRerunAction extends AnAction implements DumbAware {
|
||||
return;
|
||||
}
|
||||
|
||||
FakeRerunAction action = findActualAction(event);
|
||||
presentation.setEnabled(action != null && action.isEnabled(event));
|
||||
presentation.setVisible(false);
|
||||
presentation.setEnabledAndVisible(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent event) {
|
||||
public void actionPerformed(@NotNull AnActionEvent event) {
|
||||
ExecutionEnvironment environment = getEnvironment(event);
|
||||
if (environment != null) {
|
||||
ExecutionUtil.restart(environment);
|
||||
return;
|
||||
}
|
||||
|
||||
FakeRerunAction action = findActualAction(event);
|
||||
if (action != null && action.isEnabled(event)) {
|
||||
action.actionPerformed(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,50 +70,4 @@ class FakeRerunAction extends AnAction implements DumbAware {
|
||||
!ExecutorRegistry.getInstance().isStarting(environment) &&
|
||||
!(processHandler != null && processHandler.isProcessTerminating());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JComponent getRunComponent(@NotNull AnActionEvent event) {
|
||||
RunContentDescriptor descriptor = getDescriptor(event);
|
||||
return descriptor == null ? null : descriptor.getComponent();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static FakeRerunAction findActualAction(@NotNull final AnActionEvent event) {
|
||||
if (registry.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<FakeRerunAction> candidates = new ArrayList<FakeRerunAction>(registry);
|
||||
Collections.sort(candidates, new Comparator<FakeRerunAction>() {
|
||||
@Override
|
||||
public int compare(@NotNull FakeRerunAction action1, @NotNull FakeRerunAction action2) {
|
||||
boolean isActive1 = action1.isEnabled(event);
|
||||
if (isActive1 != action2.isEnabled(event)) {
|
||||
return isActive1 ? -1 : 1;
|
||||
}
|
||||
|
||||
JComponent component1 = action1.getRunComponent(event);
|
||||
JComponent component2 = action2.getRunComponent(event);
|
||||
Window window1 = component1 == null ? null : SwingUtilities.windowForComponent(component1);
|
||||
Window window2 = component2 == null ? null : SwingUtilities.windowForComponent(component2);
|
||||
if (window1 == null) {
|
||||
return 1;
|
||||
}
|
||||
if (window2 == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
boolean showing1 = component1.isShowing();
|
||||
boolean showing2 = component2.isShowing();
|
||||
if (showing1 && !showing2) {
|
||||
return -1;
|
||||
}
|
||||
if (showing2 && !showing1) {
|
||||
return 1;
|
||||
}
|
||||
return (window1.isActive() ? -1 : 1);
|
||||
}
|
||||
});
|
||||
return candidates.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.execution.runners;
|
||||
|
||||
import com.intellij.execution.Executor;
|
||||
import com.intellij.execution.ui.RunContentDescriptor;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CustomShortcutSet;
|
||||
import com.intellij.openapi.actionSystem.IdeActions;
|
||||
import com.intellij.openapi.keymap.KeymapManager;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* to remove in IDEA 15
|
||||
*/
|
||||
public class RestartAction extends FakeRerunAction implements DumbAware, AnAction.TransparentUpdate, Disposable {
|
||||
private final RunContentDescriptor myDescriptor;
|
||||
private final ExecutionEnvironment myEnvironment;
|
||||
|
||||
public RestartAction(@NotNull RunContentDescriptor descriptor, @NotNull ExecutionEnvironment environment) {
|
||||
//noinspection deprecation
|
||||
this(environment.getExecutor(), null, descriptor, environment);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* @deprecated environment must provide runner id
|
||||
* to remove in IDEA 15
|
||||
*/
|
||||
public RestartAction(@SuppressWarnings("UnusedParameters") @NotNull Executor executor,
|
||||
@Nullable ProgramRunner runner,
|
||||
@NotNull RunContentDescriptor descriptor,
|
||||
@NotNull ExecutionEnvironment environment) {
|
||||
Disposer.register(descriptor, this);
|
||||
FakeRerunAction.registry.add(this);
|
||||
|
||||
myEnvironment = runner == null ? environment : RunContentBuilder.fix(environment, runner);
|
||||
getTemplatePresentation().setEnabled(false);
|
||||
myDescriptor = descriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
FakeRerunAction.registry.remove(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
protected RunContentDescriptor getDescriptor(AnActionEvent event) {
|
||||
return myDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
protected ExecutionEnvironment getEnvironment(AnActionEvent event) {
|
||||
return myEnvironment;
|
||||
}
|
||||
|
||||
public void registerShortcut(JComponent component) {
|
||||
registerCustomShortcutSet(new CustomShortcutSet(KeymapManager.getInstance().getActiveKeymap().getShortcuts(IdeActions.ACTION_RERUN)),
|
||||
component);
|
||||
}
|
||||
}
|
||||
+31
-25
@@ -63,9 +63,12 @@ public class GroupByTypeComparator implements Comparator<NodeDescriptor> {
|
||||
if (descriptor1 instanceof ProjectViewNode && descriptor2 instanceof ProjectViewNode) {
|
||||
final Project project = descriptor1.getProject();
|
||||
final ProjectView projectView = ProjectView.getInstance(project);
|
||||
if (!(projectView instanceof ProjectViewImpl && !((ProjectViewImpl)projectView).isFoldersAlwaysOnTop())) {
|
||||
ProjectViewNode node1 = (ProjectViewNode)descriptor1;
|
||||
ProjectViewNode node2 = (ProjectViewNode)descriptor2;
|
||||
|
||||
ProjectViewNode node1 = (ProjectViewNode)descriptor1;
|
||||
ProjectViewNode node2 = (ProjectViewNode)descriptor2;
|
||||
|
||||
boolean isFoldersOnTop = !(projectView instanceof ProjectViewImpl && !((ProjectViewImpl)projectView).isFoldersAlwaysOnTop());
|
||||
if (isFoldersOnTop) {
|
||||
int typeWeight1 = node1.getTypeSortWeight(isSortByType());
|
||||
int typeWeight2 = node2.getTypeSortWeight(isSortByType());
|
||||
if (typeWeight1 != 0 && typeWeight2 == 0) {
|
||||
@@ -77,30 +80,34 @@ public class GroupByTypeComparator implements Comparator<NodeDescriptor> {
|
||||
if (typeWeight1 != 0 && typeWeight2 != typeWeight1) {
|
||||
return typeWeight1 - typeWeight2;
|
||||
}
|
||||
|
||||
if (isSortByType()) {
|
||||
final Comparable typeSortKey1 = node1.getTypeSortKey();
|
||||
final Comparable typeSortKey2 = node2.getTypeSortKey();
|
||||
if (typeSortKey1 != null && typeSortKey2 != null) {
|
||||
final int result = typeSortKey1.compareTo(typeSortKey2);
|
||||
if (result != 0) return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (isSortByType()) {
|
||||
final Comparable typeSortKey1 = node1.getTypeSortKey();
|
||||
final Comparable typeSortKey2 = node2.getTypeSortKey();
|
||||
if (!(typeSortKey1 == null && typeSortKey2 == null)) {
|
||||
if (typeSortKey1 == null) return 1;
|
||||
if (typeSortKey2 == null) return -1;
|
||||
//noinspection unchecked
|
||||
final int result = typeSortKey1.compareTo(typeSortKey2);
|
||||
if (result != 0) return result;
|
||||
}
|
||||
else {
|
||||
final Comparable typeSortKey1 = node1.getSortKey();
|
||||
final Comparable typeSortKey2 = node2.getSortKey();
|
||||
if (typeSortKey1 != null && typeSortKey2 != null) {
|
||||
final int result = typeSortKey1.compareTo(typeSortKey2);
|
||||
if (result != 0) return result;
|
||||
}
|
||||
}
|
||||
else {
|
||||
final Comparable typeSortKey1 = node1.getSortKey();
|
||||
final Comparable typeSortKey2 = node2.getSortKey();
|
||||
if (typeSortKey1 != null && typeSortKey2 != null) {
|
||||
//noinspection unchecked
|
||||
final int result = typeSortKey1.compareTo(typeSortKey2);
|
||||
if (result != 0) return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (isAbbreviateQualifiedNames()) {
|
||||
String key1 = node1.getQualifiedNameSortKey();
|
||||
String key2 = node2.getQualifiedNameSortKey();
|
||||
if (key1 != null && key2 != null) {
|
||||
return key1.compareToIgnoreCase(key2);
|
||||
}
|
||||
if (isAbbreviateQualifiedNames()) {
|
||||
String key1 = node1.getQualifiedNameSortKey();
|
||||
String key2 = node2.getQualifiedNameSortKey();
|
||||
if (key1 != null && key2 != null) {
|
||||
return key1.compareToIgnoreCase(key2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,5 +126,4 @@ public class GroupByTypeComparator implements Comparator<NodeDescriptor> {
|
||||
private boolean isAbbreviateQualifiedNames() {
|
||||
return myProjectView != null && myProjectView.isAbbreviatePackageNames(myPaneId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
<properties>
|
||||
<opaque value="true"/>
|
||||
</properties>
|
||||
<border type="etched"/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="61c42" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
|
||||
@@ -24,30 +24,27 @@ import javax.swing.plaf.FontUIResource;
|
||||
/**
|
||||
* @author Sergey.Malenkov
|
||||
*/
|
||||
public final class RelativeFont implements PropertyChangeListener {
|
||||
private static final String PROPERTY = "font";
|
||||
public enum RelativeFont implements PropertyChangeListener {
|
||||
PLAIN(Font.PLAIN, 0),
|
||||
BOLD(Font.BOLD, 0),
|
||||
LARGE(1f),
|
||||
SMALL(-1f),
|
||||
HUGE(2f),
|
||||
TINY(-2f);
|
||||
|
||||
public static final RelativeFont PLAIN = new RelativeFont(Font.PLAIN, 0);
|
||||
public static final RelativeFont BOLD = new RelativeFont(Font.BOLD, 0);
|
||||
public static final RelativeFont LARGE = new RelativeFont(1f);
|
||||
public static final RelativeFont SMALL = new RelativeFont(-1f);
|
||||
public static final RelativeFont HUGE = new RelativeFont(2f);
|
||||
public static final RelativeFont TINY = new RelativeFont(-2f);
|
||||
private static final String PROPERTY = "font";
|
||||
|
||||
private final int myStyle;
|
||||
private final float mySize;
|
||||
|
||||
public RelativeFont(float size) {
|
||||
RelativeFont(float size) {
|
||||
this.myStyle = -1;
|
||||
this.mySize = size;
|
||||
}
|
||||
|
||||
public RelativeFont(int style, float size) {
|
||||
RelativeFont(int style, float size) {
|
||||
this.myStyle = style & (Font.BOLD | Font.ITALIC);
|
||||
this.mySize = size;
|
||||
if (style != myStyle) {
|
||||
throw new IllegalArgumentException("style");
|
||||
}
|
||||
}
|
||||
|
||||
public <T extends Component> T install(T component) {
|
||||
|
||||
@@ -112,12 +112,12 @@ public final class HorizontalLayout implements LayoutManager2 {
|
||||
@Override
|
||||
public void addLayoutComponent(String name, Component component) {
|
||||
synchronized (component.getTreeLock()) {
|
||||
if (name == null || CENTER.equalsIgnoreCase(name)) {
|
||||
myCenter.add(component);
|
||||
}
|
||||
else if (LEFT.equalsIgnoreCase(name)) {
|
||||
if (name == null || LEFT.equalsIgnoreCase(name)) {
|
||||
myLeft.add(component);
|
||||
}
|
||||
else if (CENTER.equalsIgnoreCase(name)) {
|
||||
myCenter.add(component);
|
||||
}
|
||||
else if (RIGHT.equalsIgnoreCase(name)) {
|
||||
myRight.add(component);
|
||||
}
|
||||
@@ -242,7 +242,7 @@ public final class HorizontalLayout implements LayoutManager2 {
|
||||
if (result == null) {
|
||||
result = new Dimension();
|
||||
}
|
||||
else if (aligned) {
|
||||
else if (aligned && center != null) {
|
||||
int leftWidth = left == null ? 0 : left.width;
|
||||
int rightWidth = right == null ? 0 : right.width;
|
||||
result.width += Math.abs(leftWidth - rightWidth);
|
||||
|
||||
@@ -112,12 +112,12 @@ public final class VerticalLayout implements LayoutManager2 {
|
||||
@Override
|
||||
public void addLayoutComponent(String name, Component component) {
|
||||
synchronized (component.getTreeLock()) {
|
||||
if (name == null || CENTER.equalsIgnoreCase(name)) {
|
||||
myCenter.add(component);
|
||||
}
|
||||
else if (TOP.equalsIgnoreCase(name)) {
|
||||
if (name == null || TOP.equalsIgnoreCase(name)) {
|
||||
myTop.add(component);
|
||||
}
|
||||
else if (CENTER.equalsIgnoreCase(name)) {
|
||||
myCenter.add(component);
|
||||
}
|
||||
else if (BOTTOM.equalsIgnoreCase(name)) {
|
||||
myBottom.add(component);
|
||||
}
|
||||
@@ -242,7 +242,7 @@ public final class VerticalLayout implements LayoutManager2 {
|
||||
if (result == null) {
|
||||
result = new Dimension();
|
||||
}
|
||||
else if (aligned) {
|
||||
else if (aligned && center != null) {
|
||||
int topHeight = top == null ? 0 : top.height;
|
||||
int bottomHeight = bottom == null ? 0 : bottom.height;
|
||||
result.width += Math.abs(topHeight - bottomHeight);
|
||||
|
||||
+12
-1
@@ -42,11 +42,12 @@ import java.util.Arrays;
|
||||
|
||||
public class DiffManagerImpl extends DiffManager implements JDOMExternalizable {
|
||||
public static final int FULL_DIFF_DIVIDER_POLYGONS_OFFSET = 3;
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.external.DiffManagerImpl");
|
||||
private static final Logger LOG = Logger.getInstance(DiffManagerImpl.class);
|
||||
|
||||
private static final Externalizer<String> TOOL_PATH_UPDATE = new Externalizer<String>() {
|
||||
@NonNls private static final String NEW_VALUE = "newValue";
|
||||
|
||||
@Override
|
||||
public String readValue(Element dataElement) {
|
||||
String path = dataElement.getAttributeValue(NEW_VALUE);
|
||||
if (path != null) return path;
|
||||
@@ -54,6 +55,7 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable {
|
||||
return prevValue != null ? prevValue.trim() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeValue(Element dataElement, String path) {
|
||||
dataElement.setAttribute(VALUE_ATTRIBUTE, path);
|
||||
dataElement.setAttribute(NEW_VALUE, path);
|
||||
@@ -75,6 +77,7 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable {
|
||||
|
||||
public static final Key<Boolean> EDITOR_IS_DIFF_KEY = new Key<Boolean>("EDITOR_IS_DIFF_KEY");
|
||||
private static final MarkupEditorFilter DIFF_EDITOR_FILTER = new MarkupEditorFilter() {
|
||||
@Override
|
||||
public boolean avaliableIn(Editor editor) {
|
||||
return DiffUtil.isDiffEditor(editor);
|
||||
}
|
||||
@@ -96,8 +99,10 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable {
|
||||
myProperties.registerProperty(MERGE_TOOL_PARAMETERS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiffTool getIdeaDiffTool() { return INTERNAL_DIFF; }
|
||||
|
||||
@Override
|
||||
public DiffTool getDiffTool() {
|
||||
DiffTool[] standardTools;
|
||||
// there is inner check in multiple tool for external viewers as well
|
||||
@@ -131,21 +136,25 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable {
|
||||
return new CompositeDiffTool(allTools);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerDiffTool(@NotNull DiffTool tool) throws NullPointerException {
|
||||
if (myAdditionTools.contains(tool)) return false;
|
||||
myAdditionTools.add(tool);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterDiffTool(DiffTool tool) {
|
||||
myAdditionTools.remove(tool);
|
||||
LOG.assertTrue(!myAdditionTools.contains(tool));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkupEditorFilter getDiffEditorFilter() {
|
||||
return DIFF_EDITOR_FILTER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiffPanel createDiffPanel(Window window, Project project, DiffTool parentTool) {
|
||||
return new DiffPanelImpl(window, project, true, true, FULL_DIFF_DIVIDER_POLYGONS_OFFSET, parentTool);
|
||||
}
|
||||
@@ -161,6 +170,7 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable {
|
||||
return (DiffManagerImpl)DiffManager.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readExternal(@NotNull Element element) throws InvalidDataException {
|
||||
myProperties.readExternal(element);
|
||||
readPolicy(element);
|
||||
@@ -191,6 +201,7 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeExternal(@NotNull Element element) throws WriteExternalException {
|
||||
myProperties.writeExternal(element);
|
||||
if (myComparisonPolicy != null) {
|
||||
|
||||
@@ -66,9 +66,9 @@ final class Banner extends JPanel {
|
||||
}
|
||||
else {
|
||||
if (i > 0) {
|
||||
myLeftPanel.add(HorizontalLayout.LEFT, RelativeFont.HUGE.install(new JLabel("\u203A")));
|
||||
myLeftPanel.add(RelativeFont.HUGE.install(new JLabel("\u203A")));
|
||||
}
|
||||
myLeftPanel.add(HorizontalLayout.LEFT, RelativeFont.BOLD.install(new JLabel(name)));
|
||||
myLeftPanel.add(RelativeFont.BOLD.install(new JLabel(name)));
|
||||
}
|
||||
i += 2;
|
||||
}
|
||||
|
||||
+18
-17
@@ -69,7 +69,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
|
||||
private static final String NODE_ICON = "settings.tree.view.icon";
|
||||
private static final Color WRONG_CONTENT = JBColor.RED;
|
||||
private static final Color MODIFIED_CONTENT = JBColor.BLUE;
|
||||
public static final Color FOREGROUND = new JBColor(0x1A1A1A, 0xBBBBBB);
|
||||
public static final Color FOREGROUND = new JBColor(Gray.x1A, Gray.xBB);
|
||||
public static final Color BACKGROUND = new JBColor(0xE6EBF0, 0x3E434C);
|
||||
|
||||
final SimpleTree myTree;
|
||||
@@ -97,7 +97,6 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
|
||||
TreeUtil.installActions(myTree);
|
||||
|
||||
myTree.setOpaque(true);
|
||||
myTree.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));
|
||||
|
||||
myTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
|
||||
|
||||
@@ -116,6 +115,8 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
|
||||
|
||||
mySeparator = new JLabel();
|
||||
mySeparator.setForeground(FOREGROUND);
|
||||
mySeparator.setIconTextGap(10);
|
||||
mySeparator.setBorder(BorderFactory.createEmptyBorder(1, 19, 0, 0));
|
||||
|
||||
myTree.addComponentListener(new ComponentAdapter() {
|
||||
@Override
|
||||
@@ -273,10 +274,10 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
|
||||
return; // separator is not needed without scrolling
|
||||
}
|
||||
mySeparator.setFont(myTree.getFont());
|
||||
mySeparator.setIcon(myTree.getEmptyHandle());
|
||||
int height = mySeparator.getPreferredSize().height;
|
||||
String group = findGroupNameAt(0, height);
|
||||
String group = findGroupNameAt(0, height + 3);
|
||||
if (group != null && group.equals(findGroupNameAt(0, 0))) {
|
||||
mySeparator.setBorder(BorderFactory.createEmptyBorder(1, 22, 0, 0));
|
||||
mySeparator.setText(group);
|
||||
|
||||
Rectangle bounds = myScroller.getViewport().getBounds();
|
||||
@@ -459,16 +460,16 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
|
||||
|
||||
private final class MyRenderer extends JPanel implements TreeCellRenderer {
|
||||
private final JLabel myTextLabel = new ErrorLabel();
|
||||
private final JLabel myNodeIcon = new JLabel(" ", SwingConstants.RIGHT);
|
||||
private final JLabel myProjectIcon = new JLabel(" ", SwingConstants.LEFT);
|
||||
private final JLabel myNodeIcon = new JLabel();
|
||||
private final JLabel myProjectIcon = new JLabel();
|
||||
|
||||
public MyRenderer() {
|
||||
super(new BorderLayout());
|
||||
super(new BorderLayout(10, 0));
|
||||
myNodeIcon.setName(NODE_ICON);
|
||||
add(BorderLayout.CENTER, myTextLabel);
|
||||
add(BorderLayout.WEST, myNodeIcon);
|
||||
add(BorderLayout.EAST, myProjectIcon);
|
||||
setBorder(BorderFactory.createEmptyBorder(1, 0, 3, 0));
|
||||
setBorder(BorderFactory.createEmptyBorder(1, 10, 3, 10));
|
||||
}
|
||||
|
||||
public Component getTreeCellRendererComponent(JTree tree,
|
||||
@@ -554,9 +555,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
|
||||
myNodeIcon.setIcon(nodeIcon);
|
||||
// calculate minimum size
|
||||
if (node != null && tree.isVisible()) {
|
||||
int width = getPreferredSize().width;
|
||||
width += node.myLevel * UIUtil.getTreeLeftChildIndent();
|
||||
width += node.myLevel * UIUtil.getTreeRightChildIndent();
|
||||
int width = 10 * node.myLevel + getPreferredSize().width;
|
||||
Insets insets = tree.getInsets();
|
||||
if (insets != null) {
|
||||
width += insets.left + insets.right;
|
||||
@@ -722,19 +721,21 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
|
||||
boolean hasBeenExpanded,
|
||||
boolean isLeaf) {
|
||||
if (tree != null) {
|
||||
int width = tree.getWidth();
|
||||
bounds.width = tree.getWidth();
|
||||
Container parent = tree.getParent();
|
||||
if (parent instanceof JViewport) {
|
||||
JViewport viewport = (JViewport)parent;
|
||||
width = viewport.getWidth() - viewport.getViewPosition().x;
|
||||
}
|
||||
width -= bounds.x;
|
||||
if (bounds.width < width) {
|
||||
bounds.width = width;
|
||||
bounds.width = viewport.getWidth() - viewport.getViewPosition().x;
|
||||
}
|
||||
bounds.width -= bounds.x;
|
||||
}
|
||||
super.paintRow(g, clipBounds, insets, bounds, path, row, isExpanded, hasBeenExpanded, isLeaf);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getRowX(int row, int depth) {
|
||||
return 10 * depth;
|
||||
}
|
||||
}
|
||||
|
||||
private final class MyBuilder extends FilteringTreeBuilder {
|
||||
|
||||
+3
-2
@@ -43,6 +43,7 @@ import com.intellij.openapi.wm.impl.IdeGlassPaneImpl;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.ui.components.labels.ActionLink;
|
||||
import com.intellij.ui.components.panels.NonOpaquePanel;
|
||||
import com.intellij.util.PlatformUtils;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -171,7 +172,7 @@ public class FlatWelcomeFrame extends JFrame implements WelcomeFrameProvider, Id
|
||||
|
||||
@Override
|
||||
public IdeFrame createFrame() {
|
||||
return Registry.is("ide.new.welcome.screen") ? this : null;
|
||||
return Registry.is("ide.new.welcome.screen") && (PlatformUtils.isIntelliJ() || PlatformUtils.isCidr()) ? this : null;
|
||||
}
|
||||
|
||||
private class FlatWelcomeScreen extends JPanel implements WelcomeScreen {
|
||||
@@ -328,7 +329,7 @@ public class FlatWelcomeFrame extends JFrame implements WelcomeFrameProvider, Id
|
||||
|
||||
private JComponent createRecentProjects() {
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
panel.add(new NewRecentProjectPanel(this), BorderLayout.NORTH);
|
||||
panel.add(new NewRecentProjectPanel(this), BorderLayout.CENTER);
|
||||
panel.setBackground(getProjectsBackGround());
|
||||
return panel;
|
||||
}
|
||||
|
||||
@@ -1379,9 +1379,9 @@ action.MarkAsOriginalTypeAction.text=Mark as
|
||||
|
||||
action.Console.Execute.text=Execute Current Statement
|
||||
action.Console.Execute.description=Execute current statement in console
|
||||
action.Console.History.Previous.text=Previous
|
||||
action.Console.History.Previous.text=Previous history entry
|
||||
action.Console.History.Previous.description=Previous console history entry
|
||||
action.Console.History.Next.text=Next
|
||||
action.Console.History.Next.text=Next history entry
|
||||
action.Console.History.Next.description=Next console history entry
|
||||
action.Console.History.Browse.text=Browse History
|
||||
action.Console.History.Browse.description=Browse console history
|
||||
|
||||
@@ -295,4 +295,5 @@ exportable.CodeFoldingSettings.presentable.name=Code Folding
|
||||
exportable.XmlFoldingSettings.presentable.name=XML Code Folding
|
||||
exportable.XmlSettings.presentable.name=XML
|
||||
exportable.PlaybackDebugger.presentable.name=Playback Debugger
|
||||
exportable.XmlEditorOptions.presentable.name=XML Editor
|
||||
exportable.XmlEditorOptions.presentable.name=XML Editor
|
||||
exportable.BuiltInServerOptions.presentable.name=Built-in server
|
||||
@@ -537,9 +537,8 @@
|
||||
<customPortServerManager implementation="org.jetbrains.builtInWebServer.BuiltInServerOptions$MyCustomPortServerManager"/>
|
||||
<xdebugger.configurableProvider implementation="org.jetbrains.builtInWebServer.BuiltInServerOptions$BuiltInServerDebuggerConfigurableProvider"/>
|
||||
|
||||
<exportable serviceInterface="org.jetbrains.builtInWebServer.BuiltInServerOptions"/>
|
||||
<applicationService serviceInterface="org.jetbrains.builtInWebServer.BuiltInServerOptions" serviceImplementation="org.jetbrains.builtInWebServer.BuiltInServerOptions"/>
|
||||
<projectService serviceInterface="org.jetbrains.builtInWebServer.WebServerPathToFileManager" serviceImplementation="org.jetbrains.builtInWebServer.WebServerPathToFileManager"/>
|
||||
<applicationService serviceImplementation="org.jetbrains.builtInWebServer.BuiltInServerOptions"/>
|
||||
<projectService serviceImplementation="org.jetbrains.builtInWebServer.WebServerPathToFileManager"/>
|
||||
</extensions>
|
||||
<extensions defaultExtensionNs="org.jetbrains">
|
||||
<urlOpener implementation="com.intellij.ide.browsers.impl.DefaultUrlOpener" order="last"/>
|
||||
|
||||
@@ -631,7 +631,12 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro
|
||||
}
|
||||
catch (Throwable e) {
|
||||
CompositeException result = new CompositeException(e);
|
||||
disposeProject(result);
|
||||
try {
|
||||
tearDown();
|
||||
}
|
||||
catch (Throwable th) {
|
||||
result.add(th);
|
||||
}
|
||||
throw result;
|
||||
}
|
||||
try {
|
||||
|
||||
@@ -121,12 +121,23 @@ public class PlatformTestUtil {
|
||||
}
|
||||
|
||||
public static String print(JTree tree, boolean withSelection) {
|
||||
return print(tree, withSelection, null);
|
||||
return print(tree, tree.getModel().getRoot(), withSelection, null, null);
|
||||
}
|
||||
|
||||
public static String print(JTree tree, Object root, @Nullable Queryable.PrintInfo printInfo, boolean withSelection) {
|
||||
return print(tree, root, withSelection, printInfo, null);
|
||||
}
|
||||
|
||||
public static String print(JTree tree, boolean withSelection, @Nullable Condition<String> nodePrintCondition) {
|
||||
return print(tree, tree.getModel().getRoot(), withSelection, null, nodePrintCondition);
|
||||
}
|
||||
|
||||
public static String print(JTree tree, Object root,
|
||||
boolean withSelection,
|
||||
@Nullable Queryable.PrintInfo printInfo,
|
||||
@Nullable Condition<String> nodePrintCondition) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
final Collection<String> strings = printAsList(tree, withSelection, nodePrintCondition);
|
||||
final Collection<String> strings = printAsList(tree, root, withSelection, printInfo, nodePrintCondition);
|
||||
for (String string : strings) {
|
||||
buffer.append(string).append("\n");
|
||||
}
|
||||
@@ -134,9 +145,15 @@ public class PlatformTestUtil {
|
||||
}
|
||||
|
||||
public static Collection<String> printAsList(JTree tree, boolean withSelection, @Nullable Condition<String> nodePrintCondition) {
|
||||
return printAsList(tree, tree.getModel().getRoot(), withSelection, null, nodePrintCondition);
|
||||
}
|
||||
|
||||
private static Collection<String> printAsList(JTree tree, Object root,
|
||||
boolean withSelection,
|
||||
@Nullable Queryable.PrintInfo printInfo,
|
||||
Condition<String> nodePrintCondition) {
|
||||
Collection<String> strings = new ArrayList<String>();
|
||||
Object root = tree.getModel().getRoot();
|
||||
printImpl(tree, root, strings, 0, withSelection, nodePrintCondition);
|
||||
printImpl(tree, root, strings, 0, withSelection, printInfo, nodePrintCondition);
|
||||
return strings;
|
||||
}
|
||||
|
||||
@@ -145,13 +162,14 @@ public class PlatformTestUtil {
|
||||
Collection<String> strings,
|
||||
int level,
|
||||
boolean withSelection,
|
||||
@Nullable Queryable.PrintInfo printInfo,
|
||||
@Nullable Condition<String> nodePrintCondition) {
|
||||
DefaultMutableTreeNode defaultMutableTreeNode = (DefaultMutableTreeNode)root;
|
||||
|
||||
final Object userObject = defaultMutableTreeNode.getUserObject();
|
||||
String nodeText;
|
||||
if (userObject != null) {
|
||||
nodeText = toString(userObject, null);
|
||||
nodeText = toString(userObject, printInfo);
|
||||
}
|
||||
else {
|
||||
nodeText = "null";
|
||||
@@ -183,7 +201,7 @@ public class PlatformTestUtil {
|
||||
int childCount = tree.getModel().getChildCount(root);
|
||||
if (expanded) {
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
printImpl(tree, tree.getModel().getChild(root, i), strings, level + 1, withSelection, nodePrintCondition);
|
||||
printImpl(tree, tree.getModel().getChild(root, i), strings, level + 1, withSelection, printInfo, nodePrintCondition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -18,6 +18,7 @@ package com.intellij.openapi.vcs.changes.issueLinks;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.vcs.IssueNavigationConfiguration;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.SimpleColoredComponent;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.util.Consumer;
|
||||
@@ -84,7 +85,6 @@ public class IssueLinkRenderer {
|
||||
}
|
||||
|
||||
private static SimpleTextAttributes getLinkAttributes(final SimpleTextAttributes baseStyle) {
|
||||
return (baseStyle.getStyle() & SimpleTextAttributes.STYLE_BOLD) != 0 ?
|
||||
SimpleTextAttributes.LINK_BOLD_ATTRIBUTES : SimpleTextAttributes.LINK_ATTRIBUTES;
|
||||
return new SimpleTextAttributes(baseStyle.getStyle() | SimpleTextAttributes.STYLE_UNDERLINE, JBColor.blue);
|
||||
}
|
||||
}
|
||||
|
||||
+5
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2013 Dave Griffith, Bas Leijdekkers
|
||||
* Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,7 @@ package com.siyeh.ig.cloneable;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
@@ -67,6 +68,9 @@ public class CloneInNonCloneableClassInspection extends BaseInspection {
|
||||
if (CloneUtils.isCloneable(containingClass)) {
|
||||
return;
|
||||
}
|
||||
if (method.hasModifierProperty(PsiModifier.FINAL) && CloneUtils.onlyThrowsCloneNotSupportedException(method)) {
|
||||
return;
|
||||
}
|
||||
registerMethodError(method, containingClass);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -74,9 +74,8 @@ public class CloneUtils {
|
||||
if (!(statement instanceof PsiThrowStatement)) {
|
||||
return false;
|
||||
}
|
||||
final PsiThrowStatement throwStatement =
|
||||
(PsiThrowStatement)statement;
|
||||
final PsiExpression exception = throwStatement.getException();
|
||||
final PsiThrowStatement throwStatement = (PsiThrowStatement)statement;
|
||||
final PsiExpression exception = ParenthesesUtils.stripParentheses(throwStatement.getException());
|
||||
if (!(exception instanceof PsiNewExpression)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
+2
-16
@@ -21,8 +21,7 @@ import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.EditorSettings;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.FileTypes;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
@@ -105,24 +104,11 @@ public class ProblematicWhitespaceInspection extends BaseInspection {
|
||||
|
||||
private static class ProblematicWhitespaceVisitor extends BaseInspectionVisitor {
|
||||
|
||||
private static boolean isLanguageFileType(FileType fileType) {
|
||||
return (fileType != StdFileTypes.GUI_DESIGNER_FORM) &&
|
||||
(fileType != StdFileTypes.IDEA_MODULE) &&
|
||||
(fileType != StdFileTypes.IDEA_PROJECT) &&
|
||||
(fileType != StdFileTypes.IDEA_WORKSPACE) &&
|
||||
(fileType != FileTypes.ARCHIVE) &&
|
||||
(fileType != FileTypes.UNKNOWN) &&
|
||||
(fileType != FileTypes.PLAIN_TEXT) &&
|
||||
//!(fileType instanceof AbstractFileType) && // not sure about this one
|
||||
!fileType.isBinary() &&
|
||||
!fileType.isReadOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFile(PsiFile file) {
|
||||
super.visitFile(file);
|
||||
final FileType fileType = file.getFileType();
|
||||
if (!isLanguageFileType(fileType)) {
|
||||
if (!(fileType instanceof LanguageFileType)) {
|
||||
return;
|
||||
}
|
||||
final CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(file.getProject());
|
||||
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
package com.siyeh.igtest.cloneable;
|
||||
|
||||
public class CloneCallsConstructorInspection implements Cloneable
|
||||
{
|
||||
|
||||
public void foo()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Object clone()
|
||||
{
|
||||
return new CloneCallsConstructorInspection();
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
public class CloneInNonCloneableClass {
|
||||
|
||||
public final Object clone() throws CloneNotSupportedException {
|
||||
// don't warn on final method that only throws CloneNotSupportedException
|
||||
throw new CloneNotSupportedException();
|
||||
}
|
||||
}
|
||||
class AB {
|
||||
@Override
|
||||
protected Object <warning descr="'clone()' defined in non-Cloneable class 'AB'">clone</warning>() throws CloneNotSupportedException {
|
||||
return super.clone();
|
||||
}
|
||||
}
|
||||
+8
@@ -17,4 +17,12 @@ public class ReturnOfInnerClass {
|
||||
private Object four() {
|
||||
return new B();
|
||||
}
|
||||
|
||||
protected Object five() {
|
||||
return new B();
|
||||
}
|
||||
|
||||
Object six() {
|
||||
return new B();
|
||||
}
|
||||
}
|
||||
+11
-11
@@ -13,19 +13,19 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.execution.runners;
|
||||
package com.siyeh.ig.cloneable;
|
||||
|
||||
import com.intellij.execution.console.ProcessBackedConsoleExecuteActionHandler;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.codeInspection.InspectionProfileEntry;
|
||||
import com.siyeh.ig.LightInspectionTestCase;
|
||||
|
||||
@SuppressWarnings({"ClassNameSameAsAncestorName", "UnusedDeclaration"})
|
||||
@Deprecated
|
||||
/**
|
||||
* @deprecated Use {@link ProcessBackedConsoleExecuteActionHandler}
|
||||
* to remove in IDEA 15
|
||||
* @author Bas Leijdekkers
|
||||
*/
|
||||
public class ConsoleExecuteActionHandler extends ProcessBackedConsoleExecuteActionHandler {
|
||||
public ConsoleExecuteActionHandler(ProcessHandler processHandler, boolean preserveMarkup) {
|
||||
super(processHandler, preserveMarkup);
|
||||
public class CloneInNonCloneableClassInspectionTest extends LightInspectionTestCase {
|
||||
@Override
|
||||
protected InspectionProfileEntry getInspection() {
|
||||
return new CloneInNonCloneableClassInspection();
|
||||
}
|
||||
}
|
||||
|
||||
public void testCloneInNonCloneableClass() { doTest(); }
|
||||
}
|
||||
+3
-2
@@ -17,7 +17,6 @@ package com.siyeh.ig.memory;
|
||||
|
||||
import com.intellij.codeInspection.InspectionProfileEntry;
|
||||
import com.siyeh.ig.LightInspectionTestCase;
|
||||
import junit.framework.TestCase;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
@@ -30,6 +29,8 @@ public class ReturnOfInnerClassInspectionTest extends LightInspectionTestCase {
|
||||
@Nullable
|
||||
@Override
|
||||
protected InspectionProfileEntry getInspection() {
|
||||
return new ReturnOfInnerClassInspection();
|
||||
final ReturnOfInnerClassInspection inspection = new ReturnOfInnerClassInspection();
|
||||
inspection.ignoreNonPublic = true;
|
||||
return inspection;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention replaces a <b><></b> (diamond) with the equivalent
|
||||
This intention replaces a <b><></b> (diamond) with the equivalent
|
||||
explicit type arguments.
|
||||
<br><br>
|
||||
</body>
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.update.ActionInfo;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import git4idea.GitRevisionNumber;
|
||||
import git4idea.GitUtil;
|
||||
@@ -121,7 +122,7 @@ abstract class GitMergeAction extends GitRepositoryAction {
|
||||
GitRepositoryManager repositoryManager = GitUtil.getRepositoryManager(project);
|
||||
VirtualFile root = repository.getRoot();
|
||||
if (result.success()) {
|
||||
root.refresh(false, true);
|
||||
VfsUtil.markDirtyAndRefresh(false, true, false, root);
|
||||
List<VcsException> exceptions = new ArrayList<VcsException>();
|
||||
GitMergeUtil.showUpdates(this, project, exceptions, root, currentRev, beforeLabel, getActionName(), ActionInfo.UPDATE);
|
||||
repositoryManager.updateRepository(root);
|
||||
|
||||
@@ -15,26 +15,63 @@
|
||||
*/
|
||||
package git4idea.push;
|
||||
|
||||
import com.intellij.dvcs.DvcsUtil;
|
||||
import com.intellij.dvcs.push.PushSource;
|
||||
import git4idea.GitLocalBranch;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
class GitPushSource implements PushSource {
|
||||
abstract class GitPushSource implements PushSource {
|
||||
|
||||
@NotNull private final GitLocalBranch myBranch;
|
||||
|
||||
GitPushSource(@NotNull GitLocalBranch branch) {
|
||||
myBranch = branch;
|
||||
@NotNull
|
||||
static GitPushSource create(@NotNull GitLocalBranch branch) {
|
||||
return new OnBranch(branch);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getPresentation() {
|
||||
return myBranch.getName();
|
||||
static GitPushSource create(@NotNull String revision) {
|
||||
return new DetachedHead(revision);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public GitLocalBranch getBranch() {
|
||||
return myBranch;
|
||||
abstract GitLocalBranch getBranch();
|
||||
|
||||
private static class OnBranch extends GitPushSource {
|
||||
@NotNull private final GitLocalBranch myBranch;
|
||||
|
||||
private OnBranch(@NotNull GitLocalBranch branch) {
|
||||
myBranch = branch;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getPresentation() {
|
||||
return myBranch.getName();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
GitLocalBranch getBranch() {
|
||||
return myBranch;
|
||||
}
|
||||
}
|
||||
|
||||
private static class DetachedHead extends GitPushSource {
|
||||
@NotNull private final String myRevision;
|
||||
|
||||
public DetachedHead(@NotNull String revision) {
|
||||
myRevision = revision;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getPresentation() {
|
||||
return DvcsUtil.getShortHash(myRevision);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
GitLocalBranch getBranch() {
|
||||
throw new IllegalStateException("Push is not allowed from detached HEAD");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,6 +81,9 @@ public class GitPushSupport extends PushSupport<GitRepository, GitPushSource, Gi
|
||||
@Nullable
|
||||
@Override
|
||||
public GitPushTarget getDefaultTarget(@NotNull GitRepository repository) {
|
||||
if (repository.isFresh()) {
|
||||
return null;
|
||||
}
|
||||
GitLocalBranch currentBranch = repository.getCurrentBranch();
|
||||
if (currentBranch == null) {
|
||||
return null;
|
||||
@@ -123,7 +126,10 @@ public class GitPushSupport extends PushSupport<GitRepository, GitPushSource, Gi
|
||||
@NotNull
|
||||
@Override
|
||||
public GitPushSource getSource(@NotNull GitRepository repository) {
|
||||
return new GitPushSource(repository.getCurrentBranch()); // TODO assert: detached head => not possible to push
|
||||
GitLocalBranch currentBranch = repository.getCurrentBranch();
|
||||
return currentBranch != null
|
||||
? GitPushSource.create(currentBranch)
|
||||
: GitPushSource.create(ObjectUtils.assertNotNull(repository.getCurrentRevision())); // fresh repository is on branch
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -24,7 +24,6 @@ import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.ui.popup.ListPopup;
|
||||
import com.intellij.openapi.ui.popup.PopupStep;
|
||||
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.ColoredTreeCellRenderer;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
@@ -51,30 +50,40 @@ class GitPushTargetPanel extends PushTargetPanel<GitPushTarget> {
|
||||
|
||||
private static final Comparator<GitRemoteBranch> REMOTE_BRANCH_COMPARATOR = new MyRemoteBranchComparator();
|
||||
private static final String SEPARATOR = " : ";
|
||||
private static final String NO_REMOTES = "No remotes";
|
||||
|
||||
private final GitRepository myRepository;
|
||||
private final PushTargetTextField myTargetTextField;
|
||||
private final JLabel myRemoteLabel;
|
||||
@NotNull private final GitRepository myRepository;
|
||||
@NotNull private final PushTargetTextField myTargetTextField;
|
||||
@NotNull private final JLabel myRemoteLabel;
|
||||
@NotNull private final ExtraEditControl myEditRemoteControl;
|
||||
|
||||
@Nullable private GitPushTarget myCurrentTarget;
|
||||
@Nullable private String myError;
|
||||
@Nullable private Runnable myFireOnChangeAction;
|
||||
@NotNull private ExtraEditControl myEditRemoteControl;
|
||||
|
||||
public GitPushTargetPanel(@NotNull GitRepository repository, @Nullable GitPushTarget defaultTarget) {
|
||||
myRepository = repository;
|
||||
|
||||
myCurrentTarget = defaultTarget;
|
||||
|
||||
String initialBranch;
|
||||
String initialRemote;
|
||||
String initialBranch = "";
|
||||
String initialRemote = "";
|
||||
if (defaultTarget == null) {
|
||||
initialBranch = "";
|
||||
initialRemote = NO_REMOTES;
|
||||
if (repository.getCurrentBranch() == null) {
|
||||
myError = "Detached HEAD";
|
||||
}
|
||||
else if (repository.getRemotes().isEmpty()) {
|
||||
myError = "No remotes";
|
||||
}
|
||||
else if (repository.isFresh()) {
|
||||
myError = "Empty repository";
|
||||
}
|
||||
else {
|
||||
myError = "Can't push";
|
||||
}
|
||||
}
|
||||
else {
|
||||
initialBranch = getTextFieldText(defaultTarget);
|
||||
initialRemote = getRemoteLabelText(defaultTarget.getBranch().getRemote().getName());
|
||||
initialRemote = defaultTarget.getBranch().getRemote().getName();
|
||||
}
|
||||
|
||||
myEditRemoteControl = new ExtraEditControl() {
|
||||
@@ -89,7 +98,12 @@ class GitPushTargetPanel extends PushTargetPanel<GitPushTarget> {
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
setOpaque(false);
|
||||
add(myRemoteLabel, BorderLayout.WEST);
|
||||
JPanel remoteAndSeparator = new JPanel(new BorderLayout());
|
||||
remoteAndSeparator.setOpaque(false);
|
||||
remoteAndSeparator.add(myRemoteLabel, BorderLayout.CENTER);
|
||||
remoteAndSeparator.add(new JBLabel(SEPARATOR), BorderLayout.EAST);
|
||||
|
||||
add(remoteAndSeparator, BorderLayout.WEST);
|
||||
add(myTargetTextField, BorderLayout.CENTER);
|
||||
updateTextField();
|
||||
}
|
||||
@@ -107,7 +121,7 @@ class GitPushTargetPanel extends PushTargetPanel<GitPushTarget> {
|
||||
ListPopup popup = JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep<String>(null, remotes) {
|
||||
@Override
|
||||
public PopupStep onChosen(String selectedValue, boolean finalChoice) {
|
||||
myRemoteLabel.setText(getRemoteLabelText(selectedValue));
|
||||
myRemoteLabel.setText(selectedValue);
|
||||
if (myFireOnChangeAction != null) {
|
||||
myFireOnChangeAction.run();
|
||||
}
|
||||
@@ -129,9 +143,8 @@ class GitPushTargetPanel extends PushTargetPanel<GitPushTarget> {
|
||||
|
||||
@Override
|
||||
public void render(@NotNull final ColoredTreeCellRenderer renderer) {
|
||||
String targetName = myTargetTextField.getText();
|
||||
if (StringUtil.isEmptyOrSpaces(targetName)) {
|
||||
renderer.append(NO_REMOTES, SimpleTextAttributes.ERROR_ATTRIBUTES, this);
|
||||
if (myError != null) {
|
||||
renderer.append(myError, SimpleTextAttributes.ERROR_ATTRIBUTES);
|
||||
}
|
||||
else {
|
||||
String currentRemote = myRemoteLabel.getText();
|
||||
@@ -141,6 +154,7 @@ class GitPushTargetPanel extends PushTargetPanel<GitPushTarget> {
|
||||
else {
|
||||
renderer.append(currentRemote, SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
}
|
||||
renderer.append(SEPARATOR, SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
|
||||
GitPushTarget target = getValue();
|
||||
if (target.isNewBranchCreated()) {
|
||||
@@ -161,10 +175,6 @@ class GitPushTargetPanel extends PushTargetPanel<GitPushTarget> {
|
||||
return (target != null ? target.getBranch().getNameForRemoteOperations() : "");
|
||||
}
|
||||
|
||||
private static String getRemoteLabelText(@NotNull String selectedValue) {
|
||||
return selectedValue + SEPARATOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireOnCancel() {
|
||||
myTargetTextField.setText(getTextFieldText(myCurrentTarget));
|
||||
@@ -172,7 +182,10 @@ class GitPushTargetPanel extends PushTargetPanel<GitPushTarget> {
|
||||
|
||||
@Override
|
||||
public void fireOnChange() {
|
||||
String remoteName = getEnteredRemote();
|
||||
if (myError == null) {
|
||||
return;
|
||||
}
|
||||
String remoteName = myRemoteLabel.getText();
|
||||
String branchName = myTargetTextField.getText();
|
||||
try {
|
||||
myCurrentTarget = GitPushTarget.parse(myRepository, remoteName, branchName);
|
||||
@@ -185,9 +198,11 @@ class GitPushTargetPanel extends PushTargetPanel<GitPushTarget> {
|
||||
@Nullable
|
||||
@Override
|
||||
public ValidationInfo verify() {
|
||||
if (myError != null) {
|
||||
return new ValidationInfo(myError, myTargetTextField);
|
||||
}
|
||||
try {
|
||||
String remoteLabel = getEnteredRemote();
|
||||
GitPushTarget.parse(myRepository, remoteLabel, myTargetTextField.getText());
|
||||
GitPushTarget.parse(myRepository, myRemoteLabel.getText(), myTargetTextField.getText());
|
||||
return null;
|
||||
}
|
||||
catch (ParseException e) {
|
||||
@@ -195,17 +210,12 @@ class GitPushTargetPanel extends PushTargetPanel<GitPushTarget> {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@Override
|
||||
public void setFireOnChangeAction(@NotNull Runnable action) {
|
||||
myFireOnChangeAction = action;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getEnteredRemote() {
|
||||
String text = myRemoteLabel.getText();
|
||||
return text.equals(NO_REMOTES) ? null : text.replace(SEPARATOR, "");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<String> getTargetNames(@NotNull GitRepository repository) {
|
||||
List<GitRemoteBranch> remoteBranches = ContainerUtil.sorted(repository.getBranches().getRemoteBranches(), REMOTE_BRANCH_COMPARATOR);
|
||||
@@ -219,7 +229,7 @@ class GitPushTargetPanel extends PushTargetPanel<GitPushTarget> {
|
||||
|
||||
private static class MyRemoteBranchComparator implements Comparator<GitRemoteBranch> {
|
||||
@Override
|
||||
public int compare(GitRemoteBranch o1, GitRemoteBranch o2) {
|
||||
public int compare(@NotNull GitRemoteBranch o1, @NotNull GitRemoteBranch o2) {
|
||||
String remoteName1 = o1.getRemote().getName();
|
||||
String remoteName2 = o2.getRemote().getName();
|
||||
int remoteComparison = remoteName1.compareTo(remoteName2);
|
||||
|
||||
@@ -138,7 +138,7 @@ abstract class GitPushOperationBaseTest extends GitPlatformTest {
|
||||
else {
|
||||
newBranch = false;
|
||||
}
|
||||
return new PushSpec<GitPushSource, GitPushTarget>(new GitPushSource(source), new GitPushTarget(target, newBranch));
|
||||
return new PushSpec<GitPushSource, GitPushTarget>(GitPushSource.create(source), new GitPushTarget(target, newBranch));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.github.ui.GithubSettingsPanel">
|
||||
<grid id="27dc6" binding="myPane" layout-manager="GridLayoutManager" row-count="5" column-count="5" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="27dc6" binding="myPane" layout-manager="GridLayoutManager" row-count="6" column-count="5" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="646" height="400"/>
|
||||
@@ -13,7 +13,7 @@
|
||||
<children>
|
||||
<component id="28ddd" class="javax.swing.JTextPane" binding="mySignupTextField">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="4" vsize-policy="0" hsize-policy="2" anchor="0" fill="1" indent="0" use-parent-layout="false">
|
||||
<grid row="2" column="1" row-span="1" col-span="3" vsize-policy="0" hsize-policy="2" anchor="0" fill="1" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="150" height="10"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
@@ -28,7 +28,7 @@
|
||||
</component>
|
||||
<vspacer id="6ace">
|
||||
<constraints>
|
||||
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
<component id="45bab" class="com.intellij.ui.components.JBLabel">
|
||||
@@ -167,13 +167,13 @@
|
||||
<grid id="d384a" layout-manager="GridLayoutManager" row-count="1" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="3" column="0" row-span="1" col-span="5" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<grid row="4" column="0" row-span="1" col-span="5" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<clientProperties>
|
||||
<html.disable class="java.lang.Boolean" value="false"/>
|
||||
</clientProperties>
|
||||
<border type="etched" title="Other Settings:"/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="ae995" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
@@ -204,6 +204,15 @@
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<vspacer id="2a9d8">
|
||||
<constraints>
|
||||
<grid row="3" column="0" row-span="1" col-span="5" vsize-policy="0" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false">
|
||||
<minimum-size width="-1" height="15"/>
|
||||
<preferred-size width="-1" height="15"/>
|
||||
<maximum-size width="-1" height="15"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
|
||||
+5
-2
@@ -254,8 +254,11 @@ public class ClassWriter {
|
||||
|
||||
if (hasContent) {
|
||||
buffer.appendLineSeparator();
|
||||
startLine++;
|
||||
}
|
||||
classToJava(inner, buffer, indent + 1, tracer);
|
||||
BytecodeMappingTracer class_tracer = new BytecodeMappingTracer(startLine);
|
||||
classToJava(inner, buffer, indent + 1, class_tracer);
|
||||
startLine = buffer.countLines();
|
||||
|
||||
hasContent = true;
|
||||
}
|
||||
@@ -840,7 +843,7 @@ public class ClassWriter {
|
||||
|
||||
// save total lines
|
||||
// TODO: optimize
|
||||
tracer.setCurrentSourceLine(buffer.countLines(start_index_method));
|
||||
//tracer.setCurrentSourceLine(buffer.countLines(start_index_method));
|
||||
|
||||
return !hideMethod;
|
||||
}
|
||||
|
||||
+1
@@ -280,6 +280,7 @@ public class ClassesProcessor {
|
||||
}
|
||||
//buffer.append(lineSeparator);
|
||||
|
||||
total_offset_lines = buffer.countLines();
|
||||
buffer.append(classBuffer);
|
||||
|
||||
if (DecompilerContext.getOption(IFernflowerPreferences.BYTECODE_SOURCE_MAPPING)) {
|
||||
|
||||
+1
-1
@@ -97,7 +97,7 @@ public class BytecodeSourceMapper {
|
||||
buffer.append("Lines mapping:").appendLineSeparator();
|
||||
Map<Integer, Integer> sorted = new TreeMap<Integer, Integer>(linesMapping);
|
||||
for (Entry<Integer, Integer> entry : sorted.entrySet()) {
|
||||
buffer.append(entry.getKey()).append(" <-> ").append(entry.getValue()).appendLineSeparator();
|
||||
buffer.append(entry.getKey()).append(" <-> ").append(entry.getValue()+ offset_total + 1).appendLineSeparator();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -187,7 +187,6 @@ public class CatchStatement extends Statement {
|
||||
tracer.incrementCurrentSourceLine();
|
||||
buf.append(ExprProcessor.jmpWrapper(stats.get(i), indent + 1, true, tracer)).append(indstr)
|
||||
.append("}");
|
||||
tracer.incrementCurrentSourceLine();
|
||||
}
|
||||
buf.append(new_line_separator);
|
||||
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
+68
-20
@@ -8,6 +8,7 @@ public class TestClassSimpleBytecodeMapping {
|
||||
System.out.println("Runnable");
|
||||
}
|
||||
});
|
||||
this.test2("1");
|
||||
if(Math.random() > 0.0D) {
|
||||
System.out.println("0");
|
||||
return 0;
|
||||
@@ -17,9 +18,30 @@ public class TestClassSimpleBytecodeMapping {
|
||||
}
|
||||
}
|
||||
|
||||
public void test2(String var1) {
|
||||
try {
|
||||
Integer.parseInt(var1);
|
||||
} catch (Exception var3) {
|
||||
System.out.println(var3);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void run(Runnable var1) {
|
||||
var1.run();
|
||||
}
|
||||
|
||||
public class InnerClass2 {
|
||||
public void print() {
|
||||
System.out.println("Inner2");
|
||||
}
|
||||
}
|
||||
|
||||
public class InnerClass {
|
||||
public void print() {
|
||||
System.out.println("Inner");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class 'pkg/TestClassSimpleBytecodeMapping$1' {
|
||||
@@ -36,34 +58,60 @@ class 'pkg/TestClassSimpleBytecodeMapping' {
|
||||
3 4
|
||||
5 4
|
||||
11 5
|
||||
14 10
|
||||
15 10
|
||||
17 10
|
||||
18 10
|
||||
19 10
|
||||
1c 11
|
||||
1a 11
|
||||
1d 11
|
||||
1e 11
|
||||
1f 11
|
||||
21 11
|
||||
24 12
|
||||
22 12
|
||||
25 12
|
||||
26 14
|
||||
29 14
|
||||
2b 14
|
||||
2e 15
|
||||
27 12
|
||||
2a 13
|
||||
2b 13
|
||||
2c 15
|
||||
2f 15
|
||||
31 15
|
||||
34 16
|
||||
35 16
|
||||
}
|
||||
|
||||
method 'test2 (Ljava/lang/String;)V' {
|
||||
1 22
|
||||
}
|
||||
|
||||
method 'run (Ljava/lang/Runnable;)V' {
|
||||
1 20
|
||||
1 30
|
||||
}
|
||||
}
|
||||
|
||||
class 'pkg/TestClassSimpleBytecodeMapping$InnerClass2' {
|
||||
method 'print ()V' {
|
||||
0 35
|
||||
3 35
|
||||
5 35
|
||||
}
|
||||
}
|
||||
|
||||
class 'pkg/TestClassSimpleBytecodeMapping$InnerClass' {
|
||||
method 'print ()V' {
|
||||
0 41
|
||||
3 41
|
||||
5 41
|
||||
}
|
||||
}
|
||||
|
||||
Lines mapping:
|
||||
12 <-> 2
|
||||
14 <-> 3
|
||||
17 <-> 5
|
||||
21 <-> 8
|
||||
22 <-> 9
|
||||
23 <-> 10
|
||||
25 <-> 12
|
||||
26 <-> 13
|
||||
31 <-> 18
|
||||
12 <-> 5
|
||||
14 <-> 6
|
||||
17 <-> 8
|
||||
21 <-> 11
|
||||
23 <-> 12
|
||||
24 <-> 13
|
||||
25 <-> 14
|
||||
27 <-> 16
|
||||
28 <-> 17
|
||||
34 <-> 23
|
||||
42 <-> 42
|
||||
47 <-> 31
|
||||
52 <-> 36
|
||||
|
||||
@@ -18,6 +18,8 @@ public class TestClassSimpleBytecodeMapping {
|
||||
}
|
||||
});
|
||||
|
||||
test2("1");
|
||||
|
||||
if(Math.random() > 0) {
|
||||
System.out.println("0");
|
||||
return 0;
|
||||
@@ -27,7 +29,27 @@ public class TestClassSimpleBytecodeMapping {
|
||||
}
|
||||
}
|
||||
|
||||
public void test2(String a) {
|
||||
try {
|
||||
Integer.parseInt(a);
|
||||
} catch (Exception e) {
|
||||
System.out.println(e);
|
||||
}
|
||||
}
|
||||
|
||||
public class InnerClass {
|
||||
public void print() {
|
||||
System.out.println("Inner");
|
||||
}
|
||||
}
|
||||
|
||||
void run(Runnable r) {
|
||||
r.run();
|
||||
}
|
||||
|
||||
public class InnerClass2 {
|
||||
public void print() {
|
||||
System.out.println("Inner2");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5593,9 +5593,9 @@ action.MarkAsOriginalTypeAction.text=Mark as
|
||||
|
||||
action.Console.Execute.text=Execute Current Statement
|
||||
action.Console.Execute.description=Execute current statement in console
|
||||
action.Console.History.Previous.text=Previous
|
||||
action.Console.History.Previous.text=Previous history entry
|
||||
action.Console.History.Previous.description=Previous console history entry
|
||||
action.Console.History.Next.text=Next
|
||||
action.Console.History.Next.text=Next history entry
|
||||
action.Console.History.Next.description=Next console history entry
|
||||
action.Console.History.Browse.text=Browse History
|
||||
action.Console.History.Browse.description=Browse console history
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<grid id="27dc6" binding="myComponent" layout-manager="GridLayoutManager" row-count="7" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="1135" height="631"/>
|
||||
<xy x="20" y="20" width="1135" height="646"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<clientProperties>
|
||||
@@ -240,7 +240,7 @@
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="84b94" layout-manager="GridLayoutManager" row-count="8" column-count="31" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="84b94" layout-manager="GridLayoutManager" row-count="10" column-count="31" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<tabbedpane title="Network"/>
|
||||
@@ -250,7 +250,7 @@
|
||||
<children>
|
||||
<vspacer id="95e5d">
|
||||
<constraints>
|
||||
<grid row="6" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
<grid row="8" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
<component id="1283d" class="javax.swing.JCheckBox" binding="myUseCommonProxy">
|
||||
@@ -264,7 +264,7 @@
|
||||
<grid id="96256" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="7" column="0" row-span="1" col-span="31" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<grid row="9" column="0" row-span="1" col-span="31" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
@@ -304,19 +304,20 @@
|
||||
<text resource-bundle="org/jetbrains/idea/svn/SvnBundle" key="use.idea.proxy.as.default.label.text"/>
|
||||
</properties>
|
||||
</component>
|
||||
<grid id="9e56c" layout-manager="GridLayoutManager" row-count="3" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="6d452" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="3" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="9c08f" class="javax.swing.JLabel">
|
||||
<component id="9c08f" class="com.intellij.ui.components.JBLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<anchor value="234"/>
|
||||
<text value="HTTP timeout:"/>
|
||||
</properties>
|
||||
</component>
|
||||
@@ -328,30 +329,6 @@
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<component id="234" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="SSH connection timeout:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="21604" class="javax.swing.JSpinner" binding="mySSHConnectionTimeout" custom-create="true">
|
||||
<constraints>
|
||||
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="70" height="-1"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<component id="6949c" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="1" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="seconds"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="c9190" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
@@ -360,102 +337,159 @@
|
||||
<text value="seconds"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="a770c" class="javax.swing.JLabel">
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="6ae1d" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="234" class="com.intellij.ui.components.JBLabel">
|
||||
<constraints>
|
||||
<grid row="2" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="seconds"/>
|
||||
<text value="SSH connection timeout:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="8e59f" class="javax.swing.JSpinner" binding="mySSHReadTimeout" custom-create="true">
|
||||
<component id="21604" class="javax.swing.JSpinner" binding="mySSHConnectionTimeout" custom-create="true">
|
||||
<constraints>
|
||||
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="70" height="-1"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<component id="44801" class="javax.swing.JLabel">
|
||||
<component id="6949c" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="SSH read timeout:"/>
|
||||
<text value="seconds"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<hspacer id="29b97">
|
||||
<constraints>
|
||||
<grid row="3" column="3" row-span="1" col-span="28" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</hspacer>
|
||||
<grid id="4756d" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="85015" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children/>
|
||||
</grid>
|
||||
<grid id="4b641" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children/>
|
||||
</grid>
|
||||
<grid id="fdb89" layout-manager="GridLayoutManager" row-count="2" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none" title="SSL protocols"/>
|
||||
<children>
|
||||
<component id="a97cb" class="com.intellij.ui.components.JBRadioButton" binding="mySSLv3RadioButton" default-binding="true">
|
||||
<component id="44801" class="com.intellij.ui.components.JBLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="SSLv3"/>
|
||||
<anchor value="234"/>
|
||||
<text value="SSH read timeout:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="48af1" class="com.intellij.ui.components.JBRadioButton" binding="myTLSv1RadioButton" default-binding="true">
|
||||
<component id="8e59f" class="javax.swing.JSpinner" binding="mySSHReadTimeout" custom-create="true">
|
||||
<constraints>
|
||||
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="70" height="-1"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<component id="a770c" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="TLSv1"/>
|
||||
<text value="seconds"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="5c1ce" class="com.intellij.ui.components.JBRadioButton" binding="myAllRadioButton" default-binding="true">
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="2a91c" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="7" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="1528f" class="com.intellij.ui.components.JBLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="All"/>
|
||||
<anchor value="234"/>
|
||||
<text value="SSL protocols:"/>
|
||||
<verticalAlignment value="0"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="98a95" class="javax.swing.JLabel" binding="mySSLExplicitly">
|
||||
<grid id="fdb89" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="1" use-parent-layout="false"/>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="a97cb" class="com.intellij.ui.components.JBRadioButton" binding="mySSLv3RadioButton" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="SSLv3"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="48af1" class="com.intellij.ui.components.JBRadioButton" binding="myTLSv1RadioButton" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="TLSv1"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="5c1ce" class="com.intellij.ui.components.JBRadioButton" binding="myAllRadioButton" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="All"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<component id="98a95" class="com.intellij.ui.components.JBLabel" binding="mySSLExplicitly">
|
||||
<constraints>
|
||||
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="1" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<componentStyle value="SMALL"/>
|
||||
<fontColor value="BRIGHTER"/>
|
||||
<text value=""/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<hspacer id="c45eb">
|
||||
<vspacer id="e6874">
|
||||
<constraints>
|
||||
<grid row="5" column="1" row-span="1" col-span="12" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
<grid row="6" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false">
|
||||
<minimum-size width="-1" height="15"/>
|
||||
<preferred-size width="-1" height="15"/>
|
||||
<maximum-size width="-1" height="15"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
</hspacer>
|
||||
</vspacer>
|
||||
<vspacer id="2b945">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false">
|
||||
<minimum-size width="-1" height="15"/>
|
||||
<preferred-size width="-1" height="15"/>
|
||||
<maximum-size width="-1" height="15"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="763be" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
|
||||
+5
-3
@@ -125,10 +125,12 @@ public class StudyRefreshTaskFileAction extends DumbAwareAction {
|
||||
patternText.append("\n");
|
||||
}
|
||||
int patternLength = patternText.length();
|
||||
if (patternText.charAt(patternLength - 1) == '\n') {
|
||||
patternText.delete(patternLength - 1, patternLength);
|
||||
if (patternLength != 0) {
|
||||
if (patternText.charAt(patternLength - 1) == '\n') {
|
||||
patternText.delete(patternLength - 1, patternLength);
|
||||
}
|
||||
document.setText(patternText);
|
||||
}
|
||||
document.setText(patternText);
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
LOG.error(e);
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.intellij.updater;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
public abstract class BaseDeleteAction extends PatchAction {
|
||||
public BaseDeleteAction(String path, long checksum) {
|
||||
super(path, checksum);
|
||||
}
|
||||
|
||||
public BaseDeleteAction(DataInputStream in) throws IOException {
|
||||
super(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doBuildPatchFile(File olderFile, File newerFile, ZipOutputStream patchOutput) throws IOException {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ValidationResult doValidate(File toFile) throws IOException {
|
||||
ValidationResult result = doValidateAccess(toFile, ValidationResult.Action.DELETE);
|
||||
if (result != null) return result;
|
||||
|
||||
if (toFile.exists() && isModified(toFile)) {
|
||||
return new ValidationResult(ValidationResult.Kind.CONFLICT,
|
||||
myPath,
|
||||
ValidationResult.Action.DELETE,
|
||||
"Modified",
|
||||
ValidationResult.Option.DELETE,
|
||||
ValidationResult.Option.KEEP);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldApplyOn(File toFile) {
|
||||
return toFile.exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doApply(ZipFile patchFile, File toFile) throws IOException {
|
||||
Utils.delete(toFile);
|
||||
}
|
||||
|
||||
protected void doBackup(File toFile, File backupFile) throws IOException {
|
||||
Utils.copy(toFile, backupFile);
|
||||
}
|
||||
|
||||
protected void doRevert(File toFile, File backupFile) throws IOException {
|
||||
if (!toFile.exists() || toFile.isDirectory() || isModified(toFile)) {
|
||||
Utils.delete(toFile); // make sure there is no directory remained on this path (may remain from previous 'create' actions
|
||||
Utils.copy(backupFile, toFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,13 +35,7 @@ public abstract class BaseUpdateAction extends PatchAction {
|
||||
|
||||
protected void replaceUpdated(File from, File dest) throws IOException {
|
||||
// on OS X code signing caches seem to be associated with specific file ids, so we need to remove the original file.
|
||||
if (!dest.delete()) {
|
||||
if (Utils.isWindows()) {
|
||||
throw new RetryException("Cannot delete file " + dest);
|
||||
} else {
|
||||
throw new IOException("Cannot delete file " + dest);
|
||||
}
|
||||
}
|
||||
if (!dest.delete()) throw new IOException("Cannot delete file " + dest);
|
||||
Utils.copy(from, dest);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,11 @@ public class CreateAction extends PatchAction {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isModified(File toFile) throws IOException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doApply(ZipFile patchFile, File toFile) throws IOException {
|
||||
prepareToWriteFile(toFile);
|
||||
@@ -59,15 +64,7 @@ public class CreateAction extends PatchAction {
|
||||
|
||||
private static void prepareToWriteFile(File file) throws IOException {
|
||||
if (file.exists()) {
|
||||
try {
|
||||
Utils.delete(file);
|
||||
} catch (IOException e) {
|
||||
if (Utils.isWindows() && file.exists()) {
|
||||
throw new RetryException(e);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
Utils.delete(file);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,10 +3,8 @@ package com.intellij.updater;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
public class DeleteAction extends PatchAction {
|
||||
public class DeleteAction extends BaseDeleteAction {
|
||||
public DeleteAction(String path, long checksum) {
|
||||
super(path, checksum);
|
||||
}
|
||||
@@ -16,54 +14,7 @@ public class DeleteAction extends PatchAction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doBuildPatchFile(File olderFile, File newerFile, ZipOutputStream patchOutput) throws IOException {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ValidationResult doValidate(File toFile) throws IOException {
|
||||
ValidationResult result = doValidateAccess(toFile, ValidationResult.Action.DELETE);
|
||||
if (result != null) return result;
|
||||
|
||||
if (toFile.exists() && isModified(toFile)) {
|
||||
return new ValidationResult(ValidationResult.Kind.CONFLICT,
|
||||
myPath,
|
||||
ValidationResult.Action.DELETE,
|
||||
"Modified",
|
||||
ValidationResult.Option.DELETE,
|
||||
ValidationResult.Option.KEEP);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldApplyOn(File toFile) {
|
||||
return toFile.exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doApply(ZipFile patchFile, File toFile) throws IOException {
|
||||
try {
|
||||
Utils.delete(toFile);
|
||||
} catch (IOException e) {
|
||||
if (Utils.isWindows() && toFile.exists()) {
|
||||
throw new RetryException(e);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBackup(File toFile, File backupFile) throws IOException {
|
||||
Utils.copy(toFile, backupFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRevert(File toFile, File backupFile) throws IOException {
|
||||
if (!toFile.exists() || isModified(toFile)) {
|
||||
Utils.delete(toFile); // make sure there is no directory remained on this path (may remain from previous 'create' actions
|
||||
Utils.copy(backupFile, toFile);
|
||||
}
|
||||
protected boolean isModified(File toFile) throws IOException {
|
||||
return myChecksum != Digester.digestRegularFile(toFile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.intellij.updater;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public class DeleteZipAction extends BaseDeleteAction {
|
||||
public DeleteZipAction(String path, long checksum) {
|
||||
super(path, checksum);
|
||||
}
|
||||
|
||||
public DeleteZipAction(DataInputStream in) throws IOException {
|
||||
super(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isModified(File toFile) throws IOException {
|
||||
return myChecksum != Digester.digestFile(toFile);
|
||||
}
|
||||
}
|
||||
@@ -22,15 +22,14 @@ public class Digester {
|
||||
}
|
||||
|
||||
public static long digestFile(File file) throws IOException {
|
||||
if (Utils.isZipFile(file.getName())) {
|
||||
if (!Runner.ZIP_AS_BINARY && Utils.isZipFile(file.getName())) {
|
||||
ZipFile zipFile;
|
||||
try {
|
||||
zipFile = new ZipFile(file);
|
||||
}
|
||||
catch (IOException e) {
|
||||
// If this isn't a zip file, this isn't really an error, merely an info.
|
||||
Runner.infoStackTrace("Can't open file as zip file: " + file.getPath() + "\n", e);
|
||||
return doDigestRegularFile(file);
|
||||
Runner.printStackTrace(e);
|
||||
return digestRegularFile(file);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -40,10 +39,10 @@ public class Digester {
|
||||
zipFile.close();
|
||||
}
|
||||
}
|
||||
return doDigestRegularFile(file);
|
||||
return digestRegularFile(file);
|
||||
}
|
||||
|
||||
private static long doDigestRegularFile(File file) throws IOException {
|
||||
public static long digestRegularFile(File file) throws IOException {
|
||||
InputStream in = new BufferedInputStream(new FileInputStream(file));
|
||||
try {
|
||||
return digestStream(in);
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* 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 com.intellij.updater;
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
import com.sun.jna.StringArray;
|
||||
import com.sun.jna.WString;
|
||||
import com.sun.jna.platform.win32.Kernel32;
|
||||
import com.sun.jna.platform.win32.WinBase;
|
||||
import com.sun.jna.platform.win32.WinNT;
|
||||
import com.sun.jna.ptr.IntByReference;
|
||||
import com.sun.jna.ptr.LongByReference;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A utility class to find processes that hold a lock to a file. This relies on a Windows API called
|
||||
* RestartManager {@see http://msdn.microsoft.com/en-us/library/windows/desktop/cc948910(v=vs.85).aspx}
|
||||
*
|
||||
* This class uses the RestartManager and the Kernel32 APIs, and it tries to initialize them the first
|
||||
* time it is run. If the RestartManager DLL is not found, it being because we are running on XP or
|
||||
* because we are not running on Windows, then the class is flagged as failed and no further attempts
|
||||
* will be made to load the DLL.
|
||||
*/
|
||||
public class NativeFileManager {
|
||||
|
||||
private static final int MAX_PROCESSES = 10;
|
||||
|
||||
private static boolean ourFailed = false;
|
||||
|
||||
public static class Process {
|
||||
public final int pid;
|
||||
public final String name;
|
||||
|
||||
public Process(int pid, String name) {
|
||||
this.pid = pid;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public boolean terminate() {
|
||||
Kernel32.HANDLE process = Kernel32.INSTANCE.OpenProcess(WinNT.PROCESS_TERMINATE | WinNT.SYNCHRONIZE, false, pid);
|
||||
if (process.getPointer() == null) {
|
||||
Runner.logger.warn("Unable to find process " + name + "(" + pid + ")");
|
||||
return false;
|
||||
} else {
|
||||
Kernel32.INSTANCE.TerminateProcess(process, 1);
|
||||
int wait = Kernel32.INSTANCE.WaitForSingleObject(process, 1000);
|
||||
if (wait != WinBase.WAIT_OBJECT_0) {
|
||||
Runner.logger.warn("Timed out while waiting for process " + name + "(" + pid + ") to end");
|
||||
return false;
|
||||
}
|
||||
Kernel32.INSTANCE.CloseHandle(process);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Process> getProcessesUsing(File file) {
|
||||
List<Process> processes = new LinkedList<Process>();
|
||||
// If the DLL was not present (XP or other OS), do not try to find it again.
|
||||
if (ourFailed) {
|
||||
return processes;
|
||||
}
|
||||
try {
|
||||
IntByReference session = new IntByReference();
|
||||
char[] sessionKey = new char[Win32RestartManager.CCH_RM_SESSION_KEY + 1];
|
||||
int error = Win32RestartManager.INSTANCE.RmStartSession(session, 0, sessionKey);
|
||||
if (error != 0) {
|
||||
Runner.logger.warn("Unable to start restart manager session");
|
||||
return processes;
|
||||
}
|
||||
StringArray resources = new StringArray(new WString[]{new WString(file.toString())});
|
||||
error = Win32RestartManager.INSTANCE.RmRegisterResources(session.getValue(), 1, resources, 0, Pointer.NULL, 0, null);
|
||||
if (error != 0) {
|
||||
Runner.logger.warn("Unable to register restart manager resource " + file.getAbsolutePath());
|
||||
return processes;
|
||||
}
|
||||
|
||||
IntByReference procInfoNeeded = new IntByReference();
|
||||
Win32RestartManager.RmProcessInfo info = new Win32RestartManager.RmProcessInfo();
|
||||
Win32RestartManager.RmProcessInfo[] infos = (Win32RestartManager.RmProcessInfo[])info.toArray(MAX_PROCESSES);
|
||||
IntByReference procInfo = new IntByReference(infos.length);
|
||||
error = Win32RestartManager.INSTANCE.RmGetList(session.getValue(), procInfoNeeded, procInfo, info, new LongByReference());
|
||||
if (error != 0) {
|
||||
Runner.logger.warn("Unable to get the list of processes using " + file.getAbsolutePath());
|
||||
return processes;
|
||||
}
|
||||
for (int i = 0; i < procInfo.getValue(); i++) {
|
||||
processes.add(new Process(infos[i].Process.dwProcessId, new String(infos[i].strAppName).trim()));
|
||||
}
|
||||
Win32RestartManager.INSTANCE.RmEndSession(session.getValue());
|
||||
} catch (Throwable t) {
|
||||
// Best effort approach, if no DLL is found ignore.
|
||||
ourFailed = true;
|
||||
}
|
||||
return processes;
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ public class Patch {
|
||||
private static final int UPDATE_ACTION_KEY = 2;
|
||||
private static final int UPDATE_ZIP_ACTION_KEY = 3;
|
||||
private static final int DELETE_ACTION_KEY = 4;
|
||||
private static final int DELETE_ZIP_ACTION_KEY = 5;
|
||||
|
||||
public Patch(File olderDir,
|
||||
File newerDir,
|
||||
@@ -45,7 +46,12 @@ public class Patch {
|
||||
|
||||
// 'delete' actions before 'create' actions to prevent newly created files to be deleted if the names differ only on case.
|
||||
for (Map.Entry<String, Long> each : diff.filesToDelete.entrySet()) {
|
||||
tempActions.add(new DeleteAction(each.getKey(), each.getValue()));
|
||||
if (!Runner.ZIP_AS_BINARY && Utils.isZipFile(each.getKey())) {
|
||||
tempActions.add(new DeleteZipAction(each.getKey(), each.getValue()));
|
||||
} else
|
||||
{
|
||||
tempActions.add(new DeleteAction(each.getKey(), each.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
for (String each : diff.filesToCreate) {
|
||||
@@ -53,7 +59,7 @@ public class Patch {
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Long> each : diff.filesToUpdate.entrySet()) {
|
||||
if (Utils.isZipFile(each.getKey())) {
|
||||
if (!Runner.ZIP_AS_BINARY && Utils.isZipFile(each.getKey())) {
|
||||
tempActions.add(new UpdateZipAction(each.getKey(), each.getValue()));
|
||||
}
|
||||
else {
|
||||
@@ -98,6 +104,9 @@ public class Patch {
|
||||
else if (clazz == UpdateZipAction.class) {
|
||||
key = UPDATE_ZIP_ACTION_KEY;
|
||||
}
|
||||
else if (clazz == DeleteZipAction.class) {
|
||||
key = DELETE_ZIP_ACTION_KEY;
|
||||
}
|
||||
else if (clazz == DeleteAction.class) {
|
||||
key = DELETE_ACTION_KEY;
|
||||
}
|
||||
@@ -135,6 +144,9 @@ public class Patch {
|
||||
case DELETE_ACTION_KEY:
|
||||
a = new DeleteAction(in);
|
||||
break;
|
||||
case DELETE_ZIP_ACTION_KEY:
|
||||
a = new DeleteZipAction(in);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Unknown action type " + key);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ import java.io.*;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.FileLock;
|
||||
import java.nio.channels.OverlappingFileLockException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
@@ -60,9 +62,15 @@ public abstract class PatchAction {
|
||||
protected abstract void doBuildPatchFile(File olderFile, File newerFile, ZipOutputStream patchOutput) throws IOException;
|
||||
|
||||
public boolean shouldApply(File toDir, Map<String, ValidationResult.Option> options) {
|
||||
File file = getFile(toDir);
|
||||
ValidationResult.Option option = options.get(myPath);
|
||||
if (option == ValidationResult.Option.KEEP || option == ValidationResult.Option.IGNORE) return false;
|
||||
return shouldApplyOn(getFile(toDir));
|
||||
if (option == ValidationResult.Option.KILL_PROCESS) {
|
||||
for (NativeFileManager.Process process : NativeFileManager.getProcessesUsing(file)) {
|
||||
process.terminate();
|
||||
}
|
||||
}
|
||||
return shouldApplyOn(file);
|
||||
}
|
||||
|
||||
protected boolean shouldApplyOn(File toFile) {
|
||||
@@ -78,6 +86,10 @@ public abstract class PatchAction {
|
||||
protected ValidationResult doValidateAccess(File toFile, ValidationResult.Action action) {
|
||||
if (!toFile.exists()) return null;
|
||||
if (toFile.isDirectory()) return null;
|
||||
ValidationResult result = validateProcessLock(toFile, action);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
if (toFile.canRead() && toFile.canWrite() && isWritable(toFile)) return null;
|
||||
return new ValidationResult(ValidationResult.Kind.ERROR,
|
||||
myPath,
|
||||
@@ -111,6 +123,23 @@ public abstract class PatchAction {
|
||||
}
|
||||
}
|
||||
|
||||
private ValidationResult validateProcessLock(File toFile, ValidationResult.Action action) {
|
||||
List<NativeFileManager.Process> processes = NativeFileManager.getProcessesUsing(toFile);
|
||||
if (processes.size() > 0) {
|
||||
Iterator<NativeFileManager.Process> it = processes.iterator();
|
||||
String message = "Locked by: " + it.next().name;
|
||||
while (it.hasNext()) {
|
||||
message += ", " + it.next().name;
|
||||
}
|
||||
return new ValidationResult(ValidationResult.Kind.ERROR,
|
||||
myPath,
|
||||
action,
|
||||
message,
|
||||
ValidationResult.Option.KILL_PROCESS);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected ValidationResult doValidateNotChanged(File toFile, ValidationResult.Kind kind, ValidationResult.Action action)
|
||||
throws IOException {
|
||||
if (toFile.exists()) {
|
||||
@@ -132,9 +161,7 @@ public abstract class PatchAction {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected boolean isModified(File toFile) throws IOException {
|
||||
return myChecksum != Digester.digestFile(toFile);
|
||||
}
|
||||
abstract protected boolean isModified(File toFile) throws IOException;
|
||||
|
||||
public void apply(ZipFile patchFile, File toDir) throws IOException {
|
||||
doApply(patchFile, getFile(toDir));
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* 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 com.intellij.updater;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Exception thrown when an IOException arises when performing a patch
|
||||
* action and it's likely that retrying will be successful.
|
||||
*/
|
||||
public class RetryException extends IOException {
|
||||
public RetryException() {
|
||||
}
|
||||
|
||||
public RetryException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public RetryException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public RetryException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,13 @@ import java.util.zip.ZipInputStream;
|
||||
public class Runner {
|
||||
public static Logger logger = null;
|
||||
|
||||
/**
|
||||
* Treats zip files as regular binary files. When false, zip/jar files are unzipped and diffed file by file.
|
||||
* When true, the entire zip file is diffed as a single file. Set to true if preserving the timestamps of
|
||||
* the files inside the zip is important. This variable can change via a command line option.
|
||||
*/
|
||||
public static boolean ZIP_AS_BINARY = false;
|
||||
|
||||
private static final String PATCH_FILE_NAME = "patch-file.zip";
|
||||
private static final String PATCH_PROPERTIES_ENTRY = "patch.properties";
|
||||
private static final String OLD_BUILD_DESCRIPTION = "old.build.description";
|
||||
@@ -32,28 +39,19 @@ public class Runner {
|
||||
String patchFile = args[5];
|
||||
initLogger();
|
||||
|
||||
ZIP_AS_BINARY = Arrays.asList(args).contains("--zip_as_binary");
|
||||
|
||||
List<String> ignoredFiles = extractFiles(args, "ignored");
|
||||
List<String> criticalFiles = extractFiles(args, "critical");
|
||||
List<String> optionalFiles = extractFiles(args, "optional");
|
||||
create(oldVersionDesc, newVersionDesc, oldFolder, newFolder, patchFile, ignoredFiles, criticalFiles, optionalFiles);
|
||||
}
|
||||
else if (args.length >= 2 && "install".equals(args[0])) {
|
||||
// install [--exit0] <destination_folder>
|
||||
int nextArg = 1;
|
||||
|
||||
// Default install exit code is SwingUpdaterUI.RESULT_REQUIRES_RESTART (42) unless overridden to be 0.
|
||||
// This is used by testUI/build.gradle as gradle expects a javaexec to exit with code 0.
|
||||
boolean useExitCode0 = false;
|
||||
if (args[nextArg].equals("--exit0")) {
|
||||
useExitCode0 = true;
|
||||
nextArg++;
|
||||
}
|
||||
|
||||
String destFolder = args[nextArg++];
|
||||
String destFolder = args[1];
|
||||
initLogger();
|
||||
logger.info("destFolder: " + destFolder);
|
||||
|
||||
install(useExitCode0, destFolder);
|
||||
install(destFolder);
|
||||
}
|
||||
else {
|
||||
printUsage();
|
||||
@@ -104,10 +102,6 @@ public class Runner {
|
||||
}
|
||||
}
|
||||
|
||||
public static void infoStackTrace(String msg, Throwable e){
|
||||
logger.info(msg, e);
|
||||
}
|
||||
|
||||
public static void printStackTrace(Throwable e){
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
@@ -130,8 +124,8 @@ public class Runner {
|
||||
private static void printUsage() {
|
||||
System.err.println("Usage:\n" +
|
||||
"create <old_version_description> <new_version_description> <old_version_folder> <new_version_folder>" +
|
||||
" <patch_file_name> <log_directory> [ignored=file1;file2;...] [critical=file1;file2;...] [optional=file1;file2;...]\n" +
|
||||
"install [--exit0] <destination_folder> [log_directory]\n");
|
||||
" <patch_file_name> [ignored=file1;file2;...] [critical=file1;file2;...] [optional=file1;file2;...]\n" +
|
||||
"install <destination_folder>\n");
|
||||
}
|
||||
|
||||
private static void create(String oldBuildDesc,
|
||||
@@ -142,31 +136,9 @@ public class Runner {
|
||||
List<String> ignoredFiles,
|
||||
List<String> criticalFiles,
|
||||
List<String> optionalFiles) throws IOException, OperationCancelledException {
|
||||
File tempPatchFile = Utils.createTempFile();
|
||||
createImpl(oldBuildDesc,
|
||||
newBuildDesc,
|
||||
oldFolder,
|
||||
newFolder,
|
||||
patchFile,
|
||||
tempPatchFile,
|
||||
ignoredFiles,
|
||||
criticalFiles,
|
||||
optionalFiles,
|
||||
new ConsoleUpdaterUI(), resolveJarFile());
|
||||
}
|
||||
|
||||
static void createImpl(String oldBuildDesc,
|
||||
String newBuildDesc,
|
||||
String oldFolder,
|
||||
String newFolder,
|
||||
String outPatchJar,
|
||||
File tempPatchFile,
|
||||
List<String> ignoredFiles,
|
||||
List<String> criticalFiles,
|
||||
List<String> optionalFiles,
|
||||
UpdaterUI ui,
|
||||
File resolvedJar) throws IOException, OperationCancelledException {
|
||||
UpdaterUI ui = new ConsoleUpdaterUI();
|
||||
try {
|
||||
File tempPatchFile = Utils.createTempFile();
|
||||
PatchFileCreator.create(new File(oldFolder),
|
||||
new File(newFolder),
|
||||
tempPatchFile,
|
||||
@@ -175,13 +147,13 @@ public class Runner {
|
||||
optionalFiles,
|
||||
ui);
|
||||
|
||||
logger.info("Packing JAR file: " + outPatchJar );
|
||||
ui.startProcess("Packing JAR file '" + outPatchJar + "'...");
|
||||
logger.info("Packing JAR file: " + patchFile );
|
||||
ui.startProcess("Packing JAR file '" + patchFile + "'...");
|
||||
|
||||
FileOutputStream fileOut = new FileOutputStream(outPatchJar);
|
||||
FileOutputStream fileOut = new FileOutputStream(patchFile);
|
||||
try {
|
||||
ZipOutputWrapper out = new ZipOutputWrapper(fileOut);
|
||||
ZipInputStream in = new ZipInputStream(new FileInputStream(resolvedJar));
|
||||
ZipInputStream in = new ZipInputStream(new FileInputStream(resolveJarFile()));
|
||||
try {
|
||||
ZipEntry e;
|
||||
while ((e = in.getNextEntry()) != null) {
|
||||
@@ -223,14 +195,16 @@ public class Runner {
|
||||
Utils.cleanup();
|
||||
}
|
||||
|
||||
private static void install(final boolean useExitCode0, final String destFolder) throws Exception {
|
||||
private static void install(final String destFolder) throws Exception {
|
||||
InputStream in = Runner.class.getResourceAsStream("/" + PATCH_PROPERTIES_ENTRY);
|
||||
Properties props = new Properties();
|
||||
try {
|
||||
props.load(in);
|
||||
}
|
||||
finally {
|
||||
in.close();
|
||||
if (in != null) {
|
||||
try {
|
||||
props.load(in);
|
||||
}
|
||||
finally {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
|
||||
// todo[r.sh] to delete in IDEA 14 (after a full circle of platform updates)
|
||||
@@ -250,9 +224,7 @@ public class Runner {
|
||||
|
||||
new SwingUpdaterUI(props.getProperty(OLD_BUILD_DESCRIPTION),
|
||||
props.getProperty(NEW_BUILD_DESCRIPTION),
|
||||
useExitCode0 ? 0 : SwingUpdaterUI.RESULT_REQUIRES_RESTART,
|
||||
new SwingUpdaterUI.InstallOperation() {
|
||||
@Override
|
||||
public boolean execute(UpdaterUI ui) throws OperationCancelledException {
|
||||
logger.info("installing patch to the " + destFolder);
|
||||
return doInstall(ui, destFolder);
|
||||
@@ -260,26 +232,11 @@ public class Runner {
|
||||
});
|
||||
}
|
||||
|
||||
interface IJarResolver {
|
||||
File resolveJar() throws IOException;
|
||||
}
|
||||
|
||||
private static boolean doInstall(UpdaterUI ui, String destFolder) throws OperationCancelledException {
|
||||
return doInstallImpl(ui, destFolder, new IJarResolver() {
|
||||
@Override
|
||||
public File resolveJar() throws IOException {
|
||||
return resolveJarFile();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static boolean doInstallImpl(UpdaterUI ui,
|
||||
String destFolder,
|
||||
IJarResolver jarResolver) throws OperationCancelledException {
|
||||
try {
|
||||
try {
|
||||
File patchFile = Utils.createTempFile();
|
||||
ZipFile jarFile = new ZipFile(jarResolver.resolveJar());
|
||||
ZipFile jarFile = new ZipFile(resolveJarFile());
|
||||
|
||||
logger.info("Extracting patch file...");
|
||||
ui.startProcess("Extracting patch file...");
|
||||
@@ -325,6 +282,10 @@ public class Runner {
|
||||
}
|
||||
|
||||
private static File resolveJarFile() throws IOException {
|
||||
String jar = System.getProperty("JAR_FILE");
|
||||
if (jar != null) {
|
||||
return new File(jar);
|
||||
}
|
||||
URL url = Runner.class.getResource("");
|
||||
if (url == null) throw new IOException("Cannot resolve JAR file path");
|
||||
if (!"jar".equals(url.getProtocol())) throw new IOException("Patch file is not a JAR file");
|
||||
|
||||
@@ -10,7 +10,6 @@ import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
@@ -20,7 +19,7 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class SwingUpdaterUI implements UpdaterUI {
|
||||
static final int RESULT_REQUIRES_RESTART = 42;
|
||||
private static final int RESULT_REQUIRES_RESTART = 42;
|
||||
|
||||
private static final EmptyBorder FRAME_BORDER = new EmptyBorder(8, 8, 8, 8);
|
||||
private static final EmptyBorder LABEL_BORDER = new EmptyBorder(0, 0, 5, 0);
|
||||
@@ -33,7 +32,6 @@ public class SwingUpdaterUI implements UpdaterUI {
|
||||
|
||||
private static final String PROCEED_BUTTON_TITLE = "Proceed";
|
||||
|
||||
private final int mySuccessExitCode;
|
||||
private final InstallOperation myOperation;
|
||||
|
||||
private final JLabel myProcessTitle;
|
||||
@@ -42,30 +40,16 @@ public class SwingUpdaterUI implements UpdaterUI {
|
||||
private final JTextArea myConsole;
|
||||
private final JPanel myConsolePane;
|
||||
|
||||
private final JButton myRetryButton;
|
||||
private final JButton myCancelButton;
|
||||
|
||||
private final ConcurrentLinkedQueue<UpdateRequest> myQueue = new ConcurrentLinkedQueue<UpdateRequest>();
|
||||
private final AtomicBoolean isCancelled = new AtomicBoolean(false);
|
||||
private final AtomicBoolean isRunning = new AtomicBoolean(false);
|
||||
private final AtomicBoolean hasError = new AtomicBoolean(false);
|
||||
private final AtomicBoolean hasRetry = new AtomicBoolean(false);
|
||||
private final JFrame myFrame;
|
||||
private boolean myApplied;
|
||||
|
||||
/**
|
||||
* Displays the updater UI and asynchronously runs the operation list.
|
||||
*
|
||||
* @param oldBuildDesc The old build description, for display purposes.
|
||||
* @param newBuildDesc The new build description, for display purposes.
|
||||
* @param successExitCode The desired exit code on success. Default is {@link #RESULT_REQUIRES_RESTART}.
|
||||
* @param operation The install operations to perform.
|
||||
*/
|
||||
public SwingUpdaterUI(String oldBuildDesc,
|
||||
String newBuildDesc,
|
||||
int successExitCode,
|
||||
InstallOperation operation) {
|
||||
mySuccessExitCode = successExitCode;
|
||||
public SwingUpdaterUI(String oldBuildDesc, String newBuildDesc, InstallOperation operation) {
|
||||
myOperation = operation;
|
||||
|
||||
myProcessTitle = new JLabel(" ");
|
||||
@@ -74,10 +58,6 @@ public class SwingUpdaterUI implements UpdaterUI {
|
||||
|
||||
myCancelButton = new JButton(CANCEL_BUTTON_TITLE);
|
||||
|
||||
myRetryButton = new JButton("Retry");
|
||||
myRetryButton.setEnabled(false);
|
||||
myRetryButton.setVisible(false);
|
||||
|
||||
myConsole = new JTextArea();
|
||||
myConsole.setLineWrap(true);
|
||||
myConsole.setWrapStyleWord(true);
|
||||
@@ -90,19 +70,11 @@ public class SwingUpdaterUI implements UpdaterUI {
|
||||
myConsolePane.setVisible(false);
|
||||
|
||||
myCancelButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
doCancel();
|
||||
}
|
||||
});
|
||||
|
||||
myRetryButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
doRetry();
|
||||
}
|
||||
});
|
||||
|
||||
myFrame = new JFrame();
|
||||
myFrame.setTitle(TITLE);
|
||||
|
||||
@@ -132,7 +104,6 @@ public class SwingUpdaterUI implements UpdaterUI {
|
||||
buttonsPanel.setBorder(BUTTONS_BORDER);
|
||||
buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.X_AXIS));
|
||||
buttonsPanel.add(Box.createHorizontalGlue());
|
||||
buttonsPanel.add(myRetryButton);
|
||||
buttonsPanel.add(myCancelButton);
|
||||
|
||||
myProcessTitle.setText("<html>Updating " + oldBuildDesc + " to " + newBuildDesc + "...");
|
||||
@@ -158,7 +129,6 @@ public class SwingUpdaterUI implements UpdaterUI {
|
||||
|
||||
private void startRequestDispatching() {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
try {
|
||||
@@ -176,7 +146,6 @@ public class SwingUpdaterUI implements UpdaterUI {
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (UpdateRequest each : pendingRequests) {
|
||||
each.perform();
|
||||
@@ -203,28 +172,10 @@ public class SwingUpdaterUI implements UpdaterUI {
|
||||
}
|
||||
}
|
||||
|
||||
private void doRetry() {
|
||||
hasError.set(false);
|
||||
hasRetry.set(false);
|
||||
isCancelled.set(false);
|
||||
myQueue.add(new UpdateRequest() {
|
||||
@Override
|
||||
public void perform() {
|
||||
myConsole.setText("");
|
||||
myConsolePane.setVisible(false);
|
||||
myConsolePane.setPreferredSize(new Dimension(10, 200));
|
||||
myRetryButton.setEnabled(false);
|
||||
myCancelButton.setEnabled(true);
|
||||
}
|
||||
});
|
||||
doPerform();
|
||||
}
|
||||
|
||||
private void doPerform() {
|
||||
isRunning.set(true);
|
||||
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
myApplied = myOperation.execute(SwingUpdaterUI.this);
|
||||
@@ -239,10 +190,6 @@ public class SwingUpdaterUI implements UpdaterUI {
|
||||
finally {
|
||||
isRunning.set(false);
|
||||
|
||||
if (hasRetry.get()) {
|
||||
myRetryButton.setVisible(true);
|
||||
myRetryButton.setEnabled(true);
|
||||
}
|
||||
if (hasError.get()) {
|
||||
startProcess("Failed to apply patch");
|
||||
setProgress(100);
|
||||
@@ -257,17 +204,15 @@ public class SwingUpdaterUI implements UpdaterUI {
|
||||
}
|
||||
|
||||
private void exit() {
|
||||
System.exit(myApplied ? mySuccessExitCode : 0);
|
||||
System.exit(myApplied ? RESULT_REQUIRES_RESTART : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ValidationResult.Option> askUser(final List<ValidationResult> validationResults) throws OperationCancelledException {
|
||||
if (validationResults.isEmpty()) return Collections.emptyMap();
|
||||
|
||||
final Map<String, ValidationResult.Option> result = new HashMap<String, ValidationResult.Option>();
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final JDialog dialog = new JDialog(myFrame, TITLE, true);
|
||||
dialog.setLayout(new BorderLayout());
|
||||
@@ -279,7 +224,6 @@ public class SwingUpdaterUI implements UpdaterUI {
|
||||
buttonsPanel.add(Box.createHorizontalGlue());
|
||||
JButton proceedButton = new JButton(PROCEED_BUTTON_TITLE);
|
||||
proceedButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
dialog.setVisible(false);
|
||||
}
|
||||
@@ -287,7 +231,6 @@ public class SwingUpdaterUI implements UpdaterUI {
|
||||
|
||||
JButton cancelButton = new JButton(CANCEL_BUTTON_TITLE);
|
||||
cancelButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
isCancelled.set(true);
|
||||
myCancelButton.setEnabled(false);
|
||||
@@ -344,10 +287,8 @@ public class SwingUpdaterUI implements UpdaterUI {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startProcess(final String title) {
|
||||
myQueue.add(new UpdateRequest() {
|
||||
@Override
|
||||
public void perform() {
|
||||
myProcessStatus.setText(title);
|
||||
myProcessProgress.setIndeterminate(false);
|
||||
@@ -356,10 +297,8 @@ public class SwingUpdaterUI implements UpdaterUI {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProgress(final int percentage) {
|
||||
myQueue.add(new UpdateRequest() {
|
||||
@Override
|
||||
public void perform() {
|
||||
myProcessProgress.setIndeterminate(false);
|
||||
myProcessProgress.setValue(percentage);
|
||||
@@ -367,43 +306,21 @@ public class SwingUpdaterUI implements UpdaterUI {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProgressIndeterminate() {
|
||||
myQueue.add(new UpdateRequest() {
|
||||
@Override
|
||||
public void perform() {
|
||||
myProcessProgress.setIndeterminate(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStatus(final String status) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showError(final Throwable e) {
|
||||
hasError.set(true);
|
||||
StringWriter w = new StringWriter();
|
||||
|
||||
if (e instanceof RetryException) {
|
||||
hasRetry.set(true);
|
||||
|
||||
w.write("+----------------\n");
|
||||
w.write("| A file operation failed.\n");
|
||||
w.write("| This might be due to a file being locked by another\n");
|
||||
w.write("| application. Please try closing any application\n");
|
||||
w.write("| that uses the files being updated then press 'Retry'.\n");
|
||||
w.write("+----------------\n");
|
||||
w.write("\n\n");
|
||||
}
|
||||
|
||||
e.printStackTrace(new PrintWriter(w));
|
||||
|
||||
final String content = w.getBuffer().toString();
|
||||
|
||||
myQueue.add(new UpdateRequest() {
|
||||
@Override
|
||||
public void perform() {
|
||||
StringWriter w = new StringWriter();
|
||||
if (!myConsolePane.isVisible()) {
|
||||
@@ -411,8 +328,9 @@ public class SwingUpdaterUI implements UpdaterUI {
|
||||
w.write(System.getProperty("java.io.tmpdir"));
|
||||
w.write("\n\n");
|
||||
}
|
||||
e.printStackTrace(new PrintWriter(w));
|
||||
w.append("\n");
|
||||
myConsole.append(w.getBuffer().toString());
|
||||
myConsole.append(content);
|
||||
if (!myConsolePane.isVisible()) {
|
||||
myConsole.setCaretPosition(0);
|
||||
myConsolePane.setVisible(true);
|
||||
@@ -423,7 +341,6 @@ public class SwingUpdaterUI implements UpdaterUI {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkCancelled() throws OperationCancelledException {
|
||||
if (isCancelled.get()) throw new OperationCancelledException();
|
||||
}
|
||||
@@ -437,8 +354,7 @@ public class SwingUpdaterUI implements UpdaterUI {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new SwingUpdaterUI("xxx", "yyy", RESULT_REQUIRES_RESTART, new InstallOperation() {
|
||||
@Override
|
||||
new SwingUpdaterUI("xxx", "yyy", new InstallOperation() {
|
||||
public boolean execute(UpdaterUI ui) throws OperationCancelledException {
|
||||
ui.startProcess("Process1");
|
||||
ui.checkCancelled();
|
||||
@@ -522,7 +438,6 @@ public class SwingUpdaterUI implements UpdaterUI {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return COLUMNS.length;
|
||||
}
|
||||
@@ -549,7 +464,6 @@ public class SwingUpdaterUI implements UpdaterUI {
|
||||
return super.getColumnClass(columnIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
return myItems.size();
|
||||
}
|
||||
@@ -566,7 +480,6 @@ public class SwingUpdaterUI implements UpdaterUI {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||
Item item = myItems.get(rowIndex);
|
||||
switch (columnIndex) {
|
||||
|
||||
@@ -22,6 +22,11 @@ public class UpdateAction extends BaseUpdateAction {
|
||||
patchOutput.closeEntry();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isModified(File toFile) throws IOException {
|
||||
return myChecksum != Digester.digestRegularFile(toFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doApply(ZipFile patchFile, File toFile) throws IOException {
|
||||
InputStream in = Utils.findEntryInputStream(patchFile, myPath);
|
||||
|
||||
@@ -153,6 +153,11 @@ public class UpdateZipAction extends BaseUpdateAction {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isModified(File toFile) throws IOException {
|
||||
return myChecksum != Digester.digestFile(toFile);
|
||||
}
|
||||
|
||||
protected void doApply(final ZipFile patchFile, File toFile) throws IOException {
|
||||
File temp = Utils.createTempFile();
|
||||
FileOutputStream fileOut = new FileOutputStream(temp);
|
||||
|
||||
@@ -10,19 +10,10 @@ public class Utils {
|
||||
private static final byte[] BUFFER = new byte[64 * 1024];
|
||||
private static File myTempDir;
|
||||
|
||||
public static boolean isWindows() {
|
||||
return System.getProperty("os.name").startsWith("Windows");
|
||||
}
|
||||
|
||||
public static boolean isZipFile(String fileName) {
|
||||
return fileName.endsWith(".zip") || fileName.endsWith(".jar");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new temp file. <br/>
|
||||
* All the temp files created here are located in a unique root temp directory
|
||||
* that is automatically deleted by {@link #cleanup()}.
|
||||
*/
|
||||
@SuppressWarnings({"SSBasedInspection"})
|
||||
public static File createTempFile() throws IOException {
|
||||
if (myTempDir == null) {
|
||||
@@ -35,12 +26,6 @@ public class Utils {
|
||||
return File.createTempFile("temp.", ".tmp", myTempDir);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new temp directory. <br/>
|
||||
* All the temp directories created here are located in a unique root temp directory
|
||||
* that is automatically deleted by {@link #cleanup()}.
|
||||
*/
|
||||
public static File createTempDir() throws IOException {
|
||||
File result = createTempFile();
|
||||
delete(result);
|
||||
@@ -57,15 +42,6 @@ public class Utils {
|
||||
myTempDir = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a file or directory with a default timeout of 100 milliseconds.
|
||||
* Directories are deleted recursively. The timeout occurs on each file.
|
||||
* If one of the files fails to be deleted, the recursive directory deletion
|
||||
* is aborted and not retried.
|
||||
*
|
||||
* @param file The file or directory to delete.
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void delete(File file) throws IOException {
|
||||
if (file.isDirectory()) {
|
||||
File[] files = file.listFiles();
|
||||
@@ -76,20 +52,15 @@ public class Utils {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (file.delete() || !file.exists()) {
|
||||
return;
|
||||
}
|
||||
if (file.delete() || !file.exists()) return;
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
} catch (InterruptedException ignore) {
|
||||
Runner.printStackTrace(ignore);
|
||||
}
|
||||
}
|
||||
if (file.exists()) {
|
||||
throw new IOException("Cannot delete file " + file);
|
||||
}
|
||||
if (file.exists()) throw new IOException("Cannot delete file " + file);
|
||||
}
|
||||
|
||||
public static void setExecutable(File file, boolean executable) throws IOException {
|
||||
|
||||
@@ -24,7 +24,7 @@ public class ValidationResult implements Comparable<ValidationResult> {
|
||||
}
|
||||
|
||||
public enum Option {
|
||||
IGNORE, KEEP, REPLACE, DELETE
|
||||
IGNORE, KEEP, REPLACE, DELETE, KILL_PROCESS
|
||||
}
|
||||
|
||||
public static final String ABSENT_MESSAGE = "Absent";
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* 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 com.intellij.updater;
|
||||
|
||||
import com.sun.jna.*;
|
||||
import com.sun.jna.platform.win32.WinBase;
|
||||
import com.sun.jna.platform.win32.WinDef;
|
||||
import com.sun.jna.ptr.IntByReference;
|
||||
import com.sun.jna.ptr.LongByReference;
|
||||
|
||||
public interface Win32RestartManager extends Library {
|
||||
|
||||
Win32RestartManager INSTANCE = (Win32RestartManager) Native.loadLibrary("Rstrtmgr", Win32RestartManager.class);
|
||||
|
||||
int CCH_RM_SESSION_KEY = 32;
|
||||
int CCH_RM_MAX_APP_NAME = 255;
|
||||
int CCH_RM_MAX_SVC_NAME = 63;
|
||||
|
||||
class RmUniqueProcess extends Structure {
|
||||
public int dwProcessId;
|
||||
public WinBase.FILETIME ProcessStartTime;
|
||||
}
|
||||
|
||||
class RmProcessInfo extends Structure {
|
||||
public RmUniqueProcess Process;
|
||||
public char[] strAppName = new char[CCH_RM_MAX_APP_NAME + 1];
|
||||
public char[] strServiceShortName = new char[CCH_RM_MAX_SVC_NAME + 1];
|
||||
public int ApplicationType;
|
||||
public WinDef.LONG AppStatus;
|
||||
public int TSSessionId;
|
||||
public boolean bRestartable;
|
||||
}
|
||||
|
||||
int RmGetList(int dwSessionHandle,
|
||||
IntByReference pnProcInfoNeeded,
|
||||
IntByReference pnProcInfo,
|
||||
RmProcessInfo rgAffectedApps,
|
||||
LongByReference lpdwRebootReasons);
|
||||
|
||||
int RmStartSession(IntByReference pSessionHandle,
|
||||
int dwSessionFlags,
|
||||
char[] strSessionKey);
|
||||
|
||||
int RmRegisterResources(int dwSessionHandle,
|
||||
int nFiles,
|
||||
StringArray rgsFilenames,
|
||||
int nApplications,
|
||||
Pointer rgApplications,
|
||||
int nServices,
|
||||
StringArray rgsServiceNames);
|
||||
|
||||
int RmEndSession(int dwSessionHandle);
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.util.*;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
@@ -94,6 +95,35 @@ public class PatchFileCreatorTest extends PatchTestCase {
|
||||
assertNothingHasChanged(preparationResult, new HashMap<String, ValidationResult.Option>());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRevertedWhenFileToDeleteIsProcessLocked() throws Exception {
|
||||
if (!UtilsTest.mIsWindows) return;
|
||||
|
||||
PatchFileCreator.create(myOlderDir, myNewerDir, myFile, Collections.<String>emptyList(), Collections.<String>emptyList(),
|
||||
Collections.<String>emptyList(), TEST_UI);
|
||||
|
||||
|
||||
RandomAccessFile raf = new RandomAccessFile(new File(myOlderDir, "bin/idea.bat"),"rw");
|
||||
// Lock the file. FileLock is not good here, because we need to prevent deletion.
|
||||
int b = raf.read();
|
||||
raf.seek(0);
|
||||
raf.write(b);
|
||||
|
||||
try {
|
||||
PatchFileCreator.PreparationResult preparationResult = PatchFileCreator.prepareAndValidate(myFile, myOlderDir, TEST_UI);
|
||||
|
||||
Map<String, Long> original = Digester.digestFiles(myOlderDir, Collections.<String>emptyList(), TEST_UI);
|
||||
|
||||
File backup = getTempFile("backup");
|
||||
PatchFileCreator.apply(preparationResult, new HashMap<String, ValidationResult.Option>(), backup, TEST_UI);
|
||||
|
||||
assertEquals(original, Digester.digestFiles(myOlderDir, Collections.<String>emptyList(), TEST_UI));
|
||||
}
|
||||
finally {
|
||||
raf.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApplyingWithAbsentFileToDelete() throws Exception {
|
||||
PatchFileCreator.create(myOlderDir, myNewerDir, myFile, Collections.<String>emptyList(), Collections.<String>emptyList(),
|
||||
@@ -307,6 +337,11 @@ public class PatchFileCreatorTest extends PatchTestCase {
|
||||
super("_dummy_file_", -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isModified(File toFile) throws IOException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBuildPatchFile(File olderFile, File newerFile, ZipOutputStream patchOutput) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
@@ -139,14 +139,16 @@ public class PatchTest extends PatchTestCase {
|
||||
try {
|
||||
FileLock lock = s.getChannel().lock();
|
||||
try {
|
||||
String message = UtilsTest.mIsWindows ? "Locked by: Java(TM) Platform SE binary" : ValidationResult.ACCESS_DENIED_MESSAGE;
|
||||
ValidationResult.Option option = UtilsTest.mIsWindows ? ValidationResult.Option.KILL_PROCESS : ValidationResult.Option.IGNORE;
|
||||
List<ValidationResult> result = myPatch.validate(myOlderDir, TEST_UI);
|
||||
assertEquals(
|
||||
new HashSet<ValidationResult>(Arrays.asList(
|
||||
new ValidationResult(ValidationResult.Kind.ERROR,
|
||||
"Readme.txt",
|
||||
ValidationResult.Action.UPDATE,
|
||||
ValidationResult.ACCESS_DENIED_MESSAGE,
|
||||
ValidationResult.Option.IGNORE))),
|
||||
message,
|
||||
option))),
|
||||
new HashSet<ValidationResult>(result));
|
||||
}
|
||||
finally {
|
||||
|
||||
@@ -23,12 +23,11 @@ import java.io.IOException;
|
||||
|
||||
public class UtilsTest extends TestCase {
|
||||
|
||||
private boolean mIsWindows;
|
||||
public static boolean mIsWindows = System.getProperty("os.name").startsWith("Windows");
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
mIsWindows = Utils.isWindows();
|
||||
}
|
||||
|
||||
public void testDelete() throws Exception {
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
<orderEntry type="library" name="Log4J" level="project" />
|
||||
<orderEntry type="module" module-name="testFramework" scope="TEST" />
|
||||
<orderEntry type="library" scope="TEST" name="JUnit4" level="project" />
|
||||
<orderEntry type="library" name="jna" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user