Search in sources :

Example 11 with ProgressListener

use of org.locationtech.geogig.api.ProgressListener in project GeoGig by boundlessgeo.

the class MergeOp method _call.

/**
     * Executes the merge operation.
     * 
     * @return always {@code true}
     */
@Override
protected MergeReport _call() throws RuntimeException {
    Preconditions.checkArgument(commits.size() > 0, "No commits specified for merge.");
    Preconditions.checkArgument(!(ours && theirs), "Cannot use both --ours and --theirs.");
    final Optional<Ref> currHead = command(RefParse.class).setName(Ref.HEAD).call();
    Preconditions.checkState(currHead.isPresent(), "Repository has no HEAD, can't rebase.");
    Ref headRef = currHead.get();
    ObjectId oursId = headRef.getObjectId();
    // Preconditions.checkState(currHead.get() instanceof SymRef,
    // "Can't rebase from detached HEAD");
    // SymRef headRef = (SymRef) currHead.get();
    // final String currentBranch = headRef.getTarget();
    getProgressListener().started();
    boolean fastForward = true;
    boolean changed = false;
    Optional<MergeScenarioReport> mergeScenario = Optional.absent();
    List<CommitAncestorPair> pairs = Lists.newArrayList();
    boolean hasConflictsOrAutomerge;
    List<RevCommit> revCommits = Lists.newArrayList();
    if (!ObjectId.NULL.equals(headRef.getObjectId())) {
        revCommits.add(repository().getCommit(headRef.getObjectId()));
    }
    for (ObjectId commitId : commits) {
        revCommits.add(repository().getCommit(commitId));
    }
    hasConflictsOrAutomerge = command(CheckMergeScenarioOp.class).setCommits(revCommits).call().booleanValue();
    if (hasConflictsOrAutomerge && !theirs) {
        Preconditions.checkState(commits.size() < 2, "Conflicted merge.\nCannot merge more than two commits when conflicts exist" + " or features have been modified in several histories");
        RevCommit headCommit = repository().getCommit(headRef.getObjectId());
        ObjectId commitId = commits.get(0);
        Preconditions.checkArgument(!ObjectId.NULL.equals(commitId), "Cannot merge a NULL commit.");
        Preconditions.checkArgument(repository().commitExists(commitId), "Not a valid commit: " + commitId.toString());
        final RevCommit targetCommit = repository().getCommit(commitId);
        Optional<ObjectId> ancestorCommit = command(FindCommonAncestor.class).setLeft(headCommit).setRight(targetCommit).call();
        pairs.add(new CommitAncestorPair(commitId, ancestorCommit.get()));
        mergeScenario = Optional.of(command(ReportMergeScenarioOp.class).setMergeIntoCommit(headCommit).setToMergeCommit(targetCommit).call());
        List<FeatureInfo> merged = mergeScenario.get().getMerged();
        for (FeatureInfo feature : merged) {
            this.workingTree().insert(NodeRef.parentPath(feature.getPath()), feature.getFeature());
            Iterator<DiffEntry> unstaged = workingTree().getUnstaged(null);
            index().stage(getProgressListener(), unstaged, 0);
            changed = true;
            fastForward = false;
        }
        List<DiffEntry> unconflicting = mergeScenario.get().getUnconflicted();
        if (!unconflicting.isEmpty()) {
            index().stage(getProgressListener(), unconflicting.iterator(), 0);
            changed = true;
            fastForward = false;
        }
        workingTree().updateWorkHead(index().getTree().getId());
        List<Conflict> conflicts = mergeScenario.get().getConflicts();
        if (!ours && !conflicts.isEmpty()) {
            // In case we use the "ours" strategy, we do nothing. We ignore conflicting
            // changes and leave the current elements
            command(UpdateRef.class).setName(Ref.MERGE_HEAD).setNewValue(commitId).call();
            command(UpdateRef.class).setName(Ref.ORIG_HEAD).setNewValue(headCommit.getId()).call();
            command(ConflictsWriteOp.class).setConflicts(conflicts).call();
            StringBuilder msg = new StringBuilder();
            Optional<Ref> ref = command(ResolveBranchId.class).setObjectId(commitId).call();
            if (ref.isPresent()) {
                msg.append("Merge branch " + ref.get().getName());
            } else {
                msg.append("Merge commit '" + commitId.toString() + "'. ");
            }
            msg.append("\n\nConflicts:\n");
            for (Conflict conflict : mergeScenario.get().getConflicts()) {
                msg.append("\t" + conflict.getPath() + "\n");
            }
            command(SaveMergeCommitMessageOp.class).setMessage(msg.toString()).call();
            StringBuilder sb = new StringBuilder();
            for (Conflict conflict : conflicts) {
                sb.append("CONFLICT: Merge conflict in " + conflict.getPath() + "\n");
            }
            sb.append("Automatic merge failed. Fix conflicts and then commit the result.\n");
            throw new MergeConflictsException(sb.toString(), headCommit.getId(), commitId);
        }
    } else {
        Preconditions.checkState(!hasConflictsOrAutomerge || commits.size() < 2, "Conflicted merge.\nCannot merge more than two commits when conflicts exist" + " or features have been modified in several histories");
        for (ObjectId commitId : commits) {
            ProgressListener subProgress = subProgress(100.f / commits.size());
            Preconditions.checkArgument(!ObjectId.NULL.equals(commitId), "Cannot merge a NULL commit.");
            Preconditions.checkArgument(repository().commitExists(commitId), "Not a valid commit: " + commitId.toString());
            subProgress.started();
            if (ObjectId.NULL.equals(headRef.getObjectId())) {
                // Fast-forward
                if (headRef instanceof SymRef) {
                    final String currentBranch = ((SymRef) headRef).getTarget();
                    command(UpdateRef.class).setName(currentBranch).setNewValue(commitId).call();
                    headRef = (SymRef) command(UpdateSymRef.class).setName(Ref.HEAD).setNewValue(currentBranch).call().get();
                } else {
                    headRef = command(UpdateRef.class).setName(headRef.getName()).setNewValue(commitId).call().get();
                }
                workingTree().updateWorkHead(commitId);
                index().updateStageHead(commitId);
                subProgress.complete();
                changed = true;
                continue;
            }
            RevCommit headCommit = repository().getCommit(headRef.getObjectId());
            final RevCommit targetCommit = repository().getCommit(commitId);
            Optional<ObjectId> ancestorCommit = command(FindCommonAncestor.class).setLeft(headCommit).setRight(targetCommit).call();
            pairs.add(new CommitAncestorPair(commitId, ancestorCommit.get()));
            subProgress.setProgress(10.f);
            Preconditions.checkState(ancestorCommit.isPresent(), "No ancestor commit could be found.");
            if (commits.size() == 1) {
                mergeScenario = Optional.of(command(ReportMergeScenarioOp.class).setMergeIntoCommit(headCommit).setToMergeCommit(targetCommit).call());
                if (ancestorCommit.get().equals(headCommit.getId())) {
                    // Fast-forward
                    if (headRef instanceof SymRef) {
                        final String currentBranch = ((SymRef) headRef).getTarget();
                        command(UpdateRef.class).setName(currentBranch).setNewValue(commitId).call();
                        headRef = (SymRef) command(UpdateSymRef.class).setName(Ref.HEAD).setNewValue(currentBranch).call().get();
                    } else {
                        headRef = command(UpdateRef.class).setName(headRef.getName()).setNewValue(commitId).call().get();
                    }
                    workingTree().updateWorkHead(commitId);
                    index().updateStageHead(commitId);
                    subProgress.complete();
                    changed = true;
                    continue;
                } else if (ancestorCommit.get().equals(commitId)) {
                    continue;
                }
            }
            // get changes
            Iterator<DiffEntry> diff = command(DiffTree.class).setOldTree(ancestorCommit.get()).setNewTree(targetCommit.getId()).setReportTrees(true).call();
            // stage changes
            index().stage(new SubProgressListener(subProgress, 100.f), diff, 0);
            changed = true;
            fastForward = false;
            workingTree().updateWorkHead(index().getTree().getId());
            subProgress.complete();
        }
    }
    if (!changed) {
        throw new NothingToCommitException("The branch has already been merged.");
    }
    RevCommit mergeCommit = commit(fastForward);
    MergeReport result = new MergeReport(mergeCommit, mergeScenario, oursId, pairs);
    return result;
}
Also used : ReportMergeScenarioOp(org.locationtech.geogig.api.plumbing.merge.ReportMergeScenarioOp) SubProgressListener(org.locationtech.geogig.api.SubProgressListener) FeatureInfo(org.locationtech.geogig.api.FeatureInfo) MergeScenarioReport(org.locationtech.geogig.api.plumbing.merge.MergeScenarioReport) UpdateSymRef(org.locationtech.geogig.api.plumbing.UpdateSymRef) SymRef(org.locationtech.geogig.api.SymRef) RevCommit(org.locationtech.geogig.api.RevCommit) DiffEntry(org.locationtech.geogig.api.plumbing.diff.DiffEntry) ObjectId(org.locationtech.geogig.api.ObjectId) UpdateRef(org.locationtech.geogig.api.plumbing.UpdateRef) UpdateRef(org.locationtech.geogig.api.plumbing.UpdateRef) UpdateSymRef(org.locationtech.geogig.api.plumbing.UpdateSymRef) Ref(org.locationtech.geogig.api.Ref) SymRef(org.locationtech.geogig.api.SymRef) NodeRef(org.locationtech.geogig.api.NodeRef) ProgressListener(org.locationtech.geogig.api.ProgressListener) SubProgressListener(org.locationtech.geogig.api.SubProgressListener) Conflict(org.locationtech.geogig.api.plumbing.merge.Conflict) FindCommonAncestor(org.locationtech.geogig.api.plumbing.FindCommonAncestor)

