The initial intention for this change was to disallow users to open a codespace in VS Code if the codespace has a pending operation. This also adds a side-benefit of presenting the user an error before waiting for VS Code to open if they provide an invalid codespace to open.
60 lines
1.5 KiB
Go
60 lines
1.5 KiB
Go
package codespace
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/url"
|
|
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
func newCodeCmd(app *App) *cobra.Command {
|
|
var (
|
|
codespace string
|
|
useInsiders bool
|
|
)
|
|
|
|
codeCmd := &cobra.Command{
|
|
Use: "code",
|
|
Short: "Open a codespace in Visual Studio Code",
|
|
Args: noArgsConstraint,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
return app.VSCode(cmd.Context(), codespace, useInsiders)
|
|
},
|
|
}
|
|
|
|
codeCmd.Flags().StringVarP(&codespace, "codespace", "c", "", "Name of the codespace")
|
|
codeCmd.Flags().BoolVar(&useInsiders, "insiders", false, "Use the insiders version of Visual Studio Code")
|
|
|
|
return codeCmd
|
|
}
|
|
|
|
// VSCode opens a codespace in the local VS VSCode application.
|
|
func (a *App) VSCode(ctx context.Context, codespaceName string, useInsiders bool) error {
|
|
codespace, err := getOrChooseCodespace(ctx, a.apiClient, codespaceName)
|
|
if err != nil {
|
|
return fmt.Errorf("get or choose codespace: %w", err)
|
|
}
|
|
|
|
if codespace.PendingOperation {
|
|
return fmt.Errorf(
|
|
"codespace is disabled while it has a pending operation: %s",
|
|
codespace.PendingOperationDisabledReason,
|
|
)
|
|
}
|
|
|
|
url := vscodeProtocolURL(codespace.Name, useInsiders)
|
|
if err := a.browser.Browse(url); err != nil {
|
|
return fmt.Errorf("error opening Visual Studio Code: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func vscodeProtocolURL(codespaceName string, useInsiders bool) string {
|
|
application := "vscode"
|
|
if useInsiders {
|
|
application = "vscode-insiders"
|
|
}
|
|
return fmt.Sprintf("%s://github.codespaces/connect?name=%s", application, url.QueryEscape(codespaceName))
|
|
}
|