simplify flag handling
authorMatt Mackall <mpm@selenic.com>
Thu, 26 Jun 2008 13:46:34 -0500
changeset 6743 86e8187b721a
parent 6742 2d54e7c1e69d
child 6744 d3691d31fc9c
simplify flag handling add _checklink var to dirstate introduce dirstate.flagfunc switch users of util.execfunc/linkfunc to flagfunc change manifestdict.set to take a flags string change ctx.fileflags to ctx.flags change gitmode func to a dict remove util.execfunc/linkfunc
hgext/keyword.py
mercurial/commands.py
mercurial/context.py
mercurial/dirstate.py
mercurial/filemerge.py
mercurial/localrepo.py
mercurial/manifest.py
mercurial/patch.py
mercurial/util.py
--- a/hgext/keyword.py	Thu Jun 26 13:46:33 2008 -0500
+++ b/hgext/keyword.py	Thu Jun 26 13:46:34 2008 -0500
@@ -387,7 +387,7 @@
         files += unknown
     files.sort()
     wctx = repo.changectx(None)
-    islink = lambda p: 'l' in wctx.fileflags(p)
+    islink = lambda p: 'l' in wctx.flags(p)
     kwfiles = [f for f in files if kwt.iskwfile(f, islink)]
     cwd = pats and repo.getcwd() or ''
     kwfstats = not opts.get('ignore') and (('K', kwfiles),) or ()
--- a/mercurial/commands.py	Thu Jun 26 13:46:33 2008 -0500
+++ b/mercurial/commands.py	Thu Jun 26 13:46:34 2008 -0500
@@ -2480,7 +2480,7 @@
         if not opts.get('dry_run'):
             def checkout(f):
                 fc = ctx[f]
-                repo.wwrite(f, fc.data(), fc.fileflags())
+                repo.wwrite(f, fc.data(), fc.flags())
 
             audit_path = util.path_auditor(repo.root)
             for f in remove[0]:
--- a/mercurial/context.py	Thu Jun 26 13:46:33 2008 -0500
+++ b/mercurial/context.py	Thu Jun 26 13:46:34 2008 -0500
@@ -118,7 +118,7 @@
     def filenode(self, path):
         return self._fileinfo(path)[0]
 
-    def fileflags(self, path):
+    def flags(self, path):
         try:
             return self._fileinfo(path)[1]
         except revlog.LookupError:
@@ -237,9 +237,9 @@
 
     def filerev(self): return self._filerev
     def filenode(self): return self._filenode
-    def fileflags(self): return self._changectx.fileflags(self._path)
-    def isexec(self): return 'x' in self.fileflags()
-    def islink(self): return 'l' in self.fileflags()
+    def flags(self): return self._changectx.flags(self._path)
+    def isexec(self): return 'x' in self.flags()
+    def islink(self): return 'l' in self.flags()
     def filelog(self): return self._filelog
 
     def rev(self):
@@ -509,16 +509,14 @@
 
         man = self._parents[0].manifest().copy()
         copied = self._repo.dirstate.copies()
-        is_exec = util.execfunc(self._repo.root,
-                                lambda p: man.execf(copied.get(p,p)))
-        is_link = util.linkfunc(self._repo.root,
-                                lambda p: man.linkf(copied.get(p,p)))
+        cf = lambda x: man.flags(copied.get(x, x))
+        ff = self._repo.dirstate.flagfunc(cf)
         modified, added, removed, deleted, unknown = self._status[:5]
         for i, l in (("a", added), ("m", modified), ("u", unknown)):
             for f in l:
                 man[f] = man.get(copied.get(f, f), nullid) + i
                 try:
-                    man.set(f, is_exec(f), is_link(f))
+                    man.set(f, ff(f))
                 except OSError:
                     pass
 
@@ -555,7 +553,7 @@
     def children(self):
         return []
 
-    def fileflags(self, path):
+    def flags(self, path):
         if '_manifest' in self.__dict__:
             try:
                 return self._manifest.flags(path)
@@ -565,12 +563,9 @@
         pnode = self._parents[0].changeset()[0]
         orig = self._repo.dirstate.copies().get(path, path)
         node, flag = self._repo.manifest.find(pnode, orig)
-        is_link = util.linkfunc(self._repo.root,
-                                lambda p: flag and 'l' in flag)
-        is_exec = util.execfunc(self._repo.root,
-                                lambda p: flag and 'x' in flag)
         try:
-            return (is_link(path) and 'l' or '') + (is_exec(path) and 'x' or '')
+            ff = self._repo.dirstate.flagfunc(lambda x: flag or '')
+            return ff(path)
         except OSError:
             pass
 
