All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] review: Generate thanks commit URLs for known repositories automatically
@ 2026-09-12 10:58 Mark Brown
  0 siblings, 0 replies; only message in thread
From: Mark Brown @ 2026-09-12 10:58 UTC (permalink / raw)
  To: Konstantin Ryabitsev; +Cc: tools, Mark Brown

At present generating links to commits in web interfaces for inclusion
in thanks mails requires manual configuration of a global configuration
option b4.thanks-commit-url-mask, or the per remote equivalent
b4-thanks-url-mask.  Given that we also have the b4-check-repo option to
configure where to check to see if thanks are ready to be sent and
practically speaking this is likely to be one of a very small set of
hosting providers this is all a bit redundant.

If one of git.kernel.org, github or gitlab is configured for the check
repo or remote URL for the branch then default to generating a link
based on our knowledge of the remote, a manual configuration will still
override the default.

Signed-off-by: Mark Brown <broonie@kernel.org>
---

Also fall back to the remote URL.

 docs/config.rst                             |  32 ++++-
 docs/maintainer/review.rst                  |  15 +--
 src/b4/command.py                           |   4 +
 src/b4/review_tui/_tracking_app.py          |   4 +-
 src/b4/templates/thanks-am-template.example |   3 +
 src/b4/templates/thanks-pr-template.example |   3 +
 src/b4/ty.py                                | 131 +++++++++++++++-----
 src/tests/test_tui_tracking.py              |  45 +++++++
 src/tests/test_ty.py                        |  88 +++++++++++++
 9 files changed, 281 insertions(+), 44 deletions(-)

diff --git a/docs/config.rst b/docs/config.rst
index 4dce689..91d783e 100644
--- a/docs/config.rst
+++ b/docs/config.rst
@@ -463,6 +463,11 @@ Attestation settings
          [remote "spi"]
              b4-check-repo = https://git.kernel.org/pub/scm/linux/kernel/git/username/spi.git
 
+     For recognized HTTP(S) web hosts (currently git.kernel.org,
+     github.com, and gitlab.com), b4 also uses this URL to link commits in
+     the thank-you message. Other transports and hosting layouts can use
+     the per-remote ``b4-commit-url-mask`` described below.
+
      See :ref:`queuing thanks <thanks_queue>` for details.
 
      Default: ``None``
@@ -471,14 +476,29 @@ Attestation settings
      Used when creating summaries for ``b4 ty`` and the review TUI
      thank-you flow. Can be a value like::
 
-         thanks-commit-url-mask = https://git.kernel.org/username/c/%.12s
+         thanks-commit-url-mask = https://git.kernel.org/username/tree/c/%.12s
+
+     If no explicit mask or recognized check-repository URL is available,
+     b4 falls back to using commit hashes.
 
-     If not set, b4 falls back to using commit hashes.
+     For repositories with multiple remotes, an explicit per-remote mask
+     takes precedence over this setting::
 
-     When this option is set, the review TUI's thank-you preview offers
-     a **Queue** option that stores the message for delayed delivery.
-     Queued messages are held until their commit is verified published,
-     so you can push your commits before the thank-you is sent.
+         [remote "spi"]
+             b4-commit-url-mask = https://git.kernel.org/username/spi/c/%.12s
+
+     When no explicit per-remote mask is set, b4 automatically derives one
+     from that remote's ``b4-check-repo`` for recognized HTTP(S) web hosts.
+     The same derivation is attempted from :term:`b4.thanks-check-repo`, and
+     then from the URL of the remote the target branch tracks, when neither
+     a per-remote nor this global mask is available — the same repository
+     URLs, in the same order, that :term:`b4.thanks-check-repo` resolution
+     uses. A URL that is not a recognized web host is simply skipped.
+
+     When a commit URL can be generated, the review TUI's thank-you preview
+     offers a **Queue** option that stores the message for delayed delivery.
+     Queued messages are held until their commit is verified published, so
+     you can push your commits before the thank-you is sent.
      See :ref:`queuing thanks <thanks_queue>` for details.
 
      .. note::
diff --git a/docs/maintainer/review.rst b/docs/maintainer/review.rst
index 47aa8e7..842120b 100644
--- a/docs/maintainer/review.rst
+++ b/docs/maintainer/review.rst
@@ -1023,13 +1023,14 @@ screen shows the generated message with keybindings to **Send**
 
 **Queuing thanks for delayed delivery**
 
