Show More
@@ -1759,19 +1759,30 b' class workingctx(committablectx):' | |||
|
1759 | 1759 | # update dirstate for files that are actually clean |
|
1760 | 1760 | if fixup: |
|
1761 | 1761 | try: |
|
1762 | oldid = self._repo.dirstate.identity() | |
|
1763 | ||
|
1762 | 1764 | # updating the dirstate is optional |
|
1763 | 1765 | # so we don't wait on the lock |
|
1764 | 1766 | # wlock can invalidate the dirstate, so cache normal _after_ |
|
1765 | 1767 | # taking the lock |
|
1766 | 1768 | with self._repo.wlock(False): |
|
1767 |
|
|
|
1768 | for f in fixup: | |
|
1769 |
|
|
|
1770 | # write changes out explicitly, because nesting | |
|
1771 | # wlock at runtime may prevent 'wlock.release()' | |
|
1772 | # after this block from doing so for subsequent | |
|
1773 | # changing files | |
|
1774 | self._repo.dirstate.write(self._repo.currenttransaction()) | |
|
1769 | if self._repo.dirstate.identity() == oldid: | |
|
1770 | normal = self._repo.dirstate.normal | |
|
1771 | for f in fixup: | |
|
1772 | normal(f) | |
|
1773 | # write changes out explicitly, because nesting | |
|
1774 | # wlock at runtime may prevent 'wlock.release()' | |
|
1775 | # after this block from doing so for subsequent | |
|
1776 | # changing files | |
|
1777 | tr = self._repo.currenttransaction() | |
|
1778 | self._repo.dirstate.write(tr) | |
|
1779 | else: | |
|
1780 | # in this case, writing changes out breaks | |
|
1781 | # consistency, because .hg/dirstate was | |
|
1782 | # already changed simultaneously after last | |
|
1783 | # caching (see also issue5584 for detail) | |
|
1784 | self._repo.ui.debug('skip updating dirstate: ' | |
|
1785 | 'identity mismatch\n') | |
|
1775 | 1786 | except error.LockError: |
|
1776 | 1787 | pass |
|
1777 | 1788 | return modified, deleted, fixup |
@@ -95,3 +95,65 b' anyway.' | |||
|
95 | 95 | ! d |
|
96 | 96 | ! dir1/c |
|
97 | 97 | ! e |
|
98 | ||
|
99 | $ rmdir d e | |
|
100 | $ hg update -C -q . | |
|
101 | ||
|
102 | Test that dirstate changes aren't written out at the end of "hg | |
|
103 | status", if .hg/dirstate is already changed simultaneously before | |
|
104 | acquisition of wlock in workingctx._checklookup(). | |
|
105 | ||
|
106 | This avoidance is important to keep consistency of dirstate in race | |
|
107 | condition (see issue5584 for detail). | |
|
108 | ||
|
109 | $ hg parents -q | |
|
110 | 1:* (glob) | |
|
111 | ||
|
112 | $ hg debugrebuilddirstate | |
|
113 | $ hg debugdirstate | |
|
114 | n 0 -1 unset a | |
|
115 | n 0 -1 unset b | |
|
116 | n 0 -1 unset d | |
|
117 | n 0 -1 unset dir1/c | |
|
118 | n 0 -1 unset e | |
|
119 | ||
|
120 | $ cat > $TESTTMP/dirstaterace.sh <<EOF | |
|
121 | > # This script assumes timetable of typical issue5584 case below: | |
|
122 | > # | |
|
123 | > # 1. "hg status" loads .hg/dirstate | |
|
124 | > # 2. "hg status" confirms clean-ness of FILE | |
|
125 | > # 3. "hg update -C 0" updates the working directory simultaneously | |
|
126 | > # (FILE is removed, and FILE is dropped from .hg/dirstate) | |
|
127 | > # 4. "hg status" acquires wlock | |
|
128 | > # (.hg/dirstate is re-loaded = no FILE entry in dirstate) | |
|
129 | > # 5. "hg status" marks FILE in dirstate as clean | |
|
130 | > # (FILE entry is added to in-memory dirstate) | |
|
131 | > # 6. "hg status" writes dirstate changes into .hg/dirstate | |
|
132 | > # (FILE entry is written into .hg/dirstate) | |
|
133 | > # | |
|
134 | > # To reproduce similar situation easily and certainly, #2 and #3 | |
|
135 | > # are swapped. "hg cat" below ensures #2 on "hg status" side. | |
|
136 | > | |
|
137 | > hg update -q -C 0 | |
|
138 | > hg cat -r 1 b > b | |
|
139 | > EOF | |
|
140 | ||
|
141 | "hg status" below should excludes "e", of which exec flag is set, for | |
|
142 | portability of test scenario, because unsure but missing "e" is | |
|
143 | treated differently in _checklookup() according to runtime platform. | |
|
144 | ||
|
145 | - "missing(!)" on POSIX, "pctx[f].cmp(self[f])" raises ENOENT | |
|
146 | - "modified(M)" on Windows, "self.flags(f) != pctx.flags(f)" is True | |
|
147 | ||
|
148 | $ hg status --config extensions.dirstaterace=$TESTTMP/dirstaterace.py --debug -X path:e | |
|
149 | skip updating dirstate: identity mismatch | |
|
150 | M a | |
|
151 | ! d | |
|
152 | ! dir1/c | |
|
153 | ||
|
154 | $ hg parents -q | |
|
155 | 0:* (glob) | |
|
156 | $ hg files | |
|
157 | a | |
|
158 | $ hg debugdirstate | |
|
159 | n * * * a (glob) |
General Comments 0
You need to be logged in to leave comments.
Login now