Mercurial > public > mercurial-scm > hg-stable
diff 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 |
line wrap: on
line diff
--- a/mercurial/localrepo.py Tue Mar 28 05:06:56 2017 +0200 +++ b/mercurial/localrepo.py Tue Mar 28 06:38:09 2017 +0200 @@ -1001,8 +1001,54 @@ vfsmap = {'plain': self.vfs} # root of .hg/ # we must avoid cyclic reference between repo and transaction. reporef = weakref.ref(self) - def validate(tr): + # Code to track tag movement + # + # Since tags are all handled as file content, it is actually quite hard + # to track these movement from a code perspective. So we fallback to a + # tracking at the repository level. One could envision to track changes + # to the '.hgtags' file through changegroup apply but that fails to + # cope with case where transaction expose new heads without changegroup + # being involved (eg: phase movement). + # + # For now, We gate the feature behind a flag since this likely comes + # with performance impacts. The current code run more often than needed + # and do not use caches as much as it could. The current focus is on + # the behavior of the feature so we disable it by default. The flag + # will be removed when we are happy with the performance impact. + tracktags = lambda x: None + # experimental config: experimental.hook-track-tags + shouldtracktags = self.ui.configbool('experimental', 'hook-track-tags', + False) + if desc != 'strip' and shouldtracktags: + oldheads = self.changelog.headrevs() + def tracktags(tr2): + repo = reporef() + oldfnodes = tagsmod.fnoderevs(repo.ui, repo, oldheads) + newheads = repo.changelog.headrevs() + newfnodes = tagsmod.fnoderevs(repo.ui, repo, newheads) + # notes: we compare lists here. + # As we do it only once buiding set would not be cheaper + if oldfnodes != newfnodes: + tr2.hookargs['tag_moved'] = '1' + def validate(tr2): """will run pre-closing hooks""" + # XXX the transaction API is a bit lacking here so we take a hacky + # path for now + # + # We cannot add this as a "pending" hooks since the 'tr.hookargs' + # dict is copied before these run. In addition we needs the data + # available to in memory hooks too. + # + # Moreover, we also need to make sure this runs before txnclose + # hooks and there is no "pending" mechanism that would execute + # logic only if hooks are about to run. + # + # Fixing this limitation of the transaction is also needed to track + # other families of changes (bookmarks, phases, obsolescence). + # + # This will have to be fixed before we remove the experimental + # gating. + tracktags(tr2) reporef().hook('pretxnclose', throw=True, txnname=desc, **pycompat.strkwargs(tr.hookargs)) def releasefn(tr, success):