# HG changeset patch # User Mark Thomas # Date 2017-10-20 12:53:35 # Node ID c2b30348930fa431b1197b379cd2ff07c03a1060 # Parent 2c80a864e83eb05fdc9d17e78f1fc83ccffabde8 dirstate: clean up when restoring identical backups When a dirstate backup is restored, it is possible that no actual changes to the dirstate have been made. In this case, the backup is still a hardlink to the original dirstate. Unfortunately, `os.rename` silently fails (nothing happens, and no error occurs) when `src` and `dst` are hardlinks to the same file. As a result, the backup is left lying around. Over time, these files accumulate. When restoring dirstate backups, check if the backup and the dirstate are the same file, and if so, just delete the backup. Differential Revision: https://phab.mercurial-scm.org/D1201 diff --git a/mercurial/dirstate.py b/mercurial/dirstate.py --- a/mercurial/dirstate.py +++ b/mercurial/dirstate.py @@ -1187,7 +1187,11 @@ class dirstate(object): # changes of dirstate out after restoring from backup file self.invalidate() filename = self._actualfilename(tr) - self._opener.rename(backupname, filename, checkambig=True) + o = self._opener + if util.samefile(o.join(backupname), o.join(filename)): + o.unlink(backupname) + else: + o.rename(backupname, filename, checkambig=True) def clearbackup(self, tr, backupname): '''Clear backup file''' diff --git a/tests/test-dirstate-backup.t b/tests/test-dirstate-backup.t --- a/tests/test-dirstate-backup.t +++ b/tests/test-dirstate-backup.t @@ -11,9 +11,8 @@ Try to import an empty patch abort: stdin: no diffs found [255] -A dirstate backup is left behind +No dirstate backups are left behind $ ls .hg/dirstate* | sort .hg/dirstate - .hg/dirstate.backup.import.* (glob)