comparison mercurial/localrepo.py @ 31994:b36318e6d2ef

track-tags: introduce first bits of tags tracking during transaction This changeset introduces detection of tags changes during transaction. When this happens a 'tag_moved=1' argument is set for hooks, similar to what we do for bookmarks and phases. This code is disabled by default as there are still various performance concerns. Some require a smarter use of our existing tag caches and some other require rework around the transaction logic to skip execution when unneeded. These performance improvements have been delayed, I would like to be able to experiment and stabilize the feature behavior first. Later changesets will push the concept further and provide a way for hooks to know what are the actual changes introduced by the transaction. Similar work is needed for the other families of changes (bookmark, phase, obsolescence, etc). Upgrade of the transaction logic will likely be performed at the same time. The current code can report some false positive when .hgtags file changes but resulting tags are unchanged. This will be fixed in the next changeset. For testing, we simply globally enable a hook in the tag test as all the possible tag update cases should exist there. A couple of them show the false positive mentioned above. See in code documentation for more details.
author Pierre-Yves David <pierre-yves.david@ens-lyon.org>
date Tue, 28 Mar 2017 06:38:09 +0200
parents 95a67508fd72
children fe9c4d614600
comparison
equal deleted inserted replaced
31993:bfb826c350d4 31994:b36318e6d2ef
999 else: 999 else:
1000 rp = self.ui.warn 1000 rp = self.ui.warn
1001 vfsmap = {'plain': self.vfs} # root of .hg/ 1001 vfsmap = {'plain': self.vfs} # root of .hg/
1002 # we must avoid cyclic reference between repo and transaction. 1002 # we must avoid cyclic reference between repo and transaction.
1003 reporef = weakref.ref(self) 1003 reporef = weakref.ref(self)
1004 def validate(tr): 1004 # Code to track tag movement
1005 #
1006 # Since tags are all handled as file content, it is actually quite hard
1007 # to track these movement from a code perspective. So we fallback to a
1008 # tracking at the repository level. One could envision to track changes
1009 # to the '.hgtags' file through changegroup apply but that fails to
1010 # cope with case where transaction expose new heads without changegroup
1011 # being involved (eg: phase movement).
1012 #
1013 # For now, We gate the feature behind a flag since this likely comes
1014 # with performance impacts. The current code run more often than needed
1015 # and do not use caches as much as it could. The current focus is on
1016 # the behavior of the feature so we disable it by default. The flag
1017 # will be removed when we are happy with the performance impact.
1018 tracktags = lambda x: None
1019 # experimental config: experimental.hook-track-tags
1020 shouldtracktags = self.ui.configbool('experimental', 'hook-track-tags',
1021 False)
1022 if desc != 'strip' and shouldtracktags:
1023 oldheads = self.changelog.headrevs()
1024 def tracktags(tr2):
1025 repo = reporef()
1026 oldfnodes = tagsmod.fnoderevs(repo.ui, repo, oldheads)
1027 newheads = repo.changelog.headrevs()
1028 newfnodes = tagsmod.fnoderevs(repo.ui, repo, newheads)
1029 # notes: we compare lists here.
1030 # As we do it only once buiding set would not be cheaper
1031 if oldfnodes != newfnodes:
1032 tr2.hookargs['tag_moved'] = '1'
1033 def validate(tr2):
1005 """will run pre-closing hooks""" 1034 """will run pre-closing hooks"""
1035 # XXX the transaction API is a bit lacking here so we take a hacky
1036 # path for now
1037 #
1038 # We cannot add this as a "pending" hooks since the 'tr.hookargs'
1039 # dict is copied before these run. In addition we needs the data
1040 # available to in memory hooks too.
1041 #
1042 # Moreover, we also need to make sure this runs before txnclose
1043 # hooks and there is no "pending" mechanism that would execute
1044 # logic only if hooks are about to run.
1045 #
1046 # Fixing this limitation of the transaction is also needed to track
1047 # other families of changes (bookmarks, phases, obsolescence).
1048 #
1049 # This will have to be fixed before we remove the experimental
1050 # gating.
1051 tracktags(tr2)
1006 reporef().hook('pretxnclose', throw=True, 1052 reporef().hook('pretxnclose', throw=True,
1007 txnname=desc, **pycompat.strkwargs(tr.hookargs)) 1053 txnname=desc, **pycompat.strkwargs(tr.hookargs))
1008 def releasefn(tr, success): 1054 def releasefn(tr, success):
1009 repo = reporef() 1055 repo = reporef()
1010 if success: 1056 if success: