Mercurial > hg
comparison hgext/largefiles/overrides.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 | 1eb2fc21da12 |
children | 421fdf30c37c |
comparison
equal
deleted
inserted
replaced
42455:5ca136bbd3f6 | 42456:87a34c767384 |
---|---|
513 actions[standin] = ('r', None, 'replaced by non-standin') | 513 actions[standin] = ('r', None, 'replaced by non-standin') |
514 | 514 |
515 return actions, diverge, renamedelete | 515 return actions, diverge, renamedelete |
516 | 516 |
517 @eh.wrapfunction(merge, 'recordupdates') | 517 @eh.wrapfunction(merge, 'recordupdates') |
518 def mergerecordupdates(orig, repo, actions, branchmerge): | 518 def mergerecordupdates(orig, repo, actions, branchmerge, getfiledata): |
519 if 'lfmr' in actions: | 519 if 'lfmr' in actions: |
520 lfdirstate = lfutil.openlfdirstate(repo.ui, repo) | 520 lfdirstate = lfutil.openlfdirstate(repo.ui, repo) |
521 for lfile, args, msg in actions['lfmr']: | 521 for lfile, args, msg in actions['lfmr']: |
522 # this should be executed before 'orig', to execute 'remove' | 522 # this should be executed before 'orig', to execute 'remove' |
523 # before all other actions | 523 # before all other actions |
524 repo.dirstate.remove(lfile) | 524 repo.dirstate.remove(lfile) |
525 # make sure lfile doesn't get synclfdirstate'd as normal | 525 # make sure lfile doesn't get synclfdirstate'd as normal |
526 lfdirstate.add(lfile) | 526 lfdirstate.add(lfile) |
527 lfdirstate.write() | 527 lfdirstate.write() |
528 | 528 |
529 return orig(repo, actions, branchmerge) | 529 return orig(repo, actions, branchmerge, getfiledata) |
530 | 530 |
531 # Override filemerge to prompt the user about how they wish to merge | 531 # Override filemerge to prompt the user about how they wish to merge |
532 # largefiles. This will handle identical edits without prompting the user. | 532 # largefiles. This will handle identical edits without prompting the user. |
533 @eh.wrapfunction(filemerge, '_filemerge') | 533 @eh.wrapfunction(filemerge, '_filemerge') |
534 def overridefilemerge(origfn, premerge, repo, wctx, mynode, orig, fcd, fco, fca, | 534 def overridefilemerge(origfn, premerge, repo, wctx, mynode, orig, fcd, fco, fca, |