diff -r bfb826c350d4 -r b36318e6d2ef mercurial/localrepo.py --- 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):