Mercurial > hg
comparison mercurial/dirstate.py @ 50086:76d44983a398
dirstate: remove the dedicated backup logic
When alone, the dirstate can now take care of its commit/rollback pattern
itself.
When in a transaction, the transaction deal with commit/rollback pattern quite
fine.
Why did you have a dedicated backup logic?
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Thu, 16 Feb 2023 04:49:35 +0100 |
parents | 5b9c3ae807c8 |
children | 0f0880c8a7e5 |
comparison
equal
deleted
inserted
replaced
50085:ff12f42415f5 | 50086:76d44983a398 |
---|---|
29 scmutil, | 29 scmutil, |
30 util, | 30 util, |
31 ) | 31 ) |
32 | 32 |
33 from .dirstateutils import ( | 33 from .dirstateutils import ( |
34 docket as docketmod, | |
35 timestamp, | 34 timestamp, |
36 ) | 35 ) |
37 | 36 |
38 from .interfaces import ( | 37 from .interfaces import ( |
39 dirstate as intdirstate, | 38 dirstate as intdirstate, |
1629 self._map.docket.data_filename(), | 1628 self._map.docket.data_filename(), |
1630 ) | 1629 ) |
1631 else: | 1630 else: |
1632 return (self._filename,) | 1631 return (self._filename,) |
1633 | 1632 |
1634 def data_backup_filename(self, backupname): | |
1635 if not self._use_dirstate_v2: | |
1636 return None | |
1637 return backupname + b'.v2-data' | |
1638 | |
1639 def _new_backup_data_filename(self, backupname): | |
1640 """return a filename to backup a data-file or None""" | |
1641 if not self._use_dirstate_v2: | |
1642 return None | |
1643 if self._map.docket.uuid is None: | |
1644 # not created yet, nothing to backup | |
1645 return None | |
1646 data_filename = self._map.docket.data_filename() | |
1647 return data_filename, self.data_backup_filename(backupname) | |
1648 | |
1649 def backup_data_file(self, backupname): | |
1650 if not self._use_dirstate_v2: | |
1651 return None | |
1652 docket = docketmod.DirstateDocket.parse( | |
1653 self._opener.read(backupname), | |
1654 self._nodeconstants, | |
1655 ) | |
1656 return self.data_backup_filename(backupname), docket.data_filename() | |
1657 | |
1658 def savebackup(self, tr, backupname): | |
1659 '''Save current dirstate into backup file''' | |
1660 filename = self._actualfilename(tr) | |
1661 assert backupname != filename | |
1662 | |
1663 # use '_writedirstate' instead of 'write' to write changes certainly, | |
1664 # because the latter omits writing out if transaction is running. | |
1665 # output file will be used to create backup of dirstate at this point. | |
1666 if self._dirty: | |
1667 self._writedirstate( | |
1668 tr, | |
1669 self._opener(filename, b"w", atomictemp=True, checkambig=True), | |
1670 ) | |
1671 | |
1672 if tr: | |
1673 # ensure that subsequent tr.writepending returns True for | |
1674 # changes written out above, even if dirstate is never | |
1675 # changed after this | |
1676 tr.addfilegenerator( | |
1677 b'dirstate-1-main', | |
1678 (self._filename,), | |
1679 lambda f: self._writedirstate(tr, f), | |
1680 location=b'plain', | |
1681 post_finalize=True, | |
1682 ) | |
1683 | |
1684 self._opener.tryunlink(backupname) | |
1685 if self._opener.exists(filename): | |
1686 # hardlink backup is okay because _writedirstate is always called | |
1687 # with an "atomictemp=True" file. | |
1688 util.copyfile( | |
1689 self._opener.join(filename), | |
1690 self._opener.join(backupname), | |
1691 hardlink=True, | |
1692 ) | |
1693 data_pair = self._new_backup_data_filename(backupname) | |
1694 if data_pair is not None: | |
1695 data_filename, bck_data_filename = data_pair | |
1696 util.copyfile( | |
1697 self._opener.join(data_filename), | |
1698 self._opener.join(bck_data_filename), | |
1699 hardlink=True, | |
1700 ) | |
1701 if tr is not None: | |
1702 # ensure that pending file written above is unlinked at | |
1703 # failure, even if tr.writepending isn't invoked until the | |
1704 # end of this transaction | |
1705 tr.registertmp(bck_data_filename, location=b'plain') | |
1706 | |
1707 def restorebackup(self, tr, backupname): | |
1708 '''Restore dirstate by backup file''' | |
1709 # this "invalidate()" prevents "wlock.release()" from writing | |
1710 # changes of dirstate out after restoring from backup file | |
1711 self.invalidate() | |
1712 o = self._opener | |
1713 if not o.exists(backupname): | |
1714 # there was no file backup, delete existing files | |
1715 filename = self._actualfilename(tr) | |
1716 data_file = None | |
1717 if self._use_dirstate_v2 and self._map.docket.uuid is not None: | |
1718 data_file = self._map.docket.data_filename() | |
1719 if o.exists(filename): | |
1720 o.unlink(filename) | |
1721 if data_file is not None and o.exists(data_file): | |
1722 o.unlink(data_file) | |
1723 return | |
1724 filename = self._actualfilename(tr) | |
1725 data_pair = self.backup_data_file(backupname) | |
1726 if o.exists(filename) and util.samefile( | |
1727 o.join(backupname), o.join(filename) | |
1728 ): | |
1729 o.unlink(backupname) | |
1730 else: | |
1731 o.rename(backupname, filename, checkambig=True) | |
1732 | |
1733 if data_pair is not None: | |
1734 data_backup, target = data_pair | |
1735 if o.exists(target) and util.samefile( | |
1736 o.join(data_backup), o.join(target) | |
1737 ): | |
1738 o.unlink(data_backup) | |
1739 else: | |
1740 o.rename(data_backup, target, checkambig=True) | |
1741 | |
1742 def clearbackup(self, tr, backupname): | |
1743 '''Clear backup file''' | |
1744 o = self._opener | |
1745 if o.exists(backupname): | |
1746 data_backup = self.backup_data_file(backupname) | |
1747 o.unlink(backupname) | |
1748 if data_backup is not None: | |
1749 o.unlink(data_backup[0]) | |
1750 | |
1751 def verify(self, m1, m2, p1, narrow_matcher=None): | 1633 def verify(self, m1, m2, p1, narrow_matcher=None): |
1752 """ | 1634 """ |
1753 check the dirstate contents against the parent manifest and yield errors | 1635 check the dirstate contents against the parent manifest and yield errors |
1754 """ | 1636 """ |
1755 missing_from_p1 = _( | 1637 missing_from_p1 = _( |