Merge remote-tracking branch 'origin/master' into ghrepo-interface
This commit is contained in:
commit
c5960f0906
9 changed files with 131 additions and 20 deletions
2
.github/workflows/go.yml
vendored
2
.github/workflows/go.yml
vendored
|
|
@ -23,4 +23,4 @@ jobs:
|
|||
- name: Build
|
||||
run: |
|
||||
go test ./...
|
||||
go build -v .
|
||||
go build -v ./cmd/gh
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ before:
|
|||
- go mod tidy
|
||||
builds:
|
||||
- binary: bin/gh
|
||||
main: ./cmd/gh
|
||||
ldflags:
|
||||
- -s -w -X github.com/github/gh-cli/command.Version={{.Version}} -X github.com/github/gh-cli/command.BuildDate={{time "2006-01-02"}}
|
||||
- -X github.com/github/gh-cli/context.oauthClientID={{.Env.GH_OAUTH_CLIENT_ID}}
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -10,7 +10,7 @@ ifdef GH_OAUTH_CLIENT_SECRET
|
|||
endif
|
||||
|
||||
bin/gh: $(BUILD_FILES)
|
||||
@go build -ldflags "$(LDFLAGS)" -o "$@"
|
||||
@go build -ldflags "$(LDFLAGS)" -o "$@" ./cmd/gh
|
||||
|
||||
test:
|
||||
go test ./...
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
|
@ -12,6 +15,7 @@ import (
|
|||
"github.com/github/gh-cli/utils"
|
||||
"github.com/mattn/go-isatty"
|
||||
"github.com/mgutz/ansi"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var updaterEnabled = ""
|
||||
|
|
@ -24,12 +28,10 @@ func main() {
|
|||
updateMessageChan <- rel
|
||||
}()
|
||||
|
||||
hasDebug := os.Getenv("DEBUG") != ""
|
||||
|
||||
if cmd, err := command.RootCmd.ExecuteC(); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
_, isFlagError := err.(command.FlagError)
|
||||
if isFlagError || strings.HasPrefix(err.Error(), "unknown command ") {
|
||||
fmt.Fprintln(os.Stderr, cmd.UsageString())
|
||||
}
|
||||
printError(os.Stderr, err, cmd, hasDebug)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
|
|
@ -46,6 +48,28 @@ func main() {
|
|||
}
|
||||
}
|
||||
|
||||
func printError(out io.Writer, err error, cmd *cobra.Command, debug bool) {
|
||||
var dnsError *net.DNSError
|
||||
if errors.As(err, &dnsError) {
|
||||
fmt.Fprintf(out, "error connecting to %s\n", dnsError.Name)
|
||||
if debug {
|
||||
fmt.Fprintln(out, dnsError)
|
||||
}
|
||||
fmt.Fprintln(out, "check your internet connection or githubstatus.com")
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprintln(out, err)
|
||||
|
||||
var flagError *command.FlagError
|
||||
if errors.As(err, &flagError) || strings.HasPrefix(err.Error(), "unknown command ") {
|
||||
if !strings.HasSuffix(err.Error(), "\n") {
|
||||
fmt.Fprintln(out)
|
||||
}
|
||||
fmt.Fprintln(out, cmd.UsageString())
|
||||
}
|
||||
}
|
||||
|
||||
func shouldCheckForUpdate() bool {
|
||||
errFd := os.Stderr.Fd()
|
||||
return updaterEnabled != "" && (isatty.IsTerminal(errFd) || isatty.IsCygwinTerminal(errFd))
|
||||
78
cmd/gh/main_test.go
Normal file
78
cmd/gh/main_test.go
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/github/gh-cli/command"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func Test_printError(t *testing.T) {
|
||||
cmd := &cobra.Command{}
|
||||
|
||||
type args struct {
|
||||
err error
|
||||
cmd *cobra.Command
|
||||
debug bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantOut string
|
||||
}{
|
||||
{
|
||||
name: "generic error",
|
||||
args: args{
|
||||
err: errors.New("the app exploded"),
|
||||
cmd: nil,
|
||||
debug: false,
|
||||
},
|
||||
wantOut: "the app exploded\n",
|
||||
},
|
||||
{
|
||||
name: "DNS error",
|
||||
args: args{
|
||||
err: fmt.Errorf("DNS oopsie: %w", &net.DNSError{
|
||||
Name: "api.github.com",
|
||||
}),
|
||||
cmd: nil,
|
||||
debug: false,
|
||||
},
|
||||
wantOut: `error connecting to api.github.com
|
||||
check your internet connection or githubstatus.com
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "Cobra flag error",
|
||||
args: args{
|
||||
err: &command.FlagError{Err: errors.New("unknown flag --foo")},
|
||||
cmd: cmd,
|
||||
debug: false,
|
||||
},
|
||||
wantOut: "unknown flag --foo\n\nUsage:\n\n",
|
||||
},
|
||||
{
|
||||
name: "unknown Cobra command error",
|
||||
args: args{
|
||||
err: errors.New("unknown command foo"),
|
||||
cmd: cmd,
|
||||
debug: false,
|
||||
},
|
||||
wantOut: "unknown command foo\n\nUsage:\n\n",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
printError(out, tt.args.err, tt.args.cmd, tt.args.debug)
|
||||
if gotOut := out.String(); gotOut != tt.wantOut {
|
||||
t.Errorf("printError() = %q, want %q", gotOut, tt.wantOut)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -47,7 +47,7 @@ var issueCmd = &cobra.Command{
|
|||
|
||||
An issue can be supplied as argument in any of the following formats:
|
||||
- by number, e.g. "123"; or
|
||||
- by URL, e.g. "https://github.com/<owner>/<repo>/issues/123".`,
|
||||
- by URL, e.g. "https://github.com/OWNER/REPO/issues/123".`,
|
||||
}
|
||||
var issueCreateCmd = &cobra.Command{
|
||||
Use: "create",
|
||||
|
|
@ -68,7 +68,7 @@ var issueViewCmd = &cobra.Command{
|
|||
Use: "view {<number> | <url> | <branch>}",
|
||||
Args: func(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return errors.New("requires an issue number as an argument")
|
||||
return FlagError{errors.New("issue required as argument")}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ var prCmd = &cobra.Command{
|
|||
|
||||
A pull request can be supplied as argument in any of the following formats:
|
||||
- by number, e.g. "123";
|
||||
- by URL, e.g. "https://github.com/<owner>/<repo>/pull/123"; or
|
||||
- by the name of its head branch, e.g. "patch-1" or "<owner>:patch-1".`,
|
||||
- by URL, e.g. "https://github.com/OWNER/REPO/pull/123"; or
|
||||
- by the name of its head branch, e.g. "patch-1" or "OWNER:patch-1".`,
|
||||
}
|
||||
var prCheckoutCmd = &cobra.Command{
|
||||
Use: "checkout {<number> | <url> | <branch>}",
|
||||
|
|
@ -68,9 +68,13 @@ var prStatusCmd = &cobra.Command{
|
|||
RunE: prStatus,
|
||||
}
|
||||
var prViewCmd = &cobra.Command{
|
||||
Use: "view {<number> | <url> | <branch>}",
|
||||
Use: "view [{<number> | <url> | <branch>}]",
|
||||
Short: "View a pull request in the browser",
|
||||
RunE: prView,
|
||||
Long: `View a pull request specified by the argument in the browser.
|
||||
|
||||
Without an argument, the pull request that belongs to the current
|
||||
branch is opened.`,
|
||||
RunE: prView,
|
||||
}
|
||||
|
||||
func prStatus(cmd *cobra.Command, args []string) error {
|
||||
|
|
@ -286,10 +290,6 @@ func prView(cmd *cobra.Command, args []string) error {
|
|||
} else {
|
||||
pr, err = api.PullRequestForBranch(apiClient, baseRepo, branchWithOwner)
|
||||
if err != nil {
|
||||
var notFoundErr *api.NotFoundError
|
||||
if errors.As(err, ¬FoundErr) {
|
||||
return fmt.Errorf("%s. To open a specific pull request use the pull request's number as an argument", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -359,7 +359,7 @@ func TestPRView_noResultsForBranch(t *testing.T) {
|
|||
defer restoreCmd()
|
||||
|
||||
_, err := RunCommand(prViewCmd, "pr view")
|
||||
if err == nil || err.Error() != `no open pull requests found for branch "blueberries". To open a specific pull request use the pull request's number as an argument` {
|
||||
if err == nil || err.Error() != `no open pull requests found for branch "blueberries"` {
|
||||
t.Errorf("error running command `pr view`: %v", err)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,13 +35,21 @@ func init() {
|
|||
// RootCmd.PersistentFlags().BoolP("verbose", "V", false, "enable verbose output")
|
||||
|
||||
RootCmd.SetFlagErrorFunc(func(cmd *cobra.Command, err error) error {
|
||||
return FlagError{err}
|
||||
return &FlagError{Err: err}
|
||||
})
|
||||
}
|
||||
|
||||
// FlagError is the kind of error raised in flag processing
|
||||
type FlagError struct {
|
||||
error
|
||||
Err error
|
||||
}
|
||||
|
||||
func (fe FlagError) Error() string {
|
||||
return fe.Err.Error()
|
||||
}
|
||||
|
||||
func (fe FlagError) Unwrap() error {
|
||||
return fe.Err
|
||||
}
|
||||
|
||||
// RootCmd is the entry point of command-line execution
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue