From a17653031c4df544a515be1edbe0369fcaa1cbcf Mon Sep 17 00:00:00 2001 From: Dolev Hadar <6196971+dlvhdr@users.noreply.github.com> Date: Sat, 31 Aug 2024 20:20:33 +0300 Subject: [PATCH] feat(branches): create branch (#432) --- git/git.go | 7 +++-- ui/components/reposection/commands.go | 36 ++++++++++++++++++++++-- ui/components/reposection/delete.go | 1 - ui/components/reposection/reposection.go | 35 ++++++++++++++--------- ui/components/section/section.go | 2 ++ ui/keys/branchKeys.go | 14 +++++++++ ui/ui.go | 7 +++++ 7 files changed, 82 insertions(+), 20 deletions(-) delete mode 100644 ui/components/reposection/delete.go diff --git a/git/git.go b/git/git.go index a8c6d1d0..6513d24c 100644 --- a/git/git.go +++ b/git/git.go @@ -66,7 +66,9 @@ func GetRepo(dir string) (*Repo, error) { return nil, err } - headRev, err := repo.RevParse("HEAD") + headRef, err := repo.RevParse("HEAD", gitm.RevParseOptions{ + CommandOptions: gitm.CommandOptions{Args: []string{"--abbrev-ref"}}, + }) if err != nil { return nil, err } @@ -75,11 +77,10 @@ func GetRepo(dir string) (*Repo, error) { for i, b := range bNames { var updatedAt *time.Time var lastCommitMsg *string - isHead := false + isHead := b == headRef commits, err := gitm.Log(dir, b, gitm.LogOptions{MaxCount: 1}) if err == nil && len(commits) > 0 { updatedAt = &commits[0].Committer.When - isHead = commits[0].ID.Equal(headRev) lastCommitMsg = utils.StringPtr(commits[0].Summary()) } commitsAhead, err := repo.RevListCount([]string{fmt.Sprintf("origin/%s..%s", b, b)}) diff --git a/ui/components/reposection/commands.go b/ui/components/reposection/commands.go index 4a592aca..3a23f116 100644 --- a/ui/components/reposection/commands.go +++ b/ui/components/reposection/commands.go @@ -137,14 +137,15 @@ func (m *Model) checkout() (tea.Cmd, error) { SectionId: 0, SectionType: SectionType, TaskId: taskId, - Msg: repoMsg{repo: repo}, + Msg: repoMsg{repo: repo, resetSelection: true}, Err: err, } }), nil } type repoMsg struct { - repo *git.Repo + repo *git.Repo + resetSelection bool } func (m *Model) readRepoCmd() []tea.Cmd { @@ -316,3 +317,34 @@ func (m *Model) deleteBranch() tea.Cmd { } }) } + +func (m *Model) newBranch(name string) tea.Cmd { + taskId := fmt.Sprintf("create_branch_%s_%d", name, time.Now().Unix()) + task := context.Task{ + Id: taskId, + StartText: fmt.Sprintf("Creating branch %s", name), + FinishedText: fmt.Sprintf("Branch %s has been created", name), + State: context.TaskStart, + Error: nil, + } + startCmd := m.Ctx.StartTask(task) + return tea.Batch(startCmd, func() tea.Msg { + // TODO: find out what the default branch is / use the currently selected branch + err := gitm.Checkout(*m.Ctx.RepoPath, name, gitm.CheckoutOptions{BaseBranch: "main"}) + if err != nil { + return constants.TaskFinishedMsg{TaskId: taskId, Err: err} + } + repo, err := git.GetRepo(*m.Ctx.RepoPath) + if err != nil { + return constants.TaskFinishedMsg{TaskId: taskId, Err: err} + } + + return constants.TaskFinishedMsg{ + SectionId: 0, + SectionType: SectionType, + TaskId: taskId, + Msg: repoMsg{repo: repo}, + Err: err, + } + }) +} diff --git a/ui/components/reposection/delete.go b/ui/components/reposection/delete.go deleted file mode 100644 index 604e090f..00000000 --- a/ui/components/reposection/delete.go +++ /dev/null @@ -1 +0,0 @@ -package reposection diff --git a/ui/components/reposection/reposection.go b/ui/components/reposection/reposection.go index 26f021a4..fca5076a 100644 --- a/ui/components/reposection/reposection.go +++ b/ui/components/reposection/reposection.go @@ -102,20 +102,24 @@ func (m *Model) Update(msg tea.Msg) (section.Section, tea.Cmd) { case msg.Type == tea.KeyEnter: input := m.PromptConfirmationBox.Value() action := m.GetPromptConfirmationAction() - pr := findPRForRef(m.Prs, m.getCurrBranch().Data.Name) - sid := tasks.SectionIdentifer{Id: m.Id, Type: SectionType} - if input == "Y" || input == "y" { - switch action { - case "delete": - cmd = m.deleteBranch() - case "close": - cmd = tasks.ClosePR(m.Ctx, sid, pr) - case "reopen": - cmd = tasks.ReopenPR(m.Ctx, sid, pr) - case "ready": - cmd = tasks.PRReady(m.Ctx, sid, pr) - case "merge": - cmd = tasks.MergePR(m.Ctx, sid, pr) + if action == "new" { + cmd = m.newBranch(input) + } else { + pr := findPRForRef(m.Prs, m.getCurrBranch().Data.Name) + sid := tasks.SectionIdentifer{Id: m.Id, Type: SectionType} + if input == "Y" || input == "y" { + switch action { + case "delete": + cmd = m.deleteBranch() + case "close": + cmd = tasks.ClosePR(m.Ctx, sid, pr) + case "reopen": + cmd = tasks.ReopenPR(m.Ctx, sid, pr) + case "ready": + cmd = tasks.PRReady(m.Ctx, sid, pr) + case "merge": + cmd = tasks.MergePR(m.Ctx, sid, pr) + } } } @@ -152,6 +156,9 @@ func (m *Model) Update(msg tea.Msg) (section.Section, tea.Cmd) { m.repo = msg.repo m.Table.SetIsLoading(false) m.Table.SetRows(m.BuildRows()) + if msg.resetSelection { + m.Table.ResetCurrItem() + } case SectionPullRequestsFetchedMsg: m.Prs = msg.Prs diff --git a/ui/components/section/section.go b/ui/components/section/section.go index 594b5f75..71647fad 100644 --- a/ui/components/section/section.go +++ b/ui/components/section/section.go @@ -370,6 +370,8 @@ func (m *BaseModel) GetPromptConfirmation() string { prompt = "Are you sure you want to reopen this issue? (Y/n) " case m.PromptConfirmationAction == "delete" && m.Ctx.View == config.RepoView: prompt = "Are you sure you want to delete this branch? (Y/n) " + case m.PromptConfirmationAction == "new" && m.Ctx.View == config.RepoView: + prompt = "Enter branch name: " } m.PromptConfirmationBox.SetPrompt(prompt) diff --git a/ui/keys/branchKeys.go b/ui/keys/branchKeys.go index 5c2b3479..bfe244a3 100644 --- a/ui/keys/branchKeys.go +++ b/ui/keys/branchKeys.go @@ -11,6 +11,7 @@ import ( type BranchKeyMap struct { Checkout key.Binding + New key.Binding FastForward key.Binding Push key.Binding Delete key.Binding @@ -22,6 +23,10 @@ var BranchKeys = BranchKeyMap{ key.WithKeys("C", " "), key.WithHelp("C/space", "checkout"), ), + New: key.NewBinding( + key.WithKeys("n"), + key.WithHelp("n", "new"), + ), FastForward: key.NewBinding( key.WithKeys("f"), key.WithHelp("f", "fast-forward"), @@ -45,6 +50,7 @@ func BranchFullHelp() []key.Binding { BranchKeys.Checkout, BranchKeys.FastForward, BranchKeys.Push, + BranchKeys.New, BranchKeys.Delete, BranchKeys.ViewPRs, } @@ -61,6 +67,14 @@ func rebindBranchKeys(keys []config.Keybinding) error { var key *key.Binding switch branchKey.Builtin { + case "new": + key = &BranchKeys.New + case "delete": + key = &BranchKeys.Delete + case "push": + key = &BranchKeys.Push + case "fastForward": + key = &BranchKeys.FastForward case "checkout": key = &BranchKeys.Checkout case "viewPRs": diff --git a/ui/ui.go b/ui/ui.go index fe2494ba..348306c0 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -298,6 +298,13 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } return m, cmd + case key.Matches(msg, keys.BranchKeys.New): + if currSection != nil { + currSection.SetPromptConfirmationAction("new") + cmd = currSection.SetIsPromptConfirmationShown(true) + } + return m, cmd + case key.Matches(msg, keys.BranchKeys.ViewPRs): m.ctx.View = m.switchSelectedView() m.syncMainContentWidth()