Mercurial > hg
comparison mercurial/dirstate.py @ 26633:020b12d591f3
dirstate: make functions for backup aware of transaction activity
Some comments in this patch assume that subsequent patch changes
'dirstate.write()' like as below:
def write(self, repo):
if not self._dirty:
return
tr = repo.currenttransaction()
if tr:
tr.addfilegenerator('dirstate', (self._filename,),
self._writedirstate, location='plain')
return # omit actual writing out
st = self._opener('dirstate', "w", atomictemp=True)
self._writedirstate(st)
This patch makes '_savebackup()' write in-memory changes out, and it
causes clearing 'self._dirty'. If dirstate isn't changed after
'_savebackup()', subsequent 'dirstate.write()' never invokes
'tr.addfilegenerator()' because 'not self._dirty' is true.
Then, 'tr.writepending()' unintentionally returns False, if there is
no other (e.g. changelog) changes pending, even though dirstate
changes are already written out at '_savebackup()'.
To avoid such situation, this patch makes '_savebackup()' explicitly
invoke 'tr.addfilegenerator()', if transaction is running.
'_savebackup()' should get awareness of transaction before 'write()',
because the former depends on the behavior of the latter before this
patch.
author | FUJIWARA Katsunori <foozy@lares.dti.ne.jp> |
---|---|
date | Wed, 14 Oct 2015 02:49:17 +0900 |
parents | 59b5e8844eb0 |
children | 09bb1ee7e73e |
comparison
equal
deleted
inserted
replaced
26632:59b5e8844eb0 | 26633:020b12d591f3 |
---|---|
51 self._lastnormaltime = 0 | 51 self._lastnormaltime = 0 |
52 self._ui = ui | 52 self._ui = ui |
53 self._filecache = {} | 53 self._filecache = {} |
54 self._parentwriters = 0 | 54 self._parentwriters = 0 |
55 self._filename = 'dirstate' | 55 self._filename = 'dirstate' |
56 self._pendingfilename = '%s.pending' % self._filename | |
56 | 57 |
57 def beginparentchange(self): | 58 def beginparentchange(self): |
58 '''Marks the beginning of a set of changes that involve changing | 59 '''Marks the beginning of a set of changes that involve changing |
59 the dirstate parents. If there is an exception during this time, | 60 the dirstate parents. If there is an exception during this time, |
60 the dirstate will not be written when the wlock is released. This | 61 the dirstate will not be written when the wlock is released. This |
1050 # fast path -- all the values are known to be files, so just return | 1051 # fast path -- all the values are known to be files, so just return |
1051 # that | 1052 # that |
1052 return list(files) | 1053 return list(files) |
1053 return [f for f in dmap if match(f)] | 1054 return [f for f in dmap if match(f)] |
1054 | 1055 |
1056 def _actualfilename(self, repo): | |
1057 if repo.currenttransaction(): | |
1058 return self._pendingfilename | |
1059 else: | |
1060 return self._filename | |
1061 | |
1055 def _savebackup(self, repo, suffix): | 1062 def _savebackup(self, repo, suffix): |
1056 '''Save current dirstate into backup file with suffix''' | 1063 '''Save current dirstate into backup file with suffix''' |
1057 self.write() | 1064 filename = self._actualfilename(repo) |
1058 filename = self._filename | 1065 |
1066 # use '_writedirstate' instead of 'write' to write changes certainly, | |
1067 # because the latter omits writing out if transaction is running. | |
1068 # output file will be used to create backup of dirstate at this point. | |
1069 self._writedirstate(self._opener(filename, "w", atomictemp=True)) | |
1070 | |
1071 tr = repo.currenttransaction() | |
1072 if tr: | |
1073 # ensure that subsequent tr.writepending returns True for | |
1074 # changes written out above, even if dirstate is never | |
1075 # changed after this | |
1076 tr.addfilegenerator('dirstate', (self._filename,), | |
1077 self._writedirstate, location='plain') | |
1078 | |
1079 # ensure that pending file written above is unlinked at | |
1080 # failure, even if tr.writepending isn't invoked until the | |
1081 # end of this transaction | |
1082 tr.registertmp(filename, location='plain') | |
1083 | |
1059 self._opener.write(filename + suffix, self._opener.tryread(filename)) | 1084 self._opener.write(filename + suffix, self._opener.tryread(filename)) |
1060 | 1085 |
1061 def _restorebackup(self, repo, suffix): | 1086 def _restorebackup(self, repo, suffix): |
1062 '''Restore dirstate by backup file with suffix''' | 1087 '''Restore dirstate by backup file with suffix''' |
1063 # this "invalidate()" prevents "wlock.release()" from writing | 1088 # this "invalidate()" prevents "wlock.release()" from writing |
1064 # changes of dirstate out after restoring from backup file | 1089 # changes of dirstate out after restoring from backup file |
1065 self.invalidate() | 1090 self.invalidate() |
1066 filename = self._filename | 1091 filename = self._actualfilename(repo) |
1067 self._opener.rename(filename + suffix, filename) | 1092 self._opener.rename(filename + suffix, filename) |
1068 | 1093 |
1069 def _clearbackup(self, repo, suffix): | 1094 def _clearbackup(self, repo, suffix): |
1070 '''Clear backup file with suffix''' | 1095 '''Clear backup file with suffix''' |
1071 filename = self._filename | 1096 filename = self._actualfilename(repo) |
1072 self._opener.unlink(filename + suffix) | 1097 self._opener.unlink(filename + suffix) |