Show More
@@ -515,7 +515,7 b' def overridecalculateupdates(origfn, rep' | |||||
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']: | |
@@ -526,7 +526,7 b' def mergerecordupdates(orig, repo, actio' | |||||
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. |
@@ -16,21 +16,21 b' def wrapdirstate(repo, dirstate):' | |||||
16 | """Add narrow spec dirstate ignore, block changes outside narrow spec.""" |
|
16 | """Add narrow spec dirstate ignore, block changes outside narrow spec.""" | |
17 |
|
17 | |||
18 | def _editfunc(fn): |
|
18 | def _editfunc(fn): | |
19 | def _wrapper(self, *args): |
|
19 | def _wrapper(self, *args, **kwargs): | |
20 | narrowmatch = repo.narrowmatch() |
|
20 | narrowmatch = repo.narrowmatch() | |
21 | for f in args: |
|
21 | for f in args: | |
22 | if f is not None and not narrowmatch(f) and f not in self: |
|
22 | if f is not None and not narrowmatch(f) and f not in self: | |
23 | raise error.Abort(_("cannot track '%s' - it is outside " + |
|
23 | raise error.Abort(_("cannot track '%s' - it is outside " + | |
24 | "the narrow clone") % f) |
|
24 | "the narrow clone") % f) | |
25 | return fn(self, *args) |
|
25 | return fn(self, *args, **kwargs) | |
26 | return _wrapper |
|
26 | return _wrapper | |
27 |
|
27 | |||
28 | class narrowdirstate(dirstate.__class__): |
|
28 | class narrowdirstate(dirstate.__class__): | |
29 | # Prevent adding/editing/copying/deleting files that are outside the |
|
29 | # Prevent adding/editing/copying/deleting files that are outside the | |
30 | # sparse checkout |
|
30 | # sparse checkout | |
31 | @_editfunc |
|
31 | @_editfunc | |
32 | def normal(self, *args): |
|
32 | def normal(self, *args, **kwargs): | |
33 | return super(narrowdirstate, self).normal(*args) |
|
33 | return super(narrowdirstate, self).normal(*args, **kwargs) | |
34 |
|
34 | |||
35 | @_editfunc |
|
35 | @_editfunc | |
36 | def add(self, *args): |
|
36 | def add(self, *args): |
@@ -442,7 +442,8 b' def storewrapper(orig, requirements, pat' | |||||
442 | return s |
|
442 | return s | |
443 |
|
443 | |||
444 | # prefetch files before update |
|
444 | # prefetch files before update | |
445 |
def applyupdates(orig, repo, actions, wctx, mctx, overwrite, |
|
445 | def applyupdates(orig, repo, actions, wctx, mctx, overwrite, wantfiledata, | |
|
446 | labels=None): | |||
446 | if isenabled(repo): |
|
447 | if isenabled(repo): | |
447 | manifest = mctx.manifest() |
|
448 | manifest = mctx.manifest() | |
448 | files = [] |
|
449 | files = [] | |
@@ -450,7 +451,8 b' def applyupdates(orig, repo, actions, wc' | |||||
450 | files.append((f, hex(manifest[f]))) |
|
451 | files.append((f, hex(manifest[f]))) | |
451 | # batch fetch the needed files from the server |
|
452 | # batch fetch the needed files from the server | |
452 | repo.fileservice.prefetch(files) |
|
453 | repo.fileservice.prefetch(files) | |
453 |
return orig(repo, actions, wctx, mctx, overwrite, |
|
454 | return orig(repo, actions, wctx, mctx, overwrite, wantfiledata, | |
|
455 | labels=labels) | |||
454 |
|
456 | |||
455 | # Prefetch merge checkunknownfiles |
|
457 | # Prefetch merge checkunknownfiles | |
456 | def checkunknownfiles(orig, repo, wctx, mctx, force, actions, |
|
458 | def checkunknownfiles(orig, repo, wctx, mctx, force, actions, |
@@ -228,7 +228,7 b' def _setupdirstate(ui):' | |||||
228 | hint = _('include file with `hg debugsparse --include <pattern>` or use ' + |
|
228 | hint = _('include file with `hg debugsparse --include <pattern>` or use ' + | |
229 | '`hg add -s <file>` to include file directory while adding') |
|
229 | '`hg add -s <file>` to include file directory while adding') | |
230 | for func in editfuncs: |
|
230 | for func in editfuncs: | |
231 | def _wrapper(orig, self, *args): |
|
231 | def _wrapper(orig, self, *args, **kwargs): | |
232 | sparsematch = self._sparsematcher |
|
232 | sparsematch = self._sparsematcher | |
233 | if not sparsematch.always(): |
|
233 | if not sparsematch.always(): | |
234 | for f in args: |
|
234 | for f in args: | |
@@ -237,7 +237,7 b' def _setupdirstate(ui):' | |||||
237 | raise error.Abort(_("cannot add '%s' - it is outside " |
|
237 | raise error.Abort(_("cannot add '%s' - it is outside " | |
238 | "the sparse checkout") % f, |
|
238 | "the sparse checkout") % f, | |
239 | hint=hint) |
|
239 | hint=hint) | |
240 | return orig(self, *args) |
|
240 | return orig(self, *args, **kwargs) | |
241 | extensions.wrapfunction(dirstate.dirstate, func, _wrapper) |
|
241 | extensions.wrapfunction(dirstate.dirstate, func, _wrapper) | |
242 |
|
242 | |||
243 | @command('debugsparse', [ |
|
243 | @command('debugsparse', [ |
@@ -1766,6 +1766,8 b' class workingfilectx(committablefilectx)' | |||||
1766 |
|
1766 | |||
1767 | def size(self): |
|
1767 | def size(self): | |
1768 | return self._repo.wvfs.lstat(self._path).st_size |
|
1768 | return self._repo.wvfs.lstat(self._path).st_size | |
|
1769 | def lstat(self): | |||
|
1770 | return self._repo.wvfs.lstat(self._path) | |||
1769 | def date(self): |
|
1771 | def date(self): | |
1770 | t, tz = self._changectx.date() |
|
1772 | t, tz = self._changectx.date() | |
1771 | try: |
|
1773 | try: | |
@@ -1801,9 +1803,9 b' class workingfilectx(committablefilectx)' | |||||
1801 |
|
1803 | |||
1802 | def write(self, data, flags, backgroundclose=False, **kwargs): |
|
1804 | def write(self, data, flags, backgroundclose=False, **kwargs): | |
1803 | """wraps repo.wwrite""" |
|
1805 | """wraps repo.wwrite""" | |
1804 | self._repo.wwrite(self._path, data, flags, |
|
1806 | return self._repo.wwrite(self._path, data, flags, | |
1805 | backgroundclose=backgroundclose, |
|
1807 | backgroundclose=backgroundclose, | |
1806 | **kwargs) |
|
1808 | **kwargs) | |
1807 |
|
1809 | |||
1808 | def markcopied(self, src): |
|
1810 | def markcopied(self, src): | |
1809 | """marks this file a copy of `src`""" |
|
1811 | """marks this file a copy of `src`""" |
@@ -391,12 +391,24 b' class dirstate(object):' | |||||
391 | self._updatedfiles.add(f) |
|
391 | self._updatedfiles.add(f) | |
392 | self._map.addfile(f, oldstate, state, mode, size, mtime) |
|
392 | self._map.addfile(f, oldstate, state, mode, size, mtime) | |
393 |
|
393 | |||
394 | def normal(self, f): |
|
394 | def normal(self, f, parentfiledata=None): | |
395 |
'''Mark a file normal and clean. |
|
395 | '''Mark a file normal and clean. | |
396 | s = os.lstat(self._join(f)) |
|
396 | ||
397 | mtime = s[stat.ST_MTIME] |
|
397 | parentfiledata: (mode, size, mtime) of the clean file | |
398 | self._addpath(f, 'n', s.st_mode, |
|
398 | ||
399 | s.st_size & _rangemask, mtime & _rangemask) |
|
399 | parentfiledata should be computed from memory (for mode, | |
|
400 | size), as or close as possible from the point where we | |||
|
401 | determined the file was clean, to limit the risk of the | |||
|
402 | file having been changed by an external process between the | |||
|
403 | moment where the file was determined to be clean and now.''' | |||
|
404 | if parentfiledata: | |||
|
405 | (mode, size, mtime) = parentfiledata | |||
|
406 | else: | |||
|
407 | s = os.lstat(self._join(f)) | |||
|
408 | mode = s.st_mode | |||
|
409 | size = s.st_size | |||
|
410 | mtime = s[stat.ST_MTIME] | |||
|
411 | self._addpath(f, 'n', mode, size & _rangemask, mtime & _rangemask) | |||
400 | self._map.copymap.pop(f, None) |
|
412 | self._map.copymap.pop(f, None) | |
401 | if f in self._map.nonnormalset: |
|
413 | if f in self._map.nonnormalset: | |
402 | self._map.nonnormalset.remove(f) |
|
414 | self._map.nonnormalset.remove(f) |
@@ -10,6 +10,7 b' from __future__ import absolute_import' | |||||
10 | import errno |
|
10 | import errno | |
11 | import hashlib |
|
11 | import hashlib | |
12 | import shutil |
|
12 | import shutil | |
|
13 | import stat | |||
13 | import struct |
|
14 | import struct | |
14 |
|
15 | |||
15 | from .i18n import _ |
|
16 | from .i18n import _ | |
@@ -683,7 +684,7 b' class mergestate(object):' | |||||
683 | def recordactions(self): |
|
684 | def recordactions(self): | |
684 | """record remove/add/get actions in the dirstate""" |
|
685 | """record remove/add/get actions in the dirstate""" | |
685 | branchmerge = self._repo.dirstate.p2() != nullid |
|
686 | branchmerge = self._repo.dirstate.p2() != nullid | |
686 | recordupdates(self._repo, self.actions(), branchmerge) |
|
687 | recordupdates(self._repo, self.actions(), branchmerge, None) | |
687 |
|
688 | |||
688 | def queueremove(self, f): |
|
689 | def queueremove(self, f): | |
689 | """queues a file to be removed from the dirstate |
|
690 | """queues a file to be removed from the dirstate | |
@@ -1464,13 +1465,17 b' def batchremove(repo, wctx, actions):' | |||||
1464 | repo.ui.warn(_("current directory was removed\n" |
|
1465 | repo.ui.warn(_("current directory was removed\n" | |
1465 | "(consider changing to repo root: %s)\n") % repo.root) |
|
1466 | "(consider changing to repo root: %s)\n") % repo.root) | |
1466 |
|
1467 | |||
1467 | def batchget(repo, mctx, wctx, actions): |
|
1468 | def batchget(repo, mctx, wctx, wantfiledata, actions): | |
1468 | """apply gets to the working directory |
|
1469 | """apply gets to the working directory | |
1469 |
|
1470 | |||
1470 | mctx is the context to get from |
|
1471 | mctx is the context to get from | |
1471 |
|
1472 | |||
1472 |
|
|
1473 | Yields arbitrarily many (False, tuple) for progress updates, followed by | |
|
1474 | exactly one (True, filedata). When wantfiledata is false, filedata is an | |||
|
1475 | empty list. When wantfiledata is true, filedata[i] is a triple (mode, size, | |||
|
1476 | mtime) of the file written for action[i]. | |||
1473 | """ |
|
1477 | """ | |
|
1478 | filedata = [] | |||
1474 | verbose = repo.ui.verbose |
|
1479 | verbose = repo.ui.verbose | |
1475 | fctx = mctx.filectx |
|
1480 | fctx = mctx.filectx | |
1476 | ui = repo.ui |
|
1481 | ui = repo.ui | |
@@ -1494,16 +1499,24 b' def batchget(repo, mctx, wctx, actions):' | |||||
1494 | if repo.wvfs.lexists(conflicting): |
|
1499 | if repo.wvfs.lexists(conflicting): | |
1495 | orig = scmutil.backuppath(ui, repo, conflicting) |
|
1500 | orig = scmutil.backuppath(ui, repo, conflicting) | |
1496 | util.rename(repo.wjoin(conflicting), orig) |
|
1501 | util.rename(repo.wjoin(conflicting), orig) | |
1497 |
wctx[f] |
|
1502 | wfctx = wctx[f] | |
|
1503 | wfctx.clearunknown() | |||
1498 | atomictemp = ui.configbool("experimental", "update.atomic-file") |
|
1504 | atomictemp = ui.configbool("experimental", "update.atomic-file") | |
1499 |
wctx |
|
1505 | size = wfctx.write(fctx(f).data(), flags, | |
1500 |
|
|
1506 | backgroundclose=True, | |
|
1507 | atomictemp=atomictemp) | |||
|
1508 | if wantfiledata: | |||
|
1509 | s = wfctx.lstat() | |||
|
1510 | mode = s.st_mode | |||
|
1511 | mtime = s[stat.ST_MTIME] | |||
|
1512 | filedata.append((mode, size, mtime)) # for dirstate.normal | |||
1501 | if i == 100: |
|
1513 | if i == 100: | |
1502 | yield i, f |
|
1514 | yield False, (i, f) | |
1503 | i = 0 |
|
1515 | i = 0 | |
1504 | i += 1 |
|
1516 | i += 1 | |
1505 | if i > 0: |
|
1517 | if i > 0: | |
1506 | yield i, f |
|
1518 | yield False, (i, f) | |
|
1519 | yield True, filedata | |||
1507 |
|
1520 | |||
1508 | def _prefetchfiles(repo, ctx, actions): |
|
1521 | def _prefetchfiles(repo, ctx, actions): | |
1509 | """Invoke ``scmutil.prefetchfiles()`` for the files relevant to the dict |
|
1522 | """Invoke ``scmutil.prefetchfiles()`` for the files relevant to the dict | |
@@ -1550,14 +1563,17 b' def emptyactions():' | |||||
1550 | ACTION_PATH_CONFLICT, |
|
1563 | ACTION_PATH_CONFLICT, | |
1551 | ACTION_PATH_CONFLICT_RESOLVE)) |
|
1564 | ACTION_PATH_CONFLICT_RESOLVE)) | |
1552 |
|
1565 | |||
1553 |
def applyupdates(repo, actions, wctx, mctx, overwrite, |
|
1566 | def applyupdates(repo, actions, wctx, mctx, overwrite, wantfiledata, | |
|
1567 | labels=None): | |||
1554 | """apply the merge action list to the working directory |
|
1568 | """apply the merge action list to the working directory | |
1555 |
|
1569 | |||
1556 | wctx is the working copy context |
|
1570 | wctx is the working copy context | |
1557 | mctx is the context to be merged into the working copy |
|
1571 | mctx is the context to be merged into the working copy | |
1558 |
|
1572 | |||
1559 | Return a tuple of counts (updated, merged, removed, unresolved) that |
|
1573 | Return a tuple of (counts, filedata), where counts is a tuple | |
1560 | describes how many files were affected by the update. |
|
1574 | (updated, merged, removed, unresolved) that describes how many | |
|
1575 | files were affected by the update, and filedata is as described in | |||
|
1576 | batchget. | |||
1561 | """ |
|
1577 | """ | |
1562 |
|
1578 | |||
1563 | _prefetchfiles(repo, mctx, actions) |
|
1579 | _prefetchfiles(repo, mctx, actions) | |
@@ -1649,11 +1665,18 b' def applyupdates(repo, actions, wctx, mc' | |||||
1649 | # get in parallel. |
|
1665 | # get in parallel. | |
1650 | threadsafe = repo.ui.configbool('experimental', |
|
1666 | threadsafe = repo.ui.configbool('experimental', | |
1651 | 'worker.wdir-get-thread-safe') |
|
1667 | 'worker.wdir-get-thread-safe') | |
1652 |
prog = worker.worker(repo.ui, cost, batchget, |
|
1668 | prog = worker.worker(repo.ui, cost, batchget, | |
|
1669 | (repo, mctx, wctx, wantfiledata), | |||
1653 | actions[ACTION_GET], |
|
1670 | actions[ACTION_GET], | |
1654 |
threadsafe=threadsafe |
|
1671 | threadsafe=threadsafe, | |
1655 | for i, item in prog: |
|
1672 | hasretval=True) | |
1656 | progress.increment(step=i, item=item) |
|
1673 | getfiledata = [] | |
|
1674 | for final, res in prog: | |||
|
1675 | if final: | |||
|
1676 | getfiledata = res | |||
|
1677 | else: | |||
|
1678 | i, item = res | |||
|
1679 | progress.increment(step=i, item=item) | |||
1657 | updated = len(actions[ACTION_GET]) |
|
1680 | updated = len(actions[ACTION_GET]) | |
1658 |
|
1681 | |||
1659 | if [a for a in actions[ACTION_GET] if a[0] == '.hgsubstate']: |
|
1682 | if [a for a in actions[ACTION_GET] if a[0] == '.hgsubstate']: | |
@@ -1778,6 +1801,9 b' def applyupdates(repo, actions, wctx, mc' | |||||
1778 | mfiles = set(a[0] for a in actions[ACTION_MERGE]) |
|
1801 | mfiles = set(a[0] for a in actions[ACTION_MERGE]) | |
1779 | for k, acts in extraactions.iteritems(): |
|
1802 | for k, acts in extraactions.iteritems(): | |
1780 | actions[k].extend(acts) |
|
1803 | actions[k].extend(acts) | |
|
1804 | if k == ACTION_GET and wantfiledata: | |||
|
1805 | # no filedata until mergestate is updated to provide it | |||
|
1806 | getfiledata.extend([None] * len(acts)) | |||
1781 | # Remove these files from actions[ACTION_MERGE] as well. This is |
|
1807 | # Remove these files from actions[ACTION_MERGE] as well. This is | |
1782 | # important because in recordupdates, files in actions[ACTION_MERGE] |
|
1808 | # important because in recordupdates, files in actions[ACTION_MERGE] | |
1783 | # are processed after files in other actions, and the merge driver |
|
1809 | # are processed after files in other actions, and the merge driver | |
@@ -1800,9 +1826,10 b' def applyupdates(repo, actions, wctx, mc' | |||||
1800 | if a[0] in mfiles] |
|
1826 | if a[0] in mfiles] | |
1801 |
|
1827 | |||
1802 | progress.complete() |
|
1828 | progress.complete() | |
1803 | return updateresult(updated, merged, removed, unresolved) |
|
1829 | assert len(getfiledata) == (len(actions[ACTION_GET]) if wantfiledata else 0) | |
|
1830 | return updateresult(updated, merged, removed, unresolved), getfiledata | |||
1804 |
|
1831 | |||
1805 | def recordupdates(repo, actions, branchmerge): |
|
1832 | def recordupdates(repo, actions, branchmerge, getfiledata): | |
1806 | "record merge actions to the dirstate" |
|
1833 | "record merge actions to the dirstate" | |
1807 | # remove (must come first) |
|
1834 | # remove (must come first) | |
1808 | for f, args, msg in actions.get(ACTION_REMOVE, []): |
|
1835 | for f, args, msg in actions.get(ACTION_REMOVE, []): | |
@@ -1846,11 +1873,12 b' def recordupdates(repo, actions, branchm' | |||||
1846 | pass |
|
1873 | pass | |
1847 |
|
1874 | |||
1848 | # get |
|
1875 | # get | |
1849 | for f, args, msg in actions.get(ACTION_GET, []): |
|
1876 | for i, (f, args, msg) in enumerate(actions.get(ACTION_GET, [])): | |
1850 | if branchmerge: |
|
1877 | if branchmerge: | |
1851 | repo.dirstate.otherparent(f) |
|
1878 | repo.dirstate.otherparent(f) | |
1852 | else: |
|
1879 | else: | |
1853 | repo.dirstate.normal(f) |
|
1880 | parentfiledata = getfiledata[i] if getfiledata else None | |
|
1881 | repo.dirstate.normal(f, parentfiledata=parentfiledata) | |||
1854 |
|
1882 | |||
1855 | # merge |
|
1883 | # merge | |
1856 | for f, args, msg in actions.get(ACTION_MERGE, []): |
|
1884 | for f, args, msg in actions.get(ACTION_MERGE, []): | |
@@ -2166,12 +2194,15 b' def update(repo, node, branchmerge, forc' | |||||
2166 | 'fsmonitor enabled; enable fsmonitor to improve performance; ' |
|
2194 | 'fsmonitor enabled; enable fsmonitor to improve performance; ' | |
2167 | 'see "hg help -e fsmonitor")\n')) |
|
2195 | 'see "hg help -e fsmonitor")\n')) | |
2168 |
|
2196 | |||
2169 | stats = applyupdates(repo, actions, wc, p2, overwrite, labels=labels) |
|
2197 | updatedirstate = not partial and not wc.isinmemory() | |
|
2198 | wantfiledata = updatedirstate and not branchmerge | |||
|
2199 | stats, getfiledata = applyupdates(repo, actions, wc, p2, overwrite, | |||
|
2200 | wantfiledata, labels=labels) | |||
2170 |
|
2201 | |||
2171 | if not partial and not wc.isinmemory(): |
|
2202 | if updatedirstate: | |
2172 | with repo.dirstate.parentchange(): |
|
2203 | with repo.dirstate.parentchange(): | |
2173 | repo.setparents(fp1, fp2) |
|
2204 | repo.setparents(fp1, fp2) | |
2174 | recordupdates(repo, actions, branchmerge) |
|
2205 | recordupdates(repo, actions, branchmerge, getfiledata) | |
2175 | # update completed, clear state |
|
2206 | # update completed, clear state | |
2176 | util.unlink(repo.vfs.join('updatestate')) |
|
2207 | util.unlink(repo.vfs.join('updatestate')) | |
2177 |
|
2208 |
@@ -259,7 +259,7 b' def _writeaddedfiles(repo, pctx, files):' | |||||
259 | if not repo.wvfs.exists(f): |
|
259 | if not repo.wvfs.exists(f): | |
260 | addgaction((f, (mf.flags(f), False), "narrowspec updated")) |
|
260 | addgaction((f, (mf.flags(f), False), "narrowspec updated")) | |
261 | merge.applyupdates(repo, actions, wctx=repo[None], |
|
261 | merge.applyupdates(repo, actions, wctx=repo[None], | |
262 | mctx=repo['.'], overwrite=False) |
|
262 | mctx=repo['.'], overwrite=False, wantfiledata=False) | |
263 |
|
263 | |||
264 | def checkworkingcopynarrowspec(repo): |
|
264 | def checkworkingcopynarrowspec(repo): | |
265 | # Avoid infinite recursion when updating the working copy |
|
265 | # Avoid infinite recursion when updating the working copy |
@@ -248,7 +248,8 b' def prunetemporaryincludes(repo):' | |||||
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: | |
@@ -382,7 +383,7 b' def filterupdatesactions(repo, wctx, mct' | |||||
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: | |
@@ -486,7 +487,8 b' def refreshwdir(repo, origstatus, origsp' | |||||
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: |
@@ -27,13 +27,11 b" outside of hg's control." | |||||
27 | > EOF |
|
27 | > EOF | |
28 |
|
28 | |||
29 | Do an update where file 'a' is changed between hg writing it to disk |
|
29 | Do an update where file 'a' is changed between hg writing it to disk | |
30 | and hg writing the dirstate. It results in a corrupted dirstate, which |
|
30 | and hg writing the dirstate. The dirstate is correct nonetheless, and | |
31 | stores the wrong size, and thus hg status shows spuriously modified |
|
31 | so hg status correctly shows a as clean. | |
32 | files. |
|
|||
33 |
|
32 | |||
34 | $ hg up -r 0 --config extensions.race=$TESTTMP/dirstaterace.py |
|
33 | $ hg up -r 0 --config extensions.race=$TESTTMP/dirstaterace.py | |
35 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
34 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
36 | $ hg debugdirstate --no-dates |
|
35 | $ hg debugdirstate --no-dates | |
37 |
n 644 |
|
36 | n 644 2 (set |unset) a (re) | |
38 | $ echo a > a; hg status; hg diff |
|
37 | $ echo a > a; hg status; hg diff | |
39 | M a |
|
@@ -73,7 +73,7 b' coherent (issue4353)' | |||||
73 | > merge, |
|
73 | > merge, | |
74 | > ) |
|
74 | > ) | |
75 | > |
|
75 | > | |
76 |
> def wraprecordupdates( |
|
76 | > def wraprecordupdates(*args): | |
77 | > raise error.Abort("simulated error while recording dirstateupdates") |
|
77 | > raise error.Abort("simulated error while recording dirstateupdates") | |
78 | > |
|
78 | > | |
79 | > def reposetup(ui, repo): |
|
79 | > def reposetup(ui, repo): |
General Comments 0
You need to be logged in to leave comments.
Login now