@@ -724,6 +719,7 @@
     def clean(self): return self._status[5]
     def branch(self): return self._extra['branch']
     def extra(self): return self._extra
+    def flags(self, f): return self[f].flags()
 
     def parents(self):
         """return contexts for each parent changeset"""
@@ -750,7 +746,7 @@
     def __str__(self): return "%s@%s" % (self.path(), self._changectx)
     def path(self): return self._path
     def data(self): return self._data
-    def fileflags(self): return self._flags
+    def flags(self): return self._flags
     def isexec(self): return 'x' in self._flags
     def islink(self): return 'l' in self._flags
     def renamed(self): return self._copied
--- a/mercurial/dirstate.py	Thu Jun 26 13:46:33 2008 -0500
+++ b/mercurial/dirstate.py	Thu Jun 26 13:46:34 2008 -0500
@@ -70,6 +70,9 @@
         elif name == '_slash':
             self._slash = self._ui.configbool('ui', 'slash') and os.sep != '/'
             return self._slash
+        elif name == '_checklink':
+            self._checklink = util.checklink(self._root)
+            return self._checklink
         elif name == '_checkexec':
             self._checkexec = util.checkexec(self._root)
             return self._checkexec
@@ -91,6 +94,34 @@
     def folding(self):
         return self._folding
 
+    def flagfunc(self, fallback):
+        if self._checklink:
+            if self._checkexec:
+                def f(x):
+                    p = os.path.join(self._root, x)
+                    if os.path.islink(p):
+                        return 'l'
+                    if util.is_exec(p):
+                        return 'x'
+                    return ''
+                return f
+            def f(x):
+                if os.path.islink(os.path.join(self._root, x)):
+                    return 'l'
+                if 'x' in fallback(x):
+                    return 'x'
+                return ''
+            return f
+        if self._checkexec:
+            def f(x):
+                if 'l' in fallback(x):
+                    return 'l'
+                if util.is_exec(os.path.join(self._root, x)):
+                    return 'x'
+                return ''
+            return f
+        return fallback
+
     def getcwd(self):
         cwd = os.getcwd()
         if cwd == self._root: return ''
--- a/mercurial/filemerge.py	Thu Jun 26 13:46:33 2008 -0500
+++ b/mercurial/filemerge.py	Thu Jun 26 13:46:34 2008 -0500
@@ -146,7 +146,7 @@
     if tool == "internal:local":
         return 0
     if tool == "internal:other":
-        repo.wwrite(fd, fco.data(), fco.fileflags())
+        repo.wwrite(fd, fco.data(), fco.flags())
         return 0
     if tool == "internal:fail":
         return 1
--- a/mercurial/localrepo.py	Thu Jun 26 13:46:33 2008 -0500
+++ b/mercurial/localrepo.py	Thu Jun 26 13:46:34 2008 -0500
@@ -837,19 +837,16 @@
                 self.ui.note(f + "\n")
                 try:
                     fctx = wctx.filectx(f)
+                    newflags = fctx.flags()
                     new[f] = self.filecommit(fctx, m1, m2, linkrev, trp, changed)
-                    new_exec = fctx.isexec()
-                    new_link = fctx.islink()
                     if ((not changed or changed[-1] != f) and
                         m2.get(f) != new[f]):
                         # mention the file in the changelog if some
                         # flag changed, even if there was no content
                         # change.
-                        old_exec = m1.execf(f)
-                        old_link = m1.linkf(f)
-                        if old_exec != new_exec or old_link != new_link:
+                        if m1.flags(f) != newflags:
                             changed.append(f)
-                    m1.set(f, new_exec, new_link)
+                    m1.set(f, newflags)
                     if use_dirstate:
                         self.dirstate.normal(f)
 
@@ -1009,14 +1006,9 @@
                     fixup = []
                     # do a full compare of any files that might have changed
                     ctx = self.changectx('')
-                    mexec = lambda f: 'x' in ctx.fileflags(f)
-                    mlink = lambda f: 'l' in ctx.fileflags(f)
-                    is_exec = util.execfunc(self.root, mexec)
-                    is_link = util.linkfunc(self.root, mlink)
-                    def flags(f):
-                        return is_link(f) and 'l' or is_exec(f) and 'x' or ''
+                    ff = self.dirstate.flagfunc(ctx.flags)
                     for f in lookup:
