use of org.locationtech.geogig.api.SubProgressListener 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;
}
use of org.locationtech.geogig.api.SubProgressListener 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;
}
use of org.locationtech.geogig.api.SubProgressListener in project GeoGig by boundlessgeo.
the class OSMApplyDiffOp method parseDiffFileAndInsert.
public OSMReport parseDiffFileAndInsert() {
final WorkingTree workTree = workingTree();
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 features into the
// iterator's queue, and WorkingTree.insert consumes them on this thread
QueueIterator<Feature> target = new QueueIterator<Feature>(queueCapacity, timeout, timeoutUnit);
XmlChangeReader reader = new XmlChangeReader(file, true, resolveCompressionMethod(file));
ProgressListener progressListener = getProgressListener();
ConvertAndImportSink sink = new ConvertAndImportSink(target, context, workingTree(), platform(), new SubProgressListener(progressListener, 100));
reader.setChangeSink(sink);
Thread readerThread = new Thread(reader, "osm-diff-reader-thread");
readerThread.start();
// 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 noProgressReportingListener = new SubProgressListener(progressListener, 0) {
@Override
public void setProgress(float progress) {
// no-op
}
};
Function<Feature, String> parentTreePathResolver = new Function<Feature, String>() {
@Override
public String apply(Feature input) {
return input.getType().getName().getLocalPart();
}
};
workTree.insert(parentTreePathResolver, target, noProgressReportingListener, null, null);
OSMReport report = new OSMReport(sink.getCount(), sink.getNodeCount(), sink.getWayCount(), sink.getUnprocessedCount(), sink.getLatestChangeset(), sink.getLatestTimestamp());
return report;
}
Aggregations