/* 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 static com.google.common.base.Preconditions.checkState; import java.util.List; import javax.annotation.Nullable; import org.locationtech.geogig.api.AbstractGeoGigOp; import org.locationtech.geogig.api.ObjectId; import org.locationtech.geogig.api.RevTree; import org.locationtech.geogig.api.plumbing.diff.DiffCountConsumer; import org.locationtech.geogig.api.plumbing.diff.DiffObjectCount; import org.locationtech.geogig.api.plumbing.diff.PreOrderDiffWalk; import org.locationtech.geogig.api.plumbing.diff.PathFilteringDiffConsumer; import org.locationtech.geogig.storage.StagingDatabase; import com.google.common.base.Optional; import com.google.common.collect.Lists; /** * Counts differences between two trees. * * @see DiffCountConsumer */ public class DiffCount extends AbstractGeoGigOp<DiffObjectCount> { private final List<String> pathFilters = Lists.newLinkedList(); private String oldRefSpec; private String newRefSpec; public DiffCount setOldVersion(@Nullable String refSpec) { this.oldRefSpec = refSpec; return this; } public DiffCount setNewVersion(@Nullable String refSpec) { this.newRefSpec = refSpec; return this; } /** * @param path the path filter to use during the diff operation * @return {@code this} */ public DiffCount addFilter(@Nullable String path) { if (path != null) { pathFilters.add(path); } return this; } /** * @param paths list of paths to filter by, if {@code null} or empty, then no filtering is done, * otherwise the list must not contain null elements. */ public DiffCount setFilter(@Nullable List<String> paths) { pathFilters.clear(); if (paths != null) { pathFilters.addAll(paths); } return this; } @Override protected DiffObjectCount _call() { checkState(oldRefSpec != null, "old ref spec not provided"); checkState(newRefSpec != null, "new ref spec not provided"); final RevTree oldTree = getTree(oldRefSpec); final RevTree newTree = getTree(newRefSpec); DiffObjectCount diffCount; StagingDatabase index = stagingDatabase(); PreOrderDiffWalk visitor = new PreOrderDiffWalk(oldTree, newTree, index, index); DiffCountConsumer counter = new DiffCountConsumer(index); PreOrderDiffWalk.Consumer filter = counter; if (!pathFilters.isEmpty()) { filter = new PathFilteringDiffConsumer(pathFilters, counter); } visitor.walk(filter); diffCount = counter.get(); return diffCount; } /** * @return the tree referenced by the old ref, or the head of the index. */ private RevTree getTree(String refSpec) { final RevTree headTree; Optional<ObjectId> resolved = command(ResolveTreeish.class).setTreeish(refSpec).call(); if (resolved.isPresent()) { ObjectId headTreeId = resolved.get(); headTree = command(RevObjectParse.class).setObjectId(headTreeId).call(RevTree.class) .get(); } else { headTree = RevTree.EMPTY; } return headTree; } }