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