bridge_configure.go

  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/bridge/core/auth"
 15	"github.com/MichaelMure/git-bug/cache"
 16	"github.com/MichaelMure/git-bug/repository"
 17	"github.com/MichaelMure/git-bug/util/interrupt"
 18)
 19
 20const (
 21	defaultName = "default"
 22)
 23
 24var (
 25	bridgeConfigureName       string
 26	bridgeConfigureTarget     string
 27	bridgeConfigureParams     core.BridgeParams
 28	bridgeConfigureToken      string
 29	bridgeConfigureTokenStdin bool
 30)
 31
 32func runBridgeConfigure(cmd *cobra.Command, args []string) error {
 33	backend, err := cache.NewRepoCache(repo)
 34	if err != nil {
 35		return err
 36	}
 37	defer backend.Close()
 38	interrupt.RegisterCleaner(backend.Close)
 39
 40	if (bridgeConfigureTokenStdin || bridgeConfigureToken != "" || bridgeConfigureParams.CredPrefix != "") &&
 41		(bridgeConfigureName == "" || bridgeConfigureTarget == "") {
 42		return fmt.Errorf("you must provide a bridge name and target to configure a bridge with a credential")
 43	}
 44
 45	// early fail
 46	if bridgeConfigureParams.CredPrefix != "" {
 47		if _, err := auth.LoadWithPrefix(repo, bridgeConfigureParams.CredPrefix); err != nil {
 48			return err
 49		}
 50	}
 51
 52	switch {
 53	case bridgeConfigureTokenStdin:
 54		reader := bufio.NewReader(os.Stdin)
 55		token, err := reader.ReadString('\n')
 56		if err != nil {
 57			return fmt.Errorf("reading from stdin: %v", err)
 58		}
 59		bridgeConfigureParams.TokenRaw = strings.TrimSpace(token)
 60	case bridgeConfigureToken != "":
 61		bridgeConfigureParams.TokenRaw = bridgeConfigureToken
 62	}
 63
 64	if bridgeConfigureTarget == "" {
 65		bridgeConfigureTarget, err = promptTarget()
 66		if err != nil {
 67			return err
 68		}
 69	}
 70
 71	if bridgeConfigureName == "" {
 72		bridgeConfigureName, err = promptName(repo)
 73		if err != nil {
 74			return err
 75		}
 76	}
 77
 78	b, err := bridge.NewBridge(backend, bridgeConfigureTarget, bridgeConfigureName)
 79	if err != nil {
 80		return err
 81	}
 82
 83	err = b.Configure(bridgeConfigureParams)
 84	if err != nil {
 85		return err
 86	}
 87
 88	fmt.Printf("Successfully configured bridge: %s\n", bridgeConfigureName)
 89	return nil
 90}
 91
 92func promptTarget() (string, error) {
 93	targets := bridge.Targets()
 94
 95	for {
 96		for i, target := range targets {
 97			fmt.Printf("[%d]: %s\n", i+1, target)
 98		}
 99		fmt.Printf("target: ")
100
101		line, err := bufio.NewReader(os.Stdin).ReadString('\n')
102
103		if err != nil {
104			return "", err
105		}
106
107		line = strings.TrimSpace(line)
108
109		index, err := strconv.Atoi(line)
110		if err != nil || index <= 0 || index > len(targets) {
111			fmt.Println("invalid input")
112			continue
113		}
114
115		return targets[index-1], nil
116	}
117}
118
119func promptName(repo repository.RepoConfig) (string, error) {
120	defaultExist := core.BridgeExist(repo, defaultName)
121
122	for {
123		if defaultExist {
124			fmt.Printf("name: ")
125		} else {
126			fmt.Printf("name [%s]: ", defaultName)
127		}
128
129		line, err := bufio.NewReader(os.Stdin).ReadString('\n')
130		if err != nil {
131			return "", err
132		}
133
134		line = strings.TrimSpace(line)
135
136		name := line
137		if defaultExist && name == "" {
138			continue
139		}
140
141		if name == "" {
142			name = defaultName
143		}
144
145		if !core.BridgeExist(repo, name) {
146			return name, nil
147		}
148
149		fmt.Println("a bridge with the same name already exist")
150	}
151}
152
153var bridgeConfigureCmd = &cobra.Command{
154	Use:   "configure",
155	Short: "Configure a new bridge.",
156	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.`,
157	Example: `# Interactive example
158[1]: github
159[2]: gitlab
160[3]: jira
161[4]: launchpad-preview
162
163target: 1
164name [default]: default
165
166Detected projects:
167[1]: github.com/a-hilaly/git-bug
168[2]: github.com/MichaelMure/git-bug
169
170[0]: Another project
171
172Select option: 1
173
174[1]: user provided token
175[2]: interactive token creation
176Select option: 1
177
178You can generate a new token by visiting https://github.com/settings/tokens.
179Choose 'Generate new token' and set the necessary access scope for your repository.
180
181The access scope depend on the type of repository.
182Public:
183	- 'public_repo': to be able to read public repositories
184Private:
185	- 'repo'       : to be able to read private repositories
186
187Enter token: 87cf5c03b64029f18ea5f9ca5679daa08ccbd700
188Successfully configured bridge: default
189
190# For GitHub
191git bug bridge configure \
192    --name=default \
193    --target=github \
194    --owner=$(OWNER) \
195    --project=$(PROJECT) \
196    --token=$(TOKEN)
197
198# For Launchpad
199git bug bridge configure \
200    --name=default \
201    --target=launchpad-preview \
202	--url=https://bugs.launchpad.net/ubuntu/
203
204# For Gitlab
205git bug bridge configure \
206    --name=default \
207    --target=github \
208    --url=https://github.com/michaelmure/git-bug \
209    --token=$(TOKEN)`,
210	PreRunE: loadRepo,
211	RunE:    runBridgeConfigure,
212}
213
214func init() {
215	bridgeCmd.AddCommand(bridgeConfigureCmd)
216	bridgeConfigureCmd.Flags().StringVarP(&bridgeConfigureName, "name", "n", "", "A distinctive name to identify the bridge")
217	bridgeConfigureCmd.Flags().StringVarP(&bridgeConfigureTarget, "target", "t", "",
218		fmt.Sprintf("The target of the bridge. Valid values are [%s]", strings.Join(bridge.Targets(), ",")))
219	bridgeConfigureCmd.Flags().StringVarP(&bridgeConfigureParams.URL, "url", "u", "", "The URL of the remote repository")
220	bridgeConfigureCmd.Flags().StringVarP(&bridgeConfigureParams.BaseURL, "base-url", "b", "", "The base URL of your remote issue tracker")
221	bridgeConfigureCmd.Flags().StringVarP(&bridgeConfigureParams.Login, "login", "l", "", "The login on your remote issue tracker")
222	bridgeConfigureCmd.Flags().StringVarP(&bridgeConfigureParams.CredPrefix, "credential", "c", "", "The identifier or prefix of an already known credential for your remote issue tracker (see \"git-bug bridge auth\")")
223	bridgeConfigureCmd.Flags().StringVar(&bridgeConfigureToken, "token", "", "A raw authentication token for the remote issue tracker")
224	bridgeConfigureCmd.Flags().BoolVar(&bridgeConfigureTokenStdin, "token-stdin", false, "Will read the token from stdin and ignore --token")
225	bridgeConfigureCmd.Flags().StringVarP(&bridgeConfigureParams.Owner, "owner", "o", "", "The owner of the remote repository")
226	bridgeConfigureCmd.Flags().StringVarP(&bridgeConfigureParams.Project, "project", "p", "", "The name of the remote repository")
227	bridgeConfigureCmd.Flags().SortFlags = false
228}