/* 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: * Gabriel Roldan (Boundless) - initial implementation */ package org.locationtech.geogig.api.porcelain; import static com.google.common.base.Preconditions.checkArgument; import java.util.Iterator; import javax.annotation.Nullable; import org.locationtech.geogig.api.AbstractGeoGigOp; import org.locationtech.geogig.api.ObjectId; import org.locationtech.geogig.api.plumbing.DiffIndex; import org.locationtech.geogig.api.plumbing.DiffTree; import org.locationtech.geogig.api.plumbing.DiffWorkTree; import org.locationtech.geogig.api.plumbing.diff.DiffEntry; import org.locationtech.geogig.di.CanRunDuringConflict; /** * Perform a diff between trees pointed out by two commits * <p> * Usage: * <ul> * <li> * <code>{@link #setOldVersion(String) oldVersion} == null && {@link #setNewVersion(String) newVersion} == null</code> * : compare working tree and index * <li> * <code>{@link #setOldVersion(String) oldVersion} != null && {@link #setNewVersion(String) newVersion} == null</code> * : compare the working tree with the given commit * <li> * <code>{@link #setCompareIndex(boolean) compareIndex} == true && {@link #setOldVersion(String) oldVersion} == null && {@link #setNewVersion(String) newVersion} == null</code> * : compare the index with the HEAD commit * <li> * <code>{@link #setCompareIndex(boolean) compareIndex} == true && {@link #setOldVersion(String) oldVersion} != null && {@link #setNewVersion(String) newVersion} == null</code> * : compare the index with the given commit * <li> * <code>{@link #setOldVersion(String) oldVersion} != null && {@link #setNewVersion(String) newVersion} != null</code> * : compare {@code commit1} with {@code commit2}, where {@code commit1} is the eldest or left side * of the diff. * </ul> * * @see DiffWorkTree * @see DiffIndex * @see DiffTree */ @CanRunDuringConflict public class DiffOp extends AbstractGeoGigOp<Iterator<DiffEntry>> implements Iterable<DiffEntry> { private String oldRefSpec; private String newRefSpec; private String pathFilter; private boolean cached; private boolean reportTrees; /** * @param compareIndex if true, the index will be used in the comparison */ public DiffOp setCompareIndex(boolean compareIndex) { this.cached = compareIndex; return this; } /** * @param revObjectSpec the old version to compare against * @return {@code this} */ public DiffOp setOldVersion(@Nullable String revObjectSpec) { this.oldRefSpec = revObjectSpec; return this; } /** * @param treeishOid the old {@link ObjectId} to compare against * @return {@code this} */ public DiffOp setOldVersion(ObjectId treeishOid) { return setOldVersion(treeishOid.toString()); } /** * @param revObjectSpec the new version to compare against * @return {@code this} */ public DiffOp setNewVersion(String revObjectSpec) { this.newRefSpec = revObjectSpec; return this; } /** * @param treeishOid the new {@link ObjectId} to compare against * @return {@code this} */ public DiffOp setNewVersion(ObjectId treeishOid) { return setNewVersion(treeishOid.toString()); } /** * @param pathFilter * @return {@code this} */ public DiffOp setFilter(String pathFilter) { this.pathFilter = pathFilter; return this; } /** * Executes the diff operation. * * @return an iterator to a set of differences between the two trees * @see DiffEntry */ @Override protected Iterator<DiffEntry> _call() { checkArgument(cached && oldRefSpec == null || !cached, String.format( "compare index allows only one revision to check against, got %s / %s", oldRefSpec, newRefSpec)); checkArgument(newRefSpec == null || oldRefSpec != null, "If new rev spec is specified then old rev spec is mandatory"); Iterator<DiffEntry> iterator; if (cached) { // compare the tree-ish (default to HEAD) and the index DiffIndex diffIndex = command(DiffIndex.class).addFilter(this.pathFilter) .setReportTrees(reportTrees); if (oldRefSpec != null) { diffIndex.setOldVersion(oldRefSpec); } iterator = diffIndex.call(); } else if (newRefSpec == null) { DiffWorkTree workTreeIndexDiff = command(DiffWorkTree.class).setFilter(pathFilter) .setReportTrees(reportTrees); if (oldRefSpec != null) { workTreeIndexDiff.setOldVersion(oldRefSpec); } iterator = workTreeIndexDiff.call(); } else { iterator = command(DiffTree.class).setOldVersion(oldRefSpec).setNewVersion(newRefSpec) .setPathFilter(pathFilter).setReportTrees(reportTrees).call(); } return iterator; } /** * @param b * @return */ public DiffOp setReportTrees(boolean reportTrees) { this.reportTrees = reportTrees; return this; } @Override public Iterator<DiffEntry> iterator() { return call(); } }