Mercurial > public > mercurial-scm > hg
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( |