fsmonitor: write state with wlock held and dirstate unchanged (
issue5581)
This means that the state will not be written if:
(1) either the wlock can't be obtained
(2) something else came along and changed the dirstate while we were in the
middle of a status run.
--- a/hgext/fsmonitor/__init__.py Mon Jun 12 13:56:50 2017 -0700
+++ b/hgext/fsmonitor/__init__.py Mon Jun 12 15:34:31 2017 -0700
@@ -485,17 +485,14 @@
else:
stateunknown = listunknown
+ if updatestate:
+ ps = poststatus(startclock)
+ self.addpostdsstatus(ps)
+
r = orig(node1, node2, match, listignored, listclean, stateunknown,
listsubrepos)
modified, added, removed, deleted, unknown, ignored, clean = r
- if updatestate:
- notefiles = modified + added + removed + deleted + unknown
- self._fsmonitorstate.set(
- self._fsmonitorstate.getlastclock() or startclock,
- _hashignore(self.dirstate._ignore),
- notefiles)
-
if not listunknown:
unknown = []
@@ -528,6 +525,17 @@
return scmutil.status(
modified, added, removed, deleted, unknown, ignored, clean)
+class poststatus(object):
+ def __init__(self, startclock):
+ self._startclock = startclock
+
+ def __call__(self, wctx, status):
+ clock = wctx.repo()._fsmonitorstate.getlastclock() or self._startclock
+ hashignore = _hashignore(wctx.repo().dirstate._ignore)
+ notefiles = (status.modified + status.added + status.removed +
+ status.deleted + status.unknown)
+ wctx.repo()._fsmonitorstate.set(clock, hashignore, notefiles)
+
def makedirstate(cls):
class fsmonitordirstate(cls):
def _fsmonitorinit(self, fsmonitorstate, watchmanclient):
--- a/tests/test-dirstate-race.t Mon Jun 12 13:56:50 2017 -0700
+++ b/tests/test-dirstate-race.t Mon Jun 12 15:34:31 2017 -0700
@@ -157,3 +157,50 @@
a
$ hg debugdirstate
n * * * a (glob)
+
+ $ rm b
+
+Set up a rebase situation for issue5581.
+
+ $ echo c2 > a
+ $ echo c2 > b
+ $ hg add b
+ $ hg commit -m c2
+ created new head
+ $ echo c3 >> a
+ $ hg commit -m c3
+ $ hg update 2
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ echo c4 >> a
+ $ echo c4 >> b
+ $ hg commit -m c4
+ created new head
+
+Configure a merge tool that runs status in the middle of the rebase.
+
+ $ cat >> $TESTTMP/mergetool-race.sh << EOF
+ > echo "custom merge tool"
+ > printf "c2\nc3\nc4\n" > \$1
+ > hg --cwd $TESTTMP/repo status
+ > echo "custom merge tool end"
+ > EOF
+ $ cat >> $HGRCPATH << EOF
+ > [extensions]
+ > rebase =
+ > [merge-tools]
+ > test.executable=sh
+ > test.args=$TESTTMP/mergetool-race.sh \$output
+ > EOF
+
+ $ hg rebase -s . -d 3 --tool test
+ rebasing 4:b08445fd6b2a "c4" (tip)
+ merging a
+ custom merge tool
+ M a
+ ? a.orig
+ custom merge tool end
+ saved backup bundle to $TESTTMP/repo/.hg/strip-backup/* (glob)
+
+This hg status should be empty, whether or not fsmonitor is enabled (issue5581).
+
+ $ hg status