view hgext3rd/topic/common.py @ 6880:906b5af0b2a6

topic: use FQBN for displaying topic name when it grows multiple changesets
author Anton Shestakov <av6@dwimlabs.net>
date Tue, 17 Sep 2024 21:17:56 +0400
parents f8ea46c21b56
children
line wrap: on
line source

# Copyright 2019 Pierre-Yves David <pierre-yves.david@octobus.net>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.

def hastopicext(repo):
    """True if the repo use the topic extension"""
    return getattr(repo, 'hastopicext', False)

def parsefqbn(string):
    """parse branch//namespace/topic string into branch, namespace and topic

    >>> parsefqbn(b'branch//topic')
    ('branch', 'none', 'topic')
    >>> parsefqbn(b'//namespace/topic')
    ('default', 'namespace', 'topic')
    >>> parsefqbn(b'branch//')
    ('branch', 'none', '')
    >>> parsefqbn(b'//namespace/')
    ('default', 'namespace', '')
    >>> parsefqbn(b'/topic')
    ('/topic', 'none', '')
    >>> parsefqbn(b'//topic')
    ('default', 'none', 'topic')
    >>> parsefqbn(b'branch//namespace/topic')
    ('branch', 'namespace', 'topic')
    >>> parsefqbn(b'file:///tmp/branch//')
    ('file:///tmp/branch', 'none', '')
    >>> parsefqbn(b'http://example.com/branch//namespace/topic')
    ('http://example.com/branch', 'namespace', 'topic')
    """
    branch, sep, other = string.rpartition(b'//')
    if not sep:
        # when there's no // anywhere in the string, rpartition returns
        # untouched string as the 3rd element, and the first two are empty
        branch, other = other, b''
    if not branch:
        branch = b'default'
    tns, sep, topic = other.partition(b'/')
    if not sep:
        # when there's no / in the rest of the string, there can only be topic
        tns, topic = b'none', tns
    return branch, tns, topic

# Fully qualified branch name length constants for formatfqbn() etc
#
# Selecting different length only matters when at least one FQBN component is
# empty/default. The general idea is: short length will skip all empty
# components (except for branch if there's nothing else to show), normal length
# will only skip default topic namespace and empty topic, full length will not
# skip anything and will show everything. For example:
#
# - formatfqbn(topic=foo, length=FQBN_SHORT) gives:
#   //foo
#
# - formatfqbn(topic=foo, length=FQBN_NORMAL) gives:
#   default//foo
#
# - formatfqbn(topic=foo, length=FQBN_FULL) gives:
#   default//none/foo
#
# See also: tests for debug-format-fqbn command.
FQBN_SHORT = 1
FQBN_NORMAL = 2
FQBN_FULL = 3

def formatfqbn(branch=b'', namespace=b'', topic=b'', length=FQBN_NORMAL):
    """format branch, namespace and topic into branch//namespace/topic string

    >>> formatfqbn(branch=b'branch', topic=b'topic')
    'branch//topic'
    >>> formatfqbn(namespace=b'namespace', topic=b'topic')
    '//namespace/topic'
    >>> formatfqbn(branch=b'branch')
    'branch'
    >>> formatfqbn(branch=b'branch//')
    'branch////'
    >>> formatfqbn(branch=b'double//slash')
    'double//slash//'
    >>> formatfqbn(namespace=b'namespace')
    '//namespace/'
    >>> formatfqbn(branch=b'/topic')
    '/topic'
    >>> formatfqbn(topic=b'topic')
    '//topic'
    >>> formatfqbn(branch=b'branch', namespace=b'namespace', topic=b'topic')
    'branch//namespace/topic'
    >>> formatfqbn(branch=b'foo/bar', namespace=b'user26', topic=b'feature')
    'foo/bar//user26/feature'
    >>> formatfqbn(branch=b'http://example.com/branch', namespace=b'namespace', topic=b'topic')
    'http://example.com/branch//namespace/topic'
    """
    result = b''
    showbranch = branch and not (length == FQBN_SHORT and branch == b'default')
    shownamespace = namespace and not (length != FQBN_FULL and namespace == b'none')
    if not shownamespace and not topic:
        # if there's nothing to show, show at least branch
        showbranch = True
    if showbranch:
        result += branch
    if shownamespace or topic or b'//' in branch:
        result += b'//'
    if shownamespace:
        result += namespace + b'/'
    result += topic
    return result

def upgradeformat(branch):
    """take branch and topic in ":" format and return fqbn in "//" format

    This function can be used for transforming branchmap contents of peers that
    don't support topic namespaces yet to work with peers with topic namespaces
    support.

    >>> upgradeformat(b'branch')
    'branch'
    >>> upgradeformat(b'branch:topic')
    'branch//topic'
    >>> upgradeformat(b'branch//')
    'branch////'
    >>> upgradeformat(b'branch//:topic')
    'branch////topic'
    """
    if b':' not in branch:
        # formatting anyway, because named branch could contain "//"
        return formatfqbn(branch=branch)
    # topic namespace cannot be extracted from ":" format
    branch, topic = branch.split(b':', 1)
    return formatfqbn(branch=branch, topic=topic)