2 * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
3 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
7 * Redistribution and use in source and binary forms, with or
8 * without modification, are permitted provided that the following
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
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
;
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
;
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
) {
63 private static int system(File dir
, String cmd
) throws IOException
,
64 InterruptedException
{
65 final Process process
= Runtime
.getRuntime().exec(cmd
, null, dir
);
69 InputStream s
= process
.getErrorStream();
70 for (int c
= s
.read(); c
!= -1; c
= s
.read()) {
71 System
.err
.print((char) c
);
74 } catch (IOException e1
) {
75 // TODO Auto-generated catch block
80 final Thread t2
= new Thread() {
84 InputStream e
= process
.getInputStream();
85 for (int c
= e
.read(); c
!= -1; c
= e
.read()) {
86 System
.out
.print((char) c
);
89 } catch (IOException e1
) {
90 // TODO Auto-generated catch block
97 process
.getOutputStream().close();
98 int ret
= process
.waitFor();
104 public void testCreateEmptyIndex() throws Exception
{
105 GitIndex index
= new GitIndex(db
);
107 // native git doesn't like an empty index
108 // assertEquals(0,system(trash,"git status"));
110 GitIndex indexr
= new GitIndex(db
);
112 assertEquals(0, indexr
.getMembers().length
);
115 public void testReadWithNoIndex() throws Exception
{
116 GitIndex index
= new GitIndex(db
);
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"));
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
);
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"));
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"));
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"));
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"));
180 assertEquals(0, system(trash
, "git status"));
183 public void testReadTree() throws Exception
{
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"));
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
);
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
);
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
);
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());
254 GitIndex indexr
= new GitIndex(db
);
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"));
276 index
.remove(trash
, new File(trash
, "a:b"));
278 assertEquals("a.b", index
.getMembers()[0].getName());
279 assertEquals("a/b", index
.getMembers()[1].getName());
281 GitIndex indexr
= new GitIndex(db
);
283 assertEquals("a.b", indexr
.getMembers()[0].getName());
284 assertEquals("a/b", indexr
.getMembers()[1].getName());
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
);
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
));
318 assertEquals(0, system(trash
, "git status"));
321 public void test030_executeBit_coreModeTrue() throws IllegalArgumentException
, IllegalAccessException
, InvocationTargetException
, Error
, Exception
{
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());
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
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");
372 public void test031_executeBit_coreModeFalse() throws IllegalArgumentException
, IllegalAccessException
, InvocationTargetException
, Error
, Exception
{
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());
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
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");
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
{
434 throw new IOException("Failed to delete f");