1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 package org.eclipse.jgit.diff;
45
46 import java.io.BufferedInputStream;
47 import java.io.FileNotFoundException;
48 import java.io.IOException;
49 import java.io.InputStream;
50
51 import org.eclipse.jgit.errors.LargeObjectException;
52 import org.eclipse.jgit.errors.MissingObjectException;
53 import org.eclipse.jgit.lib.Constants;
54 import org.eclipse.jgit.lib.ObjectId;
55 import org.eclipse.jgit.lib.ObjectLoader;
56 import org.eclipse.jgit.lib.ObjectReader;
57 import org.eclipse.jgit.lib.ObjectStream;
58 import org.eclipse.jgit.treewalk.TreeWalk;
59 import org.eclipse.jgit.treewalk.WorkingTreeIterator;
60 import org.eclipse.jgit.treewalk.filter.PathFilter;
61
62
63
64
65
66
67
68
69
70
71 public abstract class ContentSource {
72
73
74
75
76
77
78
79 public static ContentSource create(ObjectReader reader) {
80 return new ObjectReaderSource(reader);
81 }
82
83
84
85
86
87
88
89
90
91
92
93
94 public static ContentSource create(WorkingTreeIterator iterator) {
95 return new WorkingTreeSource(iterator);
96 }
97
98
99
100
101
102
103
104
105
106
107
108
109 public abstract long size(String path, ObjectId id) throws IOException;
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124 public abstract ObjectLoader open(String path, ObjectId id)
125 throws IOException;
126
127 private static class ObjectReaderSource extends ContentSource {
128 private final ObjectReader reader;
129
130 ObjectReaderSource(ObjectReader reader) {
131 this.reader = reader;
132 }
133
134 @Override
135 public long size(String path, ObjectId id) throws IOException {
136 try {
137 return reader.getObjectSize(id, Constants.OBJ_BLOB);
138 } catch (MissingObjectException ignore) {
139 return 0;
140 }
141 }
142
143 @Override
144 public ObjectLoader open(String path, ObjectId id) throws IOException {
145 return reader.open(id, Constants.OBJ_BLOB);
146 }
147 }
148
149 private static class WorkingTreeSource extends ContentSource {
150 private final TreeWalk tw;
151
152 private final WorkingTreeIterator iterator;
153
154 private String current;
155
156 WorkingTreeIterator ptr;
157
158 WorkingTreeSource(WorkingTreeIterator iterator) {
159 this.tw = new TreeWalk((ObjectReader) null);
160 this.tw.setRecursive(true);
161 this.iterator = iterator;
162 }
163
164 @Override
165 public long size(String path, ObjectId id) throws IOException {
166 seek(path);
167 return ptr.getEntryLength();
168 }
169
170 @Override
171 public ObjectLoader open(String path, ObjectId id) throws IOException {
172 seek(path);
173 long entrySize = ptr.getEntryContentLength();
174 return new ObjectLoader() {
175 @Override
176 public long getSize() {
177 return entrySize;
178 }
179
180 @Override
181 public int getType() {
182 return ptr.getEntryFileMode().getObjectType();
183 }
184
185 @Override
186 public ObjectStream openStream() throws MissingObjectException,
187 IOException {
188 long contentLength = entrySize;
189 InputStream in = ptr.openEntryStream();
190 in = new BufferedInputStream(in);
191 return new ObjectStream.Filter(getType(), contentLength, in);
192 }
193
194 @Override
195 public boolean isLarge() {
196 return true;
197 }
198
199 @Override
200 public byte[] getCachedBytes() throws LargeObjectException {
201 throw new LargeObjectException();
202 }
203 };
204 }
205
206 private void seek(String path) throws IOException {
207 if (!path.equals(current)) {
208 iterator.reset();
209 tw.reset();
210 tw.addTree(iterator);
211 tw.setFilter(PathFilter.create(path));
212 current = path;
213 if (!tw.next())
214 throw new FileNotFoundException(path);
215 ptr = tw.getTree(0, WorkingTreeIterator.class);
216 if (ptr == null)
217 throw new FileNotFoundException(path);
218 }
219 }
220 }
221
222
223 public static final class Pair {
224 private final ContentSource oldSource;
225
226 private final ContentSource newSource;
227
228
229
230
231
232
233
234
235
236 public Pair(ContentSource oldSource, ContentSource newSource) {
237 this.oldSource = oldSource;
238 this.newSource = newSource;
239 }
240
241
242
243
244
245
246
247
248
249
250
251
252 public long size(DiffEntry.Side side, DiffEntry ent) throws IOException {
253 switch (side) {
254 case OLD:
255 return oldSource.size(ent.oldPath, ent.oldId.toObjectId());
256 case NEW:
257 return newSource.size(ent.newPath, ent.newId.toObjectId());
258 default:
259 throw new IllegalArgumentException();
260 }
261 }
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276 public ObjectLoader open(DiffEntry.Side side, DiffEntry ent)
277 throws IOException {
278 switch (side) {
279 case OLD:
280 return oldSource.open(ent.oldPath, ent.oldId.toObjectId());
281 case NEW:
282 return newSource.open(ent.newPath, ent.newId.toObjectId());
283 default:
284 throw new IllegalArgumentException();
285 }
286 }
287 }
288 }