[PATCH] fix symlinks on symlink-capable os but non-capable filesystem (issue1149)
Dov Feldstern
dfeldstern at fastimap.com
Thu Jul 17 15:12:42 CDT 2008
# HG changeset patch
# User Dov Feldstern <dfeldstern at fastimap.com>
# Date 1216325552 -10800
# Node ID 37ab6350ddb5da09fd7eff7dc53ef19d8b9edfea
# Parent 2134d6c09432e4e3dbee18d93ec9242a332f7cdc
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 2134d6c09432 -r 37ab6350ddb5 hgext/convert/subversion.py
--- a/hgext/convert/subversion.py Fri Jul 11 14:40:44 2008 +0200
+++ b/hgext/convert/subversion.py Thu Jul 17 23:12:32 2008 +0300
@@ -976,7 +976,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)
@@ -1003,7 +1003,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 2134d6c09432 -r 37ab6350ddb5 mercurial/localrepo.py
--- a/mercurial/localrepo.py Fri Jul 11 14:40:44 2008 +0200
+++ b/mercurial/localrepo.py Thu Jul 17 23:12:32 2008 +0300
@@ -565,8 +565,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 2134d6c09432 -r 37ab6350ddb5 mercurial/merge.py
--- a/mercurial/merge.py Fri Jul 11 14:40:44 2008 +0200
+++ b/mercurial/merge.py Thu Jul 17 23:12:32 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 2134d6c09432 -r 37ab6350ddb5 mercurial/patch.py
--- a/mercurial/patch.py Fri Jul 11 14:40:44 2008 +0200
+++ b/mercurial/patch.py Thu Jul 17 23:12:32 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 2134d6c09432 -r 37ab6350ddb5 mercurial/util.py
--- a/mercurial/util.py Fri Jul 11 14:40:44 2008 +0200
+++ b/mercurial/util.py Thu Jul 17 23:12:32 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