-When :term:`b4.thanks-commit-url-mask` is configured, the thank-you
-preview also offers a **Queue** option (``W``). Queuing writes the
-message as an RFC 2822 file in ``.git/b4-review/queue/`` instead of
-sending it immediately. This is useful when you want to push your
-commits to a public tree before sending thank-you messages — the
-message references commit URLs that may not resolve until the push is
-complete.
+When b4 can generate a web link for the commit — from
+:term:`b4.thanks-commit-url-mask`, a per-remote ``b4-commit-url-mask``, or
+a recognized HTTP(S) check-repository or remote URL — the thank-you preview
+also offers a **Queue** option (``W``). Queuing writes the message as an RFC 2822
+file in ``.git/b4-review/queue/`` instead of sending it immediately. This
+is useful when you want to push your commits to a public tree before
+sending thank-you messages — the message references commit URLs that may
+not resolve until the push is complete.
 
 Files are named ``{change-id}-v{revision}.msg`` and the check target is
 recorded as ``X-Check-URL``, ``X-Check-Commit``, ``X-Check-Repo`` and
diff --git a/src/b4/command.py b/src/b4/command.py
index 00c4c84..41bb9ae 100644
--- a/src/b4/command.py
+++ b/src/b4/command.py
@@ -249,6 +249,10 @@ def cmd_pr(cmdargs: argparse.Namespace) -> None:
 def cmd_ty(cmdargs: argparse.Namespace) -> None:
     import b4.ty
 
+    if cmdargs.gitdir:
+        # The initial setup happens relative to cwd. Reload repository-local
+        # thank-you settings when -g names a different tree.
+        b4.setup_config(cmdargs, topdir=cmdargs.gitdir)
     b4.ty.main(cmdargs)
 
 
diff --git a/src/b4/review_tui/_tracking_app.py b/src/b4/review_tui/_tracking_app.py
index 4c25f8c..0f39b8f 100644
--- a/src/b4/review_tui/_tracking_app.py
+++ b/src/b4/review_tui/_tracking_app.py
@@ -4926,8 +4926,8 @@ class TrackingApp(LoreNodeShutdownMixin, CheckRunnerMixin, App[Optional[str]]):
         # Compute checkurl from last taken commit for queue support
         checkurl: Optional[str] = None
         checkcommit: Optional[str] = None
-        cidmask = config.get('thanks-commit-url-mask')
-        if isinstance(cidmask, str) and cidmask and '%' in cidmask:
+        cidmask = b4.ty.get_commit_url_mask(topdir, target_branch)
+        if cidmask and '%' in cidmask:
             # Find the last commit ID (highest patch index with a commit)
             last_cid: Optional[str] = None
             for _idx, cid in commits:
diff --git a/src/b4/templates/thanks-am-template.example b/src/b4/templates/thanks-am-template.example
index b2c8986..bac889a 100644
--- a/src/b4/templates/thanks-am-template.example
+++ b/src/b4/templates/thanks-am-template.example
@@ -20,6 +20,9 @@ ${quote}
 #   url = https://...
 #   fetch = ...
 #   b4-treename = uname/sound.git
+#   b4-check-repo = https://git.kernel.org/pub/scm/linux/kernel/git/uname/sound.git
+# The check repo is also used to generate commit links for known web hosts.
+# For other hosts, or to choose a different link format, set an explicit mask:
 #   b4-commit-url-mask = https://git.kernel.org/uname/sound/c/%.8s
 Applied to ${branch}, thanks!
 
diff --git a/src/b4/templates/thanks-pr-template.example b/src/b4/templates/thanks-pr-template.example
index 13bd205..afae499 100644
--- a/src/b4/templates/thanks-pr-template.example
+++ b/src/b4/templates/thanks-pr-template.example
@@ -20,6 +20,9 @@ ${quote}
 #   url = https://...
 #   fetch = ...
 #   b4-treename = uname/sound.git
+#   b4-check-repo = https://git.kernel.org/pub/scm/linux/kernel/git/uname/sound.git
+# The check repo is also used to generate commit links for known web hosts.
+# For other hosts, or to choose a different link format, set an explicit mask:
 #   b4-commit-url-mask = https://git.kernel.org/uname/sound/c/%.8s
 Merged into ${branch}, thanks!
 