Example 12 with ProgressListener

use of org.locationtech.geogig.api.ProgressListener in project GeoGig by boundlessgeo.

the class WriteTree2 method _call.

/**
     * Executes the write tree operation.
     * 
     * @return the new root tree id, the current HEAD tree id if there are no differences between
     *         the index and the HEAD, or {@code null} if the operation has been cancelled (as
     *         indicated by the {@link #getProgressListener() progress listener}.
     */
@Override
protected ObjectId _call() {
    final ProgressListener progress = getProgressListener();
    TreeDifference treeDifference = computeTreeDifference();
    if (treeDifference.areEqual()) {
        MutableTree leftTree = treeDifference.getLeftTree();
        Node leftNode = leftTree.getNode();
        ObjectId leftOid = leftNode.getObjectId();
        return leftOid;
    }
    final MutableTree oldLeftTree = treeDifference.getLeftTree().clone();
    Preconditions.checkState(oldLeftTree.equals(treeDifference.getLeftTree()));
    // handle renames before new and deleted trees for the computation of new and deleted to be
    // accurate
    Set<String> ignoreList = Sets.newHashSet();
    handleRenames(treeDifference, ignoreList);
    handlePureMetadataChanges(treeDifference, ignoreList);
    handleNewTrees(treeDifference, ignoreList);
    handleDeletedTrees(treeDifference, ignoreList);
    handleRemainingDifferences(treeDifference, ignoreList);
    progress.complete();
    MutableTree newLeftTree = treeDifference.getLeftTree();
    final ObjectDatabase repositoryDatabase = objectDatabase();
    final RevTree newRoot = newLeftTree.build(stagingDatabase(), repositoryDatabase);
    if (newRoot.trees().isPresent()) {
        for (Node n : newRoot.trees().get()) {
            if (n.getMetadataId().isPresent())
                deepMove(n.getMetadataId().get());
        }
    }
    ObjectId newRootId = newRoot.getId();
    return newRootId;
}
Also used : MutableTree(org.locationtech.geogig.api.plumbing.diff.MutableTree) ProgressListener(org.locationtech.geogig.api.ProgressListener) ObjectId(org.locationtech.geogig.api.ObjectId) ObjectDatabase(org.locationtech.geogig.storage.ObjectDatabase) Node(org.locationtech.geogig.api.Node) TreeDifference(org.locationtech.geogig.api.plumbing.diff.TreeDifference) RevTree(org.locationtech.geogig.api.RevTree)

