From ca8aa47e053dbba9968f5d6435e8b6587d9f91c7 Mon Sep 17 00:00:00 2001 From: Enver Bisevac Date: Tue, 13 Sep 2022 00:08:43 +0200 Subject: [PATCH] [MAINT] initial work on linter setup (#16) * initial work on linter setup * simple linter rules fixed --- Makefile | 4 +- cli/cli.go | 4 -- cli/server/server.go | 5 +- cli/users/list.go | 4 +- cli/util/util.go | 4 +- client/client.go | 14 ++--- internal/api/handler/user/find_test.go | 4 +- internal/api/handler/user/token_test.go | 4 +- internal/api/handler/user/update_test.go | 22 ++++--- internal/api/openapi/account.go | 22 +++---- internal/api/openapi/openapi.go | 74 +++++++++++------------ internal/api/openapi/user.go | 32 +++++----- internal/api/openapi/users.go | 58 +++++++++--------- internal/api/render/render.go | 8 ++- internal/api/render/render_test.go | 26 +++++--- internal/auth/authn/token.go | 2 +- internal/auth/authz/authz.go | 2 +- internal/auth/authz/harness/authorizer.go | 11 ++-- internal/auth/authz/unsafe.go | 6 +- internal/cron/nightly.go | 3 - internal/router/api.go | 8 +-- internal/router/git.go | 2 +- internal/server/server.go | 30 ++++----- internal/store/database/path.go | 13 ++-- internal/store/database/repo.go | 14 +++-- internal/store/database/space.go | 23 ++++--- internal/store/database/store_test.go | 26 +++----- internal/store/database/user.go | 9 ++- internal/store/database/user_test.go | 18 ------ types/check/common.go | 4 +- types/check/path.go | 4 +- 31 files changed, 234 insertions(+), 226 deletions(-) diff --git a/Makefile b/Makefile index 052d6f7fd..0b755995e 100644 --- a/Makefile +++ b/Makefile @@ -35,7 +35,7 @@ tools: $(tools) ## Install tools required for the build mocks: $(mocks) @echo "Generating Test Mocks" -generate: $(mocks) wire_gen.go mocks/mock_client.go +generate: $(mocks) cli/server/wire_gen.go mocks/mock_client.go @echo "Generating Code" build: generate ## Build the gitness service binary @@ -114,7 +114,7 @@ lint: tools generate # lint the golang code # Some code generation can be slow, so we only run it if # the source file has changed. ########################################### -wire_gen.go: cli/server/wire.go ## Update the wire dependency injection if wire.go has changed. +cli/server/wire_gen.go: cli/server/wire.go ## Update the wire dependency injection if wire.go has changed. @echo "Updating wire_gen.go" go generate ./cli/server/wire_gen.go diff --git a/cli/cli.go b/cli/cli.go index f0ca564fc..6242853b1 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -5,7 +5,6 @@ package cli import ( - "context" "os" "github.com/harness/gitness/cli/server" @@ -17,9 +16,6 @@ import ( "gopkg.in/alecthomas/kingpin.v2" ) -// empty context -var nocontext = context.Background() - // application name var application = "gitness" diff --git a/cli/server/server.go b/cli/server/server.go index ca63ac01c..e09ed3c80 100644 --- a/cli/server/server.go +++ b/cli/server/server.go @@ -25,7 +25,10 @@ type command struct { func (c *command) run(*kingpin.ParseContext) error { // load environment variables from file. - godotenv.Load(c.envfile) + err := godotenv.Load(c.envfile) + if err != nil { + return err + } // create the system configuration store by loading // data from the environment. diff --git a/cli/users/list.go b/cli/users/list.go index b546930e6..4d0b4815c 100644 --- a/cli/users/list.go +++ b/cli/users/list.go @@ -51,7 +51,9 @@ func (c *listCommand) run(*kingpin.ParseContext) error { return enc.Encode(list) } for _, item := range list { - tmpl.Execute(os.Stdout, item) + if err = tmpl.Execute(os.Stdout, item); err != nil { + return err + } } return nil } diff --git a/cli/util/util.go b/cli/util/util.go index 17b47efb9..cb7302a92 100644 --- a/cli/util/util.go +++ b/cli/util/util.go @@ -9,6 +9,7 @@ import ( "encoding/json" "errors" "fmt" + "golang.org/x/term" "io/ioutil" "os" "path/filepath" @@ -20,7 +21,6 @@ import ( "github.com/harness/gitness/types" "github.com/adrg/xdg" - "golang.org/x/crypto/ssh/terminal" ) // Client returns a client that is configured from file. @@ -72,7 +72,7 @@ func Username() string { // Password returns the password from stdin. func Password() string { fmt.Print("Enter Password: ") - passwordb, _ := terminal.ReadPassword(int(syscall.Stdin)) + passwordb, _ := term.ReadPassword(int(syscall.Stdin)) password := string(passwordb) return strings.TrimSpace(password) diff --git a/client/client.go b/client/client.go index 51f2463e5..bdd268f04 100644 --- a/client/client.go +++ b/client/client.go @@ -8,6 +8,7 @@ import ( "bytes" "encoding/json" "fmt" + "github.com/rs/zerolog/log" "io" "net/http" "net/http/httputil" @@ -150,11 +151,6 @@ func (c *HTTPClient) post(rawurl string, in, out interface{}) error { return c.do(rawurl, "POST", in, out) } -// helper function for making an http PUT request. -func (c *HTTPClient) put(rawurl string, in, out interface{}) error { - return c.do(rawurl, "PUT", in, out) -} - // helper function for making an http PATCH request. func (c *HTTPClient) patch(rawurl string, in, out interface{}) error { return c.do(rawurl, "PATCH", in, out) @@ -199,7 +195,9 @@ func (c *HTTPClient) stream(rawurl, method string, in, out interface{}) (io.Read buf = new(bytes.Buffer) // if posting form data, encode the form values. if form, ok := in.(*url.Values); ok { - io.WriteString(buf, form.Encode()) + if _, err := io.WriteString(buf, form.Encode()); err != nil { + log.Err(err).Msg("in stream method") + } } else { if err := json.NewEncoder(buf).Encode(in); err != nil { return nil, err @@ -239,7 +237,9 @@ func (c *HTTPClient) stream(rawurl, method string, in, out interface{}) (io.Read if resp.StatusCode > 299 { defer resp.Body.Close() err := new(remoteError) - json.NewDecoder(resp.Body).Decode(err) + if decodeErr := json.NewDecoder(resp.Body).Decode(err); decodeErr != nil { + return nil, decodeErr + } return nil, err } return resp.Body, nil diff --git a/internal/api/handler/user/find_test.go b/internal/api/handler/user/find_test.go index e9ac199e3..7423f8c95 100644 --- a/internal/api/handler/user/find_test.go +++ b/internal/api/handler/user/find_test.go @@ -33,7 +33,9 @@ func TestFind(t *testing.T) { } got, want := &types.User{}, mockUser - json.NewDecoder(w.Body).Decode(got) + if err := json.NewDecoder(w.Body).Decode(got); err != nil { + t.Error(err) + } if diff := cmp.Diff(got, want); len(diff) != 0 { t.Errorf(diff) } diff --git a/internal/api/handler/user/token_test.go b/internal/api/handler/user/token_test.go index ce683e668..7fac1b939 100644 --- a/internal/api/handler/user/token_test.go +++ b/internal/api/handler/user/token_test.go @@ -38,7 +38,9 @@ func TestToken(t *testing.T) { } result := &types.Token{} - json.NewDecoder(w.Body).Decode(&result) + if err := json.NewDecoder(w.Body).Decode(&result); err != nil { + t.Error(err) + } _, err := jwt.Parse(result.Value, func(token *jwt.Token) (interface{}, error) { return []byte(mockUser.Salt), nil diff --git a/internal/api/handler/user/update_test.go b/internal/api/handler/user/update_test.go index 20b1d7673..4f43b4976 100644 --- a/internal/api/handler/user/update_test.go +++ b/internal/api/handler/user/update_test.go @@ -56,7 +56,7 @@ func TestUpdate(t *testing.T) { users.EXPECT().Update(gomock.Any(), before) in := new(bytes.Buffer) - json.NewEncoder(in).Encode(userInput) + _ = json.NewEncoder(in).Encode(userInput) w := httptest.NewRecorder() r := httptest.NewRequest("PATCH", "/api/v1/user", in) r = r.WithContext( @@ -81,7 +81,9 @@ func TestUpdate(t *testing.T) { // Password hash is not exposecd to JSON } got, want := new(types.User), after - json.NewDecoder(w.Body).Decode(got) + if err := json.NewDecoder(w.Body).Decode(got); err != nil { + t.Error(err) + } if diff := cmp.Diff(got, want); len(diff) != 0 { t.Errorf(diff) } @@ -108,7 +110,7 @@ func TestUpdate_HashError(t *testing.T) { } in := new(bytes.Buffer) - json.NewEncoder(in).Encode(userInput) + _ = json.NewEncoder(in).Encode(userInput) w := httptest.NewRecorder() r := httptest.NewRequest("PATCH", "/api/v1/user", in) r = r.WithContext( @@ -121,7 +123,9 @@ func TestUpdate_HashError(t *testing.T) { } got := new(render.Error) - json.NewDecoder(w.Body).Decode(got) + if err := json.NewDecoder(w.Body).Decode(got); err != nil { + t.Error(err) + } if diff := cmp.Diff(got.Message, render.ErrInternal.Message); len(diff) != 0 { t.Errorf(diff) } @@ -152,7 +156,9 @@ func TestUpdate_BadRequest(t *testing.T) { } got := new(render.Error) - json.NewDecoder(w.Body).Decode(got) + if err := json.NewDecoder(w.Body).Decode(got); err != nil { + t.Error(err) + } if diff := cmp.Diff(got.Message, "Invalid request body: EOF."); len(diff) != 0 { t.Errorf(diff) } @@ -176,7 +182,7 @@ func TestUpdate_ServerError(t *testing.T) { users.EXPECT().Update(gomock.Any(), user).Return(render.ErrNotFound) in := new(bytes.Buffer) - json.NewEncoder(in).Encode(userInput) + _ = json.NewEncoder(in).Encode(userInput) w := httptest.NewRecorder() r := httptest.NewRequest("PATCH", "/api/v1/user", in) r = r.WithContext( @@ -189,7 +195,9 @@ func TestUpdate_ServerError(t *testing.T) { } got, want := new(render.Error), render.ErrInternal - json.NewDecoder(w.Body).Decode(got) + if err := json.NewDecoder(w.Body).Decode(got); err != nil { + t.Error(err) + } if diff := cmp.Diff(got, want); len(diff) != 0 { t.Errorf(diff) } diff --git a/internal/api/openapi/account.go b/internal/api/openapi/account.go index 88dc2380a..6140e58b8 100644 --- a/internal/api/openapi/account.go +++ b/internal/api/openapi/account.go @@ -32,19 +32,19 @@ func buildAccount(reflector *openapi3.Reflector) { onLogin := openapi3.Operation{} onLogin.WithTags("account") onLogin.WithMapOfAnything(map[string]interface{}{"operationId": "onLogin"}) - reflector.SetRequest(&onLogin, new(loginRequest), http.MethodPost) - reflector.SetJSONResponse(&onLogin, new(types.Token), http.StatusOK) - reflector.SetJSONResponse(&onLogin, new(render.Error), http.StatusBadRequest) - reflector.SetJSONResponse(&onLogin, new(render.Error), http.StatusInternalServerError) - reflector.SetJSONResponse(&onLogin, new(render.Error), http.StatusNotFound) - reflector.Spec.AddOperation(http.MethodPost, "/login", onLogin) + _ = reflector.SetRequest(&onLogin, new(loginRequest), http.MethodPost) + _ = reflector.SetJSONResponse(&onLogin, new(types.Token), http.StatusOK) + _ = reflector.SetJSONResponse(&onLogin, new(render.Error), http.StatusBadRequest) + _ = reflector.SetJSONResponse(&onLogin, new(render.Error), http.StatusInternalServerError) + _ = reflector.SetJSONResponse(&onLogin, new(render.Error), http.StatusNotFound) + _ = reflector.Spec.AddOperation(http.MethodPost, "/login", onLogin) onRegister := openapi3.Operation{} onRegister.WithTags("account") onRegister.WithMapOfAnything(map[string]interface{}{"operationId": "onRegister"}) - reflector.SetRequest(&onRegister, new(registerRequest), http.MethodPost) - reflector.SetJSONResponse(&onRegister, new(types.Token), http.StatusOK) - reflector.SetJSONResponse(&onRegister, new(render.Error), http.StatusInternalServerError) - reflector.SetJSONResponse(&onRegister, new(render.Error), http.StatusBadRequest) - reflector.Spec.AddOperation(http.MethodPost, "/register", onRegister) + _ = reflector.SetRequest(&onRegister, new(registerRequest), http.MethodPost) + _ = reflector.SetJSONResponse(&onRegister, new(types.Token), http.StatusOK) + _ = reflector.SetJSONResponse(&onRegister, new(render.Error), http.StatusInternalServerError) + _ = reflector.SetJSONResponse(&onRegister, new(render.Error), http.StatusBadRequest) + _ = reflector.Spec.AddOperation(http.MethodPost, "/register", onRegister) } diff --git a/internal/api/openapi/openapi.go b/internal/api/openapi/openapi.go index 4bc86f543..4d48c1f6e 100644 --- a/internal/api/openapi/openapi.go +++ b/internal/api/openapi/openapi.go @@ -5,10 +5,6 @@ package openapi import ( - "bytes" - "net/http" - "strings" - "github.com/harness/gitness/version" "github.com/swaggest/openapi-go/openapi3" @@ -29,37 +25,38 @@ type ( Size int `query:"per_page" default:"100"` } - // base response for pagination - paginationResponse struct { - Total int `header:"x-total"` - Pagelen int `header:"x-total-pages"` - Page int `header:"x-page"` - Size int `header:"x-per-page"` - Next int `header:"x-next"` - Prev int `header:"x-prev"` - Link []string `header:"Link"` - } + // TODO: base response for pagination + //paginationResponse struct { + // Total int `header:"x-total"` + // Pagelen int `header:"x-total-pages"` + // Page int `header:"x-page"` + // Size int `header:"x-per-page"` + // Next int `header:"x-next"` + // Prev int `header:"x-prev"` + // Link []string `header:"Link"` + //} ) // Handler returns an http.HandlerFunc that writes the openapi v3 // specification file to the http.Response body. -func Handler() http.HandlerFunc { - spec := Generate() - yaml, _ := spec.MarshalYAML() - json, _ := spec.MarshalJSON() - - yaml = normalize(yaml) - json = normalize(json) - - return func(w http.ResponseWriter, r *http.Request) { - switch { - case strings.HasSuffix(r.URL.Path, ".json"): - w.Write(json) - default: - w.Write(yaml) - } - } -} +// TODO: unused function +//func Handler() http.HandlerFunc { +// spec := Generate() +// yaml, _ := spec.MarshalYAML() +// json, _ := spec.MarshalJSON() +// +// yaml = normalize(yaml) +// json = normalize(json) +// +// return func(w http.ResponseWriter, r *http.Request) { +// switch { +// case strings.HasSuffix(r.URL.Path, ".json"): +// w.Write(json) +// default: +// w.Write(yaml) +// } +// } +//} // Generate is a helper function that constructs the // openapi specification object, which can be marshaled @@ -108,10 +105,11 @@ func Generate() *openapi3.Spec { // helper function normalizes the output to ensure // automatically-generated names are more user friendly. -func normalize(data []byte) []byte { - data = bytes.ReplaceAll(data, []byte("Types"), []byte("")) - data = bytes.ReplaceAll(data, []byte("Openapi"), []byte("")) - data = bytes.ReplaceAll(data, []byte("FormData"), []byte("")) - data = bytes.ReplaceAll(data, []byte("RenderError"), []byte("Error")) - return data -} +// TODO: unused function +//func normalize(data []byte) []byte { +// data = bytes.ReplaceAll(data, []byte("Types"), []byte("")) +// data = bytes.ReplaceAll(data, []byte("Openapi"), []byte("")) +// data = bytes.ReplaceAll(data, []byte("FormData"), []byte("")) +// data = bytes.ReplaceAll(data, []byte("RenderError"), []byte("Error")) +// return data +//} diff --git a/internal/api/openapi/user.go b/internal/api/openapi/user.go index 41ba2214d..8d3e40c5b 100644 --- a/internal/api/openapi/user.go +++ b/internal/api/openapi/user.go @@ -25,32 +25,32 @@ func buildUser(reflector *openapi3.Reflector) { opFind := openapi3.Operation{} opFind.WithTags("user") opFind.WithMapOfAnything(map[string]interface{}{"operationId": "getUser"}) - reflector.SetRequest(&opFind, nil, http.MethodGet) - reflector.SetJSONResponse(&opFind, new(types.User), http.StatusOK) - reflector.SetJSONResponse(&opFind, new(render.Error), http.StatusInternalServerError) - reflector.Spec.AddOperation(http.MethodGet, "/user", opFind) + _ = reflector.SetRequest(&opFind, nil, http.MethodGet) + _ = reflector.SetJSONResponse(&opFind, new(types.User), http.StatusOK) + _ = reflector.SetJSONResponse(&opFind, new(render.Error), http.StatusInternalServerError) + _ = reflector.Spec.AddOperation(http.MethodGet, "/user", opFind) opUpdate := openapi3.Operation{} opUpdate.WithTags("user") opUpdate.WithMapOfAnything(map[string]interface{}{"operationId": "updateUser"}) - reflector.SetRequest(&opUpdate, new(types.UserInput), http.MethodPatch) - reflector.SetJSONResponse(&opUpdate, new(types.User), http.StatusOK) - reflector.SetJSONResponse(&opUpdate, new(render.Error), http.StatusInternalServerError) - reflector.Spec.AddOperation(http.MethodPatch, "/user", opUpdate) + _ = reflector.SetRequest(&opUpdate, new(types.UserInput), http.MethodPatch) + _ = reflector.SetJSONResponse(&opUpdate, new(types.User), http.StatusOK) + _ = reflector.SetJSONResponse(&opUpdate, new(render.Error), http.StatusInternalServerError) + _ = reflector.Spec.AddOperation(http.MethodPatch, "/user", opUpdate) opToken := openapi3.Operation{} opToken.WithTags("user") opToken.WithMapOfAnything(map[string]interface{}{"operationId": "createToken"}) - reflector.SetRequest(&opToken, new(types.Token), http.MethodPost) - reflector.SetJSONResponse(&opToken, new(types.User), http.StatusOK) - reflector.SetJSONResponse(&opToken, new(render.Error), http.StatusInternalServerError) - reflector.Spec.AddOperation(http.MethodPost, "/user/token", opToken) + _ = reflector.SetRequest(&opToken, new(types.Token), http.MethodPost) + _ = reflector.SetJSONResponse(&opToken, new(types.User), http.StatusOK) + _ = reflector.SetJSONResponse(&opToken, new(render.Error), http.StatusInternalServerError) + _ = reflector.Spec.AddOperation(http.MethodPost, "/user/token", opToken) opCurrent := openapi3.Operation{} opCurrent.WithTags("user") opCurrent.WithMapOfAnything(map[string]interface{}{"operationId": "getCurrentUser"}) - reflector.SetRequest(&opFind, new(baseRequest), http.MethodGet) - reflector.SetJSONResponse(&opCurrent, new(currentUserResponse), http.StatusOK) - reflector.SetJSONResponse(&opCurrent, new(render.Error), http.StatusInternalServerError) - reflector.Spec.AddOperation(http.MethodGet, "/api/user/currentUser", opCurrent) + _ = reflector.SetRequest(&opFind, new(baseRequest), http.MethodGet) + _ = reflector.SetJSONResponse(&opCurrent, new(currentUserResponse), http.StatusOK) + _ = reflector.SetJSONResponse(&opCurrent, new(render.Error), http.StatusInternalServerError) + _ = reflector.Spec.AddOperation(http.MethodGet, "/api/user/currentUser", opCurrent) } diff --git a/internal/api/openapi/users.go b/internal/api/openapi/users.go index 0b8526ff4..96739220f 100644 --- a/internal/api/openapi/users.go +++ b/internal/api/openapi/users.go @@ -44,49 +44,49 @@ func buildUsers(reflector *openapi3.Reflector) { opFind := openapi3.Operation{} opFind.WithTags("users") opFind.WithMapOfAnything(map[string]interface{}{"operationId": "getUserEmail"}) - reflector.SetRequest(&opFind, new(userRequest), http.MethodGet) - reflector.SetJSONResponse(&opFind, new(types.User), http.StatusOK) - reflector.SetJSONResponse(&opFind, new(render.Error), http.StatusBadRequest) - reflector.SetJSONResponse(&opFind, new(render.Error), http.StatusInternalServerError) - reflector.SetJSONResponse(&opFind, new(render.Error), http.StatusNotFound) - reflector.Spec.AddOperation(http.MethodGet, "/users/{email}", opFind) + _ = reflector.SetRequest(&opFind, new(userRequest), http.MethodGet) + _ = reflector.SetJSONResponse(&opFind, new(types.User), http.StatusOK) + _ = reflector.SetJSONResponse(&opFind, new(render.Error), http.StatusBadRequest) + _ = reflector.SetJSONResponse(&opFind, new(render.Error), http.StatusInternalServerError) + _ = reflector.SetJSONResponse(&opFind, new(render.Error), http.StatusNotFound) + _ = reflector.Spec.AddOperation(http.MethodGet, "/users/{email}", opFind) opList := openapi3.Operation{} opList.WithTags("users") opList.WithMapOfAnything(map[string]interface{}{"operationId": "listUsers"}) - reflector.SetRequest(&opList, new(userListRequest), http.MethodGet) - reflector.SetJSONResponse(&opList, new([]*types.User), http.StatusOK) - reflector.SetJSONResponse(&opList, new(render.Error), http.StatusBadRequest) - reflector.SetJSONResponse(&opList, new(render.Error), http.StatusInternalServerError) - reflector.SetJSONResponse(&opList, new(render.Error), http.StatusNotFound) - reflector.Spec.AddOperation(http.MethodGet, "/users", opList) + _ = reflector.SetRequest(&opList, new(userListRequest), http.MethodGet) + _ = reflector.SetJSONResponse(&opList, new([]*types.User), http.StatusOK) + _ = reflector.SetJSONResponse(&opList, new(render.Error), http.StatusBadRequest) + _ = reflector.SetJSONResponse(&opList, new(render.Error), http.StatusInternalServerError) + _ = reflector.SetJSONResponse(&opList, new(render.Error), http.StatusNotFound) + _ = reflector.Spec.AddOperation(http.MethodGet, "/users", opList) opCreate := openapi3.Operation{} opCreate.WithTags("users") opCreate.WithMapOfAnything(map[string]interface{}{"operationId": "createUser"}) - reflector.SetRequest(&opCreate, new(types.UserInput), http.MethodPost) - reflector.SetJSONResponse(&opCreate, new(types.User), http.StatusOK) - reflector.SetJSONResponse(&opCreate, new(render.Error), http.StatusBadRequest) - reflector.SetJSONResponse(&opCreate, new(render.Error), http.StatusInternalServerError) - reflector.SetJSONResponse(&opCreate, new(render.Error), http.StatusNotFound) - reflector.Spec.AddOperation(http.MethodPost, "/users", opCreate) + _ = reflector.SetRequest(&opCreate, new(types.UserInput), http.MethodPost) + _ = reflector.SetJSONResponse(&opCreate, new(types.User), http.StatusOK) + _ = reflector.SetJSONResponse(&opCreate, new(render.Error), http.StatusBadRequest) + _ = reflector.SetJSONResponse(&opCreate, new(render.Error), http.StatusInternalServerError) + _ = reflector.SetJSONResponse(&opCreate, new(render.Error), http.StatusNotFound) + _ = reflector.Spec.AddOperation(http.MethodPost, "/users", opCreate) opUpdate := openapi3.Operation{} opUpdate.WithTags("users") opUpdate.WithMapOfAnything(map[string]interface{}{"operationId": "updateUsers"}) - reflector.SetRequest(&opUpdate, new(userUpdateRequest), http.MethodPatch) - reflector.SetJSONResponse(&opUpdate, new(types.User), http.StatusOK) - reflector.SetJSONResponse(&opUpdate, new(render.Error), http.StatusBadRequest) - reflector.SetJSONResponse(&opUpdate, new(render.Error), http.StatusInternalServerError) - reflector.SetJSONResponse(&opUpdate, new(render.Error), http.StatusNotFound) - reflector.Spec.AddOperation(http.MethodPatch, "/users/{email}", opUpdate) + _ = reflector.SetRequest(&opUpdate, new(userUpdateRequest), http.MethodPatch) + _ = reflector.SetJSONResponse(&opUpdate, new(types.User), http.StatusOK) + _ = reflector.SetJSONResponse(&opUpdate, new(render.Error), http.StatusBadRequest) + _ = reflector.SetJSONResponse(&opUpdate, new(render.Error), http.StatusInternalServerError) + _ = reflector.SetJSONResponse(&opUpdate, new(render.Error), http.StatusNotFound) + _ = reflector.Spec.AddOperation(http.MethodPatch, "/users/{email}", opUpdate) opDelete := openapi3.Operation{} opDelete.WithTags("users") opDelete.WithMapOfAnything(map[string]interface{}{"operationId": "deleteUser"}) - reflector.SetRequest(&opDelete, new(userRequest), http.MethodDelete) - reflector.SetJSONResponse(&opDelete, nil, http.StatusNoContent) - reflector.SetJSONResponse(&opDelete, new(render.Error), http.StatusInternalServerError) - reflector.SetJSONResponse(&opDelete, new(render.Error), http.StatusNotFound) - reflector.Spec.AddOperation(http.MethodDelete, "/users/{email}", opDelete) + _ = reflector.SetRequest(&opDelete, new(userRequest), http.MethodDelete) + _ = reflector.SetJSONResponse(&opDelete, nil, http.StatusNoContent) + _ = reflector.SetJSONResponse(&opDelete, new(render.Error), http.StatusInternalServerError) + _ = reflector.SetJSONResponse(&opDelete, new(render.Error), http.StatusNotFound) + _ = reflector.Spec.AddOperation(http.MethodDelete, "/users/{email}", opDelete) } diff --git a/internal/api/render/render.go b/internal/api/render/render.go index 2526af724..62b385ec8 100644 --- a/internal/api/render/render.go +++ b/internal/api/render/render.go @@ -104,10 +104,12 @@ func ErrorObject(w http.ResponseWriter, code int, err *Error) { func JSON(w http.ResponseWriter, code int, v interface{}) { w.Header().Set("Content-Type", "application/json; charset=utf-8") w.Header().Set("X-Content-Type-Options", "nosniff") - w.WriteHeader(code) enc := json.NewEncoder(w) - if indent { + if indent { // is this necessary? it will affect performance enc.SetIndent("", " ") } - enc.Encode(v) + if err := enc.Encode(v); err != nil { + code = http.StatusInternalServerError + } + w.WriteHeader(code) } diff --git a/internal/api/render/render_test.go b/internal/api/render/render_test.go index 2c95f34be..db5b81758 100644 --- a/internal/api/render/render_test.go +++ b/internal/api/render/render_test.go @@ -22,7 +22,9 @@ func TestWriteErrorf(t *testing.T) { } errjson := &Error{} - json.NewDecoder(w.Body).Decode(errjson) + if err := json.NewDecoder(w.Body).Decode(errjson); err != nil { + t.Error(err) + } if got, want := errjson.Message, e.Message; got != want { t.Errorf("Want error message %s, got %s", want, got) } @@ -38,7 +40,9 @@ func TestWriteErrorCode(t *testing.T) { } errjson := &Error{} - json.NewDecoder(w.Body).Decode(errjson) + if err := json.NewDecoder(w.Body).Decode(errjson); err != nil { + t.Error(err) + } if got, want := errjson.Message, "pc load letter 1"; got != want { t.Errorf("Want error message %s, got %s", want, got) } @@ -54,7 +58,9 @@ func TestWriteNotFound(t *testing.T) { } errjson := &Error{} - json.NewDecoder(w.Body).Decode(errjson) + if err := json.NewDecoder(w.Body).Decode(errjson); err != nil { + t.Error(err) + } if got, want := errjson.Message, ErrNotFound.Message; got != want { t.Errorf("Want error message %s, got %s", want, got) } @@ -70,7 +76,9 @@ func TestWriteUnauthorized(t *testing.T) { } errjson := &Error{} - json.NewDecoder(w.Body).Decode(errjson) + if err := json.NewDecoder(w.Body).Decode(errjson); err != nil { + t.Error(err) + } if got, want := errjson.Message, ErrUnauthorized.Message; got != want { t.Errorf("Want error message %s, got %s", want, got) } @@ -86,7 +94,9 @@ func TestWriteForbidden(t *testing.T) { } errjson := &Error{} - json.NewDecoder(w.Body).Decode(errjson) + if err := json.NewDecoder(w.Body).Decode(errjson); err != nil { + t.Error(err) + } if got, want := errjson.Message, ErrForbidden.Message; got != want { t.Errorf("Want error message %s, got %s", want, got) } @@ -102,7 +112,9 @@ func TestWriteBadRequest(t *testing.T) { } errjson := &Error{} - json.NewDecoder(w.Body).Decode(errjson) + if err := json.NewDecoder(w.Body).Decode(errjson); err != nil { + t.Error(err) + } if got, want := errjson.Message, ErrBadRequest.Message; got != want { t.Errorf("Want error message %s, got %s", want, got) } @@ -116,7 +128,7 @@ func TestWriteJSON(t *testing.T) { if got, want := w.Body.String(), "{\"hello\":\"world\"}\n"; got != want { t.Errorf("Want JSON body %q, got %q", want, got) } - if got, want := w.HeaderMap.Get("Content-Type"), "application/json; charset=utf-8"; got != want { + if got, want := w.Header().Get("Content-Type"), "application/json; charset=utf-8"; got != want { t.Errorf("Want Content-Type %q, got %q", want, got) } if got, want := w.Code, http.StatusTeapot; got != want { diff --git a/internal/auth/authn/token.go b/internal/auth/authn/token.go index 4b0aa5c69..6c7ec94eb 100644 --- a/internal/auth/authn/token.go +++ b/internal/auth/authn/token.go @@ -64,7 +64,7 @@ func (a *TokenAuthenticator) Authenticate(r *http.Request) (*types.User, error) if err != nil { return nil, err } - if parsed.Valid == false { + if !parsed.Valid { return nil, errors.New("Invalid token") } diff --git a/internal/auth/authz/authz.go b/internal/auth/authz/authz.go index 6f3ab4751..fe47a57ce 100644 --- a/internal/auth/authz/authz.go +++ b/internal/auth/authz/authz.go @@ -36,5 +36,5 @@ type Authorizer interface { * (false, nil) - the principal does not have permission to perform all the actions (at least one is not allowed) * (false, err) - an error occured while performing the permission check and all actions should be denied */ - CheckAll(principalType enum.PrincipalType, principalId string, permissionChecks ...*types.PermissionCheck) (bool, error) + CheckAll(principalType enum.PrincipalType, principalId string, permissionChecks ...types.PermissionCheck) (bool, error) } diff --git a/internal/auth/authz/harness/authorizer.go b/internal/auth/authz/harness/authorizer.go index 8c33f57f0..55d575e53 100644 --- a/internal/auth/authz/harness/authorizer.go +++ b/internal/auth/authz/harness/authorizer.go @@ -42,15 +42,18 @@ func NewAuthorizer(aclEndpoint, authToken string) (authz.Authorizer, error) { } func (a *Authorizer) Check(principalType enum.PrincipalType, principalId string, scope *types.Scope, resource *types.Resource, permission enum.Permission) (bool, error) { - return a.CheckAll(principalType, principalId, &types.PermissionCheck{Scope: *scope, Resource: *resource, Permission: permission}) + return a.CheckAll(principalType, principalId, types.PermissionCheck{Scope: *scope, Resource: *resource, Permission: permission}) } -func (a *Authorizer) CheckAll(principalType enum.PrincipalType, principalId string, permissionChecks ...*types.PermissionCheck) (bool, error) { +func (a *Authorizer) CheckAll(principalType enum.PrincipalType, principalId string, permissionChecks ...types.PermissionCheck) (bool, error) { if len(permissionChecks) == 0 { return false, authz.ErrNoPermissionCheckProvided } requestDto, err := createAclRequest(principalType, principalId, permissionChecks) + if err != nil { + return false, err + } byt, err := json.Marshal(requestDto) if err != nil { return false, err @@ -91,7 +94,7 @@ func (a *Authorizer) CheckAll(principalType enum.PrincipalType, principalId stri return checkAclResponse(permissionChecks, responseDto) } -func createAclRequest(principalType enum.PrincipalType, principalId string, permissionChecks []*types.PermissionCheck) (*aclRequest, error) { +func createAclRequest(principalType enum.PrincipalType, principalId string, permissionChecks []types.PermissionCheck) (*aclRequest, error) { // Generate ACL req req := aclRequest{ Permissions: []aclPermission{}, @@ -123,7 +126,7 @@ func createAclRequest(principalType enum.PrincipalType, principalId string, perm return &req, nil } -func checkAclResponse(permissionChecks []*types.PermissionCheck, responseDto aclResponse) (bool, error) { +func checkAclResponse(permissionChecks []types.PermissionCheck, responseDto aclResponse) (bool, error) { /* * We are assuming two things: * - All permission checks were made for the same principal. diff --git a/internal/auth/authz/unsafe.go b/internal/auth/authz/unsafe.go index f8f3cbece..b7304516e 100644 --- a/internal/auth/authz/unsafe.go +++ b/internal/auth/authz/unsafe.go @@ -35,9 +35,11 @@ func (a *UnsafeAuthorizer) Check(principalType enum.PrincipalType, principalId s return true, nil } -func (a *UnsafeAuthorizer) CheckAll(principalType enum.PrincipalType, principalId string, permissionChecks ...*types.PermissionCheck) (bool, error) { +func (a *UnsafeAuthorizer) CheckAll(principalType enum.PrincipalType, principalId string, permissionChecks ...types.PermissionCheck) (bool, error) { for _, p := range permissionChecks { - a.Check(principalType, principalId, &p.Scope, &p.Resource, p.Permission) + if _, err := a.Check(principalType, principalId, &p.Scope, &p.Resource, p.Permission); err != nil { + return false, err + } } return true, nil diff --git a/internal/cron/nightly.go b/internal/cron/nightly.go index bcb419c49..a0dbc8067 100644 --- a/internal/cron/nightly.go +++ b/internal/cron/nightly.go @@ -11,9 +11,6 @@ import ( "github.com/rs/zerolog/log" ) -// helper function returns the current time. -var now = time.Now - // Nightly is a sub-routine that periodically purges historical data. type Nightly struct { // Inject required stores here diff --git a/internal/router/api.go b/internal/router/api.go index 4e34e66ab..75327f1ff 100644 --- a/internal/router/api.go +++ b/internal/router/api.go @@ -174,16 +174,16 @@ func setupRoutesV1( r.Route("/{user}", func(r chi.Router) { r.Get("/", func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(fmt.Sprintf("Get user '%s'", chi.URLParam(r, "rref")))) + _, _ = w.Write([]byte(fmt.Sprintf("Get user '%s'", chi.URLParam(r, "rref")))) }) r.Post("/", func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(fmt.Sprintf("Create user '%s'", chi.URLParam(r, "rref")))) + _, _ = w.Write([]byte(fmt.Sprintf("Create user '%s'", chi.URLParam(r, "rref")))) }) r.Put("/", func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(fmt.Sprintf("Update user '%s'", chi.URLParam(r, "rref")))) + _, _ = w.Write([]byte(fmt.Sprintf("Update user '%s'", chi.URLParam(r, "rref")))) }) r.Delete("/", func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(fmt.Sprintf("Delete user '%s'", chi.URLParam(r, "rref")))) + _, _ = w.Write([]byte(fmt.Sprintf("Delete user '%s'", chi.URLParam(r, "rref")))) }) }) }) diff --git a/internal/router/git.go b/internal/router/git.go index e1798cac3..f524312a5 100644 --- a/internal/router/git.go +++ b/internal/router/git.go @@ -92,7 +92,7 @@ func stubGitHandler(w http.ResponseWriter, r *http.Request) { rep, _ := request.RepoFrom(r.Context()) w.WriteHeader(http.StatusTeapot) - w.Write([]byte(fmt.Sprintf( + _, _ = w.Write([]byte(fmt.Sprintf( "Oooops, seems you hit a major construction site ... \n"+ " Repo: '%s' (%s)\n"+ " Method: '%s'\n"+ diff --git a/internal/server/server.go b/internal/server/server.go index 357e304df..bcd743519 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -41,10 +41,8 @@ func (s *Server) listenAndServe(ctx context.Context) error { Handler: s.Handler, } g.Go(func() error { - select { - case <-ctx.Done(): - return s1.Shutdown(ctx) - } + <-ctx.Done() + return s1.Shutdown(ctx) }) g.Go(func() error { return s1.ListenAndServe() @@ -72,12 +70,14 @@ func (s *Server) listenAndServeTLS(ctx context.Context) error { ) }) g.Go(func() error { - select { - case <-ctx.Done(): - s1.Shutdown(ctx) - s2.Shutdown(ctx) - return nil + <-ctx.Done() + if err := s1.Shutdown(ctx); err != nil { + return err } + if err := s2.Shutdown(ctx); err != nil { + return err + } + return nil }) return g.Wait() } @@ -108,12 +108,14 @@ func (s Server) listenAndServeAcme(ctx context.Context) error { return s2.ListenAndServeTLS("", "") }) g.Go(func() error { - select { - case <-ctx.Done(): - s1.Shutdown(ctx) - s2.Shutdown(ctx) - return nil + <-ctx.Done() + if err := s1.Shutdown(ctx); err != nil { + return err } + if err := s2.Shutdown(ctx); err != nil { + return err + } + return nil }) return g.Wait() } diff --git a/internal/store/database/path.go b/internal/store/database/path.go index ce1aee304..97c40c2d3 100644 --- a/internal/store/database/path.go +++ b/internal/store/database/path.go @@ -199,14 +199,15 @@ func DeletePath(ctx context.Context, db *sqlx.DB, id int64) error { if err != nil { return processSqlErrorf(err, "Failed to start a new transaction") } - defer tx.Rollback() + defer func(tx *sqlx.Tx) { + _ = tx.Rollback() + }(tx) // ensure path is an alias dst := new(types.Path) - err = tx.GetContext(ctx, dst, pathSelectId, id) - if err != nil { + if err = tx.GetContext(ctx, dst, pathSelectId, id); err != nil { return processSqlErrorf(err, "Failed to find path with id %d", id) - } else if dst.IsAlias == false { + } else if !dst.IsAlias { return store.ErrPrimaryPathCantBeDeleted } @@ -360,10 +361,6 @@ const pathSelectId = pathBase + ` WHERE path_id = $1 ` -const pathSelectPath = pathBase + ` -WHERE path_value = $1 -` - const pathDeleteId = ` DELETE FROM paths WHERE path_id = $1 diff --git a/internal/store/database/repo.go b/internal/store/database/repo.go index c6e43e979..efdbb673d 100644 --- a/internal/store/database/repo.go +++ b/internal/store/database/repo.go @@ -54,7 +54,9 @@ func (s *RepoStore) Create(ctx context.Context, repo *types.Repository) error { if err != nil { return processSqlErrorf(err, "Failed to start a new transaction") } - defer tx.Rollback() + defer func(tx *sqlx.Tx) { + _ = tx.Rollback() + }(tx) // insert repo first so we get id query, arg, err := s.db.BindNamed(repoInsert, repo) @@ -107,7 +109,9 @@ func (s *RepoStore) Move(ctx context.Context, userId int64, repoId int64, newSpa if err != nil { return nil, processSqlErrorf(err, "Failed to start a new transaction") } - defer tx.Rollback() + defer func(tx *sqlx.Tx) { + _ = tx.Rollback() // should we take care about rollbacks errors? + }(tx) // get current path of repo currentPath, err := FindPathTx(ctx, tx, enum.PathTargetTypeRepo, repoId) @@ -168,7 +172,7 @@ func (s *RepoStore) Update(ctx context.Context, repo *types.Repository) error { } if _, err = s.db.ExecContext(ctx, query, arg...); err != nil { - processSqlErrorf(err, "Update query failed") + return processSqlErrorf(err, "Update query failed") } return nil @@ -180,7 +184,9 @@ func (s *RepoStore) Delete(ctx context.Context, id int64) error { if err != nil { return processSqlErrorf(err, "Failed to start a new transaction") } - defer tx.Rollback() + defer func(tx *sqlx.Tx) { + _ = tx.Rollback() + }(tx) // delete all paths err = DeleteAllPaths(ctx, tx, enum.PathTargetTypeRepo, id) diff --git a/internal/store/database/space.go b/internal/store/database/space.go index 94576af10..8d09daa4a 100644 --- a/internal/store/database/space.go +++ b/internal/store/database/space.go @@ -55,7 +55,9 @@ func (s *SpaceStore) Create(ctx context.Context, space *types.Space) error { if err != nil { return processSqlErrorf(err, "Failed to start a new transaction") } - defer tx.Rollback() + defer func(tx *sqlx.Tx) { + _ = tx.Rollback() + }(tx) // insert space first so we get id query, arg, err := s.db.BindNamed(spaceInsert, space) @@ -111,7 +113,9 @@ func (s *SpaceStore) Move(ctx context.Context, userId int64, spaceId int64, newP if err != nil { return nil, processSqlErrorf(err, "Failed to start a new transaction") } - defer tx.Rollback() + defer func(tx *sqlx.Tx) { + _ = tx.Rollback() + }(tx) // always get currentpath (either it didn't change or we need to for validation) currentPath, err := FindPathTx(ctx, tx, enum.PathTargetTypeSpace, spaceId) @@ -183,7 +187,7 @@ func (s *SpaceStore) Update(ctx context.Context, space *types.Space) error { } if _, err = s.db.ExecContext(ctx, query, arg...); err != nil { - processSqlErrorf(err, "Update query failed") + return processSqlErrorf(err, "Update query failed") } return nil @@ -195,7 +199,9 @@ func (s *SpaceStore) Delete(ctx context.Context, id int64) error { if err != nil { return processSqlErrorf(err, "Failed to start a new transaction") } - defer tx.Rollback() + defer func(tx *sqlx.Tx) { + _ = tx.Rollback() + }(tx) // get primary path path, err := FindPathTx(ctx, tx, enum.PathTargetTypeSpace, id) @@ -205,9 +211,10 @@ func (s *SpaceStore) Delete(ctx context.Context, id int64) error { // Get child count and ensure there are none count, err := CountPrimaryChildPathsTx(ctx, tx, path.Value) - if err := tx.QueryRow(spaceCount, id).Scan(&count); err != nil { - return errors.Wrap(err, "Failed to count the child paths of the space") - } else if count > 0 { + if err != nil { + return fmt.Errorf("child count error: %w", err) + } + if count > 0 { // TODO: still returns 500 return store.ErrSpaceWithChildsCantBeDeleted } @@ -219,7 +226,7 @@ func (s *SpaceStore) Delete(ctx context.Context, id int64) error { } // delete the space - if _, err := tx.Exec(spaceDelete, id); err != nil { + if _, err = tx.Exec(spaceDelete, id); err != nil { return processSqlErrorf(err, "The delete query failed") } diff --git a/internal/store/database/store_test.go b/internal/store/database/store_test.go index 9e218aa53..9fb36fc91 100644 --- a/internal/store/database/store_test.go +++ b/internal/store/database/store_test.go @@ -5,14 +5,11 @@ package database import ( - "bytes" "context" "encoding/json" + "github.com/jmoiron/sqlx" "io/ioutil" "os" - "testing" - - "github.com/jmoiron/sqlx" _ "github.com/lib/pq" _ "github.com/mattn/go-sqlite3" @@ -35,12 +32,12 @@ func connect() (*sqlx.DB, error) { // seed seed the database state. func seed(db *sqlx.DB) error { - db.Exec("DELETE FROM executions") - db.Exec("DELETE FROM pipelines") - db.Exec("DELETE FROM users") - db.Exec("ALTER SEQUENCE users_user_id_seq RESTART WITH 1") - db.Exec("ALTER SEQUENCE pipelines_pipeline_id_seq RESTART WITH 1") - db.Exec("ALTER SEQUENCE executions_execution_id_seq RESTART WITH 1") + _, _ = db.Exec("DELETE FROM executions") + _, _ = db.Exec("DELETE FROM pipelines") + _, _ = db.Exec("DELETE FROM users") + _, _ = db.Exec("ALTER SEQUENCE users_user_id_seq RESTART WITH 1") + _, _ = db.Exec("ALTER SEQUENCE pipelines_pipeline_id_seq RESTART WITH 1") + _, _ = db.Exec("ALTER SEQUENCE executions_execution_id_seq RESTART WITH 1") return nil } @@ -52,12 +49,3 @@ func unmarshal(path string, v interface{}) error { } return json.Unmarshal(out, v) } - -// dump json data to the test logs. -func debug(t *testing.T, v interface{}) { - buf := new(bytes.Buffer) - enc := json.NewEncoder(os.Stdout) - enc.SetIndent("", " ") - enc.Encode(v) - t.Log(buf.String()) -} diff --git a/internal/store/database/user.go b/internal/store/database/user.go index 28373c69e..d80f542c9 100644 --- a/internal/store/database/user.go +++ b/internal/store/database/user.go @@ -6,6 +6,7 @@ package database import ( "context" + "database/sql" "strconv" "github.com/harness/gitness/internal/store" @@ -136,7 +137,9 @@ func (s *UserStore) Delete(ctx context.Context, user *types.User) error { if err != nil { return processSqlErrorf(err, "Failed to start a new transaction") } - defer tx.Rollback() + defer func(tx *sql.Tx) { + _ = tx.Rollback() + }(tx) // delete the user if _, err := tx.ExecContext(ctx, userDelete, user.ID); err != nil { return processSqlErrorf(err, "The delete query failed") @@ -188,10 +191,6 @@ const userSelectEmail = userBase + ` WHERE user_email = $1 ` -const userSelectToken = userBase + ` -WHERE user_salt = $1 -` - const userDelete = ` DELETE FROM users WHERE user_id = $1 diff --git a/internal/store/database/user_test.go b/internal/store/database/user_test.go index 3d62a6f30..7d7bd321b 100644 --- a/internal/store/database/user_test.go +++ b/internal/store/database/user_test.go @@ -15,7 +15,6 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/jmoiron/sqlx" ) // user fields to ignore in test comparisons @@ -252,20 +251,3 @@ func testUserDelete(s store.UserStore) func(t *testing.T) { } } } - -// helper function that returns an user store that is seeded -// with user data loaded from a json file. -func newUserStoreSeeded(db *sqlx.DB) (store.UserStore, error) { - store := NewUserStoreSync(NewUserStore(db)) - vv := []*types.User{} - if err := unmarshal("testdata/users.json", &vv); err != nil { - return nil, err - } - for _, v := range vv { - v.Salt = fmt.Sprintf("%x", v.Email) - if err := store.Create(noContext, v); err != nil { - return nil, err - } - } - return store, nil -} diff --git a/types/check/common.go b/types/check/common.go index 9ecedcdeb..78700814f 100644 --- a/types/check/common.go +++ b/types/check/common.go @@ -21,10 +21,10 @@ const ( var ( ErrNameLength = &CheckError{fmt.Sprintf("Name has to be between %d and %d in length.", minNameLength, maxNameLength)} - ErrNameRegex = &CheckError{fmt.Sprintf("Name has start with a letter and only contain the following [a-z0-9-_].")} + ErrNameRegex = &CheckError{"Name has start with a letter and only contain the following [a-z0-9-_]."} ErrDisplayNameLength = &CheckError{fmt.Sprintf("Display name has to be between %d and %d in length.", minDisplayNameLength, maxDisplayNameLength)} - ErrDisplayNameRegex = &CheckError{fmt.Sprintf("Display name has start with a letter and only contain the following [a-zA-Z0-9-_ ].")} + ErrDisplayNameRegex = &CheckError{"Display name has start with a letter and only contain the following [a-zA-Z0-9-_ ]."} ) // Name checks the provided name and returns an error in it isn't valid. diff --git a/types/check/path.go b/types/check/path.go index a4b699f2a..2ee2eba1a 100644 --- a/types/check/path.go +++ b/types/check/path.go @@ -46,7 +46,7 @@ func Path(path string, isSpace bool) error { // ensure path is not too deep segments := strings.Split(path, types.PathSeparator) l := len(segments) - if l < minPathSegments || (isSpace == false && l > maxPathSegments) || (isSpace && l > maxPathSegmentsForSpace) { + if l < minPathSegments || (!isSpace && l > maxPathSegments) || (isSpace && l > maxPathSegmentsForSpace) { return ErrPathInvalidSize } @@ -100,5 +100,5 @@ func PathParams(path *types.PathParams, currentPath string, isSpace bool) error */ func PathTooLong(path string, isSpace bool) bool { l := strings.Count(path, types.PathSeparator) + 1 - return (isSpace == false && l > maxPathSegments) || (isSpace && l > maxPathSegmentsForSpace) + return (!isSpace && l > maxPathSegments) || (isSpace && l > maxPathSegmentsForSpace) }