public inbox for tools@linux.kernel.org
 help / color / mirror / Atom feed
From: Conor Dooley <conor@kernel.org>
To: Konstantin Ryabitsev <mricon@kernel.org>
Cc: users@kernel.org, tools@kernel.org
Subject: Re: b4 review available in master
Date: Sat, 28 Feb 2026 16:36:07 +0000	[thread overview]
Message-ID: <20260228-battered-numerous-35e130c73b93@spud> (raw)
In-Reply-To: <20260227-imported-aromatic-guppy-ad3dca@lemur>

[-- Attachment #1: Type: text/plain, Size: 28691 bytes --]

On Fri, Feb 27, 2026 at 02:53:07PM -0500, Konstantin Ryabitsev wrote:
> Hi, all:
> 
> TLDR: "b4 review" is a terminal UI that hopes to streamline a lot of
> maintainer duties. A getting-started guide with screencasts is here:
> https://b4.docs.kernel.org/en/latest/reviewer/getting-started.html
> 
> It's available from b4 master pending initial testing and will be generally
> available in b4-0.15.
> 
> Longread:
> 
> I've been working on "b4 review" for a while, with a few false-starts, a lot
> of despair, and then a whole new direction that seemed to have finally worked.
> So, the usual. :)
> 
> I am finally feeling confident enough to release the code as initial
> technology preview, with the primary goal to get some direct feedback. The
> goal of the UI was to work alongside your usual email client, allowing you to
> use it for as much or as little as you like.
> 
> The feature only exists in b4 master branch, so if you want to try it, you'll
> need to be comfortable running b4 from checkout. It also requires having a
> valid email server configured with git for sending outgoing mail. If you're
> already using "b4 ty" then you're good to go.
> 
> The only new dependency introduced is python-textual. I say this with a bit of
> tongue-in-cheek, because textual pulls in a ton of other dependencies, but
> it's usually already installed on many modern distros anyway.
> 
> You can do the following things:
> 
>   - Track incoming patch series from lore using a message-id, URL, change-id,
>     or by piping a message from your mail client (e.g. via mutt integration)
>   - TUI-based tracking list with series lifecycle management (new, reviewing,
>     replied, taken, thanked, archived, waiting)
>   - Split-pane review interface with patch list and syntax-highlighted diff view
>   - Quick trailer addition (Reviewed-by, Acked-by, Tested-by) with a single
>     keypress
>   - Inline diff commenting via $EDITOR — comments are automatically formatted
>     as proper quoted-reply emails for the mailing list
>   - Preview emails to inspect exactly what will be sent before sending
>   - Fetch and display follow-up messages from other reviewers directly in the
>     diff view
>   - Range-diff between series revisions without leaving the TUI
>   - Automatic discovery of older and newer revisions when tracking a series
>   - Revision upgrade that preserves your review comments on unchanged patches
>   - Three merge strategies for applying series: merge commit, linear (git-am),
>     and cherry-pick
>   - Thank-you note generation listing each applied commit with its hash (and
>     more reliably than b4 ty, since we keep track of applied series instead of
>     guessing)
>   - AI-assisted review using an external agent (Claude Code, Gemini CLI,
>     OpenAI Codex CLI, GitHub Copilot CLI) — agent findings are private to the
>     maintainer and can then be selectively incorporated into the review

>   - Patchwork integration: browse series, view CI check results, track series
>     directly from Patchwork, and automatically synchronise Patchwork state as
>     you work

This patchwork part is neat, this is definitely something that I'll play
with. Patchwork is great, but I really dislike all the jumping back and
forth between editor/website/mailer. One thing that immediately seemed like
it'd be neat is a shortcut from the patchwork pane that does track + review.

Worktree support is something I didn't expect to exist, but it does that
that's real helpful ;)

Also, I attempted to open patchwork while my b4.pw-project was set to
"devicetree" and got an error:
MarkupError: Expected markup style value (found '1/1] dt-bindings: net: can: nxp,sja1000: add reference to fsl,imx-weim-peripherals.yaml').
There's some massive splat I can send you if this does not reproduce.

I wanted to look into whether or not I could quickly reply to stuff from
the tui (since like 80% of binding patches don't require a checkout) and
encountered this smaller reproduction of the same thing.

$ /stuff/b4/b4.sh review track -i linux-dt D8CE6E5B1001D797+a6f36da0272ac18fff2a992976b1defc3bb01af6.1772289741.git.lv.zheng@linux.spacemit.com
< snip >
$ /stuff/b4/b4.sh review tui -i linux-dt
Retrieving series: 52E07C3A9B398459+126b1f464ae2a8bfcca6f504c64346541ae4db6f.1772289741.git.lv.zheng@linux.spacemit.com
Looking up https://lore.kernel.org/all/52E07C3A9B398459%2B126b1f464ae2a8bfcca6f504c64346541ae4db6f.1772289741.git.lv.zheng@linux.spacemit.com/
Grabbing thread from lore.kernel.org/all/52E07C3A9B398459%2B126b1f464ae2a8bfcca6f504c64346541ae4db6f.1772289741.git.lv.zheng@linux.spacemit.com/t.mbox.gz
Checking attestation on all messages, may take a moment...
---
  ✓ [PATCH v5 1/8] iommu/riscv: Enable IOMMU DMA mapping support
  ✓ [PATCH v5 2/8] iommu/riscv: Add auxiliary bus framework and HPM device support
  ✓ [PATCH v5 3/8] iommu/riscv: Add HPM support for performance monitoring
  ✓ [PATCH v5 4/8] dt-bindings: iommu: Add spacemit/t100 features
  ✓ [PATCH v5 5/8] spacemit/t100: Add global filter awareness for RISC-V IOMMU HPM
  ✓ [PATCH v5 6/8] iommu/riscv: Add SpacemiT T100 IOATC HPM support
  ✓ [PATCH v5 7/8] iommu/riscv: Add vendor event support for RISC-V IOMMU HPM
  ✓ [PATCH v5 8/8] perf vendor events riscv: Add SpacemiT T100 HPM event aliases
  ---
  ✓ Signed: DKIM/linux.spacemit.com
Guessing base commit...
Base: tags/next-20260227 (best guess, 9/11 blobs matched)
Base: tags/next-20260227
Magic: Preparing a sparse worktree
---
Applying: iommu/riscv: Enable IOMMU DMA mapping support
Applying: iommu/riscv: Add auxiliary bus framework and HPM device support
Applying: iommu/riscv: Add HPM support for performance monitoring
Applying: dt-bindings: iommu: Add spacemit/t100 features
Applying: spacemit/t100: Add global filter awareness for RISC-V IOMMU HPM
Applying: iommu/riscv: Add SpacemiT T100 IOATC HPM support
Applying: iommu/riscv: Add vendor event support for RISC-V IOMMU HPM
Applying: perf vendor events riscv: Add SpacemiT T100 HPM event aliases
---
Fetching into FETCH_HEAD
Review branch b4/review/20260228-iommu-riscv-enable-iommu-dma-mapping-support-feee43387d2a created successfully
Review branch created: b4/review/20260228-iommu-riscv-enable-iommu-dma-mapping-support-feee43387d2a
Checking out branch and starting review UI...
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── Traceback (most recent call last) ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ /stuff/b4/src/b4/review_tui/_review_app.py:219 in on_mount                                                                                                                                                                                                                             │
│                                                                                                                                                                                                                                                                                        │
│    216 │                                                                                        ╭─────────────────────────────────────────── locals ────────────────────────────────────────────╮                                                                                      │
│    217 │   def on_mount(self) -> None:                                                          │ self = ReviewApp(title='b4 review', classes={'-dark-mode'}, pseudo_classes={'focus', 'dark'}) │                                                                                      │
│    218 │   │   self._refresh_newer_warning()                                                    ╰───────────────────────────────────────────────────────────────────────────────────────────────╯                                                                                      │
│ ❱  219 │   │   self._refresh_title_bar()                                                                                                                                                                                                                                               │
│    220 │   │   self._populate_patch_list()                                                                                                                                                                                                                                             │
│    221 │   │   self._show_content(self._selected_idx)                                                                                                                                                                                                                                  │
│    222                                                                                                                                                                                                                                                                                 │
│                                                                                                                                                                                                                                                                                        │
│ /stuff/b4/src/b4/review_tui/_review_app.py:235 in _refresh_title_bar                                                                                                                                                                                                                   │
│                                                                                                                                                                                                                                                                                        │
│    232 │   │   else:                                                                            ╭───────────────────────────────────────────── locals ─────────────────────────────────────────────╮                                                                                   │
│    233 │   │   │   label = f' \u270e {subject}'                                                 │     bar = Static(id='title-bar')                                                                 │                                                                                   │
│    234 │   │   │   bar.styles.background = self.get_css_variables()['primary-darken-2']         │   label = ' ✎ [PATCH v5 1/8] iommu/riscv: Enable IOMMU DMA mapping support'                      │                                                                                   │
│ ❱  235 │   │   bar.update(label)                                                                │    self = ReviewApp(title='b4 review', classes={'-dark-mode'}, pseudo_classes={'focus', 'dark'}) │                                                                                   │
│    236 │                                                                                        │ subject = '[PATCH v5 1/8] iommu/riscv: Enable IOMMU DMA mapping support'                         │                                                                                   │
│    237 │   def _refresh_newer_warning(self) -> None:                                            ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯                                                                                   │
│    238 │   │   """Show or hide the newer-version warning bar based on tracking data."""                                                                                                                                                                                                │
│                                                                                                                                                                                                                                                                                        │
│ /usr/lib/python3/dist-packages/textual/widgets/_static.py:106 in update                                                                                                                                                                                                                │
│                                                                                                                                                                                                                                                                                        │
│   103 │   │   """                                                                              ╭────────────────────────────────── locals ───────────────────────────────────╮                                                                                                         │
│   104 │   │                                                                                    │ content = ' ✎ [PATCH v5 1/8] iommu/riscv: Enable IOMMU DMA mapping support' │                                                                                                         │
│   105 │   │   self._content = content                                                          │    self = Static(id='title-bar')                                            │                                                                                                         │
│ ❱ 106 │   │   self._visual = visualize(self, content, markup=self._render_markup)              ╰─────────────────────────────────────────────────────────────────────────────╯                                                                                                         │
│   107 │   │   self.refresh(layout=True)                                                                                                                                                                                                                                                │
│   108                                                                                                                                                                                                                                                                                  │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
MarkupError: Expected markup style value (found '1/8] iommu/riscv: Enable IOMMU DMA mapping support').

NOTE: 1 of 2 errors shown. Run with textual run --dev to see all errors.
Checking out branch and starting review UI...
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── Traceback (most recent call last) ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ /stuff/b4/src/b4/review_tui/_review_app.py:219 in on_mount                                                                                                                                                                                                                             │
│                                                                                                                                                                                                                                                                                        │
│    216 │                                                                                        ╭─────────────────────────────────────────── locals ────────────────────────────────────────────╮                                                                                      │
│    217 │   def on_mount(self) -> None:                                                          │ self = ReviewApp(title='b4 review', classes={'-dark-mode'}, pseudo_classes={'focus', 'dark'}) │                                                                                      │
│    218 │   │   self._refresh_newer_warning()                                                    ╰───────────────────────────────────────────────────────────────────────────────────────────────╯                                                                                      │
│ ❱  219 │   │   self._refresh_title_bar()                                                                                                                                                                                                                                               │
│    220 │   │   self._populate_patch_list()                                                                                                                                                                                                                                             │
│    221 │   │   self._show_content(self._selected_idx)                                                                                                                                                                                                                                  │
│    222                                                                                                                                                                                                                                                                                 │
│                                                                                                                                                                                                                                                                                        │
│ /stuff/b4/src/b4/review_tui/_review_app.py:235 in _refresh_title_bar                                                                                                                                                                                                                   │
│                                                                                                                                                                                                                                                                                        │
│    232 │   │   else:                                                                            ╭───────────────────────────────────────────── locals ─────────────────────────────────────────────╮                                                                                   │
│    233 │   │   │   label = f' \u270e {subject}'                                                 │     bar = Static(id='title-bar')                                                                 │                                                                                   │
│    234 │   │   │   bar.styles.background = self.get_css_variables()['primary-darken-2']         │   label = ' ✎ [PATCH v5 1/8] iommu/riscv: Enable IOMMU DMA mapping support'                      │                                                                                   │
│ ❱  235 │   │   bar.update(label)                                                                │    self = ReviewApp(title='b4 review', classes={'-dark-mode'}, pseudo_classes={'focus', 'dark'}) │                                                                                   │
│    236 │                                                                                        │ subject = '[PATCH v5 1/8] iommu/riscv: Enable IOMMU DMA mapping support'                         │                                                                                   │
│    237 │   def _refresh_newer_warning(self) -> None:                                            ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯                                                                                   │
│    238 │   │   """Show or hide the newer-version warning bar based on tracking data."""                                                                                                                                                                                                │
│                                                                                                                                                                                                                                                                                        │
│ /usr/lib/python3/dist-packages/textual/widgets/_static.py:106 in update                                                                                                                                                                                                                │
│                                                                                                                                                                                                                                                                                        │
│   103 │   │   """                                                                              ╭────────────────────────────────── locals ───────────────────────────────────╮                                                                                                         │
│   104 │   │                                                                                    │ content = ' ✎ [PATCH v5 1/8] iommu/riscv: Enable IOMMU DMA mapping support' │                                                                                                         │
│   105 │   │   self._content = content                                                          │    self = Static(id='title-bar')                                            │                                                                                                         │
│ ❱ 106 │   │   self._visual = visualize(self, content, markup=self._render_markup)              ╰─────────────────────────────────────────────────────────────────────────────╯                                                                                                         │
│   107 │   │   self.refresh(layout=True)                                                                                                                                                                                                                                                │
│   108                                                                                                                                                                                                                                                                                  │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
MarkupError: Expected markup style value (found '1/8] iommu/riscv: Enable IOMMU DMA mapping support').

NOTE: 1 of 2 errors shown. Run with textual run --dev to see all errors

This seems promising though, could definitely see this making my life
easier, with less hoping between patchwork/mutt/git repo.

Cheers,
Conor.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

  parent reply	other threads:[~2026-02-28 16:36 UTC|newest]

Thread overview: 69+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-27 19:53 b4 review available in master Konstantin Ryabitsev
2026-02-28 15:12 ` Mark Brown
2026-02-28 15:47   ` Konstantin Ryabitsev
2026-02-28 16:00     ` Konstantin Ryabitsev
2026-02-28 18:12       ` Mark Brown
2026-02-28 15:53 ` Mark Brown
2026-02-28 21:11   ` Mark Brown
2026-03-03  5:14     ` Konstantin Ryabitsev
2026-03-03 12:42       ` Mark Brown
2026-03-03 18:21         ` Konstantin Ryabitsev
2026-03-12 17:21           ` Alexandre Belloni
2026-03-13 15:42             ` Konstantin Ryabitsev
2026-03-13 15:55               ` Alexandre Belloni
2026-03-21 10:01                 ` Alexandre Belloni
2026-03-12 17:35           ` Mark Brown
2026-03-13 15:42             ` Konstantin Ryabitsev
2026-02-28 16:36 ` Conor Dooley [this message]
2026-02-28 16:45   ` Konstantin Ryabitsev
2026-02-28 16:48     ` Conor Dooley
2026-02-28 16:57       ` Konstantin Ryabitsev
2026-02-28 17:00         ` Conor Dooley
2026-02-28 17:05           ` Konstantin Ryabitsev
2026-02-28 17:12             ` Conor Dooley
2026-02-28 17:21               ` Konstantin Ryabitsev
2026-02-28 17:34                 ` Konstantin Ryabitsev
2026-02-28 18:37                   ` Conor Dooley
2026-02-28 22:16                   ` Conor Dooley
2026-02-28 22:32                     ` Conor Dooley
2026-03-03  5:16                       ` Konstantin Ryabitsev
2026-03-04 21:38                         ` Conor Dooley
2026-03-04 22:40                           ` Konstantin Ryabitsev
2026-03-04 22:55                             ` Conor Dooley
2026-03-05  3:26                               ` Konstantin Ryabitsev
2026-03-05  6:17                             ` Konstantin Ryabitsev
2026-02-28 18:31 ` Michael S. Tsirkin
2026-02-28 20:06   ` Konstantin Ryabitsev
2026-02-28 20:23     ` Michael S. Tsirkin
2026-02-28 20:37       ` Konstantin Ryabitsev
2026-02-28 20:47         ` Michael S. Tsirkin
2026-02-28 20:53           ` Konstantin Ryabitsev
2026-02-28 21:04             ` Michael S. Tsirkin
2026-03-02  9:30 ` Michael S. Tsirkin
2026-03-02 10:33 ` Michael S. Tsirkin
2026-03-03  1:58 ` Junio C Hamano
2026-03-03  4:26   ` Konstantin Ryabitsev
2026-03-03 11:20     ` Matthieu Baerts
2026-03-04 20:56 ` range-diff hangs Marc Kleine-Budde
2026-03-14  4:20   ` Konstantin Ryabitsev
2026-03-14  9:27     ` Marc Kleine-Budde
2026-03-16 23:28 ` b4 review available in master Jonathan Corbet
2026-03-16 23:41   ` Jonathan Corbet
2026-03-17  0:15     ` Konstantin Ryabitsev
2026-03-17 14:11       ` Jonathan Corbet
2026-03-17 14:23         ` Konstantin Ryabitsev
2026-03-17 20:30           ` Konstantin Ryabitsev
2026-03-17 21:46             ` Jonathan Corbet
2026-03-17 22:39               ` Konstantin Ryabitsev
2026-03-17 23:37                 ` Konstantin Ryabitsev
2026-03-18  7:56                   ` Geert Uytterhoeven
2026-03-18 13:00                     ` Mark Brown
2026-03-18 13:26                     ` Konstantin Ryabitsev
2026-03-18 16:47                   ` Jonathan Corbet
2026-03-18 18:31                     ` Laurent Pinchart
2026-03-18 19:22                     ` Konstantin Ryabitsev
2026-03-17  0:12   ` Konstantin Ryabitsev
2026-03-18 13:43   ` Johannes Thumshirn
2026-03-20 16:53 ` Louis Chauvet
2026-03-20 19:31   ` Konstantin Ryabitsev
2026-03-20 21:14     ` Alexandre Belloni

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260228-battered-numerous-35e130c73b93@spud \
    --to=conor@kernel.org \
    --cc=mricon@kernel.org \
    --cc=tools@kernel.org \
    --cc=users@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox