comparison mercurial/util.py @ 13204:5b83ab614dab stable

checknlink: use two testfiles (issue2543) Preventing file loss repository corruption (e.g. vanished changelog.i) when Mercurial pushes to repositories on Windows shares served by Samba. This is a workaround for Samba bug 7863, which is present in current latest stable Samba 3.5.6 and various prior versions down to 3.0.26a (the oldest one I tested). Of course this should be fixed in Samba, but there probably aren't that many other applications who use hardlinks that extensively and keep files open like Mercurial, so the pressure to fix this on Samba is probably not that high. And even if the Samba project should be able to fix their bug within a month or two, it will take quite some time until users upgrade their Samba installs.
author Adrian Buehlmann <adrian@cadifra.com>
date Mon, 13 Dec 2010 22:38:06 +0100
parents 6c9345f9edca
children 18f0084a97c8 5d0a30fad7de
comparison
equal deleted inserted replaced
13203:aa72ff5abf5f 13204:5b83ab614dab
715 except (OSError, AttributeError): 715 except (OSError, AttributeError):
716 return False 716 return False
717 717
718 def checknlink(testfile): 718 def checknlink(testfile):
719 '''check whether hardlink count reporting works properly''' 719 '''check whether hardlink count reporting works properly'''
720 f = testfile + ".hgtmp" 720
721 721 # testfile may be open, so we need a separate file for checking to
722 try: 722 # work around issue2543 (or testfile may get lost on Samba shares)
723 os_link(testfile, f) 723 f1 = testfile + ".hgtmp1"
724 except OSError: 724 if os.path.lexists(f1):
725 return False 725 return False
726 726 try:
727 try: 727 posixfile(f1, 'w').close()
728 except IOError:
729 return False
730
731 f2 = testfile + ".hgtmp2"
732 fd = None
733 try:
734 try:
735 os_link(f1, f2)
736 except OSError:
737 return False
738
728 # nlinks() may behave differently for files on Windows shares if 739 # nlinks() may behave differently for files on Windows shares if
729 # the file is open. 740 # the file is open.
730 fd = open(f) 741 fd = open(f2)
731 return nlinks(f) > 1 742 return nlinks(f2) > 1
732 finally: 743 finally:
733 fd.close() 744 if fd is not None:
734 os.unlink(f) 745 fd.close()
746 for f in (f1, f2):
747 try:
748 os.unlink(f)
749 except OSError:
750 pass
735 751
736 return False 752 return False
737 753
738 def endswithsep(path): 754 def endswithsep(path):
739 '''Check path ends with os.sep or os.altsep.''' 755 '''Check path ends with os.sep or os.altsep.'''