# HG changeset patch # User Mark Thomas # Date 1510736862 28800 # Node ID 61888bd0b3005e34a032756495fc384f95a6e302 # Parent e8ae0b2d88a8f4d6c4c8df79c93513999219b227 dirstate: add explicit methods for querying directories (API) The set-like object returned by dirstate.dirs may be difficult for other implementations of the dirstate to provide, and is unnecessary as it is only ever used for __contains__. Instead, provide an explicit method for testing for a directory. .. api:: dirstate no longer provides a `dirs()` method. To test for the existence of a directory in the dirstate, use `dirstate.hasdir(dirname)`. Differential Revision: https://phab.mercurial-scm.org/D1345 diff -r e8ae0b2d88a8 -r 61888bd0b300 contrib/perf.py --- a/contrib/perf.py Wed Nov 15 01:07:42 2017 -0800 +++ b/contrib/perf.py Wed Nov 15 01:07:42 2017 -0800 @@ -525,8 +525,8 @@ dirstate = repo.dirstate 'a' in dirstate def d(): - dirstate.dirs() - del dirstate._map.dirs + dirstate.hasdir('a') + del dirstate._map._dirs timer(d) fm.end() @@ -545,8 +545,8 @@ timer, fm = gettimer(ui, opts) "a" in repo.dirstate def d(): - "a" in repo.dirstate._map.dirs - del repo.dirstate._map.dirs + repo.dirstate.hasdir("a") + del repo.dirstate._map._dirs timer(d) fm.end() @@ -569,7 +569,7 @@ def d(): dirstate._map.dirfoldmap.get('a') del dirstate._map.dirfoldmap - del dirstate._map.dirs + del dirstate._map._dirs timer(d) fm.end() diff -r e8ae0b2d88a8 -r 61888bd0b300 hgext/largefiles/reposetup.py --- a/hgext/largefiles/reposetup.py Wed Nov 15 01:07:42 2017 -0800 +++ b/hgext/largefiles/reposetup.py Wed Nov 15 01:07:42 2017 -0800 @@ -138,7 +138,7 @@ sf = lfutil.standin(f) if sf in dirstate: newfiles.append(sf) - elif sf in dirstate.dirs(): + elif dirstate.hasdir(sf): # Directory entries could be regular or # standin, check both newfiles.extend((f, sf)) @@ -156,7 +156,7 @@ def sfindirstate(f): sf = lfutil.standin(f) dirstate = self.dirstate - return sf in dirstate or sf in dirstate.dirs() + return sf in dirstate or dirstate.hasdir(sf) match._files = [f for f in match._files if sfindirstate(f)] diff -r e8ae0b2d88a8 -r 61888bd0b300 mercurial/dirstate.py --- a/mercurial/dirstate.py Wed Nov 15 01:07:42 2017 -0800 +++ b/mercurial/dirstate.py Wed Nov 15 01:07:42 2017 -0800 @@ -157,8 +157,8 @@ def _pl(self): return self._map.parents() - def dirs(self): - return self._map.dirs + def hasdir(self, d): + return self._map.hastrackeddir(d) @rootcache('.hgignore') def _ignore(self): @@ -390,11 +390,11 @@ oldstate = self[f] if state == 'a' or oldstate == 'r': scmutil.checkfilename(f) - if f in self._map.dirs: + if self._map.hastrackeddir(f): raise error.Abort(_('directory %r already in dirstate') % f) # shadows for d in util.finddirs(f): - if d in self._map.dirs: + if self._map.hastrackeddir(d): break entry = self._map.get(d) if entry is not None and entry[0] != 'r': @@ -770,7 +770,6 @@ results = dict.fromkeys(subrepos) results['.hg'] = None - alldirs = None for ff in files: # constructing the foldmap is expensive, so don't do it for the # common case where files is ['.'] @@ -801,9 +800,7 @@ if nf in dmap: # does it exactly match a missing file? results[nf] = None else: # does it match a missing directory? - if alldirs is None: - alldirs = util.dirs(dmap._map) - if nf in alldirs: + if self._map.hasdir(nf): if matchedir: matchedir(nf) notfoundadd(nf) @@ -1197,9 +1194,6 @@ - `otherparentset` is a set of the filenames that are marked as coming from the second parent when the dirstate is currently being merged. - - `dirs` is a set-like object containing all the directories that contain - files in the dirstate, excluding any files that are marked as removed. - - `filefoldmap` is a dict mapping normalized filenames to the denormalized form that they appear as in the dirstate. @@ -1235,7 +1229,8 @@ self._map.clear() self.copymap.clear() self.setparents(nullid, nullid) - util.clearcachedproperty(self, "dirs") + util.clearcachedproperty(self, "_dirs") + util.clearcachedproperty(self, "_alldirs") util.clearcachedproperty(self, "filefoldmap") util.clearcachedproperty(self, "dirfoldmap") util.clearcachedproperty(self, "nonnormalset") @@ -1268,8 +1263,10 @@ def addfile(self, f, oldstate, state, mode, size, mtime): """Add a tracked file to the dirstate.""" - if oldstate in "?r" and "dirs" in self.__dict__: - self.dirs.addpath(f) + if oldstate in "?r" and "_dirs" in self.__dict__: + self._dirs.addpath(f) + if oldstate == "?" and "_alldirs" in self.__dict__: + self._alldirs.addpath(f) self._map[f] = dirstatetuple(state, mode, size, mtime) if state != 'n' or mtime == -1: self.nonnormalset.add(f) @@ -1284,8 +1281,10 @@ the file's previous state. In the future, we should refactor this to be more explicit about what that state is. """ - if oldstate not in "?r" and "dirs" in self.__dict__: - self.dirs.delpath(f) + if oldstate not in "?r" and "_dirs" in self.__dict__: + self._dirs.delpath(f) + if oldstate == "?" and "_alldirs" in self.__dict__: + self._alldirs.addpath(f) if "filefoldmap" in self.__dict__: normed = util.normcase(f) self.filefoldmap.pop(normed, None) @@ -1299,8 +1298,10 @@ """ exists = self._map.pop(f, None) is not None if exists: - if oldstate != "r" and "dirs" in self.__dict__: - self.dirs.delpath(f) + if oldstate != "r" and "_dirs" in self.__dict__: + self._dirs.delpath(f) + if "_alldirs" in self.__dict__: + self._alldirs.delpath(f) if "filefoldmap" in self.__dict__: normed = util.normcase(f) self.filefoldmap.pop(normed, None) @@ -1349,13 +1350,28 @@ f['.'] = '.' # prevents useless util.fspath() invocation return f + def hastrackeddir(self, d): + """ + Returns True if the dirstate contains a tracked (not removed) file + in this directory. + """ + return d in self._dirs + + def hasdir(self, d): + """ + Returns True if the dirstate contains a file (tracked or removed) + in this directory. + """ + return d in self._alldirs + @propertycache - def dirs(self): - """Returns a set-like object containing all the directories in the - current dirstate. - """ + def _dirs(self): return util.dirs(self._map, 'r') + @propertycache + def _alldirs(self): + return util.dirs(self._map) + def _opendirstatefile(self): fp, mode = txnutil.trypending(self._root, self._opener, self._filename) if self._pendingmode is not None and self._pendingmode != mode: @@ -1473,6 +1489,6 @@ def dirfoldmap(self): f = {} normcase = util.normcase - for name in self.dirs: + for name in self._dirs: f[normcase(name)] = name return f