changeset 4859:41ad4105dde9

Add symlink method to util.opener. Differences from os.symlink: - the symlink name is relative to the opener base directory - if a file with that name already exists, it's removed - if necessary, parent directories are created - if the system (OS or filesystem) doesn't support symlinks, a regular file is created. Its contents are the symlink target.
author Alexis S. L. Carvalho <alexis@cecm.usp.br>
date Wed, 11 Jul 2007 17:40:41 -0300
parents 89defeae88f3
children 0403b80352c9
files mercurial/util.py
diffstat 1 files changed, 26 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -1260,6 +1260,12 @@ class opener(object):
         self.base = base
         self.audit = audit
 
+    def __getattr__(self, name):
+        if name == '_can_symlink':
+            self._can_symlink = checklink(self.base)
+            return self._can_symlink
+        raise AttributeError(name)
+
     def __call__(self, path, mode="r", text=False, atomictemp=False):
         if self.audit:
             audit_path(path)
@@ -1282,6 +1288,26 @@ class opener(object):
                 rename(mktempcopy(f), f)
         return posixfile(f, mode)
 
+    def symlink(self, src, dst):
+        if self.audit:
+            audit_path(dst)
+        linkname = os.path.join(self.base, dst)
+        try:
+            os.unlink(linkname)
+        except OSError:
+            pass
+
+        dirname = os.path.dirname(linkname)
+        if not os.path.exists(dirname):
+            os.makedirs(dirname)
+
+        if self._can_symlink:
+            os.symlink(src, linkname)
+        else:
+            f = self(self, dst, "w")
+            f.write(src)
+            f.close()
+
 class chunkbuffer(object):
     """Allow arbitrary sized chunks of data to be efficiently read from an
     iterator over chunks of arbitrary size."""