diff --git a/hgext/keyword.py b/hgext/keyword.py --- a/hgext/keyword.py +++ b/hgext/keyword.py @@ -387,7 +387,7 @@ def files(ui, repo, *pats, **opts): 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 () diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -2480,7 +2480,7 @@ def revert(ui, repo, *pats, **opts): 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]: diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -118,7 +118,7 @@ class changectx(object): 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 @@ class filectx(object): 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 @@ class workingctx(changectx): 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 @@ class workingctx(changectx): 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 @@ class workingctx(changectx): 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 @@ class memctx(object): 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 @@ class memfilectx(object): 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 diff --git a/mercurial/dirstate.py b/mercurial/dirstate.py --- a/mercurial/dirstate.py +++ b/mercurial/dirstate.py @@ -70,6 +70,9 @@ class dirstate(object): 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 @@ class dirstate(object): 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 '' diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py --- a/mercurial/filemerge.py +++ b/mercurial/filemerge.py @@ -146,7 +146,7 @@ def filemerge(repo, mynode, orig, fcd, f 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 diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -837,19 +837,16 @@ class localrepository(repo.repository): 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 @@ class localrepository(repo.repository): 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 @@ class localrepository(repo.repository): # 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] diff --git a/mercurial/manifest.py b/mercurial/manifest.py --- a/mercurial/manifest.py +++ b/mercurial/manifest.py @@ -24,10 +24,8 @@ class manifestdict(dict): 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)) diff --git a/mercurial/patch.py b/mercurial/patch.py --- a/mercurial/patch.py +++ b/mercurial/patch.py @@ -1193,16 +1193,6 @@ def diff(repo, node1=None, node2=None, m 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 @@ def diff(repo, node1=None, node2=None, m all.sort() gone = {} + gitmode = {'l': '120000', 'x': '100755', '': '100644'} + for f in all: to = None tn = None @@ -1230,18 +1222,16 @@ def diff(repo, node1=None, node2=None, m 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 @@ def diff(repo, node1=None, node2=None, m 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' diff --git a/mercurial/util.py b/mercurial/util.py --- a/mercurial/util.py +++ b/mercurial/util.py @@ -933,12 +933,6 @@ def checkexec(path): 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 @@ def checklink(path): 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)