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 package org.eclipse.jgit.lib;
44
45 import static java.lang.Long.valueOf;
46 import static org.junit.Assert.assertEquals;
47 import static org.junit.Assert.assertTrue;
48
49 import java.io.File;
50 import java.io.FileOutputStream;
51 import java.io.IOException;
52 import java.util.TreeSet;
53
54 import org.eclipse.jgit.junit.RepositoryTestCase;
55 import org.eclipse.jgit.treewalk.FileTreeIterator;
56 import org.eclipse.jgit.treewalk.FileTreeIteratorWithTimeControl;
57 import org.eclipse.jgit.treewalk.NameConflictTreeWalk;
58 import org.eclipse.jgit.util.FileUtils;
59
60 public class RacyGitTests extends RepositoryTestCase {
61 public void testIterator() throws IllegalStateException, IOException,
62 InterruptedException {
63 TreeSet<Long> modTimes = new TreeSet<Long>();
64 File lastFile = null;
65 for (int i = 0; i < 10; i++) {
66 lastFile = new File(db.getWorkTree(), "0." + i);
67 FileUtils.createNewFile(lastFile);
68 if (i == 5)
69 fsTick(lastFile);
70 }
71 modTimes.add(valueOf(fsTick(lastFile)));
72 for (int i = 0; i < 10; i++) {
73 lastFile = new File(db.getWorkTree(), "1." + i);
74 FileUtils.createNewFile(lastFile);
75 }
76 modTimes.add(valueOf(fsTick(lastFile)));
77 for (int i = 0; i < 10; i++) {
78 lastFile = new File(db.getWorkTree(), "2." + i);
79 FileUtils.createNewFile(lastFile);
80 if (i % 4 == 0)
81 fsTick(lastFile);
82 }
83 FileTreeIteratorWithTimeControl fileIt = new FileTreeIteratorWithTimeControl(
84 db, modTimes);
85 NameConflictTreeWalk tw = new NameConflictTreeWalk(db);
86 tw.addTree(fileIt);
87 tw.setRecursive(true);
88 FileTreeIterator t;
89 long t0 = 0;
90 for (int i = 0; i < 10; i++) {
91 assertTrue(tw.next());
92 t = tw.getTree(0, FileTreeIterator.class);
93 if (i == 0)
94 t0 = t.getEntryLastModified();
95 else
96 assertEquals(t0, t.getEntryLastModified());
97 }
98 long t1 = 0;
99 for (int i = 0; i < 10; i++) {
100 assertTrue(tw.next());
101 t = tw.getTree(0, FileTreeIterator.class);
102 if (i == 0) {
103 t1 = t.getEntryLastModified();
104 assertTrue(t1 > t0);
105 } else
106 assertEquals(t1, t.getEntryLastModified());
107 }
108 long t2 = 0;
109 for (int i = 0; i < 10; i++) {
110 assertTrue(tw.next());
111 t = tw.getTree(0, FileTreeIterator.class);
112 if (i == 0) {
113 t2 = t.getEntryLastModified();
114 assertTrue(t2 > t1);
115 } else
116 assertEquals(t2, t.getEntryLastModified());
117 }
118 }
119
120 public void testRacyGitDetection() throws IOException,
121 IllegalStateException, InterruptedException {
122 TreeSet<Long> modTimes = new TreeSet<Long>();
123 File lastFile;
124
125
126
127 modTimes.add(valueOf(fsTick(db.getIndexFile())));
128
129
130 addToWorkDir("a", "a");
131 lastFile = addToWorkDir("b", "b");
132
133
134
135 modTimes.add(valueOf(fsTick(lastFile)));
136
137
138 resetIndex(new FileTreeIteratorWithTimeControl(db, modTimes));
139
140 assertEquals(
141 "[a, mode:100644, time:t0, length:1, content:a]" +
142 "[b, mode:100644, time:t0, length:1, content:b]",
143 indexState(SMUDGE | MOD_TIME | LENGTH | CONTENT));
144
145
146
147
148 modTimes.add(Long.valueOf(db.getIndexFile().lastModified()));
149
150
151 addToWorkDir("a", "a2");
152
153
154
155 resetIndex(new FileTreeIteratorWithTimeControl(db, modTimes));
156
157 db.readDirCache();
158
159 assertEquals(
160 "[a, mode:100644, time:t1, smudged, length:0, content:a2]" +
161 "[b, mode:100644, time:t0, length:1, content:b]",
162 indexState(SMUDGE|MOD_TIME|LENGTH|CONTENT));
163 }
164
165 private File addToWorkDir(String path, String content) throws IOException {
166 File f = new File(db.getWorkTree(), path);
167 FileOutputStream fos = new FileOutputStream(f);
168 try {
169 fos.write(content.getBytes(Constants.CHARACTER_ENCODING));
170 return f;
171 } finally {
172 fos.close();
173 }
174 }
175 }