comparison mercurial/transaction.py @ 40462:77c4e2ae9f07

transaction: make journal a private attribute This attribute tracks the name of the journal file. It is an implementation detail of the current transaction and therefore shouldn't be exposed as part of the interface. Let's mark it as private. Differential Revision: https://phab.mercurial-scm.org/D4624
author Gregory Szorc <gregory.szorc@gmail.com>
date Mon, 17 Sep 2018 15:55:57 -0700
parents da9ce63bfa9b
children d27fde3e023e
comparison
equal deleted inserted replaced
40461:da9ce63bfa9b 40462:77c4e2ae9f07
129 vfsmap[''] = opener # set default value 129 vfsmap[''] = opener # set default value
130 self._vfsmap = vfsmap 130 self._vfsmap = vfsmap
131 self.after = after 131 self.after = after
132 self.entries = [] 132 self.entries = []
133 self.map = {} 133 self.map = {}
134 self.journal = journalname 134 self._journal = journalname
135 self._undoname = undoname 135 self._undoname = undoname
136 self._queue = [] 136 self._queue = []
137 # A callback to validate transaction content before closing it. 137 # A callback to validate transaction content before closing it.
138 # should raise exception is anything is wrong. 138 # should raise exception is anything is wrong.
139 # target user is repository hooks. 139 # target user is repository hooks.
155 # transaction. 155 # transaction.
156 self.changes = {} 156 self.changes = {}
157 157
158 # a dict of arguments to be passed to hooks 158 # a dict of arguments to be passed to hooks
159 self.hookargs = {} 159 self.hookargs = {}
160 self.file = opener.open(self.journal, "w") 160 self.file = opener.open(self._journal, "w")
161 161
162 # a list of ('location', 'path', 'backuppath', cache) entries. 162 # a list of ('location', 'path', 'backuppath', cache) entries.
163 # - if 'backuppath' is empty, no file existed at backup time 163 # - if 'backuppath' is empty, no file existed at backup time
164 # - if 'path' is empty, this is a temporary transaction file 164 # - if 'path' is empty, this is a temporary transaction file
165 # - if 'location' is not empty, the path is outside main opener reach. 165 # - if 'location' is not empty, the path is outside main opener reach.
166 # use 'location' value as a key in a vfsmap to find the right 'vfs' 166 # use 'location' value as a key in a vfsmap to find the right 'vfs'
167 # (cache is currently unused) 167 # (cache is currently unused)
168 self._backupentries = [] 168 self._backupentries = []
169 self._backupmap = {} 169 self._backupmap = {}
170 self._backupjournal = "%s.backupfiles" % self.journal 170 self._backupjournal = "%s.backupfiles" % self._journal
171 self._backupsfile = opener.open(self._backupjournal, 'w') 171 self._backupsfile = opener.open(self._backupjournal, 'w')
172 self._backupsfile.write('%d\n' % version) 172 self._backupsfile.write('%d\n' % version)
173 173
174 if createmode is not None: 174 if createmode is not None:
175 opener.chmod(self.journal, createmode & 0o666) 175 opener.chmod(self._journal, createmode & 0o666)
176 opener.chmod(self._backupjournal, createmode & 0o666) 176 opener.chmod(self._backupjournal, createmode & 0o666)
177 177
178 # hold file generations to be performed on commit 178 # hold file generations to be performed on commit
179 self._filegenerators = {} 179 self._filegenerators = {}
180 # hold callback to write pending data for hooks 180 # hold callback to write pending data for hooks
192 name = r'/'.join(self.names) 192 name = r'/'.join(self.names)
193 return (r'<transaction name=%s, count=%d, usages=%d>' % 193 return (r'<transaction name=%s, count=%d, usages=%d>' %
194 (name, self._count, self._usages)) 194 (name, self._count, self._usages))
195 195
196 def __del__(self): 196 def __del__(self):
197 if self.journal: 197 if self._journal:
198 self._abort() 198 self._abort()
199 199
200 @active 200 @active
201 def startgroup(self): 201 def startgroup(self):
202 """delay registration of file entry 202 """delay registration of file entry
253 253
254 if file in self.map or file in self._backupmap: 254 if file in self.map or file in self._backupmap:
255 return 255 return
256 vfs = self._vfsmap[location] 256 vfs = self._vfsmap[location]
257 dirname, filename = vfs.split(file) 257 dirname, filename = vfs.split(file)
258 backupfilename = "%s.backup.%s" % (self.journal, filename) 258 backupfilename = "%s.backup.%s" % (self._journal, filename)
259 backupfile = vfs.reljoin(dirname, backupfilename) 259 backupfile = vfs.reljoin(dirname, backupfilename)
260 if vfs.exists(file): 260 if vfs.exists(file):
261 filepath = vfs.join(file) 261 filepath = vfs.join(file)
262 backuppath = vfs.join(backupfile) 262 backuppath = vfs.join(backupfile)
263 util.copyfile(filepath, backuppath, hardlink=hardlink) 263 util.copyfile(filepath, backuppath, hardlink=hardlink)
491 if self.after: 491 if self.after:
492 self.after() 492 self.after()
493 self.after = None # Help prevent cycles. 493 self.after = None # Help prevent cycles.
494 if self.opener.isfile(self._backupjournal): 494 if self.opener.isfile(self._backupjournal):
495 self.opener.unlink(self._backupjournal) 495 self.opener.unlink(self._backupjournal)
496 if self.opener.isfile(self.journal): 496 if self.opener.isfile(self._journal):
497 self.opener.unlink(self.journal) 497 self.opener.unlink(self._journal)
498 for l, _f, b, c in self._backupentries: 498 for l, _f, b, c in self._backupentries:
499 if l not in self._vfsmap and c: 499 if l not in self._vfsmap and c:
500 self.report("couldn't remove %s: unknown cache location" 500 self.report("couldn't remove %s: unknown cache location"
501 "%s\n" % (b, l)) 501 "%s\n" % (b, l))
502 continue 502 continue
509 raise 509 raise
510 # Abort may be raise by read only opener 510 # Abort may be raise by read only opener
511 self.report("couldn't remove %s: %s\n" 511 self.report("couldn't remove %s: %s\n"
512 % (vfs.join(b), inst)) 512 % (vfs.join(b), inst))
513 self._backupentries = [] 513 self._backupentries = []
514 self.journal = None 514 self._journal = None
515 515
516 self.releasefn(self, True) # notify success of closing transaction 516 self.releasefn(self, True) # notify success of closing transaction
517 self.releasefn = None # Help prevent cycles. 517 self.releasefn = None # Help prevent cycles.
518 518
519 # run post close action 519 # run post close action
547 self.report("couldn't remove %s: unknown cache location" 547 self.report("couldn't remove %s: unknown cache location"
548 "%s\n" % (b, l)) 548 "%s\n" % (b, l))
549 continue 549 continue
550 vfs = self._vfsmap[l] 550 vfs = self._vfsmap[l]
551 base, name = vfs.split(b) 551 base, name = vfs.split(b)
552 assert name.startswith(self.journal), name 552 assert name.startswith(self._journal), name
553 uname = name.replace(self.journal, self._undoname, 1) 553 uname = name.replace(self._journal, self._undoname, 1)
554 u = vfs.reljoin(base, uname) 554 u = vfs.reljoin(base, uname)
555 util.copyfile(vfs.join(b), vfs.join(u), hardlink=True) 555 util.copyfile(vfs.join(b), vfs.join(u), hardlink=True)
556 undobackupfile.write("%s\0%s\0%s\0%d\n" % (l, f, u, c)) 556 undobackupfile.write("%s\0%s\0%s\0%d\n" % (l, f, u, c))
557 undobackupfile.close() 557 undobackupfile.close()
558 558
565 565
566 try: 566 try:
567 if not self.entries and not self._backupentries: 567 if not self.entries and not self._backupentries:
568 if self._backupjournal: 568 if self._backupjournal:
569 self.opener.unlink(self._backupjournal) 569 self.opener.unlink(self._backupjournal)
570 if self.journal: 570 if self._journal:
571 self.opener.unlink(self.journal) 571 self.opener.unlink(self._journal)
572 return 572 return
573 573
574 self.report(_("transaction abort!\n")) 574 self.report(_("transaction abort!\n"))
575 575
576 try: 576 try:
577 for cat in sorted(self._abortcallback): 577 for cat in sorted(self._abortcallback):
578 self._abortcallback[cat](self) 578 self._abortcallback[cat](self)
579 # Prevent double usage and help clear cycles. 579 # Prevent double usage and help clear cycles.
580 self._abortcallback = None 580 self._abortcallback = None
581 _playback(self.journal, self.report, self.opener, self._vfsmap, 581 _playback(self._journal, self.report, self.opener, self._vfsmap,
582 self.entries, self._backupentries, False, 582 self.entries, self._backupentries, False,
583 checkambigfiles=self.checkambigfiles) 583 checkambigfiles=self.checkambigfiles)
584 self.report(_("rollback completed\n")) 584 self.report(_("rollback completed\n"))
585 except BaseException: 585 except BaseException:
586 self.report(_("rollback failed - please run hg recover\n")) 586 self.report(_("rollback failed - please run hg recover\n"))
587 finally: 587 finally:
588 self.journal = None 588 self._journal = None
589 self.releasefn(self, False) # notify failure of transaction 589 self.releasefn(self, False) # notify failure of transaction
590 self.releasefn = None # Help prevent cycles. 590 self.releasefn = None # Help prevent cycles.
591 591
592 def rollback(opener, vfsmap, file, report, checkambigfiles=None): 592 def rollback(opener, vfsmap, file, report, checkambigfiles=None):
593 """Rolls back the transaction contained in the given file 593 """Rolls back the transaction contained in the given file