/* Copyright (c) 2012-2014 Boundless and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/edl-v10.html
*
* Contributors:
* Johnathan Garrett (LMN Solutions) - initial implementation
*/
package org.locationtech.geogig.test.integration;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.locationtech.geogig.api.Ref;
import org.locationtech.geogig.api.RevCommit;
import org.locationtech.geogig.api.RevTag;
import org.locationtech.geogig.api.plumbing.RefParse;
import org.locationtech.geogig.api.porcelain.BranchCreateOp;
import org.locationtech.geogig.api.porcelain.BranchDeleteOp;
import org.locationtech.geogig.api.porcelain.CheckoutOp;
import org.locationtech.geogig.api.porcelain.CloneOp;
import org.locationtech.geogig.api.porcelain.CommitOp;
import org.locationtech.geogig.api.porcelain.FetchOp;
import org.locationtech.geogig.api.porcelain.LogOp;
import org.locationtech.geogig.api.porcelain.TagCreateOp;
import org.locationtech.geogig.api.porcelain.TagListOp;
import org.locationtech.geogig.remote.RemoteRepositoryTestCase;
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
public class FetchOpTest extends RemoteRepositoryTestCase {
@Rule
public ExpectedException exception = ExpectedException.none();
LinkedList<RevCommit> expectedMaster;
LinkedList<RevCommit> expectedBranch;
@Override
protected void setUpInternal() throws Exception {
}
private void prepareForFetch(boolean doClone) throws Exception {
if (doClone) {
// clone the repository
CloneOp clone = clone();
clone.setRepositoryURL(remoteGeogig.envHome.getCanonicalPath()).call();
}
// Commit several features to the remote
expectedMaster = new LinkedList<RevCommit>();
expectedBranch = new LinkedList<RevCommit>();
insertAndAdd(remoteGeogig.geogig, points1);
RevCommit commit = remoteGeogig.geogig.command(CommitOp.class).call();
expectedMaster.addFirst(commit);
expectedBranch.addFirst(commit);
// Create and checkout branch1
remoteGeogig.geogig.command(BranchCreateOp.class).setAutoCheckout(true).setName("Branch1")
.call();
// Commit some changes to branch1
insertAndAdd(remoteGeogig.geogig, points2);
commit = remoteGeogig.geogig.command(CommitOp.class).call();
expectedBranch.addFirst(commit);
insertAndAdd(remoteGeogig.geogig, points3);
commit = remoteGeogig.geogig.command(CommitOp.class).call();
expectedBranch.addFirst(commit);
// Make sure Branch1 has all of the commits
Iterator<RevCommit> logs = remoteGeogig.geogig.command(LogOp.class).call();
List<RevCommit> logged = Lists.newArrayList(logs);
assertEquals(expectedBranch, logged);
// Checkout master and commit some changes
remoteGeogig.geogig.command(CheckoutOp.class).setSource("master").call();
insertAndAdd(remoteGeogig.geogig, lines1);
commit = remoteGeogig.geogig.command(CommitOp.class).call();
expectedMaster.addFirst(commit);
insertAndAdd(remoteGeogig.geogig, lines2);
commit = remoteGeogig.geogig.command(CommitOp.class).call();
expectedMaster.addFirst(commit);
remoteGeogig.geogig.command(TagCreateOp.class) //
.setMessage("TestTag") //
.setCommitId(commit.getId()) //
.setName("test") //
.call();
// Make sure master has all of the commits
logs = remoteGeogig.geogig.command(LogOp.class).call();
logged = Lists.newArrayList(logs);
assertEquals(expectedMaster, logged);
}
private void verifyFetch() throws Exception {
// Make sure the local repository got all of the commits from master
localGeogig.geogig.command(CheckoutOp.class).setSource("refs/remotes/origin/master").call();
Iterator<RevCommit> logs = localGeogig.geogig.command(LogOp.class).call();
List<RevCommit> logged = Lists.newArrayList(logs);
assertEquals(expectedMaster, logged);
// Make sure the local repository got all of the commits from Branch1
localGeogig.geogig.command(CheckoutOp.class).setSource("refs/remotes/origin/Branch1")
.call();
logs = localGeogig.geogig.command(LogOp.class).call();
logged = Lists.newArrayList(logs);
assertEquals(expectedBranch, logged);
List<RevTag> tags = localGeogig.geogig.command(TagListOp.class).call();
assertEquals(1, tags.size());
}
private void verifyPrune() throws Exception {
// Make sure the local repository got all of the commits from master
localGeogig.geogig.command(CheckoutOp.class).setForce(true)
.setSource("refs/remotes/origin/master").call();
Iterator<RevCommit> logs = localGeogig.geogig.command(LogOp.class).call();
List<RevCommit> logged = Lists.newArrayList(logs);
assertEquals(expectedMaster, logged);
// Make sure the local repository no longer has Branch1
Optional<Ref> missing = localGeogig.geogig.command(RefParse.class)
.setName("refs/remotes/origin/Branch1").call();
assertFalse(missing.isPresent());
}
@Test
public void testFetch() throws Exception {
prepareForFetch(true);
// fetch from the remote
FetchOp fetch = fetch();
fetch.call();
verifyFetch();
}
@Test
public void testFetchDepth() throws Exception {
prepareForFetch(false);
// clone the repository
CloneOp clone = clone();
clone.setDepth(2);
String repositoryURL = remoteGeogig.envHome.getCanonicalPath();
clone.setRepositoryURL(repositoryURL).call();
FetchOp fetch = fetch();
fetch.setDepth(3);
fetch.call();
// Make sure the local repository got all of the commits from master
localGeogig.geogig.command(CheckoutOp.class).setSource("refs/remotes/origin/master").call();
Iterator<RevCommit> logs = localGeogig.geogig.command(LogOp.class).call();
List<RevCommit> logged = Lists.newArrayList(logs);
assertEquals(3, logged.size());
assertEquals(expectedMaster.get(0), logged.get(0));
assertEquals(expectedMaster.get(1), logged.get(1));
assertEquals(expectedMaster.get(2), logged.get(2));
// Make sure the local repository got all of the commits from Branch1
localGeogig.geogig.command(CheckoutOp.class).setSource("refs/remotes/origin/Branch1")
.call();
logs = localGeogig.geogig.command(LogOp.class).call();
logged = Lists.newArrayList(logs);
assertEquals(3, logged.size());
assertEquals(expectedBranch.get(0), logged.get(0));
assertEquals(expectedBranch.get(1), logged.get(1));
assertEquals(expectedBranch.get(2), logged.get(2));
}
@Test
public void testFetchFullDepth() throws Exception {
prepareForFetch(false);
// clone the repository
CloneOp clone = clone();
clone.setDepth(2);
clone.setRepositoryURL(remoteGeogig.envHome.getCanonicalPath()).call();
FetchOp fetch = fetch();
fetch.setFullDepth(true);
fetch.call();
verifyFetch();
}
@Test
public void testFetchNewCommitsWithShallowClone() throws Exception {
prepareForFetch(false);
// clone the repository
CloneOp clone = clone();
clone.setDepth(2);
clone.setRepositoryURL(remoteGeogig.envHome.getCanonicalPath()).call();
// Checkout master and commit some changes
remoteGeogig.geogig.command(CheckoutOp.class).setSource("master").call();
insertAndAdd(remoteGeogig.geogig, points1_modified);
RevCommit commit = remoteGeogig.geogig.command(CommitOp.class).call();
expectedMaster.addFirst(commit);
FetchOp fetch = fetch();
fetch.call();
// Make sure the local repository got all of the commits from master
localGeogig.geogig.command(CheckoutOp.class).setSource("refs/remotes/origin/master").call();
Iterator<RevCommit> logs = localGeogig.geogig.command(LogOp.class).call();
List<RevCommit> logged = Lists.newArrayList(logs);
assertEquals(3, logged.size());
assertEquals(expectedMaster.get(0), logged.get(0));
assertEquals(expectedMaster.get(1), logged.get(1));
assertEquals(expectedMaster.get(2), logged.get(2));
}
@Test
public void testFetchNewCommitsWithShallowClone2() throws Exception {
insertAndAdd(remoteGeogig.geogig, points1);
RevCommit commit = remoteGeogig.geogig.command(CommitOp.class).setMessage("1").call();
insertAndAdd(remoteGeogig.geogig, points2);
commit = remoteGeogig.geogig.command(CommitOp.class).setMessage("2").call();
insertAndAdd(remoteGeogig.geogig, points3);
commit = remoteGeogig.geogig.command(CommitOp.class).setMessage("3").call();
// clone the repository
CloneOp clone = clone();
clone.setDepth(2);
clone.setRepositoryURL(remoteGeogig.envHome.getCanonicalPath()).call();
// Checkout master and commit some changes
remoteGeogig.geogig.command(CheckoutOp.class).setSource("master").call();
insertAndAdd(remoteGeogig.geogig, lines1);
commit = remoteGeogig.geogig.command(CommitOp.class).setMessage("4").call();
insertAndAdd(remoteGeogig.geogig, points1_modified);
commit = remoteGeogig.geogig.command(CommitOp.class).setMessage("5").call();
insertAndAdd(remoteGeogig.geogig, lines2);
commit = remoteGeogig.geogig.command(CommitOp.class).setMessage("6").call();
insertAndAdd(remoteGeogig.geogig, lines3);
commit = remoteGeogig.geogig.command(CommitOp.class).setMessage("7").call();
FetchOp fetch = fetch();
// fetch.setDepth(2);
fetch.call();
localGeogig.geogig.command(CheckoutOp.class).setSource("refs/remotes/origin/master").call();
Iterator<RevCommit> logs = localGeogig.geogig.command(LogOp.class).call();
List<RevCommit> logged = Lists.newArrayList(logs);
// Should have the previous 2 commits, plus all 4 new commits.
assertEquals(6, logged.size());
}
@Test
public void testFetchNewRefWithShallowClone() throws Exception {
// Commit several features to the remote
expectedMaster = new LinkedList<RevCommit>();
expectedBranch = new LinkedList<RevCommit>();
insertAndAdd(remoteGeogig.geogig, points1);
RevCommit commit = remoteGeogig.geogig.command(CommitOp.class).call();
RevCommit originCommit = commit;
expectedMaster.addFirst(commit);
expectedBranch.addFirst(commit);
insertAndAdd(remoteGeogig.geogig, lines1);
commit = remoteGeogig.geogig.command(CommitOp.class).call();
expectedMaster.addFirst(commit);
insertAndAdd(remoteGeogig.geogig, lines2);
commit = remoteGeogig.geogig.command(CommitOp.class).call();
expectedMaster.addFirst(commit);
// Make sure master has all of the commits
Iterator<RevCommit> logs = remoteGeogig.geogig.command(LogOp.class).call();
List<RevCommit> logged = Lists.newArrayList(logs);
assertEquals(expectedMaster, logged);
// clone the repository
CloneOp clone = clone();
clone.setDepth(2);
clone.setRepositoryURL(remoteGeogig.envHome.getCanonicalPath()).call();
// Create and checkout branch1
remoteGeogig.geogig.command(BranchCreateOp.class).setAutoCheckout(true).setName("Branch1")
.setSource(originCommit.getId().toString()).call();
// Commit some changes to branch1
insertAndAdd(remoteGeogig.geogig, points2);
commit = remoteGeogig.geogig.command(CommitOp.class).call();
expectedBranch.addFirst(commit);
insertAndAdd(remoteGeogig.geogig, points3);
commit = remoteGeogig.geogig.command(CommitOp.class).call();
expectedBranch.addFirst(commit);
// Make sure Branch1 has all of the commits
logs = remoteGeogig.geogig.command(LogOp.class).call();
logged = Lists.newArrayList(logs);
assertEquals(expectedBranch, logged);
FetchOp fetch = fetch();
fetch.call();
// Make sure the local repository got all of the commits from master
localGeogig.geogig.command(CheckoutOp.class).setSource("refs/remotes/origin/master").call();
logs = localGeogig.geogig.command(LogOp.class).call();
logged = Lists.newArrayList(logs);
assertEquals(2, logged.size());
assertEquals(expectedMaster.get(0), logged.get(0));
assertEquals(expectedMaster.get(1), logged.get(1));
// Make sure the local repository got all of the commits from Branch1
localGeogig.geogig.command(CheckoutOp.class).setSource("refs/remotes/origin/Branch1")
.call();
logs = localGeogig.geogig.command(LogOp.class).call();
logged = Lists.newArrayList(logs);
assertEquals(2, logged.size());
assertEquals(expectedBranch.get(0), logged.get(0));
assertEquals(expectedBranch.get(1), logged.get(1));
}
@Test
public void testFetchDepthWithFullRepo() throws Exception {
prepareForFetch(true);
FetchOp fetch = fetch();
fetch.setDepth(2);
fetch.call();
verifyFetch();
}
@Test
public void testFetchFullDepthWithFullRepo() throws Exception {
prepareForFetch(true);
FetchOp fetch = fetch();
fetch.setFullDepth(true);
fetch.call();
verifyFetch();
}
@Test
public void testFetchAll() throws Exception {
prepareForFetch(true);
// fetch from the remote
FetchOp fetch = fetch();
fetch.setAll(true).call();
verifyFetch();
}
@Test
public void testFetchSpecificRemote() throws Exception {
prepareForFetch(true);
// fetch from the remote
FetchOp fetch = fetch();
fetch.addRemote("origin").call();
verifyFetch();
}
@Test
public void testFetchSpecificRemoteAndAll() throws Exception {
prepareForFetch(true);
// fetch from the remote
FetchOp fetch = fetch();
fetch.addRemote("origin").setAll(true).call();
verifyFetch();
}
@Test
public void testFetchNoRemotes() throws Exception {
FetchOp fetch = fetch();
exception.expect(IllegalStateException.class);
fetch.call();
}
@Test
public void testFetchNoChanges() throws Exception {
prepareForFetch(true);
// fetch from the remote
FetchOp fetch = fetch();
fetch.addRemote("origin").setAll(true).call();
verifyFetch();
// fetch again
fetch.call();
verifyFetch();
}
@Test
public void testFetchWithPrune() throws Exception {
prepareForFetch(true);
// fetch from the remote
FetchOp fetch = fetch();
fetch.addRemote("origin").setAll(true).call();
verifyFetch();
// Remove a branch from the remote
remoteGeogig.geogig.command(BranchDeleteOp.class).setName("Branch1").call();
// fetch again
fetch = fetch();
fetch.setPrune(true).call();
verifyPrune();
}
@Test
public void testFetchWithPruneAndBranchAdded() throws Exception {
prepareForFetch(true);
// fetch from the remote
FetchOp fetch = fetch();
fetch.addRemote("origin").setAll(true).call();
verifyFetch();
// Remove a branch from the remote
remoteGeogig.geogig.command(BranchDeleteOp.class).setName("Branch1").call();
// Add another branch
remoteGeogig.geogig.command(BranchCreateOp.class).setName("Branch2").call();
// fetch again
fetch = fetch();
fetch.setPrune(true).call();
verifyPrune();
// Make sure the local repository has Branch2
Optional<Ref> missing = localGeogig.geogig.command(RefParse.class)
.setName("refs/remotes/origin/Branch2").call();
assertTrue(missing.isPresent());
}
}