mercurial/dirstate.py
changeset 34339 b36881c68569
parent 34200 1246acdad653
child 34340 4ac04418ce66
equal deleted inserted replaced
34338:531332502568 34339:b36881c68569
    55         vfs.unlink(tmpname)
    55         vfs.unlink(tmpname)
    56 
    56 
    57 def nonnormalentries(dmap):
    57 def nonnormalentries(dmap):
    58     '''Compute the nonnormal dirstate entries from the dmap'''
    58     '''Compute the nonnormal dirstate entries from the dmap'''
    59     try:
    59     try:
    60         return parsers.nonnormalotherparententries(dmap)
    60         return parsers.nonnormalotherparententries(dmap._map)
    61     except AttributeError:
    61     except AttributeError:
    62         nonnorm = set()
    62         nonnorm = set()
    63         otherparent = set()
    63         otherparent = set()
    64         for fname, e in dmap.iteritems():
    64         for fname, e in dmap.iteritems():
    65             if e[0] != 'n' or e[3] == -1:
    65             if e[0] != 'n' or e[3] == -1:
   177         try:
   177         try:
   178             makefilefoldmap = parsers.make_file_foldmap
   178             makefilefoldmap = parsers.make_file_foldmap
   179         except AttributeError:
   179         except AttributeError:
   180             pass
   180             pass
   181         else:
   181         else:
   182             return makefilefoldmap(self._map, util.normcasespec,
   182             return makefilefoldmap(self._map._map, util.normcasespec,
   183                                    util.normcasefallback)
   183                                    util.normcasefallback)
   184 
   184 
   185         f = {}
   185         f = {}
   186         normcase = util.normcase
   186         normcase = util.normcase
   187         for name, s in self._map.iteritems():
   187         for name, s in self._map.iteritems():
   236                 raise
   236                 raise
   237         return [nullid, nullid]
   237         return [nullid, nullid]
   238 
   238 
   239     @propertycache
   239     @propertycache
   240     def _dirs(self):
   240     def _dirs(self):
   241         return util.dirs(self._map, 'r')
   241         return util.dirs(self._map._map, 'r')
   242 
   242 
   243     def dirs(self):
   243     def dirs(self):
   244         return self._dirs
   244         return self._dirs
   245 
   245 
   246     @rootcache('.hgignore')
   246     @rootcache('.hgignore')
   442                                 'changed parallelly'))
   442                                 'changed parallelly'))
   443         self._pendingmode = mode
   443         self._pendingmode = mode
   444         return fp
   444         return fp
   445 
   445 
   446     def _read(self):
   446     def _read(self):
   447         self._map = {}
   447         self._map = dirstatemap()
       
   448 
   448         self._copymap = {}
   449         self._copymap = {}
   449         # ignore HG_PENDING because identity is used only for writing
   450         # ignore HG_PENDING because identity is used only for writing
   450         self._identity = util.filestat.frompath(
   451         self._identity = util.filestat.frompath(
   451             self._opener.join(self._filename))
   452             self._opener.join(self._filename))
   452         try:
   453         try:
   471             # size.
   472             # size.
   472             #
   473             #
   473             # This heuristic is imperfect in many ways, so in a future dirstate
   474             # This heuristic is imperfect in many ways, so in a future dirstate
   474             # format update it makes sense to just record the number of entries
   475             # format update it makes sense to just record the number of entries
   475             # on write.
   476             # on write.
   476             self._map = parsers.dict_new_presized(len(st) / 71)
   477             self._map._map = parsers.dict_new_presized(len(st) / 71)
   477 
   478 
   478         # Python's garbage collector triggers a GC each time a certain number
   479         # Python's garbage collector triggers a GC each time a certain number
   479         # of container objects (the number being defined by
   480         # of container objects (the number being defined by
   480         # gc.get_threshold()) are allocated. parse_dirstate creates a tuple
   481         # gc.get_threshold()) are allocated. parse_dirstate creates a tuple
   481         # for each file in the dirstate. The C version then immediately marks
   482         # for each file in the dirstate. The C version then immediately marks
   486         # this can get very expensive. As a workaround, disable GC while
   487         # this can get very expensive. As a workaround, disable GC while
   487         # parsing the dirstate.
   488         # parsing the dirstate.
   488         #
   489         #
   489         # (we cannot decorate the function directly since it is in a C module)
   490         # (we cannot decorate the function directly since it is in a C module)
   490         parse_dirstate = util.nogc(parsers.parse_dirstate)
   491         parse_dirstate = util.nogc(parsers.parse_dirstate)
   491         p = parse_dirstate(self._map, self._copymap, st)
   492         p = parse_dirstate(self._map._map, self._copymap, st)
   492         if not self._dirtypl:
   493         if not self._dirtypl:
   493             self._pl = p
   494             self._pl = p
   494 
   495 
   495     def invalidate(self):
   496     def invalidate(self):
   496         '''Causes the next access to reread the dirstate.
   497         '''Causes the next access to reread the dirstate.
   729         if self._checkcase:
   730         if self._checkcase:
   730             return self._normalize(path, isknown, ignoremissing)
   731             return self._normalize(path, isknown, ignoremissing)
   731         return path
   732         return path
   732 
   733 
   733     def clear(self):
   734     def clear(self):
   734         self._map = {}
   735         self._map = dirstatemap()
   735         self._nonnormalset = set()
   736         self._nonnormalset = set()
   736         self._otherparentset = set()
   737         self._otherparentset = set()
   737         if "_dirs" in self.__dict__:
   738         if "_dirs" in self.__dict__:
   738             delattr(self, "_dirs")
   739             delattr(self, "_dirs")
   739         self._copymap = {}
   740         self._copymap = {}
   838                     end = start + delaywrite
   839                     end = start + delaywrite
   839                     time.sleep(end - clock)
   840                     time.sleep(end - clock)
   840                     now = end # trust our estimate that the end is near now
   841                     now = end # trust our estimate that the end is near now
   841                     break
   842                     break
   842 
   843 
   843         st.write(parsers.pack_dirstate(self._map, self._copymap, self._pl, now))
   844         st.write(parsers.pack_dirstate(self._map._map, self._copymap, self._pl,
       
   845                                        now))
   844         self._nonnormalset, self._otherparentset = nonnormalentries(self._map)
   846         self._nonnormalset, self._otherparentset = nonnormalentries(self._map)
   845         st.close()
   847         st.close()
   846         self._lastnormaltime = 0
   848         self._lastnormaltime = 0
   847         self._dirty = self._dirtypl = False
   849         self._dirty = self._dirtypl = False
   848 
   850 
   977             except OSError as inst: # nf not found on disk - it is dirstate only
   979             except OSError as inst: # nf not found on disk - it is dirstate only
   978                 if nf in dmap: # does it exactly match a missing file?
   980                 if nf in dmap: # does it exactly match a missing file?
   979                     results[nf] = None
   981                     results[nf] = None
   980                 else: # does it match a missing directory?
   982                 else: # does it match a missing directory?
   981                     if alldirs is None:
   983                     if alldirs is None:
   982                         alldirs = util.dirs(dmap)
   984                         alldirs = util.dirs(dmap._map)
   983                     if nf in alldirs:
   985                     if nf in alldirs:
   984                         if matchedir:
   986                         if matchedir:
   985                             matchedir(nf)
   987                             matchedir(nf)
   986                         notfoundadd(nf)
   988                         notfoundadd(nf)
   987                     else:
   989                     else:
  1337         self._opener.rename(backupname, filename, checkambig=True)
  1339         self._opener.rename(backupname, filename, checkambig=True)
  1338 
  1340 
  1339     def clearbackup(self, tr, backupname):
  1341     def clearbackup(self, tr, backupname):
  1340         '''Clear backup file'''
  1342         '''Clear backup file'''
  1341         self._opener.unlink(backupname)
  1343         self._opener.unlink(backupname)
       
  1344 
       
  1345 class dirstatemap(object):
       
  1346     def __init__(self):
       
  1347         self._map = {}
       
  1348 
       
  1349     def iteritems(self):
       
  1350         return self._map.iteritems()
       
  1351 
       
  1352     def __iter__(self):
       
  1353         return iter(self._map)
       
  1354 
       
  1355     def get(self, key, default=None):
       
  1356         return self._map.get(key, default)
       
  1357 
       
  1358     def __contains__(self, key):
       
  1359         return key in self._map
       
  1360 
       
  1361     def __setitem__(self, key, value):
       
  1362         self._map[key] = value
       
  1363 
       
  1364     def __getitem__(self, key):
       
  1365         return self._map[key]
       
  1366 
       
  1367     def __delitem__(self, key):
       
  1368         del self._map[key]
       
  1369 
       
  1370     def keys(self):
       
  1371         return self._map.keys()