/******************************************************************************* * Copyright (C) 2015 Obeo and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ package org.eclipse.emf.compare.ide.ui.tests.merge; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.File; import java.util.Arrays; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.egit.core.op.MergeOperation; import org.eclipse.emf.compare.egit.internal.storage.AbstractGitResourceVariant; import org.eclipse.emf.compare.egit.internal.storage.IndexResourceVariant; import org.eclipse.emf.compare.egit.internal.storage.TreeParserResourceVariant; import org.eclipse.jgit.dircache.DirCache; import org.eclipse.jgit.dircache.DirCacheEntry; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.treewalk.CanonicalTreeParser; import org.eclipse.jgit.treewalk.TreeWalk; import org.junit.Test; public class ResourceVariantTest extends VariantsTestCase { private final static String BASE_BRANCH = "base"; private final static String BRANCH_CHANGE = "branch changes\n"; private final static String MASTER_CHANGE = "master changes\n"; @Test public void testIndexVariants() throws Exception { File file1 = repository.createFile(iProject, "file1"); File file2 = repository.createFile(iProject, "file2"); IFile iFile1 = repository.getIFile(iProject, file1); IFile iFile2 = repository.getIFile(iProject, file2); setupUnconflictingBranches(); List<String> possibleNames = Arrays.asList(iFile1.getName(), iFile2.getName()); DirCache cache = repo.readDirCache(); for (int i = 0; i < cache.getEntryCount(); i++) { final DirCacheEntry entry = cache.getEntry(i); AbstractGitResourceVariant variant = IndexResourceVariant.create(repo, entry); assertEquals(entry.getObjectId().getName(), variant.getContentIdentifier()); assertTrue(possibleNames.contains(variant.getName())); assertEquals(entry.getObjectId(), variant.getObjectId()); assertEquals(entry.getRawMode(), variant.getRawMode()); if (iFile1.getName().equals(variant.getName())) { assertContentEquals(variant, INITIAL_CONTENT_1 + MASTER_CHANGE); } else { assertContentEquals(variant, INITIAL_CONTENT_2 + MASTER_CHANGE); } } repository.checkoutBranch(BRANCH); cache = repo.readDirCache(); for (int i = 0; i < cache.getEntryCount(); i++) { final DirCacheEntry entry = cache.getEntry(i); AbstractGitResourceVariant variant = IndexResourceVariant.create(repo, entry); assertEquals(entry.getObjectId().getName(), variant.getContentIdentifier()); assertTrue(possibleNames.contains(variant.getName())); assertEquals(entry.getObjectId(), variant.getObjectId()); assertEquals(entry.getRawMode(), variant.getRawMode()); if (iFile1.getName().equals(variant.getName())) { assertContentEquals(variant, BRANCH_CHANGE + INITIAL_CONTENT_1); } else { assertContentEquals(variant, BRANCH_CHANGE + INITIAL_CONTENT_2); } } } @Test public void testIndexVariantsConflict() throws Exception { File file1 = repository.createFile(iProject, "file1"); IFile iFile1 = repository.getIFile(iProject, file1); setupConflictingBranches(); // end setup // create a conflict to force multiple stages new MergeOperation(repo, BRANCH).execute(null); DirCache cache = repo.readDirCache(); // 3 stages for file 1, 2 stages for file 2 assertEquals(5, cache.getEntryCount()); for (int i = 0; i < cache.getEntryCount(); i++) { final DirCacheEntry entry = cache.getEntry(i); AbstractGitResourceVariant variant = IndexResourceVariant.create(repo, entry); assertEquals(entry.getObjectId().getName(), variant.getContentIdentifier()); assertEquals(entry.getObjectId(), variant.getObjectId()); assertEquals(entry.getRawMode(), variant.getRawMode()); if (iFile1.getName().equals(variant.getName())) { switch (entry.getStage()) { case DirCacheEntry.STAGE_1: assertContentEquals(variant, INITIAL_CONTENT_1); break; case DirCacheEntry.STAGE_2: assertContentEquals(variant, INITIAL_CONTENT_1 + MASTER_CHANGE); break; case DirCacheEntry.STAGE_3: assertContentEquals(variant, BRANCH_CHANGE + INITIAL_CONTENT_1); break; case DirCacheEntry.STAGE_0: default: fail("Unexpected entry stage " + entry.getStage() + " in the index for file " + entry.getPathString()); break; } } else { switch (entry.getStage()) { case DirCacheEntry.STAGE_2: assertContentEquals(variant, INITIAL_CONTENT_2 + MASTER_CHANGE); break; case DirCacheEntry.STAGE_3: assertContentEquals(variant, BRANCH_CHANGE + INITIAL_CONTENT_2); break; case DirCacheEntry.STAGE_0: case DirCacheEntry.STAGE_1: default: fail("Unexpected entry stage " + entry.getStage() + " in the index for file " + entry.getPathString()); break; } } } } @Test public void testTreeWalkBranchVariants() throws Exception { File file1 = repository.createFile(iProject, "file1"); IFile iFile1 = repository.getIFile(iProject, file1); setupUnconflictingBranches(); ObjectId baseId = repo.resolve(BRANCH); RevWalk walk = new RevWalk(repo); TreeWalk tw = new TreeWalk(repo); try { tw.addTree(walk.parseTree(baseId)); while (tw.next()) { AbstractGitResourceVariant variant = TreeParserResourceVariant.create(repo, tw.getTree(0, CanonicalTreeParser.class), null); assertEquals(tw.getObjectId(0).getName(), variant.getContentIdentifier()); assertEquals(tw.getObjectId(0), variant.getObjectId()); assertEquals(tw.getRawMode(0), variant.getRawMode()); if (iFile1.getName().equals(variant.getName())) { assertContentEquals(variant, BRANCH_CHANGE + INITIAL_CONTENT_1); } else if (!tw.isSubtree()) { assertContentEquals(variant, BRANCH_CHANGE + INITIAL_CONTENT_2); } if (tw.isSubtree()) { tw.enterSubtree(); } } } finally { walk.close(); tw.close(); } } @Test public void testTreeWalkMasterVariants() throws Exception { File file1 = repository.createFile(iProject, "file1"); IFile iFile1 = repository.getIFile(iProject, file1); setupUnconflictingBranches(); ObjectId baseId = repo.resolve(MASTER); RevWalk walk = new RevWalk(repo); TreeWalk tw = new TreeWalk(repo); try { tw.addTree(walk.parseTree(baseId)); while (tw.next()) { AbstractGitResourceVariant variant = TreeParserResourceVariant.create(repo, tw.getTree(0, CanonicalTreeParser.class), null); assertEquals(tw.getObjectId(0).getName(), variant.getContentIdentifier()); assertEquals(tw.getObjectId(0), variant.getObjectId()); assertEquals(tw.getRawMode(0), variant.getRawMode()); if (iFile1.getName().equals(variant.getName())) { assertContentEquals(variant, INITIAL_CONTENT_1 + MASTER_CHANGE); } else if (!tw.isSubtree()) { assertContentEquals(variant, INITIAL_CONTENT_2 + MASTER_CHANGE); } if (tw.isSubtree()) { tw.enterSubtree(); } } } finally { walk.close(); tw.close(); } } @Test public void testTreeWalkBaseVariants() throws Exception { File file1 = repository.createFile(iProject, "file1"); IFile iFile1 = repository.getIFile(iProject, file1); setupUnconflictingBranches(); ObjectId baseId = repo.resolve(BASE_BRANCH); RevWalk walk = new RevWalk(repo); TreeWalk tw = new TreeWalk(repo); try { tw.addTree(walk.parseTree(baseId)); while (tw.next()) { AbstractGitResourceVariant variant = TreeParserResourceVariant.create(repo, tw.getTree(0, CanonicalTreeParser.class), null); assertEquals(tw.getObjectId(0).getName(), variant.getContentIdentifier()); assertEquals(tw.getObjectId(0), variant.getObjectId()); assertEquals(tw.getRawMode(0), variant.getRawMode()); if (iFile1.getName().equals(variant.getName())) { assertContentEquals(variant, INITIAL_CONTENT_1); } else if (!tw.isSubtree()) { fail("file2 shouldn't exist in our base."); } if (tw.isSubtree()) { tw.enterSubtree(); } } } finally { walk.close(); tw.close(); } } private void setupUnconflictingBranches() throws Exception { File file1 = repository.createFile(iProject, "file1"); File file2 = repository.createFile(iProject, "file2"); IFile iFile1 = repository.getIFile(iProject, file1); repository.appendContentAndCommit(iProject, file1, INITIAL_CONTENT_1, "first file - initial commit"); repository.createBranch(MASTER, BASE_BRANCH); repository.createAndCheckoutBranch(MASTER, BRANCH); setContentsAndCommit(repository, iFile1, BRANCH_CHANGE + INITIAL_CONTENT_1, "branch commit"); repository.appendContentAndCommit(iProject, file2, BRANCH_CHANGE + INITIAL_CONTENT_2, "second file - initial commit - branch"); repository.checkoutBranch(MASTER); setContentsAndCommit(repository, iFile1, INITIAL_CONTENT_1 + MASTER_CHANGE, "master commit - file1"); repository.appendContentAndCommit(iProject, file2, INITIAL_CONTENT_2 + MASTER_CHANGE, "second file - initial commit - master"); iProject.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor()); } private void setupConflictingBranches() throws Exception { File file1 = repository.createFile(iProject, "file1"); File file2 = repository.createFile(iProject, "file2"); IFile iFile1 = repository.getIFile(iProject, file1); repository.appendContentAndCommit(iProject, file1, INITIAL_CONTENT_1, "first file - initial commit"); repository.createAndCheckoutBranch(MASTER, BRANCH); setContentsAndCommit(repository, iFile1, BRANCH_CHANGE + INITIAL_CONTENT_1, "branch commit"); repository.appendContentAndCommit(iProject, file2, BRANCH_CHANGE + INITIAL_CONTENT_2, "second file - initial commit - branch"); repository.checkoutBranch(MASTER); setContentsAndCommit(repository, iFile1, INITIAL_CONTENT_1 + MASTER_CHANGE, "master commit - file1"); repository.appendContentAndCommit(iProject, file2, INITIAL_CONTENT_2 + MASTER_CHANGE, "second file - initial commit - master"); iProject.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor()); } }