diff --git a/plugins/git4idea/git4idea.iml b/plugins/git4idea/git4idea.iml index 3a86683611e2..b59acc53e8b4 100644 --- a/plugins/git4idea/git4idea.iml +++ b/plugins/git4idea/git4idea.iml @@ -35,6 +35,7 @@ + diff --git a/plugins/git4idea/testData/repo/dot_git/HEAD b/plugins/git4idea/testData/repo/dot_git/HEAD new file mode 100644 index 000000000000..cb089cd89a7d --- /dev/null +++ b/plugins/git4idea/testData/repo/dot_git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/plugins/git4idea/testData/repo/dot_git/config b/plugins/git4idea/testData/repo/dot_git/config new file mode 100644 index 000000000000..71b6c1994a62 --- /dev/null +++ b/plugins/git4idea/testData/repo/dot_git/config @@ -0,0 +1,15 @@ +[core] + repositoryformatversion = 0 + filemode = false + bare = false + logallrefupdates = true + ignorecase = true +[branch "master"] + remote = origin + merge = refs/heads/master +[remote "origin"] + url = /Users/loki/sandbox/git/parent.git/ + fetch = +refs/heads/*:refs/remotes/origin/* +[branch "newBranch"] + remote = origin + merge = refs/heads/newBranch diff --git a/plugins/git4idea/testData/repo/dot_git/index b/plugins/git4idea/testData/repo/dot_git/index new file mode 100644 index 000000000000..42745c4f0841 Binary files /dev/null and b/plugins/git4idea/testData/repo/dot_git/index differ diff --git a/plugins/git4idea/testData/repo/dot_git/packed-refs b/plugins/git4idea/testData/repo/dot_git/packed-refs new file mode 100644 index 000000000000..2c425ffc29d6 --- /dev/null +++ b/plugins/git4idea/testData/repo/dot_git/packed-refs @@ -0,0 +1,6 @@ +d85a972e14b616273c5a6f9dd858a02f9f5b12ad refs/remotes/brother/master +8a3d3a8d03e357b9baa39401faa5c9156ea4ca10 refs/remotes/origin/master +d85a972e14b616273c5a6f9dd858a02f9f5b12ad refs/remotes/smallteam/brother/master +a86078364a9ddc9f0b61f40b91ea9f4c8929f54b refs/remotes/smallteam/coolfeature +6bce43bed0bc3eb069086ad16d6d200be51f93f2 refs/remotes/smallteam/feature +a86078364a9ddc9f0b61f40b91ea9f4c8929f54b refs/remotes/smallteam/master diff --git a/plugins/git4idea/testData/repo/dot_git/refs/heads/feature b/plugins/git4idea/testData/repo/dot_git/refs/heads/feature new file mode 100644 index 000000000000..fcfb38e61716 --- /dev/null +++ b/plugins/git4idea/testData/repo/dot_git/refs/heads/feature @@ -0,0 +1 @@ +63fcb501752b1b98d5cda1f34915f846b3b4bbe2 diff --git a/plugins/git4idea/testData/repo/dot_git/refs/heads/folder/subref b/plugins/git4idea/testData/repo/dot_git/refs/heads/folder/subref new file mode 100644 index 000000000000..51b20a529fb1 --- /dev/null +++ b/plugins/git4idea/testData/repo/dot_git/refs/heads/folder/subref @@ -0,0 +1 @@ +32f76141b6a5dbef8d7e9096702ff7bfad218190 \ No newline at end of file diff --git a/plugins/git4idea/testData/repo/dot_git/refs/heads/hot_fix b/plugins/git4idea/testData/repo/dot_git/refs/heads/hot_fix new file mode 100644 index 000000000000..e09617387272 --- /dev/null +++ b/plugins/git4idea/testData/repo/dot_git/refs/heads/hot_fix @@ -0,0 +1 @@ +db5664aa94df9e7a41343fa92ddb10f340e4a991 diff --git a/plugins/git4idea/testData/repo/dot_git/refs/heads/master b/plugins/git4idea/testData/repo/dot_git/refs/heads/master new file mode 100644 index 000000000000..f75e53246e61 --- /dev/null +++ b/plugins/git4idea/testData/repo/dot_git/refs/heads/master @@ -0,0 +1 @@ +0e1d130689bc52f140c5c374aa9cc2b8916c0ad7 diff --git a/plugins/git4idea/testData/repo/dot_git/refs/remotes/origin/feature b/plugins/git4idea/testData/repo/dot_git/refs/remotes/origin/feature new file mode 100644 index 000000000000..9555a8ddd55a --- /dev/null +++ b/plugins/git4idea/testData/repo/dot_git/refs/remotes/origin/feature @@ -0,0 +1 @@ +4a6e262820fe3d5ac1c7ed52ea0dd42287780447 diff --git a/plugins/git4idea/testData/repo/dot_git/refs/remotes/origin/master b/plugins/git4idea/testData/repo/dot_git/refs/remotes/origin/master new file mode 100644 index 000000000000..a4607b3469c5 --- /dev/null +++ b/plugins/git4idea/testData/repo/dot_git/refs/remotes/origin/master @@ -0,0 +1 @@ +06d720e2dfe18592a3b7ebc938c57b0c6940176b diff --git a/plugins/git4idea/testData/repo/dot_git/refs/stash b/plugins/git4idea/testData/repo/dot_git/refs/stash new file mode 100644 index 000000000000..79160ab05ff1 --- /dev/null +++ b/plugins/git4idea/testData/repo/dot_git/refs/stash @@ -0,0 +1 @@ +32f76141b6a5dbef8d7e9096702ff7bfad218190 diff --git a/plugins/git4idea/testData/repo/dot_git/refs/tags/tag1 b/plugins/git4idea/testData/repo/dot_git/refs/tags/tag1 new file mode 100644 index 000000000000..81adde632c2d --- /dev/null +++ b/plugins/git4idea/testData/repo/dot_git/refs/tags/tag1 @@ -0,0 +1 @@ +471f3d78906e17ff2db8839381f42a3041b988b1 diff --git a/plugins/git4idea/testData/repo/dot_git/refs/tags/tag2 b/plugins/git4idea/testData/repo/dot_git/refs/tags/tag2 new file mode 100644 index 000000000000..b3f821f0a80d --- /dev/null +++ b/plugins/git4idea/testData/repo/dot_git/refs/tags/tag2 @@ -0,0 +1 @@ +f06e234d52d165b74ac615b5ef28bd871404c528 diff --git a/plugins/git4idea/tests/git4idea/repo/GitRepositoryReaderTest.java b/plugins/git4idea/tests/git4idea/repo/GitRepositoryReaderTest.java new file mode 100644 index 000000000000..ce586f69c8ec --- /dev/null +++ b/plugins/git4idea/tests/git4idea/repo/GitRepositoryReaderTest.java @@ -0,0 +1,173 @@ +/* + * Copyright 2000-2011 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.repo; + +import com.intellij.openapi.application.PluginPathManager; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.testFramework.LightIdeaTestCase; +import com.intellij.util.Processor; +import git4idea.GitBranch; +import git4idea.branch.GitBranchesCollection; +import git4idea.tests.GitTestUtil; +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; + +/** + * @author Kirill Likhodedov + */ +public class GitRepositoryReaderTest extends LightIdeaTestCase { + + private GitRepositoryReader myRepositoryReader; + private File myTempDir; + private File myGitDir; + private Collection myLocalBranches; + private Collection myRemoteBranches; + + protected void setUp() throws Exception { + super.setUp(); + myTempDir = FileUtil.createTempDirectory("GitRepositoryReaderTest", null); + + File pluginRoot = new File(PluginPathManager.getPluginHomePath("git4idea")); + File dataDir = new File(new File(pluginRoot, "testData"), "repo"); + + FileUtil.copyDir(dataDir, myTempDir); + myGitDir = new File(myTempDir, ".git"); + FileUtil.rename(new File(myTempDir, "dot_git"), myGitDir); + assertTrue(myGitDir.exists()); + myRepositoryReader = new GitRepositoryReader(myGitDir); + + myLocalBranches = readBranches(true); + myRemoteBranches = readBranches(false); + } + + protected void tearDown() throws Exception { + FileUtil.delete(myTempDir); + super.tearDown(); + } + + public void testHEAD() { + assertEquals("0e1d130689bc52f140c5c374aa9cc2b8916c0ad7", myRepositoryReader.readCurrentRevision()); + } + + public void testBranches(){ + GitBranchesCollection branchesCollection = myRepositoryReader.readBranches(); + GitBranch currentBranch = branchesCollection.getCurrentBranch(); + Collection localBranches = branchesCollection.getLocalBranches(); + Collection remoteBranches = branchesCollection.getRemoteBranches(); + + assertBranch(currentBranch, new GitTestBranch("master")); + assertBranches(localBranches, myLocalBranches); + assertBranches(remoteBranches, myRemoteBranches); + } + + private static void assertBranches(Collection actual, Collection expected) { + GitTestUtil.assertEqualCollections(actual, expected, new GitTestUtil.EqualityChecker() { + @Override + public boolean areEqual(@NotNull GitBranch actual, @NotNull GitTestBranch expected) { + return actual.getName().equals(expected.getName()); + } + }); + } + + private Collection readBranches(boolean local) throws IOException { + final Collection branches = new ArrayList(); + final File refsHeads = new File(new File(myGitDir, "refs"), local ? "heads" : "remotes"); + FileUtil.processFilesRecursively(refsHeads, new Processor() { + @Override + public boolean process(File file) { + if (file.equals(refsHeads)) { // don't process the root + return true; + } + if (file.isDirectory()) { // don't process dirs + return true; + } + String name = FileUtil.getRelativePath(refsHeads, file); + GitTestBranch branch = new GitTestBranch(name); + if (!branches.contains(branch)) { + branches.add(branch); + } + return true; + } + }); + + String packedRefs = FileUtil.loadFile(new File(myGitDir, "packed-refs")); + for (String ref : packedRefs.split("\n")) { + String[] refAndName = ref.split(" "); + String name = refAndName[1]; + String prefix = local ? "refs/heads/" : "refs/remotes/"; + if (name.startsWith(prefix)) { + GitTestBranch branch = new GitTestBranch(name.substring(prefix.length())); + if (!branches.contains(branch)) { + branches.add(branch); + } + } + } + return branches; + } + + private static void assertBranch(GitBranch actual, GitTestBranch expected) { + assertEquals(actual.getName(), expected.getName()); + // TODO test revision + } + + private static class GitTestBranch { + private final String myName; + private final String myHash = ""; + + private GitTestBranch(String name) { + myName = name; + } + + String getName() { + return myName; + } + + String getHash() { + return myHash; + } + + @Override + public String toString() { + return myName; + } + + @Override + public boolean equals(Object o) { + + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + GitTestBranch branch = (GitTestBranch)o; + + if (myHash != null ? !myHash.equals(branch.myHash) : branch.myHash != null) return false; + if (myName != null ? !myName.equals(branch.myName) : branch.myName != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = myName != null ? myName.hashCode() : 0; + result = 31 * result + (myHash != null ? myHash.hashCode() : 0); + return result; + } + } + +} diff --git a/plugins/git4idea/tests/git4idea/repo/GitRepositoryTest.java b/plugins/git4idea/tests/git4idea/repo/GitRepositoryTest.java index 0c1d704440d7..7ff940527714 100644 --- a/plugins/git4idea/tests/git4idea/repo/GitRepositoryTest.java +++ b/plugins/git4idea/tests/git4idea/repo/GitRepositoryTest.java @@ -15,6 +15,7 @@ */ package git4idea.repo; +import com.intellij.openapi.vfs.VfsUtil; import git4idea.GitBranch; import git4idea.tests.GitTest; import org.jetbrains.annotations.NotNull; @@ -22,6 +23,7 @@ import org.jetbrains.annotations.Nullable; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; +import java.io.File; import java.io.IOException; import java.util.concurrent.atomic.AtomicBoolean; @@ -46,7 +48,7 @@ public class GitRepositoryTest extends GitTest { public void setUp() throws Exception { super.setUp(); myRepository = GitRepository.getFullInstance(myRepo.getVFRootDir(), myProject, myProject); - myReader = new GitRepositoryReader(myRepository); + myReader = new GitRepositoryReader(new File(VfsUtil.virtualToIoFile(myRepository.getRoot()), ".git")); } @Test diff --git a/plugins/git4idea/tests/git4idea/tests/GitTestUtil.java b/plugins/git4idea/tests/git4idea/tests/GitTestUtil.java index c10154e64fe2..c3f799d5bf9c 100644 --- a/plugins/git4idea/tests/git4idea/tests/GitTestUtil.java +++ b/plugins/git4idea/tests/git4idea/tests/GitTestUtil.java @@ -133,7 +133,50 @@ public class GitTestUtil { } } - private static String stringifyActualExpected(@NotNull Collection actual, @NotNull Collection expected) { + /** + * Testng compares by iterating over 2 collections, but it won't work for sets which may have different order. + */ + public static void assertEqualCollections(@NotNull Collection actual, @NotNull Collection expected, @NotNull EqualityChecker equalityChecker) { + if (actual.size() != expected.size()) { + fail("Collections don't have the same size. " + stringifyActualExpected(actual, expected)); + } + for (T act : actual) { + if (!contains2(expected, act, equalityChecker)) { + fail("Unexpected object " + act + stringifyActualExpected(actual, expected)); + } + } + // backwards is needed for collections which may contain duplicates, e.g. Lists. + for (E exp : expected) { + if (!contains(actual, exp, equalityChecker)) { + fail("Object " + exp + " not found in actual collection." + stringifyActualExpected(actual, expected)); + } + } + } + + private static boolean contains(@NotNull Collection collection, @NotNull E object, @NotNull EqualityChecker equalityChecker) { + for (T t : collection) { + if (equalityChecker.areEqual(t, object)) { + return true; + } + } + return false; + } + + private static boolean contains2(Collection collection, T object, EqualityChecker equalityChecker) { + for (E e : collection) { + if (equalityChecker.areEqual(object, e)) { + return true; + } + } + return false; + } + + public interface EqualityChecker { + boolean areEqual(T actual, E expected); + } + + @NotNull + public static String stringifyActualExpected(@NotNull Object actual, @NotNull Object expected) { return "\nExpected:\n" + expected + "\nActual:\n" + actual; } }