[PATCH STABLE V2] opener: do not unlink symlinks on 'w'rite

Adrian Buehlmann adrian at cadifra.com
Thu Nov 25 16:40:33 CST 2010


# HG changeset patch
# User Adrian Buehlmann <adrian at cadifra.com>
# Date 1290708399 -3600
# Branch stable
# Node ID 0162f745b6ba9f422e22c71f03b0c7d91a17cacb
# Parent  dd24f3e7ca9e68a49fd7f38803e4d98469cad6e4
opener: do not unlink symlinks on 'w'rite

The current code replaces symlinks with a normal file on 'w'rite.

This patch restores the pre 1.7.1 behavior, which preserves symlinks.

diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -890,10 +890,13 @@ class opener(object):
                 return atomictempfile(f, mode, self.createmode)
             try:
                 if 'w' in mode:
-                    st_mode = os.lstat(f).st_mode & 0777
-                    os.unlink(f)
-                    nlink = 0
-                else:
+                    st_mode = os.lstat(f).st_mode
+                    if stat.S_ISLNK(st_mode):
+                        st_mode = None
+                    else:
+                        os.unlink(f)
+                        nlink = 0
+                if st_mode is None:
                     # nlinks() may behave differently for files on Windows
                     # shares if the file is open.
                     fd = open(f)
@@ -913,7 +916,7 @@ class opener(object):
             if st_mode is None:
                 self._fixfilemode(f)
             else:
-                os.chmod(f, st_mode)
+                os.chmod(f, st_mode & 0777)
         return fp
 
     def symlink(self, src, dst):
diff --git a/tests/test-hardlinks.t b/tests/test-hardlinks.t
--- a/tests/test-hardlinks.t
+++ b/tests/test-hardlinks.t
@@ -152,3 +152,46 @@ Committing a change to f1 in r1 must bre
   1 r2/.hg/store/data/f1.i
   1 r2/.hg/store/fncache
 
+
+symlinks should be preserved on write:
+
+  $ cat > writesymlink.py <<EOF
+  > import stat, os
+  > from mercurial import ui, hg
+  > 
+  > def show(f):
+  >     mode = os.lstat('.hg/' + f).st_mode
+  >     print "%s is symlink: %s" % (f, stat.S_ISLNK(mode))
+  > 
+  > fn = 'f2'
+  > 
+  > show('hgrc')
+  > show(fn)
+  > repo = hg.repository(ui.ui(), '.')
+  > f = repo.opener(fn, 'w')
+  > f.write('29919b4dffb283fc5b84f9dd8ddd946e8b62290d\n')
+  > f.close()
+  > show(fn)
+  > EOF
+
+  $ cd r2/.hg
+  $ echo "hello world" > f1
+  $ ln -s f1 f2
+  $ cat f2
+  hello world
+  $ cd ..
+
+  $ python $TESTTMP/writesymlink.py
+  hgrc is symlink: False
+  f2 is symlink: True
+  f2 is symlink: True
+
+  $ cd .hg
+  $ cat f1
+  29919b4dffb283fc5b84f9dd8ddd946e8b62290d
+  $ echo "foo" >> f2
+  $ cat f1
+  29919b4dffb283fc5b84f9dd8ddd946e8b62290d
+  foo
+  $ cd ..
+


More information about the Mercurial-devel mailing list