1package cmd23import (4 "fmt"5 "strings"67 gitm "github.com/aymanbagabas/git-module"8 "github.com/charmbracelet/soft-serve/git"9 "github.com/charmbracelet/soft-serve/pkg/backend"10 "github.com/charmbracelet/soft-serve/pkg/proto"11 "github.com/charmbracelet/soft-serve/pkg/webhook"12 "github.com/spf13/cobra"13)1415func branchCommand() *cobra.Command {16 cmd := &cobra.Command{17 Use: "branch",18 Short: "Manage repository branches",19 }2021 cmd.AddCommand(22 branchListCommand(),23 branchDefaultCommand(),24 branchDeleteCommand(),25 )2627 return cmd28}2930func branchListCommand() *cobra.Command {31 cmd := &cobra.Command{32 Use: "list REPOSITORY",33 Short: "List repository branches",34 Args: cobra.ExactArgs(1),35 PersistentPreRunE: checkIfReadable,36 RunE: func(cmd *cobra.Command, args []string) error {37 ctx := cmd.Context()38 be := backend.FromContext(ctx)39 rn := strings.TrimSuffix(args[0], ".git")40 rr, err := be.Repository(ctx, rn)41 if err != nil {42 return err43 }4445 r, err := rr.Open()46 if err != nil {47 return err48 }4950 branches, _ := r.Branches()51 for _, b := range branches {52 cmd.Println(b)53 }5455 return nil56 },57 }5859 return cmd60}6162func branchDefaultCommand() *cobra.Command {63 cmd := &cobra.Command{64 Use: "default REPOSITORY [BRANCH]",65 Short: "Set or get the default branch",66 Args: cobra.RangeArgs(1, 2),67 PersistentPreRunE: checkIfReadable,68 RunE: func(cmd *cobra.Command, args []string) error {69 ctx := cmd.Context()70 be := backend.FromContext(ctx)71 rn := strings.TrimSuffix(args[0], ".git")72 switch len(args) {73 case 1:74 rr, err := be.Repository(ctx, rn)75 if err != nil {76 return err77 }7879 r, err := rr.Open()80 if err != nil {81 return err82 }8384 head, err := r.HEAD()85 if err != nil {86 return err87 }8889 cmd.Println(head.Name().Short())90 case 2:91 if err := checkIfCollab(cmd, args); err != nil {92 return err93 }9495 rr, err := be.Repository(ctx, rn)96 if err != nil {97 return err98 }99100 r, err := rr.Open()101 if err != nil {102 return err103 }104105 branch := args[1]106 branches, _ := r.Branches()107 var exists bool108 for _, b := range branches {109 if branch == b {110 exists = true111 break112 }113 }114115 if !exists {116 return git.ErrReferenceNotExist117 }118119 if _, err := r.SymbolicRef(git.HEAD, gitm.RefsHeads+branch, gitm.SymbolicRefOptions{120 CommandOptions: gitm.CommandOptions{121 Context: ctx,122 },123 }); err != nil {124 return err125 }126127 // TODO: move this to backend?128 user := proto.UserFromContext(ctx)129 wh, err := webhook.NewRepositoryEvent(ctx, user, rr, webhook.RepositoryEventActionDefaultBranchChange)130 if err != nil {131 return err132 }133134 return webhook.SendEvent(ctx, wh)135 }136137 return nil138 },139 }140141 return cmd142}143144func branchDeleteCommand() *cobra.Command {145 cmd := &cobra.Command{146 Use: "delete REPOSITORY BRANCH",147 Aliases: []string{"remove", "rm", "del"},148 Short: "Delete a branch",149 Args: cobra.ExactArgs(2),150 PersistentPreRunE: checkIfReadableAndCollab,151 RunE: func(cmd *cobra.Command, args []string) error {152 ctx := cmd.Context()153 be := backend.FromContext(ctx)154 rn := strings.TrimSuffix(args[0], ".git")155 rr, err := be.Repository(ctx, rn)156 if err != nil {157 return err158 }159160 r, err := rr.Open()161 if err != nil {162 return err163 }164165 branch := args[1]166 branches, _ := r.Branches()167 var exists bool168 for _, b := range branches {169 if branch == b {170 exists = true171 break172 }173 }174175 if !exists {176 return git.ErrReferenceNotExist177 }178179 head, err := r.HEAD()180 if err != nil {181 return err182 }183184 if head.Name().Short() == branch {185 return fmt.Errorf("cannot delete the default branch")186 }187188 branchCommit, err := r.BranchCommit(branch)189 if err != nil {190 return err191 }192193 if err := r.DeleteBranch(branch, gitm.DeleteBranchOptions{Force: true}); err != nil {194 return err195 }196197 wh, err := webhook.NewBranchTagEvent(ctx, proto.UserFromContext(ctx), rr, git.RefsHeads+branch, branchCommit.ID.String(), git.ZeroID)198 if err != nil {199 return err200 }201202 return webhook.SendEvent(ctx, wh)203 },204 }205206 return cmd207}