mercurial/merge.py
changeset 18338 384df4db6520
parent 18336 77973b6a7b0b
child 18339 aadefcee1f5e
--- a/mercurial/merge.py	Tue Jan 15 01:05:12 2013 +0100
+++ b/mercurial/merge.py	Wed Jan 09 02:02:45 2013 +0100
@@ -45,11 +45,11 @@
                 f.write("\0".join([d] + v) + "\n")
             f.close()
             self._dirty = False
-    def add(self, fcl, fco, fca, fd, flags):
+    def add(self, fcl, fco, fca, fd):
         hash = util.sha1(fcl.path()).hexdigest()
         self._repo.opener.write("merge/" + hash, fcl.data())
         self._state[fd] = ['u', hash, fcl.path(), fca.path(),
-                           hex(fca.filenode()), fco.path(), flags]
+                           hex(fca.filenode()), fco.path(), fcl.flags()]
         self._dirty = True
     def __contains__(self, dfile):
         return dfile in self._state
@@ -67,12 +67,22 @@
         if self[dfile] == 'r':
             return 0
         state, hash, lfile, afile, anode, ofile, flags = self._state[dfile]
+        fcd = wctx[dfile]
+        fco = octx[ofile]
+        fca = self._repo.filectx(afile, fileid=anode)
+        # "premerge" x flags
+        flo = fco.flags()
+        fla = fca.flags()
+        if 'x' in flags + flo + fla and 'l' not in flags + flo + fla:
+            if fca.node() == nullid:
+                self._repo.ui.warn(_('warning: cannot merge flags for %s\n') %
+                                   afile)
+            elif flags == fla:
+                flags = flo
+        # restore local
         f = self._repo.opener("merge/" + hash)
         self._repo.wwrite(dfile, f.read(), flags)
         f.close()
-        fcd = wctx[dfile]
-        fco = octx[ofile]
-        fca = self._repo.filectx(afile, fileid=anode)
         r = filemerge.filemerge(self._repo, self._local, lfile, fcd, fco, fca)
         if r is None:
             # no real conflict
@@ -183,32 +193,6 @@
     partial = function to filter file lists
     """
 
-    def fmerge(f, f2, fa):
-        """merge flags"""
-        a, m, n = ma.flags(fa), m1.flags(f), m2.flags(f2)
-        if m == n: # flags agree
-            return m # unchanged
-        if m and n and not a: # flags set, don't agree, differ from parent
-            r = repo.ui.promptchoice(
-                _(" conflicting flags for %s\n"
-                  "(n)one, e(x)ec or sym(l)ink?") % f,
-                (_("&None"), _("E&xec"), _("Sym&link")), 0)
-            if r == 1:
-                return "x" # Exec
-            if r == 2:
-                return "l" # Symlink
-            return ""
-        if m and m != a: # changed from a to m
-            return m
-        if n and n != a: # changed from a to n
-            if (n == 'l' or a == 'l') and m1.get(f) != ma.get(f):
-                # can't automatically merge symlink flag when there
-                # are file-level conflicts here, let filemerge take
-                # care of it
-                return m
-            return n
-        return '' # flag was cleared
-
     def act(msg, m, f, *args):
         repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
         actions.append((f, m) + args)
@@ -248,17 +232,25 @@
         if partial and not partial(f):
             continue
         if f in m2:
-            rflags = fmerge(f, f, f)
+            n2 = m2[f]
+            fl1, fl2, fla = m1.flags(f), m2.flags(f), ma.flags(f)
+            nol = 'l' not in fl1 + fl2 + fla
             a = ma.get(f, nullid)
-            if n == m2[f] or m2[f] == a: # same or local newer
-                # is file locally modified or flags need changing?
-                # dirstate flags may need to be made current
-                if m1.flags(f) != rflags or n[20:]:
-                    act("update permissions", "e", f, rflags)
-            elif n == a: # remote newer
-                act("remote is newer", "g", f, rflags)
-            else: # both changed
-                act("versions differ", "m", f, f, f, rflags, False)
+            if n == n2 and fl1 == fl2:
+                pass # same - keep local
+            elif n2 == a and fl2 == fla:
+                pass # remote unchanged - keep local
+            elif n == a and fl1 == fla: # local unchanged - use remote
+                if n == n2: # optimization: keep local content
+                    act("update permissions", "e", f, fl2)
+                else:
+                    act("remote is newer", "g", f, fl2)
+            elif nol and n2 == a: # remote only changed 'x'
+                act("update permissions", "e", f, fl2)
+            elif nol and n == a: # local only changed 'x'
+                act("remote is newer", "g", f, fl)
+            else: # both changed something
+                act("versions differ", "m", f, f, f, False)
         elif f in copied: # files we'll deal with on m2 side
             pass
         elif f in movewithdir: # directory rename
@@ -267,8 +259,7 @@
                 m1.flags(f))
         elif f in copy: # case 2 A,B/B/B or case 4,21 A/B/B
             f2 = copy[f]
-            act("local copied/moved to " + f2, "m", f, f2, f,
-                fmerge(f, f2, f2), False)
+            act("local copied/moved to " + f2, "m", f, f2, f, False)
         elif f in ma: # clean, a different, no remote
             if n != ma[f]:
                 if repo.ui.promptchoice(
@@ -296,16 +287,15 @@
             f2 = copy[f]
             if f2 in m2: # rename case 1, A/A,B/A
                 act("remote copied to " + f, "m",
-                    f2, f, f, fmerge(f2, f, f2), False)
+                    f2, f, f, False)
             else: # case 3,20 A/B/A
                 act("remote moved to " + f, "m",
-                    f2, f, f, fmerge(f2, f, f2), True)
+                    f2, f, f, True)
         elif f not in ma:
             if (not overwrite
                 and _checkunknownfile(repo, p1, p2, f)):
-                rflags = fmerge(f, f, f)
                 act("remote differs from untracked local",
-                    "m", f, f, f, rflags, False)
+                    "m", f, f, f, False)
             else:
                 act("remote created", "g", f, m2.flags(f))
         elif n != ma[f]:
@@ -341,7 +331,7 @@
     for a in actions:
         f, m = a[:2]
         if m == "m": # merge
-            f2, fd, flags, move = a[2:]
+            f2, fd, move = a[2:]
             if fd == '.hgsubstate': # merged internally
                 continue
             repo.ui.debug("preserving %s for resolve of %s\n" % (f, fd))
@@ -356,7 +346,7 @@
                 fca = fcl.ancestor(fco, actx)
             if not fca:
                 fca = repo.filectx(f, fileid=nullrev)
-            ms.add(fcl, fco, fca, fd, flags)
+            ms.add(fcl, fco, fca, fd)
             if f != fd and move:
                 moves.append(f)
 
@@ -390,7 +380,7 @@
                 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
                                  overwrite)
                 continue
-            f2, fd, flags, move = a[2:]
+            f2, fd, move = a[2:]
             audit(fd)
             r = ms.resolve(fd, wctx, mctx)
             if r is not None and r > 0:
@@ -484,7 +474,7 @@
             else:
                 repo.dirstate.normal(f)
         elif m == "m": # merge
-            f2, fd, flag, move = a[2:]
+            f2, fd, move = a[2:]
             if branchmerge:
                 # We've done a branch merge, mark this file as merged
                 # so that we properly record the merger later