Skip to content
Snippets Groups Projects

Basic namespaces support

Merged Anton Shestakov requested to merge topic/default/wip-namespaces into branch/default
All threads resolved!
Files
5
+ 128
0
@@ -291,6 +291,24 @@
default=None,
)
def _contexttns(self, force=False):
if not force and not self.mutable():
return b'default'
cache = getattr(self._repo, '_tnscache', None)
# topic loaded, but not enabled (eg: multiple repo in the same process)
if cache is None:
return b'default'
if self.rev() is None:
# don't cache volatile ctx instances that aren't stored on-disk yet
return self.extra().get(b'topic-namespace', b'default')
tns = cache.get(self.rev())
if tns is None:
tns = self.extra().get(b'topic-namespace', b'default')
self._repo._tnscache[self.rev()] = tns
return tns
context.basectx.topic_namespace = _contexttns
def _contexttopic(self, force=False):
if not (force or self.mutable()):
return b''
@@ -323,6 +341,14 @@
return None
context.basectx.topicidx = _contexttopicidx
def _contextfqbn(self):
"""return branch//namespace/topic of the changeset, also known as fully
qualified branch name
"""
return common.formatfqbn(self.branch(), self.topic_namespace(), self.topic())
context.basectx.fqbn = _contextfqbn
stackrev = re.compile(br'^s\d+$')
topicrev = re.compile(br'^t\d+$')
@@ -504,6 +530,24 @@
return super(topicrepo, self).commitctx(ctx, *args, **kwargs)
@util.propertycache
def _tnscache(self):
return {}
@property
def topic_namespaces(self):
if self._topic_namespaces is not None:
return self._topic_namespaces
namespaces = set([self.currenttns])
for c in self.set(b'not public()'):
namespaces.add(c.topic_namespace())
self._topic_namespaces = namespaces
return namespaces
@property
def currenttns(self):
return self.vfs.tryread(b'topic-namespace') or b'default'
@util.propertycache
def _topiccache(self):
return {}
@@ -545,6 +589,7 @@
def invalidatevolatilesets(self):
# XXX we might be able to move this to something invalidated less often
super(topicrepo, self).invalidatevolatilesets()
self._topic_namespaces = None
self._topics = None
def peer(self):
@@ -691,6 +736,7 @@
return tr
repo.__class__ = topicrepo
repo._topic_namespaces = None
repo._topics = None
if util.safehasattr(repo, 'names'):
repo.names.addnamespace(namespaces.namespace(
@@ -711,7 +757,19 @@
ctx = context.resource(mapping, b'ctx')
return ctx.topicidx()
@templatekeyword(b'topic_namespace', requires={b'ctx'})
def topicnamespacekw(context, mapping):
""":topic_namespace: String. The topic namespace of the changeset"""
ctx = context.resource(mapping, b'ctx')
return ctx.topic_namespace()
@templatekeyword(b'fqbn', requires={b'ctx'})
def fqbnkw(context, mapping):
""":fqbn: String. The branch//namespace/topic of the changeset"""
ctx = context.resource(mapping, b'ctx')
return ctx.fqbn()
def wrapinit(orig, self, repo, *args, **kwargs):
orig(self, repo, *args, **kwargs)
if not hastopicext(repo):
return
@@ -714,7 +772,13 @@
def wrapinit(orig, self, repo, *args, **kwargs):
orig(self, repo, *args, **kwargs)
if not hastopicext(repo):
return
if b'topic-namespace' not in self._extra:
if getattr(repo, 'currenttns', b''):
self._extra[b'topic-namespace'] = repo.currenttns
else:
# Default value will be dropped from extra by another hack at the changegroup level
self._extra[b'topic-namespace'] = b'default'
if constants.extrakey not in self._extra:
if getattr(repo, 'currenttopic', b''):
self._extra[constants.extrakey] = repo.currenttopic
@@ -725,6 +789,9 @@
def wrapadd(orig, cl, manifest, files, desc, transaction, p1, p2, user,
date=None, extra=None, p1copies=None, p2copies=None,
filesadded=None, filesremoved=None):
if b'topic-namespace' in extra and extra[b'topic-namespace'] == b'default':
extra = extra.copy()
del extra[b'topic-namespace']
if constants.extrakey in extra and not extra[constants.extrakey]:
extra = extra.copy()
del extra[constants.extrakey]
@@ -1500,3 +1567,64 @@
# Restore the topic if need
if topic:
_changecurrenttopic(repo, topic)
def _changecurrenttns(repo, tns):
if tns:
with repo.wlock():
repo.vfs.write(b'topic-namespace', tns)
else:
repo.vfs.unlinkpath(b'topic-namespace', ignoremissing=True)
@command(b'debug-topic-namespace', [
(b'', b'clear', False, b'clear active topic namespace if any'),
],
_(b'[NAMESPACE|--clear]'))
def debugtopicnamespace(ui, repo, tns=None, **opts):
"""set or show the current topic namespace"""
if opts.get('clear'):
if tns:
raise error.Abort(_(b"cannot use --clear when setting a topic namespace"))
tns = None
elif not tns:
ui.write(b'%s\n' % repo.currenttns)
return
if tns:
tns = tns.strip()
if not tns:
raise error.Abort(_(b"topic namespace cannot consist entirely of whitespace"))
if b'/' in tns:
raise error.Abort(_(b"topic namespace cannot contain '/' character"))
scmutil.checknewlabel(repo, tns, b'topic namespace')
ctns = repo.currenttns
_changecurrenttns(repo, tns)
if ctns == b'default' and tns:
repo.ui.status(_(b'marked working directory as topic namespace: %s\n')
% tns)
@command(b'debug-topic-namespaces', [])
def debugtopicnamespaces(ui, repo, **opts):
"""list repository namespaces"""
for tns in repo.topic_namespaces:
ui.write(b'%s\n' % (tns,))
@command(b'debug-parse-fqbn', commands.formatteropts, _(b'FQBN'), optionalrepo=True)
def debugparsefqbn(ui, repo, fqbn, **opts):
"""parse branch//namespace/topic string into its components"""
branch, tns, topic = common.parsefqbn(fqbn)
opts = pycompat.byteskwargs(opts)
fm = ui.formatter(b'debug-parse-namespace', opts)
fm.startitem()
fm.write(b'branch', b'branch: %s\n', branch)
fm.write(b'topic_namespace', b'namespace: %s\n', tns)
fm.write(b'topic', b'topic: %s\n', topic)
fm.end()
@command(b'debug-format-fqbn', [
(b'b', b'branch', b'', b'branch'),
(b'n', b'topic-namespace', b'', b'topic namespace'),
(b't', b'topic', b'', b'topic'),
], optionalrepo=True)
def debugformatfqbn(ui, repo, **opts):
"""format branch, namespace and topic into branch//namespace/topic string"""
short = common.formatfqbn(opts.get('branch'), opts.get('topic_namespace'), opts.get('topic'))
ui.write(b'%s\n' % short)
Loading