[PATCH 2 of 2] fix symlinks on symlink-capable os but non-capable filesystem (issue1149)
Dov Feldstern
dfeldstern at fastimap.com
Thu Jul 31 14:50:16 CDT 2008
# HG changeset patch
# User Dov Feldstern <dfeldstern at fastimap.com>
# Date 1217533299 -10800
# Node ID e168d51006fa780a115022a1ed3543d98a9ef5a8
# Parent 1a42f2a5dcdb22ecc291918076cec1481a329c5e
fix symlinks on symlink-capable os but non-capable filesystem (issue1149)
Currently (since breaking in 14789f30ac11), cloning a repository with symlinks
to a non-symlink-capable filesystem, using a symlinks-aware operating system
(e.g., vfat on linux) breaks with the message:
abort: Operation not permitted
This patch fixes that:
1. write a symlink directly as a symlink (currently it's being written as a
file, and only then switched to a symlink by set_flags); note that writing
as a symlink already makes sure that the fs supports symlinks.
2. set_flags should only switch a file to a symlink on a symlink-capable fs.
diff -r 1a42f2a5dcdb -r e168d51006fa hgext/convert/subversion.py
--- a/hgext/convert/subversion.py Thu Jul 31 22:41:19 2008 +0300
+++ b/hgext/convert/subversion.py Thu Jul 31 22:41:39 2008 +0300
@@ -997,7 +997,7 @@
fp = open(hook, 'w')
fp.write(pre_revprop_change)
fp.close()
- util.set_flags(hook, "x")
+ util.set_flags(hook, "x", self.wopener._can_symlink)
xport = transport.SvnRaTransport(url=geturl(path))
self.uuid = svn.ra.get_uuid(xport.ra)
@@ -1024,7 +1024,8 @@
# systematically is just as expensive and much simpler.
was_exec = 'x' not in flags
- util.set_flags(self.wjoin(filename), flags)
+ util.set_flags(self.wjoin(filename), flags,
+ self.wopener._can_symlink)
if was_exec:
if 'x' not in flags:
self.delexec.append(filename)
diff -r 1a42f2a5dcdb -r e168d51006fa mercurial/localrepo.py
--- a/mercurial/localrepo.py Thu Jul 31 22:41:19 2008 +0300
+++ b/mercurial/localrepo.py Thu Jul 31 22:41:39 2008 +0300
@@ -544,8 +544,11 @@
os.unlink(self.wjoin(filename))
except OSError:
pass
- self.wopener(filename, 'w').write(data)
- util.set_flags(self.wjoin(filename), flags)
+ if 'l' in flags:
+ self.wopener.symlink(data, filename)
+ else:
+ self.wopener(filename, 'w').write(data)
+ util.set_flags(self.wjoin(filename), flags, self.wopener._can_symlink)
def wwritedata(self, filename, data):
return self._filter("decode", filename, data)
diff -r 1a42f2a5dcdb -r e168d51006fa mercurial/merge.py
--- a/mercurial/merge.py Thu Jul 31 22:41:19 2008 +0300
+++ b/mercurial/merge.py Thu Jul 31 22:41:39 2008 +0300
@@ -348,7 +348,7 @@
repo.ui.warn(" %s\n" % nf)
elif m == "e": # exec
flags = a[2]
- util.set_flags(repo.wjoin(f), flags)
+ util.set_flags(repo.wjoin(f), flags, repo.wopener._can_symlink)
return updated, merged, removed, unresolved
diff -r 1a42f2a5dcdb -r e168d51006fa mercurial/patch.py
--- a/mercurial/patch.py Thu Jul 31 22:41:19 2008 +0300
+++ b/mercurial/patch.py Thu Jul 31 22:41:39 2008 +0300
@@ -1108,7 +1108,7 @@
if ctype == 'ADD' and not os.path.exists(dst):
repo.wwrite(gp.path, '', flags)
else:
- util.set_flags(dst, flags)
+ util.set_flags(dst, flags, repo.wopener._can_symlink)
cmdutil.addremove(repo, cfiles)
files = patches.keys()
files.extend([r for r in removes if r not in files])
diff -r 1a42f2a5dcdb -r e168d51006fa mercurial/util.py
--- a/mercurial/util.py Thu Jul 31 22:41:19 2008 +0300
+++ b/mercurial/util.py Thu Jul 31 22:41:39 2008 +0300
@@ -1069,7 +1069,7 @@
'''return False if pid dead, True if running or not known'''
return True
- def set_flags(f, flags):
+ def set_flags(f, flags, can_symlink):
pass
def set_binary(fd):
@@ -1216,12 +1216,12 @@
"""check whether a file is executable"""
return (os.lstat(f).st_mode & 0100 != 0)
- def set_flags(f, flags):
+ def set_flags(f, flags, can_symlink):
s = os.lstat(f).st_mode
x = "x" in flags
l = "l" in flags
if l:
- if not stat.S_ISLNK(s):
+ if can_symlink and not stat.S_ISLNK(s):
# switch file to link
data = file(f).read()
os.unlink(f)
More information about the Mercurial-devel
mailing list