Skip to content

fix(context_chips): refresh branch dropdown when initially empty#123

Merged
zerx-lab merged 2 commits into
mainfrom
fix/branch-chip-dropdown-empty
May 20, 2026
Merged

fix(context_chips): refresh branch dropdown when initially empty#123
zerx-lab merged 2 commits into
mainfrom
fix/branch-chip-dropdown-empty

Conversation

@zerx-lab
Copy link
Copy Markdown
Owner

问题

终端输入框上方 ShellGitBranch chip 点开后的 "Search branches..." 菜单永远是空的,即使本地 git 仓库有多个分支、底栏的当前分支徽章也正常显示。

复现:

  1. 在任意一个有 ≥2 个本地分支的 git 仓库里打开 Warp。
  2. 在终端输入区点开 git 分支 chip 的 dropdown(截图里的 "Search branches..." 输入框)。
  3. 列表为空。

跑过命令、cd 切目录都不能让列表出现——一直是空。

根因

app/src/context_chips/current_prompt.rsset_git_repo_statusMetadataChanged handler 把 dropdown 刷新(refresh_on_click_values耦合在了「当前分支名变化」这个条件里:

if current_branch.as_ref() != Some(&new_branch) {
    me.update_chip_value(...);
    me.refresh_on_click_values(...);   // ← 仅在分支名变化时才跑
}

一旦文件系统 watcher(GitRepoStatusModel)接管 ShellGitBranch 的更新源(is_updated_externally(ShellGitBranch) 返回 true 后),fetch_chip_value_at_interval 的 30s 定期 timer 就不会启动(见 current_prompt.rs:1042-1077),整个生命周期里只有 MetadataChanged 路径会刷新 chip。如果用户不切分支MetadataChanged 事件因为分支名等值始终命中 true永远不会触发 dropdown 刷新。

又因为 refresh_on_click_values 有两个静默早退路径(current_prompt.rs:889-895 availability 未 ready / 898-900 session 未就绪),首次 run_chips 时触发的初始填充可能在 session 还没就绪时就早退了——结果是 dropdown 永远填不上。

修复

把 dropdown 刷新从分支名等值检查中解耦。新条件:分支名变化 OR last_on_click_valuesNone(dropdown 从未被填充过)。

let branch_changed = current_branch.as_ref() != Some(&new_branch);
if branch_changed {
    me.update_chip_value(...);
}
let dropdown_empty = me.states.get(&ContextChipKind::ShellGitBranch)
    .is_some_and(|state| state.last_on_click_values.is_none());
if branch_changed || dropdown_empty {
    me.refresh_on_click_values(...);
}

这同时解决了三个关联问题:

  1. 主 bug:dropdown 不再仅在分支切换时刷新。
  2. session 抢跑:如果初始 refresh_on_click_values 在 session 就绪前早退,下一次 MetadataChanged 会补救(即使分支名没变)。
  3. availability 抢跑:同上,availability 未 ready 时早退的也能在后续被补救。

并且没有引入文件保存洪水last_on_click_values.is_none() 这个 guard 保证一旦 dropdown 填上,后续同分支的 MetadataChanged(比如每 5s 节流的文件保存事件)不会重跑 git branch

测试

新增 test_branch_dropdown_refreshes_when_initially_empty,端到端用 RecordingCommandExecutor 验证:

  1. 正向:手动把 last_on_click_values 清成 None(模拟"首次 refresh 早退"的场景),触发同名分支的 MetadataChanged,断言 git --no-optional-locks branch ... 真的通过 session 跑了,并且 last_on_click_values 被填上了 main + feature-a 等。
  2. 反向(防文件保存洪水):dropdown 填上之后再触发一次同名分支的 MetadataChanged,断言 不会再跑 git branch

测试覆盖了修复 OR 条件的两个分支。

相关附带改动

app/src/autoupdate/linux_test.rs 引用了在 4e3853f("Remove OpenWarp upstream release update paths")中被删除的 repo_name 函数,导致 cargo test -p warp 编译失败、阻塞任何新测试的运行。我作为独立 commit 删掉了这个 orphan test,commit message 中明示了原因。这是解锁性的必要修复,不是 drive-by 重构。

验证

  • cargo check -p warp 通过。
  • cargo check -p warp --tests 通过。
  • cargo test -p warp --lib context_chips::current_prompt 全部 16/16 通过(包括新加测试)。
  • 全量 cargo test -p warp --lib 中有 ~150 个失败,但与本 PR 无关——我验证过这些失败(如 terminal::view::tests::test_prompt_context_menu_items_*AgentProviderSecrets 注册)在 main 上同样存在,且不属于 context_chips 模块。

文件改动

  • app/src/context_chips/current_prompt.rs (+27 / -2)
  • app/src/context_chips/current_prompt_test.rs (+227)
  • app/src/autoupdate/linux.rs (-3)
  • app/src/autoupdate/linux_test.rs (-7, 删除)

zerx-lab added 2 commits May 20, 2026 15:23
`linux_test.rs` references a `repo_name` function that was removed in
4e3853f ("Remove OpenWarp upstream release update paths"), so
`cargo test -p warp` has been failing to compile for any new test
work that touches this crate.

Removing the dead test file (and its `mod tests` declaration) unblocks
the test suite. The test it covered (repo_name string mapping) no longer
applies because `repo_name` itself is gone.
The branch-selector dropdown opened from the `ShellGitBranch` prompt
chip (the "Search branches..." menu) was permanently empty for users
sitting on a single branch (e.g. `main`), even though local git had
many branches and the chip badge showed the current branch correctly.

Root cause: once the filesystem watcher (`GitRepoStatusModel`) takes
over chip updates (`is_updated_externally(ShellGitBranch)` returns
`true`), the 30s periodic timer in `fetch_chip_value_at_interval`
is suppressed, so the `MetadataChanged` handler in
`set_git_repo_status` is the only place that can refresh the dropdown
in steady state. That handler gated the dropdown refresh on the
current branch name actually changing — so a user who never switched
branches would never see the dropdown populated if the initial
population attempt during `run_chips` / `fetch_chip_value_once`
early-returned (because the session wasn't ready yet and
`prepare_shell_command_context` returned `None`, or because chip
availability hadn't transitioned to `Enabled` yet).

Fix: decouple the dropdown refresh from the branch-name equality
check. Always refresh when the branch name changed, OR when
`last_on_click_values` is `None` (the dropdown has never been
populated). This re-attempts the fetch on later metadata events while
avoiding a `git branch` invocation on every file-save event once the
dropdown is populated — important because `MetadataChanged` fires on
every non-ignored file change (throttled to ~5s by
`GitStatusUpdateModel`).

Adds `test_branch_dropdown_refreshes_when_initially_empty` which
wires up `RecordingCommandExecutor` end-to-end: forces the empty-
dropdown precondition by clearing `last_on_click_values`, fires a
same-branch `MetadataChanged`, awaits the on-click future, and
asserts both that `git --no-optional-locks branch` was executed
through the session and that the dropdown is populated afterwards.
Also asserts the inverse anti-regression: once the dropdown is
populated, a subsequent same-branch `MetadataChanged` must NOT spawn
another `git branch` invocation.
@zerx-lab zerx-lab merged commit 445a245 into main May 20, 2026
1 check passed
@zerx-lab zerx-lab deleted the fix/branch-chip-dropdown-empty branch May 20, 2026 07:34
zerx-lab added a commit that referenced this pull request May 20, 2026
…n-empty"

This reverts commit 445a245, reversing
changes made to 6b83612.

撤销原因:PR #123 修复未生效。事后排查发现真根因在 terminal/view.rs 的
`should_subscribe_to_git_status` 上 —— 该函数要求 `GitDiffStats` chip 在
prompt 配置里才订阅 `GitRepoStatusModel`,导致 `MetadataChanged` 事件链路
在很多场景下根本不建立,PR #123 修改的 `MetadataChanged` handler 永远进
不去。该 PR 改的另一面(autoupdate/linux_test.rs 孤儿测试清理)随之
回退,如需保留请单独 cherry-pick 18f34ef。

后续重新调研方向:对齐上游 warpdotdev#9970(无条件订阅)
+ warpdotdev#11321(Linux inotify 监听目录而非文件)。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant