diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/status/ui/HgStatusWidget.java b/plugins/hg4idea/src/org/zmlx/hg4idea/status/ui/HgStatusWidget.java
index 11a7a09f5d68..a5724010ba1e 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/status/ui/HgStatusWidget.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/status/ui/HgStatusWidget.java
@@ -146,7 +146,7 @@ public class HgStatusWidget extends EditorBasedWidget implements StatusBarWidget
int maxLength = MAX_STRING.length();
myText = StringUtil.shortenTextWithEllipsis(myText, maxLength, 5);
- if (!isDisposed()) {
+ if (!isDisposed() && myStatusBar != null) {
myStatusBar.updateWidget(ID());
}
}
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/HgPlatformTest.java b/plugins/hg4idea/testSrc/hg4idea/test/HgPlatformTest.java
index 502e8fd7b6cc..e7bd4cdedac5 100644
--- a/plugins/hg4idea/testSrc/hg4idea/test/HgPlatformTest.java
+++ b/plugins/hg4idea/testSrc/hg4idea/test/HgPlatformTest.java
@@ -37,11 +37,11 @@ import static hg4idea.test.HgExecutor.hg;
* The base class for tests of hg4idea plugin.
* Extend this test to write a test on Mercurial which has the following features/limitations:
*
- * - This is a "platform test case", which means that IDEA [almost] production platform is set up before the test starts.
- * - Project base directory is the root of everything. It can contain as much nested repositories as needed,
- * but if you need to test the case when hg repository is above the project dir, you need either to adjust this base class,
- * or create another one.
- * - Initially one repository is created with the project dir as its root. I. e. all project is under Mercurial.
+ * - This is a "platform test case", which means that IDEA [almost] production platform is set up before the test starts.
+ * - Project base directory is the root of everything. It can contain as much nested repositories as needed,
+ * but if you need to test the case when hg repository is above the project dir, you need either to adjust this base class,
+ * or create another one.
+ * - Initially one repository is created with the project dir as its root. I. e. all project is under Mercurial.
*
*
* @author Kirill Likhodedov
@@ -51,11 +51,15 @@ public abstract class HgPlatformTest extends UsefulTestCase {
protected Project myProject;
protected VirtualFile myProjectRoot;
protected VirtualFile myRepository;
+ protected VirtualFile myChildRepo;
protected MergeProvider myMergeProvider;
+ protected static final String COMMIT_MESSAGE = "text";
+
private IdeaProjectTestFixture myProjectFixture;
protected static final String AFILE = "A.txt";
+ protected static final String BFILE = "B.txt";
@SuppressWarnings("JUnitTestCaseWithNonTrivialConstructors")
protected HgPlatformTest() {
@@ -82,6 +86,8 @@ public abstract class HgPlatformTest extends UsefulTestCase {
assertNotNull(vcs);
myMergeProvider = vcs.getMergeProvider();
assertNotNull(myMergeProvider);
+
+ prepareSecondRepository();
}
@Override
@@ -117,4 +123,15 @@ public abstract class HgPlatformTest extends UsefulTestCase {
hg("add file.txt");
hg("commit -m initial");
}
+
+ private void prepareSecondRepository() throws IOException {
+ cd(myRepository);
+ hg("clone " + myRepository.getCanonicalPath() + " childRepo");
+ myChildRepo = myRepository.findChild("childRepo");
+ cd(myChildRepo);
+ hg("pull");
+ hg("update");
+ HgTestUtil.updateDirectoryMappings(myProject, myRepository);
+ HgTestUtil.updateDirectoryMappings(myProject, myChildRepo);
+ }
}
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/HgTestUtil.java b/plugins/hg4idea/testSrc/hg4idea/test/HgTestUtil.java
new file mode 100644
index 000000000000..d3644d139b1c
--- /dev/null
+++ b/plugins/hg4idea/testSrc/hg4idea/test/HgTestUtil.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2000-2013 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 hg4idea.test;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vcs.ProjectLevelVcsManager;
+import com.intellij.openapi.vcs.VcsDirectoryMapping;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.zmlx.hg4idea.HgVcs;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Nadya Zabrodina
+ */
+public class HgTestUtil {
+
+ public static void updateDirectoryMappings(Project project, VirtualFile mapRoot) {
+ if (project != null && (!project.isDefault()) && project.getBaseDir() != null && VfsUtil
+ .isAncestor(project.getBaseDir(), mapRoot, false)) {
+ mapRoot.refresh(false, false);
+ final String path = mapRoot.equals(project.getBaseDir()) ? "" : mapRoot.getPath();
+ final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(project);
+ final List vcsDirectoryMappings = new ArrayList(vcsManager.getDirectoryMappings());
+ VcsDirectoryMapping mapping = new VcsDirectoryMapping(path, HgVcs.VCS_NAME);
+ for (int i = 0; i < vcsDirectoryMappings.size(); i++) {
+ final VcsDirectoryMapping m = vcsDirectoryMappings.get(i);
+ if (m.getDirectory().equals(path)) {
+ if (m.getVcs().length() == 0) {
+ vcsDirectoryMappings.set(i, mapping);
+ mapping = null;
+ break;
+ }
+ else if (m.getVcs().equals(mapping.getVcs())) {
+ mapping = null;
+ break;
+ }
+ }
+ }
+ if (mapping != null) {
+ vcsDirectoryMappings.add(mapping);
+ }
+ vcsManager.setDirectoryMappings(vcsDirectoryMappings);
+ vcsManager.updateActiveVcss();
+ }
+ }
+
+ private HgTestUtil() {
+ }
+
+ /**
+ * Writes the given content to the file.
+ *
+ * @param file file which content will be substituted by the given one.
+ * @param content new file content
+ */
+ public static void printToFile(VirtualFile file, String content) throws FileNotFoundException {
+ PrintStream centralPrinter = null;
+ try {
+ centralPrinter = new PrintStream(new FileOutputStream(new File(file.getPath())));
+ centralPrinter.print(content);
+ centralPrinter.close();
+ }
+ finally {
+ if (centralPrinter != null) {
+ centralPrinter.close();
+ }
+ }
+ }
+}
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/merge/HgMergeProviderTest.java b/plugins/hg4idea/testSrc/hg4idea/test/merge/HgMergeProviderTest.java
index 74197b4a919d..c084259bac2c 100644
--- a/plugins/hg4idea/testSrc/hg4idea/test/merge/HgMergeProviderTest.java
+++ b/plugins/hg4idea/testSrc/hg4idea/test/merge/HgMergeProviderTest.java
@@ -15,12 +15,16 @@
*/
package hg4idea.test.merge;
+import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.merge.MergeData;
import com.intellij.openapi.vfs.VirtualFile;
import hg4idea.test.HgPlatformTest;
+import hg4idea.test.HgTestUtil;
import org.testng.Assert;
+import java.io.IOException;
+
import static com.intellij.dvcs.test.Executor.*;
import static hg4idea.test.HgExecutor.hg;
@@ -66,6 +70,128 @@ public class HgMergeProviderTest extends HgPlatformTest {
verifyMergeData(myRepository.findChild(FILENAME), "base", "base modify with b", "base modify with a");
}
+ /**
+ * Start with a file in both repositories.
+ * 1. Edit the file in parent repository, commit the change.
+ * 2. Edit the file in child repository, commit the change.
+ * 3. Update.
+ * 4. Test the MergeData from the MergeProvider to have correct data.
+ */
+ public void testMergeWithCommittedLocalChange() throws Exception {
+ final Pair files = prepareFileInBothRepositories();
+ final VirtualFile parentFile = files.first;
+ final VirtualFile childFile = files.second;
+ cd(myRepository);
+ HgTestUtil.printToFile(parentFile, "server");
+ hg("commit -m " + COMMIT_MESSAGE);
+ // committing conflicting change
+ cd(myChildRepo);
+ HgTestUtil.printToFile(childFile, "local");
+ hg("commit -m " + COMMIT_MESSAGE);
+ hg("pull");
+ hg("update");
+ hg("merge");
+ verifyMergeData(myChildRepo.findChild(childFile.getName()), "basic", "local", "server");
+ }
+
+ /**
+ * Start with a file in both repositories.
+ * 1. Edit the file in parent repository, commit the change.
+ * 2. Edit the file in child repository, don't commit the change.
+ * 3. Update.
+ * 4. Test the MergeData from the MergeProvider to have correct data.
+ */
+ public void testMergeWithUncommittedLocalChange() throws Exception {
+ final Pair files = prepareFileInBothRepositories();
+ final VirtualFile parentFile = files.first;
+ final VirtualFile childFile = files.second;
+ cd(myRepository);
+ HgTestUtil.printToFile(parentFile, "server");
+ hg("commit -m " + COMMIT_MESSAGE);
+
+ // uncommitted conflicting change
+ cd(myChildRepo);
+ HgTestUtil.printToFile(childFile, "local");
+ hg("pull");
+ hg("update");
+ hg("merge");
+
+ verifyMergeData(myChildRepo.findChild(childFile.getName()), "basic", "local", "server");
+ }
+
+ /**
+ * Start with a non fresh repository.
+ * 1. Add a file in parent repository, commit.
+ * 2. Add a file with the same name, but different content in child repository, commit.
+ * 3. Update.
+ * 4. Test the MergeData from the MergeProvider to have correct data (there is no basic version, but it shouldn't be null - just empty).
+ */
+ public void testFileAddedAndCommitted() throws Exception {
+ // this is needed to have the same root changeset - otherwise conflicting root changeset will cause
+ // an error during 'hg pull': "abort: repository is unrelated"
+ prepareFileInBothRepositories();
+ cd(myRepository);
+ touch(BFILE, "server");
+ hg("add " + BFILE);
+ hg("commit -m " + COMMIT_MESSAGE);
+
+ cd(myChildRepo);
+ touch(BFILE, "local");
+ hg("add " + BFILE);
+ hg("commit -m " + COMMIT_MESSAGE);
+
+ hg("pull");
+ hg("update");
+ hg("merge");
+
+ verifyMergeData(myChildRepo.findChild(BFILE), "", "local", "server");
+ }
+
+ /**
+ * Start with a non fresh repository.
+ * 1. Add a file in parent repository, commit.
+ * 2. Add a file with the same name, but different content in child repository, don't commit.
+ * 3. Update.
+ * 4. Test the MergeData from the MergeProvider to have correct data (there is no basic version, but it shouldn't be null - just empty).
+ */
+ public void testFileAddedNotCommited() throws Exception {
+ // this is needed to have the same root changeset - otherwise conflicting root changeset will cause
+ // an error during 'hg pull': "abort: repository is unrelated"
+ prepareFileInBothRepositories();
+ cd(myRepository);
+ touch(BFILE, "server");
+ hg("add " + BFILE);
+ hg("commit -m " + COMMIT_MESSAGE);
+
+ cd(myChildRepo);
+ touch(BFILE, "local");
+ hg("add " + BFILE);
+
+ hg("pull");
+ hg("update");
+ hg("merge");
+
+ verifyMergeData(myChildRepo.findChild(BFILE), "", "local", "server");
+ }
+
+
+ /**
+ * Creates a file with initial content in the parent repository, pulls & updates it to the child repository.
+ *
+ * @return References to the files in parent and child repositories respectively.
+ */
+ private Pair prepareFileInBothRepositories() throws IOException {
+ cd(myRepository);
+ touch(AFILE, "basic");
+ hg("add " + AFILE);
+ hg("commit -m 'create file' ");
+ cd(myChildRepo);
+ hg("pull");
+ hg("update");
+ final VirtualFile childFile = myChildRepo.findChild(AFILE);
+ return Pair.create(myRepository.findChild(AFILE), childFile);
+ }
+
private void verifyMergeData(final VirtualFile file, String expectedBase, String expectedLocal, String expectedServer)
throws VcsException {
final MergeData mergeData = myMergeProvider.loadRevisions(file);
diff --git a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgMergeProviderTest.java b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgMergeProviderTest.java
deleted file mode 100644
index ca486678b082..000000000000
--- a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgMergeProviderTest.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright 2000-2010 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 org.zmlx.hg4idea.test;
-
-import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.vcs.VcsException;
-import com.intellij.openapi.vcs.merge.MergeData;
-import com.intellij.openapi.vcs.merge.MergeProvider;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.ui.UIUtil;
-import org.testng.Assert;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-import org.zmlx.hg4idea.HgVcs;
-
-import java.io.IOException;
-import java.lang.reflect.Method;
-import java.util.concurrent.atomic.AtomicReference;
-
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.fail;
-
-/**
- * Tests HgMergeProvider for different merge situations.
- * All Mercurial operations are performed natively to test only HgMergeProvider functionality.
- * @author Kirill Likhodedov
- */
-public class HgMergeProviderTest extends HgCollaborativeTest {
-
- private MergeProvider myMergeProvider;
-
- @BeforeMethod
- @Override
- protected void setUp(Method testMethod) throws Exception {
- super.setUp(testMethod);
- myMergeProvider = HgVcs.getInstance(myProject).getMergeProvider();
- assertNotNull(myMergeProvider);
- }
-
- /**
- * Start with a file in both repositories.
- * 1. Edit the file in parent repository, commit the change.
- * 2. Edit the file in child repository, commit the change.
- * 3. Update.
- * 4. Test the MergeData from the MergeProvider to have correct data.
- */
- @Test
- public void mergeWithCommittedLocalChange() throws Exception {
- final Pair files = prepareFileInBothRepositories();
- final VirtualFile parentFile = files.first;
- final VirtualFile childFile = files.second;
-
- HgTestUtil.printToFile(parentFile, "server");
- myParentRepo.commit();
- // committing conflicting change
- HgTestUtil.printToFile(childFile, "local");
- myRepo.commit();
-
- myRepo.pullUpdateMerge();
-
- verifyMergeData(childFile, "basic", "local", "server");
- }
-
- /**
- * Start with a file in both repositories.
- * 1. Edit the file in parent repository, commit the change.
- * 2. Edit the file in child repository, don't commit the change.
- * 3. Update.
- * 4. Test the MergeData from the MergeProvider to have correct data.
- */
- @Test
- public void mergeWithUncommittedLocalChange() throws Exception {
- final Pair files = prepareFileInBothRepositories();
- final VirtualFile parentFile = files.first;
- final VirtualFile childFile = files.second;
-
- HgTestUtil.printToFile(parentFile, "server");
- myParentRepo.commit();
-
- // uncommitted conflicting change
- HgTestUtil.printToFile(childFile, "local");
-
- myRepo.pullUpdateMerge();
-
- verifyMergeData(childFile, "basic", "local", "server");
- }
-
- /**
- * Start with a non fresh repository.
- * 1. Add a file in parent repository, commit.
- * 2. Add a file with the same name, but different content in child repository, commit.
- * 3. Update.
- * 4. Test the MergeData from the MergeProvider to have correct data (there is no basic version, but it shouldn't be null - just empty).
- */
- @Test
- public void fileAddedAndCommitted() throws Exception {
- // this is needed to have the same root changeset - otherwise conflicting root changeset will cause
- // an error during 'hg pull': "abort: repository is unrelated"
- prepareFileInBothRepositories();
-
- myParentRepo.createFile("b.txt", "server");
- myParentRepo.addCommit();
-
- final VirtualFile childFile = myRepo.createFile("b.txt", "local");
- myRepo.addCommit();
-
- myRepo.pullUpdateMerge();
-
- verifyMergeData(childFile, "", "local", "server");
- }
-
- /**
- * Start with a non fresh repository.
- * 1. Add a file in parent repository, commit.
- * 2. Add a file with the same name, but different content in child repository, don't commit.
- * 3. Update.
- * 4. Test the MergeData from the MergeProvider to have correct data (there is no basic version, but it shouldn't be null - just empty).
- */
- @Test
- public void fileAddedNotCommited() throws Exception {
- // this is needed to have the same root changeset - otherwise conflicting root changeset will cause
- // an error during 'hg pull': "abort: repository is unrelated"
- prepareFileInBothRepositories();
-
- myParentRepo.createFile("b.txt", "server");
- myParentRepo.addCommit();
-
- final VirtualFile childFile = myRepo.createFile("b.txt", "local");
- myRepo.add();
-
- myRepo.pullUpdateMerge();
-
- verifyMergeData(childFile, "", "local", "server");
- }
-
- private void verifyMergeData(final VirtualFile file, String expectedBase, String expectedLocal, String expectedServer) throws Exception {
- final AtomicReference mergeData = new AtomicReference();
- UIUtil.invokeAndWaitIfNeeded(new Runnable() {
- @Override
- public void run() {
- try {
- mergeData.set(myMergeProvider.loadRevisions(file));
- } catch (VcsException e) {
- fail("Failed to load revisions", e);
- }
- }
- });
-
- assertEquals(mergeData.get().ORIGINAL, expectedBase);
- assertEquals(mergeData.get().CURRENT, expectedLocal);
- assertEquals(mergeData.get().LAST, expectedServer);
- }
-
- private static void assertEquals(byte[] bytes, String s) {
- Assert.assertEquals(new String(bytes), s);
- }
-
- /**
- * Creates a file with initial content in the parent repository, pulls & updates it to the child repository.
- * @return References to the files in parent and child repositories respectively.
- */
- private Pair prepareFileInBothRepositories() throws IOException {
- final VirtualFile parentFile = myParentRepo.createFile("a.txt", "basic");
- myParentRepo.add();
- myParentRepo.commit();
- myRepo.pull();
- myRepo.update();
- final VirtualFile childFile = myRepo.getDir().findChild("a.txt");
- return Pair.create(parentFile, childFile);
- }
-
-}
diff --git a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgTestUtil.java b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgTestUtil.java
deleted file mode 100644
index 875ddfa0081d..000000000000
--- a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgTestUtil.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2000-2010 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 org.zmlx.hg4idea.test;
-
-import com.intellij.openapi.vfs.VirtualFile;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.PrintStream;
-
-/**
- * HgTestUtil is a collection of static utility methods for Mercurial tests.
- * @author Kirill Likhodedov
- */
-public class HgTestUtil {
-
- private HgTestUtil() {}
-
- /**
- * Writes the given content to the file.
- * @param file file which content will be substituted by the given one.
- * @param content new file content
- */
- public static void printToFile(VirtualFile file, String content) throws FileNotFoundException {
- PrintStream centralPrinter = null;
- try {
- centralPrinter = new PrintStream(new FileOutputStream(new File(file.getPath())));
- centralPrinter.print(content);
- centralPrinter.close();
- } finally {
- if (centralPrinter != null) {
- centralPrinter.close();
- }
- }
- }
-
-}