Mercurial > evolve
diff hgext3rd/topic/__init__.py @ 6752:44e41905b289 mercurial-6.6
test-compat: merge stable into mercurial-6.6
author | Anton Shestakov <av6@dwimlabs.net> |
---|---|
date | Thu, 11 Apr 2024 01:58:03 -0300 |
parents | 107c5af631a7 |
children | bdf99d434b06 2d2da4f7742a |
line wrap: on
line diff
--- a/hgext3rd/topic/__init__.py Thu Feb 29 14:18:08 2024 -0300 +++ b/hgext3rd/topic/__init__.py Thu Apr 11 01:58:03 2024 -0300 @@ -179,6 +179,7 @@ hg, localrepo, lock as lockmod, + logcmdutil, merge, namespaces, node, @@ -237,7 +238,7 @@ b'log.topic': b'green_background', } -__version__ = b'1.1.2.dev0' +__version__ = b'1.1.3.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 6.6 6.7' minimumhgversion = b'4.9' @@ -295,6 +296,9 @@ configitem(b'experimental', b'tns-default-pull-namespaces', default=configitems.dynamicdefault, ) +configitem(b'experimental', b'tns-reject-push', + default=False, +) configitem(b'experimental', b'topic-mode.server', default=configitems.dynamicdefault, ) @@ -715,31 +719,23 @@ self._topic_namespaces = namespaces return namespaces - @property - def currenttns(self): - tns = self.vfs.tryread(b'topic-namespace') + def wlock(self, wait=True): + wlock = super(topicrepo, self).wlock(wait=wait) # 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': + if wlock is not None and wlock.held: 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' + 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 + return wlock + + @property + def currenttns(self): + tns = self.vfs.tryread(b'topic-namespace') or b'none' return encoding.tolocal(tns) @util.propertycache @@ -921,6 +917,25 @@ else: tr.addvalidator(b'000-reject-publish', _validate_publish) + if self.ui.configbool(b'experimental', b'tns-reject-push'): + if util.safehasattr(tr, '_validator'): + # hg <= 5.3 (36f08ae87ef6) + origvalidator_publish = tr._validator + + def _validate_csets_with_tns(tr2): + repo = reporef() + flow.reject_csets_with_tns(repo, tr2) + + def validator(tr2): + _validate_csets_with_tns(tr2) + return origvalidator_publish(tr2) + + if util.safehasattr(tr, '_validator'): + # hg <= 5.3 (36f08ae87ef6) + tr._validator = validator + else: + tr.addvalidator(b'000-reject-csets-with-tns', _validate_csets_with_tns) + if util.safehasattr(tr, '_validator'): # hg <= 5.3 (36f08ae87ef6) origvalidator_affected_tns = tr._validator @@ -1911,6 +1926,73 @@ for tns in repo.topic_namespaces: ui.write(b'%s\n' % (tns,)) +@command(b'debug-default-topic-namespace', [ + (b'', b'none', True, b'find changesets with topic-namespace=none'), + (b'', b'default', False, b'find changesets with topic-namespace=default'), + (b'', b'clear', False, b'remove topic namespace from commit extras'), + ] + commands.formatteropts) +def debugdefaulttns(ui, repo, **opts): + """list changesets with the default topic namespace in commit extras""" + opts = pycompat.byteskwargs(opts) + condition = [] + if opts[b'none']: + condition += [b'extra("topic-namespace", "none")'] + if opts[b'default']: + condition += [b'extra("topic-namespace", "default")'] + if not condition: + condition = [b'none()'] + revs = repo.revs(b'not public() and not obsolete() and (%lr)', condition) + if opts[b'clear']: + with repo.wlock(), repo.lock(), repo.transaction(b'debug-default-topic-namespace'): + successors = {} + for rev in revs: + _clear_tns_extras(ui, repo, rev, successors) + scmutil.cleanupnodes(repo, successors, b'debug-default-topic-namespace') + return + displayer = logcmdutil.changesetdisplayer(ui, repo, opts) + logcmdutil.displayrevs(ui, repo, revs, displayer, None) + +def _clear_tns_extras(ui, repo, rev, successors): + ctx = repo[rev] + + if len(ctx.parents()) > 1: + # ctx.files() isn't reliable for merges, so fall back to the + # slower repo.status() method + st = ctx.p1().status(ctx) + files = set(st.modified) | set(st.added) | set(st.removed) + else: + files = set(ctx.files()) + + def filectxfn(repo, unused, path): + try: + return ctx[path] + except error.ManifestLookupError: + return None + + extra = ctx.extra().copy() + del extra[b'topic-namespace'] + + p1 = ctx.p1().node() + p2 = ctx.p2().node() + if p1 in successors: + p1 = successors[p1][0] + if p2 in successors: + p2 = successors[p2][0] + mc = context.memctx(repo, + (p1, p2), + ctx.description(), + files, + filectxfn, + user=ctx.user(), + date=ctx.date(), + extra=extra) + + overrides = {(b'phases', b'new-commit'): ctx.phase()} + with repo.ui.configoverride(overrides, b'debug-default-topic-namespace'): + newnode = repo.commitctx(mc) + + successors[ctx.node()] = (newnode,) + @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"""