mercurial/dirstate.py
changeset 50120 a7d11833ff48
parent 50119 de42ba9dd852
child 50121 15531d101313
equal deleted inserted replaced
50119:de42ba9dd852 50120:a7d11833ff48
   202         has_tr = repo.currenttransaction() is not None
   202         has_tr = repo.currenttransaction() is not None
   203         if not has_tr and self._changing_level == 0 and self._dirty:
   203         if not has_tr and self._changing_level == 0 and self._dirty:
   204             msg = "entering a changing context, but dirstate is already dirty"
   204             msg = "entering a changing context, but dirstate is already dirty"
   205             raise error.ProgrammingError(msg)
   205             raise error.ProgrammingError(msg)
   206 
   206 
       
   207         assert self._changing_level >= 0
   207         # different type of change are mutually exclusive
   208         # different type of change are mutually exclusive
   208         if self._change_type is None:
   209         if self._change_type is None:
   209             assert self._changing_level == 0
   210             assert self._changing_level == 0
   210             self._change_type = change_type
   211             self._change_type = change_type
   211         elif self._change_type != change_type:
   212         elif self._change_type != change_type:
   213                 'trying to open "%s" dirstate-changing context while a "%s" is'
   214                 'trying to open "%s" dirstate-changing context while a "%s" is'
   214                 ' already open'
   215                 ' already open'
   215             )
   216             )
   216             msg %= (change_type, self._change_type)
   217             msg %= (change_type, self._change_type)
   217             raise error.ProgrammingError(msg)
   218             raise error.ProgrammingError(msg)
       
   219         should_write = False
   218         self._changing_level += 1
   220         self._changing_level += 1
   219         try:
   221         try:
   220             yield
   222             yield
   221         except:  # re-raises
   223         except:  # re-raises
   222             self.invalidate()
   224             self.invalidate()  # this will set `_invalidated_context`
   223             raise
   225             raise
   224         finally:
   226         finally:
   225             tr = repo.currenttransaction()
   227             assert self._changing_level > 0
   226             if self._changing_level > 0:
   228             self._changing_level -= 1
   227                 if self._invalidated_context:
   229             # If the dirstate is being invalidated, call invalidate again.
   228                     # make sure we invalidate anything an upper context might
   230             # This will throw away anything added by a upper context and
   229                     # have changed.
   231             # reset the `_invalidated_context` flag when relevant
   230                     self.invalidate()
   232             if self._changing_level <= 0:
   231                 self._changing_level -= 1
   233                 self._change_type = None
   232                 # The invalidation is complete once we exit the final context
   234                 assert self._changing_level == 0
   233                 # manager
   235             if self._invalidated_context:
   234                 if self._changing_level <= 0:
   236                 # make sure we invalidate anything an upper context might
   235                     self._change_type = None
   237                 # have changed.
   236                     assert self._changing_level == 0
   238                 self.invalidate()
   237                     if self._invalidated_context:
   239             else:
   238                         self._invalidated_context = False
   240                 should_write = self._changing_level <= 0
   239                     else:
   241         tr = repo.currenttransaction()
   240                         # When an exception occured, `_invalidated_context`
   242         if has_tr != (tr is not None):
   241                         # would have been set to True by the `invalidate`
   243             if has_tr:
   242                         # call earlier.
   244                 m = "transaction vanished while changing dirstate"
   243                         #
   245             else:
   244                         # We don't have more straightforward code, because the
   246                 m = "transaction appeared while changing dirstate"
   245                         # Exception catching (and the associated `invalidate`
   247             raise error.ProgrammingError(m)
   246                         # calling) might have been called by a nested context
   248         if should_write:
   247                         # instead of the top level one.
   249             self.write(tr)
   248                         self.write(tr)
       
   249             if has_tr != (tr is not None):
       
   250                 if has_tr:
       
   251                     m = "transaction vanished while changing dirstate"
       
   252                 else:
       
   253                     m = "transaction appeared while changing dirstate"
       
   254                 raise error.ProgrammingError(m)
       
   255 
   250 
   256     @contextlib.contextmanager
   251     @contextlib.contextmanager
   257     def changing_parents(self, repo):
   252     def changing_parents(self, repo):
   258         with self._changing(repo, CHANGE_TYPE_PARENTS) as c:
   253         with self._changing(repo, CHANGE_TYPE_PARENTS) as c:
   259             yield c
   254             yield c