diff --git a/src/b4/ty.py b/src/b4/ty.py
index bbce149..9aca439 100644
--- a/src/b4/ty.py
+++ b/src/b4/ty.py
@@ -13,6 +13,7 @@ import json
 import os
 import re
 import sys
+import urllib.parse
 from email.message import EmailMessage
 from pathlib import Path
 from string import Template
@@ -61,8 +62,6 @@ ${signature}
 
 # Used to track commits created by current user
 MY_COMMITS: Optional[Dict[str, Tuple[str, str, List[str]]]] = None
-# Used to track additional branch info
-BRANCH_INFO: Optional[Dict[str, str]] = None
 
 
 def git_get_merge_id(
@@ -294,6 +293,87 @@ def auto_locate_series(
     return found
 
 
+def _derive_commit_url_mask(repo: str) -> Optional[str]:
+    """Return a commit URL mask for known web repository layouts."""
+    try:
+        parsed = urllib.parse.urlparse(repo.rstrip('/'))
+        hostname = parsed.hostname
+        has_credentials = parsed.username is not None or parsed.password is not None
+    except ValueError:
+        return None
+    if parsed.scheme not in ('http', 'https') or not hostname:
+        return None
+    if has_credentials or parsed.query or parsed.fragment:
+        return None
+
+    hostname = hostname.lower()
+    path = parsed.path.rstrip('/')
+    if hostname in ('github.com', 'www.github.com', 'gitlab.com', 'www.gitlab.com'):
+        path = re.sub(r'\.git$', '', path)
+    if hostname == 'git.kernel.org':
+        repo_parts = re.sub(r'\.git$', '', path).strip('/').split('/')
+        if len(repo_parts) < 2 or not all(repo_parts):
+            return None
+        short_path = f'/{repo_parts[-2]}/{repo_parts[-1]}'
+        base = urllib.parse.urlunparse(
+            (parsed.scheme, parsed.netloc, short_path, '', '', '')
+        ).replace('%', '%%')
+        return f'{base}/c/%.12s'
+    base = urllib.parse.urlunparse(
+        (parsed.scheme, parsed.netloc, path, '', '', '')
+    ).replace('%', '%%')
+    if hostname in ('github.com', 'www.github.com'):
+        return f'{base}/commit/%s'
+    if hostname in ('gitlab.com', 'www.gitlab.com'):
+        return f'{base}/-/commit/%s'
+    return None
+
+
+def _get_commit_url_mask(config: ConfigDictT, binfo: Dict[str, str]) -> Optional[str]:
+    """Resolve the commit URL mask for one branch's remote.
+
+    An explicit mask always wins, per-remote before global. Failing that
+    we derive one from the same repository URLs check-repo resolution
+    uses, in the same order: the per-remote b4-check-repo, the
+    b4.thanks-check-repo config option, then the branch's remote URL. A
+    URL we cannot derive a mask from does not end the search, so an
+    unrecognized check repo still gets a link if the remote URL is a host
+    we know. See get_check_repo_for_branch().
+    """
+    if 'b4-commit-url-mask' in binfo:
+        return binfo['b4-commit-url-mask'] or None
+
+    checkrepo = binfo.get('b4-check-repo')
+    if checkrepo:
+        cidmask = _derive_commit_url_mask(checkrepo)
+        if cidmask:
+            return cidmask
+
+    global_cidmask = config.get('thanks-commit-url-mask')
+    if global_cidmask:
+        assert isinstance(global_cidmask, str), (
+            'thanks-commit-url-mask must be a string'
+        )
+        return global_cidmask
+
+    global_checkrepo = config.get('thanks-check-repo')
+    if global_checkrepo:
+        assert isinstance(global_checkrepo, str), 'thanks-check-repo must be a string'
+        cidmask = _derive_commit_url_mask(global_checkrepo)
+        if cidmask:
+            return cidmask
+
+    remoteurl = binfo.get('url')
+    if remoteurl:
+        return _derive_commit_url_mask(remoteurl)
+    return None
+
+
+def get_commit_url_mask(gitdir: Optional[str], branch: str) -> Optional[str]:
+    """Return the effective commit URL mask for a branch."""
+    return _get_commit_url_mask(b4.get_main_config(), get_branch_info(gitdir, branch))
+
+
 def set_branch_details(
     gitdir: Optional[str], branch: str, jsondata: JsonDictT, config: ConfigDictT
 ) -> Tuple[JsonDictT, ConfigDictT]:
@@ -302,8 +382,6 @@ def set_branch_details(
     for key, val in binfo.items():
         if key == 'b4-treename':
             config['thanks-treename'] = val
-        elif key == 'b4-commit-url-mask':
-            config['thanks-commit-url-mask'] = val
         elif key == 'b4-pr-template':
             config['thanks-pr-template'] = val
         elif key == 'b4-am-template':
@@ -311,6 +389,8 @@ def set_branch_details(
         elif key == 'branch':
             jsondata['branch'] = val
 
+    config['thanks-commit-url-mask'] = _get_commit_url_mask(config, binfo)
+
     if 'thanks-treename' in config and isinstance(config['thanks-treename'], str):
         jsondata['treename'] = config['thanks-treename']
     elif 'url' in binfo:
@@ -330,7 +410,7 @@ def set_branch_details(
 def generate_pr_thanks(
     gitdir: Optional[str], jsondata: JsonDictT, branch: str, cmdargs: argparse.Namespace
 ) -> EmailMessage:
-    config = b4.get_main_config()
+    config = b4.get_main_config().copy()
     jsondata, config = set_branch_details(gitdir, branch, jsondata, config)
     thanks_template = DEFAULT_PR_TEMPLATE
     _ctpr = config.get('thanks-pr-template')
@@ -369,9 +449,7 @@ def generate_pr_thanks(
 def generate_am_thanks(
     gitdir: Optional[str], jsondata: JsonDictT, branch: str, cmdargs: argparse.Namespace
 ) -> EmailMessage:
-    global BRANCH_INFO
-    BRANCH_INFO = None
-    config = b4.get_main_config()
+    config = b4.get_main_config().copy()
     jsondata, config = set_branch_details(gitdir, branch, jsondata, config)
     thanks_template = DEFAULT_AM_TEMPLATE
     _ctat = config.get('thanks-am-template')
@@ -900,7 +978,6 @@ def check_stale_thanks(outdir: str) -> None:
 
 
 def get_wanted_branch(cmdargs: argparse.Namespace) -> str:
-    global BRANCH_INFO
     gitdir = cmdargs.gitdir
     if not cmdargs.branch:
         # Find out our current branch
@@ -995,7 +1072,7 @@ def _parse_checkurl(checkurl: str) -> Tuple[Optional[str], Optional[str]]:
     """Extract (repo_url, commit_id) from a thanks-commit-url-mask URL.
 
     The repo URL is only derivable from cgit/github/gitlab-style commit
-    URLs; for anything else (e.g. git.kernel.org /username/c/ shortlinks)
+    URLs; for anything else (e.g. git.kernel.org /username/tree/c/ shortlinks)
     we can usually still recover the commit id from a trailing hex run.
     Either element may be None.
     """
@@ -1037,10 +1114,6 @@ def get_check_repo_for_branch(
     3. the branch's remote URL
     4. a repo URL derived from the commit check URL
     """
-    # Long-lived callers (the TUI) thank series on different branches;
-    # never serve another branch's cached remote info
-    global BRANCH_INFO
-    BRANCH_INFO = None
     binfo = get_branch_info(gitdir, branch)
     crepo = binfo.get('b4-check-repo')
     if crepo:
@@ -1568,20 +1641,18 @@ def _process_queue_locked(
 
 
 def get_branch_info(gitdir: Optional[str], branch: str) -> Dict[str, str]:
-    global BRANCH_INFO
-    if BRANCH_INFO is not None:
-        return BRANCH_INFO
+    branch_info: Dict[str, str] = dict()
 
-    BRANCH_INFO = dict()
-
-    remotecfg = b4.get_config_from_git('branch\\.%s\\..*' % branch)
+    remotecfg = b4.get_config_from_git(
+        r'^branch\.%s\.' % re.escape(branch), gitdir=gitdir
+    )
     if 'remote' not in remotecfg:
         # Did not find a matching branch entry, so look at remotes
         gitargs = ['remote', 'show']
         lines = b4.git_get_command_lines(gitdir, gitargs)
         if not len(lines):
             # No remotes? Hmm...
-            return BRANCH_INFO
+            return branch_info
 
         remote = None
         for entry in lines:
@@ -1591,21 +1662,23 @@ def get_branch_info(gitdir: Optional[str], branch: str) -> Dict[str, str]:
 
         if remote is None:
             # Not found any matching remotes
-            return BRANCH_INFO
+            return branch_info
 
-        BRANCH_INFO['remote'] = remote
-        BRANCH_INFO['branch'] = branch.replace(f'{remote}/', '')
+        branch_info['remote'] = remote
+        branch_info['branch'] = branch.replace(f'{remote}/', '')
 
     else:
-        BRANCH_INFO['remote'] = remotecfg['remote']
+        branch_info['remote'] = remotecfg['remote']
         if 'merge' in remotecfg:
-            BRANCH_INFO['branch'] = re.sub(r'^refs/heads/', '', remotecfg['merge'])
+            branch_info['branch'] = re.sub(r'^refs/heads/', '', remotecfg['merge'])
 
     # Grab template overrides
-    remotecfg = b4.get_config_from_git('remote\\.%s\\..*' % BRANCH_INFO['remote'])
-    BRANCH_INFO.update(remotecfg)
+    remotecfg = b4.get_config_from_git(
+        r'^remote\.%s\.' % re.escape(branch_info['remote']), gitdir=gitdir
+    )
+    branch_info.update(remotecfg)
 
-    return BRANCH_INFO
+    return branch_info
 
 
 def main(cmdargs: argparse.Namespace) -> None:
diff --git a/src/tests/test_tui_tracking.py b/src/tests/test_tui_tracking.py
index e3d79ef..1e064cf 100644
--- a/src/tests/test_tui_tracking.py
+++ b/src/tests/test_tui_tracking.py
@@ -2931,6 +2931,51 @@ class TestSeriesLifecycle:
         # Only the two taken patches contribute commits (by 1-based index).
         assert jsondata['commits'] == [(1, 'aaa111'), (2, 'bbb222')]
 
+    def test_thank_preview_uses_branch_check_repo_url(self, gitdir: str) -> None:
+        """The queue target uses the same per-remote URL as the message."""
+        from unittest import mock
+
+        checkrepo = 'https://git.kernel.org/pub/scm/linux/kernel/git/example/spi.git'
+        b4.git_set_config(gitdir, 'branch.for-next.remote', 'spi')
+        b4.git_set_config(gitdir, 'branch.for-next.merge', 'refs/heads/for-next')
+        b4.git_set_config(gitdir, 'remote.spi.b4-check-repo', checkrepo)
+        commit = '0123456789abcdef0123456789abcdef01234567'
+        tracking_data: Dict[str, Any] = {
+            'series': {
+                'header-info': {},
+                'taken': {'branch': 'for-next'},
+                'expected': 1,
+            },
+            'patches': [
+                {
+                    'title': '[PATCH] test patch',
+                    'header-info': {'msgid': 'patch@example.com'},
+                    'taken': {'commit-id': commit},
+                }
+            ],
+        }
+        series = {'change_id': 'test-change-id'}
+        app = mock.Mock()
+        generated = email.message.EmailMessage()
+
+        with (
+            patch('b4.git_get_toplevel', return_value=gitdir),
+            patch('b4.review.load_tracking', return_value=('cover', tracking_data)),
+            patch('b4.ty.generate_am_thanks', return_value=generated),
+            patch('b4.get_email_signature', return_value='Test'),
+        ):
+            TrackingApp._start_thank(app, series)
+
+        app._show_thank_preview.assert_called_once_with(
+            generated,
+            series,
+            checkurl=f'https://git.kernel.org/example/spi/c/{commit[:12]}',
+            checkcommit=commit,
+            archive_after=False,
+            checkrepo=checkrepo,
+            checkbranch='for-next',
+        )
+
     def test_partial_series_ingests_new_revision(self, gitdir: str) -> None:
         """A 'partial' series must ingest an incoming v2 and record it.
 
diff --git a/src/tests/test_ty.py b/src/tests/test_ty.py
index be132ff..50ec18b 100644
--- a/src/tests/test_ty.py
+++ b/src/tests/test_ty.py
@@ -7,6 +7,7 @@ from unittest import mock
 import pytest
 
 import b4
+import b4.command
 import b4.ty
 
 
@@ -62,6 +63,20 @@ def test_render_ty_review_layout() -> None:
     assert b4.ty.parse_ty_review(buf, sections) == set()
 
 
+def test_cmd_ty_reloads_config_for_gitdir(monkeypatch: pytest.MonkeyPatch) -> None:
+    """-g makes repository-local thank-you settings come from that tree."""
+    cmdargs = mock.Mock(gitdir='/other/repo')
+    setup_config = mock.Mock()
+    ty_main = mock.Mock()
+    monkeypatch.setattr(b4, 'setup_config', setup_config)
+    monkeypatch.setattr(b4.ty, 'main', ty_main)
+
+    b4.command.cmd_ty(cmdargs)
+
+    setup_config.assert_called_once_with(cmdargs, topdir='/other/repo')
+    ty_main.assert_called_once_with(cmdargs)
+
+
 def test_parse_ty_review_marks_skips() -> None:
     """Flipping '+' to 'x' on an item marks it (by position) skipped."""
     sections = _review_sections()
@@ -436,6 +451,79 @@ def test_commit_reachable_uses_the_gitdir_it_is_given(
     )
 
 
+@pytest.mark.parametrize(
+    'repo,mask',
+    [
+        (
+            'https://git.kernel.org/pub/scm/linux/kernel/git/example/spi.git',
+            'https://git.kernel.org/example/spi/c/%.12s',
+        ),
+        ('https://github.com/user/repo.git', 'https://github.com/user/repo/commit/%s'),
+        (
+            'https://gitlab.com/group/repo.git',
+            'https://gitlab.com/group/repo/-/commit/%s',
+        ),
+        # Unrecognized host, and transports we cannot map to a web view
+        ('https://example.com/spi.git', None),
+        ('git://git.kernel.org/pub/scm/linux/kernel/git/example/spi.git', None),
+        ('git@github.com:user/repo.git', None),
+    ],
+)
+def test_derive_commit_url_mask(repo: str, mask: Optional[str]) -> None:
+    assert b4.ty._derive_commit_url_mask(repo) == mask
+
+
+def test_get_commit_url_mask_priority(monkeypatch: pytest.MonkeyPatch) -> None:
+    """Mask resolution: explicit per-remote mask, then derivation from the
+    per-remote b4-check-repo, then the global mask, then derivation from
+    b4.thanks-check-repo and finally from the branch's remote URL."""
+    binfo = {'url': 'https://github.com/user/repo.git'}
+
+    # Nothing configured: the branch's remote URL is the last resort
+    assert (
+        b4.ty._get_commit_url_mask(b4.MAIN_CONFIG, binfo)
+        == 'https://github.com/user/repo/commit/%s'
+    )
+    # A check repo we cannot derive from does not stop the search
+    monkeypatch.setitem(
+        b4.MAIN_CONFIG, 'thanks-check-repo', 'https://example.com/r.git'
+    )
+    assert (
+        b4.ty._get_commit_url_mask(b4.MAIN_CONFIG, binfo)
+        == 'https://github.com/user/repo/commit/%s'
+    )
+    # b4.thanks-check-repo beats the remote URL
+    monkeypatch.setitem(
+        b4.MAIN_CONFIG, 'thanks-check-repo', 'https://gitlab.com/group/repo.git'
+    )
+    assert (
+        b4.ty._get_commit_url_mask(b4.MAIN_CONFIG, binfo)
+        == 'https://gitlab.com/group/repo/-/commit/%s'
+    )
+    # The global mask beats anything derived from a check repo
+    monkeypatch.setitem(
+        b4.MAIN_CONFIG, 'thanks-commit-url-mask', 'https://example.com/c/%.8s'
+    )
+    assert (
+        b4.ty._get_commit_url_mask(b4.MAIN_CONFIG, binfo)
+        == 'https://example.com/c/%.8s'
+    )
+    # remote.<name>.b4-check-repo beats the global mask
+    binfo['b4-check-repo'] = (
+        'https://git.kernel.org/pub/scm/linux/kernel/git/example/spi.git'
+    )
+    assert (
+        b4.ty._get_commit_url_mask(b4.MAIN_CONFIG, binfo)
+        == 'https://git.kernel.org/example/spi/c/%.12s'
+    )
+    # ... and an explicit per-remote mask beats everything
+    binfo['b4-commit-url-mask'] = 'https://example.com/spi/c/%.10s'
+    assert (
+        b4.ty._get_commit_url_mask(b4.MAIN_CONFIG, binfo)
+        == 'https://example.com/spi/c/%.10s'
+    )
+
+
 def test_get_check_repo_for_branch_priority(
     monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path
 ) -> None:
-- 
2.47.3


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-09-12 10:58 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-12 10:58 [PATCH v2] review: Generate thanks commit URLs for known repositories automatically Mark Brown

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.