Switch jgit library to the EDL (3-clause BSD)
[jgit.git] / org.spearce.jgit.test / tst / org / spearce / jgit / lib / T0007_Index.java
blob30412ffdf87a93fc2f1a654b7475dccfaabd550f
1 /*
2 * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
3 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or
8 * without modification, are permitted provided that the following
9 * conditions are met:
11 * - Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * - Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer in the documentation and/or other materials provided
17 * with the distribution.
19 * - Neither the name of the Git Development Community nor the
20 * names of its contributors may be used to endorse or promote
21 * products derived from this software without specific prior
22 * written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
25 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
26 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
29 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
34 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
36 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 package org.spearce.jgit.lib;
41 import java.io.File;
42 import java.io.FileInputStream;
43 import java.io.IOException;
44 import java.io.InputStream;
45 import java.lang.reflect.InvocationTargetException;
46 import java.lang.reflect.Method;
48 import org.spearce.jgit.lib.GitIndex.Entry;
50 public class T0007_Index extends RepositoryTestCase {
52 static boolean canrungitstatus;
53 static {
54 try {
55 canrungitstatus = system(new File("."),"git --version") == 0;
56 } catch (IOException e) {
57 System.out.println("Warning: cannot invvoke native git to validate index");
58 } catch (InterruptedException e) {
59 e.printStackTrace();
63 private static int system(File dir, String cmd) throws IOException,
64 InterruptedException {
65 final Process process = Runtime.getRuntime().exec(cmd, null, dir);
66 new Thread() {
67 public void run() {
68 try {
69 InputStream s = process.getErrorStream();
70 for (int c = s.read(); c != -1; c = s.read()) {
71 System.err.print((char) c);
73 s.close();
74 } catch (IOException e1) {
75 // TODO Auto-generated catch block
76 e1.printStackTrace();
79 }.start();
80 final Thread t2 = new Thread() {
81 public void run() {
82 synchronized (this) {
83 try {
84 InputStream e = process.getInputStream();
85 for (int c = e.read(); c != -1; c = e.read()) {
86 System.out.print((char) c);
88 e.close();
89 } catch (IOException e1) {
90 // TODO Auto-generated catch block
91 e1.printStackTrace();
96 t2.start();
97 process.getOutputStream().close();
98 int ret = process.waitFor();
99 synchronized (t2) {
100 return ret;
104 public void testCreateEmptyIndex() throws Exception {
105 GitIndex index = new GitIndex(db);
106 index.write();
107 // native git doesn't like an empty index
108 // assertEquals(0,system(trash,"git status"));
110 GitIndex indexr = new GitIndex(db);
111 indexr.read();
112 assertEquals(0, indexr.getMembers().length);
115 public void testReadWithNoIndex() throws Exception {
116 GitIndex index = new GitIndex(db);
117 index.read();
118 assertEquals(0, index.getMembers().length);
121 public void testCreateSimpleSortTestIndex() throws Exception {
122 GitIndex index = new GitIndex(db);
123 writeTrashFile("a/b", "data:a/b");
124 writeTrashFile("a:b", "data:a:b");
125 writeTrashFile("a.b", "data:a.b");
126 index.add(trash, new File(trash, "a/b"));
127 index.add(trash, new File(trash, "a:b"));
128 index.add(trash, new File(trash, "a.b"));
129 index.write();
131 assertEquals("a/b", index.getEntry("a/b").getName());
132 assertEquals("a:b", index.getEntry("a:b").getName());
133 assertEquals("a.b", index.getEntry("a.b").getName());
134 assertNull(index.getEntry("a*b"));
136 // Repeat test for re-read index
137 GitIndex indexr = new GitIndex(db);
138 indexr.read();
139 assertEquals("a/b", indexr.getEntry("a/b").getName());
140 assertEquals("a:b", indexr.getEntry("a:b").getName());
141 assertEquals("a.b", indexr.getEntry("a.b").getName());
142 assertNull(indexr.getEntry("a*b"));
144 if (canrungitstatus)
145 assertEquals(0, system(trash, "git status"));
148 public void testUpdateSimpleSortTestIndex() throws Exception {
149 GitIndex index = new GitIndex(db);
150 writeTrashFile("a/b", "data:a/b");
151 writeTrashFile("a:b", "data:a:b");
152 writeTrashFile("a.b", "data:a.b");
153 index.add(trash, new File(trash, "a/b"));
154 index.add(trash, new File(trash, "a:b"));
155 index.add(trash, new File(trash, "a.b"));
156 writeTrashFile("a/b", "data:a/b modified");
157 index.add(trash, new File(trash, "a/b"));
158 index.write();
159 if (canrungitstatus)
160 assertEquals(0, system(trash, "git status"));
163 public void testWriteTree() throws Exception {
164 GitIndex index = new GitIndex(db);
165 writeTrashFile("a/b", "data:a/b");
166 writeTrashFile("a:b", "data:a:b");
167 writeTrashFile("a.b", "data:a.b");
168 index.add(trash, new File(trash, "a/b"));
169 index.add(trash, new File(trash, "a:b"));
170 index.add(trash, new File(trash, "a.b"));
171 index.write();
173 ObjectId id = index.writeTree();
174 assertEquals("c696abc3ab8e091c665f49d00eb8919690b3aec3", id.toString());
176 writeTrashFile("a/b", "data:a/b");
177 index.add(trash, new File(trash, "a/b"));
179 if (canrungitstatus)
180 assertEquals(0, system(trash, "git status"));
183 public void testReadTree() throws Exception {
184 // Prepare tree
185 GitIndex index = new GitIndex(db);
186 writeTrashFile("a/b", "data:a/b");
187 writeTrashFile("a:b", "data:a:b");
188 writeTrashFile("a.b", "data:a.b");
189 index.add(trash, new File(trash, "a/b"));
190 index.add(trash, new File(trash, "a:b"));
191 index.add(trash, new File(trash, "a.b"));
192 index.write();
194 ObjectId id = index.writeTree();
195 System.out.println("wrote id " + id);
196 assertEquals("c696abc3ab8e091c665f49d00eb8919690b3aec3", id.toString());
197 GitIndex index2 = new GitIndex(db);
199 index2.readTree(db.mapTree(ObjectId.fromString(
200 "c696abc3ab8e091c665f49d00eb8919690b3aec3")));
201 Entry[] members = index2.getMembers();
202 assertEquals(3, members.length);
203 assertEquals("a.b", members[0].getName());
204 assertEquals("a/b", members[1].getName());
205 assertEquals("a:b", members[2].getName());
206 assertEquals(3, members.length);
208 GitIndex indexr = new GitIndex(db);
209 indexr.read();
210 Entry[] membersr = indexr.getMembers();
211 assertEquals(3, membersr.length);
212 assertEquals("a.b", membersr[0].getName());
213 assertEquals("a/b", membersr[1].getName());
214 assertEquals("a:b", membersr[2].getName());
215 assertEquals(3, membersr.length);
217 if (canrungitstatus)
218 assertEquals(0, system(trash, "git status"));
221 public void testReadTree2() throws Exception {
222 // Prepare a larger tree to test some odd cases in tree writing
223 GitIndex index = new GitIndex(db);
224 File f1 = writeTrashFile("a/a/a/a", "data:a/a/a/a");
225 File f2 = writeTrashFile("a/c/c", "data:a/c/c");
226 File f3 = writeTrashFile("a/b", "data:a/b");
227 File f4 = writeTrashFile("a:b", "data:a:b");
228 File f5 = writeTrashFile("a/d", "data:a/d");
229 File f6 = writeTrashFile("a.b", "data:a.b");
230 index.add(trash, f1);
231 index.add(trash, f2);
232 index.add(trash, f3);
233 index.add(trash, f4);
234 index.add(trash, f5);
235 index.add(trash, f6);
236 index.write();
237 ObjectId id = index.writeTree();
238 System.out.println("wrote id " + id);
239 assertEquals("ba78e065e2c261d4f7b8f42107588051e87e18e9", id.toString());
240 GitIndex index2 = new GitIndex(db);
242 index2.readTree(db.mapTree(ObjectId.fromString(
243 "ba78e065e2c261d4f7b8f42107588051e87e18e9")));
244 Entry[] members = index2.getMembers();
245 assertEquals(6, members.length);
246 assertEquals("a.b", members[0].getName());
247 assertEquals("a/a/a/a", members[1].getName());
248 assertEquals("a/b", members[2].getName());
249 assertEquals("a/c/c", members[3].getName());
250 assertEquals("a/d", members[4].getName());
251 assertEquals("a:b", members[5].getName());
253 // reread and test
254 GitIndex indexr = new GitIndex(db);
255 indexr.read();
256 Entry[] membersr = indexr.getMembers();
257 assertEquals(6, membersr.length);
258 assertEquals("a.b", membersr[0].getName());
259 assertEquals("a/a/a/a", membersr[1].getName());
260 assertEquals("a/b", membersr[2].getName());
261 assertEquals("a/c/c", membersr[3].getName());
262 assertEquals("a/d", membersr[4].getName());
263 assertEquals("a:b", membersr[5].getName());
266 public void testDelete() throws Exception {
267 GitIndex index = new GitIndex(db);
268 writeTrashFile("a/b", "data:a/b");
269 writeTrashFile("a:b", "data:a:b");
270 writeTrashFile("a.b", "data:a.b");
271 index.add(trash, new File(trash, "a/b"));
272 index.add(trash, new File(trash, "a:b"));
273 index.add(trash, new File(trash, "a.b"));
274 index.write();
275 index.writeTree();
276 index.remove(trash, new File(trash, "a:b"));
277 index.write();
278 assertEquals("a.b", index.getMembers()[0].getName());
279 assertEquals("a/b", index.getMembers()[1].getName());
281 GitIndex indexr = new GitIndex(db);
282 indexr.read();
283 assertEquals("a.b", indexr.getMembers()[0].getName());
284 assertEquals("a/b", indexr.getMembers()[1].getName());
286 if (canrungitstatus)
287 assertEquals(0, system(trash, "git status"));
290 public void testCheckout() throws Exception {
291 // Prepare tree, remote it and checkout
292 GitIndex index = new GitIndex(db);
293 File aslashb = writeTrashFile("a/b", "data:a/b");
294 File acolonb = writeTrashFile("a:b", "data:a:b");
295 File adotb = writeTrashFile("a.b", "data:a.b");
296 index.add(trash, aslashb);
297 index.add(trash, acolonb);
298 index.add(trash, adotb);
299 index.write();
300 index.writeTree();
301 delete(aslashb);
302 delete(acolonb);
303 delete(adotb);
304 delete(aslashb.getParentFile());
306 GitIndex index2 = new GitIndex(db);
307 assertEquals(0, index2.getMembers().length);
309 index2.readTree(db.mapTree(ObjectId.fromString(
310 "c696abc3ab8e091c665f49d00eb8919690b3aec3")));
312 index2.checkout(trash);
313 assertEquals("data:a/b", content(aslashb));
314 assertEquals("data:a:b", content(acolonb));
315 assertEquals("data:a.b", content(adotb));
317 if (canrungitstatus)
318 assertEquals(0, system(trash, "git status"));
321 public void test030_executeBit_coreModeTrue() throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, Error, Exception {
322 try {
323 // coremode true is the default, typically set to false
324 // by git init (but not jgit!)
325 Method canExecute = File.class.getMethod("canExecute", (Class[])null);
326 Method setExecute = File.class.getMethod("setExecutable", new Class[] { Boolean.TYPE });
327 File execFile = writeTrashFile("exec","exec");
328 if (!((Boolean)setExecute.invoke(execFile, new Object[] { Boolean.TRUE })).booleanValue())
329 throw new Error("could not set execute bit on "+execFile.getAbsolutePath()+"for test");
330 File nonexecFile = writeTrashFile("nonexec","nonexec");
331 if (!((Boolean)setExecute.invoke(nonexecFile, new Object[] { Boolean.FALSE })).booleanValue())
332 throw new Error("could not clear execute bit on "+nonexecFile.getAbsolutePath()+"for test");
334 GitIndex index = new GitIndex(db);
335 index.filemode = Boolean.TRUE; // TODO: we need a way to set this using config
336 index.add(trash, execFile);
337 index.add(trash, nonexecFile);
338 Tree tree = db.mapTree(index.writeTree());
339 assertEquals(FileMode.EXECUTABLE_FILE, tree.findBlobMember(execFile.getName()).getMode());
340 assertEquals(FileMode.REGULAR_FILE, tree.findBlobMember(nonexecFile.getName()).getMode());
342 index.write();
344 if (!execFile.delete())
345 throw new Error("Problem in test, cannot delete test file "+execFile.getAbsolutePath());
346 if (!nonexecFile.delete())
347 throw new Error("Problem in test, cannot delete test file "+nonexecFile.getAbsolutePath());
348 GitIndex index2 = new GitIndex(db);
349 index2.filemode = Boolean.TRUE; // TODO: we need a way to set this using config
350 index2.read();
351 index2.checkout(trash);
352 assertTrue(((Boolean)canExecute.invoke(execFile,(Object[])null)).booleanValue());
353 assertFalse(((Boolean)canExecute.invoke(nonexecFile,(Object[])null)).booleanValue());
355 assertFalse(index2.getEntry(execFile.getName()).isModified(trash));
356 assertFalse(index2.getEntry(nonexecFile.getName()).isModified(trash));
358 if (!((Boolean)setExecute.invoke(execFile, new Object[] { Boolean.FALSE })).booleanValue())
359 throw new Error("could not clear set execute bit on "+execFile.getAbsolutePath()+"for test");
360 if (!((Boolean)setExecute.invoke(nonexecFile, new Object[] { Boolean.TRUE })).booleanValue())
361 throw new Error("could set execute bit on "+nonexecFile.getAbsolutePath()+"for test");
363 assertTrue(index2.getEntry(execFile.getName()).isModified(trash));
364 assertTrue(index2.getEntry(nonexecFile.getName()).isModified(trash));
366 } catch (NoSuchMethodException e) {
367 System.err.println("Test ignored when running under JDk < 1.6");
368 return;
372 public void test031_executeBit_coreModeFalse() throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, Error, Exception {
373 try {
374 // coremode true is the default, typically set to false
375 // by git init (but not jgit!)
376 Method canExecute = File.class.getMethod("canExecute", (Class[])null);
377 Method setExecute = File.class.getMethod("setExecutable", new Class[] { Boolean.TYPE });
378 File execFile = writeTrashFile("exec","exec");
379 if (!((Boolean)setExecute.invoke(execFile, new Object[] { Boolean.TRUE })).booleanValue())
380 throw new Error("could not set execute bit on "+execFile.getAbsolutePath()+"for test");
381 File nonexecFile = writeTrashFile("nonexec","nonexec");
382 if (!((Boolean)setExecute.invoke(nonexecFile, new Object[] { Boolean.FALSE })).booleanValue())
383 throw new Error("could not clear execute bit on "+nonexecFile.getAbsolutePath()+"for test");
385 GitIndex index = new GitIndex(db);
386 index.filemode = Boolean.FALSE; // TODO: we need a way to set this using config
387 index.add(trash, execFile);
388 index.add(trash, nonexecFile);
389 Tree tree = db.mapTree(index.writeTree());
390 assertEquals(FileMode.REGULAR_FILE, tree.findBlobMember(execFile.getName()).getMode());
391 assertEquals(FileMode.REGULAR_FILE, tree.findBlobMember(nonexecFile.getName()).getMode());
393 index.write();
395 if (!execFile.delete())
396 throw new Error("Problem in test, cannot delete test file "+execFile.getAbsolutePath());
397 if (!nonexecFile.delete())
398 throw new Error("Problem in test, cannot delete test file "+nonexecFile.getAbsolutePath());
399 GitIndex index2 = new GitIndex(db);
400 index2.filemode = Boolean.FALSE; // TODO: we need a way to set this using config
401 index2.read();
402 index2.checkout(trash);
403 assertFalse(((Boolean)canExecute.invoke(execFile,(Object[])null)).booleanValue());
404 assertFalse(((Boolean)canExecute.invoke(nonexecFile,(Object[])null)).booleanValue());
406 assertFalse(index2.getEntry(execFile.getName()).isModified(trash));
407 assertFalse(index2.getEntry(nonexecFile.getName()).isModified(trash));
409 if (!((Boolean)setExecute.invoke(execFile, new Object[] { Boolean.FALSE })).booleanValue())
410 throw new Error("could not clear set execute bit on "+execFile.getAbsolutePath()+"for test");
411 if (!((Boolean)setExecute.invoke(nonexecFile, new Object[] { Boolean.TRUE })).booleanValue())
412 throw new Error("could set execute bit on "+nonexecFile.getAbsolutePath()+"for test");
414 // no change since we ignore the execute bit
415 assertFalse(index2.getEntry(execFile.getName()).isModified(trash));
416 assertFalse(index2.getEntry(nonexecFile.getName()).isModified(trash));
418 } catch (NoSuchMethodException e) {
419 System.err.println("Test ignored when running under JDk < 1.6");
420 return;
424 private String content(File f) throws IOException {
425 byte[] buf = new byte[(int) f.length()];
426 FileInputStream is = new FileInputStream(f);
427 int read = is.read(buf);
428 assertEquals(f.length(), read);
429 return new String(buf, 0);
432 private void delete(File f) throws IOException {
433 if (!f.delete())
434 throw new IOException("Failed to delete f");