comparison mercurial/dirstate.py @ 50002:e358f6e0e50e

dirstate: do not write an empty dirstate just for backup This will get in the way when we get more strict about holding the lock when writing the dirstate. Instead, we simply don't copy dirstate files around if there are None at backup time. A couple of tests are impacted they no longer need to backup such "empty" dirstate.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Tue, 14 Feb 2023 23:05:18 +0100
parents 9313d8666a0f
children f4eef08575ce
comparison
equal deleted inserted replaced
50001:9313d8666a0f 50002:e358f6e0e50e
1484 1484
1485 def _new_backup_data_filename(self, backupname): 1485 def _new_backup_data_filename(self, backupname):
1486 """return a filename to backup a data-file or None""" 1486 """return a filename to backup a data-file or None"""
1487 if not self._use_dirstate_v2: 1487 if not self._use_dirstate_v2:
1488 return None 1488 return None
1489 if self._map.docket.uuid is None:
1490 # not created yet, nothing to backup
1491 return None
1489 data_filename = self._map.docket.data_filename() 1492 data_filename = self._map.docket.data_filename()
1490 return data_filename, self.data_backup_filename(backupname) 1493 return data_filename, self.data_backup_filename(backupname)
1491 1494
1492 def backup_data_file(self, backupname): 1495 def backup_data_file(self, backupname):
1493 if not self._use_dirstate_v2: 1496 if not self._use_dirstate_v2:
1504 assert backupname != filename 1507 assert backupname != filename
1505 1508
1506 # use '_writedirstate' instead of 'write' to write changes certainly, 1509 # use '_writedirstate' instead of 'write' to write changes certainly,
1507 # because the latter omits writing out if transaction is running. 1510 # because the latter omits writing out if transaction is running.
1508 # output file will be used to create backup of dirstate at this point. 1511 # output file will be used to create backup of dirstate at this point.
1509 if self._dirty or not self._opener.exists(filename): 1512 if self._dirty:
1510 self._writedirstate( 1513 self._writedirstate(
1511 tr, 1514 tr,
1512 self._opener(filename, b"w", atomictemp=True, checkambig=True), 1515 self._opener(filename, b"w", atomictemp=True, checkambig=True),
1513 ) 1516 )
1514 1517
1528 # failure, even if tr.writepending isn't invoked until the 1531 # failure, even if tr.writepending isn't invoked until the
1529 # end of this transaction 1532 # end of this transaction
1530 tr.registertmp(filename, location=b'plain') 1533 tr.registertmp(filename, location=b'plain')
1531 1534
1532 self._opener.tryunlink(backupname) 1535 self._opener.tryunlink(backupname)
1533 if True: 1536 if self._opener.exists(filename):
1534 # hardlink backup is okay because _writedirstate is always called 1537 # hardlink backup is okay because _writedirstate is always called
1535 # with an "atomictemp=True" file. 1538 # with an "atomictemp=True" file.
1536 util.copyfile( 1539 util.copyfile(
1537 self._opener.join(filename), 1540 self._opener.join(filename),
1538 self._opener.join(backupname), 1541 self._opener.join(backupname),
1555 def restorebackup(self, tr, backupname): 1558 def restorebackup(self, tr, backupname):
1556 '''Restore dirstate by backup file''' 1559 '''Restore dirstate by backup file'''
1557 # this "invalidate()" prevents "wlock.release()" from writing 1560 # this "invalidate()" prevents "wlock.release()" from writing
1558 # changes of dirstate out after restoring from backup file 1561 # changes of dirstate out after restoring from backup file
1559 self.invalidate() 1562 self.invalidate()
1563 o = self._opener
1564 if not o.exists(backupname):
1565 # there was no file backup, delete existing files
1566 filename = self._actualfilename(tr)
1567 data_file = None
1568 if self._use_dirstate_v2:
1569 data_file = self._map.docket.data_filename()
1570 if o.exists(filename):
1571 o.unlink(filename)
1572 if data_file is not None and o.exists(data_file):
1573 o.unlink(data_file)
1574 return
1560 filename = self._actualfilename(tr) 1575 filename = self._actualfilename(tr)
1561 o = self._opener
1562 data_pair = self.backup_data_file(backupname) 1576 data_pair = self.backup_data_file(backupname)
1563 if util.samefile(o.join(backupname), o.join(filename)): 1577 if o.exists(filename) and util.samefile(
1578 o.join(backupname), o.join(filename)
1579 ):
1564 o.unlink(backupname) 1580 o.unlink(backupname)
1565 else: 1581 else:
1566 o.rename(backupname, filename, checkambig=True) 1582 o.rename(backupname, filename, checkambig=True)
1567 1583
1568 if data_pair is not None: 1584 if data_pair is not None:
1575 o.rename(data_backup, target, checkambig=True) 1591 o.rename(data_backup, target, checkambig=True)
1576 1592
1577 def clearbackup(self, tr, backupname): 1593 def clearbackup(self, tr, backupname):
1578 '''Clear backup file''' 1594 '''Clear backup file'''
1579 o = self._opener 1595 o = self._opener
1580 data_backup = self.backup_data_file(backupname) 1596 if o.exists(backupname):
1581 o.unlink(backupname) 1597 data_backup = self.backup_data_file(backupname)
1582 1598 o.unlink(backupname)
1583 if data_backup is not None: 1599 if data_backup is not None:
1584 o.unlink(data_backup[0]) 1600 o.unlink(data_backup[0])
1585 1601
1586 def verify(self, m1, m2, p1, narrow_matcher=None): 1602 def verify(self, m1, m2, p1, narrow_matcher=None):
1587 """ 1603 """
1588 check the dirstate contents against the parent manifest and yield errors 1604 check the dirstate contents against the parent manifest and yield errors
1589 """ 1605 """