blob: 39d5946c90ff6e8e89572ab9ffe110ee472136e3 [file] [log] [blame]
package git4idea.log;
import com.intellij.mock.MockVirtualFile;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.UsefulTestCase;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.vcs.log.VcsRef;
import com.intellij.vcs.log.VcsRefType;
import com.intellij.vcs.log.impl.HashImpl;
import com.intellij.vcs.log.impl.VcsRefImpl;
import git4idea.GitLocalBranch;
import git4idea.GitRemoteBranch;
import git4idea.branch.GitBranchesCollection;
import git4idea.repo.*;
import git4idea.test.GitMockRepositoryManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
public class GitRefManagerTest extends UsefulTestCase {
public static final MockVirtualFile MOCK_VIRTUAL_FILE = new MockVirtualFile("mockFile");
public void testEmpty() {
check(Collections.<VcsRef>emptyList(), Collections.<VcsRef>emptyList());
}
public void testSingle() {
check(given("HEAD"),
expect("HEAD"));
}
public void testHeadIsMoreImportantThanBranch() {
check(given("master", "HEAD"),
expect("HEAD", "master"));
}
public void testLocalBranchesAreComparedAsStrings() {
check(given("release", "feature"),
expect("feature", "release"));
}
public void testTagIsTheLessImportant() {
check(given("tag/v1", "origin/master"),
expect("origin/master", "tag/v1"));
}
public void testMasterIsMoreImportant() {
check(given("feature", "master"),
expect("master", "feature"));
}
public void testOriginMasterIsMoreImportant() {
check(given("origin/master", "origin/aaa"),
expect("origin/master", "origin/aaa"));
}
public void testRemoteBranchHavingTrackingBranchIsMoreImportant() {
check(given("feature", "origin/aaa", "origin/feature"),
expect("feature", "origin/feature", "origin/aaa"));
}
public void testSeveral1() {
check(given("tag/v1", "feature", "HEAD", "master"),
expect("HEAD", "master", "feature", "tag/v1"));
}
public void testSeveral2() {
check(given("origin/master", "origin/great_feature", "tag/v1", "release", "HEAD", "master"),
expect("HEAD", "master", "release", "origin/master", "origin/great_feature", "tag/v1"));
}
// may happen e.g. in multi-repo case
public void testTwoMasters() {
check(given("master", "master"),
expect("master", "master"));
}
private static Collection<VcsRef> given(String... refs) {
return convertToRefs(refs);
}
private static List<VcsRef> expect(String... refs) {
return new ArrayList<VcsRef>(convertToRefs(refs));
}
private static List<VcsRef> convertToRefs(String[] refs) {
return ContainerUtil.map(refs, new Function<String, VcsRef>() {
@Override
public VcsRef fun(String name) {
return ref(name);
}
});
}
private static VcsRef ref(String name) {
String randomHash = randomHash();
if (isHead(name)) {
return ref(randomHash, name, GitRefManager.HEAD);
}
if (isRemoteBranch(name)) {
return ref(randomHash, name, GitRefManager.REMOTE_BRANCH);
}
if (isTag(name)) {
return ref(randomHash, name, GitRefManager.TAG);
}
return ref(randomHash, name, GitRefManager.LOCAL_BRANCH);
}
private static String randomHash() {
return String.valueOf(new Random().nextInt());
}
private static boolean isHead(String name) {
return name.equals("HEAD");
}
private static boolean isTag(String name) {
return name.startsWith("tag/");
}
private static boolean isRemoteBranch(String name) {
return name.startsWith("origin/");
}
private static boolean isLocalBranch(String name) {
return !isHead(name) && !isTag(name) && !isRemoteBranch(name);
}
private static VcsRef ref(String hash, String name, VcsRefType type) {
return new VcsRefImpl(HashImpl.build(hash), name, type, MOCK_VIRTUAL_FILE);
}
private static void check(Collection<VcsRef> unsorted, List<VcsRef> expected) {
// for the sake of simplicity we check only names of references
List<VcsRef> actual = sort(unsorted);
assertEquals("Collections size don't match", expected.size(), actual.size());
for (int i = 0; i < actual.size(); i++) {
assertEquals("Incorrect element at place " + i, expected.get(i).getName(), actual.get(i).getName());
}
}
private static List<VcsRef> sort(final Collection<VcsRef> refs) {
final GitMockRepositoryManager manager = new GitMockRepositoryManager();
manager.add(new MockGitRepository() {
@NotNull
@Override
public Collection<GitBranchTrackInfo> getBranchTrackInfos() {
List<GitBranchTrackInfo> infos = new ArrayList<GitBranchTrackInfo>();
List<VcsRef> remoteRefs = ContainerUtil.findAll(refs, new Condition<VcsRef>() {
@Override
public boolean value(VcsRef ref) {
return isRemoteBranch(ref.getName());
}
});
List<VcsRef> localRefs = ContainerUtil.findAll(refs, new Condition<VcsRef>() {
@Override
public boolean value(VcsRef ref) {
return isLocalBranch(ref.getName());
}
});
for (final VcsRef localRef : localRefs) {
final VcsRef trackedRef = ContainerUtil.find(remoteRefs, new Condition<VcsRef>() {
@Override
public boolean value(VcsRef remoteRef) {
return localRef.getName().equals(remoteRef.getName().substring("origin/".length()));
}
});
if (trackedRef != null) {
infos.add(new GitBranchTrackInfo(new GitLocalBranch(localRef.getName(), HashImpl.build(randomHash())),
new GitRemoteBranch(trackedRef.getName(), HashImpl.build(randomHash())) {
@NotNull
@Override
public String getNameForRemoteOperations() {
return trackedRef.getName().substring("origin/".length());
}
@NotNull
@Override
public String getNameForLocalOperations() {
return trackedRef.getName();
}
@NotNull
@Override
public GitRemote getRemote() {
return GitRemote.DOT;
}
@Override
public boolean isRemote() {
return true;
}
}, true));
}
}
return infos;
}
});
return ContainerUtil.sorted(refs, new GitRefManager(manager).getComparator());
}
// TODO either use the real GitRepository, or move upwards and make more generic implementation
private static class MockGitRepository implements GitRepository {
@NotNull
@Override
public VirtualFile getGitDir() {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public GitUntrackedFilesHolder getUntrackedFilesHolder() {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public GitRepoInfo getInfo() {
throw new UnsupportedOperationException();
}
@Nullable
@Override
public GitLocalBranch getCurrentBranch() {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public GitBranchesCollection getBranches() {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public Collection<GitRemote> getRemotes() {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public Collection<GitBranchTrackInfo> getBranchTrackInfos() {
throw new UnsupportedOperationException();
}
@Override
public boolean isRebaseInProgress() {
throw new UnsupportedOperationException();
}
@Override
public boolean isOnBranch() {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public VirtualFile getRoot() {
return MOCK_VIRTUAL_FILE;
}
@NotNull
@Override
public String getPresentableUrl() {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public Project getProject() {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public State getState() {
throw new UnsupportedOperationException();
}
@Nullable
@Override
public String getCurrentBranchName() {
throw new UnsupportedOperationException();
}
@Nullable
@Override
public AbstractVcs getVcs() {
return null;
}
@Nullable
@Override
public String getCurrentRevision() {
throw new UnsupportedOperationException();
}
@Override
public boolean isFresh() {
throw new UnsupportedOperationException();
}
@Override
public void update() {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public String toLogString() {
throw new UnsupportedOperationException();
}
@Override
public void dispose() {
}
}
}