Unverified Commit 90c723d6 authored by Hector Sanjuan's avatar Hector Sanjuan Committed by GitHub

Staticcheck fixes (#196)

* Staticcheck fixes

This fixes all staticcheck warnings for this library.
parent c3c51f79
......@@ -4,7 +4,7 @@ os:
language: go
go:
- 1.11.x
- 1.14.2
env:
global:
......
......@@ -29,12 +29,12 @@ func TestChanResponsePair(t *testing.T) {
wg.Add(1)
go func() {
for _, v := range tc.values {
v_, err := res.Next()
v2, err := res.Next()
if err != nil {
t.Error("Next returned unexpected error:", err)
}
if v != v_ {
t.Errorf("Next returned unexpected value %q, expected %q", v_, v)
if v != v2 {
t.Errorf("Next returned unexpected value %q, expected %q", v2, v)
}
}
......@@ -93,7 +93,7 @@ func TestSingle1(t *testing.T) {
err := re.Close()
if err != ErrClosingClosedEmitter {
t.Fatalf("expected double close error, got %v", err)
t.Errorf("expected double close error, got %v", err)
}
close(wait)
}()
......@@ -127,7 +127,8 @@ func TestSingle2(t *testing.T) {
go func() {
err := re.Emit(Single{42})
if err != ErrClosedEmitter {
t.Fatal("expected closed emitter error, got", err)
t.Error("expected closed emitter error, got", err)
return
}
}()
......
......@@ -38,7 +38,7 @@ func suggestUnknownCmd(args []string, root *cmds.Command) []string {
var suggestions []string
sortableSuggestions := make(suggestionSlice, 0)
var sFinal []string
const MIN_LEVENSHTEIN = 3
const MinLevenshtein = 3
var options levenshtein.Options = levenshtein.Options{
InsCost: 1,
......@@ -50,7 +50,7 @@ func suggestUnknownCmd(args []string, root *cmds.Command) []string {
}
// Start with a simple strings.Contains check
for name, _ := range root.Subcommands {
for name := range root.Subcommands {
if strings.Contains(arg, name) {
suggestions = append(suggestions, name)
}
......@@ -61,9 +61,9 @@ func suggestUnknownCmd(args []string, root *cmds.Command) []string {
return suggestions
}
for name, _ := range root.Subcommands {
for name := range root.Subcommands {
lev := levenshtein.DistanceForStrings([]rune(arg), []rune(name), options)
if lev <= MIN_LEVENSHTEIN {
if lev <= MinLevenshtein {
sortableSuggestions = append(sortableSuggestions, &suggestion{name, lev})
}
}
......@@ -78,11 +78,17 @@ func suggestUnknownCmd(args []string, root *cmds.Command) []string {
func printSuggestions(inputs []string, root *cmds.Command) (err error) {
suggestions := suggestUnknownCmd(inputs, root)
if len(suggestions) > 1 {
//lint:ignore ST1005 user facing error
err = fmt.Errorf("Unknown Command \"%s\"\n\nDid you mean any of these?\n\n\t%s", inputs[0], strings.Join(suggestions, "\n\t"))
} else if len(suggestions) > 0 {
//lint:ignore ST1005 user facing error
err = fmt.Errorf("Unknown Command \"%s\"\n\nDid you mean this?\n\n\t%s", inputs[0], suggestions[0])
} else {
//lint:ignore ST1005 user facing error
err = fmt.Errorf("Unknown Command \"%s\"\n", inputs[0])
}
return
......
......@@ -137,8 +137,11 @@ func init() {
shortHelpTemplate = template.Must(template.New("shortHelp").Parse(shortHelpFormat))
}
// ErrNoHelpRequested returns when request for help help does not include the
// short nor the long option.
var ErrNoHelpRequested = errors.New("no help requested")
// HandleHelp writes help to a writer for the given request's command.
func HandleHelp(appName string, req *cmds.Request, out io.Writer) error {
long, _ := req.Options[cmds.OptLongHelp].(bool)
short, _ := req.Options[cmds.OptShortHelp].(bool)
......@@ -369,18 +372,15 @@ func appendWrapped(prefix, text string, width int) string {
func optionFlag(flag string) string {
if len(flag) == 1 {
return fmt.Sprintf(shortFlag, flag)
} else {
return fmt.Sprintf(longFlag, flag)
}
return fmt.Sprintf(longFlag, flag)
}
func optionText(width int, cmd ...*cmds.Command) []string {
// get a slice of the options we want to list out
options := make([]cmds.Option, 0)
for _, c := range cmd {
for _, opt := range c.Options {
options = append(options, opt)
}
options = append(options, c.Options...)
}
// add option names to output
......@@ -503,13 +503,6 @@ func align(lines []string) []string {
return lines
}
func indent(lines []string, prefix string) []string {
for i, line := range lines {
lines[i] = prefix + indentString(line, prefix)
}
return lines
}
func indentString(line string, prefix string) string {
return prefix + strings.Replace(line, "\n", "\n"+prefix, -1)
}
......
......@@ -3,7 +3,6 @@ package cli
import (
"context"
"fmt"
"github.com/ipfs/go-ipfs-files"
"io"
"io/ioutil"
"net/url"
......@@ -12,6 +11,8 @@ import (
"strings"
"testing"
files "github.com/ipfs/go-ipfs-files"
cmds "github.com/ipfs/go-ipfs-cmds"
)
......@@ -211,7 +212,7 @@ func TestArgumentParsing(t *testing.T) {
test := func(cmd words, f *os.File, res words) {
if f != nil {
if _, err := f.Seek(0, os.SEEK_SET); err != nil {
if _, err := f.Seek(0, io.SeekStart); err != nil {
t.Fatal(err)
}
}
......@@ -486,7 +487,7 @@ func TestBodyArgs(t *testing.T) {
for _, tc := range tcs {
if tc.f != nil {
if _, err := tc.f.Seek(0, os.SEEK_SET); err != nil {
if _, err := tc.f.Seek(0, io.SeekStart); err != nil {
t.Fatal(err)
}
}
......
......@@ -5,15 +5,9 @@ import (
"fmt"
"testing"
"github.com/ipfs/go-ipfs-cmds"
cmds "github.com/ipfs/go-ipfs-cmds"
)
type writeCloser struct {
*bytes.Buffer
}
func (wc writeCloser) Close() error { return nil }
type tcCloseWithError struct {
stdout, stderr *bytes.Buffer
exStdout, exStderr string
......
......@@ -5,7 +5,7 @@ import (
"context"
"testing"
"github.com/ipfs/go-ipfs-cmds"
cmds "github.com/ipfs/go-ipfs-cmds"
)
func TestSingle(t *testing.T) {
......@@ -25,7 +25,8 @@ func TestSingle(t *testing.T) {
go func() {
if err := cmds.EmitOnce(re, "test"); err != nil {
t.Fatal(err)
t.Error(err)
return
}
err := re.Emit("this should not be emitted")
......
......@@ -13,11 +13,12 @@ import (
"fmt"
"strings"
"github.com/ipfs/go-ipfs-files"
files "github.com/ipfs/go-ipfs-files"
logging "github.com/ipfs/go-log"
)
// DefaultOutputEncoding defines the default API output encoding.
const DefaultOutputEncoding = JSON
var log = logging.Logger("cmds")
......@@ -93,13 +94,13 @@ type Command struct {
var (
// ErrNotCallable signals a command that cannot be called.
ErrNotCallable = ClientError("This command can't be called directly. Try one of its subcommands.")
ErrNotCallable = ClientError("this command cannot be called directly; try one of its subcommands.")
// ErrNoFormatter signals that the command can not be formatted.
ErrNoFormatter = ClientError("This command cannot be formatted to plain text")
ErrNoFormatter = ClientError("this command cannot be formatted to plain text")
// ErrIncorrectType signales that the commands returned a value with unexpected type.
ErrIncorrectType = errors.New("The command returned a value with a different type than expected")
ErrIncorrectType = errors.New("the command returned a value with a different type than expected")
)
// Call invokes the command for the given Request
......
......@@ -39,7 +39,7 @@ func TestOptionValidation(t *testing.T) {
cmd.Call(req, re, nil)
} else {
if err == nil {
t.Errorf("Should have failed with error %q", tc.NewRequestError)
t.Errorf("should have failed with error %q", tc.NewRequestError)
} else if err.Error() != tc.NewRequestError {
t.Errorf("expected error %q, got %q", tc.NewRequestError, err)
}
......@@ -50,7 +50,7 @@ func TestOptionValidation(t *testing.T) {
tcs := []testcase{
{
opts: map[string]interface{}{"boop": true},
NewRequestError: `Option "boop" should be type "string", but got type "bool"`,
NewRequestError: `option "boop" should be type "string", but got type "bool"`,
},
{opts: map[string]interface{}{"beep": 5}},
{opts: map[string]interface{}{"beep": 5, "boop": "test"}},
......@@ -61,10 +61,10 @@ func TestOptionValidation(t *testing.T) {
{opts: map[string]interface{}{"S": [2]string{"a", "b"}}},
{
opts: map[string]interface{}{"S": true},
NewRequestError: `Option "S" should be type "array", but got type "bool"`},
NewRequestError: `option "S" should be type "array", but got type "bool"`},
{
opts: map[string]interface{}{"beep": ":)"},
NewRequestError: `Could not convert value ":)" to type "int" (for option "-beep")`,
NewRequestError: `could not convert value ":)" to type "int" (for option "-beep")`,
},
}
......@@ -279,7 +279,8 @@ func TestPostRun(t *testing.T) {
t.Log("next returned", v, err)
if err != nil {
close(ch)
t.Fatal(err)
t.Error(err)
return
}
ch <- v
......
......@@ -8,7 +8,7 @@ import (
"testing"
)
var theError = errors.New("an error occurred")
var errGeneric = errors.New("an error occurred")
var root = &Command{
Subcommands: map[string]*Command{
......@@ -20,7 +20,7 @@ var root = &Command{
},
"testError": &Command{
Run: func(req *Request, re ResponseEmitter, env Environment) error {
err := theError
err := errGeneric
if err != nil {
return err
}
......
......@@ -170,15 +170,11 @@ func allowUserAgent(r *http.Request, cfg *ServerConfig) bool {
return true
}
// Allow if the user agent does not start with Mozilla... (i.e. curl)
ua := r.Header.Get("User-agent")
if !strings.HasPrefix(ua, "Mozilla") {
return true
}
// Allow if the user agent does not start with Mozilla... (i.e. curl).
// Disallow otherwise.
//
// This means the request probably came from a browser and thus, it
// should have included Origin or referer headers.
return false
ua := r.Header.Get("User-agent")
return !strings.HasPrefix(ua, "Mozilla")
}
......@@ -5,7 +5,6 @@ import (
"errors"
"net/http"
"runtime/debug"
"strings"
"sync"
"time"
......@@ -17,11 +16,12 @@ import (
var log = logging.Logger("cmds/http")
var (
ErrNotFound = errors.New("404 page not found")
errApiVersionMismatch = errors.New("api version mismatch")
// ErrNotFound is returned when the endpoint does not exist.
ErrNotFound = errors.New("404 page not found")
)
const (
// StreamErrHeader is used as trailer when stream errors happen.
StreamErrHeader = "X-Stream-Error"
streamHeader = "X-Stream-Output"
channelHeader = "X-Chunked-Output"
......@@ -32,7 +32,7 @@ const (
transferEncodingHeader = "Transfer-Encoding"
originHeader = "origin"
applicationJson = "application/json"
applicationJSON = "application/json"
applicationOctetStream = "application/octet-stream"
plainText = "text/plain"
)
......@@ -57,6 +57,7 @@ type handler struct {
env cmds.Environment
}
// NewHandler creates the http.Handler for the given commands.
func NewHandler(env cmds.Environment, root *cmds.Command, cfg *ServerConfig) http.Handler {
if cfg == nil {
panic("must provide a valid ServerConfig")
......@@ -190,13 +191,6 @@ func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h.root.Call(req, re, h.env)
}
func sanitizedErrStr(err error) string {
s := err.Error()
s = strings.Split(s, "\n")[0]
s = strings.Split(s, "\r")[0]
return s
}
func setAllowedHeaders(w http.ResponseWriter, allowGet bool) {
w.Header().Add("Allow", http.MethodHead)
w.Header().Add("Allow", http.MethodOptions)
......
......@@ -10,9 +10,9 @@ import (
"strconv"
"strings"
"github.com/ipfs/go-ipfs-cmds"
cmds "github.com/ipfs/go-ipfs-cmds"
"github.com/ipfs/go-ipfs-files"
files "github.com/ipfs/go-ipfs-files"
logging "github.com/ipfs/go-log"
)
......@@ -133,7 +133,7 @@ func parseRequest(r *http.Request, root *cmds.Command) (*cmds.Request, error) {
// if there is a required filearg, error if no files were provided
if len(requiredFile) > 0 && f == nil {
return nil, fmt.Errorf("File argument '%s' is required", requiredFile)
return nil, fmt.Errorf("file argument '%s' is required", requiredFile)
}
ctx := logging.ContextWithLoggable(r.Context(), uuidLoggable())
......
......@@ -47,7 +47,7 @@ func TestParse(t *testing.T) {
if err != nil {
t.Fatal(err)
}
req, err = parseRequest(r, root)
_, err = parseRequest(r, root)
if err != ErrNotFound {
t.Errorf("expected ErrNotFound, got: %v", err)
}
......
......@@ -384,7 +384,7 @@ func TestEncoding(t *testing.T) {
}
tcs := []httpTestCase{
gtc(cmds.JSON, applicationJson),
gtc(cmds.JSON, applicationJSON),
gtc(cmds.XML, "application/xml"),
}
......
......@@ -8,14 +8,14 @@ import (
"strings"
"sync"
"github.com/ipfs/go-ipfs-cmds"
cmds "github.com/ipfs/go-ipfs-cmds"
)
var (
HeadRequest = fmt.Errorf("HEAD request")
// AllowedExposedHeadersArr defines the default Access-Control-Expose-Headers.
AllowedExposedHeadersArr = []string{streamHeader, channelHeader, extraContentLengthHeader}
AllowedExposedHeaders = strings.Join(AllowedExposedHeadersArr, ", ")
// AllowedExposedHeaders is the list of defaults Access-Control-Expose-Headers separated by comma.
AllowedExposedHeaders = strings.Join(AllowedExposedHeadersArr, ", ")
mimeTypes = map[cmds.EncodingType]string{
cmds.Protobuf: "application/protobuf",
......@@ -25,7 +25,7 @@ var (
}
)
// NewResponeEmitter returns a new ResponseEmitter.
// NewResponseEmitter returns a new ResponseEmitter.
func NewResponseEmitter(w http.ResponseWriter, method string, req *cmds.Request, opts ...ResponseEmitterOption) (ResponseEmitter, error) {
encType, enc, err := cmds.GetEncoder(req, w, cmds.JSON)
if err != nil {
......@@ -61,6 +61,8 @@ func withRequestBodyEOFChan(ch <-chan struct{}) ResponseEmitterOption {
}
}
// ResponseEmitter interface defines the components that can care of sending
// the response to HTTP Requests.
type ResponseEmitter interface {
cmds.ResponseEmitter
http.Flusher
......@@ -75,7 +77,6 @@ type responseEmitter struct {
l sync.Mutex
length uint64
err *cmds.Error
bodyEOFChan <-chan struct{}
......@@ -315,10 +316,6 @@ func (re *responseEmitter) doPreamble(value interface{}) {
re.w.WriteHeader(http.StatusOK)
}
type responseWriterer interface {
Lower() http.ResponseWriter
}
func flushCopy(w io.Writer, r io.Reader) error {
buf := make([]byte, 4096)
f, ok := w.(http.Flusher)
......
......@@ -6,6 +6,7 @@ import (
"time"
)
// ReqLogEntry represent a log entry for a request.
type ReqLogEntry struct {
StartTime time.Time
EndTime time.Time
......@@ -16,11 +17,13 @@ type ReqLogEntry struct {
ID int
}
// Copy copies a log entry and returns a pointer to the copy.
func (r *ReqLogEntry) Copy() *ReqLogEntry {
out := *r
return &out
}
// ReqLog represents a request log.
type ReqLog struct {
Requests []*ReqLogEntry
nextID int
......@@ -28,6 +31,7 @@ type ReqLog struct {
keep time.Duration
}
// Add ads an entry to the log for the given request.
func (rl *ReqLog) Add(req *Request) *ReqLogEntry {
rle := &ReqLogEntry{
StartTime: time.Now(),
......@@ -42,6 +46,7 @@ func (rl *ReqLog) Add(req *Request) *ReqLogEntry {
return rle
}
// AddEntry adds an entry to the log.
func (rl *ReqLog) AddEntry(rle *ReqLogEntry) {
rl.lock.Lock()
defer rl.lock.Unlock()
......@@ -52,10 +57,9 @@ func (rl *ReqLog) AddEntry(rle *ReqLogEntry) {
if rle == nil || !rle.Active {
rl.maybeCleanup()
}
return
}
// ClearInactive clears any inactive requests from the log.
func (rl *ReqLog) ClearInactive() {
rl.lock.Lock()
defer rl.lock.Unlock()
......
......@@ -66,6 +66,7 @@ func (req *Request) BodyArgs() StdinArguments {
return nil
}
// ParseBodyArgs parses arguments in the request body.
func (req *Request) ParseBodyArgs() error {
s := req.BodyArgs()
if s == nil {
......@@ -78,6 +79,7 @@ func (req *Request) ParseBodyArgs() error {
return s.Err()
}
// SetOption sets a request option.
func (req *Request) SetOption(name string, value interface{}) {
optDefs, err := req.Root.GetOptions(req.Path)
optDef, found := optDefs[name]
......@@ -95,8 +97,6 @@ func (req *Request) SetOption(name string, value interface{}) {
name = optDef.Name()
req.Options[name] = value
return
}
func checkAndConvertOptions(root *Command, opts OptMap, path []string) (OptMap, error) {
......@@ -125,20 +125,20 @@ func checkAndConvertOptions(root *Command, opts OptMap, path []string) (OptMap,
if len(str) == 0 {
value = "empty value"
}
return options, fmt.Errorf("Could not convert %s to type %q (for option %q)",
return options, fmt.Errorf("could not convert %s to type %q (for option %q)",
value, opt.Type().String(), "-"+k)
}
options[k] = val
} else {
return options, fmt.Errorf("Option %q should be type %q, but got type %q",
return options, fmt.Errorf("option %q should be type %q, but got type %q",
k, opt.Type().String(), kind.String())
}
}
for _, name := range opt.Names() {
if _, ok := options[name]; name != k && ok {
return options, fmt.Errorf("Duplicate command options were provided (%q and %q)",
return options, fmt.Errorf("duplicate command options were provided (%q and %q)",
k, name)
}
}
......@@ -162,7 +162,7 @@ func GetEncoding(req *Request, def EncodingType) EncodingType {
}
}
// fillDefault fills in default values if option has not been set
// FillDefaults fills in default values if option has not been set.
func (req *Request) FillDefaults() error {
optDefMap, err := req.Root.GetOptions(req.Path)
if err != nil {
......
......@@ -12,20 +12,6 @@ type TestOutput struct {
Baz int
}
func eqStringSlice(a, b []string) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}
func TestMarshalling(t *testing.T) {
cmd := &Command{}
......
......@@ -19,18 +19,21 @@ func TestCopy(t *testing.T) {
go func() {
err := Copy(re2, res1)
if err != nil {
t.Fatal(err)
t.Error(err)
return
}
}()
go func() {
err := re1.Emit("test")
if err != nil {
t.Fatal(err)
t.Error(err)
return
}
err = re1.Close()
if err != nil {
t.Fatal(err)
t.Error(err)
return
}
}()
......@@ -64,18 +67,21 @@ func TestCopyError(t *testing.T) {
go func() {
err := Copy(re2, res1)
if err != nil {
t.Fatal(err)
t.Error(err)
return
}
}()
go func() {
err := re1.Emit("test")
if err != nil {
t.Fatal(err)
t.Error(err)
return
}
err = re1.CloseWithError(fooErr)
if err != nil {
t.Fatal(err)
t.Error(err)
return
}
}()
......@@ -106,17 +112,20 @@ func TestError(t *testing.T) {
go func() {
err := re.Emit("value1")
if err != nil {
t.Fatal(err)
t.Error(err)
return
}
err = re.Emit("value2")
if err != nil {
t.Fatal(err)
t.Error(err)
return
}
err = re.CloseWithError(&Error{Message: "foo"})
if err != nil {
t.Fatal(err)
t.Error(err)
return
}
}()
......
......@@ -22,7 +22,8 @@ func TestSingleChan(t *testing.T) {
defer wg.Done()
if err := EmitOnce(re, "test"); err != nil {
t.Fatal(err)
t.Error(err)
return
}
err := re.Emit("test")
......@@ -73,7 +74,8 @@ func TestSingleWriter(t *testing.T) {
wg.Add(1)
go func() {
if err := EmitOnce(re, "test"); err != nil {
t.Fatal(err)
t.Error(err)
return
}
err := re.Emit("this should not be sent")
......
......@@ -8,6 +8,8 @@ import (
"sync"
)
// NewWriterResponseEmitter creates a response emitter that sends responses to
// the given WriterCloser.
func NewWriterResponseEmitter(w io.WriteCloser, req *Request) (ResponseEmitter, error) {
_, valEnc, err := GetEncoder(req, w, Undefined)
if err != nil {
......@@ -24,6 +26,7 @@ func NewWriterResponseEmitter(w io.WriteCloser, req *Request) (ResponseEmitter,
return re, nil
}
// NewReaderResponse creates a Response from the given reader.
func NewReaderResponse(r io.Reader, req *Request) (Response, error) {
encType := GetEncoding(req, Undefined)
dec, ok := Decoders[encType]
......@@ -99,7 +102,6 @@ type writerResponseEmitter struct {
req *Request
length *uint64
err *Error
emitted bool
closed bool
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment