mercurial/dirstatemap.py
changeset 48121 5fc2dfb073d6
parent 48120 fe6617715464
child 48122 bbd924a36a6e
equal deleted inserted replaced
48120:fe6617715464 48121:5fc2dfb073d6
   508                 assert size is not None
   508                 assert size is not None
   509                 assert mtime is not None
   509                 assert mtime is not None
   510                 size = size & rangemask
   510                 size = size & rangemask
   511                 mtime = mtime & rangemask
   511                 mtime = mtime & rangemask
   512                 item = DirstateItem.new_normal(mode, size, mtime)
   512                 item = DirstateItem.new_normal(mode, size, mtime)
   513             self._rustmap.addfile(f, item)
   513             self._map.addfile(f, item)
   514             if added:
   514             if added:
   515                 self.copymap.pop(f, None)
   515                 self.copymap.pop(f, None)
   516 
   516 
   517         def reset_state(
   517         def reset_state(
   518             self,
   518             self,
   543             # copy information are now outdated
   543             # copy information are now outdated
   544             # (maybe new information should be in directly passed to this function)
   544             # (maybe new information should be in directly passed to this function)
   545             self.copymap.pop(filename, None)
   545             self.copymap.pop(filename, None)
   546 
   546 
   547             if not (p1_tracked or p2_tracked or wc_tracked):
   547             if not (p1_tracked or p2_tracked or wc_tracked):
   548                 self._rustmap.drop_item_and_copy_source(filename)
   548                 self._map.drop_item_and_copy_source(filename)
   549             elif merged:
   549             elif merged:
   550                 # XXX might be merged and removed ?
   550                 # XXX might be merged and removed ?
   551                 entry = self.get(filename)
   551                 entry = self.get(filename)
   552                 if entry is not None and entry.tracked:
   552                 if entry is not None and entry.tracked:
   553                     # XXX mostly replicate dirstate.other parent.  We should get
   553                     # XXX mostly replicate dirstate.other parent.  We should get
   599             if entry is None:
   599             if entry is None:
   600                 self.addfile(filename, added=True)
   600                 self.addfile(filename, added=True)
   601                 new = True
   601                 new = True
   602             elif not entry.tracked:
   602             elif not entry.tracked:
   603                 entry.set_tracked()
   603                 entry.set_tracked()
   604                 self._rustmap.set_dirstate_item(filename, entry)
   604                 self._map.set_dirstate_item(filename, entry)
   605                 new = True
   605                 new = True
   606             else:
   606             else:
   607                 # XXX This is probably overkill for more case, but we need this to
   607                 # XXX This is probably overkill for more case, but we need this to
   608                 # fully replace the `normallookup` call with `set_tracked` one.
   608                 # fully replace the `normallookup` call with `set_tracked` one.
   609                 # Consider smoothing this in the future.
   609                 # Consider smoothing this in the future.
   619             entry = self.get(f)
   619             entry = self.get(f)
   620             if entry is None:
   620             if entry is None:
   621                 return False
   621                 return False
   622             else:
   622             else:
   623                 if entry.added:
   623                 if entry.added:
   624                     self._rustmap.drop_item_and_copy_source(f)
   624                     self._map.drop_item_and_copy_source(f)
   625                 else:
   625                 else:
   626                     self._rustmap.removefile(f, in_merge=True)
   626                     self._map.removefile(f, in_merge=True)
   627                 return True
   627                 return True
   628 
   628 
   629         def removefile(self, *args, **kwargs):
   629         def removefile(self, *args, **kwargs):
   630             return self._rustmap.removefile(*args, **kwargs)
   630             return self._map.removefile(*args, **kwargs)
   631 
   631 
   632         def get(self, *args, **kwargs):
   632         def get(self, *args, **kwargs):
   633             return self._rustmap.get(*args, **kwargs)
   633             return self._map.get(*args, **kwargs)
   634 
   634 
   635         @property
   635         @property
   636         def copymap(self):
   636         def copymap(self):
   637             return self._rustmap.copymap()
   637             return self._map.copymap()
   638 
   638 
   639         def debug_iter(self, all):
   639         def debug_iter(self, all):
   640             """
   640             """
   641             Return an iterator of (filename, state, mode, size, mtime) tuples
   641             Return an iterator of (filename, state, mode, size, mtime) tuples
   642 
   642 
   643             `all`: also include with `state == b' '` dirstate tree nodes that
   643             `all`: also include with `state == b' '` dirstate tree nodes that
   644             don't have an associated `DirstateItem`.
   644             don't have an associated `DirstateItem`.
   645 
   645 
   646             """
   646             """
   647             return self._rustmap.debug_iter(all)
   647             return self._map.debug_iter(all)
   648 
   648 
   649         def preload(self):
   649         def preload(self):
   650             self._rustmap
   650             self._map
   651 
   651 
   652         def clear(self):
   652         def clear(self):
   653             self._rustmap.clear()
   653             self._map.clear()
   654             self.setparents(
   654             self.setparents(
   655                 self._nodeconstants.nullid, self._nodeconstants.nullid
   655                 self._nodeconstants.nullid, self._nodeconstants.nullid
   656             )
   656             )
   657             util.clearcachedproperty(self, b"_dirs")
   657             util.clearcachedproperty(self, b"_dirs")
   658             util.clearcachedproperty(self, b"_alldirs")
   658             util.clearcachedproperty(self, b"_alldirs")
   659             util.clearcachedproperty(self, b"dirfoldmap")
   659             util.clearcachedproperty(self, b"dirfoldmap")
   660 
   660 
   661         def items(self):
   661         def items(self):
   662             return self._rustmap.items()
   662             return self._map.items()
   663 
   663 
   664         def keys(self):
   664         def keys(self):
   665             return iter(self._rustmap)
   665             return iter(self._map)
   666 
   666 
   667         def __contains__(self, key):
   667         def __contains__(self, key):
   668             return key in self._rustmap
   668             return key in self._map
   669 
   669 
   670         def __getitem__(self, item):
   670         def __getitem__(self, item):
   671             return self._rustmap[item]
   671             return self._map[item]
   672 
   672 
   673         def __len__(self):
   673         def __len__(self):
   674             return len(self._rustmap)
   674             return len(self._map)
   675 
   675 
   676         def __iter__(self):
   676         def __iter__(self):
   677             return iter(self._rustmap)
   677             return iter(self._map)
   678 
   678 
   679         # forward for python2,3 compat
   679         # forward for python2,3 compat
   680         iteritems = items
   680         iteritems = items
   681 
   681 
   682         def _opendirstatefile(self):
   682         def _opendirstatefile(self):
   711                 # TODO: move this the whole loop to Rust where `iter_mut`
   711                 # TODO: move this the whole loop to Rust where `iter_mut`
   712                 # enables in-place mutation of elements of a collection while
   712                 # enables in-place mutation of elements of a collection while
   713                 # iterating it, without mutating the collection itself.
   713                 # iterating it, without mutating the collection itself.
   714                 candidatefiles = [
   714                 candidatefiles = [
   715                     (f, s)
   715                     (f, s)
   716                     for f, s in self._rustmap.items()
   716                     for f, s in self._map.items()
   717                     if s.merged or s.from_p2
   717                     if s.merged or s.from_p2
   718                 ]
   718                 ]
   719                 for f, s in candidatefiles:
   719                 for f, s in candidatefiles:
   720                     # Discard "merged" markers when moving away from a merge state
   720                     # Discard "merged" markers when moving away from a merge state
   721                     if s.merged:
   721                     if s.merged:
   776                     self._readdirstatefile(), self._nodeconstants
   776                     self._readdirstatefile(), self._nodeconstants
   777                 )
   777                 )
   778             return self._docket
   778             return self._docket
   779 
   779 
   780         @propertycache
   780         @propertycache
   781         def _rustmap(self):
   781         def _map(self):
   782             """
   782             """
   783             Fills the Dirstatemap when called.
   783             Fills the Dirstatemap when called.
   784             """
   784             """
   785             # ignore HG_PENDING because identity is used only for writing
   785             # ignore HG_PENDING because identity is used only for writing
   786             self.identity = util.filestat.frompath(
   786             self.identity = util.filestat.frompath(
   791                 if self.docket.uuid:
   791                 if self.docket.uuid:
   792                     # TODO: use mmap when possible
   792                     # TODO: use mmap when possible
   793                     data = self._opener.read(self.docket.data_filename())
   793                     data = self._opener.read(self.docket.data_filename())
   794                 else:
   794                 else:
   795                     data = b''
   795                     data = b''
   796                 self._rustmap = rustmod.DirstateMap.new_v2(
   796                 self._map = rustmod.DirstateMap.new_v2(
   797                     data, self.docket.data_size, self.docket.tree_metadata
   797                     data, self.docket.data_size, self.docket.tree_metadata
   798                 )
   798                 )
   799                 parents = self.docket.parents
   799                 parents = self.docket.parents
   800             else:
   800             else:
   801                 self._rustmap, parents = rustmod.DirstateMap.new_v1(
   801                 self._map, parents = rustmod.DirstateMap.new_v1(
   802                     self._readdirstatefile()
   802                     self._readdirstatefile()
   803                 )
   803                 )
   804 
   804 
   805             if parents and not self._dirtyparents:
   805             if parents and not self._dirtyparents:
   806                 self.setparents(*parents)
   806                 self.setparents(*parents)
   807 
   807 
   808             self.__contains__ = self._rustmap.__contains__
   808             self.__contains__ = self._map.__contains__
   809             self.__getitem__ = self._rustmap.__getitem__
   809             self.__getitem__ = self._map.__getitem__
   810             self.get = self._rustmap.get
   810             self.get = self._map.get
   811             return self._rustmap
   811             return self._map
   812 
   812 
   813         def write(self, tr, st, now):
   813         def write(self, tr, st, now):
   814             if not self._use_dirstate_v2:
   814             if not self._use_dirstate_v2:
   815                 p1, p2 = self.parents()
   815                 p1, p2 = self.parents()
   816                 packed = self._rustmap.write_v1(p1, p2, now)
   816                 packed = self._map.write_v1(p1, p2, now)
   817                 st.write(packed)
   817                 st.write(packed)
   818                 st.close()
   818                 st.close()
   819                 self._dirtyparents = False
   819                 self._dirtyparents = False
   820                 return
   820                 return
   821 
   821 
   822             # We can only append to an existing data file if there is one
   822             # We can only append to an existing data file if there is one
   823             can_append = self.docket.uuid is not None
   823             can_append = self.docket.uuid is not None
   824             packed, meta, append = self._rustmap.write_v2(now, can_append)
   824             packed, meta, append = self._map.write_v2(now, can_append)
   825             if append:
   825             if append:
   826                 docket = self.docket
   826                 docket = self.docket
   827                 data_filename = docket.data_filename()
   827                 data_filename = docket.data_filename()
   828                 if tr:
   828                 if tr:
   829                     tr.add(data_filename, docket.data_size)
   829                     tr.add(data_filename, docket.data_size)
   862                         tr.addpostclose(category, unlink)
   862                         tr.addpostclose(category, unlink)
   863                     else:
   863                     else:
   864                         unlink()
   864                         unlink()
   865                 self._docket = new_docket
   865                 self._docket = new_docket
   866             # Reload from the newly-written file
   866             # Reload from the newly-written file
   867             util.clearcachedproperty(self, b"_rustmap")
   867             util.clearcachedproperty(self, b"_map")
   868             self._dirtyparents = False
   868             self._dirtyparents = False
   869 
   869 
   870         @propertycache
   870         @propertycache
   871         def filefoldmap(self):
   871         def filefoldmap(self):
   872             """Returns a dictionary mapping normalized case paths to their
   872             """Returns a dictionary mapping normalized case paths to their
   873             non-normalized versions.
   873             non-normalized versions.
   874             """
   874             """
   875             return self._rustmap.filefoldmapasdict()
   875             return self._map.filefoldmapasdict()
   876 
   876 
   877         def hastrackeddir(self, d):
   877         def hastrackeddir(self, d):
   878             return self._rustmap.hastrackeddir(d)
   878             return self._map.hastrackeddir(d)
   879 
   879 
   880         def hasdir(self, d):
   880         def hasdir(self, d):
   881             return self._rustmap.hasdir(d)
   881             return self._map.hasdir(d)
   882 
   882 
   883         @propertycache
   883         @propertycache
   884         def identity(self):
   884         def identity(self):
   885             self._rustmap
   885             self._map
   886             return self.identity
   886             return self.identity
   887 
   887 
   888         @propertycache
   888         @propertycache
   889         def dirfoldmap(self):
   889         def dirfoldmap(self):
   890             f = {}
   890             f = {}
   891             normcase = util.normcase
   891             normcase = util.normcase
   892             for name in self._rustmap.tracked_dirs():
   892             for name in self._map.tracked_dirs():
   893                 f[normcase(name)] = name
   893                 f[normcase(name)] = name
   894             return f
   894             return f
   895 
   895 
   896         def set_possibly_dirty(self, filename):
   896         def set_possibly_dirty(self, filename):
   897             """record that the current state of the file on disk is unknown"""
   897             """record that the current state of the file on disk is unknown"""
   898             entry = self[filename]
   898             entry = self[filename]
   899             entry.set_possibly_dirty()
   899             entry.set_possibly_dirty()
   900             self._rustmap.set_dirstate_item(filename, entry)
   900             self._map.set_dirstate_item(filename, entry)
   901 
   901 
   902         def set_clean(self, filename, mode, size, mtime):
   902         def set_clean(self, filename, mode, size, mtime):
   903             """mark a file as back to a clean state"""
   903             """mark a file as back to a clean state"""
   904             entry = self[filename]
   904             entry = self[filename]
   905             mtime = mtime & rangemask
   905             mtime = mtime & rangemask
   906             size = size & rangemask
   906             size = size & rangemask
   907             entry.set_clean(mode, size, mtime)
   907             entry.set_clean(mode, size, mtime)
   908             self._rustmap.set_dirstate_item(filename, entry)
   908             self._map.set_dirstate_item(filename, entry)
   909             self._rustmap.copymap().pop(filename, None)
   909             self._map.copymap().pop(filename, None)
   910 
   910 
   911         def __setitem__(self, key, value):
   911         def __setitem__(self, key, value):
   912             assert isinstance(value, DirstateItem)
   912             assert isinstance(value, DirstateItem)
   913             self._rustmap.set_dirstate_item(key, value)
   913             self._map.set_dirstate_item(key, value)