mercurial/dirstate.py
changeset 48057 62188e4de549
parent 48055 84e7a86e3a63
child 48058 40dd56086056
equal deleted inserted replaced
48056:cd13d3c2ad2e 48057:62188e4de549
   128         self._parentwriters = 0
   128         self._parentwriters = 0
   129         self._filename = b'dirstate'
   129         self._filename = b'dirstate'
   130         self._pendingfilename = b'%s.pending' % self._filename
   130         self._pendingfilename = b'%s.pending' % self._filename
   131         self._plchangecallbacks = {}
   131         self._plchangecallbacks = {}
   132         self._origpl = None
   132         self._origpl = None
   133         self._updatedfiles = set()
       
   134         self._mapcls = dirstatemap.dirstatemap
   133         self._mapcls = dirstatemap.dirstatemap
   135         # Access and cache cwd early, so we don't access it for the first time
   134         # Access and cache cwd early, so we don't access it for the first time
   136         # after a working-copy update caused it to not exist (accessing it then
   135         # after a working-copy update caused it to not exist (accessing it then
   137         # raises an exception).
   136         # raises an exception).
   138         self._cwd
   137         self._cwd
   408                 elif s.from_p2:
   407                 elif s.from_p2:
   409                     source = self._map.copymap.get(f)
   408                     source = self._map.copymap.get(f)
   410                     if source:
   409                     if source:
   411                         copies[f] = source
   410                         copies[f] = source
   412                     self._check_new_tracked_filename(f)
   411                     self._check_new_tracked_filename(f)
   413                     self._updatedfiles.add(f)
       
   414                     self._map.reset_state(
   412                     self._map.reset_state(
   415                         f,
   413                         f,
   416                         p1_tracked=False,
   414                         p1_tracked=False,
   417                         wc_tracked=True,
   415                         wc_tracked=True,
   418                     )
   416                     )
   444         for a in ("_map", "_branch", "_ignore"):
   442         for a in ("_map", "_branch", "_ignore"):
   445             if a in self.__dict__:
   443             if a in self.__dict__:
   446                 delattr(self, a)
   444                 delattr(self, a)
   447         self._lastnormaltime = 0
   445         self._lastnormaltime = 0
   448         self._dirty = False
   446         self._dirty = False
   449         self._updatedfiles.clear()
       
   450         self._parentwriters = 0
   447         self._parentwriters = 0
   451         self._origpl = None
   448         self._origpl = None
   452 
   449 
   453     def copy(self, source, dest):
   450     def copy(self, source, dest):
   454         """Mark dest as a copy of source. Unmark dest if source is None."""
   451         """Mark dest as a copy of source. Unmark dest if source is None."""
   455         if source == dest:
   452         if source == dest:
   456             return
   453             return
   457         self._dirty = True
   454         self._dirty = True
   458         if source is not None:
   455         if source is not None:
   459             self._map.copymap[dest] = source
   456             self._map.copymap[dest] = source
   460             self._updatedfiles.add(source)
   457         else:
   461             self._updatedfiles.add(dest)
   458             self._map.copymap.pop(dest, None)
   462         elif self._map.copymap.pop(dest, None):
       
   463             self._updatedfiles.add(dest)
       
   464 
   459 
   465     def copied(self, file):
   460     def copied(self, file):
   466         return self._map.copymap.get(file, None)
   461         return self._map.copymap.get(file, None)
   467 
   462 
   468     def copies(self):
   463     def copies(self):
   476         example by a command like `hg add X`.
   471         example by a command like `hg add X`.
   477 
   472 
   478         return True the file was previously untracked, False otherwise.
   473         return True the file was previously untracked, False otherwise.
   479         """
   474         """
   480         self._dirty = True
   475         self._dirty = True
   481         self._updatedfiles.add(filename)
       
   482         entry = self._map.get(filename)
   476         entry = self._map.get(filename)
   483         if entry is None or not entry.tracked:
   477         if entry is None or not entry.tracked:
   484             self._check_new_tracked_filename(filename)
   478             self._check_new_tracked_filename(filename)
   485         return self._map.set_tracked(filename)
   479         return self._map.set_tracked(filename)
   486 
   480 
   494         return True the file was previously tracked, False otherwise.
   488         return True the file was previously tracked, False otherwise.
   495         """
   489         """
   496         ret = self._map.set_untracked(filename)
   490         ret = self._map.set_untracked(filename)
   497         if ret:
   491         if ret:
   498             self._dirty = True
   492             self._dirty = True
   499             self._updatedfiles.add(filename)
       
   500         return ret
   493         return ret
   501 
   494 
   502     @requires_no_parents_change
   495     @requires_no_parents_change
   503     def set_clean(self, filename, parentfiledata=None):
   496     def set_clean(self, filename, parentfiledata=None):
   504         """record that the current state of the file on disk is known to be clean"""
   497         """record that the current state of the file on disk is known to be clean"""
   505         self._dirty = True
   498         self._dirty = True
   506         self._updatedfiles.add(filename)
       
   507         if parentfiledata:
   499         if parentfiledata:
   508             (mode, size, mtime) = parentfiledata
   500             (mode, size, mtime) = parentfiledata
   509         else:
   501         else:
   510             (mode, size, mtime) = self._get_filedata(filename)
   502             (mode, size, mtime) = self._get_filedata(filename)
   511         if not self._map[filename].tracked:
   503         if not self._map[filename].tracked:
   519 
   511 
   520     @requires_no_parents_change
   512     @requires_no_parents_change
   521     def set_possibly_dirty(self, filename):
   513     def set_possibly_dirty(self, filename):
   522         """record that the current state of the file on disk is unknown"""
   514         """record that the current state of the file on disk is unknown"""
   523         self._dirty = True
   515         self._dirty = True
   524         self._updatedfiles.add(filename)
       
   525         self._map.set_possibly_dirty(filename)
   516         self._map.set_possibly_dirty(filename)
   526 
   517 
   527     @requires_parents_change
   518     @requires_parents_change
   528     def update_file_p1(
   519     def update_file_p1(
   529         self,
   520         self,
   554         elif not (p1_tracked or wc_tracked):
   545         elif not (p1_tracked or wc_tracked):
   555             # the file is no longer relevant to anyone
   546             # the file is no longer relevant to anyone
   556             if self._map.get(filename) is not None:
   547             if self._map.get(filename) is not None:
   557                 self._map.reset_state(filename)
   548                 self._map.reset_state(filename)
   558                 self._dirty = True
   549                 self._dirty = True
   559                 self._updatedfiles.add(filename)
       
   560         elif (not p1_tracked) and wc_tracked:
   550         elif (not p1_tracked) and wc_tracked:
   561             if entry is not None and entry.added:
   551             if entry is not None and entry.added:
   562                 return  # avoid dropping copy information (maybe?)
   552                 return  # avoid dropping copy information (maybe?)
   563         elif p1_tracked and not wc_tracked:
   553         elif p1_tracked and not wc_tracked:
   564             pass
   554             pass
   570         # compared to the overall update process calling this.
   560         # compared to the overall update process calling this.
   571         parentfiledata = None
   561         parentfiledata = None
   572         if wc_tracked:
   562         if wc_tracked:
   573             parentfiledata = self._get_filedata(filename)
   563             parentfiledata = self._get_filedata(filename)
   574 
   564 
   575         self._updatedfiles.add(filename)
       
   576         self._map.reset_state(
   565         self._map.reset_state(
   577             filename,
   566             filename,
   578             wc_tracked,
   567             wc_tracked,
   579             p1_tracked,
   568             p1_tracked,
   580             possibly_dirty=possibly_dirty,
   569             possibly_dirty=possibly_dirty,
   620         # note: I do not think we need to double check name clash here since we
   609         # note: I do not think we need to double check name clash here since we
   621         # are in a update/merge case that should already have taken care of
   610         # are in a update/merge case that should already have taken care of
   622         # this. The test agrees
   611         # this. The test agrees
   623 
   612 
   624         self._dirty = True
   613         self._dirty = True
   625         self._updatedfiles.add(filename)
       
   626 
   614 
   627         need_parent_file_data = (
   615         need_parent_file_data = (
   628             not (possibly_dirty or clean_p2 or merged)
   616             not (possibly_dirty or clean_p2 or merged)
   629             and wc_tracked
   617             and wc_tracked
   630             and p1_tracked
   618             and p1_tracked
   766         return path
   754         return path
   767 
   755 
   768     def clear(self):
   756     def clear(self):
   769         self._map.clear()
   757         self._map.clear()
   770         self._lastnormaltime = 0
   758         self._lastnormaltime = 0
   771         self._updatedfiles.clear()
       
   772         self._dirty = True
   759         self._dirty = True
   773 
   760 
   774     def rebuild(self, parent, allfiles, changedfiles=None):
   761     def rebuild(self, parent, allfiles, changedfiles=None):
   775         if changedfiles is None:
   762         if changedfiles is None:
   776             # Rebuild entire dirstate
   763             # Rebuild entire dirstate
   807                     f,
   794                     f,
   808                     wc_tracked=True,
   795                     wc_tracked=True,
   809                     p1_tracked=True,
   796                     p1_tracked=True,
   810                     possibly_dirty=True,
   797                     possibly_dirty=True,
   811                 )
   798                 )
   812             self._updatedfiles.add(f)
       
   813         for f in to_drop:
   799         for f in to_drop:
   814             self._map.reset_state(f)
   800             self._map.reset_state(f)
   815             self._updatedfiles.add(f)
       
   816 
   801 
   817         self._dirty = True
   802         self._dirty = True
   818 
   803 
   819     def identity(self):
   804     def identity(self):
   820         """Return identity of dirstate itself to detect changing in storage
   805         """Return identity of dirstate itself to detect changing in storage
   836             # See also the wiki page below for detail:
   821             # See also the wiki page below for detail:
   837             # https://www.mercurial-scm.org/wiki/DirstateTransactionPlan
   822             # https://www.mercurial-scm.org/wiki/DirstateTransactionPlan
   838 
   823 
   839             # record when mtime start to be ambiguous
   824             # record when mtime start to be ambiguous
   840             now = _getfsnow(self._opener)
   825             now = _getfsnow(self._opener)
   841 
       
   842             # emulate that all 'dirstate.normal' results are written out
       
   843             self._updatedfiles.clear()
       
   844 
   826 
   845             # delay writing in-memory changes out
   827             # delay writing in-memory changes out
   846             tr.addfilegenerator(
   828             tr.addfilegenerator(
   847                 b'dirstate',
   829                 b'dirstate',
   848                 (self._filename,),
   830                 (self._filename,),