Mercurial > hg
changeset 50084:5b9c3ae807c8
localrepo: "blindly" do a dirstate backup at the end of the transaction
Having the file backup mechanism dealing with file backup as benefit. So lets
move closer to that.
The fact `hg rollback` even needs this is sad. I hope to have the time to
implement one of the alternative soon.
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Thu, 16 Feb 2023 11:42:43 +0100 |
parents | a28cedb26139 |
children | ff12f42415f5 |
files | mercurial/dirstate.py mercurial/localrepo.py |
diffstat | 2 files changed, 42 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/dirstate.py Thu Feb 16 17:12:21 2023 +0100 +++ b/mercurial/dirstate.py Thu Feb 16 11:42:43 2023 +0100 @@ -1615,6 +1615,22 @@ else: return self._filename + def all_file_names(self): + """list all filename currently used by this dirstate + + This is only used to do `hg rollback` related backup in the transaction + """ + if not self._opener.exists(self._filename): + # no data every written to disk yet + return () + elif self._use_dirstate_v2: + return ( + self._filename, + self._map.docket.data_filename(), + ) + else: + return (self._filename,) + def data_backup_filename(self, backupname): if not self._use_dirstate_v2: return None
--- a/mercurial/localrepo.py Thu Feb 16 17:12:21 2023 +0100 +++ b/mercurial/localrepo.py Thu Feb 16 11:42:43 2023 +0100 @@ -2647,6 +2647,32 @@ tr.addpostclose(b'refresh-filecachestats', self._refreshfilecachestats) self._transref = weakref.ref(tr) scmutil.registersummarycallback(self, tr, desc) + # This only exist to deal with the need of rollback to have viable + # parents at the end of the operation. So backup viable parents at the + # time of this operation. + # + # We only do it when the `wlock` is taken, otherwise other might be + # altering the dirstate under us. + # + # This is really not a great way to do this (first, because we cannot + # always do it). There are more viable alternative that exists + # + # - backing only the working copy parent in a dedicated files and doing + # a clean "keep-update" to them on `hg rollback`. + # + # - slightly changing the behavior an applying a logic similar to "hg + # strip" to pick a working copy destination on `hg rollback` + if self.currentwlock() is not None: + ds = self.dirstate + + def backup_dirstate(tr): + for f in ds.all_file_names(): + # hardlink backup is okay because `dirstate` is always + # atomically written and possible data file are append only + # and resistant to trailing data. + tr.addbackup(f, hardlink=True, location=b'plain') + + tr.addvalidator(b'dirstate-backup', backup_dirstate) return tr def _journalfiles(self):