1
2
3
4
5
6
7
8
9
10
11 package org.eclipse.jgit.revwalk;
12
13 import java.io.IOException;
14
15 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
16 import org.eclipse.jgit.errors.MissingObjectException;
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 class RewriteGenerator extends Generator {
32 private static final int REWRITE = RevWalk.REWRITE;
33
34
35 private static final int DUPLICATE = RevWalk.TEMP_MARK;
36
37 private final Generator source;
38
39 private final FIFORevQueue pending;
40
41 RewriteGenerator(Generator s) {
42 super(s.firstParent);
43 source = s;
44 pending = new FIFORevQueue(s.firstParent);
45 }
46
47 @Override
48 void shareFreeList(BlockRevQueue q) {
49 source.shareFreeList(q);
50 }
51
52 @Override
53 int outputType() {
54 return source.outputType() & ~NEEDS_REWRITE;
55 }
56
57 @SuppressWarnings("ReferenceEquality")
58 @Override
59 RevCommit next() throws MissingObjectException,
60 IncorrectObjectTypeException, IOException {
61 RevCommit c = pending.next();
62
63 if (c == null) {
64 c = source.next();
65 if (c == null) {
66
67
68 return null;
69 }
70 }
71
72 applyFilterToParents(c);
73
74 boolean rewrote = false;
75 final RevCommit[] pList = c.getParents();
76 final int nParents = pList.length;
77 for (int i = 0; i < nParents; i++) {
78 final RevCommit oldp = pList[i];
79 final RevCommit newp = rewrite(oldp);
80 if (firstParent) {
81 if (newp == null) {
82 c.parents = RevCommit.NO_PARENTS;
83 } else {
84 c.parents = new RevCommit[] { newp };
85 }
86 return c;
87 }
88 if (oldp != newp) {
89 pList[i] = newp;
90 rewrote = true;
91 }
92 }
93 if (rewrote) {
94 c.parents = cleanup(pList);
95 }
96 return c;
97 }
98
99
100
101
102
103
104
105
106
107
108 private void applyFilterToParents(RevCommit c)
109 throws MissingObjectException, IncorrectObjectTypeException,
110 IOException {
111 for (RevCommit parent : c.getParents()) {
112 while ((parent.flags & RevWalk.TREE_REV_FILTER_APPLIED) == 0) {
113
114 RevCommit n = source.next();
115
116 if (n != null) {
117 pending.add(n);
118 } else {
119
120
121 return;
122 }
123
124 }
125
126 }
127 }
128
129 private RevCommit rewrite(RevCommit p) throws MissingObjectException,
130 IncorrectObjectTypeException, IOException {
131 for (;;) {
132
133 if (p.getParentCount() > 1) {
134
135
136 return p;
137 }
138
139 if ((p.flags & RevWalk.UNINTERESTING) != 0) {
140
141
142
143 return p;
144 }
145
146 if ((p.flags & REWRITE) == 0) {
147
148
149
150 return p;
151 }
152
153 if (p.getParentCount() == 0) {
154
155
156
157 return null;
158 }
159
160 applyFilterToParents(p.getParent(0));
161 p = p.getParent(0);
162
163 }
164 }
165
166 private RevCommit[] cleanup(RevCommit[] oldList) {
167
168
169
170
171 int newCnt = 0;
172 for (int o = 0; o < oldList.length; o++) {
173 final RevCommit p = oldList[o];
174 if (p == null)
175 continue;
176 if ((p.flags & DUPLICATE) != 0) {
177 oldList[o] = null;
178 continue;
179 }
180 p.flags |= DUPLICATE;
181 newCnt++;
182 }
183
184 if (newCnt == oldList.length) {
185 for (RevCommit p : oldList)
186 p.flags &= ~DUPLICATE;
187 return oldList;
188 }
189
190 final RevCommit[] newList = new RevCommit[newCnt];
191 newCnt = 0;
192 for (RevCommit p : oldList) {
193 if (p != null) {
194 newList[newCnt++] = p;
195 p.flags &= ~DUPLICATE;
196 }
197 }
198
199 return newList;
200 }
201 }