Mercurial > hg
comparison mercurial/dirstatemap.py @ 48223:b4f83c9e7905
dirstate-v2: Add support when Rust is not enabled
This wires into `dirstatemap` the parser and serializer added in previous
changesets. The memory representation is still the same, with a flat `dict`
for `DirstateItem`s and another one for copy sources. Serialization always
creates a new dirstate-v2 data file and does not support (when Rust is not
enabled) appending to an existing one, since we don’t keep track of which
tree nodes are new or modified. Instead the tree is reconstructed during
serialization.
Differential Revision: https://phab.mercurial-scm.org/D11520
author | Simon Sapin <simon.sapin@octobus.net> |
---|---|
date | Fri, 16 Jul 2021 18:42:20 +0200 |
parents | a32a96079e2d |
children | 269ff8978086 |
comparison
equal
deleted
inserted
replaced
48222:7e78c72ee3ea | 48223:b4f83c9e7905 |
---|---|
330 | 330 |
331 - `dirfoldmap` is a dict mapping normalized directory names to the | 331 - `dirfoldmap` is a dict mapping normalized directory names to the |
332 denormalized form that they appear as in the dirstate. | 332 denormalized form that they appear as in the dirstate. |
333 """ | 333 """ |
334 | 334 |
335 def __init__(self, ui, opener, root, nodeconstants, use_dirstate_v2): | |
336 super(dirstatemap, self).__init__( | |
337 ui, opener, root, nodeconstants, use_dirstate_v2 | |
338 ) | |
339 if self._use_dirstate_v2: | |
340 msg = "Dirstate V2 not supportedi" | |
341 msg += "(should have detected unsupported requirement)" | |
342 raise error.ProgrammingError(msg) | |
343 | |
344 ### Core data storage and access | 335 ### Core data storage and access |
345 | 336 |
346 @propertycache | 337 @propertycache |
347 def _map(self): | 338 def _map(self): |
348 self._map = {} | 339 self._map = {} |
404 # ignore HG_PENDING because identity is used only for writing | 395 # ignore HG_PENDING because identity is used only for writing |
405 self.identity = util.filestat.frompath( | 396 self.identity = util.filestat.frompath( |
406 self._opener.join(self._filename) | 397 self._opener.join(self._filename) |
407 ) | 398 ) |
408 | 399 |
409 try: | 400 if self._use_dirstate_v2: |
410 fp = self._opendirstatefile() | 401 if not self.docket.uuid: |
411 try: | 402 return |
412 st = fp.read() | 403 st = self._opener.read(self.docket.data_filename()) |
413 finally: | 404 else: |
414 fp.close() | 405 st = self._readdirstatefile() |
415 except IOError as err: | 406 |
416 if err.errno != errno.ENOENT: | |
417 raise | |
418 return | |
419 if not st: | 407 if not st: |
420 return | 408 return |
421 | 409 |
410 # TODO: adjust this estimate for dirstate-v2 | |
422 if util.safehasattr(parsers, b'dict_new_presized'): | 411 if util.safehasattr(parsers, b'dict_new_presized'): |
423 # Make an estimate of the number of files in the dirstate based on | 412 # Make an estimate of the number of files in the dirstate based on |
424 # its size. This trades wasting some memory for avoiding costly | 413 # its size. This trades wasting some memory for avoiding costly |
425 # resizes. Each entry have a prefix of 17 bytes followed by one or | 414 # resizes. Each entry have a prefix of 17 bytes followed by one or |
426 # two path names. Studies on various large-scale real-world repositories | 415 # two path names. Studies on various large-scale real-world repositories |
438 # Depending on when in the process's lifetime the dirstate is parsed, | 427 # Depending on when in the process's lifetime the dirstate is parsed, |
439 # this can get very expensive. As a workaround, disable GC while | 428 # this can get very expensive. As a workaround, disable GC while |
440 # parsing the dirstate. | 429 # parsing the dirstate. |
441 # | 430 # |
442 # (we cannot decorate the function directly since it is in a C module) | 431 # (we cannot decorate the function directly since it is in a C module) |
443 parse_dirstate = util.nogc(parsers.parse_dirstate) | 432 if self._use_dirstate_v2: |
444 p = parse_dirstate(self._map, self.copymap, st) | 433 p = self.docket.parents |
434 meta = self.docket.tree_metadata | |
435 parse_dirstate = util.nogc(v2.parse_dirstate) | |
436 parse_dirstate(self._map, self.copymap, st, meta) | |
437 else: | |
438 parse_dirstate = util.nogc(parsers.parse_dirstate) | |
439 p = parse_dirstate(self._map, self.copymap, st) | |
445 if not self._dirtyparents: | 440 if not self._dirtyparents: |
446 self.setparents(*p) | 441 self.setparents(*p) |
447 | 442 |
448 # Avoid excess attribute lookups by fast pathing certain checks | 443 # Avoid excess attribute lookups by fast pathing certain checks |
449 self.__contains__ = self._map.__contains__ | 444 self.__contains__ = self._map.__contains__ |
450 self.__getitem__ = self._map.__getitem__ | 445 self.__getitem__ = self._map.__getitem__ |
451 self.get = self._map.get | 446 self.get = self._map.get |
452 | 447 |
453 def write(self, _tr, st, now): | 448 def write(self, tr, st, now): |
454 d = parsers.pack_dirstate(self._map, self.copymap, self.parents(), now) | 449 if self._use_dirstate_v2: |
455 st.write(d) | 450 packed, meta = v2.pack_dirstate(self._map, self.copymap, now) |
456 st.close() | 451 self.write_v2_no_append(tr, st, meta, packed) |
452 else: | |
453 packed = parsers.pack_dirstate( | |
454 self._map, self.copymap, self.parents(), now | |
455 ) | |
456 st.write(packed) | |
457 st.close() | |
457 self._dirtyparents = False | 458 self._dirtyparents = False |
458 | 459 |
459 @propertycache | 460 @propertycache |
460 def identity(self): | 461 def identity(self): |
461 self._map | 462 self._map |