1 /*
2 * Copyright (C) 2008-2009, Google Inc.
3 * Copyright (C) 2009, Robin Rosenberg <robin.rosenberg@dewire.com>
4 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> and others
5 *
6 * This program and the accompanying materials are made available under the
7 * terms of the Eclipse Distribution License v. 1.0 which is available at
8 * https://www.eclipse.org/org/documents/edl-v10.php.
9 *
10 * SPDX-License-Identifier: BSD-3-Clause
11 */
12
13 package org.eclipse.jgit.dircache;
14
15 import java.io.IOException;
16
17 import org.eclipse.jgit.errors.CorruptObjectException;
18 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
19 import org.eclipse.jgit.lib.Constants;
20 import org.eclipse.jgit.lib.ObjectReader;
21 import org.eclipse.jgit.treewalk.AbstractTreeIterator;
22
23 /**
24 * Iterate and update a {@link org.eclipse.jgit.dircache.DirCache} as part of a
25 * <code>TreeWalk</code>.
26 * <p>
27 * Like {@link org.eclipse.jgit.dircache.DirCacheIterator} this iterator allows
28 * a DirCache to be used in parallel with other sorts of iterators in a
29 * TreeWalk. However any entry which appears in the source DirCache and which is
30 * skipped by the TreeFilter is automatically copied into
31 * {@link org.eclipse.jgit.dircache.DirCacheBuilder}, thus retaining it in the
32 * newly updated index.
33 * <p>
34 * This iterator is suitable for update processes, or even a simple delete
35 * algorithm. For example deleting a path:
36 *
37 * <pre>
38 * final DirCache dirc = db.lockDirCache();
39 * final DirCacheBuilder edit = dirc.builder();
40 *
41 * final TreeWalk walk = new TreeWalk(db);
42 * walk.reset();
43 * walk.setRecursive(true);
44 * walk.setFilter(PathFilter.create("name/to/remove"));
45 * walk.addTree(new DirCacheBuildIterator(edit));
46 *
47 * while (walk.next())
48 * ; // do nothing on a match as we want to remove matches
49 * edit.commit();
50 * </pre>
51 */
52 public class DirCacheBuildIterator extends DirCacheIterator {
53 private final DirCacheBuilder builder;
54
55 /**
56 * Create a new iterator for an already loaded DirCache instance.
57 * <p>
58 * The iterator implementation may copy part of the cache's data during
59 * construction, so the cache must be read in prior to creating the
60 * iterator.
61 *
62 * @param dcb
63 * the cache builder for the cache to walk. The cache must be
64 * already loaded into memory.
65 */
66 public DirCacheBuildIterator(DirCacheBuilder dcb) {
67 super(dcb.getDirCache());
68 builder = dcb;
69 }
70
71 DirCacheBuildIterator(final DirCacheBuildIterator p,
72 final DirCacheTree dct) {
73 super(p, dct);
74 builder = p.builder;
75 }
76
77 /** {@inheritDoc} */
78 @Override
79 public AbstractTreeIterator createSubtreeIterator(ObjectReader reader)
80 throws IncorrectObjectTypeException, IOException {
81 if (currentSubtree == null)
82 throw new IncorrectObjectTypeException(getEntryObjectId(),
83 Constants.TYPE_TREE);
84 return new DirCacheBuildIterator(this, currentSubtree);
85 }
86
87 /** {@inheritDoc} */
88 @Override
89 public void skip() throws CorruptObjectException {
90 if (currentSubtree != null)
91 builder.keep(ptr, currentSubtree.getEntrySpan());
92 else
93 builder.keep(ptr, 1);
94 next(1);
95 }
96
97 /** {@inheritDoc} */
98 @Override
99 public void stopWalk() {
100 final int cur = ptr;
101 final int cnt = cache.getEntryCount();
102 if (cur < cnt)
103 builder.keep(cur, cnt - cur);
104 }
105
106 /** {@inheritDoc} */
107 @Override
108 protected boolean needsStopWalk() {
109 return ptr < cache.getEntryCount();
110 }
111 }