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}