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