1package commands
2
3import (
4 "bufio"
5 "fmt"
6 "os"
7 "strconv"
8 "strings"
9
10 "github.com/spf13/cobra"
11
12 "github.com/MichaelMure/git-bug/bridge"
13 "github.com/MichaelMure/git-bug/bridge/core"
14 "github.com/MichaelMure/git-bug/cache"
15 "github.com/MichaelMure/git-bug/repository"
16 "github.com/MichaelMure/git-bug/util/interrupt"
17)
18
19const (
20 defaultName = "default"
21)
22
23var (
24 bridgeConfigureName string
25 bridgeConfigureTarget string
26 bridgeParams core.BridgeParams
27)
28
29func runBridgeConfigure(cmd *cobra.Command, args []string) error {
30 backend, err := cache.NewRepoCache(repo)
31 if err != nil {
32 return err
33 }
34 defer backend.Close()
35 interrupt.RegisterCleaner(backend.Close)
36
37 if (bridgeParams.TokenStdin || bridgeParams.Token != "" || bridgeParams.TokenId != "") &&
38 (bridgeConfigureName == "" || bridgeConfigureTarget == "") {
39 return fmt.Errorf("you must provide a bridge name and target to configure a bridge with a token")
40 }
41
42 if bridgeConfigureTarget == "" {
43 bridgeConfigureTarget, err = promptTarget()
44 if err != nil {
45 return err
46 }
47 }
48
49 if bridgeConfigureName == "" {
50 bridgeConfigureName, err = promptName(repo)
51 if err != nil {
52 return err
53 }
54 }
55
56 b, err := bridge.NewBridge(backend, bridgeConfigureTarget, bridgeConfigureName)
57 if err != nil {
58 return err
59 }
60
61 err = b.Configure(bridgeParams)
62 if err != nil {
63 return err
64 }
65
66 fmt.Printf("Successfully configured bridge: %s\n", bridgeConfigureName)
67 return nil
68}
69
70func promptTarget() (string, error) {
71 targets := bridge.Targets()
72
73 for {
74 for i, target := range targets {
75 fmt.Printf("[%d]: %s\n", i+1, target)
76 }
77 fmt.Printf("target: ")
78
79 line, err := bufio.NewReader(os.Stdin).ReadString('\n')
80
81 if err != nil {
82 return "", err
83 }
84
85 line = strings.TrimRight(line, "\n")
86
87 index, err := strconv.Atoi(line)
88 if err != nil || index <= 0 || index > len(targets) {
89 fmt.Println("invalid input")
90 continue
91 }
92
93 return targets[index-1], nil
94 }
95}
96
97func promptName(repo repository.RepoCommon) (string, error) {
98 defaultExist := core.BridgeExist(repo, defaultName)
99
100 for {
101 if defaultExist {
102 fmt.Printf("name: ")
103 } else {
104 fmt.Printf("name [%s]: ", defaultName)
105 }
106
107 line, err := bufio.NewReader(os.Stdin).ReadString('\n')
108 if err != nil {
109 return "", err
110 }
111
112 line = strings.TrimRight(line, "\n")
113
114 name := line
115 if defaultExist && name == "" {
116 continue
117 }
118
119 if name == "" {
120 name = defaultName
121 }
122
123 if !core.BridgeExist(repo, name) {
124 return name, nil
125 }
126
127 fmt.Println("a bridge with the same name already exist")
128 }
129}
130
131var bridgeConfigureCmd = &cobra.Command{
132 Use: "configure",
133 Short: "Configure a new bridge.",
134 Long: ` Configure a new bridge by passing flags or/and using interactive terminal prompts. You can avoid all the terminal prompts by passing all the necessary flags to configure your bridge.
135 Repository configuration can be made by passing either the --url flag or the --project and --owner flags. If the three flags are provided git-bug will use --project and --owner flags.
136 Token configuration can be directly passed with the --token flag or in the terminal prompt. If you don't already have one you can use the interactive procedure to generate one.`,
137 Example: `# Interactive example
138[1]: github
139[2]: launchpad-preview
140target: 1
141name [default]: default
142
143Detected projects:
144[1]: github.com/a-hilaly/git-bug
145[2]: github.com/MichaelMure/git-bug
146
147[0]: Another project
148
149Select option: 1
150
151[1]: user provided token
152[2]: interactive token creation
153Select option: 1
154
155You can generate a new token by visiting https://github.com/settings/tokens.
156Choose 'Generate new token' and set the necessary access scope for your repository.
157
158The access scope depend on the type of repository.
159Public:
160 - 'public_repo': to be able to read public repositories
161Private:
162 - 'repo' : to be able to read private repositories
163
164Enter token: 87cf5c03b64029f18ea5f9ca5679daa08ccbd700
165Successfully configured bridge: default
166
167# For GitHub
168git bug bridge configure \
169 --name=default \
170 --target=github \
171 --owner=$(OWNER) \
172 --project=$(PROJECT) \
173 --token=$(TOKEN)
174
175# For Launchpad
176git bug bridge configure \
177 --name=default \
178 --target=launchpad-preview \
179 --url=https://bugs.launchpad.net/ubuntu/
180
181# For Gitlab
182git bug bridge configure \
183 --name=default \
184 --target=github \
185 --url=https://github.com/michaelmure/git-bug \
186 --token=$(TOKEN)`,
187 PreRunE: loadRepo,
188 RunE: runBridgeConfigure,
189}
190
191func init() {
192 bridgeCmd.AddCommand(bridgeConfigureCmd)
193 bridgeConfigureCmd.Flags().StringVarP(&bridgeConfigureName, "name", "n", "", "A distinctive name to identify the bridge")
194 bridgeConfigureCmd.Flags().StringVarP(&bridgeConfigureTarget, "target", "t", "",
195 fmt.Sprintf("The target of the bridge. Valid values are [%s]", strings.Join(bridge.Targets(), ",")))
196 bridgeConfigureCmd.Flags().StringVarP(&bridgeParams.URL, "url", "u", "", "The URL of the target repository")
197 bridgeConfigureCmd.Flags().StringVarP(&bridgeParams.Owner, "owner", "o", "", "The owner of the target repository")
198 bridgeConfigureCmd.Flags().StringVarP(&bridgeParams.Token, "token", "T", "", "The authentication token for the API")
199 bridgeConfigureCmd.Flags().StringVarP(&bridgeParams.TokenId, "token-id", "i", "", "The authentication token identifier for the API")
200 bridgeConfigureCmd.Flags().BoolVar(&bridgeParams.TokenStdin, "token-stdin", false, "Will read the token from stdin and ignore --token")
201 bridgeConfigureCmd.Flags().StringVarP(&bridgeParams.Project, "project", "p", "", "The name of the target repository")
202 bridgeConfigureCmd.Flags().SortFlags = false
203}