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			cfg, _ := fromContext(cmd)
 35			rn := strings.TrimSuffix(args[0], ".git")
 36			rr, err := cfg.Backend.Repository(rn)
 37			if err != nil {
 38				return err
 39			}
 40
 41			r, err := rr.Open()
 42			if err != nil {
 43				return err
 44			}
 45
 46			branches, _ := r.Branches()
 47			for _, b := range branches {
 48				cmd.Println(b)
 49			}
 50
 51			return nil
 52		},
 53	}
 54
 55	return cmd
 56}
 57
 58func branchDefaultCommand() *cobra.Command {
 59	cmd := &cobra.Command{
 60		Use:   "default REPOSITORY [BRANCH]",
 61		Short: "Set or get the default branch",
 62		Args:  cobra.RangeArgs(1, 2),
 63		RunE: func(cmd *cobra.Command, args []string) error {
 64			cfg, _ := fromContext(cmd)
 65			rn := strings.TrimSuffix(args[0], ".git")
 66			switch len(args) {
 67			case 1:
 68				if err := checkIfReadable(cmd, args); err != nil {
 69					return err
 70				}
 71				rr, err := cfg.Backend.Repository(rn)
 72				if err != nil {
 73					return err
 74				}
 75
 76				r, err := rr.Open()
 77				if err != nil {
 78					return err
 79				}
 80
 81				head, err := r.HEAD()
 82				if err != nil {
 83					return err
 84				}
 85
 86				cmd.Println(head.Name().Short())
 87			case 2:
 88				if err := checkIfCollab(cmd, args); err != nil {
 89					return err
 90				}
 91
 92				rr, err := cfg.Backend.Repository(rn)
 93				if err != nil {
 94					return err
 95				}
 96
 97				r, err := rr.Open()
 98				if err != nil {
 99					return err
100				}
101
102				branch := args[1]
103				branches, _ := r.Branches()
104				var exists bool
105				for _, b := range branches {
106					if branch == b {
107						exists = true
108						break
109					}
110				}
111
112				if !exists {
113					return git.ErrReferenceNotExist
114				}
115
116				if _, err := r.SymbolicRef("HEAD", gitm.RefsHeads+branch); err != nil {
117					return err
118				}
119			}
120
121			return nil
122		},
123	}
124
125	return cmd
126}
127
128func branchDeleteCommand() *cobra.Command {
129	cmd := &cobra.Command{
130		Use:               "delete REPOSITORY BRANCH",
131		Aliases:           []string{"remove", "rm", "del"},
132		Short:             "Delete a branch",
133		PersistentPreRunE: checkIfCollab,
134		RunE: func(cmd *cobra.Command, args []string) error {
135			cfg, _ := fromContext(cmd)
136			rn := strings.TrimSuffix(args[0], ".git")
137			rr, err := cfg.Backend.Repository(rn)
138			if err != nil {
139				return err
140			}
141
142			r, err := rr.Open()
143			if err != nil {
144				return err
145			}
146
147			branch := args[1]
148			branches, _ := r.Branches()
149			var exists bool
150			for _, b := range branches {
151				if branch == b {
152					exists = true
153					break
154				}
155			}
156
157			if !exists {
158				return git.ErrReferenceNotExist
159			}
160
161			head, err := r.HEAD()
162			if err != nil {
163				return err
164			}
165
166			if head.Name().Short() == branch {
167				return fmt.Errorf("cannot delete the default branch")
168			}
169
170			if err := r.DeleteBranch(branch, gitm.DeleteBranchOptions{Force: true}); err != nil {
171				return err
172			}
173
174			return nil
175		},
176	}
177
178	return cmd
179}