/* 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.plumbing; 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.Ref; import org.locationtech.geogig.api.RevTree; import org.locationtech.geogig.api.plumbing.diff.DiffEntry; import org.locationtech.geogig.repository.StagingArea; import org.locationtech.geogig.repository.WorkingTree; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.base.Supplier; import com.google.common.collect.ImmutableList; /** * Compares the features in the {@link WorkingTree working tree} and the {@link StagingArea index} * or a given root tree-ish. */ public class DiffWorkTree extends AbstractGeoGigOp<Iterator<DiffEntry>> implements Supplier<Iterator<DiffEntry>> { private String pathFilter; private String refSpec; private boolean reportTrees; /** * @param refSpec the name of the root tree object in the to compare the working tree against. * If {@code null} or not specified, defaults to the current state of the index. * @return {@code this} */ public DiffWorkTree setOldVersion(@Nullable String refSpec) { this.refSpec = refSpec; return this; } /** * @param path the path filter to use during the diff operation * @return {@code this} */ public DiffWorkTree setFilter(@Nullable String path) { pathFilter = path; return this; } /** * If no {@link #setOldVersion(String) old version} was set, returns the differences between the * working tree and the index, otherwise the differences between the working tree and the * specified revision. * * @return an iterator to a set of differences between the two trees * @see DiffEntry */ @Override protected Iterator<DiffEntry> _call() { final Optional<String> ref = Optional.fromNullable(refSpec); final RevTree oldTree = ref.isPresent() ? getOldTree() : index().getTree(); final RevTree newTree = workingTree().getTree(); DiffTree diff = command(DiffTree.class).setReportTrees(this.reportTrees) .setOldTree(oldTree.getId()).setNewTree(newTree.getId()); if (this.pathFilter != null) { diff.setPathFilter(ImmutableList.of(pathFilter)); } return diff.call(); } /** * @return the tree referenced by the old ref, or the head of the index. */ private RevTree getOldTree() { final String oldVersion = Optional.fromNullable(refSpec).or(Ref.STAGE_HEAD); Optional<ObjectId> headTreeId = command(ResolveTreeish.class).setTreeish(oldVersion).call(); Preconditions.checkArgument(headTreeId.isPresent(), "Refspec " + oldVersion + " does not resolve to a tree"); final RevTree headTree; headTree = command(RevObjectParse.class).setObjectId(headTreeId.get()).call(RevTree.class) .get(); return headTree; } /** * @param reportTrees * @return */ public DiffWorkTree setReportTrees(boolean reportTrees) { this.reportTrees = reportTrees; return this; } /** * Implements {@link Supplier#get()} by deferring to {@link #call()} * * @see #call() */ @Override public Iterator<DiffEntry> get() { return call(); } }