Package org.eclipse.egit.core.test

Source Code of org.eclipse.egit.core.test.HistoryTest

/*******************************************************************************
* Copyright (C) 2013, Laurent Goubet <laurent.goubet@obeo.fr>
*
* 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.egit.core.test;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.egit.core.synchronize.GitResourceVariantTreeSubscriber;
import org.eclipse.egit.core.synchronize.dto.GitSynchronizeData;
import org.eclipse.egit.core.synchronize.dto.GitSynchronizeDataSet;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.team.core.RepositoryProvider;
import org.eclipse.team.core.diff.IDiff;
import org.eclipse.team.core.diff.IThreeWayDiff;
import org.eclipse.team.core.history.IFileHistory;
import org.eclipse.team.core.history.IFileHistoryProvider;
import org.eclipse.team.core.history.IFileRevision;
import org.eclipse.team.core.mapping.IResourceDiff;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class HistoryTest extends GitTestCase {
  private static final String MASTER = Constants.R_HEADS + Constants.MASTER;

  private static final String BRANCH = Constants.R_HEADS + "branch";

  private TestRepository testRepository;

  private IFile iFile1;

  private IFile iFile2;

  private final List<RevCommit> commits = new ArrayList<RevCommit>();

  private RevCommit masterCommit1;

  private RevCommit masterCommit2;

  private RevCommit masterCommit3;

  private RevCommit branchCommit1;

  private RevCommit branchCommit2;

  private IFileHistoryProvider historyProvider;

  @Before
  public void setUp() throws Exception {
    super.setUp();
    testRepository = new TestRepository(gitDir);
    testRepository.connect(project.getProject());

    File file1 = testRepository.createFile(project.getProject(), "file1");
    File file2 = testRepository.createFile(project.getProject(), "file2");

    iFile1 = testRepository.getIFile(project.getProject(), file1);
    iFile2 = testRepository.getIFile(project.getProject(), file2);

    masterCommit1 = testRepository.addAndCommit(project.getProject(),
        file1, "master-commit-1");
    masterCommit2 = testRepository.addAndCommit(project.getProject(),
        file2, "master-commit-2");
    testRepository.createBranch(MASTER, BRANCH);

    testRepository.appendFileContent(file1, "master-commit-3");
    testRepository.appendFileContent(file2, "master-commit-3");
    testRepository.track(file1);
    testRepository.track(file2);
    testRepository.addToIndex(project.getProject(), file1);
    testRepository.addToIndex(project.getProject(), file2);
    masterCommit3 = testRepository.commit("master-commit-3");

    testRepository.checkoutBranch(BRANCH);
    branchCommit1 = testRepository.appendContentAndCommit(
        project.getProject(), file1, "branch-commit-1",
        "branch-commit-1");
    branchCommit2 = testRepository.appendContentAndCommit(
        project.getProject(), file2, "branch-commit-2",
        "branch-commit-2");

    commits.add(masterCommit1);
    commits.add(masterCommit2);
    commits.add(masterCommit3);
    commits.add(branchCommit1);

    historyProvider = RepositoryProvider.getProvider(project.getProject())
        .getFileHistoryProvider();
  }

  @After
  public void tearDown() throws Exception {
    testRepository.dispose();
    super.tearDown();
  }

  @Test
  public void queryFile1FullHistory() throws CoreException {
    final List<RevCommit> expectedHistory = Arrays.asList(masterCommit1,
        masterCommit3, branchCommit1);
    assertFullHistoryMatches(iFile1, expectedHistory);
  }

  @Test
  public void queryFile2FullHistory() throws CoreException {
    final List<RevCommit> expectedHistory = Arrays.asList(masterCommit2,
        masterCommit3, branchCommit2);
    assertFullHistoryMatches(iFile2, expectedHistory);
  }

  private void assertFullHistoryMatches(IFile target,
      List<RevCommit> expectedHistory) throws CoreException {
    // Whatever the position of HEAD, the history should be the same
    for (RevCommit commit : commits) {
      testRepository.checkoutBranch(commit.getName());
      final IFileHistory history = historyProvider.getFileHistoryFor(
          target, IFileHistoryProvider.NONE,
          new NullProgressMonitor());
      assertNotNull(history);

      final IFileRevision[] revisions = history.getFileRevisions();
      assertEquals(expectedHistory.size(), revisions.length);
      final List<RevCommit> commitList = new ArrayList<RevCommit>(
          expectedHistory);
      assertMatchingRevisions(Arrays.asList(revisions), commitList);
    }
  }

  @Test
  public void querySingleRevisions() throws CoreException {
    for (RevCommit commit : commits) {
      for (IFile target : Arrays.asList(iFile1, iFile2)) {
        testRepository.checkoutBranch(commit.getName());
        final IFileHistory history = historyProvider.getFileHistoryFor(
            target, IFileHistoryProvider.SINGLE_REVISION,
            new NullProgressMonitor());
        assertNotNull(history);

        final IFileRevision[] revisions = history.getFileRevisions();
        assertEquals(1, revisions.length);
        assertRevisionMatchCommit(revisions[0], commit);
      }
    }
  }

  @Test
  public void queryFile1Contributors() {
    final IFileHistory history = historyProvider.getFileHistoryFor(iFile1,
        IFileHistoryProvider.NONE, new NullProgressMonitor());
    assertNotNull(history);

    final IFileRevision[] revisions = history.getFileRevisions();
    IFileRevision branchFileRevision1 = null;
    IFileRevision masterFileRevision3 = null;
    IFileRevision masterFileRevision1 = null;
    for (IFileRevision revision : revisions) {
      final String revisionId = revision.getContentIdentifier();
      if (branchCommit1.getName().equals(revisionId))
        branchFileRevision1 = revision;
      else if (masterCommit3.getName().equals(revisionId))
        masterFileRevision3 = revision;
      else if (masterCommit1.getName().equals(revisionId))
        masterFileRevision1 = revision;
    }
    assertNotNull(branchFileRevision1);
    assertNotNull(masterFileRevision3);
    assertNotNull(masterFileRevision1);

    /*
     * The "direct" parent of branchCommit1 is masterCommit2. However, that
     * commit did not contain file1. We thus expect the returned contributor
     * to be masterCommit1.
     */
    final IFileRevision[] branchCommit1Parents = history
        .getContributors(branchFileRevision1);
    assertEquals(1, branchCommit1Parents.length);
    assertRevisionMatchCommit(branchCommit1Parents[0], masterCommit1);

    // Likewise for masterCommit3
    final IFileRevision[] masterCommit3Parents = history
        .getContributors(masterFileRevision3);
    assertEquals(1, masterCommit3Parents.length);
    assertRevisionMatchCommit(masterCommit3Parents[0], masterCommit1);

    // masterCommit1 is our initial commit
    final IFileRevision[] masterCommit1Parents = history
        .getContributors(masterFileRevision1);
    assertEquals(0, masterCommit1Parents.length);
  }

  @Test
  public void queryFile2Contributors() {
    final IFileHistory history = historyProvider.getFileHistoryFor(iFile2,
        IFileHistoryProvider.NONE, new NullProgressMonitor());
    assertNotNull(history);

    final IFileRevision[] revisions = history.getFileRevisions();
    IFileRevision masterFileRevision3 = null;
    IFileRevision masterFileRevision2 = null;
    IFileRevision branchFileRevision2 = null;
    for (IFileRevision revision : revisions) {
      final String revisionId = revision.getContentIdentifier();
      if (masterCommit3.getName().equals(revisionId))
        masterFileRevision3 = revision;
      else if (masterCommit2.getName().equals(revisionId))
        masterFileRevision2 = revision;
      else if (branchCommit2.getName().equals(revisionId))
        branchFileRevision2 = revision;
    }
    assertNotNull(masterFileRevision3);
    assertNotNull(masterFileRevision2);
    assertNotNull(branchFileRevision2);

    final IFileRevision[] masterCommit3Parents = history
        .getContributors(masterFileRevision3);
    assertEquals(1, masterCommit3Parents.length);
    assertRevisionMatchCommit(masterCommit3Parents[0], masterCommit2);

    /*
     * The direct parent of masterCommit2 is the initial commit,
     * masterCommit1. However, file2 was not included in that commit. We
     * thus expect no parent.
     */
    final IFileRevision[] masterCommit2Parents = history
        .getContributors(masterFileRevision2);
    assertEquals(0, masterCommit2Parents.length);

    final IFileRevision[] branchCommit2Parents = history
        .getContributors(branchFileRevision2);
    assertEquals(1, branchCommit2Parents.length);
    assertRevisionMatchCommit(branchCommit2Parents[0], masterCommit2);
  }

  @Test
  public void queryFile1Targets() {
    final IFileHistory history = historyProvider.getFileHistoryFor(iFile1,
        IFileHistoryProvider.NONE, new NullProgressMonitor());
    assertNotNull(history);

    final IFileRevision[] revisions = history.getFileRevisions();
    IFileRevision branchFileRevision1 = null;
    IFileRevision masterFileRevision3 = null;
    IFileRevision masterFileRevision1 = null;
    for (IFileRevision revision : revisions) {
      final String revisionId = revision.getContentIdentifier();
      if (branchCommit1.getName().equals(revisionId))
        branchFileRevision1 = revision;
      else if (masterCommit3.getName().equals(revisionId))
        masterFileRevision3 = revision;
      else if (masterCommit1.getName().equals(revisionId))
        masterFileRevision1 = revision;
    }
    assertNotNull(branchFileRevision1);
    assertNotNull(masterFileRevision3);
    assertNotNull(masterFileRevision1);

    /*
     * The "direct" child of masterCommit1 is masterCommit2. However, that
     * commit did not contain file1. We thus expect the returned children to
     * be masterCommit3 and branchCommit1, since the ignored masterCommit2
     * is a branching point.
     */
    final IFileRevision[] masterCommit1Children = history
        .getTargets(masterFileRevision1);
    assertEquals(2, masterCommit1Children.length);
    final List<RevCommit> expected = new ArrayList<RevCommit>(
        Arrays.asList(masterCommit3, branchCommit1));
    assertMatchingRevisions(Arrays.asList(masterCommit1Children), expected);

    // masterCommit3 and branchCommit1 are leafs
    final IFileRevision[] masterCommit3Children = history
        .getTargets(masterFileRevision3);
    assertEquals(0, masterCommit3Children.length);

    final IFileRevision[] branchCommit1Children = history
        .getTargets(branchFileRevision1);
    assertEquals(0, branchCommit1Children.length);
  }

  @Test
  public void queryFile2Targets() {
    final IFileHistory history = historyProvider.getFileHistoryFor(iFile2,
        IFileHistoryProvider.NONE, new NullProgressMonitor());
    assertNotNull(history);

    final IFileRevision[] revisions = history.getFileRevisions();
    IFileRevision masterFileRevision3 = null;
    IFileRevision masterFileRevision2 = null;
    IFileRevision branchFileRevision2 = null;
    for (IFileRevision revision : revisions) {
      final String revisionId = revision.getContentIdentifier();
      if (masterCommit3.getName().equals(revisionId))
        masterFileRevision3 = revision;
      else if (masterCommit2.getName().equals(revisionId))
        masterFileRevision2 = revision;
      else if (branchCommit2.getName().equals(revisionId))
        branchFileRevision2 = revision;
    }
    assertNotNull(masterFileRevision3);
    assertNotNull(masterFileRevision2);
    assertNotNull(branchFileRevision2);

    final IFileRevision[] masterCommit2Children = history
        .getTargets(masterFileRevision2);
    assertEquals(2, masterCommit2Children.length);
    assertTrue(Arrays.asList(masterCommit2Children).contains(
        masterFileRevision3));
    assertTrue(Arrays.asList(masterCommit2Children).contains(
        branchFileRevision2));

    final IFileRevision[] masterCommit3Children = history
        .getTargets(masterFileRevision3);
    assertEquals(0, masterCommit3Children.length);

    final IFileRevision[] branchCommit2Children = history
        .getTargets(branchFileRevision2);
    assertEquals(0, branchCommit2Children.length);
  }

  /*
   * This aims at exerting the behavior of the EGit history provider when used
   * through the Team APIs. This is the behavior extenders will see when
   * interfacing with EGit through the synchronize view.
   *
   * The exact comparison with which we've reached the synchronize perspective
   * should not be relevant. To keep this test as short as possible, we'll
   * only test a single comparison.
   */
  @Test
  public void queryHistoryThroughTeam() throws IOException, CoreException {
    GitSynchronizeData gsd = new GitSynchronizeData(
        testRepository.getRepository(), MASTER, BRANCH, false);
    GitSynchronizeDataSet gsds = new GitSynchronizeDataSet(gsd);
    GitResourceVariantTreeSubscriber subscriber = new GitResourceVariantTreeSubscriber(
        gsds);
    subscriber.init(new NullProgressMonitor());

    IDiff diff = subscriber.getDiff(iFile2);
    assertTrue(diff instanceof IThreeWayDiff);

    IFileRevision sourceRevision = getSource(diff);
    IFileRevision destinationRevision = getDestination(diff);
    IFileRevision baseRevision = getBase(diff);

    assertRevisionMatchCommit(baseRevision, masterCommit2);
    assertRevisionMatchCommit(destinationRevision, branchCommit2);
    assertRevisionMatchCommit(sourceRevision, masterCommit3);

    final IFileHistory history = historyProvider.getFileHistoryFor(iFile2,
        IFileHistoryProvider.NONE,
        new NullProgressMonitor());
    assertNotNull(history);

    // no parent of masterCommit2 in file2's history
    IFileRevision[] parents = history.getContributors(baseRevision);
    assertEquals(0, parents.length);

    /*
     * branchCommit1 did not contain file2, so the "child" of masterCommit2
     * (branching point) in file2's history is branchCommit2.
     */
    IFileRevision[] children = history.getTargets(baseRevision);
    List<RevCommit> expectedChildren = new ArrayList<RevCommit>(
        Arrays.asList(masterCommit3, branchCommit2));
    assertEquals(expectedChildren.size(), children.length);
    assertMatchingRevisions(Arrays.asList(children), expectedChildren);
  }

  private static IFileRevision getSource(IDiff diff) {
    if (diff instanceof IResourceDiff)
      return ((IResourceDiff) diff).getBeforeState();

    if (diff instanceof IThreeWayDiff) {
      final IThreeWayDiff twd = (IThreeWayDiff) diff;
      final IDiff localChange = twd.getLocalChange();
      if (localChange instanceof IResourceDiff)
        return ((IResourceDiff) localChange).getAfterState();
    }

    return null;
  }

  private static IFileRevision getDestination(IDiff diff) {
    if (diff instanceof IResourceDiff)
      return ((IResourceDiff) diff).getAfterState();

    if (diff instanceof IThreeWayDiff) {
      final IThreeWayDiff twd = (IThreeWayDiff) diff;
      final IDiff remoteChange = twd.getRemoteChange();
      if (remoteChange instanceof IResourceDiff)
        return ((IResourceDiff) remoteChange).getAfterState();

      final IDiff localChange = twd.getLocalChange();
      if (localChange instanceof IResourceDiff)
        return ((IResourceDiff) localChange).getBeforeState();
    }

    return null;
  }

  private static IFileRevision getBase(IDiff diff) {
    if (diff instanceof IThreeWayDiff) {
      final IThreeWayDiff twd = (IThreeWayDiff) diff;
      final IDiff remoteChange = twd.getRemoteChange();
      if (remoteChange instanceof IResourceDiff)
        return ((IResourceDiff) remoteChange).getBeforeState();

      final IDiff localChange = twd.getLocalChange();
      if (localChange instanceof IResourceDiff)
        return ((IResourceDiff) localChange).getBeforeState();
    }

    return null;
  }

  private static void assertRevisionMatchCommit(IFileRevision revision,
      RevCommit commit) {
    assertEquals(commit.getAuthorIdent().getName(), revision.getAuthor());
    assertEquals(commit.getFullMessage(), revision.getComment());
    assertEquals(commit.getName(), revision.getContentIdentifier());
    // Git is in seconds, Team in milliseconds
    assertEquals(commit.getCommitTime(), revision.getTimestamp() / 1000);
  }

  private static void assertMatchingRevisions(List<IFileRevision> revisions,
      List<RevCommit> commits) {
    assertEquals(commits.size(), revisions.size());
    // Copy list : we'll empty it as we go
    for (IFileRevision revision : revisions) {
      boolean foundMatch = false;
      final Iterator<RevCommit> commitIterator = commits.iterator();
      while (commitIterator.hasNext() && !foundMatch) {
        final RevCommit commit = commitIterator.next();
        if (revision.getContentIdentifier().equals(commit.getName())) {
          assertRevisionMatchCommit(revision, commit);
          foundMatch = true;
          commitIterator.remove();
        }
      }
      assertTrue(foundMatch);
    }
    assertTrue(commits.isEmpty());
  }
}
TOP

Related Classes of org.eclipse.egit.core.test.HistoryTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.