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:
@@ -62,7 +62,9 @@ import org.jetbrains.jps.server.Server;
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.ToolProvider;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.RunnableFuture;
|
||||
@@ -73,8 +75,10 @@ import java.util.concurrent.TimeUnit;
|
||||
* Date: 9/6/11
|
||||
*/
|
||||
public class CompileServerManager implements ApplicationComponent{
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.JpsServerManager");
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.CompileServerManager");
|
||||
private static final String COMPILE_SERVER_SYSTEM_ROOT = "compile-server";
|
||||
private static final String LOGGER_CONFIG = "log.xml";
|
||||
private static final String DEFAULT_LOGGER_CONFIG = "defaultLogConfig.xml";
|
||||
private volatile OSProcessHandler myProcessHandler;
|
||||
private final File mySystemDirectory;
|
||||
private volatile CompileServerClient myClient = new CompileServerClient();
|
||||
@@ -272,7 +276,7 @@ public class CompileServerManager implements ApplicationComponent{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
final Ref<String> serverStartMessage = new Ref<String>(null);
|
||||
final StringBuilder serverStartMessage = new StringBuilder();
|
||||
final Semaphore semaphore = new Semaphore();
|
||||
semaphore.down();
|
||||
processHandler.addProcessListener(new ProcessAdapter() {
|
||||
@@ -298,8 +302,11 @@ public class CompileServerManager implements ApplicationComponent{
|
||||
if (text != null) {
|
||||
if (text.contains(Server.SERVER_SUCCESS_START_MESSAGE) || text.contains(Server.SERVER_ERROR_START_MESSAGE)) {
|
||||
processHandler.removeProcessListener(this);
|
||||
serverStartMessage.set(text);
|
||||
}
|
||||
if (serverStartMessage.length() > 0) {
|
||||
serverStartMessage.append("\n");
|
||||
}
|
||||
serverStartMessage.append(text);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
@@ -311,8 +318,8 @@ public class CompileServerManager implements ApplicationComponent{
|
||||
processHandler.startNotify();
|
||||
semaphore.waitFor();
|
||||
|
||||
final String startupMsg = serverStartMessage.get();
|
||||
if (startupMsg == null || !startupMsg.contains(Server.SERVER_SUCCESS_START_MESSAGE)) {
|
||||
final String startupMsg = serverStartMessage.toString();
|
||||
if (!startupMsg.contains(Server.SERVER_SUCCESS_START_MESSAGE)) {
|
||||
throw new Exception("Server startup failed: " + startupMsg);
|
||||
}
|
||||
|
||||
@@ -462,14 +469,43 @@ public class CompileServerManager implements ApplicationComponent{
|
||||
|
||||
final File workDirectory = new File(mySystemDirectory, COMPILE_SERVER_SYSTEM_ROOT);
|
||||
workDirectory.mkdirs();
|
||||
ensureLogConfigExists(workDirectory);
|
||||
|
||||
cmdLine.addParameter(FileUtil.toSystemIndependentName(workDirectory.getPath()));
|
||||
|
||||
cmdLine.setWorkDirectory(workDirectory);
|
||||
|
||||
|
||||
return cmdLine.createProcess();
|
||||
}
|
||||
|
||||
private static void ensureLogConfigExists(File workDirectory) {
|
||||
final File logConfig = new File(workDirectory, LOGGER_CONFIG);
|
||||
if (!logConfig.exists()) {
|
||||
FileUtil.createIfDoesntExist(logConfig);
|
||||
try {
|
||||
final InputStream in = Server.class.getResourceAsStream("/" + DEFAULT_LOGGER_CONFIG);
|
||||
if (in != null) {
|
||||
try {
|
||||
final FileOutputStream out = new FileOutputStream(logConfig);
|
||||
try {
|
||||
FileUtil.copy(in, out);
|
||||
}
|
||||
finally {
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdownServer() {
|
||||
shutdownServer(myClient, myProcessHandler);
|
||||
}
|
||||
|
||||
@@ -140,6 +140,7 @@ public class JavaExecutionUtil {
|
||||
|
||||
@Nullable
|
||||
public static PsiClass findMainClass(final Project project, final String mainClassName, final GlobalSearchScope scope) {
|
||||
if (project.isDefault()) return null;
|
||||
final PsiManager psiManager = PsiManager.getInstance(project);
|
||||
final String shortName = StringUtil.getShortName(mainClassName);
|
||||
final String packageName = StringUtil.getPackageName(mainClassName);
|
||||
|
||||
+32
-14
@@ -16,14 +16,16 @@
|
||||
package com.intellij.psi.impl.file;
|
||||
|
||||
import com.intellij.ide.projectView.ProjectView;
|
||||
import com.intellij.ide.projectView.impl.PackageViewPane;
|
||||
import com.intellij.ide.projectView.impl.ProjectRootsUtil;
|
||||
import com.intellij.ide.projectView.impl.nodes.PackageElement;
|
||||
import com.intellij.ide.projectView.impl.ProjectViewPane;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.undo.GlobalUndoableAction;
|
||||
import com.intellij.openapi.command.undo.UndoManager;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.module.ModuleUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.*;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
@@ -31,9 +33,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.openapi.wm.ToolWindowId;
|
||||
import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import com.intellij.psi.NonClasspathClassFinder;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiPackage;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PackagePrefixElementFinder;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
@@ -137,18 +137,36 @@ public class PsiPackageImplementationHelperImpl extends PsiPackageImplementation
|
||||
@Override
|
||||
public void run() {
|
||||
final ProjectView projectView = ProjectView.getInstance(project);
|
||||
projectView.changeView(PackageViewPane.ID);
|
||||
final PsiDirectory[] directories = psiPackage.getDirectories();
|
||||
final VirtualFile firstDir = directories[0].getVirtualFile();
|
||||
final boolean isLibraryRoot = ProjectRootsUtil.isLibraryRoot(firstDir, project);
|
||||
|
||||
final Module module = ProjectRootManager.getInstance(project).getFileIndex().getModuleForFile(firstDir);
|
||||
final PackageElement packageElement = new PackageElement(module, psiPackage, isLibraryRoot);
|
||||
projectView.getProjectViewPaneById(PackageViewPane.ID).select(packageElement, firstDir, requestFocus);
|
||||
PsiDirectory[] directories = suggestMostAppropriateDirectories(psiPackage);
|
||||
if (directories.length == 0) return;
|
||||
projectView.getProjectViewPaneById(ProjectViewPane.ID).select(directories[0], directories[0].getVirtualFile(), requestFocus);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static PsiDirectory[] suggestMostAppropriateDirectories(PsiPackage psiPackage) {
|
||||
final Project project = psiPackage.getProject();
|
||||
PsiDirectory[] directories = null;
|
||||
final Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor();
|
||||
if (editor != null) {
|
||||
final Document document = editor.getDocument();
|
||||
final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document);
|
||||
if (psiFile != null) {
|
||||
final Module module = ModuleUtil.findModuleForPsiElement(psiFile);
|
||||
if (module != null) {
|
||||
directories = psiPackage.getDirectories(GlobalSearchScope.moduleWithDependenciesScope(module));
|
||||
} else {
|
||||
directories = psiPackage.getDirectories(GlobalSearchScope.notScope(GlobalSearchScope.projectScope(project)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (directories == null || directories.length == 0) {
|
||||
directories = psiPackage.getDirectories();
|
||||
}
|
||||
return directories;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean packagePrefixExists(PsiPackage psiPackage) {
|
||||
return PackagePrefixElementFinder.getInstance(psiPackage.getProject()).packagePrefixExists(psiPackage.getQualifiedName());
|
||||
|
||||
@@ -131,11 +131,13 @@ public class ClassFilterEditor extends JPanel implements ComponentWithEmptyText
|
||||
}
|
||||
});
|
||||
|
||||
myAddPatternButton.setEnabled(!myProject.isDefault());
|
||||
myAddPatternButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
addPatternFilter();
|
||||
}
|
||||
});
|
||||
myAddClassButton.setEnabled(!myProject.isDefault());
|
||||
myAddClassButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
addClassFilter();
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
|
||||
|
||||
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
|
||||
<appender name="console" class="org.apache.log4j.ConsoleAppender">
|
||||
<param name="Target" value="System.err"/>
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<param name="ConversionPattern" value="%-5p %c{1} - %m%n"/>
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<root>
|
||||
<priority value ="info" />
|
||||
<appender-ref ref="console" />
|
||||
</root>
|
||||
|
||||
</log4j:configuration>
|
||||
@@ -34,6 +34,7 @@ public class Server {
|
||||
private static final int MAX_SIMULTANEOUS_BUILD_SESSIONS = Math.max(2, Runtime.getRuntime().availableProcessors());
|
||||
public static final String SERVER_SUCCESS_START_MESSAGE = "Compile Server started successfully. Listening on port: ";
|
||||
public static final String SERVER_ERROR_START_MESSAGE = "Error starting Compile Server: ";
|
||||
private static final String LOG_FILE_NAME = "log.xml";
|
||||
|
||||
private final ChannelGroup myAllOpenChannels = new DefaultChannelGroup("compile-server");
|
||||
private final ChannelFactory myChannelFactory;
|
||||
@@ -98,70 +99,14 @@ public class Server {
|
||||
}
|
||||
|
||||
final Server server = new Server(systemDir);
|
||||
|
||||
DOMConfigurator.configure("log.xml");
|
||||
|
||||
Logger.setFactory(new Logger.Factory() {
|
||||
@Override
|
||||
public Logger getLoggerInstance(String category) {
|
||||
final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(category);
|
||||
|
||||
return new Logger(){
|
||||
@Override
|
||||
public boolean isDebugEnabled() {
|
||||
return logger.isDebugEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(@NonNls String message) {
|
||||
logger.debug(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(@Nullable Throwable t) {
|
||||
logger.debug("", t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(@NonNls String message, @Nullable Throwable t) {
|
||||
logger.debug(message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(@NonNls String message, @Nullable Throwable t, @NonNls String... details) {
|
||||
logger.debug(message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(@NonNls String message) {
|
||||
logger.info(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(@NonNls String message, @Nullable Throwable t) {
|
||||
logger.info(message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(@NonNls String message, @Nullable Throwable t) {
|
||||
logger.warn(message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLevel(Level level) {
|
||||
logger.setLevel(level);
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
server.start(port);
|
||||
Runtime.getRuntime().addShutdownHook(new Thread("Shutdown hook thread") {
|
||||
public void run() {
|
||||
server.stop();
|
||||
}
|
||||
});
|
||||
|
||||
initLoggers();
|
||||
server.start(port);
|
||||
ServerState.getInstance().setKeepTempCachesInMemory(System.getProperty(GlobalOptions.USE_MEMORY_TEMP_CACHE_OPTION) != null);
|
||||
|
||||
System.out.println("Server classpath: " + System.getProperty("java.class.path"));
|
||||
@@ -174,6 +119,66 @@ public class Server {
|
||||
}
|
||||
}
|
||||
|
||||
private static void initLoggers() {
|
||||
if (new File(LOG_FILE_NAME).exists()) {
|
||||
DOMConfigurator.configure(LOG_FILE_NAME);
|
||||
}
|
||||
|
||||
Logger.setFactory(new Logger.Factory() {
|
||||
@Override
|
||||
public Logger getLoggerInstance(String category) {
|
||||
final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(category);
|
||||
|
||||
return new Logger() {
|
||||
@Override
|
||||
public boolean isDebugEnabled() {
|
||||
return logger.isDebugEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(@NonNls String message) {
|
||||
logger.debug(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(@Nullable Throwable t) {
|
||||
logger.debug("", t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(@NonNls String message, @Nullable Throwable t) {
|
||||
logger.debug(message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(@NonNls String message, @Nullable Throwable t, @NonNls String... details) {
|
||||
logger.debug(message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(@NonNls String message) {
|
||||
logger.info(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(@NonNls String message, @Nullable Throwable t) {
|
||||
logger.info(message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(@NonNls String message, @Nullable Throwable t) {
|
||||
logger.warn(message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLevel(Level level) {
|
||||
logger.setLevel(level);
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private class ChannelRegistrar extends SimpleChannelUpstreamHandler {
|
||||
public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
|
||||
myAllOpenChannels.add(e.getChannel());
|
||||
|
||||
@@ -112,6 +112,7 @@ public class AutoPopupController implements Disposable {
|
||||
Runnable request = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (myProject.isDefault()) return;
|
||||
CompletionAutoPopupHandler.runLaterWithCommitted(myProject, editor.getDocument(), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.intellij.ide.actions;
|
||||
|
||||
import com.intellij.idea.ActionsBundle;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
@@ -26,8 +25,6 @@ import com.intellij.openapi.fileEditor.TextEditor;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class UndoRedoAction extends DumbAwareAction {
|
||||
public UndoRedoAction() {
|
||||
@@ -56,7 +53,7 @@ public abstract class UndoRedoAction extends DumbAwareAction {
|
||||
}
|
||||
|
||||
UndoManager undoManager = getUndoManager(editor, dataContext);
|
||||
presentation.setEnabled(isAvailable(editor, undoManager));
|
||||
presentation.setEnabled(undoManager != null && isAvailable(editor, undoManager));
|
||||
|
||||
Pair<String, String> pair = getActionNameAndDescription(editor, undoManager);
|
||||
|
||||
|
||||
+7
-1
@@ -50,6 +50,7 @@ import com.intellij.openapi.project.impl.ProjectManagerImpl;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.wm.IdeFrame;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.openapi.wm.ex.ProgressIndicatorEx;
|
||||
@@ -78,6 +79,7 @@ import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@SuppressWarnings({"AssignmentToStaticFieldFromInstanceMethod"})
|
||||
public class ApplicationImpl extends ComponentManagerImpl implements ApplicationEx {
|
||||
@@ -117,6 +119,8 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application
|
||||
private final AtomicBoolean mySaveSettingsIsInProgress = new AtomicBoolean(false);
|
||||
@SuppressWarnings({"UseOfArchaicSystemPropertyAccessors"})
|
||||
private static final int ourDumpThreadsOnLongWriteActionWaiting = Integer.getInteger("dump.threads.on.long.write.action.waiting", 0);
|
||||
private final AtomicInteger myAliveThreads = new AtomicInteger(0);
|
||||
private static final int ourReasonableThreadPoolSize = Registry.intValue("core.pooled.threads");
|
||||
|
||||
private final ExecutorService ourThreadExecutorsService = new ThreadPoolExecutor(
|
||||
3,
|
||||
@@ -127,6 +131,7 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application
|
||||
new ThreadFactory() {
|
||||
int i;
|
||||
public Thread newThread(Runnable r) {
|
||||
final int count = myAliveThreads.incrementAndGet();
|
||||
final Thread thread = new Thread(r, "ApplicationImpl pooled thread "+i++) {
|
||||
public void interrupt() {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
@@ -144,9 +149,10 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application
|
||||
LOG.debug("Worker exits due to exception", t);
|
||||
}
|
||||
}
|
||||
myAliveThreads.decrementAndGet();
|
||||
}
|
||||
};
|
||||
if (ApplicationInfoImpl.getShadowInstance().isEAP() && i > 10) {
|
||||
if (ApplicationInfoImpl.getShadowInstance().isEAP() && count > ourReasonableThreadPoolSize) {
|
||||
LOG.info("Not enough pooled threads; creating one at:", new Throwable());
|
||||
}
|
||||
thread.setPriority(Thread.NORM_PRIORITY - 1);
|
||||
|
||||
@@ -181,6 +181,7 @@ dump.threads.on.empty.lookup.description=Whether IDEA should issue a thread dump
|
||||
|
||||
file.structure.tree.mode=true
|
||||
|
||||
python.new.style.resolve=false
|
||||
disable.toolwindow.overlayed=true
|
||||
disable.toolwindow.overlayed.description=Disable transparent toolwindow stripes
|
||||
disable.toolwindow.overlayed.description=Disable transparent toolwindow stripes
|
||||
|
||||
core.pooled.threads=20
|
||||
|
||||
@@ -128,10 +128,18 @@
|
||||
<projectService
|
||||
serviceInterface="git4idea.DialogManager"
|
||||
serviceImplementation="git4idea.DialogManager"/>
|
||||
<projectService serviceInterface="git4idea.history.wholeTree.GitLogSettings"
|
||||
serviceImplementation="git4idea.history.wholeTree.GitLogSettings"/>
|
||||
<applicationService serviceImplementation="git4idea.history.wholeTree.GitCommitsSequentialIndex"
|
||||
serviceInterface="git4idea.history.wholeTree.GitCommitsSequentially"/>
|
||||
<projectService
|
||||
serviceInterface="git4idea.MessageManager"
|
||||
serviceImplementation="git4idea.MessageManager"/>
|
||||
<projectService
|
||||
serviceInterface="git4idea.NotificationManager"
|
||||
serviceImplementation="git4idea.NotificationManager"/>
|
||||
<projectService
|
||||
serviceInterface="git4idea.history.wholeTree.GitLogSettings"
|
||||
serviceImplementation="git4idea.history.wholeTree.GitLogSettings"/>
|
||||
<applicationService
|
||||
serviceImplementation="git4idea.history.wholeTree.GitCommitsSequentialIndex"
|
||||
serviceInterface="git4idea.history.wholeTree.GitCommitsSequentially"/>
|
||||
<applicationService
|
||||
serviceInterface="git4idea.config.GitVcsApplicationSettings"
|
||||
serviceImplementation="git4idea.config.GitVcsApplicationSettings"/>
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package git4idea;
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class MessageManager {
|
||||
|
||||
public static MessageManager getInstance(@NotNull Project project) {
|
||||
return ServiceManager.getService(project, MessageManager.class);
|
||||
}
|
||||
|
||||
public static int showYesNoDialog(Project project, String description, String title, String yesText, String noText, @Nullable Icon icon) {
|
||||
return getInstance(project).doShowYesNoDialog(project, description, title, yesText, noText, icon);
|
||||
}
|
||||
|
||||
@SuppressWarnings("MethodMayBeStatic")
|
||||
protected int doShowYesNoDialog(Project project, String description, String title, String yesText, String noText, @Nullable Icon icon) {
|
||||
return Messages.showYesNoDialog(project, description, title, yesText, noText, icon);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package git4idea;
|
||||
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationGroup;
|
||||
import com.intellij.notification.NotificationListener;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class NotificationManager {
|
||||
|
||||
@NotNull private final Project myProject;
|
||||
|
||||
public NotificationManager(@NotNull Project project) {
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
public void notify(@NotNull NotificationGroup notificationGroup, @NotNull String title, @NotNull String message,
|
||||
@NotNull NotificationType type, @Nullable NotificationListener listener) {
|
||||
createNotification(notificationGroup, title, message, type, listener).notify(myProject);
|
||||
}
|
||||
|
||||
public static NotificationManager getInstance(@NotNull Project project) {
|
||||
return ServiceManager.getService(project, NotificationManager.class);
|
||||
}
|
||||
|
||||
public void notify(@NotNull NotificationGroup notificationGroup, @NotNull String title, @NotNull String message, @NotNull NotificationType type) {
|
||||
notify(notificationGroup, title, message, type, null);
|
||||
}
|
||||
|
||||
protected static Notification createNotification(NotificationGroup notificationGroup, String title, String message,
|
||||
NotificationType type, NotificationListener listener) {
|
||||
return notificationGroup.createNotification(title, message, type, listener);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import git4idea.DialogManager;
|
||||
import git4idea.GitBranch;
|
||||
import git4idea.history.browser.GitCommit;
|
||||
import git4idea.i18n.GitBundle;
|
||||
@@ -76,7 +77,7 @@ public class GitBranchIsNotFullyMergedDialog extends DialogWrapper {
|
||||
@NotNull List<String> mergedToBranches,
|
||||
@Nullable String currentBranch) {
|
||||
GitBranchIsNotFullyMergedDialog dialog = new GitBranchIsNotFullyMergedDialog(project, commits, branchToDelete, currentBranch, mergedToBranches);
|
||||
dialog.show();
|
||||
DialogManager.getInstance(project).showDialog(dialog);
|
||||
return dialog.isOK();
|
||||
}
|
||||
|
||||
|
||||
@@ -24,10 +24,12 @@ import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import git4idea.GitUtil;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.MessageManager;
|
||||
import git4idea.NotificationManager;
|
||||
import git4idea.merge.GitConflictResolver;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.GitUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
@@ -43,7 +45,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
*/
|
||||
abstract class GitBranchOperation {
|
||||
|
||||
private static final String UNMERGED_FILES_ERROR_TITLE = "Can't checkout because of unmerged files";
|
||||
static final String UNMERGED_FILES_ERROR_TITLE = "Can't checkout because of unmerged files";
|
||||
static final String UNMERGED_FILES_ERROR_NOTIFICATION_DESCRIPTION =
|
||||
"You have to <a href='resolve'>resolve</a> all merge conflicts before checkout.<br/>" +
|
||||
"After resolving conflicts you also probably would want to commit your files to the current branch.";
|
||||
|
||||
@NotNull protected final Project myProject;
|
||||
@NotNull private final Collection<GitRepository> myRepositories;
|
||||
@@ -129,7 +134,7 @@ abstract class GitBranchOperation {
|
||||
}
|
||||
|
||||
protected void notifySuccess() {
|
||||
GitVcs.NOTIFICATION_GROUP_ID.createNotification(getSuccessMessage(), NotificationType.INFORMATION).notify(myProject);
|
||||
NotificationManager.getInstance(myProject).notify(GitVcs.NOTIFICATION_GROUP_ID, "", getSuccessMessage(), NotificationType.INFORMATION);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,7 +156,7 @@ abstract class GitBranchOperation {
|
||||
public void run() {
|
||||
String description = message + getRollbackProposal();
|
||||
ok.set(Messages.OK ==
|
||||
Messages.showYesNoDialog(myProject, description, title, "Rollback", "Don't rollback", Messages.getErrorIcon()));
|
||||
MessageManager.showYesNoDialog(myProject, description, title, "Rollback", "Don't rollback", Messages.getErrorIcon()));
|
||||
}
|
||||
});
|
||||
if (ok.get()) {
|
||||
@@ -164,7 +169,7 @@ abstract class GitBranchOperation {
|
||||
}
|
||||
|
||||
protected void notifyError(@NotNull String title, @NotNull String message) {
|
||||
GitVcs.IMPORTANT_ERROR_NOTIFICATION.createNotification(title, message, NotificationType.ERROR, null).notify(myProject);
|
||||
NotificationManager.getInstance(myProject).notify(GitVcs.IMPORTANT_ERROR_NOTIFICATION, title, message, NotificationType.ERROR);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -192,8 +197,7 @@ abstract class GitBranchOperation {
|
||||
String description = "You have to resolve all merge conflicts before checkout.<br/>" + getRollbackProposal();
|
||||
// suppressing: this message looks ugly if capitalized by words
|
||||
//noinspection DialogTitleCapitalization
|
||||
ok.set(Messages.OK == Messages.showYesNoDialog(myProject, description, UNMERGED_FILES_ERROR_TITLE, "Rollback", "Don't rollback",
|
||||
Messages.getErrorIcon()));
|
||||
ok.set(Messages.OK == MessageManager.showYesNoDialog(myProject, description, UNMERGED_FILES_ERROR_TITLE, "Rollback", "Don't rollback", Messages.getErrorIcon()));
|
||||
}
|
||||
});
|
||||
if (ok.get()) {
|
||||
@@ -203,9 +207,8 @@ abstract class GitBranchOperation {
|
||||
|
||||
private void showUnmergedFilesNotification() {
|
||||
String title = UNMERGED_FILES_ERROR_TITLE;
|
||||
String description = "You have to <a href='resolve'>resolve</a> all merge conflicts before checkout.<br/>" +
|
||||
"After resolving conflicts you also probably would want to commit your files to the current branch.";
|
||||
GitVcs.IMPORTANT_ERROR_NOTIFICATION.createNotification(title, description, NotificationType.ERROR, new NotificationListener() {
|
||||
String description = UNMERGED_FILES_ERROR_NOTIFICATION_DESCRIPTION;
|
||||
NotificationManager.getInstance(myProject).notify(GitVcs.IMPORTANT_ERROR_NOTIFICATION, title, description, NotificationType.ERROR, new NotificationListener() {
|
||||
@Override public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
|
||||
if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED && event.getDescription().equals("resolve")) {
|
||||
GitConflictResolver.Params params = new GitConflictResolver.Params().
|
||||
@@ -214,7 +217,7 @@ abstract class GitBranchOperation {
|
||||
new GitConflictResolver(myProject, GitUtil.getRoots(getRepositories()), params).merge();
|
||||
}
|
||||
}
|
||||
}).notify(myProject);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,14 +23,12 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import git4idea.GitExecutionException;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.commands.Git;
|
||||
import git4idea.history.GitHistoryUtils;
|
||||
import git4idea.history.browser.GitCommit;
|
||||
import git4idea.merge.GitConflictResolver;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.ui.branch.GitBranchUiUtil;
|
||||
import git4idea.ui.branch.GitCompareBranchesDialog;
|
||||
@@ -125,15 +123,6 @@ public final class GitBranchOperationsProcessor {
|
||||
new GitCheckoutNewBranchOperation(myProject, myRepositories, name, getCurrentBranch(), indicator).execute();
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
static GitConflictResolver prepareConflictResolverForUnmergedFilesBeforeCheckout(Project project, Collection<VirtualFile> roots) {
|
||||
GitConflictResolver.Params params = new GitConflictResolver.Params().
|
||||
setMergeDescription("The following files have unresolved conflicts. You need to resolve them before checking out.").
|
||||
setErrorNotificationTitle("Can't create new branch");
|
||||
return new GitConflictResolver(project, roots, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and checks out a new local branch starting from the given reference:
|
||||
* {@code git checkout -b <branchname> <start-point>}. <br/>
|
||||
|
||||
@@ -38,6 +38,7 @@ import com.intellij.util.continuation.ContinuationContext;
|
||||
import com.intellij.util.text.DateFormatUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.vcsUtil.VcsUtil;
|
||||
import git4idea.DialogManager;
|
||||
import git4idea.GitUtil;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.commands.*;
|
||||
@@ -206,7 +207,7 @@ public class GitCheckoutOperation extends GitBranchOperation {
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
dialog.show();
|
||||
DialogManager.getInstance(myProject).showDialog(dialog);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -274,7 +275,7 @@ public class GitCheckoutOperation extends GitBranchOperation {
|
||||
catch (VcsException e) {
|
||||
// ignoring the exception: this is not fatal if we won't collect such a diff from other repositories.
|
||||
// At worst, use will get double dialog proposing the smart checkout.
|
||||
LOG.warn(String.format("Couldn't collect diff between %s and %s in %s", myPreviousBranch, myStartPointReference, repository.getRoot()));
|
||||
LOG.warn(String.format("Couldn't collect diff between %s and %s in %s", myPreviousBranch, myStartPointReference, repository.getRoot()), e);
|
||||
}
|
||||
}
|
||||
return changes;
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.openapi.vcs.changes.ui.ChangesBrowser;
|
||||
import com.intellij.ui.IdeBorderFactory;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import git4idea.DialogManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -49,7 +50,7 @@ class GitWouldBeOverwrittenByCheckoutDialog extends DialogWrapper {
|
||||
@Override
|
||||
public void run() {
|
||||
GitWouldBeOverwrittenByCheckoutDialog dialog = new GitWouldBeOverwrittenByCheckoutDialog(project, changes);
|
||||
dialog.show();
|
||||
DialogManager.getInstance(project).showDialog(dialog);
|
||||
ok.set(dialog.isOK());
|
||||
}
|
||||
});
|
||||
|
||||
@@ -493,7 +493,7 @@ executable.error.title = Git executable problem
|
||||
executable.error.description = Git couldn't be started. Probably the path to Git executable is not valid. <a href="">Fix it.</a>
|
||||
|
||||
git.commit.message.empty=Please specify commit message
|
||||
git.commit.message.empty.title=Commit message is empty
|
||||
git.commit.message.empty.title=Commit Message Is Empty
|
||||
|
||||
git.executable.notification.title=Can't start Git
|
||||
git.executable.notification.description=Probably the path to Git executable is not valid. <a href=''>Fix it.</a>
|
||||
|
||||
@@ -201,7 +201,7 @@ public final class GitRepository implements Disposable {
|
||||
* Returns the full-functional instance of GitRepository - with UntrackedFilesHolder and GitRepositoryUpdater.
|
||||
* This is used for repositories registered in project, and should be optained via {@link GitRepositoryManager}.
|
||||
*/
|
||||
static GitRepository getFullInstance(@NotNull VirtualFile root, @NotNull Project project, @NotNull Disposable parentDisposable) {
|
||||
public static GitRepository getFullInstance(@NotNull VirtualFile root, @NotNull Project project, @NotNull Disposable parentDisposable) {
|
||||
GitRepository repository = new GitRepository(root, project, parentDisposable);
|
||||
repository.myUntrackedFilesHolder.setupVfsListener(project);
|
||||
repository.setupUpdater();
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.changes.ui.SelectFilesDialog;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.NotificationManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -48,7 +49,7 @@ public class UntrackedFilesNotifier {
|
||||
final String notificationDesc = createUntrackedFilesOverwrittenDescription(operation, false);
|
||||
final String dialogDesc = createUntrackedFilesOverwrittenDescription(operation, true);
|
||||
|
||||
GitVcs.IMPORTANT_ERROR_NOTIFICATION.createNotification(notificationTitle, notificationDesc, NotificationType.ERROR, new NotificationListener() {
|
||||
NotificationManager.getInstance(project).notify(GitVcs.IMPORTANT_ERROR_NOTIFICATION, notificationTitle, notificationDesc, NotificationType.ERROR, new NotificationListener() {
|
||||
@Override public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
|
||||
SelectFilesDialog dlg = new SelectFilesDialog(project, new ArrayList<VirtualFile>(untrackedFiles), dialogDesc, null, false, false) {
|
||||
@Override protected Action[] createActions() {
|
||||
@@ -58,8 +59,7 @@ public class UntrackedFilesNotifier {
|
||||
dlg.setTitle("Untracked Files Preventing " + StringUtil.capitalize(operation));
|
||||
dlg.show();
|
||||
}
|
||||
}).notify(project);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public static String createUntrackedFilesOverwrittenDescription(@NotNull final String operation, boolean filesAreShown) {
|
||||
|
||||
@@ -0,0 +1,549 @@
|
||||
package git4idea.branch;
|
||||
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.openapi.progress.EmptyProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
||||
import com.intellij.openapi.vcs.VcsConfiguration;
|
||||
import com.intellij.openapi.vcs.VcsShowConfirmationOption;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.testFramework.AbstractVcsTestCase;
|
||||
import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
|
||||
import com.intellij.testFramework.fixtures.TempDirTestFixture;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.vcsUtil.VcsUtil;
|
||||
import git4idea.GitBranch;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.test.GitTestScenarioGenerator;
|
||||
import git4idea.test.GitTestUtil;
|
||||
import git4idea.test.TestMessageManager;
|
||||
import git4idea.test.TestNotificationManager;
|
||||
import git4idea.tests.TestDialogHandler;
|
||||
import git4idea.tests.TestDialogManager;
|
||||
import git4idea.util.UntrackedFilesNotifier;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.testng.annotations.AfterMethod;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static git4idea.test.GitExec.*;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class GitBranchOperationsTest extends AbstractVcsTestCase {
|
||||
|
||||
private static final String NEW_BRANCH = "new_branch";
|
||||
private static final String MASTER = "master";
|
||||
|
||||
private Collection<GitRepository> myRepositories;
|
||||
private GitRepository myUltimate;
|
||||
private GitRepository myCommunity;
|
||||
private GitRepository myContrib;
|
||||
|
||||
private TestMessageManager myMessageManager;
|
||||
private TestNotificationManager myNotificationManager;
|
||||
private TestDialogManager myDialogManager;
|
||||
|
||||
private TempDirTestFixture myTempDirFixture;
|
||||
|
||||
@BeforeMethod
|
||||
public void setup() throws Exception {
|
||||
final IdeaTestFixtureFactory fixtureFactory = IdeaTestFixtureFactory.getFixtureFactory();
|
||||
myTempDirFixture = fixtureFactory.createTempDirTestFixture();
|
||||
myTempDirFixture.setUp();
|
||||
|
||||
final File projectDir = new File(myTempDirFixture.getTempDirPath(), "ultimate");
|
||||
assertTrue(projectDir.mkdir());
|
||||
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
initProject(projectDir);
|
||||
initRepositories(VcsUtil.getVirtualFile(projectDir));
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException("Exception initializing the test", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
GitVcs vcs = GitVcs.getInstance(myProject);
|
||||
assertNotNull(vcs);
|
||||
myTraceClient = true;
|
||||
doActionSilently(VcsConfiguration.StandardConfirmation.ADD);
|
||||
doActionSilently(VcsConfiguration.StandardConfirmation.REMOVE);
|
||||
|
||||
myDialogManager = GitTestUtil.registerDialogManager(myProject);
|
||||
myNotificationManager = GitTestUtil.registerNotificationManager(myProject);
|
||||
myMessageManager = GitTestUtil.registerMessageManager(myProject);
|
||||
|
||||
createAddCommit(myUltimate, "a");
|
||||
createAddCommit(myCommunity, "a");
|
||||
createAddCommit(myContrib, "a");
|
||||
|
||||
myUltimate.getRoot().refresh(false, true);
|
||||
}
|
||||
|
||||
protected void doActionSilently(final VcsConfiguration.StandardConfirmation op) {
|
||||
setStandardConfirmation(GitVcs.NAME, op, VcsShowConfirmationOption.Value.DO_ACTION_SILENTLY);
|
||||
}
|
||||
|
||||
@AfterMethod
|
||||
public void tearDown() throws Exception {
|
||||
if (myTempDirFixture != null) {
|
||||
myTempDirFixture.tearDown();
|
||||
myTempDirFixture = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void initRepositories(VirtualFile projectDir) throws IOException {
|
||||
myUltimate = init(myProject, projectDir);
|
||||
VirtualFile communityDir = createDirInCommand(projectDir, "community");
|
||||
VirtualFile contribDir = createDirInCommand(projectDir, "contrib");
|
||||
myCommunity = init(myProject, communityDir);
|
||||
myContrib = init(myProject, contribDir);
|
||||
|
||||
addProjectRoots();
|
||||
myRepositories = Arrays.asList(myUltimate, myCommunity, myContrib);
|
||||
}
|
||||
|
||||
private void addProjectRoots() {
|
||||
ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject);
|
||||
vcsManager.setDirectoryMapping(myUltimate.getRoot().getPath(), GitVcs.NAME);
|
||||
vcsManager.setDirectoryMapping(myCommunity.getRoot().getPath(), GitVcs.NAME);
|
||||
vcsManager.setDirectoryMapping(myContrib.getRoot().getPath(), GitVcs.NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void create_new_branch_without_problems() throws Exception {
|
||||
doCheckoutNewBranch();
|
||||
assertNotify(NotificationType.INFORMATION, "Branch new_branch was created");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void create_new_branch_with_unmerged_files_in_first_repo_should_show_notification() throws Exception {
|
||||
GitTestScenarioGenerator.prepareUnmergedFiles(myUltimate);
|
||||
doCheckoutNewBranch();
|
||||
assertNotify(NotificationType.ERROR, GitBranchOperation.UNMERGED_FILES_ERROR_NOTIFICATION_DESCRIPTION);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void create_new_branch_with_unmerged_files_in_second_repo_should_propose_to_rollback() throws Exception {
|
||||
GitTestScenarioGenerator.prepareUnmergedFiles(myCommunity, myContrib);
|
||||
doCheckoutNewBranch();
|
||||
assertMessage(GitBranchOperation.UNMERGED_FILES_ERROR_TITLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rollback_create_new_branch_should_delete_branch() throws Exception {
|
||||
GitTestScenarioGenerator.prepareUnmergedFiles(myCommunity, myContrib);
|
||||
myMessageManager.nextAnswer(Messages.OK);
|
||||
doCheckoutNewBranch();
|
||||
assertMessage(GitBranchOperation.UNMERGED_FILES_ERROR_TITLE);
|
||||
assertBranch("master");
|
||||
assertTrue(!branch(myUltimate).contains(NEW_BRANCH));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deny_rollback_create_new_branch() throws Exception {
|
||||
GitTestScenarioGenerator.prepareUnmergedFiles(myCommunity, myContrib);
|
||||
myMessageManager.nextAnswer(Messages.CANCEL);
|
||||
doCheckoutNewBranch();
|
||||
assertMessage(GitBranchOperation.UNMERGED_FILES_ERROR_TITLE);
|
||||
|
||||
assertBranch(myUltimate, NEW_BRANCH);
|
||||
assertBranch(myCommunity, MASTER);
|
||||
assertBranch(myContrib, MASTER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkout_without_problems() throws Exception {
|
||||
prepareBranchForSimpleCheckout();
|
||||
doCheckout("feature", null);
|
||||
assertNotify(NotificationType.INFORMATION, "Checked out feature");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkout_with_unmerged_files_in_first_repo_should_show_notification() throws Exception {
|
||||
prepareBranchForSimpleCheckout();
|
||||
GitTestScenarioGenerator.prepareUnmergedFiles(myUltimate);
|
||||
doCheckout("feature", null);
|
||||
assertNotify(NotificationType.ERROR, GitBranchOperation.UNMERGED_FILES_ERROR_NOTIFICATION_DESCRIPTION);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkout_with_unmerged_file_in_second_repo_should_propose_to_rollback() throws Exception {
|
||||
prepareBranchForSimpleCheckout();
|
||||
GitTestScenarioGenerator.prepareUnmergedFiles(myCommunity);
|
||||
doCheckout("feature", null);
|
||||
assertMessage(GitBranchOperation.UNMERGED_FILES_ERROR_TITLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rollback_checkout_should_return_to_previous_branch() throws Exception {
|
||||
prepareBranchForSimpleCheckout();
|
||||
GitTestScenarioGenerator.prepareUnmergedFiles(myCommunity);
|
||||
myMessageManager.nextAnswer(Messages.OK);
|
||||
doCheckout("feature", null);
|
||||
assertMessage(GitBranchOperation.UNMERGED_FILES_ERROR_TITLE);
|
||||
assertBranch("master");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deny_rollback_checkout_should_do_nothing() throws Exception {
|
||||
prepareBranchForSimpleCheckout();
|
||||
GitTestScenarioGenerator.prepareUnmergedFiles(myCommunity);
|
||||
myMessageManager.nextAnswer(Messages.CANCEL);
|
||||
doCheckout("feature", null);
|
||||
assertMessage(GitBranchOperation.UNMERGED_FILES_ERROR_TITLE);
|
||||
assertBranch(myUltimate, "feature");
|
||||
assertBranch(myCommunity, "master");
|
||||
assertBranch(myContrib, "master");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkout_with_untracked_files_overwritten_by_checkout_in_first_repo_should_show_notification() throws Exception {
|
||||
prepareUntrackedFilesAndBranchWithSameTrackedFiles(myUltimate);
|
||||
branch(myCommunity, "feature");
|
||||
branch(myContrib, "feature");
|
||||
|
||||
doCheckout("feature", null);
|
||||
assertNotify(NotificationType.ERROR, UntrackedFilesNotifier.createUntrackedFilesOverwrittenDescription("checkout", false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkout_with_untracked_files_overwritten_by_checkout_in_second_repo_should_show_rollback_proposal_with_file_list() throws Exception {
|
||||
prepareUntrackedFilesAndBranchWithSameTrackedFiles(myCommunity);
|
||||
branch(myUltimate, "feature");
|
||||
branch(myContrib, "feature");
|
||||
|
||||
Class gitCheckoutOperationClass = Class.forName("git4idea.branch.GitCheckoutOperation");
|
||||
Class[] classes = gitCheckoutOperationClass.getDeclaredClasses();
|
||||
Class untrackedFilesDialogClass = null;
|
||||
for (Class aClass : classes) {
|
||||
if (aClass.getName().endsWith("UntrackedFilesDialog")) {
|
||||
untrackedFilesDialogClass = aClass;
|
||||
}
|
||||
}
|
||||
assertNotNull(untrackedFilesDialogClass);
|
||||
|
||||
final AtomicBoolean dialogShown = new AtomicBoolean();
|
||||
final Class finalUntrackedFilesDialogClass = untrackedFilesDialogClass;
|
||||
myDialogManager.registerDialogHandler(untrackedFilesDialogClass, new TestDialogHandler() {
|
||||
@Override
|
||||
public int handleDialog(Object dialog) {
|
||||
if (dialog.getClass().equals(finalUntrackedFilesDialogClass)) {
|
||||
dialogShown.set(true);
|
||||
}
|
||||
return DialogWrapper.CANCEL_EXIT_CODE;
|
||||
}
|
||||
});
|
||||
|
||||
doCheckout("feature", null);
|
||||
assertTrue(dialogShown.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkout_with_local_changes_overwritten_by_checkout_should_show_smart_checkout_dialog() throws Exception {
|
||||
prepareLocalChangesAndBranchWithSameModifiedFilesWithoutConflicts(myUltimate);
|
||||
branch(myCommunity, "feature");
|
||||
branch(myContrib, "feature");
|
||||
|
||||
final AtomicBoolean dialogShown = new AtomicBoolean();
|
||||
myDialogManager.registerDialogHandler(GitWouldBeOverwrittenByCheckoutDialog.class, new TestDialogHandler<GitWouldBeOverwrittenByCheckoutDialog>() {
|
||||
@Override
|
||||
public int handleDialog(GitWouldBeOverwrittenByCheckoutDialog dialog) {
|
||||
dialogShown.set(true);
|
||||
return DialogWrapper.CANCEL_EXIT_CODE;
|
||||
}
|
||||
});
|
||||
|
||||
doCheckout("feature", null);
|
||||
assertTrue(dialogShown.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void agree_to_smart_checkout_should_smart_checkout() throws Exception {
|
||||
prepareLocalChangesAndBranchWithSameModifiedFilesWithoutConflicts(myUltimate);
|
||||
prepareLocalChangesAndBranchWithSameModifiedFilesWithoutConflicts(myCommunity);
|
||||
prepareLocalChangesAndBranchWithSameModifiedFilesWithoutConflicts(myContrib);
|
||||
myDialogManager.registerDialogHandler(GitWouldBeOverwrittenByCheckoutDialog.class,
|
||||
new TestDialogHandler<GitWouldBeOverwrittenByCheckoutDialog>() {
|
||||
@Override
|
||||
public int handleDialog(GitWouldBeOverwrittenByCheckoutDialog dialog) {
|
||||
return DialogWrapper.OK_EXIT_CODE;
|
||||
}
|
||||
});
|
||||
|
||||
doCheckout("feature", null);
|
||||
assertBranch("feature");
|
||||
for (GitRepository repository : myRepositories) {
|
||||
refresh(repository);
|
||||
assertBranch(repository, "feature");
|
||||
assertEquals(read(repository, "local.txt"), "master\ninitial content\nfeature content\n");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deny_to_smart_checkout_in_first_repo_should_show_notification() throws Exception {
|
||||
prepareLocalChangesAndBranchWithSameModifiedFilesWithoutConflicts(myUltimate);
|
||||
branch(myCommunity, "feature");
|
||||
branch(myContrib, "feature");
|
||||
|
||||
myDialogManager.registerDialogHandler(GitWouldBeOverwrittenByCheckoutDialog.class, new TestDialogHandler<GitWouldBeOverwrittenByCheckoutDialog>() {
|
||||
@Override
|
||||
public int handleDialog(GitWouldBeOverwrittenByCheckoutDialog dialog) {
|
||||
return DialogWrapper.CANCEL_EXIT_CODE;
|
||||
}
|
||||
});
|
||||
|
||||
doCheckout("feature", null);
|
||||
assertNotify(NotificationType.ERROR, "Couldn't checkout feature", stripHtmlAndBreaks("Local changes would be overwritten by checkout." +
|
||||
"Stash or commit them before checking out a branch."));
|
||||
assertBranch("master");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deny_to_smart_checkout_in_second_repo_should_show_rollback_proposal() throws Exception {
|
||||
prepareLocalChangesAndBranchWithSameModifiedFilesWithoutConflicts(myCommunity);
|
||||
branch(myUltimate, "feature");
|
||||
branch(myContrib, "feature");
|
||||
myDialogManager.registerDialogHandler(GitWouldBeOverwrittenByCheckoutDialog.class, new TestDialogHandler<GitWouldBeOverwrittenByCheckoutDialog>() {
|
||||
@Override
|
||||
public int handleDialog(GitWouldBeOverwrittenByCheckoutDialog dialog) {
|
||||
return DialogWrapper.CANCEL_EXIT_CODE;
|
||||
}
|
||||
});
|
||||
|
||||
doCheckout("feature", null);
|
||||
assertMessage("Couldn't checkout feature",
|
||||
"Local changes would be overwritten by checkout.<br/>Stash or commit them before checking out a branch.<br/>" +
|
||||
"However checkout has succeeded for the following repositories:<br/>" +
|
||||
myUltimate.getPresentableUrl() +
|
||||
"<br/>You may rollback (checkout back to master) not to let branches diverge.",
|
||||
"Rollback", "Don't rollback");
|
||||
}
|
||||
|
||||
private static void prepareLocalChangesAndBranchWithSameModifiedFilesWithoutConflicts(GitRepository repository) throws IOException {
|
||||
create(repository, "local.txt", "initial content\n");
|
||||
addCommit(repository);
|
||||
checkout(repository, "-b", "feature");
|
||||
edit(repository, "local.txt", "initial content\nfeature content\n");
|
||||
addCommit(repository);
|
||||
checkout(repository, "master");
|
||||
edit(repository, "local.txt", "master\ninitial content\n");
|
||||
}
|
||||
|
||||
private static void prepareUntrackedFilesAndBranchWithSameTrackedFiles(GitRepository repository) throws IOException {
|
||||
checkout(repository, "-b", "feature");
|
||||
createAddCommit(repository, "untracked.txt");
|
||||
checkout(repository, "master");
|
||||
create(repository, "untracked.txt");
|
||||
}
|
||||
|
||||
private void prepareBranchForSimpleCheckout() throws IOException {
|
||||
for (GitRepository repository : myRepositories) {
|
||||
checkout(repository, "-b", "feature");
|
||||
createAddCommit(repository, "feature_file.txt");
|
||||
checkout(repository, "master");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void delete_branch_without_problems() throws Exception {
|
||||
for (GitRepository repository : myRepositories) {
|
||||
branch(repository, "master1");
|
||||
refresh(repository);
|
||||
}
|
||||
doDeleteBranch("master1");
|
||||
assertNotify(NotificationType.INFORMATION, "Deleted branch master1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void delete_unmerged_branch_should_show_dialog() throws Exception {
|
||||
prepareUnmergedBranch(myUltimate, myCommunity, myContrib);
|
||||
|
||||
final AtomicBoolean dialogShown = new AtomicBoolean();
|
||||
myDialogManager.registerDialogHandler(GitBranchIsNotFullyMergedDialog.class, new TestDialogHandler<GitBranchIsNotFullyMergedDialog>() {
|
||||
@Override public int handleDialog(GitBranchIsNotFullyMergedDialog dialog) {
|
||||
dialogShown.set(true);
|
||||
return DialogWrapper.CANCEL_EXIT_CODE;
|
||||
}
|
||||
});
|
||||
|
||||
doDeleteBranch("unmerged_branch");
|
||||
assertTrue(dialogShown.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ok_in_unmerged_branch_dialog_should_force_delete_branch() throws Exception {
|
||||
prepareUnmergedBranch(myUltimate, myCommunity, myContrib);
|
||||
registerNotFullyMergedDialog(DialogWrapper.OK_EXIT_CODE);
|
||||
doDeleteBranch("unmerged_branch");
|
||||
for (GitRepository repository : myRepositories) {
|
||||
assertTrue(!branch(repository).contains("unmerged_branch"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cancel_in_unmerged_branch_dialog_in_first_repository_should_show_notification() throws Exception {
|
||||
prepareUnmergedBranch(myUltimate, myContrib);
|
||||
branch(myCommunity, "unmerged_branch");
|
||||
|
||||
registerNotFullyMergedDialog(DialogWrapper.CANCEL_EXIT_CODE);
|
||||
doDeleteBranch("unmerged_branch");
|
||||
assertNotify(NotificationType.ERROR, "Branch unmerged_branch wasn't deleted", "This branch is not fully merged to master");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cancel_in_unmerged_branch_dialog_in_not_first_repository_should_show_rollback_proposal() throws Exception {
|
||||
branch(myUltimate, "unmerged_branch");
|
||||
prepareUnmergedBranch(myCommunity, myContrib);
|
||||
|
||||
registerNotFullyMergedDialog(DialogWrapper.CANCEL_EXIT_CODE);
|
||||
doDeleteBranch("unmerged_branch");
|
||||
assertMessage(String.format("Branch %s wasn't deleted", "unmerged_branch"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rollback_delete_branch_should_recreate_branches() throws Exception {
|
||||
branch(myUltimate, "unmerged_branch");
|
||||
prepareUnmergedBranch(myCommunity);
|
||||
branch(myContrib, "unmerged_branch");
|
||||
|
||||
registerNotFullyMergedDialog(DialogWrapper.CANCEL_EXIT_CODE);
|
||||
myMessageManager.nextAnswer(Messages.OK);
|
||||
doDeleteBranch("unmerged_branch");
|
||||
|
||||
for (GitRepository repository : myRepositories) {
|
||||
assertTrue(branch(repository).contains("unmerged_branch"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deny_rollback_delete_branch_should_do_nothing() throws Exception {
|
||||
branch(myUltimate, "unmerged_branch");
|
||||
prepareUnmergedBranch(myCommunity);
|
||||
branch(myContrib, "unmerged_branch");
|
||||
|
||||
registerNotFullyMergedDialog(DialogWrapper.CANCEL_EXIT_CODE);
|
||||
myMessageManager.nextAnswer(Messages.CANCEL);
|
||||
doDeleteBranch("unmerged_branch");
|
||||
|
||||
assertTrue(branch(myCommunity).contains("unmerged_branch"));
|
||||
assertTrue(branch(myContrib).contains("unmerged_branch"));
|
||||
assertTrue(!branch(myUltimate).contains("unmerged_branch"));
|
||||
}
|
||||
|
||||
private void registerNotFullyMergedDialog(final int answer) {
|
||||
myDialogManager.registerDialogHandler(GitBranchIsNotFullyMergedDialog.class, new TestDialogHandler<GitBranchIsNotFullyMergedDialog>() {
|
||||
@Override
|
||||
public int handleDialog(GitBranchIsNotFullyMergedDialog dialog) {
|
||||
return answer;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void prepareUnmergedBranch(GitRepository... repositories) throws IOException {
|
||||
for (GitRepository repository : repositories) {
|
||||
checkout(repository, "-b", "unmerged_branch");
|
||||
createAddCommit(repository, "unmerged_branch_file");
|
||||
checkout(repository, "master");
|
||||
refresh(repository);
|
||||
}
|
||||
}
|
||||
|
||||
private void doCheckoutNewBranch() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
||||
callPrivateBranchOperationsProcessorMethod("doCheckoutNewBranch", NEW_BRANCH);
|
||||
}
|
||||
|
||||
private void callPrivateBranchOperationsProcessorMethod(String methodName, String branchName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
|
||||
// call private doCheckoutNewBranch instead of public checkoutNewBranch to avoid dealing with background process creation
|
||||
// same for other branch operations
|
||||
GitBranchOperationsProcessor processor = new GitBranchOperationsProcessor(myProject, myRepositories, myCommunity);
|
||||
Method method = GitBranchOperationsProcessor.class.getDeclaredMethod(methodName, String.class, ProgressIndicator.class);
|
||||
method.setAccessible(true);
|
||||
method.invoke(processor, branchName, new EmptyProgressIndicator());
|
||||
}
|
||||
|
||||
private void doDeleteBranch(@NotNull String branchName) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
||||
callPrivateBranchOperationsProcessorMethod("doDelete", branchName);
|
||||
}
|
||||
|
||||
private void doCheckout(@NotNull String branchName, @Nullable String newBranch) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
|
||||
GitBranchOperationsProcessor processor = new GitBranchOperationsProcessor(myProject, myRepositories, myCommunity);
|
||||
Method doCheckout = GitBranchOperationsProcessor.class.getDeclaredMethod("doCheckout", ProgressIndicator.class, String.class, String.class);
|
||||
doCheckout.setAccessible(true);
|
||||
doCheckout.invoke(processor, new EmptyProgressIndicator(), branchName, newBranch);
|
||||
}
|
||||
|
||||
private void assertBranch(String branch) {
|
||||
for (GitRepository repository : myRepositories) {
|
||||
assertBranch(repository, branch);
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertBranch(GitRepository repository, String branchName) {
|
||||
GitBranch currentBranch = repository.getCurrentBranch();
|
||||
assertNotNull(currentBranch);
|
||||
assertEquals(currentBranch.getName(), branchName);
|
||||
}
|
||||
|
||||
private void assertNotify(NotificationType type, String content) {
|
||||
assertNotify(type, null, content);
|
||||
}
|
||||
|
||||
private void assertNotify(NotificationType type, @Nullable String title, String content) {
|
||||
Notification notification = myNotificationManager.getLastNotification();
|
||||
assertNotNull(notification);
|
||||
assertEquals(stripHtmlAndBreaks(notification.getContent()), stripHtmlAndBreaks(content));
|
||||
assertEquals(notification.getType(), type);
|
||||
if (title != null) {
|
||||
assertEquals(stripHtmlAndBreaks(notification.getTitle()), stripHtmlAndBreaks(title));
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String stripHtmlAndBreaks(@NotNull String text) {
|
||||
return StringUtil.stripHtml(text, true).replace("\n", "");
|
||||
}
|
||||
|
||||
private void assertMessage(String title) {
|
||||
assertMessage(title, null, null, null);
|
||||
}
|
||||
|
||||
private void assertMessage(@Nullable String title, @Nullable String description, @Nullable String yesButton, @Nullable String noButton) {
|
||||
TestMessageManager.Message message = myMessageManager.getLastMessage();
|
||||
assertNotNull(message);
|
||||
if (title != null) {
|
||||
assertEquals(message.getTitle(), title);
|
||||
}
|
||||
if (description != null) {
|
||||
assertEquals(message.getDescription(), description);
|
||||
}
|
||||
if (yesButton != null) {
|
||||
assertEquals(message.getYesText(), yesButton);
|
||||
}
|
||||
if (noButton != null) {
|
||||
assertEquals(message.getNoText(), noButton);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package git4idea.test;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.testFramework.AbstractVcsTestCase;
|
||||
import com.intellij.testFramework.VfsTestUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import git4idea.repo.GitRepository;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class GitExec {
|
||||
|
||||
public static void refresh(@NotNull GitRepository repository) {
|
||||
repository.getRoot().refresh(false, true);
|
||||
}
|
||||
|
||||
public static GitRepository init(@NotNull Project project, @NotNull VirtualFile root) throws IOException {
|
||||
new GitTestRunEnv(new File(root.getPath())).run("init");
|
||||
root.refresh(false, true);
|
||||
return GitRepository.getFullInstance(root, project, project);
|
||||
}
|
||||
|
||||
public static void create(@NotNull GitRepository repository, @NotNull String filePath) {
|
||||
create(repository, filePath, "content");
|
||||
}
|
||||
|
||||
public static void create(final GitRepository repository, final String filePath, @NotNull final String content) {
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
@Override public void run() {
|
||||
VfsTestUtil.createFile(repository.getRoot(), filePath, content);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void edit(final GitRepository repository, String filePath, final String newContent) {
|
||||
final VirtualFile file = repository.getRoot().findFileByRelativePath(filePath);
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
@Override public void run() {
|
||||
AbstractVcsTestCase.editFileInCommand(repository.getProject(), file, newContent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String read(final @NotNull GitRepository repository, @NotNull String filePath) throws IOException {
|
||||
final VirtualFile file = repository.getRoot().findFileByRelativePath(filePath);
|
||||
assert file != null;
|
||||
return new String(file.contentsToByteArray());
|
||||
}
|
||||
|
||||
public static void add(@NotNull GitRepository repository, @NotNull String filePath) throws IOException {
|
||||
run(repository, "add", filePath);
|
||||
}
|
||||
|
||||
public static void add(@NotNull GitRepository repository) throws IOException {
|
||||
run(repository, "add", ".");
|
||||
}
|
||||
|
||||
public static void commit(@NotNull GitRepository repository) throws IOException {
|
||||
run(repository, "commit", "-m", "message");
|
||||
}
|
||||
|
||||
public static void addCommit(@NotNull GitRepository repository, @NotNull String filePath) throws IOException {
|
||||
add(repository, filePath);
|
||||
commit(repository);
|
||||
}
|
||||
|
||||
public static void addCommit(@NotNull GitRepository repository) throws IOException {
|
||||
add(repository);
|
||||
commit(repository);
|
||||
}
|
||||
|
||||
public static void createAddCommit(@NotNull GitRepository repository, @NotNull String filePath) throws IOException {
|
||||
create(repository, filePath);
|
||||
addCommit(repository, filePath);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String branch(@NotNull GitRepository repository, String... params) throws IOException {
|
||||
return run(repository, "branch", params);
|
||||
}
|
||||
|
||||
public static void checkout(@NotNull GitRepository repository, String... params) throws IOException {
|
||||
run(repository, "checkout", params);
|
||||
}
|
||||
|
||||
public static void merge(@NotNull GitRepository repository, @NotNull String branch) throws IOException {
|
||||
run(repository, "merge", branch);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String run(@NotNull GitRepository repository, @NotNull String command, String... params) throws IOException {
|
||||
return new GitTestRunEnv(new File(repository.getRoot().getPath())).run(command, params);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package git4idea.test;
|
||||
|
||||
import git4idea.repo.GitRepository;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static git4idea.test.GitExec.*;
|
||||
|
||||
/**
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class GitTestScenarioGenerator {
|
||||
|
||||
public static void prepareUnmergedFiles(@NotNull GitRepository... repositories) throws IOException {
|
||||
for (GitRepository repository : repositories) {
|
||||
String unmergedFile = "unmerged";
|
||||
create(repository, unmergedFile, "master content");
|
||||
addCommit(repository, unmergedFile);
|
||||
|
||||
checkoutFeatureBranch(repository);
|
||||
edit(repository, unmergedFile, "feature content");
|
||||
addCommit(repository, unmergedFile);
|
||||
|
||||
checkout(repository, "master");
|
||||
edit(repository, unmergedFile, "master feature");
|
||||
addCommit(repository, unmergedFile);
|
||||
|
||||
merge(repository, "feature");
|
||||
refresh(repository);
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkoutFeatureBranch(GitRepository repository) throws IOException {
|
||||
String branches = branch(repository);
|
||||
if (!branches.contains("feature")) {
|
||||
checkout(repository, "-b", "feature");
|
||||
} else {
|
||||
checkout(repository, "feature");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,9 +22,14 @@ import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import git4idea.DialogManager;
|
||||
import git4idea.MessageManager;
|
||||
import git4idea.NotificationManager;
|
||||
import git4idea.tests.GitTestRepository;
|
||||
import git4idea.tests.TestDialogManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.picocontainer.MutablePicoContainer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
@@ -227,4 +232,33 @@ public class GitTestUtil {
|
||||
public static String stringifyActualExpected(@NotNull Object actual, @NotNull Object expected) {
|
||||
return "\nExpected:\n" + expected + "\nActual:\n" + actual;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers {@link git4idea.tests.TestDialogManager} as the {@link git4idea.DialogManager} implementation.
|
||||
* @param project
|
||||
*/
|
||||
public static TestDialogManager registerDialogManager(@NotNull Project project) {
|
||||
final String key = "git4idea.DialogManager";
|
||||
final MutablePicoContainer picoContainer = (MutablePicoContainer) project.getPicoContainer();
|
||||
picoContainer.unregisterComponent(key);
|
||||
picoContainer.registerComponentImplementation(key, TestDialogManager.class);
|
||||
return (TestDialogManager)DialogManager.getInstance(project);
|
||||
}
|
||||
|
||||
public static TestMessageManager registerMessageManager(@NotNull Project project) {
|
||||
final String key = "git4idea.MessageManager";
|
||||
final MutablePicoContainer picoContainer = (MutablePicoContainer) project.getPicoContainer();
|
||||
picoContainer.unregisterComponent(key);
|
||||
picoContainer.registerComponentImplementation(key, TestMessageManager.class);
|
||||
return (TestMessageManager)MessageManager.getInstance(project);
|
||||
}
|
||||
|
||||
public static TestNotificationManager registerNotificationManager(Project project) {
|
||||
final String key = "git4idea.NotificationManager";
|
||||
final MutablePicoContainer picoContainer = (MutablePicoContainer) project.getPicoContainer();
|
||||
picoContainer.unregisterComponent(key);
|
||||
picoContainer.registerComponentImplementation(key, TestNotificationManager.class);
|
||||
return (TestNotificationManager)NotificationManager.getInstance(project);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package git4idea.test;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import git4idea.MessageManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class TestMessageManager extends MessageManager {
|
||||
|
||||
private Message myLastMessage;
|
||||
private int myNextAnswer = DEFAULT_ANSWER;
|
||||
private static final int DEFAULT_ANSWER = Messages.CANCEL;
|
||||
|
||||
public static class Message {
|
||||
@NotNull private final String myTitle;
|
||||
@NotNull private final String myDescription;
|
||||
@NotNull private final String myYesText;
|
||||
@NotNull private final String myNoText;
|
||||
|
||||
public Message(@NotNull String title, @NotNull String description, @NotNull String yesText, @NotNull String noText) {
|
||||
myTitle = title;
|
||||
myDescription = description;
|
||||
myYesText = yesText;
|
||||
myNoText = noText;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getTitle() {
|
||||
return myTitle;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getDescription() {
|
||||
return myDescription;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getYesText() {
|
||||
return myYesText;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getNoText() {
|
||||
return myNoText;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Message getLastMessage() {
|
||||
return myLastMessage;
|
||||
}
|
||||
|
||||
public void nextAnswer(int answer) {
|
||||
myNextAnswer = answer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int doShowYesNoDialog(Project project, String description, String title, String yesText, String noText, @Nullable Icon icon) {
|
||||
myLastMessage = new Message(title, description, yesText, noText);
|
||||
return myNextAnswer;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package git4idea.test;
|
||||
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationGroup;
|
||||
import com.intellij.notification.NotificationListener;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import git4idea.NotificationManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class TestNotificationManager extends NotificationManager {
|
||||
|
||||
private Notification myLastNotification;
|
||||
|
||||
public TestNotificationManager(@NotNull Project project) {
|
||||
super(project);
|
||||
}
|
||||
|
||||
public Notification getLastNotification() {
|
||||
return myLastNotification;
|
||||
}
|
||||
|
||||
public void notify(@NotNull NotificationGroup notificationGroup, @NotNull String title, @NotNull String message, @NotNull NotificationType type) {
|
||||
notify(notificationGroup, title, message, type, null);
|
||||
}
|
||||
|
||||
public void notify(@NotNull NotificationGroup notificationGroup, @NotNull String title, @NotNull String message,
|
||||
@NotNull NotificationType type, @Nullable NotificationListener listener) {
|
||||
myLastNotification = createNotification(notificationGroup, title, message, type, listener);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,11 +23,10 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.CheckboxTreeBase;
|
||||
import com.intellij.ui.CheckedTreeNode;
|
||||
import com.intellij.ui.GuiUtils;
|
||||
import git4idea.DialogManager;
|
||||
import git4idea.config.GitVcsSettings;
|
||||
import git4idea.test.GitTestUtil;
|
||||
import git4idea.ui.GitConvertFilesDialog;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.picocontainer.MutablePicoContainer;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@@ -63,7 +62,7 @@ public class GitLineSeparatorsConverterTest extends GitTest {
|
||||
myChangeListManager = ChangeListManagerImpl.getInstanceImpl(myProject);
|
||||
mySettings = GitVcsSettings.getInstance(myProject);
|
||||
myCodeStyleSeparator = CodeStyleFacade.getInstance(myProject).getLineSeparator();
|
||||
myDialogManager = registerDialogManager();
|
||||
myDialogManager = GitTestUtil.registerDialogManager(myProject);
|
||||
|
||||
unixFile = createFileInCommand("unix_file.txt", "Unix File\n");
|
||||
winFile = createFileInCommand("win_file.txt", "Windows File\r\n");
|
||||
@@ -193,17 +192,6 @@ public class GitLineSeparatorsConverterTest extends GitTest {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers {@link TestDialogManager} as the {@link DialogManager} implementation.
|
||||
*/
|
||||
private TestDialogManager registerDialogManager() {
|
||||
final String key = "git4idea.DialogManager";
|
||||
final MutablePicoContainer picoContainer = (MutablePicoContainer) myProject.getPicoContainer();
|
||||
picoContainer.unregisterComponent(key);
|
||||
picoContainer.registerComponentImplementation(key, TestDialogManager.class);
|
||||
return (TestDialogManager)DialogManager.getInstance(myProject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Commits via the ChangeListManager.
|
||||
*/
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<suite name="Git Suite">
|
||||
<test name="Git Test">
|
||||
<packages>
|
||||
<package name="git4idea.branch"/>
|
||||
<package name="git4idea.history"/>
|
||||
<package name="git4idea.repo"/>
|
||||
<package name="git4idea.validators"/>
|
||||
|
||||
+1
@@ -210,6 +210,7 @@ public class TestNGConfigurationEditor extends SettingsEditor<TestNGConfiguratio
|
||||
}
|
||||
model.setType(TestType.CLASS);
|
||||
addListener.addActionListener(new AddTestListenerListener());
|
||||
addListener.setEnabled(!project.isDefault());
|
||||
removeListener.addActionListener(new ActionListener()
|
||||
{
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
|
||||
@@ -101,11 +101,11 @@
|
||||
</component>
|
||||
<component id="b9ad7" class="javax.swing.JCheckBox" binding="myResizeHeaders">
|
||||
<constraints>
|
||||
<grid row="5" 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="5" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<margin top="10" left="0" bottom="2" right="2"/>
|
||||
<text value="Resize column and row headers over mouse"/>
|
||||
<text value="&Resize column and row headers with mouse"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
|
||||
@@ -546,7 +546,7 @@ action.GuiDesigner.ReloadCustomComponents.text=Reload Custom Components
|
||||
action.GuiDesigner.ReloadCustomComponents.description=Reload modified custom component classes and recreate forms
|
||||
action.NewDialog.text=Dialog
|
||||
action.NewForm.text=GUI Form
|
||||
default.field.accessibility=Default accessibility for UI-bound fields:
|
||||
default.field.accessibility=Default accessibility &for UI-bound fields\:
|
||||
plugin.com.intellij.uiDesigner.description=Provides visual editing support for Swing UI forms
|
||||
group.GuiDesigner.MainToolbarActions.text=UI Designer Toolbar Actions
|
||||
group.GuiDesigner.NewActions.text=New GUI Designer Actions
|
||||
|
||||
Reference in New Issue
Block a user