View Javadoc
1   /*
2    * Copyright (C) 2010, Garmin International
3    * Copyright (C) 2010, Matt Fischer <matt.fischer@garmin.com>
4    * and other copyright owners as documented in the project's IP log.
5    *
6    * This program and the accompanying materials are made available
7    * under the terms of the Eclipse Distribution License v1.0 which
8    * accompanies this distribution, is reproduced below, and is
9    * available at http://www.eclipse.org/org/documents/edl-v10.php
10   *
11   * All rights reserved.
12   *
13   * Redistribution and use in source and binary forms, with or
14   * without modification, are permitted provided that the following
15   * conditions are met:
16   *
17   * - Redistributions of source code must retain the above copyright
18   *   notice, this list of conditions and the following disclaimer.
19   *
20   * - Redistributions in binary form must reproduce the above
21   *   copyright notice, this list of conditions and the following
22   *   disclaimer in the documentation and/or other materials provided
23   *   with the distribution.
24   *
25   * - Neither the name of the Eclipse Foundation, Inc. nor the
26   *   names of its contributors may be used to endorse or promote
27   *   products derived from this software without specific prior
28   *   written permission.
29   *
30   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
31   * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
32   * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
33   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
35   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
36   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
37   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
39   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
42   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43   */
44  
45  package org.eclipse.jgit.revwalk;
46  
47  import java.io.IOException;
48  import java.util.Collections;
49  import java.util.List;
50  import java.util.Objects;
51  
52  import org.eclipse.jgit.errors.IncorrectObjectTypeException;
53  import org.eclipse.jgit.errors.MissingObjectException;
54  import org.eclipse.jgit.lib.AnyObjectId;
55  import org.eclipse.jgit.lib.ObjectId;
56  import org.eclipse.jgit.lib.ObjectReader;
57  import org.eclipse.jgit.lib.Repository;
58  
59  /**
60   * Interface for revision walkers that perform depth filtering.
61   */
62  public interface DepthWalk {
63  	/**
64  	 * Get depth to filter to.
65  	 *
66  	 * @return Depth to filter to.
67  	 */
68  	int getDepth();
69  
70  	/**
71  	 * @return the deepen-since value; if not 0, this walk only returns commits
72  	 *         whose commit time is at or after this limit
73  	 * @since 5.2
74  	 */
75  	default int getDeepenSince() {
76  		return 0;
77  	}
78  
79  	/**
80  	 * @return the objects specified by the client using --shallow-exclude
81  	 * @since 5.2
82  	 */
83  	default List<ObjectId> getDeepenNots() {
84  		return Collections.emptyList();
85  	}
86  
87  	/** @return flag marking commits that should become unshallow. */
88  	/**
89  	 * Get flag marking commits that should become unshallow.
90  	 *
91  	 * @return flag marking commits that should become unshallow.
92  	 */
93  	RevFlag getUnshallowFlag();
94  
95  	/**
96  	 * Get flag marking commits that are interesting again.
97  	 *
98  	 * @return flag marking commits that are interesting again.
99  	 */
100 	RevFlag getReinterestingFlag();
101 
102 	/**
103 	 * @return flag marking commits that are to be excluded because of --shallow-exclude
104 	 * @since 5.2
105 	 */
106 	RevFlag getDeepenNotFlag();
107 
108 	/** RevCommit with a depth (in commits) from a root. */
109 	public static class Commit extends RevCommit {
110 		/** Depth of this commit in the graph, via shortest path. */
111 		int depth;
112 
113 		boolean isBoundary;
114 
115 		/**
116 		 * True if this commit was excluded due to a shallow fetch
117 		 * setting. All its children are thus boundary commits.
118 		 */
119 		boolean makesChildBoundary;
120 
121 		/** @return depth of this commit, as found by the shortest path. */
122 		public int getDepth() {
123 			return depth;
124 		}
125 
126 		/**
127 		 * @return true if at least one of this commit's parents was excluded
128 		 *         due to a shallow fetch setting, false otherwise
129 		 * @since 5.2
130 		 */
131 		public boolean isBoundary() {
132 			return isBoundary;
133 		}
134 
135 		/**
136 		 * Initialize a new commit.
137 		 *
138 		 * @param id
139 		 *            object name for the commit.
140 		 */
141 		protected Commit(AnyObjectId id) {
142 			super(id);
143 			depth = -1;
144 		}
145 	}
146 
147 	/** Subclass of RevWalk that performs depth filtering. */
148 	public class RevWalk extends org.eclipse.jgit.revwalk.RevWalk implements DepthWalk {
149 		private final int depth;
150 
151 		private int deepenSince;
152 
153 		private List<ObjectId> deepenNots;
154 
155 		private final RevFlag UNSHALLOW;
156 
157 		private final RevFlag REINTERESTING;
158 
159 		private final RevFlag DEEPEN_NOT;
160 
161 		/**
162 		 * @param repo Repository to walk
163 		 * @param depth Maximum depth to return
164 		 */
165 		public RevWalk(Repository repo, int depth) {
166 			super(repo);
167 
168 			this.depth = depth;
169 			this.deepenNots = Collections.emptyList();
170 			this.UNSHALLOW = newFlag("UNSHALLOW"); //$NON-NLS-1$
171 			this.REINTERESTING = newFlag("REINTERESTING"); //$NON-NLS-1$
172 			this.DEEPEN_NOT = newFlag("DEEPEN_NOT"); //$NON-NLS-1$
173 		}
174 
175 		/**
176 		 * @param or ObjectReader to use
177 		 * @param depth Maximum depth to return
178 		 */
179 		public RevWalk(ObjectReader or, int depth) {
180 			super(or);
181 
182 			this.depth = depth;
183 			this.deepenNots = Collections.emptyList();
184 			this.UNSHALLOW = newFlag("UNSHALLOW"); //$NON-NLS-1$
185 			this.REINTERESTING = newFlag("REINTERESTING"); //$NON-NLS-1$
186 			this.DEEPEN_NOT = newFlag("DEEPEN_NOT"); //$NON-NLS-1$
187 		}
188 
189 		/**
190 		 * Mark a root commit (i.e., one whose depth should be considered 0.)
191 		 *
192 		 * @param c
193 		 *            Commit to mark
194 		 * @throws IOException
195 		 * @throws IncorrectObjectTypeException
196 		 * @throws MissingObjectException
197 		 */
198 		public void markRoot(RevCommit c) throws MissingObjectException,
199 				IncorrectObjectTypeException, IOException {
200 			if (c instanceof Commit)
201 				((Commit) c).depth = 0;
202 			super.markStart(c);
203 		}
204 
205 		@Override
206 		protected RevCommit createCommit(AnyObjectId id) {
207 			return new Commit(id);
208 		}
209 
210 		@Override
211 		public int getDepth() {
212 			return depth;
213 		}
214 
215 		@Override
216 		public int getDeepenSince() {
217 			return deepenSince;
218 		}
219 
220 		/**
221 		 * Sets the deepen-since value.
222 		 *
223 		 * @param limit
224 		 *            new deepen-since value
225 		 * @since 5.2
226 		 */
227 		public void setDeepenSince(int limit) {
228 			deepenSince = limit;
229 		}
230 
231 		@Override
232 		public List<ObjectId> getDeepenNots() {
233 			return deepenNots;
234 		}
235 
236 		/**
237 		 * Mark objects that the client specified using
238 		 * --shallow-exclude. Objects that are not commits have no
239 		 * effect.
240 		 *
241 		 * @param deepenNots specified objects
242 		 * @since 5.2
243 		 */
244 		public void setDeepenNots(List<ObjectId> deepenNots) {
245 			this.deepenNots = Objects.requireNonNull(deepenNots);
246 		}
247 
248 		@Override
249 		public RevFlag getUnshallowFlag() {
250 			return UNSHALLOW;
251 		}
252 
253 		@Override
254 		public RevFlag getReinterestingFlag() {
255 			return REINTERESTING;
256 		}
257 
258 		@Override
259 		public RevFlag getDeepenNotFlag() {
260 			return DEEPEN_NOT;
261 		}
262 
263 		/**
264 		 * @since 4.5
265 		 */
266 		@Override
267 		public ObjectWalk toObjectWalkWithSameObjects() {
268 			ObjectWalk ow = new ObjectWalk(reader, depth);
269 			ow.deepenSince = deepenSince;
270 			ow.deepenNots = deepenNots;
271 			ow.objects = objects;
272 			ow.freeFlags = freeFlags;
273 			return ow;
274 		}
275 	}
276 
277 	/** Subclass of ObjectWalk that performs depth filtering. */
278 	public class ObjectWalk extends org.eclipse.jgit.revwalk.ObjectWalk implements DepthWalk {
279 		private final int depth;
280 
281 		private int deepenSince;
282 
283 		private List<ObjectId> deepenNots;
284 
285 		private final RevFlag UNSHALLOW;
286 
287 		private final RevFlag REINTERESTING;
288 
289 		private final RevFlag DEEPEN_NOT;
290 
291 		/**
292 		 * @param repo Repository to walk
293 		 * @param depth Maximum depth to return
294 		 */
295 		public ObjectWalk(Repository repo, int depth) {
296 			super(repo);
297 
298 			this.depth = depth;
299 			this.deepenNots = Collections.emptyList();
300 			this.UNSHALLOW = newFlag("UNSHALLOW"); //$NON-NLS-1$
301 			this.REINTERESTING = newFlag("REINTERESTING"); //$NON-NLS-1$
302 			this.DEEPEN_NOT = newFlag("DEEPEN_NOT"); //$NON-NLS-1$
303 		}
304 
305 		/**
306 		 * @param or Object Reader
307 		 * @param depth Maximum depth to return
308 		 */
309 		public ObjectWalk(ObjectReader or, int depth) {
310 			super(or);
311 
312 			this.depth = depth;
313 			this.deepenNots = Collections.emptyList();
314 			this.UNSHALLOW = newFlag("UNSHALLOW"); //$NON-NLS-1$
315 			this.REINTERESTING = newFlag("REINTERESTING"); //$NON-NLS-1$
316 			this.DEEPEN_NOT = newFlag("DEEPEN_NOT"); //$NON-NLS-1$
317 		}
318 
319 		/**
320 		 * Mark a root commit (i.e., one whose depth should be considered 0.)
321 		 *
322 		 * @param o
323 		 *            Commit to mark
324 		 * @throws IOException
325 		 * @throws IncorrectObjectTypeException
326 		 * @throws MissingObjectException
327 		 */
328 		public void markRoot(RevObject o) throws MissingObjectException,
329 				IncorrectObjectTypeException, IOException {
330 			RevObject c = o;
331 			while (c instanceof RevTag) {
332 				c = ((RevTag) c).getObject();
333 				parseHeaders(c);
334 			}
335 			if (c instanceof Commit)
336 				((Commit) c).depth = 0;
337 			super.markStart(o);
338 		}
339 
340 		/**
341 		 * Mark an element which used to be shallow in the client, but which
342 		 * should now be considered a full commit. Any ancestors of this commit
343 		 * should be included in the walk, even if they are the ancestor of an
344 		 * uninteresting commit.
345 		 *
346 		 * @param c
347 		 *            Commit to mark
348 		 * @throws MissingObjectException
349 		 * @throws IncorrectObjectTypeException
350 		 * @throws IOException
351 		 */
352 		public void markUnshallow(RevObject c) throws MissingObjectException,
353 				IncorrectObjectTypeException, IOException {
354 			if (c instanceof RevCommit)
355 				c.add(UNSHALLOW);
356 			super.markStart(c);
357 		}
358 
359 		@Override
360 		protected RevCommit createCommit(AnyObjectId id) {
361 			return new Commit(id);
362 		}
363 
364 		@Override
365 		public int getDepth() {
366 			return depth;
367 		}
368 
369 		@Override
370 		public int getDeepenSince() {
371 			return deepenSince;
372 		}
373 
374 		@Override
375 		public List<ObjectId> getDeepenNots() {
376 			return deepenNots;
377 		}
378 
379 		@Override
380 		public RevFlag getUnshallowFlag() {
381 			return UNSHALLOW;
382 		}
383 
384 		@Override
385 		public RevFlag getReinterestingFlag() {
386 			return REINTERESTING;
387 		}
388 
389 		@Override
390 		public RevFlag getDeepenNotFlag() {
391 			return DEEPEN_NOT;
392 		}
393 	}
394 }