2018-09-24 16:25:57 +03:00
package commands
import (
"bufio"
"fmt"
"os"
2018-10-03 22:05:19 +03:00
"strconv"
2018-09-24 16:25:57 +03:00
"strings"
2019-06-05 02:42:36 +03:00
"github.com/spf13/cobra"
2019-05-24 22:03:31 +03:00
2018-09-24 16:25:57 +03:00
"github.com/MichaelMure/git-bug/bridge"
2019-06-05 02:42:36 +03:00
"github.com/MichaelMure/git-bug/bridge/core"
2019-12-08 23:15:06 +03:00
"github.com/MichaelMure/git-bug/bridge/core/auth"
2019-07-07 13:15:01 +03:00
"github.com/MichaelMure/git-bug/repository"
2018-09-24 16:25:57 +03:00
)
2020-06-28 19:26:29 +03:00
type bridgeConfigureOptions struct {
name string
target string
params core . BridgeParams
token string
tokenStdin bool
}
2019-05-24 22:03:31 +03:00
2020-06-28 19:26:29 +03:00
func newBridgeConfigureCommand ( ) * cobra . Command {
env := newEnv ( )
options := bridgeConfigureOptions { }
cmd := & cobra . Command {
Use : "configure" ,
Short : "Configure a new bridge." ,
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. ` ,
Example : ` # Interactive example
[ 1 ] : github
[ 2 ] : gitlab
[ 3 ] : jira
[ 4 ] : launchpad - preview
target : 1
name [ default ] : default
Detected projects :
[ 1 ] : github . com / a - hilaly / git - bug
[ 2 ] : github . com / MichaelMure / git - bug
[ 0 ] : Another project
Select option : 1
[ 1 ] : user provided token
[ 2 ] : interactive token creation
Select option : 1
You can generate a new token by visiting https : //github.com/settings/tokens.
Choose ' Generate new token ' and set the necessary access scope for your repository .
The access scope depend on the type of repository .
Public :
- ' public_repo ' : to be able to read public repositories
Private :
- ' repo ' : to be able to read private repositories
Enter token : 87 cf5c03b64029f18ea5f9ca5679daa08ccbd700
Successfully configured bridge : default
# For GitHub
git bug bridge configure \
-- name = default \
-- target = github \
-- owner = $ ( OWNER ) \
-- project = $ ( PROJECT ) \
-- token = $ ( TOKEN )
# For Launchpad
git bug bridge configure \
-- name = default \
-- target = launchpad - preview \
-- url = https : //bugs.launchpad.net/ubuntu/
2019-05-24 22:03:31 +03:00
2020-06-28 19:26:29 +03:00
# For Gitlab
git bug bridge configure \
-- name = default \
-- target = github \
-- url = https : //github.com/michaelmure/git-bug \
-- token = $ ( TOKEN ) ` ,
2020-06-28 20:09:32 +03:00
PreRunE : loadBackend ( env ) ,
PostRunE : closeBackend ( env ) ,
2020-06-28 19:26:29 +03:00
RunE : func ( cmd * cobra . Command , args [ ] string ) error {
return runBridgeConfigure ( env , options )
} ,
}
flags := cmd . Flags ( )
flags . SortFlags = false
flags . StringVarP ( & options . name , "name" , "n" , "" , "A distinctive name to identify the bridge" )
flags . StringVarP ( & options . target , "target" , "t" , "" ,
fmt . Sprintf ( "The target of the bridge. Valid values are [%s]" , strings . Join ( bridge . Targets ( ) , "," ) ) )
flags . StringVarP ( & options . params . URL , "url" , "u" , "" , "The URL of the remote repository" )
flags . StringVarP ( & options . params . BaseURL , "base-url" , "b" , "" , "The base URL of your remote issue tracker" )
flags . StringVarP ( & options . params . Login , "login" , "l" , "" , "The login on your remote issue tracker" )
flags . StringVarP ( & options . params . CredPrefix , "credential" , "c" , "" , "The identifier or prefix of an already known credential for your remote issue tracker (see \"git-bug bridge auth\")" )
flags . StringVar ( & options . token , "token" , "" , "A raw authentication token for the remote issue tracker" )
flags . BoolVar ( & options . tokenStdin , "token-stdin" , false , "Will read the token from stdin and ignore --token" )
flags . StringVarP ( & options . params . Owner , "owner" , "o" , "" , "The owner of the remote repository" )
flags . StringVarP ( & options . params . Project , "project" , "p" , "" , "The name of the remote repository" )
return cmd
}
func runBridgeConfigure ( env * Env , opts bridgeConfigureOptions ) error {
2020-06-28 20:09:32 +03:00
var err error
2018-09-24 16:25:57 +03:00
2020-06-28 19:26:29 +03:00
if ( opts . tokenStdin || opts . token != "" || opts . params . CredPrefix != "" ) &&
( opts . name == "" || opts . target == "" ) {
2019-12-08 23:15:06 +03:00
return fmt . Errorf ( "you must provide a bridge name and target to configure a bridge with a credential" )
}
// early fail
2020-06-28 19:26:29 +03:00
if opts . params . CredPrefix != "" {
if _ , err := auth . LoadWithPrefix ( env . repo , opts . params . CredPrefix ) ; err != nil {
2019-12-08 23:15:06 +03:00
return err
}
}
switch {
2020-06-28 19:26:29 +03:00
case opts . tokenStdin :
2019-12-08 23:15:06 +03:00
reader := bufio . NewReader ( os . Stdin )
token , err := reader . ReadString ( '\n' )
if err != nil {
return fmt . Errorf ( "reading from stdin: %v" , err )
}
2020-06-28 19:26:29 +03:00
opts . params . TokenRaw = strings . TrimSpace ( token )
case opts . token != "" :
opts . params . TokenRaw = opts . token
2019-08-27 01:32:30 +03:00
}
2020-06-28 19:26:29 +03:00
if opts . target == "" {
opts . target , err = promptTarget ( )
2019-05-24 22:03:31 +03:00
if err != nil {
return err
}
2018-09-24 16:25:57 +03:00
}
2020-06-28 19:26:29 +03:00
if opts . name == "" {
opts . name , err = promptName ( env . repo )
2019-05-24 22:03:31 +03:00
if err != nil {
return err
}
2018-09-24 16:25:57 +03:00
}
2020-06-28 20:09:32 +03:00
b , err := bridge . NewBridge ( env . backend , opts . target , opts . name )
2018-09-24 16:25:57 +03:00
if err != nil {
return err
}
2020-06-28 19:26:29 +03:00
err = b . Configure ( opts . params )
2018-09-24 16:25:57 +03:00
if err != nil {
return err
}
2020-06-28 19:26:29 +03:00
env . out . Printf ( "Successfully configured bridge: %s\n" , opts . name )
2018-09-24 16:25:57 +03:00
return nil
}
func promptTarget ( ) ( string , error ) {
2020-06-28 19:26:29 +03:00
// TODO: use the reusable prompt from the input package
2018-09-24 16:25:57 +03:00
targets := bridge . Targets ( )
for {
2018-10-03 22:05:19 +03:00
for i , target := range targets {
fmt . Printf ( "[%d]: %s\n" , i + 1 , target )
}
fmt . Printf ( "target: " )
2018-09-24 16:25:57 +03:00
line , err := bufio . NewReader ( os . Stdin ) . ReadString ( '\n' )
2019-06-05 02:42:36 +03:00
2018-09-24 16:25:57 +03:00
if err != nil {
2019-06-07 02:28:52 +03:00
return "" , err
2018-09-24 16:25:57 +03:00
}
2019-11-25 17:08:48 +03:00
line = strings . TrimSpace ( line )
2018-09-24 16:25:57 +03:00
2018-10-03 22:05:19 +03:00
index , err := strconv . Atoi ( line )
if err != nil || index <= 0 || index > len ( targets ) {
fmt . Println ( "invalid input" )
continue
2018-09-24 16:25:57 +03:00
}
2018-10-03 22:05:19 +03:00
return targets [ index - 1 ] , nil
2018-09-24 16:25:57 +03:00
}
}
2019-12-08 23:15:06 +03:00
func promptName ( repo repository . RepoConfig ) ( string , error ) {
2020-06-28 19:26:29 +03:00
// TODO: use the reusable prompt from the input package
const defaultName = "default"
2019-11-19 22:20:19 +03:00
defaultExist := core . BridgeExist ( repo , defaultName )
2019-07-07 13:15:01 +03:00
for {
2019-11-19 22:20:19 +03:00
if defaultExist {
fmt . Printf ( "name: " )
} else {
fmt . Printf ( "name [%s]: " , defaultName )
}
2018-09-24 16:25:57 +03:00
2019-07-07 13:15:01 +03:00
line , err := bufio . NewReader ( os . Stdin ) . ReadString ( '\n' )
if err != nil {
return "" , err
}
2018-09-24 16:25:57 +03:00
2019-11-25 17:08:48 +03:00
line = strings . TrimSpace ( line )
2018-09-24 16:25:57 +03:00
2019-07-07 13:15:01 +03:00
name := line
2019-11-19 22:20:19 +03:00
if defaultExist && name == "" {
continue
}
2019-07-07 13:15:01 +03:00
if name == "" {
name = defaultName
}
2018-09-24 16:25:57 +03:00
2019-07-07 13:15:01 +03:00
if ! core . BridgeExist ( repo , name ) {
return name , nil
}
fmt . Println ( "a bridge with the same name already exist" )
}
2018-09-24 16:25:57 +03:00
}