Mercurial > hg
changeset 26635:79d86ab65c9d
dirstate: read from pending file under HG_PENDING mode if it exists
True/False value of '_pendingmode' means whether 'dirstate.pending' is
used to initialize own '_map' and so on. When it is None, neither
'dirstate' nor 'dirstate.pending' is read in yet.
This is used to keep consistent view between '_pl()' and '_read()'.
Once '_pendingmode' is determined by reading one of 'dirstate' or
'dirstate.pending' in, '_pendingmode' is kept even if 'invalidate()'
is invoked. This should be reasonable, because:
- effective 'invalidate()' invocation should occur only in wlock scope, and
- wlock can't be gotten under HG_PENDING mode
'_trypending()' is defined as a normal function to factor similar code
path (in bookmarks and phases) out in the future easily.
author | FUJIWARA Katsunori <foozy@lares.dti.ne.jp> |
---|---|
date | Wed, 14 Oct 2015 02:49:17 +0900 |
parents | 09bb1ee7e73e |
children | ff6baf32b3ba |
files | mercurial/dirstate.py |
diffstat | 1 files changed, 30 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/dirstate.py Wed Oct 14 02:49:17 2015 +0900 +++ b/mercurial/dirstate.py Wed Oct 14 02:49:17 2015 +0900 @@ -36,6 +36,22 @@ os.close(tmpfd) vfs.unlink(tmpname) +def _trypending(root, vfs, filename): + '''Open file to be read according to HG_PENDING environment variable + + This opens '.pending' of specified 'filename' only when HG_PENDING + is equal to 'root'. + + This returns '(fp, is_pending_opened)' tuple. + ''' + if root == os.environ.get('HG_PENDING'): + try: + return (vfs('%s.pending' % filename), True) + except IOError as inst: + if inst.errno != errno.ENOENT: + raise + return (vfs(filename), False) + class dirstate(object): def __init__(self, opener, ui, root, validate): @@ -64,6 +80,9 @@ self._filename = 'dirstate' self._pendingfilename = '%s.pending' % self._filename + # for consitent view between _pl() and _read() invocations + self._pendingmode = None + def beginparentchange(self): '''Marks the beginning of a set of changes that involve changing the dirstate parents. If there is an exception during this time, @@ -137,7 +156,7 @@ @propertycache def _pl(self): try: - fp = self._opener(self._filename) + fp = self._opendirstatefile() st = fp.read(40) fp.close() l = len(st) @@ -342,11 +361,20 @@ f.discard() raise + def _opendirstatefile(self): + fp, mode = _trypending(self._root, self._opener, self._filename) + if self._pendingmode is not None and self._pendingmode != mode: + fp.close() + raise error.Abort(_('working directory state may be ' + 'changed parallelly')) + self._pendingmode = mode + return fp + def _read(self): self._map = {} self._copymap = {} try: - fp = self._opener.open(self._filename) + fp = self._opendirstatefile() try: st = fp.read() finally: