/* 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.assertNotNull; import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.Arrays; 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.ObjectId; import org.locationtech.geogig.api.RevCommit; import org.locationtech.geogig.api.RevObject; import org.locationtech.geogig.api.RevTag; import org.locationtech.geogig.api.plumbing.RevObjectParse; 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.LogOp; import org.locationtech.geogig.api.porcelain.MergeOp; import org.locationtech.geogig.api.porcelain.MergeOp.MergeReport; import org.locationtech.geogig.api.porcelain.TagCreateOp; import org.locationtech.geogig.api.porcelain.TagListOp; import org.locationtech.geogig.remote.RemoteRepositoryTestCase; import org.opengis.feature.Feature; import com.google.common.base.Optional; import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; public class CloneOpTest extends RemoteRepositoryTestCase { @Rule public ExpectedException exception = ExpectedException.none(); @Override protected void setUpInternal() throws Exception { } @Test public void testClone() throws Exception { // Commit several features to the remote List<Feature> features = Arrays.asList(points1, lines1, points2, lines2, points3, lines3); LinkedList<RevCommit> expected = new LinkedList<RevCommit>(); for (Feature f : features) { ObjectId oId = insertAndAdd(remoteGeogig.geogig, f); final RevCommit commit = remoteGeogig.geogig.command(CommitOp.class).call(); expected.addFirst(commit); Optional<RevObject> childObject = remoteGeogig.geogig.command(RevObjectParse.class) .setObjectId(oId).call(); assertTrue(childObject.isPresent()); } // Make sure the remote has all of the commits Iterator<RevCommit> logs = remoteGeogig.geogig.command(LogOp.class).call(); List<RevCommit> logged = new ArrayList<RevCommit>(); for (; logs.hasNext();) { logged.add(logs.next()); } assertEquals(expected, logged); // Make sure the local repository has no commits prior to clone logs = localGeogig.geogig.command(LogOp.class).call(); assertNotNull(logs); assertFalse(logs.hasNext()); // clone from the remote CloneOp clone = clone(); clone.setDepth(0); clone.setRepositoryURL(remoteGeogig.envHome.getCanonicalPath()).call(); // Make sure the local repository got all of the commits logs = localGeogig.geogig.command(LogOp.class).call(); logged = new ArrayList<RevCommit>(); for (; logs.hasNext();) { logged.add(logs.next()); } assertEquals(expected, logged); } @Test public void testCloneWithTags() throws Exception { // Commit several features to the remote List<Feature> features = Arrays.asList(points1, lines1, points2, lines2, points3, lines3); LinkedList<RevCommit> expected = new LinkedList<RevCommit>(); List<RevTag> tags = Lists.newArrayList(); for (Feature f : features) { ObjectId oId = insertAndAdd(remoteGeogig.geogig, f); final RevCommit commit = remoteGeogig.geogig.command(CommitOp.class).call(); expected.addFirst(commit); Optional<RevObject> childObject = remoteGeogig.geogig.command(RevObjectParse.class) .setObjectId(oId).call(); assertTrue(childObject.isPresent()); RevTag tag = remoteGeogig.geogig.command(TagCreateOp.class).setCommitId(commit.getId()) .setName(f.getIdentifier().getID()).call(); tags.add(tag); } // Make sure the remote has all of the commits Iterator<RevCommit> logs = remoteGeogig.geogig.command(LogOp.class).call(); List<RevCommit> logged = new ArrayList<RevCommit>(); for (; logs.hasNext();) { logged.add(logs.next()); } assertEquals(expected, logged); // Make sure the remote has all of the tags ImmutableList<RevTag> remoteTags = remoteGeogig.geogig.command(TagListOp.class).call(); assertEquals(tags.size(), remoteTags.size()); for (RevTag tag : tags) { assertTrue(remoteTags.contains(tag)); } // Make sure the local repository has no commits prior to clone logs = localGeogig.geogig.command(LogOp.class).call(); assertNotNull(logs); assertFalse(logs.hasNext()); // clone from the remote CloneOp clone = clone(); clone.setDepth(0); clone.setRepositoryURL(remoteGeogig.envHome.getCanonicalPath()).call(); // Make sure the local repository got all of the commits logs = localGeogig.geogig.command(LogOp.class).call(); logged = new ArrayList<RevCommit>(); for (; logs.hasNext();) { logged.add(logs.next()); } assertEquals(expected, logged); /* * This is commented out, since the clone operation does not clone tags yet This test * verifies that no errors are raised when the repo to clone contains tags, but not to * verify that tags are also cloned, since that is not supported * * I leave this dommented code here, to uncomment it once tag support is implemented for the * clone operation * * * // Make sure the local repository got all of the tags * * ImmutableList<RevTag> localTags = localGeogig.geogig.command(TagListOp.class).call(); * * assertEquals(tags.size(), localTags.size()); * * for (RevTag tag : tags) { * * assertTrue(localTags.contains(tag)); * * } */ } @Test public void testCloneWithMergeCommit() throws Exception { // Commit several features to the remote LinkedList<RevCommit> expectedMaster = new LinkedList<RevCommit>(); LinkedList<RevCommit> expectedBranch = new LinkedList<RevCommit>(); insertAndAdd(remoteGeogig.geogig, points1); RevCommit commit = remoteGeogig.geogig.command(CommitOp.class).call(); expectedMaster.addFirst(commit); expectedBranch.addFirst(commit); insertAndAdd(remoteGeogig.geogig, points1_modified); 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 a change to branch1 insertAndAdd(remoteGeogig.geogig, points2); RevCommit branch1commit = remoteGeogig.geogig.command(CommitOp.class).call(); expectedBranch.addFirst(branch1commit); // Make sure Branch1 has all of the commits Iterator<RevCommit> logs = remoteGeogig.geogig.command(LogOp.class).call(); List<RevCommit> logged = new ArrayList<RevCommit>(); for (; logs.hasNext();) { logged.add(logs.next()); } 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); // Make sure master has all of the commits logs = remoteGeogig.geogig.command(LogOp.class).call(); logged = new ArrayList<RevCommit>(); for (; logs.hasNext();) { logged.add(logs.next()); } assertEquals(expectedMaster, logged); // Merge branch1 into master MergeReport report = remoteGeogig.geogig.command(MergeOp.class) .addCommit(Suppliers.ofInstance(branch1commit.getId())).call(); expectedMaster.addFirst(report.getMergeCommit()); // Delete Branch1 // Create and checkout branch1 remoteGeogig.geogig.command(BranchDeleteOp.class).setName("Branch1").call(); // clone from the remote CloneOp clone = clone(); clone.setRepositoryURL(remoteGeogig.envHome.getCanonicalPath()).setBranch("master").call(); // Make sure the local repository got all of the commits logs = localGeogig.geogig.command(LogOp.class).setFirstParentOnly(true).call(); logged = new ArrayList<RevCommit>(); for (; logs.hasNext();) { logged.add(logs.next()); } assertEquals(expectedMaster, logged); } @Test public void testShallowClone() throws Exception { // Commit several features to the remote List<Feature> features = Arrays.asList(points1, lines1, points2, lines2, points3, lines3); LinkedList<RevCommit> expected = new LinkedList<RevCommit>(); for (Feature f : features) { ObjectId oId = insertAndAdd(remoteGeogig.geogig, f); final RevCommit commit = remoteGeogig.geogig.command(CommitOp.class).call(); expected.addFirst(commit); Optional<RevObject> childObject = remoteGeogig.geogig.command(RevObjectParse.class) .setObjectId(oId).call(); assertTrue(childObject.isPresent()); } // Make sure the remote has all of the commits Iterator<RevCommit> logs = remoteGeogig.geogig.command(LogOp.class).call(); List<RevCommit> logged = new ArrayList<RevCommit>(); for (; logs.hasNext();) { logged.add(logs.next()); } assertEquals(expected, logged); // Make sure the local repository has no commits prior to clone logs = localGeogig.geogig.command(LogOp.class).call(); assertNotNull(logs); assertFalse(logs.hasNext()); // clone from the remote CloneOp clone = clone(); clone.setDepth(2); clone.setRepositoryURL(remoteGeogig.envHome.getCanonicalPath()).call(); // Make sure the local repository got only 2 commits logs = localGeogig.geogig.command(LogOp.class).call(); logged = new ArrayList<RevCommit>(); for (; logs.hasNext();) { logged.add(logs.next()); } assertEquals(2, logged.size()); assertEquals(expected.get(0), logged.get(0)); assertEquals(expected.get(1), logged.get(1)); } @Test public void testCloneRepoWithBranches() throws Exception { // Commit several features to the remote LinkedList<RevCommit> expectedMaster = new LinkedList<RevCommit>(); 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 = new ArrayList<RevCommit>(); for (; logs.hasNext();) { logged.add(logs.next()); } 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); // Make sure master has all of the commits logs = remoteGeogig.geogig.command(LogOp.class).call(); logged = new ArrayList<RevCommit>(); for (; logs.hasNext();) { logged.add(logs.next()); } assertEquals(expectedMaster, logged); // Make sure the local repository has no commits prior to clone logs = localGeogig.geogig.command(LogOp.class).call(); assertNotNull(logs); assertFalse(logs.hasNext()); // clone from the remote CloneOp clone = clone(); clone.setRepositoryURL(remoteGeogig.envHome.getCanonicalPath()).setBranch("Branch1").call(); // Make sure the local repository got all of the commits logs = localGeogig.geogig.command(LogOp.class).call(); logged = new ArrayList<RevCommit>(); for (; logs.hasNext();) { logged.add(logs.next()); } assertEquals(expectedBranch, logged); // Make sure the local master matches the remote localGeogig.geogig.command(CheckoutOp.class).setSource("master").call(); logs = localGeogig.geogig.command(LogOp.class).call(); logged = new ArrayList<RevCommit>(); for (; logs.hasNext();) { logged.add(logs.next()); } assertEquals(expectedMaster, logged); } @Test public void testCloneEmptyRepo() throws Exception { CloneOp clone = clone(); clone.setRepositoryURL(remoteGeogig.envHome.getCanonicalPath()).call(); } @Test public void testCloneNoRepoSpecified() throws Exception { CloneOp clone = clone(); exception.expect(IllegalArgumentException.class); clone.call(); } @Test public void testCloneEmptyRepoString() throws Exception { CloneOp clone = clone(); exception.expect(IllegalArgumentException.class); clone.setRepositoryURL("").call(); } }