# HG changeset patch # User Siddharth Agarwal # Date 1497306871 25200 # Node ID 15e85dded93323d286dc0a758edde1b9dbea5cdd # Parent 2083d1643d691ec5d21ae222aaf4658c0a863c10 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. diff --git a/hgext/fsmonitor/__init__.py b/hgext/fsmonitor/__init__.py --- a/hgext/fsmonitor/__init__.py +++ b/hgext/fsmonitor/__init__.py @@ -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): diff --git a/tests/test-dirstate-race.t b/tests/test-dirstate-race.t --- a/tests/test-dirstate-race.t +++ b/tests/test-dirstate-race.t @@ -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