##// END OF EJS Templates
dirstate: make writing in-memory changes aware of transaction activity...
FUJIWARA Katsunori -
r26634:09bb1ee7 default
parent child Browse files
Show More
@@ -27,6 +27,15 b' class rootcache(filecache):'
27 def join(self, obj, fname):
27 def join(self, obj, fname):
28 return obj._join(fname)
28 return obj._join(fname)
29
29
30 def _getfsnow(vfs):
31 '''Get "now" timestamp on filesystem'''
32 tmpfd, tmpname = vfs.mkstemp()
33 try:
34 return util.statmtimesec(os.fstat(tmpfd))
35 finally:
36 os.close(tmpfd)
37 vfs.unlink(tmpname)
38
30 class dirstate(object):
39 class dirstate(object):
31
40
32 def __init__(self, opener, ui, root, validate):
41 def __init__(self, opener, ui, root, validate):
@@ -611,7 +620,7 b' class dirstate(object):'
611 self._pl = (parent, nullid)
620 self._pl = (parent, nullid)
612 self._dirty = True
621 self._dirty = True
613
622
614 def write(self):
623 def write(self, repo=None):
615 if not self._dirty:
624 if not self._dirty:
616 return
625 return
617
626
@@ -622,7 +631,40 b' class dirstate(object):'
622 import time # to avoid useless import
631 import time # to avoid useless import
623 time.sleep(delaywrite)
632 time.sleep(delaywrite)
624
633
625 st = self._opener(self._filename, "w", atomictemp=True)
634 filename = self._filename
635 if not repo:
636 tr = None
637 if self._opener.lexists(self._pendingfilename):
638 # if pending file already exists, in-memory changes
639 # should be written into it, because it has priority
640 # to '.hg/dirstate' at reading under HG_PENDING mode
641 filename = self._pendingfilename
642 else:
643 tr = repo.currenttransaction()
644
645 if tr:
646 # 'dirstate.write()' is not only for writing in-memory
647 # changes out, but also for dropping ambiguous timestamp.
648 # delayed writing re-raise "ambiguous timestamp issue".
649 # See also the wiki page below for detail:
650 # https://www.mercurial-scm.org/wiki/DirstateTransactionPlan
651
652 # emulate dropping timestamp in 'parsers.pack_dirstate'
653 now = _getfsnow(repo.vfs)
654 dmap = self._map
655 for f, e in dmap.iteritems():
656 if e[0] == 'n' and e[3] == now:
657 dmap[f] = dirstatetuple(e[0], e[1], e[2], -1)
658
659 # emulate that all 'dirstate.normal' results are written out
660 self._lastnormaltime = 0
661
662 # delay writing in-memory changes out
663 tr.addfilegenerator('dirstate', (self._filename,),
664 self._writedirstate, location='plain')
665 return
666
667 st = self._opener(filename, "w", atomictemp=True)
626 self._writedirstate(st)
668 self._writedirstate(st)
627
669
628 def _writedirstate(self, st):
670 def _writedirstate(self, st):
@@ -1000,6 +1000,11 b' class localrepository(object):'
1000 def releasefn(tr, success):
1000 def releasefn(tr, success):
1001 repo = reporef()
1001 repo = reporef()
1002 if success:
1002 if success:
1003 # this should be explicitly invoked here, because
1004 # in-memory changes aren't written out at closing
1005 # transaction, if tr.addfilegenerator (via
1006 # dirstate.write or so) isn't invoked while
1007 # transaction running
1003 repo.dirstate.write()
1008 repo.dirstate.write()
1004 else:
1009 else:
1005 # prevent in-memory changes from being written out at
1010 # prevent in-memory changes from being written out at
@@ -5,7 +5,7 b''
5 # - 'workingctx._checklookup()' (= 'repo.status()')
5 # - 'workingctx._checklookup()' (= 'repo.status()')
6 # - 'committablectx.markcommitted()'
6 # - 'committablectx.markcommitted()'
7
7
8 from mercurial import context, extensions, parsers, util
8 from mercurial import context, dirstate, extensions, parsers, util
9
9
10 def pack_dirstate(fakenow, orig, dmap, copymap, pl, now):
10 def pack_dirstate(fakenow, orig, dmap, copymap, pl, now):
11 # execute what original parsers.pack_dirstate should do actually
11 # execute what original parsers.pack_dirstate should do actually
@@ -34,13 +34,16 b' def fakewrite(ui, func):'
34 fakenow = util.parsedate(fakenow, ['%Y%m%d%H%M'])[0]
34 fakenow = util.parsedate(fakenow, ['%Y%m%d%H%M'])[0]
35
35
36 orig_pack_dirstate = parsers.pack_dirstate
36 orig_pack_dirstate = parsers.pack_dirstate
37 orig_dirstate_getfsnow = dirstate._getfsnow
37 wrapper = lambda *args: pack_dirstate(fakenow, orig_pack_dirstate, *args)
38 wrapper = lambda *args: pack_dirstate(fakenow, orig_pack_dirstate, *args)
38
39
39 parsers.pack_dirstate = wrapper
40 parsers.pack_dirstate = wrapper
41 dirstate._getfsnow = lambda *args: fakenow
40 try:
42 try:
41 return func()
43 return func()
42 finally:
44 finally:
43 parsers.pack_dirstate = orig_pack_dirstate
45 parsers.pack_dirstate = orig_pack_dirstate
46 dirstate._getfsnow = orig_dirstate_getfsnow
44
47
45 def _checklookup(orig, workingctx, files):
48 def _checklookup(orig, workingctx, files):
46 ui = workingctx.repo().ui
49 ui = workingctx.repo().ui
General Comments 0
You need to be logged in to leave comments. Login now