mercurial/context.py
branchstable
changeset 15337 cf5f9df6406b
parent 14674 1c151b963254
child 15421 405ca90df2b1
child 15848 012b285cf643
--- a/mercurial/context.py	Fri Oct 21 15:09:33 2011 -0500
+++ b/mercurial/context.py	Sat Oct 22 16:12:33 2011 -0500
@@ -632,6 +632,42 @@
     def __contains__(self, key):
         return self._repo.dirstate[key] not in "?r"
 
+    def _buildflagfunc(self):
+        # Create a fallback function for getting file flags when the
+        # filesystem doesn't support them
+
+        copiesget = self._repo.dirstate.copies().get
+
+        if len(self._parents) < 2:
+            # when we have one parent, it's easy: copy from parent
+            man = self._parents[0].manifest()
+            def func(f):
+                f = copiesget(f, f)
+                return man.flags(f)
+        else:
+            # merges are tricky: we try to reconstruct the unstored
+            # result from the merge (issue1802)
+            p1, p2 = self._parents
+            pa = p1.ancestor(p2)
+            m1, m2, ma = p1.manifest(), p2.manifest(), pa.manifest()
+
+            def func(f):
+                f = copiesget(f, f) # may be wrong for merges with copies
+                fl1, fl2, fla = m1.flags(f), m2.flags(f), ma.flags(f)
+                if fl1 == fl2:
+                    return fl1
+                if fl1 == fla:
+                    return fl2
+                if fl2 == fla:
+                    return fl1
+                return '' # punt for conflicts
+
+        return func
+
+    @propertycache
+    def _flagfunc(self):
+        return self._repo.dirstate.flagfunc(self._buildflagfunc)
+
     @propertycache
     def _manifest(self):
         """generate a manifest corresponding to the working directory"""
@@ -640,7 +676,6 @@
             self.status(unknown=True)
 
         man = self._parents[0].manifest().copy()
-        copied = self._repo.dirstate.copies()
         if len(self._parents) > 1:
             man2 = self.p2().manifest()
             def getman(f):
@@ -649,10 +684,9 @@
                 return man2
         else:
             getman = lambda f: man
-        def cf(f):
-            f = copied.get(f, f)
-            return getman(f).flags(f)
-        ff = self._repo.dirstate.flagfunc(cf)
+
+        copied = self._repo.dirstate.copies()
+        ff = self._flagfunc
         modified, added, removed, deleted = self._status
         unknown = self._unknown
         for i, l in (("a", added), ("m", modified), ("u", unknown)):
@@ -767,23 +801,10 @@
             except KeyError:
                 return ''
 
-        orig = self._repo.dirstate.copies().get(path, path)
-
-        def findflag(ctx):
-            mnode = ctx.changeset()[0]
-            node, flag = self._repo.manifest.find(mnode, orig)
-            ff = self._repo.dirstate.flagfunc(lambda x: flag or '')
-            try:
-                return ff(path)
-            except OSError:
-                pass
-
-        flag = findflag(self._parents[0])
-        if flag is None and len(self.parents()) > 1:
-            flag = findflag(self._parents[1])
-        if flag is None or self._repo.dirstate[path] == 'r':
+        try:
+            return self._flagfunc(path)
+        except OSError:
             return ''
-        return flag
 
     def filectx(self, path, filelog=None):
         """get a file context from the working directory"""