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((ObjectReader) null);
127 this.tw.setRecursive(true);
128 this.iterator = iterator;
129 }
130
131 @Override
132 public long size(String path, ObjectId id) throws IOException {
133 seek(path);
134 return ptr.getEntryLength();
135 }
136
137 @Override
138 public ObjectLoader open(String path, ObjectId id) throws IOException {
139 seek(path);
140 long entrySize = ptr.getEntryContentLength();
141 return new ObjectLoader() {
142 @Override
143 public long getSize() {
144 return entrySize;
145 }
146
147 @Override
148 public int getType() {
149 return ptr.getEntryFileMode().getObjectType();
150 }
151
152 @Override
153 public ObjectStream openStream() throws MissingObjectException,
154 IOException {
155 long contentLength = entrySize;
156 InputStream in = ptr.openEntryStream();
157 in = new BufferedInputStream(in);
158 return new ObjectStream.Filter(getType(), contentLength, in);
159 }
160
161 @Override
162 public boolean isLarge() {
163 return true;
164 }
165
166 @Override
167 public byte[] getCachedBytes() throws LargeObjectException {
168 throw new LargeObjectException();
169 }
170 };
171 }
172
173 private void seek(String path) throws IOException {
174 if (!path.equals(current)) {
175 iterator.reset();
176 tw.reset();
177 tw.addTree(iterator);
178 tw.setFilter(PathFilter.create(path));
179 current = path;
180 if (!tw.next())
181 throw new FileNotFoundException(path);
182 ptr = tw.getTree(0, WorkingTreeIterator.class);
183 if (ptr == null)
184 throw new FileNotFoundException(path);
185 }
186 }
187 }
188
189
190 public static final class Pair {
191 private final ContentSource oldSource;
192
193 private final ContentSource newSource;
194
195
196
197
198
199
200
201
202
203 public Pair(ContentSource/../org/eclipse/jgit/diff/ContentSource.html#ContentSource">ContentSource oldSource, ContentSource newSource) {
204 this.oldSource = oldSource;
205 this.newSource = newSource;
206 }
207
208
209
210
211
212
213
214
215
216
217
218
219 public long size(DiffEntry.Side side, DiffEntry ent) throws IOException {
220 switch (side) {
221 case OLD:
222 return oldSource.size(ent.oldPath, ent.oldId.toObjectId());
223 case NEW:
224 return newSource.size(ent.newPath, ent.newId.toObjectId());
225 default:
226 throw new IllegalArgumentException();
227 }
228 }
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243 public ObjectLoader open(DiffEntry.Side side, DiffEntry ent)
244 throws IOException {
245 switch (side) {
246 case OLD:
247 return oldSource.open(ent.oldPath, ent.oldId.toObjectId());
248 case NEW:
249 return newSource.open(ent.newPath, ent.newId.toObjectId());
250 default:
251 throw new IllegalArgumentException();
252 }
253 }
254 }
255 }