Compare commits
68 Commits
Author | SHA1 | Date | |
---|---|---|---|
07743e46cd | |||
abdce361b5 | |||
40071a52f9 | |||
05a63554c5 | |||
8a03bb83be | |||
69c0256439 | |||
9f0398ffae | |||
822af715a3 | |||
7b092aa8c4 | |||
684dc1ef7c | |||
0fcdb13eb8 | |||
4aadfe3def | |||
853c7734e6 | |||
d5882c0243 | |||
c53f33cbf7 | |||
b563f3890a | |||
538de91555 | |||
766dbf8abe | |||
f68037f057 | |||
b265231dca | |||
36ce7028a0 | |||
ea6b2be648 | |||
df19a8c2f5 | |||
fcfbca695a | |||
7751dfea95 | |||
bc84a6fb50 | |||
f94f6962f5 | |||
63a16a3253 | |||
d5a7d1d9a4 | |||
285349a481 | |||
e1f28c3d93 | |||
5a75d11f8a | |||
d1f0d5c64c | |||
dc9688d53d | |||
9823c97d56 | |||
d2312ef5d9 | |||
ffab7c3cd0 | |||
5f1c0e9199 | |||
01560e497f | |||
4aa0313e73 | |||
db7012fe3b | |||
4a21568bcd | |||
ea314f1fae | |||
eb3430d180 | |||
a99ae51a49 | |||
93437074ac | |||
3de8271fb1 | |||
b7418991e1 | |||
70ed46d408 | |||
8e9b7d5e3e | |||
71aa7282b5 | |||
cdc35d2992 | |||
3b630a6dbd | |||
9c9ed4e94a | |||
62e1ee822a | |||
949d97b49c | |||
a369f65cba | |||
ae35d9ab41 | |||
d5e48e86b6 | |||
c0b7c2b5fd | |||
61bd2f41c7 | |||
ee85b7c9d2 | |||
8f33ce3a00 | |||
35fe4a04df | |||
e0b2640000 | |||
9af55ee991 | |||
979040227e | |||
2ad0221259 |
31
.air.toml
Normal file
31
.air.toml
Normal file
@ -0,0 +1,31 @@
|
||||
root = "."
|
||||
tmp_dir = "tmp"
|
||||
|
||||
[build]
|
||||
cmd = "go build -o ./tmp/main ."
|
||||
bin = "tmp/main"
|
||||
full_bin = "./tmp/main web -c config.example.yaml"
|
||||
include_ext = ["go", "tpl", "tmpl", "html", "js"]
|
||||
exclude_dir = ["tmp", "vendor"]
|
||||
include_dir = []
|
||||
exclude_file = []
|
||||
exclude_regex = ["_test.go"]
|
||||
exclude_unchanged = true
|
||||
follow_symlink = true
|
||||
log = "air.log"
|
||||
delay = 1000 # ms
|
||||
stop_on_error = true
|
||||
send_interrupt = false
|
||||
kill_delay = 500 # ms
|
||||
|
||||
[log]
|
||||
time = false
|
||||
|
||||
[color]
|
||||
main = "magenta"
|
||||
watcher = "cyan"
|
||||
build = "yellow"
|
||||
runner = "green"
|
||||
|
||||
[misc]
|
||||
clean_on_exit = true
|
132
.drone.yml
132
.drone.yml
@ -1,6 +1,8 @@
|
||||
---
|
||||
kind: pipeline
|
||||
name: default
|
||||
node:
|
||||
runner: hetzner
|
||||
|
||||
steps:
|
||||
- name: tags
|
||||
@ -9,44 +11,154 @@ steps:
|
||||
- git fetch --tags
|
||||
|
||||
- name: lint
|
||||
image: golangci/golangci-lint:latest
|
||||
image: golangci/golangci-lint:v1.42.0
|
||||
commands:
|
||||
- make lint
|
||||
- make install-tools
|
||||
- make lint-go
|
||||
- make lint-buf
|
||||
depends_on:
|
||||
- tags
|
||||
|
||||
- name: lint-js
|
||||
image: alpine:3.14
|
||||
commands:
|
||||
- >
|
||||
apk add
|
||||
make
|
||||
nodejs
|
||||
npm
|
||||
- >
|
||||
npm install
|
||||
eslint
|
||||
prettier
|
||||
eslint-plugin-prettier
|
||||
eslint-config-prettier
|
||||
- export PATH=$PWD/node_modules/.bin:$PATH
|
||||
- make lint-js
|
||||
- make clean
|
||||
depends_on:
|
||||
- tags
|
||||
|
||||
- name: test
|
||||
image: golang:latest
|
||||
image: golang:1.17
|
||||
pull: always
|
||||
commands:
|
||||
- make test
|
||||
depends_on:
|
||||
- tags
|
||||
|
||||
- name: build
|
||||
image: goreleaser/goreleaser:v0.162.0
|
||||
- name: create-image
|
||||
image: docker:latest
|
||||
volumes:
|
||||
- name: dockersock
|
||||
path: /var/run
|
||||
- name: swap
|
||||
path: /SWAP
|
||||
commands:
|
||||
- apk add --no-cache openssh-client curl
|
||||
- mkdir ~/.ssh
|
||||
- curl https://raw.githubusercontent.com/xsteadfastx/docker-qemu-alpine/main/ssh -o ~/.ssh/id_rsa
|
||||
- chmod 600 ~/.ssh/id_rsa
|
||||
- wget -O /usr/local/bin/don https://git.xsfx.dev/attachments/8f8f4dbb-8254-448a-a549-552f8b96cb26
|
||||
- chmod +x /usr/local/bin/don
|
||||
- don -t 15m -r 15s -c "ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 root@qemu-alpine"
|
||||
- cat scripts/rpi-image-test/build.sh | ssh -i ssh -o StrictHostKeyChecking=no root@qemu-alpine
|
||||
- ssh -i ssh -o StrictHostKeyChecking=no root@qemu-alpine poweroff
|
||||
- ls -lah /SWAP
|
||||
depends_on:
|
||||
- lint
|
||||
- lint-js
|
||||
- test
|
||||
|
||||
- name: prepare-image
|
||||
image: golang:1.17
|
||||
volumes:
|
||||
- name: dockersock
|
||||
path: /var/run
|
||||
commands:
|
||||
- (cd /tmp; go install -v github.com/goreleaser/goreleaser@v0.169.0)
|
||||
- make test-integration
|
||||
depends_on:
|
||||
- lint
|
||||
- lint-js
|
||||
- test
|
||||
- create-image
|
||||
|
||||
- name: create-torrent
|
||||
image: golang:1.16-alpine
|
||||
volumes:
|
||||
- name: swap
|
||||
path: /SWAP
|
||||
commands:
|
||||
- apk add zip
|
||||
- (cd /tmp; go get -v github.com/cenkalti/rain@v1.6.4)
|
||||
- cd /SWAP
|
||||
- zip 2021-05-07-raspios-buster-armhf-lite.zip 2021-05-07-raspios-buster-armhf-lite.img
|
||||
- rain torrent create -o schnutibox.torrent -f 2021-05-07-raspios-buster-armhf-lite.zip
|
||||
- ls -lah
|
||||
depends_on:
|
||||
- prepare-image
|
||||
|
||||
- name: build
|
||||
image: goreleaser/goreleaser:v0.176.0
|
||||
commands:
|
||||
- (cd /tmp; go get -u github.com/go-bindata/go-bindata/...)
|
||||
- make build
|
||||
depends_on:
|
||||
- tags
|
||||
- lint
|
||||
- lint-js
|
||||
- test
|
||||
- prepare-image
|
||||
when:
|
||||
event:
|
||||
exclude:
|
||||
- tag
|
||||
|
||||
- name: release
|
||||
image: goreleaser/goreleaser:v0.162.0
|
||||
image: goreleaser/goreleaser:v0.176.0
|
||||
volumes:
|
||||
- name: dockersock
|
||||
path: /var/run
|
||||
environment:
|
||||
GITHUB_TOKEN:
|
||||
from_secret: github_token
|
||||
DOCKER_USERNAME:
|
||||
from_secret: docker_username
|
||||
DOCKER_PASSWORD:
|
||||
from_secret: github_token
|
||||
DOCKER_REGISTRY: ghcr.io
|
||||
commands:
|
||||
- sleep 5
|
||||
- >
|
||||
echo $DOCKER_PASSWORD |
|
||||
docker login $DOCKER_REGISTRY -u $DOCKER_USERNAME --password-stdin
|
||||
- goreleaser release --rm-dist
|
||||
depends_on:
|
||||
- tags
|
||||
- lint
|
||||
- test
|
||||
- lint
|
||||
- lint-js
|
||||
when:
|
||||
event:
|
||||
- tag
|
||||
|
||||
services:
|
||||
- name: docker
|
||||
image: docker:dind
|
||||
privileged: true
|
||||
volumes:
|
||||
- name: dockersock
|
||||
path: /var/run
|
||||
- name: swap
|
||||
path: /SWAP
|
||||
|
||||
- name: qemu-alpine
|
||||
image: ghcr.io/xsteadfastx/qemu-alpine:latest
|
||||
volumes:
|
||||
- name: swap
|
||||
path: /SWAP
|
||||
|
||||
volumes:
|
||||
- name: dockersock
|
||||
temp: {}
|
||||
|
||||
- name: swap
|
||||
temp: {}
|
||||
|
6
.eslintrc.json
Normal file
6
.eslintrc.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"env": {
|
||||
"browser": true
|
||||
},
|
||||
"extends": ["eslint:recommended", "prettier"]
|
||||
}
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,6 @@
|
||||
config.y*
|
||||
dist/
|
||||
.envrc
|
||||
tmp/*
|
||||
node_modules/*
|
||||
package*
|
||||
|
@ -18,9 +18,9 @@ builds:
|
||||
- "-s"
|
||||
- "-w"
|
||||
- "-extldflags '-static'"
|
||||
- "-X go.xsfx.dev/cmd.version={{.Version}}"
|
||||
- "-X go.xsfx.dev/cmd.commit={{.ShortCommit}}"
|
||||
- "-X go.xsfx.dev/cmd.date={{.Date}}"
|
||||
- "-X go.xsfx.dev/schnutibox/cmd.version={{.Version}}"
|
||||
- "-X go.xsfx.dev/schnutibox/cmd.commit={{.ShortCommit}}"
|
||||
- "-X go.xsfx.dev/schnutibox/cmd.date={{.Date}}"
|
||||
|
||||
checksum:
|
||||
name_template: "checksums.txt"
|
||||
@ -35,9 +35,19 @@ changelog:
|
||||
- "^docs:"
|
||||
- "^test:"
|
||||
- "^ci:"
|
||||
- "^dev:"
|
||||
- "happy linting"
|
||||
|
||||
release:
|
||||
github:
|
||||
owner: xsteadfastx
|
||||
name: schnutibox
|
||||
|
||||
dockers:
|
||||
- dockerfile: build/package/docker/Dockerfile
|
||||
goos: linux
|
||||
goarch: amd64
|
||||
image_templates:
|
||||
- ghcr.io/xsteadfastx/schnutibox:latest
|
||||
- ghcr.io/xsteadfastx/schnutibox:{{ .Tag }}
|
||||
- ghcr.io/xsteadfastx/schnutibox:v{{ .Major}}
|
||||
|
1
.prettierrc.json
Normal file
1
.prettierrc.json
Normal file
@ -0,0 +1 @@
|
||||
{}
|
45
Makefile
45
Makefile
@ -11,16 +11,30 @@ generate:
|
||||
go generate
|
||||
|
||||
.PHONY: lint
|
||||
lint:
|
||||
golangci-lint run --timeout 10m --enable-all --disable=exhaustivestruct
|
||||
lint: lint-go lint-buf lint-js
|
||||
|
||||
.PHONY: lint-go
|
||||
lint-go:
|
||||
golangci-lint run --timeout 10m --enable-all --disable=exhaustivestruct,godox
|
||||
|
||||
.PHONY: lint-buf
|
||||
lint-buf:
|
||||
buf lint -v
|
||||
|
||||
.PHONY: lint-js
|
||||
lint-js:
|
||||
eslint assets/web/files/**.js
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
go test -v -race -cover ./...
|
||||
|
||||
.PHONY: test-integration
|
||||
test-integration: release
|
||||
go test -v -tags=integration -timeout=120m
|
||||
test-integration: build
|
||||
go test -v -tags=integration -timeout=240m
|
||||
|
||||
.PHONY: test-all
|
||||
test-all: test test-integration
|
||||
|
||||
.PHONY: readme
|
||||
readme:
|
||||
@ -33,4 +47,25 @@ tidy:
|
||||
|
||||
.PHONY: build-image
|
||||
build-image:
|
||||
sudo ./scripts/build.sh
|
||||
./scripts/build.sh
|
||||
|
||||
.PHONY: install-tools
|
||||
install-tools:
|
||||
@cat tools.go | grep _ | awk -F'"' '{print $$2}' | xargs -tI % go install %
|
||||
|
||||
.PHONY: grpc-gen
|
||||
grpc-gen:
|
||||
buf generate -v
|
||||
|
||||
.PHONY: air
|
||||
air:
|
||||
air
|
||||
|
||||
.PHONY: drone-local
|
||||
drone-local:
|
||||
drone exec --trusted --timeout 5h
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf node_modules
|
||||
rm -rf package* || exit 0
|
||||
|
45
api/proto/v1/schnutibox.proto
Normal file
45
api/proto/v1/schnutibox.proto
Normal file
@ -0,0 +1,45 @@
|
||||
syntax = "proto3";
|
||||
package schnutibox.v1;
|
||||
option go_package = "go.xsfx.dev/schnutibox/pkg/api/v1";
|
||||
import "google/api/annotations.proto";
|
||||
import "google/protobuf/duration.proto";
|
||||
|
||||
service IdentifierService {
|
||||
rpc Identify (IdentifyRequest) returns (IdentifyResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/api/v1/identify"
|
||||
body: "*"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
message IdentifyRequest {
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
message IdentifyResponse {
|
||||
string name = 1;
|
||||
repeated string uris = 2;
|
||||
}
|
||||
|
||||
service TimerService {
|
||||
rpc Create(Timer) returns (Timer) {
|
||||
option (google.api.http) = {
|
||||
post: "/api/v1/timer"
|
||||
body: "*"
|
||||
};
|
||||
}
|
||||
|
||||
rpc Get(TimerEmpty) returns (Timer) {
|
||||
option (google.api.http) = {
|
||||
get: "/api/v1/timer"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
message Timer {
|
||||
google.protobuf.Duration duration = 1;
|
||||
google.protobuf.Duration current = 2;
|
||||
}
|
||||
|
||||
message TimerEmpty {}
|
31
api/proto/vendor/google/api/annotations.proto
vendored
Normal file
31
api/proto/vendor/google/api/annotations.proto
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2015 Google LLC
|
||||
//
|
||||
// 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.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.api;
|
||||
|
||||
import "google/api/http.proto";
|
||||
import "google/protobuf/descriptor.proto";
|
||||
|
||||
option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations";
|
||||
option java_multiple_files = true;
|
||||
option java_outer_classname = "AnnotationsProto";
|
||||
option java_package = "com.google.api";
|
||||
option objc_class_prefix = "GAPI";
|
||||
|
||||
extend google.protobuf.MethodOptions {
|
||||
// See `HttpRule`.
|
||||
HttpRule http = 72295728;
|
||||
}
|
375
api/proto/vendor/google/api/http.proto
vendored
Normal file
375
api/proto/vendor/google/api/http.proto
vendored
Normal file
@ -0,0 +1,375 @@
|
||||
// Copyright 2015 Google LLC
|
||||
//
|
||||
// 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.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.api;
|
||||
|
||||
option cc_enable_arenas = true;
|
||||
option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations";
|
||||
option java_multiple_files = true;
|
||||
option java_outer_classname = "HttpProto";
|
||||
option java_package = "com.google.api";
|
||||
option objc_class_prefix = "GAPI";
|
||||
|
||||
// Defines the HTTP configuration for an API service. It contains a list of
|
||||
// [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method
|
||||
// to one or more HTTP REST API methods.
|
||||
message Http {
|
||||
// A list of HTTP configuration rules that apply to individual API methods.
|
||||
//
|
||||
// **NOTE:** All service configuration rules follow "last one wins" order.
|
||||
repeated HttpRule rules = 1;
|
||||
|
||||
// When set to true, URL path parameters will be fully URI-decoded except in
|
||||
// cases of single segment matches in reserved expansion, where "%2F" will be
|
||||
// left encoded.
|
||||
//
|
||||
// The default behavior is to not decode RFC 6570 reserved characters in multi
|
||||
// segment matches.
|
||||
bool fully_decode_reserved_expansion = 2;
|
||||
}
|
||||
|
||||
// # gRPC Transcoding
|
||||
//
|
||||
// gRPC Transcoding is a feature for mapping between a gRPC method and one or
|
||||
// more HTTP REST endpoints. It allows developers to build a single API service
|
||||
// that supports both gRPC APIs and REST APIs. Many systems, including [Google
|
||||
// APIs](https://github.com/googleapis/googleapis),
|
||||
// [Cloud Endpoints](https://cloud.google.com/endpoints), [gRPC
|
||||
// Gateway](https://github.com/grpc-ecosystem/grpc-gateway),
|
||||
// and [Envoy](https://github.com/envoyproxy/envoy) proxy support this feature
|
||||
// and use it for large scale production services.
|
||||
//
|
||||
// `HttpRule` defines the schema of the gRPC/REST mapping. The mapping specifies
|
||||
// how different portions of the gRPC request message are mapped to the URL
|
||||
// path, URL query parameters, and HTTP request body. It also controls how the
|
||||
// gRPC response message is mapped to the HTTP response body. `HttpRule` is
|
||||
// typically specified as an `google.api.http` annotation on the gRPC method.
|
||||
//
|
||||
// Each mapping specifies a URL path template and an HTTP method. The path
|
||||
// template may refer to one or more fields in the gRPC request message, as long
|
||||
// as each field is a non-repeated field with a primitive (non-message) type.
|
||||
// The path template controls how fields of the request message are mapped to
|
||||
// the URL path.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// service Messaging {
|
||||
// rpc GetMessage(GetMessageRequest) returns (Message) {
|
||||
// option (google.api.http) = {
|
||||
// get: "/v1/{name=messages/*}"
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
// message GetMessageRequest {
|
||||
// string name = 1; // Mapped to URL path.
|
||||
// }
|
||||
// message Message {
|
||||
// string text = 1; // The resource content.
|
||||
// }
|
||||
//
|
||||
// This enables an HTTP REST to gRPC mapping as below:
|
||||
//
|
||||
// HTTP | gRPC
|
||||
// -----|-----
|
||||
// `GET /v1/messages/123456` | `GetMessage(name: "messages/123456")`
|
||||
//
|
||||
// Any fields in the request message which are not bound by the path template
|
||||
// automatically become HTTP query parameters if there is no HTTP request body.
|
||||
// For example:
|
||||
//
|
||||
// service Messaging {
|
||||
// rpc GetMessage(GetMessageRequest) returns (Message) {
|
||||
// option (google.api.http) = {
|
||||
// get:"/v1/messages/{message_id}"
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
// message GetMessageRequest {
|
||||
// message SubMessage {
|
||||
// string subfield = 1;
|
||||
// }
|
||||
// string message_id = 1; // Mapped to URL path.
|
||||
// int64 revision = 2; // Mapped to URL query parameter `revision`.
|
||||
// SubMessage sub = 3; // Mapped to URL query parameter `sub.subfield`.
|
||||
// }
|
||||
//
|
||||
// This enables a HTTP JSON to RPC mapping as below:
|
||||
//
|
||||
// HTTP | gRPC
|
||||
// -----|-----
|
||||
// `GET /v1/messages/123456?revision=2&sub.subfield=foo` |
|
||||
// `GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield:
|
||||
// "foo"))`
|
||||
//
|
||||
// Note that fields which are mapped to URL query parameters must have a
|
||||
// primitive type or a repeated primitive type or a non-repeated message type.
|
||||
// In the case of a repeated type, the parameter can be repeated in the URL
|
||||
// as `...?param=A¶m=B`. In the case of a message type, each field of the
|
||||
// message is mapped to a separate parameter, such as
|
||||
// `...?foo.a=A&foo.b=B&foo.c=C`.
|
||||
//
|
||||
// For HTTP methods that allow a request body, the `body` field
|
||||
// specifies the mapping. Consider a REST update method on the
|
||||
// message resource collection:
|
||||
//
|
||||
// service Messaging {
|
||||
// rpc UpdateMessage(UpdateMessageRequest) returns (Message) {
|
||||
// option (google.api.http) = {
|
||||
// patch: "/v1/messages/{message_id}"
|
||||
// body: "message"
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
// message UpdateMessageRequest {
|
||||
// string message_id = 1; // mapped to the URL
|
||||
// Message message = 2; // mapped to the body
|
||||
// }
|
||||
//
|
||||
// The following HTTP JSON to RPC mapping is enabled, where the
|
||||
// representation of the JSON in the request body is determined by
|
||||
// protos JSON encoding:
|
||||
//
|
||||
// HTTP | gRPC
|
||||
// -----|-----
|
||||
// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id:
|
||||
// "123456" message { text: "Hi!" })`
|
||||
//
|
||||
// The special name `*` can be used in the body mapping to define that
|
||||
// every field not bound by the path template should be mapped to the
|
||||
// request body. This enables the following alternative definition of
|
||||
// the update method:
|
||||
//
|
||||
// service Messaging {
|
||||
// rpc UpdateMessage(Message) returns (Message) {
|
||||
// option (google.api.http) = {
|
||||
// patch: "/v1/messages/{message_id}"
|
||||
// body: "*"
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
// message Message {
|
||||
// string message_id = 1;
|
||||
// string text = 2;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// The following HTTP JSON to RPC mapping is enabled:
|
||||
//
|
||||
// HTTP | gRPC
|
||||
// -----|-----
|
||||
// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id:
|
||||
// "123456" text: "Hi!")`
|
||||
//
|
||||
// Note that when using `*` in the body mapping, it is not possible to
|
||||
// have HTTP parameters, as all fields not bound by the path end in
|
||||
// the body. This makes this option more rarely used in practice when
|
||||
// defining REST APIs. The common usage of `*` is in custom methods
|
||||
// which don't use the URL at all for transferring data.
|
||||
//
|
||||
// It is possible to define multiple HTTP methods for one RPC by using
|
||||
// the `additional_bindings` option. Example:
|
||||
//
|
||||
// service Messaging {
|
||||
// rpc GetMessage(GetMessageRequest) returns (Message) {
|
||||
// option (google.api.http) = {
|
||||
// get: "/v1/messages/{message_id}"
|
||||
// additional_bindings {
|
||||
// get: "/v1/users/{user_id}/messages/{message_id}"
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
// message GetMessageRequest {
|
||||
// string message_id = 1;
|
||||
// string user_id = 2;
|
||||
// }
|
||||
//
|
||||
// This enables the following two alternative HTTP JSON to RPC mappings:
|
||||
//
|
||||
// HTTP | gRPC
|
||||
// -----|-----
|
||||
// `GET /v1/messages/123456` | `GetMessage(message_id: "123456")`
|
||||
// `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id:
|
||||
// "123456")`
|
||||
//
|
||||
// ## Rules for HTTP mapping
|
||||
//
|
||||
// 1. Leaf request fields (recursive expansion nested messages in the request
|
||||
// message) are classified into three categories:
|
||||
// - Fields referred by the path template. They are passed via the URL path.
|
||||
// - Fields referred by the [HttpRule.body][google.api.HttpRule.body]. They are passed via the HTTP
|
||||
// request body.
|
||||
// - All other fields are passed via the URL query parameters, and the
|
||||
// parameter name is the field path in the request message. A repeated
|
||||
// field can be represented as multiple query parameters under the same
|
||||
// name.
|
||||
// 2. If [HttpRule.body][google.api.HttpRule.body] is "*", there is no URL query parameter, all fields
|
||||
// are passed via URL path and HTTP request body.
|
||||
// 3. If [HttpRule.body][google.api.HttpRule.body] is omitted, there is no HTTP request body, all
|
||||
// fields are passed via URL path and URL query parameters.
|
||||
//
|
||||
// ### Path template syntax
|
||||
//
|
||||
// Template = "/" Segments [ Verb ] ;
|
||||
// Segments = Segment { "/" Segment } ;
|
||||
// Segment = "*" | "**" | LITERAL | Variable ;
|
||||
// Variable = "{" FieldPath [ "=" Segments ] "}" ;
|
||||
// FieldPath = IDENT { "." IDENT } ;
|
||||
// Verb = ":" LITERAL ;
|
||||
//
|
||||
// The syntax `*` matches a single URL path segment. The syntax `**` matches
|
||||
// zero or more URL path segments, which must be the last part of the URL path
|
||||
// except the `Verb`.
|
||||
//
|
||||
// The syntax `Variable` matches part of the URL path as specified by its
|
||||
// template. A variable template must not contain other variables. If a variable
|
||||
// matches a single path segment, its template may be omitted, e.g. `{var}`
|
||||
// is equivalent to `{var=*}`.
|
||||
//
|
||||
// The syntax `LITERAL` matches literal text in the URL path. If the `LITERAL`
|
||||
// contains any reserved character, such characters should be percent-encoded
|
||||
// before the matching.
|
||||
//
|
||||
// If a variable contains exactly one path segment, such as `"{var}"` or
|
||||
// `"{var=*}"`, when such a variable is expanded into a URL path on the client
|
||||
// side, all characters except `[-_.~0-9a-zA-Z]` are percent-encoded. The
|
||||
// server side does the reverse decoding. Such variables show up in the
|
||||
// [Discovery
|
||||
// Document](https://developers.google.com/discovery/v1/reference/apis) as
|
||||
// `{var}`.
|
||||
//
|
||||
// If a variable contains multiple path segments, such as `"{var=foo/*}"`
|
||||
// or `"{var=**}"`, when such a variable is expanded into a URL path on the
|
||||
// client side, all characters except `[-_.~/0-9a-zA-Z]` are percent-encoded.
|
||||
// The server side does the reverse decoding, except "%2F" and "%2f" are left
|
||||
// unchanged. Such variables show up in the
|
||||
// [Discovery
|
||||
// Document](https://developers.google.com/discovery/v1/reference/apis) as
|
||||
// `{+var}`.
|
||||
//
|
||||
// ## Using gRPC API Service Configuration
|
||||
//
|
||||
// gRPC API Service Configuration (service config) is a configuration language
|
||||
// for configuring a gRPC service to become a user-facing product. The
|
||||
// service config is simply the YAML representation of the `google.api.Service`
|
||||
// proto message.
|
||||
//
|
||||
// As an alternative to annotating your proto file, you can configure gRPC
|
||||
// transcoding in your service config YAML files. You do this by specifying a
|
||||
// `HttpRule` that maps the gRPC method to a REST endpoint, achieving the same
|
||||
// effect as the proto annotation. This can be particularly useful if you
|
||||
// have a proto that is reused in multiple services. Note that any transcoding
|
||||
// specified in the service config will override any matching transcoding
|
||||
// configuration in the proto.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// http:
|
||||
// rules:
|
||||
// # Selects a gRPC method and applies HttpRule to it.
|
||||
// - selector: example.v1.Messaging.GetMessage
|
||||
// get: /v1/messages/{message_id}/{sub.subfield}
|
||||
//
|
||||
// ## Special notes
|
||||
//
|
||||
// When gRPC Transcoding is used to map a gRPC to JSON REST endpoints, the
|
||||
// proto to JSON conversion must follow the [proto3
|
||||
// specification](https://developers.google.com/protocol-buffers/docs/proto3#json).
|
||||
//
|
||||
// While the single segment variable follows the semantics of
|
||||
// [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2 Simple String
|
||||
// Expansion, the multi segment variable **does not** follow RFC 6570 Section
|
||||
// 3.2.3 Reserved Expansion. The reason is that the Reserved Expansion
|
||||
// does not expand special characters like `?` and `#`, which would lead
|
||||
// to invalid URLs. As the result, gRPC Transcoding uses a custom encoding
|
||||
// for multi segment variables.
|
||||
//
|
||||
// The path variables **must not** refer to any repeated or mapped field,
|
||||
// because client libraries are not capable of handling such variable expansion.
|
||||
//
|
||||
// The path variables **must not** capture the leading "/" character. The reason
|
||||
// is that the most common use case "{var}" does not capture the leading "/"
|
||||
// character. For consistency, all path variables must share the same behavior.
|
||||
//
|
||||
// Repeated message fields must not be mapped to URL query parameters, because
|
||||
// no client library can support such complicated mapping.
|
||||
//
|
||||
// If an API needs to use a JSON array for request or response body, it can map
|
||||
// the request or response body to a repeated field. However, some gRPC
|
||||
// Transcoding implementations may not support this feature.
|
||||
message HttpRule {
|
||||
// Selects a method to which this rule applies.
|
||||
//
|
||||
// Refer to [selector][google.api.DocumentationRule.selector] for syntax details.
|
||||
string selector = 1;
|
||||
|
||||
// Determines the URL pattern is matched by this rules. This pattern can be
|
||||
// used with any of the {get|put|post|delete|patch} methods. A custom method
|
||||
// can be defined using the 'custom' field.
|
||||
oneof pattern {
|
||||
// Maps to HTTP GET. Used for listing and getting information about
|
||||
// resources.
|
||||
string get = 2;
|
||||
|
||||
// Maps to HTTP PUT. Used for replacing a resource.
|
||||
string put = 3;
|
||||
|
||||
// Maps to HTTP POST. Used for creating a resource or performing an action.
|
||||
string post = 4;
|
||||
|
||||
// Maps to HTTP DELETE. Used for deleting a resource.
|
||||
string delete = 5;
|
||||
|
||||
// Maps to HTTP PATCH. Used for updating a resource.
|
||||
string patch = 6;
|
||||
|
||||
// The custom pattern is used for specifying an HTTP method that is not
|
||||
// included in the `pattern` field, such as HEAD, or "*" to leave the
|
||||
// HTTP method unspecified for this rule. The wild-card rule is useful
|
||||
// for services that provide content to Web (HTML) clients.
|
||||
CustomHttpPattern custom = 8;
|
||||
}
|
||||
|
||||
// The name of the request field whose value is mapped to the HTTP request
|
||||
// body, or `*` for mapping all request fields not captured by the path
|
||||
// pattern to the HTTP body, or omitted for not having any HTTP request body.
|
||||
//
|
||||
// NOTE: the referred field must be present at the top-level of the request
|
||||
// message type.
|
||||
string body = 7;
|
||||
|
||||
// Optional. The name of the response field whose value is mapped to the HTTP
|
||||
// response body. When omitted, the entire response message will be used
|
||||
// as the HTTP response body.
|
||||
//
|
||||
// NOTE: The referred field must be present at the top-level of the response
|
||||
// message type.
|
||||
string response_body = 12;
|
||||
|
||||
// Additional HTTP bindings for the selector. Nested bindings must
|
||||
// not contain an `additional_bindings` field themselves (that is,
|
||||
// the nesting may only be one level deep).
|
||||
repeated HttpRule additional_bindings = 11;
|
||||
}
|
||||
|
||||
// A custom pattern is used for defining custom HTTP verb.
|
||||
message CustomHttpPattern {
|
||||
// The name of this custom HTTP verb.
|
||||
string kind = 1;
|
||||
|
||||
// The path matched by this custom verb.
|
||||
string path = 2;
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
//nolint:gochecknoglobals,golint,stylecheck,godox
|
||||
package assets
|
||||
|
||||
import _ "embed"
|
||||
|
||||
// TODO: Using embed.FS
|
||||
|
||||
//go:embed templates/schnutibox.yml.tmpl
|
||||
var SchnutiboxConfig string
|
||||
|
||||
//go:embed files/schnutibox.service
|
||||
var SchnutiboxService []byte
|
||||
|
||||
//go:embed templates/fstab.raspbian.tmpl
|
||||
var FstabRaspbianTemplate string
|
||||
|
||||
//go:embed templates/mopidy.conf.tmpl
|
||||
var MopidyConf string
|
||||
|
||||
//go:embed files/upmpdcli.conf
|
||||
var UpmpdcliConf []byte
|
||||
|
||||
//go:embed files/ntp.service
|
||||
var NtpService []byte
|
||||
|
||||
//go:embed templates/50-neuftech.rules.tmpl
|
||||
var UDEVRules string
|
12
assets/prepare/assets.go
Normal file
12
assets/prepare/assets.go
Normal file
@ -0,0 +1,12 @@
|
||||
//nolint:gochecknoglobals
|
||||
package prepare
|
||||
|
||||
import "embed"
|
||||
|
||||
// Files are files to be copied to the system.
|
||||
//go:embed files
|
||||
var Files embed.FS
|
||||
|
||||
// Templates are the used templates for creating file on the system.
|
||||
//go:embed templates
|
||||
var Templates embed.FS
|
12
assets/prepare/templates/fstab.raspbian.tmpl
Normal file
12
assets/prepare/templates/fstab.raspbian.tmpl
Normal file
@ -0,0 +1,12 @@
|
||||
proc /proc proc defaults 0 0
|
||||
/dev/mmcblk0p1 /boot vfat ro,defaults 0 2
|
||||
/dev/mmcblk0p2 / ext4 ro,defaults,noatime 0 1
|
||||
tmpfs /var/log tmpfs nodev,nosuid 0 0
|
||||
tmpfs /var/tmp tmpfs nodev,nosuid 0 0
|
||||
tmpfs /tmp tmpfs nodev,nosuid 0 0
|
||||
tmpfs /var/lib/systemd/timesync tmpfs auto,noatime,size=5m,mode=0755,uid={{.TimesyncUID}},gid={{.TimesyncGID}} 0 0
|
||||
tmpfs /var/cache/mopidy tmpfs auto,noatime,size=5m,mode=0755,uid={{.MopidyUID}},gid={{.MopidyGID}} 0 0
|
||||
tmpfs /var/cache/upmpdcli tmpfs auto,noatime,size=5m,mode=0755,uid={{.UpmpdcliUID}},gid={{.UpmpdcliGID}} 0 0
|
||||
tmpfs /var/lib/ntp tmpfs nosuid,nodev 0 0
|
||||
tmpfs /var/lib/snapserver tmpfs nosuid,nodev 0 0
|
||||
tmpfs /var/lib/snapclient tmpfs nosuid,nodev 0 0
|
@ -3,7 +3,7 @@ cache_dir = /var/cache/mopidy
|
||||
config_dir = /etc/mopidy/
|
||||
|
||||
[audio]
|
||||
output = alsasink
|
||||
output = audioresample ! audioconvert ! audio/x-raw,rate=48000,channels=2,format=S16LE ! filesink location=/tmp/snapfifo
|
||||
mixer = alsamixer
|
||||
mixer_volume = 100
|
||||
|
||||
@ -11,9 +11,9 @@ mixer_volume = 100
|
||||
card = 0
|
||||
control= Headphone
|
||||
|
||||
|
||||
[mpd]
|
||||
hostname = 0.0.0.0
|
||||
max_connections = 200
|
||||
|
||||
[youtube]
|
||||
enabled = true
|
@ -1,10 +0,0 @@
|
||||
proc /proc proc defaults 0 0
|
||||
/dev/mmcblk0p1 /boot vfat ro,defaults 0 2
|
||||
/dev/mmcblk0p2 / ext4 ro,defaults,noatime 0 1
|
||||
tmpfs /var/log tmpfs nodev,nosuid 0 0
|
||||
tmpfs /var/tmp tmpfs nodev,nosuid 0 0
|
||||
tmpfs /tmp tmpfs nodev,nosuid 0 0
|
||||
tmpfs /var/lib/systemd/timesync tmpfs auto,noatime,size=5m,mode=0755,uid={{.TimesyncUID}},gid={{.TimesyncGID}} 0 0
|
||||
tmpfs /var/cache/mopidy tmpfs auto,noatime,size=5m,mode=0755,uid={{.MopidyUID}},gid={{.MopidyGID}} 0 0
|
||||
tmpfs /var/cache/upmpdcli tmpfs auto,noatime,size=5m,mode=0755,uid={{.UpmpdcliUID}},gid={{.UpmpdcliGID}} 0 0
|
||||
tmpfs /var/lib/ntp tmpfs nosuid,nodev 0 0
|
37
assets/web/assets.go
Normal file
37
assets/web/assets.go
Normal file
@ -0,0 +1,37 @@
|
||||
//nolint:gochecknoglobals
|
||||
package web
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
//go:embed files
|
||||
var files embed.FS
|
||||
|
||||
// Files is the sub directed http.FileSystem for files.
|
||||
var Files = sub(files, "files")
|
||||
|
||||
// Templates stores the templates.
|
||||
//go:embed templates
|
||||
var Templates embed.FS
|
||||
|
||||
//go:embed swagger-ui
|
||||
var swaggerUI embed.FS
|
||||
|
||||
// SwaggerUI is the sub directed http.FileSystem for the swagger-ui.
|
||||
var SwaggerUI = sub(swaggerUI, "swagger-ui")
|
||||
|
||||
func sub(f embed.FS, dir string) http.FileSystem {
|
||||
fsys, err := fs.Sub(f, dir)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Str("dir", dir).Msg("could not sub into dir")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return http.FS(fsys)
|
||||
}
|
635
assets/web/files/milligram.css
Normal file
635
assets/web/files/milligram.css
Normal file
@ -0,0 +1,635 @@
|
||||
/*!
|
||||
* Milligram v1.4.1
|
||||
* https://milligram.io
|
||||
*
|
||||
* Copyright (c) 2020 CJ Patoilo
|
||||
* Licensed under the MIT license
|
||||
*/
|
||||
|
||||
*,
|
||||
*:after,
|
||||
*:before {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
font-size: 62.5%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: #606c76;
|
||||
font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;
|
||||
font-size: 1.6em;
|
||||
font-weight: 300;
|
||||
letter-spacing: .01em;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-left: 0.3rem solid #d1d1d1;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
padding: 1rem 1.5rem;
|
||||
}
|
||||
|
||||
blockquote *:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.button,
|
||||
button,
|
||||
input[type='button'],
|
||||
input[type='reset'],
|
||||
input[type='submit'] {
|
||||
background-color: #9b4dca;
|
||||
border: 0.1rem solid #9b4dca;
|
||||
border-radius: .4rem;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700;
|
||||
height: 3.8rem;
|
||||
letter-spacing: .1rem;
|
||||
line-height: 3.8rem;
|
||||
padding: 0 3.0rem;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.button:focus, .button:hover,
|
||||
button:focus,
|
||||
button:hover,
|
||||
input[type='button']:focus,
|
||||
input[type='button']:hover,
|
||||
input[type='reset']:focus,
|
||||
input[type='reset']:hover,
|
||||
input[type='submit']:focus,
|
||||
input[type='submit']:hover {
|
||||
background-color: #606c76;
|
||||
border-color: #606c76;
|
||||
color: #fff;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.button[disabled],
|
||||
button[disabled],
|
||||
input[type='button'][disabled],
|
||||
input[type='reset'][disabled],
|
||||
input[type='submit'][disabled] {
|
||||
cursor: default;
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
.button[disabled]:focus, .button[disabled]:hover,
|
||||
button[disabled]:focus,
|
||||
button[disabled]:hover,
|
||||
input[type='button'][disabled]:focus,
|
||||
input[type='button'][disabled]:hover,
|
||||
input[type='reset'][disabled]:focus,
|
||||
input[type='reset'][disabled]:hover,
|
||||
input[type='submit'][disabled]:focus,
|
||||
input[type='submit'][disabled]:hover {
|
||||
background-color: #9b4dca;
|
||||
border-color: #9b4dca;
|
||||
}
|
||||
|
||||
.button.button-outline,
|
||||
button.button-outline,
|
||||
input[type='button'].button-outline,
|
||||
input[type='reset'].button-outline,
|
||||
input[type='submit'].button-outline {
|
||||
background-color: transparent;
|
||||
color: #9b4dca;
|
||||
}
|
||||
|
||||
.button.button-outline:focus, .button.button-outline:hover,
|
||||
button.button-outline:focus,
|
||||
button.button-outline:hover,
|
||||
input[type='button'].button-outline:focus,
|
||||
input[type='button'].button-outline:hover,
|
||||
input[type='reset'].button-outline:focus,
|
||||
input[type='reset'].button-outline:hover,
|
||||
input[type='submit'].button-outline:focus,
|
||||
input[type='submit'].button-outline:hover {
|
||||
background-color: transparent;
|
||||
border-color: #606c76;
|
||||
color: #606c76;
|
||||
}
|
||||
|
||||
.button.button-outline[disabled]:focus, .button.button-outline[disabled]:hover,
|
||||
button.button-outline[disabled]:focus,
|
||||
button.button-outline[disabled]:hover,
|
||||
input[type='button'].button-outline[disabled]:focus,
|
||||
input[type='button'].button-outline[disabled]:hover,
|
||||
input[type='reset'].button-outline[disabled]:focus,
|
||||
input[type='reset'].button-outline[disabled]:hover,
|
||||
input[type='submit'].button-outline[disabled]:focus,
|
||||
input[type='submit'].button-outline[disabled]:hover {
|
||||
border-color: inherit;
|
||||
color: #9b4dca;
|
||||
}
|
||||
|
||||
.button.button-clear,
|
||||
button.button-clear,
|
||||
input[type='button'].button-clear,
|
||||
input[type='reset'].button-clear,
|
||||
input[type='submit'].button-clear {
|
||||
background-color: transparent;
|
||||
border-color: transparent;
|
||||
color: #9b4dca;
|
||||
}
|
||||
|
||||
.button.button-clear:focus, .button.button-clear:hover,
|
||||
button.button-clear:focus,
|
||||
button.button-clear:hover,
|
||||
input[type='button'].button-clear:focus,
|
||||
input[type='button'].button-clear:hover,
|
||||
input[type='reset'].button-clear:focus,
|
||||
input[type='reset'].button-clear:hover,
|
||||
input[type='submit'].button-clear:focus,
|
||||
input[type='submit'].button-clear:hover {
|
||||
background-color: transparent;
|
||||
border-color: transparent;
|
||||
color: #606c76;
|
||||
}
|
||||
|
||||
.button.button-clear[disabled]:focus, .button.button-clear[disabled]:hover,
|
||||
button.button-clear[disabled]:focus,
|
||||
button.button-clear[disabled]:hover,
|
||||
input[type='button'].button-clear[disabled]:focus,
|
||||
input[type='button'].button-clear[disabled]:hover,
|
||||
input[type='reset'].button-clear[disabled]:focus,
|
||||
input[type='reset'].button-clear[disabled]:hover,
|
||||
input[type='submit'].button-clear[disabled]:focus,
|
||||
input[type='submit'].button-clear[disabled]:hover {
|
||||
color: #9b4dca;
|
||||
}
|
||||
|
||||
code {
|
||||
background: #f4f5f6;
|
||||
border-radius: .4rem;
|
||||
font-size: 86%;
|
||||
margin: 0 .2rem;
|
||||
padding: .2rem .5rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
pre {
|
||||
background: #f4f5f6;
|
||||
border-left: 0.3rem solid #9b4dca;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
pre > code {
|
||||
border-radius: 0;
|
||||
display: block;
|
||||
padding: 1rem 1.5rem;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 0;
|
||||
border-top: 0.1rem solid #f4f5f6;
|
||||
margin: 3.0rem 0;
|
||||
}
|
||||
|
||||
input[type='color'],
|
||||
input[type='date'],
|
||||
input[type='datetime'],
|
||||
input[type='datetime-local'],
|
||||
input[type='email'],
|
||||
input[type='month'],
|
||||
input[type='number'],
|
||||
input[type='password'],
|
||||
input[type='search'],
|
||||
input[type='tel'],
|
||||
input[type='text'],
|
||||
input[type='url'],
|
||||
input[type='week'],
|
||||
input:not([type]),
|
||||
textarea,
|
||||
select {
|
||||
-webkit-appearance: none;
|
||||
background-color: transparent;
|
||||
border: 0.1rem solid #d1d1d1;
|
||||
border-radius: .4rem;
|
||||
box-shadow: none;
|
||||
box-sizing: inherit;
|
||||
height: 3.8rem;
|
||||
padding: .6rem 1.0rem .7rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
input[type='color']:focus,
|
||||
input[type='date']:focus,
|
||||
input[type='datetime']:focus,
|
||||
input[type='datetime-local']:focus,
|
||||
input[type='email']:focus,
|
||||
input[type='month']:focus,
|
||||
input[type='number']:focus,
|
||||
input[type='password']:focus,
|
||||
input[type='search']:focus,
|
||||
input[type='tel']:focus,
|
||||
input[type='text']:focus,
|
||||
input[type='url']:focus,
|
||||
input[type='week']:focus,
|
||||
input:not([type]):focus,
|
||||
textarea:focus,
|
||||
select:focus {
|
||||
border-color: #9b4dca;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
select {
|
||||
background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 8" width="30"><path fill="%23d1d1d1" d="M0,0l6,8l6-8"/></svg>') center right no-repeat;
|
||||
padding-right: 3.0rem;
|
||||
}
|
||||
|
||||
select:focus {
|
||||
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 8" width="30"><path fill="%239b4dca" d="M0,0l6,8l6-8"/></svg>');
|
||||
}
|
||||
|
||||
select[multiple] {
|
||||
background: none;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
textarea {
|
||||
min-height: 6.5rem;
|
||||
}
|
||||
|
||||
label,
|
||||
legend {
|
||||
display: block;
|
||||
font-size: 1.6rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: .5rem;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
border-width: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
input[type='checkbox'],
|
||||
input[type='radio'] {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.label-inline {
|
||||
display: inline-block;
|
||||
font-weight: normal;
|
||||
margin-left: .5rem;
|
||||
}
|
||||
|
||||
.container {
|
||||
margin: 0 auto;
|
||||
max-width: 112.0rem;
|
||||
padding: 0 2.0rem;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.row.row-no-padding {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.row.row-no-padding > .column {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.row.row-wrap {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.row.row-top {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.row.row-bottom {
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.row.row-center {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.row.row-stretch {
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.row.row-baseline {
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.row .column {
|
||||
display: block;
|
||||
flex: 1 1 auto;
|
||||
margin-left: 0;
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.row .column.column-offset-10 {
|
||||
margin-left: 10%;
|
||||
}
|
||||
|
||||
.row .column.column-offset-20 {
|
||||
margin-left: 20%;
|
||||
}
|
||||
|
||||
.row .column.column-offset-25 {
|
||||
margin-left: 25%;
|
||||
}
|
||||
|
||||
.row .column.column-offset-33, .row .column.column-offset-34 {
|
||||
margin-left: 33.3333%;
|
||||
}
|
||||
|
||||
.row .column.column-offset-40 {
|
||||
margin-left: 40%;
|
||||
}
|
||||
|
||||
.row .column.column-offset-50 {
|
||||
margin-left: 50%;
|
||||
}
|
||||
|
||||
.row .column.column-offset-60 {
|
||||
margin-left: 60%;
|
||||
}
|
||||
|
||||
.row .column.column-offset-66, .row .column.column-offset-67 {
|
||||
margin-left: 66.6666%;
|
||||
}
|
||||
|
||||
.row .column.column-offset-75 {
|
||||
margin-left: 75%;
|
||||
}
|
||||
|
||||
.row .column.column-offset-80 {
|
||||
margin-left: 80%;
|
||||
}
|
||||
|
||||
.row .column.column-offset-90 {
|
||||
margin-left: 90%;
|
||||
}
|
||||
|
||||
.row .column.column-10 {
|
||||
flex: 0 0 10%;
|
||||
max-width: 10%;
|
||||
}
|
||||
|
||||
.row .column.column-20 {
|
||||
flex: 0 0 20%;
|
||||
max-width: 20%;
|
||||
}
|
||||
|
||||
.row .column.column-25 {
|
||||
flex: 0 0 25%;
|
||||
max-width: 25%;
|
||||
}
|
||||
|
||||
.row .column.column-33, .row .column.column-34 {
|
||||
flex: 0 0 33.3333%;
|
||||
max-width: 33.3333%;
|
||||
}
|
||||
|
||||
.row .column.column-40 {
|
||||
flex: 0 0 40%;
|
||||
max-width: 40%;
|
||||
}
|
||||
|
||||
.row .column.column-50 {
|
||||
flex: 0 0 50%;
|
||||
max-width: 50%;
|
||||
}
|
||||
|
||||
.row .column.column-60 {
|
||||
flex: 0 0 60%;
|
||||
max-width: 60%;
|
||||
}
|
||||
|
||||
.row .column.column-66, .row .column.column-67 {
|
||||
flex: 0 0 66.6666%;
|
||||
max-width: 66.6666%;
|
||||
}
|
||||
|
||||
.row .column.column-75 {
|
||||
flex: 0 0 75%;
|
||||
max-width: 75%;
|
||||
}
|
||||
|
||||
.row .column.column-80 {
|
||||
flex: 0 0 80%;
|
||||
max-width: 80%;
|
||||
}
|
||||
|
||||
.row .column.column-90 {
|
||||
flex: 0 0 90%;
|
||||
max-width: 90%;
|
||||
}
|
||||
|
||||
.row .column .column-top {
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.row .column .column-bottom {
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
.row .column .column-center {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
@media (min-width: 40rem) {
|
||||
.row {
|
||||
flex-direction: row;
|
||||
margin-left: -1.0rem;
|
||||
width: calc(100% + 2.0rem);
|
||||
}
|
||||
.row .column {
|
||||
margin-bottom: inherit;
|
||||
padding: 0 1.0rem;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: #9b4dca;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:focus, a:hover {
|
||||
color: #606c76;
|
||||
}
|
||||
|
||||
dl,
|
||||
ol,
|
||||
ul {
|
||||
list-style: none;
|
||||
margin-top: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
dl dl,
|
||||
dl ol,
|
||||
dl ul,
|
||||
ol dl,
|
||||
ol ol,
|
||||
ol ul,
|
||||
ul dl,
|
||||
ul ol,
|
||||
ul ul {
|
||||
font-size: 90%;
|
||||
margin: 1.5rem 0 1.5rem 3.0rem;
|
||||
}
|
||||
|
||||
ol {
|
||||
list-style: decimal inside;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: circle inside;
|
||||
}
|
||||
|
||||
.button,
|
||||
button,
|
||||
dd,
|
||||
dt,
|
||||
li {
|
||||
margin-bottom: 1.0rem;
|
||||
}
|
||||
|
||||
fieldset,
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
blockquote,
|
||||
dl,
|
||||
figure,
|
||||
form,
|
||||
ol,
|
||||
p,
|
||||
pre,
|
||||
table,
|
||||
ul {
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
table {
|
||||
border-spacing: 0;
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
text-align: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
border-bottom: 0.1rem solid #e1e1e1;
|
||||
padding: 1.2rem 1.5rem;
|
||||
}
|
||||
|
||||
td:first-child,
|
||||
th:first-child {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
td:last-child,
|
||||
th:last-child {
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 40rem) {
|
||||
table {
|
||||
display: table;
|
||||
overflow-x: initial;
|
||||
}
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-weight: 300;
|
||||
letter-spacing: -.1rem;
|
||||
margin-bottom: 2.0rem;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 4.6rem;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 3.6rem;
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 2.8rem;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 2.2rem;
|
||||
letter-spacing: -.08rem;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1.8rem;
|
||||
letter-spacing: -.05rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1.6rem;
|
||||
letter-spacing: 0;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.clearfix:after {
|
||||
clear: both;
|
||||
content: ' ';
|
||||
display: table;
|
||||
}
|
||||
|
||||
.float-left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.float-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=milligram.css.map */
|
349
assets/web/files/normalize.css
vendored
Normal file
349
assets/web/files/normalize.css
vendored
Normal file
@ -0,0 +1,349 @@
|
||||
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
|
||||
|
||||
/* Document
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Correct the line height in all browsers.
|
||||
* 2. Prevent adjustments of font size after orientation changes in iOS.
|
||||
*/
|
||||
|
||||
html {
|
||||
line-height: 1.15; /* 1 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
|
||||
/* Sections
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the margin in all browsers.
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the `main` element consistently in IE.
|
||||
*/
|
||||
|
||||
main {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the font size and margin on `h1` elements within `section` and
|
||||
* `article` contexts in Chrome, Firefox, and Safari.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/* Grouping content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in Firefox.
|
||||
* 2. Show the overflow in Edge and IE.
|
||||
*/
|
||||
|
||||
hr {
|
||||
box-sizing: content-box; /* 1 */
|
||||
height: 0; /* 1 */
|
||||
overflow: visible; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/* Text-level semantics
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the gray background on active links in IE 10.
|
||||
*/
|
||||
|
||||
a {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Remove the bottom border in Chrome 57-
|
||||
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: none; /* 1 */
|
||||
text-decoration: underline; /* 2 */
|
||||
text-decoration: underline dotted; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font weight in Chrome, Edge, and Safari.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` elements from affecting the line height in
|
||||
* all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
/* Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the border on images inside links in IE 10.
|
||||
*/
|
||||
|
||||
img {
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
/* Forms
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Change the font styles in all browsers.
|
||||
* 2. Remove the margin in Firefox and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
font-family: inherit; /* 1 */
|
||||
font-size: 100%; /* 1 */
|
||||
line-height: 1.15; /* 1 */
|
||||
margin: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the overflow in IE.
|
||||
* 1. Show the overflow in Edge.
|
||||
*/
|
||||
|
||||
button,
|
||||
input { /* 1 */
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inheritance of text transform in Edge, Firefox, and IE.
|
||||
* 1. Remove the inheritance of text transform in Firefox.
|
||||
*/
|
||||
|
||||
button,
|
||||
select { /* 1 */
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the inability to style clickable types in iOS and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
[type="button"],
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner border and padding in Firefox.
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner,
|
||||
[type="button"]::-moz-focus-inner,
|
||||
[type="reset"]::-moz-focus-inner,
|
||||
[type="submit"]::-moz-focus-inner {
|
||||
border-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the focus styles unset by the previous rule.
|
||||
*/
|
||||
|
||||
button:-moz-focusring,
|
||||
[type="button"]:-moz-focusring,
|
||||
[type="reset"]:-moz-focusring,
|
||||
[type="submit"]:-moz-focusring {
|
||||
outline: 1px dotted ButtonText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the padding in Firefox.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
padding: 0.35em 0.75em 0.625em;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the text wrapping in Edge and IE.
|
||||
* 2. Correct the color inheritance from `fieldset` elements in IE.
|
||||
* 3. Remove the padding so developers are not caught out when they zero out
|
||||
* `fieldset` elements in all browsers.
|
||||
*/
|
||||
|
||||
legend {
|
||||
box-sizing: border-box; /* 1 */
|
||||
color: inherit; /* 2 */
|
||||
display: table; /* 1 */
|
||||
max-width: 100%; /* 1 */
|
||||
padding: 0; /* 3 */
|
||||
white-space: normal; /* 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||
*/
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the default vertical scrollbar in IE 10+.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in IE 10.
|
||||
* 2. Remove the padding in IE 10.
|
||||
*/
|
||||
|
||||
[type="checkbox"],
|
||||
[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the cursor style of increment and decrement buttons in Chrome.
|
||||
*/
|
||||
|
||||
[type="number"]::-webkit-inner-spin-button,
|
||||
[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the odd appearance in Chrome and Safari.
|
||||
* 2. Correct the outline style in Safari.
|
||||
*/
|
||||
|
||||
[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
outline-offset: -2px; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner padding in Chrome and Safari on macOS.
|
||||
*/
|
||||
|
||||
[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inability to style clickable types in iOS and Safari.
|
||||
* 2. Change font properties to `inherit` in Safari.
|
||||
*/
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
-webkit-appearance: button; /* 1 */
|
||||
font: inherit; /* 2 */
|
||||
}
|
||||
|
||||
/* Interactive
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Add the correct display in Edge, IE 10+, and Firefox.
|
||||
*/
|
||||
|
||||
details {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the correct display in all browsers.
|
||||
*/
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
/* Misc
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10+.
|
||||
*/
|
||||
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10.
|
||||
*/
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
39
assets/web/files/schnutibox.js
Normal file
39
assets/web/files/schnutibox.js
Normal file
@ -0,0 +1,39 @@
|
||||
if(typeof(EventSource) !== "undefined") {
|
||||
var logSource = new EventSource("/log");
|
||||
logSource.onmessage = function(event) {
|
||||
var j = JSON.parse(event.data);
|
||||
/* eslint-disable no-prototype-builtins */
|
||||
if (j.hasOwnProperty("message")) {
|
||||
document.getElementById("log").innerHTML += j.message + "<br>";
|
||||
}
|
||||
};
|
||||
} else {
|
||||
document.getElementById("log").innerHTML = "Sorry, your browser does not support server-sent events...";
|
||||
}
|
||||
|
||||
if(typeof(EventSource) !== "undefined") {
|
||||
var currentsongSource = new EventSource("/currentsong");
|
||||
currentsongSource.onmessage = function(event){
|
||||
document.getElementById("currentsong").innerHTML = event.data
|
||||
};
|
||||
} else {
|
||||
document.getElementById("currentsong").innerHTML = "Sorry, your browser does not support server-sent events...";
|
||||
};
|
||||
|
||||
function handleSubmit(event, url) {
|
||||
event.preventDefault()
|
||||
|
||||
var data = new FormData(event.target)
|
||||
var value = Object.fromEntries(data.entries())
|
||||
var jsonValue = JSON.stringify(value)
|
||||
|
||||
console.log(jsonValue)
|
||||
|
||||
var xhr = new XMLHttpRequest()
|
||||
xhr.open("POST", url)
|
||||
xhr.setRequestHeader("Content-Type", "application/json")
|
||||
xhr.send(jsonValue)
|
||||
}
|
||||
|
||||
var timerForm = document.querySelector('#timerForm')
|
||||
timerForm.addEventListener('submit', function(){handleSubmit(event, "/api/v1/timer")})
|
BIN
assets/web/swagger-ui/favicon-16x16.png
Normal file
BIN
assets/web/swagger-ui/favicon-16x16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 665 B |
BIN
assets/web/swagger-ui/favicon-32x32.png
Normal file
BIN
assets/web/swagger-ui/favicon-32x32.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 628 B |
46
assets/web/swagger-ui/google/api/annotations.swagger.json
Normal file
46
assets/web/swagger-ui/google/api/annotations.swagger.json
Normal file
@ -0,0 +1,46 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"title": "google/api/annotations.proto",
|
||||
"version": "version not set"
|
||||
},
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"paths": {},
|
||||
"definitions": {
|
||||
"protobufAny": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"typeUrl": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"format": "byte"
|
||||
}
|
||||
}
|
||||
},
|
||||
"rpcStatus": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"details": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
46
assets/web/swagger-ui/google/api/http.swagger.json
Normal file
46
assets/web/swagger-ui/google/api/http.swagger.json
Normal file
@ -0,0 +1,46 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"title": "google/api/http.proto",
|
||||
"version": "version not set"
|
||||
},
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"paths": {},
|
||||
"definitions": {
|
||||
"protobufAny": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"typeUrl": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"format": "byte"
|
||||
}
|
||||
}
|
||||
},
|
||||
"rpcStatus": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"details": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
62
assets/web/swagger-ui/index.html
Normal file
62
assets/web/swagger-ui/index.html
Normal file
@ -0,0 +1,62 @@
|
||||
<!-- HTML for static distribution bundle build -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Swagger UI</title>
|
||||
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" />
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
href="./favicon-32x32.png"
|
||||
sizes="32x32"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
href="./favicon-16x16.png"
|
||||
sizes="16x16"
|
||||
/>
|
||||
<style>
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
overflow: -moz-scrollbars-vertical;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
background: #fafafa;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="swagger-ui"></div>
|
||||
|
||||
<script src="./swagger-ui-bundle.js" charset="UTF-8"></script>
|
||||
<script src="./swagger-ui-standalone-preset.js" charset="UTF-8"></script>
|
||||
<script>
|
||||
window.onload = function () {
|
||||
// Begin Swagger UI call region
|
||||
const ui = SwaggerUIBundle({
|
||||
url: "./schnutibox.swagger.json",
|
||||
dom_id: "#swagger-ui",
|
||||
deepLinking: true,
|
||||
presets: [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset],
|
||||
plugins: [SwaggerUIBundle.plugins.DownloadUrl],
|
||||
layout: "StandaloneLayout",
|
||||
});
|
||||
// End Swagger UI call region
|
||||
|
||||
window.ui = ui;
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
75
assets/web/swagger-ui/oauth2-redirect.html
Normal file
75
assets/web/swagger-ui/oauth2-redirect.html
Normal file
@ -0,0 +1,75 @@
|
||||
<!doctype html>
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<title>Swagger UI: OAuth2 Redirect</title>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
'use strict';
|
||||
function run () {
|
||||
var oauth2 = window.opener.swaggerUIRedirectOauth2;
|
||||
var sentState = oauth2.state;
|
||||
var redirectUrl = oauth2.redirectUrl;
|
||||
var isValid, qp, arr;
|
||||
|
||||
if (/code|token|error/.test(window.location.hash)) {
|
||||
qp = window.location.hash.substring(1);
|
||||
} else {
|
||||
qp = location.search.substring(1);
|
||||
}
|
||||
|
||||
arr = qp.split("&");
|
||||
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';});
|
||||
qp = qp ? JSON.parse('{' + arr.join() + '}',
|
||||
function (key, value) {
|
||||
return key === "" ? value : decodeURIComponent(value);
|
||||
}
|
||||
) : {};
|
||||
|
||||
isValid = qp.state === sentState;
|
||||
|
||||
if ((
|
||||
oauth2.auth.schema.get("flow") === "accessCode" ||
|
||||
oauth2.auth.schema.get("flow") === "authorizationCode" ||
|
||||
oauth2.auth.schema.get("flow") === "authorization_code"
|
||||
) && !oauth2.auth.code) {
|
||||
if (!isValid) {
|
||||
oauth2.errCb({
|
||||
authId: oauth2.auth.name,
|
||||
source: "auth",
|
||||
level: "warning",
|
||||
message: "Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server"
|
||||
});
|
||||
}
|
||||
|
||||
if (qp.code) {
|
||||
delete oauth2.state;
|
||||
oauth2.auth.code = qp.code;
|
||||
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
|
||||
} else {
|
||||
let oauthErrorMsg;
|
||||
if (qp.error) {
|
||||
oauthErrorMsg = "["+qp.error+"]: " +
|
||||
(qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
|
||||
(qp.error_uri ? "More info: "+qp.error_uri : "");
|
||||
}
|
||||
|
||||
oauth2.errCb({
|
||||
authId: oauth2.auth.name,
|
||||
source: "auth",
|
||||
level: "error",
|
||||
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server"
|
||||
});
|
||||
}
|
||||
} else {
|
||||
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
|
||||
}
|
||||
window.close();
|
||||
}
|
||||
|
||||
window.addEventListener('DOMContentLoaded', function () {
|
||||
run();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
172
assets/web/swagger-ui/schnutibox.swagger.json
Normal file
172
assets/web/swagger-ui/schnutibox.swagger.json
Normal file
@ -0,0 +1,172 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"title": "schnutibox.proto",
|
||||
"version": "version not set"
|
||||
},
|
||||
"tags": [
|
||||
{
|
||||
"name": "IdentifierService"
|
||||
},
|
||||
{
|
||||
"name": "TimerService"
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"paths": {
|
||||
"/api/v1/identify": {
|
||||
"post": {
|
||||
"operationId": "IdentifierService_Identify",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1IdentifyResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1IdentifyRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"IdentifierService"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/timer": {
|
||||
"get": {
|
||||
"operationId": "TimerService_Get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1Timer"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"TimerService"
|
||||
]
|
||||
},
|
||||
"post": {
|
||||
"operationId": "TimerService_Create",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1Timer"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1Timer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"TimerService"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"protobufAny": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"typeUrl": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"format": "byte"
|
||||
}
|
||||
}
|
||||
},
|
||||
"rpcStatus": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"details": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1IdentifyRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1IdentifyResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"uris": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1Timer": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"duration": {
|
||||
"type": "string"
|
||||
},
|
||||
"current": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
3
assets/web/swagger-ui/swagger-ui-bundle.js
Normal file
3
assets/web/swagger-ui/swagger-ui-bundle.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/web/swagger-ui/swagger-ui-bundle.js.map
Normal file
1
assets/web/swagger-ui/swagger-ui-bundle.js.map
Normal file
File diff suppressed because one or more lines are too long
3
assets/web/swagger-ui/swagger-ui-es-bundle-core.js
Normal file
3
assets/web/swagger-ui/swagger-ui-es-bundle-core.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/web/swagger-ui/swagger-ui-es-bundle-core.js.map
Normal file
1
assets/web/swagger-ui/swagger-ui-es-bundle-core.js.map
Normal file
File diff suppressed because one or more lines are too long
3
assets/web/swagger-ui/swagger-ui-es-bundle.js
Normal file
3
assets/web/swagger-ui/swagger-ui-es-bundle.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/web/swagger-ui/swagger-ui-es-bundle.js.map
Normal file
1
assets/web/swagger-ui/swagger-ui-es-bundle.js.map
Normal file
File diff suppressed because one or more lines are too long
3
assets/web/swagger-ui/swagger-ui-standalone-preset.js
Normal file
3
assets/web/swagger-ui/swagger-ui-standalone-preset.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
4
assets/web/swagger-ui/swagger-ui.css
Normal file
4
assets/web/swagger-ui/swagger-ui.css
Normal file
File diff suppressed because one or more lines are too long
1
assets/web/swagger-ui/swagger-ui.css.map
Normal file
1
assets/web/swagger-ui/swagger-ui.css.map
Normal file
File diff suppressed because one or more lines are too long
3
assets/web/swagger-ui/swagger-ui.js
Normal file
3
assets/web/swagger-ui/swagger-ui.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/web/swagger-ui/swagger-ui.js.map
Normal file
1
assets/web/swagger-ui/swagger-ui.js.map
Normal file
File diff suppressed because one or more lines are too long
33
assets/web/templates/index.html.tmpl
Normal file
33
assets/web/templates/index.html.tmpl
Normal file
@ -0,0 +1,33 @@
|
||||
<!doctype html>
|
||||
<html lang=en>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<title>schnutibox</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300italic,700,700italic">
|
||||
<link rel="stylesheet" href="/static/normalize.css">
|
||||
<link rel="stylesheet" href="/static/milligram.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>schnutibox</h1>
|
||||
|
||||
<h2>Currently playing</h2>
|
||||
<div id="currentsong"></div>
|
||||
|
||||
<h2>Timer</h2>
|
||||
Takes only seconds. Example: 600s
|
||||
<form id="timerForm">
|
||||
<input type="text" name="duration" placeholder="600s">
|
||||
<input type="submit" value="Set">
|
||||
</form>
|
||||
|
||||
<h2>logs</h2>
|
||||
<pre>
|
||||
<code>
|
||||
<div id="log"></div>
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
<script src=/static/schnutibox.js></script>
|
||||
</body>
|
||||
</html>
|
17
buf.gen.yaml
Normal file
17
buf.gen.yaml
Normal file
@ -0,0 +1,17 @@
|
||||
---
|
||||
version: v1beta1
|
||||
plugins:
|
||||
- name: go
|
||||
out: pkg/api/v1
|
||||
opt: paths=source_relative
|
||||
|
||||
- name: go-grpc
|
||||
out: pkg/api/v1
|
||||
opt: paths=source_relative,require_unimplemented_servers=false
|
||||
|
||||
- name: grpc-gateway
|
||||
out: pkg/api/v1
|
||||
opt: paths=source_relative
|
||||
|
||||
- name: openapiv2
|
||||
out: assets/web/swagger-ui
|
14
buf.yaml
Normal file
14
buf.yaml
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
version: v1beta1
|
||||
name: buf.build/xsteadfastx/schnutibox
|
||||
build:
|
||||
roots:
|
||||
- api/proto/v1/
|
||||
- api/proto/vendor/
|
||||
lint:
|
||||
except:
|
||||
- PACKAGE_DIRECTORY_MATCH
|
||||
- RPC_REQUEST_STANDARD_NAME
|
||||
- RPC_RESPONSE_STANDARD_NAME
|
||||
- RPC_REQUEST_RESPONSE_UNIQUE
|
||||
- PACKAGE_VERSION_SUFFIX
|
4
build/package/docker/Dockerfile
Normal file
4
build/package/docker/Dockerfile
Normal file
@ -0,0 +1,4 @@
|
||||
FROM scratch
|
||||
COPY schnutibox /
|
||||
ENTRYPOINT ["/schnutibox"]
|
||||
CMD ["web"]
|
127
cmd/root.go
127
cmd/root.go
@ -1,15 +1,17 @@
|
||||
//nolint:exhaustivestruct,gochecknoglobals,gochecknoinits
|
||||
//nolint:exhaustivestruct,gochecknoglobals,gochecknoinits,gomnd
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/spf13/viper"
|
||||
"go.xsfx.dev/schnutibox/internal/config"
|
||||
"go.xsfx.dev/schnutibox/pkg/prepare"
|
||||
@ -27,7 +29,12 @@ var rootCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
// init initializes the command line interface.
|
||||
//
|
||||
// nolint:funlen
|
||||
func init() {
|
||||
// Root.
|
||||
rootCmd.PersistentFlags().Bool("pprof", false, "Enables pprof for debugging")
|
||||
|
||||
// Run.
|
||||
rootCmd.AddCommand(runCmd)
|
||||
runCmd.Flags().StringVarP(&cfgFile, "config", "c", "", "config file")
|
||||
@ -36,6 +43,8 @@ func init() {
|
||||
log.Fatal().Err(err).Msg("missing flag")
|
||||
}
|
||||
|
||||
runCmd.Flags().Bool("ignore-reader", false, "Ignoring that the reader is missing")
|
||||
|
||||
// Prepare.
|
||||
rootCmd.AddCommand(prepareCmd)
|
||||
prepareCmd.Flags().BoolVar(&prepare.Cfg.ReadOnly, "read-only", false, "Setup read-only system")
|
||||
@ -49,18 +58,34 @@ func init() {
|
||||
|
||||
// Version.
|
||||
rootCmd.AddCommand(versionCmd)
|
||||
}
|
||||
|
||||
// initConfig loads the config file.
|
||||
func initConfig() {
|
||||
logger := log.With().Str("config", cfgFile).Logger()
|
||||
// Web.
|
||||
rootCmd.AddCommand(webCmd)
|
||||
webCmd.Flags().StringVarP(&cfgFile, "config", "c", "", "config file")
|
||||
|
||||
if err := webCmd.MarkFlagRequired("config"); err != nil {
|
||||
log.Fatal().Err(err).Msg("missing flag")
|
||||
}
|
||||
|
||||
// Timer.
|
||||
rootCmd.AddCommand(timerCmd)
|
||||
timerCmd.Flags().String("hostname", "localhost", "Hostname of schnutibox")
|
||||
timerCmd.Flags().Int("port", 6600, "Port of schnutibox")
|
||||
timerCmd.Flags().DurationP("duration", "d", time.Minute, "Duration until the timer stops the playback")
|
||||
|
||||
if err := timerCmd.MarkFlagRequired("duration"); err != nil {
|
||||
log.Fatal().Err(err).Msg("missing flag")
|
||||
}
|
||||
|
||||
// Defaults.
|
||||
viper.SetDefault("box.hostname", "localhost")
|
||||
viper.SetDefault("box.port", 9999)
|
||||
viper.SetDefault("web.hostname", "localhost")
|
||||
viper.SetDefault("web.port", 9999)
|
||||
viper.SetDefault("mpd.hostname", "localhost")
|
||||
viper.SetDefault("mpd.port", 6600)
|
||||
viper.SetDefault("reader.dev", "/dev/hidraw0")
|
||||
viper.SetDefault("reader.ignore", false)
|
||||
viper.SetDefault("debug.pprof", false)
|
||||
viper.SetDefault("timer.duration", time.Minute)
|
||||
|
||||
// Environment handling.
|
||||
viper.SetEnvPrefix("SCHNUTIBOX")
|
||||
@ -68,36 +93,82 @@ func initConfig() {
|
||||
viper.AutomaticEnv()
|
||||
|
||||
// Flags.
|
||||
if err := viper.BindPFlag("reader.dev", prepareCmd.Flags().Lookup("rfid-reader")); err != nil {
|
||||
logger.Fatal().Err(err).Msg("could not bind flag")
|
||||
for k, v := range map[string]*pflag.Flag{
|
||||
"debug.pprof": rootCmd.PersistentFlags().Lookup("pprof"),
|
||||
"reader.dev": prepareCmd.Flags().Lookup("rfid-reader"),
|
||||
"reader.ignore": runCmd.Flags().Lookup("ignore-reader"),
|
||||
"web.hostname": timerCmd.Flags().Lookup("hostname"),
|
||||
"web.port": timerCmd.Flags().Lookup("port"),
|
||||
"timer.duration": timerCmd.Flags().Lookup("duration"),
|
||||
} {
|
||||
if err := viper.BindPFlag(k, v); err != nil {
|
||||
log.Fatal().Err(err).Msg("could not bind flag")
|
||||
}
|
||||
}
|
||||
|
||||
// Parse config file.
|
||||
if cfgFile != "" {
|
||||
viper.SetConfigFile(cfgFile)
|
||||
parseConfig(logger)
|
||||
} else {
|
||||
logger.Fatal().Msg("missing config file")
|
||||
}
|
||||
|
||||
viper.WatchConfig()
|
||||
viper.OnConfigChange(func(e fsnotify.Event) {
|
||||
logger.Info().Msg("config file changed")
|
||||
parseConfig(logger)
|
||||
})
|
||||
}
|
||||
|
||||
func parseConfig(logger zerolog.Logger) {
|
||||
// initConfig loads the config file.
|
||||
// fatal defines if config parsing should end in a fatal error or not.
|
||||
func initConfig(fatal bool) {
|
||||
logger := log.With().Str("config", cfgFile).Logger()
|
||||
|
||||
// Parse config file.
|
||||
if cfgFile == "" && fatal {
|
||||
logger.Fatal().Msg("missing config file")
|
||||
} else if cfgFile == "" {
|
||||
logger.Warn().Msg("missing config file")
|
||||
}
|
||||
|
||||
// Dont mind if there is no config file... viper also should populate
|
||||
// flags and environment variables.
|
||||
viper.SetConfigFile(cfgFile)
|
||||
parseConfig(logger, fatal)
|
||||
|
||||
// Configfile changes watch only enabled if there is a config file.
|
||||
if cfgFile != "" {
|
||||
viper.WatchConfig()
|
||||
viper.OnConfigChange(func(e fsnotify.Event) {
|
||||
logger.Info().Msg("config file changed")
|
||||
parseConfig(logger, false)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// parseConfig parses the config and does some tests if required fields are there.
|
||||
// Its also possible to decide if parsing should end up in a fatal or just an error.
|
||||
func parseConfig(logger zerolog.Logger, fatal bool) {
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
logger.Fatal().Err(err).Msg("error loading config file")
|
||||
if fatal {
|
||||
logger.Fatal().Err(err).Msg("error loading config file")
|
||||
}
|
||||
|
||||
logger.Error().Err(err).Msg("error loading config file")
|
||||
}
|
||||
|
||||
if err := viper.Unmarshal(&config.Cfg); err != nil {
|
||||
logger.Fatal().Err(err).Msg("could not unmarshal config")
|
||||
if fatal {
|
||||
logger.Fatal().Err(err).Msg("could not unmarshal config")
|
||||
}
|
||||
|
||||
logger.Error().Err(err).Msg("could not unmarshal config")
|
||||
}
|
||||
|
||||
if err := config.Cfg.Require(); err != nil {
|
||||
logger.Fatal().Err(err).Msg("missing config parts")
|
||||
// Disabling require check if no config is set.
|
||||
// Not sure about this!
|
||||
if cfgFile != "" {
|
||||
if err := config.Cfg.Require(); err != nil {
|
||||
if fatal {
|
||||
logger.Fatal().Err(err).Msg("missing config parts")
|
||||
}
|
||||
|
||||
logger.Error().Err(err).Msg("missing config parts")
|
||||
|
||||
return
|
||||
}
|
||||
} else {
|
||||
logger.Warn().Msg("doesnt do a config requirement check")
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,6 @@ var runCmd = &cobra.Command{
|
||||
Short: "Running this thing",
|
||||
Run: run.Run,
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
initConfig()
|
||||
initConfig(true)
|
||||
},
|
||||
}
|
||||
|
21
cmd/timer.go
Normal file
21
cmd/timer.go
Normal file
@ -0,0 +1,21 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/cobra"
|
||||
"go.xsfx.dev/schnutibox/pkg/timer"
|
||||
)
|
||||
|
||||
// nolint:gochecknoglobals
|
||||
var timerCmd = &cobra.Command{
|
||||
Use: "timer",
|
||||
Short: "Handling timer",
|
||||
Run: timer.Run,
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
||||
initConfig(false)
|
||||
},
|
||||
}
|
16
cmd/web.go
Normal file
16
cmd/web.go
Normal file
@ -0,0 +1,16 @@
|
||||
// nolint:gochecknoglobals
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"go.xsfx.dev/schnutibox/pkg/web"
|
||||
)
|
||||
|
||||
var webCmd = &cobra.Command{
|
||||
Use: "web",
|
||||
Short: "Starting webservice",
|
||||
Run: web.Run,
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
initConfig(false)
|
||||
},
|
||||
}
|
17
config.example.yaml
Normal file
17
config.example.yaml
Normal file
@ -0,0 +1,17 @@
|
||||
---
|
||||
Reader:
|
||||
Dev: /dev/hidraw4
|
||||
|
||||
Meta:
|
||||
Stop: "0000350934"
|
||||
|
||||
Tracks:
|
||||
"0000224543":
|
||||
name: scarlett begonias
|
||||
uris:
|
||||
- "https://ia902608.us.archive.org/3/items/gd1977-05-08.shure57.stevenson.29303.flac16/gd1977-05-08d02t04.ogg"
|
||||
|
||||
"0000195026":
|
||||
name: they love eachother
|
||||
uris:
|
||||
- "https://ia802608.us.archive.org/3/items/gd1977-05-08.shure57.stevenson.29303.flac16/gd1977-05-08d01t05.ogg"
|
22
go.mod
22
go.mod
@ -4,22 +4,32 @@ go 1.16
|
||||
|
||||
require (
|
||||
github.com/Microsoft/go-winio v0.4.16 // indirect
|
||||
github.com/bufbuild/buf v0.37.0
|
||||
github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e // indirect
|
||||
github.com/cosmtrek/air v1.27.3
|
||||
github.com/fhs/gompd/v2 v2.2.0
|
||||
github.com/fsnotify/fsnotify v1.4.7
|
||||
github.com/google/go-cmp v0.5.5 // indirect
|
||||
github.com/fsnotify/fsnotify v1.4.9
|
||||
github.com/golang/protobuf v1.5.2
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.4.0
|
||||
github.com/helloyi/go-sshclient v1.0.0
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
github.com/manifoldco/promptui v0.8.0
|
||||
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 // indirect
|
||||
github.com/ory/dockertest/v3 v3.6.3
|
||||
github.com/philip-bui/grpc-zerolog v1.0.1
|
||||
github.com/prometheus/client_golang v0.9.3
|
||||
github.com/rs/zerolog v1.21.0
|
||||
github.com/rs/zerolog v1.22.0
|
||||
github.com/spf13/cobra v1.1.3
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/spf13/viper v1.7.0
|
||||
github.com/stretchr/testify v1.4.0
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/tmc/scp v0.0.0-20170824174625-f7b48647feef
|
||||
go.xsfx.dev/don v1.0.0
|
||||
go.xsfx.dev/logginghandler v0.0.4
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
|
||||
golang.org/x/sys v0.0.0-20210216224549-f992740a1bac // indirect
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4
|
||||
google.golang.org/genproto v0.0.0-20210426193834-eac7f76ac494
|
||||
google.golang.org/grpc v1.37.0
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0
|
||||
google.golang.org/protobuf v1.26.0
|
||||
gotest.tools/v3 v3.0.3 // indirect
|
||||
)
|
||||
|
350
go.sum
350
go.sum
@ -6,11 +6,32 @@ cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6A
|
||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
||||
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
@ -25,24 +46,29 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
|
||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||
github.com/bufbuild/buf v0.37.0 h1:11zJVA0D4uJVGOC9h+oOVHrKKoBgMYIqJJ0d1Xt6oeQ=
|
||||
github.com/bufbuild/buf v0.37.0/go.mod h1:lQ1m2HkIaGOFba6w/aC3KYBHhKEOESP3gaAEpS3dAFM=
|
||||
github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c=
|
||||
github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e h1:6JKvHHt396/qabvMhnhUZvWaHZzfVfldxE60TK8YLhg=
|
||||
github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ=
|
||||
@ -51,6 +77,8 @@ github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cosmtrek/air v1.27.3 h1:laO93SnYnEiJsH0QIeXyso6FJ5maSNufE5d/MmHKBmk=
|
||||
github.com/cosmtrek/air v1.27.3/go.mod h1:vrGZm+zmL5htsEr6YjqLXyjSoelgDQIl/DuOtsWVLeU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
|
||||
@ -65,47 +93,103 @@ github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5Xh
|
||||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
|
||||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/fhs/gompd/v2 v2.2.0 h1:zdSYAAOzQ5cCCgYa5CoXkL0Vr0Cqb/b5JmTobirLc90=
|
||||
github.com/fhs/gompd/v2 v2.2.0/go.mod h1:nNdZtcpD5VpmzZbRl5rV6RhxeMmAWTxEsSIMBkmMIy4=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gofrs/flock v0.8.0 h1:MSdYClljsF3PbENUUEx85nkWfJSGfzYI9yEBZOJz6CY=
|
||||
github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
|
||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0 h1:bM6ZAFZmc/wPFaRDi0d5L7hGEZEx/2u+Tmr2evNHDiI=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.4.0 h1:R+ZwHcCaBVMLvCQzo/lhJCYkjkL7G506oi2N8SIob/g=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.4.0/go.mod h1:IOyTYjcIO0rkmnGBfJTL0NJ11exy/Tc2QEuv7hCXp24=
|
||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
@ -129,20 +213,28 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/helloyi/go-sshclient v1.0.0 h1:pwDDc54wwyMlkwYbhszsX2UB1ajJM296WqLDtNDvcn8=
|
||||
github.com/helloyi/go-sshclient v1.0.0/go.mod h1:NrhRWsYJDjoQXTDWZ4YtVk84wZ4LK3NSM9jD2TZDAm8=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
|
||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jhump/protoreflect v1.8.1 h1:z7Ciiz3Bz37zSd485fbiTW8ABafIasyOWZI0N9EUUdo=
|
||||
github.com/jhump/protoreflect v1.8.1/go.mod h1:7GcYQDdMU/O/BBrl/cX6PNHpXh6cenjd8pneu5yW7Tg=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU=
|
||||
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.11.7 h1:0hzRabrMN4tSTvMfnL3SCv1ZGeAP23ynzodBgaHeMeg=
|
||||
github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
|
||||
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
@ -153,17 +245,14 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lib/pq v0.0.0-20180327071824-d34b9ff171c2 h1:hRGSmZu7j271trc9sneMrpOW7GN5ngLm8YUZIPzf394=
|
||||
github.com/lib/pq v0.0.0-20180327071824-d34b9ff171c2/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBFRlAiJQROKQs8oC9vOxvm4rZmBBk0ONw=
|
||||
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/manifoldco/promptui v0.8.0 h1:R95mMF+McvXZQ7j1g8ucVZE1gLP3Sv6j9vlF9kyRqQo=
|
||||
github.com/manifoldco/promptui v0.8.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ=
|
||||
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
@ -182,6 +271,7 @@ github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXy
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nishanths/predeclared v0.0.0-20200524104333-86fad755b4d3/go.mod h1:nt3d53pc1VYcphSCIaYAJtnPYnr3Zyn8fMq2wvPGPso=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
@ -193,12 +283,17 @@ github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rm
|
||||
github.com/ory/dockertest/v3 v3.6.3 h1:L8JWiGgR+fnj90AEOkTFIEp4j5uWAK72P3IUsYgn2cs=
|
||||
github.com/ory/dockertest/v3 v3.6.3/go.mod h1:EFLcVUOl8qCwp9NyDAcCDtq/QviLtYswW/VbWzUnTNE=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM=
|
||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||
github.com/philip-bui/grpc-zerolog v1.0.1 h1:EMacvLRUd2O1K0eWod27ZP5CY1iTNkhBDLSN+Q4JEvA=
|
||||
github.com/philip-bui/grpc-zerolog v1.0.1/go.mod h1:qXbiq/2X4ZUMMshsqlWyTHOcw7ns+GZmlqZZN05ZHcQ=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v1.5.0 h1:042Buzk+NhDI+DeSAA62RwJL8VAuZUMQZUjCsRz1Mug=
|
||||
github.com/pkg/profile v1.5.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
@ -206,8 +301,9 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP
|
||||
github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM=
|
||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
@ -216,10 +312,12 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzr
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/zerolog v1.21.0 h1:Q3vdXlfLNT+OftyBHsU0Y445MD+8m8axjKgf2si0QcM=
|
||||
github.com/rs/zerolog v1.21.0/go.mod h1:ZPhntP/xmq1nnND05hhpAh2QMhSsA4UN3MGZ6O2J3hM=
|
||||
github.com/rs/zerolog v1.20.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo=
|
||||
github.com/rs/zerolog v1.22.0 h1:XrVUjV4K+izZpKXZHlPrYQiDtmdGiCylnT4i43AAWxg=
|
||||
github.com/rs/zerolog v1.22.0/go.mod h1:ZPhntP/xmq1nnND05hhpAh2QMhSsA4UN3MGZ6O2J3hM=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
@ -240,6 +338,7 @@ github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B
|
||||
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v1.0.1-0.20201006035406-b97b5ead31f7/go.mod h1:yk5b0mALVusDL5fMM6Rd1wgnoO5jUPhwsQ6LQAJTidQ=
|
||||
github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M=
|
||||
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
|
||||
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
|
||||
@ -251,24 +350,51 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
|
||||
github.com/spf13/viper v1.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM=
|
||||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tmc/scp v0.0.0-20170824174625-f7b48647feef h1:7D6Nm4D6f0ci9yttWaKjM1TMAXrH5Su72dojqYGntFY=
|
||||
github.com/tmc/scp v0.0.0-20170824174625-f7b48647feef/go.mod h1:WLFStEdnJXpjK8kd4qKLwQKX/1vrDzp5BcDyiZJBHJM=
|
||||
github.com/twitchtv/twirp v7.1.0+incompatible h1:3fNSDoSPyq+fTrifIvGue9XM/tptzuhiGY83rxPVNUg=
|
||||
github.com/twitchtv/twirp v7.1.0+incompatible/go.mod h1:RRJoFSAmTEh2weEqWtpPE3vFK5YBhA6bqp2l1kfCC5A=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.6 h1:BdkrbWrzDlV9dnbzoP7sfN+dHheJ4J9JOaYxcUDL+ok=
|
||||
go.opencensus.io v0.22.6/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.16.0 h1:uFRZXykJGK9lLY4HtgSw44DnIcAM+kRBP7x5m+NpAOM=
|
||||
go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
|
||||
go.xsfx.dev/don v1.0.0 h1:gYyK1w23PFlqKCxhERlq3p59ugHsXcJeAWKQ/wI23+U=
|
||||
go.xsfx.dev/don v1.0.0/go.mod h1:eLqKA6S/io/qhqY1U8j/ErrXofu7qPZ8+4udedC9wU0=
|
||||
go.xsfx.dev/logginghandler v0.0.4 h1:WLV5DX3qHBFJAwI2Rwm12IEIjaxhiUZUxWlDb0uYg8U=
|
||||
go.xsfx.dev/logginghandler v0.0.4/go.mod h1:eBdnUeB7noknVfwTYrSiVl3hYYy0/5jfDSH4mwExGdc=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
@ -283,6 +409,11 @@ golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@ -292,10 +423,19 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
|
||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 h1:2M3HP5CCK1Si9FQhwnzYhXdG6DXeebvUHFpre8QvbyI=
|
||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -312,17 +452,42 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191003171128-d98b1b443823/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4 h1:b0LrWgu8+q7z4J+0Y3Umo5q1dL7NXBkKBWkaVkAq17E=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@ -330,7 +495,6 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -339,23 +503,49 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210216224549-f992740a1bac h1:9glrpwtNjBYgRpb67AZJKHfzj1stG/8BL5H7In2oTC4=
|
||||
golang.org/x/sys v0.0.0-20210216224549-f992740a1bac/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4 h1:EZ2mChiOa8udjfp6rRmswTbtZN/QzUQp4ptM4rnjHvc=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@ -366,29 +556,74 @@ golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190828213141-aed303cbaa74/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200717024301-6ddee64345a6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
@ -398,9 +633,64 @@ google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210207032614-bba0dbe2a9ea/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210426193834-eac7f76ac494 h1:KMgpo2lWy1vfrYjtxPAzR0aNWeAR1UdQykt6sj/hpBY=
|
||||
google.golang.org/genproto v0.0.0-20210426193834-eac7f76ac494/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.35.0-dev.0.20201218190559-666aea1fb34c/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.37.0 h1:uSZWeQJX5j11bIQ4AJoj+McDBo29cY1MCoC1wO3ts+c=
|
||||
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.0.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 h1:M1YKkFIboKNieVO5DLUEVzQfGwJD30Nv2jfUgzb5UcE=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.25.1-0.20200805231151-a709e31e5d12/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.25.1-0.20201208041424-160c7477e0e8/go.mod h1:hFxJC2f0epmp1elRCiEGJTKAWbwxZ2nvqZdHl3FQXCY=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
@ -414,13 +704,23 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||
gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
|
||||
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
|
@ -12,18 +12,20 @@ import (
|
||||
|
||||
sshclient "github.com/helloyi/go-sshclient"
|
||||
"github.com/ory/dockertest/v3"
|
||||
dc "github.com/ory/dockertest/v3/docker"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/tmc/scp"
|
||||
"go.xsfx.dev/don"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
const (
|
||||
sdcard = "/home/marv/tmp/2021-03-04-raspios-buster-armhf-lite.img"
|
||||
sdcard = "/SWAP/2021-05-07-raspios-buster-armhf-lite.img"
|
||||
sshUser = "pi"
|
||||
sshPass = "raspberry"
|
||||
sshHost = "localhost"
|
||||
containerTimeout = 5 * time.Minute
|
||||
sshHost = "docker"
|
||||
containerTimeout = 15 * time.Minute
|
||||
)
|
||||
|
||||
// Variables used for accessing stuff in the test functions.
|
||||
@ -91,32 +93,18 @@ func copySchnutibox(user, pass, host string) error {
|
||||
}
|
||||
|
||||
// teardown removes some temp test stuff.
|
||||
func teardown(img string, pool *dockertest.Pool, resource *dockertest.Resource) {
|
||||
func teardown(pool *dockertest.Pool, resource *dockertest.Resource) {
|
||||
log.Info().Msg("getting rid of container")
|
||||
|
||||
if err := pool.Purge(resource); err != nil {
|
||||
log.Fatal().Err(err).Msg("could not cleanup")
|
||||
}
|
||||
|
||||
log.Info().Str("img", img).Msg("deleting temp image")
|
||||
|
||||
if err := os.Remove(img); err != nil {
|
||||
log.Fatal().Err(err).Msg("could not delete temp image")
|
||||
}
|
||||
}
|
||||
|
||||
// nolint:funlen
|
||||
func TestMain(m *testing.M) {
|
||||
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
||||
|
||||
// Create tmp image.
|
||||
img, err := raspbianWorkCopy()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("could not create temp work image")
|
||||
}
|
||||
|
||||
log.Info().Str("img", img).Msg("created temp image file")
|
||||
|
||||
pool, err := dockertest.NewPool("")
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("could not connect to docker")
|
||||
@ -132,8 +120,11 @@ func TestMain(m *testing.M) {
|
||||
&dockertest.RunOptions{
|
||||
Repository: "lukechilds/dockerpi",
|
||||
Tag: "vm",
|
||||
Mounts: []string{img + ":/sdcard/filesystem.img"},
|
||||
Mounts: []string{sdcard + ":/sdcard/filesystem.img"},
|
||||
ExposedPorts: []string{"5022/tcp"},
|
||||
PortBindings: map[dc.Port][]dc.PortBinding{
|
||||
"5022/tcp": {{HostIP: "0.0.0.0", HostPort: "5022"}},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("could not start resource")
|
||||
@ -144,37 +135,26 @@ func TestMain(m *testing.M) {
|
||||
|
||||
sshConn = sshHost + ":" + resource.GetPort("5022/tcp")
|
||||
|
||||
// Channels for checking readyness of the container.
|
||||
sshReady := make(chan struct{})
|
||||
sshError := make(chan error)
|
||||
|
||||
// Constant check for readyness of container.
|
||||
go func() {
|
||||
for {
|
||||
// Readiness.
|
||||
if err := don.Check(
|
||||
func() bool {
|
||||
client, err := sshclient.DialWithPasswd(sshConn, sshUser, sshPass)
|
||||
if err == nil {
|
||||
if err := client.Close(); err != nil {
|
||||
sshError <- err
|
||||
return false
|
||||
}
|
||||
sshReady <- struct{}{}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
log.Debug().Msg("container not ready yet")
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case err := <-sshError:
|
||||
log.Error().Err(err).Msg("could not connect to container via ssh")
|
||||
teardown(img, pool, resource)
|
||||
return false
|
||||
},
|
||||
20*time.Minute,
|
||||
15*time.Second,
|
||||
); err != nil {
|
||||
log.Error().Err(err).Msg("timeout. could not connect to container via ssh")
|
||||
teardown(pool, resource)
|
||||
os.Exit(1)
|
||||
case <-time.After(containerTimeout):
|
||||
log.Error().Msg("timeout. could not connect to container via ssh")
|
||||
teardown(img, pool, resource)
|
||||
os.Exit(1)
|
||||
case <-sshReady:
|
||||
log.Info().Msg("container is ready")
|
||||
}
|
||||
|
||||
// Connect via SSH.
|
||||
@ -183,7 +163,7 @@ func TestMain(m *testing.M) {
|
||||
client, err = sshclient.DialWithPasswd(sshConn, sshUser, sshPass)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("could not connect via ssh")
|
||||
teardown(img, pool, resource)
|
||||
teardown(pool, resource)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@ -196,7 +176,7 @@ func TestMain(m *testing.M) {
|
||||
|
||||
if err := copySchnutibox(sshUser, sshPass, sshConn); err != nil {
|
||||
log.Error().Err(err).Msg("could not copy schnutibox")
|
||||
teardown(img, pool, resource)
|
||||
teardown(pool, resource)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@ -208,7 +188,7 @@ func TestMain(m *testing.M) {
|
||||
SetStdio(os.Stdout, os.Stderr).
|
||||
Run(); err != nil {
|
||||
log.Error().Err(err).Msg("could not create /usr/local/bin on container")
|
||||
teardown(img, pool, resource)
|
||||
teardown(pool, resource)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@ -219,7 +199,7 @@ func TestMain(m *testing.M) {
|
||||
code := m.Run()
|
||||
|
||||
// Removing container.
|
||||
teardown(img, pool, resource)
|
||||
teardown(pool, resource)
|
||||
|
||||
os.Exit(code)
|
||||
}
|
||||
|
@ -1,21 +1,30 @@
|
||||
//nolint:gochecknoglobals,goerr113
|
||||
package config
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
api "go.xsfx.dev/schnutibox/pkg/api/v1"
|
||||
)
|
||||
|
||||
// Cfg stores a global config object.
|
||||
var Cfg Config
|
||||
|
||||
type Config struct {
|
||||
Debug struct {
|
||||
PPROF bool `mapstructure:"PPROF"`
|
||||
}
|
||||
|
||||
// Reader is used to configure the RFID Reader.
|
||||
Reader struct {
|
||||
Dev string `mapstructure:"Dev"`
|
||||
} `mapstructure:"Reader"`
|
||||
|
||||
// Box is used to configure a webinterface.
|
||||
Box struct {
|
||||
// Web is used to configure the webinterface.
|
||||
Web struct {
|
||||
Hostname string `mapstructure:"Hostname"`
|
||||
Port int `mapstructure:"Port"`
|
||||
} `mapstructure:"Box"`
|
||||
} `mapstructure:"Web"`
|
||||
|
||||
// MPD contains the connection details for the Music Player Daemon.
|
||||
MPD struct {
|
||||
@ -29,10 +38,7 @@ type Config struct {
|
||||
} `mapstructure:"Meta"`
|
||||
|
||||
// Tracks contains all RFID's and its MPD URLs.
|
||||
Tracks map[string]struct {
|
||||
Name string `mapstructure:"Name"`
|
||||
URIS []string `mapstructure:"URIS"`
|
||||
} `mapstructure:"Tracks"`
|
||||
Tracks map[string]api.IdentifyResponse `mapstructure:"Tracks"`
|
||||
}
|
||||
|
||||
func (c *Config) Require() error {
|
||||
|
18
internal/grpcclient/grpcclient.go
Normal file
18
internal/grpcclient/grpcclient.go
Normal file
@ -0,0 +1,18 @@
|
||||
package grpcclient
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
func Conn(hostname string, port int) (*grpc.ClientConn, error) {
|
||||
var conn *grpc.ClientConn
|
||||
|
||||
conn, err := grpc.Dial(fmt.Sprintf("%s:%d", hostname, port), grpc.WithInsecure())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not connect: %w", err)
|
||||
}
|
||||
|
||||
return conn, nil
|
||||
}
|
@ -4,18 +4,75 @@ package metrics
|
||||
import (
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
api "go.xsfx.dev/schnutibox/pkg/api/v1"
|
||||
)
|
||||
|
||||
var (
|
||||
TracksPlayed = promauto.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "schnutibox_played_tracks_total",
|
||||
},
|
||||
[]string{"rfid", "name"})
|
||||
// Plays is a map of tracked plays.
|
||||
// Its a map, so its easier to check if the metric is already initialized
|
||||
// and usable. The Key string is the RFID identification.
|
||||
var Plays = make(map[string]*api.IdentifyResponse)
|
||||
|
||||
BoxErrors = promauto.NewCounter(
|
||||
prometheus.CounterOpts{
|
||||
Name: "schnutbox_errors_total",
|
||||
},
|
||||
)
|
||||
// NewPlay initialize a new play metric.
|
||||
func NewPlay(rfid, name string, uris []string) {
|
||||
if _, ok := Plays[rfid]; !ok {
|
||||
Plays[rfid] = &api.IdentifyResponse{
|
||||
Name: name,
|
||||
Uris: uris,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Play is the play metric.
|
||||
var Play = promauto.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "schnutibox_plays",
|
||||
Help: "play metrics",
|
||||
},
|
||||
[]string{"rfid", "name"},
|
||||
)
|
||||
|
||||
// Seconds tracks the seconds a play was played.
|
||||
var Seconds = promauto.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "schnutibox_play_seconds_total",
|
||||
Help: "play seconds metrics",
|
||||
},
|
||||
[]string{"rfid", "name"},
|
||||
)
|
||||
|
||||
// BoxErrors counts schnutibox errors.
|
||||
var BoxErrors = promauto.NewCounter(
|
||||
prometheus.CounterOpts{
|
||||
Name: "schnutibox_errors_total",
|
||||
Help: "counter of errors",
|
||||
},
|
||||
)
|
||||
|
||||
// tracksEqual checks if uris slices are equal.
|
||||
// This is needed to search for the right play item.
|
||||
func tracksEqual(a, b []string) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i, v := range a {
|
||||
if v != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Set sets `1` on play gauge if item is playing, a `0` on every other play.
|
||||
// It also raises the counter for played seconds of a play.
|
||||
func Set(uris []string, state string) {
|
||||
for r, p := range Plays {
|
||||
if tracksEqual(uris, p.Uris) && state == "play" {
|
||||
Play.WithLabelValues(r, p.Name).Set(1)
|
||||
Seconds.WithLabelValues(r, p.Name).Inc()
|
||||
} else {
|
||||
Play.WithLabelValues(r, p.Name).Set(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
7
main.go
7
main.go
@ -1,5 +1,3 @@
|
||||
// thanks to: https://medium.com/coinmonks/iot-tutorial-read-tags-from-a-usb-rfid-reader-with-raspberry-pi-and-node-red-from-scratch-4554836be127
|
||||
//nolint:lll,godox
|
||||
package main
|
||||
|
||||
import (
|
||||
@ -9,11 +7,12 @@ import (
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
"go.xsfx.dev/schnutibox/cmd"
|
||||
"go.xsfx.dev/schnutibox/pkg/sselog"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// TODO: Using io.MultiWriter here to implement a SSE Logger at some point.
|
||||
log.Logger = zerolog.New(io.MultiWriter(os.Stderr)).With().Caller().Logger()
|
||||
sselog.Log = sselog.NewSSELog()
|
||||
log.Logger = zerolog.New(io.MultiWriter(zerolog.ConsoleWriter{Out: os.Stderr}, sselog.Log)).With().Caller().Logger()
|
||||
|
||||
cmd.Execute()
|
||||
}
|
||||
|
118
pkg/api/v1/google/api/annotations.pb.go
Normal file
118
pkg/api/v1/google/api/annotations.pb.go
Normal file
@ -0,0 +1,118 @@
|
||||
// Copyright 2015 Google LLC
|
||||
//
|
||||
// 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.
|
||||
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.13.0
|
||||
// source: google/api/annotations.proto
|
||||
|
||||
package annotations
|
||||
|
||||
import (
|
||||
descriptor "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
var file_google_api_annotations_proto_extTypes = []protoimpl.ExtensionInfo{
|
||||
{
|
||||
ExtendedType: (*descriptor.MethodOptions)(nil),
|
||||
ExtensionType: (*HttpRule)(nil),
|
||||
Field: 72295728,
|
||||
Name: "google.api.http",
|
||||
Tag: "bytes,72295728,opt,name=http",
|
||||
Filename: "google/api/annotations.proto",
|
||||
},
|
||||
}
|
||||
|
||||
// Extension fields to descriptor.MethodOptions.
|
||||
var (
|
||||
// See `HttpRule`.
|
||||
//
|
||||
// optional google.api.HttpRule http = 72295728;
|
||||
E_Http = &file_google_api_annotations_proto_extTypes[0]
|
||||
)
|
||||
|
||||
var File_google_api_annotations_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_google_api_annotations_proto_rawDesc = []byte{
|
||||
0x0a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e,
|
||||
0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a,
|
||||
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x1a, 0x15, 0x67, 0x6f, 0x6f, 0x67,
|
||||
0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
|
||||
0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x3a, 0x4b, 0x0a, 0x04, 0x68, 0x74, 0x74, 0x70, 0x12, 0x1e, 0x2e, 0x67, 0x6f,
|
||||
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65,
|
||||
0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xb0, 0xca, 0xbc, 0x22,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70,
|
||||
0x69, 0x2e, 0x48, 0x74, 0x74, 0x70, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x04, 0x68, 0x74, 0x74, 0x70,
|
||||
0x42, 0x6e, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61,
|
||||
0x70, 0x69, 0x42, 0x10, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x50,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x41, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67,
|
||||
0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x61, 0x70,
|
||||
0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3b, 0x61, 0x6e,
|
||||
0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0xa2, 0x02, 0x04, 0x47, 0x41, 0x50, 0x49,
|
||||
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var file_google_api_annotations_proto_goTypes = []interface{}{
|
||||
(*descriptor.MethodOptions)(nil), // 0: google.protobuf.MethodOptions
|
||||
(*HttpRule)(nil), // 1: google.api.HttpRule
|
||||
}
|
||||
var file_google_api_annotations_proto_depIdxs = []int32{
|
||||
0, // 0: google.api.http:extendee -> google.protobuf.MethodOptions
|
||||
1, // 1: google.api.http:type_name -> google.api.HttpRule
|
||||
2, // [2:2] is the sub-list for method output_type
|
||||
2, // [2:2] is the sub-list for method input_type
|
||||
1, // [1:2] is the sub-list for extension type_name
|
||||
0, // [0:1] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_google_api_annotations_proto_init() }
|
||||
func file_google_api_annotations_proto_init() {
|
||||
if File_google_api_annotations_proto != nil {
|
||||
return
|
||||
}
|
||||
file_google_api_http_proto_init()
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_google_api_annotations_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 0,
|
||||
NumExtensions: 1,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_google_api_annotations_proto_goTypes,
|
||||
DependencyIndexes: file_google_api_annotations_proto_depIdxs,
|
||||
ExtensionInfos: file_google_api_annotations_proto_extTypes,
|
||||
}.Build()
|
||||
File_google_api_annotations_proto = out.File
|
||||
file_google_api_annotations_proto_rawDesc = nil
|
||||
file_google_api_annotations_proto_goTypes = nil
|
||||
file_google_api_annotations_proto_depIdxs = nil
|
||||
}
|
777
pkg/api/v1/google/api/http.pb.go
Normal file
777
pkg/api/v1/google/api/http.pb.go
Normal file
@ -0,0 +1,777 @@
|
||||
// Copyright 2015 Google LLC
|
||||
//
|
||||
// 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.
|
||||
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.13.0
|
||||
// source: google/api/http.proto
|
||||
|
||||
package annotations
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// Defines the HTTP configuration for an API service. It contains a list of
|
||||
// [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method
|
||||
// to one or more HTTP REST API methods.
|
||||
type Http struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// A list of HTTP configuration rules that apply to individual API methods.
|
||||
//
|
||||
// **NOTE:** All service configuration rules follow "last one wins" order.
|
||||
Rules []*HttpRule `protobuf:"bytes,1,rep,name=rules,proto3" json:"rules,omitempty"`
|
||||
// When set to true, URL path parameters will be fully URI-decoded except in
|
||||
// cases of single segment matches in reserved expansion, where "%2F" will be
|
||||
// left encoded.
|
||||
//
|
||||
// The default behavior is to not decode RFC 6570 reserved characters in multi
|
||||
// segment matches.
|
||||
FullyDecodeReservedExpansion bool `protobuf:"varint,2,opt,name=fully_decode_reserved_expansion,json=fullyDecodeReservedExpansion,proto3" json:"fully_decode_reserved_expansion,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Http) Reset() {
|
||||
*x = Http{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_google_api_http_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Http) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Http) ProtoMessage() {}
|
||||
|
||||
func (x *Http) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_google_api_http_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Http.ProtoReflect.Descriptor instead.
|
||||
func (*Http) Descriptor() ([]byte, []int) {
|
||||
return file_google_api_http_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *Http) GetRules() []*HttpRule {
|
||||
if x != nil {
|
||||
return x.Rules
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Http) GetFullyDecodeReservedExpansion() bool {
|
||||
if x != nil {
|
||||
return x.FullyDecodeReservedExpansion
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// # gRPC Transcoding
|
||||
//
|
||||
// gRPC Transcoding is a feature for mapping between a gRPC method and one or
|
||||
// more HTTP REST endpoints. It allows developers to build a single API service
|
||||
// that supports both gRPC APIs and REST APIs. Many systems, including [Google
|
||||
// APIs](https://github.com/googleapis/googleapis),
|
||||
// [Cloud Endpoints](https://cloud.google.com/endpoints), [gRPC
|
||||
// Gateway](https://github.com/grpc-ecosystem/grpc-gateway),
|
||||
// and [Envoy](https://github.com/envoyproxy/envoy) proxy support this feature
|
||||
// and use it for large scale production services.
|
||||
//
|
||||
// `HttpRule` defines the schema of the gRPC/REST mapping. The mapping specifies
|
||||
// how different portions of the gRPC request message are mapped to the URL
|
||||
// path, URL query parameters, and HTTP request body. It also controls how the
|
||||
// gRPC response message is mapped to the HTTP response body. `HttpRule` is
|
||||
// typically specified as an `google.api.http` annotation on the gRPC method.
|
||||
//
|
||||
// Each mapping specifies a URL path template and an HTTP method. The path
|
||||
// template may refer to one or more fields in the gRPC request message, as long
|
||||
// as each field is a non-repeated field with a primitive (non-message) type.
|
||||
// The path template controls how fields of the request message are mapped to
|
||||
// the URL path.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// service Messaging {
|
||||
// rpc GetMessage(GetMessageRequest) returns (Message) {
|
||||
// option (google.api.http) = {
|
||||
// get: "/v1/{name=messages/*}"
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
// message GetMessageRequest {
|
||||
// string name = 1; // Mapped to URL path.
|
||||
// }
|
||||
// message Message {
|
||||
// string text = 1; // The resource content.
|
||||
// }
|
||||
//
|
||||
// This enables an HTTP REST to gRPC mapping as below:
|
||||
//
|
||||
// HTTP | gRPC
|
||||
// -----|-----
|
||||
// `GET /v1/messages/123456` | `GetMessage(name: "messages/123456")`
|
||||
//
|
||||
// Any fields in the request message which are not bound by the path template
|
||||
// automatically become HTTP query parameters if there is no HTTP request body.
|
||||
// For example:
|
||||
//
|
||||
// service Messaging {
|
||||
// rpc GetMessage(GetMessageRequest) returns (Message) {
|
||||
// option (google.api.http) = {
|
||||
// get:"/v1/messages/{message_id}"
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
// message GetMessageRequest {
|
||||
// message SubMessage {
|
||||
// string subfield = 1;
|
||||
// }
|
||||
// string message_id = 1; // Mapped to URL path.
|
||||
// int64 revision = 2; // Mapped to URL query parameter `revision`.
|
||||
// SubMessage sub = 3; // Mapped to URL query parameter `sub.subfield`.
|
||||
// }
|
||||
//
|
||||
// This enables a HTTP JSON to RPC mapping as below:
|
||||
//
|
||||
// HTTP | gRPC
|
||||
// -----|-----
|
||||
// `GET /v1/messages/123456?revision=2&sub.subfield=foo` |
|
||||
// `GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield:
|
||||
// "foo"))`
|
||||
//
|
||||
// Note that fields which are mapped to URL query parameters must have a
|
||||
// primitive type or a repeated primitive type or a non-repeated message type.
|
||||
// In the case of a repeated type, the parameter can be repeated in the URL
|
||||
// as `...?param=A¶m=B`. In the case of a message type, each field of the
|
||||
// message is mapped to a separate parameter, such as
|
||||
// `...?foo.a=A&foo.b=B&foo.c=C`.
|
||||
//
|
||||
// For HTTP methods that allow a request body, the `body` field
|
||||
// specifies the mapping. Consider a REST update method on the
|
||||
// message resource collection:
|
||||
//
|
||||
// service Messaging {
|
||||
// rpc UpdateMessage(UpdateMessageRequest) returns (Message) {
|
||||
// option (google.api.http) = {
|
||||
// patch: "/v1/messages/{message_id}"
|
||||
// body: "message"
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
// message UpdateMessageRequest {
|
||||
// string message_id = 1; // mapped to the URL
|
||||
// Message message = 2; // mapped to the body
|
||||
// }
|
||||
//
|
||||
// The following HTTP JSON to RPC mapping is enabled, where the
|
||||
// representation of the JSON in the request body is determined by
|
||||
// protos JSON encoding:
|
||||
//
|
||||
// HTTP | gRPC
|
||||
// -----|-----
|
||||
// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id:
|
||||
// "123456" message { text: "Hi!" })`
|
||||
//
|
||||
// The special name `*` can be used in the body mapping to define that
|
||||
// every field not bound by the path template should be mapped to the
|
||||
// request body. This enables the following alternative definition of
|
||||
// the update method:
|
||||
//
|
||||
// service Messaging {
|
||||
// rpc UpdateMessage(Message) returns (Message) {
|
||||
// option (google.api.http) = {
|
||||
// patch: "/v1/messages/{message_id}"
|
||||
// body: "*"
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
// message Message {
|
||||
// string message_id = 1;
|
||||
// string text = 2;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// The following HTTP JSON to RPC mapping is enabled:
|
||||
//
|
||||
// HTTP | gRPC
|
||||
// -----|-----
|
||||
// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id:
|
||||
// "123456" text: "Hi!")`
|
||||
//
|
||||
// Note that when using `*` in the body mapping, it is not possible to
|
||||
// have HTTP parameters, as all fields not bound by the path end in
|
||||
// the body. This makes this option more rarely used in practice when
|
||||
// defining REST APIs. The common usage of `*` is in custom methods
|
||||
// which don't use the URL at all for transferring data.
|
||||
//
|
||||
// It is possible to define multiple HTTP methods for one RPC by using
|
||||
// the `additional_bindings` option. Example:
|
||||
//
|
||||
// service Messaging {
|
||||
// rpc GetMessage(GetMessageRequest) returns (Message) {
|
||||
// option (google.api.http) = {
|
||||
// get: "/v1/messages/{message_id}"
|
||||
// additional_bindings {
|
||||
// get: "/v1/users/{user_id}/messages/{message_id}"
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
// message GetMessageRequest {
|
||||
// string message_id = 1;
|
||||
// string user_id = 2;
|
||||
// }
|
||||
//
|
||||
// This enables the following two alternative HTTP JSON to RPC mappings:
|
||||
//
|
||||
// HTTP | gRPC
|
||||
// -----|-----
|
||||
// `GET /v1/messages/123456` | `GetMessage(message_id: "123456")`
|
||||
// `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id:
|
||||
// "123456")`
|
||||
//
|
||||
// ## Rules for HTTP mapping
|
||||
//
|
||||
// 1. Leaf request fields (recursive expansion nested messages in the request
|
||||
// message) are classified into three categories:
|
||||
// - Fields referred by the path template. They are passed via the URL path.
|
||||
// - Fields referred by the [HttpRule.body][google.api.HttpRule.body]. They are passed via the HTTP
|
||||
// request body.
|
||||
// - All other fields are passed via the URL query parameters, and the
|
||||
// parameter name is the field path in the request message. A repeated
|
||||
// field can be represented as multiple query parameters under the same
|
||||
// name.
|
||||
// 2. If [HttpRule.body][google.api.HttpRule.body] is "*", there is no URL query parameter, all fields
|
||||
// are passed via URL path and HTTP request body.
|
||||
// 3. If [HttpRule.body][google.api.HttpRule.body] is omitted, there is no HTTP request body, all
|
||||
// fields are passed via URL path and URL query parameters.
|
||||
//
|
||||
// ### Path template syntax
|
||||
//
|
||||
// Template = "/" Segments [ Verb ] ;
|
||||
// Segments = Segment { "/" Segment } ;
|
||||
// Segment = "*" | "**" | LITERAL | Variable ;
|
||||
// Variable = "{" FieldPath [ "=" Segments ] "}" ;
|
||||
// FieldPath = IDENT { "." IDENT } ;
|
||||
// Verb = ":" LITERAL ;
|
||||
//
|
||||
// The syntax `*` matches a single URL path segment. The syntax `**` matches
|
||||
// zero or more URL path segments, which must be the last part of the URL path
|
||||
// except the `Verb`.
|
||||
//
|
||||
// The syntax `Variable` matches part of the URL path as specified by its
|
||||
// template. A variable template must not contain other variables. If a variable
|
||||
// matches a single path segment, its template may be omitted, e.g. `{var}`
|
||||
// is equivalent to `{var=*}`.
|
||||
//
|
||||
// The syntax `LITERAL` matches literal text in the URL path. If the `LITERAL`
|
||||
// contains any reserved character, such characters should be percent-encoded
|
||||
// before the matching.
|
||||
//
|
||||
// If a variable contains exactly one path segment, such as `"{var}"` or
|
||||
// `"{var=*}"`, when such a variable is expanded into a URL path on the client
|
||||
// side, all characters except `[-_.~0-9a-zA-Z]` are percent-encoded. The
|
||||
// server side does the reverse decoding. Such variables show up in the
|
||||
// [Discovery
|
||||
// Document](https://developers.google.com/discovery/v1/reference/apis) as
|
||||
// `{var}`.
|
||||
//
|
||||
// If a variable contains multiple path segments, such as `"{var=foo/*}"`
|
||||
// or `"{var=**}"`, when such a variable is expanded into a URL path on the
|
||||
// client side, all characters except `[-_.~/0-9a-zA-Z]` are percent-encoded.
|
||||
// The server side does the reverse decoding, except "%2F" and "%2f" are left
|
||||
// unchanged. Such variables show up in the
|
||||
// [Discovery
|
||||
// Document](https://developers.google.com/discovery/v1/reference/apis) as
|
||||
// `{+var}`.
|
||||
//
|
||||
// ## Using gRPC API Service Configuration
|
||||
//
|
||||
// gRPC API Service Configuration (service config) is a configuration language
|
||||
// for configuring a gRPC service to become a user-facing product. The
|
||||
// service config is simply the YAML representation of the `google.api.Service`
|
||||
// proto message.
|
||||
//
|
||||
// As an alternative to annotating your proto file, you can configure gRPC
|
||||
// transcoding in your service config YAML files. You do this by specifying a
|
||||
// `HttpRule` that maps the gRPC method to a REST endpoint, achieving the same
|
||||
// effect as the proto annotation. This can be particularly useful if you
|
||||
// have a proto that is reused in multiple services. Note that any transcoding
|
||||
// specified in the service config will override any matching transcoding
|
||||
// configuration in the proto.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// http:
|
||||
// rules:
|
||||
// # Selects a gRPC method and applies HttpRule to it.
|
||||
// - selector: example.v1.Messaging.GetMessage
|
||||
// get: /v1/messages/{message_id}/{sub.subfield}
|
||||
//
|
||||
// ## Special notes
|
||||
//
|
||||
// When gRPC Transcoding is used to map a gRPC to JSON REST endpoints, the
|
||||
// proto to JSON conversion must follow the [proto3
|
||||
// specification](https://developers.google.com/protocol-buffers/docs/proto3#json).
|
||||
//
|
||||
// While the single segment variable follows the semantics of
|
||||
// [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2 Simple String
|
||||
// Expansion, the multi segment variable **does not** follow RFC 6570 Section
|
||||
// 3.2.3 Reserved Expansion. The reason is that the Reserved Expansion
|
||||
// does not expand special characters like `?` and `#`, which would lead
|
||||
// to invalid URLs. As the result, gRPC Transcoding uses a custom encoding
|
||||
// for multi segment variables.
|
||||
//
|
||||
// The path variables **must not** refer to any repeated or mapped field,
|
||||
// because client libraries are not capable of handling such variable expansion.
|
||||
//
|
||||
// The path variables **must not** capture the leading "/" character. The reason
|
||||
// is that the most common use case "{var}" does not capture the leading "/"
|
||||
// character. For consistency, all path variables must share the same behavior.
|
||||
//
|
||||
// Repeated message fields must not be mapped to URL query parameters, because
|
||||
// no client library can support such complicated mapping.
|
||||
//
|
||||
// If an API needs to use a JSON array for request or response body, it can map
|
||||
// the request or response body to a repeated field. However, some gRPC
|
||||
// Transcoding implementations may not support this feature.
|
||||
type HttpRule struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Selects a method to which this rule applies.
|
||||
//
|
||||
// Refer to [selector][google.api.DocumentationRule.selector] for syntax details.
|
||||
Selector string `protobuf:"bytes,1,opt,name=selector,proto3" json:"selector,omitempty"`
|
||||
// Determines the URL pattern is matched by this rules. This pattern can be
|
||||
// used with any of the {get|put|post|delete|patch} methods. A custom method
|
||||
// can be defined using the 'custom' field.
|
||||
//
|
||||
// Types that are assignable to Pattern:
|
||||
// *HttpRule_Get
|
||||
// *HttpRule_Put
|
||||
// *HttpRule_Post
|
||||
// *HttpRule_Delete
|
||||
// *HttpRule_Patch
|
||||
// *HttpRule_Custom
|
||||
Pattern isHttpRule_Pattern `protobuf_oneof:"pattern"`
|
||||
// The name of the request field whose value is mapped to the HTTP request
|
||||
// body, or `*` for mapping all request fields not captured by the path
|
||||
// pattern to the HTTP body, or omitted for not having any HTTP request body.
|
||||
//
|
||||
// NOTE: the referred field must be present at the top-level of the request
|
||||
// message type.
|
||||
Body string `protobuf:"bytes,7,opt,name=body,proto3" json:"body,omitempty"`
|
||||
// Optional. The name of the response field whose value is mapped to the HTTP
|
||||
// response body. When omitted, the entire response message will be used
|
||||
// as the HTTP response body.
|
||||
//
|
||||
// NOTE: The referred field must be present at the top-level of the response
|
||||
// message type.
|
||||
ResponseBody string `protobuf:"bytes,12,opt,name=response_body,json=responseBody,proto3" json:"response_body,omitempty"`
|
||||
// Additional HTTP bindings for the selector. Nested bindings must
|
||||
// not contain an `additional_bindings` field themselves (that is,
|
||||
// the nesting may only be one level deep).
|
||||
AdditionalBindings []*HttpRule `protobuf:"bytes,11,rep,name=additional_bindings,json=additionalBindings,proto3" json:"additional_bindings,omitempty"`
|
||||
}
|
||||
|
||||
func (x *HttpRule) Reset() {
|
||||
*x = HttpRule{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_google_api_http_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *HttpRule) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*HttpRule) ProtoMessage() {}
|
||||
|
||||
func (x *HttpRule) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_google_api_http_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use HttpRule.ProtoReflect.Descriptor instead.
|
||||
func (*HttpRule) Descriptor() ([]byte, []int) {
|
||||
return file_google_api_http_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *HttpRule) GetSelector() string {
|
||||
if x != nil {
|
||||
return x.Selector
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *HttpRule) GetPattern() isHttpRule_Pattern {
|
||||
if m != nil {
|
||||
return m.Pattern
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *HttpRule) GetGet() string {
|
||||
if x, ok := x.GetPattern().(*HttpRule_Get); ok {
|
||||
return x.Get
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *HttpRule) GetPut() string {
|
||||
if x, ok := x.GetPattern().(*HttpRule_Put); ok {
|
||||
return x.Put
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *HttpRule) GetPost() string {
|
||||
if x, ok := x.GetPattern().(*HttpRule_Post); ok {
|
||||
return x.Post
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *HttpRule) GetDelete() string {
|
||||
if x, ok := x.GetPattern().(*HttpRule_Delete); ok {
|
||||
return x.Delete
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *HttpRule) GetPatch() string {
|
||||
if x, ok := x.GetPattern().(*HttpRule_Patch); ok {
|
||||
return x.Patch
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *HttpRule) GetCustom() *CustomHttpPattern {
|
||||
if x, ok := x.GetPattern().(*HttpRule_Custom); ok {
|
||||
return x.Custom
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *HttpRule) GetBody() string {
|
||||
if x != nil {
|
||||
return x.Body
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *HttpRule) GetResponseBody() string {
|
||||
if x != nil {
|
||||
return x.ResponseBody
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *HttpRule) GetAdditionalBindings() []*HttpRule {
|
||||
if x != nil {
|
||||
return x.AdditionalBindings
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type isHttpRule_Pattern interface {
|
||||
isHttpRule_Pattern()
|
||||
}
|
||||
|
||||
type HttpRule_Get struct {
|
||||
// Maps to HTTP GET. Used for listing and getting information about
|
||||
// resources.
|
||||
Get string `protobuf:"bytes,2,opt,name=get,proto3,oneof"`
|
||||
}
|
||||
|
||||
type HttpRule_Put struct {
|
||||
// Maps to HTTP PUT. Used for replacing a resource.
|
||||
Put string `protobuf:"bytes,3,opt,name=put,proto3,oneof"`
|
||||
}
|
||||
|
||||
type HttpRule_Post struct {
|
||||
// Maps to HTTP POST. Used for creating a resource or performing an action.
|
||||
Post string `protobuf:"bytes,4,opt,name=post,proto3,oneof"`
|
||||
}
|
||||
|
||||
type HttpRule_Delete struct {
|
||||
// Maps to HTTP DELETE. Used for deleting a resource.
|
||||
Delete string `protobuf:"bytes,5,opt,name=delete,proto3,oneof"`
|
||||
}
|
||||
|
||||
type HttpRule_Patch struct {
|
||||
// Maps to HTTP PATCH. Used for updating a resource.
|
||||
Patch string `protobuf:"bytes,6,opt,name=patch,proto3,oneof"`
|
||||
}
|
||||
|
||||
type HttpRule_Custom struct {
|
||||
// The custom pattern is used for specifying an HTTP method that is not
|
||||
// included in the `pattern` field, such as HEAD, or "*" to leave the
|
||||
// HTTP method unspecified for this rule. The wild-card rule is useful
|
||||
// for services that provide content to Web (HTML) clients.
|
||||
Custom *CustomHttpPattern `protobuf:"bytes,8,opt,name=custom,proto3,oneof"`
|
||||
}
|
||||
|
||||
func (*HttpRule_Get) isHttpRule_Pattern() {}
|
||||
|
||||
func (*HttpRule_Put) isHttpRule_Pattern() {}
|
||||
|
||||
func (*HttpRule_Post) isHttpRule_Pattern() {}
|
||||
|
||||
func (*HttpRule_Delete) isHttpRule_Pattern() {}
|
||||
|
||||
func (*HttpRule_Patch) isHttpRule_Pattern() {}
|
||||
|
||||
func (*HttpRule_Custom) isHttpRule_Pattern() {}
|
||||
|
||||
// A custom pattern is used for defining custom HTTP verb.
|
||||
type CustomHttpPattern struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// The name of this custom HTTP verb.
|
||||
Kind string `protobuf:"bytes,1,opt,name=kind,proto3" json:"kind,omitempty"`
|
||||
// The path matched by this custom verb.
|
||||
Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
|
||||
}
|
||||
|
||||
func (x *CustomHttpPattern) Reset() {
|
||||
*x = CustomHttpPattern{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_google_api_http_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *CustomHttpPattern) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*CustomHttpPattern) ProtoMessage() {}
|
||||
|
||||
func (x *CustomHttpPattern) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_google_api_http_proto_msgTypes[2]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use CustomHttpPattern.ProtoReflect.Descriptor instead.
|
||||
func (*CustomHttpPattern) Descriptor() ([]byte, []int) {
|
||||
return file_google_api_http_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *CustomHttpPattern) GetKind() string {
|
||||
if x != nil {
|
||||
return x.Kind
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *CustomHttpPattern) GetPath() string {
|
||||
if x != nil {
|
||||
return x.Path
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_google_api_http_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_google_api_http_proto_rawDesc = []byte{
|
||||
0x0a, 0x15, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x68, 0x74, 0x74,
|
||||
0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
|
||||
0x61, 0x70, 0x69, 0x22, 0x79, 0x0a, 0x04, 0x48, 0x74, 0x74, 0x70, 0x12, 0x2a, 0x0a, 0x05, 0x72,
|
||||
0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f,
|
||||
0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x48, 0x74, 0x74, 0x70, 0x52, 0x75, 0x6c, 0x65,
|
||||
0x52, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x45, 0x0a, 0x1f, 0x66, 0x75, 0x6c, 0x6c, 0x79,
|
||||
0x5f, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64,
|
||||
0x5f, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08,
|
||||
0x52, 0x1c, 0x66, 0x75, 0x6c, 0x6c, 0x79, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73,
|
||||
0x65, 0x72, 0x76, 0x65, 0x64, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xda,
|
||||
0x02, 0x0a, 0x08, 0x48, 0x74, 0x74, 0x70, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x73,
|
||||
0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73,
|
||||
0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x03, 0x67, 0x65, 0x74, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x67, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x03, 0x70,
|
||||
0x75, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x70, 0x75, 0x74, 0x12,
|
||||
0x14, 0x0a, 0x04, 0x70, 0x6f, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52,
|
||||
0x04, 0x70, 0x6f, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x06, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x18,
|
||||
0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12,
|
||||
0x16, 0x0a, 0x05, 0x70, 0x61, 0x74, 0x63, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00,
|
||||
0x52, 0x05, 0x70, 0x61, 0x74, 0x63, 0x68, 0x12, 0x37, 0x0a, 0x06, 0x63, 0x75, 0x73, 0x74, 0x6f,
|
||||
0x6d, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
|
||||
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x48, 0x74, 0x74, 0x70, 0x50,
|
||||
0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x48, 0x00, 0x52, 0x06, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d,
|
||||
0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
|
||||
0x62, 0x6f, 0x64, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x5f, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x13, 0x61, 0x64, 0x64,
|
||||
0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73,
|
||||
0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
|
||||
0x61, 0x70, 0x69, 0x2e, 0x48, 0x74, 0x74, 0x70, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x12, 0x61, 0x64,
|
||||
0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73,
|
||||
0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x22, 0x3b, 0x0a, 0x11, 0x43,
|
||||
0x75, 0x73, 0x74, 0x6f, 0x6d, 0x48, 0x74, 0x74, 0x70, 0x50, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e,
|
||||
0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
|
||||
0x6b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x42, 0x6a, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x2e,
|
||||
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x42, 0x09, 0x48, 0x74, 0x74, 0x70,
|
||||
0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x41, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
|
||||
0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x61,
|
||||
0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3b, 0x61,
|
||||
0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0xf8, 0x01, 0x01, 0xa2, 0x02, 0x04,
|
||||
0x47, 0x41, 0x50, 0x49, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_google_api_http_proto_rawDescOnce sync.Once
|
||||
file_google_api_http_proto_rawDescData = file_google_api_http_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_google_api_http_proto_rawDescGZIP() []byte {
|
||||
file_google_api_http_proto_rawDescOnce.Do(func() {
|
||||
file_google_api_http_proto_rawDescData = protoimpl.X.CompressGZIP(file_google_api_http_proto_rawDescData)
|
||||
})
|
||||
return file_google_api_http_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_google_api_http_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
|
||||
var file_google_api_http_proto_goTypes = []interface{}{
|
||||
(*Http)(nil), // 0: google.api.Http
|
||||
(*HttpRule)(nil), // 1: google.api.HttpRule
|
||||
(*CustomHttpPattern)(nil), // 2: google.api.CustomHttpPattern
|
||||
}
|
||||
var file_google_api_http_proto_depIdxs = []int32{
|
||||
1, // 0: google.api.Http.rules:type_name -> google.api.HttpRule
|
||||
2, // 1: google.api.HttpRule.custom:type_name -> google.api.CustomHttpPattern
|
||||
1, // 2: google.api.HttpRule.additional_bindings:type_name -> google.api.HttpRule
|
||||
3, // [3:3] is the sub-list for method output_type
|
||||
3, // [3:3] is the sub-list for method input_type
|
||||
3, // [3:3] is the sub-list for extension type_name
|
||||
3, // [3:3] is the sub-list for extension extendee
|
||||
0, // [0:3] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_google_api_http_proto_init() }
|
||||
func file_google_api_http_proto_init() {
|
||||
if File_google_api_http_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_google_api_http_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Http); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_google_api_http_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*HttpRule); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_google_api_http_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*CustomHttpPattern); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
file_google_api_http_proto_msgTypes[1].OneofWrappers = []interface{}{
|
||||
(*HttpRule_Get)(nil),
|
||||
(*HttpRule_Put)(nil),
|
||||
(*HttpRule_Post)(nil),
|
||||
(*HttpRule_Delete)(nil),
|
||||
(*HttpRule_Patch)(nil),
|
||||
(*HttpRule_Custom)(nil),
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_google_api_http_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 3,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_google_api_http_proto_goTypes,
|
||||
DependencyIndexes: file_google_api_http_proto_depIdxs,
|
||||
MessageInfos: file_google_api_http_proto_msgTypes,
|
||||
}.Build()
|
||||
File_google_api_http_proto = out.File
|
||||
file_google_api_http_proto_rawDesc = nil
|
||||
file_google_api_http_proto_goTypes = nil
|
||||
file_google_api_http_proto_depIdxs = nil
|
||||
}
|
376
pkg/api/v1/schnutibox.pb.go
Normal file
376
pkg/api/v1/schnutibox.pb.go
Normal file
@ -0,0 +1,376 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.13.0
|
||||
// source: schnutibox.proto
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
duration "github.com/golang/protobuf/ptypes/duration"
|
||||
_ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type IdentifyRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
}
|
||||
|
||||
func (x *IdentifyRequest) Reset() {
|
||||
*x = IdentifyRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_schnutibox_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *IdentifyRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*IdentifyRequest) ProtoMessage() {}
|
||||
|
||||
func (x *IdentifyRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_schnutibox_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use IdentifyRequest.ProtoReflect.Descriptor instead.
|
||||
func (*IdentifyRequest) Descriptor() ([]byte, []int) {
|
||||
return file_schnutibox_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *IdentifyRequest) GetId() string {
|
||||
if x != nil {
|
||||
return x.Id
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type IdentifyResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Uris []string `protobuf:"bytes,2,rep,name=uris,proto3" json:"uris,omitempty"`
|
||||
}
|
||||
|
||||
func (x *IdentifyResponse) Reset() {
|
||||
*x = IdentifyResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_schnutibox_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *IdentifyResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*IdentifyResponse) ProtoMessage() {}
|
||||
|
||||
func (x *IdentifyResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_schnutibox_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use IdentifyResponse.ProtoReflect.Descriptor instead.
|
||||
func (*IdentifyResponse) Descriptor() ([]byte, []int) {
|
||||
return file_schnutibox_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *IdentifyResponse) GetName() string {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *IdentifyResponse) GetUris() []string {
|
||||
if x != nil {
|
||||
return x.Uris
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Timer struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Duration *duration.Duration `protobuf:"bytes,1,opt,name=duration,proto3" json:"duration,omitempty"`
|
||||
Current *duration.Duration `protobuf:"bytes,2,opt,name=current,proto3" json:"current,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Timer) Reset() {
|
||||
*x = Timer{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_schnutibox_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Timer) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Timer) ProtoMessage() {}
|
||||
|
||||
func (x *Timer) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_schnutibox_proto_msgTypes[2]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Timer.ProtoReflect.Descriptor instead.
|
||||
func (*Timer) Descriptor() ([]byte, []int) {
|
||||
return file_schnutibox_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *Timer) GetDuration() *duration.Duration {
|
||||
if x != nil {
|
||||
return x.Duration
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Timer) GetCurrent() *duration.Duration {
|
||||
if x != nil {
|
||||
return x.Current
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type TimerEmpty struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
}
|
||||
|
||||
func (x *TimerEmpty) Reset() {
|
||||
*x = TimerEmpty{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_schnutibox_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *TimerEmpty) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*TimerEmpty) ProtoMessage() {}
|
||||
|
||||
func (x *TimerEmpty) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_schnutibox_proto_msgTypes[3]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use TimerEmpty.ProtoReflect.Descriptor instead.
|
||||
func (*TimerEmpty) Descriptor() ([]byte, []int) {
|
||||
return file_schnutibox_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
var File_schnutibox_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_schnutibox_proto_rawDesc = []byte{
|
||||
0x0a, 0x10, 0x73, 0x63, 0x68, 0x6e, 0x75, 0x74, 0x69, 0x62, 0x6f, 0x78, 0x2e, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x12, 0x0d, 0x73, 0x63, 0x68, 0x6e, 0x75, 0x74, 0x69, 0x62, 0x6f, 0x78, 0x2e, 0x76,
|
||||
0x31, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e,
|
||||
0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
|
||||
0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
|
||||
0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22,
|
||||
0x21, 0x0a, 0x0f, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02,
|
||||
0x69, 0x64, 0x22, 0x3a, 0x0a, 0x10, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x72,
|
||||
0x69, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x75, 0x72, 0x69, 0x73, 0x22, 0x73,
|
||||
0x0a, 0x05, 0x54, 0x69, 0x6d, 0x65, 0x72, 0x12, 0x35, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
|
||||
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x33,
|
||||
0x0a, 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||
0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
|
||||
0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x63, 0x75, 0x72, 0x72,
|
||||
0x65, 0x6e, 0x74, 0x22, 0x0c, 0x0a, 0x0a, 0x54, 0x69, 0x6d, 0x65, 0x72, 0x45, 0x6d, 0x70, 0x74,
|
||||
0x79, 0x32, 0x7d, 0x0a, 0x11, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x53,
|
||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x68, 0x0a, 0x08, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69,
|
||||
0x66, 0x79, 0x12, 0x1e, 0x2e, 0x73, 0x63, 0x68, 0x6e, 0x75, 0x74, 0x69, 0x62, 0x6f, 0x78, 0x2e,
|
||||
0x76, 0x31, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x73, 0x63, 0x68, 0x6e, 0x75, 0x74, 0x69, 0x62, 0x6f, 0x78, 0x2e,
|
||||
0x76, 0x31, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x22, 0x10, 0x2f, 0x61, 0x70,
|
||||
0x69, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x3a, 0x01, 0x2a,
|
||||
0x32, 0xb0, 0x01, 0x0a, 0x0c, 0x54, 0x69, 0x6d, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
|
||||
0x65, 0x12, 0x4e, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x14, 0x2e, 0x73, 0x63,
|
||||
0x68, 0x6e, 0x75, 0x74, 0x69, 0x62, 0x6f, 0x78, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65,
|
||||
0x72, 0x1a, 0x14, 0x2e, 0x73, 0x63, 0x68, 0x6e, 0x75, 0x74, 0x69, 0x62, 0x6f, 0x78, 0x2e, 0x76,
|
||||
0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x72, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x22,
|
||||
0x0d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x3a, 0x01,
|
||||
0x2a, 0x12, 0x50, 0x0a, 0x03, 0x47, 0x65, 0x74, 0x12, 0x19, 0x2e, 0x73, 0x63, 0x68, 0x6e, 0x75,
|
||||
0x74, 0x69, 0x62, 0x6f, 0x78, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x72, 0x45, 0x6d,
|
||||
0x70, 0x74, 0x79, 0x1a, 0x14, 0x2e, 0x73, 0x63, 0x68, 0x6e, 0x75, 0x74, 0x69, 0x62, 0x6f, 0x78,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x72, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02,
|
||||
0x12, 0x12, 0x0d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x72,
|
||||
0x3a, 0x01, 0x2a, 0x42, 0x23, 0x5a, 0x21, 0x67, 0x6f, 0x2e, 0x78, 0x73, 0x66, 0x78, 0x2e, 0x64,
|
||||
0x65, 0x76, 0x2f, 0x73, 0x63, 0x68, 0x6e, 0x75, 0x74, 0x69, 0x62, 0x6f, 0x78, 0x2f, 0x70, 0x6b,
|
||||
0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_schnutibox_proto_rawDescOnce sync.Once
|
||||
file_schnutibox_proto_rawDescData = file_schnutibox_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_schnutibox_proto_rawDescGZIP() []byte {
|
||||
file_schnutibox_proto_rawDescOnce.Do(func() {
|
||||
file_schnutibox_proto_rawDescData = protoimpl.X.CompressGZIP(file_schnutibox_proto_rawDescData)
|
||||
})
|
||||
return file_schnutibox_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_schnutibox_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
|
||||
var file_schnutibox_proto_goTypes = []interface{}{
|
||||
(*IdentifyRequest)(nil), // 0: schnutibox.v1.IdentifyRequest
|
||||
(*IdentifyResponse)(nil), // 1: schnutibox.v1.IdentifyResponse
|
||||
(*Timer)(nil), // 2: schnutibox.v1.Timer
|
||||
(*TimerEmpty)(nil), // 3: schnutibox.v1.TimerEmpty
|
||||
(*duration.Duration)(nil), // 4: google.protobuf.Duration
|
||||
}
|
||||
var file_schnutibox_proto_depIdxs = []int32{
|
||||
4, // 0: schnutibox.v1.Timer.duration:type_name -> google.protobuf.Duration
|
||||
4, // 1: schnutibox.v1.Timer.current:type_name -> google.protobuf.Duration
|
||||
0, // 2: schnutibox.v1.IdentifierService.Identify:input_type -> schnutibox.v1.IdentifyRequest
|
||||
2, // 3: schnutibox.v1.TimerService.Create:input_type -> schnutibox.v1.Timer
|
||||
3, // 4: schnutibox.v1.TimerService.Get:input_type -> schnutibox.v1.TimerEmpty
|
||||
1, // 5: schnutibox.v1.IdentifierService.Identify:output_type -> schnutibox.v1.IdentifyResponse
|
||||
2, // 6: schnutibox.v1.TimerService.Create:output_type -> schnutibox.v1.Timer
|
||||
2, // 7: schnutibox.v1.TimerService.Get:output_type -> schnutibox.v1.Timer
|
||||
5, // [5:8] is the sub-list for method output_type
|
||||
2, // [2:5] is the sub-list for method input_type
|
||||
2, // [2:2] is the sub-list for extension type_name
|
||||
2, // [2:2] is the sub-list for extension extendee
|
||||
0, // [0:2] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_schnutibox_proto_init() }
|
||||
func file_schnutibox_proto_init() {
|
||||
if File_schnutibox_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_schnutibox_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*IdentifyRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_schnutibox_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*IdentifyResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_schnutibox_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Timer); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_schnutibox_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*TimerEmpty); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_schnutibox_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 4,
|
||||
NumExtensions: 0,
|
||||
NumServices: 2,
|
||||
},
|
||||
GoTypes: file_schnutibox_proto_goTypes,
|
||||
DependencyIndexes: file_schnutibox_proto_depIdxs,
|
||||
MessageInfos: file_schnutibox_proto_msgTypes,
|
||||
}.Build()
|
||||
File_schnutibox_proto = out.File
|
||||
file_schnutibox_proto_rawDesc = nil
|
||||
file_schnutibox_proto_goTypes = nil
|
||||
file_schnutibox_proto_depIdxs = nil
|
||||
}
|
367
pkg/api/v1/schnutibox.pb.gw.go
Normal file
367
pkg/api/v1/schnutibox.pb.gw.go
Normal file
@ -0,0 +1,367 @@
|
||||
// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
|
||||
// source: schnutibox.proto
|
||||
|
||||
/*
|
||||
Package v1 is a reverse proxy.
|
||||
|
||||
It translates gRPC into RESTful JSON APIs.
|
||||
*/
|
||||
package v1
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/v2/utilities"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// Suppress "imported and not used" errors
|
||||
var _ codes.Code
|
||||
var _ io.Reader
|
||||
var _ status.Status
|
||||
var _ = runtime.String
|
||||
var _ = utilities.NewDoubleArray
|
||||
var _ = metadata.Join
|
||||
|
||||
func request_IdentifierService_Identify_0(ctx context.Context, marshaler runtime.Marshaler, client IdentifierServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq IdentifyRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.Identify(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_IdentifierService_Identify_0(ctx context.Context, marshaler runtime.Marshaler, server IdentifierServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq IdentifyRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.Identify(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_TimerService_Create_0(ctx context.Context, marshaler runtime.Marshaler, client TimerServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq Timer
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.Create(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_TimerService_Create_0(ctx context.Context, marshaler runtime.Marshaler, server TimerServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq Timer
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.Create(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_TimerService_Get_0(ctx context.Context, marshaler runtime.Marshaler, client TimerServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq TimerEmpty
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := client.Get(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_TimerService_Get_0(ctx context.Context, marshaler runtime.Marshaler, server TimerServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq TimerEmpty
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := server.Get(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
// RegisterIdentifierServiceHandlerServer registers the http handlers for service IdentifierService to "mux".
|
||||
// UnaryRPC :call IdentifierServiceServer directly.
|
||||
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
|
||||
// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterIdentifierServiceHandlerFromEndpoint instead.
|
||||
func RegisterIdentifierServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server IdentifierServiceServer) error {
|
||||
|
||||
mux.Handle("POST", pattern_IdentifierService_Identify_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/schnutibox.v1.IdentifierService/Identify")
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_IdentifierService_Identify_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_IdentifierService_Identify_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterTimerServiceHandlerServer registers the http handlers for service TimerService to "mux".
|
||||
// UnaryRPC :call TimerServiceServer directly.
|
||||
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
|
||||
// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterTimerServiceHandlerFromEndpoint instead.
|
||||
func RegisterTimerServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server TimerServiceServer) error {
|
||||
|
||||
mux.Handle("POST", pattern_TimerService_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/schnutibox.v1.TimerService/Create")
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_TimerService_Create_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_TimerService_Create_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_TimerService_Get_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/schnutibox.v1.TimerService/Get")
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_TimerService_Get_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_TimerService_Get_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterIdentifierServiceHandlerFromEndpoint is same as RegisterIdentifierServiceHandler but
|
||||
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
|
||||
func RegisterIdentifierServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
|
||||
conn, err := grpc.Dial(endpoint, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
}()
|
||||
}()
|
||||
|
||||
return RegisterIdentifierServiceHandler(ctx, mux, conn)
|
||||
}
|
||||
|
||||
// RegisterIdentifierServiceHandler registers the http handlers for service IdentifierService to "mux".
|
||||
// The handlers forward requests to the grpc endpoint over "conn".
|
||||
func RegisterIdentifierServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
|
||||
return RegisterIdentifierServiceHandlerClient(ctx, mux, NewIdentifierServiceClient(conn))
|
||||
}
|
||||
|
||||
// RegisterIdentifierServiceHandlerClient registers the http handlers for service IdentifierService
|
||||
// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "IdentifierServiceClient".
|
||||
// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "IdentifierServiceClient"
|
||||
// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
|
||||
// "IdentifierServiceClient" to call the correct interceptors.
|
||||
func RegisterIdentifierServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client IdentifierServiceClient) error {
|
||||
|
||||
mux.Handle("POST", pattern_IdentifierService_Identify_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/schnutibox.v1.IdentifierService/Identify")
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_IdentifierService_Identify_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_IdentifierService_Identify_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
pattern_IdentifierService_Identify_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "identify"}, ""))
|
||||
)
|
||||
|
||||
var (
|
||||
forward_IdentifierService_Identify_0 = runtime.ForwardResponseMessage
|
||||
)
|
||||
|
||||
// RegisterTimerServiceHandlerFromEndpoint is same as RegisterTimerServiceHandler but
|
||||
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
|
||||
func RegisterTimerServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
|
||||
conn, err := grpc.Dial(endpoint, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
}()
|
||||
}()
|
||||
|
||||
return RegisterTimerServiceHandler(ctx, mux, conn)
|
||||
}
|
||||
|
||||
// RegisterTimerServiceHandler registers the http handlers for service TimerService to "mux".
|
||||
// The handlers forward requests to the grpc endpoint over "conn".
|
||||
func RegisterTimerServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
|
||||
return RegisterTimerServiceHandlerClient(ctx, mux, NewTimerServiceClient(conn))
|
||||
}
|
||||
|
||||
// RegisterTimerServiceHandlerClient registers the http handlers for service TimerService
|
||||
// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "TimerServiceClient".
|
||||
// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "TimerServiceClient"
|
||||
// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
|
||||
// "TimerServiceClient" to call the correct interceptors.
|
||||
func RegisterTimerServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client TimerServiceClient) error {
|
||||
|
||||
mux.Handle("POST", pattern_TimerService_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/schnutibox.v1.TimerService/Create")
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_TimerService_Create_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_TimerService_Create_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_TimerService_Get_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/schnutibox.v1.TimerService/Get")
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_TimerService_Get_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_TimerService_Get_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
pattern_TimerService_Create_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "timer"}, ""))
|
||||
|
||||
pattern_TimerService_Get_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "timer"}, ""))
|
||||
)
|
||||
|
||||
var (
|
||||
forward_TimerService_Create_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_TimerService_Get_0 = runtime.ForwardResponseMessage
|
||||
)
|
219
pkg/api/v1/schnutibox_grpc.pb.go
Normal file
219
pkg/api/v1/schnutibox_grpc.pb.go
Normal file
@ -0,0 +1,219 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
// IdentifierServiceClient is the client API for IdentifierService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type IdentifierServiceClient interface {
|
||||
Identify(ctx context.Context, in *IdentifyRequest, opts ...grpc.CallOption) (*IdentifyResponse, error)
|
||||
}
|
||||
|
||||
type identifierServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewIdentifierServiceClient(cc grpc.ClientConnInterface) IdentifierServiceClient {
|
||||
return &identifierServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *identifierServiceClient) Identify(ctx context.Context, in *IdentifyRequest, opts ...grpc.CallOption) (*IdentifyResponse, error) {
|
||||
out := new(IdentifyResponse)
|
||||
err := c.cc.Invoke(ctx, "/schnutibox.v1.IdentifierService/Identify", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// IdentifierServiceServer is the server API for IdentifierService service.
|
||||
// All implementations should embed UnimplementedIdentifierServiceServer
|
||||
// for forward compatibility
|
||||
type IdentifierServiceServer interface {
|
||||
Identify(context.Context, *IdentifyRequest) (*IdentifyResponse, error)
|
||||
}
|
||||
|
||||
// UnimplementedIdentifierServiceServer should be embedded to have forward compatible implementations.
|
||||
type UnimplementedIdentifierServiceServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedIdentifierServiceServer) Identify(context.Context, *IdentifyRequest) (*IdentifyResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Identify not implemented")
|
||||
}
|
||||
|
||||
// UnsafeIdentifierServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to IdentifierServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeIdentifierServiceServer interface {
|
||||
mustEmbedUnimplementedIdentifierServiceServer()
|
||||
}
|
||||
|
||||
func RegisterIdentifierServiceServer(s grpc.ServiceRegistrar, srv IdentifierServiceServer) {
|
||||
s.RegisterService(&IdentifierService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _IdentifierService_Identify_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(IdentifyRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(IdentifierServiceServer).Identify(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/schnutibox.v1.IdentifierService/Identify",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(IdentifierServiceServer).Identify(ctx, req.(*IdentifyRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// IdentifierService_ServiceDesc is the grpc.ServiceDesc for IdentifierService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var IdentifierService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "schnutibox.v1.IdentifierService",
|
||||
HandlerType: (*IdentifierServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Identify",
|
||||
Handler: _IdentifierService_Identify_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "schnutibox.proto",
|
||||
}
|
||||
|
||||
// TimerServiceClient is the client API for TimerService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type TimerServiceClient interface {
|
||||
Create(ctx context.Context, in *Timer, opts ...grpc.CallOption) (*Timer, error)
|
||||
Get(ctx context.Context, in *TimerEmpty, opts ...grpc.CallOption) (*Timer, error)
|
||||
}
|
||||
|
||||
type timerServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewTimerServiceClient(cc grpc.ClientConnInterface) TimerServiceClient {
|
||||
return &timerServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *timerServiceClient) Create(ctx context.Context, in *Timer, opts ...grpc.CallOption) (*Timer, error) {
|
||||
out := new(Timer)
|
||||
err := c.cc.Invoke(ctx, "/schnutibox.v1.TimerService/Create", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *timerServiceClient) Get(ctx context.Context, in *TimerEmpty, opts ...grpc.CallOption) (*Timer, error) {
|
||||
out := new(Timer)
|
||||
err := c.cc.Invoke(ctx, "/schnutibox.v1.TimerService/Get", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// TimerServiceServer is the server API for TimerService service.
|
||||
// All implementations should embed UnimplementedTimerServiceServer
|
||||
// for forward compatibility
|
||||
type TimerServiceServer interface {
|
||||
Create(context.Context, *Timer) (*Timer, error)
|
||||
Get(context.Context, *TimerEmpty) (*Timer, error)
|
||||
}
|
||||
|
||||
// UnimplementedTimerServiceServer should be embedded to have forward compatible implementations.
|
||||
type UnimplementedTimerServiceServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedTimerServiceServer) Create(context.Context, *Timer) (*Timer, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Create not implemented")
|
||||
}
|
||||
func (UnimplementedTimerServiceServer) Get(context.Context, *TimerEmpty) (*Timer, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Get not implemented")
|
||||
}
|
||||
|
||||
// UnsafeTimerServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to TimerServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeTimerServiceServer interface {
|
||||
mustEmbedUnimplementedTimerServiceServer()
|
||||
}
|
||||
|
||||
func RegisterTimerServiceServer(s grpc.ServiceRegistrar, srv TimerServiceServer) {
|
||||
s.RegisterService(&TimerService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _TimerService_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Timer)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(TimerServiceServer).Create(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/schnutibox.v1.TimerService/Create",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(TimerServiceServer).Create(ctx, req.(*Timer))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _TimerService_Get_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(TimerEmpty)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(TimerServiceServer).Get(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/schnutibox.v1.TimerService/Get",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(TimerServiceServer).Get(ctx, req.(*TimerEmpty))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// TimerService_ServiceDesc is the grpc.ServiceDesc for TimerService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var TimerService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "schnutibox.v1.TimerService",
|
||||
HandlerType: (*TimerServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Create",
|
||||
Handler: _TimerService_Create_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Get",
|
||||
Handler: _TimerService_Get_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "schnutibox.proto",
|
||||
}
|
56
pkg/currentsong/currentsong.go
Normal file
56
pkg/currentsong/currentsong.go
Normal file
@ -0,0 +1,56 @@
|
||||
package currentsong
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"go.xsfx.dev/logginghandler"
|
||||
)
|
||||
|
||||
var recvs = make(map[chan string]struct{}) // nolint:gochecknoglobals
|
||||
|
||||
// Write writes current track to the receivers.
|
||||
func Write(track string) {
|
||||
for k := range recvs {
|
||||
k <- track
|
||||
}
|
||||
}
|
||||
|
||||
func Handler(w http.ResponseWriter, r *http.Request) {
|
||||
logger := logginghandler.Logger(r)
|
||||
logger.Debug().Msg("got a new receiver")
|
||||
|
||||
flusher, ok := w.(http.Flusher)
|
||||
if !ok {
|
||||
logger.Error().Msg("streaming unsupported")
|
||||
http.Error(w, "streaming unsupported", http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "text/event-stream")
|
||||
w.Header().Set("Cache-Control", "no-cache")
|
||||
w.Header().Set("Connection", "keep-alive")
|
||||
// TODO: has to be something else!
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
|
||||
cChan := make(chan string)
|
||||
|
||||
recvs[cChan] = struct{}{}
|
||||
|
||||
for {
|
||||
select {
|
||||
case e := <-cChan:
|
||||
// Send event to client.
|
||||
fmt.Fprintf(w, "data: %s\n\n", e)
|
||||
|
||||
// Send it right now and not buffering it.
|
||||
flusher.Flush()
|
||||
case <-r.Context().Done():
|
||||
close(cChan)
|
||||
delete(recvs, cChan)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
138
pkg/mpc/mpc.go
Normal file
138
pkg/mpc/mpc.go
Normal file
@ -0,0 +1,138 @@
|
||||
package mpc
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/fhs/gompd/v2/mpd"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
"go.xsfx.dev/schnutibox/internal/config"
|
||||
"go.xsfx.dev/schnutibox/internal/metrics"
|
||||
)
|
||||
|
||||
const (
|
||||
timeout = 5 * time.Second
|
||||
timeoutWait = time.Second / 2
|
||||
)
|
||||
|
||||
var errTimeout = errors.New("timeout")
|
||||
|
||||
func Conn() (*mpd.Client, error) {
|
||||
t := time.NewTimer(timeout)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-t.C:
|
||||
return nil, errTimeout
|
||||
default:
|
||||
c, err := mpd.Dial("tcp", fmt.Sprintf("%s:%d", config.Cfg.MPD.Hostname, config.Cfg.MPD.Port))
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("could not connect")
|
||||
|
||||
time.Sleep(timeoutWait)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if !t.Stop() {
|
||||
go func() {
|
||||
<-t.C
|
||||
}()
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PlaylistURIS extracts uris from MPD playlist.
|
||||
func PlaylistURIS(m *mpd.Client) ([]string, error) {
|
||||
attrs, err := m.PlaylistInfo(-1, -1)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get playlist: %w", err)
|
||||
}
|
||||
|
||||
// Stores the tracklist it got from the MPD server.
|
||||
uris := []string{}
|
||||
|
||||
// Builds uri list.
|
||||
for _, a := range attrs {
|
||||
uris = append(uris, a["file"])
|
||||
}
|
||||
|
||||
return uris, nil
|
||||
}
|
||||
|
||||
func Stop(logger zerolog.Logger) error {
|
||||
logger.Info().Msg("trying to stop playback")
|
||||
|
||||
m, err := Conn()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not connect: %w", err)
|
||||
}
|
||||
|
||||
// nolint:wrapcheck
|
||||
return m.Stop()
|
||||
}
|
||||
|
||||
func Clear(logger zerolog.Logger) error {
|
||||
logger.Info().Msg("trying to clear playlist")
|
||||
|
||||
m, err := Conn()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not connect: %w", err)
|
||||
}
|
||||
|
||||
// nolint:wrapcheck
|
||||
return m.Clear()
|
||||
}
|
||||
|
||||
func Play(logger zerolog.Logger, rfid string, name string, uris []string) error {
|
||||
logger.Info().Msg("trying to add tracks")
|
||||
|
||||
m, err := Conn()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not connect: %w", err)
|
||||
}
|
||||
|
||||
// Stop playing track.
|
||||
if err := Stop(logger); err != nil {
|
||||
metrics.BoxErrors.Inc()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Clear playlist.
|
||||
if err := Clear(logger); err != nil {
|
||||
metrics.BoxErrors.Inc()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Adding every single uri to playlist
|
||||
for _, i := range uris {
|
||||
logger.Debug().Str("uri", i).Msg("add track")
|
||||
|
||||
if err := m.Add(i); err != nil {
|
||||
metrics.BoxErrors.Inc()
|
||||
|
||||
return fmt.Errorf("could not add track: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Getting playlist uris from MPD server.
|
||||
// This is needed to identify the right metric to use.
|
||||
mpdURIS, err := PlaylistURIS(m)
|
||||
if err != nil {
|
||||
metrics.BoxErrors.Inc()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
metrics.NewPlay(rfid, name, mpdURIS)
|
||||
|
||||
// nolint:wrapcheck
|
||||
return m.Play(-1)
|
||||
}
|
@ -13,7 +13,7 @@ import (
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/cobra"
|
||||
"go.xsfx.dev/schnutibox/assets"
|
||||
assets "go.xsfx.dev/schnutibox/assets/prepare"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -27,8 +27,13 @@ const (
|
||||
schnutboxConfigDir = "/etc/schnutibox"
|
||||
upmpdcliUser = "upmpdcli"
|
||||
upmpdcliGroup = "nogroup"
|
||||
snapserverUser = "snapserver"
|
||||
snapserverGroup = "snapserver"
|
||||
snapclientUser = "snapclient"
|
||||
snapclientGroup = "snapclient"
|
||||
)
|
||||
|
||||
// Cfg represents the structured data for the schnutibox config file.
|
||||
var Cfg = struct {
|
||||
RFIDReader string
|
||||
ReadOnly bool
|
||||
@ -41,11 +46,11 @@ var Cfg = struct {
|
||||
System string
|
||||
}{}
|
||||
|
||||
// BoxService creates a systemd service for schnutibox.
|
||||
func BoxService(filename string, enable bool) error {
|
||||
// boxService creates a systemd service for schnutibox.
|
||||
func boxService(filename string, enable bool) error {
|
||||
logger := log.With().Str("stage", "BoxService").Logger()
|
||||
|
||||
if err := CreateUser(); err != nil {
|
||||
if err := createUser(); err != nil {
|
||||
return fmt.Errorf("could not create user: %w", err)
|
||||
}
|
||||
|
||||
@ -54,8 +59,13 @@ func BoxService(filename string, enable bool) error {
|
||||
return fmt.Errorf("could not create config dir: %w", err)
|
||||
}
|
||||
|
||||
//nolint:gosec
|
||||
if err := ioutil.WriteFile(filename, assets.SchnutiboxService, 0o644); err != nil {
|
||||
schnutiboxService, err := assets.Files.ReadFile("files/schnutibox.service")
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get service file: %w", err)
|
||||
}
|
||||
|
||||
//nolint:gosec,gomnd
|
||||
if err := ioutil.WriteFile(filename, schnutiboxService, 0o644); err != nil {
|
||||
return fmt.Errorf("could not write service file: %w", err)
|
||||
}
|
||||
|
||||
@ -78,7 +88,7 @@ func BoxService(filename string, enable bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func NTP() error {
|
||||
func ntp() error {
|
||||
logger := log.With().Str("stage", "NTP").Logger()
|
||||
|
||||
cmd := exec.Command("apt-get", "install", "-y", "ntp", "ntpdate")
|
||||
@ -91,8 +101,13 @@ func NTP() error {
|
||||
return fmt.Errorf("could not install ntp: %w", err)
|
||||
}
|
||||
|
||||
// nolint:gosec
|
||||
if err := ioutil.WriteFile("/etc/systemd/system/ntp.service", assets.NtpService, 0o644); err != nil {
|
||||
ntpService, err := assets.Files.ReadFile("files/ntp.service")
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get ntp service file: %w", err)
|
||||
}
|
||||
|
||||
// nolint:gosec,gomnd
|
||||
if err := ioutil.WriteFile("/etc/systemd/system/ntp.service", ntpService, 0o644); err != nil {
|
||||
return fmt.Errorf("could not copy ntp service file: %w", err)
|
||||
}
|
||||
|
||||
@ -109,10 +124,11 @@ func NTP() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Fstab creates a fstab for a read-only system.
|
||||
// nolint:funlen
|
||||
func Fstab(system string) error {
|
||||
// fstab creates a fstab for a read-only system.
|
||||
// nolint:funlen,cyclop
|
||||
func fstab(system string) error {
|
||||
logger := log.With().Str("stage", "Fstab").Logger()
|
||||
logger.Debug().Str("system", system).Msg("ignoring for now")
|
||||
|
||||
// Getting timesync user and group informations.
|
||||
timesyncUser, err := user.Lookup(timesyncUser)
|
||||
@ -153,12 +169,40 @@ func Fstab(system string) error {
|
||||
|
||||
logger.Debug().Str("uid", upmpdcliUser.Uid).Str("gid", upmpdcliGroup.Gid).Msg("upmpdcli")
|
||||
|
||||
// Getting snapserver user and group informations.
|
||||
snapserverUser, err := user.Lookup(snapserverUser)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not lookup snapserver user: %w", err)
|
||||
}
|
||||
|
||||
snapserverGroup, err := user.LookupGroup(snapserverGroup)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not lookup snapserver group: %w", err)
|
||||
}
|
||||
|
||||
logger.Debug().Str("uid", snapserverUser.Uid).Str("gid", snapserverGroup.Gid).Msg("snapserver")
|
||||
|
||||
snapclientUser, err := user.Lookup(snapclientUser)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not lookup snapclient user: %w", err)
|
||||
}
|
||||
|
||||
snapclientGroup, err := user.LookupGroup(snapclientGroup)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not lookup snapclient group: %w", err)
|
||||
}
|
||||
|
||||
logger.Debug().Str("uid", snapclientUser.Uid).Str("gid", snapclientGroup.Gid).Msg("snapclient")
|
||||
|
||||
// Chose the right template.
|
||||
// In future it should be a switch statement.
|
||||
tmpl := assets.FstabRaspbianTemplate
|
||||
tmpl, err := assets.Templates.ReadFile("templates/fstab.raspbian.tmpl")
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get fstab template: %w", err)
|
||||
}
|
||||
|
||||
// Parse template.
|
||||
t := template.Must(template.New("fstab").Parse(tmpl))
|
||||
t := template.Must(template.New("fstab").Parse(string(tmpl)))
|
||||
|
||||
// Open fstab.
|
||||
f, err := os.Create("/etc/fstab")
|
||||
@ -169,12 +213,16 @@ func Fstab(system string) error {
|
||||
|
||||
// Create and write.
|
||||
if err := t.Execute(f, struct {
|
||||
TimesyncUID string
|
||||
TimesyncGID string
|
||||
MopidyUID string
|
||||
MopidyGID string
|
||||
UpmpdcliUID string
|
||||
UpmpdcliGID string
|
||||
TimesyncUID string
|
||||
TimesyncGID string
|
||||
MopidyUID string
|
||||
MopidyGID string
|
||||
UpmpdcliUID string
|
||||
UpmpdcliGID string
|
||||
SnapserverUID string
|
||||
SnapserverGID string
|
||||
SnapclientUID string
|
||||
SnapclientGID string
|
||||
}{
|
||||
timesyncUser.Uid,
|
||||
timesyncGroup.Gid,
|
||||
@ -182,6 +230,10 @@ func Fstab(system string) error {
|
||||
mopidyGroup.Gid,
|
||||
upmpdcliUser.Uid,
|
||||
upmpdcliGroup.Gid,
|
||||
snapserverUser.Uid,
|
||||
snapserverGroup.Gid,
|
||||
snapclientUser.Uid,
|
||||
snapclientGroup.Gid,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("could not write templated fstab: %w", err)
|
||||
}
|
||||
@ -189,8 +241,8 @@ func Fstab(system string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemovePkgs removes not needed software in read-only mode.
|
||||
func RemovePkgs(system string) error {
|
||||
// removePkgs removes not needed software in read-only mode.
|
||||
func removePkgs(system string) error {
|
||||
logger := log.With().Str("stage", "RemovePkgs").Logger()
|
||||
if system != "raspbian" {
|
||||
logger.Info().Msg("nothing to do")
|
||||
@ -227,12 +279,17 @@ func RemovePkgs(system string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateUDEVrules() error {
|
||||
func udevRules() error {
|
||||
logger := log.With().Str("stage", "CreateUDEVrules").Logger()
|
||||
logger.Info().Msg("writing udev rule file")
|
||||
|
||||
// Parse template.
|
||||
t := template.Must(template.New("udev").Parse(assets.UDEVRules))
|
||||
tmpl, err := assets.Templates.ReadFile("templates/50-neuftech.rules.tmpl")
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get udev rules file: %w", err)
|
||||
}
|
||||
|
||||
t := template.Must(template.New("udev").Parse(string(tmpl)))
|
||||
|
||||
// Open file.
|
||||
f, err := os.Create("/etc/udev/rules.d/50-neuftech.rules")
|
||||
@ -253,8 +310,8 @@ func CreateUDEVrules() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateUser creates schnutibox system user and group.
|
||||
func CreateUser() error {
|
||||
// createUser creates schnutibox system user and group.
|
||||
func createUser() error {
|
||||
logger := log.With().Str("stage", "CreateUser").Logger()
|
||||
|
||||
cmd := exec.Command("adduser", "--system", "--group", "--no-create-home", schnutiboxUser)
|
||||
@ -267,9 +324,10 @@ func CreateUser() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateSymlinks creates all needed symlinks.
|
||||
func CreateSymlinks(system string) error {
|
||||
// symlinks creates all needed symlinks.
|
||||
func symlinks(system string) error {
|
||||
logger := log.With().Str("stage", "Symlinks").Logger()
|
||||
logger.Debug().Str("system", system).Msg("ignoring for now")
|
||||
|
||||
links := []struct {
|
||||
symlink string
|
||||
@ -339,7 +397,7 @@ func cmdlineTxt() error {
|
||||
newLine := strings.TrimSuffix(string(oldLine), "\n") + " " + "fastboot" + " " + "noswap"
|
||||
|
||||
// Write.
|
||||
// nolint:gosec
|
||||
// nolint:gosec,gomnd
|
||||
if err := ioutil.WriteFile("/boot/cmdline.txt", []byte(newLine), 0o644); err != nil {
|
||||
return fmt.Errorf("could not write cmdline.txt: %w", err)
|
||||
}
|
||||
@ -347,17 +405,17 @@ func cmdlineTxt() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// makeReadOnly executes stuff if a read-only system is wanted.
|
||||
func makeReadOnly(system string) error {
|
||||
if err := RemovePkgs(system); err != nil {
|
||||
// readOnly executes stuff if a read-only system is wanted.
|
||||
func readOnly(system string) error {
|
||||
if err := removePkgs(system); err != nil {
|
||||
return fmt.Errorf("could not remove pkgs: %w", err)
|
||||
}
|
||||
|
||||
if err := CreateSymlinks(system); err != nil {
|
||||
if err := symlinks(system); err != nil {
|
||||
return fmt.Errorf("could not create symlinks: %w", err)
|
||||
}
|
||||
|
||||
if err := Fstab(system); err != nil {
|
||||
if err := fstab(system); err != nil {
|
||||
return fmt.Errorf("could not create fstab: %w", err)
|
||||
}
|
||||
|
||||
@ -368,9 +426,9 @@ func makeReadOnly(system string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Mopidy setups mopidy.
|
||||
// mopidy setups mopidy.
|
||||
//nolint:funlen,cyclop
|
||||
func Mopidy() error {
|
||||
func mopidy() error {
|
||||
logger := log.With().Str("stage", "Mopidy").Logger()
|
||||
|
||||
// GPG Key.
|
||||
@ -412,6 +470,7 @@ func Mopidy() error {
|
||||
// Install.
|
||||
cmd = exec.Command(
|
||||
"apt-get", "install", "-y",
|
||||
"libgstreamer-plugins-bad1.0",
|
||||
"mopidy",
|
||||
"mopidy-alsamixer",
|
||||
"mopidy-mpd",
|
||||
@ -461,7 +520,12 @@ func Mopidy() error {
|
||||
Cfg.Spotify = true
|
||||
}
|
||||
|
||||
t := template.Must(template.New("mopidyConf").Parse(assets.MopidyConf))
|
||||
tmpl, err := assets.Templates.ReadFile("templates/mopidy.conf.tmpl")
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get mopidy.conf: %w", err)
|
||||
}
|
||||
|
||||
t := template.Must(template.New("mopidyConf").Parse(string(tmpl)))
|
||||
|
||||
f, err := os.Create("/etc/mopidy/mopidy.conf")
|
||||
if err != nil {
|
||||
@ -478,7 +542,7 @@ func Mopidy() error {
|
||||
|
||||
// Upmpdcli setups upmpdcli.
|
||||
//nolint:funlen
|
||||
func Upmpdcli() error {
|
||||
func upmpdcli() error {
|
||||
logger := log.With().Str("stage", "Upmpdcli").Logger()
|
||||
|
||||
// GPG Key.
|
||||
@ -548,20 +612,95 @@ func Upmpdcli() error {
|
||||
}
|
||||
|
||||
// Create config.
|
||||
// nolint:gosec
|
||||
if err := ioutil.WriteFile("/etc/upmpdcli.conf", assets.UpmpdcliConf, 0o644); err != nil {
|
||||
upmpdcliConf, err := assets.Files.ReadFile("files/upmpdcli.conf")
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get upmpdcli.conf: %w", err)
|
||||
}
|
||||
|
||||
// nolint:gosec,gomnd
|
||||
if err := ioutil.WriteFile("/etc/upmpdcli.conf", upmpdcliConf, 0o644); err != nil {
|
||||
return fmt.Errorf("could not copy upmpdcli config: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func SchnutiboxConfig() error {
|
||||
logger := log.With().Str("stage", "Upmpdcli").Logger()
|
||||
// nolint:funlen
|
||||
func snapcast() error {
|
||||
logger := log.With().Str("stage", "snapcast").Logger()
|
||||
|
||||
// Download deb.
|
||||
cmd := exec.Command(
|
||||
"wget",
|
||||
"https://github.com/badaix/snapcast/releases/download/v0.24.0/snapclient_0.24.0-1_without-pulse_armhf.deb",
|
||||
"-O", "/tmp/snapclient.deb",
|
||||
)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
logger.Debug().Str("cmd", cmd.String()).Msg("running")
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("could not download snapclient deb: %w", err)
|
||||
}
|
||||
|
||||
// Install deb
|
||||
cmd = exec.Command(
|
||||
"/bin/sh", "-c",
|
||||
"dpkg -i /tmp/snapclient.deb; apt --fix-broken install -y; rm /tmp/snapclient.deb",
|
||||
)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
logger.Debug().Str("cmd", cmd.String()).Msg("running")
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("could not install snapclient deb: %w", err)
|
||||
}
|
||||
|
||||
// Download deb.
|
||||
cmd = exec.Command(
|
||||
"wget",
|
||||
"https://github.com/badaix/snapcast/releases/download/v0.24.0/snapserver_0.24.0-1_armhf.deb",
|
||||
"-O", "/tmp/snapserver.deb",
|
||||
)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
logger.Debug().Str("cmd", cmd.String()).Msg("running")
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("could not download snapserver deb: %w", err)
|
||||
}
|
||||
|
||||
// Install deb
|
||||
cmd = exec.Command(
|
||||
"/bin/sh", "-c",
|
||||
"dpkg -i /tmp/snapserver.deb; apt --fix-broken install -y; rm /tmp/snapserver.deb",
|
||||
)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
logger.Debug().Str("cmd", cmd.String()).Msg("running")
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("could not install snapserver deb: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func schnutiboxConfig() error {
|
||||
logger := log.With().Str("stage", "schnutiboxConfig").Logger()
|
||||
logger.Info().Msg("writing schnutibox config")
|
||||
|
||||
// Parse template.
|
||||
t := template.Must(template.New("config").Parse(assets.SchnutiboxConfig))
|
||||
tmpl, err := assets.Templates.ReadFile("templates/schnutibox.yml.tmpl")
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get template: %w", err)
|
||||
}
|
||||
|
||||
t := template.Must(template.New("config").Parse(string(tmpl)))
|
||||
|
||||
// Open file.
|
||||
f, err := os.Create("/etc/schnutibox/schnutibox.yml")
|
||||
@ -582,38 +721,43 @@ func Run(cmd *cobra.Command, args []string) {
|
||||
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
||||
|
||||
// Install schnutibox service.
|
||||
if err := BoxService(serviceLocation+"/"+serviceFileName, true); err != nil {
|
||||
if err := boxService(serviceLocation+"/"+serviceFileName, true); err != nil {
|
||||
log.Fatal().Err(err).Msg("could not create schnutibox service")
|
||||
}
|
||||
|
||||
// Create schnutibox config.
|
||||
if err := SchnutiboxConfig(); err != nil {
|
||||
if err := schnutiboxConfig(); err != nil {
|
||||
log.Fatal().Err(err).Msg("could not create schnutibox config.")
|
||||
}
|
||||
|
||||
// Install udev file.
|
||||
if err := CreateUDEVrules(); err != nil {
|
||||
if err := udevRules(); err != nil {
|
||||
log.Fatal().Err(err).Msg("could not install udev rules")
|
||||
}
|
||||
|
||||
// Setup NTP.
|
||||
if err := NTP(); err != nil {
|
||||
if err := ntp(); err != nil {
|
||||
log.Fatal().Err(err).Msg("could not setup ntp")
|
||||
}
|
||||
|
||||
// Setup mopidy.
|
||||
if err := Mopidy(); err != nil {
|
||||
if err := mopidy(); err != nil {
|
||||
log.Fatal().Err(err).Msg("could not setup mopidy")
|
||||
}
|
||||
|
||||
// Setup upmpdcli.
|
||||
if err := Upmpdcli(); err != nil {
|
||||
if err := upmpdcli(); err != nil {
|
||||
log.Fatal().Err(err).Msg("could not setup upmpdcli")
|
||||
}
|
||||
|
||||
// Setup snapcast.
|
||||
if err := snapcast(); err != nil {
|
||||
log.Fatal().Err(err).Msg("could not setup snapclient")
|
||||
}
|
||||
|
||||
// Making system read-only.
|
||||
if Cfg.ReadOnly {
|
||||
if err := makeReadOnly(Cfg.System); err != nil {
|
||||
if err := readOnly(Cfg.System); err != nil {
|
||||
log.Fatal().Err(err).Msg("could not make system read-only")
|
||||
}
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ func (r *RFID) Run() error {
|
||||
}
|
||||
|
||||
go func() {
|
||||
buf := make([]byte, 3)
|
||||
buf := make([]byte, 3) // nolint:gomnd
|
||||
|
||||
rfid := ""
|
||||
|
||||
|
178
pkg/run/run.go
178
pkg/run/run.go
@ -1,77 +1,16 @@
|
||||
//nolint:wrapcheck
|
||||
package run
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/fhs/gompd/v2/mpd"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"go.xsfx.dev/schnutibox/internal/config"
|
||||
"go.xsfx.dev/schnutibox/internal/metrics"
|
||||
"go.xsfx.dev/schnutibox/pkg/mpc"
|
||||
"go.xsfx.dev/schnutibox/pkg/rfid"
|
||||
"go.xsfx.dev/schnutibox/pkg/watcher"
|
||||
"go.xsfx.dev/schnutibox/pkg/web"
|
||||
)
|
||||
|
||||
type mpc struct {
|
||||
conn *mpd.Client
|
||||
}
|
||||
|
||||
func newMpc(conn *mpd.Client) *mpc {
|
||||
return &mpc{conn}
|
||||
}
|
||||
|
||||
func (m *mpc) stop(logger zerolog.Logger) error {
|
||||
logger.Info().Msg("trying to stop playback")
|
||||
|
||||
return m.conn.Stop()
|
||||
}
|
||||
|
||||
func (m *mpc) clear(logger zerolog.Logger) error {
|
||||
logger.Info().Msg("trying to clear playlist")
|
||||
|
||||
return m.conn.Clear()
|
||||
}
|
||||
|
||||
func (m *mpc) play(logger zerolog.Logger, rfid string, name string, uris []string) error {
|
||||
logger.Info().Msg("trying to add tracks")
|
||||
|
||||
// Metric labels.
|
||||
mLabels := []string{rfid, name}
|
||||
|
||||
// Stop playing track.
|
||||
if err := m.stop(logger); err != nil {
|
||||
metrics.BoxErrors.Inc()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Clear playlist.
|
||||
if err := m.clear(logger); err != nil {
|
||||
metrics.BoxErrors.Inc()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Adding every single uri to playlist
|
||||
for _, i := range uris {
|
||||
logger.Debug().Str("uri", i).Msg("add track")
|
||||
|
||||
if err := m.conn.Add(i); err != nil {
|
||||
metrics.BoxErrors.Inc()
|
||||
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
metrics.TracksPlayed.WithLabelValues(mLabels...).Inc()
|
||||
|
||||
return m.conn.Play(-1)
|
||||
}
|
||||
|
||||
//nolint:funlen
|
||||
func Run(cmd *cobra.Command, args []string) {
|
||||
log.Info().Msg("starting the RFID reader")
|
||||
|
||||
@ -79,65 +18,58 @@ func Run(cmd *cobra.Command, args []string) {
|
||||
r := rfid.NewRFID(config.Cfg, idChan)
|
||||
|
||||
if err := r.Run(); err != nil {
|
||||
log.Fatal().Err(err).Msg("could not start RFID reader")
|
||||
}
|
||||
|
||||
go func() {
|
||||
var id string
|
||||
|
||||
for {
|
||||
// Wating for a scanned tag.
|
||||
id = <-idChan
|
||||
logger := log.With().Str("id", id).Logger()
|
||||
logger.Info().Msg("received id")
|
||||
|
||||
// Create MPD connection on every received event.
|
||||
c, err := mpd.Dial("tcp", fmt.Sprintf("%s:%d", config.Cfg.MPD.Hostname, config.Cfg.MPD.Port))
|
||||
if err != nil {
|
||||
logger.Error().Err(err).Msg("could not connect to MPD server")
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
m := newMpc(c)
|
||||
|
||||
// Check of stop tag was detected.
|
||||
if id == config.Cfg.Meta.Stop {
|
||||
logger.Info().Msg("stopping")
|
||||
|
||||
if err := m.stop(logger); err != nil {
|
||||
logger.Error().Err(err).Msg("could not stop")
|
||||
}
|
||||
|
||||
if err := m.clear(logger); err != nil {
|
||||
logger.Error().Err(err).Msg("could not clear")
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Check if there is a track for the ID.
|
||||
tracks, ok := config.Cfg.Tracks[id]
|
||||
if !ok {
|
||||
logger.Error().Msg("could not find track for ID")
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Try to play track.
|
||||
if err := m.play(logger, id, tracks.Name, tracks.URIS); err != nil {
|
||||
logger.Error().Err(err).Msg("could not play track")
|
||||
}
|
||||
if !viper.GetBool("reader.ignore") {
|
||||
log.Fatal().Err(err).Msg("could not start RFID reader")
|
||||
}
|
||||
}()
|
||||
|
||||
l := fmt.Sprintf("%s:%d", config.Cfg.Box.Hostname, config.Cfg.Box.Port)
|
||||
|
||||
http.Handle("/metrics", promhttp.Handler())
|
||||
|
||||
log.Info().Msgf("serving on %s...", l)
|
||||
|
||||
if err := http.ListenAndServe(l, nil); err != nil {
|
||||
log.Fatal().Err(err).Msg("")
|
||||
log.Warn().Err(err).Msg("could not start RFID reader. ignoring...")
|
||||
}
|
||||
|
||||
// Stating watcher.
|
||||
watcher.Run()
|
||||
|
||||
// nolint:nestif
|
||||
if !viper.GetBool("reader.ignore") {
|
||||
go func() {
|
||||
var id string
|
||||
|
||||
for {
|
||||
// Wating for a scanned tag.
|
||||
id = <-idChan
|
||||
logger := log.With().Str("id", id).Logger()
|
||||
logger.Info().Msg("received id")
|
||||
|
||||
// Check of stop tag was detected.
|
||||
if id == config.Cfg.Meta.Stop {
|
||||
logger.Info().Msg("stopping")
|
||||
|
||||
if err := mpc.Stop(logger); err != nil {
|
||||
logger.Error().Err(err).Msg("could not stop")
|
||||
}
|
||||
|
||||
if err := mpc.Clear(logger); err != nil {
|
||||
logger.Error().Err(err).Msg("could not clear")
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Check if there is a track for the ID.
|
||||
tracks, ok := config.Cfg.Tracks[id]
|
||||
if !ok {
|
||||
logger.Error().Msg("could not find track for ID")
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Try to play track.
|
||||
if err := mpc.Play(logger, id, tracks.Name, tracks.Uris); err != nil {
|
||||
logger.Error().Err(err).Msg("could not play track")
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Running web interface. Blocking.
|
||||
web.Run(cmd, args)
|
||||
}
|
||||
|
@ -1,20 +1,73 @@
|
||||
// package sselog is work in progress to implement a writer that sends its logs
|
||||
// to a http server side event.
|
||||
// nolint:gochecknoglobals,godox
|
||||
package sselog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"go.xsfx.dev/logginghandler"
|
||||
)
|
||||
|
||||
// Log is the global sse logger struct.
|
||||
var Log *SSELog
|
||||
|
||||
type SSELog struct {
|
||||
LogChan chan []byte
|
||||
Receivers []chan string
|
||||
Receivers map[chan []byte]struct{}
|
||||
}
|
||||
|
||||
func NewSSELog() *SSELog {
|
||||
return &SSELog{
|
||||
Receivers: make(map[chan []byte]struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
func (l SSELog) Write(p []byte) (n int, err error) {
|
||||
wCount := 0
|
||||
// Send log message to all receiver channels.
|
||||
for _, i := range l.Receivers {
|
||||
i <- string(p)
|
||||
|
||||
wCount = +len(p)
|
||||
for r := range l.Receivers {
|
||||
r <- p
|
||||
}
|
||||
|
||||
return wCount, nil
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func LogHandler(w http.ResponseWriter, r *http.Request) {
|
||||
logger := logginghandler.Logger(r)
|
||||
|
||||
logger.Info().Msg("registering a new sse logger")
|
||||
|
||||
flusher, ok := w.(http.Flusher)
|
||||
if !ok {
|
||||
logger.Error().Msg("streaming unsupported")
|
||||
http.Error(w, "streaming unsupported", http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "text/event-stream")
|
||||
w.Header().Set("Cache-Control", "no-cache")
|
||||
w.Header().Set("Connection", "keep-alive")
|
||||
// TODO: has to be something else!
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
|
||||
cChan := make(chan []byte)
|
||||
|
||||
Log.Receivers[cChan] = struct{}{}
|
||||
|
||||
for {
|
||||
select {
|
||||
case e := <-cChan:
|
||||
// Send event to client.
|
||||
fmt.Fprintf(w, "data: %s\n\n", e)
|
||||
|
||||
// Send it right now and not buffering it.
|
||||
flusher.Flush()
|
||||
case <-r.Context().Done():
|
||||
close(cChan)
|
||||
delete(Log.Receivers, cChan)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
79
pkg/timer/timer.go
Normal file
79
pkg/timer/timer.go
Normal file
@ -0,0 +1,79 @@
|
||||
package timer
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/golang/protobuf/ptypes/duration"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"go.xsfx.dev/schnutibox/internal/config"
|
||||
"go.xsfx.dev/schnutibox/internal/grpcclient"
|
||||
api "go.xsfx.dev/schnutibox/pkg/api/v1"
|
||||
"go.xsfx.dev/schnutibox/pkg/mpc"
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
)
|
||||
|
||||
// T is the global Timer object.
|
||||
// nolint:gochecknoglobals
|
||||
var T = &Timer{}
|
||||
|
||||
type Timer struct {
|
||||
Req *api.Timer
|
||||
}
|
||||
|
||||
func (t *Timer) Handle() {
|
||||
if t.Req != nil {
|
||||
// Initialize the current object.
|
||||
if t.Req.Current == nil {
|
||||
t.Req.Current = &duration.Duration{}
|
||||
t.Req.Current.Seconds = t.Req.Duration.Seconds
|
||||
}
|
||||
|
||||
switch {
|
||||
// There is some timing going on.
|
||||
case t.Req.Duration.Seconds != 0 && t.Req.Current.Seconds != 0:
|
||||
log.Debug().
|
||||
Int64("current", t.Req.Current.Seconds).
|
||||
Int64("duration", t.Req.Duration.Seconds).
|
||||
Msg("timer is running")
|
||||
|
||||
if t.Req.Current.Seconds > 0 {
|
||||
t.Req.Current.Seconds--
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// No timer is running... so setting the duration to 0.
|
||||
case t.Req.Current.Seconds == 0 && t.Req.Duration.Seconds != 0:
|
||||
log.Debug().Msg("stoping timer")
|
||||
|
||||
if err := mpc.Stop(log.Logger); err != nil {
|
||||
log.Error().Err(err).Msg("could not stop")
|
||||
}
|
||||
|
||||
t.Req.Duration.Seconds = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Run is the command line interface for triggering the timer.
|
||||
func Run(cmd *cobra.Command, args []string) {
|
||||
conn, err := grpcclient.Conn(config.Cfg.Web.Hostname, config.Cfg.Web.Port)
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("could not connect")
|
||||
}
|
||||
|
||||
c := api.NewTimerServiceClient(conn)
|
||||
|
||||
d := durationpb.New(viper.GetDuration("timer.duration"))
|
||||
|
||||
_, err = c.Create(context.Background(), &api.Timer{Duration: d})
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
log.Fatal().Err(err).Msg("could not create timer")
|
||||
}
|
||||
|
||||
conn.Close()
|
||||
log.Info().Msg("added timer")
|
||||
}
|
75
pkg/watcher/watcher.go
Normal file
75
pkg/watcher/watcher.go
Normal file
@ -0,0 +1,75 @@
|
||||
package watcher
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
"go.xsfx.dev/schnutibox/internal/metrics"
|
||||
"go.xsfx.dev/schnutibox/pkg/currentsong"
|
||||
"go.xsfx.dev/schnutibox/pkg/mpc"
|
||||
"go.xsfx.dev/schnutibox/pkg/timer"
|
||||
)
|
||||
|
||||
const tickerTime = time.Second
|
||||
|
||||
// Run runs actions after tickerTime is over, over again and again.
|
||||
// Right now its mostly used for setting metrics.
|
||||
func Run() {
|
||||
log.Debug().Msg("starting watch")
|
||||
|
||||
ticker := time.NewTicker(tickerTime)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
<-ticker.C
|
||||
|
||||
// Timer.
|
||||
go timer.T.Handle()
|
||||
|
||||
// Metrics.
|
||||
go func() {
|
||||
m, err := mpc.Conn()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("could not connect")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
uris, err := mpc.PlaylistURIS(m)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("could not get playlist uris")
|
||||
metrics.BoxErrors.Inc()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Gettings MPD state.
|
||||
s, err := m.Status()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("could not get status")
|
||||
metrics.BoxErrors.Inc()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
currentSong, err := m.CurrentSong()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("could not get current song")
|
||||
metrics.BoxErrors.Inc()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if len(currentSong) != 0 {
|
||||
currentsong.Write(fmt.Sprintf("%s - %s", currentSong["Artist"], currentSong["Track"]))
|
||||
} else {
|
||||
currentsong.Write("")
|
||||
}
|
||||
|
||||
// Sets the metrics.
|
||||
metrics.Set(uris, s["state"])
|
||||
}()
|
||||
}
|
||||
}()
|
||||
}
|
45
pkg/web/timer_test.go
Normal file
45
pkg/web/timer_test.go
Normal file
@ -0,0 +1,45 @@
|
||||
package web_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
api "go.xsfx.dev/schnutibox/pkg/api/v1"
|
||||
"go.xsfx.dev/schnutibox/pkg/web"
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
)
|
||||
|
||||
func TestTimerService(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tables := []struct {
|
||||
name string
|
||||
req *api.Timer
|
||||
expected *api.Timer
|
||||
err error
|
||||
}{
|
||||
{
|
||||
"10 seconds",
|
||||
&api.Timer{Duration: &durationpb.Duration{Seconds: 10}},
|
||||
&api.Timer{Duration: &durationpb.Duration{Seconds: 10}},
|
||||
nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, table := range tables {
|
||||
table := table
|
||||
t.Run(table.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
require := require.New(t)
|
||||
ctx := context.Background()
|
||||
timerSvc := web.TimerServer{}
|
||||
resp, err := timerSvc.Create(ctx, &api.Timer{Duration: &durationpb.Duration{Seconds: 10}})
|
||||
if table.err == nil {
|
||||
require.NoError(err)
|
||||
}
|
||||
|
||||
require.Equal(table.expected, resp)
|
||||
})
|
||||
}
|
||||
}
|
172
pkg/web/web.go
Normal file
172
pkg/web/web.go
Normal file
@ -0,0 +1,172 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"net/http/pprof"
|
||||
"strings"
|
||||
|
||||
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||
zerolog "github.com/philip-bui/grpc-zerolog"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/cobra"
|
||||
"go.xsfx.dev/logginghandler"
|
||||
assets "go.xsfx.dev/schnutibox/assets/web"
|
||||
"go.xsfx.dev/schnutibox/internal/config"
|
||||
api "go.xsfx.dev/schnutibox/pkg/api/v1"
|
||||
"go.xsfx.dev/schnutibox/pkg/currentsong"
|
||||
"go.xsfx.dev/schnutibox/pkg/sselog"
|
||||
"go.xsfx.dev/schnutibox/pkg/timer"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/h2c"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/reflection"
|
||||
)
|
||||
|
||||
func root(w http.ResponseWriter, r *http.Request) {
|
||||
logger := logginghandler.Logger(r)
|
||||
|
||||
t, err := template.ParseFS(assets.Templates, "templates/index.html.tmpl")
|
||||
if err != nil {
|
||||
logger.Error().Err(err).Msg("could not parse template")
|
||||
http.Error(w, "could not parse template", http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if err := t.Execute(w, struct{}{}); err != nil {
|
||||
logger.Error().Err(err).Msg("could not execute template")
|
||||
http.Error(w, "could not execute template", http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// grpcHandlerFunc reads header and returns a grpc handler or a http one.
|
||||
// nolint:interfacer
|
||||
func grpcHandlerFunc(grpcServer *grpc.Server, otherHandler http.Handler) http.Handler {
|
||||
return h2c.NewHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.ProtoMajor == 2 && strings.Contains(r.Header.Get("Content-Type"), "application/grpc") {
|
||||
grpcServer.ServeHTTP(w, r)
|
||||
} else {
|
||||
otherHandler.ServeHTTP(w, r)
|
||||
}
|
||||
}), &http2.Server{})
|
||||
}
|
||||
|
||||
type identifyServer struct{}
|
||||
|
||||
// Identify searches in tracks config for entries and returns them.
|
||||
// nolint:goerr113
|
||||
func (i identifyServer) Identify(ctx context.Context, in *api.IdentifyRequest) (*api.IdentifyResponse, error) {
|
||||
r := &api.IdentifyResponse{}
|
||||
|
||||
if in.Id == "" {
|
||||
return r, fmt.Errorf("no id in request specified")
|
||||
}
|
||||
|
||||
t, ok := config.Cfg.Tracks[in.Id]
|
||||
if !ok {
|
||||
return r, fmt.Errorf("could not find track for id: %s", in.Id)
|
||||
}
|
||||
|
||||
r.Name = t.Name
|
||||
r.Uris = t.Uris
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
type TimerServer struct{}
|
||||
|
||||
func (t TimerServer) Create(ctx context.Context, req *api.Timer) (*api.Timer, error) {
|
||||
timer.T.Req = req
|
||||
|
||||
return timer.T.Req, nil
|
||||
}
|
||||
|
||||
// Get just returns the status of the timer.
|
||||
func (t TimerServer) Get(ctx context.Context, req *api.TimerEmpty) (*api.Timer, error) {
|
||||
// Nothing there yet, so return a fresh struct.
|
||||
if timer.T.Req == nil {
|
||||
return &api.Timer{}, nil
|
||||
}
|
||||
|
||||
return timer.T.Req, nil
|
||||
}
|
||||
|
||||
func currentSong(w http.ResponseWriter, r *http.Request) {}
|
||||
|
||||
func gw(s *grpc.Server, conn string) *runtime.ServeMux {
|
||||
ctx := context.Background()
|
||||
gopts := []grpc.DialOption{grpc.WithInsecure()}
|
||||
|
||||
api.RegisterIdentifierServiceServer(s, identifyServer{})
|
||||
api.RegisterTimerServiceServer(s, TimerServer{})
|
||||
|
||||
// Adds reflections.
|
||||
reflection.Register(s)
|
||||
|
||||
gwmux := runtime.NewServeMux()
|
||||
if err := api.RegisterIdentifierServiceHandlerFromEndpoint(ctx, gwmux, conn, gopts); err != nil {
|
||||
log.Fatal().Err(err).Msg("could not register grpc endpoint")
|
||||
}
|
||||
|
||||
if err := api.RegisterTimerServiceHandlerFromEndpoint(ctx, gwmux, conn, gopts); err != nil {
|
||||
log.Fatal().Err(err).Msg("could not register grpc endpoint")
|
||||
}
|
||||
|
||||
return gwmux
|
||||
}
|
||||
|
||||
func Run(command *cobra.Command, args []string) {
|
||||
// Create host string for serving web.
|
||||
lh := fmt.Sprintf("%s:%d", config.Cfg.Web.Hostname, config.Cfg.Web.Port)
|
||||
|
||||
// Create grpc server.
|
||||
grpcServer := grpc.NewServer(
|
||||
zerolog.UnaryInterceptor(),
|
||||
)
|
||||
|
||||
// Define http handlers.
|
||||
mux := http.NewServeMux()
|
||||
|
||||
mux.Handle("/", http.HandlerFunc(root))
|
||||
|
||||
mux.Handle("/log", http.HandlerFunc(sselog.LogHandler))
|
||||
mux.Handle("/currentsong", http.HandlerFunc(currentsong.Handler))
|
||||
|
||||
mux.Handle(
|
||||
"/static/",
|
||||
http.StripPrefix("/static/", http.FileServer(assets.Files)),
|
||||
)
|
||||
|
||||
mux.Handle(
|
||||
"/swagger-ui/",
|
||||
http.StripPrefix("/swagger-ui/", http.FileServer(assets.SwaggerUI)),
|
||||
)
|
||||
|
||||
mux.Handle("/metrics", promhttp.Handler())
|
||||
|
||||
mux.Handle("/api/", gw(grpcServer, lh))
|
||||
|
||||
// PPROF.
|
||||
if config.Cfg.Debug.PPROF {
|
||||
mux.HandleFunc("/debug/pprof/", pprof.Index)
|
||||
}
|
||||
|
||||
// Serving http.
|
||||
log.Info().Msgf("serving HTTP on %s...", lh)
|
||||
|
||||
log.Fatal().Err(
|
||||
http.ListenAndServe(
|
||||
lh,
|
||||
grpcHandlerFunc(
|
||||
grpcServer,
|
||||
logginghandler.Handler(mux),
|
||||
),
|
||||
),
|
||||
).Msg("goodbye")
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -ex
|
||||
|
||||
if [ -z "$RASPBIAN_IMAGE" ]; then
|
||||
echo "missing \$RASPBIAN_IMAGE environment variable"
|
||||
exit 1
|
||||
fi
|
||||
imagePath=$RASPBIAN_IMAGE
|
||||
|
||||
# resize partition
|
||||
truncate -s +3G "$imagePath"
|
||||
parted "$imagePath" resizepart 2 3G
|
||||
|
||||
# create loop devices
|
||||
bootLoopDevice="$(kpartx -l "$imagePath" | sed -n 1p | awk '{print $1}')"
|
||||
systemLoopDevice="$(kpartx -l "$imagePath" | sed -n 2p | awk '{print $1}')"
|
||||
|
||||
if [ -z "$bootLoopDevice" ] || [ -z "$systemLoopDevice" ]; then
|
||||
echo "could not extract loop devices"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
kpartx -avs "$imagePath"
|
||||
|
||||
# resize filesystem
|
||||
resize2fs "/dev/mapper/${systemLoopDevice}"
|
||||
|
||||
# enable ssh
|
||||
mkdir -p boot
|
||||
mount -o loop "/dev/mapper/${bootLoopDevice}" boot
|
||||
touch boot/ssh
|
||||
|
||||
# cleaning up
|
||||
umount boot
|
||||
kpartx -d "$imagePath"
|
||||
rm -rf boot
|
3
scripts/putio/main.go
Normal file
3
scripts/putio/main.go
Normal file
@ -0,0 +1,3 @@
|
||||
package main
|
||||
|
||||
func main() {}
|
54
scripts/rpi-image-test/build.sh
Executable file
54
scripts/rpi-image-test/build.sh
Executable file
@ -0,0 +1,54 @@
|
||||
#!/bin/sh -eux
|
||||
|
||||
set -ex
|
||||
|
||||
RASPBIAN_IMAGE=2021-05-07-raspios-buster-armhf-lite.img
|
||||
|
||||
# prepare
|
||||
# =======
|
||||
mkdir /SWAP
|
||||
mount -t 9p -o trans=virtio,version=9p2000.L host0 /SWAP
|
||||
|
||||
echo "http://dl-cdn.alpinelinux.org/alpine/v3.13/community/" >>/etc/apk/repositories
|
||||
apk add aria2 coreutils e2fsprogs-extra parted util-linux multipath-tools
|
||||
|
||||
cd /SWAP
|
||||
|
||||
aria2c --seed-time=0 https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-05-28/2021-05-07-raspios-buster-armhf-lite.zip.torrent
|
||||
unzip 2021-05-07-raspios-buster-armhf-lite.zip
|
||||
|
||||
rm 2021-05-07-raspios-buster-armhf-lite.zip*
|
||||
|
||||
# building
|
||||
# ========
|
||||
imagePath=$RASPBIAN_IMAGE
|
||||
|
||||
# resize partition
|
||||
truncate -s +5G "$imagePath"
|
||||
parted "$imagePath" resizepart 2 5G
|
||||
|
||||
# create loop devices
|
||||
kpartx -avs "$imagePath"
|
||||
|
||||
ls -la /dev/mapper
|
||||
|
||||
bootLoopDevice="$(find /dev/mapper -name 'loop*p1')"
|
||||
systemLoopDevice="$(find /dev/mapper -name 'loop*p2')"
|
||||
|
||||
if [ -z "$bootLoopDevice" ] || [ -z "$systemLoopDevice" ]; then
|
||||
echo "could not extract loop devices"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# resize filesystem
|
||||
resize2fs "$systemLoopDevice"
|
||||
|
||||
# enable ssh
|
||||
mkdir -p boot
|
||||
mount "$bootLoopDevice" boot
|
||||
touch boot/ssh
|
||||
|
||||
# cleaning up
|
||||
umount boot
|
||||
kpartx -d "$imagePath"
|
||||
rm -rf boot
|
14
tools.go
Normal file
14
tools.go
Normal file
@ -0,0 +1,14 @@
|
||||
// +build tools
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "github.com/bufbuild/buf/cmd/buf"
|
||||
_ "github.com/bufbuild/buf/cmd/protoc-gen-buf-breaking"
|
||||
_ "github.com/bufbuild/buf/cmd/protoc-gen-buf-lint"
|
||||
_ "github.com/cosmtrek/air"
|
||||
_ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway"
|
||||
_ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2"
|
||||
_ "google.golang.org/grpc/cmd/protoc-gen-go-grpc"
|
||||
_ "google.golang.org/protobuf/cmd/protoc-gen-go"
|
||||
)
|
20
vendor/github.com/bgentry/go-netrc/LICENSE
generated
vendored
Normal file
20
vendor/github.com/bgentry/go-netrc/LICENSE
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
Original version Copyright © 2010 Fazlul Shahriar <fshahriar@gmail.com>. Newer
|
||||
portions Copyright © 2014 Blake Gentry <blakesgentry@gmail.com>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
510
vendor/github.com/bgentry/go-netrc/netrc/netrc.go
generated
vendored
Normal file
510
vendor/github.com/bgentry/go-netrc/netrc/netrc.go
generated
vendored
Normal file
@ -0,0 +1,510 @@
|
||||
package netrc
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type tkType int
|
||||
|
||||
const (
|
||||
tkMachine tkType = iota
|
||||
tkDefault
|
||||
tkLogin
|
||||
tkPassword
|
||||
tkAccount
|
||||
tkMacdef
|
||||
tkComment
|
||||
tkWhitespace
|
||||
)
|
||||
|
||||
var keywords = map[string]tkType{
|
||||
"machine": tkMachine,
|
||||
"default": tkDefault,
|
||||
"login": tkLogin,
|
||||
"password": tkPassword,
|
||||
"account": tkAccount,
|
||||
"macdef": tkMacdef,
|
||||
"#": tkComment,
|
||||
}
|
||||
|
||||
type Netrc struct {
|
||||
tokens []*token
|
||||
machines []*Machine
|
||||
macros Macros
|
||||
updateLock sync.Mutex
|
||||
}
|
||||
|
||||
// FindMachine returns the Machine in n named by name. If a machine named by
|
||||
// name exists, it is returned. If no Machine with name name is found and there
|
||||
// is a ``default'' machine, the ``default'' machine is returned. Otherwise, nil
|
||||
// is returned.
|
||||
func (n *Netrc) FindMachine(name string) (m *Machine) {
|
||||
// TODO(bgentry): not safe for concurrency
|
||||
var def *Machine
|
||||
for _, m = range n.machines {
|
||||
if m.Name == name {
|
||||
return m
|
||||
}
|
||||
if m.IsDefault() {
|
||||
def = m
|
||||
}
|
||||
}
|
||||
if def == nil {
|
||||
return nil
|
||||
}
|
||||
return def
|
||||
}
|
||||
|
||||
// MarshalText implements the encoding.TextMarshaler interface to encode a
|
||||
// Netrc into text format.
|
||||
func (n *Netrc) MarshalText() (text []byte, err error) {
|
||||
// TODO(bgentry): not safe for concurrency
|
||||
for i := range n.tokens {
|
||||
switch n.tokens[i].kind {
|
||||
case tkComment, tkDefault, tkWhitespace: // always append these types
|
||||
text = append(text, n.tokens[i].rawkind...)
|
||||
default:
|
||||
if n.tokens[i].value != "" { // skip empty-value tokens
|
||||
text = append(text, n.tokens[i].rawkind...)
|
||||
}
|
||||
}
|
||||
if n.tokens[i].kind == tkMacdef {
|
||||
text = append(text, ' ')
|
||||
text = append(text, n.tokens[i].macroName...)
|
||||
}
|
||||
text = append(text, n.tokens[i].rawvalue...)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (n *Netrc) NewMachine(name, login, password, account string) *Machine {
|
||||
n.updateLock.Lock()
|
||||
defer n.updateLock.Unlock()
|
||||
|
||||
prefix := "\n"
|
||||
if len(n.tokens) == 0 {
|
||||
prefix = ""
|
||||
}
|
||||
m := &Machine{
|
||||
Name: name,
|
||||
Login: login,
|
||||
Password: password,
|
||||
Account: account,
|
||||
|
||||
nametoken: &token{
|
||||
kind: tkMachine,
|
||||
rawkind: []byte(prefix + "machine"),
|
||||
value: name,
|
||||
rawvalue: []byte(" " + name),
|
||||
},
|
||||
logintoken: &token{
|
||||
kind: tkLogin,
|
||||
rawkind: []byte("\n\tlogin"),
|
||||
value: login,
|
||||
rawvalue: []byte(" " + login),
|
||||
},
|
||||
passtoken: &token{
|
||||
kind: tkPassword,
|
||||
rawkind: []byte("\n\tpassword"),
|
||||
value: password,
|
||||
rawvalue: []byte(" " + password),
|
||||
},
|
||||
accounttoken: &token{
|
||||
kind: tkAccount,
|
||||
rawkind: []byte("\n\taccount"),
|
||||
value: account,
|
||||
rawvalue: []byte(" " + account),
|
||||
},
|
||||
}
|
||||
n.insertMachineTokensBeforeDefault(m)
|
||||
for i := range n.machines {
|
||||
if n.machines[i].IsDefault() {
|
||||
n.machines = append(append(n.machines[:i], m), n.machines[i:]...)
|
||||
return m
|
||||
}
|
||||
}
|
||||
n.machines = append(n.machines, m)
|
||||
return m
|
||||
}
|
||||
|
||||
func (n *Netrc) insertMachineTokensBeforeDefault(m *Machine) {
|
||||
newtokens := []*token{m.nametoken}
|
||||
if m.logintoken.value != "" {
|
||||
newtokens = append(newtokens, m.logintoken)
|
||||
}
|
||||
if m.passtoken.value != "" {
|
||||
newtokens = append(newtokens, m.passtoken)
|
||||
}
|
||||
if m.accounttoken.value != "" {
|
||||
newtokens = append(newtokens, m.accounttoken)
|
||||
}
|
||||
for i := range n.tokens {
|
||||
if n.tokens[i].kind == tkDefault {
|
||||
// found the default, now insert tokens before it
|
||||
n.tokens = append(n.tokens[:i], append(newtokens, n.tokens[i:]...)...)
|
||||
return
|
||||
}
|
||||
}
|
||||
// didn't find a default, just add the newtokens to the end
|
||||
n.tokens = append(n.tokens, newtokens...)
|
||||
return
|
||||
}
|
||||
|
||||
func (n *Netrc) RemoveMachine(name string) {
|
||||
n.updateLock.Lock()
|
||||
defer n.updateLock.Unlock()
|
||||
|
||||
for i := range n.machines {
|
||||
if n.machines[i] != nil && n.machines[i].Name == name {
|
||||
m := n.machines[i]
|
||||
for _, t := range []*token{
|
||||
m.nametoken, m.logintoken, m.passtoken, m.accounttoken,
|
||||
} {
|
||||
n.removeToken(t)
|
||||
}
|
||||
n.machines = append(n.machines[:i], n.machines[i+1:]...)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Netrc) removeToken(t *token) {
|
||||
if t != nil {
|
||||
for i := range n.tokens {
|
||||
if n.tokens[i] == t {
|
||||
n.tokens = append(n.tokens[:i], n.tokens[i+1:]...)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Machine contains information about a remote machine.
|
||||
type Machine struct {
|
||||
Name string
|
||||
Login string
|
||||
Password string
|
||||
Account string
|
||||
|
||||
nametoken *token
|
||||
logintoken *token
|
||||
passtoken *token
|
||||
accounttoken *token
|
||||
}
|
||||
|
||||
// IsDefault returns true if the machine is a "default" token, denoted by an
|
||||
// empty name.
|
||||
func (m *Machine) IsDefault() bool {
|
||||
return m.Name == ""
|
||||
}
|
||||
|
||||
// UpdatePassword sets the password for the Machine m.
|
||||
func (m *Machine) UpdatePassword(newpass string) {
|
||||
m.Password = newpass
|
||||
updateTokenValue(m.passtoken, newpass)
|
||||
}
|
||||
|
||||
// UpdateLogin sets the login for the Machine m.
|
||||
func (m *Machine) UpdateLogin(newlogin string) {
|
||||
m.Login = newlogin
|
||||
updateTokenValue(m.logintoken, newlogin)
|
||||
}
|
||||
|
||||
// UpdateAccount sets the login for the Machine m.
|
||||
func (m *Machine) UpdateAccount(newaccount string) {
|
||||
m.Account = newaccount
|
||||
updateTokenValue(m.accounttoken, newaccount)
|
||||
}
|
||||
|
||||
func updateTokenValue(t *token, value string) {
|
||||
oldvalue := t.value
|
||||
t.value = value
|
||||
newraw := make([]byte, len(t.rawvalue))
|
||||
copy(newraw, t.rawvalue)
|
||||
t.rawvalue = append(
|
||||
bytes.TrimSuffix(newraw, []byte(oldvalue)),
|
||||
[]byte(value)...,
|
||||
)
|
||||
}
|
||||
|
||||
// Macros contains all the macro definitions in a netrc file.
|
||||
type Macros map[string]string
|
||||
|
||||
type token struct {
|
||||
kind tkType
|
||||
macroName string
|
||||
value string
|
||||
rawkind []byte
|
||||
rawvalue []byte
|
||||
}
|
||||
|
||||
// Error represents a netrc file parse error.
|
||||
type Error struct {
|
||||
LineNum int // Line number
|
||||
Msg string // Error message
|
||||
}
|
||||
|
||||
// Error returns a string representation of error e.
|
||||
func (e *Error) Error() string {
|
||||
return fmt.Sprintf("line %d: %s", e.LineNum, e.Msg)
|
||||
}
|
||||
|
||||
func (e *Error) BadDefaultOrder() bool {
|
||||
return e.Msg == errBadDefaultOrder
|
||||
}
|
||||
|
||||
const errBadDefaultOrder = "default token must appear after all machine tokens"
|
||||
|
||||
// scanLinesKeepPrefix is a split function for a Scanner that returns each line
|
||||
// of text. The returned token may include newlines if they are before the
|
||||
// first non-space character. The returned line may be empty. The end-of-line
|
||||
// marker is one optional carriage return followed by one mandatory newline. In
|
||||
// regular expression notation, it is `\r?\n`. The last non-empty line of
|
||||
// input will be returned even if it has no newline.
|
||||
func scanLinesKeepPrefix(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||
if atEOF && len(data) == 0 {
|
||||
return 0, nil, nil
|
||||
}
|
||||
// Skip leading spaces.
|
||||
start := 0
|
||||
for width := 0; start < len(data); start += width {
|
||||
var r rune
|
||||
r, width = utf8.DecodeRune(data[start:])
|
||||
if !unicode.IsSpace(r) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if i := bytes.IndexByte(data[start:], '\n'); i >= 0 {
|
||||
// We have a full newline-terminated line.
|
||||
return start + i, data[0 : start+i], nil
|
||||
}
|
||||
// If we're at EOF, we have a final, non-terminated line. Return it.
|
||||
if atEOF {
|
||||
return len(data), data, nil
|
||||
}
|
||||
// Request more data.
|
||||
return 0, nil, nil
|
||||
}
|
||||
|
||||
// scanWordsKeepPrefix is a split function for a Scanner that returns each
|
||||
// space-separated word of text, with prefixing spaces included. It will never
|
||||
// return an empty string. The definition of space is set by unicode.IsSpace.
|
||||
//
|
||||
// Adapted from bufio.ScanWords().
|
||||
func scanTokensKeepPrefix(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||
// Skip leading spaces.
|
||||
start := 0
|
||||
for width := 0; start < len(data); start += width {
|
||||
var r rune
|
||||
r, width = utf8.DecodeRune(data[start:])
|
||||
if !unicode.IsSpace(r) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if atEOF && len(data) == 0 || start == len(data) {
|
||||
return len(data), data, nil
|
||||
}
|
||||
if len(data) > start && data[start] == '#' {
|
||||
return scanLinesKeepPrefix(data, atEOF)
|
||||
}
|
||||
// Scan until space, marking end of word.
|
||||
for width, i := 0, start; i < len(data); i += width {
|
||||
var r rune
|
||||
r, width = utf8.DecodeRune(data[i:])
|
||||
if unicode.IsSpace(r) {
|
||||
return i, data[:i], nil
|
||||
}
|
||||
}
|
||||
// If we're at EOF, we have a final, non-empty, non-terminated word. Return it.
|
||||
if atEOF && len(data) > start {
|
||||
return len(data), data, nil
|
||||
}
|
||||
// Request more data.
|
||||
return 0, nil, nil
|
||||
}
|
||||
|
||||
func newToken(rawb []byte) (*token, error) {
|
||||
_, tkind, err := bufio.ScanWords(rawb, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var ok bool
|
||||
t := token{rawkind: rawb}
|
||||
t.kind, ok = keywords[string(tkind)]
|
||||
if !ok {
|
||||
trimmed := strings.TrimSpace(string(tkind))
|
||||
if trimmed == "" {
|
||||
t.kind = tkWhitespace // whitespace-only, should happen only at EOF
|
||||
return &t, nil
|
||||
}
|
||||
if strings.HasPrefix(trimmed, "#") {
|
||||
t.kind = tkComment // this is a comment
|
||||
return &t, nil
|
||||
}
|
||||
return &t, fmt.Errorf("keyword expected; got " + string(tkind))
|
||||
}
|
||||
return &t, nil
|
||||
}
|
||||
|
||||
func scanValue(scanner *bufio.Scanner, pos int) ([]byte, string, int, error) {
|
||||
if scanner.Scan() {
|
||||
raw := scanner.Bytes()
|
||||
pos += bytes.Count(raw, []byte{'\n'})
|
||||
return raw, strings.TrimSpace(string(raw)), pos, nil
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, "", pos, &Error{pos, err.Error()}
|
||||
}
|
||||
return nil, "", pos, nil
|
||||
}
|
||||
|
||||
func parse(r io.Reader, pos int) (*Netrc, error) {
|
||||
b, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nrc := Netrc{machines: make([]*Machine, 0, 20), macros: make(Macros, 10)}
|
||||
|
||||
defaultSeen := false
|
||||
var currentMacro *token
|
||||
var m *Machine
|
||||
var t *token
|
||||
scanner := bufio.NewScanner(bytes.NewReader(b))
|
||||
scanner.Split(scanTokensKeepPrefix)
|
||||
|
||||
for scanner.Scan() {
|
||||
rawb := scanner.Bytes()
|
||||
if len(rawb) == 0 {
|
||||
break
|
||||
}
|
||||
pos += bytes.Count(rawb, []byte{'\n'})
|
||||
t, err = newToken(rawb)
|
||||
if err != nil {
|
||||
if currentMacro == nil {
|
||||
return nil, &Error{pos, err.Error()}
|
||||
}
|
||||
currentMacro.rawvalue = append(currentMacro.rawvalue, rawb...)
|
||||
continue
|
||||
}
|
||||
|
||||
if currentMacro != nil && bytes.Contains(rawb, []byte{'\n', '\n'}) {
|
||||
// if macro rawvalue + rawb would contain \n\n, then macro def is over
|
||||
currentMacro.value = strings.TrimLeft(string(currentMacro.rawvalue), "\r\n")
|
||||
nrc.macros[currentMacro.macroName] = currentMacro.value
|
||||
currentMacro = nil
|
||||
}
|
||||
|
||||
switch t.kind {
|
||||
case tkMacdef:
|
||||
if _, t.macroName, pos, err = scanValue(scanner, pos); err != nil {
|
||||
return nil, &Error{pos, err.Error()}
|
||||
}
|
||||
currentMacro = t
|
||||
case tkDefault:
|
||||
if defaultSeen {
|
||||
return nil, &Error{pos, "multiple default token"}
|
||||
}
|
||||
if m != nil {
|
||||
nrc.machines, m = append(nrc.machines, m), nil
|
||||
}
|
||||
m = new(Machine)
|
||||
m.Name = ""
|
||||
defaultSeen = true
|
||||
case tkMachine:
|
||||
if defaultSeen {
|
||||
return nil, &Error{pos, errBadDefaultOrder}
|
||||
}
|
||||
if m != nil {
|
||||
nrc.machines, m = append(nrc.machines, m), nil
|
||||
}
|
||||
m = new(Machine)
|
||||
if t.rawvalue, m.Name, pos, err = scanValue(scanner, pos); err != nil {
|
||||
return nil, &Error{pos, err.Error()}
|
||||
}
|
||||
t.value = m.Name
|
||||
m.nametoken = t
|
||||
case tkLogin:
|
||||
if m == nil || m.Login != "" {
|
||||
return nil, &Error{pos, "unexpected token login "}
|
||||
}
|
||||
if t.rawvalue, m.Login, pos, err = scanValue(scanner, pos); err != nil {
|
||||
return nil, &Error{pos, err.Error()}
|
||||
}
|
||||
t.value = m.Login
|
||||
m.logintoken = t
|
||||
case tkPassword:
|
||||
if m == nil || m.Password != "" {
|
||||
return nil, &Error{pos, "unexpected token password"}
|
||||
}
|
||||
if t.rawvalue, m.Password, pos, err = scanValue(scanner, pos); err != nil {
|
||||
return nil, &Error{pos, err.Error()}
|
||||
}
|
||||
t.value = m.Password
|
||||
m.passtoken = t
|
||||
case tkAccount:
|
||||
if m == nil || m.Account != "" {
|
||||
return nil, &Error{pos, "unexpected token account"}
|
||||
}
|
||||
if t.rawvalue, m.Account, pos, err = scanValue(scanner, pos); err != nil {
|
||||
return nil, &Error{pos, err.Error()}
|
||||
}
|
||||
t.value = m.Account
|
||||
m.accounttoken = t
|
||||
}
|
||||
|
||||
nrc.tokens = append(nrc.tokens, t)
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if m != nil {
|
||||
nrc.machines, m = append(nrc.machines, m), nil
|
||||
}
|
||||
return &nrc, nil
|
||||
}
|
||||
|
||||
// ParseFile opens the file at filename and then passes its io.Reader to
|
||||
// Parse().
|
||||
func ParseFile(filename string) (*Netrc, error) {
|
||||
fd, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer fd.Close()
|
||||
return Parse(fd)
|
||||
}
|
||||
|
||||
// Parse parses from the the Reader r as a netrc file and returns the set of
|
||||
// machine information and macros defined in it. The ``default'' machine,
|
||||
// which is intended to be used when no machine name matches, is identified
|
||||
// by an empty machine name. There can be only one ``default'' machine.
|
||||
//
|
||||
// If there is a parsing error, an Error is returned.
|
||||
func Parse(r io.Reader) (*Netrc, error) {
|
||||
return parse(r, 1)
|
||||
}
|
||||
|
||||
// FindMachine parses the netrc file identified by filename and returns the
|
||||
// Machine named by name. If a problem occurs parsing the file at filename, an
|
||||
// error is returned. If a machine named by name exists, it is returned. If no
|
||||
// Machine with name name is found and there is a ``default'' machine, the
|
||||
// ``default'' machine is returned. Otherwise, nil is returned.
|
||||
func FindMachine(filename, name string) (m *Machine, err error) {
|
||||
n, err := ParseFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return n.FindMachine(name), nil
|
||||
}
|
201
vendor/github.com/bufbuild/buf/LICENSE
generated
vendored
Normal file
201
vendor/github.com/bufbuild/buf/LICENSE
generated
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2020-2021 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.
|
21
vendor/github.com/bufbuild/buf/cmd/buf/main.go
generated
vendored
Normal file
21
vendor/github.com/bufbuild/buf/cmd/buf/main.go
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2020-2021 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 main
|
||||
|
||||
import "github.com/bufbuild/buf/internal/buf/cmd/buf"
|
||||
|
||||
func main() {
|
||||
buf.Main("buf")
|
||||
}
|
21
vendor/github.com/bufbuild/buf/cmd/protoc-gen-buf-breaking/main.go
generated
vendored
Normal file
21
vendor/github.com/bufbuild/buf/cmd/protoc-gen-buf-breaking/main.go
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2020-2021 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 main
|
||||
|
||||
import breaking "github.com/bufbuild/buf/internal/buf/cmd/protoc-gen-buf-breaking"
|
||||
|
||||
func main() {
|
||||
breaking.Main()
|
||||
}
|
21
vendor/github.com/bufbuild/buf/cmd/protoc-gen-buf-lint/main.go
generated
vendored
Normal file
21
vendor/github.com/bufbuild/buf/cmd/protoc-gen-buf-lint/main.go
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2020-2021 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 main
|
||||
|
||||
import lint "github.com/bufbuild/buf/internal/buf/cmd/protoc-gen-buf-lint"
|
||||
|
||||
func main() {
|
||||
lint.Main()
|
||||
}
|
286
vendor/github.com/bufbuild/buf/internal/buf/bufanalysis/bufanalysis.go
generated
vendored
Normal file
286
vendor/github.com/bufbuild/buf/internal/buf/bufanalysis/bufanalysis.go
generated
vendored
Normal file
@ -0,0 +1,286 @@
|
||||
// Copyright 2020-2021 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 bufanalysis
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
// FormatText is the text format for FileAnnotations.
|
||||
FormatText Format = iota + 1
|
||||
// FormatJSON is the JSON format for FileAnnotations.
|
||||
FormatJSON
|
||||
// FormatMSVS is the MSVS format for FileAnnotations.
|
||||
FormatMSVS
|
||||
)
|
||||
|
||||
var (
|
||||
// AllFormatStrings is all format strings without aliases.
|
||||
//
|
||||
// Sorted in the order we want to display them.
|
||||
AllFormatStrings = []string{
|
||||
"text",
|
||||
"json",
|
||||
"msvs",
|
||||
}
|
||||
// AllFormatStringsWithAliases is all format strings with aliases.
|
||||
//
|
||||
// Sorted in the order we want to display them.
|
||||
AllFormatStringsWithAliases = []string{
|
||||
"text",
|
||||
"gcc",
|
||||
"json",
|
||||
"msvs",
|
||||
}
|
||||
|
||||
stringToFormat = map[string]Format{
|
||||
"text": FormatText,
|
||||
// alias for text
|
||||
"gcc": FormatText,
|
||||
"json": FormatJSON,
|
||||
"msvs": FormatMSVS,
|
||||
}
|
||||
formatToString = map[Format]string{
|
||||
FormatText: "text",
|
||||
FormatJSON: "json",
|
||||
FormatMSVS: "msvs",
|
||||
}
|
||||
)
|
||||
|
||||
// Format is a FileAnnotation format.
|
||||
type Format int
|
||||
|
||||
// String implements fmt.Stringer.
|
||||
func (f Format) String() string {
|
||||
s, ok := formatToString[f]
|
||||
if !ok {
|
||||
return strconv.Itoa(int(f))
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// ParseFormat parses the Format.
|
||||
//
|
||||
// The empty strings defaults to FormatText.
|
||||
func ParseFormat(s string) (Format, error) {
|
||||
s = strings.ToLower(strings.TrimSpace(s))
|
||||
if s == "" {
|
||||
return FormatText, nil
|
||||
}
|
||||
f, ok := stringToFormat[s]
|
||||
if ok {
|
||||
return f, nil
|
||||
}
|
||||
return 0, fmt.Errorf("unknown format: %q", s)
|
||||
}
|
||||
|
||||
// FileInfo is a minimal FileInfo interface.
|
||||
type FileInfo interface {
|
||||
Path() string
|
||||
ExternalPath() string
|
||||
}
|
||||
|
||||
// FileAnnotation is a file annotation.
|
||||
type FileAnnotation interface {
|
||||
// Stringer returns the string representation in text format.
|
||||
fmt.Stringer
|
||||
// Marshaler returns the string representation in JSON foramt.
|
||||
json.Marshaler
|
||||
// MSVSString returns the string representation in MSVS format.
|
||||
//
|
||||
// https://docs.microsoft.com/en-us/cpp/build/formatting-the-output-of-a-custom-build-step-or-build-event?view=vs-2019
|
||||
MSVSString() string
|
||||
|
||||
// FileInfo is the FileInfo for this annotation.
|
||||
//
|
||||
// This may be nil.
|
||||
FileInfo() FileInfo
|
||||
|
||||
// StartLine is the starting line.
|
||||
//
|
||||
// If the starting line is not known, this will be 0.
|
||||
StartLine() int
|
||||
// StartColumn is the starting column.
|
||||
//
|
||||
// If the starting column is not known, this will be 0.
|
||||
StartColumn() int
|
||||
// EndLine is the ending line.
|
||||
//
|
||||
// If the ending line is not known, this will be 0.
|
||||
// If the ending line is the same as the starting line, this will be explicitly
|
||||
// set to the same value as start_line.
|
||||
EndLine() int
|
||||
// EndColumn is the ending column.
|
||||
//
|
||||
// If the ending column is not known, this will be 0.
|
||||
// If the ending column is the same as the starting column, this will be explicitly
|
||||
// set to the same value as start_column.
|
||||
EndColumn() int
|
||||
// Type is the type of annotation, typically an ID representing a failure type.
|
||||
Type() string
|
||||
// Message is the message of the annotation.
|
||||
Message() string
|
||||
}
|
||||
|
||||
// NewFileAnnotation returns a new FileAnnotation.
|
||||
func NewFileAnnotation(
|
||||
fileInfo FileInfo,
|
||||
startLine int,
|
||||
startColumn int,
|
||||
endLine int,
|
||||
endColumn int,
|
||||
typeString string,
|
||||
message string,
|
||||
) FileAnnotation {
|
||||
return newFileAnnotation(
|
||||
fileInfo,
|
||||
startLine,
|
||||
startColumn,
|
||||
endLine,
|
||||
endColumn,
|
||||
typeString,
|
||||
message,
|
||||
)
|
||||
}
|
||||
|
||||
// SortFileAnnotations sorts the FileAnnotations.
|
||||
//
|
||||
// The order of sorting is:
|
||||
//
|
||||
// ExternalPath
|
||||
// StartLine
|
||||
// StartColumn
|
||||
// Type
|
||||
// Message
|
||||
// EndLine
|
||||
// EndColumn
|
||||
func SortFileAnnotations(fileAnnotations []FileAnnotation) {
|
||||
sort.Stable(sortFileAnnotations(fileAnnotations))
|
||||
}
|
||||
|
||||
// PrintFileAnnotations prints the file annotations separated by newlines.
|
||||
func PrintFileAnnotations(writer io.Writer, fileAnnotations []FileAnnotation, formatString string) error {
|
||||
format, err := ParseFormat(formatString)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, fileAnnotation := range fileAnnotations {
|
||||
s, err := FormatFileAnnotation(fileAnnotation, format)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := writer.Write([]byte(s + "\n")); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FormatFileAnnotation formats the FileAnnotation.
|
||||
func FormatFileAnnotation(fileAnnotation FileAnnotation, format Format) (string, error) {
|
||||
switch format {
|
||||
case FormatText:
|
||||
return fileAnnotation.String(), nil
|
||||
case FormatJSON:
|
||||
data, err := fileAnnotation.MarshalJSON()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(data), nil
|
||||
case FormatMSVS:
|
||||
return fileAnnotation.MSVSString(), nil
|
||||
default:
|
||||
return "", fmt.Errorf("unknown FileAnnotation Format: %v", format)
|
||||
}
|
||||
}
|
||||
|
||||
type sortFileAnnotations []FileAnnotation
|
||||
|
||||
func (a sortFileAnnotations) Len() int { return len(a) }
|
||||
func (a sortFileAnnotations) Swap(i int, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a sortFileAnnotations) Less(i int, j int) bool { return fileAnnotationCompareTo(a[i], a[j]) < 0 }
|
||||
|
||||
// fileAnnotationCompareTo returns a value less than 0 if a < b, a value
|
||||
// greater than 0 if a > b, and 0 if a == b.
|
||||
func fileAnnotationCompareTo(a FileAnnotation, b FileAnnotation) int {
|
||||
if a == nil && b == nil {
|
||||
return 0
|
||||
}
|
||||
if a == nil && b != nil {
|
||||
return -1
|
||||
}
|
||||
if a != nil && b == nil {
|
||||
return 1
|
||||
}
|
||||
aFileInfo := a.FileInfo()
|
||||
bFileInfo := b.FileInfo()
|
||||
if aFileInfo == nil && bFileInfo != nil {
|
||||
return -1
|
||||
}
|
||||
if aFileInfo != nil && bFileInfo == nil {
|
||||
return 1
|
||||
}
|
||||
if aFileInfo != nil && bFileInfo != nil {
|
||||
if aFileInfo.ExternalPath() < bFileInfo.ExternalPath() {
|
||||
return -1
|
||||
}
|
||||
if aFileInfo.ExternalPath() > bFileInfo.ExternalPath() {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
if a.StartLine() < b.StartLine() {
|
||||
return -1
|
||||
}
|
||||
if a.StartLine() > b.StartLine() {
|
||||
return 1
|
||||
}
|
||||
if a.StartColumn() < b.StartColumn() {
|
||||
return -1
|
||||
}
|
||||
if a.StartColumn() > b.StartColumn() {
|
||||
return 1
|
||||
}
|
||||
if a.Type() < b.Type() {
|
||||
return -1
|
||||
}
|
||||
if a.Type() > b.Type() {
|
||||
return 1
|
||||
}
|
||||
if a.Message() < b.Message() {
|
||||
return -1
|
||||
}
|
||||
if a.Message() > b.Message() {
|
||||
return 1
|
||||
}
|
||||
if a.EndLine() < b.EndLine() {
|
||||
return -1
|
||||
}
|
||||
if a.EndLine() > b.EndLine() {
|
||||
return 1
|
||||
}
|
||||
if a.EndColumn() < b.EndColumn() {
|
||||
return -1
|
||||
}
|
||||
if a.EndColumn() > b.EndColumn() {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
188
vendor/github.com/bufbuild/buf/internal/buf/bufanalysis/file_annotation.go
generated
vendored
Normal file
188
vendor/github.com/bufbuild/buf/internal/buf/bufanalysis/file_annotation.go
generated
vendored
Normal file
@ -0,0 +1,188 @@
|
||||
// Copyright 2020-2021 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 bufanalysis
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type fileAnnotation struct {
|
||||
fileInfo FileInfo
|
||||
startLine int
|
||||
startColumn int
|
||||
endLine int
|
||||
endColumn int
|
||||
typeString string
|
||||
message string
|
||||
}
|
||||
|
||||
func newFileAnnotation(
|
||||
fileInfo FileInfo,
|
||||
startLine int,
|
||||
startColumn int,
|
||||
endLine int,
|
||||
endColumn int,
|
||||
typeString string,
|
||||
message string,
|
||||
) *fileAnnotation {
|
||||
return &fileAnnotation{
|
||||
fileInfo: fileInfo,
|
||||
startLine: startLine,
|
||||
startColumn: startColumn,
|
||||
endLine: endLine,
|
||||
endColumn: endColumn,
|
||||
typeString: typeString,
|
||||
message: message,
|
||||
}
|
||||
}
|
||||
|
||||
func (f *fileAnnotation) FileInfo() FileInfo {
|
||||
return f.fileInfo
|
||||
}
|
||||
|
||||
func (f *fileAnnotation) StartLine() int {
|
||||
return f.startLine
|
||||
}
|
||||
|
||||
func (f *fileAnnotation) StartColumn() int {
|
||||
return f.startColumn
|
||||
}
|
||||
|
||||
func (f *fileAnnotation) EndLine() int {
|
||||
return f.endLine
|
||||
}
|
||||
|
||||
func (f *fileAnnotation) EndColumn() int {
|
||||
return f.endColumn
|
||||
}
|
||||
|
||||
func (f *fileAnnotation) Type() string {
|
||||
return f.typeString
|
||||
}
|
||||
|
||||
func (f *fileAnnotation) Message() string {
|
||||
return f.message
|
||||
}
|
||||
|
||||
func (f *fileAnnotation) String() string {
|
||||
if f == nil {
|
||||
return ""
|
||||
}
|
||||
path := "<input>"
|
||||
line := f.startLine
|
||||
column := f.startColumn
|
||||
message := f.message
|
||||
if f.fileInfo != nil {
|
||||
path = f.fileInfo.ExternalPath()
|
||||
}
|
||||
if line == 0 {
|
||||
line = 1
|
||||
}
|
||||
if column == 0 {
|
||||
column = 1
|
||||
}
|
||||
if message == "" {
|
||||
message = f.typeString
|
||||
// should never happen but just in case
|
||||
if message == "" {
|
||||
message = "FAILURE"
|
||||
}
|
||||
}
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
_, _ = buffer.WriteString(path)
|
||||
_, _ = buffer.WriteRune(':')
|
||||
_, _ = buffer.WriteString(strconv.Itoa(line))
|
||||
_, _ = buffer.WriteRune(':')
|
||||
_, _ = buffer.WriteString(strconv.Itoa(column))
|
||||
_, _ = buffer.WriteRune(':')
|
||||
_, _ = buffer.WriteString(message)
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
func (f *fileAnnotation) MarshalJSON() ([]byte, error) {
|
||||
if f == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return json.Marshal(f.toExternalFileAnnotation())
|
||||
}
|
||||
|
||||
func (f *fileAnnotation) MSVSString() string {
|
||||
if f == nil {
|
||||
return ""
|
||||
}
|
||||
path := "<input>"
|
||||
line := f.startLine
|
||||
column := f.startColumn
|
||||
message := f.message
|
||||
if f.fileInfo != nil {
|
||||
path = f.fileInfo.ExternalPath()
|
||||
}
|
||||
if line == 0 {
|
||||
line = 1
|
||||
}
|
||||
typeString := f.typeString
|
||||
if typeString == "" {
|
||||
// should never happen but just in case
|
||||
typeString = "FAILURE"
|
||||
}
|
||||
if message == "" {
|
||||
message = f.typeString
|
||||
// should never happen but just in case
|
||||
if message == "" {
|
||||
message = "FAILURE"
|
||||
}
|
||||
}
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
_, _ = buffer.WriteString(path)
|
||||
_, _ = buffer.WriteRune('(')
|
||||
_, _ = buffer.WriteString(strconv.Itoa(line))
|
||||
if column != 0 {
|
||||
_, _ = buffer.WriteRune(',')
|
||||
_, _ = buffer.WriteString(strconv.Itoa(column))
|
||||
}
|
||||
_, _ = buffer.WriteString(") : error ")
|
||||
_, _ = buffer.WriteString(typeString)
|
||||
_, _ = buffer.WriteString(" : ")
|
||||
_, _ = buffer.WriteString(message)
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
func (f *fileAnnotation) toExternalFileAnnotation() externalFileAnnotation {
|
||||
path := ""
|
||||
if f.fileInfo != nil {
|
||||
path = f.fileInfo.ExternalPath()
|
||||
}
|
||||
return externalFileAnnotation{
|
||||
Path: path,
|
||||
StartLine: f.startLine,
|
||||
StartColumn: f.startColumn,
|
||||
EndLine: f.endLine,
|
||||
EndColumn: f.endColumn,
|
||||
Type: f.typeString,
|
||||
Message: f.message,
|
||||
}
|
||||
}
|
||||
|
||||
type externalFileAnnotation struct {
|
||||
Path string `json:"path,omitempty" yaml:"path,omitempty"`
|
||||
StartLine int `json:"start_line,omitempty" yaml:"start_line,omitempty"`
|
||||
StartColumn int `json:"start_column,omitempty" yaml:"start_column,omitempty"`
|
||||
EndLine int `json:"end_line,omitempty" yaml:"end_line,omitempty"`
|
||||
EndColumn int `json:"end_column,omitempty" yaml:"end_column,omitempty"`
|
||||
Type string `json:"type,omitempty" yaml:"type,omitempty"`
|
||||
Message string `json:"message,omitempty" yaml:"message,omitempty"`
|
||||
}
|
118
vendor/github.com/bufbuild/buf/internal/buf/bufapiclient/bufapiclient.go
generated
vendored
Normal file
118
vendor/github.com/bufbuild/buf/internal/buf/bufapiclient/bufapiclient.go
generated
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
// Copyright 2020-2021 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 bufapiclient switches between grpc and twirp on the client-side.
|
||||
package bufapiclient
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
|
||||
"github.com/bufbuild/buf/internal/gen/proto/apiclient/buf/alpha/registry/v1alpha1/registryv1alpha1apiclient"
|
||||
"github.com/bufbuild/buf/internal/gen/proto/apiclientgrpc/buf/alpha/registry/v1alpha1/registryv1alpha1apiclientgrpc"
|
||||
"github.com/bufbuild/buf/internal/gen/proto/apiclienttwirp/buf/alpha/registry/v1alpha1/registryv1alpha1apiclienttwirp"
|
||||
"github.com/bufbuild/buf/internal/pkg/transport/grpc/grpcclient"
|
||||
"github.com/bufbuild/buf/internal/pkg/transport/http/httpclient"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// NewRegistryProvider creates a new registryv1alpha1apiclient.Provider for either grpc or twirp.
|
||||
//
|
||||
// If tlsConfig is nil, no TLS is used.
|
||||
func NewRegistryProvider(
|
||||
ctx context.Context,
|
||||
logger *zap.Logger,
|
||||
tlsConfig *tls.Config,
|
||||
options ...RegistryProviderOption,
|
||||
) (registryv1alpha1apiclient.Provider, error) {
|
||||
registryProviderOptions := ®istryProviderOptions{}
|
||||
for _, option := range options {
|
||||
option(registryProviderOptions)
|
||||
}
|
||||
if registryProviderOptions.useGRPC {
|
||||
clientConnProvider, err := NewGRPCClientConnProvider(ctx, logger, tlsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return registryv1alpha1apiclientgrpc.NewProvider(
|
||||
logger,
|
||||
clientConnProvider,
|
||||
registryv1alpha1apiclientgrpc.WithAddressMapper(registryProviderOptions.addressMapper),
|
||||
), nil
|
||||
}
|
||||
httpClient, err := NewHTTPClient(tlsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return registryv1alpha1apiclienttwirp.NewProvider(
|
||||
logger,
|
||||
httpClient,
|
||||
registryv1alpha1apiclienttwirp.WithAddressMapper(registryProviderOptions.addressMapper),
|
||||
), nil
|
||||
}
|
||||
|
||||
// RegistryProviderOption is an option for a new registry Provider.
|
||||
type RegistryProviderOption func(*registryProviderOptions)
|
||||
|
||||
type registryProviderOptions struct {
|
||||
useGRPC bool
|
||||
addressMapper func(string) string
|
||||
}
|
||||
|
||||
// RegistryProviderWithGRPC returns a new RegistryProviderOption that turns on gRPC.
|
||||
func RegistryProviderWithGRPC() RegistryProviderOption {
|
||||
return func(options *registryProviderOptions) {
|
||||
options.useGRPC = true
|
||||
}
|
||||
}
|
||||
|
||||
// RegistryProviderWithAddressMapper returns a new RegistryProviderOption that maps
|
||||
// addresses with the given function.
|
||||
func RegistryProviderWithAddressMapper(addressMapper func(string) string) RegistryProviderOption {
|
||||
return func(options *registryProviderOptions) {
|
||||
options.addressMapper = addressMapper
|
||||
}
|
||||
}
|
||||
|
||||
// NewGRPCClientConnProvider returns a new gRPC ClientConnProvider.
|
||||
//
|
||||
// TODO: move this to another location.
|
||||
func NewGRPCClientConnProvider(
|
||||
ctx context.Context,
|
||||
logger *zap.Logger,
|
||||
tlsConfig *tls.Config,
|
||||
) (grpcclient.ClientConnProvider, error) {
|
||||
return grpcclient.NewClientConnProvider(
|
||||
ctx,
|
||||
logger,
|
||||
grpcclient.ClientConnProviderWithTLSConfig(
|
||||
tlsConfig,
|
||||
),
|
||||
grpcclient.ClientConnProviderWithObservability(),
|
||||
)
|
||||
}
|
||||
|
||||
// NewHTTPClient returns a new HTTP Client.
|
||||
//
|
||||
// TODO: move this to another location.
|
||||
func NewHTTPClient(
|
||||
tlsConfig *tls.Config,
|
||||
) (httpclient.Client, error) {
|
||||
return httpclient.NewClient(
|
||||
httpclient.ClientWithTLSConfig(
|
||||
tlsConfig,
|
||||
),
|
||||
httpclient.ClientWithObservability(),
|
||||
)
|
||||
}
|
39
vendor/github.com/bufbuild/buf/internal/buf/bufapimodule/bufapimodule.go
generated
vendored
Normal file
39
vendor/github.com/bufbuild/buf/internal/buf/bufapimodule/bufapimodule.go
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright 2020-2021 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 bufapimodule provides bufmodule types based on bufapi types.
|
||||
package bufapimodule
|
||||
|
||||
import (
|
||||
"github.com/bufbuild/buf/internal/buf/bufcore/bufmodule"
|
||||
"github.com/bufbuild/buf/internal/gen/proto/apiclient/buf/alpha/registry/v1alpha1/registryv1alpha1apiclient"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// NewModuleReader returns a new ModuleReader backed by the download service.
|
||||
func NewModuleReader(
|
||||
downloadServiceProvider registryv1alpha1apiclient.DownloadServiceProvider,
|
||||
) bufmodule.ModuleReader {
|
||||
return newModuleReader(
|
||||
downloadServiceProvider,
|
||||
)
|
||||
}
|
||||
|
||||
// NewModuleResolver returns a new ModuleResolver backed by the resolve service.
|
||||
func NewModuleResolver(
|
||||
logger *zap.Logger,
|
||||
resolveServiceProvider registryv1alpha1apiclient.ResolveServiceProvider,
|
||||
) bufmodule.ModuleResolver {
|
||||
return newModuleResolver(logger, resolveServiceProvider)
|
||||
}
|
57
vendor/github.com/bufbuild/buf/internal/buf/bufapimodule/module_reader.go
generated
vendored
Normal file
57
vendor/github.com/bufbuild/buf/internal/buf/bufapimodule/module_reader.go
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
// Copyright 2020-2021 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 bufapimodule
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/bufbuild/buf/internal/buf/bufcore/bufmodule"
|
||||
"github.com/bufbuild/buf/internal/gen/proto/apiclient/buf/alpha/registry/v1alpha1/registryv1alpha1apiclient"
|
||||
"github.com/bufbuild/buf/internal/pkg/rpc"
|
||||
"github.com/bufbuild/buf/internal/pkg/storage"
|
||||
)
|
||||
|
||||
type moduleReader struct {
|
||||
downloadServiceProvider registryv1alpha1apiclient.DownloadServiceProvider
|
||||
}
|
||||
|
||||
func newModuleReader(
|
||||
downloadServiceProvider registryv1alpha1apiclient.DownloadServiceProvider,
|
||||
) *moduleReader {
|
||||
return &moduleReader{
|
||||
downloadServiceProvider: downloadServiceProvider,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *moduleReader) GetModule(ctx context.Context, modulePin bufmodule.ModulePin) (bufmodule.Module, error) {
|
||||
downloadService, err := m.downloadServiceProvider.NewDownloadService(ctx, modulePin.Remote())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
module, err := downloadService.Download(
|
||||
ctx,
|
||||
modulePin.Owner(),
|
||||
modulePin.Repository(),
|
||||
modulePin.Commit(),
|
||||
)
|
||||
if err != nil {
|
||||
if rpc.GetErrorCode(err) == rpc.ErrorCodeNotFound {
|
||||
// Required by ModuleReader interface spec
|
||||
return nil, storage.NewErrNotExist(modulePin.String())
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return bufmodule.NewModuleForProto(ctx, module)
|
||||
}
|
81
vendor/github.com/bufbuild/buf/internal/buf/bufapimodule/module_resolver.go
generated
vendored
Normal file
81
vendor/github.com/bufbuild/buf/internal/buf/bufapimodule/module_resolver.go
generated
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
// Copyright 2020-2021 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 bufapimodule
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/bufbuild/buf/internal/buf/bufcore/bufmodule"
|
||||
"github.com/bufbuild/buf/internal/gen/proto/apiclient/buf/alpha/registry/v1alpha1/registryv1alpha1apiclient"
|
||||
modulev1alpha1 "github.com/bufbuild/buf/internal/gen/proto/go/buf/alpha/module/v1alpha1"
|
||||
"github.com/bufbuild/buf/internal/pkg/rpc"
|
||||
"github.com/bufbuild/buf/internal/pkg/storage"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type moduleResolver struct {
|
||||
logger *zap.Logger
|
||||
resolveServiceProvider registryv1alpha1apiclient.ResolveServiceProvider
|
||||
}
|
||||
|
||||
func newModuleResolver(logger *zap.Logger, resolveServiceProvider registryv1alpha1apiclient.ResolveServiceProvider) *moduleResolver {
|
||||
return &moduleResolver{
|
||||
logger: logger,
|
||||
resolveServiceProvider: resolveServiceProvider,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *moduleResolver) GetModulePin(ctx context.Context, moduleReference bufmodule.ModuleReference) (bufmodule.ModulePin, error) {
|
||||
resolveService, err := m.resolveServiceProvider.NewResolveService(ctx, moduleReference.Remote())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
protoModulePins, err := resolveService.GetModulePins(
|
||||
ctx,
|
||||
[]*modulev1alpha1.ModuleReference{
|
||||
bufmodule.NewProtoModuleReferenceForModuleReference(moduleReference),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
if rpc.GetErrorCode(err) == rpc.ErrorCodeNotFound {
|
||||
// Required by ModuleResolver interface spec
|
||||
return nil, storage.NewErrNotExist(moduleReference.String())
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
var targetModulePin bufmodule.ModulePin
|
||||
moduleIdentity := getModuleIdentity(moduleReference)
|
||||
for _, protoModulePin := range protoModulePins {
|
||||
modulePin, err := bufmodule.NewModulePinForProto(protoModulePin)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if getModuleIdentity(modulePin) == moduleIdentity {
|
||||
if targetModulePin != nil {
|
||||
return nil, fmt.Errorf("resolved multiple module pins for %q", moduleIdentity)
|
||||
}
|
||||
targetModulePin = modulePin
|
||||
}
|
||||
}
|
||||
if targetModulePin == nil {
|
||||
return nil, fmt.Errorf("resolved module pins did not contain module %q", moduleIdentity)
|
||||
}
|
||||
return targetModulePin, nil
|
||||
}
|
||||
|
||||
func getModuleIdentity(moduleIdentity bufmodule.ModuleIdentity) string {
|
||||
return moduleIdentity.Remote() + "/" + moduleIdentity.Owner() + "/" + moduleIdentity.Repository()
|
||||
}
|
72
vendor/github.com/bufbuild/buf/internal/buf/bufapp/bufapp.go
generated
vendored
Normal file
72
vendor/github.com/bufbuild/buf/internal/buf/bufapp/bufapp.go
generated
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
// Copyright 2020-2021 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 bufapp
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
|
||||
"github.com/bufbuild/buf/internal/pkg/app/appname"
|
||||
"github.com/bufbuild/buf/internal/pkg/cert/certclient"
|
||||
"github.com/bufbuild/buf/internal/pkg/netconfig"
|
||||
)
|
||||
|
||||
const currentVersion = "v1"
|
||||
|
||||
// ExternalConfig is an external config.
|
||||
type ExternalConfig struct {
|
||||
// if editing ExternalConfig, make sure to update externalConfigIsEmpty at the bottom of this file!
|
||||
|
||||
Version string `json:"version,omitempty" yaml:"version,omitempty"`
|
||||
TLS certclient.ExternalClientTLSConfig `json:"tls,omitempty" yaml:"tls,omitempty"`
|
||||
Remotes []netconfig.ExternalRemote `json:"remotes,omitempty" yaml:"remotes,omitempty"`
|
||||
}
|
||||
|
||||
// IsEmpty returns true if the externalConfig is empty.
|
||||
func (e ExternalConfig) IsEmpty() bool {
|
||||
// you can't just do externalConfig == ExternalConfig{} as Golang does not allow
|
||||
// this if you have a slice field, i.e. Remotes
|
||||
return e.Version == "" &&
|
||||
e.TLS.IsEmpty() &&
|
||||
len(e.Remotes) == 0
|
||||
}
|
||||
|
||||
// Config is a config.
|
||||
type Config struct {
|
||||
TLS *tls.Config
|
||||
RemoteProvider netconfig.RemoteProvider
|
||||
}
|
||||
|
||||
// NewConfig returns a new Config for the ExternalConfig.
|
||||
func NewConfig(
|
||||
container appname.Container,
|
||||
externalConfig ExternalConfig,
|
||||
) (*Config, error) {
|
||||
if externalConfig.Version != currentVersion && !externalConfig.IsEmpty() {
|
||||
return nil, fmt.Errorf("buf configuration at %q must declare 'version: %s'", container.ConfigDirPath(), currentVersion)
|
||||
}
|
||||
tlsConfig, err := certclient.NewClientTLSConfig(container, externalConfig.TLS)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
remoteProvider, err := netconfig.NewRemoteProvider(externalConfig.Remotes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse remotes configuration at %q: %v", container.ConfigDirPath(), err)
|
||||
}
|
||||
return &Config{
|
||||
TLS: tlsConfig,
|
||||
RemoteProvider: remoteProvider,
|
||||
}, nil
|
||||
}
|
148
vendor/github.com/bufbuild/buf/internal/buf/bufcheck/bufbreaking/bufbreaking.go
generated
vendored
Normal file
148
vendor/github.com/bufbuild/buf/internal/buf/bufcheck/bufbreaking/bufbreaking.go
generated
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
// Copyright 2020-2021 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 bufbreaking contains the breaking change detection functionality.
|
||||
//
|
||||
// The primary entry point to this package is the Handler.
|
||||
package bufbreaking
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/bufbuild/buf/internal/buf/bufanalysis"
|
||||
"github.com/bufbuild/buf/internal/buf/bufcheck"
|
||||
"github.com/bufbuild/buf/internal/buf/bufcheck/bufbreaking/internal/bufbreakingv1beta1"
|
||||
"github.com/bufbuild/buf/internal/buf/bufcheck/internal"
|
||||
"github.com/bufbuild/buf/internal/buf/bufcore/bufimage"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// Handler handles the main breaking functionality.
|
||||
type Handler interface {
|
||||
// Check runs the breaking checks.
|
||||
//
|
||||
// The image should have source code info for this to work properly. The previousImage
|
||||
// does not need to have source code info.
|
||||
//
|
||||
// Images should be filtered with regards to imports before passing to this function.
|
||||
Check(
|
||||
ctx context.Context,
|
||||
config *Config,
|
||||
previousImage bufimage.Image,
|
||||
image bufimage.Image,
|
||||
) ([]bufanalysis.FileAnnotation, error)
|
||||
}
|
||||
|
||||
// NewHandler returns a new Handler.
|
||||
func NewHandler(logger *zap.Logger) Handler {
|
||||
return newHandler(logger)
|
||||
}
|
||||
|
||||
// Rule is a rule.
|
||||
type Rule interface {
|
||||
bufcheck.Rule
|
||||
|
||||
internalBreaking() *internal.Rule
|
||||
}
|
||||
|
||||
// Config is the check config.
|
||||
type Config struct {
|
||||
// Rules are the rules to run.
|
||||
//
|
||||
// Rules will be sorted by first categories, then id when Configs are
|
||||
// created from this package, i.e. created wth ConfigBuilder.NewConfig.
|
||||
Rules []Rule
|
||||
IgnoreIDToRootPaths map[string]map[string]struct{}
|
||||
IgnoreRootPaths map[string]struct{}
|
||||
IgnoreUnstablePackages bool
|
||||
}
|
||||
|
||||
// GetRules returns the rules.
|
||||
//
|
||||
// Should only be used for printing.
|
||||
func (c *Config) GetRules() []bufcheck.Rule {
|
||||
return rulesToBufcheckRules(c.Rules)
|
||||
}
|
||||
|
||||
// NewConfigV1Beta1 returns a new Config.
|
||||
func NewConfigV1Beta1(externalConfig ExternalConfigV1Beta1) (*Config, error) {
|
||||
internalConfig, err := internal.ConfigBuilder{
|
||||
Use: externalConfig.Use,
|
||||
Except: externalConfig.Except,
|
||||
IgnoreRootPaths: externalConfig.Ignore,
|
||||
IgnoreIDOrCategoryToRootPaths: externalConfig.IgnoreOnly,
|
||||
IgnoreUnstablePackages: externalConfig.IgnoreUnstablePackages,
|
||||
}.NewConfig(
|
||||
bufbreakingv1beta1.VersionSpec,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return internalConfigToConfig(internalConfig), nil
|
||||
}
|
||||
|
||||
// GetAllRulesV1Beta1 gets all known rules.
|
||||
//
|
||||
// Should only be used for printing.
|
||||
func GetAllRulesV1Beta1() ([]bufcheck.Rule, error) {
|
||||
config, err := NewConfigV1Beta1(
|
||||
ExternalConfigV1Beta1{
|
||||
Use: bufbreakingv1beta1.VersionSpec.AllCategories,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rulesToBufcheckRules(config.Rules), nil
|
||||
}
|
||||
|
||||
// ExternalConfigV1Beta1 is an external config.
|
||||
type ExternalConfigV1Beta1 struct {
|
||||
Use []string `json:"use,omitempty" yaml:"use,omitempty"`
|
||||
Except []string `json:"except,omitempty" yaml:"except,omitempty"`
|
||||
// IgnoreRootPaths
|
||||
Ignore []string `json:"ignore,omitempty" yaml:"ignore,omitempty"`
|
||||
// IgnoreIDOrCategoryToRootPaths
|
||||
IgnoreOnly map[string][]string `json:"ignore_only,omitempty" yaml:"ignore_only,omitempty"`
|
||||
IgnoreUnstablePackages bool `json:"ignore_unstable_packages,omitempty" yaml:"ignore_unstable_packages,omitempty"`
|
||||
}
|
||||
|
||||
func internalConfigToConfig(internalConfig *internal.Config) *Config {
|
||||
return &Config{
|
||||
Rules: internalRulesToRules(internalConfig.Rules),
|
||||
IgnoreIDToRootPaths: internalConfig.IgnoreIDToRootPaths,
|
||||
IgnoreRootPaths: internalConfig.IgnoreRootPaths,
|
||||
IgnoreUnstablePackages: internalConfig.IgnoreUnstablePackages,
|
||||
}
|
||||
}
|
||||
|
||||
func configToInternalConfig(config *Config) *internal.Config {
|
||||
return &internal.Config{
|
||||
Rules: rulesToInternalRules(config.Rules),
|
||||
IgnoreIDToRootPaths: config.IgnoreIDToRootPaths,
|
||||
IgnoreRootPaths: config.IgnoreRootPaths,
|
||||
IgnoreUnstablePackages: config.IgnoreUnstablePackages,
|
||||
}
|
||||
}
|
||||
|
||||
func rulesToBufcheckRules(rules []Rule) []bufcheck.Rule {
|
||||
if rules == nil {
|
||||
return nil
|
||||
}
|
||||
s := make([]bufcheck.Rule, len(rules))
|
||||
for i, e := range rules {
|
||||
s[i] = e
|
||||
}
|
||||
return s
|
||||
}
|
59
vendor/github.com/bufbuild/buf/internal/buf/bufcheck/bufbreaking/handler.go
generated
vendored
Normal file
59
vendor/github.com/bufbuild/buf/internal/buf/bufcheck/bufbreaking/handler.go
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright 2020-2021 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 bufbreaking
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/bufbuild/buf/internal/buf/bufanalysis"
|
||||
"github.com/bufbuild/buf/internal/buf/bufcheck/internal"
|
||||
"github.com/bufbuild/buf/internal/buf/bufcore/bufimage"
|
||||
"github.com/bufbuild/buf/internal/buf/bufcore/bufimage/bufimageutil"
|
||||
"github.com/bufbuild/buf/internal/pkg/protosource"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type handler struct {
|
||||
logger *zap.Logger
|
||||
runner *internal.Runner
|
||||
}
|
||||
|
||||
func newHandler(
|
||||
logger *zap.Logger,
|
||||
) *handler {
|
||||
return &handler{
|
||||
logger: logger,
|
||||
// comment ignores are not allowed for breaking changes
|
||||
// so do not set the ignore prefix per the RunnerWithIgnorePrefix comments
|
||||
runner: internal.NewRunner(logger),
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) Check(
|
||||
ctx context.Context,
|
||||
config *Config,
|
||||
previousImage bufimage.Image,
|
||||
image bufimage.Image,
|
||||
) ([]bufanalysis.FileAnnotation, error) {
|
||||
previousFiles, err := protosource.NewFilesUnstable(ctx, bufimageutil.NewInputFiles(previousImage.Files())...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
files, err := protosource.NewFilesUnstable(ctx, bufimageutil.NewInputFiles(image.Files())...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return h.runner.Check(ctx, configToInternalConfig(config), previousFiles, files)
|
||||
}
|
353
vendor/github.com/bufbuild/buf/internal/buf/bufcheck/bufbreaking/internal/bufbreakingbuild/bufbreakingbuild.go
generated
vendored
Normal file
353
vendor/github.com/bufbuild/buf/internal/buf/bufcheck/bufbreaking/internal/bufbreakingbuild/bufbreakingbuild.go
generated
vendored
Normal file
@ -0,0 +1,353 @@
|
||||
// Copyright 2020-2021 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 bufbreakingbuild contains the RuleBuilders used by bufbreakingv*.
|
||||
//
|
||||
// In the future, we can have multiple versions of a RuleBuilder here, and then
|
||||
// include them separately in the bufbreakingv* packages. For example, FieldSameTypeRuleBuilder
|
||||
// could be split into FieldSameTypeRuleBuilder/FieldSameTypeRuleBuilderV2 which handle
|
||||
// primitives differently, and we could use the former in v1beta1, and the latter in v1.
|
||||
package bufbreakingbuild
|
||||
|
||||
import (
|
||||
"github.com/bufbuild/buf/internal/buf/bufcheck/bufbreaking/internal/bufbreakingcheck"
|
||||
"github.com/bufbuild/buf/internal/buf/bufcheck/internal"
|
||||
)
|
||||
|
||||
var (
|
||||
// EnumNoDeleteRuleBuilder is a rule builder.
|
||||
EnumNoDeleteRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"ENUM_NO_DELETE",
|
||||
"enums are not deleted from a given file",
|
||||
bufbreakingcheck.CheckEnumNoDelete,
|
||||
)
|
||||
// EnumValueNoDeleteRuleBuilder is a rule builder.
|
||||
EnumValueNoDeleteRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"ENUM_VALUE_NO_DELETE",
|
||||
"enum values are not deleted from a given enum",
|
||||
bufbreakingcheck.CheckEnumValueNoDelete,
|
||||
)
|
||||
// EnumValueNoDeleteUnlessNameReservedRuleBuilder is a rule builder.
|
||||
EnumValueNoDeleteUnlessNameReservedRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"ENUM_VALUE_NO_DELETE_UNLESS_NAME_RESERVED",
|
||||
"enum values are not deleted from a given enum unless the name is reserved",
|
||||
bufbreakingcheck.CheckEnumValueNoDeleteUnlessNameReserved,
|
||||
)
|
||||
// EnumValueNoDeleteUnlessNumberReservedRuleBuilder is a rule builder.
|
||||
EnumValueNoDeleteUnlessNumberReservedRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"ENUM_VALUE_NO_DELETE_UNLESS_NUMBER_RESERVED",
|
||||
"enum values are not deleted from a given enum unless the number is reserved",
|
||||
bufbreakingcheck.CheckEnumValueNoDeleteUnlessNumberReserved,
|
||||
)
|
||||
// EnumValueSameNameRuleBuilder is a rule builder.
|
||||
EnumValueSameNameRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"ENUM_VALUE_SAME_NAME",
|
||||
"enum values have the same name",
|
||||
bufbreakingcheck.CheckEnumValueSameName,
|
||||
)
|
||||
// ExtensionMessageNoDeleteRuleBuilder is a rule builder.
|
||||
ExtensionMessageNoDeleteRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"EXTENSION_MESSAGE_NO_DELETE",
|
||||
"extension ranges are not deleted from a given message",
|
||||
bufbreakingcheck.CheckExtensionMessageNoDelete,
|
||||
)
|
||||
// FieldNoDeleteRuleBuilder is a rule builder.
|
||||
FieldNoDeleteRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FIELD_NO_DELETE",
|
||||
"fields are not deleted from a given message",
|
||||
bufbreakingcheck.CheckFieldNoDelete,
|
||||
)
|
||||
// FieldNoDeleteUnlessNameReservedRuleBuilder is a rule builder.
|
||||
FieldNoDeleteUnlessNameReservedRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FIELD_NO_DELETE_UNLESS_NAME_RESERVED",
|
||||
"fields are not deleted from a given message unless the name is reserved",
|
||||
bufbreakingcheck.CheckFieldNoDeleteUnlessNameReserved,
|
||||
)
|
||||
// FieldNoDeleteUnlessNumberReservedRuleBuilder is a rule builder.
|
||||
FieldNoDeleteUnlessNumberReservedRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FIELD_NO_DELETE_UNLESS_NUMBER_RESERVED",
|
||||
"fields are not deleted from a given message unless the number is reserved",
|
||||
bufbreakingcheck.CheckFieldNoDeleteUnlessNumberReserved,
|
||||
)
|
||||
// FieldSameCTypeRuleBuilder is a rule builder.
|
||||
FieldSameCTypeRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FIELD_SAME_CTYPE",
|
||||
"fields have the same value for the ctype option",
|
||||
bufbreakingcheck.CheckFieldSameCType,
|
||||
)
|
||||
// FieldSameJSONNameRuleBuilder is a rule builder.
|
||||
FieldSameJSONNameRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FIELD_SAME_JSON_NAME",
|
||||
"fields have the same value for the json_name option",
|
||||
bufbreakingcheck.CheckFieldSameJSONName,
|
||||
)
|
||||
// FieldSameJSTypeRuleBuilder is a rule builder.
|
||||
FieldSameJSTypeRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FIELD_SAME_JSTYPE",
|
||||
"fields have the same value for the jstype option",
|
||||
bufbreakingcheck.CheckFieldSameJSType,
|
||||
)
|
||||
// FieldSameLabelRuleBuilder is a rule builder.
|
||||
FieldSameLabelRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FIELD_SAME_LABEL",
|
||||
"fields have the same labels in a given message",
|
||||
bufbreakingcheck.CheckFieldSameLabel,
|
||||
)
|
||||
// FieldSameNameRuleBuilder is a rule builder.
|
||||
FieldSameNameRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FIELD_SAME_NAME",
|
||||
"fields have the same names in a given message",
|
||||
bufbreakingcheck.CheckFieldSameName,
|
||||
)
|
||||
// FieldSameOneofRuleBuilder is a rule builder.
|
||||
FieldSameOneofRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FIELD_SAME_ONEOF",
|
||||
"fields have the same oneofs in a given message",
|
||||
bufbreakingcheck.CheckFieldSameOneof,
|
||||
)
|
||||
// FieldSameTypeRuleBuilder is a rule builder.
|
||||
FieldSameTypeRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FIELD_SAME_TYPE",
|
||||
"fields have the same types in a given message",
|
||||
bufbreakingcheck.CheckFieldSameType,
|
||||
)
|
||||
// FileNoDeleteRuleBuilder is a rule builder.
|
||||
FileNoDeleteRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FILE_NO_DELETE",
|
||||
"files are not deleted",
|
||||
bufbreakingcheck.CheckFileNoDelete,
|
||||
)
|
||||
// FileSameCsharpNamespaceRuleBuilder is a rule builder.
|
||||
FileSameCsharpNamespaceRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FILE_SAME_CSHARP_NAMESPACE",
|
||||
"files have the same value for the csharp_namespace option",
|
||||
bufbreakingcheck.CheckFileSameCsharpNamespace,
|
||||
)
|
||||
// FileSameGoPackageRuleBuilder is a rule builder.
|
||||
FileSameGoPackageRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FILE_SAME_GO_PACKAGE",
|
||||
"files have the same value for the go_package option",
|
||||
bufbreakingcheck.CheckFileSameGoPackage,
|
||||
)
|
||||
// FileSameJavaMultipleFilesRuleBuilder is a rule builder.
|
||||
FileSameJavaMultipleFilesRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FILE_SAME_JAVA_MULTIPLE_FILES",
|
||||
"files have the same value for the java_multiple_files option",
|
||||
bufbreakingcheck.CheckFileSameJavaMultipleFiles,
|
||||
)
|
||||
// FileSameJavaOuterClassnameRuleBuilder is a rule builder.
|
||||
FileSameJavaOuterClassnameRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FILE_SAME_JAVA_OUTER_CLASSNAME",
|
||||
"files have the same value for the java_outer_classname option",
|
||||
bufbreakingcheck.CheckFileSameJavaOuterClassname,
|
||||
)
|
||||
// FileSameJavaPackageRuleBuilder is a rule builder.
|
||||
FileSameJavaPackageRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FILE_SAME_JAVA_PACKAGE",
|
||||
"files have the same value for the java_package option",
|
||||
bufbreakingcheck.CheckFileSameJavaPackage,
|
||||
)
|
||||
// FileSameJavaStringCheckUtf8RuleBuilder is a rule builder.
|
||||
FileSameJavaStringCheckUtf8RuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FILE_SAME_JAVA_STRING_CHECK_UTF8",
|
||||
"files have the same value for the java_string_check_utf8 option",
|
||||
bufbreakingcheck.CheckFileSameJavaStringCheckUtf8,
|
||||
)
|
||||
// FileSameObjcClassPrefixRuleBuilder is a rule builder.
|
||||
FileSameObjcClassPrefixRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FILE_SAME_OBJC_CLASS_PREFIX",
|
||||
"files have the same value for the objc_class_prefix option",
|
||||
bufbreakingcheck.CheckFileSameObjcClassPrefix,
|
||||
)
|
||||
// FileSamePackageRuleBuilder is a rule builder.
|
||||
FileSamePackageRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FILE_SAME_PACKAGE",
|
||||
"files have the same package",
|
||||
bufbreakingcheck.CheckFileSamePackage,
|
||||
)
|
||||
// FileSamePhpClassPrefixRuleBuilder is a rule builder.
|
||||
FileSamePhpClassPrefixRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FILE_SAME_PHP_CLASS_PREFIX",
|
||||
"files have the same value for the php_class_prefix option",
|
||||
bufbreakingcheck.CheckFileSamePhpClassPrefix,
|
||||
)
|
||||
// FileSamePhpMetadataNamespaceRuleBuilder is a rule builder.
|
||||
FileSamePhpMetadataNamespaceRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FILE_SAME_PHP_METADATA_NAMESPACE",
|
||||
"files have the same value for the php_metadata_namespace option",
|
||||
bufbreakingcheck.CheckFileSamePhpMetadataNamespace,
|
||||
)
|
||||
// FileSamePhpNamespaceRuleBuilder is a rule builder.
|
||||
FileSamePhpNamespaceRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FILE_SAME_PHP_NAMESPACE",
|
||||
"files have the same value for the php_namespace option",
|
||||
bufbreakingcheck.CheckFileSamePhpNamespace,
|
||||
)
|
||||
// FileSameRubyPackageRuleBuilder is a rule builder.
|
||||
FileSameRubyPackageRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FILE_SAME_RUBY_PACKAGE",
|
||||
"files have the same value for the ruby_package option",
|
||||
bufbreakingcheck.CheckFileSameRubyPackage,
|
||||
)
|
||||
// FileSameSwiftPrefixRuleBuilder is a rule builder.
|
||||
FileSameSwiftPrefixRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FILE_SAME_SWIFT_PREFIX",
|
||||
"files have the same value for the swift_prefix option",
|
||||
bufbreakingcheck.CheckFileSameSwiftPrefix,
|
||||
)
|
||||
// FileSameOptimizeForRuleBuilder is a rule builder.
|
||||
FileSameOptimizeForRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FILE_SAME_OPTIMIZE_FOR",
|
||||
"files have the same value for the optimize_for option",
|
||||
bufbreakingcheck.CheckFileSameOptimizeFor,
|
||||
)
|
||||
// FileSameCcGenericServicesRuleBuilder is a rule builder.
|
||||
FileSameCcGenericServicesRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FILE_SAME_CC_GENERIC_SERVICES",
|
||||
"files have the same value for the cc_generic_services option",
|
||||
bufbreakingcheck.CheckFileSameCcGenericServices,
|
||||
)
|
||||
// FileSameJavaGenericServicesRuleBuilder is a rule builder.
|
||||
FileSameJavaGenericServicesRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FILE_SAME_JAVA_GENERIC_SERVICES",
|
||||
"files have the same value for the java_generic_services option",
|
||||
bufbreakingcheck.CheckFileSameJavaGenericServices,
|
||||
)
|
||||
// FileSamePyGenericServicesRuleBuilder is a rule builder.
|
||||
FileSamePyGenericServicesRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FILE_SAME_PY_GENERIC_SERVICES",
|
||||
"files have the same value for the py_generic_services option",
|
||||
bufbreakingcheck.CheckFileSamePyGenericServices,
|
||||
)
|
||||
// FileSamePhpGenericServicesRuleBuilder is a rule builder.
|
||||
FileSamePhpGenericServicesRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FILE_SAME_PHP_GENERIC_SERVICES",
|
||||
"files have the same value for the php_generic_services option",
|
||||
bufbreakingcheck.CheckFileSamePhpGenericServices,
|
||||
)
|
||||
// FileSameCcEnableArenasRuleBuilder is a rule builder.
|
||||
FileSameCcEnableArenasRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FILE_SAME_CC_ENABLE_ARENAS",
|
||||
"files have the same value for the cc_enable_arenas option",
|
||||
bufbreakingcheck.CheckFileSameCcEnableArenas,
|
||||
)
|
||||
// FileSameSyntaxRuleBuilder is a rule builder.
|
||||
FileSameSyntaxRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"FILE_SAME_SYNTAX",
|
||||
"files have the same syntax",
|
||||
bufbreakingcheck.CheckFileSameSyntax,
|
||||
)
|
||||
// MessageNoDeleteRuleBuilder is a rule builder.
|
||||
MessageNoDeleteRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"MESSAGE_NO_DELETE",
|
||||
"messages are not deleted from a given file",
|
||||
bufbreakingcheck.CheckMessageNoDelete,
|
||||
)
|
||||
// MessageNoRemoveStandardDescriptorAccessorRuleBuilder is a rule builder.
|
||||
MessageNoRemoveStandardDescriptorAccessorRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"MESSAGE_NO_REMOVE_STANDARD_DESCRIPTOR_ACCESSOR",
|
||||
"messages do not change the no_standard_descriptor_accessor option from false or unset to true",
|
||||
bufbreakingcheck.CheckMessageNoRemoveStandardDescriptorAccessor,
|
||||
)
|
||||
// MessageSameMessageSetWireFormatRuleBuilder is a rule builder.
|
||||
MessageSameMessageSetWireFormatRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"MESSAGE_SAME_MESSAGE_SET_WIRE_FORMAT",
|
||||
"messages have the same value for the message_set_wire_format option",
|
||||
bufbreakingcheck.CheckMessageSameMessageSetWireFormat,
|
||||
)
|
||||
// OneofNoDeleteRuleBuilder is a rule builder.
|
||||
OneofNoDeleteRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"ONEOF_NO_DELETE",
|
||||
"oneofs are not deleted from a given message",
|
||||
bufbreakingcheck.CheckOneofNoDelete,
|
||||
)
|
||||
// PackageEnumNoDeleteRuleBuilder is a rule builder.
|
||||
PackageEnumNoDeleteRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"PACKAGE_ENUM_NO_DELETE",
|
||||
"enums are not deleted from a given package",
|
||||
bufbreakingcheck.CheckPackageEnumNoDelete,
|
||||
)
|
||||
// PackageMessageNoDeleteRuleBuilder is a rule builder.
|
||||
PackageMessageNoDeleteRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"PACKAGE_MESSAGE_NO_DELETE",
|
||||
"messages are not deleted from a given package",
|
||||
bufbreakingcheck.CheckPackageMessageNoDelete,
|
||||
)
|
||||
// PackageNoDeleteRuleBuilder is a rule builder.
|
||||
PackageNoDeleteRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"PACKAGE_NO_DELETE",
|
||||
"packages are not deleted",
|
||||
bufbreakingcheck.CheckPackageNoDelete,
|
||||
)
|
||||
// PackageServiceNoDeleteRuleBuilder is a rule builder.
|
||||
PackageServiceNoDeleteRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"PACKAGE_SERVICE_NO_DELETE",
|
||||
"services are not deleted from a given package",
|
||||
bufbreakingcheck.CheckPackageServiceNoDelete,
|
||||
)
|
||||
// ReservedEnumNoDeleteRuleBuilder is a rule builder.
|
||||
ReservedEnumNoDeleteRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"RESERVED_ENUM_NO_DELETE",
|
||||
"reserved ranges and names are not deleted from a given enum",
|
||||
bufbreakingcheck.CheckReservedEnumNoDelete,
|
||||
)
|
||||
// ReservedMessageNoDeleteRuleBuilder is a rule builder.
|
||||
ReservedMessageNoDeleteRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"RESERVED_MESSAGE_NO_DELETE",
|
||||
"reserved ranges and names are not deleted from a given message",
|
||||
bufbreakingcheck.CheckReservedMessageNoDelete,
|
||||
)
|
||||
// RPCNoDeleteRuleBuilder is a rule builder.
|
||||
RPCNoDeleteRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"RPC_NO_DELETE",
|
||||
"rpcs are not deleted from a given service",
|
||||
bufbreakingcheck.CheckRPCNoDelete,
|
||||
)
|
||||
// RPCSameClientStreamingRuleBuilder is a rule builder.
|
||||
RPCSameClientStreamingRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"RPC_SAME_CLIENT_STREAMING",
|
||||
"rpcs have the same client streaming value",
|
||||
bufbreakingcheck.CheckRPCSameClientStreaming,
|
||||
)
|
||||
// RPCSameIdempotencyLevelRuleBuilder is a rule builder.
|
||||
RPCSameIdempotencyLevelRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"RPC_SAME_IDEMPOTENCY_LEVEL",
|
||||
"rpcs have the same value for the idempotency_level option",
|
||||
bufbreakingcheck.CheckRPCSameIdempotencyLevel,
|
||||
)
|
||||
// RPCSameRequestTypeRuleBuilder is a rule builder.
|
||||
RPCSameRequestTypeRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"RPC_SAME_REQUEST_TYPE",
|
||||
"rpcs are have the same request type",
|
||||
bufbreakingcheck.CheckRPCSameRequestType,
|
||||
)
|
||||
// RPCSameResponseTypeRuleBuilder is a rule builder.
|
||||
RPCSameResponseTypeRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"RPC_SAME_RESPONSE_TYPE",
|
||||
"rpcs are have the same response type",
|
||||
bufbreakingcheck.CheckRPCSameResponseType,
|
||||
)
|
||||
// RPCSameServerStreamingRuleBuilder is a rule builder.
|
||||
RPCSameServerStreamingRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"RPC_SAME_SERVER_STREAMING",
|
||||
"rpcs have the same server streaming value",
|
||||
bufbreakingcheck.CheckRPCSameServerStreaming,
|
||||
)
|
||||
// ServiceNoDeleteRuleBuilder is a rule builder.
|
||||
ServiceNoDeleteRuleBuilder = internal.NewNopRuleBuilder(
|
||||
"SERVICE_NO_DELETE",
|
||||
"services are not deleted from a given file",
|
||||
bufbreakingcheck.CheckServiceNoDelete,
|
||||
)
|
||||
)
|
888
vendor/github.com/bufbuild/buf/internal/buf/bufcheck/bufbreaking/internal/bufbreakingcheck/bufbreakingcheck.go
generated
vendored
Normal file
888
vendor/github.com/bufbuild/buf/internal/buf/bufcheck/bufbreaking/internal/bufbreakingcheck/bufbreakingcheck.go
generated
vendored
Normal file
@ -0,0 +1,888 @@
|
||||
// Copyright 2020-2021 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 bufbreakingcheck impelements the check functions.
|
||||
//
|
||||
// These are used by bufbreakingbuild to create RuleBuilders.
|
||||
package bufbreakingcheck
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/bufbuild/buf/internal/pkg/protosource"
|
||||
"github.com/bufbuild/buf/internal/pkg/stringutil"
|
||||
)
|
||||
|
||||
// CheckEnumNoDelete is a check function.
|
||||
var CheckEnumNoDelete = newFilePairCheckFunc(checkEnumNoDelete)
|
||||
|
||||
func checkEnumNoDelete(add addFunc, previousFile protosource.File, file protosource.File) error {
|
||||
previousNestedNameToEnum, err := protosource.NestedNameToEnum(previousFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nestedNameToEnum, err := protosource.NestedNameToEnum(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for previousNestedName := range previousNestedNameToEnum {
|
||||
if _, ok := nestedNameToEnum[previousNestedName]; !ok {
|
||||
// TODO: search for enum in other files and return that the enum was moved?
|
||||
descriptor, location, err := getDescriptorAndLocationForDeletedEnum(file, previousNestedName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
add(descriptor, location, `Previously present enum %q was deleted from file.`, previousNestedName)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckEnumValueNoDelete is a check function.
|
||||
var CheckEnumValueNoDelete = newEnumPairCheckFunc(checkEnumValueNoDelete)
|
||||
|
||||
func checkEnumValueNoDelete(add addFunc, previousEnum protosource.Enum, enum protosource.Enum) error {
|
||||
return checkEnumValueNoDeleteWithRules(add, previousEnum, enum, false, false)
|
||||
}
|
||||
|
||||
// CheckEnumValueNoDeleteUnlessNumberReserved is a check function.
|
||||
var CheckEnumValueNoDeleteUnlessNumberReserved = newEnumPairCheckFunc(checkEnumValueNoDeleteUnlessNumberReserved)
|
||||
|
||||
func checkEnumValueNoDeleteUnlessNumberReserved(add addFunc, previousEnum protosource.Enum, enum protosource.Enum) error {
|
||||
return checkEnumValueNoDeleteWithRules(add, previousEnum, enum, true, false)
|
||||
}
|
||||
|
||||
// CheckEnumValueNoDeleteUnlessNameReserved is a check function.
|
||||
var CheckEnumValueNoDeleteUnlessNameReserved = newEnumPairCheckFunc(checkEnumValueNoDeleteUnlessNameReserved)
|
||||
|
||||
func checkEnumValueNoDeleteUnlessNameReserved(add addFunc, previousEnum protosource.Enum, enum protosource.Enum) error {
|
||||
return checkEnumValueNoDeleteWithRules(add, previousEnum, enum, false, true)
|
||||
}
|
||||
|
||||
func checkEnumValueNoDeleteWithRules(add addFunc, previousEnum protosource.Enum, enum protosource.Enum, allowIfNumberReserved bool, allowIfNameReserved bool) error {
|
||||
previousNumberToNameToEnumValue, err := protosource.NumberToNameToEnumValue(previousEnum)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
numberToNameToEnumValue, err := protosource.NumberToNameToEnumValue(enum)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for previousNumber, previousNameToEnumValue := range previousNumberToNameToEnumValue {
|
||||
if _, ok := numberToNameToEnumValue[previousNumber]; !ok {
|
||||
if !isDeletedEnumValueAllowedWithRules(previousNumber, previousNameToEnumValue, enum, allowIfNumberReserved, allowIfNameReserved) {
|
||||
suffix := ""
|
||||
if allowIfNumberReserved && allowIfNameReserved {
|
||||
return errors.New("both allowIfNumberReserved and allowIfNameReserved set")
|
||||
}
|
||||
if allowIfNumberReserved {
|
||||
suffix = fmt.Sprintf(` without reserving the number "%d"`, previousNumber)
|
||||
}
|
||||
if allowIfNameReserved {
|
||||
nameSuffix := ""
|
||||
if len(previousNameToEnumValue) > 1 {
|
||||
nameSuffix = "s"
|
||||
}
|
||||
suffix = fmt.Sprintf(` without reserving the name%s %s`, nameSuffix, stringutil.JoinSliceQuoted(getSortedEnumValueNames(previousNameToEnumValue), ", "))
|
||||
}
|
||||
add(enum, enum.Location(), `Previously present enum value "%d" on enum %q was deleted%s.`, previousNumber, enum.Name(), suffix)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func isDeletedEnumValueAllowedWithRules(previousNumber int, previousNameToEnumValue map[string]protosource.EnumValue, enum protosource.Enum, allowIfNumberReserved bool, allowIfNameReserved bool) bool {
|
||||
if allowIfNumberReserved {
|
||||
return protosource.NumberInReservedRanges(previousNumber, enum.ReservedTagRanges()...)
|
||||
}
|
||||
if allowIfNameReserved {
|
||||
// if true for all names, then ok
|
||||
for previousName := range previousNameToEnumValue {
|
||||
if !protosource.NameInReservedNames(previousName, enum.ReservedNames()...) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// CheckEnumValueSameName is a check function.
|
||||
var CheckEnumValueSameName = newEnumValuePairCheckFunc(checkEnumValueSameName)
|
||||
|
||||
func checkEnumValueSameName(add addFunc, previousNameToEnumValue map[string]protosource.EnumValue, nameToEnumValue map[string]protosource.EnumValue) error {
|
||||
previousNames := getSortedEnumValueNames(previousNameToEnumValue)
|
||||
names := getSortedEnumValueNames(nameToEnumValue)
|
||||
// all current names for this number need to be in the previous set
|
||||
// ie if you now have FOO=2, BAR=2, you need to have had FOO=2, BAR=2 previously
|
||||
// FOO=2, BAR=2, BAZ=2 now would pass
|
||||
// FOO=2, BAR=2, BAZ=2 previously would fail
|
||||
if !stringutil.SliceElementsContained(names, previousNames) {
|
||||
previousNamesString := stringutil.JoinSliceQuoted(previousNames, ", ")
|
||||
namesString := stringutil.JoinSliceQuoted(names, ", ")
|
||||
nameSuffix := ""
|
||||
if len(previousNames) > 1 && len(names) > 1 {
|
||||
nameSuffix = "s"
|
||||
}
|
||||
for _, enumValue := range nameToEnumValue {
|
||||
add(enumValue, enumValue.NumberLocation(), `Enum value "%d" on enum %q changed name%s from %s to %s.`, enumValue.Number(), enumValue.Enum().Name(), nameSuffix, previousNamesString, namesString)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckExtensionMessageNoDelete is a check function.
|
||||
var CheckExtensionMessageNoDelete = newMessagePairCheckFunc(checkExtensionMessageNoDelete)
|
||||
|
||||
func checkExtensionMessageNoDelete(add addFunc, previousMessage protosource.Message, message protosource.Message) error {
|
||||
previousStringToExtensionRange := protosource.StringToExtensionMessageRange(previousMessage)
|
||||
stringToExtensionRange := protosource.StringToExtensionMessageRange(message)
|
||||
for previousString := range previousStringToExtensionRange {
|
||||
if _, ok := stringToExtensionRange[previousString]; !ok {
|
||||
add(message, message.Location(), `Previously present extension range %q on message %q was deleted.`, previousString, message.Name())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckFieldNoDelete is a check function.
|
||||
var CheckFieldNoDelete = newMessagePairCheckFunc(checkFieldNoDelete)
|
||||
|
||||
func checkFieldNoDelete(add addFunc, previousMessage protosource.Message, message protosource.Message) error {
|
||||
return checkFieldNoDeleteWithRules(add, previousMessage, message, false, false)
|
||||
}
|
||||
|
||||
// CheckFieldNoDeleteUnlessNumberReserved is a check function.
|
||||
var CheckFieldNoDeleteUnlessNumberReserved = newMessagePairCheckFunc(checkFieldNoDeleteUnlessNumberReserved)
|
||||
|
||||
func checkFieldNoDeleteUnlessNumberReserved(add addFunc, previousMessage protosource.Message, message protosource.Message) error {
|
||||
return checkFieldNoDeleteWithRules(add, previousMessage, message, true, false)
|
||||
}
|
||||
|
||||
// CheckFieldNoDeleteUnlessNameReserved is a check function.
|
||||
var CheckFieldNoDeleteUnlessNameReserved = newMessagePairCheckFunc(checkFieldNoDeleteUnlessNameReserved)
|
||||
|
||||
func checkFieldNoDeleteUnlessNameReserved(add addFunc, previousMessage protosource.Message, message protosource.Message) error {
|
||||
return checkFieldNoDeleteWithRules(add, previousMessage, message, false, true)
|
||||
}
|
||||
|
||||
func checkFieldNoDeleteWithRules(add addFunc, previousMessage protosource.Message, message protosource.Message, allowIfNumberReserved bool, allowIfNameReserved bool) error {
|
||||
previousNumberToField, err := protosource.NumberToMessageField(previousMessage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
numberToField, err := protosource.NumberToMessageField(message)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for previousNumber, previousField := range previousNumberToField {
|
||||
if _, ok := numberToField[previousNumber]; !ok {
|
||||
if !isDeletedFieldAllowedWithRules(previousField, message, allowIfNumberReserved, allowIfNameReserved) {
|
||||
// otherwise prints as hex
|
||||
previousNumberString := strconv.FormatInt(int64(previousNumber), 10)
|
||||
suffix := ""
|
||||
if allowIfNumberReserved && allowIfNameReserved {
|
||||
return errors.New("both allowIfNumberReserved and allowIfNameReserved set")
|
||||
}
|
||||
if allowIfNumberReserved {
|
||||
suffix = fmt.Sprintf(` without reserving the number "%d"`, previousField.Number())
|
||||
}
|
||||
if allowIfNameReserved {
|
||||
suffix = fmt.Sprintf(` without reserving the name %q`, previousField.Name())
|
||||
}
|
||||
add(message, message.Location(), `Previously present field %q with name %q on message %q was deleted%s.`, previousNumberString, previousField.Name(), message.Name(), suffix)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func isDeletedFieldAllowedWithRules(previousField protosource.Field, message protosource.Message, allowIfNumberReserved bool, allowIfNameReserved bool) bool {
|
||||
return (allowIfNumberReserved && protosource.NumberInReservedRanges(previousField.Number(), message.ReservedTagRanges()...)) ||
|
||||
(allowIfNameReserved && protosource.NameInReservedNames(previousField.Name(), message.ReservedNames()...))
|
||||
}
|
||||
|
||||
// CheckFieldSameCType is a check function.
|
||||
var CheckFieldSameCType = newFieldPairCheckFunc(checkFieldSameCType)
|
||||
|
||||
func checkFieldSameCType(add addFunc, previousField protosource.Field, field protosource.Field) error {
|
||||
if previousField.CType() != field.CType() {
|
||||
// otherwise prints as hex
|
||||
numberString := strconv.FormatInt(int64(field.Number()), 10)
|
||||
add(field, withBackupLocation(field.CTypeLocation(), field.Location()), `Field %q with name %q on message %q changed option "ctype" from %q to %q.`, numberString, field.Name(), field.Message().Name(), previousField.CType().String(), field.CType().String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckFieldSameJSONName is a check function.
|
||||
var CheckFieldSameJSONName = newFieldPairCheckFunc(checkFieldSameJSONName)
|
||||
|
||||
func checkFieldSameJSONName(add addFunc, previousField protosource.Field, field protosource.Field) error {
|
||||
if previousField.JSONName() != field.JSONName() {
|
||||
// otherwise prints as hex
|
||||
numberString := strconv.FormatInt(int64(field.Number()), 10)
|
||||
add(field, withBackupLocation(field.JSONNameLocation(), field.Location()), `Field %q with name %q on message %q changed option "json_name" from %q to %q.`, numberString, field.Name(), field.Message().Name(), previousField.JSONName(), field.JSONName())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckFieldSameJSType is a check function.
|
||||
var CheckFieldSameJSType = newFieldPairCheckFunc(checkFieldSameJSType)
|
||||
|
||||
func checkFieldSameJSType(add addFunc, previousField protosource.Field, field protosource.Field) error {
|
||||
if previousField.JSType() != field.JSType() {
|
||||
// otherwise prints as hex
|
||||
numberString := strconv.FormatInt(int64(field.Number()), 10)
|
||||
add(field, withBackupLocation(field.JSTypeLocation(), field.Location()), `Field %q with name %q on message %q changed option "jstype" from %q to %q.`, numberString, field.Name(), field.Message().Name(), previousField.JSType().String(), field.JSType().String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckFieldSameLabel is a check function.
|
||||
var CheckFieldSameLabel = newFieldPairCheckFunc(checkFieldSameLabel)
|
||||
|
||||
func checkFieldSameLabel(add addFunc, previousField protosource.Field, field protosource.Field) error {
|
||||
if previousField.Label() != field.Label() {
|
||||
// otherwise prints as hex
|
||||
numberString := strconv.FormatInt(int64(field.Number()), 10)
|
||||
// TODO: specific label location
|
||||
add(field, field.Location(), `Field %q on message %q changed label from %q to %q.`, numberString, field.Message().Name(), previousField.Label().String(), field.Label().String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckFieldSameName is a check function.
|
||||
var CheckFieldSameName = newFieldPairCheckFunc(checkFieldSameName)
|
||||
|
||||
func checkFieldSameName(add addFunc, previousField protosource.Field, field protosource.Field) error {
|
||||
if previousField.Name() != field.Name() {
|
||||
// otherwise prints as hex
|
||||
numberString := strconv.FormatInt(int64(field.Number()), 10)
|
||||
add(field, field.NameLocation(), `Field %q on message %q changed name from %q to %q.`, numberString, field.Message().Name(), previousField.Name(), field.Name())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckFieldSameOneof is a check function.
|
||||
var CheckFieldSameOneof = newFieldPairCheckFunc(checkFieldSameOneof)
|
||||
|
||||
func checkFieldSameOneof(add addFunc, previousField protosource.Field, field protosource.Field) error {
|
||||
previousOneof := previousField.Oneof()
|
||||
oneof := field.Oneof()
|
||||
previousInsideOneof := previousOneof != nil
|
||||
insideOneof := oneof != nil
|
||||
if !previousInsideOneof && !insideOneof {
|
||||
return nil
|
||||
}
|
||||
if previousInsideOneof && insideOneof {
|
||||
if previousOneof.Name() != oneof.Name() {
|
||||
// otherwise prints as hex
|
||||
numberString := strconv.FormatInt(int64(field.Number()), 10)
|
||||
add(field, field.Location(), `Field %q on message %q moved from oneof %q to oneof %q.`, numberString, field.Message().Name(), previousOneof.Name(), oneof.Name())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
previous := "inside"
|
||||
current := "outside"
|
||||
if insideOneof {
|
||||
previous = "outside"
|
||||
current = "inside"
|
||||
}
|
||||
// otherwise prints as hex
|
||||
numberString := strconv.FormatInt(int64(field.Number()), 10)
|
||||
add(field, field.Location(), `Field %q on message %q moved from %s to %s a oneof.`, numberString, field.Message().Name(), previous, current)
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckFieldSameType is a check function.
|
||||
var CheckFieldSameType = newFieldPairCheckFunc(checkFieldSameType)
|
||||
|
||||
// TODO: locations not working for map entries
|
||||
// TODO: weird output for map entries:
|
||||
//
|
||||
// breaking_field_same_type/1.proto:1:1:Field "2" on message "SixEntry" changed type from ".a.One" to ".a.Two".
|
||||
// breaking_field_same_type/1.proto:1:1:Field "2" on message "SixEntry" changed type from ".a.One" to ".a.Two".
|
||||
// breaking_field_same_type/1.proto:1:1:Field "2" on message "SixEntry" changed type from ".a.One" to ".a.Two".
|
||||
// breaking_field_same_type/1.proto:8:3:Field "1" on message "Two" changed type from "int32" to "int64".
|
||||
// breaking_field_same_type/1.proto:9:3:Field "2" on message "Two" changed type from ".a.One" to ".a.Two".
|
||||
// breaking_field_same_type/1.proto:11:3:Field "4" on message "Two" changed type from ".a.One" to ".a.Two".
|
||||
// breaking_field_same_type/1.proto:12:3:Field "5" on message "Two" changed type from ".a.Two.FiveEntry" to ".a.Two".
|
||||
// breaking_field_same_type/1.proto:19:7:Field "1" on message "Five" changed type from "int32" to "int64".
|
||||
// breaking_field_same_type/1.proto:20:7:Field "2" on message "Five" changed type from ".a.One" to ".a.Two".
|
||||
// breaking_field_same_type/1.proto:22:7:Field "4" on message "Five" changed type from ".a.One" to ".a.Two".
|
||||
// breaking_field_same_type/1.proto:23:7:Field "5" on message "Five" changed type from ".a.Three.Four.Five.FiveEntry" to ".a.Two".
|
||||
// breaking_field_same_type/1.proto:36:5:Field "1" on message "Seven" changed type from "int32" to "int64".
|
||||
// breaking_field_same_type/1.proto:37:5:Field "2" on message "Seven" changed type from ".a.One" to ".a.Two".
|
||||
// breaking_field_same_type/1.proto:39:5:Field "4" on message "Seven" changed type from ".a.One" to ".a.Two".
|
||||
// breaking_field_same_type/1.proto:40:5:Field "5" on message "Seven" changed type from ".a.Three.Seven.FiveEntry" to ".a.Two".
|
||||
// breaking_field_same_type/2.proto:64:5:Field "1" on message "Nine" changed type from "int32" to "int64".
|
||||
// breaking_field_same_type/2.proto:65:5:Field "2" on message "Nine" changed type from ".a.One" to ".a.Nine".
|
||||
func checkFieldSameType(add addFunc, previousField protosource.Field, field protosource.Field) error {
|
||||
if previousField.Type() != field.Type() {
|
||||
// otherwise prints as hex
|
||||
previousNumberString := strconv.FormatInt(int64(previousField.Number()), 10)
|
||||
add(field, field.TypeLocation(), `Field %q on message %q changed type from %q to %q.`, previousNumberString, field.Message().Name(), previousField.Type().String(), field.Type().String())
|
||||
return nil
|
||||
}
|
||||
|
||||
switch field.Type() {
|
||||
case protosource.FieldDescriptorProtoTypeEnum, protosource.FieldDescriptorProtoTypeGroup, protosource.FieldDescriptorProtoTypeMessage:
|
||||
// otherwise prints as hex
|
||||
numberString := strconv.FormatInt(int64(previousField.Number()), 10)
|
||||
if previousField.TypeName() != field.TypeName() {
|
||||
add(
|
||||
field,
|
||||
field.TypeNameLocation(),
|
||||
`Field %q on message %q changed type from %q to %q.`,
|
||||
numberString,
|
||||
field.Message().Name(),
|
||||
strings.TrimPrefix(previousField.TypeName(), "."),
|
||||
strings.TrimPrefix(field.TypeName(), "."),
|
||||
)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckFileNoDelete is a check function.
|
||||
var CheckFileNoDelete = newFilesCheckFunc(checkFileNoDelete)
|
||||
|
||||
func checkFileNoDelete(add addFunc, previousFiles []protosource.File, files []protosource.File) error {
|
||||
previousFilePathToFile, err := protosource.FilePathToFile(previousFiles...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
filePathToFile, err := protosource.FilePathToFile(files...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for previousFilePath := range previousFilePathToFile {
|
||||
if _, ok := filePathToFile[previousFilePath]; !ok {
|
||||
add(nil, nil, `Previously present file %q was deleted.`, previousFilePath)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckFileSameCsharpNamespace is a check function.
|
||||
var CheckFileSameCsharpNamespace = newFilePairCheckFunc(checkFileSameCsharpNamespace)
|
||||
|
||||
func checkFileSameCsharpNamespace(add addFunc, previousFile protosource.File, file protosource.File) error {
|
||||
return checkFileSameValue(add, previousFile.CsharpNamespace(), file.CsharpNamespace(), file, file.CsharpNamespaceLocation(), `option "csharp_namespace"`)
|
||||
}
|
||||
|
||||
// CheckFileSameGoPackage is a check function.
|
||||
var CheckFileSameGoPackage = newFilePairCheckFunc(checkFileSameGoPackage)
|
||||
|
||||
func checkFileSameGoPackage(add addFunc, previousFile protosource.File, file protosource.File) error {
|
||||
return checkFileSameValue(add, previousFile.GoPackage(), file.GoPackage(), file, file.GoPackageLocation(), `option "go_package"`)
|
||||
}
|
||||
|
||||
// CheckFileSameJavaMultipleFiles is a check function.
|
||||
var CheckFileSameJavaMultipleFiles = newFilePairCheckFunc(checkFileSameJavaMultipleFiles)
|
||||
|
||||
func checkFileSameJavaMultipleFiles(add addFunc, previousFile protosource.File, file protosource.File) error {
|
||||
return checkFileSameValue(add, strconv.FormatBool(previousFile.JavaMultipleFiles()), strconv.FormatBool(file.JavaMultipleFiles()), file, file.JavaMultipleFilesLocation(), `option "java_multiple_files"`)
|
||||
}
|
||||
|
||||
// CheckFileSameJavaOuterClassname is a check function.
|
||||
var CheckFileSameJavaOuterClassname = newFilePairCheckFunc(checkFileSameJavaOuterClassname)
|
||||
|
||||
func checkFileSameJavaOuterClassname(add addFunc, previousFile protosource.File, file protosource.File) error {
|
||||
return checkFileSameValue(add, previousFile.JavaOuterClassname(), file.JavaOuterClassname(), file, file.JavaOuterClassnameLocation(), `option "java_outer_classname"`)
|
||||
}
|
||||
|
||||
// CheckFileSameJavaPackage is a check function.
|
||||
var CheckFileSameJavaPackage = newFilePairCheckFunc(checkFileSameJavaPackage)
|
||||
|
||||
func checkFileSameJavaPackage(add addFunc, previousFile protosource.File, file protosource.File) error {
|
||||
return checkFileSameValue(add, previousFile.JavaPackage(), file.JavaPackage(), file, file.JavaPackageLocation(), `option "java_package"`)
|
||||
}
|
||||
|
||||
// CheckFileSameJavaStringCheckUtf8 is a check function.
|
||||
var CheckFileSameJavaStringCheckUtf8 = newFilePairCheckFunc(checkFileSameJavaStringCheckUtf8)
|
||||
|
||||
func checkFileSameJavaStringCheckUtf8(add addFunc, previousFile protosource.File, file protosource.File) error {
|
||||
return checkFileSameValue(add, strconv.FormatBool(previousFile.JavaStringCheckUtf8()), strconv.FormatBool(file.JavaStringCheckUtf8()), file, file.JavaStringCheckUtf8Location(), `option "java_string_check_utf8"`)
|
||||
}
|
||||
|
||||
// CheckFileSameObjcClassPrefix is a check function.
|
||||
var CheckFileSameObjcClassPrefix = newFilePairCheckFunc(checkFileSameObjcClassPrefix)
|
||||
|
||||
func checkFileSameObjcClassPrefix(add addFunc, previousFile protosource.File, file protosource.File) error {
|
||||
return checkFileSameValue(add, previousFile.ObjcClassPrefix(), file.ObjcClassPrefix(), file, file.ObjcClassPrefixLocation(), `option "objc_class_prefix"`)
|
||||
}
|
||||
|
||||
// CheckFileSamePackage is a check function.
|
||||
var CheckFileSamePackage = newFilePairCheckFunc(checkFileSamePackage)
|
||||
|
||||
func checkFileSamePackage(add addFunc, previousFile protosource.File, file protosource.File) error {
|
||||
return checkFileSameValue(add, previousFile.Package(), file.Package(), file, file.PackageLocation(), `package`)
|
||||
}
|
||||
|
||||
// CheckFileSamePhpClassPrefix is a check function.
|
||||
var CheckFileSamePhpClassPrefix = newFilePairCheckFunc(checkFileSamePhpClassPrefix)
|
||||
|
||||
func checkFileSamePhpClassPrefix(add addFunc, previousFile protosource.File, file protosource.File) error {
|
||||
return checkFileSameValue(add, previousFile.PhpClassPrefix(), file.PhpClassPrefix(), file, file.PhpClassPrefixLocation(), `option "php_class_prefix"`)
|
||||
}
|
||||
|
||||
// CheckFileSamePhpNamespace is a check function.
|
||||
var CheckFileSamePhpNamespace = newFilePairCheckFunc(checkFileSamePhpNamespace)
|
||||
|
||||
func checkFileSamePhpNamespace(add addFunc, previousFile protosource.File, file protosource.File) error {
|
||||
return checkFileSameValue(add, previousFile.PhpNamespace(), file.PhpNamespace(), file, file.PhpNamespaceLocation(), `option "php_namespace"`)
|
||||
}
|
||||
|
||||
// CheckFileSamePhpMetadataNamespace is a check function.
|
||||
var CheckFileSamePhpMetadataNamespace = newFilePairCheckFunc(checkFileSamePhpMetadataNamespace)
|
||||
|
||||
func checkFileSamePhpMetadataNamespace(add addFunc, previousFile protosource.File, file protosource.File) error {
|
||||
return checkFileSameValue(add, previousFile.PhpMetadataNamespace(), file.PhpMetadataNamespace(), file, file.PhpMetadataNamespaceLocation(), `option "php_metadata_namespace"`)
|
||||
}
|
||||
|
||||
// CheckFileSameRubyPackage is a check function.
|
||||
var CheckFileSameRubyPackage = newFilePairCheckFunc(checkFileSameRubyPackage)
|
||||
|
||||
func checkFileSameRubyPackage(add addFunc, previousFile protosource.File, file protosource.File) error {
|
||||
return checkFileSameValue(add, previousFile.RubyPackage(), file.RubyPackage(), file, file.RubyPackageLocation(), `option "ruby_package"`)
|
||||
}
|
||||
|
||||
// CheckFileSameSwiftPrefix is a check function.
|
||||
var CheckFileSameSwiftPrefix = newFilePairCheckFunc(checkFileSameSwiftPrefix)
|
||||
|
||||
func checkFileSameSwiftPrefix(add addFunc, previousFile protosource.File, file protosource.File) error {
|
||||
return checkFileSameValue(add, previousFile.SwiftPrefix(), file.SwiftPrefix(), file, file.SwiftPrefixLocation(), `option "swift_prefix"`)
|
||||
}
|
||||
|
||||
// CheckFileSameOptimizeFor is a check function.
|
||||
var CheckFileSameOptimizeFor = newFilePairCheckFunc(checkFileSameOptimizeFor)
|
||||
|
||||
func checkFileSameOptimizeFor(add addFunc, previousFile protosource.File, file protosource.File) error {
|
||||
return checkFileSameValue(add, previousFile.OptimizeFor().String(), file.OptimizeFor().String(), file, file.OptimizeForLocation(), `option "optimize_for"`)
|
||||
}
|
||||
|
||||
// CheckFileSameCcGenericServices is a check function.
|
||||
var CheckFileSameCcGenericServices = newFilePairCheckFunc(checkFileSameCcGenericServices)
|
||||
|
||||
func checkFileSameCcGenericServices(add addFunc, previousFile protosource.File, file protosource.File) error {
|
||||
return checkFileSameValue(add, strconv.FormatBool(previousFile.CcGenericServices()), strconv.FormatBool(file.CcGenericServices()), file, file.CcGenericServicesLocation(), `option "cc_generic_services"`)
|
||||
}
|
||||
|
||||
// CheckFileSameJavaGenericServices is a check function.
|
||||
var CheckFileSameJavaGenericServices = newFilePairCheckFunc(checkFileSameJavaGenericServices)
|
||||
|
||||
func checkFileSameJavaGenericServices(add addFunc, previousFile protosource.File, file protosource.File) error {
|
||||
return checkFileSameValue(add, strconv.FormatBool(previousFile.JavaGenericServices()), strconv.FormatBool(file.JavaGenericServices()), file, file.JavaGenericServicesLocation(), `option "java_generic_services"`)
|
||||
}
|
||||
|
||||
// CheckFileSamePyGenericServices is a check function.
|
||||
var CheckFileSamePyGenericServices = newFilePairCheckFunc(checkFileSamePyGenericServices)
|
||||
|
||||
func checkFileSamePyGenericServices(add addFunc, previousFile protosource.File, file protosource.File) error {
|
||||
return checkFileSameValue(add, strconv.FormatBool(previousFile.PyGenericServices()), strconv.FormatBool(file.PyGenericServices()), file, file.PyGenericServicesLocation(), `option "py_generic_services"`)
|
||||
}
|
||||
|
||||
// CheckFileSamePhpGenericServices is a check function.
|
||||
var CheckFileSamePhpGenericServices = newFilePairCheckFunc(checkFileSamePhpGenericServices)
|
||||
|
||||
func checkFileSamePhpGenericServices(add addFunc, previousFile protosource.File, file protosource.File) error {
|
||||
return checkFileSameValue(add, strconv.FormatBool(previousFile.PhpGenericServices()), strconv.FormatBool(file.PhpGenericServices()), file, file.PhpGenericServicesLocation(), `option "php_generic_services"`)
|
||||
}
|
||||
|
||||
// CheckFileSameCcEnableArenas is a check function.
|
||||
var CheckFileSameCcEnableArenas = newFilePairCheckFunc(checkFileSameCcEnableArenas)
|
||||
|
||||
func checkFileSameCcEnableArenas(add addFunc, previousFile protosource.File, file protosource.File) error {
|
||||
return checkFileSameValue(add, strconv.FormatBool(previousFile.CcEnableArenas()), strconv.FormatBool(file.CcEnableArenas()), file, file.CcEnableArenasLocation(), `option "cc_enable_arenas"`)
|
||||
}
|
||||
|
||||
// CheckFileSameSyntax is a check function.
|
||||
var CheckFileSameSyntax = newFilePairCheckFunc(checkFileSameSyntax)
|
||||
|
||||
func checkFileSameSyntax(add addFunc, previousFile protosource.File, file protosource.File) error {
|
||||
return checkFileSameValue(add, previousFile.Syntax().String(), file.Syntax().String(), file, file.SyntaxLocation(), `syntax`)
|
||||
}
|
||||
|
||||
func checkFileSameValue(add addFunc, previousValue interface{}, value interface{}, file protosource.File, location protosource.Location, name string) error {
|
||||
if previousValue != value {
|
||||
add(file, location, `File %s changed from %q to %q.`, name, previousValue, value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckMessageNoDelete is a check function.
|
||||
var CheckMessageNoDelete = newFilePairCheckFunc(checkMessageNoDelete)
|
||||
|
||||
func checkMessageNoDelete(add addFunc, previousFile protosource.File, file protosource.File) error {
|
||||
previousNestedNameToMessage, err := protosource.NestedNameToMessage(previousFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nestedNameToMessage, err := protosource.NestedNameToMessage(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for previousNestedName := range previousNestedNameToMessage {
|
||||
if _, ok := nestedNameToMessage[previousNestedName]; !ok {
|
||||
descriptor, location := getDescriptorAndLocationForDeletedMessage(file, nestedNameToMessage, previousNestedName)
|
||||
add(descriptor, location, `Previously present message %q was deleted from file.`, previousNestedName)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckMessageNoRemoveStandardDescriptorAccessor is a check function.
|
||||
var CheckMessageNoRemoveStandardDescriptorAccessor = newMessagePairCheckFunc(checkMessageNoRemoveStandardDescriptorAccessor)
|
||||
|
||||
func checkMessageNoRemoveStandardDescriptorAccessor(add addFunc, previousMessage protosource.Message, message protosource.Message) error {
|
||||
previous := strconv.FormatBool(previousMessage.NoStandardDescriptorAccessor())
|
||||
current := strconv.FormatBool(message.NoStandardDescriptorAccessor())
|
||||
if previous == "false" && current == "true" {
|
||||
add(message, message.NoStandardDescriptorAccessorLocation(), `Message option "no_standard_descriptor_accessor" changed from %q to %q.`, previous, current)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckMessageSameMessageSetWireFormat is a check function.
|
||||
var CheckMessageSameMessageSetWireFormat = newMessagePairCheckFunc(checkMessageSameMessageSetWireFormat)
|
||||
|
||||
func checkMessageSameMessageSetWireFormat(add addFunc, previousMessage protosource.Message, message protosource.Message) error {
|
||||
previous := strconv.FormatBool(previousMessage.MessageSetWireFormat())
|
||||
current := strconv.FormatBool(message.MessageSetWireFormat())
|
||||
if previous != current {
|
||||
add(message, message.MessageSetWireFormatLocation(), `Message option "message_set_wire_format" changed from %q to %q.`, previous, current)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckOneofNoDelete is a check function.
|
||||
var CheckOneofNoDelete = newMessagePairCheckFunc(checkOneofNoDelete)
|
||||
|
||||
func checkOneofNoDelete(add addFunc, previousMessage protosource.Message, message protosource.Message) error {
|
||||
previousNameToOneof, err := protosource.NameToMessageOneof(previousMessage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nameToOneof, err := protosource.NameToMessageOneof(message)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for previousName := range previousNameToOneof {
|
||||
if _, ok := nameToOneof[previousName]; !ok {
|
||||
add(message, message.Location(), `Previously present oneof %q on message %q was deleted.`, previousName, message.Name())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckPackageEnumNoDelete is a check function.
|
||||
var CheckPackageEnumNoDelete = newFilesCheckFunc(checkPackageEnumNoDelete)
|
||||
|
||||
func checkPackageEnumNoDelete(add addFunc, previousFiles []protosource.File, files []protosource.File) error {
|
||||
previousPackageToNestedNameToEnum, err := protosource.PackageToNestedNameToEnum(previousFiles...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
packageToNestedNameToEnum, err := protosource.PackageToNestedNameToEnum(files...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// caching across loops
|
||||
var filePathToFile map[string]protosource.File
|
||||
for previousPackage, previousNestedNameToEnum := range previousPackageToNestedNameToEnum {
|
||||
if nestedNameToEnum, ok := packageToNestedNameToEnum[previousPackage]; ok {
|
||||
for previousNestedName, previousEnum := range previousNestedNameToEnum {
|
||||
if _, ok := nestedNameToEnum[previousNestedName]; !ok {
|
||||
// if cache not populated, populate it
|
||||
if filePathToFile == nil {
|
||||
filePathToFile, err = protosource.FilePathToFile(files...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// check if the file still exists
|
||||
file, ok := filePathToFile[previousEnum.File().Path()]
|
||||
if ok {
|
||||
// file exists, try to get a location to attach the error to
|
||||
descriptor, location, err := getDescriptorAndLocationForDeletedEnum(file, previousNestedName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
add(descriptor, location, `Previously present enum %q was deleted from package %q.`, previousNestedName, previousPackage)
|
||||
} else {
|
||||
// file does not exist, we don't know where the enum was deleted from
|
||||
add(nil, nil, `Previously present enum %q was deleted from package %q.`, previousNestedName, previousPackage)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckPackageMessageNoDelete is a check function.
|
||||
var CheckPackageMessageNoDelete = newFilesCheckFunc(checkPackageMessageNoDelete)
|
||||
|
||||
func checkPackageMessageNoDelete(add addFunc, previousFiles []protosource.File, files []protosource.File) error {
|
||||
previousPackageToNestedNameToMessage, err := protosource.PackageToNestedNameToMessage(previousFiles...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
packageToNestedNameToMessage, err := protosource.PackageToNestedNameToMessage(files...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// caching across loops
|
||||
var filePathToFile map[string]protosource.File
|
||||
for previousPackage, previousNestedNameToMessage := range previousPackageToNestedNameToMessage {
|
||||
if nestedNameToMessage, ok := packageToNestedNameToMessage[previousPackage]; ok {
|
||||
for previousNestedName, previousMessage := range previousNestedNameToMessage {
|
||||
if _, ok := nestedNameToMessage[previousNestedName]; !ok {
|
||||
// if cache not populated, populate it
|
||||
if filePathToFile == nil {
|
||||
filePathToFile, err = protosource.FilePathToFile(files...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// check if the file still exists
|
||||
file, ok := filePathToFile[previousMessage.File().Path()]
|
||||
if ok {
|
||||
// file exists, try to get a location to attach the error to
|
||||
descriptor, location := getDescriptorAndLocationForDeletedMessage(file, nestedNameToMessage, previousNestedName)
|
||||
add(descriptor, location, `Previously present message %q was deleted from package %q.`, previousNestedName, previousPackage)
|
||||
} else {
|
||||
// file does not exist, we don't know where the message was deleted from
|
||||
add(nil, nil, `Previously present message %q was deleted from package %q.`, previousNestedName, previousPackage)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckPackageNoDelete is a check function.
|
||||
var CheckPackageNoDelete = newFilesCheckFunc(checkPackageNoDelete)
|
||||
|
||||
func checkPackageNoDelete(add addFunc, previousFiles []protosource.File, files []protosource.File) error {
|
||||
previousPackageToFiles, err := protosource.PackageToFiles(previousFiles...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
packageToFiles, err := protosource.PackageToFiles(files...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for previousPackage := range previousPackageToFiles {
|
||||
if _, ok := packageToFiles[previousPackage]; !ok {
|
||||
add(nil, nil, `Previously present package %q was deleted.`, previousPackage)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckPackageServiceNoDelete is a check function.
|
||||
var CheckPackageServiceNoDelete = newFilesCheckFunc(checkPackageServiceNoDelete)
|
||||
|
||||
func checkPackageServiceNoDelete(add addFunc, previousFiles []protosource.File, files []protosource.File) error {
|
||||
previousPackageToNameToService, err := protosource.PackageToNameToService(previousFiles...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
packageToNameToService, err := protosource.PackageToNameToService(files...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// caching across loops
|
||||
var filePathToFile map[string]protosource.File
|
||||
for previousPackage, previousNameToService := range previousPackageToNameToService {
|
||||
if nameToService, ok := packageToNameToService[previousPackage]; ok {
|
||||
for previousName, previousService := range previousNameToService {
|
||||
if _, ok := nameToService[previousName]; !ok {
|
||||
// if cache not populated, populate it
|
||||
if filePathToFile == nil {
|
||||
filePathToFile, err = protosource.FilePathToFile(files...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// check if the file still exists
|
||||
file, ok := filePathToFile[previousService.File().Path()]
|
||||
if ok {
|
||||
// file exists
|
||||
add(file, nil, `Previously present service %q was deleted from package %q.`, previousName, previousPackage)
|
||||
} else {
|
||||
// file does not exist, we don't know where the service was deleted from
|
||||
// TODO: find the service and print that this moved?
|
||||
add(nil, nil, `Previously present service %q was deleted from package %q.`, previousName, previousPackage)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckReservedEnumNoDelete is a check function.
|
||||
var CheckReservedEnumNoDelete = newEnumPairCheckFunc(checkReservedEnumNoDelete)
|
||||
|
||||
func checkReservedEnumNoDelete(add addFunc, previousEnum protosource.Enum, enum protosource.Enum) error {
|
||||
previousStringToReservedRange := protosource.StringToReservedTagRange(previousEnum)
|
||||
stringToReservedRange := protosource.StringToReservedTagRange(enum)
|
||||
for previousString := range previousStringToReservedRange {
|
||||
if _, ok := stringToReservedRange[previousString]; !ok {
|
||||
add(enum, enum.Location(), `Previously present reserved range %q on enum %q was deleted.`, previousString, enum.Name())
|
||||
}
|
||||
}
|
||||
previousValueToReservedName := protosource.ValueToReservedName(previousEnum)
|
||||
valueToReservedName := protosource.ValueToReservedName(enum)
|
||||
for previousValue := range previousValueToReservedName {
|
||||
if _, ok := valueToReservedName[previousValue]; !ok {
|
||||
add(enum, enum.Location(), `Previously present reserved name %q on enum %q was deleted.`, previousValue, enum.Name())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckReservedMessageNoDelete is a check function.
|
||||
var CheckReservedMessageNoDelete = newMessagePairCheckFunc(checkReservedMessageNoDelete)
|
||||
|
||||
func checkReservedMessageNoDelete(add addFunc, previousMessage protosource.Message, message protosource.Message) error {
|
||||
previousStringToReservedRange := protosource.StringToReservedTagRange(previousMessage)
|
||||
stringToReservedRange := protosource.StringToReservedTagRange(message)
|
||||
for previousString := range previousStringToReservedRange {
|
||||
if _, ok := stringToReservedRange[previousString]; !ok {
|
||||
add(message, message.Location(), `Previously present reserved range %q on message %q was deleted.`, previousString, message.Name())
|
||||
}
|
||||
}
|
||||
previousValueToReservedName := protosource.ValueToReservedName(previousMessage)
|
||||
valueToReservedName := protosource.ValueToReservedName(message)
|
||||
for previousValue := range previousValueToReservedName {
|
||||
if _, ok := valueToReservedName[previousValue]; !ok {
|
||||
add(message, message.Location(), `Previously present reserved name %q on message %q was deleted.`, previousValue, message.Name())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckRPCNoDelete is a check function.
|
||||
var CheckRPCNoDelete = newServicePairCheckFunc(checkRPCNoDelete)
|
||||
|
||||
func checkRPCNoDelete(add addFunc, previousService protosource.Service, service protosource.Service) error {
|
||||
previousNameToMethod, err := protosource.NameToMethod(previousService)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nameToMethod, err := protosource.NameToMethod(service)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for previousName := range previousNameToMethod {
|
||||
if _, ok := nameToMethod[previousName]; !ok {
|
||||
add(service, service.Location(), `Previously present RPC %q on service %q was deleted.`, previousName, service.Name())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckRPCSameClientStreaming is a check function.
|
||||
var CheckRPCSameClientStreaming = newMethodPairCheckFunc(checkRPCSameClientStreaming)
|
||||
|
||||
func checkRPCSameClientStreaming(add addFunc, previousMethod protosource.Method, method protosource.Method) error {
|
||||
if previousMethod.ClientStreaming() != method.ClientStreaming() {
|
||||
previous := "streaming"
|
||||
current := "unary"
|
||||
if method.ClientStreaming() {
|
||||
previous = "unary"
|
||||
current = "streaming"
|
||||
}
|
||||
add(method, method.Location(), `RPC %q on service %q changed from client %s to client %s.`, method.Name(), method.Service().Name(), previous, current)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckRPCSameIdempotencyLevel is a check function.
|
||||
var CheckRPCSameIdempotencyLevel = newMethodPairCheckFunc(checkRPCSameIdempotencyLevel)
|
||||
|
||||
func checkRPCSameIdempotencyLevel(add addFunc, previousMethod protosource.Method, method protosource.Method) error {
|
||||
previous := previousMethod.IdempotencyLevel()
|
||||
current := method.IdempotencyLevel()
|
||||
if previous != current {
|
||||
add(method, method.IdempotencyLevelLocation(), `RPC %q on service %q changed option "idempotency_level" from %q to %q.`, method.Name(), method.Service().Name(), previous.String(), current.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckRPCSameRequestType is a check function.
|
||||
var CheckRPCSameRequestType = newMethodPairCheckFunc(checkRPCSameRequestType)
|
||||
|
||||
func checkRPCSameRequestType(add addFunc, previousMethod protosource.Method, method protosource.Method) error {
|
||||
if previousMethod.InputTypeName() != method.InputTypeName() {
|
||||
add(method, method.InputTypeLocation(), `RPC %q on service %q changed request type from %q to %q.`, method.Name(), method.Service().Name(), previousMethod.InputTypeName(), method.InputTypeName())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckRPCSameResponseType is a check function.
|
||||
var CheckRPCSameResponseType = newMethodPairCheckFunc(checkRPCSameResponseType)
|
||||
|
||||
func checkRPCSameResponseType(add addFunc, previousMethod protosource.Method, method protosource.Method) error {
|
||||
if previousMethod.OutputTypeName() != method.OutputTypeName() {
|
||||
add(method, method.OutputTypeLocation(), `RPC %q on service %q changed response type from %q to %q.`, method.Name(), method.Service().Name(), previousMethod.OutputTypeName(), method.OutputTypeName())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckRPCSameServerStreaming is a check function.
|
||||
var CheckRPCSameServerStreaming = newMethodPairCheckFunc(checkRPCSameServerStreaming)
|
||||
|
||||
func checkRPCSameServerStreaming(add addFunc, previousMethod protosource.Method, method protosource.Method) error {
|
||||
if previousMethod.ServerStreaming() != method.ServerStreaming() {
|
||||
previous := "streaming"
|
||||
current := "unary"
|
||||
if method.ServerStreaming() {
|
||||
previous = "unary"
|
||||
current = "streaming"
|
||||
}
|
||||
add(method, method.Location(), `RPC %q on service %q changed from server %s to server %s.`, method.Name(), method.Service().Name(), previous, current)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckServiceNoDelete is a check function.
|
||||
var CheckServiceNoDelete = newFilePairCheckFunc(checkServiceNoDelete)
|
||||
|
||||
func checkServiceNoDelete(add addFunc, previousFile protosource.File, file protosource.File) error {
|
||||
previousNameToService, err := protosource.NameToService(previousFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nameToService, err := protosource.NameToService(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for previousName := range previousNameToService {
|
||||
if _, ok := nameToService[previousName]; !ok {
|
||||
add(file, nil, `Previously present service %q was deleted from file.`, previousName)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
262
vendor/github.com/bufbuild/buf/internal/buf/bufcheck/bufbreaking/internal/bufbreakingcheck/util.go
generated
vendored
Normal file
262
vendor/github.com/bufbuild/buf/internal/buf/bufcheck/bufbreaking/internal/bufbreakingcheck/util.go
generated
vendored
Normal file
@ -0,0 +1,262 @@
|
||||
// Copyright 2020-2021 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 bufbreakingcheck
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/bufbuild/buf/internal/buf/bufanalysis"
|
||||
"github.com/bufbuild/buf/internal/buf/bufcheck/internal"
|
||||
"github.com/bufbuild/buf/internal/pkg/protosource"
|
||||
)
|
||||
|
||||
// addFunc adds a FileAnnotation.
|
||||
//
|
||||
// Both the Descriptor and Location can be nil.
|
||||
type addFunc func(protosource.Descriptor, protosource.Location, string, ...interface{})
|
||||
|
||||
func newFilesCheckFunc(
|
||||
f func(addFunc, []protosource.File, []protosource.File) error,
|
||||
) func(string, internal.IgnoreFunc, []protosource.File, []protosource.File) ([]bufanalysis.FileAnnotation, error) {
|
||||
return func(id string, ignoreFunc internal.IgnoreFunc, previousFiles []protosource.File, files []protosource.File) ([]bufanalysis.FileAnnotation, error) {
|
||||
helper := internal.NewHelper(id, ignoreFunc)
|
||||
if err := f(helper.AddFileAnnotationf, previousFiles, files); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return helper.FileAnnotations(), nil
|
||||
}
|
||||
}
|
||||
|
||||
func newFilePairCheckFunc(
|
||||
f func(addFunc, protosource.File, protosource.File) error,
|
||||
) func(string, internal.IgnoreFunc, []protosource.File, []protosource.File) ([]bufanalysis.FileAnnotation, error) {
|
||||
return newFilesCheckFunc(
|
||||
func(add addFunc, previousFiles []protosource.File, files []protosource.File) error {
|
||||
previousFilePathToFile, err := protosource.FilePathToFile(previousFiles...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
filePathToFile, err := protosource.FilePathToFile(files...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for previousFilePath, previousFile := range previousFilePathToFile {
|
||||
if file, ok := filePathToFile[previousFilePath]; ok {
|
||||
if err := f(add, previousFile, file); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func newEnumPairCheckFunc(
|
||||
f func(addFunc, protosource.Enum, protosource.Enum) error,
|
||||
) func(string, internal.IgnoreFunc, []protosource.File, []protosource.File) ([]bufanalysis.FileAnnotation, error) {
|
||||
return newFilesCheckFunc(
|
||||
func(add addFunc, previousFiles []protosource.File, files []protosource.File) error {
|
||||
previousFullNameToEnum, err := protosource.FullNameToEnum(previousFiles...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fullNameToEnum, err := protosource.FullNameToEnum(files...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for previousFullName, previousEnum := range previousFullNameToEnum {
|
||||
if enum, ok := fullNameToEnum[previousFullName]; ok {
|
||||
if err := f(add, previousEnum, enum); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// compares all the enums that are of the same number
|
||||
// map is from name to EnumValue for the given number
|
||||
func newEnumValuePairCheckFunc(
|
||||
f func(addFunc, map[string]protosource.EnumValue, map[string]protosource.EnumValue) error,
|
||||
) func(string, internal.IgnoreFunc, []protosource.File, []protosource.File) ([]bufanalysis.FileAnnotation, error) {
|
||||
return newEnumPairCheckFunc(
|
||||
func(add addFunc, previousEnum protosource.Enum, enum protosource.Enum) error {
|
||||
previousNumberToNameToEnumValue, err := protosource.NumberToNameToEnumValue(previousEnum)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
numberToNameToEnumValue, err := protosource.NumberToNameToEnumValue(enum)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for previousNumber, previousNameToEnumValue := range previousNumberToNameToEnumValue {
|
||||
if nameToEnumValue, ok := numberToNameToEnumValue[previousNumber]; ok {
|
||||
if err := f(add, previousNameToEnumValue, nameToEnumValue); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func newMessagePairCheckFunc(
|
||||
f func(addFunc, protosource.Message, protosource.Message) error,
|
||||
) func(string, internal.IgnoreFunc, []protosource.File, []protosource.File) ([]bufanalysis.FileAnnotation, error) {
|
||||
return newFilesCheckFunc(
|
||||
func(add addFunc, previousFiles []protosource.File, files []protosource.File) error {
|
||||
previousFullNameToMessage, err := protosource.FullNameToMessage(previousFiles...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fullNameToMessage, err := protosource.FullNameToMessage(files...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for previousFullName, previousMessage := range previousFullNameToMessage {
|
||||
if message, ok := fullNameToMessage[previousFullName]; ok {
|
||||
if err := f(add, previousMessage, message); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func newFieldPairCheckFunc(
|
||||
f func(addFunc, protosource.Field, protosource.Field) error,
|
||||
) func(string, internal.IgnoreFunc, []protosource.File, []protosource.File) ([]bufanalysis.FileAnnotation, error) {
|
||||
return newMessagePairCheckFunc(
|
||||
func(add addFunc, previousMessage protosource.Message, message protosource.Message) error {
|
||||
previousNumberToField, err := protosource.NumberToMessageField(previousMessage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
numberToField, err := protosource.NumberToMessageField(message)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for previousNumber, previousField := range previousNumberToField {
|
||||
if field, ok := numberToField[previousNumber]; ok {
|
||||
if err := f(add, previousField, field); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func newServicePairCheckFunc(
|
||||
f func(addFunc, protosource.Service, protosource.Service) error,
|
||||
) func(string, internal.IgnoreFunc, []protosource.File, []protosource.File) ([]bufanalysis.FileAnnotation, error) {
|
||||
return newFilesCheckFunc(
|
||||
func(add addFunc, previousFiles []protosource.File, files []protosource.File) error {
|
||||
previousFullNameToService, err := protosource.FullNameToService(previousFiles...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fullNameToService, err := protosource.FullNameToService(files...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for previousFullName, previousService := range previousFullNameToService {
|
||||
if service, ok := fullNameToService[previousFullName]; ok {
|
||||
if err := f(add, previousService, service); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func newMethodPairCheckFunc(
|
||||
f func(addFunc, protosource.Method, protosource.Method) error,
|
||||
) func(string, internal.IgnoreFunc, []protosource.File, []protosource.File) ([]bufanalysis.FileAnnotation, error) {
|
||||
return newServicePairCheckFunc(
|
||||
func(add addFunc, previousService protosource.Service, service protosource.Service) error {
|
||||
previousNameToMethod, err := protosource.NameToMethod(previousService)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nameToMethod, err := protosource.NameToMethod(service)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for previousName, previousMethod := range previousNameToMethod {
|
||||
if method, ok := nameToMethod[previousName]; ok {
|
||||
if err := f(add, previousMethod, method); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func getDescriptorAndLocationForDeletedEnum(file protosource.File, previousNestedName string) (protosource.Descriptor, protosource.Location, error) {
|
||||
if strings.Contains(previousNestedName, ".") {
|
||||
nestedNameToMessage, err := protosource.NestedNameToMessage(file)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
split := strings.Split(previousNestedName, ".")
|
||||
for i := len(split) - 1; i > 0; i-- {
|
||||
if message, ok := nestedNameToMessage[strings.Join(split[0:i], ".")]; ok {
|
||||
return message, message.Location(), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return file, nil, nil
|
||||
}
|
||||
|
||||
func getDescriptorAndLocationForDeletedMessage(file protosource.File, nestedNameToMessage map[string]protosource.Message, previousNestedName string) (protosource.Descriptor, protosource.Location) {
|
||||
if strings.Contains(previousNestedName, ".") {
|
||||
split := strings.Split(previousNestedName, ".")
|
||||
for i := len(split) - 1; i > 0; i-- {
|
||||
if message, ok := nestedNameToMessage[strings.Join(split[0:i], ".")]; ok {
|
||||
return message, message.Location()
|
||||
}
|
||||
}
|
||||
}
|
||||
return file, nil
|
||||
}
|
||||
|
||||
func getSortedEnumValueNames(nameToEnumValue map[string]protosource.EnumValue) []string {
|
||||
names := make([]string, 0, len(nameToEnumValue))
|
||||
for name := range nameToEnumValue {
|
||||
names = append(names, name)
|
||||
}
|
||||
sort.Strings(names)
|
||||
return names
|
||||
}
|
||||
|
||||
func withBackupLocation(primary protosource.Location, secondary protosource.Location) protosource.Location {
|
||||
if primary != nil {
|
||||
return primary
|
||||
}
|
||||
return secondary
|
||||
}
|
28
vendor/github.com/bufbuild/buf/internal/buf/bufcheck/bufbreaking/internal/bufbreakingv1beta1/bufbreakingv1beta1.go
generated
vendored
Normal file
28
vendor/github.com/bufbuild/buf/internal/buf/bufcheck/bufbreaking/internal/bufbreakingv1beta1/bufbreakingv1beta1.go
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2020-2021 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 bufbreakingv1beta1 contains the VersionSpec for v1beta1.
|
||||
//
|
||||
// It uses bufbreakingfunc and bufbreakingbuild.
|
||||
package bufbreakingv1beta1
|
||||
|
||||
import "github.com/bufbuild/buf/internal/buf/bufcheck/internal"
|
||||
|
||||
// VersionSpec is the version specification for v1beta1.
|
||||
var VersionSpec = &internal.VersionSpec{
|
||||
RuleBuilders: v1beta1RuleBuilders,
|
||||
DefaultCategories: v1beta1DefaultCategories,
|
||||
AllCategories: v1beta1AllCategories,
|
||||
IDToCategories: v1beta1IDToCategories,
|
||||
}
|
325
vendor/github.com/bufbuild/buf/internal/buf/bufcheck/bufbreaking/internal/bufbreakingv1beta1/vars.go
generated
vendored
Normal file
325
vendor/github.com/bufbuild/buf/internal/buf/bufcheck/bufbreaking/internal/bufbreakingv1beta1/vars.go
generated
vendored
Normal file
@ -0,0 +1,325 @@
|
||||
// Copyright 2020-2021 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 bufbreakingv1beta1
|
||||
|
||||
import (
|
||||
"github.com/bufbuild/buf/internal/buf/bufcheck/bufbreaking/internal/bufbreakingbuild"
|
||||
"github.com/bufbuild/buf/internal/buf/bufcheck/internal"
|
||||
)
|
||||
|
||||
var (
|
||||
// v1beta1RuleBuilders are the rule builders.
|
||||
v1beta1RuleBuilders = []*internal.RuleBuilder{
|
||||
bufbreakingbuild.EnumNoDeleteRuleBuilder,
|
||||
bufbreakingbuild.EnumValueNoDeleteRuleBuilder,
|
||||
bufbreakingbuild.EnumValueNoDeleteUnlessNameReservedRuleBuilder,
|
||||
bufbreakingbuild.EnumValueNoDeleteUnlessNumberReservedRuleBuilder,
|
||||
bufbreakingbuild.EnumValueSameNameRuleBuilder,
|
||||
bufbreakingbuild.ExtensionMessageNoDeleteRuleBuilder,
|
||||
bufbreakingbuild.FieldNoDeleteRuleBuilder,
|
||||
bufbreakingbuild.FieldNoDeleteUnlessNameReservedRuleBuilder,
|
||||
bufbreakingbuild.FieldNoDeleteUnlessNumberReservedRuleBuilder,
|
||||
bufbreakingbuild.FieldSameCTypeRuleBuilder,
|
||||
bufbreakingbuild.FieldSameJSONNameRuleBuilder,
|
||||
bufbreakingbuild.FieldSameJSTypeRuleBuilder,
|
||||
bufbreakingbuild.FieldSameLabelRuleBuilder,
|
||||
bufbreakingbuild.FieldSameNameRuleBuilder,
|
||||
bufbreakingbuild.FieldSameOneofRuleBuilder,
|
||||
bufbreakingbuild.FieldSameTypeRuleBuilder,
|
||||
bufbreakingbuild.FileNoDeleteRuleBuilder,
|
||||
bufbreakingbuild.FileSameCsharpNamespaceRuleBuilder,
|
||||
bufbreakingbuild.FileSameGoPackageRuleBuilder,
|
||||
bufbreakingbuild.FileSameJavaMultipleFilesRuleBuilder,
|
||||
bufbreakingbuild.FileSameJavaOuterClassnameRuleBuilder,
|
||||
bufbreakingbuild.FileSameJavaPackageRuleBuilder,
|
||||
bufbreakingbuild.FileSameJavaStringCheckUtf8RuleBuilder,
|
||||
bufbreakingbuild.FileSameObjcClassPrefixRuleBuilder,
|
||||
bufbreakingbuild.FileSamePackageRuleBuilder,
|
||||
bufbreakingbuild.FileSamePhpClassPrefixRuleBuilder,
|
||||
bufbreakingbuild.FileSamePhpMetadataNamespaceRuleBuilder,
|
||||
bufbreakingbuild.FileSamePhpNamespaceRuleBuilder,
|
||||
bufbreakingbuild.FileSameRubyPackageRuleBuilder,
|
||||
bufbreakingbuild.FileSameSwiftPrefixRuleBuilder,
|
||||
bufbreakingbuild.FileSameOptimizeForRuleBuilder,
|
||||
bufbreakingbuild.FileSameCcGenericServicesRuleBuilder,
|
||||
bufbreakingbuild.FileSameJavaGenericServicesRuleBuilder,
|
||||
bufbreakingbuild.FileSamePyGenericServicesRuleBuilder,
|
||||
bufbreakingbuild.FileSamePhpGenericServicesRuleBuilder,
|
||||
bufbreakingbuild.FileSameCcEnableArenasRuleBuilder,
|
||||
bufbreakingbuild.FileSameSyntaxRuleBuilder,
|
||||
bufbreakingbuild.MessageNoDeleteRuleBuilder,
|
||||
bufbreakingbuild.MessageNoRemoveStandardDescriptorAccessorRuleBuilder,
|
||||
bufbreakingbuild.MessageSameMessageSetWireFormatRuleBuilder,
|
||||
bufbreakingbuild.OneofNoDeleteRuleBuilder,
|
||||
bufbreakingbuild.PackageEnumNoDeleteRuleBuilder,
|
||||
bufbreakingbuild.PackageMessageNoDeleteRuleBuilder,
|
||||
bufbreakingbuild.PackageNoDeleteRuleBuilder,
|
||||
bufbreakingbuild.PackageServiceNoDeleteRuleBuilder,
|
||||
bufbreakingbuild.ReservedEnumNoDeleteRuleBuilder,
|
||||
bufbreakingbuild.ReservedMessageNoDeleteRuleBuilder,
|
||||
bufbreakingbuild.RPCNoDeleteRuleBuilder,
|
||||
bufbreakingbuild.RPCSameClientStreamingRuleBuilder,
|
||||
bufbreakingbuild.RPCSameIdempotencyLevelRuleBuilder,
|
||||
bufbreakingbuild.RPCSameRequestTypeRuleBuilder,
|
||||
bufbreakingbuild.RPCSameResponseTypeRuleBuilder,
|
||||
bufbreakingbuild.RPCSameServerStreamingRuleBuilder,
|
||||
bufbreakingbuild.ServiceNoDeleteRuleBuilder,
|
||||
}
|
||||
|
||||
// v1beta1DefaultCategories are the default categories.
|
||||
v1beta1DefaultCategories = []string{
|
||||
"FILE",
|
||||
}
|
||||
// v1beta1AllCategories are all categories.
|
||||
v1beta1AllCategories = []string{
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
"WIRE_JSON",
|
||||
"WIRE",
|
||||
}
|
||||
// v1beta1IDToCategories are the revision 1 ID to categories.
|
||||
v1beta1IDToCategories = map[string][]string{
|
||||
"ENUM_NO_DELETE": {
|
||||
"FILE",
|
||||
},
|
||||
"ENUM_VALUE_NO_DELETE": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"ENUM_VALUE_NO_DELETE_UNLESS_NAME_RESERVED": {
|
||||
"WIRE_JSON",
|
||||
},
|
||||
"ENUM_VALUE_NO_DELETE_UNLESS_NUMBER_RESERVED": {
|
||||
"WIRE_JSON",
|
||||
"WIRE",
|
||||
},
|
||||
"ENUM_VALUE_SAME_NAME": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
"WIRE_JSON",
|
||||
},
|
||||
"EXTENSION_MESSAGE_NO_DELETE": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"FIELD_NO_DELETE": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"FIELD_NO_DELETE_UNLESS_NAME_RESERVED": {
|
||||
"WIRE_JSON",
|
||||
},
|
||||
"FIELD_NO_DELETE_UNLESS_NUMBER_RESERVED": {
|
||||
"WIRE_JSON",
|
||||
"WIRE",
|
||||
},
|
||||
"FIELD_SAME_CTYPE": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"FIELD_SAME_JSON_NAME": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
"WIRE_JSON",
|
||||
},
|
||||
"FIELD_SAME_JSTYPE": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"FIELD_SAME_LABEL": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
"WIRE_JSON",
|
||||
"WIRE",
|
||||
},
|
||||
"FIELD_SAME_NAME": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
"WIRE_JSON",
|
||||
},
|
||||
"FIELD_SAME_ONEOF": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
"WIRE_JSON",
|
||||
"WIRE",
|
||||
},
|
||||
"FIELD_SAME_TYPE": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
"WIRE_JSON",
|
||||
"WIRE",
|
||||
},
|
||||
"FILE_NO_DELETE": {
|
||||
"FILE",
|
||||
},
|
||||
"FILE_SAME_CSHARP_NAMESPACE": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"FILE_SAME_GO_PACKAGE": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"FILE_SAME_JAVA_MULTIPLE_FILES": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"FILE_SAME_JAVA_OUTER_CLASSNAME": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"FILE_SAME_JAVA_PACKAGE": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"FILE_SAME_JAVA_STRING_CHECK_UTF8": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"FILE_SAME_OBJC_CLASS_PREFIX": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"FILE_SAME_PACKAGE": {
|
||||
"FILE",
|
||||
},
|
||||
"FILE_SAME_PHP_CLASS_PREFIX": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"FILE_SAME_PHP_METADATA_NAMESPACE": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"FILE_SAME_PHP_NAMESPACE": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"FILE_SAME_RUBY_PACKAGE": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"FILE_SAME_SWIFT_PREFIX": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"FILE_SAME_OPTIMIZE_FOR": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"FILE_SAME_CC_GENERIC_SERVICES": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"FILE_SAME_JAVA_GENERIC_SERVICES": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"FILE_SAME_PY_GENERIC_SERVICES": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"FILE_SAME_PHP_GENERIC_SERVICES": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"FILE_SAME_CC_ENABLE_ARENAS": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"FILE_SAME_SYNTAX": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"MESSAGE_NO_DELETE": {
|
||||
"FILE",
|
||||
},
|
||||
"MESSAGE_NO_REMOVE_STANDARD_DESCRIPTOR_ACCESSOR": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"MESSAGE_SAME_MESSAGE_SET_WIRE_FORMAT": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
"WIRE_JSON",
|
||||
"WIRE",
|
||||
},
|
||||
"ONEOF_NO_DELETE": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"PACKAGE_ENUM_NO_DELETE": {
|
||||
"PACKAGE",
|
||||
},
|
||||
"PACKAGE_MESSAGE_NO_DELETE": {
|
||||
"PACKAGE",
|
||||
},
|
||||
"PACKAGE_NO_DELETE": {
|
||||
"PACKAGE",
|
||||
},
|
||||
"PACKAGE_SERVICE_NO_DELETE": {
|
||||
"PACKAGE",
|
||||
},
|
||||
"RESERVED_ENUM_NO_DELETE": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
"WIRE_JSON",
|
||||
"WIRE",
|
||||
},
|
||||
"RESERVED_MESSAGE_NO_DELETE": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
"WIRE_JSON",
|
||||
"WIRE",
|
||||
},
|
||||
"RPC_NO_DELETE": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
},
|
||||
"RPC_SAME_CLIENT_STREAMING": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
"WIRE_JSON",
|
||||
"WIRE",
|
||||
},
|
||||
"RPC_SAME_IDEMPOTENCY_LEVEL": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
"WIRE_JSON",
|
||||
"WIRE",
|
||||
},
|
||||
"RPC_SAME_REQUEST_TYPE": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
"WIRE_JSON",
|
||||
"WIRE",
|
||||
},
|
||||
"RPC_SAME_RESPONSE_TYPE": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
"WIRE_JSON",
|
||||
"WIRE",
|
||||
},
|
||||
"RPC_SAME_SERVER_STREAMING": {
|
||||
"FILE",
|
||||
"PACKAGE",
|
||||
"WIRE_JSON",
|
||||
"WIRE",
|
||||
},
|
||||
"SERVICE_NO_DELETE": {
|
||||
"FILE",
|
||||
},
|
||||
}
|
||||
)
|
51
vendor/github.com/bufbuild/buf/internal/buf/bufcheck/bufbreaking/rule.go
generated
vendored
Normal file
51
vendor/github.com/bufbuild/buf/internal/buf/bufcheck/bufbreaking/rule.go
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright 2020-2021 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 bufbreaking
|
||||
|
||||
import "github.com/bufbuild/buf/internal/buf/bufcheck/internal"
|
||||
|
||||
type rule struct {
|
||||
*internal.Rule
|
||||
}
|
||||
|
||||
func newRule(internalRule *internal.Rule) *rule {
|
||||
return &rule{Rule: internalRule}
|
||||
}
|
||||
|
||||
func (c *rule) internalBreaking() *internal.Rule {
|
||||
return c.Rule
|
||||
}
|
||||
|
||||
func internalRulesToRules(internalRules []*internal.Rule) []Rule {
|
||||
if internalRules == nil {
|
||||
return nil
|
||||
}
|
||||
rules := make([]Rule, len(internalRules))
|
||||
for i, internalRule := range internalRules {
|
||||
rules[i] = newRule(internalRule)
|
||||
}
|
||||
return rules
|
||||
}
|
||||
|
||||
func rulesToInternalRules(rules []Rule) []*internal.Rule {
|
||||
if rules == nil {
|
||||
return nil
|
||||
}
|
||||
internalRules := make([]*internal.Rule, len(rules))
|
||||
for i, rule := range rules {
|
||||
internalRules[i] = rule.internalBreaking()
|
||||
}
|
||||
return internalRules
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user