Mercurial > public > mercurial-scm > hg
comparison mercurial/localrepo.py @ 27291:a18328aad48c
commit: make commit acquire store lock before processing for consistency
If acquisition of wlock waits for another "hg commit" process to
release it, dirstate will refer newly committed revision after
acquisition of wlock.
At that time, '00changelog.i' on the filesystem contains this new
revision, but in-memory 'repo.changelog' doesn't, if it is cached
without store lock (slock) before updating by another "hg commit".
This makes validating parents at re-loading 'repo.dirstate' from
'.hg/dirstate' replace such new revision with 'nullid'. Then,
'localrepository.commit()' creates "orphan" revision (see issue4368
for detail).
a01d3d32b53a makes 'commands.commit()' acquire both wlock and slock
before processing to avoid this issue at "hg commit".
But similar issue can occur even after a01d3d32b53a, if 3rd party
extension does:
- refer 'repo.changelog' outside wlock scope, and
- invoke 'repo.commit()' directly (instead of 'commands.commit()')
This patch makes 'commit()' acquire slock before processing, to refer
recent changelog at validating parents of 'repo.dirstate'.
author | FUJIWARA Katsunori <foozy@lares.dti.ne.jp> |
---|---|
date | Wed, 09 Dec 2015 08:28:53 +0900 |
parents | 42aa0e570eaa |
children | b64b6fdc5c9b |
comparison
equal
deleted
inserted
replaced
27290:525d9b3f0a31 | 27291:a18328aad48c |
---|---|
1469 match.bad = fail | 1469 match.bad = fail |
1470 | 1470 |
1471 wlock = lock = tr = None | 1471 wlock = lock = tr = None |
1472 try: | 1472 try: |
1473 wlock = self.wlock() | 1473 wlock = self.wlock() |
1474 lock = self.lock() # for recent changelog (see issue4368) | |
1475 | |
1474 wctx = self[None] | 1476 wctx = self[None] |
1475 merge = len(wctx.parents()) > 1 | 1477 merge = len(wctx.parents()) > 1 |
1476 | 1478 |
1477 if not force and merge and match.ispartial(): | 1479 if not force and merge and match.ispartial(): |
1478 raise error.Abort(_('cannot partially commit a merge ' | 1480 raise error.Abort(_('cannot partially commit a merge ' |
1596 sr = sub.commit(cctx._text, user, date) | 1598 sr = sub.commit(cctx._text, user, date) |
1597 newstate[s] = (newstate[s][0], sr) | 1599 newstate[s] = (newstate[s][0], sr) |
1598 subrepo.writestate(self, newstate) | 1600 subrepo.writestate(self, newstate) |
1599 | 1601 |
1600 p1, p2 = self.dirstate.parents() | 1602 p1, p2 = self.dirstate.parents() |
1601 lock = self.lock() | |
1602 hookp1, hookp2 = hex(p1), (p2 != nullid and hex(p2) or '') | 1603 hookp1, hookp2 = hex(p1), (p2 != nullid and hex(p2) or '') |
1603 try: | 1604 try: |
1604 self.hook("precommit", throw=True, parent1=hookp1, | 1605 self.hook("precommit", throw=True, parent1=hookp1, |
1605 parent2=hookp2) | 1606 parent2=hookp2) |
1606 tr = self.transaction('commit') | 1607 tr = self.transaction('commit') |