/* Copyright (c) 2013-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 java.util.Iterator; import java.util.List; import org.junit.Test; import org.locationtech.geogig.api.NodeRef; import org.locationtech.geogig.api.ObjectId; import org.locationtech.geogig.api.Ref; import org.locationtech.geogig.api.RevFeatureType; import org.locationtech.geogig.api.RevFeatureTypeImpl; import org.locationtech.geogig.api.RevObject; import org.locationtech.geogig.api.RevObject.TYPE; import org.locationtech.geogig.api.plumbing.FindTreeChild; import org.locationtech.geogig.api.plumbing.RefParse; import org.locationtech.geogig.api.plumbing.diff.DiffEntry; import org.locationtech.geogig.api.plumbing.diff.DiffEntry.ChangeType; import org.locationtech.geogig.api.plumbing.merge.Conflict; import org.locationtech.geogig.api.porcelain.AddOp; import org.locationtech.geogig.api.porcelain.BranchCreateOp; import org.locationtech.geogig.api.porcelain.CheckoutOp; import org.locationtech.geogig.api.porcelain.CommitOp; import org.locationtech.geogig.api.porcelain.MergeConflictsException; import org.locationtech.geogig.api.porcelain.MergeOp; 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 AddOpTest extends RepositoryTestCase { @Override protected void setUpInternal() throws Exception { injector.configDatabase().put("user.name", "groldan"); injector.configDatabase().put("user.email", "groldan@boundlessgeo.com"); } @Test public void testAddSingleFile() throws Exception { insert(points1); List<DiffEntry> diffs = toList(repo.workingTree().getUnstaged(null)); assertEquals(2, diffs.size()); assertEquals(pointsName, diffs.get(0).newPath()); assertEquals(NodeRef.appendChild(pointsName, idP1), diffs.get(1).newPath()); } @Test public void testAddMultipleFeatures() throws Exception { insert(points1); insert(points2); insert(points3); geogig.command(AddOp.class).call(); List<DiffEntry> unstaged = toList(repo.workingTree().getUnstaged(null)); assertEquals(ImmutableList.of(), unstaged); } @Test public void testAddMultipleTimes() throws Exception { insert(points1); insert(points2); insert(points3); geogig.command(AddOp.class).call(); Iterator<DiffEntry> iterator = repo.workingTree().getUnstaged(null); assertFalse(iterator.hasNext()); insert(lines1); insert(lines2); geogig.command(AddOp.class).call(); iterator = repo.workingTree().getUnstaged(null); assertFalse(iterator.hasNext()); } @Test public void testAddNewPathUsingPathFilter() throws Exception { insert(points1); insert(points2); geogig.command(AddOp.class).addPattern("Points/Points.1").call(); List<DiffEntry> unstaged = toList(repo.index().getStaged(null)); assertEquals(unstaged.toString(), 2, unstaged.size()); assertEquals(ChangeType.ADDED, unstaged.get(0).changeType()); assertEquals(RevObject.TYPE.TREE, unstaged.get(0).getNewObject().getType()); assertEquals("Points", unstaged.get(0).newName()); RevFeatureType ft = RevFeatureTypeImpl.build(pointsType); ObjectId expectedTreeMdId = ft.getId(); assertEquals(expectedTreeMdId, unstaged.get(0).getNewObject().getMetadataId()); assertEquals(ChangeType.ADDED, unstaged.get(1).changeType()); assertEquals(RevObject.TYPE.FEATURE, unstaged.get(1).getNewObject().getType()); assertEquals("Points.1", unstaged.get(1).newName()); assertFalse("feature node's metadata id should not be set, as it uses the parent tree one", unstaged.get(1).getNewObject().getNode().getMetadataId().isPresent()); } @Test public void testAddMultipleFeaturesWithPathFilter() throws Exception { insert(points1); insert(points2); insert(lines1); geogig.command(AddOp.class).addPattern("Points").call(); List<DiffEntry> unstaged = toList(repo.workingTree().getUnstaged(null)); assertEquals(2, unstaged.size()); assertEquals(linesName, unstaged.get(0).newName()); assertEquals(ChangeType.ADDED, unstaged.get(0).changeType()); assertEquals(TYPE.TREE, unstaged.get(0).getNewObject().getType()); } @Test public void testAddSingleDeletion() throws Exception { insert(points1); insert(points2); geogig.command(AddOp.class).call(); List<DiffEntry> staged = toList(repo.index().getStaged(Lists.newArrayList(pointsName))); assertEquals(3, staged.size()); delete(points1); geogig.command(AddOp.class).call(); staged = toList(repo.index().getStaged(Lists.newArrayList(pointsName))); assertEquals(2, staged.size()); } @Test public void testAddTreeDeletion() throws Exception { insert(points1); insert(points2); geogig.command(AddOp.class).call(); repo.workingTree().delete(pointsName); geogig.command(AddOp.class).call(); List<DiffEntry> staged = toList(repo.index().getStaged(Lists.newArrayList(pointsName))); assertEquals(0, staged.size()); assertEquals(0, repo.index().countStaged(null).featureCount()); assertEquals(0, repo.index().countStaged(null).treeCount()); } @Test public void testAddUpdate() throws Exception { insert(points1); geogig.command(AddOp.class).call(); geogig.command(CommitOp.class).call(); insert(points1_modified); insert(lines1); geogig.command(AddOp.class).setUpdateOnly(true).call(); List<DiffEntry> unstaged = toList(repo.workingTree().getUnstaged(null)); assertEquals(2, unstaged.size()); assertEquals(linesName, unstaged.get(0).newName()); assertEquals(lines1.getIdentifier().getID(), unstaged.get(1).newName()); } @Test public void testAddUpdateWithPathFilter() throws Exception { insertAndAdd(points1); geogig.command(CommitOp.class).call(); insert(points1_modified); insert(lines1); // stage only Lines changed geogig.command(AddOp.class).setUpdateOnly(true).addPattern(pointsName).call(); List<DiffEntry> staged = toList(repo.index().getStaged(null)); assertEquals(2, staged.size()); assertEquals(pointsName, staged.get(0).newName()); assertEquals(idP1, staged.get(1).newName()); List<DiffEntry> unstaged = toList(repo.workingTree().getUnstaged(null)); assertEquals(2, unstaged.size()); assertEquals(linesName, unstaged.get(0).newName()); assertEquals(idL1, unstaged.get(1).newName()); geogig.command(AddOp.class).setUpdateOnly(true).addPattern("Points").call(); unstaged = toList(repo.workingTree().getUnstaged(null)); assertEquals(2, unstaged.size()); assertEquals(linesName, unstaged.get(0).newName()); assertEquals(idL1, unstaged.get(1).newName()); } @Test public void testInsertionAndAdditionFixesConflict() throws Exception { Feature points1Modified = feature(pointsType, idP1, "StringProp1_2", new Integer(1000), "POINT(1 1)"); Feature points1ModifiedB = feature(pointsType, idP1, "StringProp1_3", new Integer(2000), "POINT(1 1)"); insertAndAdd(points1); geogig.command(CommitOp.class).call(); geogig.command(BranchCreateOp.class).setName("TestBranch").call(); insertAndAdd(points1Modified); geogig.command(CommitOp.class).call(); geogig.command(CheckoutOp.class).setSource("TestBranch").call(); insertAndAdd(points1ModifiedB); insertAndAdd(points2); geogig.command(CommitOp.class).call(); geogig.command(CheckoutOp.class).setSource("master").call(); Ref branch = geogig.command(RefParse.class).setName("TestBranch").call().get(); try { geogig.command(MergeOp.class).addCommit(Suppliers.ofInstance(branch.getObjectId())) .call(); fail(); } catch (MergeConflictsException e) { assertTrue(e.getMessage().contains("conflict")); } insert(points1); geogig.command(AddOp.class).call(); List<Conflict> conflicts = geogig.getRepository().stagingDatabase() .getConflicts(null, null); assertTrue(conflicts.isEmpty()); geogig.command(CommitOp.class).call(); Optional<Ref> ref = geogig.command(RefParse.class).setName(Ref.MERGE_HEAD).call(); assertFalse(ref.isPresent()); } @Test public void testAdditionFixesConflict() throws Exception { Feature points1Modified = feature(pointsType, idP1, "StringProp1_2", new Integer(1000), "POINT(1 1)"); Feature points1ModifiedB = feature(pointsType, idP1, "StringProp1_3", new Integer(2000), "POINT(1 1)"); insertAndAdd(points1); geogig.command(CommitOp.class).call(); geogig.command(BranchCreateOp.class).setName("TestBranch").call(); insertAndAdd(points1Modified); geogig.command(CommitOp.class).call(); geogig.command(CheckoutOp.class).setSource("TestBranch").call(); insertAndAdd(points1ModifiedB); insertAndAdd(points2); geogig.command(CommitOp.class).call(); geogig.command(CheckoutOp.class).setSource("master").call(); Ref branch = geogig.command(RefParse.class).setName("TestBranch").call().get(); try { geogig.command(MergeOp.class).addCommit(Suppliers.ofInstance(branch.getObjectId())) .call(); fail(); } catch (MergeConflictsException e) { assertTrue(true); } geogig.command(AddOp.class).call(); List<Conflict> conflicts = geogig.getRepository().stagingDatabase() .getConflicts(null, null); assertTrue(conflicts.isEmpty()); geogig.command(CommitOp.class).call(); Optional<Ref> ref = geogig.command(RefParse.class).setName(Ref.MERGE_HEAD).call(); assertFalse(ref.isPresent()); } @Test public void testAddModifiedFeatureType() throws Exception { insertAndAdd(points2, points1B); geogig.command(CommitOp.class).call(); geogig.getRepository().workingTree().updateTypeTree(pointsName, modifiedPointsType); geogig.command(AddOp.class).call(); List<DiffEntry> list = toList(geogig.getRepository().index().getStaged(null)); assertFalse(list.isEmpty()); String path = NodeRef.appendChild(pointsName, idP1); Optional<NodeRef> ref = geogig.command(FindTreeChild.class).setChildPath(path) .setIndex(true).setParent(geogig.getRepository().index().getTree()).call(); assertTrue(ref.isPresent()); assertFalse(ref.get().getNode().getMetadataId().isPresent()); path = NodeRef.appendChild(pointsName, idP2); ref = geogig.command(FindTreeChild.class).setChildPath(path).setIndex(true) .setParent(geogig.getRepository().index().getTree()).call(); assertTrue(ref.isPresent()); assertTrue(ref.get().getNode().getMetadataId().isPresent()); } }