##// END OF EJS Templates
dirstate: test a `hg status` raced by another `hg status`...
marmoute -
r51114:72104dd9 stable
parent child Browse files
Show More
@@ -1,361 +1,410 b''
1 1 =====================================================================
2 2 Check potential race conditions between a status and other operations
3 3 =====================================================================
4 4
5 5 The `hg status` command can run without the wlock, however it might end up
6 6 having to update the on-disk dirstate files, for example to mark ambiguous
7 7 files as clean, or to update directory caches information with dirstate-v2.
8 8
9 9
10 10 If another process updates the dirstate in the meantime we might run into
11 11 trouble. Especially, commands doing semantic changes like `hg add` or
12 12 `hg commit` should not see their update erased by a concurrent status.
13 13
14 14 Unlike commands like `add` or `commit`, `status` only writes the dirstate
15 15 to update caches, no actual information is lost if we fail to write to disk.
16 16
17 17
18 18 This test file is meant to test various cases where such parallel operations
19 19 between a status with reasons to update the dirstate and another semantic
20 20 changes happen.
21 21
22 22
23 23 Setup
24 24 =====
25 25
26 26 $ directories="dir dir/nested dir2"
27 27 $ first_files="dir/nested/a dir/b dir/c dir/d dir2/e f"
28 28 $ second_files="g dir/nested/h dir/i dir/j dir2/k dir2/l dir/nested/m"
29 29 $ extra_files="dir/n dir/o p q"
30 30
31 31 $ hg init reference-repo
32 32 $ cd reference-repo
33 33 $ mkdir -p dir/nested dir2
34 34 $ touch -t 200001010000 $first_files $directories
35 35 $ hg commit -Aqm "recreate a bunch of files to facilitate dirstate-v2 append"
36 36 $ touch -t 200001010010 $second_files $directories
37 37 $ hg commit -Aqm "more files to have two commits"
38 38 $ hg log -G -v
39 39 @ changeset: 1:c349430a1631
40 40 | tag: tip
41 41 | user: test
42 42 | date: Thu Jan 01 00:00:00 1970 +0000
43 43 | files: dir/i dir/j dir/nested/h dir/nested/m dir2/k dir2/l g
44 44 | description:
45 45 | more files to have two commits
46 46 |
47 47 |
48 48 o changeset: 0:4f23db756b09
49 49 user: test
50 50 date: Thu Jan 01 00:00:00 1970 +0000
51 51 files: dir/b dir/c dir/d dir/nested/a dir2/e f
52 52 description:
53 53 recreate a bunch of files to facilitate dirstate-v2 append
54 54
55 55
56 56 $ hg manifest
57 57 dir/b
58 58 dir/c
59 59 dir/d
60 60 dir/i
61 61 dir/j
62 62 dir/nested/a
63 63 dir/nested/h
64 64 dir/nested/m
65 65 dir2/e
66 66 dir2/k
67 67 dir2/l
68 68 f
69 69 g
70 70
71 71 Add some unknown files and refresh the dirstate
72 72
73 73 $ touch -t 200001010020 $extra_files
74 74 $ hg add dir/o
75 75 $ hg remove dir/nested/m
76 76
77 77 $ hg st
78 78 A dir/o
79 79 R dir/nested/m
80 80 ? dir/n
81 81 ? p
82 82 ? q
83 83 $ hg debugstate
84 84 n 644 0 2000-01-01 00:00:00 dir/b
85 85 n 644 0 2000-01-01 00:00:00 dir/c
86 86 n 644 0 2000-01-01 00:00:00 dir/d
87 87 n 644 0 2000-01-01 00:10:00 dir/i
88 88 n 644 0 2000-01-01 00:10:00 dir/j
89 89 n 644 0 2000-01-01 00:00:00 dir/nested/a
90 90 n 644 0 2000-01-01 00:10:00 dir/nested/h
91 91 r ?????????????????????????????????? dir/nested/m (glob)
92 92 a ?????????????????????????????????? dir/o (glob)
93 93 n 644 0 2000-01-01 00:00:00 dir2/e
94 94 n 644 0 2000-01-01 00:10:00 dir2/k
95 95 n 644 0 2000-01-01 00:10:00 dir2/l
96 96 n 644 0 2000-01-01 00:00:00 f
97 97 n 644 0 2000-01-01 00:10:00 g
98 98 $ hg debugstate > ../reference
99 99 $ cd ..
100 100
101 101 Explain / verify the test principles
102 102 ------------------------------------
103 103
104 104 First, we can properly copy the reference
105 105
106 106 $ cp -a reference-repo sanity-check
107 107 $ cd sanity-check
108 108 $ hg debugstate
109 109 n 644 0 2000-01-01 00:00:00 dir/b
110 110 n 644 0 2000-01-01 00:00:00 dir/c
111 111 n 644 0 2000-01-01 00:00:00 dir/d
112 112 n 644 0 2000-01-01 00:10:00 dir/i
113 113 n 644 0 2000-01-01 00:10:00 dir/j
114 114 n 644 0 2000-01-01 00:00:00 dir/nested/a
115 115 n 644 0 2000-01-01 00:10:00 dir/nested/h
116 116 r ?????????????????????????????????? dir/nested/m (glob)
117 117 a ?????????????????????????????????? dir/o (glob)
118 118 n 644 0 2000-01-01 00:00:00 dir2/e
119 119 n 644 0 2000-01-01 00:10:00 dir2/k
120 120 n 644 0 2000-01-01 00:10:00 dir2/l
121 121 n 644 0 2000-01-01 00:00:00 f
122 122 n 644 0 2000-01-01 00:10:00 g
123 123 $ hg debugstate > ../post-copy
124 124 $ diff ../reference ../post-copy
125 125
126 126 And status thinks the cache is in a proper state
127 127
128 128 $ hg st
129 129 A dir/o
130 130 R dir/nested/m
131 131 ? dir/n
132 132 ? p
133 133 ? q
134 134 $ hg debugstate
135 135 n 644 0 2000-01-01 00:00:00 dir/b
136 136 n 644 0 2000-01-01 00:00:00 dir/c
137 137 n 644 0 2000-01-01 00:00:00 dir/d
138 138 n 644 0 2000-01-01 00:10:00 dir/i
139 139 n 644 0 2000-01-01 00:10:00 dir/j
140 140 n 644 0 2000-01-01 00:00:00 dir/nested/a
141 141 n 644 0 2000-01-01 00:10:00 dir/nested/h
142 142 r ?????????????????????????????????? dir/nested/m (glob)
143 143 a ?????????????????????????????????? dir/o (glob)
144 144 n 644 0 2000-01-01 00:00:00 dir2/e
145 145 n 644 0 2000-01-01 00:10:00 dir2/k
146 146 n 644 0 2000-01-01 00:10:00 dir2/l
147 147 n 644 0 2000-01-01 00:00:00 f
148 148 n 644 0 2000-01-01 00:10:00 g
149 149 $ hg debugstate > ../post-status
150 150 $ diff ../reference ../post-status
151 151
152 152 Then we can start a status that:
153 153 - has some update to do (the touch call)
154 154 - will wait AFTER running status, but before updating the cache on disk
155 155
156 156 $ touch -t 200001010001 dir/c
157 157 $ hg st >$TESTTMP/status-race-lock.out 2>$TESTTMP/status-race-lock.log \
158 158 > --config rhg.on-unsupported=abort \
159 159 > --config devel.sync.status.pre-dirstate-write-file=$TESTTMP/status-race-lock \
160 160 > &
161 161 $ $RUNTESTDIR/testlib/wait-on-file 5 $TESTTMP/status-race-lock.waiting
162 162
163 163 We check it runs the status first by modifying a file and updating another timestamp
164 164
165 165 $ touch -t 200001010003 dir/i
166 166 $ echo babar > dir/j
167 167 $ touch $TESTTMP/status-race-lock
168 168 $ wait
169 169
170 170 The test process should have reported a status before the change we made,
171 171 and should have missed the timestamp update
172 172
173 173 $ cat $TESTTMP/status-race-lock.out
174 174 A dir/o
175 175 R dir/nested/m
176 176 ? dir/n
177 177 ? p
178 178 ? q
179 179 $ cat $TESTTMP/status-race-lock.log
180 180 $ hg debugstate | grep dir/c
181 181 n 644 0 2000-01-01 00:01:00 dir/c
182 182 $ hg debugstate | grep dir/i
183 183 n 644 0 2000-01-01 00:10:00 dir/i
184 184 $ hg debugstate | grep dir/j
185 185 n 644 0 2000-01-01 00:10:00 dir/j
186 186
187 187 final cleanup
188 188
189 189 $ rm $TESTTMP/status-race-lock $TESTTMP/status-race-lock.waiting
190 190 $ cd ..
191 191
192 192 Actual Testing
193 193 ==============
194 194
195 195 Race with a `hg add`
196 196 -------------------
197 197
198 198 $ cp -a reference-repo race-with-add
199 199 $ cd race-with-add
200 200
201 201 spin a `hg status` with some caches to update
202 202
203 203 $ touch -t 200001020001 f
204 204 $ hg st >$TESTTMP/status-race-lock.out 2>$TESTTMP/status-race-lock.log \
205 205 > --config rhg.on-unsupported=abort \
206 206 > --config devel.sync.status.pre-dirstate-write-file=$TESTTMP/status-race-lock \
207 207 > &
208 208 $ $RUNTESTDIR/testlib/wait-on-file 5 $TESTTMP/status-race-lock.waiting
209 209
210 210 Add a file
211 211
212 212 $ hg add dir/n
213 213 $ touch $TESTTMP/status-race-lock
214 214 $ wait
215 215
216 216 The file should in a "added" state
217 217
218 218 $ hg status
219 219 A dir/n (no-rhg !)
220 220 A dir/n (missing-correct-output rhg !)
221 221 A dir/o
222 222 R dir/nested/m
223 223 ? dir/n (known-bad-output rhg !)
224 224 ? p
225 225 ? q
226 226
227 227 The status process should return a consistent result and not crash.
228 228
229 229 $ cat $TESTTMP/status-race-lock.out
230 230 A dir/o
231 231 R dir/nested/m
232 232 ? dir/n
233 233 ? p
234 234 ? q
235 235 $ cat $TESTTMP/status-race-lock.log
236 236
237 237 final cleanup
238 238
239 239 $ rm $TESTTMP/status-race-lock $TESTTMP/status-race-lock.waiting
240 240 $ cd ..
241 241
242 242 Race with a `hg commit`
243 243 ----------------------
244 244
245 245 $ cp -a reference-repo race-with-commit
246 246 $ cd race-with-commit
247 247
248 248 spin a `hg status` with some caches to update
249 249
250 250 $ touch -t 200001020001 dir/j
251 251 $ hg st >$TESTTMP/status-race-lock.out 2>$TESTTMP/status-race-lock.log \
252 252 > --config rhg.on-unsupported=abort \
253 253 > --config devel.sync.status.pre-dirstate-write-file=$TESTTMP/status-race-lock \
254 254 > &
255 255 $ $RUNTESTDIR/testlib/wait-on-file 5 $TESTTMP/status-race-lock.waiting
256 256
257 257 Add a file and force the data file rewrite
258 258
259 259 $ hg commit -m created-during-status dir/o
260 260 $ touch $TESTTMP/status-race-lock
261 261 $ wait
262 262
263 263 The parent must change and the status should be clean
264 264
265 265 # XXX rhg misbehaves here
266 266 #if no-rhg
267 267 $ hg summary
268 268 parent: 2:2e3b442a2fd4 tip
269 269 created-during-status
270 270 branch: default
271 271 commit: 1 removed, 3 unknown
272 272 update: (current)
273 273 phases: 3 draft
274 274 $ hg status
275 275 R dir/nested/m
276 276 ? dir/n
277 277 ? p
278 278 ? q
279 279 #else
280 280 $ hg summary
281 281 parent: 1:c349430a1631
282 282 more files to have two commits
283 283 branch: default
284 284 commit: 1 added, 1 removed, 3 unknown (new branch head)
285 285 update: 1 new changesets (update)
286 286 phases: 3 draft
287 287 $ hg status
288 288 A dir/o
289 289 R dir/nested/m
290 290 ? dir/n
291 291 ? p
292 292 ? q
293 293 #endif
294 294
295 295 The status process should return a consistent result and not crash.
296 296
297 297 $ cat $TESTTMP/status-race-lock.out
298 298 A dir/o
299 299 R dir/nested/m
300 300 ? dir/n
301 301 ? p
302 302 ? q
303 303 $ cat $TESTTMP/status-race-lock.log
304 304
305 305 final cleanup
306 306
307 307 $ rm $TESTTMP/status-race-lock $TESTTMP/status-race-lock.waiting
308 308 $ cd ..
309 309
310 310 Race with a `hg update`
311 311 ----------------------
312 312
313 313 $ cp -a reference-repo race-with-update
314 314 $ cd race-with-update
315 315
316 316 spin a `hg status` with some caches to update
317 317
318 318 $ touch -t 200001020001 dir2/k
319 319 $ hg st >$TESTTMP/status-race-lock.out 2>$TESTTMP/status-race-lock.log \
320 320 > --config rhg.on-unsupported=abort \
321 321 > --config devel.sync.status.pre-dirstate-write-file=$TESTTMP/status-race-lock \
322 322 > &
323 323 $ $RUNTESTDIR/testlib/wait-on-file 5 $TESTTMP/status-race-lock.waiting
324 324
325 325 Add a file and force the data file rewrite
326 326
327 327 $ hg update ".~1"
328 328 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
329 329 $ touch $TESTTMP/status-race-lock
330 330 $ wait
331 331
332 332 The parent must change and the status should be clean
333 333
334 334 $ hg summary
335 335 parent: 0:4f23db756b09
336 336 recreate a bunch of files to facilitate dirstate-v2 append
337 337 branch: default
338 338 commit: 1 added, 3 unknown (new branch head)
339 339 update: 1 new changesets (update)
340 340 phases: 2 draft
341 341 $ hg status
342 342 A dir/o
343 343 ? dir/n
344 344 ? p
345 345 ? q
346 346
347 347 The status process should return a consistent result and not crash.
348 348
349 349 $ cat $TESTTMP/status-race-lock.out
350 350 A dir/o
351 351 R dir/nested/m
352 352 ? dir/n
353 353 ? p
354 354 ? q
355 355 $ cat $TESTTMP/status-race-lock.log
356 356 abort: when reading $TESTTMP/race-with-update/dir2/k: $ENOENT$ (known-bad-output rhg !)
357 357
358 358 final cleanup
359 359
360 360 $ rm $TESTTMP/status-race-lock $TESTTMP/status-race-lock.waiting
361 361 $ cd ..
362
363 Race with another status
364 ------------------------
365
366 $ cp -a reference-repo race-with-status
367 $ cd race-with-status
368
369 spin a `hg status` with some caches to update
370
371 $ touch -t 200001010030 dir/nested/h
372 $ hg st >$TESTTMP/status-race-lock.out 2>$TESTTMP/status-race-lock.log \
373 > --config rhg.on-unsupported=abort \
374 > --config devel.sync.status.pre-dirstate-write-file=$TESTTMP/status-race-lock \
375 > &
376 $ $RUNTESTDIR/testlib/wait-on-file 5 $TESTTMP/status-race-lock.waiting
377
378 touch g
379
380 $ touch -t 200001010025 g
381 $ hg status
382 A dir/o
383 R dir/nested/m
384 ? dir/n
385 ? p
386 ? q
387 $ touch $TESTTMP/status-race-lock
388 $ wait
389
390 the first update should be on disk
391
392 $ hg debugstate --all | grep "g"
393 n 644 0 2000-01-01 00:25:00 g (no-rhg !)
394 n 644 0 2000-01-01 00:25:00 g (missing-correct-output rhg !)
395 n 644 0 2000-01-01 00:10:00 g (known-bad-output rhg !)
396
397 The status process should return a consistent result and not crash.
398
399 $ cat $TESTTMP/status-race-lock.out
400 A dir/o
401 R dir/nested/m
402 ? dir/n
403 ? p
404 ? q
405 $ cat $TESTTMP/status-race-lock.log
406
407 final cleanup
408
409 $ rm $TESTTMP/status-race-lock $TESTTMP/status-race-lock.waiting
410 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now