Example 13 with ProgressListener

use of org.locationtech.geogig.api.ProgressListener in project GeoGig by boundlessgeo.

the class CommitOpTest method testCancel.

@Test
public void testCancel() throws Exception {
    ProgressListener listener1 = mock(ProgressListener.class);
    when(listener1.isCanceled()).thenReturn(true);
    ProgressListener listener2 = mock(ProgressListener.class);
    when(listener2.isCanceled()).thenReturn(false, true);
    ProgressListener listener3 = mock(ProgressListener.class);
    when(listener3.isCanceled()).thenReturn(false, false, true);
    try {
        geogig.command(AddOp.class).addPattern(".").call();
        geogig.command(CommitOp.class).call();
        fail("expected NothingToCommitException");
    } catch (NothingToCommitException e) {
        assertTrue(true);
    }
    CommitOp commitCommand1 = geogig.command(CommitOp.class);
    commitCommand1.setProgressListener(listener1);
    assertNull(commitCommand1.setAllowEmpty(true).call());
    CommitOp commitCommand2 = geogig.command(CommitOp.class);
    commitCommand2.setProgressListener(listener2);
    assertNull(commitCommand2.setAllowEmpty(true).call());
    CommitOp commitCommand3 = geogig.command(CommitOp.class);
    commitCommand3.setProgressListener(listener3);
    assertNull(commitCommand3.setAllowEmpty(true).call());
}
Also used : ProgressListener(org.locationtech.geogig.api.ProgressListener) NothingToCommitException(org.locationtech.geogig.api.porcelain.NothingToCommitException) CommitOp(org.locationtech.geogig.api.porcelain.CommitOp) Test(org.junit.Test)

