Change choose codespace prompt
- Repo + branch is favored - Codespace name is included to disambiguate between two codespaces - Move Codespace model out of out API into its own package - Update call sites and group behavior under codespace.Codespace
This commit is contained in:
parent
93cea6d370
commit
975bd7c08a
12 changed files with 237 additions and 175 deletions
|
|
@ -38,6 +38,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cli/cli/v2/internal/codespaces/codespace"
|
||||
"github.com/opentracing/opentracing-go"
|
||||
)
|
||||
|
||||
|
|
@ -140,46 +141,7 @@ func (a *API) GetRepository(ctx context.Context, nwo string) (*Repository, error
|
|||
return &response, nil
|
||||
}
|
||||
|
||||
type Codespace struct {
|
||||
Name string `json:"name"`
|
||||
GUID string `json:"guid"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
LastUsedAt string `json:"last_used_at"`
|
||||
Branch string `json:"branch"`
|
||||
RepositoryName string `json:"repository_name"`
|
||||
RepositoryNWO string `json:"repository_nwo"`
|
||||
OwnerLogin string `json:"owner_login"`
|
||||
Environment CodespaceEnvironment `json:"environment"`
|
||||
}
|
||||
|
||||
type CodespaceEnvironment struct {
|
||||
State string `json:"state"`
|
||||
Connection CodespaceEnvironmentConnection `json:"connection"`
|
||||
GitStatus CodespaceEnvironmentGitStatus `json:"gitStatus"`
|
||||
}
|
||||
|
||||
type CodespaceEnvironmentGitStatus struct {
|
||||
Ahead int `json:"ahead"`
|
||||
Behind int `json:"behind"`
|
||||
Branch string `json:"branch"`
|
||||
Commit string `json:"commit"`
|
||||
HasUnpushedChanges bool `json:"hasUnpushedChanges"`
|
||||
HasUncommitedChanges bool `json:"hasUncommitedChanges"`
|
||||
}
|
||||
|
||||
const (
|
||||
CodespaceEnvironmentStateAvailable = "Available"
|
||||
)
|
||||
|
||||
type CodespaceEnvironmentConnection struct {
|
||||
SessionID string `json:"sessionId"`
|
||||
SessionToken string `json:"sessionToken"`
|
||||
RelayEndpoint string `json:"relayEndpoint"`
|
||||
RelaySAS string `json:"relaySas"`
|
||||
HostPublicKeys []string `json:"hostPublicKeys"`
|
||||
}
|
||||
|
||||
func (a *API) ListCodespaces(ctx context.Context) ([]*Codespace, error) {
|
||||
func (a *API) ListCodespaces(ctx context.Context) ([]*codespace.Codespace, error) {
|
||||
req, err := http.NewRequest(
|
||||
http.MethodGet, a.githubAPI+"/user/codespaces", nil,
|
||||
)
|
||||
|
|
@ -204,7 +166,7 @@ func (a *API) ListCodespaces(ctx context.Context) ([]*Codespace, error) {
|
|||
}
|
||||
|
||||
var response struct {
|
||||
Codespaces []*Codespace `json:"codespaces"`
|
||||
Codespaces []*codespace.Codespace `json:"codespaces"`
|
||||
}
|
||||
if err := json.Unmarshal(b, &response); err != nil {
|
||||
return nil, fmt.Errorf("error unmarshaling response: %w", err)
|
||||
|
|
@ -267,10 +229,10 @@ func (a *API) GetCodespaceToken(ctx context.Context, ownerLogin, codespaceName s
|
|||
return response.RepositoryToken, nil
|
||||
}
|
||||
|
||||
func (a *API) GetCodespace(ctx context.Context, token, owner, codespace string) (*Codespace, error) {
|
||||
func (a *API) GetCodespace(ctx context.Context, token, owner, codespaceName string) (*codespace.Codespace, error) {
|
||||
req, err := http.NewRequest(
|
||||
http.MethodGet,
|
||||
a.githubAPI+"/vscs_internal/user/"+owner+"/codespaces/"+codespace,
|
||||
a.githubAPI+"/vscs_internal/user/"+owner+"/codespaces/"+codespaceName,
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
|
|
@ -294,7 +256,7 @@ func (a *API) GetCodespace(ctx context.Context, token, owner, codespace string)
|
|||
return nil, jsonErrorResponse(b)
|
||||
}
|
||||
|
||||
var response Codespace
|
||||
var response codespace.Codespace
|
||||
if err := json.Unmarshal(b, &response); err != nil {
|
||||
return nil, fmt.Errorf("error unmarshaling response: %w", err)
|
||||
}
|
||||
|
|
@ -302,7 +264,7 @@ func (a *API) GetCodespace(ctx context.Context, token, owner, codespace string)
|
|||
return &response, nil
|
||||
}
|
||||
|
||||
func (a *API) StartCodespace(ctx context.Context, token string, codespace *Codespace) error {
|
||||
func (a *API) StartCodespace(ctx context.Context, token string, codespace *codespace.Codespace) error {
|
||||
req, err := http.NewRequest(
|
||||
http.MethodPost,
|
||||
a.githubAPI+"/vscs_internal/proxy/environments/"+codespace.GUID+"/start",
|
||||
|
|
@ -429,7 +391,7 @@ type CreateCodespaceParams struct {
|
|||
|
||||
// CreateCodespace creates a codespace with the given parameters and returns a non-nil error if it
|
||||
// fails to create.
|
||||
func (a *API) CreateCodespace(ctx context.Context, params *CreateCodespaceParams) (*Codespace, error) {
|
||||
func (a *API) CreateCodespace(ctx context.Context, params *CreateCodespaceParams) (*codespace.Codespace, error) {
|
||||
codespace, err := a.startCreate(ctx, params.RepositoryID, params.Machine, params.Branch, params.Location)
|
||||
if err != errProvisioningInProgress {
|
||||
return codespace, err
|
||||
|
|
@ -482,7 +444,7 @@ var errProvisioningInProgress = errors.New("provisioning in progress")
|
|||
// It may return success or an error, or errProvisioningInProgress indicating that the operation
|
||||
// did not complete before the GitHub API's time limit for RPCs (10s), in which case the caller
|
||||
// must poll the server to learn the outcome.
|
||||
func (a *API) startCreate(ctx context.Context, repoID int, machine, branch, location string) (*Codespace, error) {
|
||||
func (a *API) startCreate(ctx context.Context, repoID int, machine, branch, location string) (*codespace.Codespace, error) {
|
||||
requestBody, err := json.Marshal(startCreateRequest{repoID, branch, location, machine})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error marshaling request: %w", err)
|
||||
|
|
@ -512,7 +474,7 @@ func (a *API) startCreate(ctx context.Context, repoID int, machine, branch, loca
|
|||
return nil, errProvisioningInProgress // RPC finished before result of creation known
|
||||
}
|
||||
|
||||
var response Codespace
|
||||
var response codespace.Codespace
|
||||
if err := json.Unmarshal(b, &response); err != nil {
|
||||
return nil, fmt.Errorf("error unmarshaling response: %w", err)
|
||||
}
|
||||
|
|
@ -554,7 +516,7 @@ type getCodespaceRepositoryContentsResponse struct {
|
|||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
func (a *API) GetCodespaceRepositoryContents(ctx context.Context, codespace *Codespace, path string) ([]byte, error) {
|
||||
func (a *API) GetCodespaceRepositoryContents(ctx context.Context, codespace *codespace.Codespace, path string) ([]byte, error) {
|
||||
req, err := http.NewRequest(http.MethodGet, a.githubAPI+"/repos/"+codespace.RepositoryNWO+"/contents/"+path, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating request: %w", err)
|
||||
|
|
|
|||
|
|
@ -7,10 +7,12 @@ import (
|
|||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/cli/cli/v2/internal/codespaces/codespace"
|
||||
)
|
||||
|
||||
func TestListCodespaces(t *testing.T) {
|
||||
codespaces := []*Codespace{
|
||||
codespaces := []*codespace.Codespace{
|
||||
{
|
||||
Name: "testcodespace",
|
||||
CreatedAt: "2021-08-09T10:10:24+02:00",
|
||||
|
|
@ -19,7 +21,7 @@ func TestListCodespaces(t *testing.T) {
|
|||
}
|
||||
svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
response := struct {
|
||||
Codespaces []*Codespace `json:"codespaces"`
|
||||
Codespaces []*codespace.Codespace `json:"codespaces"`
|
||||
}{
|
||||
Codespaces: codespaces,
|
||||
}
|
||||
|
|
|
|||
76
internal/codespaces/codespace/codespace.go
Normal file
76
internal/codespaces/codespace/codespace.go
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
package codespace
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Codespace struct {
|
||||
Name string `json:"name"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
LastUsedAt string `json:"last_used_at"`
|
||||
GUID string `json:"guid"`
|
||||
Branch string `json:"branch"`
|
||||
RepositoryName string `json:"repository_name"`
|
||||
RepositoryNWO string `json:"repository_nwo"`
|
||||
OwnerLogin string `json:"owner_login"`
|
||||
Environment Environment `json:"environment"`
|
||||
}
|
||||
|
||||
// DisplayName returns the repository nwo and branch.
|
||||
// If includeName is true, the name of the codespace is included.
|
||||
// If includeGitStatus is true, the branch will include a star if
|
||||
// the codespace has unsaved changes.
|
||||
func (c *Codespace) DisplayName(includeName, includeGitStatus bool) string {
|
||||
branch := c.Branch
|
||||
if includeGitStatus {
|
||||
branch = c.BranchWithGitStatus()
|
||||
}
|
||||
|
||||
if includeName {
|
||||
return fmt.Sprintf(
|
||||
"%s: %s [%s]", c.RepositoryNWO, branch, c.Name,
|
||||
)
|
||||
}
|
||||
return c.RepositoryNWO + ": " + branch
|
||||
}
|
||||
|
||||
// BranchWithGitStatus returns the branch with a star
|
||||
// if the branch is currently being worked on.
|
||||
func (c *Codespace) BranchWithGitStatus() string {
|
||||
if c.HasUnsavedChanges() {
|
||||
return c.Branch + "*"
|
||||
}
|
||||
|
||||
return c.Branch
|
||||
}
|
||||
|
||||
// HasUnsavedChanges returns whether the environment has
|
||||
// unsaved changes.
|
||||
func (c *Codespace) HasUnsavedChanges() bool {
|
||||
return c.Environment.GitStatus.HasUncommitedChanges || c.Environment.GitStatus.HasUnpushedChanges
|
||||
}
|
||||
|
||||
type Environment struct {
|
||||
State string `json:"state"`
|
||||
Connection EnvironmentConnection `json:"connection"`
|
||||
GitStatus EnvironmentGitStatus `json:"gitStatus"`
|
||||
}
|
||||
|
||||
type EnvironmentGitStatus struct {
|
||||
Ahead int `json:"ahead"`
|
||||
Behind int `json:"behind"`
|
||||
Branch string `json:"branch"`
|
||||
Commit string `json:"commit"`
|
||||
HasUnpushedChanges bool `json:"hasUnpushedChanges"`
|
||||
HasUncommitedChanges bool `json:"hasUncommitedChanges"`
|
||||
}
|
||||
|
||||
const (
|
||||
EnvironmentStateAvailable = "Available"
|
||||
)
|
||||
|
||||
type EnvironmentConnection struct {
|
||||
SessionID string `json:"sessionId"`
|
||||
SessionToken string `json:"sessionToken"`
|
||||
RelayEndpoint string `json:"relayEndpoint"`
|
||||
RelaySAS string `json:"relaySas"`
|
||||
HostPublicKeys []string `json:"hostPublicKeys"`
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ import (
|
|||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/cli/cli/v2/internal/codespaces/api"
|
||||
"github.com/cli/cli/v2/internal/codespaces/codespace"
|
||||
"github.com/cli/cli/v2/pkg/liveshare"
|
||||
)
|
||||
|
||||
|
|
@ -15,33 +15,33 @@ type logger interface {
|
|||
Println(v ...interface{}) (int, error)
|
||||
}
|
||||
|
||||
func connectionReady(codespace *api.Codespace) bool {
|
||||
return codespace.Environment.Connection.SessionID != "" &&
|
||||
codespace.Environment.Connection.SessionToken != "" &&
|
||||
codespace.Environment.Connection.RelayEndpoint != "" &&
|
||||
codespace.Environment.Connection.RelaySAS != "" &&
|
||||
codespace.Environment.State == api.CodespaceEnvironmentStateAvailable
|
||||
func connectionReady(cs *codespace.Codespace) bool {
|
||||
return cs.Environment.Connection.SessionID != "" &&
|
||||
cs.Environment.Connection.SessionToken != "" &&
|
||||
cs.Environment.Connection.RelayEndpoint != "" &&
|
||||
cs.Environment.Connection.RelaySAS != "" &&
|
||||
cs.Environment.State == codespace.EnvironmentStateAvailable
|
||||
}
|
||||
|
||||
type apiClient interface {
|
||||
GetCodespace(ctx context.Context, token, user, name string) (*api.Codespace, error)
|
||||
GetCodespace(ctx context.Context, token, user, name string) (*codespace.Codespace, error)
|
||||
GetCodespaceToken(ctx context.Context, user, codespace string) (string, error)
|
||||
StartCodespace(ctx context.Context, token string, codespace *api.Codespace) error
|
||||
StartCodespace(ctx context.Context, token string, codespace *codespace.Codespace) error
|
||||
}
|
||||
|
||||
// ConnectToLiveshare waits for a Codespace to become running,
|
||||
// and connects to it using a Live Share session.
|
||||
func ConnectToLiveshare(ctx context.Context, log logger, apiClient apiClient, userLogin, token string, codespace *api.Codespace) (*liveshare.Session, error) {
|
||||
func ConnectToLiveshare(ctx context.Context, log logger, apiClient apiClient, userLogin, token string, cs *codespace.Codespace) (*liveshare.Session, error) {
|
||||
var startedCodespace bool
|
||||
if codespace.Environment.State != api.CodespaceEnvironmentStateAvailable {
|
||||
if cs.Environment.State != codespace.EnvironmentStateAvailable {
|
||||
startedCodespace = true
|
||||
log.Print("Starting your codespace...")
|
||||
if err := apiClient.StartCodespace(ctx, token, codespace); err != nil {
|
||||
if err := apiClient.StartCodespace(ctx, token, cs); err != nil {
|
||||
return nil, fmt.Errorf("error starting codespace: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
for retries := 0; !connectionReady(codespace); retries++ {
|
||||
for retries := 0; !connectionReady(cs); retries++ {
|
||||
if retries > 1 {
|
||||
if retries%2 == 0 {
|
||||
log.Print(".")
|
||||
|
|
@ -55,7 +55,7 @@ func ConnectToLiveshare(ctx context.Context, log logger, apiClient apiClient, us
|
|||
}
|
||||
|
||||
var err error
|
||||
codespace, err = apiClient.GetCodespace(ctx, token, userLogin, codespace.Name)
|
||||
cs, err = apiClient.GetCodespace(ctx, token, userLogin, cs.Name)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting codespace: %w", err)
|
||||
}
|
||||
|
|
@ -68,10 +68,10 @@ func ConnectToLiveshare(ctx context.Context, log logger, apiClient apiClient, us
|
|||
log.Println("Connecting to your codespace...")
|
||||
|
||||
return liveshare.Connect(ctx, liveshare.Options{
|
||||
SessionID: codespace.Environment.Connection.SessionID,
|
||||
SessionToken: codespace.Environment.Connection.SessionToken,
|
||||
RelaySAS: codespace.Environment.Connection.RelaySAS,
|
||||
RelayEndpoint: codespace.Environment.Connection.RelayEndpoint,
|
||||
HostPublicKeys: codespace.Environment.Connection.HostPublicKeys,
|
||||
SessionID: cs.Environment.Connection.SessionID,
|
||||
SessionToken: cs.Environment.Connection.SessionToken,
|
||||
RelaySAS: cs.Environment.Connection.RelaySAS,
|
||||
RelayEndpoint: cs.Environment.Connection.RelayEndpoint,
|
||||
HostPublicKeys: cs.Environment.Connection.HostPublicKeys,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/cli/cli/v2/internal/codespaces/api"
|
||||
"github.com/cli/cli/v2/internal/codespaces/codespace"
|
||||
"github.com/cli/cli/v2/pkg/liveshare"
|
||||
)
|
||||
|
||||
|
|
@ -36,13 +37,13 @@ type PostCreateState struct {
|
|||
// PollPostCreateStates watches for state changes in a codespace,
|
||||
// and calls the supplied poller for each batch of state changes.
|
||||
// It runs until it encounters an error, including cancellation of the context.
|
||||
func PollPostCreateStates(ctx context.Context, log logger, apiClient apiClient, user *api.User, codespace *api.Codespace, poller func([]PostCreateState)) (err error) {
|
||||
token, err := apiClient.GetCodespaceToken(ctx, user.Login, codespace.Name)
|
||||
func PollPostCreateStates(ctx context.Context, log logger, apiClient apiClient, user *api.User, c *codespace.Codespace, poller func([]PostCreateState)) (err error) {
|
||||
token, err := apiClient.GetCodespaceToken(ctx, user.Login, c.Name)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting codespace token: %w", err)
|
||||
}
|
||||
|
||||
session, err := ConnectToLiveshare(ctx, log, apiClient, user.Login, token, codespace)
|
||||
session, err := ConnectToLiveshare(ctx, log, apiClient, user.Login, token, c)
|
||||
if err != nil {
|
||||
return fmt.Errorf("connect to Live Share: %w", err)
|
||||
}
|
||||
|
|
@ -83,7 +84,7 @@ func PollPostCreateStates(ctx context.Context, log logger, apiClient apiClient,
|
|||
return fmt.Errorf("connection failed: %w", err)
|
||||
|
||||
case <-t.C:
|
||||
states, err := getPostCreateOutput(ctx, localPort, codespace, sshUser)
|
||||
states, err := getPostCreateOutput(ctx, localPort, sshUser)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get post create output: %w", err)
|
||||
}
|
||||
|
|
@ -93,7 +94,7 @@ func PollPostCreateStates(ctx context.Context, log logger, apiClient apiClient,
|
|||
}
|
||||
}
|
||||
|
||||
func getPostCreateOutput(ctx context.Context, tunnelPort int, codespace *api.Codespace, user string) ([]PostCreateState, error) {
|
||||
func getPostCreateOutput(ctx context.Context, tunnelPort int, user string) ([]PostCreateState, error) {
|
||||
cmd, err := NewRemoteCommand(
|
||||
ctx, tunnelPort, fmt.Sprintf("%s@localhost", user),
|
||||
"cat /workspaces/.codespaces/shared/postCreateOutput.json",
|
||||
|
|
|
|||
|
|
@ -9,10 +9,12 @@ import (
|
|||
"io"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/AlecAivazis/survey/v2/terminal"
|
||||
"github.com/cli/cli/v2/internal/codespaces/api"
|
||||
"github.com/cli/cli/v2/internal/codespaces/codespace"
|
||||
"github.com/cli/cli/v2/pkg/cmd/codespace/output"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/term"
|
||||
|
|
@ -34,21 +36,21 @@ func NewApp(logger *output.Logger, apiClient apiClient) *App {
|
|||
type apiClient interface {
|
||||
GetUser(ctx context.Context) (*api.User, error)
|
||||
GetCodespaceToken(ctx context.Context, user, name string) (string, error)
|
||||
GetCodespace(ctx context.Context, token, user, name string) (*api.Codespace, error)
|
||||
ListCodespaces(ctx context.Context) ([]*api.Codespace, error)
|
||||
GetCodespace(ctx context.Context, token, user, name string) (*codespace.Codespace, error)
|
||||
ListCodespaces(ctx context.Context) ([]*codespace.Codespace, error)
|
||||
DeleteCodespace(ctx context.Context, user, name string) error
|
||||
StartCodespace(ctx context.Context, token string, codespace *api.Codespace) error
|
||||
CreateCodespace(ctx context.Context, params *api.CreateCodespaceParams) (*api.Codespace, error)
|
||||
StartCodespace(ctx context.Context, token string, codespace *codespace.Codespace) error
|
||||
CreateCodespace(ctx context.Context, params *api.CreateCodespaceParams) (*codespace.Codespace, error)
|
||||
GetRepository(ctx context.Context, nwo string) (*api.Repository, error)
|
||||
AuthorizedKeys(ctx context.Context, user string) ([]byte, error)
|
||||
GetCodespaceRegionLocation(ctx context.Context) (string, error)
|
||||
GetCodespacesSKUs(ctx context.Context, user *api.User, repository *api.Repository, branch, location string) ([]*api.SKU, error)
|
||||
GetCodespaceRepositoryContents(ctx context.Context, codespace *api.Codespace, path string) ([]byte, error)
|
||||
GetCodespaceRepositoryContents(ctx context.Context, codespace *codespace.Codespace, path string) ([]byte, error)
|
||||
}
|
||||
|
||||
var errNoCodespaces = errors.New("you have no codespaces")
|
||||
|
||||
func chooseCodespace(ctx context.Context, apiClient apiClient) (*api.Codespace, error) {
|
||||
func chooseCodespace(ctx context.Context, apiClient apiClient) (*codespace.Codespace, error) {
|
||||
codespaces, err := apiClient.ListCodespaces(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting codespaces: %w", err)
|
||||
|
|
@ -56,7 +58,9 @@ func chooseCodespace(ctx context.Context, apiClient apiClient) (*api.Codespace,
|
|||
return chooseCodespaceFromList(ctx, codespaces)
|
||||
}
|
||||
|
||||
func chooseCodespaceFromList(ctx context.Context, codespaces []*api.Codespace) (*api.Codespace, error) {
|
||||
// chooseCodespaceFromList returns the selected codespace from the list,
|
||||
// or an error if there are no codespaces.
|
||||
func chooseCodespaceFromList(ctx context.Context, codespaces []*codespace.Codespace) (*codespace.Codespace, error) {
|
||||
if len(codespaces) == 0 {
|
||||
return nil, errNoCodespaces
|
||||
}
|
||||
|
|
@ -65,14 +69,38 @@ func chooseCodespaceFromList(ctx context.Context, codespaces []*api.Codespace) (
|
|||
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)
|
||||
type codespaceWithIndex struct {
|
||||
cs *codespace.Codespace
|
||||
idx int
|
||||
}
|
||||
|
||||
sshSurvey := []*survey.Question{
|
||||
codespacesByName := make(map[string]codespaceWithIndex)
|
||||
codespacesNames := make([]string, 0, len(codespaces))
|
||||
for _, cs := range codespaces {
|
||||
csName := cs.DisplayName(false, false)
|
||||
displayNameWithGitStatus := cs.DisplayName(false, true)
|
||||
|
||||
if seenCodespace, ok := codespacesByName[csName]; ok {
|
||||
// there is an existing codespace on the repo and branch
|
||||
// we need to disambiguate by adding the codespace name
|
||||
// to the existing entry and the one we are adding now
|
||||
fullDisplayName := seenCodespace.cs.DisplayName(true, false)
|
||||
fullDisplayNameWithGitStatus := seenCodespace.cs.DisplayName(true, true)
|
||||
|
||||
codespacesByName[fullDisplayName] = codespaceWithIndex{seenCodespace.cs, seenCodespace.idx}
|
||||
codespacesNames[seenCodespace.idx] = fullDisplayNameWithGitStatus
|
||||
delete(codespacesByName, csName) // delete the existing map entry with old name
|
||||
|
||||
// update this codespace names to include the name to disambiguate
|
||||
csName = cs.DisplayName(true, false)
|
||||
displayNameWithGitStatus = cs.DisplayName(true, true)
|
||||
}
|
||||
|
||||
codespacesByName[csName] = codespaceWithIndex{cs, len(codespacesNames)}
|
||||
codespacesNames = append(codespacesNames, displayNameWithGitStatus)
|
||||
}
|
||||
|
||||
csSurvey := []*survey.Question{
|
||||
{
|
||||
Name: "codespace",
|
||||
Prompt: &survey.Select{
|
||||
|
|
@ -87,17 +115,18 @@ func chooseCodespaceFromList(ctx context.Context, codespaces []*api.Codespace) (
|
|||
var answers struct {
|
||||
Codespace string
|
||||
}
|
||||
if err := ask(sshSurvey, &answers); err != nil {
|
||||
if err := ask(csSurvey, &answers); err != nil {
|
||||
return nil, fmt.Errorf("error getting answers: %w", err)
|
||||
}
|
||||
|
||||
codespace := codespacesByName[answers.Codespace]
|
||||
selectedCodespace := strings.Replace(answers.Codespace, "*", "", -1)
|
||||
codespace := codespacesByName[selectedCodespace].cs
|
||||
return codespace, nil
|
||||
}
|
||||
|
||||
// getOrChooseCodespace prompts the user to choose a codespace if the codespaceName is empty.
|
||||
// It then fetches the codespace token and the codespace record.
|
||||
func getOrChooseCodespace(ctx context.Context, apiClient apiClient, user *api.User, codespaceName string) (codespace *api.Codespace, token string, err error) {
|
||||
func getOrChooseCodespace(ctx context.Context, apiClient apiClient, user *api.User, codespaceName string) (codespace *codespace.Codespace, token string, err error) {
|
||||
if codespaceName == "" {
|
||||
codespace, err = chooseCodespace(ctx, apiClient)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/cli/cli/v2/internal/codespaces"
|
||||
"github.com/cli/cli/v2/internal/codespaces/api"
|
||||
"github.com/cli/cli/v2/internal/codespaces/codespace"
|
||||
"github.com/cli/cli/v2/pkg/cmd/codespace/output"
|
||||
"github.com/fatih/camelcase"
|
||||
"github.com/spf13/cobra"
|
||||
|
|
@ -108,7 +109,7 @@ func (a *App) Create(ctx context.Context, opts createOptions) error {
|
|||
// showStatus polls the codespace for a list of post create states and their status. It will keep polling
|
||||
// until all states have finished. Once all states have finished, we poll once more to check if any new
|
||||
// states have been introduced and stop polling otherwise.
|
||||
func showStatus(ctx context.Context, log *output.Logger, apiClient apiClient, user *api.User, codespace *api.Codespace) error {
|
||||
func showStatus(ctx context.Context, log *output.Logger, apiClient apiClient, user *api.User, cs *codespace.Codespace) error {
|
||||
var lastState codespaces.PostCreateState
|
||||
var breakNextState bool
|
||||
|
||||
|
|
@ -157,7 +158,7 @@ func showStatus(ctx context.Context, log *output.Logger, apiClient apiClient, us
|
|||
}
|
||||
}
|
||||
|
||||
err := codespaces.PollPostCreateStates(ctx, log, apiClient, user, codespace, poller)
|
||||
err := codespaces.PollPostCreateStates(ctx, log, apiClient, user, cs, poller)
|
||||
if err != nil {
|
||||
if errors.Is(err, context.Canceled) && breakNextState {
|
||||
return nil // we cancelled the context to stop polling, we can ignore the error
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/cli/cli/v2/internal/codespaces/api"
|
||||
"github.com/cli/cli/v2/internal/codespaces/codespace"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
|
@ -64,7 +64,7 @@ func (a *App) Delete(ctx context.Context, opts deleteOptions) error {
|
|||
return fmt.Errorf("error getting user: %w", err)
|
||||
}
|
||||
|
||||
var codespaces []*api.Codespace
|
||||
var codespaces []*codespace.Codespace
|
||||
nameFilter := opts.codespaceName
|
||||
if nameFilter == "" {
|
||||
codespaces, err = a.apiClient.ListCodespaces(ctx)
|
||||
|
|
@ -86,15 +86,15 @@ func (a *App) Delete(ctx context.Context, opts deleteOptions) error {
|
|||
return fmt.Errorf("error getting codespace token: %w", err)
|
||||
}
|
||||
|
||||
codespace, err := a.apiClient.GetCodespace(ctx, token, user.Login, nameFilter)
|
||||
cs, err := a.apiClient.GetCodespace(ctx, token, user.Login, nameFilter)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error fetching codespace information: %w", err)
|
||||
}
|
||||
|
||||
codespaces = []*api.Codespace{codespace}
|
||||
codespaces = []*codespace.Codespace{cs}
|
||||
}
|
||||
|
||||
codespacesToDelete := make([]*api.Codespace, 0, len(codespaces))
|
||||
codespacesToDelete := make([]*codespace.Codespace, 0, len(codespaces))
|
||||
lastUpdatedCutoffTime := opts.now().AddDate(0, 0, -int(opts.keepDays))
|
||||
for _, c := range codespaces {
|
||||
if nameFilter != "" && c.Name != nameFilter {
|
||||
|
|
@ -146,16 +146,14 @@ func (a *App) Delete(ctx context.Context, opts deleteOptions) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func confirmDeletion(p prompter, codespace *api.Codespace, isInteractive bool) (bool, error) {
|
||||
gs := codespace.Environment.GitStatus
|
||||
hasUnsavedChanges := gs.HasUncommitedChanges || gs.HasUnpushedChanges
|
||||
if !hasUnsavedChanges {
|
||||
func confirmDeletion(p prompter, cs *codespace.Codespace, isInteractive bool) (bool, error) {
|
||||
if !cs.HasUnsavedChanges() {
|
||||
return true, nil
|
||||
}
|
||||
if !isInteractive {
|
||||
return false, fmt.Errorf("codespace %s has unsaved changes (use --force to override)", codespace.Name)
|
||||
return false, fmt.Errorf("codespace %s has unsaved changes (use --force to override)", cs.Name)
|
||||
}
|
||||
return p.Confirm(fmt.Sprintf("Codespace %s has unsaved changes. OK to delete?", codespace.Name))
|
||||
return p.Confirm(fmt.Sprintf("Codespace %s has unsaved changes. OK to delete?", cs.Name))
|
||||
}
|
||||
|
||||
type surveyPrompter struct{}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import (
|
|||
|
||||
"github.com/MakeNowJust/heredoc"
|
||||
"github.com/cli/cli/v2/internal/codespaces/api"
|
||||
"github.com/cli/cli/v2/internal/codespaces/codespace"
|
||||
"github.com/cli/cli/v2/pkg/cmd/codespace/output"
|
||||
)
|
||||
|
||||
|
|
@ -25,7 +26,7 @@ func TestDelete(t *testing.T) {
|
|||
tests := []struct {
|
||||
name string
|
||||
opts deleteOptions
|
||||
codespaces []*api.Codespace
|
||||
codespaces []*codespace.Codespace
|
||||
confirms map[string]bool
|
||||
deleteErr error
|
||||
wantErr bool
|
||||
|
|
@ -38,7 +39,7 @@ func TestDelete(t *testing.T) {
|
|||
opts: deleteOptions{
|
||||
codespaceName: "hubot-robawt-abc",
|
||||
},
|
||||
codespaces: []*api.Codespace{
|
||||
codespaces: []*codespace.Codespace{
|
||||
{
|
||||
Name: "hubot-robawt-abc",
|
||||
},
|
||||
|
|
@ -50,7 +51,7 @@ func TestDelete(t *testing.T) {
|
|||
opts: deleteOptions{
|
||||
repoFilter: "monalisa/spoon-knife",
|
||||
},
|
||||
codespaces: []*api.Codespace{
|
||||
codespaces: []*codespace.Codespace{
|
||||
{
|
||||
Name: "monalisa-spoonknife-123",
|
||||
RepositoryNWO: "monalisa/Spoon-Knife",
|
||||
|
|
@ -72,7 +73,7 @@ func TestDelete(t *testing.T) {
|
|||
deleteAll: true,
|
||||
keepDays: 3,
|
||||
},
|
||||
codespaces: []*api.Codespace{
|
||||
codespaces: []*codespace.Codespace{
|
||||
{
|
||||
Name: "monalisa-spoonknife-123",
|
||||
LastUsedAt: daysAgo(1),
|
||||
|
|
@ -93,7 +94,7 @@ func TestDelete(t *testing.T) {
|
|||
opts: deleteOptions{
|
||||
deleteAll: true,
|
||||
},
|
||||
codespaces: []*api.Codespace{
|
||||
codespaces: []*codespace.Codespace{
|
||||
{
|
||||
Name: "monalisa-spoonknife-123",
|
||||
},
|
||||
|
|
@ -116,27 +117,27 @@ func TestDelete(t *testing.T) {
|
|||
deleteAll: true,
|
||||
skipConfirm: false,
|
||||
},
|
||||
codespaces: []*api.Codespace{
|
||||
codespaces: []*codespace.Codespace{
|
||||
{
|
||||
Name: "monalisa-spoonknife-123",
|
||||
Environment: api.CodespaceEnvironment{
|
||||
GitStatus: api.CodespaceEnvironmentGitStatus{
|
||||
Environment: codespace.Environment{
|
||||
GitStatus: codespace.EnvironmentGitStatus{
|
||||
HasUnpushedChanges: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "hubot-robawt-abc",
|
||||
Environment: api.CodespaceEnvironment{
|
||||
GitStatus: api.CodespaceEnvironmentGitStatus{
|
||||
Environment: codespace.Environment{
|
||||
GitStatus: codespace.EnvironmentGitStatus{
|
||||
HasUncommitedChanges: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "monalisa-spoonknife-c4f3",
|
||||
Environment: api.CodespaceEnvironment{
|
||||
GitStatus: api.CodespaceEnvironmentGitStatus{
|
||||
Environment: codespace.Environment{
|
||||
GitStatus: codespace.EnvironmentGitStatus{
|
||||
HasUnpushedChanges: false,
|
||||
HasUncommitedChanges: false,
|
||||
},
|
||||
|
|
@ -167,7 +168,7 @@ func TestDelete(t *testing.T) {
|
|||
},
|
||||
}
|
||||
if tt.opts.codespaceName == "" {
|
||||
apiMock.ListCodespacesFunc = func(_ context.Context) ([]*api.Codespace, error) {
|
||||
apiMock.ListCodespacesFunc = func(_ context.Context) ([]*codespace.Codespace, error) {
|
||||
return tt.codespaces, nil
|
||||
}
|
||||
} else {
|
||||
|
|
@ -177,7 +178,7 @@ func TestDelete(t *testing.T) {
|
|||
}
|
||||
return "CS_TOKEN", nil
|
||||
}
|
||||
apiMock.GetCodespaceFunc = func(_ context.Context, token, userLogin, name string) (*api.Codespace, error) {
|
||||
apiMock.GetCodespaceFunc = func(_ context.Context, token, userLogin, name string) (*codespace.Codespace, error) {
|
||||
if userLogin != user.Login {
|
||||
return nil, fmt.Errorf("unexpected user %q", userLogin)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/cli/cli/v2/internal/codespaces/api"
|
||||
"github.com/cli/cli/v2/pkg/cmd/codespace/output"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
|
@ -39,7 +38,7 @@ func (a *App) List(ctx context.Context, asJSON bool) error {
|
|||
table.Append([]string{
|
||||
codespace.Name,
|
||||
codespace.RepositoryNWO,
|
||||
codespace.Branch + dirtyStar(codespace.Environment.GitStatus),
|
||||
codespace.BranchWithGitStatus(),
|
||||
codespace.Environment.State,
|
||||
codespace.CreatedAt,
|
||||
})
|
||||
|
|
@ -48,11 +47,3 @@ func (a *App) List(ctx context.Context, asJSON bool) error {
|
|||
table.Render()
|
||||
return nil
|
||||
}
|
||||
|
||||
func dirtyStar(status api.CodespaceEnvironmentGitStatus) string {
|
||||
if status.HasUncommitedChanges || status.HasUnpushedChanges {
|
||||
return "*"
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"sync"
|
||||
|
||||
"github.com/cli/cli/v2/internal/codespaces/api"
|
||||
"github.com/cli/cli/v2/internal/codespaces/codespace"
|
||||
)
|
||||
|
||||
// apiClientMock is a mock implementation of apiClient.
|
||||
|
|
@ -19,19 +20,19 @@ import (
|
|||
// AuthorizedKeysFunc: func(ctx context.Context, user string) ([]byte, error) {
|
||||
// panic("mock out the AuthorizedKeys method")
|
||||
// },
|
||||
// CreateCodespaceFunc: func(ctx context.Context, params *api.CreateCodespaceParams) (*api.Codespace, error) {
|
||||
// CreateCodespaceFunc: func(ctx context.Context, params *api.CreateCodespaceParams) (*codespace.Codespace, error) {
|
||||
// panic("mock out the CreateCodespace method")
|
||||
// },
|
||||
// DeleteCodespaceFunc: func(ctx context.Context, user string, name string) error {
|
||||
// panic("mock out the DeleteCodespace method")
|
||||
// },
|
||||
// GetCodespaceFunc: func(ctx context.Context, token string, user string, name string) (*api.Codespace, error) {
|
||||
// GetCodespaceFunc: func(ctx context.Context, token string, user string, name string) (*codespace.Codespace, error) {
|
||||
// panic("mock out the GetCodespace method")
|
||||
// },
|
||||
// GetCodespaceRegionLocationFunc: func(ctx context.Context) (string, error) {
|
||||
// panic("mock out the GetCodespaceRegionLocation method")
|
||||
// },
|
||||
// GetCodespaceRepositoryContentsFunc: func(ctx context.Context, codespace *api.Codespace, path string) ([]byte, error) {
|
||||
// GetCodespaceRepositoryContentsFunc: func(ctx context.Context, codespaceMoqParam *codespace.Codespace, path string) ([]byte, error) {
|
||||
// panic("mock out the GetCodespaceRepositoryContents method")
|
||||
// },
|
||||
// GetCodespaceTokenFunc: func(ctx context.Context, user string, name string) (string, error) {
|
||||
|
|
@ -46,10 +47,10 @@ import (
|
|||
// GetUserFunc: func(ctx context.Context) (*api.User, error) {
|
||||
// panic("mock out the GetUser method")
|
||||
// },
|
||||
// ListCodespacesFunc: func(ctx context.Context) ([]*api.Codespace, error) {
|
||||
// ListCodespacesFunc: func(ctx context.Context) ([]*codespace.Codespace, error) {
|
||||
// panic("mock out the ListCodespaces method")
|
||||
// },
|
||||
// StartCodespaceFunc: func(ctx context.Context, token string, codespace *api.Codespace) error {
|
||||
// StartCodespaceFunc: func(ctx context.Context, token string, codespaceMoqParam *codespace.Codespace) error {
|
||||
// panic("mock out the StartCodespace method")
|
||||
// },
|
||||
// }
|
||||
|
|
@ -63,19 +64,19 @@ type apiClientMock struct {
|
|||
AuthorizedKeysFunc func(ctx context.Context, user string) ([]byte, error)
|
||||
|
||||
// CreateCodespaceFunc mocks the CreateCodespace method.
|
||||
CreateCodespaceFunc func(ctx context.Context, params *api.CreateCodespaceParams) (*api.Codespace, error)
|
||||
CreateCodespaceFunc func(ctx context.Context, params *api.CreateCodespaceParams) (*codespace.Codespace, error)
|
||||
|
||||
// DeleteCodespaceFunc mocks the DeleteCodespace method.
|
||||
DeleteCodespaceFunc func(ctx context.Context, user string, name string) error
|
||||
|
||||
// GetCodespaceFunc mocks the GetCodespace method.
|
||||
GetCodespaceFunc func(ctx context.Context, token string, user string, name string) (*api.Codespace, error)
|
||||
GetCodespaceFunc func(ctx context.Context, token string, user string, name string) (*codespace.Codespace, error)
|
||||
|
||||
// GetCodespaceRegionLocationFunc mocks the GetCodespaceRegionLocation method.
|
||||
GetCodespaceRegionLocationFunc func(ctx context.Context) (string, error)
|
||||
|
||||
// GetCodespaceRepositoryContentsFunc mocks the GetCodespaceRepositoryContents method.
|
||||
GetCodespaceRepositoryContentsFunc func(ctx context.Context, codespace *api.Codespace, path string) ([]byte, error)
|
||||
GetCodespaceRepositoryContentsFunc func(ctx context.Context, codespaceMoqParam *codespace.Codespace, path string) ([]byte, error)
|
||||
|
||||
// GetCodespaceTokenFunc mocks the GetCodespaceToken method.
|
||||
GetCodespaceTokenFunc func(ctx context.Context, user string, name string) (string, error)
|
||||
|
|
@ -90,10 +91,10 @@ type apiClientMock struct {
|
|||
GetUserFunc func(ctx context.Context) (*api.User, error)
|
||||
|
||||
// ListCodespacesFunc mocks the ListCodespaces method.
|
||||
ListCodespacesFunc func(ctx context.Context) ([]*api.Codespace, error)
|
||||
ListCodespacesFunc func(ctx context.Context) ([]*codespace.Codespace, error)
|
||||
|
||||
// StartCodespaceFunc mocks the StartCodespace method.
|
||||
StartCodespaceFunc func(ctx context.Context, token string, codespace *api.Codespace) error
|
||||
StartCodespaceFunc func(ctx context.Context, token string, codespaceMoqParam *codespace.Codespace) error
|
||||
|
||||
// calls tracks calls to the methods.
|
||||
calls struct {
|
||||
|
|
@ -140,8 +141,8 @@ type apiClientMock struct {
|
|||
GetCodespaceRepositoryContents []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
// Codespace is the codespace argument value.
|
||||
Codespace *api.Codespace
|
||||
// CodespaceMoqParam is the codespaceMoqParam argument value.
|
||||
CodespaceMoqParam *codespace.Codespace
|
||||
// Path is the path argument value.
|
||||
Path string
|
||||
}
|
||||
|
|
@ -190,8 +191,8 @@ type apiClientMock struct {
|
|||
Ctx context.Context
|
||||
// Token is the token argument value.
|
||||
Token string
|
||||
// Codespace is the codespace argument value.
|
||||
Codespace *api.Codespace
|
||||
// CodespaceMoqParam is the codespaceMoqParam argument value.
|
||||
CodespaceMoqParam *codespace.Codespace
|
||||
}
|
||||
}
|
||||
lockAuthorizedKeys sync.RWMutex
|
||||
|
|
@ -244,7 +245,7 @@ func (mock *apiClientMock) AuthorizedKeysCalls() []struct {
|
|||
}
|
||||
|
||||
// CreateCodespace calls CreateCodespaceFunc.
|
||||
func (mock *apiClientMock) CreateCodespace(ctx context.Context, params *api.CreateCodespaceParams) (*api.Codespace, error) {
|
||||
func (mock *apiClientMock) CreateCodespace(ctx context.Context, params *api.CreateCodespaceParams) (*codespace.Codespace, error) {
|
||||
if mock.CreateCodespaceFunc == nil {
|
||||
panic("apiClientMock.CreateCodespaceFunc: method is nil but apiClient.CreateCodespace was just called")
|
||||
}
|
||||
|
|
@ -318,7 +319,7 @@ func (mock *apiClientMock) DeleteCodespaceCalls() []struct {
|
|||
}
|
||||
|
||||
// GetCodespace calls GetCodespaceFunc.
|
||||
func (mock *apiClientMock) GetCodespace(ctx context.Context, token string, user string, name string) (*api.Codespace, error) {
|
||||
func (mock *apiClientMock) GetCodespace(ctx context.Context, token string, user string, name string) (*codespace.Codespace, error) {
|
||||
if mock.GetCodespaceFunc == nil {
|
||||
panic("apiClientMock.GetCodespaceFunc: method is nil but apiClient.GetCodespace was just called")
|
||||
}
|
||||
|
|
@ -392,37 +393,37 @@ func (mock *apiClientMock) GetCodespaceRegionLocationCalls() []struct {
|
|||
}
|
||||
|
||||
// GetCodespaceRepositoryContents calls GetCodespaceRepositoryContentsFunc.
|
||||
func (mock *apiClientMock) GetCodespaceRepositoryContents(ctx context.Context, codespace *api.Codespace, path string) ([]byte, error) {
|
||||
func (mock *apiClientMock) GetCodespaceRepositoryContents(ctx context.Context, codespaceMoqParam *codespace.Codespace, path string) ([]byte, error) {
|
||||
if mock.GetCodespaceRepositoryContentsFunc == nil {
|
||||
panic("apiClientMock.GetCodespaceRepositoryContentsFunc: method is nil but apiClient.GetCodespaceRepositoryContents was just called")
|
||||
}
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
Codespace *api.Codespace
|
||||
Path string
|
||||
Ctx context.Context
|
||||
CodespaceMoqParam *codespace.Codespace
|
||||
Path string
|
||||
}{
|
||||
Ctx: ctx,
|
||||
Codespace: codespace,
|
||||
Path: path,
|
||||
Ctx: ctx,
|
||||
CodespaceMoqParam: codespaceMoqParam,
|
||||
Path: path,
|
||||
}
|
||||
mock.lockGetCodespaceRepositoryContents.Lock()
|
||||
mock.calls.GetCodespaceRepositoryContents = append(mock.calls.GetCodespaceRepositoryContents, callInfo)
|
||||
mock.lockGetCodespaceRepositoryContents.Unlock()
|
||||
return mock.GetCodespaceRepositoryContentsFunc(ctx, codespace, path)
|
||||
return mock.GetCodespaceRepositoryContentsFunc(ctx, codespaceMoqParam, path)
|
||||
}
|
||||
|
||||
// GetCodespaceRepositoryContentsCalls gets all the calls that were made to GetCodespaceRepositoryContents.
|
||||
// Check the length with:
|
||||
// len(mockedapiClient.GetCodespaceRepositoryContentsCalls())
|
||||
func (mock *apiClientMock) GetCodespaceRepositoryContentsCalls() []struct {
|
||||
Ctx context.Context
|
||||
Codespace *api.Codespace
|
||||
Path string
|
||||
Ctx context.Context
|
||||
CodespaceMoqParam *codespace.Codespace
|
||||
Path string
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
Codespace *api.Codespace
|
||||
Path string
|
||||
Ctx context.Context
|
||||
CodespaceMoqParam *codespace.Codespace
|
||||
Path string
|
||||
}
|
||||
mock.lockGetCodespaceRepositoryContents.RLock()
|
||||
calls = mock.calls.GetCodespaceRepositoryContents
|
||||
|
|
@ -583,7 +584,7 @@ func (mock *apiClientMock) GetUserCalls() []struct {
|
|||
}
|
||||
|
||||
// ListCodespaces calls ListCodespacesFunc.
|
||||
func (mock *apiClientMock) ListCodespaces(ctx context.Context) ([]*api.Codespace, error) {
|
||||
func (mock *apiClientMock) ListCodespaces(ctx context.Context) ([]*codespace.Codespace, error) {
|
||||
if mock.ListCodespacesFunc == nil {
|
||||
panic("apiClientMock.ListCodespacesFunc: method is nil but apiClient.ListCodespaces was just called")
|
||||
}
|
||||
|
|
@ -614,37 +615,37 @@ func (mock *apiClientMock) ListCodespacesCalls() []struct {
|
|||
}
|
||||
|
||||
// StartCodespace calls StartCodespaceFunc.
|
||||
func (mock *apiClientMock) StartCodespace(ctx context.Context, token string, codespace *api.Codespace) error {
|
||||
func (mock *apiClientMock) StartCodespace(ctx context.Context, token string, codespaceMoqParam *codespace.Codespace) error {
|
||||
if mock.StartCodespaceFunc == nil {
|
||||
panic("apiClientMock.StartCodespaceFunc: method is nil but apiClient.StartCodespace was just called")
|
||||
}
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
Token string
|
||||
Codespace *api.Codespace
|
||||
Ctx context.Context
|
||||
Token string
|
||||
CodespaceMoqParam *codespace.Codespace
|
||||
}{
|
||||
Ctx: ctx,
|
||||
Token: token,
|
||||
Codespace: codespace,
|
||||
Ctx: ctx,
|
||||
Token: token,
|
||||
CodespaceMoqParam: codespaceMoqParam,
|
||||
}
|
||||
mock.lockStartCodespace.Lock()
|
||||
mock.calls.StartCodespace = append(mock.calls.StartCodespace, callInfo)
|
||||
mock.lockStartCodespace.Unlock()
|
||||
return mock.StartCodespaceFunc(ctx, token, codespace)
|
||||
return mock.StartCodespaceFunc(ctx, token, codespaceMoqParam)
|
||||
}
|
||||
|
||||
// StartCodespaceCalls gets all the calls that were made to StartCodespace.
|
||||
// Check the length with:
|
||||
// len(mockedapiClient.StartCodespaceCalls())
|
||||
func (mock *apiClientMock) StartCodespaceCalls() []struct {
|
||||
Ctx context.Context
|
||||
Token string
|
||||
Codespace *api.Codespace
|
||||
Ctx context.Context
|
||||
Token string
|
||||
CodespaceMoqParam *codespace.Codespace
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
Token string
|
||||
Codespace *api.Codespace
|
||||
Ctx context.Context
|
||||
Token string
|
||||
CodespaceMoqParam *codespace.Codespace
|
||||
}
|
||||
mock.lockStartCodespace.RLock()
|
||||
calls = mock.calls.StartCodespace
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/cli/cli/v2/internal/codespaces"
|
||||
"github.com/cli/cli/v2/internal/codespaces/api"
|
||||
"github.com/cli/cli/v2/internal/codespaces/codespace"
|
||||
"github.com/cli/cli/v2/pkg/cmd/codespace/output"
|
||||
"github.com/cli/cli/v2/pkg/liveshare"
|
||||
"github.com/muhammadmuzzammil1998/jsonc"
|
||||
|
|
@ -119,7 +119,7 @@ type portAttribute struct {
|
|||
Label string `json:"label"`
|
||||
}
|
||||
|
||||
func getDevContainer(ctx context.Context, apiClient apiClient, codespace *api.Codespace) <-chan devContainerResult {
|
||||
func getDevContainer(ctx context.Context, apiClient apiClient, codespace *codespace.Codespace) <-chan devContainerResult {
|
||||
ch := make(chan devContainerResult, 1)
|
||||
go func() {
|
||||
contents, err := apiClient.GetCodespaceRepositoryContents(ctx, codespace, ".devcontainer/devcontainer.json")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue