def _interestingfiles(repo, matcher): '''Walk dirstate with matcher, looking for files that addremove would care about. This is different from dirstate.status because it doesn't care about whether files are modified or clean.''' added, unknown, deleted, removed = [], [], [], [] audit_path = pathutil.pathauditor(repo.root) ctx = repo[None] dirstate = repo.dirstate walkresults = dirstate.walk(matcher, sorted(ctx.substate), True, False, full=False) for abs, st in walkresults.iteritems(): dstate = dirstate[abs] if dstate == '?' and audit_path.check(abs): unknown.append(abs) elif dstate != 'r' and not st: deleted.append(abs) # for finding renames elif dstate == 'r': removed.append(abs) elif dstate == 'a': added.append(abs) return added, unknown, deleted, removed
def _interestingfiles(repo, matcher): '''Walk dirstate with matcher, looking for files that addremove would care about. This is different from dirstate.status because it doesn't care about whether files are modified or clean.''' added, unknown, deleted, removed, forgotten = [], [], [], [], [] audit_path = pathutil.pathauditor(repo.root) ctx = repo[None] dirstate = repo.dirstate walkresults = dirstate.walk(matcher, sorted(ctx.substate), True, False, full=False) for abs, st in walkresults.iteritems(): dstate = dirstate[abs] if dstate == '?' and audit_path.check(abs): unknown.append(abs) elif dstate != 'r' and not st: deleted.append(abs) elif dstate == 'r' and st: forgotten.append(abs) # for finding renames elif dstate == 'r' and not st: removed.append(abs) elif dstate == 'a': added.append(abs) return added, unknown, deleted, removed, forgotten
if not skipstep3 and not exact: # If a dmap file is not in results yet, it was either # a) not matching matchfn b) ignored, c) missing, or d) under a # symlink directory. if not results and matchalways: visit = dmap.keys() else: visit = [f for f in dmap if f not in results and matchfn(f)] visit.sort() if unknown: # unknown == True means we walked all dirs under the roots # that wasn't ignored, and everything that matched was stat'ed # and is already in results. # The rest must thus be ignored or under a symlink. audit_path = pathutil.pathauditor(self._root) for nf in iter(visit): # Report ignored items in the dmap as long as they are not # under a symlink directory. if audit_path.check(nf): try: results[nf] = lstat(join(nf)) # file was just ignored, no links, and exists except OSError: # file doesn't exist results[nf] = None else: # It's either missing or under a symlink directory # which we in this case report as missing results[nf] = None
def _setmustaudit(self, onoff): self._audit = onoff if onoff: self.audit = pathutil.pathauditor(self.base) else: self.audit = util.always
def walk(self, match, subrepos, unknown, ignored, full=True): ''' Walk recursively through the directory tree, finding all files matched by match. If full is False, maybe skip some known-clean files. Return a dict mapping filename to stat-like object (either mercurial.osutil.stat instance or return value of os.stat()). ''' # full is a flag that extensions that hook into walk can use -- this # implementation doesn't use it at all. This satisfies the contract # because we only guarantee a "maybe". if ignored: ignore = util.never dirignore = util.never elif unknown: ignore = self._ignore dirignore = self._dirignore else: # if not unknown and not ignored, drop dir recursion and step 2 ignore = util.always dirignore = util.always matchfn = match.matchfn matchalways = match.always() matchtdir = match.traversedir dmap = self._map listdir = osutil.listdir lstat = os.lstat dirkind = stat.S_IFDIR regkind = stat.S_IFREG lnkkind = stat.S_IFLNK join = self._join exact = skipstep3 = False if match.isexact(): # match.exact exact = True dirignore = util.always # skip step 2 elif match.prefix(): # match.match, no patterns skipstep3 = True if not exact and self._checkcase: normalize = self._normalize normalizefile = self._normalizefile skipstep3 = False else: normalize = self._normalize normalizefile = None # step 1: find all explicit files results, work, dirsnotfound = self._walkexplicit(match, subrepos) skipstep3 = skipstep3 and not (work or dirsnotfound) work = [d for d in work if not dirignore(d[0])] # step 2: visit subdirectories def traverse(work, alreadynormed): wadd = work.append while work: nd = work.pop() skip = None if nd == '.': nd = '' else: skip = '.hg' try: entries = listdir(join(nd), stat=True, skip=skip) except OSError as inst: if inst.errno in (errno.EACCES, errno.ENOENT): match.bad(self.pathto(nd), inst.strerror) continue raise for f, kind, st in entries: if normalizefile: # even though f might be a directory, we're only # interested in comparing it to files currently in the # dmap -- therefore normalizefile is enough nf = normalizefile(nd and (nd + "/" + f) or f, True, True) else: nf = nd and (nd + "/" + f) or f if nf not in results: if kind == dirkind: if not ignore(nf): if matchtdir: matchtdir(nf) wadd(nf) if nf in dmap and (matchalways or matchfn(nf)): results[nf] = None elif kind == regkind or kind == lnkkind: if nf in dmap: if matchalways or matchfn(nf): results[nf] = st elif ((matchalways or matchfn(nf)) and not ignore(nf)): # unknown file -- normalize if necessary if not alreadynormed: nf = normalize(nf, False, True) results[nf] = st elif nf in dmap and (matchalways or matchfn(nf)): results[nf] = None for nd, d in work: # alreadynormed means that processwork doesn't have to do any # expensive directory normalization alreadynormed = not normalize or nd == d traverse([d], alreadynormed) for s in subrepos: del results[s] del results['.hg'] # step 3: visit remaining files from dmap if not skipstep3 and not exact: # If a dmap file is not in results yet, it was either # a) not matching matchfn b) ignored, c) missing, or d) under a # symlink directory. if not results and matchalways: visit = dmap.keys() else: visit = [f for f in dmap if f not in results and matchfn(f)] visit.sort() if unknown: # unknown == True means we walked all dirs under the roots # that wasn't ignored, and everything that matched was stat'ed # and is already in results. # The rest must thus be ignored or under a symlink. audit_path = pathutil.pathauditor(self._root) for nf in iter(visit): # If a stat for the same file was already added with a # different case, don't add one for this, since that would # make it appear as if the file exists under both names # on disk. if (normalizefile and normalizefile(nf, True, True) in results): results[nf] = None # Report ignored items in the dmap as long as they are not # under a symlink directory. elif audit_path.check(nf): try: results[nf] = lstat(join(nf)) # file was just ignored, no links, and exists except OSError: # file doesn't exist results[nf] = None else: # It's either missing or under a symlink directory # which we in this case report as missing results[nf] = None else: # We may not have walked the full directory tree above, # so stat and check everything we missed. nf = iter(visit).next pos = 0 while pos < len(visit): # visit in mid-sized batches so that we don't # block signals indefinitely xr = xrange(pos, min(len(visit), pos + 1000)) for st in util.statfiles([join(visit[n]) for n in xr]): results[nf()] = st pos += 1000 return results
def walk(self, match, subrepos, unknown, ignored, full=True): ''' Walk recursively through the directory tree, finding all files matched by match. If full is False, maybe skip some known-clean files. Return a dict mapping filename to stat-like object (either mercurial.osutil.stat instance or return value of os.stat()). ''' # full is a flag that extensions that hook into walk can use -- this # implementation doesn't use it at all. This satisfies the contract # because we only guarantee a "maybe". if ignored: ignore = util.never dirignore = util.never elif unknown: ignore = self._ignore dirignore = self._dirignore else: # if not unknown and not ignored, drop dir recursion and step 2 ignore = util.always dirignore = util.always matchfn = match.matchfn matchalways = match.always() matchtdir = match.traversedir dmap = self._map listdir = osutil.listdir lstat = os.lstat dirkind = stat.S_IFDIR regkind = stat.S_IFREG lnkkind = stat.S_IFLNK join = self._join exact = skipstep3 = False if match.isexact(): # match.exact exact = True dirignore = util.always # skip step 2 elif match.prefix(): # match.match, no patterns skipstep3 = True if not exact and self._checkcase: normalize = self._normalize normalizefile = self._normalizefile skipstep3 = False else: normalize = self._normalize normalizefile = None # step 1: find all explicit files results, work, dirsnotfound = self._walkexplicit(match, subrepos) skipstep3 = skipstep3 and not (work or dirsnotfound) work = [d for d in work if not dirignore(d[0])] # step 2: visit subdirectories def traverse(work, alreadynormed): wadd = work.append while work: nd = work.pop() skip = None if nd == '.': nd = '' else: skip = '.hg' try: entries = listdir(join(nd), stat=True, skip=skip) except OSError as inst: if inst.errno in (errno.EACCES, errno.ENOENT): match.bad(self.pathto(nd), inst.strerror) continue raise for f, kind, st in entries: if normalizefile: # even though f might be a directory, we're only # interested in comparing it to files currently in the # dmap -- therefore normalizefile is enough nf = normalizefile(nd and (nd + "/" + f) or f, True, True) else: nf = nd and (nd + "/" + f) or f if nf not in results: if kind == dirkind: if not ignore(nf): if matchtdir: matchtdir(nf) wadd(nf) if nf in dmap and (matchalways or matchfn(nf)): results[nf] = None elif kind == regkind or kind == lnkkind: if nf in dmap: if matchalways or matchfn(nf): results[nf] = st elif ((matchalways or matchfn(nf)) and not ignore(nf)): # unknown file -- normalize if necessary if not alreadynormed: nf = normalize(nf, False, True) results[nf] = st elif nf in dmap and (matchalways or matchfn(nf)): results[nf] = None for nd, d in work: # alreadynormed means that processwork doesn't have to do any # expensive directory normalization alreadynormed = not normalize or nd == d traverse([d], alreadynormed) for s in subrepos: del results[s] del results['.hg'] # step 3: visit remaining files from dmap if not skipstep3 and not exact: # If a dmap file is not in results yet, it was either # a) not matching matchfn b) ignored, c) missing, or d) under a # symlink directory. if not results and matchalways: visit = dmap.keys() else: visit = [f for f in dmap if f not in results and matchfn(f)] visit.sort() if unknown: # unknown == True means we walked all dirs under the roots # that wasn't ignored, and everything that matched was stat'ed # and is already in results. # The rest must thus be ignored or under a symlink. audit_path = pathutil.pathauditor(self._root) for nf in iter(visit): # If a stat for the same file was already added with a # different case, don't add one for this, since that would # make it appear as if the file exists under both names # on disk. if (normalizefile and normalizefile(nf, True, True) in results): results[nf] = None # Report ignored items in the dmap as long as they are not # under a symlink directory. elif audit_path.check(nf): try: results[nf] = lstat(join(nf)) # file was just ignored, no links, and exists except OSError: # file doesn't exist results[nf] = None else: # It's either missing or under a symlink directory # which we in this case report as missing results[nf] = None else: # We may not have walked the full directory tree above, # so stat and check everything we missed. nf = iter(visit).next for st in util.statfiles([join(i) for i in visit]): results[nf()] = st return results