Example 14 with ProgressListener

use of org.locationtech.geogig.api.ProgressListener in project GeoGig by boundlessgeo.

the class OSMImportOp method parseDataFileAndInsert.

private OSMReport parseDataFileAndInsert(@Nullable File file, final InputStream dataIn, final EntityConverter converter) {
    final boolean pbf;
    final CompressionMethod compression;
    if (file == null) {
        pbf = false;
        compression = CompressionMethod.None;
    } else {
        pbf = file.getName().endsWith(".pbf");
        compression = resolveCompressionMethod(file);
    }
    RunnableSource reader;
    if (pbf) {
        reader = new OsmosisReader(dataIn);
    } else {
        reader = new org.locationtech.geogig.osm.internal.XmlReader(dataIn, true, compression);
    }
    final WorkingTree workTree = workingTree();
    if (!add) {
        workTree.delete(OSMUtils.NODE_TYPE_NAME);
        workTree.delete(OSMUtils.WAY_TYPE_NAME);
    }
    final int queueCapacity = 100 * 1000;
    final int timeout = 1;
    final TimeUnit timeoutUnit = TimeUnit.SECONDS;
    // With this iterator and the osm parsing happening on a separate thread, we follow a
    // producer/consumer approach so that the osm parse thread produces featrures into the
    // iterator's queue, and WorkingTree.insert consumes them on this thread
    QueueIterator<Feature> iterator = new QueueIterator<Feature>(queueCapacity, timeout, timeoutUnit);
    ProgressListener progressListener = getProgressListener();
    ConvertAndImportSink sink = new ConvertAndImportSink(converter, iterator, platform(), mapping, noRaw, new SubProgressListener(progressListener, 100));
    reader.setSink(sink);
    Thread readerThread = new Thread(reader, "osm-import-reader-thread");
    readerThread.start();
    Function<Feature, String> parentTreePathResolver = new Function<Feature, String>() {

        @Override
        public String apply(Feature input) {
            if (input instanceof MappedFeature) {
                return ((MappedFeature) input).getPath();
            }
            return input.getType().getName().getLocalPart();
        }
    };
    // used to set the task status name, but report no progress so it does not interfere
    // with the progress reported by the reader thread
    SubProgressListener noPorgressReportingListener = new SubProgressListener(progressListener, 0) {

        @Override
        public void setProgress(float progress) {
        // no-op
        }
    };
    workTree.insert(parentTreePathResolver, iterator, noPorgressReportingListener, null, null);
    if (sink.getCount() == 0) {
        throw new EmptyOSMDownloadException();
    }
    OSMReport report = new OSMReport(sink.getCount(), sink.getNodeCount(), sink.getWayCount(), sink.getUnprocessedCount(), sink.getLatestChangeset(), sink.getLatestTimestamp());
    return report;
}
Also used : SubProgressListener(org.locationtech.geogig.api.SubProgressListener) LineString(com.vividsolutions.jts.geom.LineString) Feature(org.opengis.feature.Feature) RunnableSource(org.openstreetmap.osmosis.core.task.v0_6.RunnableSource) Point(com.vividsolutions.jts.geom.Point) WorkingTree(org.locationtech.geogig.repository.WorkingTree) Function(com.google.common.base.Function) ProgressListener(org.locationtech.geogig.api.ProgressListener) SubProgressListener(org.locationtech.geogig.api.SubProgressListener) CompressionMethod(org.openstreetmap.osmosis.xml.common.CompressionMethod) TimeUnit(java.util.concurrent.TimeUnit) OsmosisReader(crosby.binary.osmosis.OsmosisReader)

