Archived
Add switch branch (b): stage the tip and restore to it
b opens a centered popup with a search line and the local and remote branches of the selection. Enter stages the branch tip as the pin of a submodule, restores it (and everything below) to it, and puts HEAD on the branch; a remote branch gets a local tracking branch unless one exists elsewhere. Works on the superproject too. Losses are asked like restore. The backdrop behind the popup is dimmed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
package tui
|
||||
|
||||
import (
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
|
||||
"submarine/internal/submodule"
|
||||
"submarine/internal/tui/branches"
|
||||
)
|
||||
|
||||
// branchesMsg is the branch list for the picker of path.
|
||||
type branchesMsg struct {
|
||||
path string
|
||||
branches []submodule.Branch
|
||||
err error
|
||||
}
|
||||
|
||||
// startSwitch opens the branch picker for the selection and reads its
|
||||
// branches.
|
||||
func (m Model) startSwitch() (tea.Model, tea.Cmd) {
|
||||
s := m.tree.Selected()
|
||||
sw, ok := m.provider.(submodule.Switcher)
|
||||
var flash string
|
||||
switch {
|
||||
case s == nil:
|
||||
return m, nil
|
||||
case !ok:
|
||||
flash = "this data source can't switch branches"
|
||||
case m.restore != nil:
|
||||
flash = "wait for the restore of " + m.restore.name + " to finish"
|
||||
case !s.IsRoot() && s.Status != nil && s.Status.Presence != submodule.PresenceOK:
|
||||
flash = s.Path + " is not initialized; restore it first"
|
||||
}
|
||||
if flash != "" {
|
||||
cmd := m.footer.Flash(flash)
|
||||
m.layout()
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
m.picker, m.pickerPath = branches.New(m.theme, restoreName(s)), s.Path
|
||||
m.picker.SetSpinner(m.spinner.View())
|
||||
ctx, path := m.ctx, s.Path
|
||||
load := func() tea.Msg {
|
||||
bs, err := sw.Branches(ctx, path)
|
||||
return branchesMsg{path, bs, err}
|
||||
}
|
||||
return m, tea.Batch(load, m.tick())
|
||||
}
|
||||
|
||||
// branchesLoaded fills the picker, unless it was closed or is for another
|
||||
// repository meanwhile.
|
||||
func (m Model) branchesLoaded(msg branchesMsg) (tea.Model, tea.Cmd) {
|
||||
if m.picker == nil || m.pickerPath != msg.path {
|
||||
return m, nil
|
||||
}
|
||||
if msg.err != nil {
|
||||
m.picker.SetErr(msg.err)
|
||||
} else {
|
||||
m.picker.SetBranches(msg.branches)
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// pickBranch handles a key while the picker is open: arrows move, enter
|
||||
// switches, esc closes, everything else edits the search.
|
||||
func (m Model) pickBranch(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
||||
switch msg.Type {
|
||||
case tea.KeyCtrlC:
|
||||
return m, tea.Quit
|
||||
case tea.KeyEsc:
|
||||
m.picker = nil
|
||||
case tea.KeyUp:
|
||||
m.picker.Up()
|
||||
case tea.KeyDown:
|
||||
m.picker.Down()
|
||||
case tea.KeyPgUp:
|
||||
m.picker.PageUp()
|
||||
case tea.KeyPgDown:
|
||||
m.picker.PageDown()
|
||||
case tea.KeyEnter:
|
||||
b := m.picker.Selected()
|
||||
if b == nil {
|
||||
return m, nil
|
||||
}
|
||||
s := m.byPath[m.pickerPath]
|
||||
m.picker = nil
|
||||
if s == nil || m.restore != nil {
|
||||
return m, nil
|
||||
}
|
||||
m.restore = &restoreState{path: s.Path, name: restoreName(s), branch: b}
|
||||
return m.checkRestore()
|
||||
default:
|
||||
return m, m.picker.Update(msg)
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
Reference in New Issue
Block a user