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