-                        if (f not in ctx or flags(f) != ctx.fileflags(f)
+                        if (f not in ctx or ff(f) != ctx.flags(f)
                             or ctx[f].cmp(self.wread(f))):
                             modified.append(f)
                         else:
@@ -1042,11 +1034,10 @@
                 # generate a pseudo-manifest for the working dir
                 # XXX: create it in dirstate.py ?
                 mf2 = mfmatches(self.dirstate.parents()[0])
-                is_exec = util.execfunc(self.root, mf2.execf)
-                is_link = util.linkfunc(self.root, mf2.linkf)
+                ff = self.dirstate.flagfunc(mf2.flags)
                 for f in lookup + modified + added:
                     mf2[f] = ""
-                    mf2.set(f, is_exec(f), is_link(f))
+                    mf2.set(f, ff(f))
                 for f in removed:
                     if f in mf2:
                         del mf2[f]
--- a/mercurial/manifest.py	Thu Jun 26 13:46:33 2008 -0500
+++ b/mercurial/manifest.py	Thu Jun 26 13:46:34 2008 -0500
@@ -24,10 +24,8 @@
     def linkf(self, f):
         "test for symlink in manifest flags"
         return "l" in self.flags(f)
-    def set(self, f, execf=False, linkf=False):
-        if linkf: self._flags[f] = "l"
-        elif execf: self._flags[f] = "x"
-        else: self._flags[f] = ""
+    def set(self, f, flags):
+        self._flags[f] = flags
     def copy(self):
         return manifestdict(dict.copy(self), dict.copy(self._flags))
 
--- a/mercurial/patch.py	Thu Jun 26 13:46:33 2008 -0500
+++ b/mercurial/patch.py	Thu Jun 26 13:46:34 2008 -0500
@@ -1193,16 +1193,6 @@
         return
 
     ctx2 = repo.changectx(node2)
-    if node2:
-        execf2 = ctx2.manifest().execf
-        linkf2 = ctx2.manifest().linkf
-    else:
-        execf2 = util.execfunc(repo.root, None)
-        linkf2 = util.linkfunc(repo.root, None)
-        if execf2 is None:
-            mc = ctx2.parents()[0].manifest().copy()
-            execf2 = mc.execf
-            linkf2 = mc.linkf
 
     if repo.ui.quiet:
         r = None
@@ -1219,6 +1209,8 @@
     all.sort()
     gone = {}
 
+    gitmode = {'l': '120000', 'x': '100755', '': '100644'}
+
     for f in all:
         to = None
         tn = None
@@ -1230,18 +1222,16 @@
             tn = getfilectx(f, ctx2).data()
         a, b = f, f
         if opts.git:
-            def gitmode(x, l):
-                return l and '120000' or (x and '100755' or '100644')
             def addmodehdr(header, omode, nmode):
                 if omode != nmode:
                     header.append('old mode %s\n' % omode)
                     header.append('new mode %s\n' % nmode)
 
             if f in added:
-                mode = gitmode(execf2(f), linkf2(f))
+                mode = gitmode[ctx2.flags(f)]
                 if f in copy:
                     a = copy[f]
-                    omode = gitmode(man1.execf(a), man1.linkf(a))
+                    omode = gitmode[man1.flags(a)]
                     addmodehdr(header, omode, mode)
                     if a in removed and a not in gone:
                         op = 'rename'
@@ -1260,11 +1250,11 @@
                 if f in copy and copy[f] in added and copy[copy[f]] == f:
                     dodiff = False
                 else:
-                    mode = gitmode(man1.execf(f), man1.linkf(f))
-                    header.append('deleted file mode %s\n' % mode)
+                    header.append('deleted file mode %s\n' %
+                                  gitmode[man1.flags(f)])
             else:
-                omode = gitmode(man1.execf(f), man1.linkf(f))
-                nmode = gitmode(execf2(f), linkf2(f))
+                omode = gitmode[man1.flags(f)]
+                nmode = gitmode[ctx2.flags(f)]
                 addmodehdr(header, omode, nmode)
                 if util.binary(to) or util.binary(tn):
                     dodiff = 'binary'
--- a/mercurial/util.py	Thu Jun 26 13:46:33 2008 -0500
+++ b/mercurial/util.py	Thu Jun 26 13:46:34 2008 -0500
@@ -933,12 +933,6 @@
         return False
     return not (new_file_has_exec or exec_flags_cannot_flip)
 
-def execfunc(path, fallback):
-    '''return an is_exec() function with default to fallback'''
-    if checkexec(path):
-        return lambda x: is_exec(os.path.join(path, x))
-    return fallback
-
 def checklink(path):
     """check whether the given path is on a symlink-capable filesystem"""
     # mktemp is not racy because symlink creation will fail if the
@@ -951,12 +945,6 @@
     except (OSError, AttributeError):
         return False
 
-def linkfunc(path, fallback):
-    '''return an is_link() function with default to fallback'''
-    if checklink(path):
-        return lambda x: os.path.islink(os.path.join(path, x))
-    return fallback
-
 _umask = os.umask(0)
 os.umask(_umask)