comparison mercurial/localrepo.py @ 50085:ff12f42415f5

localrepo: stop doing special dirstate backup at transaction open Since the dirstate writes are already managed by the transaction, we already do a backup of the dirstate when necessary (and even trigger one to keep `hg rollback` happy). We needs some special code to deal with the initial empty checkout, but it is not too complicated. Managing variable filename (as dirstate-v2 uses) at the "journalfile" level, is complex and fragile (which is consistent with the fact these files are not journal?). If we no longer do it, our life is significantly simpler. In some sense, we apply the xkcd-1134? solution to our savebackup/restorebackup problem. [1] https://xkcd.com/1134/ (the change to test-hardlink are expect as decreasing the number of duplicated backup drive the hardlink count down)
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Thu, 16 Feb 2023 04:02:36 +0100
parents 5b9c3ae807c8
children ec769cbc1fa2
comparison
equal deleted inserted replaced
50084:5b9c3ae807c8 50085:ff12f42415f5
2546 else: 2546 else:
2547 # discard all changes (including ones already written 2547 # discard all changes (including ones already written
2548 # out) in this transaction 2548 # out) in this transaction
2549 narrowspec.restorebackup(self, b'journal.narrowspec') 2549 narrowspec.restorebackup(self, b'journal.narrowspec')
2550 narrowspec.restorewcbackup(self, b'journal.narrowspec.dirstate') 2550 narrowspec.restorewcbackup(self, b'journal.narrowspec.dirstate')
2551 if repo.currentwlock() is not None:
2552 repo.dirstate.restorebackup(None, b'journal.dirstate')
2553 2551
2554 repo.invalidate(clearfilecache=True) 2552 repo.invalidate(clearfilecache=True)
2555 2553
2556 tr = transaction.transaction( 2554 tr = transaction.transaction(
2557 rp, 2555 rp,
2674 2672
2675 tr.addvalidator(b'dirstate-backup', backup_dirstate) 2673 tr.addvalidator(b'dirstate-backup', backup_dirstate)
2676 return tr 2674 return tr
2677 2675
2678 def _journalfiles(self): 2676 def _journalfiles(self):
2679 first = ( 2677 return (
2680 (self.svfs, b'journal'), 2678 (self.svfs, b'journal'),
2681 (self.svfs, b'journal.narrowspec'), 2679 (self.svfs, b'journal.narrowspec'),
2682 (self.vfs, b'journal.narrowspec.dirstate'), 2680 (self.vfs, b'journal.narrowspec.dirstate'),
2683 (self.vfs, b'journal.dirstate'),
2684 )
2685 middle = []
2686 dirstate_data = self.dirstate.data_backup_filename(b'journal.dirstate')
2687 if dirstate_data is not None:
2688 middle.append((self.vfs, dirstate_data))
2689 end = (
2690 (self.vfs, b'journal.branch'), 2681 (self.vfs, b'journal.branch'),
2691 (self.vfs, b'journal.desc'), 2682 (self.vfs, b'journal.desc'),
2692 (bookmarks.bookmarksvfs(self), b'journal.bookmarks'), 2683 (bookmarks.bookmarksvfs(self), b'journal.bookmarks'),
2693 (self.svfs, b'journal.phaseroots'), 2684 (self.svfs, b'journal.phaseroots'),
2694 ) 2685 )
2695 return first + tuple(middle) + end
2696 2686
2697 def undofiles(self): 2687 def undofiles(self):
2698 return [(vfs, undoname(x)) for vfs, x in self._journalfiles()] 2688 return [(vfs, undoname(x)) for vfs, x in self._journalfiles()]
2699 2689
2700 @unfilteredmethod 2690 @unfilteredmethod
2701 def _writejournal(self, desc): 2691 def _writejournal(self, desc):
2702 if self.currentwlock() is not None:
2703 self.dirstate.savebackup(None, b'journal.dirstate')
2704 narrowspec.savewcbackup(self, b'journal.narrowspec.dirstate') 2692 narrowspec.savewcbackup(self, b'journal.narrowspec.dirstate')
2705 narrowspec.savebackup(self, b'journal.narrowspec') 2693 narrowspec.savebackup(self, b'journal.narrowspec')
2706 self.vfs.write( 2694 self.vfs.write(
2707 b"journal.branch", encoding.fromlocal(self.dirstate.branch()) 2695 b"journal.branch", encoding.fromlocal(self.dirstate.branch())
2708 ) 2696 )
2806 b'undo.bookmarks', b'bookmarks', checkambig=True 2794 b'undo.bookmarks', b'bookmarks', checkambig=True
2807 ) 2795 )
2808 if self.svfs.exists(b'undo.phaseroots'): 2796 if self.svfs.exists(b'undo.phaseroots'):
2809 self.svfs.rename(b'undo.phaseroots', b'phaseroots', checkambig=True) 2797 self.svfs.rename(b'undo.phaseroots', b'phaseroots', checkambig=True)
2810 self.invalidate() 2798 self.invalidate()
2799 self.dirstate.invalidate()
2811 2800
2812 if parentgone: 2801 if parentgone:
2802 # replace this with some explicit parent update in the future.
2803 has_node = self.changelog.index.has_node
2804 if not all(has_node(p) for p in self.dirstate._pl):
2805 # There was no dirstate to backup initially, we need to drop
2806 # the existing one.
2807 with self.dirstate.changing_parents(self):
2808 self.dirstate.setparents(self.nullid)
2809 self.dirstate.clear()
2810
2813 narrowspec.restorebackup(self, b'undo.narrowspec') 2811 narrowspec.restorebackup(self, b'undo.narrowspec')
2814 narrowspec.restorewcbackup(self, b'undo.narrowspec.dirstate') 2812 narrowspec.restorewcbackup(self, b'undo.narrowspec.dirstate')
2815 self.dirstate.restorebackup(None, b'undo.dirstate')
2816 try: 2813 try:
2817 branch = self.vfs.read(b'undo.branch') 2814 branch = self.vfs.read(b'undo.branch')
2818 self.dirstate.setbranch(encoding.tolocal(branch)) 2815 self.dirstate.setbranch(encoding.tolocal(branch))
2819 except IOError: 2816 except IOError:
2820 ui.warn( 2817 ui.warn(