87 self._parentwriters = 0 |
87 self._parentwriters = 0 |
88 self._filename = 'dirstate' |
88 self._filename = 'dirstate' |
89 self._pendingfilename = '%s.pending' % self._filename |
89 self._pendingfilename = '%s.pending' % self._filename |
90 self._plchangecallbacks = {} |
90 self._plchangecallbacks = {} |
91 self._origpl = None |
91 self._origpl = None |
|
92 self._updatedfiles = set() |
92 |
93 |
93 # for consistent view between _pl() and _read() invocations |
94 # for consistent view between _pl() and _read() invocations |
94 self._pendingmode = None |
95 self._pendingmode = None |
95 |
96 |
96 def beginparentchange(self): |
97 def beginparentchange(self): |
429 "_pl", "_dirs", "_ignore", "_nonnormalset"): |
430 "_pl", "_dirs", "_ignore", "_nonnormalset"): |
430 if a in self.__dict__: |
431 if a in self.__dict__: |
431 delattr(self, a) |
432 delattr(self, a) |
432 self._lastnormaltime = 0 |
433 self._lastnormaltime = 0 |
433 self._dirty = False |
434 self._dirty = False |
|
435 self._updatedfiles.clear() |
434 self._parentwriters = 0 |
436 self._parentwriters = 0 |
435 self._origpl = None |
437 self._origpl = None |
436 |
438 |
437 def copy(self, source, dest): |
439 def copy(self, source, dest): |
438 """Mark dest as a copy of source. Unmark dest if source is None.""" |
440 """Mark dest as a copy of source. Unmark dest if source is None.""" |
439 if source == dest: |
441 if source == dest: |
440 return |
442 return |
441 self._dirty = True |
443 self._dirty = True |
442 if source is not None: |
444 if source is not None: |
443 self._copymap[dest] = source |
445 self._copymap[dest] = source |
|
446 self._updatedfiles.add(source) |
|
447 self._updatedfiles.add(dest) |
444 elif dest in self._copymap: |
448 elif dest in self._copymap: |
445 del self._copymap[dest] |
449 del self._copymap[dest] |
|
450 self._updatedfiles.add(dest) |
446 |
451 |
447 def copied(self, file): |
452 def copied(self, file): |
448 return self._copymap.get(file, None) |
453 return self._copymap.get(file, None) |
449 |
454 |
450 def copies(self): |
455 def copies(self): |
456 |
461 |
457 if "_filefoldmap" in self.__dict__: |
462 if "_filefoldmap" in self.__dict__: |
458 normed = util.normcase(f) |
463 normed = util.normcase(f) |
459 if normed in self._filefoldmap: |
464 if normed in self._filefoldmap: |
460 del self._filefoldmap[normed] |
465 del self._filefoldmap[normed] |
|
466 |
|
467 self._updatedfiles.add(f) |
461 |
468 |
462 def _addpath(self, f, state, mode, size, mtime): |
469 def _addpath(self, f, state, mode, size, mtime): |
463 oldstate = self[f] |
470 oldstate = self[f] |
464 if state == 'a' or oldstate == 'r': |
471 if state == 'a' or oldstate == 'r': |
465 scmutil.checkfilename(f) |
472 scmutil.checkfilename(f) |
473 raise error.Abort( |
480 raise error.Abort( |
474 _('file %r in dirstate clashes with %r') % (d, f)) |
481 _('file %r in dirstate clashes with %r') % (d, f)) |
475 if oldstate in "?r" and "_dirs" in self.__dict__: |
482 if oldstate in "?r" and "_dirs" in self.__dict__: |
476 self._dirs.addpath(f) |
483 self._dirs.addpath(f) |
477 self._dirty = True |
484 self._dirty = True |
|
485 self._updatedfiles.add(f) |
478 self._map[f] = dirstatetuple(state, mode, size, mtime) |
486 self._map[f] = dirstatetuple(state, mode, size, mtime) |
479 if state != 'n' or mtime == -1: |
487 if state != 'n' or mtime == -1: |
480 self._nonnormalset.add(f) |
488 self._nonnormalset.add(f) |
481 |
489 |
482 def normal(self, f): |
490 def normal(self, f): |
654 if "_dirs" in self.__dict__: |
662 if "_dirs" in self.__dict__: |
655 delattr(self, "_dirs") |
663 delattr(self, "_dirs") |
656 self._copymap = {} |
664 self._copymap = {} |
657 self._pl = [nullid, nullid] |
665 self._pl = [nullid, nullid] |
658 self._lastnormaltime = 0 |
666 self._lastnormaltime = 0 |
|
667 self._updatedfiles.clear() |
659 self._dirty = True |
668 self._dirty = True |
660 |
669 |
661 def rebuild(self, parent, allfiles, changedfiles=None): |
670 def rebuild(self, parent, allfiles, changedfiles=None): |
662 if changedfiles is None: |
671 if changedfiles is None: |
663 # Rebuild entire dirstate |
672 # Rebuild entire dirstate |
690 # https://www.mercurial-scm.org/wiki/DirstateTransactionPlan |
699 # https://www.mercurial-scm.org/wiki/DirstateTransactionPlan |
691 |
700 |
692 # emulate dropping timestamp in 'parsers.pack_dirstate' |
701 # emulate dropping timestamp in 'parsers.pack_dirstate' |
693 now = _getfsnow(self._opener) |
702 now = _getfsnow(self._opener) |
694 dmap = self._map |
703 dmap = self._map |
695 for f, e in dmap.iteritems(): |
704 for f in self._updatedfiles: |
696 if e[0] == 'n' and e[3] == now: |
705 e = dmap.get(f) |
|
706 if e is not None and e[0] == 'n' and e[3] == now: |
697 dmap[f] = dirstatetuple(e[0], e[1], e[2], -1) |
707 dmap[f] = dirstatetuple(e[0], e[1], e[2], -1) |
698 self._nonnormalset.add(f) |
708 self._nonnormalset.add(f) |
699 |
709 |
700 # emulate that all 'dirstate.normal' results are written out |
710 # emulate that all 'dirstate.normal' results are written out |
701 self._lastnormaltime = 0 |
711 self._lastnormaltime = 0 |
|
712 self._updatedfiles.clear() |
702 |
713 |
703 # delay writing in-memory changes out |
714 # delay writing in-memory changes out |
704 tr.addfilegenerator('dirstate', (self._filename,), |
715 tr.addfilegenerator('dirstate', (self._filename,), |
705 self._writedirstate, location='plain') |
716 self._writedirstate, location='plain') |
706 return |
717 return |