/* * Copyright (C) 2010, Garmin International * Copyright (C) 2010, Matt Fischer and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at * https://www.eclipse.org/org/documents/edl-v10.php. * * SPDX-License-Identifier: BSD-3-Clause */ package org.eclipse.jgit.revwalk; import java.io.IOException; import java.util.Collections; import java.util.List; import java.util.Objects; import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.lib.Repository; /** * Interface for revision walkers that perform depth filtering. */ public interface DepthWalk { /** * Get depth to filter to. * * @return Depth to filter to. */ int getDepth(); /** * Get deepen-since value * * @return the deepen-since value; if not 0, this walk only returns commits * whose commit time is at or after this limit * @since 5.2 */ default int getDeepenSince() { return 0; } /** * Get deepen-not values * * @return the objects specified by the client using --shallow-exclude * @since 5.2 */ default List getDeepenNots() { return Collections.emptyList(); } /** * Get unshallow flag * * @return flag marking commits that should become unshallow. */ /** * Get flag marking commits that should become unshallow. * * @return flag marking commits that should become unshallow. */ RevFlag getUnshallowFlag(); /** * Get flag marking commits that are interesting again. * * @return flag marking commits that are interesting again. */ RevFlag getReinterestingFlag(); /** * Get deepen-not flag * * @return flag marking commits that are to be excluded because of * --shallow-exclude * @since 5.2 */ RevFlag getDeepenNotFlag(); /** RevCommit with a depth (in commits) from a root. */ public static class Commit extends RevCommit { /** Depth of this commit in the graph, via shortest path. */ int depth; boolean isBoundary; /** * True if this commit was excluded due to a shallow fetch * setting. All its children are thus boundary commits. */ boolean makesChildBoundary; /** * Get depth * * @return depth of this commit, as found by the shortest path. */ public int getDepth() { return depth; } /** * Whether at least one commit was excluded due to shallow fetch * * @return true if at least one of this commit's parents was excluded * due to a shallow fetch setting, false otherwise * @since 5.2 */ public boolean isBoundary() { return isBoundary; } /** * Initialize a new commit. * * @param id * object name for the commit. */ protected Commit(AnyObjectId id) { super(id); depth = -1; } } /** Subclass of RevWalk that performs depth filtering. */ public class RevWalk extends org.eclipse.jgit.revwalk.RevWalk implements DepthWalk { private final int depth; private int deepenSince; private List deepenNots; private final RevFlag UNSHALLOW; private final RevFlag REINTERESTING; private final RevFlag DEEPEN_NOT; /** * Create RevWalk * * @param repo * Repository to walk * @param depth * Maximum depth to return */ public RevWalk(Repository repo, int depth) { super(repo); this.depth = depth; this.deepenNots = Collections.emptyList(); this.UNSHALLOW = newFlag("UNSHALLOW"); //$NON-NLS-1$ this.REINTERESTING = newFlag("REINTERESTING"); //$NON-NLS-1$ this.DEEPEN_NOT = newFlag("DEEPEN_NOT"); //$NON-NLS-1$ } /** * Create RevWalk * * @param or * ObjectReader to use * @param depth * Maximum depth to return */ public RevWalk(ObjectReader or, int depth) { super(or); this.depth = depth; this.deepenNots = Collections.emptyList(); this.UNSHALLOW = newFlag("UNSHALLOW"); //$NON-NLS-1$ this.REINTERESTING = newFlag("REINTERESTING"); //$NON-NLS-1$ this.DEEPEN_NOT = newFlag("DEEPEN_NOT"); //$NON-NLS-1$ } /** * Mark a root commit (i.e., one whose depth should be considered 0.) * * @param c * Commit to mark * @throws IOException * if an IO error occurred * @throws IncorrectObjectTypeException * if object has an unexpected type * @throws MissingObjectException * if object is missing */ public void markRoot(RevCommit c) throws MissingObjectException, IncorrectObjectTypeException, IOException { if (c instanceof Commit) ((Commit) c).depth = 0; super.markStart(c); } @Override protected RevCommit createCommit(AnyObjectId id) { return new Commit(id); } @Override public int getDepth() { return depth; } @Override public int getDeepenSince() { return deepenSince; } /** * Sets the deepen-since value. * * @param limit * new deepen-since value * @since 5.2 */ public void setDeepenSince(int limit) { deepenSince = limit; } @Override public List getDeepenNots() { return deepenNots; } /** * Mark objects that the client specified using * --shallow-exclude. Objects that are not commits have no * effect. * * @param deepenNots specified objects * @since 5.2 */ public void setDeepenNots(List deepenNots) { this.deepenNots = Objects.requireNonNull(deepenNots); } @Override public RevFlag getUnshallowFlag() { return UNSHALLOW; } @Override public RevFlag getReinterestingFlag() { return REINTERESTING; } @Override public RevFlag getDeepenNotFlag() { return DEEPEN_NOT; } /** * Convert to ObjectWalk with same objects * * @since 4.5 */ @Override public ObjectWalk toObjectWalkWithSameObjects() { ObjectWalk ow = new ObjectWalk(reader, depth); ow.deepenSince = deepenSince; ow.deepenNots = deepenNots; ow.objects = objects; ow.freeFlags = freeFlags; return ow; } } /** Subclass of ObjectWalk that performs depth filtering. */ public class ObjectWalk extends org.eclipse.jgit.revwalk.ObjectWalk implements DepthWalk { private final int depth; private int deepenSince; private List deepenNots; private final RevFlag UNSHALLOW; private final RevFlag REINTERESTING; private final RevFlag DEEPEN_NOT; /** * Create ObjectWalk * * @param repo * Repository to walk * @param depth * Maximum depth to return */ public ObjectWalk(Repository repo, int depth) { super(repo); this.depth = depth; this.deepenNots = Collections.emptyList(); this.UNSHALLOW = newFlag("UNSHALLOW"); //$NON-NLS-1$ this.REINTERESTING = newFlag("REINTERESTING"); //$NON-NLS-1$ this.DEEPEN_NOT = newFlag("DEEPEN_NOT"); //$NON-NLS-1$ } /** * Create ObjectWalk * * @param or * Object Reader * @param depth * Maximum depth to return */ public ObjectWalk(ObjectReader or, int depth) { super(or); this.depth = depth; this.deepenNots = Collections.emptyList(); this.UNSHALLOW = newFlag("UNSHALLOW"); //$NON-NLS-1$ this.REINTERESTING = newFlag("REINTERESTING"); //$NON-NLS-1$ this.DEEPEN_NOT = newFlag("DEEPEN_NOT"); //$NON-NLS-1$ } /** * Mark a root commit (i.e., one whose depth should be considered 0.) * * @param o * Commit to mark * @throws IOException * if an IO error occurred * @throws IncorrectObjectTypeException * if object has an unexpected type * @throws MissingObjectException * if object is missing */ public void markRoot(RevObject o) throws MissingObjectException, IncorrectObjectTypeException, IOException { RevObject c = o; while (c instanceof RevTag) { c = ((RevTag) c).getObject(); parseHeaders(c); } if (c instanceof Commit) ((Commit) c).depth = 0; super.markStart(o); } /** * Mark an element which used to be shallow in the client, but which * should now be considered a full commit. Any ancestors of this commit * should be included in the walk, even if they are the ancestor of an * uninteresting commit. * * @param c * Commit to mark * @throws MissingObjectException * if object is missing * @throws IncorrectObjectTypeException * if object has an unexpected type * @throws IOException * if an IO error occurred */ public void markUnshallow(RevObject c) throws MissingObjectException, IncorrectObjectTypeException, IOException { if (c instanceof RevCommit) c.add(UNSHALLOW); super.markStart(c); } @Override protected RevCommit createCommit(AnyObjectId id) { return new Commit(id); } @Override public int getDepth() { return depth; } @Override public int getDeepenSince() { return deepenSince; } @Override public List getDeepenNots() { return deepenNots; } @Override public RevFlag getUnshallowFlag() { return UNSHALLOW; } @Override public RevFlag getReinterestingFlag() { return REINTERESTING; } @Override public RevFlag getDeepenNotFlag() { return DEEPEN_NOT; } } }