-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #50 from bufbuild/rodaine/builder-refactor
Refactor Registry To Match Bike Shedding
- Loading branch information
Showing
46 changed files
with
1,822 additions
and
2,295 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,28 +28,23 @@ clean: ## Delete intermediate build artifacts | |
|
||
.PHONY: test | ||
test: build ## Run unit tests | ||
$(GO) test -vet=off -race -cover ./... | ||
$(GO) test -race -cover ./go/... | ||
|
||
.PHONY: build | ||
build: generate ## Build all packages | ||
$(GO) build ./... | ||
|
||
.PHONY: install | ||
install: ## Install all binaries | ||
$(GO) install ./... | ||
$(GO) build ./go/... | ||
|
||
.PHONY: lint | ||
lint: $(BIN)/golangci-lint ## Lint Go and protobuf | ||
$(GO) vet ./... | ||
$(BIN)/golangci-lint run | ||
cd ./go && ../$(BIN)/golangci-lint run | ||
|
||
.PHONY: lintfix | ||
lintfix: $(BIN)/golangci-lint ## Automatically fix some lint errors | ||
$(BIN)/golangci-lint run --fix | ||
cd ./go && ../$(BIN)/golangci-lint run --fix | ||
|
||
.PHONY: generate | ||
generate: $(BIN)/buf $(BIN)/protoc-gen-go $(BIN)/license-header ## Regenerate code and licenses | ||
rm -rf gen | ||
generate: $(BIN)/buf $(BIN)/license-header ## Regenerate code and licenses | ||
rm -rf go/gen | ||
PATH=$(abspath $(BIN)) buf generate | ||
@# We want to operate on a list of modified and new files, excluding | ||
@# deleted and ignored files. git-ls-files can't do this alone. comm -23 takes | ||
|
@@ -67,7 +62,7 @@ generate: $(BIN)/buf $(BIN)/protoc-gen-go $(BIN)/license-header ## Regenerate co | |
|
||
.PHONY: upgrade | ||
upgrade: ## Upgrade dependencies | ||
$(GO) get -u -t ./... && go mod tidy -v | ||
cd ./go && $(GO) get -u -t ./... && go mod tidy -v | ||
|
||
.PHONY: checkgenerate | ||
checkgenerate: | ||
|
@@ -76,18 +71,18 @@ checkgenerate: | |
|
||
.PHONY: benchmarks | ||
benchmarks: ## Run benchmarks tests | ||
$(GO) test -bench=. -count=10 > ./.tmp/benchmarks.txt | ||
$(GO) test -bench=. -count=10 ./go/... > ./.tmp/benchmarks.txt | ||
|
||
.PHONY: profile | ||
profile: memprofile cpuprofile ## Generate memory and cpu profile | ||
|
||
.PHONY: memprofile | ||
memprofile: | ||
$(GO) test -bench=. -count=10 -memprofile .tmp/memprofile.out | ||
$(GO) test -bench=. -count=10 -memprofile .tmp/memprofile.out ./go | ||
|
||
.PHONY: cpuprofile | ||
cpuprofile: | ||
$(GO) test -bench=. -count=10 -cpuprofile .tmp/cpuprofile.out | ||
$(GO) test -bench=. -count=10 -cpuprofile .tmp/cpuprofile.out ./go | ||
|
||
.PHONY: showmemprofile ## Visualize memory profile | ||
showmemprofile: memprofile | ||
|
@@ -101,11 +96,6 @@ $(BIN)/buf: Makefile | |
@mkdir -p $(@D) | ||
GOBIN=$(abspath $(@D)) $(GO) install github.com/bufbuild/buf/cmd/[email protected] | ||
|
||
$(BIN)/protoc-gen-go: Makefile | ||
@mkdir -p $(@D) | ||
@# The version of protoc-gen-go is determined by the version in go.mod | ||
GOBIN=$(abspath $(@D)) $(GO) install google.golang.org/protobuf/cmd/protoc-gen-go | ||
|
||
$(BIN)/license-header: Makefile | ||
@mkdir -p $(@D) | ||
GOBIN=$(abspath $(@D)) $(GO) install \ | ||
|
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
use ( | ||
"go" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
// Copyright 2023 Buf Technologies, Inc. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package protovalidate | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/bufbuild/protovalidate/go/gen/buf/validate" | ||
) | ||
|
||
func mergeErrors(dst, src error, failFast bool) (err error, ok bool) { | ||
if src == nil { | ||
return dst, true | ||
} | ||
|
||
srcValErrs, ok := src.(*ValidationError) | ||
if !ok { | ||
return src, false | ||
} | ||
|
||
if dst == nil { | ||
return src, !(failFast && srcValErrs.hasViolations()) | ||
} | ||
|
||
dstValErrs, ok := dst.(*ValidationError) | ||
if !ok { | ||
// what should we do here? | ||
return dst, false | ||
} | ||
|
||
dstValErrs.Violations = append(dstValErrs.Violations, srcValErrs.Violations...) | ||
return dst, !(failFast && dstValErrs.hasViolations()) | ||
} | ||
|
||
// A ValidationError is returned if one or more constraint violations were | ||
// detected. | ||
type ValidationError validate.Violations | ||
|
||
func (err *ValidationError) Error() string { | ||
sb := &strings.Builder{} | ||
sb.WriteString("[protovalidate] validation error:\n") | ||
for _, violation := range err.Violations { | ||
sb.WriteString(" - ") | ||
if violation.FieldPath != "" { | ||
sb.WriteString(violation.FieldPath) | ||
sb.WriteString(": ") | ||
} | ||
_, _ = fmt.Fprintf(sb, "%s [%s]\n", | ||
violation.Message, | ||
violation.ConstraintId) | ||
} | ||
return sb.String() | ||
} | ||
|
||
func (err *ValidationError) ToProto() *validate.Violations { return (*validate.Violations)(err) } | ||
|
||
func (err *ValidationError) prefixPaths(prefix string, sep string) { | ||
for _, violation := range err.Violations { | ||
if violation.FieldPath == "" { | ||
violation.FieldPath = prefix | ||
} else { | ||
violation.FieldPath = prefix + sep + violation.FieldPath | ||
} | ||
} | ||
} | ||
|
||
func (err *ValidationError) hasViolations() bool { | ||
return err != nil && len(err.Violations) > 0 | ||
} | ||
|
||
// A RuntimeError is returned if a valid CEL expression evaluation is terminated. | ||
// The two built-in reasons are 'no_matching_overload' when a CEL function has | ||
// no overload for the types of the arguments or 'no_such_field' when a map or | ||
// message does not contain the desired field. | ||
type RuntimeError struct { | ||
cause error | ||
} | ||
|
||
func (err RuntimeError) Error() string { | ||
return fmt.Sprintf("[protovalidate] runtime error: %v", err.cause) | ||
} | ||
|
||
func (err RuntimeError) Unwrap() error { return err.cause } | ||
|
||
// A CompilationError is returned if a CEL expression cannot be compiled and | ||
// type-checked. | ||
type CompilationError struct { | ||
cause error | ||
} | ||
|
||
func (err CompilationError) Error() string { | ||
return fmt.Sprintf("[protovalidate] compilation error: %v", err.cause) | ||
} | ||
|
||
func (err CompilationError) Unwrap() error { return err.cause } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
// Copyright 2023 Buf Technologies, Inc. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package protovalidate | ||
|
||
import ( | ||
validatev2 "github.com/bufbuild/protovalidate/go/gen/buf/validate" | ||
"google.golang.org/protobuf/reflect/protoreflect" | ||
) | ||
|
||
type evaluator interface { | ||
evaluate(msg protoreflect.Message, failFast bool) error | ||
} | ||
|
||
type messageEvaluator struct { | ||
err error | ||
constraints []evaluator | ||
} | ||
|
||
func (m *messageEvaluator) evaluate(msg protoreflect.Message, failFast bool) error { | ||
if err := m.err; err != nil { | ||
return err | ||
} | ||
var ( | ||
err error | ||
ok bool | ||
) | ||
for _, constraint := range m.constraints { | ||
evalErr := constraint.evaluate(msg, failFast) | ||
if err, ok = mergeErrors(err, evalErr, failFast); !ok { | ||
break | ||
} | ||
} | ||
return err | ||
} | ||
|
||
type messageExpressionEvaluator struct { | ||
exprs []compiledExpression | ||
} | ||
|
||
func (m messageExpressionEvaluator) evaluate(msg protoreflect.Message, failFast bool) error { | ||
binding := namedBinding{name: "this", val: msg.Interface()} | ||
return evalExprs(m.exprs, binding, failFast) | ||
} | ||
|
||
type fieldExpressionEvaluator struct { | ||
field protoreflect.FieldDescriptor | ||
exprs []compiledExpression | ||
} | ||
|
||
func (f fieldExpressionEvaluator) evaluate(msg protoreflect.Message, failFast bool) error { | ||
binding := namedBinding{name: "this", val: msg.Get(f.field)} | ||
err := evalExprs(f.exprs, binding, failFast) | ||
if valErr, ok := err.(*ValidationError); ok { | ||
valErr.prefixPaths(string(f.field.Name()), ".") | ||
} | ||
return err | ||
} | ||
|
||
type messageFieldEvaluator struct { | ||
field protoreflect.FieldDescriptor | ||
embeddedMessageEvaluator | ||
} | ||
|
||
func (m messageFieldEvaluator) evaluate(msg protoreflect.Message, failFast bool) error { | ||
fldMsg := msg.Get(m.field).Message() | ||
err := m.embeddedMessageEvaluator.evaluate(fldMsg, failFast) | ||
if valErr, ok := err.(*ValidationError); ok { | ||
valErr.prefixPaths(string(m.field.FullName()), ".") | ||
} | ||
return err | ||
} | ||
|
||
type embeddedMessageEvaluator struct { | ||
required bool | ||
skipped bool | ||
|
||
msgEval *messageEvaluator | ||
exprs []compiledExpression | ||
} | ||
|
||
func (e embeddedMessageEvaluator) evaluate(msg protoreflect.Message, failFast bool) error { | ||
if e.required && !msg.IsValid() { | ||
return &ValidationError{Violations: []*validatev2.Violation{{ | ||
ConstraintId: "required", | ||
Message: "value is required", | ||
}}} | ||
} | ||
|
||
var ( | ||
err error | ||
ok bool | ||
) | ||
if !e.skipped && msg.IsValid() { | ||
evalErr := e.msgEval.evaluate(msg, failFast) | ||
err, ok = mergeErrors(err, evalErr, failFast) | ||
if !ok { | ||
return err | ||
} | ||
} | ||
|
||
binding := namedBinding{name: "this", val: msg.Interface()} | ||
evalErr := evalExprs(e.exprs, binding, failFast) | ||
err, _ = mergeErrors(err, evalErr, failFast) | ||
return err | ||
} | ||
|
||
var ( | ||
_ evaluator = (*messageEvaluator)(nil) | ||
_ evaluator = messageExpressionEvaluator{} | ||
_ evaluator = fieldExpressionEvaluator{} | ||
_ evaluator = messageFieldEvaluator{} | ||
_ evaluator = embeddedMessageEvaluator{} | ||
) |
Oops, something went wrong.