checklink: work around sshfs brain-damage (issue3636) stable
authorMatt Mackall <mpm@selenic.com>
Sun, 28 Jul 2013 15:02:32 -0500
branchstable
changeset 19514 cfdae231ba78
parent 19513 9e8298a324ac
child 19515 14c91b18d798
child 19520 e057796450a6
checklink: work around sshfs brain-damage (issue3636) With the follow_symlinks option, sshfs will successfully create links while claiming it encountered an I/O error. In addition, depending on the type of link, it may subsequently be impossible to delete the link via sshfs. Our existing link to '.' will cause sshfs to think the link is a directory, and thus cause unlink to give EISDIR. Links to non-existent names or circular links will cause the created link to not even be visible. Thus, we need to create a new temporary file and link to that. We'll still get a failure, but we'll be able to remove the link.
mercurial/posix.py
--- a/mercurial/posix.py	Sat Jul 27 19:31:14 2013 -0500
+++ b/mercurial/posix.py	Sun Jul 28 15:02:32 2013 -0500
@@ -154,10 +154,16 @@
     # file already exists
     name = tempfile.mktemp(dir=path, prefix='hg-checklink-')
     try:
-        os.symlink(".", name)
+        fd = tempfile.NamedTemporaryFile(dir=path, prefix='hg-checklink-')
+        os.symlink(os.path.basename(fd.name), name)
         os.unlink(name)
         return True
-    except (OSError, AttributeError):
+    except AttributeError:
+        return False
+    except OSError, inst:
+        # sshfs might report failure while successfully creating the link
+        if inst[0] == errno.EIO and os.path.exists(name):
+            os.unlink(name)
         return False
 
 def checkosfilename(path):