view hgext3rd/topic/common.py @ 6889:a66cf9008781

obslog: also display patch for rebased changesets This applies the same logic that is used for "merge-diff" to rebased changesets. The successors' content is compared to the content of the predecessors rebased in-memory on the new parents. This highlights the changes that were actually introduced while rebasing (like conflict resolution or API adjustment). As a side effect, obslog now also outputs slightly more diffs for splits, showing what parts of the original big changeset were moved to the smaller split components (but for now it only works for the first few changesets).
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Sun, 22 Sep 2024 02:58:54 +0200
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)