[PATCH STABLE?] commit: avoid a dirstate race with multiple commits in the same process
Matt Mackall
mpm at selenic.com
Tue Mar 15 23:40:16 UTC 2011
On Mon, 2011-03-14 at 14:48 -0400, Greg Ward wrote:
> # HG changeset patch
> # User Greg Ward <greg-hg at gerg.ca>
> # Date 1300128285 14400
> # Branch stable
> # Node ID 396982a5883383fc043d3f5ad78a0f9f0366bd06
> # Parent 4bfff063aed6fb4b3c8abe8a9ec51fe1e55725bf
> commit: avoid a dirstate race with multiple commits in the same process
> (issue2264, issue2516)
>
> The race happens when two commits in a row change the same file but do
> not change its size, *if* those two commits happen in the same second
> in the same process while holding the same repo lock. For example:
>
> commit i:
> M a
> M b
> commit i+1: # same process, same second, same repo lock
> M b # modify b without changing its size
> M c
>
> This first manifested in transplant, which is the most common way to
> do multiple commits in the same process. But it can manifest in any
> script or extension that does multiple commits under the same repo
> lock.
>
> The problem was that dirstate failed to notice the changes to b when
> localrepo is doing the second commit, meaning that change gets left in
> the working directory. In the context of transplant, that means either
> a crash ("RuntimeError: nothing committed after transplant") or a
> silently inaccurate transplant, depending on whether any other files
> were modified by the second transplanted changeset.
>
> The fix is to work a little harder in the second (and subsequent)
> commits run in the same process:
> - dirstate: factor out maybelookup() from write()
> - localrepo: add _lastcommitfiles attribute, and use it with
> maybelookup() to force repo.status() to look harder at files
> added/modified by the *previous* commit
>
> Incidentally, there is a simpler fix: call dirstate.normallookup() on
> every file modified by commit() at the end of the commit. The trouble
> with that solution is that it imposes a performance penalty on the
> common case: it means the next status-dependent hg command after every
> "hg commit" will be a little bit slower. The patch here is more
> complex, but it only affects performance for the uncommon case of
> multiple commits in the same process.
I think you're going to need to break this up. There's a lot going on
here and some of it you haven't told us about. You might start by
introducing getfstime and we can debate whether that's the right thing.
--
Mathematics is the supreme nostalgia of our time.
More information about the Mercurial-devel
mailing list