Mercurial > hg
comparison mercurial/dirstate.py @ 34332:b36881c68569
dirstate: create new dirstatemap class
This is part of a larger refactor to move the dirstate storage logic to a
separate class, so it's easier to rewrite the dirstate storage layer without
having to rewrite all the algorithms as well.
Step one it to create the class, and replace dirstate._map with it. The
abstraction bleeds through in a few places where the main dirstate class has to
access self._map._map, but those will be cleaned up in future patches.
Differential Revision: https://phab.mercurial-scm.org/D752
author | Durham Goode <durham@fb.com> |
---|---|
date | Tue, 26 Sep 2017 03:56:20 -0700 |
parents | 1246acdad653 |
children | 4ac04418ce66 |
comparison
equal
deleted
inserted
replaced
34331:531332502568 | 34332: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() |