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)