Mercurial > evolve
diff hgext3rd/topic/__init__.py @ 6679:a1453b601ff1 mercurial-6.4
test-compat: merge mercurial-6.5 into mercurial-6.4
author | Anton Shestakov <av6@dwimlabs.net> |
---|---|
date | Sun, 04 Feb 2024 15:46:44 -0300 |
parents | 991d78f5c401 |
children | 369e248b6312 752201811d5a |
line wrap: on
line diff
--- a/hgext3rd/topic/__init__.py Fri Oct 13 16:12:31 2023 -0300 +++ b/hgext3rd/topic/__init__.py Sun Feb 04 15:46:44 2024 -0300 @@ -157,6 +157,7 @@ from __future__ import absolute_import +import errno import functools import re import time @@ -236,9 +237,9 @@ b'log.topic': b'green_background', } -__version__ = b'1.1.0.dev0' +__version__ = b'1.1.1.dev0' -testedwith = b'4.9 5.0 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 6.0 6.1 6.2 6.3 6.4 6.5' +testedwith = b'4.9 5.0 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 6.0 6.1 6.2 6.3 6.4 6.5 6.6' minimumhgversion = b'4.9' buglink = b'https://bz.mercurial-scm.org/' @@ -277,6 +278,12 @@ configitem(b'_internal', b'tns-explicit-target', default=False, ) +# used for selecting what topic and topic namespace values take priority during +# some history rewriting operations: 'local' prefers active topic and tns, +# 'other' prefers values in commit extras, if there are any +configitem(b'_internal', b'topic-source', + default=b'other', +) configitem(b'devel', b'tns-report-transactions', default=lambda: [], ) @@ -516,6 +523,30 @@ if tr.changes[b'tns']: repo.ui.status(b'topic namespaces affected: %s\n' % b' '.join(sorted(tr.changes[b'tns']))) +def wrapmakebundlerepository(orig, ui, repopath, bundlepath): + repo = orig(ui, repopath, bundlepath) + + # We want bundle repos to also have caches for topic extension, because we + # want to, for example, see topic and topic namespaces in `hg incoming` + # regardless if the bundle repo has topic extension, as long as local repo + # has topic enabled. + class topicbundlerepo(repo.__class__): + @util.propertycache + def _tnscache(self): + return {} + + @util.propertycache + def _topiccache(self): + return {} + + def invalidatecaches(self): + self._tnscache.clear() + self._topiccache.clear() + super(topicbundlerepo, self).invalidatecaches() + + repo.__class__ = topicbundlerepo + return repo + def uisetup(ui): destination.modsetup(ui) discovery.modsetup(ui) @@ -601,27 +632,9 @@ except (KeyError, AttributeError): pass - server.setupserver(ui) - - # We want bundle repos to also have caches for topic extension, because we - # want to, for example, see topic and topic namespaces in `hg incoming` - # regardless if the bundle repo has topic extension, as long as local repo - # has topic enabled. - class topicbundlerepo(bundlerepo.bundlerepository): - @util.propertycache - def _tnscache(self): - return {} + extensions.wrapfunction(bundlerepo, 'makebundlerepository', wrapmakebundlerepository) - @util.propertycache - def _topiccache(self): - return {} - - def invalidatecaches(self): - self._tnscache.clear() - self._topiccache.clear() - super(topicbundlerepo, self).invalidatecaches() - - bundlerepo.bundlerepository = topicbundlerepo + server.setupserver(ui) def reposetup(ui, repo): if not isinstance(repo, localrepo.localrepository): @@ -665,15 +678,26 @@ # bypass the core "nothing changed" logic configoverride = self.ui.configoverride({ (b'ui', b'allowemptycommit'): True - }) + }, b'topic-extension') with configoverride: return super(topicrepo, self).commit(*args, **kwargs) def commitctx(self, ctx, *args, **kwargs): if isinstance(ctx, context.workingcommitctx): - current = self.currenttopic - if current and constants.extrakey not in ctx.extra(): - ctx.extra()[constants.extrakey] = current + tns = self.currenttns + topic = self.currenttopic + # topic source: + # - 'local': we need to put currently active tns and topic into + # commit extras in any case + # - 'other': we could use active tns and topic, but only if + # commit extras don't already have them + ts = self.ui.config(b'_internal', b'topic-source') + if ts == b'local' or (tns != b'none' and b'topic-namespace' not in ctx.extra()): + # default value will be dropped from extra later on + ctx.extra()[b'topic-namespace'] = tns + if ts == b'local' or (topic and constants.extrakey not in ctx.extra()): + # empty value will be dropped from extra later on + ctx.extra()[constants.extrakey] = topic return super(topicrepo, self).commitctx(ctx, *args, **kwargs) @util.propertycache @@ -693,7 +717,30 @@ @property def currenttns(self): - return self.vfs.tryread(b'topic-namespace') or b'none' + tns = self.vfs.tryread(b'topic-namespace') + # we should definitely drop this at some point, but it depends on + # our own release schedule, not core's, so here's hg 1.0 + # hg <= 1.0 (cfa08c88a5c4) + if tns == b'none': + try: + with self.wlock(wait=False): + try: + # we make sure the file contains what we expect + if self.vfs.read(b'topic-namespace') == b'none': + repo.vfs.unlinkpath(b'topic-namespace') + except IOError as err: + if err.errno != errno.ENOENT: + raise + except error.LockError: + # if we cannot acquire wdir lock, then we shouldn't do + # anything at all, since it'd be unsafe to modify wdir + pass + elif tns == b'': + # technically, if user creates an empty file, it should be + # handled differently than non-existing file, but the + # distinction is probably not that important + tns = b'none' + return encoding.tolocal(tns) @util.propertycache def _topiccache(self): @@ -712,7 +759,8 @@ @property def currenttopic(self): - return self.vfs.tryread(b'topic') + topic = self.vfs.tryread(b'topic') + return encoding.tolocal(topic) # overwritten at the instance level by topicmap.py _autobranchmaptopic = True @@ -1092,7 +1140,7 @@ # Have some restrictions on the topic name just like bookmark name scmutil.checknewlabel(repo, topic, b'topic') - helptxt = _(b"topic names can only consist of alphanumeric, '-'" + helptxt = _(b"topic names can only consist of alphanumeric, '-'," b" '_' and '.' characters") try: utopic = encoding.unifromlocal(topic) @@ -1679,10 +1727,10 @@ if pctx.phase() > phases.public: tns = pctx.topic_namespace() t = pctx.topic() - repo.vfs.write(b'topic-namespace', tns) + _changecurrenttns(repo, tns) if tns != b'none' and tns != otns: repo.ui.status(_(b"switching to topic-namespace %s\n") % tns) - repo.vfs.write(b'topic', t) + _changecurrenttopic(repo, t) if t and t != ot: repo.ui.status(_(b"switching to topic %s\n") % t) if ot and not t: @@ -1839,6 +1887,18 @@ if b'/' in tns: raise error.Abort(_(b"topic namespace cannot contain '/' character")) scmutil.checknewlabel(repo, tns, b'topic namespace') + + helptxt = _(b"topic namespace names can only consist of alphanumeric, " + b"'-', '_' and '.' characters") + try: + utns = encoding.unifromlocal(tns) + except error.Abort: + # Maybe we should allow these topic names as well, as long as they + # don't break any other rules + utns = '' + rmatch = re.match(r'[-_.\w]+', utns, re.UNICODE) + if not utns or not rmatch or rmatch.group(0) != utns: + raise compat.InputError(_(b"invalid topic namespace name: '%s'") % tns, hint=helptxt) ctns = repo.currenttns _changecurrenttns(repo, tns) if ctns == b'none' and tns != b'none':