branch.go

  1package cmd
  2
  3import (
  4	"fmt"
  5	"strings"
  6
  7	"github.com/charmbracelet/soft-serve/git"
  8	gitm "github.com/gogs/git-module"
  9	"github.com/spf13/cobra"
 10)
 11
 12func branchCommand() *cobra.Command {
 13	cmd := &cobra.Command{
 14		Use:   "branch",
 15		Short: "Manage repository branches",
 16	}
 17
 18	cmd.AddCommand(
 19		branchListCommand(),
 20		branchDefaultCommand(),
 21		branchDeleteCommand(),
 22	)
 23
 24	return cmd
 25}
 26
 27func branchListCommand() *cobra.Command {
 28	cmd := &cobra.Command{
 29		Use:               "list REPOSITORY",
 30		Short:             "List repository branches",
 31		Args:              cobra.ExactArgs(1),
 32		PersistentPreRunE: checkIfReadable,
 33		RunE: func(cmd *cobra.Command, args []string) error {
 34			be, _ := fromContext(cmd)
 35			rn := strings.TrimSuffix(args[0], ".git")
 36			ctx := cmd.Context()
 37			rr, err := be.Repository(ctx, rn)
 38			if err != nil {
 39				return err
 40			}
 41
 42			r, err := rr.Open()
 43			if err != nil {
 44				return err
 45			}
 46
 47			branches, _ := r.Branches()
 48			for _, b := range branches {
 49				cmd.Println(b)
 50			}
 51
 52			return nil
 53		},
 54	}
 55
 56	return cmd
 57}
 58
 59func branchDefaultCommand() *cobra.Command {
 60	cmd := &cobra.Command{
 61		Use:   "default REPOSITORY [BRANCH]",
 62		Short: "Set or get the default branch",
 63		Args:  cobra.RangeArgs(1, 2),
 64		RunE: func(cmd *cobra.Command, args []string) error {
 65			ctx := cmd.Context()
 66			be, _ := fromContext(cmd)
 67			rn := strings.TrimSuffix(args[0], ".git")
 68			switch len(args) {
 69			case 1:
 70				if err := checkIfReadable(cmd, args); err != nil {
 71					return err
 72				}
 73
 74				rr, err := be.Repository(ctx, rn)
 75				if err != nil {
 76					return err
 77				}
 78
 79				r, err := rr.Open()
 80				if err != nil {
 81					return err
 82				}
 83
 84				head, err := r.HEAD()
 85				if err != nil {
 86					return err
 87				}
 88
 89				cmd.Println(head.Name().Short())
 90			case 2:
 91				if err := checkIfCollab(cmd, args); err != nil {
 92					return err
 93				}
 94
 95				rr, err := be.Repository(ctx, rn)
 96				if err != nil {
 97					return err
 98				}
 99
100				r, err := rr.Open()
101				if err != nil {
102					return err
103				}
104
105				branch := args[1]
106				branches, _ := r.Branches()
107				var exists bool
108				for _, b := range branches {
109					if branch == b {
110						exists = true
111						break
112					}
113				}
114
115				if !exists {
116					return git.ErrReferenceNotExist
117				}
118
119				if _, err := r.SymbolicRef("HEAD", gitm.RefsHeads+branch); err != nil {
120					return err
121				}
122			}
123
124			return nil
125		},
126	}
127
128	return cmd
129}
130
131func branchDeleteCommand() *cobra.Command {
132	cmd := &cobra.Command{
133		Use:               "delete REPOSITORY BRANCH",
134		Aliases:           []string{"remove", "rm", "del"},
135		Short:             "Delete a branch",
136		PersistentPreRunE: checkIfCollab,
137		RunE: func(cmd *cobra.Command, args []string) error {
138			ctx := cmd.Context()
139			be, _ := fromContext(cmd)
140			rn := strings.TrimSuffix(args[0], ".git")
141			rr, err := be.Repository(ctx, rn)
142			if err != nil {
143				return err
144			}
145
146			r, err := rr.Open()
147			if err != nil {
148				return err
149			}
150
151			branch := args[1]
152			branches, _ := r.Branches()
153			var exists bool
154			for _, b := range branches {
155				if branch == b {
156					exists = true
157					break
158				}
159			}
160
161			if !exists {
162				return git.ErrReferenceNotExist
163			}
164
165			head, err := r.HEAD()
166			if err != nil {
167				return err
168			}
169
170			if head.Name().Short() == branch {
171				return fmt.Errorf("cannot delete the default branch")
172			}
173
174			if err := r.DeleteBranch(branch, gitm.DeleteBranchOptions{Force: true}); err != nil {
175				return err
176			}
177
178			return nil
179		},
180	}
181
182	return cmd
183}