diff --git a/controller/gettargetgraph_test.go b/controller/gettargetgraph_test.go index db957fdb..1c13d549 100644 --- a/controller/gettargetgraph_test.go +++ b/controller/gettargetgraph_test.go @@ -57,8 +57,8 @@ func TestGetTargetGraph_CacheMiss_NoSend(t *testing.T) { Remote: "repo:go-code", BaseSha: "sha", Requests: []*pb.Request{ - {Url: "github://repo/1", Commit: "abc111"}, - {Url: "github://repo/2", Commit: "abc222"}, + {Url: "github://github.com/org/repo/pull/1/1111111111111111111111111111111111111111"}, + {Url: "github://github.com/org/repo/pull/2/2222222222222222222222222222222222222222"}, }, }, } @@ -83,8 +83,8 @@ func TestGetTargetGraph_StorageError_Propagates(t *testing.T) { Remote: "repo:go-code", BaseSha: "sha", Requests: []*pb.Request{ - {Url: "github://repo/1", Commit: "abc111"}, - {Url: "github://repo/2", Commit: "abc222"}, + {Url: "github://github.com/org/repo/pull/1/1111111111111111111111111111111111111111"}, + {Url: "github://github.com/org/repo/pull/2/2222222222222222222222222222222222222222"}, }, }, }, stream) @@ -110,8 +110,8 @@ func TestGetTargetGraph_DecodeError_ReturnsError(t *testing.T) { Remote: "repo:go-code", BaseSha: "sha", Requests: []*pb.Request{ - {Url: "github://repo/1", Commit: "abc111"}, - {Url: "github://repo/2", Commit: "abc222"}, + {Url: "github://github.com/org/repo/pull/1/1111111111111111111111111111111111111111"}, + {Url: "github://github.com/org/repo/pull/2/2222222222222222222222222222222222222222"}, }, }, }, stream) @@ -141,8 +141,8 @@ func TestGetTargetGraph_SendsWhenItemPresent(t *testing.T) { Remote: "repo:go-code", BaseSha: "sha", Requests: []*pb.Request{ - {Url: "github://repo/1", Commit: "abc111"}, - {Url: "github://repo/2", Commit: "abc222"}, + {Url: "github://github.com/org/repo/pull/1/1111111111111111111111111111111111111111"}, + {Url: "github://github.com/org/repo/pull/2/2222222222222222222222222222222222222222"}, }, }, }, stream) @@ -163,8 +163,8 @@ func TestGetTargetGraph_BuildDescriptionMissingRequiredFields_ReturnsError(t *te Strategy: pb.COMPUTATION_STRATEGY_UNSET, Remote: "repo:go-code", Requests: []*pb.Request{ - {Url: "github://repo/1", Commit: "abc111"}, - {Url: "github://repo/2", Commit: "abc222"}, + {Url: "github://github.com/org/repo/pull/1/1111111111111111111111111111111111111111"}, + {Url: "github://github.com/org/repo/pull/2/2222222222222222222222222222222222222222"}, }, }, }, stream) diff --git a/core/cachekey/cachekey_test.go b/core/cachekey/cachekey_test.go index 48db2da6..f38006d4 100644 --- a/core/cachekey/cachekey_test.go +++ b/core/cachekey/cachekey_test.go @@ -54,8 +54,8 @@ func TestGetTreehashCachePath(t *testing.T) { Remote: "git@github:uber/tango", BaseSha: "deadbeef", ChangeRequests: []entity.ChangeRequest{ - {URL: "github://org/repo/pull/1", Commit: "abc"}, - {URL: "custom://foo/bar", Commit: "def"}, + {URL: "github://github.com/org/repo/pull/1/1111111111111111111111111111111111111111"}, + {URL: "github://github.com/org/repo/pull/2/2222222222222222222222222222222222222222"}, }, } got := GetTreehashCachePath(desc) diff --git a/core/cachekey/treehash_rapid_test.go b/core/cachekey/treehash_rapid_test.go index c9fb0089..0eed349d 100644 --- a/core/cachekey/treehash_rapid_test.go +++ b/core/cachekey/treehash_rapid_test.go @@ -22,19 +22,21 @@ import ( "pgregory.net/rapid" ) -func TestGetTreehashCachePath_commitAffectsKey(t *testing.T) { +func TestGetTreehashCachePath_headSHAAffectsKey(t *testing.T) { rapid.Check(t, func(t *rapid.T) { - commit := rapid.StringMatching(`[a-z]+`).Draw(t, "commit") + sha := rapid.StringMatching(`[0-9a-f]{40}`).Draw(t, "sha") + otherSHA := rapid.StringMatching(`[0-9a-f]{40}`).Filter(func(s string) bool { return s != sha }).Draw(t, "otherSHA") build := entity.BuildDescription{ Remote: "git@github:uber/tango", BaseSha: "base", ChangeRequests: []entity.ChangeRequest{ - {URL: "github://uber/tango/pull/1", Commit: commit}, + {URL: "github://github.com/uber/tango/pull/1/" + sha}, }, } changed := build - changed.ChangeRequests = append([]entity.ChangeRequest(nil), build.ChangeRequests...) - changed.ChangeRequests[0].Commit = commit + "x" + changed.ChangeRequests = []entity.ChangeRequest{ + {URL: "github://github.com/uber/tango/pull/1/" + otherSHA}, + } require.NotEqual(t, GetTreehashCachePath(build), GetTreehashCachePath(changed)) }) @@ -42,14 +44,14 @@ func TestGetTreehashCachePath_commitAffectsKey(t *testing.T) { func TestGetTreehashCachePath_changeRequestOrderAffectsKey(t *testing.T) { rapid.Check(t, func(t *rapid.T) { - firstCommit := rapid.StringMatching(`[a-z]+`).Draw(t, "firstCommit") - secondCommit := rapid.StringMatching(`[a-z]+`).Draw(t, "secondCommit") + firstSHA := rapid.StringMatching(`[0-9a-f]{40}`).Draw(t, "firstSHA") + secondSHA := rapid.StringMatching(`[0-9a-f]{40}`).Filter(func(s string) bool { return s != firstSHA }).Draw(t, "secondSHA") build := entity.BuildDescription{ Remote: "git@github:uber/tango", BaseSha: "base", ChangeRequests: []entity.ChangeRequest{ - {URL: "github://uber/tango/pull/1", Commit: firstCommit}, - {URL: "github://uber/tango/pull/2", Commit: secondCommit}, + {URL: "github://github.com/uber/tango/pull/1/" + firstSHA}, + {URL: "github://github.com/uber/tango/pull/2/" + secondSHA}, }, } swapped := build diff --git a/core/changeuri/BUILD.bazel b/core/changeuri/BUILD.bazel new file mode 100644 index 00000000..2a735d1b --- /dev/null +++ b/core/changeuri/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "changeuri", + srcs = ["changeuri.go"], + importpath = "github.com/uber/tango/core/changeuri", + visibility = ["//visibility:public"], +) + +go_test( + name = "changeuri_test", + srcs = ["changeuri_test.go"], + embed = [":changeuri"], + deps = [ + "@com_github_stretchr_testify//assert", + "@com_github_stretchr_testify//require", + "@net_pgregory_rapid//:rapid", + ], +) diff --git a/core/changeuri/changeuri.go b/core/changeuri/changeuri.go new file mode 100644 index 00000000..3464f2ca --- /dev/null +++ b/core/changeuri/changeuri.go @@ -0,0 +1,181 @@ +// Copyright (c) 2026 Uber 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 changeuri parses and validates change URIs — the system-wide +// identity of a code change, per the submitqueue change-URI RFC +// (https://github.com/uber/submitqueue/blob/main/doc/rfc/change-uri.md). +// +// A change URI is an RFC 3986 URI of the form scheme://{host[:port]}/{path} +// whose path pins the change to an exact code state. Only the GitHub pull +// request scheme is supported: +// +// github://{host[:port]}/{org}/{repo}/pull/{pr}/{head_sha} +// +// URIs are compared as opaque strings everywhere (cache keys, correlation +// keys), so exactly one spelling per change is valid. Parse validates the +// canonical form and rejects everything else — it never normalizes, because +// normalization applied at one entry point and skipped at another lets two +// spellings of one change into the system. +package changeuri + +import ( + "fmt" + "net/url" + "strings" +) + +// Scheme is the URI scheme for GitHub pull requests. +const Scheme = "github" + +// PullRequest is the parsed form of a canonical GitHub pull request URI. +// Re-serializing with String yields the original URI byte-for-byte. +type PullRequest struct { + // Host is the provider instance as host[:port]. The hostname is + // lowercase; the port, when present, is digits only and kept verbatim. + Host string + // Org is the organization path within the instance. It may span + // multiple path segments (e.g. "uber/frontend") and is kept verbatim. + Org string + // Repo is the repository name, kept verbatim. + Repo string + // Number is the pull request number: a positive integer without + // leading zeros, kept as a string to preserve the canonical spelling. + Number string + // HeadSHA is the PR's head commit at submission time: the full + // 40-character lowercase hex form. It pins the exact code state the + // URI identifies. + HeadSHA string +} + +// String serializes the pull request back to its canonical URI form. +func (p PullRequest) String() string { + return Scheme + "://" + p.Host + "/" + p.Org + "/" + p.Repo + "/pull/" + p.Number + "/" + p.HeadSHA +} + +// Parse validates raw as a canonical GitHub pull request change URI and +// returns its parsed form. Non-canonical spellings (uppercase host, +// abbreviated or uppercase SHA, leading-zero PR number, query, fragment, +// userinfo, empty path segments) are rejected, never normalized. +func Parse(raw string) (PullRequest, error) { + u, err := url.Parse(raw) + if err != nil { + return PullRequest{}, fmt.Errorf("parse change URI: %w", err) + } + if err := validateURL(raw, u); err != nil { + return PullRequest{}, err + } + + // {org…}/{repo}/pull/{pr}/{head_sha}: org spans one or more segments, + // so the layout is anchored from the end of the path. + segments := strings.Split(strings.TrimPrefix(u.EscapedPath(), "/"), "/") + if len(segments) < 5 { + return PullRequest{}, fmt.Errorf("change URI path must be {org}/{repo}/pull/{pr}/{head_sha}: %q", raw) + } + for _, s := range segments { + if s == "" { + return PullRequest{}, fmt.Errorf("change URI path must not contain empty segments: %q", raw) + } + } + n := len(segments) + if segments[n-3] != "pull" { + return PullRequest{}, fmt.Errorf("change URI path must be {org}/{repo}/pull/{pr}/{head_sha}: %q", raw) + } + number, headSHA := segments[n-2], segments[n-1] + if !isCanonicalNumber(number) { + return PullRequest{}, fmt.Errorf("pull request number must be a positive integer without leading zeros, got %q", number) + } + if !isCanonicalSHA(headSHA) { + return PullRequest{}, fmt.Errorf("head SHA must be the full 40-character lowercase hex form, got %q", headSHA) + } + + p := PullRequest{ + Host: u.Host, + Org: strings.Join(segments[:n-4], "/"), + Repo: segments[n-4], + Number: number, + HeadSHA: headSHA, + } + // Canonical form round-trips byte-for-byte. This catches every + // non-canonical spelling net/url silently tolerates (uppercase scheme, + // percent-encoding variants, default-port cosmetics). + if p.String() != raw { + return PullRequest{}, fmt.Errorf("change URI is not in canonical form: %q", raw) + } + return p, nil +} + +// validateURL enforces the URI-level canonical-form rules: the github +// scheme, an authority with a lowercase hostname and an optional +// digits-only port, and no userinfo, query, or fragment. +func validateURL(raw string, u *url.URL) error { + if u.Scheme != Scheme { + return fmt.Errorf("unsupported scheme %q: only %q is supported", u.Scheme, Scheme) + } + if u.Opaque != "" { + return fmt.Errorf("change URI must have an authority: %q", raw) + } + if u.User != nil { + return fmt.Errorf("change URI must not contain userinfo: %q", raw) + } + if u.RawQuery != "" || u.ForceQuery || u.Fragment != "" { + return fmt.Errorf("change URI must not contain a query or fragment: %q", raw) + } + return validateHost(u) +} + +// validateHost enforces the RFC host rules: required, lowercase hostname +// (rejected, not folded), and an optional digits-only port kept verbatim. +func validateHost(u *url.URL) error { + if u.Hostname() == "" { + return fmt.Errorf("change URI host is required: %q", u.String()) + } + if strings.ToLower(u.Hostname()) != u.Hostname() { + return fmt.Errorf("change URI host must be lowercase: %q", u.Host) + } + // net/url validates that a present port is numeric, but tolerates a + // trailing colon with an empty port, which would round-trip. + if strings.HasSuffix(u.Host, ":") { + return fmt.Errorf("change URI port must not be empty: %q", u.Host) + } + return nil +} + +// isCanonicalNumber reports whether s is a positive integer without leading +// zeros. +func isCanonicalNumber(s string) bool { + if s == "" || s[0] < '1' || s[0] > '9' { + return false + } + for i := 1; i < len(s); i++ { + if s[i] < '0' || s[i] > '9' { + return false + } + } + return true +} + +// isCanonicalSHA reports whether s is a full 40-character lowercase hex +// commit SHA. +func isCanonicalSHA(s string) bool { + if len(s) != 40 { + return false + } + for i := 0; i < len(s); i++ { + c := s[i] + if (c < '0' || c > '9') && (c < 'a' || c > 'f') { + return false + } + } + return true +} diff --git a/core/changeuri/changeuri_test.go b/core/changeuri/changeuri_test.go new file mode 100644 index 00000000..dbcb36ea --- /dev/null +++ b/core/changeuri/changeuri_test.go @@ -0,0 +1,135 @@ +// Copyright (c) 2026 Uber 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 changeuri + +import ( + "strconv" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "pgregory.net/rapid" +) + +const _sha = "c3a4b5d6e7f80912a3b4c5d6e7f80912a3b4c5d6" + +func TestParse_Valid(t *testing.T) { + tests := []struct { + name string + in string + want PullRequest + }{ + { + name: "simple", + in: "github://github.com/uber/tango/pull/123/" + _sha, + want: PullRequest{Host: "github.com", Org: "uber", Repo: "tango", Number: "123", HeadSHA: _sha}, + }, + { + name: "internal host", + in: "github://github.uberinternal.com/uber/submitqueue/pull/1/" + _sha, + want: PullRequest{Host: "github.uberinternal.com", Org: "uber", Repo: "submitqueue", Number: "1", HeadSHA: _sha}, + }, + { + name: "host with port", + in: "github://github.example.com:8443/org/repo/pull/42/" + _sha, + want: PullRequest{Host: "github.example.com:8443", Org: "org", Repo: "repo", Number: "42", HeadSHA: _sha}, + }, + { + name: "nested org", + in: "github://github.com/uber/frontend/webapp/pull/7/" + _sha, + want: PullRequest{Host: "github.com", Org: "uber/frontend", Repo: "webapp", Number: "7", HeadSHA: _sha}, + }, + { + name: "org segment literally named pull", + in: "github://github.com/org/pull/repo/pull/9/" + _sha, + want: PullRequest{Host: "github.com", Org: "org/pull", Repo: "repo", Number: "9", HeadSHA: _sha}, + }, + { + name: "case-sensitive org and repo kept verbatim", + in: "github://github.com/Uber/Tango/pull/5/" + _sha, + want: PullRequest{Host: "github.com", Org: "Uber", Repo: "Tango", Number: "5", HeadSHA: _sha}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := Parse(tt.in) + require.NoError(t, err) + assert.Equal(t, tt.want, got) + assert.Equal(t, tt.in, got.String(), "round-trip must be byte-for-byte") + }) + } +} + +func TestParse_Invalid(t *testing.T) { + tests := []struct { + name string + in string + }{ + {name: "empty", in: ""}, + {name: "no scheme", in: "github.com/uber/tango/pull/123/" + _sha}, + {name: "wrong scheme", in: "phab://phabricator.example.com/D12345/67890"}, + {name: "https web URL", in: "https://github.com/uber/tango/pull/123"}, + {name: "missing host", in: "github:///uber/tango/pull/123/" + _sha}, + {name: "legacy hostless form", in: "github://uber/tango/pull/123"}, + {name: "uppercase host", in: "github://GitHub.com/uber/tango/pull/123/" + _sha}, + {name: "uppercase scheme", in: "GITHUB://github.com/uber/tango/pull/123/" + _sha}, + {name: "userinfo", in: "github://user@github.com/uber/tango/pull/123/" + _sha}, + {name: "empty port", in: "github://github.com:/uber/tango/pull/123/" + _sha}, + {name: "non-numeric port", in: "github://github.com:abc/uber/tango/pull/123/" + _sha}, + {name: "query", in: "github://github.com/uber/tango/pull/123/" + _sha + "?x=1"}, + {name: "bare question mark", in: "github://github.com/uber/tango/pull/123/" + _sha + "?"}, + {name: "fragment", in: "github://github.com/uber/tango/pull/123/" + _sha + "#frag"}, + {name: "missing head sha", in: "github://github.com/uber/tango/pull/123"}, + {name: "short sha", in: "github://github.com/uber/tango/pull/123/c3a4b5d"}, + {name: "uppercase sha", in: "github://github.com/uber/tango/pull/123/C3A4B5D6E7F80912A3B4C5D6E7F80912A3B4C5D6"}, + {name: "non-hex sha", in: "github://github.com/uber/tango/pull/123/z3a4b5d6e7f80912a3b4c5d6e7f80912a3b4c5d6"}, + {name: "zero pr number", in: "github://github.com/uber/tango/pull/0/" + _sha}, + {name: "leading-zero pr number", in: "github://github.com/uber/tango/pull/0123/" + _sha}, + {name: "non-numeric pr number", in: "github://github.com/uber/tango/pull/12a/" + _sha}, + {name: "missing pull segment", in: "github://github.com/uber/tango/123/" + _sha}, + {name: "missing repo", in: "github://github.com/uber/pull/123/" + _sha}, + {name: "trailing slash", in: "github://github.com/uber/tango/pull/123/" + _sha + "/"}, + {name: "empty path segment", in: "github://github.com/uber//tango/pull/123/" + _sha}, + {name: "no path", in: "github://github.com"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, err := Parse(tt.in) + require.Error(t, err) + }) + } +} + +func TestParse_RoundTrip(t *testing.T) { + segment := rapid.StringMatching(`[A-Za-z0-9][A-Za-z0-9._-]{0,20}`) + rapid.Check(t, func(t *rapid.T) { + p := PullRequest{ + Host: rapid.StringMatching(`[a-z0-9.-]{1,30}(:[1-9][0-9]{0,4})?`).Draw(t, "host"), + Org: segment.Draw(t, "org"), + Repo: segment.Draw(t, "repo"), + Number: strconv.Itoa(rapid.IntRange(1, 1<<30).Draw(t, "number")), + HeadSHA: rapid.StringMatching(`[0-9a-f]{40}`).Draw(t, "sha"), + } + parsed, err := Parse(p.String()) + if err != nil { + // Some generated hosts are not valid URI authorities (e.g. a + // bare "-"); rejection is fine, silent mutation is not. + return + } + require.Equal(t, p.String(), parsed.String(), "parse then serialize must round-trip byte-for-byte") + require.Equal(t, p.Number, parsed.Number) + require.Equal(t, p.HeadSHA, parsed.HeadSHA) + }) +} diff --git a/core/workspace/BUILD.bazel b/core/workspace/BUILD.bazel index d762ffb3..8a48972b 100644 --- a/core/workspace/BUILD.bazel +++ b/core/workspace/BUILD.bazel @@ -10,6 +10,7 @@ go_library( importpath = "github.com/uber/tango/core/workspace", visibility = ["//visibility:public"], deps = [ + "//core/changeuri", "//core/git", "@org_uber_go_zap//:zap", ], diff --git a/core/workspace/gitrequest.go b/core/workspace/gitrequest.go index 7432848d..304492a0 100644 --- a/core/workspace/gitrequest.go +++ b/core/workspace/gitrequest.go @@ -17,7 +17,6 @@ package workspace import ( "context" "fmt" - "path/filepath" "github.com/uber/tango/core/git" "go.uber.org/zap" @@ -27,38 +26,37 @@ type gitRequest struct { git git.Interface requestID string baseRef string - commit string + headSHA string logger *zap.SugaredLogger } -func NewGitRequest(git git.Interface, requestPath string, baseRef string, commit string, logger *zap.SugaredLogger) Request { - // get the last part of the request path - requestID := filepath.Base(requestPath) +// NewGitRequest creates a Request that applies a GitHub pull request. +// requestID and headSHA come from the parsed change URI; see +// https://github.com/uber/submitqueue/blob/main/doc/rfc/change-uri.md. +func NewGitRequest(git git.Interface, requestID string, baseRef string, headSHA string, logger *zap.SugaredLogger) Request { return &gitRequest{ git: git, requestID: requestID, baseRef: baseRef, - commit: commit, + headSHA: headSHA, logger: logger, } } // Apply applies the change request to the workspace. func (r *gitRequest) Apply(ctx context.Context) error { - r.logger.Infow("gitRequest: Applying PR", zap.String("request_id", r.requestID), zap.String("base_ref", r.baseRef), zap.String("commit", r.commit)) + r.logger.Infow("gitRequest: Applying PR", zap.String("request_id", r.requestID), zap.String("base_ref", r.baseRef), zap.String("head_sha", r.headSHA)) ref := fmt.Sprintf("+pull/%s/head:pull/%s/head", r.requestID, r.requestID) err := r.git.Fetch(ctx, "origin", ref, "--force", "--no-tags") if err != nil { return fmt.Errorf("fetch PR %s: %w", r.requestID, err) } - if r.commit != "" { - isAncestor, err := r.git.IsAncestor(ctx, r.commit, fmt.Sprintf("pull/%s/head", r.requestID)) - if err != nil { - return fmt.Errorf("failed to read PR commit history: %w", err) - } - if !isAncestor { - return fmt.Errorf("commit %q is not an ancestor of PR %s", r.commit, r.requestID) - } + isAncestor, err := r.git.IsAncestor(ctx, r.headSHA, fmt.Sprintf("pull/%s/head", r.requestID)) + if err != nil { + return fmt.Errorf("failed to read PR commit history: %w", err) + } + if !isAncestor { + return fmt.Errorf("head SHA %q is not an ancestor of PR %s", r.headSHA, r.requestID) } patch, err := r.git.Diff(ctx, r.baseRef, fmt.Sprintf("pull/%s/head", r.requestID), "--binary", "--merge-base") if err != nil { diff --git a/core/workspace/gitrequest_test.go b/core/workspace/gitrequest_test.go index d0bc84e4..efcdbda0 100644 --- a/core/workspace/gitrequest_test.go +++ b/core/workspace/gitrequest_test.go @@ -26,21 +26,16 @@ import ( "go.uber.org/zap" ) -func TestNewGitRequest_InvalidPath(t *testing.T) { - req := NewGitRequest(nil, "invalid", "baseRef", "", zap.NewNop().Sugar()) - require.NotNil(t, req) -} - -func TestNewGitRequest_ExtractsID(t *testing.T) { - r := NewGitRequest(nil, "/org/repo/pull/456", "baseRef", "abc123", zap.NewNop().Sugar()) +func TestNewGitRequest_Fields(t *testing.T) { + r := NewGitRequest(nil, "456", "baseRef", _testHeadSHA, zap.NewNop().Sugar()) gr, ok := r.(*gitRequest) assert.True(t, ok, "expected *gitRequest, got %T", r) assert.Equal(t, "456", gr.requestID) assert.Equal(t, "baseRef", gr.baseRef) - assert.Equal(t, "abc123", gr.commit) + assert.Equal(t, _testHeadSHA, gr.headSHA) } -func TestGitRequest_Apply_CommitIsAncestor_Success(t *testing.T) { +func TestGitRequest_Apply_HeadSHAIsAncestor_Success(t *testing.T) { ctrl := gomock.NewController(t) git := gitmock.NewMockInterface(ctrl) git.EXPECT().Fetch(gomock.Any(), "origin", gomock.Any(), gomock.Any()).Return(nil) @@ -54,7 +49,7 @@ func TestGitRequest_Apply_CommitIsAncestor_Success(t *testing.T) { require.NoError(t, err) } -func TestGitRequest_Apply_CommitNotAncestor_ReturnsError(t *testing.T) { +func TestGitRequest_Apply_HeadSHANotAncestor_ReturnsError(t *testing.T) { ctrl := gomock.NewController(t) git := gitmock.NewMockInterface(ctrl) git.EXPECT().Fetch(gomock.Any(), "origin", gomock.Any(), gomock.Any()).Return(nil) diff --git a/core/workspace/request.go b/core/workspace/request.go index c5bc2ef2..69dcaf32 100644 --- a/core/workspace/request.go +++ b/core/workspace/request.go @@ -19,6 +19,7 @@ import ( "fmt" "net/url" + "github.com/uber/tango/core/changeuri" "github.com/uber/tango/core/git" "go.uber.org/zap" ) @@ -28,15 +29,20 @@ type Request interface { Apply(ctx context.Context) error } -// NewRequest creates a new request based on the request URL. -func NewRequest(rawURL string, g git.Interface, baseRef string, commit string, logger *zap.SugaredLogger) (Request, error) { +// NewRequest creates a new request from a canonical change URI, e.g. +// github://{host[:port]}/{org}/{repo}/pull/{pr}/{head_sha}. +func NewRequest(rawURL string, g git.Interface, baseRef string, logger *zap.SugaredLogger) (Request, error) { u, err := url.Parse(rawURL) if err != nil { return nil, err } switch u.Scheme { - case "github": - return NewGitRequest(g, u.Path, baseRef, commit, logger), nil + case changeuri.Scheme: + pr, err := changeuri.Parse(rawURL) + if err != nil { + return nil, fmt.Errorf("invalid change URI %q: %w", rawURL, err) + } + return NewGitRequest(g, pr.Number, baseRef, pr.HeadSHA, logger), nil } return nil, fmt.Errorf("unsupported scheme: %v", u.Scheme) } diff --git a/core/workspace/request_test.go b/core/workspace/request_test.go index 15db59ff..6ac70778 100644 --- a/core/workspace/request_test.go +++ b/core/workspace/request_test.go @@ -22,17 +22,19 @@ import ( "go.uber.org/zap" ) +const _testHeadSHA = "c3a4b5d6e7f80912a3b4c5d6e7f80912a3b4c5d6" + func TestNewRequest_Github_Success(t *testing.T) { - rawURL := "github://org/repo/pull/123" + rawURL := "github://github.com/org/repo/pull/123/" + _testHeadSHA var g git.Interface = nil - req, err := NewRequest(rawURL, g, "baseRef", "abc123", zap.NewNop().Sugar()) + req, err := NewRequest(rawURL, g, "baseRef", zap.NewNop().Sugar()) require.NoError(t, err) require.NotNil(t, req) gr, ok := req.(*gitRequest) require.True(t, ok, "returned Request should be *gitRequest") require.Equal(t, "123", gr.requestID) - require.Equal(t, "abc123", gr.commit) + require.Equal(t, _testHeadSHA, gr.headSHA) require.Nil(t, gr.git) } @@ -40,7 +42,7 @@ func TestNewRequest_InvalidURL(t *testing.T) { rawURL := "://bad" var g git.Interface = nil - req, err := NewRequest(rawURL, g, "baseRef", "", zap.NewNop().Sugar()) + req, err := NewRequest(rawURL, g, "baseRef", zap.NewNop().Sugar()) require.Error(t, err) require.Nil(t, req) } @@ -49,7 +51,26 @@ func TestNewRequest_InvalidScheme(t *testing.T) { rawURL := "phabricator://bad" var g git.Interface = nil - req, err := NewRequest(rawURL, g, "baseRef", "", zap.NewNop().Sugar()) + req, err := NewRequest(rawURL, g, "baseRef", zap.NewNop().Sugar()) require.Error(t, err) require.Nil(t, req) } + +func TestNewRequest_NonCanonicalURI(t *testing.T) { + tests := []struct { + name string + url string + }{ + {name: "legacy hostless form", url: "github://org/repo/pull/123"}, + {name: "missing head sha", url: "github://github.com/org/repo/pull/123"}, + {name: "uppercase host", url: "github://GitHub.com/org/repo/pull/123/" + _testHeadSHA}, + {name: "short sha", url: "github://github.com/org/repo/pull/123/abc123"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + req, err := NewRequest(tt.url, nil, "baseRef", zap.NewNop().Sugar()) + require.Error(t, err) + require.Nil(t, req) + }) + } +} diff --git a/entity/build_description.go b/entity/build_description.go index 23d7fcba..6bcebc2c 100644 --- a/entity/build_description.go +++ b/entity/build_description.go @@ -3,10 +3,16 @@ package entity // ChangeRequest describes a single change (PR, diff) to layer on top of a // base revision. type ChangeRequest struct { - // URL identifies the change request (PR/diff link) being layered on. + // URL identifies the change request. Its format is interpreted by the + // Orchestrator implementation that consumes it: the bundled native + // orchestrator requires a canonical change URI of the form + // github://{host[:port]}/{org}/{repo}/pull/{pr}/{head_sha}, per the + // change-URI RFC + // (https://github.com/uber/submitqueue/blob/main/doc/rfc/change-uri.md), + // whose embedded head SHA pins the exact code state; custom + // orchestrators may accept formats of their own. The URL participates + // in cache keys as an opaque string. URL string - // Commit is the SHA to apply on top of the base revision. - Commit string } // BuildDescription identifies a repository state: a base revision plus diff --git a/example/README.md b/example/README.md index 98ec86e8..369313d2 100644 --- a/example/README.md +++ b/example/README.md @@ -48,6 +48,8 @@ and flags for limiting changed-target distance (`-max-distance`), cache bypass `-include-attributes`), and request URLs (`-request-urls`, `-new-request-urls`). Run with `-h` for the full list. +Change requests are identified by canonical change URIs of the form `github://{host[:port]}/{org}/{repo}/pull/{pr}/{head_sha}`, per the [change-URI RFC](https://github.com/uber/submitqueue/blob/main/doc/rfc/change-uri.md) — for example `github://github.com/uber/tango/pull/123/c3a4b5d6e7f80912a3b4c5d6e7f80912a3b4c5d6`. The head SHA is the PR's head commit at submission time; it pins the exact code state applied on top of the base revision and forms the cache identity. The bundled native orchestrator rejects non-canonical spellings (uppercase host, abbreviated SHA, missing host); custom Orchestrator implementations may accept formats of their own. + ## Benchmarking The query-bench tool times the standard Tango query against a real Bazel diff --git a/example/client/client.go b/example/client/client.go index 031bdd45..c439284a 100644 --- a/example/client/client.go +++ b/example/client/client.go @@ -36,7 +36,7 @@ func main() { method := flag.String("method", "get-target-graph", "method to call: get-target-graph, get-changed-targets") remote := flag.String("remote", "", "build description remote") baseSHA := flag.String("base-sha", "", "build description base sha") - reqURLs := flag.String("request-urls", "", "comma-separated change request URLs") + reqURLs := flag.String("request-urls", "", "comma-separated canonical change URIs, e.g. github://{host}/{org}/{repo}/pull/{pr}/{head_sha}") timeout := flag.Duration("timeout", 5*time.Minute, "request timeout") maxDistance := flag.Int("max-distance", -1, "max distance for changed targets") bypassCache := flag.Bool("bypass-cache", false, "skip cache lookup and force recomputation, overwriting cached result") @@ -45,7 +45,7 @@ func main() { includeAttributes := flag.Bool("include-attributes", false, "include per-target attributes + attribute mappings in responses (proto3 default: false)") newBaseSHA := flag.String("new-base-sha", "", "build description new base sha") - newRequestURLs := flag.String("new-request-urls", "", "comma-separated change request URLs for new state") + newRequestURLs := flag.String("new-request-urls", "", "comma-separated canonical change URIs for new state, e.g. github://{host}/{org}/{repo}/pull/{pr}/{head_sha}") flag.Parse() grpcTransport := yarpcgrpc.NewTransport() diff --git a/internal/mapper/build_description.go b/internal/mapper/build_description.go index cf8f5b30..8962a73f 100644 --- a/internal/mapper/build_description.go +++ b/internal/mapper/build_description.go @@ -43,8 +43,7 @@ func toChangeRequests(requests []*tangopb.Request) []entity.ChangeRequest { out := make([]entity.ChangeRequest, len(requests)) for i, r := range requests { out[i] = entity.ChangeRequest{ - URL: r.GetUrl(), - Commit: r.GetCommit(), + URL: r.GetUrl(), } } return out diff --git a/internal/mapper/build_description_test.go b/internal/mapper/build_description_test.go index d61e17e5..2bea8511 100644 --- a/internal/mapper/build_description_test.go +++ b/internal/mapper/build_description_test.go @@ -44,8 +44,10 @@ func TestProtoToBuildDescription(t *testing.T) { Remote: "git@example.com:org/repo", BaseSha: "abc123", Requests: []*tangopb.Request{ - {Url: "https://example.com/pr/1", Commit: "sha1"}, - {Url: "https://example.com/pr/2", Commit: "sha2"}, + {Url: "github://github.com/org/repo/pull/1/1111111111111111111111111111111111111111"}, + // URL format is orchestrator-specific; the mapper passes + // it through opaquely without validation. + {Url: "https://example.com/pr/2"}, }, Strategy: tangopb.COMPUTATION_STRATEGY_NATIVE, }, @@ -53,8 +55,8 @@ func TestProtoToBuildDescription(t *testing.T) { Remote: "git@example.com:org/repo", BaseSha: "abc123", ChangeRequests: []entity.ChangeRequest{ - {URL: "https://example.com/pr/1", Commit: "sha1"}, - {URL: "https://example.com/pr/2", Commit: "sha2"}, + {URL: "github://github.com/org/repo/pull/1/1111111111111111111111111111111111111111"}, + {URL: "https://example.com/pr/2"}, }, Strategy: entity.ComputationStrategyNative, }, diff --git a/internal/url/url.go b/internal/url/url.go index 18fb1eaf..62197279 100644 --- a/internal/url/url.go +++ b/internal/url/url.go @@ -33,7 +33,6 @@ func ToShortRemote(remote string) string { } // GetReqURLsHash returns a fixed-length hash of the ordered change requests. -// Both URL and commit participate because either can change the materialized tree. func GetReqURLsHash(requests []entity.ChangeRequest) string { if len(requests) == 0 { return "" @@ -41,7 +40,6 @@ func GetReqURLsHash(requests []entity.ChangeRequest) string { h := md5.New() for _, request := range requests { writeFramedString(h, request.URL) - writeFramedString(h, request.Commit) } return fmt.Sprintf("%x", h.Sum(nil)) } diff --git a/internal/url/url_test.go b/internal/url/url_test.go index 9e512d9b..fa1e7252 100644 --- a/internal/url/url_test.go +++ b/internal/url/url_test.go @@ -58,10 +58,14 @@ func TestGetReqURLsHash(t *testing.T) { md5hex := func(requests ...entity.ChangeRequest) string { h := md5.New() for _, request := range requests { - fmt.Fprintf(h, "%d:%s%d:%s", len(request.URL), request.URL, len(request.Commit), request.Commit) + fmt.Fprintf(h, "%d:%s", len(request.URL), request.URL) } return fmt.Sprintf("%x", h.Sum(nil)) } + const ( + uri1 = "github://github.com/org/repo/pull/42/c3a4b5d6e7f80912a3b4c5d6e7f80912a3b4c5d6" + uri2 = "github://github.com/org/repo/pull/43/1111111111111111111111111111111111111111" + ) tests := []struct { name string in []entity.ChangeRequest @@ -74,18 +78,18 @@ func TestGetReqURLsHash(t *testing.T) { }, { name: "single", - in: []entity.ChangeRequest{{URL: "github://org/repo/pull/42", Commit: "abc"}}, - want: md5hex(entity.ChangeRequest{URL: "github://org/repo/pull/42", Commit: "abc"}), + in: []entity.ChangeRequest{{URL: uri1}}, + want: md5hex(entity.ChangeRequest{URL: uri1}), }, { name: "multiple", - in: []entity.ChangeRequest{{URL: "a", Commit: "1"}, {URL: "b", Commit: "2"}}, - want: md5hex(entity.ChangeRequest{URL: "a", Commit: "1"}, entity.ChangeRequest{URL: "b", Commit: "2"}), + in: []entity.ChangeRequest{{URL: uri1}, {URL: uri2}}, + want: md5hex(entity.ChangeRequest{URL: uri1}, entity.ChangeRequest{URL: uri2}), }, { name: "reverse order", - in: []entity.ChangeRequest{{URL: "b", Commit: "2"}, {URL: "a", Commit: "1"}}, - want: md5hex(entity.ChangeRequest{URL: "b", Commit: "2"}, entity.ChangeRequest{URL: "a", Commit: "1"}), + in: []entity.ChangeRequest{{URL: uri2}, {URL: uri1}}, + want: md5hex(entity.ChangeRequest{URL: uri2}, entity.ChangeRequest{URL: uri1}), }, } for _, tt := range tests { diff --git a/orchestrator/native_orchestrator.go b/orchestrator/native_orchestrator.go index 718f98b8..4c0f7b41 100644 --- a/orchestrator/native_orchestrator.go +++ b/orchestrator/native_orchestrator.go @@ -150,9 +150,9 @@ func (b *nativeOrchestrator) GetTargetGraph(ctx context.Context, req entity.GetT gitModule := gitFactory(ws.Path()) for _, req := range build.ChangeRequests { - request, err := workspace.NewRequest(req.URL, gitModule, build.BaseSha, req.Commit, logger) + request, err := workspace.NewRequest(req.URL, gitModule, build.BaseSha, logger) if err != nil { - return nil, fmt.Errorf("create request for %q: %w", req.URL, err) + return nil, tangoerrors.NewUser(fmt.Errorf("create request for %q: %w", req.URL, err)) } requests = append(requests, request) } diff --git a/orchestrator/native_orchestrator_test.go b/orchestrator/native_orchestrator_test.go index 005fc3cb..28ad7865 100644 --- a/orchestrator/native_orchestrator_test.go +++ b/orchestrator/native_orchestrator_test.go @@ -234,7 +234,7 @@ func TestNative_GetTargetGraph_AppliesGitHubPR(t *testing.T) { Build: entity.BuildDescription{ Remote: "git@github:uber/tango", BaseSha: "1234567890", - ChangeRequests: []entity.ChangeRequest{{URL: "github://org/repo/pull/123"}}, + ChangeRequests: []entity.ChangeRequest{{URL: "github://github.com/org/repo/pull/123/c3a4b5d6e7f80912a3b4c5d6e7f80912a3b4c5d6"}}, }, }) require.NoError(t, err) @@ -245,6 +245,39 @@ func TestNative_GetTargetGraph_AppliesGitHubPR(t *testing.T) { require.NotNil(t, chunk.Targets) } +func TestNative_GetTargetGraph_InvalidChangeURI_UserError(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + st := storagemock.NewMockStorage(ctrl) + g := gitmock.NewMockInterface(ctrl) + ws := workspacemock.NewMockWorkspace(ctrl) + ws.EXPECT().Path().Return("/tmp/ws") + ws.EXPECT().Checkout(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + ws.EXPECT().Release().Return(nil) + rm := repomanagermock.NewMockRepoManager(ctrl) + rm.EXPECT().Lease(gomock.Any(), gomock.Any()).Return(ws, nil) + o, err := NewNativeOrchestrator(context.Background(), Params{ + Storage: st, + RepoManager: rm, + Logger: zaptest.NewLogger(t).Sugar(), + GitFactory: func(dir string) git.Interface { return g }, + Config: testConfig(t), + }) + require.NoError(t, err) + resp, err := o.GetTargetGraph(context.Background(), entity.GetTargetGraphRequest{ + Build: entity.BuildDescription{ + Remote: "git@github:uber/tango", + BaseSha: "1234567890", + // Legacy hostless form without a head SHA — rejected by the + // native orchestrator as a user error. + ChangeRequests: []entity.ChangeRequest{{URL: "github://org/repo/pull/123"}}, + }, + }) + require.Error(t, err) + require.Nil(t, resp) + assert.Equal(t, tangoerrors.ErrorUser, tangoerrors.GetErrorCode(err)) +} + func TestNewNativeOrchestrator_usesProvidedConfig(t *testing.T) { cfg := testConfig(t) diff --git a/proto/tango.proto b/proto/tango.proto index fec1ef1d..8df3cd68 100644 --- a/proto/tango.proto +++ b/proto/tango.proto @@ -19,12 +19,17 @@ message TangoError { string message = 2; } -// Request represents a single change request with a URL and optional commit SHA. +// Request represents a single change request, identified by a change URI. message Request { - // The URL of the change request (e.g., a GitHub pull request URL or Phabricator diff URL) + // The change URI of the request. The format is interpreted by the + // Orchestrator implementation: the bundled native orchestrator requires + // the canonical change-URI form + // github://{host[:port]}/{org}/{repo}/pull/{pr}/{head_sha} + // e.g. github://github.com/uber/tango/pull/123/c3a4b5d6e7f80912a3b4c5d6e7f80912a3b4c5d6 + // whose embedded head SHA pins the exact code state; custom + // orchestrators may accept formats of their own. The URL participates + // in cache keys as an opaque string. string url = 1; - // The commit SHA associated with the change request - string commit = 2; } // BuildDescription defines a Storage state by a primary revision string and @@ -35,8 +40,9 @@ message BuildDescription { // The base commit sha of the Storage string base_sha = 2; // List of change requests to apply on top of the base revision. - // Each request contains a URL (e.g., a GitHub pull request or Phabricator diff URL) - // and an required commit SHA. If empty, the computation happens on the base revision. + // Each request is identified by a canonical change URI whose embedded + // head SHA pins the applied content. If empty, the computation happens + // on the base revision. repeated Request requests = 3; // The computation strategy of the original target graph ComputationStrategy strategy = 4; diff --git a/tangopb/tango.pb.go b/tangopb/tango.pb.go index 80bc7ae9..61c5c36f 100644 --- a/tangopb/tango.pb.go +++ b/tangopb/tango.pb.go @@ -172,12 +172,17 @@ func (m *TangoError) GetMessage() string { return "" } -// Request represents a single change request with a URL and optional commit SHA. +// Request represents a single change request, identified by a change URI. type Request struct { - // The URL of the change request (e.g., a GitHub pull request URL or Phabricator diff URL) + // The change URI of the request. The format is interpreted by the + // Orchestrator implementation: the bundled native orchestrator requires + // the canonical change-URI form + // github://{host[:port]}/{org}/{repo}/pull/{pr}/{head_sha} + // e.g. github://github.com/uber/tango/pull/123/c3a4b5d6e7f80912a3b4c5d6e7f80912a3b4c5d6 + // whose embedded head SHA pins the exact code state; custom + // orchestrators may accept formats of their own. The URL participates + // in cache keys as an opaque string. Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"` - // The commit SHA associated with the change request - Commit string `protobuf:"bytes,2,opt,name=commit,proto3" json:"commit,omitempty"` } func (m *Request) Reset() { *m = Request{} } @@ -219,13 +224,6 @@ func (m *Request) GetUrl() string { return "" } -func (m *Request) GetCommit() string { - if m != nil { - return m.Commit - } - return "" -} - // BuildDescription defines a Storage state by a primary revision string and // an optional list of change identifiers (e.g., diff IDs or PR IDs). type BuildDescription struct { @@ -234,8 +232,9 @@ type BuildDescription struct { // The base commit sha of the Storage BaseSha string `protobuf:"bytes,2,opt,name=base_sha,json=baseSha,proto3" json:"base_sha,omitempty"` // List of change requests to apply on top of the base revision. - // Each request contains a URL (e.g., a GitHub pull request or Phabricator diff URL) - // and an required commit SHA. If empty, the computation happens on the base revision. + // Each request is identified by a canonical change URI whose embedded + // head SHA pins the applied content. If empty, the computation happens + // on the base revision. Requests []*Request `protobuf:"bytes,3,rep,name=requests,proto3" json:"requests,omitempty"` // The computation strategy of the original target graph Strategy ComputationStrategy `protobuf:"varint,4,opt,name=strategy,proto3,enum=uber.tango.ComputationStrategy" json:"strategy,omitempty"` @@ -1330,101 +1329,100 @@ func init() { func init() { proto.RegisterFile("tango.proto", fileDescriptor_c4210c857dbeec96) } var fileDescriptor_c4210c857dbeec96 = []byte{ - // 1489 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x58, 0xbf, 0x6f, 0xdb, 0xc6, - 0x17, 0x17, 0xf5, 0xc3, 0x96, 0x9e, 0x6c, 0x49, 0x3e, 0x3b, 0xfe, 0xca, 0x72, 0xc2, 0x38, 0x44, - 0x02, 0x38, 0xf9, 0xa2, 0x4e, 0xe1, 0x20, 0x68, 0x9a, 0x22, 0x83, 0x2c, 0x31, 0xb6, 0x10, 0x47, - 0x76, 0xcf, 0x72, 0x8a, 0x34, 0x05, 0x88, 0x13, 0x79, 0x91, 0x89, 0x4a, 0x24, 0x4b, 0x9e, 0x12, - 0x3b, 0x53, 0xd7, 0x2e, 0x45, 0xc7, 0x4e, 0x1d, 0x3a, 0x75, 0xef, 0xda, 0xa5, 0x5b, 0x3b, 0x14, - 0x48, 0xd1, 0x25, 0x43, 0x87, 0xc6, 0x59, 0x3a, 0xe6, 0x4f, 0x28, 0x78, 0x47, 0x51, 0xa4, 0x2c, - 0xff, 0x42, 0x96, 0x0e, 0xdd, 0xee, 0xde, 0x8f, 0xcf, 0x7b, 0xf7, 0x3e, 0x77, 0xf7, 0x8e, 0x84, - 0x3c, 0x23, 0x56, 0xc7, 0x5e, 0x71, 0x5c, 0x9b, 0xd9, 0x08, 0xfa, 0x6d, 0xea, 0xae, 0x70, 0x89, - 0xf2, 0x31, 0x40, 0xcb, 0x1f, 0xa8, 0xae, 0x6b, 0xbb, 0xe8, 0x3a, 0xa4, 0x75, 0xdb, 0xa0, 0x65, - 0x69, 0x49, 0x5a, 0x2e, 0xac, 0x5e, 0x58, 0x19, 0x1a, 0xae, 0x70, 0x83, 0x9a, 0x6d, 0x50, 0xcc, - 0x4d, 0x50, 0x19, 0x26, 0x7b, 0xd4, 0xf3, 0x48, 0x87, 0x96, 0x93, 0x4b, 0xd2, 0x72, 0x0e, 0x0f, - 0xa6, 0xca, 0x2d, 0x98, 0xc4, 0xf4, 0x8b, 0x3e, 0xf5, 0x18, 0x2a, 0x41, 0xaa, 0xef, 0x76, 0x39, - 0x5c, 0x0e, 0xfb, 0x43, 0x34, 0x0f, 0x13, 0xba, 0xdd, 0xeb, 0x99, 0x2c, 0xf0, 0x0a, 0x66, 0xca, - 0x8f, 0x12, 0x94, 0xd6, 0xfa, 0x66, 0xd7, 0xa8, 0x53, 0x4f, 0x77, 0x4d, 0x87, 0x99, 0xb6, 0xe5, - 0x1b, 0xbb, 0xb4, 0x67, 0x33, 0x1a, 0x20, 0x04, 0x33, 0xb4, 0x00, 0xd9, 0x36, 0xf1, 0xa8, 0xe6, - 0xed, 0x91, 0x41, 0x70, 0x7f, 0xbe, 0xb3, 0x47, 0xd0, 0x4d, 0xc8, 0xba, 0x22, 0xb8, 0x57, 0x4e, - 0x2d, 0xa5, 0x96, 0xf3, 0xab, 0xb3, 0xd1, 0x55, 0x04, 0x89, 0xe1, 0xd0, 0x08, 0x7d, 0x04, 0x59, - 0x8f, 0xb9, 0x84, 0xd1, 0xce, 0x41, 0x39, 0xcd, 0x97, 0x7d, 0x39, 0xea, 0x50, 0xb3, 0x7b, 0x4e, - 0x9f, 0x11, 0x3f, 0x9d, 0x9d, 0xc0, 0x0c, 0x87, 0x0e, 0xca, 0xaf, 0x12, 0x4c, 0x6d, 0xf5, 0x99, - 0xd3, 0x67, 0x35, 0xdb, 0x7a, 0x6a, 0x76, 0xd0, 0x15, 0x98, 0x32, 0x2d, 0xbd, 0xdb, 0x37, 0xa8, - 0xc6, 0x48, 0xc7, 0xe3, 0x79, 0x67, 0x71, 0x3e, 0x90, 0xb5, 0x48, 0xc7, 0x43, 0xef, 0x01, 0x1a, - 0x98, 0x10, 0xc6, 0x5c, 0xb3, 0xdd, 0x67, 0xd4, 0xe3, 0xcb, 0xc8, 0xe2, 0x99, 0x40, 0x53, 0x0d, - 0x15, 0xe8, 0x1a, 0x14, 0x06, 0xe6, 0x7b, 0xc4, 0xdb, 0xa3, 0xfe, 0xb2, 0x7c, 0xd3, 0xe9, 0x40, - 0xba, 0xc1, 0x85, 0xe8, 0x12, 0x80, 0x6b, 0xdb, 0xcc, 0xd3, 0x6c, 0xab, 0x2b, 0x16, 0x92, 0xc5, - 0x39, 0x2e, 0xd9, 0xb2, 0xba, 0x07, 0x7e, 0x5e, 0x3d, 0xb2, 0xaf, 0x19, 0xa6, 0xc7, 0x88, 0xa5, - 0xd3, 0x72, 0x66, 0x49, 0x5a, 0xce, 0xe0, 0x7c, 0x8f, 0xec, 0xd7, 0x03, 0x91, 0xf2, 0x00, 0x0a, - 0x41, 0x75, 0xb6, 0x78, 0xf5, 0x3d, 0xf4, 0x21, 0x2c, 0xd0, 0x7d, 0xe6, 0x12, 0x8d, 0xee, 0x8b, - 0x04, 0x9e, 0x9a, 0x5d, 0xea, 0x69, 0x2e, 0xed, 0xd0, 0xfd, 0xb2, 0xb4, 0x94, 0x5a, 0xce, 0xe1, - 0x79, 0x6e, 0xa0, 0x0a, 0xfd, 0x7d, 0x5f, 0x8d, 0x7d, 0xad, 0xf2, 0x47, 0x12, 0x8a, 0x3e, 0x4c, - 0xcf, 0x7c, 0x41, 0x8d, 0x16, 0x71, 0x3b, 0x94, 0xa1, 0x02, 0x24, 0x4d, 0x83, 0x57, 0x24, 0x83, - 0x93, 0xa6, 0x81, 0x10, 0xa4, 0xfd, 0x15, 0x05, 0x0c, 0xf2, 0x31, 0xba, 0x09, 0xb3, 0x86, 0xe9, - 0x52, 0x9d, 0x69, 0x06, 0x75, 0xa8, 0x65, 0x50, 0x4b, 0x37, 0xa9, 0x60, 0x32, 0x83, 0x91, 0x50, - 0xd5, 0x23, 0x1a, 0x1f, 0x84, 0x17, 0x3a, 0xcd, 0x2d, 0xf8, 0x18, 0x2d, 0x42, 0xce, 0xed, 0x77, - 0xa9, 0xc6, 0x0e, 0x9c, 0xc1, 0x4a, 0xb3, 0xbe, 0xa0, 0x75, 0xe0, 0x50, 0xdf, 0xc1, 0x2f, 0x4b, - 0x79, 0x82, 0x97, 0x88, 0x8f, 0x51, 0x05, 0xb2, 0x74, 0x9f, 0x51, 0xd7, 0x22, 0xdd, 0xf2, 0x24, - 0x97, 0x87, 0x73, 0xf4, 0x00, 0x20, 0x42, 0x53, 0x96, 0x6f, 0xa9, 0xff, 0x47, 0x77, 0xc8, 0xc8, - 0x32, 0x57, 0x86, 0xdc, 0xa9, 0x16, 0x73, 0x0f, 0x70, 0xc4, 0xbd, 0x72, 0x0f, 0x8a, 0x23, 0x6a, - 0xff, 0x88, 0x7c, 0x4e, 0x0f, 0x82, 0xb2, 0xf8, 0x43, 0x34, 0x07, 0x99, 0x67, 0xa4, 0xdb, 0x17, - 0xe7, 0x2a, 0x83, 0xc5, 0xe4, 0x6e, 0xf2, 0x8e, 0xa4, 0x34, 0xa0, 0x34, 0x12, 0xcd, 0x43, 0xb7, - 0x61, 0x92, 0x89, 0x21, 0xa7, 0x24, 0xbf, 0xba, 0x78, 0x42, 0x72, 0x78, 0x60, 0xab, 0xb4, 0xa0, - 0x50, 0xdb, 0x23, 0x56, 0x67, 0x08, 0xb4, 0x06, 0x45, 0x5d, 0x48, 0xb4, 0x38, 0xe0, 0x42, 0xec, - 0x3c, 0x44, 0x9d, 0x70, 0x41, 0x8f, 0x61, 0x28, 0x7f, 0x4a, 0x30, 0x1d, 0xb3, 0x40, 0x1f, 0x40, - 0x5e, 0xd8, 0x08, 0x36, 0xc4, 0xc5, 0x32, 0x7f, 0x14, 0xd1, 0xe7, 0x06, 0x83, 0x1e, 0x8e, 0xd1, - 0x5d, 0x00, 0xbb, 0x3b, 0x48, 0x85, 0x97, 0xe2, 0x94, 0xa5, 0xe5, 0xec, 0xee, 0x20, 0xe8, 0x5d, - 0x00, 0x8b, 0x3e, 0x1f, 0xf8, 0xa6, 0xce, 0xe0, 0x6b, 0xd1, 0xe7, 0x81, 0x6f, 0x05, 0xb2, 0xe1, - 0x29, 0x49, 0x8b, 0xbd, 0x33, 0x98, 0x2b, 0x3f, 0x4f, 0x40, 0xf6, 0x21, 0x65, 0xc4, 0x20, 0x8c, - 0xa0, 0x5d, 0x98, 0x11, 0x01, 0x34, 0xd3, 0xd0, 0x7a, 0xc4, 0x71, 0x4c, 0xab, 0x13, 0x54, 0xec, - 0x7a, 0x34, 0xd6, 0xc0, 0x61, 0x45, 0x04, 0x68, 0x18, 0x0f, 0x85, 0xad, 0xd8, 0x1d, 0x45, 0x16, - 0x97, 0xfa, 0xb0, 0xe1, 0xe6, 0x0d, 0x61, 0x93, 0x27, 0xc0, 0xe2, 0x60, 0x67, 0xc7, 0x61, 0xdd, - 0xb8, 0x14, 0xa9, 0x7e, 0x0b, 0xe8, 0x84, 0x80, 0xe2, 0x6a, 0xbc, 0x7a, 0x4c, 0x9e, 0x9d, 0x18, - 0x16, 0xb0, 0x50, 0x80, 0x0c, 0x98, 0x0f, 0xb7, 0xb3, 0x66, 0x91, 0xde, 0x30, 0xc5, 0x34, 0x47, - 0x5c, 0x19, 0x8b, 0x18, 0xee, 0xf9, 0x26, 0xe9, 0xc5, 0xf3, 0x9c, 0x23, 0x63, 0x54, 0xe8, 0x05, - 0xc8, 0xc3, 0x28, 0x1e, 0x73, 0x4d, 0xab, 0xa3, 0xf1, 0x53, 0x10, 0x46, 0xcb, 0xf0, 0x68, 0xb7, - 0x4f, 0x8e, 0xb6, 0xc3, 0x3d, 0x1f, 0xf9, 0x8e, 0xb1, 0xa0, 0x8b, 0xe4, 0x78, 0x8b, 0xca, 0x1a, - 0xcc, 0x8d, 0x23, 0xea, 0xb4, 0x73, 0x9a, 0x8b, 0x9c, 0x53, 0x1f, 0x63, 0x1c, 0x2b, 0xe7, 0xc2, - 0xb8, 0x07, 0xc5, 0x11, 0x22, 0xce, 0xe5, 0xbe, 0x0e, 0x0b, 0xc7, 0x56, 0xfd, 0x5c, 0x40, 0x4d, - 0x58, 0x3a, 0xad, 0xa0, 0xe7, 0xc1, 0x53, 0xbe, 0x4a, 0xc2, 0x85, 0x75, 0xca, 0x44, 0x8d, 0xd7, - 0x5d, 0xe2, 0xec, 0x0d, 0x1e, 0x0b, 0x0d, 0x98, 0x69, 0xfb, 0x2f, 0x00, 0xcd, 0x18, 0x3e, 0x01, - 0x38, 0x66, 0x7e, 0xf5, 0x62, 0x94, 0xe8, 0xd1, 0x67, 0x02, 0x2e, 0xb5, 0x47, 0x1f, 0x0e, 0xf7, - 0x60, 0xda, 0xe6, 0x6d, 0x59, 0xd3, 0x79, 0x5f, 0x0e, 0xee, 0x8f, 0x72, 0xec, 0x0e, 0x88, 0xf4, - 0x6d, 0x3c, 0x65, 0x47, 0xbb, 0x78, 0x0d, 0x8a, 0xc1, 0xfb, 0x40, 0xb3, 0x45, 0x2f, 0x0c, 0x2e, - 0x91, 0xca, 0x98, 0xb7, 0x44, 0xd0, 0x2d, 0x71, 0xc1, 0x8d, 0x77, 0xcf, 0x2b, 0x30, 0xd5, 0x3e, - 0x70, 0x88, 0xe7, 0x69, 0x3a, 0xd1, 0xf7, 0x68, 0xd0, 0x93, 0xf3, 0x42, 0x56, 0xf3, 0x45, 0xca, - 0xd7, 0x12, 0xcc, 0x8f, 0xd6, 0xc2, 0x73, 0x6c, 0xcb, 0xa3, 0xe8, 0x4e, 0xf4, 0x5a, 0x3f, 0x52, - 0x82, 0xd1, 0x2e, 0xb0, 0x91, 0x08, 0x6f, 0x76, 0xb4, 0x0a, 0xd9, 0x5e, 0x70, 0x14, 0x82, 0x65, - 0xcf, 0x8d, 0x3b, 0x26, 0x1b, 0x09, 0x1c, 0xda, 0xad, 0x4d, 0x40, 0xda, 0x64, 0xb4, 0xa7, 0xfc, - 0x96, 0x84, 0xf2, 0x3a, 0x65, 0xf1, 0xce, 0x30, 0xe0, 0xa7, 0x06, 0x85, 0xa7, 0xa6, 0xeb, 0x31, - 0xcd, 0xa5, 0xcf, 0x4c, 0xef, 0xac, 0xe4, 0x4c, 0x73, 0x1f, 0x1c, 0xb8, 0x20, 0x15, 0x8a, 0x1e, - 0xd5, 0x6d, 0xcb, 0x18, 0xa2, 0x24, 0xcf, 0x80, 0x52, 0x10, 0x4e, 0x21, 0xcc, 0x11, 0x82, 0x53, - 0xef, 0x4a, 0x70, 0xfa, 0x9d, 0x09, 0xce, 0x1c, 0x25, 0xf8, 0x3b, 0x09, 0x16, 0xc6, 0xd4, 0x33, - 0xe0, 0x58, 0x1d, 0xd7, 0x71, 0x8f, 0x64, 0x11, 0x77, 0xde, 0x48, 0x8c, 0x36, 0xdd, 0x77, 0x22, - 0xfc, 0xf7, 0x24, 0x5c, 0x1c, 0x4d, 0x30, 0x76, 0x28, 0xff, 0x23, 0xfd, 0xdc, 0xa4, 0x7f, 0x2f, - 0xc1, 0xa5, 0x63, 0x6a, 0xfa, 0xaf, 0x21, 0xfe, 0xc6, 0x67, 0x90, 0x0b, 0xbf, 0xe8, 0x50, 0x11, - 0xf2, 0x2a, 0xc6, 0x5b, 0x58, 0x6b, 0x34, 0xef, 0xe3, 0x6a, 0x29, 0x81, 0x66, 0xa1, 0x28, 0x04, - 0xb5, 0x6a, 0xb3, 0xa6, 0x6e, 0x6e, 0xaa, 0xf5, 0x92, 0x84, 0x0a, 0x00, 0x42, 0xb8, 0xbb, 0xa3, - 0xe2, 0x52, 0x12, 0x2d, 0xc0, 0x85, 0x88, 0x97, 0x86, 0xd5, 0x16, 0x7e, 0x5c, 0x5d, 0xdb, 0x54, - 0x4b, 0xa9, 0x1b, 0xdf, 0x4a, 0x30, 0x3b, 0xe6, 0xcb, 0x09, 0x2d, 0xc1, 0xc5, 0xda, 0xd6, 0xc3, - 0xed, 0xdd, 0x56, 0xb5, 0xd5, 0xd8, 0x6a, 0x6a, 0x3b, 0x2d, 0x5c, 0x6d, 0xa9, 0xeb, 0x8f, 0xb5, - 0x46, 0xf3, 0x51, 0x75, 0xb3, 0x51, 0x2f, 0x25, 0x90, 0x0c, 0x95, 0xb1, 0x16, 0xbb, 0xcd, 0x1d, - 0xb5, 0x55, 0x92, 0x8e, 0xd5, 0xef, 0x6c, 0xa8, 0x9b, 0x9b, 0xa5, 0x24, 0xba, 0x0c, 0x8b, 0x63, - 0xf5, 0xcd, 0x6a, 0xab, 0xf1, 0xc8, 0x4f, 0xad, 0x0b, 0x30, 0x7c, 0x71, 0xa2, 0xff, 0xc1, 0x6c, - 0x6d, 0xa3, 0xda, 0x5c, 0x57, 0xb5, 0xd6, 0xe3, 0x6d, 0x35, 0x92, 0xc7, 0x2c, 0x14, 0xa3, 0x8a, - 0xa6, 0xfa, 0x49, 0x49, 0x1a, 0xb5, 0xae, 0xab, 0x9b, 0x6a, 0x4b, 0xad, 0x97, 0x92, 0xa3, 0x0a, - 0x31, 0xae, 0x97, 0x52, 0xab, 0x3f, 0x25, 0x21, 0xc3, 0xbf, 0xaf, 0xd1, 0x13, 0x28, 0xc4, 0xaf, - 0x7a, 0x74, 0x25, 0x4a, 0xd6, 0xd8, 0x96, 0x58, 0x51, 0x4e, 0x32, 0x11, 0x9b, 0x49, 0x49, 0xbc, - 0x2f, 0x21, 0x03, 0x66, 0x8e, 0x5c, 0x33, 0xe8, 0xea, 0x88, 0xf3, 0xd8, 0x5b, 0xbd, 0x72, 0xed, - 0x14, 0xab, 0x48, 0x14, 0x87, 0x77, 0xee, 0xa3, 0xfb, 0x1a, 0x2d, 0x9f, 0x84, 0x11, 0x5b, 0xd0, - 0xf5, 0x33, 0x58, 0x0e, 0x23, 0xae, 0x3d, 0x79, 0xf9, 0x5a, 0x4e, 0xbc, 0x7a, 0x2d, 0x27, 0xde, - 0xbe, 0x96, 0xa5, 0x2f, 0x0f, 0x65, 0xe9, 0x87, 0x43, 0x59, 0xfa, 0xe5, 0x50, 0x96, 0x5e, 0x1e, - 0xca, 0xd2, 0x5f, 0x87, 0xb2, 0xf4, 0xf7, 0xa1, 0x9c, 0x78, 0x7b, 0x28, 0x4b, 0xdf, 0xbc, 0x91, - 0x13, 0x2f, 0xdf, 0xc8, 0x89, 0x57, 0x6f, 0xe4, 0x04, 0x14, 0x74, 0xbb, 0x17, 0x89, 0xb3, 0x26, - 0xfe, 0x70, 0x6c, 0xbb, 0x36, 0xb3, 0xb7, 0xa5, 0x4f, 0x27, 0xb9, 0xd0, 0x69, 0xb7, 0x27, 0xf8, - 0xdf, 0x90, 0x5b, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0x57, 0x9b, 0xab, 0x53, 0x1c, 0x11, 0x00, - 0x00, + // 1478 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x58, 0xbd, 0x6f, 0xdb, 0x46, + 0x14, 0x17, 0xf5, 0x61, 0x4b, 0x4f, 0xb6, 0x24, 0x9f, 0x1d, 0x57, 0x96, 0x13, 0xc6, 0x21, 0x12, + 0xc0, 0x49, 0x51, 0xa7, 0x70, 0x11, 0x34, 0x4d, 0x91, 0x41, 0x96, 0x18, 0x5b, 0x88, 0x23, 0xbb, + 0x67, 0x39, 0x45, 0x9a, 0x02, 0xc4, 0x89, 0xbc, 0xc8, 0x44, 0x25, 0x92, 0x25, 0x4f, 0x89, 0x9d, + 0xa9, 0x6b, 0x97, 0xa2, 0x63, 0xa7, 0x0e, 0x9d, 0xba, 0x77, 0xed, 0xd2, 0xad, 0x1d, 0x0a, 0xa4, + 0xe8, 0x92, 0xa1, 0x43, 0xe3, 0x2c, 0x1d, 0xf3, 0x27, 0x14, 0xbc, 0xa3, 0x28, 0x52, 0x96, 0xbf, + 0x90, 0xa5, 0x43, 0xb7, 0xe3, 0xfb, 0xf8, 0xbd, 0x77, 0xef, 0x77, 0xf7, 0xde, 0x49, 0x90, 0x67, + 0xc4, 0xea, 0xd8, 0x2b, 0x8e, 0x6b, 0x33, 0x1b, 0x41, 0xbf, 0x4d, 0xdd, 0x15, 0x2e, 0x51, 0x3e, + 0x01, 0x68, 0xf9, 0x0b, 0xd5, 0x75, 0x6d, 0x17, 0x5d, 0x87, 0xb4, 0x6e, 0x1b, 0xb4, 0x2c, 0x2d, + 0x49, 0xcb, 0x85, 0xd5, 0x0b, 0x2b, 0x43, 0xc3, 0x15, 0x6e, 0x50, 0xb3, 0x0d, 0x8a, 0xb9, 0x09, + 0x2a, 0xc3, 0x64, 0x8f, 0x7a, 0x1e, 0xe9, 0xd0, 0x72, 0x72, 0x49, 0x5a, 0xce, 0xe1, 0xc1, 0xa7, + 0xb2, 0x08, 0x93, 0x98, 0x7e, 0xd9, 0xa7, 0x1e, 0x43, 0x25, 0x48, 0xf5, 0xdd, 0x2e, 0x87, 0xcb, + 0x61, 0x7f, 0xa9, 0xfc, 0x24, 0x41, 0x69, 0xad, 0x6f, 0x76, 0x8d, 0x3a, 0xf5, 0x74, 0xd7, 0x74, + 0x98, 0x69, 0x5b, 0x68, 0x1e, 0x26, 0x5c, 0xda, 0xb3, 0x19, 0x0d, 0x2c, 0x83, 0x2f, 0xb4, 0x00, + 0xd9, 0x36, 0xf1, 0xa8, 0xe6, 0xed, 0x91, 0x41, 0x10, 0xff, 0x7b, 0x67, 0x8f, 0xa0, 0x9b, 0x90, + 0x75, 0x45, 0x10, 0xaf, 0x9c, 0x5a, 0x4a, 0x2d, 0xe7, 0x57, 0x67, 0xa3, 0xd9, 0x06, 0x09, 0xe0, + 0xd0, 0x08, 0x7d, 0x0c, 0x59, 0x8f, 0xb9, 0x84, 0xd1, 0xce, 0x41, 0x39, 0xcd, 0xb7, 0x77, 0x39, + 0xea, 0x50, 0xb3, 0x7b, 0x4e, 0x9f, 0x11, 0x3f, 0x9d, 0x9d, 0xc0, 0x0c, 0x87, 0x0e, 0xca, 0x6f, + 0x12, 0x4c, 0x6d, 0xf5, 0x99, 0xd3, 0x67, 0x35, 0xdb, 0x7a, 0x62, 0x76, 0xd0, 0x15, 0x98, 0x32, + 0x2d, 0xbd, 0xdb, 0x37, 0xa8, 0xc6, 0x48, 0xc7, 0xe3, 0x79, 0x67, 0x71, 0x3e, 0x90, 0xb5, 0x48, + 0xc7, 0x43, 0xef, 0x01, 0x1a, 0x98, 0x10, 0xc6, 0x5c, 0xb3, 0xdd, 0x67, 0xd4, 0xe3, 0xdb, 0xc8, + 0xe2, 0x99, 0x40, 0x53, 0x0d, 0x15, 0xe8, 0x1a, 0x14, 0x06, 0xe6, 0x7b, 0xc4, 0xdb, 0xa3, 0xfe, + 0xb6, 0x7c, 0xd3, 0xe9, 0x40, 0xba, 0xc1, 0x85, 0xe8, 0x12, 0x80, 0x6b, 0xdb, 0xcc, 0xd3, 0x6c, + 0xab, 0x2b, 0x36, 0x92, 0xc5, 0x39, 0x2e, 0xd9, 0xb2, 0xba, 0x07, 0x7e, 0x5e, 0x3d, 0xb2, 0xaf, + 0x19, 0xa6, 0xc7, 0x88, 0xa5, 0xd3, 0x72, 0x66, 0x49, 0x5a, 0xce, 0xe0, 0x7c, 0x8f, 0xec, 0xd7, + 0x03, 0x91, 0x72, 0x1f, 0x0a, 0x41, 0x75, 0xb6, 0x78, 0xf5, 0x3d, 0xf4, 0x11, 0x2c, 0xd0, 0x7d, + 0xe6, 0x12, 0x8d, 0xee, 0x8b, 0x04, 0x9e, 0x98, 0x5d, 0xea, 0x69, 0x2e, 0xed, 0xd0, 0xfd, 0xb2, + 0xb4, 0x94, 0x5a, 0xce, 0xe1, 0x79, 0x6e, 0xa0, 0x0a, 0xfd, 0x3d, 0x5f, 0x8d, 0x7d, 0xad, 0xf2, + 0x67, 0x12, 0x8a, 0x3e, 0x4c, 0xcf, 0x7c, 0x4e, 0x8d, 0x16, 0x71, 0x3b, 0x94, 0xa1, 0x02, 0x24, + 0x4d, 0x83, 0x57, 0x24, 0x83, 0x93, 0xa6, 0x81, 0x10, 0xa4, 0xfd, 0x1d, 0x05, 0x0c, 0xf2, 0x35, + 0xba, 0x09, 0xb3, 0x86, 0xe9, 0x52, 0x9d, 0x69, 0x06, 0x75, 0xa8, 0x65, 0x50, 0x4b, 0x37, 0xa9, + 0x60, 0x32, 0x83, 0x91, 0x50, 0xd5, 0x23, 0x1a, 0x1f, 0x84, 0x17, 0x3a, 0xcd, 0x2d, 0xf8, 0x1a, + 0x2d, 0x42, 0xce, 0xed, 0x77, 0xa9, 0xc6, 0x0e, 0x9c, 0xc1, 0x4e, 0xb3, 0xbe, 0xa0, 0x75, 0xe0, + 0x50, 0xdf, 0xc1, 0x2f, 0x4b, 0x79, 0x82, 0x97, 0x88, 0xaf, 0x51, 0x05, 0xb2, 0x74, 0x9f, 0x51, + 0xd7, 0x22, 0xdd, 0xf2, 0x24, 0x97, 0x87, 0xdf, 0xe8, 0x3e, 0x40, 0x84, 0xa6, 0x2c, 0x3f, 0x52, + 0xef, 0x46, 0x4f, 0xc8, 0xc8, 0x36, 0x57, 0x86, 0xdc, 0xa9, 0x16, 0x73, 0x0f, 0x70, 0xc4, 0xbd, + 0x72, 0x17, 0x8a, 0x23, 0x6a, 0xff, 0x2a, 0x7c, 0x41, 0x0f, 0x82, 0xb2, 0xf8, 0x4b, 0x34, 0x07, + 0x99, 0xa7, 0xa4, 0xdb, 0x17, 0xf7, 0x27, 0x83, 0xc5, 0xc7, 0x9d, 0xe4, 0x6d, 0x49, 0x69, 0x40, + 0x69, 0x24, 0x9a, 0x87, 0x6e, 0xc1, 0x24, 0x13, 0x4b, 0x4e, 0x49, 0x7e, 0x75, 0xf1, 0x84, 0xe4, + 0xf0, 0xc0, 0x56, 0x69, 0x41, 0xa1, 0xb6, 0x47, 0xac, 0xce, 0x10, 0x68, 0x0d, 0x8a, 0xba, 0x90, + 0x68, 0x71, 0xc0, 0x85, 0xd8, 0x7d, 0x88, 0x3a, 0xe1, 0x82, 0x1e, 0xc3, 0x50, 0xfe, 0x92, 0x60, + 0x3a, 0x66, 0x81, 0x3e, 0x84, 0xbc, 0xb0, 0x11, 0x6c, 0x88, 0x06, 0x32, 0x7f, 0x14, 0xd1, 0xe7, + 0x06, 0x83, 0x1e, 0xae, 0xd1, 0x1d, 0x00, 0xbb, 0x3b, 0x48, 0x85, 0x97, 0xe2, 0x94, 0xad, 0xe5, + 0xec, 0xee, 0x20, 0xe8, 0x1d, 0x00, 0x8b, 0x3e, 0x1b, 0xf8, 0xa6, 0xce, 0xe0, 0x6b, 0xd1, 0x67, + 0x81, 0x6f, 0x05, 0xb2, 0xe1, 0x2d, 0x49, 0x8b, 0xb3, 0x33, 0xf8, 0x56, 0x7e, 0x99, 0x80, 0xec, + 0x03, 0xca, 0x88, 0x41, 0x18, 0x41, 0xbb, 0x30, 0x23, 0x02, 0x68, 0xa6, 0xa1, 0xf5, 0x88, 0xe3, + 0x98, 0x56, 0x27, 0xa8, 0xd8, 0xf5, 0x68, 0xac, 0x81, 0xc3, 0x8a, 0x08, 0xd0, 0x30, 0x1e, 0x08, + 0x5b, 0x71, 0x3a, 0x8a, 0x2c, 0x2e, 0xf5, 0x61, 0xc3, 0xc3, 0x1b, 0xc2, 0x26, 0x4f, 0x80, 0xc5, + 0xc1, 0xc9, 0x8e, 0xc3, 0xba, 0x71, 0x29, 0x52, 0xfd, 0x56, 0xdf, 0x09, 0x01, 0x45, 0x6b, 0xbc, + 0x7a, 0x4c, 0x9e, 0x9d, 0x18, 0x16, 0xb0, 0x50, 0x80, 0x0c, 0x98, 0x0f, 0x8f, 0xb3, 0x66, 0x91, + 0xde, 0x30, 0xc5, 0x34, 0x47, 0x5c, 0x19, 0x8b, 0x18, 0x9e, 0xf9, 0x26, 0xe9, 0xc5, 0xf3, 0x9c, + 0x23, 0x63, 0x54, 0xe8, 0x39, 0xc8, 0xc3, 0x28, 0x1e, 0x73, 0x4d, 0xab, 0xa3, 0xf1, 0x5b, 0x10, + 0x46, 0xcb, 0xf0, 0x68, 0xb7, 0x4e, 0x8e, 0xb6, 0xc3, 0x3d, 0x1f, 0xfa, 0x8e, 0xb1, 0xa0, 0x8b, + 0xe4, 0x78, 0x8b, 0xca, 0x1a, 0xcc, 0x8d, 0x23, 0xea, 0xb4, 0x7b, 0x9a, 0x8b, 0xdc, 0x53, 0x1f, + 0x63, 0x1c, 0x2b, 0xe7, 0xc2, 0xb8, 0x0b, 0xc5, 0x11, 0x22, 0xce, 0xe5, 0xbe, 0x0e, 0x0b, 0xc7, + 0x56, 0xfd, 0x5c, 0x40, 0x4d, 0x58, 0x3a, 0xad, 0xa0, 0xe7, 0xc1, 0x53, 0xbe, 0x4e, 0xc2, 0x85, + 0x75, 0xca, 0x44, 0x8d, 0xd7, 0x5d, 0xe2, 0xec, 0x0d, 0x1e, 0x05, 0x0d, 0x98, 0x69, 0xfb, 0x2f, + 0x00, 0xcd, 0x18, 0x3e, 0x01, 0x38, 0x66, 0x7e, 0xf5, 0x62, 0x94, 0xe8, 0xd1, 0x67, 0x02, 0x2e, + 0xb5, 0x47, 0x1f, 0x0e, 0x77, 0x61, 0xda, 0xe6, 0x63, 0x59, 0xd3, 0xf9, 0x5c, 0x0e, 0xfa, 0x47, + 0x39, 0xd6, 0x03, 0x22, 0x73, 0x1b, 0x4f, 0xd9, 0xd1, 0x29, 0x5e, 0x83, 0x62, 0xf0, 0x3e, 0xd0, + 0x6c, 0x31, 0x0b, 0x83, 0x26, 0x52, 0x19, 0xf3, 0x96, 0x08, 0xa6, 0x25, 0x2e, 0xb8, 0xf1, 0xe9, + 0x79, 0x05, 0xa6, 0xda, 0x07, 0x0e, 0xf1, 0x3c, 0x4d, 0x27, 0xfa, 0x1e, 0x0d, 0x66, 0x72, 0x5e, + 0xc8, 0x6a, 0xbe, 0x48, 0xf9, 0x46, 0x82, 0xf9, 0xd1, 0x5a, 0x78, 0x8e, 0x6d, 0x79, 0x14, 0xdd, + 0x8e, 0xb6, 0xf5, 0x23, 0x25, 0x18, 0x9d, 0x02, 0x1b, 0x89, 0xb0, 0xb3, 0xa3, 0x55, 0xc8, 0xf6, + 0x82, 0xab, 0x10, 0x6c, 0x7b, 0x6e, 0xdc, 0x35, 0xd9, 0x48, 0xe0, 0xd0, 0x6e, 0x6d, 0x02, 0xd2, + 0x26, 0xa3, 0x3d, 0xe5, 0xf7, 0x24, 0x94, 0xd7, 0x29, 0x8b, 0x4f, 0x86, 0x01, 0x3f, 0x35, 0x28, + 0x3c, 0x31, 0x5d, 0x8f, 0x69, 0x2e, 0x7d, 0x6a, 0x7a, 0x67, 0x25, 0x67, 0x9a, 0xfb, 0xe0, 0xc0, + 0x05, 0xa9, 0x50, 0xf4, 0xa8, 0x6e, 0x5b, 0xc6, 0x10, 0x25, 0x79, 0x06, 0x94, 0x82, 0x70, 0x0a, + 0x61, 0x8e, 0x10, 0x9c, 0x7a, 0x5b, 0x82, 0xd3, 0x6f, 0x4d, 0x70, 0xe6, 0x28, 0xc1, 0xdf, 0x4b, + 0xb0, 0x30, 0xa6, 0x9e, 0x01, 0xc7, 0xea, 0xb8, 0x89, 0x7b, 0x24, 0x8b, 0xb8, 0xf3, 0x46, 0x62, + 0x74, 0xe8, 0xbe, 0x15, 0xe1, 0x7f, 0x24, 0xe1, 0xe2, 0x68, 0x82, 0xb1, 0x4b, 0xf9, 0x3f, 0xe9, + 0xe7, 0x26, 0xfd, 0x07, 0x09, 0x2e, 0x1d, 0x53, 0xd3, 0xff, 0x0c, 0xf1, 0x37, 0x3e, 0x87, 0x5c, + 0xf8, 0xcb, 0x0d, 0x15, 0x21, 0xaf, 0x62, 0xbc, 0x85, 0xb5, 0x46, 0xf3, 0x1e, 0xae, 0x96, 0x12, + 0x68, 0x16, 0x8a, 0x42, 0x50, 0xab, 0x36, 0x6b, 0xea, 0xe6, 0xa6, 0x5a, 0x2f, 0x49, 0xa8, 0x00, + 0x20, 0x84, 0xbb, 0x3b, 0x2a, 0x2e, 0x25, 0xd1, 0x02, 0x5c, 0x88, 0x78, 0x69, 0x58, 0x6d, 0xe1, + 0x47, 0xd5, 0xb5, 0x4d, 0xb5, 0x94, 0xba, 0xf1, 0x9d, 0x04, 0xb3, 0x63, 0x7e, 0x39, 0xa1, 0x25, + 0xb8, 0x58, 0xdb, 0x7a, 0xb0, 0xbd, 0xdb, 0xaa, 0xb6, 0x1a, 0x5b, 0x4d, 0x6d, 0xa7, 0x85, 0xab, + 0x2d, 0x75, 0xfd, 0x91, 0xd6, 0x68, 0x3e, 0xac, 0x6e, 0x36, 0xea, 0xa5, 0x04, 0x92, 0xa1, 0x32, + 0xd6, 0x62, 0xb7, 0xb9, 0xa3, 0xb6, 0x4a, 0xd2, 0xb1, 0xfa, 0x9d, 0x0d, 0x75, 0x73, 0xb3, 0x94, + 0x44, 0x97, 0x61, 0x71, 0xac, 0xbe, 0x59, 0x6d, 0x35, 0x1e, 0xfa, 0xa9, 0x75, 0x01, 0x86, 0x2f, + 0x4e, 0xf4, 0x0e, 0xcc, 0xd6, 0x36, 0xaa, 0xcd, 0x75, 0x55, 0x6b, 0x3d, 0xda, 0x56, 0x23, 0x79, + 0xcc, 0x42, 0x31, 0xaa, 0x68, 0xaa, 0x9f, 0x96, 0xa4, 0x51, 0xeb, 0xba, 0xba, 0xa9, 0xb6, 0xd4, + 0x7a, 0x29, 0x39, 0xaa, 0x10, 0xeb, 0x7a, 0x29, 0xb5, 0xfa, 0x73, 0x12, 0x32, 0xfc, 0x77, 0x34, + 0x7a, 0x0c, 0x85, 0x78, 0xab, 0x47, 0x57, 0xa2, 0x64, 0x8d, 0x1d, 0x89, 0x15, 0xe5, 0x24, 0x13, + 0x71, 0x98, 0x94, 0xc4, 0xfb, 0x12, 0x32, 0x60, 0xe6, 0x48, 0x9b, 0x41, 0x57, 0x47, 0x9c, 0xc7, + 0x76, 0xf5, 0xca, 0xb5, 0x53, 0xac, 0x22, 0x51, 0x1c, 0x3e, 0xb9, 0x8f, 0x9e, 0x6b, 0xb4, 0x7c, + 0x12, 0x46, 0x6c, 0x43, 0xd7, 0xcf, 0x60, 0x39, 0x8c, 0xb8, 0xf6, 0xf8, 0xc5, 0x2b, 0x39, 0xf1, + 0xf2, 0x95, 0x9c, 0x78, 0xf3, 0x4a, 0x96, 0xbe, 0x3a, 0x94, 0xa5, 0x1f, 0x0f, 0x65, 0xe9, 0xd7, + 0x43, 0x59, 0x7a, 0x71, 0x28, 0x4b, 0x7f, 0x1f, 0xca, 0xd2, 0x3f, 0x87, 0x72, 0xe2, 0xcd, 0xa1, + 0x2c, 0x7d, 0xfb, 0x5a, 0x4e, 0xbc, 0x78, 0x2d, 0x27, 0x5e, 0xbe, 0x96, 0x13, 0x50, 0xd0, 0xed, + 0x5e, 0x24, 0xce, 0x9a, 0xf8, 0x27, 0x63, 0xdb, 0xb5, 0x99, 0xbd, 0x2d, 0x7d, 0x36, 0xc9, 0x85, + 0x4e, 0xbb, 0x3d, 0xc1, 0xff, 0xf5, 0xf8, 0xe0, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x30, 0x46, + 0x40, 0xd5, 0x04, 0x11, 0x00, 0x00, } func (x ErrorCode) String() string { @@ -1497,9 +1495,6 @@ func (this *Request) Equal(that interface{}) bool { if this.Url != that1.Url { return false } - if this.Commit != that1.Commit { - return false - } return true } func (this *BuildDescription) Equal(that interface{}) bool { @@ -2171,10 +2166,9 @@ func (this *Request) GoString() string { if this == nil { return "nil" } - s := make([]string, 0, 6) + s := make([]string, 0, 5) s = append(s, "&tangopb.Request{") s = append(s, "Url: "+fmt.Sprintf("%#v", this.Url)+",\n") - s = append(s, "Commit: "+fmt.Sprintf("%#v", this.Commit)+",\n") s = append(s, "}") return strings.Join(s, "") } @@ -2571,13 +2565,6 @@ func (m *Request) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.Commit) > 0 { - i -= len(m.Commit) - copy(dAtA[i:], m.Commit) - i = encodeVarintTango(dAtA, i, uint64(len(m.Commit))) - i-- - dAtA[i] = 0x12 - } if len(m.Url) > 0 { i -= len(m.Url) copy(dAtA[i:], m.Url) @@ -3586,10 +3573,6 @@ func (m *Request) Size() (n int) { if l > 0 { n += 1 + l + sovTango(uint64(l)) } - l = len(m.Commit) - if l > 0 { - n += 1 + l + sovTango(uint64(l)) - } return n } @@ -4019,7 +4002,6 @@ func (this *Request) String() string { } s := strings.Join([]string{`&Request{`, `Url:` + fmt.Sprintf("%v", this.Url) + `,`, - `Commit:` + fmt.Sprintf("%v", this.Commit) + `,`, `}`, }, "") return s @@ -4501,38 +4483,6 @@ func (m *Request) Unmarshal(dAtA []byte) error { } m.Url = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Commit", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTango - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTango - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTango - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Commit = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTango(dAtA[iNdEx:]) diff --git a/tangopb/tango.pb.yarpc.go b/tangopb/tango.pb.yarpc.go index 43f006fa..3a8d55c8 100644 --- a/tangopb/tango.pb.yarpc.go +++ b/tangopb/tango.pb.yarpc.go @@ -463,96 +463,95 @@ var ( var yarpcFileDescriptorClosurec4210c857dbeec96 = [][]byte{ // tango.proto []byte{ - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x58, 0x4b, 0x6f, 0xdb, 0xc6, - 0x16, 0x36, 0x29, 0xc9, 0x96, 0x8e, 0x6c, 0x89, 0x1e, 0x3b, 0xbe, 0xb2, 0x9c, 0x87, 0x43, 0x24, - 0xb8, 0x4e, 0x2e, 0xae, 0x73, 0xe1, 0x20, 0xb8, 0x69, 0x8a, 0x2c, 0x64, 0x89, 0xb1, 0x85, 0x38, - 0xb2, 0x3b, 0xa6, 0x53, 0xa4, 0x2d, 0x40, 0x8c, 0xc8, 0x89, 0x4c, 0x54, 0x7c, 0x94, 0x1c, 0x25, - 0x56, 0xfe, 0x41, 0x37, 0x5d, 0x77, 0xd5, 0x45, 0xff, 0x42, 0xb7, 0xdd, 0x74, 0xd9, 0x45, 0x17, - 0x45, 0xb7, 0xfd, 0x31, 0x05, 0x67, 0x28, 0x8a, 0x94, 0xe4, 0x17, 0xb2, 0xe9, 0xa2, 0xbb, 0x99, - 0xf3, 0xf8, 0xce, 0x99, 0xf3, 0xcd, 0xcc, 0x19, 0x12, 0xca, 0x8c, 0xb8, 0x3d, 0x6f, 0xdb, 0x0f, - 0x3c, 0xe6, 0x21, 0x18, 0x74, 0x69, 0xb0, 0xcd, 0x25, 0xea, 0x67, 0x00, 0x7a, 0x34, 0xd0, 0x82, - 0xc0, 0x0b, 0xd0, 0x03, 0xc8, 0x9b, 0x9e, 0x45, 0x6b, 0xd2, 0xa6, 0xb4, 0x55, 0xd9, 0xb9, 0xb1, - 0x3d, 0x36, 0xdc, 0xe6, 0x06, 0x4d, 0xcf, 0xa2, 0x98, 0x9b, 0xa0, 0x1a, 0x2c, 0x38, 0x34, 0x0c, - 0x49, 0x8f, 0xd6, 0xe4, 0x4d, 0x69, 0xab, 0x84, 0x47, 0x53, 0xf5, 0x31, 0x2c, 0x60, 0xfa, 0xcd, - 0x80, 0x86, 0x0c, 0x29, 0x90, 0x1b, 0x04, 0x7d, 0x0e, 0x57, 0xc2, 0xd1, 0x10, 0xad, 0xc1, 0xbc, - 0xe9, 0x39, 0x8e, 0xcd, 0x62, 0xaf, 0x78, 0xa6, 0xfe, 0x24, 0x81, 0xb2, 0x3b, 0xb0, 0xfb, 0x56, - 0x8b, 0x86, 0x66, 0x60, 0xfb, 0xcc, 0xf6, 0xdc, 0xc8, 0x38, 0xa0, 0x8e, 0xc7, 0x68, 0x8c, 0x10, - 0xcf, 0xd0, 0x3a, 0x14, 0xbb, 0x24, 0xa4, 0x46, 0x78, 0x4a, 0x46, 0xc1, 0xa3, 0xf9, 0xf1, 0x29, - 0x41, 0x8f, 0xa0, 0x18, 0x88, 0xe0, 0x61, 0x2d, 0xb7, 0x99, 0xdb, 0x2a, 0xef, 0xac, 0xa4, 0x57, - 0x11, 0x27, 0x86, 0x13, 0x23, 0xf4, 0x29, 0x14, 0x43, 0x16, 0x10, 0x46, 0x7b, 0xc3, 0x5a, 0x9e, - 0x2f, 0xfb, 0x4e, 0xda, 0xa1, 0xe9, 0x39, 0xfe, 0x80, 0x91, 0x28, 0x9d, 0xe3, 0xd8, 0x0c, 0x27, - 0x0e, 0xea, 0xaf, 0x12, 0x2c, 0x1e, 0x0e, 0x98, 0x3f, 0x60, 0x4d, 0xcf, 0x7d, 0x6b, 0xf7, 0xd0, - 0x5d, 0x58, 0xb4, 0x5d, 0xb3, 0x3f, 0xb0, 0xa8, 0xc1, 0x48, 0x2f, 0xe4, 0x79, 0x17, 0x71, 0x39, - 0x96, 0xe9, 0xa4, 0x17, 0xa2, 0xff, 0x02, 0x1a, 0x99, 0x10, 0xc6, 0x02, 0xbb, 0x3b, 0x60, 0x34, - 0xe4, 0xcb, 0x28, 0xe2, 0xe5, 0x58, 0xd3, 0x48, 0x14, 0xe8, 0x3e, 0x54, 0x46, 0xe6, 0xa7, 0x24, - 0x3c, 0xa5, 0xd1, 0xb2, 0x22, 0xd3, 0xa5, 0x58, 0xba, 0xcf, 0x85, 0xe8, 0x16, 0x40, 0xe0, 0x79, - 0x2c, 0x34, 0x3c, 0xb7, 0x2f, 0x16, 0x52, 0xc4, 0x25, 0x2e, 0x39, 0x74, 0xfb, 0xc3, 0x28, 0x2f, - 0x87, 0x9c, 0x19, 0x96, 0x1d, 0x32, 0xe2, 0x9a, 0xb4, 0x56, 0xd8, 0x94, 0xb6, 0x0a, 0xb8, 0xec, - 0x90, 0xb3, 0x56, 0x2c, 0x52, 0x5f, 0x42, 0x25, 0xae, 0xce, 0x21, 0xaf, 0x7e, 0x88, 0x3e, 0x81, - 0x75, 0x7a, 0xc6, 0x02, 0x62, 0xd0, 0x33, 0x91, 0xc0, 0x5b, 0xbb, 0x4f, 0x43, 0x23, 0xa0, 0x3d, - 0x7a, 0x56, 0x93, 0x36, 0x73, 0x5b, 0x25, 0xbc, 0xc6, 0x0d, 0x34, 0xa1, 0x7f, 0x11, 0xa9, 0x71, - 0xa4, 0x55, 0xff, 0x90, 0xa1, 0x1a, 0xc1, 0x38, 0xf6, 0x07, 0x6a, 0xe9, 0x24, 0xe8, 0x51, 0x86, - 0x2a, 0x20, 0xdb, 0x16, 0xaf, 0x48, 0x01, 0xcb, 0xb6, 0x85, 0x10, 0xe4, 0xa3, 0x15, 0xc5, 0x0c, - 0xf2, 0x31, 0x7a, 0x04, 0x2b, 0x96, 0x1d, 0x50, 0x93, 0x19, 0x16, 0xf5, 0xa9, 0x6b, 0x51, 0xd7, - 0xb4, 0xa9, 0x60, 0xb2, 0x80, 0x91, 0x50, 0xb5, 0x52, 0x9a, 0x08, 0x84, 0x17, 0x3a, 0xcf, 0x2d, - 0xf8, 0x18, 0x6d, 0x40, 0x29, 0x18, 0xf4, 0xa9, 0xc1, 0x86, 0xfe, 0x68, 0xa5, 0xc5, 0x48, 0xa0, - 0x0f, 0x7d, 0x1a, 0x39, 0x44, 0x65, 0xa9, 0xcd, 0xf3, 0x12, 0xf1, 0x31, 0xaa, 0x43, 0x91, 0x9e, - 0x31, 0x1a, 0xb8, 0xa4, 0x5f, 0x5b, 0xe0, 0xf2, 0x64, 0x8e, 0x5e, 0x02, 0xa4, 0x68, 0x2a, 0xf2, - 0x2d, 0xf5, 0x9f, 0xf4, 0x0e, 0x99, 0x58, 0xe6, 0xf6, 0x98, 0x3b, 0xcd, 0x65, 0xc1, 0x10, 0xa7, - 0xdc, 0xeb, 0xcf, 0xa1, 0x3a, 0xa1, 0x8e, 0x8e, 0xc8, 0xd7, 0x74, 0x18, 0x97, 0x25, 0x1a, 0xa2, - 0x55, 0x28, 0xbc, 0x23, 0xfd, 0x81, 0x38, 0x57, 0x05, 0x2c, 0x26, 0xcf, 0xe4, 0xa7, 0x92, 0xda, - 0x06, 0x65, 0x22, 0x5a, 0x88, 0x9e, 0xc0, 0x02, 0x13, 0x43, 0x4e, 0x49, 0x79, 0x67, 0xe3, 0x82, - 0xe4, 0xf0, 0xc8, 0x56, 0xd5, 0xa1, 0xd2, 0x3c, 0x25, 0x6e, 0x6f, 0x0c, 0xb4, 0x0b, 0x55, 0x53, - 0x48, 0x8c, 0x2c, 0xe0, 0x7a, 0xe6, 0x3c, 0xa4, 0x9d, 0x70, 0xc5, 0xcc, 0x60, 0xa8, 0x7f, 0x4a, - 0xb0, 0x94, 0xb1, 0x40, 0xff, 0x87, 0xb2, 0xb0, 0x11, 0x6c, 0x88, 0x8b, 0x65, 0x6d, 0x1a, 0x31, - 0xe2, 0x06, 0x83, 0x99, 0x8c, 0xd1, 0x33, 0x00, 0xaf, 0x3f, 0x4a, 0x85, 0x97, 0xe2, 0x92, 0xa5, - 0x95, 0xbc, 0xfe, 0x28, 0xe8, 0x33, 0x00, 0x97, 0xbe, 0x1f, 0xf9, 0xe6, 0xae, 0xe0, 0xeb, 0xd2, - 0xf7, 0xb1, 0x6f, 0x1d, 0x8a, 0xc9, 0x29, 0xc9, 0x8b, 0xbd, 0x33, 0x9a, 0xab, 0xbf, 0xcc, 0x43, - 0xf1, 0x15, 0x65, 0xc4, 0x22, 0x8c, 0xa0, 0x13, 0x58, 0x16, 0x01, 0x0c, 0xdb, 0x32, 0x1c, 0xe2, - 0xfb, 0xb6, 0xdb, 0x8b, 0x2b, 0xf6, 0x20, 0x1d, 0x6b, 0xe4, 0xb0, 0x2d, 0x02, 0xb4, 0xad, 0x57, - 0xc2, 0x56, 0xec, 0x8e, 0x2a, 0xcb, 0x4a, 0x23, 0xd8, 0x64, 0xf3, 0x26, 0xb0, 0xf2, 0x05, 0xb0, - 0x38, 0xde, 0xd9, 0x59, 0xd8, 0x20, 0x2b, 0x45, 0x5a, 0xd4, 0x02, 0x7a, 0x09, 0xa0, 0xb8, 0x1a, - 0xef, 0x9d, 0x93, 0x67, 0x2f, 0x83, 0x05, 0x2c, 0x11, 0x20, 0x0b, 0xd6, 0x92, 0xed, 0x6c, 0xb8, - 0xc4, 0x19, 0xa7, 0x98, 0xe7, 0x88, 0xdb, 0x33, 0x11, 0x93, 0x3d, 0xdf, 0x21, 0x4e, 0x36, 0xcf, - 0x55, 0x32, 0x43, 0x85, 0x3e, 0xc0, 0xed, 0x71, 0x94, 0x90, 0x05, 0xb6, 0xdb, 0x33, 0xf8, 0x29, - 0x48, 0xa2, 0x15, 0x78, 0xb4, 0x27, 0x17, 0x47, 0x3b, 0xe6, 0x9e, 0xaf, 0x23, 0xc7, 0x4c, 0xd0, - 0x0d, 0x72, 0xbe, 0x45, 0x7d, 0x17, 0x56, 0x67, 0x11, 0x75, 0xd9, 0x39, 0x2d, 0xa5, 0xce, 0x69, - 0x84, 0x31, 0x8b, 0x95, 0x6b, 0x61, 0x3c, 0x87, 0xea, 0x04, 0x11, 0xd7, 0x72, 0xdf, 0x83, 0xf5, - 0x73, 0xab, 0x7e, 0x2d, 0xa0, 0x0e, 0x6c, 0x5e, 0x56, 0xd0, 0xeb, 0xe0, 0xa9, 0xdf, 0xca, 0x70, - 0x63, 0x8f, 0x32, 0x51, 0xe3, 0xbd, 0x80, 0xf8, 0xa7, 0xa3, 0xc7, 0x42, 0x1b, 0x96, 0xbb, 0xd1, - 0x0b, 0xc0, 0xb0, 0xc6, 0x4f, 0x00, 0x8e, 0x59, 0xde, 0xb9, 0x99, 0x26, 0x7a, 0xf2, 0x99, 0x80, - 0x95, 0xee, 0xe4, 0xc3, 0xe1, 0x39, 0x2c, 0x79, 0xbc, 0x2d, 0x1b, 0x26, 0xef, 0xcb, 0xf1, 0xfd, - 0x51, 0xcb, 0xdc, 0x01, 0xa9, 0xbe, 0x8d, 0x17, 0xbd, 0x74, 0x17, 0x6f, 0x42, 0x35, 0x7e, 0x1f, - 0x18, 0x9e, 0xe8, 0x85, 0xf1, 0x25, 0x52, 0x9f, 0xf1, 0x96, 0x88, 0xbb, 0x25, 0xae, 0x04, 0xd9, - 0xee, 0x79, 0x17, 0x16, 0xbb, 0x43, 0x9f, 0x84, 0xa1, 0x61, 0x12, 0xf3, 0x94, 0xc6, 0x3d, 0xb9, - 0x2c, 0x64, 0xcd, 0x48, 0xa4, 0x7e, 0x27, 0xc1, 0xda, 0x64, 0x2d, 0x42, 0xdf, 0x73, 0x43, 0x8a, - 0x9e, 0xa6, 0xaf, 0xf5, 0xa9, 0x12, 0x4c, 0x76, 0x81, 0xfd, 0xb9, 0xe4, 0x66, 0x47, 0x3b, 0x50, - 0x74, 0xe2, 0xa3, 0x10, 0x2f, 0x7b, 0x75, 0xd6, 0x31, 0xd9, 0x9f, 0xc3, 0x89, 0xdd, 0xee, 0x3c, - 0xe4, 0x6d, 0x46, 0x1d, 0xf5, 0x37, 0x19, 0x6a, 0x7b, 0x94, 0x65, 0x3b, 0xc3, 0x88, 0x9f, 0x26, - 0x54, 0xde, 0xda, 0x41, 0xc8, 0x8c, 0x80, 0xbe, 0xb3, 0xc3, 0xab, 0x92, 0xb3, 0xc4, 0x7d, 0x70, - 0xec, 0x82, 0x34, 0xa8, 0x86, 0xd4, 0xf4, 0x5c, 0x6b, 0x8c, 0x22, 0x5f, 0x01, 0xa5, 0x22, 0x9c, - 0x12, 0x98, 0x29, 0x82, 0x73, 0x1f, 0x4b, 0x70, 0xfe, 0xa3, 0x09, 0x2e, 0x4c, 0x13, 0xfc, 0x83, - 0x04, 0xeb, 0x33, 0xea, 0x19, 0x73, 0xac, 0xcd, 0xea, 0xb8, 0x53, 0x59, 0x64, 0x9d, 0xf7, 0xe7, - 0x26, 0x9b, 0xee, 0x47, 0x11, 0xfe, 0xbb, 0x0c, 0x37, 0x27, 0x13, 0xcc, 0x1c, 0xca, 0x7f, 0x48, - 0xbf, 0x36, 0xe9, 0x3f, 0x4a, 0x70, 0xeb, 0x9c, 0x9a, 0xfe, 0x6d, 0x88, 0x7f, 0xf8, 0x15, 0x94, - 0x92, 0x2f, 0x3a, 0x54, 0x85, 0xb2, 0x86, 0xf1, 0x21, 0x36, 0xda, 0x9d, 0x17, 0xb8, 0xa1, 0xcc, - 0xa1, 0x15, 0xa8, 0x0a, 0x41, 0xb3, 0xd1, 0x69, 0x6a, 0x07, 0x07, 0x5a, 0x4b, 0x91, 0x50, 0x05, - 0x40, 0x08, 0x4f, 0x8e, 0x35, 0xac, 0xc8, 0x68, 0x1d, 0x6e, 0xa4, 0xbc, 0x0c, 0xac, 0xe9, 0xf8, - 0x4d, 0x63, 0xf7, 0x40, 0x53, 0x72, 0x0f, 0xbf, 0x97, 0x60, 0x65, 0xc6, 0x97, 0x13, 0xda, 0x84, - 0x9b, 0xcd, 0xc3, 0x57, 0x47, 0x27, 0x7a, 0x43, 0x6f, 0x1f, 0x76, 0x8c, 0x63, 0x1d, 0x37, 0x74, - 0x6d, 0xef, 0x8d, 0xd1, 0xee, 0xbc, 0x6e, 0x1c, 0xb4, 0x5b, 0xca, 0x1c, 0xba, 0x0d, 0xf5, 0x99, - 0x16, 0x27, 0x9d, 0x63, 0x4d, 0x57, 0xa4, 0x73, 0xf5, 0xc7, 0xfb, 0xda, 0xc1, 0x81, 0x22, 0xa3, - 0x3b, 0xb0, 0x31, 0x53, 0xdf, 0x69, 0xe8, 0xed, 0xd7, 0x51, 0x6a, 0x7d, 0x80, 0xf1, 0x8b, 0x13, - 0xfd, 0x0b, 0x56, 0x9a, 0xfb, 0x8d, 0xce, 0x9e, 0x66, 0xe8, 0x6f, 0x8e, 0xb4, 0x54, 0x1e, 0x2b, - 0x50, 0x4d, 0x2b, 0x3a, 0xda, 0xe7, 0x8a, 0x34, 0x69, 0xdd, 0xd2, 0x0e, 0x34, 0x5d, 0x6b, 0x29, - 0xf2, 0xa4, 0x42, 0x8c, 0x5b, 0x4a, 0x6e, 0xe7, 0x67, 0x19, 0x0a, 0xfc, 0xfb, 0x1a, 0x7d, 0x09, - 0x95, 0xec, 0x55, 0x8f, 0xee, 0xa6, 0xc9, 0x9a, 0xd9, 0x12, 0xeb, 0xea, 0x45, 0x26, 0x62, 0x33, - 0xa9, 0x73, 0xff, 0x93, 0x90, 0x05, 0xcb, 0x53, 0xd7, 0x0c, 0xba, 0x37, 0xe1, 0x3c, 0xf3, 0x56, - 0xaf, 0xdf, 0xbf, 0xc4, 0x2a, 0x15, 0xc5, 0xe7, 0x9d, 0x7b, 0x7a, 0x5f, 0xa3, 0xad, 0x8b, 0x30, - 0x32, 0x0b, 0x7a, 0x70, 0x05, 0xcb, 0x71, 0xc4, 0xdd, 0x7f, 0x43, 0xc5, 0xf4, 0x9c, 0x94, 0xcf, - 0xae, 0xf8, 0x5b, 0x71, 0x14, 0x78, 0xcc, 0x3b, 0x92, 0xbe, 0x58, 0xe0, 0x42, 0xbf, 0xdb, 0x9d, - 0xe7, 0x7f, 0x36, 0x1e, 0xff, 0x15, 0x00, 0x00, 0xff, 0xff, 0xcd, 0xf1, 0x53, 0x45, 0xe8, 0x10, - 0x00, 0x00, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x58, 0x4d, 0x6f, 0xdb, 0x46, + 0x13, 0x36, 0x29, 0xc9, 0x96, 0x46, 0xb6, 0x44, 0xaf, 0x1d, 0xbf, 0xb2, 0x9c, 0x0f, 0x87, 0x48, + 0xf0, 0x3a, 0x79, 0xf1, 0x3a, 0x85, 0x8b, 0xa0, 0x69, 0x8a, 0x1c, 0x64, 0x89, 0xb1, 0x85, 0x38, + 0xb2, 0xbb, 0xa2, 0x53, 0xa4, 0x2d, 0x40, 0xac, 0xc8, 0x8d, 0x44, 0x54, 0x22, 0x59, 0x72, 0x95, + 0x58, 0xf9, 0x07, 0xbd, 0xf4, 0xdc, 0x53, 0x0f, 0xfd, 0x0b, 0xbd, 0xf6, 0xd2, 0x63, 0x0f, 0x3d, + 0x14, 0xbd, 0xf6, 0xc7, 0x14, 0xdc, 0xa5, 0x28, 0x52, 0x92, 0xbf, 0x90, 0x4b, 0x0f, 0xbd, 0x2d, + 0xe7, 0xe3, 0x99, 0xd9, 0x79, 0x76, 0x67, 0x56, 0x82, 0x22, 0x23, 0x4e, 0xd7, 0xdd, 0xf5, 0x7c, + 0x97, 0xb9, 0x08, 0x86, 0x1d, 0xea, 0xef, 0x72, 0x89, 0xfa, 0x39, 0x80, 0x1e, 0x2e, 0x34, 0xdf, + 0x77, 0x7d, 0xf4, 0x00, 0xb2, 0xa6, 0x6b, 0xd1, 0x8a, 0xb4, 0x2d, 0xed, 0x94, 0xf6, 0x6e, 0xec, + 0x4e, 0x0c, 0x77, 0xb9, 0x41, 0xdd, 0xb5, 0x28, 0xe6, 0x26, 0xa8, 0x02, 0x4b, 0x03, 0x1a, 0x04, + 0xa4, 0x4b, 0x2b, 0xf2, 0xb6, 0xb4, 0x53, 0xc0, 0xe3, 0x4f, 0x75, 0x0b, 0x96, 0x30, 0xfd, 0x76, + 0x48, 0x03, 0x86, 0x14, 0xc8, 0x0c, 0xfd, 0x3e, 0x87, 0x2b, 0xe0, 0x70, 0xa9, 0xfe, 0x2c, 0x81, + 0xb2, 0x3f, 0xb4, 0xfb, 0x56, 0x83, 0x06, 0xa6, 0x6f, 0x7b, 0xcc, 0x76, 0x1d, 0xb4, 0x01, 0x8b, + 0x3e, 0x1d, 0xb8, 0x8c, 0x46, 0x96, 0xd1, 0x17, 0xda, 0x84, 0x7c, 0x87, 0x04, 0xd4, 0x08, 0x7a, + 0x64, 0x1c, 0x24, 0xfc, 0x6e, 0xf7, 0x08, 0x7a, 0x04, 0x79, 0x5f, 0x04, 0x09, 0x2a, 0x99, 0xed, + 0xcc, 0x4e, 0x71, 0x6f, 0x2d, 0x99, 0x6d, 0x94, 0x00, 0x8e, 0x8d, 0xd0, 0x67, 0x90, 0x0f, 0x98, + 0x4f, 0x18, 0xed, 0x8e, 0x2a, 0x59, 0xbe, 0xbd, 0x3b, 0x49, 0x87, 0xba, 0x3b, 0xf0, 0x86, 0x8c, + 0x84, 0xe9, 0xb4, 0x23, 0x33, 0x1c, 0x3b, 0xa8, 0xbf, 0x49, 0xb0, 0x7c, 0x3c, 0x64, 0xde, 0x90, + 0xd5, 0x5d, 0xe7, 0x8d, 0xdd, 0x45, 0x77, 0x61, 0xd9, 0x76, 0xcc, 0xfe, 0xd0, 0xa2, 0x06, 0x23, + 0xdd, 0x80, 0xe7, 0x9d, 0xc7, 0xc5, 0x48, 0xa6, 0x93, 0x6e, 0x80, 0xfe, 0x0f, 0x68, 0x6c, 0x42, + 0x18, 0xf3, 0xed, 0xce, 0x90, 0xd1, 0x80, 0x6f, 0x23, 0x8f, 0x57, 0x23, 0x4d, 0x2d, 0x56, 0xa0, + 0xfb, 0x50, 0x1a, 0x9b, 0xf7, 0x48, 0xd0, 0xa3, 0xe1, 0xb6, 0x42, 0xd3, 0x95, 0x48, 0x7a, 0xc8, + 0x85, 0xe8, 0x16, 0x80, 0xef, 0xba, 0x2c, 0x30, 0x5c, 0xa7, 0x2f, 0x36, 0x92, 0xc7, 0x05, 0x2e, + 0x39, 0x76, 0xfa, 0xa3, 0x30, 0xaf, 0x01, 0x39, 0x33, 0x2c, 0x3b, 0x60, 0xc4, 0x31, 0x69, 0x25, + 0xb7, 0x2d, 0xed, 0xe4, 0x70, 0x71, 0x40, 0xce, 0x1a, 0x91, 0x48, 0x7d, 0x01, 0xa5, 0xa8, 0x3a, + 0xc7, 0xbc, 0xfa, 0x01, 0xfa, 0x14, 0x36, 0xe9, 0x19, 0xf3, 0x89, 0x41, 0xcf, 0x44, 0x02, 0x6f, + 0xec, 0x3e, 0x0d, 0x0c, 0x9f, 0x76, 0xe9, 0x59, 0x45, 0xda, 0xce, 0xec, 0x14, 0xf0, 0x06, 0x37, + 0xd0, 0x84, 0xfe, 0x79, 0xa8, 0xc6, 0xa1, 0x56, 0xfd, 0x53, 0x86, 0x72, 0x08, 0x33, 0xb0, 0xdf, + 0x53, 0x4b, 0x27, 0x7e, 0x97, 0x32, 0x54, 0x02, 0xd9, 0xb6, 0x78, 0x45, 0x72, 0x58, 0xb6, 0x2d, + 0x84, 0x20, 0x1b, 0xee, 0x28, 0x62, 0x90, 0xaf, 0xd1, 0x23, 0x58, 0xb3, 0x6c, 0x9f, 0x9a, 0xcc, + 0xb0, 0xa8, 0x47, 0x1d, 0x8b, 0x3a, 0xa6, 0x4d, 0x05, 0x93, 0x39, 0x8c, 0x84, 0xaa, 0x91, 0xd0, + 0x84, 0x20, 0xbc, 0xd0, 0x59, 0x6e, 0xc1, 0xd7, 0x68, 0x0b, 0x0a, 0xfe, 0xb0, 0x4f, 0x0d, 0x36, + 0xf2, 0xc6, 0x3b, 0xcd, 0x87, 0x02, 0x7d, 0xe4, 0xd1, 0xd0, 0x21, 0x2c, 0x4b, 0x65, 0x91, 0x97, + 0x88, 0xaf, 0x51, 0x15, 0xf2, 0xf4, 0x8c, 0x51, 0xdf, 0x21, 0xfd, 0xca, 0x12, 0x97, 0xc7, 0xdf, + 0xe8, 0x05, 0x40, 0x82, 0xa6, 0x3c, 0x3f, 0x52, 0xff, 0x4b, 0x9e, 0x90, 0xa9, 0x6d, 0xee, 0x4e, + 0xb8, 0xd3, 0x1c, 0xe6, 0x8f, 0x70, 0xc2, 0xbd, 0xfa, 0x0c, 0xca, 0x53, 0xea, 0xf0, 0x2a, 0x7c, + 0x43, 0x47, 0x51, 0x59, 0xc2, 0x25, 0x5a, 0x87, 0xdc, 0x5b, 0xd2, 0x1f, 0x8a, 0xfb, 0x93, 0xc3, + 0xe2, 0xe3, 0xa9, 0xfc, 0x44, 0x52, 0x9b, 0xa0, 0x4c, 0x45, 0x0b, 0xd0, 0x63, 0x58, 0x62, 0x62, + 0xc9, 0x29, 0x29, 0xee, 0x6d, 0x5d, 0x90, 0x1c, 0x1e, 0xdb, 0xaa, 0x3a, 0x94, 0xea, 0x3d, 0xe2, + 0x74, 0x27, 0x40, 0xfb, 0x50, 0x36, 0x85, 0xc4, 0x48, 0x03, 0x6e, 0xa6, 0xee, 0x43, 0xd2, 0x09, + 0x97, 0xcc, 0x14, 0x86, 0xfa, 0x97, 0x04, 0x2b, 0x29, 0x0b, 0xf4, 0x09, 0x14, 0x85, 0x8d, 0x60, + 0x43, 0x34, 0x90, 0x8d, 0x59, 0xc4, 0x90, 0x1b, 0x0c, 0x66, 0xbc, 0x46, 0x4f, 0x01, 0xdc, 0xfe, + 0x38, 0x15, 0x5e, 0x8a, 0x4b, 0xb6, 0x56, 0x70, 0xfb, 0xe3, 0xa0, 0x4f, 0x01, 0x1c, 0xfa, 0x6e, + 0xec, 0x9b, 0xb9, 0x82, 0xaf, 0x43, 0xdf, 0x45, 0xbe, 0x55, 0xc8, 0xc7, 0xb7, 0x24, 0x2b, 0xce, + 0xce, 0xf8, 0x5b, 0xfd, 0x75, 0x11, 0xf2, 0x2f, 0x29, 0x23, 0x16, 0x61, 0x04, 0x9d, 0xc2, 0xaa, + 0x08, 0x60, 0xd8, 0x96, 0x31, 0x20, 0x9e, 0x67, 0x3b, 0xdd, 0xa8, 0x62, 0x0f, 0x92, 0xb1, 0xc6, + 0x0e, 0xbb, 0x22, 0x40, 0xd3, 0x7a, 0x29, 0x6c, 0xc5, 0xe9, 0x28, 0xb3, 0xb4, 0x34, 0x84, 0x8d, + 0x0f, 0x6f, 0x0c, 0x2b, 0x5f, 0x00, 0x8b, 0xa3, 0x93, 0x9d, 0x86, 0xf5, 0xd3, 0x52, 0xa4, 0x85, + 0xad, 0xbe, 0x1b, 0x03, 0x8a, 0xd6, 0x78, 0xef, 0x9c, 0x3c, 0xbb, 0x29, 0x2c, 0x60, 0xb1, 0x00, + 0x59, 0xb0, 0x11, 0x1f, 0x67, 0xc3, 0x21, 0x83, 0x49, 0x8a, 0x59, 0x8e, 0xb8, 0x3b, 0x17, 0x31, + 0x3e, 0xf3, 0x2d, 0x32, 0x48, 0xe7, 0xb9, 0x4e, 0xe6, 0xa8, 0xd0, 0x7b, 0xb8, 0x3d, 0x89, 0x12, + 0x30, 0xdf, 0x76, 0xba, 0x06, 0xbf, 0x05, 0x71, 0xb4, 0x1c, 0x8f, 0xf6, 0xf8, 0xe2, 0x68, 0x6d, + 0xee, 0xf9, 0x2a, 0x74, 0x4c, 0x05, 0xdd, 0x22, 0xe7, 0x5b, 0x54, 0xf7, 0x61, 0x7d, 0x1e, 0x51, + 0x97, 0xdd, 0xd3, 0x42, 0xe2, 0x9e, 0x86, 0x18, 0xf3, 0x58, 0xb9, 0x16, 0xc6, 0x33, 0x28, 0x4f, + 0x11, 0x71, 0x2d, 0xf7, 0x03, 0xd8, 0x3c, 0xb7, 0xea, 0xd7, 0x02, 0x6a, 0xc1, 0xf6, 0x65, 0x05, + 0xbd, 0x0e, 0x9e, 0xfa, 0x9d, 0x0c, 0x37, 0x0e, 0x28, 0x13, 0x35, 0x3e, 0xf0, 0x89, 0xd7, 0x1b, + 0x3f, 0x0a, 0x9a, 0xb0, 0xda, 0x09, 0x5f, 0x00, 0x86, 0x35, 0x79, 0x02, 0x70, 0xcc, 0xe2, 0xde, + 0xcd, 0x24, 0xd1, 0xd3, 0xcf, 0x04, 0xac, 0x74, 0xa6, 0x1f, 0x0e, 0xcf, 0x60, 0xc5, 0xe5, 0x63, + 0xd9, 0x30, 0xf9, 0x5c, 0x8e, 0xfa, 0x47, 0x25, 0xd5, 0x03, 0x12, 0x73, 0x1b, 0x2f, 0xbb, 0xc9, + 0x29, 0x5e, 0x87, 0x72, 0xf4, 0x3e, 0x30, 0x5c, 0x31, 0x0b, 0xa3, 0x26, 0x52, 0x9d, 0xf3, 0x96, + 0x88, 0xa6, 0x25, 0x2e, 0xf9, 0xe9, 0xe9, 0x79, 0x17, 0x96, 0x3b, 0x23, 0x8f, 0x04, 0x81, 0x61, + 0x12, 0xb3, 0x47, 0xa3, 0x99, 0x5c, 0x14, 0xb2, 0x7a, 0x28, 0x52, 0xbf, 0x97, 0x60, 0x63, 0xba, + 0x16, 0x81, 0xe7, 0x3a, 0x01, 0x45, 0x4f, 0x92, 0x6d, 0x7d, 0xa6, 0x04, 0xd3, 0x53, 0xe0, 0x70, + 0x21, 0xee, 0xec, 0x68, 0x0f, 0xf2, 0x83, 0xe8, 0x2a, 0x44, 0xdb, 0x5e, 0x9f, 0x77, 0x4d, 0x0e, + 0x17, 0x70, 0x6c, 0xb7, 0xbf, 0x08, 0x59, 0x9b, 0xd1, 0x81, 0xfa, 0xbb, 0x0c, 0x95, 0x03, 0xca, + 0xd2, 0x93, 0x61, 0xcc, 0x4f, 0x1d, 0x4a, 0x6f, 0x6c, 0x3f, 0x60, 0x86, 0x4f, 0xdf, 0xda, 0xc1, + 0x55, 0xc9, 0x59, 0xe1, 0x3e, 0x38, 0x72, 0x41, 0x1a, 0x94, 0x03, 0x6a, 0xba, 0x8e, 0x35, 0x41, + 0x91, 0xaf, 0x80, 0x52, 0x12, 0x4e, 0x31, 0xcc, 0x0c, 0xc1, 0x99, 0x0f, 0x25, 0x38, 0xfb, 0xc1, + 0x04, 0xe7, 0x66, 0x09, 0xfe, 0x51, 0x82, 0xcd, 0x39, 0xf5, 0x8c, 0x38, 0xd6, 0xe6, 0x4d, 0xdc, + 0x99, 0x2c, 0xd2, 0xce, 0x87, 0x0b, 0xd3, 0x43, 0xf7, 0x83, 0x08, 0xff, 0x43, 0x86, 0x9b, 0xd3, + 0x09, 0xa6, 0x2e, 0xe5, 0xbf, 0xa4, 0x5f, 0x9b, 0xf4, 0x9f, 0x24, 0xb8, 0x75, 0x4e, 0x4d, 0xff, + 0x31, 0xc4, 0x3f, 0xfc, 0x1a, 0x0a, 0xf1, 0x2f, 0x37, 0x54, 0x86, 0xa2, 0x86, 0xf1, 0x31, 0x36, + 0x9a, 0xad, 0xe7, 0xb8, 0xa6, 0x2c, 0xa0, 0x35, 0x28, 0x0b, 0x41, 0xbd, 0xd6, 0xaa, 0x6b, 0x47, + 0x47, 0x5a, 0x43, 0x91, 0x50, 0x09, 0x40, 0x08, 0x4f, 0xdb, 0x1a, 0x56, 0x64, 0xb4, 0x09, 0x37, + 0x12, 0x5e, 0x06, 0xd6, 0x74, 0xfc, 0xba, 0xb6, 0x7f, 0xa4, 0x29, 0x99, 0x87, 0x3f, 0x48, 0xb0, + 0x36, 0xe7, 0x97, 0x13, 0xda, 0x86, 0x9b, 0xf5, 0xe3, 0x97, 0x27, 0xa7, 0x7a, 0x4d, 0x6f, 0x1e, + 0xb7, 0x8c, 0xb6, 0x8e, 0x6b, 0xba, 0x76, 0xf0, 0xda, 0x68, 0xb6, 0x5e, 0xd5, 0x8e, 0x9a, 0x0d, + 0x65, 0x01, 0xdd, 0x86, 0xea, 0x5c, 0x8b, 0xd3, 0x56, 0x5b, 0xd3, 0x15, 0xe9, 0x5c, 0x7d, 0xfb, + 0x50, 0x3b, 0x3a, 0x52, 0x64, 0x74, 0x07, 0xb6, 0xe6, 0xea, 0x5b, 0x35, 0xbd, 0xf9, 0x2a, 0x4c, + 0xad, 0x0f, 0x30, 0x79, 0x71, 0xa2, 0xff, 0xc0, 0x5a, 0xfd, 0xb0, 0xd6, 0x3a, 0xd0, 0x0c, 0xfd, + 0xf5, 0x89, 0x96, 0xc8, 0x63, 0x0d, 0xca, 0x49, 0x45, 0x4b, 0xfb, 0x42, 0x91, 0xa6, 0xad, 0x1b, + 0xda, 0x91, 0xa6, 0x6b, 0x0d, 0x45, 0x9e, 0x56, 0x88, 0x75, 0x43, 0xc9, 0xec, 0xfd, 0x22, 0x43, + 0x8e, 0xff, 0x8e, 0x46, 0x5f, 0x41, 0x29, 0xdd, 0xea, 0xd1, 0xdd, 0x24, 0x59, 0x73, 0x47, 0x62, + 0x55, 0xbd, 0xc8, 0x44, 0x1c, 0x26, 0x75, 0xe1, 0x23, 0x09, 0x59, 0xb0, 0x3a, 0xd3, 0x66, 0xd0, + 0xbd, 0x29, 0xe7, 0xb9, 0x5d, 0xbd, 0x7a, 0xff, 0x12, 0xab, 0x44, 0x14, 0x8f, 0x4f, 0xee, 0xd9, + 0x73, 0x8d, 0x76, 0x2e, 0xc2, 0x48, 0x6d, 0xe8, 0xc1, 0x15, 0x2c, 0x27, 0x11, 0xf7, 0xff, 0x0b, + 0x25, 0xd3, 0x1d, 0x24, 0x7c, 0xf6, 0xc5, 0xbf, 0x12, 0x27, 0xbe, 0xcb, 0xdc, 0x13, 0xe9, 0xcb, + 0x25, 0x2e, 0xf4, 0x3a, 0x9d, 0x45, 0xfe, 0x0f, 0xc6, 0xc7, 0x7f, 0x07, 0x00, 0x00, 0xff, 0xff, + 0x5b, 0xa9, 0xc7, 0xfa, 0xd0, 0x10, 0x00, 0x00, }, }