consolidate survey functions
This commit is contained in:
parent
6b0510f81a
commit
cbb8253544
8 changed files with 108 additions and 94 deletions
|
|
@ -7,7 +7,6 @@ import (
|
|||
"os"
|
||||
|
||||
"github.com/github/ghcs/api"
|
||||
"github.com/github/ghcs/internal/codespaces"
|
||||
"github.com/skratchdot/open-golang/open"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
|
@ -47,9 +46,9 @@ func code(codespaceName string, useInsiders bool) error {
|
|||
}
|
||||
|
||||
if codespaceName == "" {
|
||||
codespace, err := codespaces.ChooseCodespace(ctx, apiClient, user)
|
||||
codespace, err := chooseCodespace(ctx, apiClient, user)
|
||||
if err != nil {
|
||||
if err == codespaces.ErrNoCodespaces {
|
||||
if err == errNoCodespaces {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("error choosing codespace: %v", err)
|
||||
|
|
|
|||
101
cmd/ghcs/common.go
Normal file
101
cmd/ghcs/common.go
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
package main
|
||||
|
||||
// This file defines functions common to the entire ghcs command set.
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/github/ghcs/api"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
var errNoCodespaces = errors.New("You have no codespaces.")
|
||||
|
||||
func chooseCodespace(ctx context.Context, apiClient *api.API, user *api.User) (*api.Codespace, error) {
|
||||
codespaces, err := apiClient.ListCodespaces(ctx, user)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting codespaces: %v", err)
|
||||
}
|
||||
|
||||
if len(codespaces) == 0 {
|
||||
return nil, errNoCodespaces
|
||||
}
|
||||
|
||||
sort.Slice(codespaces, func(i, j int) bool {
|
||||
return codespaces[i].CreatedAt > codespaces[j].CreatedAt
|
||||
})
|
||||
|
||||
codespacesByName := make(map[string]*api.Codespace)
|
||||
codespacesNames := make([]string, 0, len(codespaces))
|
||||
for _, codespace := range codespaces {
|
||||
codespacesByName[codespace.Name] = codespace
|
||||
codespacesNames = append(codespacesNames, codespace.Name)
|
||||
}
|
||||
|
||||
sshSurvey := []*survey.Question{
|
||||
{
|
||||
Name: "codespace",
|
||||
Prompt: &survey.Select{
|
||||
Message: "Choose codespace:",
|
||||
Options: codespacesNames,
|
||||
Default: codespacesNames[0],
|
||||
},
|
||||
Validate: survey.Required,
|
||||
},
|
||||
}
|
||||
|
||||
var answers struct {
|
||||
Codespace string
|
||||
}
|
||||
if err := ask(sshSurvey, &answers); err != nil {
|
||||
return nil, fmt.Errorf("error getting answers: %v", err)
|
||||
}
|
||||
|
||||
codespace := codespacesByName[answers.Codespace]
|
||||
return codespace, nil
|
||||
}
|
||||
|
||||
func getOrChooseCodespace(ctx context.Context, apiClient *api.API, user *api.User, codespaceName string) (codespace *api.Codespace, token string, err error) {
|
||||
if codespaceName == "" {
|
||||
codespace, err = chooseCodespace(ctx, apiClient, user)
|
||||
if err != nil {
|
||||
if err == errNoCodespaces {
|
||||
return nil, "", err
|
||||
}
|
||||
return nil, "", fmt.Errorf("choosing codespace: %v", err)
|
||||
}
|
||||
codespaceName = codespace.Name
|
||||
|
||||
token, err = apiClient.GetCodespaceToken(ctx, user.Login, codespaceName)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("getting codespace token: %v", err)
|
||||
}
|
||||
} else {
|
||||
token, err = apiClient.GetCodespaceToken(ctx, user.Login, codespaceName)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("getting codespace token for given codespace: %v", err)
|
||||
}
|
||||
|
||||
codespace, err = apiClient.GetCodespace(ctx, token, user.Login, codespaceName)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("getting full codespace details: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return codespace, token, nil
|
||||
}
|
||||
|
||||
var hasTTY = term.IsTerminal(0) && term.IsTerminal(1) // is process connected to a terminal?
|
||||
|
||||
// ask asks survey questions on the terminal, using standard options.
|
||||
// It fails unless hasTTY, but ideally callers should avoid calling it in that case.
|
||||
func ask(qs []*survey.Question, response interface{}) error {
|
||||
if !hasTTY {
|
||||
return fmt.Errorf("no terminal")
|
||||
}
|
||||
return survey.Ask(qs, response, survey.WithShowCursor(true))
|
||||
}
|
||||
|
|
@ -286,8 +286,3 @@ func getMachineName(ctx context.Context, machine string, user *api.User, repo *a
|
|||
|
||||
return machine, nil
|
||||
}
|
||||
|
||||
// ask asks survery questions using standard options.
|
||||
func ask(qs []*survey.Question, response interface{}) error {
|
||||
return survey.Ask(qs, response, survey.WithShowCursor(true))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import (
|
|||
|
||||
"github.com/github/ghcs/api"
|
||||
"github.com/github/ghcs/cmd/ghcs/output"
|
||||
"github.com/github/ghcs/internal/codespaces"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
|
@ -63,7 +62,7 @@ func delete_(codespaceName string) error {
|
|||
return fmt.Errorf("error getting user: %v", err)
|
||||
}
|
||||
|
||||
codespace, token, err := codespaces.GetOrChooseCodespace(ctx, apiClient, user, codespaceName)
|
||||
codespace, token, err := getOrChooseCodespace(ctx, apiClient, user, codespaceName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get or choose codespace: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ func logs(ctx context.Context, tail bool, codespaceName string) error {
|
|||
return fmt.Errorf("getting user: %v", err)
|
||||
}
|
||||
|
||||
codespace, token, err := codespaces.GetOrChooseCodespace(ctx, apiClient, user, codespaceName)
|
||||
codespace, token, err := getOrChooseCodespace(ctx, apiClient, user, codespaceName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get or choose codespace: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,9 +67,9 @@ func ports(opts *portsOptions) error {
|
|||
return fmt.Errorf("error getting user: %v", err)
|
||||
}
|
||||
|
||||
codespace, token, err := codespaces.GetOrChooseCodespace(ctx, apiClient, user, opts.codespaceName)
|
||||
codespace, token, err := getOrChooseCodespace(ctx, apiClient, user, opts.codespaceName)
|
||||
if err != nil {
|
||||
if err == codespaces.ErrNoCodespaces {
|
||||
if err == errNoCodespaces {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("error choosing codespace: %v", err)
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ func ssh(ctx context.Context, sshProfile, codespaceName string, localSSHServerPo
|
|||
return fmt.Errorf("error getting user: %v", err)
|
||||
}
|
||||
|
||||
codespace, token, err := codespaces.GetOrChooseCodespace(ctx, apiClient, user, codespaceName)
|
||||
codespace, token, err := getOrChooseCodespace(ctx, apiClient, user, codespaceName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get or choose codespace: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,62 +4,12 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/github/ghcs/api"
|
||||
"github.com/github/go-liveshare"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNoCodespaces = errors.New("You have no codespaces.")
|
||||
)
|
||||
|
||||
func ChooseCodespace(ctx context.Context, apiClient *api.API, user *api.User) (*api.Codespace, error) {
|
||||
codespaces, err := apiClient.ListCodespaces(ctx, user)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting codespaces: %v", err)
|
||||
}
|
||||
|
||||
if len(codespaces) == 0 {
|
||||
return nil, ErrNoCodespaces
|
||||
}
|
||||
|
||||
sort.Slice(codespaces, func(i, j int) bool {
|
||||
return codespaces[i].CreatedAt > codespaces[j].CreatedAt
|
||||
})
|
||||
|
||||
codespacesByName := make(map[string]*api.Codespace)
|
||||
codespacesNames := make([]string, 0, len(codespaces))
|
||||
for _, codespace := range codespaces {
|
||||
codespacesByName[codespace.Name] = codespace
|
||||
codespacesNames = append(codespacesNames, codespace.Name)
|
||||
}
|
||||
|
||||
sshSurvey := []*survey.Question{
|
||||
{
|
||||
Name: "codespace",
|
||||
Prompt: &survey.Select{
|
||||
Message: "Choose codespace:",
|
||||
Options: codespacesNames,
|
||||
Default: codespacesNames[0],
|
||||
},
|
||||
Validate: survey.Required,
|
||||
},
|
||||
}
|
||||
|
||||
answers := struct {
|
||||
Codespace string
|
||||
}{}
|
||||
if err := survey.Ask(sshSurvey, &answers); err != nil {
|
||||
return nil, fmt.Errorf("error getting answers: %v", err)
|
||||
}
|
||||
|
||||
codespace := codespacesByName[answers.Codespace]
|
||||
return codespace, nil
|
||||
}
|
||||
|
||||
type logger interface {
|
||||
Print(v ...interface{}) (int, error)
|
||||
Println(v ...interface{}) (int, error)
|
||||
|
|
@ -123,33 +73,3 @@ func ConnectToLiveshare(ctx context.Context, log logger, apiClient *api.API, use
|
|||
|
||||
return lsclient.JoinWorkspace(ctx)
|
||||
}
|
||||
|
||||
func GetOrChooseCodespace(ctx context.Context, apiClient *api.API, user *api.User, codespaceName string) (codespace *api.Codespace, token string, err error) {
|
||||
if codespaceName == "" {
|
||||
codespace, err = ChooseCodespace(ctx, apiClient, user)
|
||||
if err != nil {
|
||||
if err == ErrNoCodespaces {
|
||||
return nil, "", err
|
||||
}
|
||||
return nil, "", fmt.Errorf("choosing codespace: %v", err)
|
||||
}
|
||||
codespaceName = codespace.Name
|
||||
|
||||
token, err = apiClient.GetCodespaceToken(ctx, user.Login, codespaceName)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("getting codespace token: %v", err)
|
||||
}
|
||||
} else {
|
||||
token, err = apiClient.GetCodespaceToken(ctx, user.Login, codespaceName)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("getting codespace token for given codespace: %v", err)
|
||||
}
|
||||
|
||||
codespace, err = apiClient.GetCodespace(ctx, token, user.Login, codespaceName)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("getting full codespace details: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return codespace, token, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue