1431 if tr: |
1432 if tr: |
1432 return self._pendingfilename |
1433 return self._pendingfilename |
1433 else: |
1434 else: |
1434 return self._filename |
1435 return self._filename |
1435 |
1436 |
|
1437 def data_backup_filename(self, backupname): |
|
1438 if not self._use_dirstate_v2: |
|
1439 return None |
|
1440 return backupname + b'.v2-data' |
|
1441 |
|
1442 def _new_backup_data_filename(self, backupname): |
|
1443 """return a filename to backup a data-file or None""" |
|
1444 if not self._use_dirstate_v2: |
|
1445 return None |
|
1446 data_filename = self._map.docket.data_filename() |
|
1447 return data_filename, self.data_backup_filename(backupname) |
|
1448 |
|
1449 def backup_data_file(self, backupname): |
|
1450 if not self._use_dirstate_v2: |
|
1451 return None |
|
1452 docket = docketmod.DirstateDocket.parse( |
|
1453 self._opener.read(backupname), |
|
1454 self._nodeconstants, |
|
1455 ) |
|
1456 return self.data_backup_filename(backupname), docket.data_filename() |
|
1457 |
1436 def savebackup(self, tr, backupname): |
1458 def savebackup(self, tr, backupname): |
1437 '''Save current dirstate into backup file''' |
1459 '''Save current dirstate into backup file''' |
1438 filename = self._actualfilename(tr) |
1460 filename = self._actualfilename(tr) |
1439 assert backupname != filename |
1461 assert backupname != filename |
1440 |
1462 |
1470 util.copyfile( |
1492 util.copyfile( |
1471 self._opener.join(filename), |
1493 self._opener.join(filename), |
1472 self._opener.join(backupname), |
1494 self._opener.join(backupname), |
1473 hardlink=True, |
1495 hardlink=True, |
1474 ) |
1496 ) |
|
1497 data_pair = self._new_backup_data_filename(backupname) |
|
1498 if data_pair is not None: |
|
1499 data_filename, bck_data_filename = data_pair |
|
1500 util.copyfile( |
|
1501 self._opener.join(data_filename), |
|
1502 self._opener.join(bck_data_filename), |
|
1503 hardlink=True, |
|
1504 ) |
|
1505 if tr is not None: |
|
1506 # ensure that pending file written above is unlinked at |
|
1507 # failure, even if tr.writepending isn't invoked until the |
|
1508 # end of this transaction |
|
1509 tr.registertmp(bck_data_filename, location=b'plain') |
1475 |
1510 |
1476 def restorebackup(self, tr, backupname): |
1511 def restorebackup(self, tr, backupname): |
1477 '''Restore dirstate by backup file''' |
1512 '''Restore dirstate by backup file''' |
1478 # this "invalidate()" prevents "wlock.release()" from writing |
1513 # this "invalidate()" prevents "wlock.release()" from writing |
1479 # changes of dirstate out after restoring from backup file |
1514 # changes of dirstate out after restoring from backup file |
1480 self.invalidate() |
1515 self.invalidate() |
1481 filename = self._actualfilename(tr) |
1516 filename = self._actualfilename(tr) |
1482 o = self._opener |
1517 o = self._opener |
|
1518 data_pair = self.backup_data_file(backupname) |
1483 if util.samefile(o.join(backupname), o.join(filename)): |
1519 if util.samefile(o.join(backupname), o.join(filename)): |
1484 o.unlink(backupname) |
1520 o.unlink(backupname) |
1485 else: |
1521 else: |
1486 o.rename(backupname, filename, checkambig=True) |
1522 o.rename(backupname, filename, checkambig=True) |
1487 |
1523 |
|
1524 if data_pair is not None: |
|
1525 data_backup, target = data_pair |
|
1526 if o.exists(target) and util.samefile( |
|
1527 o.join(data_backup), o.join(target) |
|
1528 ): |
|
1529 o.unlink(data_backup) |
|
1530 else: |
|
1531 o.rename(data_backup, target, checkambig=True) |
|
1532 |
1488 def clearbackup(self, tr, backupname): |
1533 def clearbackup(self, tr, backupname): |
1489 '''Clear backup file''' |
1534 '''Clear backup file''' |
1490 self._opener.unlink(backupname) |
1535 o = self._opener |
|
1536 data_backup = self.backup_data_file(backupname) |
|
1537 o.unlink(backupname) |
|
1538 |
|
1539 if data_backup is not None: |
|
1540 o.unlink(data_backup[0]) |
1491 |
1541 |
1492 def verify(self, m1, m2): |
1542 def verify(self, m1, m2): |
1493 """check the dirstate content again the parent manifest and yield errors""" |
1543 """check the dirstate content again the parent manifest and yield errors""" |
1494 missing_from_p1 = b"%s in state %s, but not in manifest1\n" |
1544 missing_from_p1 = b"%s in state %s, but not in manifest1\n" |
1495 unexpected_in_p1 = b"%s in state %s, but also in manifest1\n" |
1545 unexpected_in_p1 = b"%s in state %s, but also in manifest1\n" |