commands/stack/navigate/stack_navigate.go (174 lines of code) (raw):

package navigate import ( "errors" "fmt" "github.com/AlecAivazis/survey/v2" "github.com/spf13/cobra" "gitlab.com/gitlab-org/cli/commands/cmdutils" "gitlab.com/gitlab-org/cli/pkg/git" "gitlab.com/gitlab-org/cli/pkg/text" ) func baseCommand() (git.Stack, error) { title, err := git.GetCurrentStackTitle() if err != nil { return git.Stack{}, err } stack, err := git.GatherStackRefs(title) if err != nil { return git.Stack{}, err } return stack, nil } func NewCmdStackFirst(f *cmdutils.Factory, gr git.GitRunner) *cobra.Command { return &cobra.Command{ Use: "first", Short: "Moves to the first diff in the stack. (EXPERIMENTAL.)", Long: "Moves to the first diff in the stack, and checks out that branch.\n" + text.ExperimentalString, Example: "glab stack first", RunE: func(cmd *cobra.Command, args []string) error { stack, err := baseCommand() if err != nil { return err } if stack.Empty() { return errors.New("you are on an empty stack. To use a stack, first save a diff.") } ref := stack.First() err = git.CheckoutBranch(ref.Branch, gr) if err != nil { return err } switchMessage(f, &ref) return nil }, } } func NewCmdStackNext(f *cmdutils.Factory, gr git.GitRunner) *cobra.Command { return &cobra.Command{ Use: "next", Short: "Moves to the next diff in the stack. (EXPERIMENTAL.)", Long: "Moves to the next diff in the stack, and checks out that branch.\n" + text.ExperimentalString, Example: "glab stack next", RunE: func(cmd *cobra.Command, args []string) error { stack, err := baseCommand() if err != nil { return err } ref, err := git.CurrentStackRefFromCurrentBranch(stack.Title) if err != nil { return err } if ref.IsLast() { return fmt.Errorf("you are already at the last diff. Use `glab stack list` to see the complete list.") } err = git.CheckoutBranch(stack.Refs[ref.Next].Branch, gr) if err != nil { return err } next := stack.Refs[ref.Next] switchMessage(f, &next) return nil }, } } func NewCmdStackPrev(f *cmdutils.Factory, gr git.GitRunner) *cobra.Command { return &cobra.Command{ Use: "prev", Short: "Moves to the previous diff in the stack. (EXPERIMENTAL.)", Long: "Moves to the previous diff in the stack, and checks out that branch.\n" + text.ExperimentalString, Example: "glab stack prev", RunE: func(cmd *cobra.Command, args []string) error { stack, err := baseCommand() if err != nil { return err } ref, err := git.CurrentStackRefFromCurrentBranch(stack.Title) if err != nil { return err } if ref.IsFirst() { return fmt.Errorf("you are already at the first diff. Use `glab stack list` to see the complete list.") } err = git.CheckoutBranch(stack.Refs[ref.Prev].Branch, gr) if err != nil { return err } prev := stack.Refs[ref.Prev] switchMessage(f, &prev) return nil }, } } func NewCmdStackLast(f *cmdutils.Factory, gr git.GitRunner) *cobra.Command { return &cobra.Command{ Use: "last", Short: "Moves to the last diff in the stack. (EXPERIMENTAL.)", Long: "Moves to the last diff in the stack, and checks out that branch.\n" + text.ExperimentalString, Example: "glab stack last", RunE: func(cmd *cobra.Command, args []string) error { stack, err := baseCommand() if err != nil { return err } if stack.Empty() { return errors.New("stack is empty until you save a diff.") } ref := stack.Last() err = git.CheckoutBranch(ref.Branch, gr) if err != nil { return err } switchMessage(f, &ref) return nil }, } } func NewCmdStackMove(f *cmdutils.Factory, gr git.GitRunner) *cobra.Command { return &cobra.Command{ Use: "move", Short: "Moves to any selected entry in the stack. (EXPERIMENTAL.)", Long: "Shows a menu with a fuzzy finder to select a stack.\n" + text.ExperimentalString, Example: "glab stack move", RunE: func(cmd *cobra.Command, args []string) error { stack, err := baseCommand() if err != nil { return err } var branches []string var descriptions []string i := 1 for ref := range stack.Iter() { branches = append(branches, ref.Branch) message := fmt.Sprintf("%v: %v", i, ref.Description) descriptions = append(descriptions, message) i++ } var branch string prompt := &survey.Select{ Message: "Choose a diff to be checked out:", Options: branches, Description: func(value string, index int) string { return descriptions[index] }, } err = survey.AskOne(prompt, &branch) if err != nil { return err } err = git.CheckoutBranch(branch, gr) if err != nil { return err } return nil }, } } func switchMessage(f *cmdutils.Factory, ref *git.StackRef) { color := f.IO.Color() fmt.Printf( "%v Switched to branch: %v - %v\n", color.ProgressIcon(), color.Blue(ref.Branch), color.Bold(ref.Description), ) }