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.dircache;
45
46 import static org.eclipse.jgit.junit.Assert.assertEquals;
47 import static org.junit.Assert.assertArrayEquals;
48 import static org.junit.Assert.assertEquals;
49 import static org.junit.Assert.assertNotNull;
50 import static org.junit.Assert.assertTrue;
51 import static org.junit.Assert.fail;
52
53 import java.io.BufferedReader;
54 import java.io.ByteArrayOutputStream;
55 import java.io.File;
56 import java.io.FileInputStream;
57 import java.io.InputStreamReader;
58 import java.util.ArrayList;
59 import java.util.Iterator;
60 import java.util.LinkedHashMap;
61 import java.util.Map;
62
63 import org.eclipse.jgit.errors.CorruptObjectException;
64 import org.eclipse.jgit.junit.JGitTestUtil;
65 import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
66 import org.eclipse.jgit.lib.FileMode;
67 import org.eclipse.jgit.lib.ObjectId;
68 import org.eclipse.jgit.lib.Repository;
69 import org.eclipse.jgit.treewalk.TreeWalk;
70 import org.eclipse.jgit.util.FS;
71 import org.eclipse.jgit.util.IO;
72 import org.junit.Test;
73
74 public class DirCacheCGitCompatabilityTest extends LocalDiskRepositoryTestCase {
75 private final File index = pathOf("gitgit.index");
76
77 @Test
78 public void testReadIndex_LsFiles() throws Exception {
79 final Map<String, CGitIndexRecord> ls = readLsFiles();
80 final DirCache dc = new DirCache(index, FS.DETECTED);
81 assertEquals(0, dc.getEntryCount());
82 dc.read();
83 assertEquals(ls.size(), dc.getEntryCount());
84 {
85 final Iterator<CGitIndexRecord> rItr = ls.values().iterator();
86 for (int i = 0; rItr.hasNext(); i++)
87 assertEqual(rItr.next(), dc.getEntry(i));
88 }
89 }
90
91 @Test
92 public void testTreeWalk_LsFiles() throws Exception {
93 final Repository db = createBareRepository();
94 final Map<String, CGitIndexRecord> ls = readLsFiles();
95 final DirCache dc = new DirCache(index, db.getFS());
96 assertEquals(0, dc.getEntryCount());
97 dc.read();
98 assertEquals(ls.size(), dc.getEntryCount());
99 {
100 final Iterator<CGitIndexRecord> rItr = ls.values().iterator();
101 final TreeWalk tw = new TreeWalk(db);
102 tw.setRecursive(true);
103 tw.addTree(new DirCacheIterator(dc));
104 while (rItr.hasNext()) {
105 final DirCacheIterator dcItr;
106
107 assertTrue(tw.next());
108 dcItr = tw.getTree(0, DirCacheIterator.class);
109 assertNotNull(dcItr);
110
111 assertEqual(rItr.next(), dcItr.getDirCacheEntry());
112 }
113 }
114 }
115
116 @Test
117 public void testUnsupportedOptionalExtension() throws Exception {
118 final DirCache dc = new DirCache(pathOf("gitgit.index.ZZZZ"),
119 FS.DETECTED);
120 dc.read();
121 assertEquals(1, dc.getEntryCount());
122 assertEquals("A", dc.getEntry(0).getPathString());
123 }
124
125 @Test
126 public void testUnsupportedRequiredExtension() throws Exception {
127 final DirCache dc = new DirCache(pathOf("gitgit.index.aaaa"),
128 FS.DETECTED);
129 try {
130 dc.read();
131 fail("Cache loaded an unsupported extension");
132 } catch (CorruptObjectException err) {
133 assertEquals("DIRC extension 'aaaa'"
134 + " not supported by this version.", err.getMessage());
135 }
136 }
137
138 @Test
139 public void testCorruptChecksumAtFooter() throws Exception {
140 final DirCache dc = new DirCache(pathOf("gitgit.index.badchecksum"),
141 FS.DETECTED);
142 try {
143 dc.read();
144 fail("Cache loaded despite corrupt checksum");
145 } catch (CorruptObjectException err) {
146 assertEquals("DIRC checksum mismatch", err.getMessage());
147 }
148 }
149
150 private static void assertEqual(final CGitIndexRecord c,
151 final DirCacheEntry j) {
152 assertNotNull(c);
153 assertNotNull(j);
154
155 assertEquals(c.path, j.getPathString());
156 assertEquals(c.id, j.getObjectId());
157 assertEquals(c.mode, j.getRawMode());
158 assertEquals(c.stage, j.getStage());
159 }
160
161 @Test
162 public void testReadIndex_DirCacheTree() throws Exception {
163 final Map<String, CGitIndexRecord> cList = readLsFiles();
164 final Map<String, CGitLsTreeRecord> cTree = readLsTree();
165 final DirCache dc = new DirCache(index, FS.DETECTED);
166 assertEquals(0, dc.getEntryCount());
167 dc.read();
168 assertEquals(cList.size(), dc.getEntryCount());
169
170 final DirCacheTree jTree = dc.getCacheTree(false);
171 assertNotNull(jTree);
172 assertEquals("", jTree.getNameString());
173 assertEquals("", jTree.getPathString());
174 assertTrue(jTree.isValid());
175 assertEquals(ObjectId
176 .fromString("698dd0b8d0c299f080559a1cffc7fe029479a408"), jTree
177 .getObjectId());
178 assertEquals(cList.size(), jTree.getEntrySpan());
179
180 final ArrayList<CGitLsTreeRecord> subtrees = new ArrayList<CGitLsTreeRecord>();
181 for (final CGitLsTreeRecord r : cTree.values()) {
182 if (FileMode.TREE.equals(r.mode))
183 subtrees.add(r);
184 }
185 assertEquals(subtrees.size(), jTree.getChildCount());
186
187 for (int i = 0; i < jTree.getChildCount(); i++) {
188 final DirCacheTree sj = jTree.getChild(i);
189 final CGitLsTreeRecord sc = subtrees.get(i);
190 assertEquals(sc.path, sj.getNameString());
191 assertEquals(sc.path + "/", sj.getPathString());
192 assertTrue(sj.isValid());
193 assertEquals(sc.id, sj.getObjectId());
194 }
195 }
196
197 @Test
198 public void testReadWriteV3() throws Exception {
199 final File file = pathOf("gitgit.index.v3");
200 final DirCache dc = new DirCache(file, FS.DETECTED);
201 dc.read();
202
203 assertEquals(10, dc.getEntryCount());
204 assertV3TreeEntry(0, "dir1/file1.txt", false, false, dc);
205 assertV3TreeEntry(1, "dir2/file2.txt", true, false, dc);
206 assertV3TreeEntry(2, "dir3/file3.txt", false, false, dc);
207 assertV3TreeEntry(3, "dir3/file3a.txt", true, false, dc);
208 assertV3TreeEntry(4, "dir4/file4.txt", true, false, dc);
209 assertV3TreeEntry(5, "dir4/file4a.txt", false, false, dc);
210 assertV3TreeEntry(6, "file.txt", true, false, dc);
211 assertV3TreeEntry(7, "newdir1/newfile1.txt", false, true, dc);
212 assertV3TreeEntry(8, "newdir1/newfile2.txt", false, true, dc);
213 assertV3TreeEntry(9, "newfile.txt", false, true, dc);
214
215 final ByteArrayOutputStream bos = new ByteArrayOutputStream();
216 dc.writeTo(null, bos);
217 final byte[] indexBytes = bos.toByteArray();
218 final byte[] expectedBytes = IO.readFully(file);
219 assertArrayEquals(expectedBytes, indexBytes);
220 }
221
222 private static void assertV3TreeEntry(int indexPosition, String path,
223 boolean skipWorkTree, boolean intentToAdd, DirCache dc) {
224 final DirCacheEntry entry = dc.getEntry(indexPosition);
225 assertEquals(path, entry.getPathString());
226 assertEquals(skipWorkTree, entry.isSkipWorkTree());
227 assertEquals(intentToAdd, entry.isIntentToAdd());
228 }
229
230 private static File pathOf(final String name) {
231 return JGitTestUtil.getTestResourceFile(name);
232 }
233
234 private static Map<String, CGitIndexRecord> readLsFiles() throws Exception {
235 final LinkedHashMap<String, CGitIndexRecord> r = new LinkedHashMap<String, CGitIndexRecord>();
236 final BufferedReader br = new BufferedReader(new InputStreamReader(
237 new FileInputStream(pathOf("gitgit.lsfiles")), "UTF-8"));
238 try {
239 String line;
240 while ((line = br.readLine()) != null) {
241 final CGitIndexRecord cr = new CGitIndexRecord(line);
242 r.put(cr.path, cr);
243 }
244 } finally {
245 br.close();
246 }
247 return r;
248 }
249
250 private static Map<String, CGitLsTreeRecord> readLsTree() throws Exception {
251 final LinkedHashMap<String, CGitLsTreeRecord> r = new LinkedHashMap<String, CGitLsTreeRecord>();
252 final BufferedReader br = new BufferedReader(new InputStreamReader(
253 new FileInputStream(pathOf("gitgit.lstree")), "UTF-8"));
254 try {
255 String line;
256 while ((line = br.readLine()) != null) {
257 final CGitLsTreeRecord cr = new CGitLsTreeRecord(line);
258 r.put(cr.path, cr);
259 }
260 } finally {
261 br.close();
262 }
263 return r;
264 }
265
266 private static class CGitIndexRecord {
267 final int mode;
268
269 final ObjectId id;
270
271 final int stage;
272
273 final String path;
274
275 CGitIndexRecord(final String line) {
276 final int tab = line.indexOf('\t');
277 final int sp1 = line.indexOf(' ');
278 final int sp2 = line.indexOf(' ', sp1 + 1);
279 mode = Integer.parseInt(line.substring(0, sp1), 8);
280 id = ObjectId.fromString(line.substring(sp1 + 1, sp2));
281 stage = Integer.parseInt(line.substring(sp2 + 1, tab));
282 path = line.substring(tab + 1);
283 }
284 }
285
286 private static class CGitLsTreeRecord {
287 final int mode;
288
289 final ObjectId id;
290
291 final String path;
292
293 CGitLsTreeRecord(final String line) {
294 final int tab = line.indexOf('\t');
295 final int sp1 = line.indexOf(' ');
296 final int sp2 = line.indexOf(' ', sp1 + 1);
297 mode = Integer.parseInt(line.substring(0, sp1), 8);
298 id = ObjectId.fromString(line.substring(sp2 + 1, tab));
299 path = line.substring(tab + 1);
300 }
301 }
302 }