symlinks: minimal support for symlinks in merge/update
authorMatt Mackall <mpm@selenic.com>
Fri, 29 Dec 2006 20:04:31 -0600
changeset 4007 20da40cc1c73
parent 4006 67982d3ee76c
child 4016 a195f11ed1a2
child 4019 c3864dfb7812
symlinks: minimal support for symlinks in merge/update This will get angry, confused, and sad if you try to merge a symlink with a regular file.
mercurial/localrepo.py
mercurial/merge.py
--- a/mercurial/localrepo.py	Fri Dec 29 20:04:31 2006 -0600
+++ b/mercurial/localrepo.py	Fri Dec 29 20:04:31 2006 -0600
@@ -508,7 +508,10 @@
     def wwrite(self, filename, data, flags):
         data = self._filter("decode", filename, data)
         if "l" in flags:
-            os.unlink(self.wjoin(filename))
+            try:
+                os.unlink(self.wjoin(filename))
+            except OSError:
+                pass
             os.symlink(data, self.wjoin(filename))
         else:
             try:
--- a/mercurial/merge.py	Fri Dec 29 20:04:31 2006 -0600
+++ b/mercurial/merge.py	Fri Dec 29 20:04:31 2006 -0600
@@ -220,12 +220,17 @@
     copy = {}
 
     def fmerge(f, f2=None, fa=None):
-        """merge executable flags"""
+        """merge flags"""
         if not f2:
             f2 = f
             fa = f
         a, b, c = ma.execf(fa), m1.execf(f), m2.execf(f2)
-        return ((a^b) | (a^c)) ^ a
+        if ((a^b) | (a^c)) ^ a:
+            return 'x'
+        a, b, c = ma.linkf(fa), m1.linkf(f), m2.linkf(f2)
+        if ((a^b) | (a^c)) ^ a:
+            return 'l'
+        return ''
 
     def act(msg, m, f, *args):
         repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
@@ -250,21 +255,21 @@
                 # is remote's version newer?
                 # or are we going back in time and clean?
                 elif overwrite or m2[f] != a or (backwards and not n[20:]):
-                    act("remote is newer", "g", f, m2.execf(f))
+                    act("remote is newer", "g", f, m2.flags(f))
                 # local is newer, not overwrite, check mode bits
-                elif fmerge(f) != m1.execf(f):
-                    act("update permissions", "e", f, m2.execf(f))
+                elif fmerge(f) != m1.flags(f):
+                    act("update permissions", "e", f, m2.flags(f))
             # contents same, check mode bits
-            elif m1.execf(f) != m2.execf(f):
-                if overwrite or fmerge(f) != m1.execf(f):
-                    act("update permissions", "e", f, m2.execf(f))
+            elif m1.flags(f) != m2.flags(f):
+                if overwrite or fmerge(f) != m1.flags(f):
+                    act("update permissions", "e", f, m2.flags(f))
         elif f in copied:
             continue
         elif f in copy:
             f2 = copy[f]
             if f2 not in m2: # directory rename
                 act("remote renamed directory to " + f2, "d",
-                    f, None, f2, m1.execf(f))
+                    f, None, f2, m1.flags(f))
             elif f2 in m1: # case 2 A,B/B/B
                 act("local copied to " + f2, "m",
                     f, f2, f, fmerge(f, f2, f2), False)
@@ -295,7 +300,7 @@
             f2 = copy[f]
             if f2 not in m1: # directory rename
                 act("local renamed directory to " + f2, "d",
-                    None, f, f2, m2.execf(f))
+                    None, f, f2, m2.flags(f))
             elif f2 in m2: # rename case 1, A/A,B/A
                 act("remote copied to " + f, "m",
                     f2, f, f, fmerge(f2, f, f2), False)
@@ -304,14 +309,14 @@
                     f2, f, f, fmerge(f2, f, f2), True)
         elif f in ma:
             if overwrite or backwards:
-                act("recreating", "g", f, m2.execf(f))
+                act("recreating", "g", f, m2.flags(f))
             elif n != ma[f]:
                 if repo.ui.prompt(
                     (_("remote changed %s which local deleted\n") % f) +
                     _("(k)eep or (d)elete?"), _("[kd]"), _("k")) == _("k"):
-                    act("prompt recreating", "g", f, m2.execf(f))
+                    act("prompt recreating", "g", f, m2.flags(f))
         else:
-            act("remote created", "g", f, m2.execf(f))
+            act("remote created", "g", f, m2.flags(f))
 
     return action
 
@@ -335,7 +340,7 @@
                                  (f, inst.strerror))
             removed += 1
         elif m == "m": # merge
-            f2, fd, flag, move = a[2:]
+            f2, fd, flags, move = a[2:]
             r = filemerge(repo, f, f2, wctx, mctx)
             if r > 0:
                 unresolved += 1
@@ -346,32 +351,32 @@
                     merged += 1
                 if f != fd:
                     repo.ui.debug(_("copying %s to %s\n") % (f, fd))
-                    repo.wwrite(fd, repo.wread(f), flag and 'x' or '')
+                    repo.wwrite(fd, repo.wread(f), flags)
                     if move:
                         repo.ui.debug(_("removing %s\n") % f)
                         os.unlink(repo.wjoin(f))
-            util.set_exec(repo.wjoin(fd), flag)
+            util.set_exec(repo.wjoin(fd), "x" in flags)
         elif m == "g": # get
-            flag = a[2]
+            flags = a[2]
             repo.ui.note(_("getting %s\n") % f)
             t = mctx.filectx(f).data()
-            repo.wwrite(f, t, flag and 'x' or '')
+            repo.wwrite(f, t, flags)
             updated += 1
         elif m == "d": # directory rename
-            f2, fd, flag = a[2:]
+            f2, fd, flags = a[2:]
             if f:
                 repo.ui.note(_("moving %s to %s\n") % (f, fd))
                 t = wctx.filectx(f).data()
-                repo.wwrite(fd, t, flag and 'x' or '')
+                repo.wwrite(fd, t, flags)
                 util.unlink(repo.wjoin(f))
             if f2:
                 repo.ui.note(_("getting %s to %s\n") % (f2, fd))
                 t = mctx.filectx(f2).data()
-                repo.wwrite(fd, t, flag and 'x' or '')
+                repo.wwrite(fd, t, flags)
             updated += 1
         elif m == "e": # exec
-            flag = a[2]
-            util.set_exec(repo.wjoin(f), flag)
+            flags = a[2]
+            util.set_exec(repo.wjoin(f), flags)
 
     return updated, merged, removed, unresolved