Example 15 with ProgressListener

use of org.locationtech.geogig.api.ProgressListener in project GeoGig by boundlessgeo.

the class OSMHistoryImport method commit.

/**
     * @param cli
     * @param changeset
     * @throws IOException
     */
private void commit(GeogigCLI cli, Changeset changeset) throws IOException {
    Preconditions.checkArgument(!changeset.isOpen());
    ConsoleReader console = cli.getConsole();
    console.print("Committing changeset " + changeset.getId() + "...");
    console.flush();
    GeoGIG geogig = cli.getGeogig();
    CommitOp command = geogig.command(CommitOp.class);
    command.setAllowEmpty(true);
    String message = "";
    if (changeset.getComment().isPresent()) {
        message = changeset.getComment().get() + "\nchangeset " + changeset.getId();
    } else {
        message = "changeset " + changeset.getId();
    }
    command.setMessage(message);
    final String userName = changeset.getUserName();
    command.setAuthor(userName, null);
    command.setAuthorTimestamp(changeset.getCreated());
    // osm timestamps are in GMT
    command.setAuthorTimeZoneOffset(0);
    if (userName != null) {
        command.setCommitter(userName, null);
    }
    command.setCommitterTimestamp(changeset.getClosed().get());
    // osm timestamps are in GMT
    command.setCommitterTimeZoneOffset(0);
    ProgressListener listener = cli.getProgressListener();
    listener.setProgress(0f);
    listener.started();
    command.setProgressListener(listener);
    try {
        RevCommit commit = command.call();
        Ref head = geogig.command(RefParse.class).setName(Ref.HEAD).call().get();
        Preconditions.checkState(commit.getId().equals(head.getObjectId()));
        updateBranchChangeset(geogig, changeset.getId());
        listener.complete();
        console.println("Commit " + commit.getId().toString());
        console.flush();
    } catch (Exception e) {
        throw Throwables.propagate(e);
    }
}
Also used : Ref(org.locationtech.geogig.api.Ref) SymRef(org.locationtech.geogig.api.SymRef) NodeRef(org.locationtech.geogig.api.NodeRef) ConsoleReader(jline.console.ConsoleReader) ProgressListener(org.locationtech.geogig.api.ProgressListener) DefaultProgressListener(org.locationtech.geogig.api.DefaultProgressListener) RefParse(org.locationtech.geogig.api.plumbing.RefParse) CommitOp(org.locationtech.geogig.api.porcelain.CommitOp) GeoGIG(org.locationtech.geogig.api.GeoGIG) URISyntaxException(java.net.URISyntaxException) InvalidParameterException(org.locationtech.geogig.cli.InvalidParameterException) CommandFailedException(org.locationtech.geogig.cli.CommandFailedException) IOException(java.io.IOException) RevCommit(org.locationtech.geogig.api.RevCommit)

Aggregations

ProgressListener (org.locationtech.geogig.api.ProgressListener)25 IOException (java.io.IOException)9 CommandFailedException (org.locationtech.geogig.cli.CommandFailedException)7 DataStore (org.geotools.data.DataStore)6 ObjectId (org.locationtech.geogig.api.ObjectId)6 SubProgressListener (org.locationtech.geogig.api.SubProgressListener)6 GeoToolsOpException (org.locationtech.geogig.geotools.plumbing.GeoToolsOpException)6 WorkingTree (org.locationtech.geogig.repository.WorkingTree)6 SimpleFeature (org.opengis.feature.simple.SimpleFeature)6 DefaultProgressListener (org.locationtech.geogig.api.DefaultProgressListener)5 NodeRef (org.locationtech.geogig.api.NodeRef)5 Function (com.google.common.base.Function)4 Ref (org.locationtech.geogig.api.Ref)4 RevTree (org.locationtech.geogig.api.RevTree)4 SymRef (org.locationtech.geogig.api.SymRef)4 Feature (org.opengis.feature.Feature)4 SimpleFeatureType (org.opengis.feature.simple.SimpleFeatureType)4 Point (com.vividsolutions.jts.geom.Point)3 Node (org.locationtech.geogig.api.Node)3 RevFeature (org.locationtech.geogig.api.RevFeature)3