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/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	tokenStdin            bool
 25	bridgeConfigureName   string
 26	bridgeConfigureTarget string
 27	bridgeParams          core.BridgeParams
 28)
 29
 30func runBridgeConfigure(cmd *cobra.Command, args []string) error {
 31	backend, err := cache.NewRepoCache(repo)
 32	if err != nil {
 33		return err
 34	}
 35	defer backend.Close()
 36	interrupt.RegisterCleaner(backend.Close)
 37
 38	if (tokenStdin || bridgeParams.Token != "") && (bridgeConfigureName == "" || bridgeConfigureTarget == "") {
 39		return fmt.Errorf("you must 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	if tokenStdin {
 62		reader := bufio.NewReader(os.Stdin)
 63		token, err := reader.ReadString('\n')
 64		if err != nil {
 65			return fmt.Errorf("reading from stdin: %v", err)
 66		}
 67		bridgeParams.Token = strings.TrimSuffix(token, "\n")
 68	}
 69
 70	err = b.Configure(bridgeParams)
 71	if err != nil {
 72		return err
 73	}
 74
 75	fmt.Printf("Successfully configured bridge: %s\n", bridgeConfigureName)
 76	return nil
 77}
 78
 79func promptTarget() (string, error) {
 80	targets := bridge.Targets()
 81
 82	for {
 83		for i, target := range targets {
 84			fmt.Printf("[%d]: %s\n", i+1, target)
 85		}
 86		fmt.Printf("target: ")
 87
 88		line, err := bufio.NewReader(os.Stdin).ReadString('\n')
 89
 90		if err != nil {
 91			return "", err
 92		}
 93
 94		line = strings.TrimRight(line, "\n")
 95
 96		index, err := strconv.Atoi(line)
 97		if err != nil || index <= 0 || index > len(targets) {
 98			fmt.Println("invalid input")
 99			continue
100		}
101
102		return targets[index-1], nil
103	}
104}
105
106func promptName(repo repository.RepoCommon) (string, error) {
107	for {
108		fmt.Printf("name [%s]: ", defaultName)
109
110		line, err := bufio.NewReader(os.Stdin).ReadString('\n')
111		if err != nil {
112			return "", err
113		}
114
115		line = strings.TrimRight(line, "\n")
116
117		name := line
118		if name == "" {
119			name = defaultName
120		}
121
122		if !core.BridgeExist(repo, name) {
123			return name, nil
124		}
125
126		fmt.Println("a bridge with the same name already exist")
127	}
128}
129
130var bridgeConfigureCmd = &cobra.Command{
131	Use:   "configure",
132	Short: "Configure a new bridge.",
133	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.
134	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.
135	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.`,
136	Example: `# Interactive example
137[1]: github
138[2]: launchpad-preview
139target: 1
140name [default]: default
141
142Detected projects:
143[1]: github.com/a-hilaly/git-bug
144[2]: github.com/MichaelMure/git-bug
145
146[0]: Another project
147
148Select option: 1
149
150[1]: user provided token
151[2]: interactive token creation
152Select option: 1
153
154You can generate a new token by visiting https://github.com/settings/tokens.
155Choose 'Generate new token' and set the necessary access scope for your repository.
156
157The access scope depend on the type of repository.
158Public:
159	- 'public_repo': to be able to read public repositories
160Private:
161	- 'repo'       : to be able to read private repositories
162
163Enter token: 87cf5c03b64029f18ea5f9ca5679daa08ccbd700
164Successfully configured bridge: default
165
166# For GitHub
167git bug bridge configure \
168    --name=default \
169    --target=github \
170    --owner=$(OWNER) \
171    --project=$(PROJECT) \
172    --token=$(TOKEN)
173
174# For Launchpad
175git bug bridge configure \
176    --name=default \
177    --target=launchpad-preview \
178	--url=https://bugs.launchpad.net/ubuntu/
179
180# For Gitlab
181git bug bridge configure \
182    --name=default \
183    --target=github \
184    --url=https://github.com/michaelmure/git-bug \
185    --token=$(TOKEN)`,
186	PreRunE: loadRepo,
187	RunE:    runBridgeConfigure,
188}
189
190func init() {
191	bridgeCmd.AddCommand(bridgeConfigureCmd)
192	bridgeConfigureCmd.Flags().StringVarP(&bridgeConfigureName, "name", "n", "", "A distinctive name to identify the bridge")
193	bridgeConfigureCmd.Flags().StringVarP(&bridgeConfigureTarget, "target", "t", "",
194		fmt.Sprintf("The target of the bridge. Valid values are [%s]", strings.Join(bridge.Targets(), ",")))
195	bridgeConfigureCmd.Flags().StringVarP(&bridgeParams.URL, "url", "u", "", "The URL of the target repository")
196	bridgeConfigureCmd.Flags().StringVarP(&bridgeParams.Owner, "owner", "o", "", "The owner of the target repository")
197	bridgeConfigureCmd.Flags().StringVarP(&bridgeParams.Token, "token", "T", "", "The authentication token for the API")
198	bridgeConfigureCmd.Flags().BoolVar(&tokenStdin, "token-stdin", false, "Will read the token from stdin and ignore --token")
199	bridgeConfigureCmd.Flags().StringVarP(&bridgeParams.Project, "project", "p", "", "The name of the target repository")
200	bridgeConfigureCmd.Flags().SortFlags = false
201}