Mercurial > public > mercurial-scm > hg
comparison mercurial/sparse.py @ 42456:87a34c767384
merge: fix race that could cause wrong size in dirstate
The problem is that hg merge/update/etc work the following way:
1. figure out what files to update
2. apply the update to disk
3. apply the update to in-memory dirstate
4. write dirstate
where step3 looks at the filesystem and assumes it sees the result of
step2. If a file is changed between step2 and step3, step3 will record
incorrect information in the dirstate.
I avoid this by passing the size step3 needs directly from step2, for
the common path (not implemented for change/delete conflicts for
instance).
I didn't fix the same race for the exec bit for now, because it's less
likely to be problematic and I had trouble due to the fact that the
dirstate stores the permissions differently from the manifest (st_mode
vs '' 'l' 'x'), in combination with tests that pretend that symlinks
are not supported.
However, I moved the lstat from step3 to step2, which should tighten
the race window markedly, both for the exec bit and for the mtime.
Differential Revision: https://phab.mercurial-scm.org/D6475
author | Valentin Gatien-Baron <valentin.gatienbaron@gmail.com> |
---|---|
date | Mon, 27 May 2019 16:55:46 -0400 |
parents | aaad36b88298 |
children | 2372284d9457 |
comparison
equal
deleted
inserted
replaced
42455:5ca136bbd3f6 | 42456:87a34c767384 |
---|---|
246 actions.append((file, None, message)) | 246 actions.append((file, None, message)) |
247 dropped.append(file) | 247 dropped.append(file) |
248 | 248 |
249 typeactions = mergemod.emptyactions() | 249 typeactions = mergemod.emptyactions() |
250 typeactions['r'] = actions | 250 typeactions['r'] = actions |
251 mergemod.applyupdates(repo, typeactions, repo[None], repo['.'], False) | 251 mergemod.applyupdates(repo, typeactions, repo[None], repo['.'], False, |
252 wantfiledata=False) | |
252 | 253 |
253 # Fix dirstate | 254 # Fix dirstate |
254 for file in dropped: | 255 for file in dropped: |
255 dirstate.drop(file) | 256 dirstate.drop(file) |
256 | 257 |
380 actions.append((file, (fctx.flags(), False), message)) | 381 actions.append((file, (fctx.flags(), False), message)) |
381 | 382 |
382 typeactions = mergemod.emptyactions() | 383 typeactions = mergemod.emptyactions() |
383 typeactions['g'] = actions | 384 typeactions['g'] = actions |
384 mergemod.applyupdates(repo, typeactions, repo[None], repo['.'], | 385 mergemod.applyupdates(repo, typeactions, repo[None], repo['.'], |
385 False) | 386 False, wantfiledata=False) |
386 | 387 |
387 dirstate = repo.dirstate | 388 dirstate = repo.dirstate |
388 for file, flags, msg in actions: | 389 for file, flags, msg in actions: |
389 dirstate.normal(file) | 390 dirstate.normal(file) |
390 | 391 |
484 # Apply changes to disk | 485 # Apply changes to disk |
485 typeactions = mergemod.emptyactions() | 486 typeactions = mergemod.emptyactions() |
486 for f, (m, args, msg) in actions.iteritems(): | 487 for f, (m, args, msg) in actions.iteritems(): |
487 typeactions[m].append((f, args, msg)) | 488 typeactions[m].append((f, args, msg)) |
488 | 489 |
489 mergemod.applyupdates(repo, typeactions, repo[None], repo['.'], False) | 490 mergemod.applyupdates(repo, typeactions, repo[None], repo['.'], False, |
491 wantfiledata=False) | |
490 | 492 |
491 # Fix dirstate | 493 # Fix dirstate |
492 for file in added: | 494 for file in added: |
493 dirstate.normal(file) | 495 dirstate.normal(file) |
494 | 496 |