[PATCH 4 of 6] dirstate: add _writepending to make pending data visible to external process
FUJIWARA Katsunori
foozy at lares.dti.ne.jp
Tue May 19 11:42:04 CDT 2015
# HG changeset patch
# User FUJIWARA Katsunori <foozy at lares.dti.ne.jp>
# Date 1432051569 -32400
# Wed May 20 01:06:09 2015 +0900
# Node ID 32bb772580da70c05822ab830349585f0245ae92
# Parent e830ef506b9aaa01c5406d100a385961c4c0dff0
dirstate: add _writepending to make pending data visible to external process
This patch adds `_writepending()`, which is used to make pending data
visible to external process.
Combination of `_dirty` and newly introduced `_diverted` property
means status below:
_diverted|_dirty| status
---------+------+-----------------------------------------------
x | x | exactly clean
x | o | all changes are held in memory
o | x | all changes are also held in pending file (*1)
o | o | pending file is out of date (*2)
For safety and consistency, `invalidate()` should remove pending file
in both (*1) and (*2) cases: remaining it may cause accidental reading
it in.
On the other hand, `write()` should:
- rename from `dirstate.pending` to `dirstate` in (*1) case, because:
- the former works well as the latter
(dirstate hasn't been changed since last `_writepending()`), and
- renaming is more efficient than writing out again
- remove `dirstate.pending` and write changes into `dirstate` in (*2) case
For review-ability, this patch focuses only on writing `.pending` file
out. Then, `dirstate.pending` remains even after `write()`,
`invalidate()` and the end of transaction. But it is still safe
enough, because there is no code path invoking `_writepending()` yet.
BTW, in many cases, changes on dirstate shouldn't be `invalidate()`-ed
even if transaction is aborted. This is reason why `_writepending()`
doesn't use `tr.registertmp()`, which removes specified file before
"abort callback" invocation and may cause losing changes held in
pending file.
diff --git a/mercurial/dirstate.py b/mercurial/dirstate.py
--- a/mercurial/dirstate.py
+++ b/mercurial/dirstate.py
@@ -64,10 +64,19 @@
self._filecache = {}
self._parentwriters = 0
self._filename = 'dirstate'
+ self._pendingfilename = '%s.pending' % self._filename
# for consitent view between _pl() and _read() invocations
self._pendingmode = None
+ # _diverted|_dirty| status
+ # ---------+------+-----------------------------------------------
+ # x | x | exactly clean
+ # x | o | all changes are held in memory
+ # o | x | all changes are also held in pending file
+ # o | o | pending file is out of date
+ self._diverted = False
+
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,
@@ -611,6 +620,23 @@
def write(self):
if not self._dirty:
return
+ self._writedirstate(self._filename)
+
+ def _writepending(self, tr):
+ '''Make pending data visible to external processes
+
+ This returns whether HG_PENDING should be defined or not.
+ '''
+ if self._dirty:
+ self._writedirstate(self._pendingfilename)
+ self._diverted = True
+ return self._diverted
+
+ def _writedirstate(self, filename):
+ if self._pendingmode:
+ # maybe "dirstate.write()" out of wlock scope
+ raise util.Abort(_('unexpected writing dirstate out'
+ ' under PENDING mode'))
# enough 'delaywrite' prevents 'pack_dirstate' from dropping
# timestamp of each entries in dirstate, because of 'now > mtime'
@@ -619,7 +645,7 @@
import time # to avoid useless import
time.sleep(delaywrite)
- st = self._opener(self._filename, "w", atomictemp=True)
+ st = self._opener(filename, "w", atomictemp=True)
# use the modification time of the newly created temporary file as the
# filesystem's notion of 'now'
now = util.fstat(st).st_mtime
More information about the Mercurial-devel
mailing list