# HG changeset patch # User Alexis S. L. Carvalho # Date 1184186441 10800 # Node ID 41ad4105dde962b93f9cd826c484aa33ee750ba8 # Parent 89defeae88f3a9f0a6e81910c7b5ce5dc3998bdf 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. diff --git a/mercurial/util.py b/mercurial/util.py --- 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."""