From 0380cf68a855be8e05df59c0202cf6f4b328b0cb23fe491eb99f11b0a2a8cb0a Mon Sep 17 00:00:00 2001 From: Aleksa Sarai Date: Tue, 17 Dec 2024 13:26:31 +0000 Subject: [PATCH] Accepting request 1231695 from home:cyphar:docker - Update to docker-buildx 0.19.3. See upstream changelog online at OBS-URL: https://build.opensuse.org/request/show/1231695 OBS-URL: https://build.opensuse.org/package/show/Virtualization:containers/docker-stable?expand=0&rev=14 --- .gitattributes | 23 + .gitignore | 1 + ...llow-directory-creation-in-run-secre.patch | 74 + ...USE-implement-SUSE-container-secrets.patch | 510 + ...rt-graphdriver-btrfs-use-kernel-UAPI.patch | 46 + ...mor-clobber-docker-default-profile-o.patch | 89 + ...armor-remove-version-conditionals-fr.patch | 241 + ...pdate-buildkit-to-include-CVE-patche.patch | 3150 ++ ...e-to-patched-buildkit-version-to-fix.patch | 898 + ...e-use-AtomicWriteFile-to-save-volume.patch | 53 + ...024-41110-AuthZ-plugin-securty-fixes.patch | 209 + ...backport-fixes-for-integration-tests.patch | 65 + 80-docker.rules | 5 + README_SUSE.md | 230 + _service | 30 + ...nclude-required-tools-in-source-tree.patch | 31967 ++++++++++++++++ docker-24.0.9_ce_fca702de7f71.tar.xz | 3 + docker-audit.rules | 27 + docker-buildx-0.17.1.tar.xz | 3 + docker-buildx-0.19.2.tar.xz | 3 + docker-buildx-0.19.3.tar.xz | 3 + docker-cli-24.0.9_ce.tar.xz | 3 + docker-daemon.json | 8 + docker-integration.sh | 294 + docker-rpmlintrc | 7 + docker-stable.changes | 120 + docker-stable.spec | 643 + docker.service | 45 + docker.socket | 18 + docker.sysusers | 3 + sysconfig.docker | 8 + 31 files changed, 38779 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 0001-SECRETS-daemon-allow-directory-creation-in-run-secre.patch create mode 100644 0002-SECRETS-SUSE-implement-SUSE-container-secrets.patch create mode 100644 0003-BUILD-SLE12-revert-graphdriver-btrfs-use-kernel-UAPI.patch create mode 100644 0004-bsc1073877-apparmor-clobber-docker-default-profile-o.patch create mode 100644 0005-SLE12-revert-apparmor-remove-version-conditionals-fr.patch create mode 100644 0006-CVE-2024-23653-update-buildkit-to-include-CVE-patche.patch create mode 100644 0007-bsc1221916-update-to-patched-buildkit-version-to-fix.patch create mode 100644 0008-bsc1214855-volume-use-AtomicWriteFile-to-save-volume.patch create mode 100644 0009-CVE-2024-41110-AuthZ-plugin-securty-fixes.patch create mode 100644 0010-TESTS-backport-fixes-for-integration-tests.patch create mode 100644 80-docker.rules create mode 100644 README_SUSE.md create mode 100644 _service create mode 100644 cli-0001-docs-include-required-tools-in-source-tree.patch create mode 100644 docker-24.0.9_ce_fca702de7f71.tar.xz create mode 100644 docker-audit.rules create mode 100644 docker-buildx-0.17.1.tar.xz create mode 100644 docker-buildx-0.19.2.tar.xz create mode 100644 docker-buildx-0.19.3.tar.xz create mode 100644 docker-cli-24.0.9_ce.tar.xz create mode 100644 docker-daemon.json create mode 100644 docker-integration.sh create mode 100644 docker-rpmlintrc create mode 100644 docker-stable.changes create mode 100644 docker-stable.spec create mode 100644 docker.service create mode 100644 docker.socket create mode 100644 docker.sysusers create mode 100644 sysconfig.docker diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9b03811 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,23 @@ +## Default LFS +*.7z filter=lfs diff=lfs merge=lfs -text +*.bsp filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.gem filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.jar filter=lfs diff=lfs merge=lfs -text +*.lz filter=lfs diff=lfs merge=lfs -text +*.lzma filter=lfs diff=lfs merge=lfs -text +*.obscpio filter=lfs diff=lfs merge=lfs -text +*.oxt filter=lfs diff=lfs merge=lfs -text +*.pdf filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text +*.rpm filter=lfs diff=lfs merge=lfs -text +*.tbz filter=lfs diff=lfs merge=lfs -text +*.tbz2 filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.ttf filter=lfs diff=lfs merge=lfs -text +*.txz filter=lfs diff=lfs merge=lfs -text +*.whl filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.zst filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..57affb6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.osc diff --git a/0001-SECRETS-daemon-allow-directory-creation-in-run-secre.patch b/0001-SECRETS-daemon-allow-directory-creation-in-run-secre.patch new file mode 100644 index 0000000..a2d2645 --- /dev/null +++ b/0001-SECRETS-daemon-allow-directory-creation-in-run-secre.patch @@ -0,0 +1,74 @@ +From a94378d92f7ef523b17aa399ce83b27f7986980f Mon Sep 17 00:00:00 2001 +From: Aleksa Sarai +Date: Wed, 8 Mar 2017 12:41:54 +1100 +Subject: [PATCH 01/13] SECRETS: daemon: allow directory creation in + /run/secrets + +Since FileMode can have the directory bit set, allow a SecretStore +implementation to return secrets that are actually directories. This is +useful for creating directories and subdirectories of secrets. + +Signed-off-by: Antonio Murdaca +Signed-off-by: Aleksa Sarai +--- + daemon/container_operations_unix.go | 23 ++++++++++++++++++++--- + 1 file changed, 20 insertions(+), 3 deletions(-) + +diff --git a/daemon/container_operations_unix.go b/daemon/container_operations_unix.go +index 290ec59a34a7..b7013fb89c83 100644 +--- a/daemon/container_operations_unix.go ++++ b/daemon/container_operations_unix.go +@@ -4,6 +4,7 @@ + package daemon // import "github.com/docker/docker/daemon" + + import ( ++ "bytes" + "fmt" + "os" + "path/filepath" +@@ -14,6 +15,7 @@ import ( + "github.com/docker/docker/daemon/links" + "github.com/docker/docker/errdefs" + "github.com/docker/docker/libnetwork" ++ "github.com/docker/docker/pkg/archive" + "github.com/docker/docker/pkg/idtools" + "github.com/docker/docker/pkg/process" + "github.com/docker/docker/pkg/stringid" +@@ -206,9 +208,6 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) { + if err != nil { + return errors.Wrap(err, "unable to get secret from secret store") + } +- if err := os.WriteFile(fPath, secret.Spec.Data, s.File.Mode); err != nil { +- return errors.Wrap(err, "error injecting secret") +- } + + uid, err := strconv.Atoi(s.File.UID) + if err != nil { +@@ -219,6 +218,24 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) { + return err + } + ++ if s.File.Mode.IsDir() { ++ if err := os.Mkdir(fPath, s.File.Mode); err != nil { ++ return errors.Wrap(err, "error creating secretdir") ++ } ++ if secret.Spec.Data != nil { ++ // If the "file" is a directory, then s.File.Data is actually a tar ++ // archive of the directory. So we just do a tar extraction here. ++ if err := archive.UntarUncompressed(bytes.NewBuffer(secret.Spec.Data), fPath, &archive.TarOptions{ ++ IDMap: daemon.idMapping, ++ }); err != nil { ++ return errors.Wrap(err, "error injecting secretdir") ++ } ++ } ++ } else { ++ if err := os.WriteFile(fPath, secret.Spec.Data, s.File.Mode); err != nil { ++ return errors.Wrap(err, "error injecting secret") ++ } ++ } + if err := os.Chown(fPath, rootIDs.UID+uid, rootIDs.GID+gid); err != nil { + return errors.Wrap(err, "error setting ownership for secret") + } +-- +2.47.0 + diff --git a/0002-SECRETS-SUSE-implement-SUSE-container-secrets.patch b/0002-SECRETS-SUSE-implement-SUSE-container-secrets.patch new file mode 100644 index 0000000..f108416 --- /dev/null +++ b/0002-SECRETS-SUSE-implement-SUSE-container-secrets.patch @@ -0,0 +1,510 @@ +From 009cad241857541779baa2a9fae8291597dc85f8 Mon Sep 17 00:00:00 2001 +From: Aleksa Sarai +Date: Wed, 8 Mar 2017 11:43:29 +1100 +Subject: [PATCH 02/10] SECRETS: SUSE: implement SUSE container secrets + +This allows for us to pass in host credentials to a container, allowing +for SUSEConnect to work with containers. + +Users can disable this by setting DOCKER_SUSE_SECRETS_ENABLE=0 in +/etc/sysconfig/docker or by adding that setting to docker.service's +Environment using a drop-in file. + +THIS PATCH IS NOT TO BE UPSTREAMED, DUE TO THE FACT THAT IT IS +SUSE-SPECIFIC, AND UPSTREAM DOES NOT APPROVE OF THIS CONCEPT BECAUSE IT +MAKES BUILDS NOT ENTIRELY REPRODUCIBLE. + +SUSE-Bugs: bsc#1065609 bsc#1057743 bsc#1055676 bsc#1030702 bsc#1231348 +Signed-off-by: Aleksa Sarai +--- + daemon/start.go | 5 + + daemon/suse_secrets.go | 461 +++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 466 insertions(+) + create mode 100644 daemon/suse_secrets.go + +diff --git a/daemon/start.go b/daemon/start.go +index 2e0b9e6be847..dca04486888f 100644 +--- a/daemon/start.go ++++ b/daemon/start.go +@@ -151,6 +151,11 @@ func (daemon *Daemon) containerStart(ctx context.Context, container *container.C + return err + } + ++ // SUSE:secrets -- inject the SUSE secret store ++ if err := daemon.injectSuseSecretStore(container); err != nil { ++ return errdefs.System(err) ++ } ++ + spec, err := daemon.createSpec(ctx, container) + if err != nil { + return errdefs.System(err) +diff --git a/daemon/suse_secrets.go b/daemon/suse_secrets.go +new file mode 100644 +index 000000000000..85b37bf46544 +--- /dev/null ++++ b/daemon/suse_secrets.go +@@ -0,0 +1,461 @@ ++/* ++ * suse-secrets: patch for Docker to implement SUSE secrets ++ * Copyright (C) 2017-2021 SUSE 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. ++ */ ++ ++package daemon ++ ++import ( ++ "archive/tar" ++ "bytes" ++ "fmt" ++ "io" ++ "io/ioutil" ++ "os" ++ "path/filepath" ++ "strings" ++ "syscall" ++ ++ "github.com/docker/docker/container" ++ "github.com/docker/docker/pkg/archive" ++ "github.com/docker/docker/pkg/idtools" ++ ++ swarmtypes "github.com/docker/docker/api/types/swarm" ++ swarmexec "github.com/moby/swarmkit/v2/agent/exec" ++ swarmapi "github.com/moby/swarmkit/v2/api" ++ ++ "github.com/opencontainers/go-digest" ++ "github.com/sirupsen/logrus" ++) ++ ++const suseSecretsTogglePath = "/etc/docker/suse-secrets-enable" ++ ++// parseEnableFile parses a file that can only contain "0" or "1" (with some ++// whitespace). ++func parseEnableFile(path string) (bool, error) { ++ data, err := os.ReadFile(path) ++ if err != nil { ++ return false, err ++ } ++ data = bytes.TrimSpace(data) ++ ++ switch value := string(data); value { ++ case "1": ++ return true, nil ++ case "0", "": ++ return false, nil ++ default: ++ return false, fmt.Errorf("invalid value %q (must be 0 to disable or 1 to enable)", value) ++ } ++} ++ ++func isSuseSecretsEnabled() bool { ++ value, err := parseEnableFile(suseSecretsTogglePath) ++ if err != nil { ++ logrus.Warnf("SUSE:secrets :: error parsing %s: %v -- disabling SUSE secrets", suseSecretsTogglePath, err) ++ value = false ++ } ++ return value ++} ++ ++var suseSecretsEnabled = true ++ ++func init() { ++ // Make this entire feature toggle-able so that users can disable it if ++ // they run into issues like bsc#1231348. ++ suseSecretsEnabled = isSuseSecretsEnabled() ++ if suseSecretsEnabled { ++ logrus.Infof("SUSE:secrets :: SUSEConnect support enabled (set %s to 0 to disable)", suseSecretsTogglePath) ++ } else { ++ logrus.Infof("SUSE:secrets :: SUSEConnect support disabled by %s", suseSecretsTogglePath) ++ } ++} ++ ++// Creating a fake file. ++type SuseFakeFile struct { ++ Path string ++ Uid int ++ Gid int ++ Mode os.FileMode ++ Data []byte ++} ++ ++func (s SuseFakeFile) id() string { ++ // NOTE: It is _very_ important that this string always has a prefix of ++ // "suse". This is how we can ensure that we can operate on ++ // SecretReferences with a confidence that it was made by us. ++ return fmt.Sprintf("suse_%s_%s", digest.FromBytes(s.Data).Hex(), s.Path) ++} ++ ++func (s SuseFakeFile) toSecret() *swarmapi.Secret { ++ return &swarmapi.Secret{ ++ ID: s.id(), ++ Internal: true, ++ Spec: swarmapi.SecretSpec{ ++ Data: s.Data, ++ }, ++ } ++} ++ ++func (s SuseFakeFile) toSecretReference(idMaps idtools.IdentityMapping) *swarmtypes.SecretReference { ++ // Figure out the host-facing {uid,gid} based on the provided maps. Fall ++ // back to root if the UID/GID don't match (we are guaranteed that root is ++ // mapped). ++ ctrUser := idtools.Identity{UID: s.Uid, GID: s.Gid} ++ hostUser := idMaps.RootPair() ++ if user, err := idMaps.ToHost(ctrUser); err == nil { ++ hostUser = user ++ } ++ ++ // Return the secret reference as a file target. ++ return &swarmtypes.SecretReference{ ++ SecretID: s.id(), ++ SecretName: s.id(), ++ File: &swarmtypes.SecretReferenceFileTarget{ ++ Name: s.Path, ++ UID: fmt.Sprintf("%d", hostUser.UID), ++ GID: fmt.Sprintf("%d", hostUser.GID), ++ Mode: s.Mode, ++ }, ++ } ++} ++ ++// readDir will recurse into a directory prefix/dir, and return the set of ++// secrets in that directory (as a tar archive that is packed inside the "data" ++// field). The Path attribute of each has the prefix stripped. Symlinks are ++// dereferenced. ++func readDir(prefix, dir string) ([]*SuseFakeFile, error) { ++ var suseFiles []*SuseFakeFile ++ ++ path := filepath.Join(prefix, dir) ++ fi, err := os.Stat(path) ++ if err != nil { ++ // Ignore missing files. ++ if os.IsNotExist(err) { ++ // If the path itself exists it was a dangling symlink so give a ++ // warning about the symlink dangling. ++ _, err2 := os.Lstat(path) ++ if !os.IsNotExist(err2) { ++ logrus.Warnf("SUSE:secrets :: ignoring dangling symlink: %s", path) ++ } ++ return nil, nil ++ } ++ return nil, err ++ } else if !fi.IsDir() { ++ // Just to be safe. ++ logrus.Infof("SUSE:secrets :: expected %q to be a directory, but was a file", path) ++ return readFile(prefix, dir) ++ } ++ path, err = filepath.EvalSymlinks(path) ++ if err != nil { ++ return nil, err ++ } ++ ++ // Construct a tar archive of the source directory. We tar up the prefix ++ // directory and add dir as an IncludeFiles specifically so that we ++ // preserve the name of the directory itself. ++ tarStream, err := archive.TarWithOptions(path, &archive.TarOptions{ ++ Compression: archive.Uncompressed, ++ IncludeSourceDir: true, ++ }) ++ if err != nil { ++ return nil, fmt.Errorf("SUSE:secrets :: failed to tar source directory %q: %v", path, err) ++ } ++ tarStreamBytes, err := ioutil.ReadAll(tarStream) ++ if err != nil { ++ return nil, fmt.Errorf("SUSE:secrets :: failed to read full tar archive: %v", err) ++ } ++ ++ // Get a list of the symlinks in the tar archive. ++ var symlinks []string ++ tmpTr := tar.NewReader(bytes.NewBuffer(tarStreamBytes)) ++ for { ++ hdr, err := tmpTr.Next() ++ if err == io.EOF { ++ break ++ } ++ if err != nil { ++ return nil, fmt.Errorf("SUSE:secrets :: failed to read through tar reader: %v", err) ++ } ++ if hdr.Typeflag == tar.TypeSymlink { ++ symlinks = append(symlinks, hdr.Name) ++ } ++ } ++ ++ // Symlinks aren't dereferenced in the above archive, so we explicitly do a ++ // rewrite of the tar archive to include all symlinks to files. We cannot ++ // do directories here, but lower-level directory symlinks aren't supported ++ // by zypper so this isn't an issue. ++ symlinkModifyMap := map[string]archive.TarModifierFunc{} ++ for _, sym := range symlinks { ++ logrus.Debugf("SUSE:secrets: archive(%q) %q is a need-to-rewrite symlink", path, sym) ++ symlinkModifyMap[sym] = func(tarPath string, hdr *tar.Header, r io.Reader) (*tar.Header, []byte, error) { ++ logrus.Debugf("SUSE:secrets: archive(%q) mapping for symlink %q", path, tarPath) ++ tarFullPath := filepath.Join(path, tarPath) ++ ++ // Get a copy of the original byte stream. ++ oldContent, err := ioutil.ReadAll(r) ++ if err != nil { ++ return nil, nil, fmt.Errorf("suse_rewrite: failed to read archive entry %q: %v", tarPath, err) ++ } ++ ++ // Check that the file actually exists. ++ fi, err := os.Stat(tarFullPath) ++ if err != nil { ++ logrus.Warnf("suse_rewrite: failed to stat archive entry %q: %v", tarFullPath, err) ++ return hdr, oldContent, nil ++ } ++ ++ // Read the actual contents. ++ content, err := ioutil.ReadFile(tarFullPath) ++ if err != nil { ++ logrus.Warnf("suse_rewrite: failed to read %q: %v", tarFullPath, err) ++ return hdr, oldContent, nil ++ } ++ ++ newHdr, err := tar.FileInfoHeader(fi, "") ++ if err != nil { ++ // Fake the header. ++ newHdr = &tar.Header{ ++ Typeflag: tar.TypeReg, ++ Mode: 0644, ++ } ++ } ++ ++ // Update the key fields. ++ hdr.Typeflag = newHdr.Typeflag ++ hdr.Mode = newHdr.Mode ++ hdr.Linkname = "" ++ return hdr, content, nil ++ } ++ } ++ ++ // Create the rewritten tar stream. ++ tarStream = archive.ReplaceFileTarWrapper(ioutil.NopCloser(bytes.NewBuffer(tarStreamBytes)), symlinkModifyMap) ++ tarStreamBytes, err = ioutil.ReadAll(tarStream) ++ if err != nil { ++ return nil, fmt.Errorf("SUSE:secrets :: failed to read rewritten archive: %v", err) ++ } ++ ++ // Add the tar stream as a "file". ++ suseFiles = append(suseFiles, &SuseFakeFile{ ++ Path: dir, ++ Mode: fi.Mode(), ++ Data: tarStreamBytes, ++ }) ++ return suseFiles, nil ++} ++ ++// readFile returns a secret given a file under a given prefix. ++func readFile(prefix, file string) ([]*SuseFakeFile, error) { ++ path := filepath.Join(prefix, file) ++ fi, err := os.Stat(path) ++ if err != nil { ++ // Ignore missing files. ++ if os.IsNotExist(err) { ++ // If the path itself exists it was a dangling symlink so give a ++ // warning about the symlink dangling. ++ _, err2 := os.Lstat(path) ++ if !os.IsNotExist(err2) { ++ logrus.Warnf("SUSE:secrets :: ignoring dangling symlink: %s", path) ++ } ++ return nil, nil ++ } ++ return nil, err ++ } else if fi.IsDir() { ++ // Just to be safe. ++ logrus.Infof("SUSE:secrets :: expected %q to be a file, but was a directory", path) ++ return readDir(prefix, file) ++ } ++ ++ var uid, gid int ++ if stat, ok := fi.Sys().(*syscall.Stat_t); ok { ++ uid, gid = int(stat.Uid), int(stat.Gid) ++ } else { ++ logrus.Warnf("SUSE:secrets :: failed to cast file stat_t: defaulting to owned by root:root: %s", path) ++ uid, gid = 0, 0 ++ } ++ ++ bytes, err := ioutil.ReadFile(path) ++ if err != nil { ++ return nil, err ++ } ++ ++ var suseFiles []*SuseFakeFile ++ suseFiles = append(suseFiles, &SuseFakeFile{ ++ Path: file, ++ Uid: uid, ++ Gid: gid, ++ Mode: fi.Mode(), ++ Data: bytes, ++ }) ++ return suseFiles, nil ++} ++ ++// getHostSuseSecretData returns the list of SuseFakeFiles the need to be added ++// as SUSE secrets. ++func getHostSuseSecretData() ([]*SuseFakeFile, error) { ++ secrets := []*SuseFakeFile{} ++ ++ credentials, err := readDir("/etc/zypp", "credentials.d") ++ if err != nil { ++ if os.IsNotExist(err) { ++ credentials = []*SuseFakeFile{} ++ } else { ++ logrus.Errorf("SUSE:secrets :: error while reading zypp credentials: %s", err) ++ return nil, err ++ } ++ } ++ secrets = append(secrets, credentials...) ++ ++ suseConnect, err := readFile("/etc", "SUSEConnect") ++ if err != nil { ++ if os.IsNotExist(err) { ++ suseConnect = []*SuseFakeFile{} ++ } else { ++ logrus.Errorf("SUSE:secrets :: error while reading /etc/SUSEConnect: %s", err) ++ return nil, err ++ } ++ } ++ secrets = append(secrets, suseConnect...) ++ ++ return secrets, nil ++} ++ ++// To fake an empty store, in the case where we are operating on a container ++// that was created pre-swarmkit. Otherwise segfaults and other fun things ++// happen. See bsc#1057743. ++type ( ++ suseEmptyStore struct{} ++ suseEmptySecret struct{} ++ suseEmptyConfig struct{} ++ suseEmptyVolume struct{} ++) ++ ++// In order to reduce the amount of code touched outside of this file, we ++// implement the swarm API for DependencyGetter. This asserts that this ++// requirement will always be matched. In addition, for the case of the *empty* ++// getters this reduces memory usage by having a global instance. ++var ( ++ _ swarmexec.DependencyGetter = &suseDependencyStore{} ++ emptyStore swarmexec.DependencyGetter = suseEmptyStore{} ++ emptySecret swarmexec.SecretGetter = suseEmptySecret{} ++ emptyConfig swarmexec.ConfigGetter = suseEmptyConfig{} ++ emptyVolume swarmexec.VolumeGetter = suseEmptyVolume{} ++) ++ ++var errSuseEmptyStore = fmt.Errorf("SUSE:secrets :: tried to get a resource from empty store [this is a bug]") ++ ++func (_ suseEmptyConfig) Get(_ string) (*swarmapi.Config, error) { return nil, errSuseEmptyStore } ++func (_ suseEmptySecret) Get(_ string) (*swarmapi.Secret, error) { return nil, errSuseEmptyStore } ++func (_ suseEmptyVolume) Get(_ string) (string, error) { return "", errSuseEmptyStore } ++func (_ suseEmptyStore) Secrets() swarmexec.SecretGetter { return emptySecret } ++func (_ suseEmptyStore) Configs() swarmexec.ConfigGetter { return emptyConfig } ++func (_ suseEmptyStore) Volumes() swarmexec.VolumeGetter { return emptyVolume } ++ ++type suseDependencyStore struct { ++ dfl swarmexec.DependencyGetter ++ secrets map[string]*swarmapi.Secret ++} ++ ++// The following are effectively dumb wrappers that return ourselves, or the ++// default. ++func (s *suseDependencyStore) Secrets() swarmexec.SecretGetter { return s } ++func (s *suseDependencyStore) Volumes() swarmexec.VolumeGetter { return emptyVolume } ++func (s *suseDependencyStore) Configs() swarmexec.ConfigGetter { return s.dfl.Configs() } ++ ++// Get overrides the underlying DependencyGetter with our own secrets (falling ++// through to the underlying DependencyGetter if the secret isn't present). ++func (s *suseDependencyStore) Get(id string) (*swarmapi.Secret, error) { ++ logrus.Debugf("SUSE:secrets :: id=%s requested from suseDependencyGetter", id) ++ ++ secret, ok := s.secrets[id] ++ if !ok { ++ // fallthrough ++ return s.dfl.Secrets().Get(id) ++ } ++ return secret, nil ++} ++ ++// removeSuseSecrets removes any SecretReferences which were added by us ++// explicitly (this is detected by checking that the prefix has a 'suse' ++// prefix). See bsc#1057743. ++func removeSuseSecrets(c *container.Container) { ++ var without []*swarmtypes.SecretReference ++ for _, secret := range c.SecretReferences { ++ if strings.HasPrefix(secret.SecretID, "suse") { ++ logrus.Debugf("SUSE:secrets :: removing 'old' suse secret %q from container %q", secret.SecretID, c.ID) ++ continue ++ } ++ without = append(without, secret) ++ } ++ c.SecretReferences = without ++} ++ ++func (daemon *Daemon) injectSuseSecretStore(c *container.Container) error { ++ // We drop any "old" SUSE secrets, as it appears that old containers (when ++ // restarted) could still have references to old secrets. The .id() of all ++ // secrets have a prefix of "suse" so this is much easier. See bsc#1057743 ++ // for details on why this could cause issues. ++ removeSuseSecrets(c) ++ ++ // Don't inject anything if the administrator has disabled suse secrets. ++ // However, for previous existing containers we need to remove old secrets ++ // (see above), otherwise they will still have old secret data. ++ if !suseSecretsEnabled { ++ logrus.Debugf("SUSE:secrets :: skipping injection of secrets into container %q because of %s", c.ID, suseSecretsTogglePath) ++ return nil ++ } ++ ++ newDependencyStore := &suseDependencyStore{ ++ dfl: c.DependencyStore, ++ secrets: make(map[string]*swarmapi.Secret), ++ } ++ // Handle old containers. See bsc#1057743. ++ if newDependencyStore.dfl == nil { ++ newDependencyStore.dfl = emptyStore ++ } ++ ++ secrets, err := getHostSuseSecretData() ++ if err != nil { ++ return err ++ } ++ ++ idMaps := daemon.idMapping ++ for _, secret := range secrets { ++ newDependencyStore.secrets[secret.id()] = secret.toSecret() ++ c.SecretReferences = append(c.SecretReferences, secret.toSecretReference(idMaps)) ++ } ++ ++ c.DependencyStore = newDependencyStore ++ ++ // bsc#1057743 -- In older versions of Docker we added volumes explicitly ++ // to the mount list. This causes clashes because of duplicate namespaces. ++ // If we see an existing mount that will clash with the in-built secrets ++ // mount we assume it's our fault. ++ intendedMounts, err := c.SecretMounts() ++ if err != nil { ++ logrus.Warnf("SUSE:secrets :: fetching old secret mounts: %v", err) ++ return err ++ } ++ for _, intendedMount := range intendedMounts { ++ mountPath := intendedMount.Destination ++ if volume, ok := c.MountPoints[mountPath]; ok { ++ logrus.Debugf("SUSE:secrets :: removing pre-existing %q mount: %#v", mountPath, volume) ++ delete(c.MountPoints, mountPath) ++ } ++ } ++ return nil ++} +-- +2.47.1 + diff --git a/0003-BUILD-SLE12-revert-graphdriver-btrfs-use-kernel-UAPI.patch b/0003-BUILD-SLE12-revert-graphdriver-btrfs-use-kernel-UAPI.patch new file mode 100644 index 0000000..4fb3626 --- /dev/null +++ b/0003-BUILD-SLE12-revert-graphdriver-btrfs-use-kernel-UAPI.patch @@ -0,0 +1,46 @@ +From 7824330a0012e6b1d9b00db40a7c58b42d6adbfd Mon Sep 17 00:00:00 2001 +From: Aleksa Sarai +Date: Mon, 22 May 2023 15:44:54 +1000 +Subject: [PATCH 03/13] BUILD: SLE12: revert "graphdriver/btrfs: use kernel + UAPI headers" + +This reverts commit 3208dcabdc8997340b255f5b880fef4e3f54580d. + +On SLE 12, our UAPI headers are too old, resulting in us being unable to +build the btrfs driver with the new headers. This patch is only needed +for SLE-12. + +Signed-off-by: Aleksa Sarai +--- + daemon/graphdriver/btrfs/btrfs.go | 13 ++++--------- + 1 file changed, 4 insertions(+), 9 deletions(-) + +diff --git a/daemon/graphdriver/btrfs/btrfs.go b/daemon/graphdriver/btrfs/btrfs.go +index d88efc4be2bb..4e976aa689cd 100644 +--- a/daemon/graphdriver/btrfs/btrfs.go ++++ b/daemon/graphdriver/btrfs/btrfs.go +@@ -5,17 +5,12 @@ package btrfs // import "github.com/docker/docker/daemon/graphdriver/btrfs" + + /* + #include +-#include + #include + +-#include +-#if LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0) +- #error "Headers from kernel >= 4.12 are required to build with Btrfs support." +- #error "HINT: Set 'DOCKER_BUILDTAGS=exclude_graphdriver_btrfs' to build without Btrfs." +-#endif +- +-#include +-#include ++// keep struct field name compatible with btrfs-progs < 6.1. ++#define max_referenced max_rfer ++#include ++#include + + static void set_name_btrfs_ioctl_vol_args_v2(struct btrfs_ioctl_vol_args_v2* btrfs_struct, const char* value) { + snprintf(btrfs_struct->name, BTRFS_SUBVOL_NAME_MAX, "%s", value); +-- +2.47.0 + diff --git a/0004-bsc1073877-apparmor-clobber-docker-default-profile-o.patch b/0004-bsc1073877-apparmor-clobber-docker-default-profile-o.patch new file mode 100644 index 0000000..37100ce --- /dev/null +++ b/0004-bsc1073877-apparmor-clobber-docker-default-profile-o.patch @@ -0,0 +1,89 @@ +From 5deaa3fad88f7a6d8d5d342e23d3e2027571b9e2 Mon Sep 17 00:00:00 2001 +From: Aleksa Sarai +Date: Fri, 29 Jun 2018 17:59:30 +1000 +Subject: [PATCH 04/13] bsc1073877: apparmor: clobber docker-default profile on + start + +In the process of making docker-default reloading far less expensive, +567ef8e7858c ("daemon: switch to 'ensure' workflow for AppArmor +profiles") mistakenly made the initial profile load at dockerd start-up +lazy. As a result, if you have a running Docker daemon and upgrade it to +a new one with an updated AppArmor profile the new profile will not take +effect (because the old one is still loaded). The fix for this is quite +trivial, and just requires us to clobber the profile on start-up. + +Fixes: 567ef8e7858c ("daemon: switch to 'ensure' workflow for AppArmor profiles") +SUSE-Bugs: bsc#1099277 +Signed-off-by: Aleksa Sarai +--- + daemon/apparmor_default.go | 14 ++++++++++---- + daemon/apparmor_default_unsupported.go | 4 ++++ + daemon/daemon.go | 5 +++-- + 3 files changed, 17 insertions(+), 6 deletions(-) + +diff --git a/daemon/apparmor_default.go b/daemon/apparmor_default.go +index 6376001613f7..5fde21a4af8a 100644 +--- a/daemon/apparmor_default.go ++++ b/daemon/apparmor_default.go +@@ -24,6 +24,15 @@ func DefaultApparmorProfile() string { + return "" + } + ++func clobberDefaultAppArmorProfile() error { ++ if apparmor.HostSupports() { ++ if err := aaprofile.InstallDefault(defaultAppArmorProfile); err != nil { ++ return fmt.Errorf("AppArmor enabled on system but the %s profile could not be loaded: %s", defaultAppArmorProfile, err) ++ } ++ } ++ return nil ++} ++ + func ensureDefaultAppArmorProfile() error { + if apparmor.HostSupports() { + loaded, err := aaprofile.IsLoaded(defaultAppArmorProfile) +@@ -37,10 +46,7 @@ func ensureDefaultAppArmorProfile() error { + } + + // Load the profile. +- if err := aaprofile.InstallDefault(defaultAppArmorProfile); err != nil { +- return fmt.Errorf("AppArmor enabled on system but the %s profile could not be loaded: %s", defaultAppArmorProfile, err) +- } ++ return clobberDefaultAppArmorProfile() + } +- + return nil + } +diff --git a/daemon/apparmor_default_unsupported.go b/daemon/apparmor_default_unsupported.go +index e3dc18b32b5e..9c7723056268 100644 +--- a/daemon/apparmor_default_unsupported.go ++++ b/daemon/apparmor_default_unsupported.go +@@ -3,6 +3,10 @@ + + package daemon // import "github.com/docker/docker/daemon" + ++func clobberDefaultAppArmorProfile() error { ++ return nil ++} ++ + func ensureDefaultAppArmorProfile() error { + return nil + } +diff --git a/daemon/daemon.go b/daemon/daemon.go +index 585d85086f8d..6e4c6ad1ac01 100644 +--- a/daemon/daemon.go ++++ b/daemon/daemon.go +@@ -845,8 +845,9 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S + logrus.Warnf("Failed to configure golang's threads limit: %v", err) + } + +- // ensureDefaultAppArmorProfile does nothing if apparmor is disabled +- if err := ensureDefaultAppArmorProfile(); err != nil { ++ // Make sure we clobber any pre-existing docker-default profile to ensure ++ // that upgrades to the profile actually work smoothly. ++ if err := clobberDefaultAppArmorProfile(); err != nil { + logrus.Errorf(err.Error()) + } + +-- +2.47.0 + diff --git a/0005-SLE12-revert-apparmor-remove-version-conditionals-fr.patch b/0005-SLE12-revert-apparmor-remove-version-conditionals-fr.patch new file mode 100644 index 0000000..ab647d2 --- /dev/null +++ b/0005-SLE12-revert-apparmor-remove-version-conditionals-fr.patch @@ -0,0 +1,241 @@ +From 6e3d78c8d9f569ed7142994a802e2bce988b59bf Mon Sep 17 00:00:00 2001 +From: Aleksa Sarai +Date: Wed, 11 Oct 2023 21:19:12 +1100 +Subject: [PATCH 05/13] SLE12: revert "apparmor: remove version-conditionals + from template" + +This reverts the following commits: + + * 7008a514493a ("profiles/apparmor: remove version-conditional constraints (< 2.8.96)") + * 2e19a4d56bf2 ("contrib/apparmor: remove version-conditionals (< 2.9) from template") + * d169a5730649 ("contrib/apparmor: remove remaining version-conditionals (< 2.9) from template") + * ecaab085db4b ("profiles/apparmor: remove use of aaparser.GetVersion()") + * e3e715666f95 ("pkg/aaparser: deprecate GetVersion, as it's no longer used") + +These version conditionals are still required on SLE 12, where our +apparmor_parser version is quite old. + +Signed-off-by: Aleksa Sarai +--- + contrib/apparmor/main.go | 16 ++++++++++++++-- + contrib/apparmor/template.go | 16 ++++++++++++++++ + pkg/aaparser/aaparser.go | 2 -- + profiles/apparmor/apparmor.go | 14 ++++++++++++-- + profiles/apparmor/template.go | 4 ++++ + 5 files changed, 46 insertions(+), 6 deletions(-) + +diff --git a/contrib/apparmor/main.go b/contrib/apparmor/main.go +index d67890d265de..f4a2978b86cb 100644 +--- a/contrib/apparmor/main.go ++++ b/contrib/apparmor/main.go +@@ -6,9 +6,13 @@ import ( + "os" + "path" + "text/template" ++ ++ "github.com/docker/docker/pkg/aaparser" + ) + +-type profileData struct{} ++type profileData struct { ++ Version int ++} + + func main() { + if len(os.Args) < 2 { +@@ -18,6 +22,15 @@ func main() { + // parse the arg + apparmorProfilePath := os.Args[1] + ++ version, err := aaparser.GetVersion() ++ if err != nil { ++ log.Fatal(err) ++ } ++ data := profileData{ ++ Version: version, ++ } ++ fmt.Printf("apparmor_parser is of version %+v\n", data) ++ + // parse the template + compiled, err := template.New("apparmor_profile").Parse(dockerProfileTemplate) + if err != nil { +@@ -35,7 +48,6 @@ func main() { + } + defer f.Close() + +- data := profileData{} + if err := compiled.Execute(f, data); err != nil { + log.Fatalf("executing template failed: %v", err) + } +diff --git a/contrib/apparmor/template.go b/contrib/apparmor/template.go +index 58afcbe845ee..e6d0b6d37c58 100644 +--- a/contrib/apparmor/template.go ++++ b/contrib/apparmor/template.go +@@ -20,9 +20,11 @@ profile /usr/bin/docker (attach_disconnected, complain) { + + umount, + pivot_root, ++{{if ge .Version 209000}} + signal (receive) peer=@{profile_name}, + signal (receive) peer=unconfined, + signal (send), ++{{end}} + network, + capability, + owner /** rw, +@@ -45,10 +47,12 @@ profile /usr/bin/docker (attach_disconnected, complain) { + /etc/ld.so.cache r, + /etc/passwd r, + ++{{if ge .Version 209000}} + ptrace peer=@{profile_name}, + ptrace (read) peer=docker-default, + deny ptrace (trace) peer=docker-default, + deny ptrace peer=/usr/bin/docker///bin/ps, ++{{end}} + + /usr/lib/** rm, + /lib/** rm, +@@ -69,9 +73,11 @@ profile /usr/bin/docker (attach_disconnected, complain) { + /sbin/zfs rCx, + /sbin/apparmor_parser rCx, + ++{{if ge .Version 209000}} + # Transitions + change_profile -> docker-*, + change_profile -> unconfined, ++{{end}} + + profile /bin/cat (complain) { + /etc/ld.so.cache r, +@@ -93,8 +99,10 @@ profile /usr/bin/docker (attach_disconnected, complain) { + /dev/null rw, + /bin/ps mr, + ++{{if ge .Version 209000}} + # We don't need ptrace so we'll deny and ignore the error. + deny ptrace (read, trace), ++{{end}} + + # Quiet dac_override denials + deny capability dac_override, +@@ -112,11 +120,15 @@ profile /usr/bin/docker (attach_disconnected, complain) { + /proc/tty/drivers r, + } + profile /sbin/iptables (complain) { ++{{if ge .Version 209000}} + signal (receive) peer=/usr/bin/docker, ++{{end}} + capability net_admin, + } + profile /sbin/auplink flags=(attach_disconnected, complain) { ++{{if ge .Version 209000}} + signal (receive) peer=/usr/bin/docker, ++{{end}} + capability sys_admin, + capability dac_override, + +@@ -135,7 +147,9 @@ profile /usr/bin/docker (attach_disconnected, complain) { + /proc/[0-9]*/mounts rw, + } + profile /sbin/modprobe /bin/kmod (complain) { ++{{if ge .Version 209000}} + signal (receive) peer=/usr/bin/docker, ++{{end}} + capability sys_module, + /etc/ld.so.cache r, + /lib/** rm, +@@ -149,7 +163,9 @@ profile /usr/bin/docker (attach_disconnected, complain) { + } + # xz works via pipes, so we do not need access to the filesystem. + profile /usr/bin/xz (complain) { ++{{if ge .Version 209000}} + signal (receive) peer=/usr/bin/docker, ++{{end}} + /etc/ld.so.cache r, + /lib/** rm, + /usr/bin/xz rm, +diff --git a/pkg/aaparser/aaparser.go b/pkg/aaparser/aaparser.go +index 3d7c2c5a97b3..2b5a2605f9c1 100644 +--- a/pkg/aaparser/aaparser.go ++++ b/pkg/aaparser/aaparser.go +@@ -13,8 +13,6 @@ const ( + ) + + // GetVersion returns the major and minor version of apparmor_parser. +-// +-// Deprecated: no longer used, and will be removed in the next release. + func GetVersion() (int, error) { + output, err := cmd("", "--version") + if err != nil { +diff --git a/profiles/apparmor/apparmor.go b/profiles/apparmor/apparmor.go +index d0f236160506..b3566b2f7354 100644 +--- a/profiles/apparmor/apparmor.go ++++ b/profiles/apparmor/apparmor.go +@@ -14,8 +14,10 @@ import ( + "github.com/docker/docker/pkg/aaparser" + ) + +-// profileDirectory is the file store for apparmor profiles and macros. +-const profileDirectory = "/etc/apparmor.d" ++var ( ++ // profileDirectory is the file store for apparmor profiles and macros. ++ profileDirectory = "/etc/apparmor.d" ++) + + // profileData holds information about the given profile for generation. + type profileData struct { +@@ -27,6 +29,8 @@ type profileData struct { + Imports []string + // InnerImports defines the apparmor functions to import in the profile. + InnerImports []string ++ // Version is the {major, minor, patch} version of apparmor_parser as a single number. ++ Version int + } + + // generateDefault creates an apparmor profile from ProfileData. +@@ -46,6 +50,12 @@ func (p *profileData) generateDefault(out io.Writer) error { + p.InnerImports = append(p.InnerImports, "#include ") + } + ++ ver, err := aaparser.GetVersion() ++ if err != nil { ++ return err ++ } ++ p.Version = ver ++ + return compiled.Execute(out, p) + } + +diff --git a/profiles/apparmor/template.go b/profiles/apparmor/template.go +index 9f207e2014a8..626e5f6789a3 100644 +--- a/profiles/apparmor/template.go ++++ b/profiles/apparmor/template.go +@@ -24,12 +24,14 @@ profile {{.Name}} flags=(attach_disconnected,mediate_deleted) { + capability, + file, + umount, ++{{if ge .Version 208096}} + # Host (privileged) processes may send signals to container processes. + signal (receive) peer=unconfined, + # dockerd may send signals to container processes (for "docker kill"). + signal (receive) peer={{.DaemonProfile}}, + # Container processes may send signals amongst themselves. + signal (send,receive) peer={{.Name}}, ++{{end}} + + deny @{PROC}/* w, # deny write for all files directly in /proc (not in a subdir) + # deny write to files not in /proc//** or /proc/sys/** +@@ -50,7 +52,9 @@ profile {{.Name}} flags=(attach_disconnected,mediate_deleted) { + deny /sys/devices/virtual/powercap/** rwklx, + deny /sys/kernel/security/** rwklx, + ++{{if ge .Version 208095}} + # suppress ptrace denials when using 'docker ps' or using 'ps' inside a container + ptrace (trace,read,tracedby,readby) peer={{.Name}}, ++{{end}} + } + ` +-- +2.47.0 + diff --git a/0006-CVE-2024-23653-update-buildkit-to-include-CVE-patche.patch b/0006-CVE-2024-23653-update-buildkit-to-include-CVE-patche.patch new file mode 100644 index 0000000..94433ce --- /dev/null +++ b/0006-CVE-2024-23653-update-buildkit-to-include-CVE-patche.patch @@ -0,0 +1,3150 @@ +From d3d04b94a209b056c30bec37ce9dd42f646ebd54 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Dan=20=C4=8Cerm=C3=A1k?= +Date: Tue, 13 Feb 2024 16:57:32 +0100 +Subject: [PATCH 06/13] CVE-2024-23653: update buildkit to include CVE patches +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +- https://github.com/moby/buildkit/pull/4638 +- https://github.com/moby/buildkit/pull/4639 +- https://github.com/moby/buildkit/pull/4640 + +additionally change the version in builder/builder-next/worker/worker.go +and adjust calls to NewGatewayFrontend() in builder/builder-next (Worker +is no longer implementing the correct interface). + +Signed-off-by: Dan Čermák +Signed-off-by: Aleksa Sarai +--- + builder/builder-next/controller.go | 8 +- + builder/builder-next/worker/worker.go | 2 +- + vendor.mod | 3 + + vendor.sum | 797 +++++++----------- + .../moby/buildkit/executor/executor.go | 10 +- + .../moby/buildkit/executor/oci/spec.go | 30 +- + .../moby/buildkit/executor/oci/spec_linux.go | 57 ++ + .../buildkit/executor/oci/spec_non_linux.go | 18 + + .../buildkit/executor/oci/spec_windows.go | 11 + + .../moby/buildkit/executor/stubs.go | 18 +- + .../moby/buildkit/frontend/frontend.go | 3 +- + .../buildkit/frontend/gateway/container.go | 9 +- + .../frontend/gateway/forwarder/forward.go | 9 +- + .../frontend/gateway/forwarder/frontend.go | 5 +- + .../moby/buildkit/frontend/gateway/gateway.go | 28 +- + .../moby/buildkit/snapshot/localmounter.go | 35 +- + .../buildkit/snapshot/localmounter_unix.go | 45 +- + .../moby/buildkit/snapshot/snapshotter.go | 7 +- + .../moby/buildkit/solver/llbsolver/bridge.go | 52 ++ + .../buildkit/solver/llbsolver/provenance.go | 2 +- + .../moby/buildkit/solver/llbsolver/solver.go | 2 +- + .../moby/buildkit/solver/llbsolver/vertex.go | 14 +- + .../util/entitlements/entitlements.go | 20 + + .../github.com/moby/buildkit/worker/worker.go | 2 +- + .../moby/buildkit/worker/workercontroller.go | 23 + + vendor/modules.txt | 3 +- + 26 files changed, 615 insertions(+), 598 deletions(-) + create mode 100644 vendor/github.com/moby/buildkit/executor/oci/spec_linux.go + create mode 100644 vendor/github.com/moby/buildkit/executor/oci/spec_non_linux.go + +diff --git a/builder/builder-next/controller.go b/builder/builder-next/controller.go +index 46fc83eb7402..2693b8fab180 100644 +--- a/builder/builder-next/controller.go ++++ b/builder/builder-next/controller.go +@@ -116,8 +116,8 @@ func newSnapshotterController(ctx context.Context, rt http.RoundTripper, opt Opt + return nil, err + } + frontends := map[string]frontend.Frontend{ +- "dockerfile.v0": forwarder.NewGatewayForwarder(wc, dockerfile.Build), +- "gateway.v0": gateway.NewGatewayFrontend(wc), ++ "dockerfile.v0": forwarder.NewGatewayForwarder(wc.Infos(), dockerfile.Build), ++ "gateway.v0": gateway.NewGatewayFrontend(wc.Infos()), + } + + return control.NewController(control.Opt{ +@@ -338,8 +338,8 @@ func newGraphDriverController(ctx context.Context, rt http.RoundTripper, opt Opt + wc.Add(w) + + frontends := map[string]frontend.Frontend{ +- "dockerfile.v0": forwarder.NewGatewayForwarder(wc, dockerfile.Build), +- "gateway.v0": gateway.NewGatewayFrontend(wc), ++ "dockerfile.v0": forwarder.NewGatewayForwarder(wc.Infos(), dockerfile.Build), ++ "gateway.v0": gateway.NewGatewayFrontend(wc.Infos()), + } + + return control.NewController(control.Opt{ +diff --git a/builder/builder-next/worker/worker.go b/builder/builder-next/worker/worker.go +index 3773b95c949a..210218bf5a37 100644 +--- a/builder/builder-next/worker/worker.go ++++ b/builder/builder-next/worker/worker.go +@@ -50,7 +50,7 @@ import ( + ) + + func init() { +- version.Version = "v0.11.7+435cb77e369c" ++ version.Version = "v0.11.7+5d3afed3f7b4" + } + + const labelCreatedAt = "buildkit/createdat" +diff --git a/vendor.mod b/vendor.mod +index a1f8664e7d75..7946cbb75613 100644 +--- a/vendor.mod ++++ b/vendor.mod +@@ -98,6 +98,9 @@ require ( + resenje.org/singleflight v0.3.0 + ) + ++// github.com/cyphar/buildkit suse-stable-v24.0.9 ++replace github.com/moby/buildkit => github.com/cyphar/buildkit v0.0.0-20240814025459-5d3afed3f7b4 ++ + require ( + cloud.google.com/go v0.102.1 // indirect + github.com/agext/levenshtein v1.2.3 // indirect +diff --git a/vendor.sum b/vendor.sum +index 11d3aa6860f2..a426cdb147ce 100644 +--- a/vendor.sum ++++ b/vendor.sum +@@ -1,19 +1,13 @@ + bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= +-bazil.org/fuse v0.0.0-20180421153158-65cc252bf669/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= +-cloud.google.com/go v0.25.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= ++bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= + cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +-cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= + cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +-cloud.google.com/go v0.37.2/go.mod h1:H8IAquKe2L30IxoupDgqTaQvKSwF/c8prYHynGIWQbA= + cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +-cloud.google.com/go v0.39.0/go.mod h1:rVLT6fkc8chs9sfPtFc1SBH6em7n+ZoXaG+87tDISts= + cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= + cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +-cloud.google.com/go v0.44.3/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.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= + 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= +@@ -69,109 +63,78 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 + cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= + code.cloudfoundry.org/clock v1.0.0 h1:kFXWQM4bxYvdBw2X8BbBeXwQNgfoWv1vqAk2ZZyBN2o= + code.cloudfoundry.org/clock v1.0.0/go.mod h1:QD9Lzhd/ux6eNQVUDVRJX/RKTigpewimNYBi7ivZKY8= +-code.gitea.io/sdk/gitea v0.12.0/go.mod h1:z3uwDV/b9Ls47NGukYM9XhnHtqPh/J+t40lsUrR6JDY= +-contrib.go.opencensus.io/exporter/aws v0.0.0-20181029163544-2befc13012d0/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA= +-contrib.go.opencensus.io/exporter/ocagent v0.5.0/go.mod h1:ImxhfLRpxoYiSq891pBrLVhN+qmP8BTVvdH2YLs7Gl0= +-contrib.go.opencensus.io/exporter/stackdriver v0.12.1/go.mod h1:iwB6wGarfphGGe/e5CWqyUk/cLzKnWsOKPVW3no6OTw= +-contrib.go.opencensus.io/integrations/ocsql v0.1.4/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE= +-contrib.go.opencensus.io/resource v0.1.1/go.mod h1:F361eGI91LCmW1I/Saf+rX0+OFcigGlFvXwEGEnkRLA= + dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +-git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= +-git.apache.org/thrift.git v0.12.0/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= ++github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg= + github.com/AdaLogics/go-fuzz-headers v0.0.0-20221118232415-3345c89a7c72 h1:kq78byqmxX6R9uk4uN3HD2F5tkZJAZMauuLSkNPS8to= + github.com/AdaLogics/go-fuzz-headers v0.0.0-20221118232415-3345c89a7c72/go.mod h1:VzwV+t+dZ9j/H867F1M2ziD+yLHtB46oM35FxxMJ4d0= +-github.com/AkihiroSuda/containerd-fuse-overlayfs v1.0.0/go.mod h1:0mMDvQFeLbbn1Wy8P2j3hwFhqBq+FKn8OZPno8WLmp8= +-github.com/Azure/azure-amqp-common-go/v2 v2.1.0/go.mod h1:R8rea+gJRuJR6QxTir/XuEd+YuKoUiazDC/N96FiDEU= +-github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= +-github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= + github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +-github.com/Azure/azure-sdk-for-go v19.1.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +-github.com/Azure/azure-sdk-for-go v29.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +-github.com/Azure/azure-sdk-for-go v30.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +-github.com/Azure/azure-sdk-for-go v35.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +-github.com/Azure/azure-sdk-for-go v38.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +-github.com/Azure/azure-sdk-for-go v42.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +-github.com/Azure/azure-service-bus-go v0.9.1/go.mod h1:yzBx6/BUGfjfeqbRZny9AQIbIe3AcV9WZbAdpkoXOa0= +-github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0= ++github.com/Azure/azure-sdk-for-go/sdk/azcore v1.0.0/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U= ++github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.0/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U= ++github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0/go.mod h1:+6sju8gk8FRmSajX3Oz4G5Gm7P+mbqE9FVaXXFYTkCM= ++github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0= ++github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= ++github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.4.1/go.mod h1:eZ4g6GUvXiGulfIbbhh1Xr4XwUYaYaWMqzGD/284wCA= + github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= ++github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= + github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= + github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= + github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +-github.com/Azure/go-autorest v10.15.5+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +-github.com/Azure/go-autorest v12.0.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +-github.com/Azure/go-autorest v14.1.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= + github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +-github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +-github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0= +-github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= +-github.com/Azure/go-autorest/autorest v0.10.2/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= + github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= +-github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +-github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= +-github.com/Azure/go-autorest/autorest/adal v0.8.1/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= +-github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= +-github.com/Azure/go-autorest/autorest/adal v0.8.3/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= ++github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= ++github.com/Azure/go-autorest/autorest v0.11.27/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U= + github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= + github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= +-github.com/Azure/go-autorest/autorest/azure/auth v0.4.2/go.mod h1:90gmfKdlmKgfjUpnCEpOJzsUEjrWDSLwHIG73tSXddM= +-github.com/Azure/go-autorest/autorest/azure/cli v0.3.1/go.mod h1:ZG5p860J94/0kI9mNJVoIoLgXcirM2gF5i2kWloofxw= +-github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +-github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= ++github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= ++github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= ++github.com/Azure/go-autorest/autorest/adal v0.9.20/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= + github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +-github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +-github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +-github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= + github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= + github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +-github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc= +-github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA= +-github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8= +-github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI= +-github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= ++github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU= + github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +-github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= ++github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= + github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= ++github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= ++github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= ++github.com/AzureAD/microsoft-authentication-library-for-go v0.6.0/go.mod h1:BDJ5qMFKx9DugEg3+uQSDCdbYPr5s9vBTrL9P8TpqOU= + github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= + github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= + github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +-github.com/Djarvur/go-err113 v0.0.0-20200410182137-af658d038157/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= +-github.com/Djarvur/go-err113 v0.1.0/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= +-github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20191009163259-e802c2cb94ae/go.mod h1:mjwGPas4yKduTyubHvD1Atl9r1rUq8DfVy+gkVvZ+oo= +-github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190822182118-27a4ced34534/go.mod h1:iroGtC8B3tQiqtds1l+mgk/BBOrxbqjH+eUfFQYRc14= + github.com/Graylog2/go-gelf v0.0.0-20191017102106-1550ee647df0 h1:cOjLyhBhe91glgZZNbQUg9BJC57l6BiSKov0Ivv7k0U= + github.com/Graylog2/go-gelf v0.0.0-20191017102106-1550ee647df0/go.mod h1:fBaQWrftOD5CrVCUfoYGHs4X4VViTuGOXA8WloCjTY0= +-github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +-github.com/Masterminds/semver/v3 v3.0.3/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +-github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= ++github.com/KarpelesLab/reflink v0.0.2/go.mod h1:mB+2afhyn+eZTMFSH1gXunrgArTsiUBzfoAy0X2fatA= + github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= + github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= + github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= +-github.com/Microsoft/go-winio v0.4.15-0.20200908182639-5b44b70ab3ab/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= +-github.com/Microsoft/go-winio v0.4.15/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= + github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= + github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= + github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= + github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= + github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= ++github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= + github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= + github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= + github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= + github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= + github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= + github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= +-github.com/Microsoft/hcsshim v0.8.10/go.mod h1:g5uw8EV2mAlzqe94tfNBNdr89fnbD/n3HV0OhsddkmM= + github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= + github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= + github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= ++github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= + github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= ++github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= ++github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= ++github.com/Microsoft/hcsshim v0.9.3/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= ++github.com/Microsoft/hcsshim v0.9.4/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= + github.com/Microsoft/hcsshim v0.9.8 h1:lf7xxK2+Ikbj9sVf2QZsouGjRjEp2STj1yDHgoVtU5k= + github.com/Microsoft/hcsshim v0.9.8/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= +-github.com/Microsoft/hcsshim/test v0.0.0-20200826032352-301c83a30e7c/go.mod h1:30A5igQ91GEmhYJF8TaRP79pMBOYynRsyOByfVV0dU4= + github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= + github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= + github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= ++github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= + github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +-github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM= + github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= + github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= + github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +@@ -179,28 +142,19 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdko + github.com/RackSec/srslog v0.0.0-20180709174129-a4725f04ec91 h1:vX+gnvBc56EbWYrmlhYbFYRaeikAke1GL84N4BEYOFE= + github.com/RackSec/srslog v0.0.0-20180709174129-a4725f04ec91/go.mod h1:cDLGBht23g0XQdLjzn6xOGXDkLK182YfINAaZEQLCHQ= + github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= +-github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +-github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +-github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= + github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= + github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= + github.com/akutz/gosync v0.1.0 h1:naxPT/aDYDh79PMwM3XmencmNQeYmpNFSZy4ZE9zIW0= + github.com/akutz/memconn v0.1.0 h1:NawI0TORU4hcOMsMr11g7vwlCdkYeLKXBcxWu2W/P8A= +-github.com/alecthomas/kingpin v2.2.6+incompatible/go.mod h1:59OFYbFVLKQKq+mqrL6Rw5bR0c3ACQaawgXx0QYndlE= + github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= + github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= + github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= + github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= + github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= + github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= +-github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= ++github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= ++github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= + github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +-github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +-github.com/apex/log v1.1.4/go.mod h1:AlpoD9aScyQfJDVHmLMEcx4oU6LqzkWp4Mg9GdAcEvQ= +-github.com/apex/log v1.3.0/go.mod h1:jd8Vpsr46WAe3EZSQ/IUMs2qQD/GOycT5rPWCO1yGcs= +-github.com/apex/logs v0.0.4/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo= +-github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy8kCu4PNA+aP7WUV72eXWJeP9/r3/K9aLE= +-github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3stzu0Xys= + github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= + github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2 h1:7Ip0wMmLHLRJdrloDxZfhMm0xrLXZS8+COSu2bXmEQs= + github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +@@ -209,44 +163,55 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV + github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= + github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= + github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= ++github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= + github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= + github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= +-github.com/aws/aws-sdk-go v1.15.27/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= +-github.com/aws/aws-sdk-go v1.15.90/go.mod h1:es1KtYUFs7le0xQ3rOihkuoVD90z7D0fR2Qm4S00/gU= +-github.com/aws/aws-sdk-go v1.16.26/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +-github.com/aws/aws-sdk-go v1.19.18/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +-github.com/aws/aws-sdk-go v1.19.45/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +-github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +-github.com/aws/aws-sdk-go v1.25.11/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +-github.com/aws/aws-sdk-go v1.27.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +-github.com/aws/aws-sdk-go v1.31.6/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= ++github.com/aws/aws-sdk-go-v2 v1.16.3/go.mod h1:ytwTPBG6fXTZLxxeeCCWj2/EMYp/xDUgX+OET6TLNNU= + github.com/aws/aws-sdk-go-v2 v1.16.13 h1:HgF7OX2q0gSZtcXoo9DMEA8A2Qk/GCxmWyM0RI7Yz2Y= + github.com/aws/aws-sdk-go-v2 v1.16.13/go.mod h1:xSyvSnzh0KLs5H4HJGeIEsNYemUWdNIl0b/rP6SIsLU= ++github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.1/go.mod h1:n8Bs1ElDD2wJ9kCRTczA83gYbBmjSwZp3umc6zF4EeM= ++github.com/aws/aws-sdk-go-v2/config v1.15.5/go.mod h1:ZijHHh0xd/A+ZY53az0qzC5tT46kt4JVCePf2NX9Lk4= + github.com/aws/aws-sdk-go-v2/config v1.17.4 h1:9HY1wbShqObySCHP2Z07blfrSWVX+nVxCZmUuLZKcG8= + github.com/aws/aws-sdk-go-v2/config v1.17.4/go.mod h1:ul+ru+huVpfduF9XRmGUq82T8T3K+nIFQuF6F+L+548= ++github.com/aws/aws-sdk-go-v2/credentials v1.12.0/go.mod h1:9YWk7VW+eyKsoIL6/CljkTrNVWBSK9pkqOPUuijid4A= + github.com/aws/aws-sdk-go-v2/credentials v1.12.17 h1:htUjIJOQcvIUR0jC4eLkdis1DfaLL4EUbIKUFqh2WFA= + github.com/aws/aws-sdk-go-v2/credentials v1.12.17/go.mod h1:jd1mvJulXY7ccHvcSiJceYhv06yWIIRkJnwWEA4IX+g= ++github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.4/go.mod h1:u/s5/Z+ohUQOPXl00m2yJVyioWDECsbpXTQlaqSlufc= + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.14 h1:NZwZFtxXGOEIiCd8jWN55lexakug543CaO68bTpoLwg= + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.14/go.mod h1:5CU57SyF5jZLSIw4OOll0PG83ThXwNdkRFOc0EltD/0= ++github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.10/go.mod h1:p+ul5bLZSDRRXCZ/vePvfmZBH9akozXBJA5oMshWa5U= ++github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.10/go.mod h1:F+EZtuIwjlv35kRJPyBGcsA4f7bnSoz15zOQ2lJq1Z4= + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.20 h1:Rk8eqZSdFovt8Id+O+i2qT0c3CY13DPn2SfGOEVlxNs= + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.20/go.mod h1:gdZ5gRUaxThXIZyZQ8MTtgYBk2jbHgp05BO3GcD9Cwc= ++github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.4/go.mod h1:8glyUqVIM4AmeenIsPo0oVh3+NUwnsQml2OFupfQW+0= + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.14 h1:6Yxuq9yrkoLYab5JXqJnto9tdRuIcYVdR+eiKjsJYWU= + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.14/go.mod h1:GEV9jaDPIgayiU+uevxwozcvUOjc+P4aHE2BeSjm2vE= ++github.com/aws/aws-sdk-go-v2/internal/ini v1.3.11/go.mod h1:0MR+sS1b/yxsfAPvAESrw8NfwUoxMinDyw6EYR9BS2U= + github.com/aws/aws-sdk-go-v2/internal/ini v1.3.21 h1:lpwSbLKYTuABo6SyUoC25xAmfO3/TehGS2SmD1EtOL0= + github.com/aws/aws-sdk-go-v2/internal/ini v1.3.21/go.mod h1:Q0pktZjvRZk77TBto6yAvUAi7fcse1bdcMctBDVGgBw= ++github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.1/go.mod h1:l/BbcfqDCT3hePawhy4ZRtewjtdkl6GWtd9/U+1penQ= + github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.15.17 h1:cDudPvUMS1LzoXgwhAVqUoaOK3PY7oCSL4pGmQmxlSk= + github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.15.17/go.mod h1:60NdwPCecURV9rIq6Hg8U4kOsKsz1aXvAAYNKlhG9+E= ++github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.1/go.mod h1:GeUru+8VzrTXV/83XyMJ80KpH8xO89VPoUileyNQ+tc= ++github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.5/go.mod h1:S8TVP66AAkMMdYYCNZGvrdEq9YRm+qLXjio4FqRnrEE= ++github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.4/go.mod h1:uKkN7qmSIsNJVyMtxNQoCEYMvFEXbOg9fwCJPdfp2u8= + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.14 h1:c5hJNN2DkK1gAytcKp7LkiKNDJeevFSboPezEHAM4Ro= + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.14/go.mod h1:8qOLjqMzY/S1kh3myDXA1yxK5eD4uN8aOJgKpgvc4OM= ++github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.4/go.mod h1:oudbsSdDtazNj47z1ut1n37re9hDsKpk2ZI3v7KSxq0= ++github.com/aws/aws-sdk-go-v2/service/s3 v1.26.9/go.mod h1:iMYipLPXlWpBJ0KFX7QJHZ84rBydHBY8as2aQICTPWk= ++github.com/aws/aws-sdk-go-v2/service/sso v1.11.4/go.mod h1:cPDwJwsP4Kff9mldCXAmddjJL6JGQqtA3Mzer2zyr88= + github.com/aws/aws-sdk-go-v2/service/sso v1.11.20 h1:3raP0UC9rvRyY4/cc4o4F3jTrNo94AYiarNUGNnq6dU= + github.com/aws/aws-sdk-go-v2/service/sso v1.11.20/go.mod h1:hPsROgDdgY/NQ1gPt7VJWG0GjSnalDC0DkkMfGEw2gc= + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.2 h1:/SYpdjjAtraymql+/r719OgjxezdanAQiLb/NMxDb04= + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.2/go.mod h1:5cxfDYtY2mDOlmesy4yycb6lwyy1U/iAUOHKhQLKw/E= ++github.com/aws/aws-sdk-go-v2/service/sts v1.16.4/go.mod h1:lfSYenAXtavyX2A1LsViglqlG9eEFYxNryTZS5rn3QE= + github.com/aws/aws-sdk-go-v2/service/sts v1.16.16 h1:otZvq9r+xjPL7qU/luX2QdBamiN+oSZURRi4sAKymO8= + github.com/aws/aws-sdk-go-v2/service/sts v1.16.16/go.mod h1:Y9iBgT1w2vHtYzJEkwD6FqILjDSsvbxcW/+wIYxyse4= ++github.com/aws/smithy-go v1.11.2/go.mod h1:3xHYmszWVx2c0kIwQeEVf9uSm4fYZt67FBJnwub1bgM= + github.com/aws/smithy-go v1.13.1 h1:q09BdpUiaqpothcv393ACfWJJHzlzjB5HaNL1XHKmoQ= + github.com/aws/smithy-go v1.13.1/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= +-github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= ++github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc= ++github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= + github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= + github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= + github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +@@ -258,31 +223,21 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB + github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= + github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= + github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +-github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI= + github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +-github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= + github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= + github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= + github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +-github.com/bombsimon/wsl/v2 v2.0.0/go.mod h1:mf25kr/SqFEPhhcxW1+7pxzGlW+hIl/hYTKY95VwV8U= +-github.com/bombsimon/wsl/v2 v2.2.0/go.mod h1:Azh8c3XGEJl9LyX0/sFC+CKMc7Ssgua0g+6abzXN4Pg= +-github.com/bombsimon/wsl/v3 v3.0.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= +-github.com/bombsimon/wsl/v3 v3.1.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= +-github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= + github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= + github.com/bsphere/le_go v0.0.0-20200109081728-fc06dab2caa8 h1:fcONpniVVbh9+duVZYYbJuc+yGGdLRxTqpk7pTTz/qI= + github.com/bsphere/le_go v0.0.0-20200109081728-fc06dab2caa8/go.mod h1:GrjfimWtH8h8EqJSfbO+sTQYV/fAjL/VN7dMeU8XP2Y= + github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= ++github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= + github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= + github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= + github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= +-github.com/caarlos0/ctrlc v1.0.0/go.mod h1:CdXpj4rmq0q/1Eb44M9zi2nKB0QraNKuRGYGrrHhcQw= +-github.com/campoy/unique v0.0.0-20180121183637-88950e537e7e/go.mod h1:9IOqJGCPMSc6E5ydlp5NIonxObaeu/Iub/X03EKPVYo= +-github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e/go.mod h1:oDpT4efm8tSYHXV5tHSdRvBet/b/QzxZ+XyyPehvm3A= + github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= + github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo= + github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +-github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= + github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= + github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= + github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 h1:uH66TXeswKn5PW5zdZ39xEwfS9an067BirqA+P4QaLI= +@@ -293,6 +248,7 @@ github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cb + github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= + github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= + github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= ++github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= + github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= + github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= + github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +@@ -301,6 +257,7 @@ github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLI + github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= + github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= + github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= ++github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= + github.com/cilium/ebpf v0.9.1 h1:64sn2K3UKw8NbP/blsixRpF3nXuyhz/VjRlRzvlBRu4= + github.com/cilium/ebpf v0.9.1/go.mod h1:+OhNOIXx/Fnu1IE8bJz2dzOA+VSfyTfdNUVdlQnxUFY= + github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +@@ -324,8 +281,8 @@ github.com/cockroachdb/errors v1.2.4 h1:Lap807SXTH5tri2TivECb/4abUkMZC9zRoLarvcK + github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= + github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= + github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= +-github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= + github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE= ++github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4= + github.com/container-storage-interface/spec v1.5.0 h1:lvKxe3uLgqQeVQcrnL2CPQKISoKjTJxojEs9cBk+HXo= + github.com/container-storage-interface/spec v1.5.0/go.mod h1:8K96oQNkJ7pFcC2R9Z1ynGGBB1I93kcS6PGg3SsOk8s= + github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= +@@ -342,6 +299,7 @@ github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4S + github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= + github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= + github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= ++github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8= + github.com/containerd/cgroups v1.0.4 h1:jN/mbWBEaz+T1pi5OFtnkQ+8qnmEbAr1Oo1FRm5B0dA= + github.com/containerd/cgroups v1.0.4/go.mod h1:nLNQtsF7Sl2HxNebu77i1R0oDlhiTG+kO4JTrUzo6IA= + github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0= +@@ -349,7 +307,6 @@ github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxz + github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= + github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= + github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= +-github.com/containerd/console v1.0.0/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= + github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= + github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= + github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= +@@ -360,16 +317,20 @@ github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMX + github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= + github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= + github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +-github.com/containerd/containerd v1.4.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +-github.com/containerd/containerd v1.4.1-0.20201117152358-0edc412565dc/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= + github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= + github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= ++github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= + github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= + github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= + github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= + github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= + github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= + github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c= ++github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s= ++github.com/containerd/containerd v1.6.1/go.mod h1:1nJz5xCZPusx6jJU8Frfct988y0NpumIq9ODB0kLtoE= ++github.com/containerd/containerd v1.6.6/go.mod h1:ZoP1geJldzCVY3Tonoz7b1IXk8rIX0Nltt5QE4OMNk0= ++github.com/containerd/containerd v1.6.9/go.mod h1:XVicUvkxOrftE2Q1YWUXgZwkkAxwQYNOFzYWvfVfEfQ= ++github.com/containerd/containerd v1.6.21/go.mod h1:apei1/i5Ux2FzrK6+DM/suEsGuK/MeVOfy8tR2q7Wnw= + github.com/containerd/containerd v1.6.22 h1:rGTIBxPJusM0evF6wKgIzuD+tV70nmx9eEjzHVm1JzI= + github.com/containerd/containerd v1.6.22/go.mod h1:BQAJdahvGz8xboAvxKg9hsDYIovn79Ea318anowQ1/o= + github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +@@ -379,6 +340,7 @@ github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cE + github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= + github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= + github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= ++github.com/containerd/continuity v0.2.2/go.mod h1:pWygW9u7LtS1o4N/Tn0FoCFDIXZ7rxcMX7HX1Dmibvk= + github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= + github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= + github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +@@ -389,8 +351,11 @@ github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1S + github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= + github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY= + github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o= ++github.com/containerd/fuse-overlayfs-snapshotter v1.0.2/go.mod h1:nRZceC8a7dRm3Ao6cJAwuJWPFiBPaibHiFntRUnzhwU= + github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= + github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= ++github.com/containerd/go-cni v1.1.0/go.mod h1:Rflh2EJ/++BA2/vY5ao3K6WJRR/bZKsX123aPk+kUtA= ++github.com/containerd/go-cni v1.1.3/go.mod h1:Rflh2EJ/++BA2/vY5ao3K6WJRR/bZKsX123aPk+kUtA= + github.com/containerd/go-cni v1.1.6 h1:el5WPymG5nRRLQF1EfB97FWob4Tdc8INg8RZMaXWZlo= + github.com/containerd/go-cni v1.1.6/go.mod h1:BWtoWl5ghVymxu6MBjg79W9NZrCRyHIdUtk4cauMe34= + github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +@@ -404,13 +369,16 @@ github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak + github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA= + github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow= + github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms= ++github.com/containerd/imgcrypt v1.1.3/go.mod h1:/TPA1GIDXMzbj01yd8pIbQiLdQxed5ue1wb8bP7PQu4= ++github.com/containerd/imgcrypt v1.1.4/go.mod h1:LorQnPtzL/T0IyCeftcsMEO7AqxUDbdO8j/tSUpgxvo= + github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= + github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= + github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= + github.com/containerd/nydus-snapshotter v0.3.1 h1:b8WahTrPkt3XsabjG2o/leN4fw3HWZYr+qxo/Z8Mfzk= + github.com/containerd/nydus-snapshotter v0.3.1/go.mod h1:+8R7NX7vrjlxAgtidnsstwIhpzyTlriYPssTxH++uiM= +-github.com/containerd/stargz-snapshotter v0.0.0-20201027054423-3a04e4c2c116/go.mod h1:o59b3PCKVAf9jjiKtCc/9hLAd+5p/rfhBfm6aBcTEr4= ++github.com/containerd/stargz-snapshotter v0.13.0/go.mod h1:01uOvoNzN1T4kV+8HeVt9p29esO5/61x8+VP/KU4fvQ= + github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM= ++github.com/containerd/stargz-snapshotter/estargz v0.11.4/go.mod h1:7vRJIcImfY8bpifnMjt+HTJoQxASq7T28MYbP15/Nf0= + github.com/containerd/stargz-snapshotter/estargz v0.13.0 h1:fD7AwuVV+B40p0d9qVkH/Au1qhp8hn/HWJHIYjpEcfw= + github.com/containerd/stargz-snapshotter/estargz v0.13.0/go.mod h1:m+9VaGJGlhCnrcEUod8mYumTmRgblwd3rC5UCEh2Yp0= + github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +@@ -419,6 +387,7 @@ github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0x + github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= + github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= + github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ= ++github.com/containerd/ttrpc v1.1.1/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ= + github.com/containerd/ttrpc v1.1.2 h1:4jH6OQDQqjfVD2b5TJS5TxmGuLGmp5WW7KtW2TWOP7c= + github.com/containerd/ttrpc v1.1.2/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ= + github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= +@@ -436,36 +405,39 @@ github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNR + github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= + github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= + github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= ++github.com/containernetworking/cni v1.0.1/go.mod h1:AKuhXbN5EzmD4yTNtfSsX3tPcmtrBI6QcRV0NiNt15Y= + github.com/containernetworking/cni v1.1.1 h1:ky20T7c0MvKvbMOwS/FrlbNwjEoqJEUUYfsL4b0mc4k= + github.com/containernetworking/cni v1.1.1/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw= + github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= + github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= ++github.com/containernetworking/plugins v1.0.1/go.mod h1:QHCfGpaTwYTbbH+nZXKVTxNBDZcxSOplJT5ico8/FLE= ++github.com/containernetworking/plugins v1.1.1/go.mod h1:Sr5TH/eBsGLXK/h71HeLfX19sZPp3ry5uHSkI4LPxV8= + github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= + github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= + github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= ++github.com/containers/ocicrypt v1.1.2/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= ++github.com/containers/ocicrypt v1.1.3/go.mod h1:xpdkbVAuaH3WzbEabUd5yDsl9SwJA5pABH85425Es2g= + github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= + github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= + github.com/coreos/etcd v3.3.13+incompatible h1:8F3hqu9fGYLBifCmRCJsicFqDx/D68Rt3q1JMazcgBQ= + github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +-github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= + github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= + github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= ++github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= + github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= + github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= + github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= + github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= + github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +-github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= + github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= + github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= + github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= + github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= ++github.com/coreos/go-systemd/v22 v22.4.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= + github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= + github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= + github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +-github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= + github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +-github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= + github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= + github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= + github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +@@ -474,44 +446,48 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 + github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= + github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= + github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= ++github.com/cyphar/buildkit v0.0.0-20240814025459-5d3afed3f7b4 h1:e2A5JTqDADxy9xYHM0KxRXfYl9wCISpo5TitiaUmfGw= ++github.com/cyphar/buildkit v0.0.0-20240814025459-5d3afed3f7b4/go.mod h1:bMQDryngJKGvJ/ZuRFhrejurbvYSv3NkGCheQ59X4AM= + github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= ++github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= + github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= + github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= + github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= + github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= + github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= + github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= +-github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= ++github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg= ++github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= + github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= + github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= + github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= + github.com/deckarep/golang-set/v2 v2.3.0 h1:qs18EKUfHm2X9fA50Mr/M5hccg2tNnVqsiBImnyDs0g= + github.com/deckarep/golang-set/v2 v2.3.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= + github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= +-github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY= + github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= + github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= + github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +-github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= + github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= + github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= + github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= +-github.com/docker/cli v0.0.0-20190925022749-754388324470/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= ++github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= + github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= + github.com/docker/cli v20.10.0-beta1.0.20201029214301-1d20b15adc38+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= ++github.com/docker/cli v20.10.21+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= ++github.com/docker/cli v23.0.6+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= + github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= +-github.com/docker/distribution v2.6.0-rc.1.0.20180327202408-83389a148052+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= + github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= + github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= ++github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= + github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= + github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +-github.com/docker/docker v0.0.0-20200511152416-a93e9eb0e95c/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +-github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +-github.com/docker/docker v1.4.2-0.20180531152204-71cd53e4a197/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= + github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +-github.com/docker/docker v17.12.0-ce-rc1.0.20200730172259-9f28837c1d93+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +-github.com/docker/docker v20.10.0-beta1.0.20201110211921-af34b94a78a1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= ++github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= ++github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= ++github.com/docker/docker v23.0.7-0.20230720050051-0cae31c7dd6e+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= + github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= ++github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c= ++github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= + github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= + github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= + github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +@@ -520,13 +496,11 @@ github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6Uezg + github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= + github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= + github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= +-github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= + github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= + github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= + github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= + github.com/docker/libkv v0.2.2-0.20211217103745-e480589147e3 h1:q6MhOaE4xsrl6cAiFYrazobNFSQN6ckhD6Et9zYbcrU= + github.com/docker/libkv v0.2.2-0.20211217103745-e480589147e3/go.mod h1:r5hEwHwW8dr0TFBYGCarMNbrQOiwL1xoqDYZ/JqoTK0= +-github.com/docker/libnetwork v0.8.0-dev.2.0.20200917202933-d0951081b35f/go.mod h1:93m0aTqz6z+g32wla4l4WxTrdtvBRmVzYRkYvasA5Z8= + github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= + github.com/docker/libtrust v0.0.0-20150526203908-9cbd2a1374f4 h1:k8TfKGeAcDQFFQOGCQMRN04N4a9YrPlRMMKnzAuvM9Q= + github.com/docker/libtrust v0.0.0-20150526203908-9cbd2a1374f4/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= +@@ -535,13 +509,11 @@ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3 + github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= + github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= + github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +-github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +-github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +-github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +-github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= + github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= + github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= + github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= ++github.com/emicklei/go-restful/v3 v3.7.3/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= ++github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= + 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= +@@ -552,20 +524,19 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m + github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= + github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= + github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +-github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= + github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= ++github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= ++github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= + github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +-github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= ++github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= + github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o= + github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= + github.com/fernet/fernet-go v0.0.0-20211208181803-9f70042a33ee h1:v6Eju/FhxsACGNipFEPBZZAzGr1F/jlRQr1qiBw2nEE= + github.com/fernet/fernet-go v0.0.0-20211208181803-9f70042a33ee/go.mod h1:2H9hjfbpSMHwY503FclkV/lZTBh2YlOmLLSda12uL8c= + github.com/fluent/fluent-logger-golang v1.9.0 h1:zUdY44CHX2oIUc7VTNZc+4m+ORuO/mldQDA7czhWXEg= + github.com/fluent/fluent-logger-golang v1.9.0/go.mod h1:2/HCT/jTy78yGyeNGQLGQsjF3zzzAuy6Xlk6FCMV5eU= +-github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= + github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +-github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +-github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= ++github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= + github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= + github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss= + github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +@@ -573,13 +544,11 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4 + github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= + github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= + github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= ++github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= + github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= + github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= + github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= + github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +-github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +-github.com/go-critic/go-critic v0.4.1/go.mod h1:7/14rZGnZbY6E38VEGk2kVhoq6itzc1E68facVDK23g= +-github.com/go-critic/go-critic v0.4.3/go.mod h1:j4O3D4RoIwRqlZw5jJpx0BNfXWWbpcJoKu5cYSe4YmQ= + 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= +@@ -588,77 +557,62 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 + github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= + github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= + github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +-github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM= + 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-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= + github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= + github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= + github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= ++github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= + github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= ++github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= + github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= + github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= + github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= ++github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI= + github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= + github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +-github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= + github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= + github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= + github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= ++github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= + github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= + github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= + github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= ++github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= + github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= + github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= + github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= + github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= + github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +-github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +-github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +-github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= ++github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= + github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= + github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +-github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= +-github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ= +-github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +-github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +-github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086/go.mod h1:mP93XdblcopXwlyN4X4uodxXQhldPGZbcEJIimQHrkg= +-github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw= +-github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21/go.mod h1:dDStQCHtmZpYOmjRP/8gHHnCCch3Zz3oEgCdZVdtweU= +-github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30/go.mod h1:SV2ur98SGypH1UjcPpCatrV5hPazG6+IfNHbkDXBRrk= +-github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI= +-github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoMrjiy4zvdS+Bg6z9jZH82QXwkcgCBX6nOfnmdaHks= +-github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc= +-github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= +-github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= +-github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= +-github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= +-github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= + github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= + github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= + github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= + github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= + github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= ++github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= + github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= + github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +-github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +-github.com/gofrs/flock v0.7.3/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= + github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= + github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= + github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= +-github.com/gogo/googleapis v1.3.2/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= + github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= + github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= + github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= + github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +-github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= + github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= + github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= + github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= + github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= + github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= + github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= ++github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= ++github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= + github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= ++github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= + github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= + github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= + github.com/golang/gddo v0.0.0-20190904175337-72a348e765d2 h1:xisWqjiKEff2B0KfFYGpCqc3M3zdTz+OHQHRc09FeYk= +@@ -671,7 +625,6 @@ github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4er + github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +-github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= + 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= +@@ -681,7 +634,6 @@ github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt + github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= + github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= + github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +-github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= + 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/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +@@ -700,28 +652,7 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS + github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= + 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/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= + github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +-github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= +-github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= +-github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6/go.mod h1:DbHgvLiFKX1Sh2T1w8Q/h4NAI8MHIpzCdnBUDTXU3I0= +-github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8= +-github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3/go.mod h1:JXrF4TWy4tXYn62/9x8Wm/K/dm06p8tCKwFRDPZG/1o= +-github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU= +-github.com/golangci/gocyclo v0.0.0-20180528144436-0a533e8fa43d/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU= +-github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU= +-github.com/golangci/golangci-lint v1.23.7/go.mod h1:g/38bxfhp4rI7zeWSxcdIeHTQGS58TCak8FYcyCmavQ= +-github.com/golangci/golangci-lint v1.27.0/go.mod h1:+eZALfxIuthdrHPtfM7w/R3POJLjHDfJJw8XZl9xOng= +-github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU= +-github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= +-github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= +-github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= +-github.com/golangci/misspell v0.3.5/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= +-github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21/go.mod h1:tf5+bzsHdTM0bsB7+8mt0GUMvjCgwLpTapNZHU8AajI= +-github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4= +-github.com/golangci/revgrep v0.0.0-20180812185044-276a5c0a1039/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4= +-github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= +-github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= + 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/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +@@ -729,7 +660,7 @@ github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= + github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= + github.com/google/certificate-transparency-go v1.1.4 h1:hCyXHDbtqlr/lMXU0D4WgbalXL0Zk4dSWWMbPV8VrqY= + github.com/google/certificate-transparency-go v1.1.4/go.mod h1:D6lvbfwckhNrbM9WVl1EVeMOyzC19mpIjMOI4nxBHtQ= +-github.com/google/crfs v0.0.0-20191108021818-71d77da419c9/go.mod h1:etGhoOqfwPkooV6aqoX3eBGQOJblqdoc9XvWOeuxpPw= ++github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= + 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= +@@ -746,20 +677,11 @@ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8 + github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= + github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= + github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +-github.com/google/go-containerregistry v0.0.0-20191010200024-a3d713f9b7f8/go.mod h1:KyKXa9ciM8+lgMXwOVsXi7UxGrsf9mM61Mzs+xKUrKE= +-github.com/google/go-containerregistry v0.1.2/go.mod h1:GPivBPgdAyd2SU+vf6EpsgOtWDuPqjW0hJZt4rNdTZ4= + github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= +-github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +-github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM= +-github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +-github.com/google/go-replayers/grpcreplay v0.1.0/go.mod h1:8Ig2Idjpr6gifRd6pNVggX6TC1Zw6Jx74AKp7QNH2QE= +-github.com/google/go-replayers/httpreplay v0.1.0/go.mod h1:YKZViNhiGgqdBlUbI2MwGpq4pXxNmhJLPHQ7cv2b5no= +-github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +-github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= + github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= + github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= ++github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= + github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +-github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= + github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= + github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= + github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +@@ -779,23 +701,17 @@ github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLe + github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= + github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= + github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +-github.com/google/rpmpack v0.0.0-20191226140753-aa36bfddb3a0/go.mod h1:RaTPr0KUf2K7fnZYLNDrr8rxAamWs3iNywJLtQ2AzBg= + github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= + github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +-github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= + github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= + github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= + github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= + github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= + github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= + github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +-github.com/google/wire v0.3.0/go.mod h1:i1DMg/Lu8Sz5yYl25iOdmc5CT5qusaa+zmRWs16741s= +-github.com/google/wire v0.4.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU= + github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= + github.com/googleapis/enterprise-certificate-proxy v0.1.0 h1:zO8WHNx/MYiAKJ3d5spxZXZE6KHmIQGQcAzwUzV7qQw= + github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +-github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= +-github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= + 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/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +@@ -804,19 +720,12 @@ github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/Oth + github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= + github.com/googleapis/gax-go/v2 v2.4.0 h1:dS9eYAjhrE2RjmzYw2XAPvcXfmcQLtFEQWn0CR82awk= + github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= +-github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +-github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= + github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= ++github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= ++github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= + github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= +-github.com/gookit/color v1.2.4/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg= +-github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= + github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +-github.com/goreleaser/goreleaser v0.136.0/go.mod h1:wiKrPUeSNh6Wu8nUHxZydSOVQ/OZvOaO7DTtFqie904= +-github.com/goreleaser/nfpm v1.2.1/go.mod h1:TtWrABZozuLOttX2uDlYyECfQX7x5XYkVxhjYcR6G9w= +-github.com/goreleaser/nfpm v1.3.0/go.mod h1:w0p7Kc9TAUgWMyrub63ex3M2Mgw88M4GZXoTq5UCb40= +-github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= + github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= +-github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= + github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= + github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= + github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +@@ -824,28 +733,18 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7 + github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= + github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= + github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +-github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= +-github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= +-github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= + github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= + github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= + github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +-github.com/grpc-ecosystem/go-grpc-middleware v1.2.0/go.mod h1:mJzapYve32yjrKlk9GbyCZHuPgZsrbyIbyKhSzOpg6s= + github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= + github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= + github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= + github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +-github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +-github.com/grpc-ecosystem/grpc-gateway v1.6.2/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +-github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= + github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +-github.com/grpc-ecosystem/grpc-gateway v1.9.2/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= + github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= + github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= + github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +-github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= +-github.com/hanwen/go-fuse v1.0.0/go.mod h1:unqXarDXqzAk0rt98O2tVndEPIpUgLD9+rwFisZH3Ok= +-github.com/hanwen/go-fuse/v2 v2.0.3/go.mod h1:0EQM6aH2ctVpvZ6a+onrQ/vaykxh2GH7hy3e13vzTUY= ++github.com/hanwen/go-fuse/v2 v2.1.1-0.20220112183258-f57e95bda82d/go.mod h1:B1nGE/6RBFyBRC1RRnf23UpwCdyJ31eukw34oAKukAc= + 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 v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +@@ -869,8 +768,7 @@ github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHh + github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= + github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= + github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +-github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +-github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= ++github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= + github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= + github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= + github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= +@@ -879,11 +777,9 @@ github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdv + github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= + github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= + github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +-github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= + github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= + github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= + github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +-github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= + github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= + github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= + github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +@@ -895,13 +791,12 @@ github.com/hashicorp/memberlist v0.4.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4 + github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= + github.com/hashicorp/serf v0.8.5 h1:ZynDUIQiA8usmRgPdGPHFdPnb1wgGI9tK3mO9hcAJjc= + github.com/hashicorp/serf v0.8.5/go.mod h1:UpNcs7fFbpKIyZaUuSW6EPiH+eZC7OuyFD+wc1oal+k= +-github.com/hashicorp/uuid v0.0.0-20160311170451-ebb0a03e909c/go.mod h1:fHzc09UnyJyqyW+bFuq864eh+wC7dj65aXmXLRe5to0= + github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= + github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= + github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= + github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= ++github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= + github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +-github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= + github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= + github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= + github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +@@ -912,34 +807,22 @@ github.com/in-toto/in-toto-golang v0.5.0/go.mod h1:/Rq0IZHLV7Ku5gielPT4wPHJfH1Gd + github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= + github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= + github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +-github.com/ishidawataru/sctp v0.0.0-20191218070446-00ab2ac2db07/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg= ++github.com/intel/goresctrl v0.2.0/go.mod h1:+CZdzouYFn5EsxgqAQTEzMfwKwuc0fVdMrT9FCCAVRQ= + github.com/ishidawataru/sctp v0.0.0-20230406120618-7ff4192f6ff2 h1:i2fYnDurfLlJH8AyyMOnkLHnHeP8Ff/DDpuZA/D3bPo= + github.com/ishidawataru/sctp v0.0.0-20230406120618-7ff4192f6ff2/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg= + github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= +-github.com/jaguilar/vt100 v0.0.0-20150826170717-2703a27b14ea/go.mod h1:QMdK4dGB3YhEW2BmA1wgGpPYI3HZy/5gD705PXKUVSg= +-github.com/jarcoal/httpmock v1.0.5/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= +-github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= +-github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a/go.mod h1:xRskid8CManxVta/ALEhJha/pweKBaVG6fWgc0yH25s= +-github.com/jirfag/go-printf-func-name v0.0.0-20191110105641-45db9963cdd3/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= +-github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= ++github.com/j-keck/arping v1.0.2/go.mod h1:aJbELhR92bSk7tp79AWM/ftfc90EfEi2bQJrbBFOsPw= + github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= + github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +-github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +-github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= + github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= + github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +-github.com/jmoiron/sqlx v1.2.1-0.20190826204134-d7d95172beb5/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= + github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= +-github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= + github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= + github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +-github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0= ++github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= + github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +-github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +-github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= + github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= + github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +-github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= + github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= + github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= + github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +@@ -953,15 +836,12 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW + github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= + github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= + github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +-github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +-github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= + github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= + github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= ++github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= + github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= + github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= + github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +-github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +-github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= + 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/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +@@ -971,131 +851,102 @@ github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn + github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= + github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= + github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +-github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= + github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= +-github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= + github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= + github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= + github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= + github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= +-github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +-github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +-github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= ++github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= + github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo= +-github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= + github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= + github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= + github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= + github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= + github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= + github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +-github.com/maratori/testpackage v1.0.1/go.mod h1:ddKdw+XG0Phzhx8BFDTKgpWP4i7MpApTE5fXSKAqwDU= ++github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= + github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= +-github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= + github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +-github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +-github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +-github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +-github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +-github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +-github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +-github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E= + github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= + github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +-github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +-github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +-github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +-github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= + github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= + github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= + github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= +-github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= +-github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +-github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= +-github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= ++github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= + github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= + github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= + github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= + github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= + github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= +-github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= + github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= + github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= + github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= + github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= + github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= ++github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= + github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= + github.com/mistifyio/go-zfs/v3 v3.0.1 h1:YaoXgBePoMA12+S1u/ddkv+QqxcfiZK4prI6HPnkFiU= + github.com/mistifyio/go-zfs/v3 v3.0.1/go.mod h1:CzVgeB0RvF2EGzQnytKVvVSDwmKJXxkOTUGbNrTja/k= + github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= + github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= + github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +-github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk= + github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= + github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= + github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +-github.com/mitchellh/hashstructure v1.0.0/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= + github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= + github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= + github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= + github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= + github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +-github.com/mitchellh/mapstructure v1.3.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= + github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= +-github.com/moby/buildkit v0.8.1/go.mod h1:/kyU1hKy/aYCuP39GZA9MaKioovHku57N6cqlKZIaiQ= +-github.com/moby/buildkit v0.11.7-0.20240124010513-435cb77e369c h1:g/BEZuMQ7Jws8NGsrS2yvMgtShhVe5t/IhSy7yP9Z0c= +-github.com/moby/buildkit v0.11.7-0.20240124010513-435cb77e369c/go.mod h1:bMQDryngJKGvJ/ZuRFhrejurbvYSv3NkGCheQ59X4AM= + github.com/moby/ipvs v1.1.0 h1:ONN4pGaZQgAx+1Scz5RvWV4Q7Gb+mvfRh3NsPS+1XQQ= + github.com/moby/ipvs v1.1.0/go.mod h1:4VJMWuf098bsUMmZEiD4Tjk/O7mOn3l1PTD3s4OoYAs= + github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= + github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= ++github.com/moby/patternmatcher v0.5.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= + github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= + github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= + github.com/moby/pubsub v1.0.0 h1:jkp/imWsmJz2f6LyFsk7EkVeN2HxR/HTTOY8kHrsxfA= + github.com/moby/pubsub v1.0.0/go.mod h1:bXSO+3h5MNXXCaEG+6/NlAIk7MMZbySZlnB+cUQhKKc= ++github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= + github.com/moby/swarmkit/v2 v2.0.0-20230531205928-01bb7a41396b h1:w07xyBXYTrihwBqCkuXPLqcQ1a2guqXlRIocU+e9K7A= + github.com/moby/swarmkit/v2 v2.0.0-20230531205928-01bb7a41396b/go.mod h1:Z5i5At5g0zU+ZBWb/95yVwDeNQX8BZmei9ZoYvoVD7g= +-github.com/moby/sys/mount v0.1.0/go.mod h1:FVQFLDRWwyBjDTBNQXDlWnSFREqOo3OKX9aqhmeoo74= +-github.com/moby/sys/mount v0.1.1/go.mod h1:FVQFLDRWwyBjDTBNQXDlWnSFREqOo3OKX9aqhmeoo74= + github.com/moby/sys/mount v0.3.3 h1:fX1SVkXFJ47XWDoeFW4Sq7PdQJnV2QIDZAqjNqgEjUs= + github.com/moby/sys/mount v0.3.3/go.mod h1:PBaEorSNTLG5t/+4EgukEQVlAvVEc6ZjTySwKdqp5K0= +-github.com/moby/sys/mountinfo v0.1.0/go.mod h1:w2t2Avltqx8vE7gX5l+QiBKxODu2TX0+Syr3h52Tw4o= +-github.com/moby/sys/mountinfo v0.1.3/go.mod h1:w2t2Avltqx8vE7gX5l+QiBKxODu2TX0+Syr3h52Tw4o= + github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= + github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= ++github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= + github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78= + github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= + github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= + github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= ++github.com/moby/sys/signal v0.6.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg= + github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI= + github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg= + github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= + github.com/moby/sys/symlink v0.2.0 h1:tk1rOM+Ljp0nFmfOIBtlV3rTDlWOwFRhjEeAhZB0nZc= + github.com/moby/sys/symlink v0.2.0/go.mod h1:7uZVF2dqJjG/NsClqul95CqKOBRQyYSNnJ6BMgR/gFs= + github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= +-github.com/moby/term v0.0.0-20200915141129-7f0af18e79f2/go.mod h1:TjQg8pa4iejrUrjiz0MCtMV38jdMNW4doKSiBrEvCQQ= ++github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A= + github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= + github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +-github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= + github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= + github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= + github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= ++github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= ++github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= + github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= + github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +-github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= +-github.com/mozilla/tls-observatory v0.0.0-20200317151703-4fa42e1c2dee/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= +-github.com/mrunalp/fileutils v0.0.0-20200520151820-abd8a0e76976/go.mod h1:x8F1gnqOkIEiO4rqoeEEEqQbo7HjGMTvyoq3gej4iT0= + github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= + github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= + github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= + github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= + github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +-github.com/nakabonne/nestif v0.3.0/go.mod h1:dI314BppzXjJ4HsCnbo7XzrJHPszZsjnk5wEBSYHI2c= +-github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= + github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= ++github.com/networkplumbing/go-nft v0.2.0/go.mod h1:HnnM+tYvlGAsMU7yoYwXEVLLiDW9gdMmb5HoGcwpuQs= + github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= + github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= + github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +@@ -1105,30 +956,33 @@ github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:v + github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= + github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= + github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +-github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= + github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= + github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= + github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= + github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= + github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= + github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= ++github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= ++github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= + github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= + github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +-github.com/onsi/ginkgo/v2 v2.1.3 h1:e/3Cwtogj0HA+25nMP1jCMDIf8RtRYbGwGGuBIFztkc= + github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= ++github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= ++github.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU= ++github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= + github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= + github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +-github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= + github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= + github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= + github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +-github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= + github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= + github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= + github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= +-github.com/onsi/gomega v1.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE= ++github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= + github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +-github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= ++github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= ++github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q= ++github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= + github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= + github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= + github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +@@ -1137,23 +991,27 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 + github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= + github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= + github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= ++github.com/opencontainers/image-spec v1.0.2-0.20211117181255-693428a734f5/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= ++github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= ++github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= ++github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= + github.com/opencontainers/image-spec v1.1.0-rc3 h1:fzg1mXZFj8YdPeNkRXMg+zb88BFV0Ys52cJydRwBkb8= + github.com/opencontainers/image-spec v1.1.0-rc3/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= + github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= + github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +-github.com/opencontainers/runc v1.0.0-rc10/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= + github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= + github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +-github.com/opencontainers/runc v1.0.0-rc92/go.mod h1:X1zlU4p7wOlX4+WRCz+hvlRv8phdL7UqbYD+vQwNMmE= + github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= + github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= ++github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= ++github.com/opencontainers/runc v1.1.2/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= ++github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= + github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss= + github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8= + github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= + github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= + github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= + github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +-github.com/opencontainers/runtime-spec v1.0.3-0.20200728170252-4d89ac9fbff6/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= + github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= + github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= + github.com/opencontainers/runtime-spec v1.1.0-rc.2 h1:ucBtEms2tamYYW/SvGpvq9yUN0NEVL6oyLEwDcTSrk8= +@@ -1162,47 +1020,41 @@ github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mo + github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= + github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= + github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= ++github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= ++github.com/opencontainers/selinux v1.10.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= ++github.com/opencontainers/selinux v1.10.2/go.mod h1:cARutUbaUrlRClyvxOICCgKixCs6L05aUsohzA3EkHQ= + github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= + github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= +-github.com/opentracing-contrib/go-stdlib v1.0.0/go.mod h1:qtI1ogk+2JhVPIXVc6q+NHziSmy2W5GbdQZFUHADCBU= + github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +-github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +-github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= +-github.com/openzipkin/zipkin-go v0.1.3/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= +-github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= + github.com/package-url/packageurl-go v0.1.1-0.20220428063043-89078438f170 h1:DiLBVp4DAcZlBVBEtJpNWZpZVq0AEeCY7Hqk8URVs4o= + github.com/package-url/packageurl-go v0.1.1-0.20220428063043-89078438f170/go.mod h1:uQd4a7Rh3ZsVg5j0lNyAfyxIeGde9yrlhjF78GzeW0c= + github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= + github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= + github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +-github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= + github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +-github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs= + github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= ++github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= ++github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= + github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= + github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= + github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +-github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw= + github.com/phayes/permbits v0.0.0-20190612203442-39d7c581d2ee h1:P6U24L02WMfj9ymZTxl7CxS73JC99x3ukk+DBkgQGQs= + github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= + github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= + github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= +-github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= ++github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= + github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= + github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/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/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18= +-github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= + 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= + github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= + github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +-github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= + github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +-github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= + github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= + github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= + github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= +@@ -1215,29 +1067,25 @@ github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj + github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= + github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= + github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +-github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= + github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= + github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= + github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= + github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= + github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= + github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +-github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= + github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +-github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= + github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= + github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= + github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= + github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= + github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= + github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= ++github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= + github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= + github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= + github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= + github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +-github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= + github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +-github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= + github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= + github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= + github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +@@ -1251,48 +1099,34 @@ github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 + github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= + github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= + github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +-github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI= +-github.com/quasilyte/go-ruleguard v0.1.2-0.20200318202121-b00d7a75d3d8/go.mod h1:CGFX09Ci3pq9QZdj86B+VGIdNj4VyCo2iPOGS9esB/k= +-github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +-github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= + github.com/rexray/gocsi v1.2.2 h1:h9F/eSizORihN+XT+mxhq7ClZ3cYo1L9RvasN6dKz8U= + github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +-github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= + 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/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= + github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= + github.com/rootless-containers/rootlesskit v1.1.1 h1:F5psKWoWY9/VjZ3ifVcaosjvFZJOagX85U22M0/EQZE= + github.com/rootless-containers/rootlesskit v1.1.1/go.mod h1:UD5GoA3dqKCJrnvnhVgQQnweMF2qZnf9KLw8EewcMZI= +-github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +-github.com/rubiojr/go-vhd v0.0.0-20160810183302-0bfd3b39853c/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto= +-github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= ++github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= ++github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= + github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= + github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +-github.com/ryancurrah/gomodguard v1.0.4/go.mod h1:9T/Cfuxs5StfsocWr4WzDL36HqnX0fVb9d5fSEaLhoE= +-github.com/ryancurrah/gomodguard v1.1.0/go.mod h1:4O8tr7hBODaGE6VIhfJDHcwzh5GUccKSJBU0UMXJFVM= + github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= + github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= + github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= +-github.com/sassoftware/go-rpmutils v0.0.0-20190420191620-a8f1baeba37b/go.mod h1:am+Fp8Bt506lA3Rk3QCmSqmYmLMnPDhdDUcosQCAx+I= ++github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= + github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= ++github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= + github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= + github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= + github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= + github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= ++github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= ++github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= + github.com/secure-systems-lab/go-securesystemslib v0.4.0 h1:b23VGrQhTA8cN2CbBw7/FulN9fTtqYUdS5+Oxzt+DUE= + github.com/secure-systems-lab/go-securesystemslib v0.4.0/go.mod h1:FGBZgq2tXWICsxWQW1msNf49F0Pf2Op5Htayx335Qbs= +-github.com/securego/gosec v0.0.0-20200103095621-79fbf3af8d83/go.mod h1:vvbZ2Ae7AzSq3/kywjUDxSNq2SJ27RxCz2un0H3ePqE= +-github.com/securego/gosec v0.0.0-20200401082031-e946c8c39989/go.mod h1:i9l/TNj+yDFh9SZXUTvspXTjbFXgZGP/UvhU1S65A4A= +-github.com/securego/gosec/v2 v2.3.0/go.mod h1:UzeVyUXbxukhLeHKV3VVqo7HdoQR9MrRfFmZYotn8ME= +-github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= + github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002/go.mod h1:/yeG0My1xr/u+HZrFQ1tOQQQQrOawfyMUH13ai5brBc= + github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh5dkI= + github.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh5tVaaMCl3jE= +-github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc= +-github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= +-github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +-github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= + github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= + github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= + github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +@@ -1302,18 +1136,14 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd + github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= + github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= + github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= ++github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= + github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= + github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= + github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +-github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= +-github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= + github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= + github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +-github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs= + github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= + github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= +-github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE= +-github.com/sourcegraph/go-diff v0.5.3/go.mod h1:v9JDtjCE4HHHCZGId75rg8gkKKa98RVjBcBGsVmMmak= + github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= + github.com/spdx/gordf v0.0.0-20201111095634-7098f93598fb/go.mod h1:uKWaldnbMnjsSAXRurWqqrdyZen1R7kxl8TkmWk2OyM= + github.com/spdx/tools-golang v0.3.1-0.20230104082527-d6f58551be3f h1:9B623Cfs+mclYK6dsae7gLSwuIBHvlgmEup87qpqsAQ= +@@ -1321,33 +1151,31 @@ github.com/spdx/tools-golang v0.3.1-0.20230104082527-d6f58551be3f/go.mod h1:VHzv + github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= + github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= + github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +-github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= + github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= + github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +-github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= + github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= + github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= ++github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= + github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= + github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= + github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +-github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= + github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= + github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= + github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= + github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= + github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= + github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +-github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= + github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +-github.com/spf13/viper v1.6.1/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k= + github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= ++github.com/spiffe/go-spiffe/v2 v2.1.1/go.mod h1:5qg6rpqlwIub0JAiF1UK9IMD6BpPTmvG6yfSgDBs5lg= + github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= ++github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= + github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= + github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= + github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +-github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= + github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +-github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= ++github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= ++github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= + github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= + github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= + github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +@@ -1355,31 +1183,19 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P + 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/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= ++github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= ++github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= + github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= + github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= + github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= + github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= + github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +-github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= + github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= +-github.com/tdakkota/asciicheck v0.0.0-20200416190851-d7f85be797a2/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= +-github.com/tdakkota/asciicheck v0.0.0-20200416200610-e657995f937b/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= +-github.com/tetafro/godot v0.3.7/go.mod h1:/7NLHhv08H1+8DNj0MElpAACw1ajsCuf3TKNQxA5S+0= +-github.com/tetafro/godot v0.4.2/go.mod h1:/7NLHhv08H1+8DNj0MElpAACw1ajsCuf3TKNQxA5S+0= +-github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= +-github.com/timakin/bodyclose v0.0.0-20200424151742-cb6215831a94/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= + github.com/tinylib/msgp v1.1.6 h1:i+SbKraHhnrf9M5MYmvQhFnbLhAXSDWF8WWsuyRdocw= + github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw= +-github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0= +-github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eNAjXGDx2yma7uG2XoyRZTq1uv3M/o7imD0= +-github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b/go.mod h1:/yhzCV0xPfx6jb1bBgRFjl5lytqVqZXEaeqWP8lTEao= +-github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4= + github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= + github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= + github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +-github.com/tommy-muehle/go-mnd v1.1.1/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig= +-github.com/tommy-muehle/go-mnd v1.3.1-0.20200224220436-e6f9a994e8fa/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig= +-github.com/tonistiigi/fsutil v0.0.0-20201103201449-0834f99b7b85/go.mod h1:a7cilN64dG941IOXfhJhlH0qB92hxJ9A1ewrdUmJ6xo= + github.com/tonistiigi/fsutil v0.0.0-20230105215944-fb433841cbfa h1:XOFp/3aBXlqmOFAg3r6e0qQjPnK5I970LilqX+Is1W8= + github.com/tonistiigi/fsutil v0.0.0-20230105215944-fb433841cbfa/go.mod h1:AvLEd1LEIl64G2Jpgwo7aVV5lGH0ePcKl0ygGIHNYl8= + github.com/tonistiigi/go-actions-cache v0.0.0-20220404170428-0bdeb6e1eac7 h1:8eY6m1mjgyB8XySUR7WvebTM8D/Vs86jLJzD/Tw7zkc= +@@ -1388,47 +1204,36 @@ github.com/tonistiigi/go-archvariant v1.0.0 h1:5LC1eDWiBNflnTF1prCiX09yfNHIxDC/a + github.com/tonistiigi/go-archvariant v1.0.0/go.mod h1:TxFmO5VS6vMq2kvs3ht04iPXtu2rUT/erOnGFYfk5Ho= + github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/v/cCndK0AMpt1wiVFb/YYmqB3/QG0= + github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea/go.mod h1:WPnis/6cRcDZSUvVmezrxJPkiO87ThFYsoUiMwWNDJk= ++github.com/tonistiigi/vt100 v0.0.0-20210615222946-8066bb97264f/go.mod h1:ulncasL3N9uLrVann0m+CDlJKWsIAP34MPcOJF6VRvc= + github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +-github.com/uber/jaeger-client-go v2.25.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= +-github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= ++github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= + github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +-github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +-github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= +-github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +-github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= +-github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= + github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= + github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= + github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= + github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= + github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +-github.com/uudashr/gocognit v1.0.1/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM= +-github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +-github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s= +-github.com/valyala/quicktemplate v1.2.0/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4= +-github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= ++github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= + github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME= + github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI= +-github.com/vdemeester/k8s-pkg-credentialprovider v1.17.4/go.mod h1:inCTmtUdr5KJbreVojo06krnTgaeAz/Z7lynpPk/Q2c= + github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= + github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= + github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= ++github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= + github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs= + github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= + github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= + github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= + github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= ++github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= + github.com/vishvananda/netns v0.0.2 h1:Cn05BRLm+iRP/DZxyVSsfVyrzgjDbwHwkVt38qvXnNI= + github.com/vishvananda/netns v0.0.2/go.mod h1:yitZXdAVI+yPFSb4QUe+VW3vOVl4PZPNcBgbPxAtJxw= +-github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= + github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= + github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= +-github.com/xanzy/go-gitlab v0.31.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug= +-github.com/xanzy/go-gitlab v0.32.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug= + github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= + github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +-github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= ++github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= + github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= + github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= + github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +@@ -1436,33 +1241,38 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de + github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= + github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= + github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= ++github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= ++github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= + github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= + github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= + github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= ++github.com/zeebo/errs v1.2.2/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4= + go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= + go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= + go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= + go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= + go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= + go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +-go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= + go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= ++go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= + go.etcd.io/etcd/api/v3 v3.5.6/go.mod h1:KFtNaxGDw4Yx/BA4iPPwevUTAuqcsPxzyX8PHydchN8= ++go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= + go.etcd.io/etcd/client/pkg/v3 v3.5.6 h1:TXQWYceBKqLp4sa87rcPs11SXxUA/mHwH975v+BDvLU= + go.etcd.io/etcd/client/pkg/v3 v3.5.6/go.mod h1:ggrwbk069qxpKPq8/FKkQ3Xq9y39kbFR4LnKszpRXeQ= ++go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= + go.etcd.io/etcd/client/v2 v2.305.6/go.mod h1:BHha8XJGe8vCIBfWBpbBLVZ4QjOIlfoouvOwydu63E0= ++go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= + go.etcd.io/etcd/client/v3 v3.5.6/go.mod h1:f6GRinRMCsFVv9Ht42EyY7nfsVGwrNO0WEoS2pRKzQk= ++go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= + go.etcd.io/etcd/pkg/v3 v3.5.6 h1:k1GZrGrfMHy5/cg2bxNGsmLTFisatyhDYCFLRuaavWg= + go.etcd.io/etcd/pkg/v3 v3.5.6/go.mod h1:qATwUzDb6MLyGWq2nUj+jwXqZJcxkCuabh0P7Cuff3k= ++go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= + go.etcd.io/etcd/raft/v3 v3.5.6 h1:tOmx6Ym6rn2GpZOrvTGJZciJHek6RnC3U/zNInzIN50= + go.etcd.io/etcd/raft/v3 v3.5.6/go.mod h1:wL8kkRGx1Hp8FmZUuHfL3K2/OaGIDaXGr1N7i2G07J0= ++go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= + go.etcd.io/etcd/server/v3 v3.5.6 h1:RXuwaB8AMiV62TqcqIt4O4bG8NWjsxOkDJVT3MZI5Ds= + go.etcd.io/etcd/server/v3 v3.5.6/go.mod h1:6/Gfe8XTGXQJgLYQ65oGKMfPivb2EASLUSMSWN9Sroo= + go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= +-go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0= +-go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= +-go.opencensus.io v0.19.1/go.mod h1:gug0GbSHa8Pafr0d2urOSgoXHZ6x/RUlaiT0d9pqb4A= +-go.opencensus.io v0.19.2/go.mod h1:NO/8qkisMZLZ1FCsKNqtJPwc8/TaclWyY0B6wcYNg9M= + 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= +@@ -1471,40 +1281,61 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= + go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= + go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= + go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= ++go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= ++go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.25.0/go.mod h1:E5NNboN0UqSAki0Atn9kVwaN7I+l25gGxDqBueo/74E= ++go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.28.0/go.mod h1:vEhqr0m4eTc+DWxfsXoXue2GBgV2uUwVznkGIHW/e5w= + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.29.0 h1:n9b7AAdbQtQ0k9dm0Dm2/KUcUqtG8i2O15KzNaDze8c= + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.29.0/go.mod h1:LsankqVDx4W+RhZNA5uWarULII/MBhF5qwCYxTuyXjs= + go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.29.0 h1:Wjp9vsVSIEyvdiaECfqxY9xBqQ7JaSCGtvHgR4doXZk= + go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.29.0/go.mod h1:vHItvsnJtp7ES++nFLLFBzUWny7fJQSvTlxFcqQGUr4= ++go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.29.0 h1:SLme4Porm+UwX0DdHMxlwRt7FzPSE0sys81bet2o0pU= + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.29.0/go.mod h1:tLYsuf2v8fZreBVwp9gVMhefZlLFZaUiNVSq8QxXRII= ++go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= + go.opentelemetry.io/otel v1.0.1/go.mod h1:OPEOD4jIT2SlZPMmwT6FqZz2C0ZNdQqiWcoK6M0SNFU= ++go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs= + go.opentelemetry.io/otel v1.4.0/go.mod h1:jeAqMFKy2uLIxCtKxoFj0FAL5zAPKQagc3+GtBWakzk= + go.opentelemetry.io/otel v1.4.1 h1:QbINgGDDcoQUoMJa2mMaWno49lja9sHwp6aoa2n3a4g= + go.opentelemetry.io/otel v1.4.1/go.mod h1:StM6F/0fSwpd8dKWDCdRr7uRvEPYdW0hBSlbdTiUde4= ++go.opentelemetry.io/otel/exporters/jaeger v1.4.1/go.mod h1:ZW7vkOu9nC1CxsD8bHNHCia5JUbwP39vxgd1q4Z5rCI= ++go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= ++go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4= + go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.4.1 h1:imIM3vRDMyZK1ypQlQlO+brE22I9lRhJsBDXpDWjlz8= + go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.4.1/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4= + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1/go.mod h1:Kv8liBeVNFkkkbilbgWRpV+wWuu+H5xdOT6HAgd30iw= ++go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0/go.mod h1:hO1KLR7jcKaDDKDkvI9dP/FIhpmna5lkqPUQdEjFAM8= + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.4.1 h1:WPpPsAAs8I2rA47v5u0558meKmmwm1Dj99ZbqCV8sZ8= + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.4.1/go.mod h1:o5RW5o2pKpJLD5dNTCmjF1DorYwMeFJmb/rKr5sLaa8= + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1/go.mod h1:xOvWoTOrQjxjW61xtOmD/WKGRYb/P4NzRo3bs65U6Rk= ++go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0/go.mod h1:keUU7UfnwWTWpJ+FWnyqmogPa82nuU5VUANFq49hlMY= + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.4.1 h1:AxqDiGk8CorEXStMDZF5Hz9vo9Z7ZZ+I5m8JRl/ko40= + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.4.1/go.mod h1:c6E4V3/U+miqjs/8l950wggHGL1qzlp0Ypj9xoGrPqo= ++go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.3.0/go.mod h1:QNX1aly8ehqqX1LEa6YniTU7VY9I6R3X/oPxhGdTceE= + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.4.1 h1:8qOago/OqoFclMUUj/184tZyRdDZFpcejSjbk5Jrl6Y= + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.4.1/go.mod h1:VwYo0Hak6Efuy0TXsZs8o1hnV3dHDPNtDbycG0hI8+M= + go.opentelemetry.io/otel/internal/metric v0.27.0 h1:9dAVGAfFiiEq5NVB9FUJ5et+btbDQAUIJehJ+ikyryk= + go.opentelemetry.io/otel/internal/metric v0.27.0/go.mod h1:n1CVxRqKqYZtqyTh9U/onvKapPGv7y/rpyOTI+LFNzw= ++go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= + go.opentelemetry.io/otel/metric v0.27.0 h1:HhJPsGhJoKRSegPQILFbODU56NS/L1UE4fS1sC5kIwQ= + go.opentelemetry.io/otel/metric v0.27.0/go.mod h1:raXDJ7uP2/Jc0nVZWQjJtzoyssOYWu/+pjZqRzfvZ7g= ++go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= ++go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= + go.opentelemetry.io/otel/sdk v1.0.1/go.mod h1:HrdXne+BiwsOHYYkBE5ysIcv2bvdZstxzmCQhxTcZkI= ++go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs= + go.opentelemetry.io/otel/sdk v1.4.1 h1:J7EaW71E0v87qflB4cDolaqq3AcujGrtyIPGQoZOB0Y= + go.opentelemetry.io/otel/sdk v1.4.1/go.mod h1:NBwHDgDIBYjwK2WNu1OPgsIc2IJzmBXNnvIJxJc8BpE= ++go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= ++go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= ++go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= + go.opentelemetry.io/otel/trace v1.0.1/go.mod h1:5g4i4fKLaX2BQpSBsxw8YYcgKpMMSW3x7ZTuYBr3sUk= ++go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk= + go.opentelemetry.io/otel/trace v1.4.0/go.mod h1:uc3eRsqDfWs9R7b92xbQbU42/eTNz4N+gLP8qJCi4aE= + go.opentelemetry.io/otel/trace v1.4.1 h1:O+16qcdTrT7zxv2J6GejTPFinSwA++cYerC5iSiF8EQ= + go.opentelemetry.io/otel/trace v1.4.1/go.mod h1:iYEVbroFCNut9QkwEczV9vMRPHNKSSwYZjulEtsmhFc= + go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= + go.opentelemetry.io/proto/otlp v0.9.0/go.mod h1:1vKfU9rv61e9EVGthD1zNvUbiwPcimSsOPU9brfSHJg= ++go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg3NAKnUGl9YpQ= + go.opentelemetry.io/proto/otlp v0.12.0 h1:CMJ/3Wp7iOWES+CYLfnBv+DVmPbB+kmy9PJ92XvlR6c= + go.opentelemetry.io/proto/otlp v0.12.0/go.mod h1:TsIjwGWIx5VFYv9KGVlOpxoBl5Dy+63SUguV7GGvlSQ= + go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +@@ -1512,6 +1343,7 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= + go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= + go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= + go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= ++go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= + go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= + go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= + go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +@@ -1523,39 +1355,35 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= + go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= + go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= + go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= +-go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= +-gocloud.dev v0.19.0/go.mod h1:SmKwiR8YwIMMJvQBKLsC3fHNyMwXLw3PMDO+VVteJMI= +-golang.org/x/build v0.0.0-20190314133821-5284462c4bec/go.mod h1:atTaCNAy0f16Ah5aV1gMSwgiKVHwu/JncqDpuRr7lS4= + golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= + golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= + golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= + golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +-golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +-golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +-golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= + golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +-golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= + golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= + golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= + golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= + golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= + golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= +-golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= + golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +-golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +-golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= + golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= + golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= + golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +-golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= ++golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= + golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= ++golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= ++golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= ++golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= ++golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= ++golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= ++golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= + golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= ++golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= ++golang.org/x/crypto v0.2.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= + golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= + golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= + golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +-golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= + golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +-golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= + 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= +@@ -1566,9 +1394,7 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH + 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-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= + golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +-golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= + golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= + golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= + golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +@@ -1591,21 +1417,17 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= + golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= + golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= + golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +-golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= ++golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= ++golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= + 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= + golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +-golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= + golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= + golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +-golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +-golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +-golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= + golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= + golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= + golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= + golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +-golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= + golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= + golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= + golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +@@ -1622,7 +1444,6 @@ golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLL + golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= + golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= + golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +-golang.org/x/net v0.0.0-20191112182307-2180aed22343/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= + 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= +@@ -1639,6 +1460,7 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R + 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-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= ++golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= + golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= + golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= + golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +@@ -1651,9 +1473,13 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd + golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= + golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= + golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= ++golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= + golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= + golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= ++golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= + golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= ++golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= ++golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= + golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= + golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= + golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +@@ -1661,15 +1487,14 @@ golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su + golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= + golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= + golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= ++golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= ++golang.org/x/net v0.1.1-0.20221027164007-c63010009c80/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= ++golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= ++golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= + golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= + golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +-golang.org/x/oauth2 v0.0.0-20180724155351-3d292e4d0cdc/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= + golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +-golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +-golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +-golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/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-20190402181905-9f3314589c9a/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= +@@ -1692,7 +1517,6 @@ golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7Lm + golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= + golang.org/x/oauth2 v0.1.0 h1:isLCZuhj4v+tYv7eskaN4v/TM+A1begWWgyVJDdl1+Y= + golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= +-golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= + 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= +@@ -1705,23 +1529,17 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ + golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= + golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= ++golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= + golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= + golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +-golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= + 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= + golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= + golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= + golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +-golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/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-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +-golang.org/x/sys v0.0.0-20181218192612-074acd46bca6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +-golang.org/x/sys v0.0.0-20190209173611-3b5209105503/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-20190222072716-a9d3bda3a223/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= + golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +@@ -1733,7 +1551,6 @@ golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7w + golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +-golang.org/x/sys v0.0.0-20190620070143-6f217b454f45/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +@@ -1748,7 +1565,6 @@ golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7w + golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +-golang.org/x/sys v0.0.0-20191112214154-59a1497f0cea/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +@@ -1756,7 +1572,6 @@ golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7w + golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/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-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +@@ -1770,6 +1585,7 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w + 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-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +@@ -1781,11 +1597,9 @@ golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7w + golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +-golang.org/x/sys v0.0.0-20200917073148-efd3b9a0ff20/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +-golang.org/x/sys v0.0.0-20201013081832-0aaa2718063a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +@@ -1815,9 +1629,16 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc + golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= + golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= + golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= ++golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= ++golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= + golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= ++golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= ++golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= ++golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= + golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= ++golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= + golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= ++golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= + golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= + golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= + golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +@@ -1825,23 +1646,34 @@ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBc + golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= + golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= + golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= ++golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= + golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= ++golang.org/x/sys v0.0.0-20220405210540-1e041c57c461/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= + golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= ++golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= + golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= + golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= + golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= + golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= + golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= + golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= ++golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= + golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= ++golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= ++golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= + golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= ++golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= + golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= + golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= + golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= + golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= ++golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= ++golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= ++golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= ++golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= ++golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= + golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= +-golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= + 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= +@@ -1851,6 +1683,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= + golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= + golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= + golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= ++golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= ++golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= + golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= + golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= + golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +@@ -1860,31 +1694,22 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb + golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= + golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= + golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= ++golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= ++golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= + golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= + golang.org/x/time v0.3.0/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-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +-golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/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-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= + golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +-golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +-golang.org/x/tools v0.0.0-20181219222714-6e267b5cc78e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +-golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= + golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +-golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +-golang.org/x/tools v0.0.0-20190221204921-83362c3779f5/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= + golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= + golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +-golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= + golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= + golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +-golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= + golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +-golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/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-20190521203540-521d6ed310dd/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-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +@@ -1892,43 +1717,31 @@ golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgw + 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-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= +-golang.org/x/tools v0.0.0-20190719005602-e377ae9d6386/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= + golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= + golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +-golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/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-20190920225731-5eefd052ad72/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-20191108193012-7d206e10da11/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-20191113232020-e2727e816f5a/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-20200102140908-9497f49d5709/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-20200204192400-7124308813f3/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-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= + golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +-golang.org/x/tools v0.0.0-20200331202046-9d5940d49312/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +-golang.org/x/tools v0.0.0-20200414032229-332987a829c3/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +-golang.org/x/tools v0.0.0-20200422022333-3d57cf2e726e/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +-golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= + golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +-golang.org/x/tools v0.0.0-20200502202811-ed308ab3e770/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= + golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/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= +@@ -1953,6 +1766,8 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= + golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= + golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= + golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= ++golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= ++golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= + 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= +@@ -1960,19 +1775,8 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T + golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= + golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= + golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +-gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= +-gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +-gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= + google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +-google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +-google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +-google.golang.org/api v0.0.0-20181220000619-583d854617af/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +-google.golang.org/api v0.2.0/go.mod h1:IfRCZScioGtypHNTlz3gFk67J8uePVW7uDTBzXuIkhU= +-google.golang.org/api v0.3.0/go.mod h1:IuvZyQh8jgscv8qWfQ4ABd8m7hEudgBFM/EdhA3BnXw= + google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +-google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +-google.golang.org/api v0.6.0/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4= +-google.golang.org/api v0.6.1-0.20190607001116-5213b8090861/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4= + 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= +@@ -1985,7 +1789,6 @@ google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/ + 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.25.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= +@@ -2016,8 +1819,6 @@ google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3p + google.golang.org/api v0.93.0 h1:T2xt9gi0gHdxdnRkVQhT8mIvPaXKNsDNWz+L696M66M= + google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= + google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +-google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +-google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= + 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= +@@ -2027,17 +1828,11 @@ google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6 + google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= + google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= + google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +-google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +-google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +-google.golang.org/genproto v0.0.0-20181219182458-5a97ab628bfb/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= + 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= + google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= + google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +-google.golang.org/genproto v0.0.0-20190508193815-b515fa19cec8/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= + google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +-google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +-google.golang.org/genproto v0.0.0-20190620144150-6af8c5fc6601/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= + google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= + 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= +@@ -2065,8 +1860,10 @@ google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7Fc + 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-20200806141610-86f49bd18e98/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-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= ++google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= + google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= + google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= + google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +@@ -2112,6 +1909,7 @@ google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX + google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= + google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= + google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= ++google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= + google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= + google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= + google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +@@ -2122,9 +1920,6 @@ google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljW + google.golang.org/genproto v0.0.0-20220706185917-7780775163c4 h1:7YDGQC/0sigNGzsEWyb9s72jTxlFdwVEYNJHbfQ+Dtg= + google.golang.org/genproto v0.0.0-20220706185917-7780775163c4/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= + google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +-google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +-google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= +-google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= + 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.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +@@ -2155,15 +1950,18 @@ google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD + google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= + google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= + google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= ++google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= + google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= + google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= + google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= + google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= + google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= + google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= ++google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= + google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= + google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= + google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= ++google.golang.org/grpc/examples v0.0.0-20201130180447-c456688b1860/go.mod h1:Ly7ZA/ARzg8fnPU9TyZIxoz33sEUuWX7txiqs8lPTgE= + 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= +@@ -2188,34 +1986,33 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 + gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= + gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= ++gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= + gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= + gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= + gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +-gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= + gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= + gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= + gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +-gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= + gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= + gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= + gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= + gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= ++gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= + gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= + gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= + gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +-gopkg.in/warnings.v0 v0.1.1/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= + gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= + 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.3/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.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +-gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= + gopkg.in/yaml.v2 v2.2.8/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-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= + gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= + gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +@@ -2225,9 +2022,6 @@ gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= + gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= + gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= + gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= +-grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= +-honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +-honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= + 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= +@@ -2235,74 +2029,61 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh + 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/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +-honnef.co/go/tools v0.0.1-2020.1.5/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +-k8s.io/api v0.0.0-20180904230853-4e7be11eab3f/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= +-k8s.io/api v0.17.4/go.mod h1:5qxx6vjmwUVG2nHQTKGlLts8Tbok8PzHl4vHtVFuZCA= +-k8s.io/api v0.19.0/go.mod h1:I1K45XlvTrDjmj5LoM5LuP/KYrhWbjUKT/SoPG0qTjw= + k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= + k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= + k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= +-k8s.io/apimachinery v0.0.0-20180904193909-def12e63c512/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= +-k8s.io/apimachinery v0.17.4/go.mod h1:gxLnyZcGNdZTCLnq3fgzyg2A5BVCHTNDFrw8AmuJ+0g= +-k8s.io/apimachinery v0.19.0/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= ++k8s.io/api v0.22.5/go.mod h1:mEhXyLaSD1qTOf40rRiKXkc+2iCem09rWLlFwhCEiAs= ++k8s.io/api v0.25.4/go.mod h1:IG2+RzyPQLllQxnhzD8KQNEu4c4YvyDTpSMztf4A0OQ= + k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= + k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= + k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= +-k8s.io/apiserver v0.17.4/go.mod h1:5ZDQ6Xr5MNBxyi3iUZXS84QOhZl+W7Oq2us/29c0j9I= ++k8s.io/apimachinery v0.22.1/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= ++k8s.io/apimachinery v0.22.5/go.mod h1:xziclGKwuuJ2RM5/rSFQSYAj0zdbci3DH8kj+WvyN0U= ++k8s.io/apimachinery v0.25.4/go.mod h1:jaF9C/iPNM1FuLl7Zuy5b9v+n35HGSh6AQ4HYRkCqwo= + k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= + k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= + k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= +-k8s.io/client-go v0.0.0-20180910083459-2cefa64ff137/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= +-k8s.io/client-go v0.17.4/go.mod h1:ouF6o5pz3is8qU0/qYL2RnoxOPqgfuidYLowytyLJmc= +-k8s.io/client-go v0.19.0/go.mod h1:H9E/VT95blcFQnlyShFgnFT9ZnJOAceiUHM3MlRC+mU= ++k8s.io/apiserver v0.22.5/go.mod h1:s2WbtgZAkTKt679sYtSudEQrTGWUSQAPe6MupLnlmaQ= + k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= + k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= + k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= +-k8s.io/cloud-provider v0.17.4/go.mod h1:XEjKDzfD+b9MTLXQFlDGkk6Ho8SGMpaU8Uugx/KNK9U= +-k8s.io/code-generator v0.17.2/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s= ++k8s.io/client-go v0.22.5/go.mod h1:cs6yf/61q2T1SdQL5Rdcjg9J1ElXSwbjSrW2vFImM4Y= ++k8s.io/client-go v0.25.4/go.mod h1:8trHCAC83XKY0wsBIpbirZU4NTUpbuhc2JnI7OruGZw= + k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0= +-k8s.io/component-base v0.17.4/go.mod h1:5BRqHMbbQPm2kKu35v3G+CpVq4K0RJKC7TRioF0I9lE= + k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= + k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= + k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= ++k8s.io/component-base v0.22.5/go.mod h1:VK3I+TjuF9eaa+Ln67dKxhGar5ynVbwnGrUiNF4MqCI= + k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= + k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= + k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= + k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= +-k8s.io/csi-translation-lib v0.17.4/go.mod h1:CsxmjwxEI0tTNMzffIAcgR9lX4wOh6AKHdxQrT7L0oo= +-k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +-k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= ++k8s.io/cri-api v0.23.1/go.mod h1:REJE3PSU0h/LOV1APBrupxrEJqnoxZC8KWzkBUHwrK4= ++k8s.io/cri-api v0.25.0/go.mod h1:J1rAyQkSJ2Q6I+aBMOVgg2/cbbebso6FNa0UagiR0kc= ++k8s.io/cri-api v0.26.0-alpha.3/go.mod h1:E49tenyB7esgfIguEd7+g9qYhHOr9peyyBcSaeH6Gxw= + k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= + k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= + k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +-k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +-k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +-k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= ++k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= + k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= + k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= + k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= ++k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= ++k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= ++k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= + k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= + k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +-k8s.io/kube-openapi v0.0.0-20180731170545-e3762e86a74c/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= +-k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= + k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= + k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= +-k8s.io/kubernetes v1.11.10/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= ++k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= ++k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= ++k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU= + k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= +-k8s.io/legacy-cloud-providers v0.17.4/go.mod h1:FikRNoD64ECjkxO36gkDgJeiQWwyZTuBkhu+yxOc1Js= +-k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +-k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= + k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +-modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= +-modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= +-modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= +-modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= +-modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= +-mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= +-mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= +-mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw= +-mvdan.cc/unparam v0.0.0-20200501210554-b37ab49443f7/go.mod h1:HGC5lll35J70Y5v7vCGb9oLhHoScFwkHDJm/05RdSTc= +-pack.ag/amqp v0.11.2/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4= ++k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= ++k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= ++k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= ++k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= + resenje.org/singleflight v0.3.0 h1:USJtsAN6HTUA827ksc+2Kcr7QZ4HBq/z/P8ugVbqKFY= + resenje.org/singleflight v0.3.0/go.mod h1:lAgQK7VfjG6/pgredbQfmV0RvG/uVhKo6vSuZ0vCWfk= + rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +@@ -2310,13 +2091,13 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= + rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= + sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= + sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +-sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= +-sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18= ++sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= ++sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= + sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= + sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= + sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= ++sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= ++sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= + sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= + sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= + sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +-sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= +-sourcegraph.com/sqs/pbtypes v1.0.0/go.mod h1:3AciMUv4qUuRHRHhOG4TZOB+72GdPVz5k+c648qsFS4= +diff --git a/vendor/github.com/moby/buildkit/executor/executor.go b/vendor/github.com/moby/buildkit/executor/executor.go +index a323bcc9cc94..61da4c9dd7c3 100644 +--- a/vendor/github.com/moby/buildkit/executor/executor.go ++++ b/vendor/github.com/moby/buildkit/executor/executor.go +@@ -6,7 +6,8 @@ import ( + "net" + "syscall" + +- "github.com/moby/buildkit/snapshot" ++ "github.com/containerd/containerd/mount" ++ "github.com/docker/docker/pkg/idtools" + "github.com/moby/buildkit/solver/pb" + ) + +@@ -27,8 +28,13 @@ type Meta struct { + RemoveMountStubsRecursive bool + } + ++type MountableRef interface { ++ Mount() ([]mount.Mount, func() error, error) ++ IdentityMapping() *idtools.IdentityMapping ++} ++ + type Mountable interface { +- Mount(ctx context.Context, readonly bool) (snapshot.Mountable, error) ++ Mount(ctx context.Context, readonly bool) (MountableRef, error) + } + + type Mount struct { +diff --git a/vendor/github.com/moby/buildkit/executor/oci/spec.go b/vendor/github.com/moby/buildkit/executor/oci/spec.go +index f825b1dce7ef..2c0e81b7b5b2 100644 +--- a/vendor/github.com/moby/buildkit/executor/oci/spec.go ++++ b/vendor/github.com/moby/buildkit/executor/oci/spec.go +@@ -12,7 +12,6 @@ import ( + "github.com/containerd/containerd/namespaces" + "github.com/containerd/containerd/oci" + "github.com/containerd/containerd/pkg/userns" +- "github.com/containerd/continuity/fs" + "github.com/docker/docker/pkg/idtools" + "github.com/mitchellh/hashstructure/v2" + "github.com/moby/buildkit/executor" +@@ -208,6 +207,7 @@ func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mou + type mountRef struct { + mount mount.Mount + unmount func() error ++ subRefs map[string]mountRef + } + + type submounts struct { +@@ -226,10 +226,17 @@ func (s *submounts) subMount(m mount.Mount, subPath string) (mount.Mount, error) + return mount.Mount{}, nil + } + if mr, ok := s.m[h]; ok { +- sm, err := sub(mr.mount, subPath) ++ if sm, ok := mr.subRefs[subPath]; ok { ++ return sm.mount, nil ++ } ++ sm, unmount, err := sub(mr.mount, subPath) + if err != nil { + return mount.Mount{}, nil + } ++ mr.subRefs[subPath] = mountRef{ ++ mount: sm, ++ unmount: unmount, ++ } + return sm, nil + } + +@@ -254,12 +261,17 @@ func (s *submounts) subMount(m mount.Mount, subPath string) (mount.Mount, error) + Options: opts, + }, + unmount: lm.Unmount, ++ subRefs: map[string]mountRef{}, + } + +- sm, err := sub(s.m[h].mount, subPath) ++ sm, unmount, err := sub(s.m[h].mount, subPath) + if err != nil { + return mount.Mount{}, err + } ++ s.m[h].subRefs[subPath] = mountRef{ ++ mount: sm, ++ unmount: unmount, ++ } + return sm, nil + } + +@@ -269,6 +281,9 @@ func (s *submounts) cleanup() { + for _, m := range s.m { + func(m mountRef) { + go func() { ++ for _, sm := range m.subRefs { ++ sm.unmount() ++ } + m.unmount() + wg.Done() + }() +@@ -277,15 +292,6 @@ func (s *submounts) cleanup() { + wg.Wait() + } + +-func sub(m mount.Mount, subPath string) (mount.Mount, error) { +- src, err := fs.RootPath(m.Source, subPath) +- if err != nil { +- return mount.Mount{}, err +- } +- m.Source = src +- return m, nil +-} +- + func specMapping(s []idtools.IDMap) []specs.LinuxIDMapping { + var ids []specs.LinuxIDMapping + for _, item := range s { +diff --git a/vendor/github.com/moby/buildkit/executor/oci/spec_linux.go b/vendor/github.com/moby/buildkit/executor/oci/spec_linux.go +new file mode 100644 +index 000000000000..abbf0879d87a +--- /dev/null ++++ b/vendor/github.com/moby/buildkit/executor/oci/spec_linux.go +@@ -0,0 +1,57 @@ ++//go:build linux ++// +build linux ++ ++package oci ++ ++import ( ++ "os" ++ "strconv" ++ ++ "github.com/containerd/containerd/mount" ++ "github.com/containerd/continuity/fs" ++ "github.com/moby/buildkit/snapshot" ++ "github.com/pkg/errors" ++ "golang.org/x/sys/unix" ++) ++ ++func sub(m mount.Mount, subPath string) (mount.Mount, func() error, error) { ++ var retries = 10 ++ root := m.Source ++ for { ++ src, err := fs.RootPath(root, subPath) ++ if err != nil { ++ return mount.Mount{}, nil, err ++ } ++ // similar to runc.WithProcfd ++ fh, err := os.OpenFile(src, unix.O_PATH|unix.O_CLOEXEC, 0) ++ if err != nil { ++ return mount.Mount{}, nil, err ++ } ++ ++ fdPath := "/proc/self/fd/" + strconv.Itoa(int(fh.Fd())) ++ if resolved, err := os.Readlink(fdPath); err != nil { ++ fh.Close() ++ return mount.Mount{}, nil, err ++ } else if resolved != src { ++ retries-- ++ if retries <= 0 { ++ fh.Close() ++ return mount.Mount{}, nil, errors.Errorf("unable to safely resolve subpath %s", subPath) ++ } ++ fh.Close() ++ continue ++ } ++ ++ m.Source = fdPath ++ lm := snapshot.LocalMounterWithMounts([]mount.Mount{m}, snapshot.ForceRemount()) ++ mp, err := lm.Mount() ++ if err != nil { ++ fh.Close() ++ return mount.Mount{}, nil, err ++ } ++ m.Source = mp ++ fh.Close() // release the fd, we don't need it anymore ++ ++ return m, lm.Unmount, nil ++ } ++} +diff --git a/vendor/github.com/moby/buildkit/executor/oci/spec_non_linux.go b/vendor/github.com/moby/buildkit/executor/oci/spec_non_linux.go +new file mode 100644 +index 000000000000..3442f594dbe6 +--- /dev/null ++++ b/vendor/github.com/moby/buildkit/executor/oci/spec_non_linux.go +@@ -0,0 +1,18 @@ ++//go:build !windows && !linux ++// +build !windows,!linux ++ ++package oci ++ ++import ( ++ "github.com/containerd/containerd/mount" ++ "github.com/containerd/continuity/fs" ++) ++ ++func sub(m mount.Mount, subPath string) (mount.Mount, func() error, error) { ++ src, err := fs.RootPath(m.Source, subPath) ++ if err != nil { ++ return mount.Mount{}, nil, err ++ } ++ m.Source = src ++ return m, func() error { return nil }, nil ++} +diff --git a/vendor/github.com/moby/buildkit/executor/oci/spec_windows.go b/vendor/github.com/moby/buildkit/executor/oci/spec_windows.go +index 48b0969e3922..757bd397dec4 100644 +--- a/vendor/github.com/moby/buildkit/executor/oci/spec_windows.go ++++ b/vendor/github.com/moby/buildkit/executor/oci/spec_windows.go +@@ -4,7 +4,9 @@ + package oci + + import ( ++ "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/oci" ++ "github.com/containerd/continuity/fs" + "github.com/docker/docker/pkg/idtools" + "github.com/moby/buildkit/solver/pb" + "github.com/pkg/errors" +@@ -43,3 +45,12 @@ func generateRlimitOpts(ulimits []*pb.Ulimit) ([]oci.SpecOpts, error) { + } + return nil, errors.New("no support for POSIXRlimit on Windows") + } ++ ++func sub(m mount.Mount, subPath string) (mount.Mount, func() error, error) { ++ src, err := fs.RootPath(m.Source, subPath) ++ if err != nil { ++ return mount.Mount{}, nil, err ++ } ++ m.Source = src ++ return m, func() error { return nil }, nil ++} +diff --git a/vendor/github.com/moby/buildkit/executor/stubs.go b/vendor/github.com/moby/buildkit/executor/stubs.go +index 22a8ac1310c4..09e26581a68c 100644 +--- a/vendor/github.com/moby/buildkit/executor/stubs.go ++++ b/vendor/github.com/moby/buildkit/executor/stubs.go +@@ -4,6 +4,7 @@ import ( + "errors" + "os" + "path/filepath" ++ "strings" + "syscall" + + "github.com/containerd/continuity/fs" +@@ -42,7 +43,7 @@ func MountStubsCleaner(dir string, mounts []Mount, recursive bool) func() { + } + + realPathNext := filepath.Dir(realPath) +- if realPath == realPathNext { ++ if realPath == realPathNext || realPathNext == dir { + break + } + realPath = realPathNext +@@ -51,6 +52,11 @@ func MountStubsCleaner(dir string, mounts []Mount, recursive bool) func() { + + return func() { + for _, p := range paths { ++ p, err := fs.RootPath(dir, strings.TrimPrefix(p, dir)) ++ if err != nil { ++ continue ++ } ++ + st, err := os.Lstat(p) + if err != nil { + continue +@@ -69,8 +75,12 @@ func MountStubsCleaner(dir string, mounts []Mount, recursive bool) func() { + + // Back up the timestamps of the dir for reproducible builds + // https://github.com/moby/buildkit/issues/3148 +- dir := filepath.Dir(p) +- dirSt, err := os.Stat(dir) ++ parent := filepath.Dir(p) ++ if realPath, err := fs.RootPath(dir, strings.TrimPrefix(parent, dir)); err != nil || realPath != parent { ++ continue ++ } ++ ++ dirSt, err := os.Stat(parent) + if err != nil { + logrus.WithError(err).Warnf("Failed to stat %q (parent of mount stub %q)", dir, p) + continue +@@ -87,7 +97,7 @@ func MountStubsCleaner(dir string, mounts []Mount, recursive bool) func() { + } + + // Restore the timestamps of the dir +- if err := os.Chtimes(dir, atime, mtime); err != nil { ++ if err := os.Chtimes(parent, atime, mtime); err != nil { + logrus.WithError(err).Warnf("Failed to restore time time mount stub timestamp (os.Chtimes(%q, %v, %v))", dir, atime, mtime) + } + } +diff --git a/vendor/github.com/moby/buildkit/frontend/frontend.go b/vendor/github.com/moby/buildkit/frontend/frontend.go +index 024ac802045c..4a068d17d41f 100644 +--- a/vendor/github.com/moby/buildkit/frontend/frontend.go ++++ b/vendor/github.com/moby/buildkit/frontend/frontend.go +@@ -4,6 +4,7 @@ import ( + "context" + + "github.com/moby/buildkit/client/llb" ++ "github.com/moby/buildkit/executor" + gw "github.com/moby/buildkit/frontend/gateway/client" + "github.com/moby/buildkit/session" + "github.com/moby/buildkit/solver" +@@ -17,7 +18,7 @@ type Result = result.Result[solver.ResultProxy] + type Attestation = result.Attestation[solver.ResultProxy] + + type Frontend interface { +- Solve(ctx context.Context, llb FrontendLLBBridge, opt map[string]string, inputs map[string]*pb.Definition, sid string, sm *session.Manager) (*Result, error) ++ Solve(ctx context.Context, llb FrontendLLBBridge, exec executor.Executor, opt map[string]string, inputs map[string]*pb.Definition, sid string, sm *session.Manager) (*Result, error) + } + + type FrontendLLBBridge interface { +diff --git a/vendor/github.com/moby/buildkit/frontend/gateway/container.go b/vendor/github.com/moby/buildkit/frontend/gateway/container.go +index d6161d1def93..9fb4d928d66d 100644 +--- a/vendor/github.com/moby/buildkit/frontend/gateway/container.go ++++ b/vendor/github.com/moby/buildkit/frontend/gateway/container.go +@@ -43,7 +43,7 @@ type Mount struct { + WorkerRef *worker.WorkerRef + } + +-func NewContainer(ctx context.Context, w worker.Worker, sm *session.Manager, g session.Group, req NewContainerRequest) (client.Container, error) { ++func NewContainer(ctx context.Context, cm cache.Manager, exec executor.Executor, sm *session.Manager, g session.Group, req NewContainerRequest) (client.Container, error) { + ctx, cancel := context.WithCancel(ctx) + eg, ctx := errgroup.WithContext(ctx) + platform := opspb.Platform{ +@@ -58,7 +58,7 @@ func NewContainer(ctx context.Context, w worker.Worker, sm *session.Manager, g s + netMode: req.NetMode, + extraHosts: req.ExtraHosts, + platform: platform, +- executor: w.Executor(), ++ executor: exec, + errGroup: eg, + ctx: ctx, + cancel: cancel, +@@ -79,9 +79,8 @@ func NewContainer(ctx context.Context, w worker.Worker, sm *session.Manager, g s + } + + name := fmt.Sprintf("container %s", req.ContainerID) +- mm := mounts.NewMountManager(name, w.CacheManager(), sm) +- p, err := PrepareMounts(ctx, mm, w.CacheManager(), g, "", mnts, refs, func(m *opspb.Mount, ref cache.ImmutableRef) (cache.MutableRef, error) { +- cm := w.CacheManager() ++ mm := mounts.NewMountManager(name, cm, sm) ++ p, err := PrepareMounts(ctx, mm, cm, g, "", mnts, refs, func(m *opspb.Mount, ref cache.ImmutableRef) (cache.MutableRef, error) { + if m.Input != opspb.Empty { + cm = refs[m.Input].Worker.CacheManager() + } +diff --git a/vendor/github.com/moby/buildkit/frontend/gateway/forwarder/forward.go b/vendor/github.com/moby/buildkit/frontend/gateway/forwarder/forward.go +index e13894ba37ed..4c374e781de9 100644 +--- a/vendor/github.com/moby/buildkit/frontend/gateway/forwarder/forward.go ++++ b/vendor/github.com/moby/buildkit/frontend/gateway/forwarder/forward.go +@@ -6,6 +6,7 @@ import ( + + cacheutil "github.com/moby/buildkit/cache/util" + "github.com/moby/buildkit/client/llb" ++ "github.com/moby/buildkit/executor" + "github.com/moby/buildkit/frontend" + "github.com/moby/buildkit/frontend/gateway" + "github.com/moby/buildkit/frontend/gateway/client" +@@ -26,7 +27,7 @@ import ( + "golang.org/x/sync/errgroup" + ) + +-func llbBridgeToGatewayClient(ctx context.Context, llbBridge frontend.FrontendLLBBridge, opts map[string]string, inputs map[string]*opspb.Definition, w worker.Infos, sid string, sm *session.Manager) (*bridgeClient, error) { ++func llbBridgeToGatewayClient(ctx context.Context, llbBridge frontend.FrontendLLBBridge, exec executor.Executor, opts map[string]string, inputs map[string]*opspb.Definition, w worker.Infos, sid string, sm *session.Manager) (*bridgeClient, error) { + bc := &bridgeClient{ + opts: opts, + inputs: inputs, +@@ -35,6 +36,7 @@ func llbBridgeToGatewayClient(ctx context.Context, llbBridge frontend.FrontendLL + sm: sm, + workers: w, + workerRefByID: make(map[string]*worker.WorkerRef), ++ executor: exec, + } + bc.buildOpts = bc.loadBuildOpts() + return bc, nil +@@ -52,6 +54,7 @@ type bridgeClient struct { + workerRefByID map[string]*worker.WorkerRef + buildOpts client.BuildOpts + ctrs []client.Container ++ executor executor.Executor + } + + func (c *bridgeClient) Solve(ctx context.Context, req client.SolveRequest) (*client.Result, error) { +@@ -292,13 +295,13 @@ func (c *bridgeClient) NewContainer(ctx context.Context, req client.NewContainer + return nil, err + } + +- w, err := c.workers.GetDefault() ++ cm, err := c.workers.DefaultCacheManager() + if err != nil { + return nil, err + } + + group := session.NewGroup(c.sid) +- ctr, err := gateway.NewContainer(ctx, w, c.sm, group, ctrReq) ++ ctr, err := gateway.NewContainer(ctx, cm, c.executor, c.sm, group, ctrReq) + if err != nil { + return nil, err + } +diff --git a/vendor/github.com/moby/buildkit/frontend/gateway/forwarder/frontend.go b/vendor/github.com/moby/buildkit/frontend/gateway/forwarder/frontend.go +index 7cd25a0e8ea0..331559a39057 100644 +--- a/vendor/github.com/moby/buildkit/frontend/gateway/forwarder/frontend.go ++++ b/vendor/github.com/moby/buildkit/frontend/gateway/forwarder/frontend.go +@@ -3,6 +3,7 @@ package forwarder + import ( + "context" + ++ "github.com/moby/buildkit/executor" + "github.com/moby/buildkit/frontend" + "github.com/moby/buildkit/frontend/gateway/client" + "github.com/moby/buildkit/session" +@@ -22,8 +23,8 @@ type GatewayForwarder struct { + f client.BuildFunc + } + +-func (gf *GatewayForwarder) Solve(ctx context.Context, llbBridge frontend.FrontendLLBBridge, opts map[string]string, inputs map[string]*pb.Definition, sid string, sm *session.Manager) (retRes *frontend.Result, retErr error) { +- c, err := llbBridgeToGatewayClient(ctx, llbBridge, opts, inputs, gf.workers, sid, sm) ++func (gf *GatewayForwarder) Solve(ctx context.Context, llbBridge frontend.FrontendLLBBridge, exec executor.Executor, opts map[string]string, inputs map[string]*pb.Definition, sid string, sm *session.Manager) (retRes *frontend.Result, retErr error) { ++ c, err := llbBridgeToGatewayClient(ctx, llbBridge, exec, opts, inputs, gf.workers, sid, sm) + if err != nil { + return nil, err + } +diff --git a/vendor/github.com/moby/buildkit/frontend/gateway/gateway.go b/vendor/github.com/moby/buildkit/frontend/gateway/gateway.go +index 79825d0b651a..8f2af4d34101 100644 +--- a/vendor/github.com/moby/buildkit/frontend/gateway/gateway.go ++++ b/vendor/github.com/moby/buildkit/frontend/gateway/gateway.go +@@ -82,7 +82,7 @@ func filterPrefix(opts map[string]string, pfx string) map[string]string { + return m + } + +-func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.FrontendLLBBridge, opts map[string]string, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) (*frontend.Result, error) { ++func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.FrontendLLBBridge, exec executor.Executor, opts map[string]string, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) (*frontend.Result, error) { + source, ok := opts[keySource] + if !ok { + return nil, errors.Errorf("no source specified for gateway") +@@ -251,18 +251,13 @@ func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.Fronten + } + } + +- lbf, ctx, err := serveLLBBridgeForwarder(ctx, llbBridge, gf.workers, inputs, sid, sm) ++ lbf, ctx, err := serveLLBBridgeForwarder(ctx, llbBridge, exec, gf.workers, inputs, sid, sm) + defer lbf.conn.Close() //nolint + if err != nil { + return nil, err + } + defer lbf.Discard() + +- w, err := gf.workers.GetDefault() +- if err != nil { +- return nil, err +- } +- + mdmnt, release, err := metadataMount(frontendDef) + if err != nil { + return nil, err +@@ -275,8 +270,7 @@ func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.Fronten + mnts = append(mnts, *mdmnt) + } + +- err = w.Executor().Run(ctx, "", mountWithSession(rootFS, session.NewGroup(sid)), mnts, executor.ProcessInfo{Meta: meta, Stdin: lbf.Stdin, Stdout: lbf.Stdout, Stderr: os.Stderr}, nil) +- ++ err = exec.Run(ctx, "", mountWithSession(rootFS, session.NewGroup(sid)), mnts, executor.ProcessInfo{Meta: meta, Stdin: lbf.Stdin, Stdout: lbf.Stdout, Stderr: os.Stderr}, nil) + if err != nil { + if errdefs.IsCanceled(ctx, err) && lbf.isErrServerClosed { + err = errors.Errorf("frontend grpc server closed unexpectedly") +@@ -405,11 +399,11 @@ func (lbf *llbBridgeForwarder) Result() (*frontend.Result, error) { + return lbf.result, nil + } + +-func NewBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, workers worker.Infos, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) LLBBridgeForwarder { +- return newBridgeForwarder(ctx, llbBridge, workers, inputs, sid, sm) ++func NewBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, exec executor.Executor, workers worker.Infos, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) LLBBridgeForwarder { ++ return newBridgeForwarder(ctx, llbBridge, exec, workers, inputs, sid, sm) + } + +-func newBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, workers worker.Infos, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) *llbBridgeForwarder { ++func newBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, exec executor.Executor, workers worker.Infos, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) *llbBridgeForwarder { + lbf := &llbBridgeForwarder{ + callCtx: ctx, + llbBridge: llbBridge, +@@ -422,13 +416,14 @@ func newBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridg + sid: sid, + sm: sm, + ctrs: map[string]gwclient.Container{}, ++ executor: exec, + } + return lbf + } + +-func serveLLBBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, workers worker.Infos, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) (*llbBridgeForwarder, context.Context, error) { ++func serveLLBBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, exec executor.Executor, workers worker.Infos, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) (*llbBridgeForwarder, context.Context, error) { + ctx, cancel := context.WithCancel(ctx) +- lbf := newBridgeForwarder(ctx, llbBridge, workers, inputs, sid, sm) ++ lbf := newBridgeForwarder(ctx, llbBridge, exec, workers, inputs, sid, sm) + server := grpc.NewServer(grpc.UnaryInterceptor(grpcerrors.UnaryServerInterceptor), grpc.StreamInterceptor(grpcerrors.StreamServerInterceptor)) + grpc_health_v1.RegisterHealthServer(server, health.NewServer()) + pb.RegisterLLBBridgeServer(server, lbf) +@@ -523,6 +518,7 @@ type llbBridgeForwarder struct { + isErrServerClosed bool + sid string + sm *session.Manager ++ executor executor.Executor + *pipe + ctrs map[string]gwclient.Container + ctrsMu sync.Mutex +@@ -1001,7 +997,7 @@ func (lbf *llbBridgeForwarder) NewContainer(ctx context.Context, in *pb.NewConta + // and we want the context to live for the duration of the container. + group := session.NewGroup(lbf.sid) + +- w, err := lbf.workers.GetDefault() ++ cm, err := lbf.workers.DefaultCacheManager() + if err != nil { + return nil, stack.Enable(err) + } +@@ -1011,7 +1007,7 @@ func (lbf *llbBridgeForwarder) NewContainer(ctx context.Context, in *pb.NewConta + return nil, stack.Enable(err) + } + +- ctr, err := NewContainer(context.Background(), w, lbf.sm, group, ctrReq) ++ ctr, err := NewContainer(context.Background(), cm, lbf.executor, lbf.sm, group, ctrReq) + if err != nil { + return nil, stack.Enable(err) + } +diff --git a/vendor/github.com/moby/buildkit/snapshot/localmounter.go b/vendor/github.com/moby/buildkit/snapshot/localmounter.go +index 9ddb7c1af642..304eebc9e02d 100644 +--- a/vendor/github.com/moby/buildkit/snapshot/localmounter.go ++++ b/vendor/github.com/moby/buildkit/snapshot/localmounter.go +@@ -11,22 +11,39 @@ type Mounter interface { + Unmount() error + } + ++type LocalMounterOpt func(*localMounter) ++ + // LocalMounter is a helper for mounting mountfactory to temporary path. In + // addition it can mount binds without privileges +-func LocalMounter(mountable Mountable) Mounter { +- return &localMounter{mountable: mountable} ++func LocalMounter(mountable Mountable, opts ...LocalMounterOpt) Mounter { ++ lm := &localMounter{mountable: mountable} ++ for _, opt := range opts { ++ opt(lm) ++ } ++ return lm + } + + // LocalMounterWithMounts is a helper for mounting to temporary path. In + // addition it can mount binds without privileges +-func LocalMounterWithMounts(mounts []mount.Mount) Mounter { +- return &localMounter{mounts: mounts} ++func LocalMounterWithMounts(mounts []mount.Mount, opts ...LocalMounterOpt) Mounter { ++ lm := &localMounter{mounts: mounts} ++ for _, opt := range opts { ++ opt(lm) ++ } ++ return lm + } + + type localMounter struct { +- mu sync.Mutex +- mounts []mount.Mount +- mountable Mountable +- target string +- release func() error ++ mu sync.Mutex ++ mounts []mount.Mount ++ mountable Mountable ++ target string ++ release func() error ++ forceRemount bool ++} ++ ++func ForceRemount() LocalMounterOpt { ++ return func(lm *localMounter) { ++ lm.forceRemount = true ++ } + } +diff --git a/vendor/github.com/moby/buildkit/snapshot/localmounter_unix.go b/vendor/github.com/moby/buildkit/snapshot/localmounter_unix.go +index a4b7b1a9e409..0e1f40f298c4 100644 +--- a/vendor/github.com/moby/buildkit/snapshot/localmounter_unix.go ++++ b/vendor/github.com/moby/buildkit/snapshot/localmounter_unix.go +@@ -5,6 +5,7 @@ package snapshot + + import ( + "os" ++ "path/filepath" + "syscall" + + "github.com/containerd/containerd/mount" +@@ -34,30 +35,48 @@ func (lm *localMounter) Mount() (string, error) { + } + } + ++ var isFile bool + if len(lm.mounts) == 1 && (lm.mounts[0].Type == "bind" || lm.mounts[0].Type == "rbind") { +- ro := false +- for _, opt := range lm.mounts[0].Options { +- if opt == "ro" { +- ro = true +- break ++ if !lm.forceRemount { ++ ro := false ++ for _, opt := range lm.mounts[0].Options { ++ if opt == "ro" { ++ ro = true ++ break ++ } + } ++ if !ro { ++ return lm.mounts[0].Source, nil ++ } ++ } ++ fi, err := os.Stat(lm.mounts[0].Source) ++ if err != nil { ++ return "", err + } +- if !ro { +- return lm.mounts[0].Source, nil ++ if !fi.IsDir() { ++ isFile = true + } + } + +- dir, err := os.MkdirTemp("", "buildkit-mount") ++ dest, err := os.MkdirTemp("", "buildkit-mount") + if err != nil { + return "", errors.Wrap(err, "failed to create temp dir") + } + +- if err := mount.All(lm.mounts, dir); err != nil { +- os.RemoveAll(dir) +- return "", errors.Wrapf(err, "failed to mount %s: %+v", dir, lm.mounts) ++ if isFile { ++ dest = filepath.Join(dest, "file") ++ if err := os.WriteFile(dest, []byte{}, 0644); err != nil { ++ os.RemoveAll(dest) ++ return "", errors.Wrap(err, "failed to create temp file") ++ } ++ } ++ ++ if err := mount.All(lm.mounts, dest); err != nil { ++ os.RemoveAll(dest) ++ return "", errors.Wrapf(err, "failed to mount %s: %+v", dest, lm.mounts) + } +- lm.target = dir +- return dir, nil ++ lm.target = dest ++ return dest, nil + } + + func (lm *localMounter) Unmount() error { +diff --git a/vendor/github.com/moby/buildkit/snapshot/snapshotter.go b/vendor/github.com/moby/buildkit/snapshot/snapshotter.go +index edf95cee70cd..3150815bb3bc 100644 +--- a/vendor/github.com/moby/buildkit/snapshot/snapshotter.go ++++ b/vendor/github.com/moby/buildkit/snapshot/snapshotter.go +@@ -10,14 +10,11 @@ import ( + "github.com/containerd/containerd/pkg/userns" + "github.com/containerd/containerd/snapshots" + "github.com/docker/docker/pkg/idtools" ++ "github.com/moby/buildkit/executor" + "github.com/pkg/errors" + ) + +-type Mountable interface { +- // ID() string +- Mount() ([]mount.Mount, func() error, error) +- IdentityMapping() *idtools.IdentityMapping +-} ++type Mountable = executor.MountableRef + + // Snapshotter defines interface that any snapshot implementation should satisfy + type Snapshotter interface { +diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/bridge.go b/vendor/github.com/moby/buildkit/solver/llbsolver/bridge.go +index 185fe81f0649..5c95a3e7e958 100644 +--- a/vendor/github.com/moby/buildkit/solver/llbsolver/bridge.go ++++ b/vendor/github.com/moby/buildkit/solver/llbsolver/bridge.go +@@ -11,6 +11,7 @@ import ( + "github.com/moby/buildkit/cache/remotecache" + "github.com/moby/buildkit/client" + "github.com/moby/buildkit/client/llb" ++ "github.com/moby/buildkit/executor" + "github.com/moby/buildkit/frontend" + gw "github.com/moby/buildkit/frontend/gateway/client" + "github.com/moby/buildkit/identity" +@@ -23,6 +24,7 @@ import ( + "github.com/moby/buildkit/sourcepolicy" + spb "github.com/moby/buildkit/sourcepolicy/pb" + "github.com/moby/buildkit/util/bklog" ++ "github.com/moby/buildkit/util/entitlements" + "github.com/moby/buildkit/util/flightcontrol" + "github.com/moby/buildkit/util/progress" + "github.com/moby/buildkit/worker" +@@ -39,6 +41,10 @@ type llbBridge struct { + cms map[string]solver.CacheManager + cmsMu sync.Mutex + sm *session.Manager ++ ++ executorOnce sync.Once ++ executorErr error ++ executor executor.Executor + } + + func (b *llbBridge) Warn(ctx context.Context, dgst digest.Digest, msg string, opts frontend.WarnOpts) error { +@@ -151,6 +157,52 @@ func (b *llbBridge) loadResult(ctx context.Context, def *pb.Definition, cacheImp + return res, nil + } + ++func (b *llbBridge) validateEntitlements(p executor.ProcessInfo) error { ++ ent, err := loadEntitlements(b.builder) ++ if err != nil { ++ return err ++ } ++ v := entitlements.Values{ ++ NetworkHost: p.Meta.NetMode == pb.NetMode_HOST, ++ SecurityInsecure: p.Meta.SecurityMode == pb.SecurityMode_INSECURE, ++ } ++ return ent.Check(v) ++} ++ ++func (b *llbBridge) Run(ctx context.Context, id string, rootfs executor.Mount, mounts []executor.Mount, process executor.ProcessInfo, started chan<- struct{}) error { ++ if err := b.validateEntitlements(process); err != nil { ++ return err ++ } ++ ++ if err := b.loadExecutor(); err != nil { ++ return err ++ } ++ return b.executor.Run(ctx, id, rootfs, mounts, process, started) ++} ++ ++func (b *llbBridge) Exec(ctx context.Context, id string, process executor.ProcessInfo) error { ++ if err := b.validateEntitlements(process); err != nil { ++ return err ++ } ++ ++ if err := b.loadExecutor(); err != nil { ++ return err ++ } ++ return b.executor.Exec(ctx, id, process) ++} ++ ++func (b *llbBridge) loadExecutor() error { ++ b.executorOnce.Do(func() { ++ w, err := b.resolveWorker() ++ if err != nil { ++ b.executorErr = err ++ return ++ } ++ b.executor = w.Executor() ++ }) ++ return b.executorErr ++} ++ + type resultProxy struct { + id string + b *provenanceBridge +diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/provenance.go b/vendor/github.com/moby/buildkit/solver/llbsolver/provenance.go +index b30581c852d9..8b60f5e885fb 100644 +--- a/vendor/github.com/moby/buildkit/solver/llbsolver/provenance.go ++++ b/vendor/github.com/moby/buildkit/solver/llbsolver/provenance.go +@@ -161,7 +161,7 @@ func (b *provenanceBridge) Solve(ctx context.Context, req frontend.SolveRequest, + return nil, errors.Errorf("invalid frontend: %s", req.Frontend) + } + wb := &provenanceBridge{llbBridge: b.llbBridge, req: &req} +- res, err = f.Solve(ctx, wb, req.FrontendOpt, req.FrontendInputs, sid, b.llbBridge.sm) ++ res, err = f.Solve(ctx, wb, b.llbBridge, req.FrontendOpt, req.FrontendInputs, sid, b.llbBridge.sm) + if err != nil { + return nil, err + } +diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/solver.go b/vendor/github.com/moby/buildkit/solver/llbsolver/solver.go +index 94d25ce5b7b2..c9921085337c 100644 +--- a/vendor/github.com/moby/buildkit/solver/llbsolver/solver.go ++++ b/vendor/github.com/moby/buildkit/solver/llbsolver/solver.go +@@ -440,7 +440,7 @@ func (s *Solver) Solve(ctx context.Context, id string, sessionID string, req fro + br := s.bridge(j) + var fwd gateway.LLBBridgeForwarder + if s.gatewayForwarder != nil && req.Definition == nil && req.Frontend == "" { +- fwd = gateway.NewBridgeForwarder(ctx, br, s.workerController, req.FrontendInputs, sessionID, s.sm) ++ fwd = gateway.NewBridgeForwarder(ctx, br, br, s.workerController.Infos(), req.FrontendInputs, sessionID, s.sm) + defer fwd.Discard() + // Register build before calling s.recordBuildHistory, because + // s.recordBuildHistory can block for several seconds on +diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/vertex.go b/vendor/github.com/moby/buildkit/solver/llbsolver/vertex.go +index 41a31bb9bbba..d57f2a053db1 100644 +--- a/vendor/github.com/moby/buildkit/solver/llbsolver/vertex.go ++++ b/vendor/github.com/moby/buildkit/solver/llbsolver/vertex.go +@@ -101,16 +101,12 @@ func ValidateEntitlements(ent entitlements.Set) LoadOpt { + return func(op *pb.Op, _ *pb.OpMetadata, opt *solver.VertexOptions) error { + switch op := op.Op.(type) { + case *pb.Op_Exec: +- if op.Exec.Network == pb.NetMode_HOST { +- if !ent.Allowed(entitlements.EntitlementNetworkHost) { +- return errors.Errorf("%s is not allowed", entitlements.EntitlementNetworkHost) +- } ++ v := entitlements.Values{ ++ NetworkHost: op.Exec.Network == pb.NetMode_HOST, ++ SecurityInsecure: op.Exec.Security == pb.SecurityMode_INSECURE, + } +- +- if op.Exec.Security == pb.SecurityMode_INSECURE { +- if !ent.Allowed(entitlements.EntitlementSecurityInsecure) { +- return errors.Errorf("%s is not allowed", entitlements.EntitlementSecurityInsecure) +- } ++ if err := ent.Check(v); err != nil { ++ return err + } + } + return nil +diff --git a/vendor/github.com/moby/buildkit/util/entitlements/entitlements.go b/vendor/github.com/moby/buildkit/util/entitlements/entitlements.go +index f65b426bb201..328580c326df 100644 +--- a/vendor/github.com/moby/buildkit/util/entitlements/entitlements.go ++++ b/vendor/github.com/moby/buildkit/util/entitlements/entitlements.go +@@ -58,3 +58,23 @@ func (s Set) Allowed(e Entitlement) bool { + _, ok := s[e] + return ok + } ++ ++func (s Set) Check(v Values) error { ++ if v.NetworkHost { ++ if !s.Allowed(EntitlementNetworkHost) { ++ return errors.Errorf("%s is not allowed", EntitlementNetworkHost) ++ } ++ } ++ ++ if v.SecurityInsecure { ++ if !s.Allowed(EntitlementSecurityInsecure) { ++ return errors.Errorf("%s is not allowed", EntitlementSecurityInsecure) ++ } ++ } ++ return nil ++} ++ ++type Values struct { ++ NetworkHost bool ++ SecurityInsecure bool ++} +diff --git a/vendor/github.com/moby/buildkit/worker/worker.go b/vendor/github.com/moby/buildkit/worker/worker.go +index 2f426e9ead40..0a708227204b 100644 +--- a/vendor/github.com/moby/buildkit/worker/worker.go ++++ b/vendor/github.com/moby/buildkit/worker/worker.go +@@ -43,6 +43,6 @@ type Worker interface { + } + + type Infos interface { +- GetDefault() (Worker, error) ++ DefaultCacheManager() (cache.Manager, error) + WorkerInfos() []client.WorkerInfo + } +diff --git a/vendor/github.com/moby/buildkit/worker/workercontroller.go b/vendor/github.com/moby/buildkit/worker/workercontroller.go +index e175b4002b4a..150eed352a3a 100644 +--- a/vendor/github.com/moby/buildkit/worker/workercontroller.go ++++ b/vendor/github.com/moby/buildkit/worker/workercontroller.go +@@ -3,6 +3,7 @@ package worker + import ( + "github.com/containerd/containerd/filters" + "github.com/hashicorp/go-multierror" ++ "github.com/moby/buildkit/cache" + "github.com/moby/buildkit/client" + "github.com/pkg/errors" + ) +@@ -81,3 +82,25 @@ func (c *Controller) WorkerInfos() []client.WorkerInfo { + } + return out + } ++ ++func (c *Controller) Infos() Infos { ++ return &infosController{c: c} ++} ++ ++type infosController struct { ++ c *Controller ++} ++ ++var _ Infos = &infosController{} ++ ++func (c *infosController) DefaultCacheManager() (cache.Manager, error) { ++ w, err := c.c.GetDefault() ++ if err != nil { ++ return nil, err ++ } ++ return w.CacheManager(), nil ++} ++ ++func (c *infosController) WorkerInfos() []client.WorkerInfo { ++ return c.c.WorkerInfos() ++} +diff --git a/vendor/modules.txt b/vendor/modules.txt +index dd3fb54fefd2..2a3b597c5858 100644 +--- a/vendor/modules.txt ++++ b/vendor/modules.txt +@@ -577,7 +577,7 @@ github.com/mistifyio/go-zfs/v3 + # github.com/mitchellh/hashstructure/v2 v2.0.2 + ## explicit; go 1.14 + github.com/mitchellh/hashstructure/v2 +-# github.com/moby/buildkit v0.11.7-0.20240124010513-435cb77e369c ++# github.com/moby/buildkit v0.11.7-0.20240124010513-435cb77e369c => github.com/cyphar/buildkit v0.0.0-20240814025459-5d3afed3f7b4 + ## explicit; go 1.18 + github.com/moby/buildkit/api/services/control + github.com/moby/buildkit/api/types +@@ -1313,3 +1313,4 @@ k8s.io/klog/v2/internal/severity + # resenje.org/singleflight v0.3.0 + ## explicit; go 1.18 + resenje.org/singleflight ++# github.com/moby/buildkit => github.com/cyphar/buildkit v0.0.0-20240814025459-5d3afed3f7b4 +-- +2.47.0 + diff --git a/0007-bsc1221916-update-to-patched-buildkit-version-to-fix.patch b/0007-bsc1221916-update-to-patched-buildkit-version-to-fix.patch new file mode 100644 index 0000000..ad22444 --- /dev/null +++ b/0007-bsc1221916-update-to-patched-buildkit-version-to-fix.patch @@ -0,0 +1,898 @@ +From 7719675180f785c4e92df7efc25df9adc882b289 Mon Sep 17 00:00:00 2001 +From: Aleksa Sarai +Date: Thu, 2 May 2024 22:50:23 +1000 +Subject: [PATCH 07/13] bsc1221916: update to patched buildkit version to fix + symlink resolution + +SUSE-Bugs: https://bugzilla.suse.com/show_bug.cgi?id=1221916 +Signed-off-by: Aleksa Sarai +--- + builder/builder-next/worker/worker.go | 2 +- + vendor.mod | 2 +- + vendor.sum | 4 +- + .../buildkit/cache/contenthash/checksum.go | 393 ++++++++++-------- + .../moby/buildkit/cache/contenthash/path.go | 161 +++---- + vendor/modules.txt | 4 +- + 6 files changed, 314 insertions(+), 252 deletions(-) + +diff --git a/builder/builder-next/worker/worker.go b/builder/builder-next/worker/worker.go +index 210218bf5a37..e36517da2914 100644 +--- a/builder/builder-next/worker/worker.go ++++ b/builder/builder-next/worker/worker.go +@@ -50,7 +50,7 @@ import ( + ) + + func init() { +- version.Version = "v0.11.7+5d3afed3f7b4" ++ version.Version = "v0.11.7+ea1ca9670261" + } + + const labelCreatedAt = "buildkit/createdat" +diff --git a/vendor.mod b/vendor.mod +index 7946cbb75613..878ec24cee4b 100644 +--- a/vendor.mod ++++ b/vendor.mod +@@ -99,7 +99,7 @@ require ( + ) + + // github.com/cyphar/buildkit suse-stable-v24.0.9 +-replace github.com/moby/buildkit => github.com/cyphar/buildkit v0.0.0-20240814025459-5d3afed3f7b4 ++replace github.com/moby/buildkit => github.com/cyphar/buildkit v0.0.0-20240814030244-ea1ca9670261 + + require ( + cloud.google.com/go v0.102.1 // indirect +diff --git a/vendor.sum b/vendor.sum +index a426cdb147ce..187a4138d110 100644 +--- a/vendor.sum ++++ b/vendor.sum +@@ -446,8 +446,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 + github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= + github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= + github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +-github.com/cyphar/buildkit v0.0.0-20240814025459-5d3afed3f7b4 h1:e2A5JTqDADxy9xYHM0KxRXfYl9wCISpo5TitiaUmfGw= +-github.com/cyphar/buildkit v0.0.0-20240814025459-5d3afed3f7b4/go.mod h1:bMQDryngJKGvJ/ZuRFhrejurbvYSv3NkGCheQ59X4AM= ++github.com/cyphar/buildkit v0.0.0-20240814030244-ea1ca9670261 h1:xcmjjOjBMdaa2Z3Blblc3J2FraOISKtT6I/cjGG/244= ++github.com/cyphar/buildkit v0.0.0-20240814030244-ea1ca9670261/go.mod h1:bMQDryngJKGvJ/ZuRFhrejurbvYSv3NkGCheQ59X4AM= + github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= + github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= + github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= +diff --git a/vendor/github.com/moby/buildkit/cache/contenthash/checksum.go b/vendor/github.com/moby/buildkit/cache/contenthash/checksum.go +index dcf424a6b4fc..13a74be24c4e 100644 +--- a/vendor/github.com/moby/buildkit/cache/contenthash/checksum.go ++++ b/vendor/github.com/moby/buildkit/cache/contenthash/checksum.go +@@ -10,6 +10,7 @@ import ( + "path/filepath" + "strings" + "sync" ++ "sync/atomic" + + iradix "github.com/hashicorp/go-immutable-radix" + "github.com/hashicorp/golang-lru/simplelru" +@@ -288,7 +289,7 @@ func keyPath(p string) string { + // HandleChange notifies the source about a modification operation + func (cc *cacheContext) HandleChange(kind fsutil.ChangeKind, p string, fi os.FileInfo, err error) (retErr error) { + p = keyPath(p) +- k := convertPathToKey([]byte(p)) ++ k := convertPathToKey(p) + + deleteDir := func(cr *CacheRecord) { + if cr.Type == CacheRecordTypeDir { +@@ -367,7 +368,7 @@ func (cc *cacheContext) HandleChange(kind fsutil.ChangeKind, p string, fi os.Fil + // note that the source may be called later because data writing is async + if fi.Mode()&os.ModeSymlink == 0 && stat.Linkname != "" { + ln := path.Join("/", filepath.ToSlash(stat.Linkname)) +- v, ok := cc.txn.Get(convertPathToKey([]byte(ln))) ++ v, ok := cc.txn.Get(convertPathToKey(ln)) + if ok { + cp := *v.(*CacheRecord) + cr = &cp +@@ -405,7 +406,7 @@ func (cc *cacheContext) Checksum(ctx context.Context, mountable cache.Mountable, + defer m.clean() + + if !opts.Wildcard && len(opts.IncludePatterns) == 0 && len(opts.ExcludePatterns) == 0 { +- return cc.checksumFollow(ctx, m, p, opts.FollowLinks) ++ return cc.lazyChecksum(ctx, m, p, opts.FollowLinks) + } + + includedPaths, err := cc.includedPaths(ctx, m, p, opts) +@@ -416,7 +417,7 @@ func (cc *cacheContext) Checksum(ctx context.Context, mountable cache.Mountable, + if opts.FollowLinks { + for i, w := range includedPaths { + if w.record.Type == CacheRecordTypeSymlink { +- dgst, err := cc.checksumFollow(ctx, m, w.path, opts.FollowLinks) ++ dgst, err := cc.lazyChecksum(ctx, m, w.path, opts.FollowLinks) + if err != nil { + return "", err + } +@@ -443,30 +444,6 @@ func (cc *cacheContext) Checksum(ctx context.Context, mountable cache.Mountable, + return digester.Digest(), nil + } + +-func (cc *cacheContext) checksumFollow(ctx context.Context, m *mount, p string, follow bool) (digest.Digest, error) { +- const maxSymlinkLimit = 255 +- i := 0 +- for { +- if i > maxSymlinkLimit { +- return "", errors.Errorf("too many symlinks: %s", p) +- } +- cr, err := cc.checksumNoFollow(ctx, m, p) +- if err != nil { +- return "", err +- } +- if cr.Type == CacheRecordTypeSymlink && follow { +- link := cr.Linkname +- if !path.IsAbs(cr.Linkname) { +- link = path.Join(path.Dir(p), link) +- } +- i++ +- p = link +- } else { +- return cr.Digest, nil +- } +- } +-} +- + func (cc *cacheContext) includedPaths(ctx context.Context, m *mount, p string, opts ChecksumOpts) ([]*includedPath, error) { + cc.mu.Lock() + defer cc.mu.Unlock() +@@ -476,12 +453,12 @@ func (cc *cacheContext) includedPaths(ctx context.Context, m *mount, p string, o + } + + root := cc.tree.Root() +- scan, err := cc.needsScan(root, "") ++ scan, err := cc.needsScan(root, "", false) + if err != nil { + return nil, err + } + if scan { +- if err := cc.scanPath(ctx, m, ""); err != nil { ++ if err := cc.scanPath(ctx, m, "", false); err != nil { + return nil, err + } + } +@@ -534,13 +511,13 @@ func (cc *cacheContext) includedPaths(ctx context.Context, m *mount, p string, o + } + } else { + origPrefix = p +- k = convertPathToKey([]byte(origPrefix)) ++ k = convertPathToKey(origPrefix) + + // We need to resolve symlinks here, in case the base path + // involves a symlink. That will match fsutil behavior of + // calling functions such as stat and walk. + var cr *CacheRecord +- k, cr, err = getFollowLinks(root, k, true) ++ k, cr, err = getFollowLinks(root, k, false) + if err != nil { + return nil, err + } +@@ -552,7 +529,7 @@ func (cc *cacheContext) includedPaths(ctx context.Context, m *mount, p string, o + iter.SeekLowerBound(append(append([]byte{}, k...), 0)) + } + +- resolvedPrefix = string(convertKeyToPath(k)) ++ resolvedPrefix = convertKeyToPath(k) + } else { + k, _, keyOk = iter.Next() + } +@@ -563,7 +540,7 @@ func (cc *cacheContext) includedPaths(ctx context.Context, m *mount, p string, o + ) + + for keyOk { +- fn := string(convertKeyToPath(k)) ++ fn := convertKeyToPath(k) + + // Convert the path prefix from what we found in the prefix + // tree to what the argument specified. +@@ -749,36 +726,12 @@ func wildcardPrefix(root *iradix.Node, p string) (string, []byte, bool, error) { + return "", nil, false, nil + } + +- linksWalked := 0 +- k, cr, err := getFollowLinksWalk(root, convertPathToKey([]byte(d1)), true, &linksWalked) ++ // Only resolve the final symlink component if there are components in the ++ // wildcard segment. ++ k, cr, err := getFollowLinks(root, convertPathToKey(d1), d2 != "") + if err != nil { + return "", k, false, err + } +- +- if d2 != "" && cr != nil && cr.Type == CacheRecordTypeSymlink { +- // getFollowLinks only handles symlinks in path +- // components before the last component, so +- // handle last component in d1 specially. +- resolved := string(convertKeyToPath(k)) +- for { +- v, ok := root.Get(k) +- +- if !ok { +- return d1, k, false, nil +- } +- if v.(*CacheRecord).Type != CacheRecordTypeSymlink { +- break +- } +- +- linksWalked++ +- if linksWalked > 255 { +- return "", k, false, errors.Errorf("too many links") +- } +- +- resolved := cleanLink(resolved, v.(*CacheRecord).Linkname) +- k = convertPathToKey([]byte(resolved)) +- } +- } + return d1, k, cr != nil, nil + } + +@@ -814,19 +767,22 @@ func containsWildcards(name string) bool { + return false + } + +-func (cc *cacheContext) checksumNoFollow(ctx context.Context, m *mount, p string) (*CacheRecord, error) { ++func (cc *cacheContext) lazyChecksum(ctx context.Context, m *mount, p string, followTrailing bool) (digest.Digest, error) { + p = keyPath(p) ++ k := convertPathToKey(p) + ++ // Try to look up the path directly without doing a scan. + cc.mu.RLock() + if cc.txn == nil { + root := cc.tree.Root() + cc.mu.RUnlock() +- v, ok := root.Get(convertPathToKey([]byte(p))) +- if ok { +- cr := v.(*CacheRecord) +- if cr.Digest != "" { +- return cr, nil +- } ++ ++ _, cr, err := getFollowLinks(root, k, followTrailing) ++ if err != nil { ++ return "", err ++ } ++ if cr != nil && cr.Digest != "" { ++ return cr.Digest, nil + } + } else { + cc.mu.RUnlock() +@@ -846,7 +802,11 @@ func (cc *cacheContext) checksumNoFollow(ctx context.Context, m *mount, p string + } + }() + +- return cc.lazyChecksum(ctx, m, p) ++ cr, err := cc.scanChecksum(ctx, m, p, followTrailing) ++ if err != nil { ++ return "", err ++ } ++ return cr.Digest, nil + } + + func (cc *cacheContext) commitActiveTransaction() { +@@ -854,7 +814,7 @@ func (cc *cacheContext) commitActiveTransaction() { + addParentToMap(d, cc.dirtyMap) + } + for d := range cc.dirtyMap { +- k := convertPathToKey([]byte(d)) ++ k := convertPathToKey(d) + if _, ok := cc.txn.Get(k); ok { + cc.txn.Insert(k, &CacheRecord{Type: CacheRecordTypeDir}) + } +@@ -865,21 +825,21 @@ func (cc *cacheContext) commitActiveTransaction() { + cc.txn = nil + } + +-func (cc *cacheContext) lazyChecksum(ctx context.Context, m *mount, p string) (*CacheRecord, error) { ++func (cc *cacheContext) scanChecksum(ctx context.Context, m *mount, p string, followTrailing bool) (*CacheRecord, error) { + root := cc.tree.Root() +- scan, err := cc.needsScan(root, p) ++ scan, err := cc.needsScan(root, p, followTrailing) + if err != nil { + return nil, err + } + if scan { +- if err := cc.scanPath(ctx, m, p); err != nil { ++ if err := cc.scanPath(ctx, m, p, followTrailing); err != nil { + return nil, err + } + } +- k := convertPathToKey([]byte(p)) ++ k := convertPathToKey(p) + txn := cc.tree.Txn() + root = txn.Root() +- cr, updated, err := cc.checksum(ctx, root, txn, m, k, true) ++ cr, updated, err := cc.checksum(ctx, root, txn, m, k, followTrailing) + if err != nil { + return nil, err + } +@@ -888,9 +848,9 @@ func (cc *cacheContext) lazyChecksum(ctx context.Context, m *mount, p string) (* + return cr, err + } + +-func (cc *cacheContext) checksum(ctx context.Context, root *iradix.Node, txn *iradix.Txn, m *mount, k []byte, follow bool) (*CacheRecord, bool, error) { ++func (cc *cacheContext) checksum(ctx context.Context, root *iradix.Node, txn *iradix.Txn, m *mount, k []byte, followTrailing bool) (*CacheRecord, bool, error) { + origk := k +- k, cr, err := getFollowLinks(root, k, follow) ++ k, cr, err := getFollowLinks(root, k, followTrailing) + if err != nil { + return nil, false, err + } +@@ -916,7 +876,9 @@ func (cc *cacheContext) checksum(ctx context.Context, root *iradix.Node, txn *ir + } + h.Write(bytes.TrimPrefix(subk, k)) + +- subcr, _, err := cc.checksum(ctx, root, txn, m, subk, true) ++ // We do not follow trailing links when checksumming a directory's ++ // contents. ++ subcr, _, err := cc.checksum(ctx, root, txn, m, subk, false) + if err != nil { + return nil, false, err + } +@@ -933,7 +895,7 @@ func (cc *cacheContext) checksum(ctx context.Context, root *iradix.Node, txn *ir + dgst = digest.NewDigest(digest.SHA256, h) + + default: +- p := string(convertKeyToPath(bytes.TrimSuffix(k, []byte{0}))) ++ p := convertKeyToPath(bytes.TrimSuffix(k, []byte{0})) + + target, err := m.mount(ctx) + if err != nil { +@@ -965,42 +927,82 @@ func (cc *cacheContext) checksum(ctx context.Context, root *iradix.Node, txn *ir + return cr2, true, nil + } + +-// needsScan returns false if path is in the tree or a parent path is in tree +-// and subpath is missing +-func (cc *cacheContext) needsScan(root *iradix.Node, p string) (bool, error) { +- var linksWalked int +- return cc.needsScanFollow(root, p, &linksWalked) ++// pathSet is a set of path prefixes that can be used to see if a given path is ++// lexically a child of any path in the set. All paths provided to this set ++// MUST be absolute and use / as the separator. ++type pathSet struct { ++ // prefixes contains paths of the form "/a/b/", so that we correctly detect ++ // /a/b as being a parent of /a/b/c but not /a/bc. ++ prefixes []string + } + +-func (cc *cacheContext) needsScanFollow(root *iradix.Node, p string, linksWalked *int) (bool, error) { +- if p == "/" { +- p = "" +- } +- v, ok := root.Get(convertPathToKey([]byte(p))) +- if !ok { +- if p == "" { +- return true, nil ++// add a path to the set. This is a no-op if includes(path) == true. ++func (s *pathSet) add(p string) { ++ // Ensure the path is absolute and clean. ++ p = path.Join("/", p) ++ if !s.includes(p) { ++ if p != "/" { ++ p += "/" + } +- return cc.needsScanFollow(root, path.Clean(path.Dir(p)), linksWalked) ++ s.prefixes = append(s.prefixes, p) ++ } ++} ++ ++// includes returns true iff there is a path in the pathSet which is a lexical ++// parent of the given path. The provided path MUST be an absolute path and ++// MUST NOT contain any ".." components, as they will be path.Clean'd. ++func (s pathSet) includes(p string) bool { ++ // Ensure the path is absolute and clean. ++ p = path.Join("/", p) ++ if p != "/" { ++ p += "/" + } +- cr := v.(*CacheRecord) +- if cr.Type == CacheRecordTypeSymlink { +- if *linksWalked > 255 { +- return false, errTooManyLinks ++ for _, prefix := range s.prefixes { ++ if strings.HasPrefix(p, prefix) { ++ return true + } +- *linksWalked++ +- link := path.Clean(cr.Linkname) +- if !path.IsAbs(cr.Linkname) { +- link = path.Join("/", path.Dir(p), link) ++ } ++ return false ++} ++ ++// needsScan returns false if path is in the tree or a parent path is in tree ++// and subpath is missing. ++func (cc *cacheContext) needsScan(root *iradix.Node, path string, followTrailing bool) (bool, error) { ++ var ( ++ goodPaths pathSet ++ hasParentInTree bool ++ ) ++ k := convertPathToKey(path) ++ _, cr, err := getFollowLinksCallback(root, k, followTrailing, func(subpath string, cr *CacheRecord) error { ++ // If we found a path that exists in the cache, add it to the set of ++ // known-scanned paths. Otherwise, verify whether the not-found subpath ++ // is inside a known-scanned path (we might have hit a "..", taking us ++ // out of the scanned paths, or we might hit a non-existent path inside ++ // a scanned path). getFollowLinksCallback iterates left-to-right, so ++ // we will always hit ancestors first. ++ if cr != nil { ++ hasParentInTree = cr.Type != CacheRecordTypeSymlink ++ goodPaths.add(subpath) ++ } else { ++ hasParentInTree = goodPaths.includes(subpath) + } +- return cc.needsScanFollow(root, link, linksWalked) ++ return nil ++ }) ++ if err != nil { ++ return false, err + } +- return false, nil ++ return cr == nil && !hasParentInTree, nil + } + +-func (cc *cacheContext) scanPath(ctx context.Context, m *mount, p string) (retErr error) { ++// Only used by TestNeedScanChecksumRegression to make sure scanPath is not ++// called for paths we have already scanned. ++var ( ++ scanCounterEnable bool ++ scanCounter atomic.Uint64 ++) ++ ++func (cc *cacheContext) scanPath(ctx context.Context, m *mount, p string, followTrailing bool) (retErr error) { + p = path.Join("/", p) +- d, _ := path.Split(p) + + mp, err := m.mount(ctx) + if err != nil { +@@ -1010,33 +1012,42 @@ func (cc *cacheContext) scanPath(ctx context.Context, m *mount, p string) (retEr + n := cc.tree.Root() + txn := cc.tree.Txn() + +- parentPath, err := rootPath(mp, filepath.FromSlash(d), func(p, link string) error { ++ resolvedPath, err := rootPath(mp, filepath.FromSlash(p), followTrailing, func(p, link string) error { + cr := &CacheRecord{ + Type: CacheRecordTypeSymlink, + Linkname: filepath.ToSlash(link), + } +- k := []byte(path.Join("/", filepath.ToSlash(p))) +- k = convertPathToKey(k) +- txn.Insert(k, cr) ++ p = path.Join("/", filepath.ToSlash(p)) ++ txn.Insert(convertPathToKey(p), cr) + return nil + }) + if err != nil { + return err + } + +- err = filepath.Walk(parentPath, func(itemPath string, fi os.FileInfo, err error) error { ++ // Scan the parent directory of the path we resolved, unless we're at the ++ // root (in which case we scan the root). ++ scanPath := filepath.Dir(resolvedPath) ++ if !strings.HasPrefix(filepath.ToSlash(scanPath)+"/", filepath.ToSlash(mp)+"/") { ++ scanPath = resolvedPath ++ } ++ ++ err = filepath.Walk(scanPath, func(itemPath string, fi os.FileInfo, err error) error { ++ if scanCounterEnable { ++ scanCounter.Add(1) ++ } + if err != nil { ++ // If the root doesn't exist, ignore the error. ++ if itemPath == scanPath && errors.Is(err, os.ErrNotExist) { ++ return nil ++ } + return errors.Wrapf(err, "failed to walk %s", itemPath) + } + rel, err := filepath.Rel(mp, itemPath) + if err != nil { + return err + } +- k := []byte(path.Join("/", filepath.ToSlash(rel))) +- if string(k) == "/" { +- k = []byte{} +- } +- k = convertPathToKey(k) ++ k := convertPathToKey(keyPath(rel)) + if _, ok := n.Get(k); !ok { + cr := &CacheRecord{ + Type: CacheRecordTypeFile, +@@ -1069,55 +1080,118 @@ func (cc *cacheContext) scanPath(ctx context.Context, m *mount, p string) (retEr + return nil + } + +-func getFollowLinks(root *iradix.Node, k []byte, follow bool) ([]byte, *CacheRecord, error) { +- var linksWalked int +- return getFollowLinksWalk(root, k, follow, &linksWalked) ++// followLinksCallback is called after we try to resolve each element. If the ++// path was not found, cr is nil. ++type followLinksCallback func(path string, cr *CacheRecord) error ++ ++// getFollowLinks is shorthand for getFollowLinksCallback(..., nil). ++func getFollowLinks(root *iradix.Node, k []byte, followTrailing bool) ([]byte, *CacheRecord, error) { ++ return getFollowLinksCallback(root, k, followTrailing, nil) + } + +-func getFollowLinksWalk(root *iradix.Node, k []byte, follow bool, linksWalked *int) ([]byte, *CacheRecord, error) { ++// getFollowLinksCallback looks up the requested key, fully resolving any ++// symlink components encountered. The implementation is heavily based on ++// . ++// ++// followTrailing indicates whether the *final component* of the path should be ++// resolved (effectively O_PATH|O_NOFOLLOW). Note that (in contrast to some ++// Linux APIs), followTrailing is obeyed even if the key has a trailing slash ++// (though paths like "foo/link/." will cause the link to be resolved). ++// ++// cb is a callback that is called for each path component encountered during ++// path resolution (after the path component is looked up in the cache). This ++// means for a path like /a/b/c, the callback will be called for at least ++// ++// {/, /a, /a/b, /a/b/c} ++// ++// Note that if any of the components are symlinks, the paths will depend on ++// the symlink contents and there will be more callbacks. If the requested key ++// has a trailing slash, the callback will also be called for the final ++// trailing-slash lookup (/a/b/c/ in the above example). Note that ++// getFollowLinksCallback will try to look up the original key directly first ++// and the callback is not called for this first lookup. ++func getFollowLinksCallback(root *iradix.Node, k []byte, followTrailing bool, cb followLinksCallback) ([]byte, *CacheRecord, error) { + v, ok := root.Get(k) +- if ok { ++ if ok && (!followTrailing || v.(*CacheRecord).Type != CacheRecordTypeSymlink) { + return k, v.(*CacheRecord), nil + } +- if !follow || len(k) == 0 { ++ if len(k) == 0 { + return k, nil, nil + } + +- dir, file := splitKey(k) ++ var ( ++ currentPath = "/" ++ remainingPath = convertKeyToPath(k) ++ linksWalked int ++ cr *CacheRecord ++ ) ++ // Trailing slashes are significant for the cache, but path.Clean strips ++ // them. We only care about the slash for the final lookup. ++ remainingPath, hadTrailingSlash := strings.CutSuffix(remainingPath, "/") ++ for remainingPath != "" { ++ // Get next component. ++ var part string ++ if i := strings.IndexRune(remainingPath, '/'); i == -1 { ++ part, remainingPath = remainingPath, "" ++ } else { ++ part, remainingPath = remainingPath[:i], remainingPath[i+1:] ++ } + +- k, parent, err := getFollowLinksWalk(root, dir, follow, linksWalked) +- if err != nil { +- return nil, nil, err +- } +- if parent != nil { +- if parent.Type == CacheRecordTypeSymlink { +- *linksWalked++ +- if *linksWalked > 255 { +- return nil, nil, errors.Errorf("too many links") ++ // Apply the component to the path. Since it is a single component, and ++ // our current path contains no symlinks, we can just apply it ++ // leixically. ++ nextPath := keyPath(path.Join("/", currentPath, part)) ++ // In contrast to rootPath, we don't skip lookups for no-op components ++ // or / because we need to call the callback for every path component ++ // we hit (including /) and we need to make sure that the CacheRecord ++ // we return is correct after every iteration. ++ ++ cr = nil ++ v, ok := root.Get(convertPathToKey(nextPath)) ++ if ok { ++ cr = v.(*CacheRecord) ++ } ++ if cb != nil { ++ if err := cb(nextPath, cr); err != nil { ++ return nil, nil, err + } ++ } ++ if !ok || cr.Type != CacheRecordTypeSymlink { ++ currentPath = nextPath ++ continue ++ } ++ if !followTrailing && remainingPath == "" { ++ currentPath = nextPath ++ break ++ } + +- link := cleanLink(string(convertKeyToPath(dir)), parent.Linkname) +- return getFollowLinksWalk(root, append(convertPathToKey([]byte(link)), file...), follow, linksWalked) ++ linksWalked++ ++ if linksWalked > maxSymlinkLimit { ++ return nil, nil, errTooManyLinks + } +- } +- k = append(k, file...) +- v, ok = root.Get(k) +- if ok { +- return k, v.(*CacheRecord), nil +- } +- return k, nil, nil +-} + +-func cleanLink(dir, linkname string) string { +- dirPath := path.Clean(dir) +- if dirPath == "." || dirPath == "/" { +- dirPath = "" ++ remainingPath = cr.Linkname + "/" + remainingPath ++ if path.IsAbs(cr.Linkname) { ++ currentPath = "/" ++ } + } +- link := path.Clean(linkname) +- if !path.IsAbs(link) { +- return path.Join("/", path.Join(path.Dir(dirPath), link)) ++ // We've already looked up the final component. However, if there was a ++ // trailing slash in the original path, we need to do the lookup again with ++ // the slash applied. ++ if hadTrailingSlash { ++ cr = nil ++ currentPath += "/" ++ v, ok := root.Get(convertPathToKey(currentPath)) ++ if ok { ++ cr = v.(*CacheRecord) ++ } ++ if cb != nil { ++ if err := cb(currentPath, cr); err != nil { ++ return nil, nil, err ++ } ++ } + } +- return link ++ return convertPathToKey(currentPath), cr, nil + } + + func prepareDigest(fp, p string, fi os.FileInfo) (digest.Digest, error) { +@@ -1174,25 +1248,10 @@ func poolsCopy(dst io.Writer, src io.Reader) (written int64, err error) { + return + } + +-func convertPathToKey(p []byte) []byte { ++func convertPathToKey(p string) []byte { + return bytes.Replace([]byte(p), []byte("/"), []byte{0}, -1) + } + +-func convertKeyToPath(p []byte) []byte { +- return bytes.Replace([]byte(p), []byte{0}, []byte("/"), -1) +-} +- +-func splitKey(k []byte) ([]byte, []byte) { +- foundBytes := false +- i := len(k) - 1 +- for { +- if i <= 0 || foundBytes && k[i] == 0 { +- break +- } +- if k[i] != 0 { +- foundBytes = true +- } +- i-- +- } +- return append([]byte{}, k[:i]...), k[i:] ++func convertKeyToPath(p []byte) string { ++ return string(bytes.Replace(p, []byte{0}, []byte("/"), -1)) + } +diff --git a/vendor/github.com/moby/buildkit/cache/contenthash/path.go b/vendor/github.com/moby/buildkit/cache/contenthash/path.go +index 42b7fd8349c7..ae950f713241 100644 +--- a/vendor/github.com/moby/buildkit/cache/contenthash/path.go ++++ b/vendor/github.com/moby/buildkit/cache/contenthash/path.go +@@ -1,108 +1,111 @@ ++// This code mostly comes from . ++ ++// Copyright (C) 2014-2015 Docker Inc & Go Authors. All rights reserved. ++// Copyright (C) 2017-2024 SUSE LLC. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ + package contenthash + + import ( + "os" + "path/filepath" ++ "strings" + + "github.com/pkg/errors" + ) + +-var ( +- errTooManyLinks = errors.New("too many links") +-) ++var errTooManyLinks = errors.New("too many links") ++ ++const maxSymlinkLimit = 255 + + type onSymlinkFunc func(string, string) error + +-// rootPath joins a path with a root, evaluating and bounding any +-// symlink to the root directory. +-// This is containerd/continuity/fs RootPath implementation with a callback on +-// resolving the symlink. +-func rootPath(root, path string, cb onSymlinkFunc) (string, error) { +- if path == "" { ++// rootPath joins a path with a root, evaluating and bounding any symlink to ++// the root directory. This is a slightly modified version of SecureJoin from ++// github.com/cyphar/filepath-securejoin, with a callback which we call after ++// each symlink resolution. ++func rootPath(root, unsafePath string, followTrailing bool, cb onSymlinkFunc) (string, error) { ++ if unsafePath == "" { + return root, nil + } +- var linksWalked int // to protect against cycles +- for { +- i := linksWalked +- newpath, err := walkLinks(root, path, &linksWalked, cb) +- if err != nil { +- return "", err +- } +- path = newpath +- if i == linksWalked { +- newpath = filepath.Join("/", newpath) +- if path == newpath { +- return filepath.Join(root, newpath), nil +- } +- path = newpath +- } +- } +-} + +-func walkLink(root, path string, linksWalked *int, cb onSymlinkFunc) (newpath string, islink bool, err error) { +- if *linksWalked > 255 { +- return "", false, errTooManyLinks +- } ++ unsafePath = filepath.FromSlash(unsafePath) ++ var ( ++ currentPath string ++ linksWalked int ++ ) ++ for unsafePath != "" { ++ // Windows-specific: remove any drive letters from the path. ++ if v := filepath.VolumeName(unsafePath); v != "" { ++ unsafePath = unsafePath[len(v):] ++ } + +- path = filepath.Join("/", path) +- if path == "/" { +- return path, false, nil +- } +- realPath := filepath.Join(root, path) ++ // Remove any unnecessary trailing slashes. ++ unsafePath = strings.TrimSuffix(unsafePath, string(filepath.Separator)) + +- fi, err := os.Lstat(realPath) +- if err != nil { +- // If path does not yet exist, treat as non-symlink +- if errors.Is(err, os.ErrNotExist) { +- return path, false, nil ++ // Get the next path component. ++ var part string ++ if i := strings.IndexRune(unsafePath, filepath.Separator); i == -1 { ++ part, unsafePath = unsafePath, "" ++ } else { ++ part, unsafePath = unsafePath[:i], unsafePath[i+1:] + } +- return "", false, err +- } +- if fi.Mode()&os.ModeSymlink == 0 { +- return path, false, nil +- } +- newpath, err = os.Readlink(realPath) +- if err != nil { +- return "", false, err +- } +- if cb != nil { +- if err := cb(path, newpath); err != nil { +- return "", false, err +- } +- } +- *linksWalked++ +- return newpath, true, nil +-} + +-func walkLinks(root, path string, linksWalked *int, cb onSymlinkFunc) (string, error) { +- switch dir, file := filepath.Split(path); { +- case dir == "": +- newpath, _, err := walkLink(root, file, linksWalked, cb) +- return newpath, err +- case file == "": +- if os.IsPathSeparator(dir[len(dir)-1]) { +- if dir == "/" { +- return dir, nil +- } +- return walkLinks(root, dir[:len(dir)-1], linksWalked, cb) ++ // Apply the component lexically to the path we are building. path does ++ // not contain any symlinks, and we are lexically dealing with a single ++ // component, so it's okay to do filepath.Clean here. ++ nextPath := filepath.Join(string(filepath.Separator), currentPath, part) ++ if nextPath == string(filepath.Separator) { ++ // If we end up back at the root, we don't need to re-evaluate /. ++ currentPath = "" ++ continue + } +- newpath, _, err := walkLink(root, dir, linksWalked, cb) +- return newpath, err +- default: +- newdir, err := walkLinks(root, dir, linksWalked, cb) +- if err != nil { ++ fullPath := root + string(filepath.Separator) + nextPath ++ ++ // Figure out whether the path is a symlink. ++ fi, err := os.Lstat(fullPath) ++ if err != nil && !errors.Is(err, os.ErrNotExist) { + return "", err + } +- newpath, islink, err := walkLink(root, filepath.Join(newdir, file), linksWalked, cb) ++ // Treat non-existent path components the same as non-symlinks (we ++ // can't do any better here). ++ if errors.Is(err, os.ErrNotExist) || fi.Mode()&os.ModeSymlink == 0 { ++ currentPath = nextPath ++ continue ++ } ++ // Don't resolve the final component with !followTrailing. ++ if !followTrailing && unsafePath == "" { ++ currentPath = nextPath ++ break ++ } ++ ++ // It's a symlink, so get its contents and expand it by prepending it ++ // to the yet-unparsed path. ++ linksWalked++ ++ if linksWalked > maxSymlinkLimit { ++ return "", errTooManyLinks ++ } ++ ++ dest, err := os.Readlink(fullPath) + if err != nil { + return "", err + } +- if !islink { +- return newpath, nil ++ if cb != nil { ++ if err := cb(nextPath, dest); err != nil { ++ return "", err ++ } + } +- if filepath.IsAbs(newpath) { +- return newpath, nil ++ ++ unsafePath = dest + string(filepath.Separator) + unsafePath ++ // Absolute symlinks reset any work we've already done. ++ if filepath.IsAbs(dest) { ++ currentPath = "" + } +- return filepath.Join(newdir, newpath), nil + } ++ ++ // There should be no lexical components left in path here, but just for ++ // safety do a filepath.Clean before the join. ++ finalPath := filepath.Join(string(filepath.Separator), currentPath) ++ return filepath.Join(root, finalPath), nil + } +diff --git a/vendor/modules.txt b/vendor/modules.txt +index 2a3b597c5858..335c85392288 100644 +--- a/vendor/modules.txt ++++ b/vendor/modules.txt +@@ -577,7 +577,7 @@ github.com/mistifyio/go-zfs/v3 + # github.com/mitchellh/hashstructure/v2 v2.0.2 + ## explicit; go 1.14 + github.com/mitchellh/hashstructure/v2 +-# github.com/moby/buildkit v0.11.7-0.20240124010513-435cb77e369c => github.com/cyphar/buildkit v0.0.0-20240814025459-5d3afed3f7b4 ++# github.com/moby/buildkit v0.11.7-0.20240124010513-435cb77e369c => github.com/cyphar/buildkit v0.0.0-20240814030244-ea1ca9670261 + ## explicit; go 1.18 + github.com/moby/buildkit/api/services/control + github.com/moby/buildkit/api/types +@@ -1313,4 +1313,4 @@ k8s.io/klog/v2/internal/severity + # resenje.org/singleflight v0.3.0 + ## explicit; go 1.18 + resenje.org/singleflight +-# github.com/moby/buildkit => github.com/cyphar/buildkit v0.0.0-20240814025459-5d3afed3f7b4 ++# github.com/moby/buildkit => github.com/cyphar/buildkit v0.0.0-20240814030244-ea1ca9670261 +-- +2.47.0 + diff --git a/0008-bsc1214855-volume-use-AtomicWriteFile-to-save-volume.patch b/0008-bsc1214855-volume-use-AtomicWriteFile-to-save-volume.patch new file mode 100644 index 0000000..4ee4b9c --- /dev/null +++ b/0008-bsc1214855-volume-use-AtomicWriteFile-to-save-volume.patch @@ -0,0 +1,53 @@ +From b6213c77313f15ac74a551b9a03670fce06280fb Mon Sep 17 00:00:00 2001 +From: Aleksa Sarai +Date: Wed, 19 Jun 2024 16:30:49 +1000 +Subject: [PATCH 08/13] bsc1214855: volume: use AtomicWriteFile to save volume + options + +If the system (or Docker) crashes while saivng the volume options, on +restart the daemon will error out when trying to read the options file +because it doesn't contain valid JSON. + +In such a crash scenario, the new volume will be treated as though it +has the default options configuration. This is not ideal, but volumes +created on very old Docker versions (pre-1.11[1], circa 2016) do not +have opts.json and so doing some kind of cleanup when loading the volume +store (even if we take care to only delete empty volumes) could delete +existing volumes carried over from very old Docker versions that users +would not expect to disappear. + +Ultimately, if a user creates a volume and the system crashes, a volume +that has the wrong config is better than Docker not being able to start. + +[1]: commit b05b2370757d ("Support mount opts for `local` volume driver") + +SUSE-Bugs: https://bugzilla.suse.com/show_bug.cgi?id=1214855 +Signed-off-by: Aleksa Sarai +--- + volume/local/local.go | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/volume/local/local.go b/volume/local/local.go +index b4f3a3669a84..077b26f1b813 100644 +--- a/volume/local/local.go ++++ b/volume/local/local.go +@@ -16,6 +16,7 @@ import ( + "github.com/docker/docker/daemon/names" + "github.com/docker/docker/errdefs" + "github.com/docker/docker/pkg/idtools" ++ "github.com/docker/docker/pkg/ioutils" + "github.com/docker/docker/quota" + "github.com/docker/docker/volume" + "github.com/pkg/errors" +@@ -381,7 +382,7 @@ func (v *localVolume) saveOpts() error { + if err != nil { + return err + } +- err = os.WriteFile(filepath.Join(v.rootPath, "opts.json"), b, 0600) ++ err = ioutils.AtomicWriteFile(filepath.Join(v.rootPath, "opts.json"), b, 0o600) + if err != nil { + return errdefs.System(errors.Wrap(err, "error while persisting volume options")) + } +-- +2.47.0 + diff --git a/0009-CVE-2024-41110-AuthZ-plugin-securty-fixes.patch b/0009-CVE-2024-41110-AuthZ-plugin-securty-fixes.patch new file mode 100644 index 0000000..9fd13be --- /dev/null +++ b/0009-CVE-2024-41110-AuthZ-plugin-securty-fixes.patch @@ -0,0 +1,209 @@ +From 989f5ae4dea1619b7e1d7ec7f9cac8d64b3a2209 Mon Sep 17 00:00:00 2001 +From: Jameson Hyde +Date: Mon, 26 Nov 2018 14:15:22 -0500 +Subject: [PATCH 09/13] CVE-2024-41110: AuthZ plugin securty fixes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is a backport of the following upstream patches: + + * 2ac8a479c53d ("Authz plugin security fixes for 0-length content and path validation") + * 5282cb25d09d ("If url includes scheme, urlPath will drop hostname, which would not match the auth check") + +Signed-off-by: Jameson Hyde +Signed-off-by: Paweł Gronowski +Signed-off-by: Aleksa Sarai +--- + pkg/authorization/authz.go | 38 +++++++++++-- + pkg/authorization/authz_unix_test.go | 84 +++++++++++++++++++++++++++- + 2 files changed, 115 insertions(+), 7 deletions(-) + +diff --git a/pkg/authorization/authz.go b/pkg/authorization/authz.go +index 590ac8dddd88..68ed8bbdaf97 100644 +--- a/pkg/authorization/authz.go ++++ b/pkg/authorization/authz.go +@@ -7,6 +7,8 @@ import ( + "io" + "mime" + "net/http" ++ "net/url" ++ "regexp" + "strings" + + "github.com/docker/docker/pkg/ioutils" +@@ -52,10 +54,23 @@ type Ctx struct { + authReq *Request + } + ++func isChunked(r *http.Request) bool { ++ // RFC 7230 specifies that content length is to be ignored if Transfer-Encoding is chunked ++ if strings.EqualFold(r.Header.Get("Transfer-Encoding"), "chunked") { ++ return true ++ } ++ for _, v := range r.TransferEncoding { ++ if strings.EqualFold(v, "chunked") { ++ return true ++ } ++ } ++ return false ++} ++ + // AuthZRequest authorized the request to the docker daemon using authZ plugins + func (ctx *Ctx) AuthZRequest(w http.ResponseWriter, r *http.Request) error { + var body []byte +- if sendBody(ctx.requestURI, r.Header) && r.ContentLength > 0 && r.ContentLength < maxBodySize { ++ if sendBody(ctx.requestURI, r.Header) && (r.ContentLength > 0 || isChunked(r)) && r.ContentLength < maxBodySize { + var err error + body, r.Body, err = drainBody(r.Body) + if err != nil { +@@ -108,7 +123,6 @@ func (ctx *Ctx) AuthZResponse(rm ResponseModifier, r *http.Request) error { + if sendBody(ctx.requestURI, rm.Header()) { + ctx.authReq.ResponseBody = rm.RawBody() + } +- + for _, plugin := range ctx.plugins { + logrus.Debugf("AuthZ response using plugin %s", plugin.Name()) + +@@ -146,10 +160,26 @@ func drainBody(body io.ReadCloser) ([]byte, io.ReadCloser, error) { + return nil, newBody, err + } + ++func isAuthEndpoint(urlPath string) (bool, error) { ++ // eg www.test.com/v1.24/auth/optional?optional1=something&optional2=something (version optional) ++ matched, err := regexp.MatchString(`^[^\/]*\/(v\d[\d\.]*\/)?auth.*`, urlPath) ++ if err != nil { ++ return false, err ++ } ++ return matched, nil ++} ++ + // sendBody returns true when request/response body should be sent to AuthZPlugin +-func sendBody(url string, header http.Header) bool { ++func sendBody(inURL string, header http.Header) bool { ++ u, err := url.Parse(inURL) ++ // Assume no if the URL cannot be parsed - an empty request will still be forwarded to the plugin and should be rejected ++ if err != nil { ++ return false ++ } ++ + // Skip body for auth endpoint +- if strings.HasSuffix(url, "/auth") { ++ isAuth, err := isAuthEndpoint(u.Path) ++ if isAuth || err != nil { + return false + } + +diff --git a/pkg/authorization/authz_unix_test.go b/pkg/authorization/authz_unix_test.go +index 835cb703839b..8bfe44e1a840 100644 +--- a/pkg/authorization/authz_unix_test.go ++++ b/pkg/authorization/authz_unix_test.go +@@ -175,8 +175,8 @@ func TestDrainBody(t *testing.T) { + + func TestSendBody(t *testing.T) { + var ( +- url = "nothing.com" + testcases = []struct { ++ url string + contentType string + expected bool + }{ +@@ -220,15 +220,93 @@ func TestSendBody(t *testing.T) { + contentType: "", + expected: false, + }, ++ { ++ url: "nothing.com/auth", ++ contentType: "", ++ expected: false, ++ }, ++ { ++ url: "nothing.com/auth", ++ contentType: "application/json;charset=UTF8", ++ expected: false, ++ }, ++ { ++ url: "nothing.com/auth?p1=test", ++ contentType: "application/json;charset=UTF8", ++ expected: false, ++ }, ++ { ++ url: "nothing.com/test?p1=/auth", ++ contentType: "application/json;charset=UTF8", ++ expected: true, ++ }, ++ { ++ url: "nothing.com/something/auth", ++ contentType: "application/json;charset=UTF8", ++ expected: true, ++ }, ++ { ++ url: "nothing.com/auth/test", ++ contentType: "application/json;charset=UTF8", ++ expected: false, ++ }, ++ { ++ url: "nothing.com/v1.24/auth/test", ++ contentType: "application/json;charset=UTF8", ++ expected: false, ++ }, ++ { ++ url: "nothing.com/v1/auth/test", ++ contentType: "application/json;charset=UTF8", ++ expected: false, ++ }, ++ { ++ url: "www.nothing.com/v1.24/auth/test", ++ contentType: "application/json;charset=UTF8", ++ expected: false, ++ }, ++ { ++ url: "https://www.nothing.com/v1.24/auth/test", ++ contentType: "application/json;charset=UTF8", ++ expected: false, ++ }, ++ { ++ url: "http://nothing.com/v1.24/auth/test", ++ contentType: "application/json;charset=UTF8", ++ expected: false, ++ }, ++ { ++ url: "www.nothing.com/test?p1=/auth", ++ contentType: "application/json;charset=UTF8", ++ expected: true, ++ }, ++ { ++ url: "http://www.nothing.com/test?p1=/auth", ++ contentType: "application/json;charset=UTF8", ++ expected: true, ++ }, ++ { ++ url: "www.nothing.com/something/auth", ++ contentType: "application/json;charset=UTF8", ++ expected: true, ++ }, ++ { ++ url: "https://www.nothing.com/something/auth", ++ contentType: "application/json;charset=UTF8", ++ expected: true, ++ }, + } + ) + + for _, testcase := range testcases { + header := http.Header{} + header.Set("Content-Type", testcase.contentType) ++ if testcase.url == "" { ++ testcase.url = "nothing.com" ++ } + +- if b := sendBody(url, header); b != testcase.expected { +- t.Fatalf("Unexpected Content-Type; Expected: %t, Actual: %t", testcase.expected, b) ++ if b := sendBody(testcase.url, header); b != testcase.expected { ++ t.Fatalf("sendBody failed: url: %s, content-type: %s; Expected: %t, Actual: %t", testcase.url, testcase.contentType, testcase.expected, b) + } + } + } +-- +2.47.0 + diff --git a/0010-TESTS-backport-fixes-for-integration-tests.patch b/0010-TESTS-backport-fixes-for-integration-tests.patch new file mode 100644 index 0000000..601888f --- /dev/null +++ b/0010-TESTS-backport-fixes-for-integration-tests.patch @@ -0,0 +1,65 @@ +From 971d5a3b8431c9263060b12c6b131ebb8158a389 Mon Sep 17 00:00:00 2001 +From: Aleksa Sarai +Date: Thu, 21 Nov 2024 20:00:07 +1100 +Subject: [PATCH 10/10] TESTS: backport fixes for integration tests + +We need a couple of patches to make the tests work on SLES: + + * 143b3b2ef3d0 ("test: update registry version to latest") + * 1a453abfb172 ("integration-cli: don't skip AppArmor tests on SLES") + +Signed-off-by: Aleksa Sarai +--- + Dockerfile | 2 +- + integration-cli/requirements_test.go | 3 --- + testutil/registry/registry.go | 4 +++- + 3 files changed, 4 insertions(+), 5 deletions(-) + +diff --git a/Dockerfile b/Dockerfile +index 463d5cfc1a86..7a23962af09b 100644 +--- a/Dockerfile ++++ b/Dockerfile +@@ -59,7 +59,7 @@ WORKDIR /go/src/github.com/docker/distribution + # from the https://github.com/docker/distribution repository. This version of + # the registry is used to test both schema 1 and schema 2 manifests. Generally, + # the version specified here should match a current release. +-ARG REGISTRY_VERSION=v2.3.0 ++ARG REGISTRY_VERSION=v2.8.2 + # REGISTRY_VERSION_SCHEMA1 specifies the version of the registry to build and + # install from the https://github.com/docker/distribution repository. This is + # an older (pre v2.3.0) version of the registry that only supports schema1 +diff --git a/integration-cli/requirements_test.go b/integration-cli/requirements_test.go +index 2313272d7704..e5f72397e1bc 100644 +--- a/integration-cli/requirements_test.go ++++ b/integration-cli/requirements_test.go +@@ -85,9 +85,6 @@ func Network() bool { + } + + func Apparmor() bool { +- if strings.HasPrefix(testEnv.DaemonInfo.OperatingSystem, "SUSE Linux Enterprise Server ") { +- return false +- } + buf, err := os.ReadFile("/sys/module/apparmor/parameters/enabled") + return err == nil && len(buf) > 1 && buf[0] == 'Y' + } +diff --git a/testutil/registry/registry.go b/testutil/registry/registry.go +index 9213db2ba21a..d8bfe17678a4 100644 +--- a/testutil/registry/registry.go ++++ b/testutil/registry/registry.go +@@ -107,10 +107,12 @@ http: + } + + binary := V2binary ++ args := []string{"serve", confPath} + if c.schema1 { + binary = V2binarySchema1 ++ args = []string{confPath} + } +- cmd := exec.Command(binary, confPath) ++ cmd := exec.Command(binary, args...) + cmd.Stdout = c.stdout + cmd.Stderr = c.stderr + if err := cmd.Start(); err != nil { +-- +2.47.1 + diff --git a/80-docker.rules b/80-docker.rules new file mode 100644 index 0000000..a3dac1c --- /dev/null +++ b/80-docker.rules @@ -0,0 +1,5 @@ +# hide docker's loopback devices from udisks, and thus from user desktops +SUBSYSTEM=="block", ENV{DM_NAME}=="docker-*", ENV{UDISKS_PRESENTATION_HIDE}="1", ENV{UDISKS_IGNORE}="1" +SUBSYSTEM=="block", DEVPATH=="/devices/virtual/block/loop*", ATTR{loop/backing_file}=="/var/lib/docker/*", ENV{UDISKS_PRESENTATION_HIDE}="1", ENV{UDISKS_IGNORE}="1" + + diff --git a/README_SUSE.md b/README_SUSE.md new file mode 100644 index 0000000..fb0ee48 --- /dev/null +++ b/README_SUSE.md @@ -0,0 +1,230 @@ +# Abstract + +Docker is a lightweight "virtualization" method to run multiple virtual units +(containers, akin to “chroot”) simultaneously on a single control host. +Containers are isolated with Kernel Control Groups (cgroups) and Kernel Namespaces. + +Docker provides an operating system-level virtualization where the Kernel +controls the isolated containers. With other full virtualization solutions +like Xen, KVM, or libvirt the processor simulates a complete hardware +environment and controls its virtual machines. + +# Terminology + +## chroot + +A change root (chroot, or change root jail) is a section in the file system +which is isolated from the rest of the file system. For this purpose, the chroot +command is used to change the root of the file system. A program which is +executed in such a “chroot jail” cannot access files outside the designated +directory tree. + +## cgroups + +Kernel Control Groups (commonly referred to as just “cgroups”) are a Kernel +feature that allows aggregating or partitioning tasks (processes) and all their +children into hierarchical organized groups to isolate resources. + +## Image + +A "virtual machine" on the host server that can run any Linux system, for +example openSUSE, SUSE Linux Enterprise Desktop, or SUSE Linux Enterprise Server. + +A Docker image is made by a series of layers built one over the other. Each layer +corresponds to a permanent change committed from a container to the image. + +For more details checkout [Docker's official documentation](http://docs.docker.com/terms/image/). + +## Image Name + +A name that refers to an image. The name is used by the docker commands. + +## Container + +A running Docker Image. + +## Container ID + +A ID that refers to a container. The ID is used by the docker commands. + +## TAG + +A string associated to a Image. It commonly used to identify a specific version +of a Image (like tags in version control systems). It is also possible to refer +the same Image with different TAGs. + +## Kernel Namespaces + +A Kernel feature to isolate some resources like network, users, and others for +a group of processes. + +## Docker Host Server + +The system that runs the Docker daemon, provides the images, and the management +control capabilities through cgroups. + + +# Overview + +Docker is a platform that allows developers and sysadmins to manage the complete +lifecycle of images. + +Docker makes incredibly easy to build, ship and run images containing +applications. + +Benefits of Docker: + + * Isolating applications and operating systems through containers. + * Providing nearly native performance as Docker manages allocation of resources + in real-time. + * Controlling network interfaces and applying resources inside containers through cgroups. + * Versioning of images. + * Building images based on existing ones. + * Sharining/storing on [public](http://docs.docker.com/docker-hub/) or + [private](http://docs.docker.com/userguide/dockerrepos/#private-repositories) + repositories. + +Limitations of Docker: + + * All Docker containers are running inside the host system's Kernel and not with + a different Kernel. + * Only allows Linux "guest" operating systems. + * Docker is not a full virtualization stack like Xen, KVM, or libvirt. + * Security depends on the host system. Refer to the [official documentation](http://docs.docker.com/articles/security/) + for more details. + +## Container drivers + +Docker has different backend drivers to handle the containers. The recommended +on is [libcontainer](https://github.com/docker/libcontainer), which is also the +default choice. This driver provides direct access with cgroups. + +The Docker packages ships also a LXC driver which handles containers using the +LXC tools. + +At the time of writing, upstream is working on a `libvirt-lxc` driver. + +## Storage drivers + +Docker supports different storage drivers: + + * `vfs`: this driver is automatically used when the Docker host filesystem + does not support copy-on-write. This is a simple driver which does not offer + some of the advantages of Docker (like sharing layers, more on that in the + next sections). It is highly reliable but also slow. + * `devicemapper`: this driver relies on the device-mapper thin provisioning + module. It supports copy-on-write, hence it offers all the advantages of + Docker. + * `btrfs`: this driver relies on Btrfs to provide all the features required + by Docker. To use this driver the `/var/lib/docker` directory must be on a + btrfs filesystem. + * `AUFS`: this driver relies on AUFS union filesystem. Neither the upstream + kernel nor the SUSE one supports this filesystem. Hence the AUFS driver is + not built into the SUSE Docker package. + +It is possible to specify which driver to use by changing the value of the +`DOCKER_OPTS` variable defined inside of the `/etc/sysconfig/docker` file. +This can be done either manually or using &yast; by browsing to: + * System + * /etc/sysconfig Editor + * System + * Management + * DOCKER_OPTS +menu and entering the `-s storage_driver` string. + +For example, to force the usage of the `devicemapper` driver +enter the following text: +``` +DOCKER_OPTS="-s devicemapper +``` + +It is recommended to have `/var/lib/docker` mounted on a different filesystem +to not affect the Docker host OS in case of a filesystem corruption. + +# Setting up a Docker host + +Prepare the host: + + 1. Install the `docker` package. + 2. Automatically start the Docker daemon at boot: + `sudo systemctl enable docker` + 3. Start the Docker daemon: + `sudo systemctl start docker` + +The Docker daemon listens on a local socket which is accessible only by the `root` +user and by the members of the `docker` group. + +The `docker` group is automatically created at package installation time. To +allow a certain user to connect to the local Docker daemon use the following +command: + +``` +sudo /usr/sbin/usermod -aG docker +``` + +The user will be able to communicate with the local Docker daemon upon his next +login. + +## Networking + +If you want your containers to be able to access the external network you must +enable the `net.ipv4.ip_forward` rule. +This can be done using YaST by browsing to the +`Network Devices -> Network Settings -> Routing` menu and ensuring that the +`Enable IPv4 Forwarding` box is checked. + +This option cannot be changed when networking is handled by the Network Manager. +In such cases the `/etc/sysconfig/SuSEfirewall2` file needs to be edited by +hand to ensure the `FW_ROUTE` flag is set to `yes` like so: + +``` + FW_ROUTE="yes" +``` + + +# Basic Docker operations + +Images can be pulled from [Docker's central index](http://index.docker.io) using +the following command: + +``` +docker pull +``` + +Containers can be started using the `docker run` command. + +Please refer to the [official documentation](http://docs.docker.com/) +for more details. + + +# Building Docker containers using KIWI + +Starting from version 5.06.8 KIWI can be used to build Docker images. +Please refer to KIWI's [official documentation](https://doc.opensuse.org/projects/kiwi/doc/#chap.lxc). +The official `kiwi-doc` package contains examples of Docker images. + +## Docker build system versus KIWI + +Docker has an [internal build system](http://docs.docker.com/reference/builder/) +which makes incredibly easy to create new images based on existing ones. + +Some users might be confused about what to use. The right approach is to build +the [base images](http://docs.docker.com/terms/image/#base-image-def) using KIWI +and then use them as foundation blocks inside of your Docker's build system. + +That two advantages: + + 1. Be able to use docker specific directives (like `ENTRYPOINT`, `EXPOSE`, ...). + 2. Be able to reuse already existing layers. + +Sharing the common layers between different images makes possible to: + + * Use less disk space on the Docker hosts. + * Make the deployments faster: only the requested layers are sent over the + network (it is like upgrading installed packages using delta rpms). + * Take full advantage of caching while building Docker images: this will result + in faster executions of `docker build` command. + +To recap: KIWI is not to be intended as a replacement for Docker's build system. +It rather complements with it. + diff --git a/_service b/_service new file mode 100644 index 0000000..31cb32d --- /dev/null +++ b/_service @@ -0,0 +1,30 @@ + + + https://github.com/moby/moby.git + git + .git + 24.0.9_ce_%h + v24.0.9 + docker + + + https://github.com/docker/cli.git + git + .git + 24.0.9_ce + v24.0.9 + docker-cli + + + https://github.com/docker/buildx.git + git + .git + 0.19.3 + v0.19.3 + docker-buildx + + + docker-*.tar + xz + + diff --git a/cli-0001-docs-include-required-tools-in-source-tree.patch b/cli-0001-docs-include-required-tools-in-source-tree.patch new file mode 100644 index 0000000..4f4d347 --- /dev/null +++ b/cli-0001-docs-include-required-tools-in-source-tree.patch @@ -0,0 +1,31967 @@ +From 293803c69c7de3f223a2c86d46f887658ab4c3b3 Mon Sep 17 00:00:00 2001 +From: Aleksa Sarai +Date: Wed, 26 Apr 2023 10:13:48 +1000 +Subject: [PATCH] docs: include required tools in source tree + +In order to be able to build the documentation without internet access +(as is required by some distribution build systems), all of the source +code needed for the build needs to be available in the source tarball. + +This used to be possible with the docker-cli sources but was +accidentally broken with some CI changes that switched to downloading +the tools (by modifying go.mod as part of the docs build script). + +This pattern also maked documentation builds less reproducible since the +tool version used was not based on the source code version. + +Fixes: commit 7dc35c03fca5 ("validate manpages target") +Fixes: commit a650f4ddd008 ("switch to cli-docs-tool for yaml docs generation") +Signed-off-by: Aleksa Sarai +--- + docs/generate/go.mod | 13 - + docs/generate/tools.go | 8 - + import.go | 17 + + man/tools.go | 11 - + scripts/docs/generate-man.sh | 33 +- + scripts/docs/generate-md.sh | 27 +- + scripts/docs/generate-yaml.sh | 29 +- + vendor.mod | 13 +- + vendor.sum | 46 +- + vendor/github.com/cespare/xxhash/v2/README.md | 31 +- + .../github.com/cespare/xxhash/v2/testall.sh | 10 + + vendor/github.com/cespare/xxhash/v2/xxhash.go | 47 +- + .../cespare/xxhash/v2/xxhash_amd64.s | 336 +- + .../cespare/xxhash/v2/xxhash_arm64.s | 183 + + .../v2/{xxhash_amd64.go => xxhash_asm.go} | 2 + + .../cespare/xxhash/v2/xxhash_other.go | 22 +- + .../cespare/xxhash/v2/xxhash_safe.go | 1 + + .../cespare/xxhash/v2/xxhash_unsafe.go | 3 +- + .../cpuguy83/go-md2man/v2/.gitignore | 2 + + .../cpuguy83/go-md2man/v2/.golangci.yml | 6 + + .../cpuguy83/go-md2man/v2/Dockerfile | 20 + + .../cpuguy83/go-md2man/v2/LICENSE.md | 21 + + .../github.com/cpuguy83/go-md2man/v2/Makefile | 35 + + .../cpuguy83/go-md2man/v2/README.md | 15 + + .../cpuguy83/go-md2man/v2/go-md2man.1.md | 28 + + .../cpuguy83/go-md2man/v2/md2man.go | 53 + + .../cpuguy83/go-md2man/v2/md2man/md2man.go | 16 + + .../cpuguy83/go-md2man/v2/md2man/roff.go | 348 ++ + .../docker/cli-docs-tool/.dockerignore | 2 + + .../docker/cli-docs-tool/.gitignore | 2 + + .../docker/cli-docs-tool/.golangci.yml | 37 + + .../docker/cli-docs-tool/Dockerfile | 86 + + .../github.com/docker/cli-docs-tool/LICENSE | 202 ++ + .../github.com/docker/cli-docs-tool/README.md | 67 + + .../cli-docs-tool/annotation/annotation.go | 25 + + .../docker/cli-docs-tool/clidocstool.go | 123 + + .../docker/cli-docs-tool/clidocstool_md.go | 280 ++ + .../docker/cli-docs-tool/clidocstool_yaml.go | 435 +++ + .../docker/cli-docs-tool/docker-bake.hcl | 51 + + .../docker/cli-docs-tool/markdown.go | 87 + + .../russross/blackfriday/v2/.gitignore | 8 + + .../russross/blackfriday/v2/.travis.yml | 17 + + .../russross/blackfriday/v2/LICENSE.txt | 29 + + .../russross/blackfriday/v2/README.md | 335 ++ + .../russross/blackfriday/v2/block.go | 1612 +++++++++ + .../github.com/russross/blackfriday/v2/doc.go | 46 + + .../russross/blackfriday/v2/entities.go | 2236 ++++++++++++ + .../github.com/russross/blackfriday/v2/esc.go | 70 + + .../russross/blackfriday/v2/html.go | 952 ++++++ + .../russross/blackfriday/v2/inline.go | 1228 +++++++ + .../russross/blackfriday/v2/markdown.go | 950 ++++++ + .../russross/blackfriday/v2/node.go | 360 ++ + .../russross/blackfriday/v2/smartypants.go | 457 +++ + vendor/github.com/spf13/cobra/doc/README.md | 17 + + vendor/github.com/spf13/cobra/doc/man_docs.go | 246 ++ + vendor/github.com/spf13/cobra/doc/man_docs.md | 31 + + vendor/github.com/spf13/cobra/doc/md_docs.go | 156 + + vendor/github.com/spf13/cobra/doc/md_docs.md | 115 + + .../github.com/spf13/cobra/doc/rest_docs.go | 186 + + .../github.com/spf13/cobra/doc/rest_docs.md | 114 + + vendor/github.com/spf13/cobra/doc/util.go | 52 + + .../github.com/spf13/cobra/doc/yaml_docs.go | 175 + + .../github.com/spf13/cobra/doc/yaml_docs.md | 112 + + .../googleapis/rpc/status/status.pb.go | 10 +- + .../grpc/attributes/attributes.go | 2 +- + vendor/google.golang.org/grpc/backoff.go | 2 +- + .../grpc/balancer/balancer.go | 31 + + .../grpc/balancer/base/balancer.go | 4 +- + .../grpc/balancer/conn_state_evaluator.go | 12 +- + .../grpc/balancer_conn_wrappers.go | 71 +- + .../grpc_binarylog_v1/binarylog.pb.go | 20 +- + .../grpc/channelz/channelz.go | 2 +- + vendor/google.golang.org/grpc/clientconn.go | 173 +- + .../grpc/credentials/credentials.go | 20 +- + .../google.golang.org/grpc/credentials/tls.go | 6 +- + vendor/google.golang.org/grpc/dialoptions.go | 25 +- + .../grpc/encoding/encoding.go | 7 +- + .../grpc/grpclog/loggerv2.go | 9 +- + .../grpc/internal/binarylog/env_config.go | 18 +- + .../grpc/internal/binarylog/method_logger.go | 128 +- + .../grpc/internal/binarylog/sink.go | 12 +- + .../grpc/internal/channelz/types.go | 16 +- + .../grpc/internal/envconfig/envconfig.go | 39 +- + .../grpc/internal/envconfig/xds.go | 31 +- + .../grpc/internal/grpclog/grpclog.go | 2 +- + .../grpc/internal/grpcsync/oncefunc.go | 32 + + .../grpc/internal/grpcutil/compressor.go | 47 + + .../grpc/internal/grpcutil/method.go | 1 - + .../grpc/internal/internal.go | 3 + + .../internal/resolver/dns/dns_resolver.go | 6 +- + .../resolver/passthrough/passthrough.go | 11 +- + .../grpc/internal/resolver/unix/unix.go | 4 +- + .../internal/serviceconfig/serviceconfig.go | 8 +- + .../grpc/internal/status/status.go | 10 + + .../grpc/internal/transport/controlbuf.go | 62 +- + .../grpc/internal/transport/defaults.go | 6 + + .../grpc/internal/transport/handler_server.go | 53 +- + .../grpc/internal/transport/http2_client.go | 261 +- + .../grpc/internal/transport/http2_server.go | 142 +- + .../grpc/internal/transport/transport.go | 16 +- + .../grpc/metadata/metadata.go | 20 +- + .../google.golang.org/grpc/picker_wrapper.go | 35 +- + vendor/google.golang.org/grpc/pickfirst.go | 6 +- + vendor/google.golang.org/grpc/preloader.go | 2 +- + vendor/google.golang.org/grpc/regenerate.sh | 7 +- + .../grpc/resolver/resolver.go | 36 +- + vendor/google.golang.org/grpc/rpc_util.go | 56 +- + vendor/google.golang.org/grpc/server.go | 79 +- + .../google.golang.org/grpc/service_config.go | 10 +- + .../grpc/serviceconfig/serviceconfig.go | 2 +- + .../google.golang.org/grpc/status/status.go | 12 +- + vendor/google.golang.org/grpc/stream.go | 62 +- + vendor/google.golang.org/grpc/tap/tap.go | 2 +- + vendor/google.golang.org/grpc/version.go | 2 +- + vendor/google.golang.org/grpc/vet.sh | 29 +- + .../protobuf/encoding/protojson/doc.go | 2 +- + .../encoding/protojson/well_known_types.go | 12 +- + .../protobuf/encoding/protowire/wire.go | 8 +- + .../protobuf/internal/encoding/json/decode.go | 2 +- + .../protobuf/internal/encoding/text/decode.go | 5 +- + .../internal/encoding/text/decode_number.go | 43 +- + .../protobuf/internal/genid/descriptor_gen.go | 90 +- + .../protobuf/internal/impl/convert.go | 1 - + .../protobuf/internal/strs/strings_unsafe.go | 2 +- + .../protobuf/internal/version/version.go | 4 +- + .../google.golang.org/protobuf/proto/doc.go | 9 +- + .../google.golang.org/protobuf/proto/equal.go | 172 +- + .../reflect/protoreflect/source_gen.go | 14 + + .../protobuf/reflect/protoreflect/value.go | 2 +- + .../reflect/protoreflect/value_equal.go | 168 + + .../reflect/protoreflect/value_union.go | 4 +- + .../reflect/protoregistry/registry.go | 2 +- + .../types/descriptorpb/descriptor.pb.go | 1547 +++++---- + .../protobuf/types/known/anypb/any.pb.go | 135 +- + .../types/known/durationpb/duration.pb.go | 63 +- + .../types/known/timestamppb/timestamp.pb.go | 61 +- + vendor/gopkg.in/yaml.v3/LICENSE | 50 + + vendor/gopkg.in/yaml.v3/NOTICE | 13 + + vendor/gopkg.in/yaml.v3/README.md | 150 + + vendor/gopkg.in/yaml.v3/apic.go | 747 ++++ + vendor/gopkg.in/yaml.v3/decode.go | 1000 ++++++ + vendor/gopkg.in/yaml.v3/emitterc.go | 2020 +++++++++++ + vendor/gopkg.in/yaml.v3/encode.go | 577 ++++ + vendor/gopkg.in/yaml.v3/parserc.go | 1258 +++++++ + vendor/gopkg.in/yaml.v3/readerc.go | 434 +++ + vendor/gopkg.in/yaml.v3/resolve.go | 326 ++ + vendor/gopkg.in/yaml.v3/scannerc.go | 3038 +++++++++++++++++ + vendor/gopkg.in/yaml.v3/sorter.go | 134 + + vendor/gopkg.in/yaml.v3/writerc.go | 48 + + vendor/gopkg.in/yaml.v3/yaml.go | 698 ++++ + vendor/gopkg.in/yaml.v3/yamlh.go | 807 +++++ + vendor/gopkg.in/yaml.v3/yamlprivateh.go | 198 ++ + vendor/modules.txt | 25 +- + 153 files changed, 25896 insertions(+), 1912 deletions(-) + delete mode 100644 docs/generate/go.mod + delete mode 100644 docs/generate/tools.go + create mode 100644 import.go + delete mode 100644 man/tools.go + create mode 100644 vendor/github.com/cespare/xxhash/v2/testall.sh + create mode 100644 vendor/github.com/cespare/xxhash/v2/xxhash_arm64.s + rename vendor/github.com/cespare/xxhash/v2/{xxhash_amd64.go => xxhash_asm.go} (73%) + create mode 100644 vendor/github.com/cpuguy83/go-md2man/v2/.gitignore + create mode 100644 vendor/github.com/cpuguy83/go-md2man/v2/.golangci.yml + create mode 100644 vendor/github.com/cpuguy83/go-md2man/v2/Dockerfile + create mode 100644 vendor/github.com/cpuguy83/go-md2man/v2/LICENSE.md + create mode 100644 vendor/github.com/cpuguy83/go-md2man/v2/Makefile + create mode 100644 vendor/github.com/cpuguy83/go-md2man/v2/README.md + create mode 100644 vendor/github.com/cpuguy83/go-md2man/v2/go-md2man.1.md + create mode 100644 vendor/github.com/cpuguy83/go-md2man/v2/md2man.go + create mode 100644 vendor/github.com/cpuguy83/go-md2man/v2/md2man/md2man.go + create mode 100644 vendor/github.com/cpuguy83/go-md2man/v2/md2man/roff.go + create mode 100644 vendor/github.com/docker/cli-docs-tool/.dockerignore + create mode 100644 vendor/github.com/docker/cli-docs-tool/.gitignore + create mode 100644 vendor/github.com/docker/cli-docs-tool/.golangci.yml + create mode 100644 vendor/github.com/docker/cli-docs-tool/Dockerfile + create mode 100644 vendor/github.com/docker/cli-docs-tool/LICENSE + create mode 100644 vendor/github.com/docker/cli-docs-tool/README.md + create mode 100644 vendor/github.com/docker/cli-docs-tool/annotation/annotation.go + create mode 100644 vendor/github.com/docker/cli-docs-tool/clidocstool.go + create mode 100644 vendor/github.com/docker/cli-docs-tool/clidocstool_md.go + create mode 100644 vendor/github.com/docker/cli-docs-tool/clidocstool_yaml.go + create mode 100644 vendor/github.com/docker/cli-docs-tool/docker-bake.hcl + create mode 100644 vendor/github.com/docker/cli-docs-tool/markdown.go + create mode 100644 vendor/github.com/russross/blackfriday/v2/.gitignore + create mode 100644 vendor/github.com/russross/blackfriday/v2/.travis.yml + create mode 100644 vendor/github.com/russross/blackfriday/v2/LICENSE.txt + create mode 100644 vendor/github.com/russross/blackfriday/v2/README.md + create mode 100644 vendor/github.com/russross/blackfriday/v2/block.go + create mode 100644 vendor/github.com/russross/blackfriday/v2/doc.go + create mode 100644 vendor/github.com/russross/blackfriday/v2/entities.go + create mode 100644 vendor/github.com/russross/blackfriday/v2/esc.go + create mode 100644 vendor/github.com/russross/blackfriday/v2/html.go + create mode 100644 vendor/github.com/russross/blackfriday/v2/inline.go + create mode 100644 vendor/github.com/russross/blackfriday/v2/markdown.go + create mode 100644 vendor/github.com/russross/blackfriday/v2/node.go + create mode 100644 vendor/github.com/russross/blackfriday/v2/smartypants.go + create mode 100644 vendor/github.com/spf13/cobra/doc/README.md + create mode 100644 vendor/github.com/spf13/cobra/doc/man_docs.go + create mode 100644 vendor/github.com/spf13/cobra/doc/man_docs.md + create mode 100644 vendor/github.com/spf13/cobra/doc/md_docs.go + create mode 100644 vendor/github.com/spf13/cobra/doc/md_docs.md + create mode 100644 vendor/github.com/spf13/cobra/doc/rest_docs.go + create mode 100644 vendor/github.com/spf13/cobra/doc/rest_docs.md + create mode 100644 vendor/github.com/spf13/cobra/doc/util.go + create mode 100644 vendor/github.com/spf13/cobra/doc/yaml_docs.go + create mode 100644 vendor/github.com/spf13/cobra/doc/yaml_docs.md + create mode 100644 vendor/google.golang.org/grpc/internal/grpcsync/oncefunc.go + create mode 100644 vendor/google.golang.org/grpc/internal/grpcutil/compressor.go + create mode 100644 vendor/google.golang.org/protobuf/reflect/protoreflect/value_equal.go + create mode 100644 vendor/gopkg.in/yaml.v3/LICENSE + create mode 100644 vendor/gopkg.in/yaml.v3/NOTICE + create mode 100644 vendor/gopkg.in/yaml.v3/README.md + create mode 100644 vendor/gopkg.in/yaml.v3/apic.go + create mode 100644 vendor/gopkg.in/yaml.v3/decode.go + create mode 100644 vendor/gopkg.in/yaml.v3/emitterc.go + create mode 100644 vendor/gopkg.in/yaml.v3/encode.go + create mode 100644 vendor/gopkg.in/yaml.v3/parserc.go + create mode 100644 vendor/gopkg.in/yaml.v3/readerc.go + create mode 100644 vendor/gopkg.in/yaml.v3/resolve.go + create mode 100644 vendor/gopkg.in/yaml.v3/scannerc.go + create mode 100644 vendor/gopkg.in/yaml.v3/sorter.go + create mode 100644 vendor/gopkg.in/yaml.v3/writerc.go + create mode 100644 vendor/gopkg.in/yaml.v3/yaml.go + create mode 100644 vendor/gopkg.in/yaml.v3/yamlh.go + create mode 100644 vendor/gopkg.in/yaml.v3/yamlprivateh.go + +diff --git a/docs/generate/go.mod b/docs/generate/go.mod +deleted file mode 100644 +index d62ff455713a..000000000000 +--- a/docs/generate/go.mod ++++ /dev/null +@@ -1,13 +0,0 @@ +-module github.com/docker/cli/docs/generate +- +-// dummy go.mod to avoid dealing with dependencies specific +-// to docs generation and not really part of the project. +- +-go 1.16 +- +-//require ( +-// github.com/docker/cli v0.0.0+incompatible +-// github.com/docker/cli-docs-tool v0.5.0 +-//) +-// +-//replace github.com/docker/cli v0.0.0+incompatible => ../../ +diff --git a/docs/generate/tools.go b/docs/generate/tools.go +deleted file mode 100644 +index 47510bc49a89..000000000000 +--- a/docs/generate/tools.go ++++ /dev/null +@@ -1,8 +0,0 @@ +-//go:build tools +-// +build tools +- +-package main +- +-import ( +- _ "github.com/docker/cli-docs-tool" +-) +diff --git a/import.go b/import.go +new file mode 100644 +index 000000000000..662a6055146c +--- /dev/null ++++ b/import.go +@@ -0,0 +1,17 @@ ++// This is only used to define imports we need for doc generation. ++ ++//go:build never ++// +build never ++ ++package cli ++ ++import ( ++ // Used for md and yaml doc generation. ++ _ "github.com/docker/cli-docs-tool" ++ ++ // Used for man page generation. ++ _ "github.com/cpuguy83/go-md2man/v2" ++ _ "github.com/spf13/cobra" ++ _ "github.com/spf13/cobra/doc" ++ _ "github.com/spf13/pflag" ++) +diff --git a/man/tools.go b/man/tools.go +deleted file mode 100644 +index 3cafe6533aff..000000000000 +--- a/man/tools.go ++++ /dev/null +@@ -1,11 +0,0 @@ +-//go:build tools +-// +build tools +- +-package main +- +-import ( +- _ "github.com/cpuguy83/go-md2man/v2" +- _ "github.com/spf13/cobra" +- _ "github.com/spf13/cobra/doc" +- _ "github.com/spf13/pflag" +-) +diff --git a/scripts/docs/generate-man.sh b/scripts/docs/generate-man.sh +index 12a4b81199db..1e12a95e9c9a 100755 +--- a/scripts/docs/generate-man.sh ++++ b/scripts/docs/generate-man.sh +@@ -1,35 +1,22 @@ + #!/usr/bin/env bash + +-set -eu +- +-: "${MD2MAN_VERSION=v2.0.3}" ++set -Eeuo pipefail + + export GO111MODULE=auto + +-function clean { +- rm -rf "$buildir" ++# temporary "go.mod" to make -modfile= work ++touch go.mod ++ ++function clean() { ++ rm -f "$(pwd)/go.mod" + } + +-buildir=$(mktemp -d -t docker-cli-docsgen.XXXXXXXXXX) + trap clean EXIT + +-( +- set -x +- cp -r . "$buildir/" +- cd "$buildir" +- # init dummy go.mod +- ./scripts/vendor init +- # install go-md2man and copy man/tools.go in root folder +- # to be able to fetch the required dependencies +- go mod edit -modfile=vendor.mod -require=github.com/cpuguy83/go-md2man/v2@${MD2MAN_VERSION} +- cp man/tools.go . +- # update vendor +- ./scripts/vendor update +- # build gen-manpages +- go build -mod=vendor -modfile=vendor.mod -tags manpages -o /tmp/gen-manpages ./man/generate.go +- # build go-md2man +- go build -mod=vendor -modfile=vendor.mod -o /tmp/go-md2man ./vendor/github.com/cpuguy83/go-md2man/v2 +-) ++# build gen-manpages ++go build -mod=vendor -modfile=vendor.mod -tags manpages -o /tmp/gen-manpages ./man/generate.go ++# build go-md2man ++go build -mod=vendor -modfile=vendor.mod -o /tmp/go-md2man ./vendor/github.com/cpuguy83/go-md2man/v2 + + mkdir -p man/man1 + (set -x ; /tmp/gen-manpages --root "." --target "$(pwd)/man/man1") +diff --git a/scripts/docs/generate-md.sh b/scripts/docs/generate-md.sh +index 7b49c39341ec..0af86843bbe4 100755 +--- a/scripts/docs/generate-md.sh ++++ b/scripts/docs/generate-md.sh +@@ -1,36 +1,23 @@ + #!/usr/bin/env bash + +-set -eu +- +-: "${CLI_DOCS_TOOL_VERSION=v0.6.0}" ++set -Eeuo pipefail + + export GO111MODULE=auto + ++# temporary "go.mod" to make -modfile= work ++touch go.mod ++ + function clean { +- rm -rf "$buildir" ++ rm -f "$(pwd)/go.mod" + if [ -f "$(pwd)/docs/reference/commandline/docker.md" ]; then + mv "$(pwd)/docs/reference/commandline/docker.md" "$(pwd)/docs/reference/commandline/cli.md" + fi + } + +-buildir=$(mktemp -d -t docker-cli-docsgen.XXXXXXXXXX) + trap clean EXIT + +-( +- set -x +- cp -r . "$buildir/" +- cd "$buildir" +- # init dummy go.mod +- ./scripts/vendor init +- # install cli-docs-tool and copy docs/tools.go in root folder +- # to be able to fetch the required depedencies +- go mod edit -modfile=vendor.mod -require=github.com/docker/cli-docs-tool@${CLI_DOCS_TOOL_VERSION} +- cp docs/generate/tools.go . +- # update vendor +- ./scripts/vendor update +- # build docsgen +- go build -mod=vendor -modfile=vendor.mod -tags docsgen -o /tmp/docsgen ./docs/generate/generate.go +-) ++# build docsgen ++go build -mod=vendor -modfile=vendor.mod -tags docsgen -o /tmp/docsgen ./docs/generate/generate.go + + # yaml generation on docs repo needs the cli.md file: https://github.com/docker/cli/pull/3924#discussion_r1059986605 + # but markdown generation docker.md atm. While waiting for a fix in cli-docs-tool +diff --git a/scripts/docs/generate-yaml.sh b/scripts/docs/generate-yaml.sh +index 4d0006e43e79..7d98e161df5d 100755 +--- a/scripts/docs/generate-yaml.sh ++++ b/scripts/docs/generate-yaml.sh +@@ -1,33 +1,20 @@ + #!/usr/bin/env bash + +-set -eu +- +-: "${CLI_DOCS_TOOL_VERSION=v0.5.1}" ++set -Eeuo pipefail + + export GO111MODULE=auto + +-function clean { +- rm -rf "$buildir" ++# temporary "go.mod" to make -modfile= work ++touch go.mod ++ ++function clean() { ++ rm -f "$(pwd)/go.mod" + } + +-buildir=$(mktemp -d -t docker-cli-docsgen.XXXXXXXXXX) + trap clean EXIT + +-( +- set -x +- cp -r . "$buildir/" +- cd "$buildir" +- # init dummy go.mod +- ./scripts/vendor init +- # install cli-docs-tool and copy docs/tools.go in root folder +- # to be able to fetch the required depedencies +- go mod edit -modfile=vendor.mod -require=github.com/docker/cli-docs-tool@${CLI_DOCS_TOOL_VERSION} +- cp docs/generate/tools.go . +- # update vendor +- ./scripts/vendor update +- # build docsgen +- go build -mod=vendor -modfile=vendor.mod -tags docsgen -o /tmp/docsgen ./docs/generate/generate.go +-) ++# build docsgen ++go build -mod=vendor -modfile=vendor.mod -tags docsgen -o /tmp/docsgen ./docs/generate/generate.go + + mkdir -p docs/yaml + set -x +diff --git a/vendor.mod b/vendor.mod +index c7b8ae6c4755..b6822249d961 100644 +--- a/vendor.mod ++++ b/vendor.mod +@@ -9,6 +9,7 @@ go 1.19 + require ( + github.com/containerd/containerd v1.6.21 + github.com/creack/pty v1.1.18 ++ github.com/docker/cli-docs-tool v0.6.0 + github.com/docker/distribution v2.8.2+incompatible + github.com/docker/docker v24.0.8+incompatible + github.com/docker/docker-credential-helpers v0.7.0 +@@ -45,11 +46,13 @@ require ( + gotest.tools/v3 v3.5.0 + ) + ++require github.com/cpuguy83/go-md2man/v2 v2.0.3 ++ + require ( + github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/Microsoft/go-winio v0.5.2 // indirect + github.com/beorn7/perks v1.0.1 // indirect +- github.com/cespare/xxhash/v2 v2.1.2 // indirect ++ github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect + github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect + github.com/docker/go-metrics v0.0.1 // indirect +@@ -67,13 +70,15 @@ require ( + github.com/prometheus/common v0.37.0 // indirect + github.com/prometheus/procfs v0.8.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect ++ github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + go.etcd.io/etcd/raft/v3 v3.5.6 // indirect + golang.org/x/crypto v0.14.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/time v0.3.0 // indirect +- google.golang.org/genproto v0.0.0-20220706185917-7780775163c4 // indirect +- google.golang.org/grpc v1.50.1 // indirect +- google.golang.org/protobuf v1.28.1 // indirect ++ google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect ++ google.golang.org/grpc v1.53.0 // indirect ++ google.golang.org/protobuf v1.30.0 // indirect ++ gopkg.in/yaml.v3 v3.0.1 // indirect + ) +diff --git a/vendor.sum b/vendor.sum +index e42542c36a24..329a8899cba6 100644 +--- a/vendor.sum ++++ b/vendor.sum +@@ -47,7 +47,6 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy + github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= + github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= + github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +-github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= + github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= + github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= + github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +@@ -65,8 +64,9 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA + github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= + github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= + github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +-github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= + github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= ++github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= ++github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= + github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= + github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= + github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +@@ -74,11 +74,6 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk + github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA= + github.com/cloudflare/cfssl v0.0.0-20180323000720-5d63dbd981b5 h1:PqZ3bA4yzwywivzk7PBQWngJp2/PAS0bWRZerKteicY= + 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/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +-github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +-github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +-github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= + github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= + github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= + github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= +@@ -86,6 +81,8 @@ github.com/containerd/containerd v1.6.21 h1:eSTAmnvDKRPWan+MpSSfNyrtleXd86ogK9X8 + github.com/containerd/containerd v1.6.21/go.mod h1:apei1/i5Ux2FzrK6+DM/suEsGuK/MeVOfy8tR2q7Wnw= + github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= + github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= ++github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= ++github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= + github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= + github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= + github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +@@ -93,6 +90,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs + github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= + github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= + github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= ++github.com/docker/cli-docs-tool v0.6.0 h1:Z9x10SaZgFaB6jHgz3OWooynhSa40CsWkpe5hEnG/qA= ++github.com/docker/cli-docs-tool v0.6.0/go.mod h1:zMjqTFCU361PRh8apiXzeAZ1Q/xupbIwTusYpzCXS/o= + github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= + github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= + github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +@@ -117,15 +116,12 @@ github.com/dvsekhvalnov/jose2go v0.0.0-20170216131308-f21a8cedbbae/go.mod h1:7Bv + 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.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= + github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= + github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= + github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= + github.com/fvbommel/sortorder v1.0.2 h1:mV4o8B2hKboCdkJm+a7uX/SIpZob4JzUpc5GGnM45eo= + github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= + github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= +-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= +@@ -190,7 +186,6 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ + github.com/google/go-cmp v0.5.1/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/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +-github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= + github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= + github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= + github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +@@ -206,13 +201,11 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf + github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= + github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= + github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +-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/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= + github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= + github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +-github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= + github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= + github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= + github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +@@ -348,8 +341,8 @@ github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5 + github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= + github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= + github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +-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/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= + github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= + github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= + github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +@@ -403,7 +396,6 @@ 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.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= + go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= + go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= + go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +@@ -478,7 +470,6 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R + 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-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= + golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= + golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= + golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +@@ -540,12 +531,9 @@ golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7w + golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/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-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +-golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +-golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= + golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= + golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= + golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +@@ -565,7 +553,6 @@ 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/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +-golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= + golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= + golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= + golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +@@ -667,15 +654,14 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG + 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-20200513103714-09dca8ec2884/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-20220706185917-7780775163c4 h1:7YDGQC/0sigNGzsEWyb9s72jTxlFdwVEYNJHbfQ+Dtg= +-google.golang.org/genproto v0.0.0-20220706185917-7780775163c4/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= ++google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 h1:DdoeryqhaXp1LtT/emMP1BRJPHHKFi5akj/nbx/zNTA= ++google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= + google.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= + google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= + google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +@@ -689,11 +675,8 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa + 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.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +-google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +-google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +-google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= +-google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= ++google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= ++google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= + 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= +@@ -706,10 +689,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj + google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= + google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= + google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +-google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +-google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +-google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +-google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= ++google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= ++google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= + gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= + gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= + gopkg.in/cenkalti/backoff.v2 v2.2.1 h1:eJ9UAg01/HIHG987TwxvnzK2MgxXq97YY6rYDpY9aII= +@@ -727,7 +708,6 @@ gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1/go.mod h1:WbjuEoo1oadwzQ4apSDU+JTvmllE + gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= + 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.3/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.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= + gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +diff --git a/vendor/github.com/cespare/xxhash/v2/README.md b/vendor/github.com/cespare/xxhash/v2/README.md +index 792b4a60b346..8bf0e5b78153 100644 +--- a/vendor/github.com/cespare/xxhash/v2/README.md ++++ b/vendor/github.com/cespare/xxhash/v2/README.md +@@ -3,8 +3,7 @@ + [![Go Reference](https://pkg.go.dev/badge/github.com/cespare/xxhash/v2.svg)](https://pkg.go.dev/github.com/cespare/xxhash/v2) + [![Test](https://github.com/cespare/xxhash/actions/workflows/test.yml/badge.svg)](https://github.com/cespare/xxhash/actions/workflows/test.yml) + +-xxhash is a Go implementation of the 64-bit +-[xxHash](http://cyan4973.github.io/xxHash/) algorithm, XXH64. This is a ++xxhash is a Go implementation of the 64-bit [xxHash] algorithm, XXH64. This is a + high-quality hashing algorithm that is much faster than anything in the Go + standard library. + +@@ -25,8 +24,11 @@ func (*Digest) WriteString(string) (int, error) + func (*Digest) Sum64() uint64 + ``` + +-This implementation provides a fast pure-Go implementation and an even faster +-assembly implementation for amd64. ++The package is written with optimized pure Go and also contains even faster ++assembly implementations for amd64 and arm64. If desired, the `purego` build tag ++opts into using the Go code even on those architectures. ++ ++[xxHash]: http://cyan4973.github.io/xxHash/ + + ## Compatibility + +@@ -45,19 +47,20 @@ I recommend using the latest release of Go. + Here are some quick benchmarks comparing the pure-Go and assembly + implementations of Sum64. + +-| input size | purego | asm | +-| --- | --- | --- | +-| 5 B | 979.66 MB/s | 1291.17 MB/s | +-| 100 B | 7475.26 MB/s | 7973.40 MB/s | +-| 4 KB | 17573.46 MB/s | 17602.65 MB/s | +-| 10 MB | 17131.46 MB/s | 17142.16 MB/s | ++| input size | purego | asm | ++| ---------- | --------- | --------- | ++| 4 B | 1.3 GB/s | 1.2 GB/s | ++| 16 B | 2.9 GB/s | 3.5 GB/s | ++| 100 B | 6.9 GB/s | 8.1 GB/s | ++| 4 KB | 11.7 GB/s | 16.7 GB/s | ++| 10 MB | 12.0 GB/s | 17.3 GB/s | + +-These numbers were generated on Ubuntu 18.04 with an Intel i7-8700K CPU using +-the following commands under Go 1.11.2: ++These numbers were generated on Ubuntu 20.04 with an Intel Xeon Platinum 8252C ++CPU using the following commands under Go 1.19.2: + + ``` +-$ go test -tags purego -benchtime 10s -bench '/xxhash,direct,bytes' +-$ go test -benchtime 10s -bench '/xxhash,direct,bytes' ++benchstat <(go test -tags purego -benchtime 500ms -count 15 -bench 'Sum64$') ++benchstat <(go test -benchtime 500ms -count 15 -bench 'Sum64$') + ``` + + ## Projects using this package +diff --git a/vendor/github.com/cespare/xxhash/v2/testall.sh b/vendor/github.com/cespare/xxhash/v2/testall.sh +new file mode 100644 +index 000000000000..94b9c443987c +--- /dev/null ++++ b/vendor/github.com/cespare/xxhash/v2/testall.sh +@@ -0,0 +1,10 @@ ++#!/bin/bash ++set -eu -o pipefail ++ ++# Small convenience script for running the tests with various combinations of ++# arch/tags. This assumes we're running on amd64 and have qemu available. ++ ++go test ./... ++go test -tags purego ./... ++GOARCH=arm64 go test ++GOARCH=arm64 go test -tags purego +diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash.go b/vendor/github.com/cespare/xxhash/v2/xxhash.go +index 15c835d5417c..a9e0d45c9dcc 100644 +--- a/vendor/github.com/cespare/xxhash/v2/xxhash.go ++++ b/vendor/github.com/cespare/xxhash/v2/xxhash.go +@@ -16,19 +16,11 @@ const ( + prime5 uint64 = 2870177450012600261 + ) + +-// NOTE(caleb): I'm using both consts and vars of the primes. Using consts where +-// possible in the Go code is worth a small (but measurable) performance boost +-// by avoiding some MOVQs. Vars are needed for the asm and also are useful for +-// convenience in the Go code in a few places where we need to intentionally +-// avoid constant arithmetic (e.g., v1 := prime1 + prime2 fails because the +-// result overflows a uint64). +-var ( +- prime1v = prime1 +- prime2v = prime2 +- prime3v = prime3 +- prime4v = prime4 +- prime5v = prime5 +-) ++// Store the primes in an array as well. ++// ++// The consts are used when possible in Go code to avoid MOVs but we need a ++// contiguous array of the assembly code. ++var primes = [...]uint64{prime1, prime2, prime3, prime4, prime5} + + // Digest implements hash.Hash64. + type Digest struct { +@@ -50,10 +42,10 @@ func New() *Digest { + + // Reset clears the Digest's state so that it can be reused. + func (d *Digest) Reset() { +- d.v1 = prime1v + prime2 ++ d.v1 = primes[0] + prime2 + d.v2 = prime2 + d.v3 = 0 +- d.v4 = -prime1v ++ d.v4 = -primes[0] + d.total = 0 + d.n = 0 + } +@@ -69,21 +61,23 @@ func (d *Digest) Write(b []byte) (n int, err error) { + n = len(b) + d.total += uint64(n) + ++ memleft := d.mem[d.n&(len(d.mem)-1):] ++ + if d.n+n < 32 { + // This new data doesn't even fill the current block. +- copy(d.mem[d.n:], b) ++ copy(memleft, b) + d.n += n + return + } + + if d.n > 0 { + // Finish off the partial block. +- copy(d.mem[d.n:], b) ++ c := copy(memleft, b) + d.v1 = round(d.v1, u64(d.mem[0:8])) + d.v2 = round(d.v2, u64(d.mem[8:16])) + d.v3 = round(d.v3, u64(d.mem[16:24])) + d.v4 = round(d.v4, u64(d.mem[24:32])) +- b = b[32-d.n:] ++ b = b[c:] + d.n = 0 + } + +@@ -133,21 +127,20 @@ func (d *Digest) Sum64() uint64 { + + h += d.total + +- i, end := 0, d.n +- for ; i+8 <= end; i += 8 { +- k1 := round(0, u64(d.mem[i:i+8])) ++ b := d.mem[:d.n&(len(d.mem)-1)] ++ for ; len(b) >= 8; b = b[8:] { ++ k1 := round(0, u64(b[:8])) + h ^= k1 + h = rol27(h)*prime1 + prime4 + } +- if i+4 <= end { +- h ^= uint64(u32(d.mem[i:i+4])) * prime1 ++ if len(b) >= 4 { ++ h ^= uint64(u32(b[:4])) * prime1 + h = rol23(h)*prime2 + prime3 +- i += 4 ++ b = b[4:] + } +- for i < end { +- h ^= uint64(d.mem[i]) * prime5 ++ for ; len(b) > 0; b = b[1:] { ++ h ^= uint64(b[0]) * prime5 + h = rol11(h) * prime1 +- i++ + } + + h ^= h >> 33 +diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s b/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s +index be8db5bf7960..3e8b132579ec 100644 +--- a/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s ++++ b/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s +@@ -1,215 +1,209 @@ ++//go:build !appengine && gc && !purego + // +build !appengine + // +build gc + // +build !purego + + #include "textflag.h" + +-// Register allocation: +-// AX h +-// SI pointer to advance through b +-// DX n +-// BX loop end +-// R8 v1, k1 +-// R9 v2 +-// R10 v3 +-// R11 v4 +-// R12 tmp +-// R13 prime1v +-// R14 prime2v +-// DI prime4v +- +-// round reads from and advances the buffer pointer in SI. +-// It assumes that R13 has prime1v and R14 has prime2v. +-#define round(r) \ +- MOVQ (SI), R12 \ +- ADDQ $8, SI \ +- IMULQ R14, R12 \ +- ADDQ R12, r \ +- ROLQ $31, r \ +- IMULQ R13, r +- +-// mergeRound applies a merge round on the two registers acc and val. +-// It assumes that R13 has prime1v, R14 has prime2v, and DI has prime4v. +-#define mergeRound(acc, val) \ +- IMULQ R14, val \ +- ROLQ $31, val \ +- IMULQ R13, val \ +- XORQ val, acc \ +- IMULQ R13, acc \ +- ADDQ DI, acc ++// Registers: ++#define h AX ++#define d AX ++#define p SI // pointer to advance through b ++#define n DX ++#define end BX // loop end ++#define v1 R8 ++#define v2 R9 ++#define v3 R10 ++#define v4 R11 ++#define x R12 ++#define prime1 R13 ++#define prime2 R14 ++#define prime4 DI ++ ++#define round(acc, x) \ ++ IMULQ prime2, x \ ++ ADDQ x, acc \ ++ ROLQ $31, acc \ ++ IMULQ prime1, acc ++ ++// round0 performs the operation x = round(0, x). ++#define round0(x) \ ++ IMULQ prime2, x \ ++ ROLQ $31, x \ ++ IMULQ prime1, x ++ ++// mergeRound applies a merge round on the two registers acc and x. ++// It assumes that prime1, prime2, and prime4 have been loaded. ++#define mergeRound(acc, x) \ ++ round0(x) \ ++ XORQ x, acc \ ++ IMULQ prime1, acc \ ++ ADDQ prime4, acc ++ ++// blockLoop processes as many 32-byte blocks as possible, ++// updating v1, v2, v3, and v4. It assumes that there is at least one block ++// to process. ++#define blockLoop() \ ++loop: \ ++ MOVQ +0(p), x \ ++ round(v1, x) \ ++ MOVQ +8(p), x \ ++ round(v2, x) \ ++ MOVQ +16(p), x \ ++ round(v3, x) \ ++ MOVQ +24(p), x \ ++ round(v4, x) \ ++ ADDQ $32, p \ ++ CMPQ p, end \ ++ JLE loop + + // func Sum64(b []byte) uint64 +-TEXT ·Sum64(SB), NOSPLIT, $0-32 ++TEXT ·Sum64(SB), NOSPLIT|NOFRAME, $0-32 + // Load fixed primes. +- MOVQ ·prime1v(SB), R13 +- MOVQ ·prime2v(SB), R14 +- MOVQ ·prime4v(SB), DI ++ MOVQ ·primes+0(SB), prime1 ++ MOVQ ·primes+8(SB), prime2 ++ MOVQ ·primes+24(SB), prime4 + + // Load slice. +- MOVQ b_base+0(FP), SI +- MOVQ b_len+8(FP), DX +- LEAQ (SI)(DX*1), BX ++ MOVQ b_base+0(FP), p ++ MOVQ b_len+8(FP), n ++ LEAQ (p)(n*1), end + + // The first loop limit will be len(b)-32. +- SUBQ $32, BX ++ SUBQ $32, end + + // Check whether we have at least one block. +- CMPQ DX, $32 ++ CMPQ n, $32 + JLT noBlocks + + // Set up initial state (v1, v2, v3, v4). +- MOVQ R13, R8 +- ADDQ R14, R8 +- MOVQ R14, R9 +- XORQ R10, R10 +- XORQ R11, R11 +- SUBQ R13, R11 +- +- // Loop until SI > BX. +-blockLoop: +- round(R8) +- round(R9) +- round(R10) +- round(R11) +- +- CMPQ SI, BX +- JLE blockLoop +- +- MOVQ R8, AX +- ROLQ $1, AX +- MOVQ R9, R12 +- ROLQ $7, R12 +- ADDQ R12, AX +- MOVQ R10, R12 +- ROLQ $12, R12 +- ADDQ R12, AX +- MOVQ R11, R12 +- ROLQ $18, R12 +- ADDQ R12, AX +- +- mergeRound(AX, R8) +- mergeRound(AX, R9) +- mergeRound(AX, R10) +- mergeRound(AX, R11) ++ MOVQ prime1, v1 ++ ADDQ prime2, v1 ++ MOVQ prime2, v2 ++ XORQ v3, v3 ++ XORQ v4, v4 ++ SUBQ prime1, v4 ++ ++ blockLoop() ++ ++ MOVQ v1, h ++ ROLQ $1, h ++ MOVQ v2, x ++ ROLQ $7, x ++ ADDQ x, h ++ MOVQ v3, x ++ ROLQ $12, x ++ ADDQ x, h ++ MOVQ v4, x ++ ROLQ $18, x ++ ADDQ x, h ++ ++ mergeRound(h, v1) ++ mergeRound(h, v2) ++ mergeRound(h, v3) ++ mergeRound(h, v4) + + JMP afterBlocks + + noBlocks: +- MOVQ ·prime5v(SB), AX ++ MOVQ ·primes+32(SB), h + + afterBlocks: +- ADDQ DX, AX +- +- // Right now BX has len(b)-32, and we want to loop until SI > len(b)-8. +- ADDQ $24, BX +- +- CMPQ SI, BX +- JG fourByte +- +-wordLoop: +- // Calculate k1. +- MOVQ (SI), R8 +- ADDQ $8, SI +- IMULQ R14, R8 +- ROLQ $31, R8 +- IMULQ R13, R8 +- +- XORQ R8, AX +- ROLQ $27, AX +- IMULQ R13, AX +- ADDQ DI, AX +- +- CMPQ SI, BX +- JLE wordLoop +- +-fourByte: +- ADDQ $4, BX +- CMPQ SI, BX +- JG singles +- +- MOVL (SI), R8 +- ADDQ $4, SI +- IMULQ R13, R8 +- XORQ R8, AX +- +- ROLQ $23, AX +- IMULQ R14, AX +- ADDQ ·prime3v(SB), AX +- +-singles: +- ADDQ $4, BX +- CMPQ SI, BX ++ ADDQ n, h ++ ++ ADDQ $24, end ++ CMPQ p, end ++ JG try4 ++ ++loop8: ++ MOVQ (p), x ++ ADDQ $8, p ++ round0(x) ++ XORQ x, h ++ ROLQ $27, h ++ IMULQ prime1, h ++ ADDQ prime4, h ++ ++ CMPQ p, end ++ JLE loop8 ++ ++try4: ++ ADDQ $4, end ++ CMPQ p, end ++ JG try1 ++ ++ MOVL (p), x ++ ADDQ $4, p ++ IMULQ prime1, x ++ XORQ x, h ++ ++ ROLQ $23, h ++ IMULQ prime2, h ++ ADDQ ·primes+16(SB), h ++ ++try1: ++ ADDQ $4, end ++ CMPQ p, end + JGE finalize + +-singlesLoop: +- MOVBQZX (SI), R12 +- ADDQ $1, SI +- IMULQ ·prime5v(SB), R12 +- XORQ R12, AX ++loop1: ++ MOVBQZX (p), x ++ ADDQ $1, p ++ IMULQ ·primes+32(SB), x ++ XORQ x, h ++ ROLQ $11, h ++ IMULQ prime1, h + +- ROLQ $11, AX +- IMULQ R13, AX +- +- CMPQ SI, BX +- JL singlesLoop ++ CMPQ p, end ++ JL loop1 + + finalize: +- MOVQ AX, R12 +- SHRQ $33, R12 +- XORQ R12, AX +- IMULQ R14, AX +- MOVQ AX, R12 +- SHRQ $29, R12 +- XORQ R12, AX +- IMULQ ·prime3v(SB), AX +- MOVQ AX, R12 +- SHRQ $32, R12 +- XORQ R12, AX +- +- MOVQ AX, ret+24(FP) ++ MOVQ h, x ++ SHRQ $33, x ++ XORQ x, h ++ IMULQ prime2, h ++ MOVQ h, x ++ SHRQ $29, x ++ XORQ x, h ++ IMULQ ·primes+16(SB), h ++ MOVQ h, x ++ SHRQ $32, x ++ XORQ x, h ++ ++ MOVQ h, ret+24(FP) + RET + +-// writeBlocks uses the same registers as above except that it uses AX to store +-// the d pointer. +- + // func writeBlocks(d *Digest, b []byte) int +-TEXT ·writeBlocks(SB), NOSPLIT, $0-40 ++TEXT ·writeBlocks(SB), NOSPLIT|NOFRAME, $0-40 + // Load fixed primes needed for round. +- MOVQ ·prime1v(SB), R13 +- MOVQ ·prime2v(SB), R14 ++ MOVQ ·primes+0(SB), prime1 ++ MOVQ ·primes+8(SB), prime2 + + // Load slice. +- MOVQ b_base+8(FP), SI +- MOVQ b_len+16(FP), DX +- LEAQ (SI)(DX*1), BX +- SUBQ $32, BX ++ MOVQ b_base+8(FP), p ++ MOVQ b_len+16(FP), n ++ LEAQ (p)(n*1), end ++ SUBQ $32, end + + // Load vN from d. +- MOVQ d+0(FP), AX +- MOVQ 0(AX), R8 // v1 +- MOVQ 8(AX), R9 // v2 +- MOVQ 16(AX), R10 // v3 +- MOVQ 24(AX), R11 // v4 ++ MOVQ s+0(FP), d ++ MOVQ 0(d), v1 ++ MOVQ 8(d), v2 ++ MOVQ 16(d), v3 ++ MOVQ 24(d), v4 + + // We don't need to check the loop condition here; this function is + // always called with at least one block of data to process. +-blockLoop: +- round(R8) +- round(R9) +- round(R10) +- round(R11) +- +- CMPQ SI, BX +- JLE blockLoop ++ blockLoop() + + // Copy vN back to d. +- MOVQ R8, 0(AX) +- MOVQ R9, 8(AX) +- MOVQ R10, 16(AX) +- MOVQ R11, 24(AX) +- +- // The number of bytes written is SI minus the old base pointer. +- SUBQ b_base+8(FP), SI +- MOVQ SI, ret+32(FP) ++ MOVQ v1, 0(d) ++ MOVQ v2, 8(d) ++ MOVQ v3, 16(d) ++ MOVQ v4, 24(d) ++ ++ // The number of bytes written is p minus the old base pointer. ++ SUBQ b_base+8(FP), p ++ MOVQ p, ret+32(FP) + + RET +diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_arm64.s b/vendor/github.com/cespare/xxhash/v2/xxhash_arm64.s +new file mode 100644 +index 000000000000..7e3145a22186 +--- /dev/null ++++ b/vendor/github.com/cespare/xxhash/v2/xxhash_arm64.s +@@ -0,0 +1,183 @@ ++//go:build !appengine && gc && !purego ++// +build !appengine ++// +build gc ++// +build !purego ++ ++#include "textflag.h" ++ ++// Registers: ++#define digest R1 ++#define h R2 // return value ++#define p R3 // input pointer ++#define n R4 // input length ++#define nblocks R5 // n / 32 ++#define prime1 R7 ++#define prime2 R8 ++#define prime3 R9 ++#define prime4 R10 ++#define prime5 R11 ++#define v1 R12 ++#define v2 R13 ++#define v3 R14 ++#define v4 R15 ++#define x1 R20 ++#define x2 R21 ++#define x3 R22 ++#define x4 R23 ++ ++#define round(acc, x) \ ++ MADD prime2, acc, x, acc \ ++ ROR $64-31, acc \ ++ MUL prime1, acc ++ ++// round0 performs the operation x = round(0, x). ++#define round0(x) \ ++ MUL prime2, x \ ++ ROR $64-31, x \ ++ MUL prime1, x ++ ++#define mergeRound(acc, x) \ ++ round0(x) \ ++ EOR x, acc \ ++ MADD acc, prime4, prime1, acc ++ ++// blockLoop processes as many 32-byte blocks as possible, ++// updating v1, v2, v3, and v4. It assumes that n >= 32. ++#define blockLoop() \ ++ LSR $5, n, nblocks \ ++ PCALIGN $16 \ ++ loop: \ ++ LDP.P 16(p), (x1, x2) \ ++ LDP.P 16(p), (x3, x4) \ ++ round(v1, x1) \ ++ round(v2, x2) \ ++ round(v3, x3) \ ++ round(v4, x4) \ ++ SUB $1, nblocks \ ++ CBNZ nblocks, loop ++ ++// func Sum64(b []byte) uint64 ++TEXT ·Sum64(SB), NOSPLIT|NOFRAME, $0-32 ++ LDP b_base+0(FP), (p, n) ++ ++ LDP ·primes+0(SB), (prime1, prime2) ++ LDP ·primes+16(SB), (prime3, prime4) ++ MOVD ·primes+32(SB), prime5 ++ ++ CMP $32, n ++ CSEL LT, prime5, ZR, h // if n < 32 { h = prime5 } else { h = 0 } ++ BLT afterLoop ++ ++ ADD prime1, prime2, v1 ++ MOVD prime2, v2 ++ MOVD $0, v3 ++ NEG prime1, v4 ++ ++ blockLoop() ++ ++ ROR $64-1, v1, x1 ++ ROR $64-7, v2, x2 ++ ADD x1, x2 ++ ROR $64-12, v3, x3 ++ ROR $64-18, v4, x4 ++ ADD x3, x4 ++ ADD x2, x4, h ++ ++ mergeRound(h, v1) ++ mergeRound(h, v2) ++ mergeRound(h, v3) ++ mergeRound(h, v4) ++ ++afterLoop: ++ ADD n, h ++ ++ TBZ $4, n, try8 ++ LDP.P 16(p), (x1, x2) ++ ++ round0(x1) ++ ++ // NOTE: here and below, sequencing the EOR after the ROR (using a ++ // rotated register) is worth a small but measurable speedup for small ++ // inputs. ++ ROR $64-27, h ++ EOR x1 @> 64-27, h, h ++ MADD h, prime4, prime1, h ++ ++ round0(x2) ++ ROR $64-27, h ++ EOR x2 @> 64-27, h, h ++ MADD h, prime4, prime1, h ++ ++try8: ++ TBZ $3, n, try4 ++ MOVD.P 8(p), x1 ++ ++ round0(x1) ++ ROR $64-27, h ++ EOR x1 @> 64-27, h, h ++ MADD h, prime4, prime1, h ++ ++try4: ++ TBZ $2, n, try2 ++ MOVWU.P 4(p), x2 ++ ++ MUL prime1, x2 ++ ROR $64-23, h ++ EOR x2 @> 64-23, h, h ++ MADD h, prime3, prime2, h ++ ++try2: ++ TBZ $1, n, try1 ++ MOVHU.P 2(p), x3 ++ AND $255, x3, x1 ++ LSR $8, x3, x2 ++ ++ MUL prime5, x1 ++ ROR $64-11, h ++ EOR x1 @> 64-11, h, h ++ MUL prime1, h ++ ++ MUL prime5, x2 ++ ROR $64-11, h ++ EOR x2 @> 64-11, h, h ++ MUL prime1, h ++ ++try1: ++ TBZ $0, n, finalize ++ MOVBU (p), x4 ++ ++ MUL prime5, x4 ++ ROR $64-11, h ++ EOR x4 @> 64-11, h, h ++ MUL prime1, h ++ ++finalize: ++ EOR h >> 33, h ++ MUL prime2, h ++ EOR h >> 29, h ++ MUL prime3, h ++ EOR h >> 32, h ++ ++ MOVD h, ret+24(FP) ++ RET ++ ++// func writeBlocks(d *Digest, b []byte) int ++TEXT ·writeBlocks(SB), NOSPLIT|NOFRAME, $0-40 ++ LDP ·primes+0(SB), (prime1, prime2) ++ ++ // Load state. Assume v[1-4] are stored contiguously. ++ MOVD d+0(FP), digest ++ LDP 0(digest), (v1, v2) ++ LDP 16(digest), (v3, v4) ++ ++ LDP b_base+8(FP), (p, n) ++ ++ blockLoop() ++ ++ // Store updated state. ++ STP (v1, v2), 0(digest) ++ STP (v3, v4), 16(digest) ++ ++ BIC $31, n ++ MOVD n, ret+32(FP) ++ RET +diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.go b/vendor/github.com/cespare/xxhash/v2/xxhash_asm.go +similarity index 73% +rename from vendor/github.com/cespare/xxhash/v2/xxhash_amd64.go +rename to vendor/github.com/cespare/xxhash/v2/xxhash_asm.go +index ad14b807f4d9..9216e0a40c1a 100644 +--- a/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.go ++++ b/vendor/github.com/cespare/xxhash/v2/xxhash_asm.go +@@ -1,3 +1,5 @@ ++//go:build (amd64 || arm64) && !appengine && gc && !purego ++// +build amd64 arm64 + // +build !appengine + // +build gc + // +build !purego +diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_other.go b/vendor/github.com/cespare/xxhash/v2/xxhash_other.go +index 4a5a821603e5..26df13bba4b7 100644 +--- a/vendor/github.com/cespare/xxhash/v2/xxhash_other.go ++++ b/vendor/github.com/cespare/xxhash/v2/xxhash_other.go +@@ -1,4 +1,5 @@ +-// +build !amd64 appengine !gc purego ++//go:build (!amd64 && !arm64) || appengine || !gc || purego ++// +build !amd64,!arm64 appengine !gc purego + + package xxhash + +@@ -14,10 +15,10 @@ func Sum64(b []byte) uint64 { + var h uint64 + + if n >= 32 { +- v1 := prime1v + prime2 ++ v1 := primes[0] + prime2 + v2 := prime2 + v3 := uint64(0) +- v4 := -prime1v ++ v4 := -primes[0] + for len(b) >= 32 { + v1 = round(v1, u64(b[0:8:len(b)])) + v2 = round(v2, u64(b[8:16:len(b)])) +@@ -36,19 +37,18 @@ func Sum64(b []byte) uint64 { + + h += uint64(n) + +- i, end := 0, len(b) +- for ; i+8 <= end; i += 8 { +- k1 := round(0, u64(b[i:i+8:len(b)])) ++ for ; len(b) >= 8; b = b[8:] { ++ k1 := round(0, u64(b[:8])) + h ^= k1 + h = rol27(h)*prime1 + prime4 + } +- if i+4 <= end { +- h ^= uint64(u32(b[i:i+4:len(b)])) * prime1 ++ if len(b) >= 4 { ++ h ^= uint64(u32(b[:4])) * prime1 + h = rol23(h)*prime2 + prime3 +- i += 4 ++ b = b[4:] + } +- for ; i < end; i++ { +- h ^= uint64(b[i]) * prime5 ++ for ; len(b) > 0; b = b[1:] { ++ h ^= uint64(b[0]) * prime5 + h = rol11(h) * prime1 + } + +diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_safe.go b/vendor/github.com/cespare/xxhash/v2/xxhash_safe.go +index fc9bea7a31f2..e86f1b5fd8e4 100644 +--- a/vendor/github.com/cespare/xxhash/v2/xxhash_safe.go ++++ b/vendor/github.com/cespare/xxhash/v2/xxhash_safe.go +@@ -1,3 +1,4 @@ ++//go:build appengine + // +build appengine + + // This file contains the safe implementations of otherwise unsafe-using code. +diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go b/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go +index 376e0ca2e497..1c1638fd88a1 100644 +--- a/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go ++++ b/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go +@@ -1,3 +1,4 @@ ++//go:build !appengine + // +build !appengine + + // This file encapsulates usage of unsafe. +@@ -11,7 +12,7 @@ import ( + + // In the future it's possible that compiler optimizations will make these + // XxxString functions unnecessary by realizing that calls such as +-// Sum64([]byte(s)) don't need to copy s. See https://golang.org/issue/2205. ++// Sum64([]byte(s)) don't need to copy s. See https://go.dev/issue/2205. + // If that happens, even if we keep these functions they can be replaced with + // the trivial safe code. + +diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/.gitignore b/vendor/github.com/cpuguy83/go-md2man/v2/.gitignore +new file mode 100644 +index 000000000000..30f97c3d73ab +--- /dev/null ++++ b/vendor/github.com/cpuguy83/go-md2man/v2/.gitignore +@@ -0,0 +1,2 @@ ++go-md2man ++bin +diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/.golangci.yml b/vendor/github.com/cpuguy83/go-md2man/v2/.golangci.yml +new file mode 100644 +index 000000000000..71f073f3c6b9 +--- /dev/null ++++ b/vendor/github.com/cpuguy83/go-md2man/v2/.golangci.yml +@@ -0,0 +1,6 @@ ++# For documentation, see https://golangci-lint.run/usage/configuration/ ++ ++linters: ++ enable: ++ - gofumpt ++ +diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/Dockerfile b/vendor/github.com/cpuguy83/go-md2man/v2/Dockerfile +new file mode 100644 +index 000000000000..7181c5306f41 +--- /dev/null ++++ b/vendor/github.com/cpuguy83/go-md2man/v2/Dockerfile +@@ -0,0 +1,20 @@ ++ARG GO_VERSION=1.18 ++ARG GO_IMAGE=golang:${GO_VERSION} ++ ++FROM --platform=$BUILDPLATFORM $GO_IMAGE AS build ++COPY . /go/src/github.com/cpuguy83/go-md2man ++WORKDIR /go/src/github.com/cpuguy83/go-md2man ++ARG TARGETOS ++ARG TARGETARCH ++ARG TARGETVARIANT ++RUN \ ++ export GOOS="${TARGETOS}"; \ ++ export GOARCH="${TARGETARCH}"; \ ++ if [ "${TARGETARCH}" = "arm" ] && [ "${TARGETVARIANT}" ]; then \ ++ export GOARM="${TARGETVARIANT#v}"; \ ++ fi; \ ++ CGO_ENABLED=0 go build ++ ++FROM scratch ++COPY --from=build /go/src/github.com/cpuguy83/go-md2man/go-md2man /go-md2man ++ENTRYPOINT ["/go-md2man"] +diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/LICENSE.md b/vendor/github.com/cpuguy83/go-md2man/v2/LICENSE.md +new file mode 100644 +index 000000000000..1cade6cef6a1 +--- /dev/null ++++ b/vendor/github.com/cpuguy83/go-md2man/v2/LICENSE.md +@@ -0,0 +1,21 @@ ++The MIT License (MIT) ++ ++Copyright (c) 2014 Brian Goff ++ ++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. +diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/Makefile b/vendor/github.com/cpuguy83/go-md2man/v2/Makefile +new file mode 100644 +index 000000000000..437fc9997926 +--- /dev/null ++++ b/vendor/github.com/cpuguy83/go-md2man/v2/Makefile +@@ -0,0 +1,35 @@ ++GO111MODULE ?= on ++LINTER_BIN ?= golangci-lint ++ ++export GO111MODULE ++ ++.PHONY: ++build: bin/go-md2man ++ ++.PHONY: clean ++clean: ++ @rm -rf bin/* ++ ++.PHONY: test ++test: ++ @go test $(TEST_FLAGS) ./... ++ ++bin/go-md2man: actual_build_flags := $(BUILD_FLAGS) -o bin/go-md2man ++bin/go-md2man: bin ++ @CGO_ENABLED=0 go build $(actual_build_flags) ++ ++bin: ++ @mkdir ./bin ++ ++.PHONY: mod ++mod: ++ @go mod tidy ++ ++.PHONY: check-mod ++check-mod: # verifies that module changes for go.mod and go.sum are checked in ++ @hack/ci/check_mods.sh ++ ++.PHONY: vendor ++vendor: mod ++ @go mod vendor -v ++ +diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/README.md b/vendor/github.com/cpuguy83/go-md2man/v2/README.md +new file mode 100644 +index 000000000000..0e30d341483c +--- /dev/null ++++ b/vendor/github.com/cpuguy83/go-md2man/v2/README.md +@@ -0,0 +1,15 @@ ++go-md2man ++========= ++ ++Converts markdown into roff (man pages). ++ ++Uses blackfriday to process markdown into man pages. ++ ++### Usage ++ ++./md2man -in /path/to/markdownfile.md -out /manfile/output/path ++ ++### How to contribute ++ ++We use go modules to manage dependencies. ++As such you must be using at lest go1.11. +diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/go-md2man.1.md b/vendor/github.com/cpuguy83/go-md2man/v2/go-md2man.1.md +new file mode 100644 +index 000000000000..aa4587e279ff +--- /dev/null ++++ b/vendor/github.com/cpuguy83/go-md2man/v2/go-md2man.1.md +@@ -0,0 +1,28 @@ ++go-md2man 1 "January 2015" go-md2man "User Manual" ++================================================== ++ ++# NAME ++go-md2man - Convert markdown files into manpages ++ ++# SYNOPSIS ++**go-md2man** [**-in**=*/path/to/md/file*] [**-out**=*/path/to/output*] ++ ++# DESCRIPTION ++**go-md2man** converts standard markdown formatted documents into manpages. It is ++written purely in Go so as to reduce dependencies on 3rd party libs. ++ ++By default, the input is stdin and the output is stdout. ++ ++# EXAMPLES ++Convert the markdown file *go-md2man.1.md* into a manpage: ++``` ++go-md2man < go-md2man.1.md > go-md2man.1 ++``` ++ ++Same, but using command line arguments instead of shell redirection: ++``` ++go-md2man -in=go-md2man.1.md -out=go-md2man.1 ++``` ++ ++# HISTORY ++January 2015, Originally compiled by Brian Goff (cpuguy83@gmail.com). +diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/md2man.go b/vendor/github.com/cpuguy83/go-md2man/v2/md2man.go +new file mode 100644 +index 000000000000..4ff873b8e767 +--- /dev/null ++++ b/vendor/github.com/cpuguy83/go-md2man/v2/md2man.go +@@ -0,0 +1,53 @@ ++package main ++ ++import ( ++ "flag" ++ "fmt" ++ "io/ioutil" ++ "os" ++ ++ "github.com/cpuguy83/go-md2man/v2/md2man" ++) ++ ++var ( ++ inFilePath = flag.String("in", "", "Path to file to be processed (default: stdin)") ++ outFilePath = flag.String("out", "", "Path to output processed file (default: stdout)") ++) ++ ++func main() { ++ var err error ++ flag.Parse() ++ ++ inFile := os.Stdin ++ if *inFilePath != "" { ++ inFile, err = os.Open(*inFilePath) ++ if err != nil { ++ fmt.Println(err) ++ os.Exit(1) ++ } ++ } ++ defer inFile.Close() // nolint: errcheck ++ ++ doc, err := ioutil.ReadAll(inFile) ++ if err != nil { ++ fmt.Println(err) ++ os.Exit(1) ++ } ++ ++ out := md2man.Render(doc) ++ ++ outFile := os.Stdout ++ if *outFilePath != "" { ++ outFile, err = os.Create(*outFilePath) ++ if err != nil { ++ fmt.Println(err) ++ os.Exit(1) ++ } ++ defer outFile.Close() // nolint: errcheck ++ } ++ _, err = outFile.Write(out) ++ if err != nil { ++ fmt.Println(err) ++ os.Exit(1) ++ } ++} +diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/md2man/md2man.go b/vendor/github.com/cpuguy83/go-md2man/v2/md2man/md2man.go +new file mode 100644 +index 000000000000..42bf32aab003 +--- /dev/null ++++ b/vendor/github.com/cpuguy83/go-md2man/v2/md2man/md2man.go +@@ -0,0 +1,16 @@ ++package md2man ++ ++import ( ++ "github.com/russross/blackfriday/v2" ++) ++ ++// Render converts a markdown document into a roff formatted document. ++func Render(doc []byte) []byte { ++ renderer := NewRoffRenderer() ++ ++ return blackfriday.Run(doc, ++ []blackfriday.Option{ ++ blackfriday.WithRenderer(renderer), ++ blackfriday.WithExtensions(renderer.GetExtensions()), ++ }...) ++} +diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/md2man/roff.go b/vendor/github.com/cpuguy83/go-md2man/v2/md2man/roff.go +new file mode 100644 +index 000000000000..4b19188d90fd +--- /dev/null ++++ b/vendor/github.com/cpuguy83/go-md2man/v2/md2man/roff.go +@@ -0,0 +1,348 @@ ++package md2man ++ ++import ( ++ "bytes" ++ "fmt" ++ "io" ++ "os" ++ "strings" ++ ++ "github.com/russross/blackfriday/v2" ++) ++ ++// roffRenderer implements the blackfriday.Renderer interface for creating ++// roff format (manpages) from markdown text ++type roffRenderer struct { ++ extensions blackfriday.Extensions ++ listCounters []int ++ firstHeader bool ++ firstDD bool ++ listDepth int ++} ++ ++const ( ++ titleHeader = ".TH " ++ topLevelHeader = "\n\n.SH " ++ secondLevelHdr = "\n.SH " ++ otherHeader = "\n.SS " ++ crTag = "\n" ++ emphTag = "\\fI" ++ emphCloseTag = "\\fP" ++ strongTag = "\\fB" ++ strongCloseTag = "\\fP" ++ breakTag = "\n.br\n" ++ paraTag = "\n.PP\n" ++ hruleTag = "\n.ti 0\n\\l'\\n(.lu'\n" ++ linkTag = "\n\\[la]" ++ linkCloseTag = "\\[ra]" ++ codespanTag = "\\fB" ++ codespanCloseTag = "\\fR" ++ codeTag = "\n.EX\n" ++ codeCloseTag = "\n.EE\n" ++ quoteTag = "\n.PP\n.RS\n" ++ quoteCloseTag = "\n.RE\n" ++ listTag = "\n.RS\n" ++ listCloseTag = "\n.RE\n" ++ dtTag = "\n.TP\n" ++ dd2Tag = "\n" ++ tableStart = "\n.TS\nallbox;\n" ++ tableEnd = ".TE\n" ++ tableCellStart = "T{\n" ++ tableCellEnd = "\nT}\n" ++) ++ ++// NewRoffRenderer creates a new blackfriday Renderer for generating roff documents ++// from markdown ++func NewRoffRenderer() *roffRenderer { // nolint: golint ++ var extensions blackfriday.Extensions ++ ++ extensions |= blackfriday.NoIntraEmphasis ++ extensions |= blackfriday.Tables ++ extensions |= blackfriday.FencedCode ++ extensions |= blackfriday.SpaceHeadings ++ extensions |= blackfriday.Footnotes ++ extensions |= blackfriday.Titleblock ++ extensions |= blackfriday.DefinitionLists ++ return &roffRenderer{ ++ extensions: extensions, ++ } ++} ++ ++// GetExtensions returns the list of extensions used by this renderer implementation ++func (r *roffRenderer) GetExtensions() blackfriday.Extensions { ++ return r.extensions ++} ++ ++// RenderHeader handles outputting the header at document start ++func (r *roffRenderer) RenderHeader(w io.Writer, ast *blackfriday.Node) { ++ // disable hyphenation ++ out(w, ".nh\n") ++} ++ ++// RenderFooter handles outputting the footer at the document end; the roff ++// renderer has no footer information ++func (r *roffRenderer) RenderFooter(w io.Writer, ast *blackfriday.Node) { ++} ++ ++// RenderNode is called for each node in a markdown document; based on the node ++// type the equivalent roff output is sent to the writer ++func (r *roffRenderer) RenderNode(w io.Writer, node *blackfriday.Node, entering bool) blackfriday.WalkStatus { ++ walkAction := blackfriday.GoToNext ++ ++ switch node.Type { ++ case blackfriday.Text: ++ escapeSpecialChars(w, node.Literal) ++ case blackfriday.Softbreak: ++ out(w, crTag) ++ case blackfriday.Hardbreak: ++ out(w, breakTag) ++ case blackfriday.Emph: ++ if entering { ++ out(w, emphTag) ++ } else { ++ out(w, emphCloseTag) ++ } ++ case blackfriday.Strong: ++ if entering { ++ out(w, strongTag) ++ } else { ++ out(w, strongCloseTag) ++ } ++ case blackfriday.Link: ++ // Don't render the link text for automatic links, because this ++ // will only duplicate the URL in the roff output. ++ // See https://daringfireball.net/projects/markdown/syntax#autolink ++ if !bytes.Equal(node.LinkData.Destination, node.FirstChild.Literal) { ++ out(w, string(node.FirstChild.Literal)) ++ } ++ // Hyphens in a link must be escaped to avoid word-wrap in the rendered man page. ++ escapedLink := strings.ReplaceAll(string(node.LinkData.Destination), "-", "\\-") ++ out(w, linkTag+escapedLink+linkCloseTag) ++ walkAction = blackfriday.SkipChildren ++ case blackfriday.Image: ++ // ignore images ++ walkAction = blackfriday.SkipChildren ++ case blackfriday.Code: ++ out(w, codespanTag) ++ escapeSpecialChars(w, node.Literal) ++ out(w, codespanCloseTag) ++ case blackfriday.Document: ++ break ++ case blackfriday.Paragraph: ++ // roff .PP markers break lists ++ if r.listDepth > 0 { ++ return blackfriday.GoToNext ++ } ++ if entering { ++ out(w, paraTag) ++ } else { ++ out(w, crTag) ++ } ++ case blackfriday.BlockQuote: ++ if entering { ++ out(w, quoteTag) ++ } else { ++ out(w, quoteCloseTag) ++ } ++ case blackfriday.Heading: ++ r.handleHeading(w, node, entering) ++ case blackfriday.HorizontalRule: ++ out(w, hruleTag) ++ case blackfriday.List: ++ r.handleList(w, node, entering) ++ case blackfriday.Item: ++ r.handleItem(w, node, entering) ++ case blackfriday.CodeBlock: ++ out(w, codeTag) ++ escapeSpecialChars(w, node.Literal) ++ out(w, codeCloseTag) ++ case blackfriday.Table: ++ r.handleTable(w, node, entering) ++ case blackfriday.TableHead: ++ case blackfriday.TableBody: ++ case blackfriday.TableRow: ++ // no action as cell entries do all the nroff formatting ++ return blackfriday.GoToNext ++ case blackfriday.TableCell: ++ r.handleTableCell(w, node, entering) ++ case blackfriday.HTMLSpan: ++ // ignore other HTML tags ++ case blackfriday.HTMLBlock: ++ if bytes.HasPrefix(node.Literal, []byte(" ++ ++ ++`) ++ if err != nil { ++ return err ++ } ++ if err = icTpl.Execute(&icBuf, struct { ++ Command string ++ }{ ++ Command: cmd.CommandPath(), ++ }); err != nil { ++ return err ++ } ++ if err = os.WriteFile(targetPath, icBuf.Bytes(), 0644); err != nil { ++ return err ++ } ++ } else if err := copyFile(sourcePath, targetPath); err != nil { ++ return err ++ } ++ ++ content, err := os.ReadFile(targetPath) ++ if err != nil { ++ return err ++ } ++ ++ cs := string(content) ++ ++ start := strings.Index(cs, "") ++ end := strings.Index(cs, "") ++ ++ if start == -1 { ++ return fmt.Errorf("no start marker in %s", mdFile) ++ } ++ if end == -1 { ++ return fmt.Errorf("no end marker in %s", mdFile) ++ } ++ ++ out, err := mdCmdOutput(cmd, cs) ++ if err != nil { ++ return err ++ } ++ cont := cs[:start] + "" + "\n" + out + "\n" + cs[end:] ++ ++ fi, err := os.Stat(targetPath) ++ if err != nil { ++ return err ++ } ++ if err = os.WriteFile(targetPath, []byte(cont), fi.Mode()); err != nil { ++ return fmt.Errorf("failed to write %s: %w", targetPath, err) ++ } ++ ++ return nil ++} ++ ++func mdFilename(cmd *cobra.Command) string { ++ name := cmd.CommandPath() ++ if i := strings.Index(name, " "); i >= 0 { ++ name = name[i+1:] ++ } ++ return strings.ReplaceAll(name, " ", "_") + ".md" ++} ++ ++func mdMakeLink(txt, link string, f *pflag.Flag, isAnchor bool) string { ++ link = "#" + link ++ annotations, ok := f.Annotations[annotation.ExternalURL] ++ if ok && len(annotations) > 0 { ++ link = annotations[0] ++ } else { ++ if !isAnchor { ++ return txt ++ } ++ } ++ ++ return "[" + txt + "](" + link + ")" ++} ++ ++type mdTable struct { ++ out *strings.Builder ++ tabWriter *tabwriter.Writer ++} ++ ++func newMdTable(headers ...string) *mdTable { ++ w := &strings.Builder{} ++ t := &mdTable{ ++ out: w, ++ // Using tabwriter.Debug, which uses "|" as separator instead of tabs, ++ // which is what we want. It's a bit of a hack, but does the job :) ++ tabWriter: tabwriter.NewWriter(w, 5, 5, 1, ' ', tabwriter.Debug), ++ } ++ t.addHeader(headers...) ++ return t ++} ++ ++func (t *mdTable) addHeader(cols ...string) { ++ t.AddRow(cols...) ++ _, _ = t.tabWriter.Write([]byte("|" + strings.Repeat(":---\t", len(cols)) + "\n")) ++} ++ ++func (t *mdTable) AddRow(cols ...string) { ++ for i := range cols { ++ cols[i] = mdEscapePipe(cols[i]) ++ } ++ _, _ = t.tabWriter.Write([]byte("| " + strings.Join(cols, "\t ") + "\t\n")) ++} ++ ++func (t *mdTable) String() string { ++ _ = t.tabWriter.Flush() ++ return adjustSep.ReplaceAllStringFunc(t.out.String()+"\n", func(in string) string { ++ return strings.ReplaceAll(in, " ", "-") ++ }) ++} ++ ++func mdCmdOutput(cmd *cobra.Command, old string) (string, error) { ++ b := &strings.Builder{} ++ ++ desc := cmd.Short ++ if cmd.Long != "" { ++ desc = cmd.Long ++ } ++ if desc != "" { ++ b.WriteString(desc + "\n\n") ++ } ++ ++ if aliases := getAliases(cmd); len(aliases) != 0 { ++ b.WriteString("### Aliases\n\n") ++ b.WriteString("`" + strings.Join(aliases, "`, `") + "`") ++ b.WriteString("\n\n") ++ } ++ ++ if len(cmd.Commands()) != 0 { ++ b.WriteString("### Subcommands\n\n") ++ table := newMdTable("Name", "Description") ++ for _, c := range cmd.Commands() { ++ if c.Hidden { ++ continue ++ } ++ table.AddRow(fmt.Sprintf("[`%s`](%s)", c.Name(), mdFilename(c)), c.Short) ++ } ++ b.WriteString(table.String() + "\n") ++ } ++ ++ // add inherited flags before checking for flags availability ++ cmd.Flags().AddFlagSet(cmd.InheritedFlags()) ++ ++ if cmd.Flags().HasAvailableFlags() { ++ b.WriteString("### Options\n\n") ++ table := newMdTable("Name", "Type", "Default", "Description") ++ cmd.Flags().VisitAll(func(f *pflag.Flag) { ++ if f.Hidden { ++ return ++ } ++ isLink := strings.Contains(old, "") ++ var name string ++ if f.Shorthand != "" { ++ name = mdMakeLink("`-"+f.Shorthand+"`", f.Name, f, isLink) ++ name += ", " ++ } ++ name += mdMakeLink("`--"+f.Name+"`", f.Name, f, isLink) ++ ++ var ftype string ++ if f.Value.Type() != "bool" { ++ ftype = "`" + f.Value.Type() + "`" ++ } ++ ++ var defval string ++ if v, ok := f.Annotations[annotation.DefaultValue]; ok && len(v) > 0 { ++ defval = v[0] ++ if cd, ok := f.Annotations[annotation.CodeDelimiter]; ok { ++ defval = strings.ReplaceAll(defval, cd[0], "`") ++ } else if cd, ok := cmd.Annotations[annotation.CodeDelimiter]; ok { ++ defval = strings.ReplaceAll(defval, cd, "`") ++ } ++ } else if f.DefValue != "" && (f.Value.Type() != "bool" && f.DefValue != "true") && f.DefValue != "[]" { ++ defval = "`" + f.DefValue + "`" ++ } ++ ++ usage := f.Usage ++ if cd, ok := f.Annotations[annotation.CodeDelimiter]; ok { ++ usage = strings.ReplaceAll(usage, cd[0], "`") ++ } else if cd, ok := cmd.Annotations[annotation.CodeDelimiter]; ok { ++ usage = strings.ReplaceAll(usage, cd, "`") ++ } ++ table.AddRow(name, ftype, defval, mdReplaceNewline(usage)) ++ }) ++ b.WriteString(table.String()) ++ } ++ ++ return b.String(), nil ++} ++ ++func mdEscapePipe(s string) string { ++ return strings.ReplaceAll(s, `|`, `\|`) ++} ++ ++func mdReplaceNewline(s string) string { ++ return nlRegexp.ReplaceAllString(s, "
") ++} +diff --git a/vendor/github.com/docker/cli-docs-tool/clidocstool_yaml.go b/vendor/github.com/docker/cli-docs-tool/clidocstool_yaml.go +new file mode 100644 +index 000000000000..523524297af4 +--- /dev/null ++++ b/vendor/github.com/docker/cli-docs-tool/clidocstool_yaml.go +@@ -0,0 +1,435 @@ ++// Copyright 2017 cli-docs-tool authors ++// ++// 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 clidocstool ++ ++import ( ++ "fmt" ++ "io" ++ "log" ++ "os" ++ "path/filepath" ++ "sort" ++ "strings" ++ ++ "github.com/docker/cli-docs-tool/annotation" ++ "github.com/spf13/cobra" ++ "github.com/spf13/pflag" ++ "gopkg.in/yaml.v3" ++) ++ ++type cmdOption struct { ++ Option string ++ Shorthand string `yaml:",omitempty"` ++ ValueType string `yaml:"value_type,omitempty"` ++ DefaultValue string `yaml:"default_value,omitempty"` ++ Description string `yaml:",omitempty"` ++ DetailsURL string `yaml:"details_url,omitempty"` // DetailsURL contains an anchor-id or link for more information on this flag ++ Deprecated bool ++ Hidden bool ++ MinAPIVersion string `yaml:"min_api_version,omitempty"` ++ Experimental bool ++ ExperimentalCLI bool ++ Kubernetes bool ++ Swarm bool ++ OSType string `yaml:"os_type,omitempty"` ++} ++ ++type cmdDoc struct { ++ Name string `yaml:"command"` ++ SeeAlso []string `yaml:"parent,omitempty"` ++ Version string `yaml:"engine_version,omitempty"` ++ Aliases string `yaml:",omitempty"` ++ Short string `yaml:",omitempty"` ++ Long string `yaml:",omitempty"` ++ Usage string `yaml:",omitempty"` ++ Pname string `yaml:",omitempty"` ++ Plink string `yaml:",omitempty"` ++ Cname []string `yaml:",omitempty"` ++ Clink []string `yaml:",omitempty"` ++ Options []cmdOption `yaml:",omitempty"` ++ InheritedOptions []cmdOption `yaml:"inherited_options,omitempty"` ++ Example string `yaml:"examples,omitempty"` ++ Deprecated bool ++ Hidden bool ++ MinAPIVersion string `yaml:"min_api_version,omitempty"` ++ Experimental bool ++ ExperimentalCLI bool ++ Kubernetes bool ++ Swarm bool ++ OSType string `yaml:"os_type,omitempty"` ++} ++ ++// GenYamlTree creates yaml structured ref files for this command and all descendants ++// in the directory given. This function may not work ++// correctly if your command names have `-` in them. If you have `cmd` with two ++// subcmds, `sub` and `sub-third`, and `sub` has a subcommand called `third` ++// it is undefined which help output will be in the file `cmd-sub-third.1`. ++func (c *Client) GenYamlTree(cmd *cobra.Command) error { ++ emptyStr := func(s string) string { return "" } ++ if err := c.loadLongDescription(cmd); err != nil { ++ return err ++ } ++ return c.genYamlTreeCustom(cmd, emptyStr) ++} ++ ++// genYamlTreeCustom creates yaml structured ref files. ++func (c *Client) genYamlTreeCustom(cmd *cobra.Command, filePrepender func(string) string) error { ++ for _, sc := range cmd.Commands() { ++ if !sc.Runnable() && !sc.HasAvailableSubCommands() { ++ // skip non-runnable commands without subcommands ++ // but *do* generate YAML for hidden and deprecated commands ++ // the YAML will have those included as metadata, so that the ++ // documentation repository can decide whether or not to present them ++ continue ++ } ++ if err := c.genYamlTreeCustom(sc, filePrepender); err != nil { ++ return err ++ } ++ } ++ ++ // always disable the addition of [flags] to the usage ++ cmd.DisableFlagsInUseLine = true ++ ++ // The "root" command used in the generator is just a "stub", and only has a ++ // list of subcommands, but not (e.g.) global options/flags. We should fix ++ // that, so that the YAML file for the docker "root" command contains the ++ // global flags. ++ ++ // Skip the root command altogether, to prevent generating a useless ++ // YAML file for plugins. ++ if c.plugin && !cmd.HasParent() { ++ return nil ++ } ++ ++ log.Printf("INFO: Generating YAML for %q", cmd.CommandPath()) ++ basename := strings.Replace(cmd.CommandPath(), " ", "_", -1) + ".yaml" ++ target := filepath.Join(c.target, basename) ++ f, err := os.Create(target) ++ if err != nil { ++ return err ++ } ++ defer f.Close() ++ ++ if _, err := io.WriteString(f, filePrepender(target)); err != nil { ++ return err ++ } ++ return c.genYamlCustom(cmd, f) ++} ++ ++// genYamlCustom creates custom yaml output. ++// nolint: gocyclo ++func (c *Client) genYamlCustom(cmd *cobra.Command, w io.Writer) error { ++ const ( ++ // shortMaxWidth is the maximum width for the "Short" description before ++ // we force YAML to use multi-line syntax. The goal is to make the total ++ // width fit within 80 characters. This value is based on 80 characters ++ // minus the with of the field, colon, and whitespace ('short: '). ++ shortMaxWidth = 73 ++ ++ // longMaxWidth is the maximum width for the "Short" description before ++ // we force YAML to use multi-line syntax. The goal is to make the total ++ // width fit within 80 characters. This value is based on 80 characters ++ // minus the with of the field, colon, and whitespace ('long: '). ++ longMaxWidth = 74 ++ ) ++ ++ // necessary to add inherited flags otherwise some ++ // fields are not properly declared like usage ++ cmd.Flags().AddFlagSet(cmd.InheritedFlags()) ++ ++ cliDoc := cmdDoc{ ++ Name: cmd.CommandPath(), ++ Aliases: strings.Join(getAliases(cmd), ", "), ++ Short: forceMultiLine(cmd.Short, shortMaxWidth), ++ Long: forceMultiLine(cmd.Long, longMaxWidth), ++ Example: cmd.Example, ++ Deprecated: len(cmd.Deprecated) > 0, ++ Hidden: cmd.Hidden, ++ } ++ ++ if len(cliDoc.Long) == 0 { ++ cliDoc.Long = cliDoc.Short ++ } ++ ++ if cmd.Runnable() { ++ cliDoc.Usage = cmd.UseLine() ++ } ++ ++ // check recursively to handle inherited annotations ++ for curr := cmd; curr != nil; curr = curr.Parent() { ++ if v, ok := curr.Annotations["version"]; ok && cliDoc.MinAPIVersion == "" { ++ cliDoc.MinAPIVersion = v ++ } ++ if _, ok := curr.Annotations["experimental"]; ok && !cliDoc.Experimental { ++ cliDoc.Experimental = true ++ } ++ if _, ok := curr.Annotations["experimentalCLI"]; ok && !cliDoc.ExperimentalCLI { ++ cliDoc.ExperimentalCLI = true ++ } ++ if _, ok := curr.Annotations["kubernetes"]; ok && !cliDoc.Kubernetes { ++ cliDoc.Kubernetes = true ++ } ++ if _, ok := curr.Annotations["swarm"]; ok && !cliDoc.Swarm { ++ cliDoc.Swarm = true ++ } ++ if o, ok := curr.Annotations["ostype"]; ok && cliDoc.OSType == "" { ++ cliDoc.OSType = o ++ } ++ if _, ok := cmd.Annotations[annotation.CodeDelimiter]; !ok { ++ if cd, cok := curr.Annotations[annotation.CodeDelimiter]; cok { ++ if cmd.Annotations == nil { ++ cmd.Annotations = map[string]string{} ++ } ++ cmd.Annotations[annotation.CodeDelimiter] = cd ++ } ++ } ++ } ++ ++ anchors := make(map[string]struct{}) ++ if a, ok := cmd.Annotations["anchors"]; ok && a != "" { ++ for _, anchor := range strings.Split(a, ",") { ++ anchors[anchor] = struct{}{} ++ } ++ } ++ ++ flags := cmd.NonInheritedFlags() ++ if flags.HasFlags() { ++ cliDoc.Options = genFlagResult(cmd, flags, anchors) ++ } ++ flags = cmd.InheritedFlags() ++ if flags.HasFlags() { ++ cliDoc.InheritedOptions = genFlagResult(cmd, flags, anchors) ++ } ++ ++ if hasSeeAlso(cmd) { ++ if cmd.HasParent() { ++ parent := cmd.Parent() ++ cliDoc.Pname = parent.CommandPath() ++ cliDoc.Plink = strings.Replace(cliDoc.Pname, " ", "_", -1) + ".yaml" ++ cmd.VisitParents(func(c *cobra.Command) { ++ if c.DisableAutoGenTag { ++ cmd.DisableAutoGenTag = c.DisableAutoGenTag ++ } ++ }) ++ } ++ ++ children := cmd.Commands() ++ sort.Sort(byName(children)) ++ ++ for _, child := range children { ++ if !child.IsAvailableCommand() || child.IsAdditionalHelpTopicCommand() { ++ continue ++ } ++ cliDoc.Cname = append(cliDoc.Cname, cliDoc.Name+" "+child.Name()) ++ cliDoc.Clink = append(cliDoc.Clink, strings.Replace(cliDoc.Name+"_"+child.Name(), " ", "_", -1)+".yaml") ++ } ++ } ++ ++ final, err := yaml.Marshal(&cliDoc) ++ if err != nil { ++ fmt.Println(err) ++ os.Exit(1) ++ } ++ if _, err := fmt.Fprintln(w, string(final)); err != nil { ++ return err ++ } ++ return nil ++} ++ ++func genFlagResult(cmd *cobra.Command, flags *pflag.FlagSet, anchors map[string]struct{}) []cmdOption { ++ var ( ++ result []cmdOption ++ opt cmdOption ++ ) ++ ++ const ( ++ // shortMaxWidth is the maximum width for the "Short" description before ++ // we force YAML to use multi-line syntax. The goal is to make the total ++ // width fit within 80 characters. This value is based on 80 characters ++ // minus the with of the field, colon, and whitespace (' default_value: '). ++ defaultValueMaxWidth = 64 ++ ++ // longMaxWidth is the maximum width for the "Short" description before ++ // we force YAML to use multi-line syntax. The goal is to make the total ++ // width fit within 80 characters. This value is based on 80 characters ++ // minus the with of the field, colon, and whitespace (' description: '). ++ descriptionMaxWidth = 66 ++ ) ++ ++ flags.VisitAll(func(flag *pflag.Flag) { ++ opt = cmdOption{ ++ Option: flag.Name, ++ ValueType: flag.Value.Type(), ++ Deprecated: len(flag.Deprecated) > 0, ++ Hidden: flag.Hidden, ++ } ++ ++ var defval string ++ if v, ok := flag.Annotations[annotation.DefaultValue]; ok && len(v) > 0 { ++ defval = v[0] ++ if cd, ok := flag.Annotations[annotation.CodeDelimiter]; ok { ++ defval = strings.ReplaceAll(defval, cd[0], "`") ++ } else if cd, ok := cmd.Annotations[annotation.CodeDelimiter]; ok { ++ defval = strings.ReplaceAll(defval, cd, "`") ++ } ++ } else { ++ defval = flag.DefValue ++ } ++ opt.DefaultValue = forceMultiLine(defval, defaultValueMaxWidth) ++ ++ usage := flag.Usage ++ if cd, ok := flag.Annotations[annotation.CodeDelimiter]; ok { ++ usage = strings.ReplaceAll(usage, cd[0], "`") ++ } else if cd, ok := cmd.Annotations[annotation.CodeDelimiter]; ok { ++ usage = strings.ReplaceAll(usage, cd, "`") ++ } ++ opt.Description = forceMultiLine(usage, descriptionMaxWidth) ++ ++ if v, ok := flag.Annotations[annotation.ExternalURL]; ok && len(v) > 0 { ++ opt.DetailsURL = strings.TrimPrefix(v[0], "https://docs.docker.com") ++ } else if _, ok = anchors[flag.Name]; ok { ++ opt.DetailsURL = "#" + flag.Name ++ } ++ ++ // Todo, when we mark a shorthand is deprecated, but specify an empty message. ++ // The flag.ShorthandDeprecated is empty as the shorthand is deprecated. ++ // Using len(flag.ShorthandDeprecated) > 0 can't handle this, others are ok. ++ if !(len(flag.ShorthandDeprecated) > 0) && len(flag.Shorthand) > 0 { ++ opt.Shorthand = flag.Shorthand ++ } ++ if _, ok := flag.Annotations["experimental"]; ok { ++ opt.Experimental = true ++ } ++ if _, ok := flag.Annotations["deprecated"]; ok { ++ opt.Deprecated = true ++ } ++ if v, ok := flag.Annotations["version"]; ok { ++ opt.MinAPIVersion = v[0] ++ } ++ if _, ok := flag.Annotations["experimentalCLI"]; ok { ++ opt.ExperimentalCLI = true ++ } ++ if _, ok := flag.Annotations["kubernetes"]; ok { ++ opt.Kubernetes = true ++ } ++ if _, ok := flag.Annotations["swarm"]; ok { ++ opt.Swarm = true ++ } ++ ++ // Note that the annotation can have multiple ostypes set, however, multiple ++ // values are currently not used (and unlikely will). ++ // ++ // To simplify usage of the os_type property in the YAML, and for consistency ++ // with the same property for commands, we're only using the first ostype that's set. ++ if ostypes, ok := flag.Annotations["ostype"]; ok && len(opt.OSType) == 0 && len(ostypes) > 0 { ++ opt.OSType = ostypes[0] ++ } ++ ++ result = append(result, opt) ++ }) ++ ++ return result ++} ++ ++// forceMultiLine appends a newline (\n) to strings that are longer than max ++// to force the yaml lib to use block notation (https://yaml.org/spec/1.2/spec.html#Block) ++// instead of a single-line string with newlines and tabs encoded("string\nline1\nline2"). ++// ++// This makes the generated YAML more readable, and easier to review changes. ++// max can be used to customize the width to keep the whole line < 80 chars. ++func forceMultiLine(s string, max int) string { ++ s = strings.TrimSpace(s) ++ if len(s) > max && !strings.Contains(s, "\n") { ++ s = s + "\n" ++ } ++ return s ++} ++ ++// Small duplication for cobra utils ++func hasSeeAlso(cmd *cobra.Command) bool { ++ if cmd.HasParent() { ++ return true ++ } ++ for _, c := range cmd.Commands() { ++ if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { ++ continue ++ } ++ return true ++ } ++ return false ++} ++ ++// loadLongDescription gets long descriptions and examples from markdown. ++func (c *Client) loadLongDescription(parentCmd *cobra.Command) error { ++ for _, cmd := range parentCmd.Commands() { ++ if cmd.HasSubCommands() { ++ if err := c.loadLongDescription(cmd); err != nil { ++ return err ++ } ++ } ++ name := cmd.CommandPath() ++ if i := strings.Index(name, " "); i >= 0 { ++ // remove root command / binary name ++ name = name[i+1:] ++ } ++ if name == "" { ++ continue ++ } ++ mdFile := strings.ReplaceAll(name, " ", "_") + ".md" ++ sourcePath := filepath.Join(c.source, mdFile) ++ content, err := os.ReadFile(sourcePath) ++ if os.IsNotExist(err) { ++ log.Printf("WARN: %s does not exist, skipping Markdown examples for YAML doc\n", mdFile) ++ continue ++ } ++ if err != nil { ++ return err ++ } ++ applyDescriptionAndExamples(cmd, string(content)) ++ } ++ return nil ++} ++ ++// applyDescriptionAndExamples fills in cmd.Long and cmd.Example with the ++// "Description" and "Examples" H2 sections in mdString (if present). ++func applyDescriptionAndExamples(cmd *cobra.Command, mdString string) { ++ sections := getSections(mdString) ++ var ( ++ anchors []string ++ md string ++ ) ++ if sections["description"] != "" { ++ md, anchors = cleanupMarkDown(sections["description"]) ++ cmd.Long = md ++ anchors = append(anchors, md) ++ } ++ if sections["examples"] != "" { ++ md, anchors = cleanupMarkDown(sections["examples"]) ++ cmd.Example = md ++ anchors = append(anchors, md) ++ } ++ if len(anchors) > 0 { ++ if cmd.Annotations == nil { ++ cmd.Annotations = make(map[string]string) ++ } ++ cmd.Annotations["anchors"] = strings.Join(anchors, ",") ++ } ++} ++ ++type byName []*cobra.Command ++ ++func (s byName) Len() int { return len(s) } ++func (s byName) Swap(i, j int) { s[i], s[j] = s[j], s[i] } ++func (s byName) Less(i, j int) bool { return s[i].Name() < s[j].Name() } +diff --git a/vendor/github.com/docker/cli-docs-tool/docker-bake.hcl b/vendor/github.com/docker/cli-docs-tool/docker-bake.hcl +new file mode 100644 +index 000000000000..4a5f44f83018 +--- /dev/null ++++ b/vendor/github.com/docker/cli-docs-tool/docker-bake.hcl +@@ -0,0 +1,51 @@ ++// Copyright 2021 cli-docs-tool authors ++// ++// 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. ++ ++group "default" { ++ targets = ["test"] ++} ++ ++group "validate" { ++ targets = ["lint", "vendor-validate", "license-validate"] ++} ++ ++target "lint" { ++ target = "lint" ++ output = ["type=cacheonly"] ++} ++ ++target "vendor-validate" { ++ target = "vendor-validate" ++ output = ["type=cacheonly"] ++} ++ ++target "vendor-update" { ++ target = "vendor-update" ++ output = ["."] ++} ++ ++target "test" { ++ target = "test-coverage" ++ output = ["."] ++} ++ ++target "license-validate" { ++ target = "license-validate" ++ output = ["type=cacheonly"] ++} ++ ++target "license-update" { ++ target = "license-update" ++ output = ["."] ++} +diff --git a/vendor/github.com/docker/cli-docs-tool/markdown.go b/vendor/github.com/docker/cli-docs-tool/markdown.go +new file mode 100644 +index 000000000000..32849236ed9c +--- /dev/null ++++ b/vendor/github.com/docker/cli-docs-tool/markdown.go +@@ -0,0 +1,87 @@ ++// Copyright 2017 cli-docs-tool authors ++// ++// 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 clidocstool ++ ++import ( ++ "regexp" ++ "strings" ++ "unicode" ++) ++ ++var ( ++ // mdHeading matches MarkDown H1..h6 headings. Note that this regex may produce ++ // false positives for (e.g.) comments in code-blocks (# this is a comment), ++ // so should not be used as a generic regex for other purposes. ++ mdHeading = regexp.MustCompile(`^([#]{1,6})\s(.*)$`) ++ // htmlAnchor matches inline HTML anchors. This is intended to only match anchors ++ // for our use-case; DO NOT consider using this as a generic regex, or at least ++ // not before reading https://stackoverflow.com/a/1732454/1811501. ++ htmlAnchor = regexp.MustCompile(`\s*`) ++) ++ ++// getSections returns all H2 sections by title (lowercase) ++func getSections(mdString string) map[string]string { ++ parsedContent := strings.Split("\n"+mdString, "\n## ") ++ sections := make(map[string]string, len(parsedContent)) ++ for _, s := range parsedContent { ++ if strings.HasPrefix(s, "#") { ++ // not a H2 Section ++ continue ++ } ++ parts := strings.SplitN(s, "\n", 2) ++ if len(parts) == 2 { ++ sections[strings.ToLower(parts[0])] = parts[1] ++ } ++ } ++ return sections ++} ++ ++// cleanupMarkDown cleans up the MarkDown passed in mdString for inclusion in ++// YAML. It removes trailing whitespace and substitutes tabs for four spaces ++// to prevent YAML switching to use "compact" form; ("line1 \nline\t2\n") ++// which, although equivalent, is hard to read. ++func cleanupMarkDown(mdString string) (md string, anchors []string) { ++ // remove leading/trailing whitespace, and replace tabs in the whole content ++ mdString = strings.TrimSpace(mdString) ++ mdString = strings.ReplaceAll(mdString, "\t", " ") ++ mdString = strings.ReplaceAll(mdString, "https://docs.docker.com", "") ++ ++ var id string ++ // replace trailing whitespace per line, and handle custom anchors ++ lines := strings.Split(mdString, "\n") ++ for i := 0; i < len(lines); i++ { ++ lines[i] = strings.TrimRightFunc(lines[i], unicode.IsSpace) ++ lines[i], id = convertHTMLAnchor(lines[i]) ++ if id != "" { ++ anchors = append(anchors, id) ++ } ++ } ++ return strings.Join(lines, "\n"), anchors ++} ++ ++// convertHTMLAnchor converts inline anchor-tags in headings () ++// to an extended-markdown property ({#myanchor}). Extended Markdown properties ++// are not supported in GitHub Flavored Markdown, but are supported by Jekyll, ++// and lead to cleaner HTML in our docs, and prevents duplicate anchors. ++// It returns the converted MarkDown heading and the custom ID (if present) ++func convertHTMLAnchor(mdLine string) (md string, customID string) { ++ if m := mdHeading.FindStringSubmatch(mdLine); len(m) > 0 { ++ if a := htmlAnchor.FindStringSubmatch(m[2]); len(a) > 0 { ++ customID = a[1] ++ mdLine = m[1] + " " + htmlAnchor.ReplaceAllString(m[2], "") + " {#" + customID + "}" ++ } ++ } ++ return mdLine, customID ++} +diff --git a/vendor/github.com/russross/blackfriday/v2/.gitignore b/vendor/github.com/russross/blackfriday/v2/.gitignore +new file mode 100644 +index 000000000000..75623dcccbb7 +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/.gitignore +@@ -0,0 +1,8 @@ ++*.out ++*.swp ++*.8 ++*.6 ++_obj ++_test* ++markdown ++tags +diff --git a/vendor/github.com/russross/blackfriday/v2/.travis.yml b/vendor/github.com/russross/blackfriday/v2/.travis.yml +new file mode 100644 +index 000000000000..b0b525a5a8e1 +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/.travis.yml +@@ -0,0 +1,17 @@ ++sudo: false ++language: go ++go: ++ - "1.10.x" ++ - "1.11.x" ++ - tip ++matrix: ++ fast_finish: true ++ allow_failures: ++ - go: tip ++install: ++ - # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step). ++script: ++ - go get -t -v ./... ++ - diff -u <(echo -n) <(gofmt -d -s .) ++ - go tool vet . ++ - go test -v ./... +diff --git a/vendor/github.com/russross/blackfriday/v2/LICENSE.txt b/vendor/github.com/russross/blackfriday/v2/LICENSE.txt +new file mode 100644 +index 000000000000..2885af3602d8 +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/LICENSE.txt +@@ -0,0 +1,29 @@ ++Blackfriday is distributed under the Simplified BSD License: ++ ++> Copyright © 2011 Russ Ross ++> All rights reserved. ++> ++> Redistribution and use in source and binary forms, with or without ++> modification, are permitted provided that the following conditions ++> are met: ++> ++> 1. Redistributions of source code must retain the above copyright ++> notice, this list of conditions and the following disclaimer. ++> ++> 2. Redistributions in binary form must reproduce the above ++> copyright notice, this list of conditions and the following ++> disclaimer in the documentation and/or other materials provided with ++> the distribution. ++> ++> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++> "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++> LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++> FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++> COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++> INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++> BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++> LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++> CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++> LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ++> ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++> POSSIBILITY OF SUCH DAMAGE. +diff --git a/vendor/github.com/russross/blackfriday/v2/README.md b/vendor/github.com/russross/blackfriday/v2/README.md +new file mode 100644 +index 000000000000..d9c08a22fc54 +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/README.md +@@ -0,0 +1,335 @@ ++Blackfriday ++[![Build Status][BuildV2SVG]][BuildV2URL] ++[![PkgGoDev][PkgGoDevV2SVG]][PkgGoDevV2URL] ++=========== ++ ++Blackfriday is a [Markdown][1] processor implemented in [Go][2]. It ++is paranoid about its input (so you can safely feed it user-supplied ++data), it is fast, it supports common extensions (tables, smart ++punctuation substitutions, etc.), and it is safe for all utf-8 ++(unicode) input. ++ ++HTML output is currently supported, along with Smartypants ++extensions. ++ ++It started as a translation from C of [Sundown][3]. ++ ++ ++Installation ++------------ ++ ++Blackfriday is compatible with modern Go releases in module mode. ++With Go installed: ++ ++ go get github.com/russross/blackfriday/v2 ++ ++will resolve and add the package to the current development module, ++then build and install it. Alternatively, you can achieve the same ++if you import it in a package: ++ ++ import "github.com/russross/blackfriday/v2" ++ ++and `go get` without parameters. ++ ++Legacy GOPATH mode is unsupported. ++ ++ ++Versions ++-------- ++ ++Currently maintained and recommended version of Blackfriday is `v2`. It's being ++developed on its own branch: https://github.com/russross/blackfriday/tree/v2 and the ++documentation is available at ++https://pkg.go.dev/github.com/russross/blackfriday/v2. ++ ++It is `go get`-able in module mode at `github.com/russross/blackfriday/v2`. ++ ++Version 2 offers a number of improvements over v1: ++ ++* Cleaned up API ++* A separate call to [`Parse`][4], which produces an abstract syntax tree for ++ the document ++* Latest bug fixes ++* Flexibility to easily add your own rendering extensions ++ ++Potential drawbacks: ++ ++* Our benchmarks show v2 to be slightly slower than v1. Currently in the ++ ballpark of around 15%. ++* API breakage. If you can't afford modifying your code to adhere to the new API ++ and don't care too much about the new features, v2 is probably not for you. ++* Several bug fixes are trailing behind and still need to be forward-ported to ++ v2. See issue [#348](https://github.com/russross/blackfriday/issues/348) for ++ tracking. ++ ++If you are still interested in the legacy `v1`, you can import it from ++`github.com/russross/blackfriday`. Documentation for the legacy v1 can be found ++here: https://pkg.go.dev/github.com/russross/blackfriday. ++ ++ ++Usage ++----- ++ ++For the most sensible markdown processing, it is as simple as getting your input ++into a byte slice and calling: ++ ++```go ++output := blackfriday.Run(input) ++``` ++ ++Your input will be parsed and the output rendered with a set of most popular ++extensions enabled. If you want the most basic feature set, corresponding with ++the bare Markdown specification, use: ++ ++```go ++output := blackfriday.Run(input, blackfriday.WithNoExtensions()) ++``` ++ ++### Sanitize untrusted content ++ ++Blackfriday itself does nothing to protect against malicious content. If you are ++dealing with user-supplied markdown, we recommend running Blackfriday's output ++through HTML sanitizer such as [Bluemonday][5]. ++ ++Here's an example of simple usage of Blackfriday together with Bluemonday: ++ ++```go ++import ( ++ "github.com/microcosm-cc/bluemonday" ++ "github.com/russross/blackfriday/v2" ++) ++ ++// ... ++unsafe := blackfriday.Run(input) ++html := bluemonday.UGCPolicy().SanitizeBytes(unsafe) ++``` ++ ++### Custom options ++ ++If you want to customize the set of options, use `blackfriday.WithExtensions`, ++`blackfriday.WithRenderer` and `blackfriday.WithRefOverride`. ++ ++### `blackfriday-tool` ++ ++You can also check out `blackfriday-tool` for a more complete example ++of how to use it. Download and install it using: ++ ++ go get github.com/russross/blackfriday-tool ++ ++This is a simple command-line tool that allows you to process a ++markdown file using a standalone program. You can also browse the ++source directly on github if you are just looking for some example ++code: ++ ++* ++ ++Note that if you have not already done so, installing ++`blackfriday-tool` will be sufficient to download and install ++blackfriday in addition to the tool itself. The tool binary will be ++installed in `$GOPATH/bin`. This is a statically-linked binary that ++can be copied to wherever you need it without worrying about ++dependencies and library versions. ++ ++### Sanitized anchor names ++ ++Blackfriday includes an algorithm for creating sanitized anchor names ++corresponding to a given input text. This algorithm is used to create ++anchors for headings when `AutoHeadingIDs` extension is enabled. The ++algorithm has a specification, so that other packages can create ++compatible anchor names and links to those anchors. ++ ++The specification is located at https://pkg.go.dev/github.com/russross/blackfriday/v2#hdr-Sanitized_Anchor_Names. ++ ++[`SanitizedAnchorName`](https://pkg.go.dev/github.com/russross/blackfriday/v2#SanitizedAnchorName) exposes this functionality, and can be used to ++create compatible links to the anchor names generated by blackfriday. ++This algorithm is also implemented in a small standalone package at ++[`github.com/shurcooL/sanitized_anchor_name`](https://pkg.go.dev/github.com/shurcooL/sanitized_anchor_name). It can be useful for clients ++that want a small package and don't need full functionality of blackfriday. ++ ++ ++Features ++-------- ++ ++All features of Sundown are supported, including: ++ ++* **Compatibility**. The Markdown v1.0.3 test suite passes with ++ the `--tidy` option. Without `--tidy`, the differences are ++ mostly in whitespace and entity escaping, where blackfriday is ++ more consistent and cleaner. ++ ++* **Common extensions**, including table support, fenced code ++ blocks, autolinks, strikethroughs, non-strict emphasis, etc. ++ ++* **Safety**. Blackfriday is paranoid when parsing, making it safe ++ to feed untrusted user input without fear of bad things ++ happening. The test suite stress tests this and there are no ++ known inputs that make it crash. If you find one, please let me ++ know and send me the input that does it. ++ ++ NOTE: "safety" in this context means *runtime safety only*. In order to ++ protect yourself against JavaScript injection in untrusted content, see ++ [this example](https://github.com/russross/blackfriday#sanitize-untrusted-content). ++ ++* **Fast processing**. It is fast enough to render on-demand in ++ most web applications without having to cache the output. ++ ++* **Thread safety**. You can run multiple parsers in different ++ goroutines without ill effect. There is no dependence on global ++ shared state. ++ ++* **Minimal dependencies**. Blackfriday only depends on standard ++ library packages in Go. The source code is pretty ++ self-contained, so it is easy to add to any project, including ++ Google App Engine projects. ++ ++* **Standards compliant**. Output successfully validates using the ++ W3C validation tool for HTML 4.01 and XHTML 1.0 Transitional. ++ ++ ++Extensions ++---------- ++ ++In addition to the standard markdown syntax, this package ++implements the following extensions: ++ ++* **Intra-word emphasis supression**. The `_` character is ++ commonly used inside words when discussing code, so having ++ markdown interpret it as an emphasis command is usually the ++ wrong thing. Blackfriday lets you treat all emphasis markers as ++ normal characters when they occur inside a word. ++ ++* **Tables**. Tables can be created by drawing them in the input ++ using a simple syntax: ++ ++ ``` ++ Name | Age ++ --------|------ ++ Bob | 27 ++ Alice | 23 ++ ``` ++ ++* **Fenced code blocks**. In addition to the normal 4-space ++ indentation to mark code blocks, you can explicitly mark them ++ and supply a language (to make syntax highlighting simple). Just ++ mark it like this: ++ ++ ```go ++ func getTrue() bool { ++ return true ++ } ++ ``` ++ ++ You can use 3 or more backticks to mark the beginning of the ++ block, and the same number to mark the end of the block. ++ ++ To preserve classes of fenced code blocks while using the bluemonday ++ HTML sanitizer, use the following policy: ++ ++ ```go ++ p := bluemonday.UGCPolicy() ++ p.AllowAttrs("class").Matching(regexp.MustCompile("^language-[a-zA-Z0-9]+$")).OnElements("code") ++ html := p.SanitizeBytes(unsafe) ++ ``` ++ ++* **Definition lists**. A simple definition list is made of a single-line ++ term followed by a colon and the definition for that term. ++ ++ Cat ++ : Fluffy animal everyone likes ++ ++ Internet ++ : Vector of transmission for pictures of cats ++ ++ Terms must be separated from the previous definition by a blank line. ++ ++* **Footnotes**. A marker in the text that will become a superscript number; ++ a footnote definition that will be placed in a list of footnotes at the ++ end of the document. A footnote looks like this: ++ ++ This is a footnote.[^1] ++ ++ [^1]: the footnote text. ++ ++* **Autolinking**. Blackfriday can find URLs that have not been ++ explicitly marked as links and turn them into links. ++ ++* **Strikethrough**. Use two tildes (`~~`) to mark text that ++ should be crossed out. ++ ++* **Hard line breaks**. With this extension enabled newlines in the input ++ translate into line breaks in the output. This extension is off by default. ++ ++* **Smart quotes**. Smartypants-style punctuation substitution is ++ supported, turning normal double- and single-quote marks into ++ curly quotes, etc. ++ ++* **LaTeX-style dash parsing** is an additional option, where `--` ++ is translated into `–`, and `---` is translated into ++ `—`. This differs from most smartypants processors, which ++ turn a single hyphen into an ndash and a double hyphen into an ++ mdash. ++ ++* **Smart fractions**, where anything that looks like a fraction ++ is translated into suitable HTML (instead of just a few special ++ cases like most smartypant processors). For example, `4/5` ++ becomes `45`, which renders as ++ 45. ++ ++ ++Other renderers ++--------------- ++ ++Blackfriday is structured to allow alternative rendering engines. Here ++are a few of note: ++ ++* [github_flavored_markdown](https://pkg.go.dev/github.com/shurcooL/github_flavored_markdown): ++ provides a GitHub Flavored Markdown renderer with fenced code block ++ highlighting, clickable heading anchor links. ++ ++ It's not customizable, and its goal is to produce HTML output ++ equivalent to the [GitHub Markdown API endpoint](https://developer.github.com/v3/markdown/#render-a-markdown-document-in-raw-mode), ++ except the rendering is performed locally. ++ ++* [markdownfmt](https://github.com/shurcooL/markdownfmt): like gofmt, ++ but for markdown. ++ ++* [LaTeX output](https://gitlab.com/ambrevar/blackfriday-latex): ++ renders output as LaTeX. ++ ++* [bfchroma](https://github.com/Depado/bfchroma/): provides convenience ++ integration with the [Chroma](https://github.com/alecthomas/chroma) code ++ highlighting library. bfchroma is only compatible with v2 of Blackfriday and ++ provides a drop-in renderer ready to use with Blackfriday, as well as ++ options and means for further customization. ++ ++* [Blackfriday-Confluence](https://github.com/kentaro-m/blackfriday-confluence): provides a [Confluence Wiki Markup](https://confluence.atlassian.com/doc/confluence-wiki-markup-251003035.html) renderer. ++ ++* [Blackfriday-Slack](https://github.com/karriereat/blackfriday-slack): converts markdown to slack message style ++ ++ ++TODO ++---- ++ ++* More unit testing ++* Improve Unicode support. It does not understand all Unicode ++ rules (about what constitutes a letter, a punctuation symbol, ++ etc.), so it may fail to detect word boundaries correctly in ++ some instances. It is safe on all UTF-8 input. ++ ++ ++License ++------- ++ ++[Blackfriday is distributed under the Simplified BSD License](LICENSE.txt) ++ ++ ++ [1]: https://daringfireball.net/projects/markdown/ "Markdown" ++ [2]: https://golang.org/ "Go Language" ++ [3]: https://github.com/vmg/sundown "Sundown" ++ [4]: https://pkg.go.dev/github.com/russross/blackfriday/v2#Parse "Parse func" ++ [5]: https://github.com/microcosm-cc/bluemonday "Bluemonday" ++ ++ [BuildV2SVG]: https://travis-ci.org/russross/blackfriday.svg?branch=v2 ++ [BuildV2URL]: https://travis-ci.org/russross/blackfriday ++ [PkgGoDevV2SVG]: https://pkg.go.dev/badge/github.com/russross/blackfriday/v2 ++ [PkgGoDevV2URL]: https://pkg.go.dev/github.com/russross/blackfriday/v2 +diff --git a/vendor/github.com/russross/blackfriday/v2/block.go b/vendor/github.com/russross/blackfriday/v2/block.go +new file mode 100644 +index 000000000000..dcd61e6e35bc +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/block.go +@@ -0,0 +1,1612 @@ ++// ++// Blackfriday Markdown Processor ++// Available at http://github.com/russross/blackfriday ++// ++// Copyright © 2011 Russ Ross . ++// Distributed under the Simplified BSD License. ++// See README.md for details. ++// ++ ++// ++// Functions to parse block-level elements. ++// ++ ++package blackfriday ++ ++import ( ++ "bytes" ++ "html" ++ "regexp" ++ "strings" ++ "unicode" ++) ++ ++const ( ++ charEntity = "&(?:#x[a-f0-9]{1,8}|#[0-9]{1,8}|[a-z][a-z0-9]{1,31});" ++ escapable = "[!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]" ++) ++ ++var ( ++ reBackslashOrAmp = regexp.MustCompile("[\\&]") ++ reEntityOrEscapedChar = regexp.MustCompile("(?i)\\\\" + escapable + "|" + charEntity) ++) ++ ++// Parse block-level data. ++// Note: this function and many that it calls assume that ++// the input buffer ends with a newline. ++func (p *Markdown) block(data []byte) { ++ // this is called recursively: enforce a maximum depth ++ if p.nesting >= p.maxNesting { ++ return ++ } ++ p.nesting++ ++ ++ // parse out one block-level construct at a time ++ for len(data) > 0 { ++ // prefixed heading: ++ // ++ // # Heading 1 ++ // ## Heading 2 ++ // ... ++ // ###### Heading 6 ++ if p.isPrefixHeading(data) { ++ data = data[p.prefixHeading(data):] ++ continue ++ } ++ ++ // block of preformatted HTML: ++ // ++ //
++ // ... ++ //
++ if data[0] == '<' { ++ if i := p.html(data, true); i > 0 { ++ data = data[i:] ++ continue ++ } ++ } ++ ++ // title block ++ // ++ // % stuff ++ // % more stuff ++ // % even more stuff ++ if p.extensions&Titleblock != 0 { ++ if data[0] == '%' { ++ if i := p.titleBlock(data, true); i > 0 { ++ data = data[i:] ++ continue ++ } ++ } ++ } ++ ++ // blank lines. note: returns the # of bytes to skip ++ if i := p.isEmpty(data); i > 0 { ++ data = data[i:] ++ continue ++ } ++ ++ // indented code block: ++ // ++ // func max(a, b int) int { ++ // if a > b { ++ // return a ++ // } ++ // return b ++ // } ++ if p.codePrefix(data) > 0 { ++ data = data[p.code(data):] ++ continue ++ } ++ ++ // fenced code block: ++ // ++ // ``` go ++ // func fact(n int) int { ++ // if n <= 1 { ++ // return n ++ // } ++ // return n * fact(n-1) ++ // } ++ // ``` ++ if p.extensions&FencedCode != 0 { ++ if i := p.fencedCodeBlock(data, true); i > 0 { ++ data = data[i:] ++ continue ++ } ++ } ++ ++ // horizontal rule: ++ // ++ // ------ ++ // or ++ // ****** ++ // or ++ // ______ ++ if p.isHRule(data) { ++ p.addBlock(HorizontalRule, nil) ++ var i int ++ for i = 0; i < len(data) && data[i] != '\n'; i++ { ++ } ++ data = data[i:] ++ continue ++ } ++ ++ // block quote: ++ // ++ // > A big quote I found somewhere ++ // > on the web ++ if p.quotePrefix(data) > 0 { ++ data = data[p.quote(data):] ++ continue ++ } ++ ++ // table: ++ // ++ // Name | Age | Phone ++ // ------|-----|--------- ++ // Bob | 31 | 555-1234 ++ // Alice | 27 | 555-4321 ++ if p.extensions&Tables != 0 { ++ if i := p.table(data); i > 0 { ++ data = data[i:] ++ continue ++ } ++ } ++ ++ // an itemized/unordered list: ++ // ++ // * Item 1 ++ // * Item 2 ++ // ++ // also works with + or - ++ if p.uliPrefix(data) > 0 { ++ data = data[p.list(data, 0):] ++ continue ++ } ++ ++ // a numbered/ordered list: ++ // ++ // 1. Item 1 ++ // 2. Item 2 ++ if p.oliPrefix(data) > 0 { ++ data = data[p.list(data, ListTypeOrdered):] ++ continue ++ } ++ ++ // definition lists: ++ // ++ // Term 1 ++ // : Definition a ++ // : Definition b ++ // ++ // Term 2 ++ // : Definition c ++ if p.extensions&DefinitionLists != 0 { ++ if p.dliPrefix(data) > 0 { ++ data = data[p.list(data, ListTypeDefinition):] ++ continue ++ } ++ } ++ ++ // anything else must look like a normal paragraph ++ // note: this finds underlined headings, too ++ data = data[p.paragraph(data):] ++ } ++ ++ p.nesting-- ++} ++ ++func (p *Markdown) addBlock(typ NodeType, content []byte) *Node { ++ p.closeUnmatchedBlocks() ++ container := p.addChild(typ, 0) ++ container.content = content ++ return container ++} ++ ++func (p *Markdown) isPrefixHeading(data []byte) bool { ++ if data[0] != '#' { ++ return false ++ } ++ ++ if p.extensions&SpaceHeadings != 0 { ++ level := 0 ++ for level < 6 && level < len(data) && data[level] == '#' { ++ level++ ++ } ++ if level == len(data) || data[level] != ' ' { ++ return false ++ } ++ } ++ return true ++} ++ ++func (p *Markdown) prefixHeading(data []byte) int { ++ level := 0 ++ for level < 6 && level < len(data) && data[level] == '#' { ++ level++ ++ } ++ i := skipChar(data, level, ' ') ++ end := skipUntilChar(data, i, '\n') ++ skip := end ++ id := "" ++ if p.extensions&HeadingIDs != 0 { ++ j, k := 0, 0 ++ // find start/end of heading id ++ for j = i; j < end-1 && (data[j] != '{' || data[j+1] != '#'); j++ { ++ } ++ for k = j + 1; k < end && data[k] != '}'; k++ { ++ } ++ // extract heading id iff found ++ if j < end && k < end { ++ id = string(data[j+2 : k]) ++ end = j ++ skip = k + 1 ++ for end > 0 && data[end-1] == ' ' { ++ end-- ++ } ++ } ++ } ++ for end > 0 && data[end-1] == '#' { ++ if isBackslashEscaped(data, end-1) { ++ break ++ } ++ end-- ++ } ++ for end > 0 && data[end-1] == ' ' { ++ end-- ++ } ++ if end > i { ++ if id == "" && p.extensions&AutoHeadingIDs != 0 { ++ id = SanitizedAnchorName(string(data[i:end])) ++ } ++ block := p.addBlock(Heading, data[i:end]) ++ block.HeadingID = id ++ block.Level = level ++ } ++ return skip ++} ++ ++func (p *Markdown) isUnderlinedHeading(data []byte) int { ++ // test of level 1 heading ++ if data[0] == '=' { ++ i := skipChar(data, 1, '=') ++ i = skipChar(data, i, ' ') ++ if i < len(data) && data[i] == '\n' { ++ return 1 ++ } ++ return 0 ++ } ++ ++ // test of level 2 heading ++ if data[0] == '-' { ++ i := skipChar(data, 1, '-') ++ i = skipChar(data, i, ' ') ++ if i < len(data) && data[i] == '\n' { ++ return 2 ++ } ++ return 0 ++ } ++ ++ return 0 ++} ++ ++func (p *Markdown) titleBlock(data []byte, doRender bool) int { ++ if data[0] != '%' { ++ return 0 ++ } ++ splitData := bytes.Split(data, []byte("\n")) ++ var i int ++ for idx, b := range splitData { ++ if !bytes.HasPrefix(b, []byte("%")) { ++ i = idx // - 1 ++ break ++ } ++ } ++ ++ data = bytes.Join(splitData[0:i], []byte("\n")) ++ consumed := len(data) ++ data = bytes.TrimPrefix(data, []byte("% ")) ++ data = bytes.Replace(data, []byte("\n% "), []byte("\n"), -1) ++ block := p.addBlock(Heading, data) ++ block.Level = 1 ++ block.IsTitleblock = true ++ ++ return consumed ++} ++ ++func (p *Markdown) html(data []byte, doRender bool) int { ++ var i, j int ++ ++ // identify the opening tag ++ if data[0] != '<' { ++ return 0 ++ } ++ curtag, tagfound := p.htmlFindTag(data[1:]) ++ ++ // handle special cases ++ if !tagfound { ++ // check for an HTML comment ++ if size := p.htmlComment(data, doRender); size > 0 { ++ return size ++ } ++ ++ // check for an
tag ++ if size := p.htmlHr(data, doRender); size > 0 { ++ return size ++ } ++ ++ // no special case recognized ++ return 0 ++ } ++ ++ // look for an unindented matching closing tag ++ // followed by a blank line ++ found := false ++ /* ++ closetag := []byte("\n") ++ j = len(curtag) + 1 ++ for !found { ++ // scan for a closing tag at the beginning of a line ++ if skip := bytes.Index(data[j:], closetag); skip >= 0 { ++ j += skip + len(closetag) ++ } else { ++ break ++ } ++ ++ // see if it is the only thing on the line ++ if skip := p.isEmpty(data[j:]); skip > 0 { ++ // see if it is followed by a blank line/eof ++ j += skip ++ if j >= len(data) { ++ found = true ++ i = j ++ } else { ++ if skip := p.isEmpty(data[j:]); skip > 0 { ++ j += skip ++ found = true ++ i = j ++ } ++ } ++ } ++ } ++ */ ++ ++ // if not found, try a second pass looking for indented match ++ // but not if tag is "ins" or "del" (following original Markdown.pl) ++ if !found && curtag != "ins" && curtag != "del" { ++ i = 1 ++ for i < len(data) { ++ i++ ++ for i < len(data) && !(data[i-1] == '<' && data[i] == '/') { ++ i++ ++ } ++ ++ if i+2+len(curtag) >= len(data) { ++ break ++ } ++ ++ j = p.htmlFindEnd(curtag, data[i-1:]) ++ ++ if j > 0 { ++ i += j - 1 ++ found = true ++ break ++ } ++ } ++ } ++ ++ if !found { ++ return 0 ++ } ++ ++ // the end of the block has been found ++ if doRender { ++ // trim newlines ++ end := i ++ for end > 0 && data[end-1] == '\n' { ++ end-- ++ } ++ finalizeHTMLBlock(p.addBlock(HTMLBlock, data[:end])) ++ } ++ ++ return i ++} ++ ++func finalizeHTMLBlock(block *Node) { ++ block.Literal = block.content ++ block.content = nil ++} ++ ++// HTML comment, lax form ++func (p *Markdown) htmlComment(data []byte, doRender bool) int { ++ i := p.inlineHTMLComment(data) ++ // needs to end with a blank line ++ if j := p.isEmpty(data[i:]); j > 0 { ++ size := i + j ++ if doRender { ++ // trim trailing newlines ++ end := size ++ for end > 0 && data[end-1] == '\n' { ++ end-- ++ } ++ block := p.addBlock(HTMLBlock, data[:end]) ++ finalizeHTMLBlock(block) ++ } ++ return size ++ } ++ return 0 ++} ++ ++// HR, which is the only self-closing block tag considered ++func (p *Markdown) htmlHr(data []byte, doRender bool) int { ++ if len(data) < 4 { ++ return 0 ++ } ++ if data[0] != '<' || (data[1] != 'h' && data[1] != 'H') || (data[2] != 'r' && data[2] != 'R') { ++ return 0 ++ } ++ if data[3] != ' ' && data[3] != '/' && data[3] != '>' { ++ // not an
tag after all; at least not a valid one ++ return 0 ++ } ++ i := 3 ++ for i < len(data) && data[i] != '>' && data[i] != '\n' { ++ i++ ++ } ++ if i < len(data) && data[i] == '>' { ++ i++ ++ if j := p.isEmpty(data[i:]); j > 0 { ++ size := i + j ++ if doRender { ++ // trim newlines ++ end := size ++ for end > 0 && data[end-1] == '\n' { ++ end-- ++ } ++ finalizeHTMLBlock(p.addBlock(HTMLBlock, data[:end])) ++ } ++ return size ++ } ++ } ++ return 0 ++} ++ ++func (p *Markdown) htmlFindTag(data []byte) (string, bool) { ++ i := 0 ++ for i < len(data) && isalnum(data[i]) { ++ i++ ++ } ++ key := string(data[:i]) ++ if _, ok := blockTags[key]; ok { ++ return key, true ++ } ++ return "", false ++} ++ ++func (p *Markdown) htmlFindEnd(tag string, data []byte) int { ++ // assume data[0] == '<' && data[1] == '/' already tested ++ if tag == "hr" { ++ return 2 ++ } ++ // check if tag is a match ++ closetag := []byte("") ++ if !bytes.HasPrefix(data, closetag) { ++ return 0 ++ } ++ i := len(closetag) ++ ++ // check that the rest of the line is blank ++ skip := 0 ++ if skip = p.isEmpty(data[i:]); skip == 0 { ++ return 0 ++ } ++ i += skip ++ skip = 0 ++ ++ if i >= len(data) { ++ return i ++ } ++ ++ if p.extensions&LaxHTMLBlocks != 0 { ++ return i ++ } ++ if skip = p.isEmpty(data[i:]); skip == 0 { ++ // following line must be blank ++ return 0 ++ } ++ ++ return i + skip ++} ++ ++func (*Markdown) isEmpty(data []byte) int { ++ // it is okay to call isEmpty on an empty buffer ++ if len(data) == 0 { ++ return 0 ++ } ++ ++ var i int ++ for i = 0; i < len(data) && data[i] != '\n'; i++ { ++ if data[i] != ' ' && data[i] != '\t' { ++ return 0 ++ } ++ } ++ if i < len(data) && data[i] == '\n' { ++ i++ ++ } ++ return i ++} ++ ++func (*Markdown) isHRule(data []byte) bool { ++ i := 0 ++ ++ // skip up to three spaces ++ for i < 3 && data[i] == ' ' { ++ i++ ++ } ++ ++ // look at the hrule char ++ if data[i] != '*' && data[i] != '-' && data[i] != '_' { ++ return false ++ } ++ c := data[i] ++ ++ // the whole line must be the char or whitespace ++ n := 0 ++ for i < len(data) && data[i] != '\n' { ++ switch { ++ case data[i] == c: ++ n++ ++ case data[i] != ' ': ++ return false ++ } ++ i++ ++ } ++ ++ return n >= 3 ++} ++ ++// isFenceLine checks if there's a fence line (e.g., ``` or ``` go) at the beginning of data, ++// and returns the end index if so, or 0 otherwise. It also returns the marker found. ++// If info is not nil, it gets set to the syntax specified in the fence line. ++func isFenceLine(data []byte, info *string, oldmarker string) (end int, marker string) { ++ i, size := 0, 0 ++ ++ // skip up to three spaces ++ for i < len(data) && i < 3 && data[i] == ' ' { ++ i++ ++ } ++ ++ // check for the marker characters: ~ or ` ++ if i >= len(data) { ++ return 0, "" ++ } ++ if data[i] != '~' && data[i] != '`' { ++ return 0, "" ++ } ++ ++ c := data[i] ++ ++ // the whole line must be the same char or whitespace ++ for i < len(data) && data[i] == c { ++ size++ ++ i++ ++ } ++ ++ // the marker char must occur at least 3 times ++ if size < 3 { ++ return 0, "" ++ } ++ marker = string(data[i-size : i]) ++ ++ // if this is the end marker, it must match the beginning marker ++ if oldmarker != "" && marker != oldmarker { ++ return 0, "" ++ } ++ ++ // TODO(shurcooL): It's probably a good idea to simplify the 2 code paths here ++ // into one, always get the info string, and discard it if the caller doesn't care. ++ if info != nil { ++ infoLength := 0 ++ i = skipChar(data, i, ' ') ++ ++ if i >= len(data) { ++ if i == len(data) { ++ return i, marker ++ } ++ return 0, "" ++ } ++ ++ infoStart := i ++ ++ if data[i] == '{' { ++ i++ ++ infoStart++ ++ ++ for i < len(data) && data[i] != '}' && data[i] != '\n' { ++ infoLength++ ++ i++ ++ } ++ ++ if i >= len(data) || data[i] != '}' { ++ return 0, "" ++ } ++ ++ // strip all whitespace at the beginning and the end ++ // of the {} block ++ for infoLength > 0 && isspace(data[infoStart]) { ++ infoStart++ ++ infoLength-- ++ } ++ ++ for infoLength > 0 && isspace(data[infoStart+infoLength-1]) { ++ infoLength-- ++ } ++ i++ ++ i = skipChar(data, i, ' ') ++ } else { ++ for i < len(data) && !isverticalspace(data[i]) { ++ infoLength++ ++ i++ ++ } ++ } ++ ++ *info = strings.TrimSpace(string(data[infoStart : infoStart+infoLength])) ++ } ++ ++ if i == len(data) { ++ return i, marker ++ } ++ if i > len(data) || data[i] != '\n' { ++ return 0, "" ++ } ++ return i + 1, marker // Take newline into account. ++} ++ ++// fencedCodeBlock returns the end index if data contains a fenced code block at the beginning, ++// or 0 otherwise. It writes to out if doRender is true, otherwise it has no side effects. ++// If doRender is true, a final newline is mandatory to recognize the fenced code block. ++func (p *Markdown) fencedCodeBlock(data []byte, doRender bool) int { ++ var info string ++ beg, marker := isFenceLine(data, &info, "") ++ if beg == 0 || beg >= len(data) { ++ return 0 ++ } ++ fenceLength := beg - 1 ++ ++ var work bytes.Buffer ++ work.Write([]byte(info)) ++ work.WriteByte('\n') ++ ++ for { ++ // safe to assume beg < len(data) ++ ++ // check for the end of the code block ++ fenceEnd, _ := isFenceLine(data[beg:], nil, marker) ++ if fenceEnd != 0 { ++ beg += fenceEnd ++ break ++ } ++ ++ // copy the current line ++ end := skipUntilChar(data, beg, '\n') + 1 ++ ++ // did we reach the end of the buffer without a closing marker? ++ if end >= len(data) { ++ return 0 ++ } ++ ++ // verbatim copy to the working buffer ++ if doRender { ++ work.Write(data[beg:end]) ++ } ++ beg = end ++ } ++ ++ if doRender { ++ block := p.addBlock(CodeBlock, work.Bytes()) // TODO: get rid of temp buffer ++ block.IsFenced = true ++ block.FenceLength = fenceLength ++ finalizeCodeBlock(block) ++ } ++ ++ return beg ++} ++ ++func unescapeChar(str []byte) []byte { ++ if str[0] == '\\' { ++ return []byte{str[1]} ++ } ++ return []byte(html.UnescapeString(string(str))) ++} ++ ++func unescapeString(str []byte) []byte { ++ if reBackslashOrAmp.Match(str) { ++ return reEntityOrEscapedChar.ReplaceAllFunc(str, unescapeChar) ++ } ++ return str ++} ++ ++func finalizeCodeBlock(block *Node) { ++ if block.IsFenced { ++ newlinePos := bytes.IndexByte(block.content, '\n') ++ firstLine := block.content[:newlinePos] ++ rest := block.content[newlinePos+1:] ++ block.Info = unescapeString(bytes.Trim(firstLine, "\n")) ++ block.Literal = rest ++ } else { ++ block.Literal = block.content ++ } ++ block.content = nil ++} ++ ++func (p *Markdown) table(data []byte) int { ++ table := p.addBlock(Table, nil) ++ i, columns := p.tableHeader(data) ++ if i == 0 { ++ p.tip = table.Parent ++ table.Unlink() ++ return 0 ++ } ++ ++ p.addBlock(TableBody, nil) ++ ++ for i < len(data) { ++ pipes, rowStart := 0, i ++ for ; i < len(data) && data[i] != '\n'; i++ { ++ if data[i] == '|' { ++ pipes++ ++ } ++ } ++ ++ if pipes == 0 { ++ i = rowStart ++ break ++ } ++ ++ // include the newline in data sent to tableRow ++ if i < len(data) && data[i] == '\n' { ++ i++ ++ } ++ p.tableRow(data[rowStart:i], columns, false) ++ } ++ ++ return i ++} ++ ++// check if the specified position is preceded by an odd number of backslashes ++func isBackslashEscaped(data []byte, i int) bool { ++ backslashes := 0 ++ for i-backslashes-1 >= 0 && data[i-backslashes-1] == '\\' { ++ backslashes++ ++ } ++ return backslashes&1 == 1 ++} ++ ++func (p *Markdown) tableHeader(data []byte) (size int, columns []CellAlignFlags) { ++ i := 0 ++ colCount := 1 ++ for i = 0; i < len(data) && data[i] != '\n'; i++ { ++ if data[i] == '|' && !isBackslashEscaped(data, i) { ++ colCount++ ++ } ++ } ++ ++ // doesn't look like a table header ++ if colCount == 1 { ++ return ++ } ++ ++ // include the newline in the data sent to tableRow ++ j := i ++ if j < len(data) && data[j] == '\n' { ++ j++ ++ } ++ header := data[:j] ++ ++ // column count ignores pipes at beginning or end of line ++ if data[0] == '|' { ++ colCount-- ++ } ++ if i > 2 && data[i-1] == '|' && !isBackslashEscaped(data, i-1) { ++ colCount-- ++ } ++ ++ columns = make([]CellAlignFlags, colCount) ++ ++ // move on to the header underline ++ i++ ++ if i >= len(data) { ++ return ++ } ++ ++ if data[i] == '|' && !isBackslashEscaped(data, i) { ++ i++ ++ } ++ i = skipChar(data, i, ' ') ++ ++ // each column header is of form: / *:?-+:? *|/ with # dashes + # colons >= 3 ++ // and trailing | optional on last column ++ col := 0 ++ for i < len(data) && data[i] != '\n' { ++ dashes := 0 ++ ++ if data[i] == ':' { ++ i++ ++ columns[col] |= TableAlignmentLeft ++ dashes++ ++ } ++ for i < len(data) && data[i] == '-' { ++ i++ ++ dashes++ ++ } ++ if i < len(data) && data[i] == ':' { ++ i++ ++ columns[col] |= TableAlignmentRight ++ dashes++ ++ } ++ for i < len(data) && data[i] == ' ' { ++ i++ ++ } ++ if i == len(data) { ++ return ++ } ++ // end of column test is messy ++ switch { ++ case dashes < 3: ++ // not a valid column ++ return ++ ++ case data[i] == '|' && !isBackslashEscaped(data, i): ++ // marker found, now skip past trailing whitespace ++ col++ ++ i++ ++ for i < len(data) && data[i] == ' ' { ++ i++ ++ } ++ ++ // trailing junk found after last column ++ if col >= colCount && i < len(data) && data[i] != '\n' { ++ return ++ } ++ ++ case (data[i] != '|' || isBackslashEscaped(data, i)) && col+1 < colCount: ++ // something else found where marker was required ++ return ++ ++ case data[i] == '\n': ++ // marker is optional for the last column ++ col++ ++ ++ default: ++ // trailing junk found after last column ++ return ++ } ++ } ++ if col != colCount { ++ return ++ } ++ ++ p.addBlock(TableHead, nil) ++ p.tableRow(header, columns, true) ++ size = i ++ if size < len(data) && data[size] == '\n' { ++ size++ ++ } ++ return ++} ++ ++func (p *Markdown) tableRow(data []byte, columns []CellAlignFlags, header bool) { ++ p.addBlock(TableRow, nil) ++ i, col := 0, 0 ++ ++ if data[i] == '|' && !isBackslashEscaped(data, i) { ++ i++ ++ } ++ ++ for col = 0; col < len(columns) && i < len(data); col++ { ++ for i < len(data) && data[i] == ' ' { ++ i++ ++ } ++ ++ cellStart := i ++ ++ for i < len(data) && (data[i] != '|' || isBackslashEscaped(data, i)) && data[i] != '\n' { ++ i++ ++ } ++ ++ cellEnd := i ++ ++ // skip the end-of-cell marker, possibly taking us past end of buffer ++ i++ ++ ++ for cellEnd > cellStart && cellEnd-1 < len(data) && data[cellEnd-1] == ' ' { ++ cellEnd-- ++ } ++ ++ cell := p.addBlock(TableCell, data[cellStart:cellEnd]) ++ cell.IsHeader = header ++ cell.Align = columns[col] ++ } ++ ++ // pad it out with empty columns to get the right number ++ for ; col < len(columns); col++ { ++ cell := p.addBlock(TableCell, nil) ++ cell.IsHeader = header ++ cell.Align = columns[col] ++ } ++ ++ // silently ignore rows with too many cells ++} ++ ++// returns blockquote prefix length ++func (p *Markdown) quotePrefix(data []byte) int { ++ i := 0 ++ for i < 3 && i < len(data) && data[i] == ' ' { ++ i++ ++ } ++ if i < len(data) && data[i] == '>' { ++ if i+1 < len(data) && data[i+1] == ' ' { ++ return i + 2 ++ } ++ return i + 1 ++ } ++ return 0 ++} ++ ++// blockquote ends with at least one blank line ++// followed by something without a blockquote prefix ++func (p *Markdown) terminateBlockquote(data []byte, beg, end int) bool { ++ if p.isEmpty(data[beg:]) <= 0 { ++ return false ++ } ++ if end >= len(data) { ++ return true ++ } ++ return p.quotePrefix(data[end:]) == 0 && p.isEmpty(data[end:]) == 0 ++} ++ ++// parse a blockquote fragment ++func (p *Markdown) quote(data []byte) int { ++ block := p.addBlock(BlockQuote, nil) ++ var raw bytes.Buffer ++ beg, end := 0, 0 ++ for beg < len(data) { ++ end = beg ++ // Step over whole lines, collecting them. While doing that, check for ++ // fenced code and if one's found, incorporate it altogether, ++ // irregardless of any contents inside it ++ for end < len(data) && data[end] != '\n' { ++ if p.extensions&FencedCode != 0 { ++ if i := p.fencedCodeBlock(data[end:], false); i > 0 { ++ // -1 to compensate for the extra end++ after the loop: ++ end += i - 1 ++ break ++ } ++ } ++ end++ ++ } ++ if end < len(data) && data[end] == '\n' { ++ end++ ++ } ++ if pre := p.quotePrefix(data[beg:]); pre > 0 { ++ // skip the prefix ++ beg += pre ++ } else if p.terminateBlockquote(data, beg, end) { ++ break ++ } ++ // this line is part of the blockquote ++ raw.Write(data[beg:end]) ++ beg = end ++ } ++ p.block(raw.Bytes()) ++ p.finalize(block) ++ return end ++} ++ ++// returns prefix length for block code ++func (p *Markdown) codePrefix(data []byte) int { ++ if len(data) >= 1 && data[0] == '\t' { ++ return 1 ++ } ++ if len(data) >= 4 && data[0] == ' ' && data[1] == ' ' && data[2] == ' ' && data[3] == ' ' { ++ return 4 ++ } ++ return 0 ++} ++ ++func (p *Markdown) code(data []byte) int { ++ var work bytes.Buffer ++ ++ i := 0 ++ for i < len(data) { ++ beg := i ++ for i < len(data) && data[i] != '\n' { ++ i++ ++ } ++ if i < len(data) && data[i] == '\n' { ++ i++ ++ } ++ ++ blankline := p.isEmpty(data[beg:i]) > 0 ++ if pre := p.codePrefix(data[beg:i]); pre > 0 { ++ beg += pre ++ } else if !blankline { ++ // non-empty, non-prefixed line breaks the pre ++ i = beg ++ break ++ } ++ ++ // verbatim copy to the working buffer ++ if blankline { ++ work.WriteByte('\n') ++ } else { ++ work.Write(data[beg:i]) ++ } ++ } ++ ++ // trim all the \n off the end of work ++ workbytes := work.Bytes() ++ eol := len(workbytes) ++ for eol > 0 && workbytes[eol-1] == '\n' { ++ eol-- ++ } ++ if eol != len(workbytes) { ++ work.Truncate(eol) ++ } ++ ++ work.WriteByte('\n') ++ ++ block := p.addBlock(CodeBlock, work.Bytes()) // TODO: get rid of temp buffer ++ block.IsFenced = false ++ finalizeCodeBlock(block) ++ ++ return i ++} ++ ++// returns unordered list item prefix ++func (p *Markdown) uliPrefix(data []byte) int { ++ i := 0 ++ // start with up to 3 spaces ++ for i < len(data) && i < 3 && data[i] == ' ' { ++ i++ ++ } ++ if i >= len(data)-1 { ++ return 0 ++ } ++ // need one of {'*', '+', '-'} followed by a space or a tab ++ if (data[i] != '*' && data[i] != '+' && data[i] != '-') || ++ (data[i+1] != ' ' && data[i+1] != '\t') { ++ return 0 ++ } ++ return i + 2 ++} ++ ++// returns ordered list item prefix ++func (p *Markdown) oliPrefix(data []byte) int { ++ i := 0 ++ ++ // start with up to 3 spaces ++ for i < 3 && i < len(data) && data[i] == ' ' { ++ i++ ++ } ++ ++ // count the digits ++ start := i ++ for i < len(data) && data[i] >= '0' && data[i] <= '9' { ++ i++ ++ } ++ if start == i || i >= len(data)-1 { ++ return 0 ++ } ++ ++ // we need >= 1 digits followed by a dot and a space or a tab ++ if data[i] != '.' || !(data[i+1] == ' ' || data[i+1] == '\t') { ++ return 0 ++ } ++ return i + 2 ++} ++ ++// returns definition list item prefix ++func (p *Markdown) dliPrefix(data []byte) int { ++ if len(data) < 2 { ++ return 0 ++ } ++ i := 0 ++ // need a ':' followed by a space or a tab ++ if data[i] != ':' || !(data[i+1] == ' ' || data[i+1] == '\t') { ++ return 0 ++ } ++ for i < len(data) && data[i] == ' ' { ++ i++ ++ } ++ return i + 2 ++} ++ ++// parse ordered or unordered list block ++func (p *Markdown) list(data []byte, flags ListType) int { ++ i := 0 ++ flags |= ListItemBeginningOfList ++ block := p.addBlock(List, nil) ++ block.ListFlags = flags ++ block.Tight = true ++ ++ for i < len(data) { ++ skip := p.listItem(data[i:], &flags) ++ if flags&ListItemContainsBlock != 0 { ++ block.ListData.Tight = false ++ } ++ i += skip ++ if skip == 0 || flags&ListItemEndOfList != 0 { ++ break ++ } ++ flags &= ^ListItemBeginningOfList ++ } ++ ++ above := block.Parent ++ finalizeList(block) ++ p.tip = above ++ return i ++} ++ ++// Returns true if the list item is not the same type as its parent list ++func (p *Markdown) listTypeChanged(data []byte, flags *ListType) bool { ++ if p.dliPrefix(data) > 0 && *flags&ListTypeDefinition == 0 { ++ return true ++ } else if p.oliPrefix(data) > 0 && *flags&ListTypeOrdered == 0 { ++ return true ++ } else if p.uliPrefix(data) > 0 && (*flags&ListTypeOrdered != 0 || *flags&ListTypeDefinition != 0) { ++ return true ++ } ++ return false ++} ++ ++// Returns true if block ends with a blank line, descending if needed ++// into lists and sublists. ++func endsWithBlankLine(block *Node) bool { ++ // TODO: figure this out. Always false now. ++ for block != nil { ++ //if block.lastLineBlank { ++ //return true ++ //} ++ t := block.Type ++ if t == List || t == Item { ++ block = block.LastChild ++ } else { ++ break ++ } ++ } ++ return false ++} ++ ++func finalizeList(block *Node) { ++ block.open = false ++ item := block.FirstChild ++ for item != nil { ++ // check for non-final list item ending with blank line: ++ if endsWithBlankLine(item) && item.Next != nil { ++ block.ListData.Tight = false ++ break ++ } ++ // recurse into children of list item, to see if there are spaces ++ // between any of them: ++ subItem := item.FirstChild ++ for subItem != nil { ++ if endsWithBlankLine(subItem) && (item.Next != nil || subItem.Next != nil) { ++ block.ListData.Tight = false ++ break ++ } ++ subItem = subItem.Next ++ } ++ item = item.Next ++ } ++} ++ ++// Parse a single list item. ++// Assumes initial prefix is already removed if this is a sublist. ++func (p *Markdown) listItem(data []byte, flags *ListType) int { ++ // keep track of the indentation of the first line ++ itemIndent := 0 ++ if data[0] == '\t' { ++ itemIndent += 4 ++ } else { ++ for itemIndent < 3 && data[itemIndent] == ' ' { ++ itemIndent++ ++ } ++ } ++ ++ var bulletChar byte = '*' ++ i := p.uliPrefix(data) ++ if i == 0 { ++ i = p.oliPrefix(data) ++ } else { ++ bulletChar = data[i-2] ++ } ++ if i == 0 { ++ i = p.dliPrefix(data) ++ // reset definition term flag ++ if i > 0 { ++ *flags &= ^ListTypeTerm ++ } ++ } ++ if i == 0 { ++ // if in definition list, set term flag and continue ++ if *flags&ListTypeDefinition != 0 { ++ *flags |= ListTypeTerm ++ } else { ++ return 0 ++ } ++ } ++ ++ // skip leading whitespace on first line ++ for i < len(data) && data[i] == ' ' { ++ i++ ++ } ++ ++ // find the end of the line ++ line := i ++ for i > 0 && i < len(data) && data[i-1] != '\n' { ++ i++ ++ } ++ ++ // get working buffer ++ var raw bytes.Buffer ++ ++ // put the first line into the working buffer ++ raw.Write(data[line:i]) ++ line = i ++ ++ // process the following lines ++ containsBlankLine := false ++ sublist := 0 ++ codeBlockMarker := "" ++ ++gatherlines: ++ for line < len(data) { ++ i++ ++ ++ // find the end of this line ++ for i < len(data) && data[i-1] != '\n' { ++ i++ ++ } ++ ++ // if it is an empty line, guess that it is part of this item ++ // and move on to the next line ++ if p.isEmpty(data[line:i]) > 0 { ++ containsBlankLine = true ++ line = i ++ continue ++ } ++ ++ // calculate the indentation ++ indent := 0 ++ indentIndex := 0 ++ if data[line] == '\t' { ++ indentIndex++ ++ indent += 4 ++ } else { ++ for indent < 4 && line+indent < i && data[line+indent] == ' ' { ++ indent++ ++ indentIndex++ ++ } ++ } ++ ++ chunk := data[line+indentIndex : i] ++ ++ if p.extensions&FencedCode != 0 { ++ // determine if in or out of codeblock ++ // if in codeblock, ignore normal list processing ++ _, marker := isFenceLine(chunk, nil, codeBlockMarker) ++ if marker != "" { ++ if codeBlockMarker == "" { ++ // start of codeblock ++ codeBlockMarker = marker ++ } else { ++ // end of codeblock. ++ codeBlockMarker = "" ++ } ++ } ++ // we are in a codeblock, write line, and continue ++ if codeBlockMarker != "" || marker != "" { ++ raw.Write(data[line+indentIndex : i]) ++ line = i ++ continue gatherlines ++ } ++ } ++ ++ // evaluate how this line fits in ++ switch { ++ // is this a nested list item? ++ case (p.uliPrefix(chunk) > 0 && !p.isHRule(chunk)) || ++ p.oliPrefix(chunk) > 0 || ++ p.dliPrefix(chunk) > 0: ++ ++ // to be a nested list, it must be indented more ++ // if not, it is either a different kind of list ++ // or the next item in the same list ++ if indent <= itemIndent { ++ if p.listTypeChanged(chunk, flags) { ++ *flags |= ListItemEndOfList ++ } else if containsBlankLine { ++ *flags |= ListItemContainsBlock ++ } ++ ++ break gatherlines ++ } ++ ++ if containsBlankLine { ++ *flags |= ListItemContainsBlock ++ } ++ ++ // is this the first item in the nested list? ++ if sublist == 0 { ++ sublist = raw.Len() ++ } ++ ++ // is this a nested prefix heading? ++ case p.isPrefixHeading(chunk): ++ // if the heading is not indented, it is not nested in the list ++ // and thus ends the list ++ if containsBlankLine && indent < 4 { ++ *flags |= ListItemEndOfList ++ break gatherlines ++ } ++ *flags |= ListItemContainsBlock ++ ++ // anything following an empty line is only part ++ // of this item if it is indented 4 spaces ++ // (regardless of the indentation of the beginning of the item) ++ case containsBlankLine && indent < 4: ++ if *flags&ListTypeDefinition != 0 && i < len(data)-1 { ++ // is the next item still a part of this list? ++ next := i ++ for next < len(data) && data[next] != '\n' { ++ next++ ++ } ++ for next < len(data)-1 && data[next] == '\n' { ++ next++ ++ } ++ if i < len(data)-1 && data[i] != ':' && data[next] != ':' { ++ *flags |= ListItemEndOfList ++ } ++ } else { ++ *flags |= ListItemEndOfList ++ } ++ break gatherlines ++ ++ // a blank line means this should be parsed as a block ++ case containsBlankLine: ++ raw.WriteByte('\n') ++ *flags |= ListItemContainsBlock ++ } ++ ++ // if this line was preceded by one or more blanks, ++ // re-introduce the blank into the buffer ++ if containsBlankLine { ++ containsBlankLine = false ++ raw.WriteByte('\n') ++ } ++ ++ // add the line into the working buffer without prefix ++ raw.Write(data[line+indentIndex : i]) ++ ++ line = i ++ } ++ ++ rawBytes := raw.Bytes() ++ ++ block := p.addBlock(Item, nil) ++ block.ListFlags = *flags ++ block.Tight = false ++ block.BulletChar = bulletChar ++ block.Delimiter = '.' // Only '.' is possible in Markdown, but ')' will also be possible in CommonMark ++ ++ // render the contents of the list item ++ if *flags&ListItemContainsBlock != 0 && *flags&ListTypeTerm == 0 { ++ // intermediate render of block item, except for definition term ++ if sublist > 0 { ++ p.block(rawBytes[:sublist]) ++ p.block(rawBytes[sublist:]) ++ } else { ++ p.block(rawBytes) ++ } ++ } else { ++ // intermediate render of inline item ++ if sublist > 0 { ++ child := p.addChild(Paragraph, 0) ++ child.content = rawBytes[:sublist] ++ p.block(rawBytes[sublist:]) ++ } else { ++ child := p.addChild(Paragraph, 0) ++ child.content = rawBytes ++ } ++ } ++ return line ++} ++ ++// render a single paragraph that has already been parsed out ++func (p *Markdown) renderParagraph(data []byte) { ++ if len(data) == 0 { ++ return ++ } ++ ++ // trim leading spaces ++ beg := 0 ++ for data[beg] == ' ' { ++ beg++ ++ } ++ ++ end := len(data) ++ // trim trailing newline ++ if data[len(data)-1] == '\n' { ++ end-- ++ } ++ ++ // trim trailing spaces ++ for end > beg && data[end-1] == ' ' { ++ end-- ++ } ++ ++ p.addBlock(Paragraph, data[beg:end]) ++} ++ ++func (p *Markdown) paragraph(data []byte) int { ++ // prev: index of 1st char of previous line ++ // line: index of 1st char of current line ++ // i: index of cursor/end of current line ++ var prev, line, i int ++ tabSize := TabSizeDefault ++ if p.extensions&TabSizeEight != 0 { ++ tabSize = TabSizeDouble ++ } ++ // keep going until we find something to mark the end of the paragraph ++ for i < len(data) { ++ // mark the beginning of the current line ++ prev = line ++ current := data[i:] ++ line = i ++ ++ // did we find a reference or a footnote? If so, end a paragraph ++ // preceding it and report that we have consumed up to the end of that ++ // reference: ++ if refEnd := isReference(p, current, tabSize); refEnd > 0 { ++ p.renderParagraph(data[:i]) ++ return i + refEnd ++ } ++ ++ // did we find a blank line marking the end of the paragraph? ++ if n := p.isEmpty(current); n > 0 { ++ // did this blank line followed by a definition list item? ++ if p.extensions&DefinitionLists != 0 { ++ if i < len(data)-1 && data[i+1] == ':' { ++ return p.list(data[prev:], ListTypeDefinition) ++ } ++ } ++ ++ p.renderParagraph(data[:i]) ++ return i + n ++ } ++ ++ // an underline under some text marks a heading, so our paragraph ended on prev line ++ if i > 0 { ++ if level := p.isUnderlinedHeading(current); level > 0 { ++ // render the paragraph ++ p.renderParagraph(data[:prev]) ++ ++ // ignore leading and trailing whitespace ++ eol := i - 1 ++ for prev < eol && data[prev] == ' ' { ++ prev++ ++ } ++ for eol > prev && data[eol-1] == ' ' { ++ eol-- ++ } ++ ++ id := "" ++ if p.extensions&AutoHeadingIDs != 0 { ++ id = SanitizedAnchorName(string(data[prev:eol])) ++ } ++ ++ block := p.addBlock(Heading, data[prev:eol]) ++ block.Level = level ++ block.HeadingID = id ++ ++ // find the end of the underline ++ for i < len(data) && data[i] != '\n' { ++ i++ ++ } ++ return i ++ } ++ } ++ ++ // if the next line starts a block of HTML, then the paragraph ends here ++ if p.extensions&LaxHTMLBlocks != 0 { ++ if data[i] == '<' && p.html(current, false) > 0 { ++ // rewind to before the HTML block ++ p.renderParagraph(data[:i]) ++ return i ++ } ++ } ++ ++ // if there's a prefixed heading or a horizontal rule after this, paragraph is over ++ if p.isPrefixHeading(current) || p.isHRule(current) { ++ p.renderParagraph(data[:i]) ++ return i ++ } ++ ++ // if there's a fenced code block, paragraph is over ++ if p.extensions&FencedCode != 0 { ++ if p.fencedCodeBlock(current, false) > 0 { ++ p.renderParagraph(data[:i]) ++ return i ++ } ++ } ++ ++ // if there's a definition list item, prev line is a definition term ++ if p.extensions&DefinitionLists != 0 { ++ if p.dliPrefix(current) != 0 { ++ ret := p.list(data[prev:], ListTypeDefinition) ++ return ret ++ } ++ } ++ ++ // if there's a list after this, paragraph is over ++ if p.extensions&NoEmptyLineBeforeBlock != 0 { ++ if p.uliPrefix(current) != 0 || ++ p.oliPrefix(current) != 0 || ++ p.quotePrefix(current) != 0 || ++ p.codePrefix(current) != 0 { ++ p.renderParagraph(data[:i]) ++ return i ++ } ++ } ++ ++ // otherwise, scan to the beginning of the next line ++ nl := bytes.IndexByte(data[i:], '\n') ++ if nl >= 0 { ++ i += nl + 1 ++ } else { ++ i += len(data[i:]) ++ } ++ } ++ ++ p.renderParagraph(data[:i]) ++ return i ++} ++ ++func skipChar(data []byte, start int, char byte) int { ++ i := start ++ for i < len(data) && data[i] == char { ++ i++ ++ } ++ return i ++} ++ ++func skipUntilChar(text []byte, start int, char byte) int { ++ i := start ++ for i < len(text) && text[i] != char { ++ i++ ++ } ++ return i ++} ++ ++// SanitizedAnchorName returns a sanitized anchor name for the given text. ++// ++// It implements the algorithm specified in the package comment. ++func SanitizedAnchorName(text string) string { ++ var anchorName []rune ++ futureDash := false ++ for _, r := range text { ++ switch { ++ case unicode.IsLetter(r) || unicode.IsNumber(r): ++ if futureDash && len(anchorName) > 0 { ++ anchorName = append(anchorName, '-') ++ } ++ futureDash = false ++ anchorName = append(anchorName, unicode.ToLower(r)) ++ default: ++ futureDash = true ++ } ++ } ++ return string(anchorName) ++} +diff --git a/vendor/github.com/russross/blackfriday/v2/doc.go b/vendor/github.com/russross/blackfriday/v2/doc.go +new file mode 100644 +index 000000000000..57ff152a0568 +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/doc.go +@@ -0,0 +1,46 @@ ++// Package blackfriday is a markdown processor. ++// ++// It translates plain text with simple formatting rules into an AST, which can ++// then be further processed to HTML (provided by Blackfriday itself) or other ++// formats (provided by the community). ++// ++// The simplest way to invoke Blackfriday is to call the Run function. It will ++// take a text input and produce a text output in HTML (or other format). ++// ++// A slightly more sophisticated way to use Blackfriday is to create a Markdown ++// processor and to call Parse, which returns a syntax tree for the input ++// document. You can leverage Blackfriday's parsing for content extraction from ++// markdown documents. You can assign a custom renderer and set various options ++// to the Markdown processor. ++// ++// If you're interested in calling Blackfriday from command line, see ++// https://github.com/russross/blackfriday-tool. ++// ++// Sanitized Anchor Names ++// ++// Blackfriday includes an algorithm for creating sanitized anchor names ++// corresponding to a given input text. This algorithm is used to create ++// anchors for headings when AutoHeadingIDs extension is enabled. The ++// algorithm is specified below, so that other packages can create ++// compatible anchor names and links to those anchors. ++// ++// The algorithm iterates over the input text, interpreted as UTF-8, ++// one Unicode code point (rune) at a time. All runes that are letters (category L) ++// or numbers (category N) are considered valid characters. They are mapped to ++// lower case, and included in the output. All other runes are considered ++// invalid characters. Invalid characters that precede the first valid character, ++// as well as invalid character that follow the last valid character ++// are dropped completely. All other sequences of invalid characters ++// between two valid characters are replaced with a single dash character '-'. ++// ++// SanitizedAnchorName exposes this functionality, and can be used to ++// create compatible links to the anchor names generated by blackfriday. ++// This algorithm is also implemented in a small standalone package at ++// github.com/shurcooL/sanitized_anchor_name. It can be useful for clients ++// that want a small package and don't need full functionality of blackfriday. ++package blackfriday ++ ++// NOTE: Keep Sanitized Anchor Name algorithm in sync with package ++// github.com/shurcooL/sanitized_anchor_name. ++// Otherwise, users of sanitized_anchor_name will get anchor names ++// that are incompatible with those generated by blackfriday. +diff --git a/vendor/github.com/russross/blackfriday/v2/entities.go b/vendor/github.com/russross/blackfriday/v2/entities.go +new file mode 100644 +index 000000000000..a2c3edb691c8 +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/entities.go +@@ -0,0 +1,2236 @@ ++package blackfriday ++ ++// Extracted from https://html.spec.whatwg.org/multipage/entities.json ++var entities = map[string]bool{ ++ "Æ": true, ++ "Æ": true, ++ "&": true, ++ "&": true, ++ "Á": true, ++ "Á": true, ++ "Ă": true, ++ "Â": true, ++ "Â": true, ++ "А": true, ++ "𝔄": true, ++ "À": true, ++ "À": true, ++ "Α": true, ++ "Ā": true, ++ "⩓": true, ++ "Ą": true, ++ "𝔸": true, ++ "⁡": true, ++ "Å": true, ++ "Å": true, ++ "𝒜": true, ++ "≔": true, ++ "Ã": true, ++ "Ã": true, ++ "Ä": true, ++ "Ä": true, ++ "∖": true, ++ "⫧": true, ++ "⌆": true, ++ "Б": true, ++ "∵": true, ++ "ℬ": true, ++ "Β": true, ++ "𝔅": true, ++ "𝔹": true, ++ "˘": true, ++ "ℬ": true, ++ "≎": true, ++ "Ч": true, ++ "©": true, ++ "©": true, ++ "Ć": true, ++ "⋒": true, ++ "ⅅ": true, ++ "ℭ": true, ++ "Č": true, ++ "Ç": true, ++ "Ç": true, ++ "Ĉ": true, ++ "∰": true, ++ "Ċ": true, ++ "¸": true, ++ "·": true, ++ "ℭ": true, ++ "Χ": true, ++ "⊙": true, ++ "⊖": true, ++ "⊕": true, ++ "⊗": true, ++ "∲": true, ++ "”": true, ++ "’": true, ++ "∷": true, ++ "⩴": true, ++ "≡": true, ++ "∯": true, ++ "∮": true, ++ "ℂ": true, ++ "∐": true, ++ "∳": true, ++ "⨯": true, ++ "𝒞": true, ++ "⋓": true, ++ "≍": true, ++ "ⅅ": true, ++ "⤑": true, ++ "Ђ": true, ++ "Ѕ": true, ++ "Џ": true, ++ "‡": true, ++ "↡": true, ++ "⫤": true, ++ "Ď": true, ++ "Д": true, ++ "∇": true, ++ "Δ": true, ++ "𝔇": true, ++ "´": true, ++ "˙": true, ++ "˝": true, ++ "`": true, ++ "˜": true, ++ "⋄": true, ++ "ⅆ": true, ++ "𝔻": true, ++ "¨": true, ++ "⃜": true, ++ "≐": true, ++ "∯": true, ++ "¨": true, ++ "⇓": true, ++ "⇐": true, ++ "⇔": true, ++ "⫤": true, ++ "⟸": true, ++ "⟺": true, ++ "⟹": true, ++ "⇒": true, ++ "⊨": true, ++ "⇑": true, ++ "⇕": true, ++ "∥": true, ++ "↓": true, ++ "⤓": true, ++ "⇵": true, ++ "̑": true, ++ "⥐": true, ++ "⥞": true, ++ "↽": true, ++ "⥖": true, ++ "⥟": true, ++ "⇁": true, ++ "⥗": true, ++ "⊤": true, ++ "↧": true, ++ "⇓": true, ++ "𝒟": true, ++ "Đ": true, ++ "Ŋ": true, ++ "Ð": true, ++ "Ð": true, ++ "É": true, ++ "É": true, ++ "Ě": true, ++ "Ê": true, ++ "Ê": true, ++ "Э": true, ++ "Ė": true, ++ "𝔈": true, ++ "È": true, ++ "È": true, ++ "∈": true, ++ "Ē": true, ++ "◻": true, ++ "▫": true, ++ "Ę": true, ++ "𝔼": true, ++ "Ε": true, ++ "⩵": true, ++ "≂": true, ++ "⇌": true, ++ "ℰ": true, ++ "⩳": true, ++ "Η": true, ++ "Ë": true, ++ "Ë": true, ++ "∃": true, ++ "ⅇ": true, ++ "Ф": true, ++ "𝔉": true, ++ "◼": true, ++ "▪": true, ++ "𝔽": true, ++ "∀": true, ++ "ℱ": true, ++ "ℱ": true, ++ "Ѓ": true, ++ ">": true, ++ ">": true, ++ "Γ": true, ++ "Ϝ": true, ++ "Ğ": true, ++ "Ģ": true, ++ "Ĝ": true, ++ "Г": true, ++ "Ġ": true, ++ "𝔊": true, ++ "⋙": true, ++ "𝔾": true, ++ "≥": true, ++ "⋛": true, ++ "≧": true, ++ "⪢": true, ++ "≷": true, ++ "⩾": true, ++ "≳": true, ++ "𝒢": true, ++ "≫": true, ++ "Ъ": true, ++ "ˇ": true, ++ "^": true, ++ "Ĥ": true, ++ "ℌ": true, ++ "ℋ": true, ++ "ℍ": true, ++ "─": true, ++ "ℋ": true, ++ "Ħ": true, ++ "≎": true, ++ "≏": true, ++ "Е": true, ++ "IJ": true, ++ "Ё": true, ++ "Í": true, ++ "Í": true, ++ "Î": true, ++ "Î": true, ++ "И": true, ++ "İ": true, ++ "ℑ": true, ++ "Ì": true, ++ "Ì": true, ++ "ℑ": true, ++ "Ī": true, ++ "ⅈ": true, ++ "⇒": true, ++ "∬": true, ++ "∫": true, ++ "⋂": true, ++ "⁣": true, ++ "⁢": true, ++ "Į": true, ++ "𝕀": true, ++ "Ι": true, ++ "ℐ": true, ++ "Ĩ": true, ++ "І": true, ++ "Ï": true, ++ "Ï": true, ++ "Ĵ": true, ++ "Й": true, ++ "𝔍": true, ++ "𝕁": true, ++ "𝒥": true, ++ "Ј": true, ++ "Є": true, ++ "Х": true, ++ "Ќ": true, ++ "Κ": true, ++ "Ķ": true, ++ "К": true, ++ "𝔎": true, ++ "𝕂": true, ++ "𝒦": true, ++ "Љ": true, ++ "<": true, ++ "<": true, ++ "Ĺ": true, ++ "Λ": true, ++ "⟪": true, ++ "ℒ": true, ++ "↞": true, ++ "Ľ": true, ++ "Ļ": true, ++ "Л": true, ++ "⟨": true, ++ "←": true, ++ "⇤": true, ++ "⇆": true, ++ "⌈": true, ++ "⟦": true, ++ "⥡": true, ++ "⇃": true, ++ "⥙": true, ++ "⌊": true, ++ "↔": true, ++ "⥎": true, ++ "⊣": true, ++ "↤": true, ++ "⥚": true, ++ "⊲": true, ++ "⧏": true, ++ "⊴": true, ++ "⥑": true, ++ "⥠": true, ++ "↿": true, ++ "⥘": true, ++ "↼": true, ++ "⥒": true, ++ "⇐": true, ++ "⇔": true, ++ "⋚": true, ++ "≦": true, ++ "≶": true, ++ "⪡": true, ++ "⩽": true, ++ "≲": true, ++ "𝔏": true, ++ "⋘": true, ++ "⇚": true, ++ "Ŀ": true, ++ "⟵": true, ++ "⟷": true, ++ "⟶": true, ++ "⟸": true, ++ "⟺": true, ++ "⟹": true, ++ "𝕃": true, ++ "↙": true, ++ "↘": true, ++ "ℒ": true, ++ "↰": true, ++ "Ł": true, ++ "≪": true, ++ "⤅": true, ++ "М": true, ++ " ": true, ++ "ℳ": true, ++ "𝔐": true, ++ "∓": true, ++ "𝕄": true, ++ "ℳ": true, ++ "Μ": true, ++ "Њ": true, ++ "Ń": true, ++ "Ň": true, ++ "Ņ": true, ++ "Н": true, ++ "​": true, ++ "​": true, ++ "​": true, ++ "​": true, ++ "≫": true, ++ "≪": true, ++ " ": true, ++ "𝔑": true, ++ "⁠": true, ++ " ": true, ++ "ℕ": true, ++ "⫬": true, ++ "≢": true, ++ "≭": true, ++ "∦": true, ++ "∉": true, ++ "≠": true, ++ "≂̸": true, ++ "∄": true, ++ "≯": true, ++ "≱": true, ++ "≧̸": true, ++ "≫̸": true, ++ "≹": true, ++ "⩾̸": true, ++ "≵": true, ++ "≎̸": true, ++ "≏̸": true, ++ "⋪": true, ++ "⧏̸": true, ++ "⋬": true, ++ "≮": true, ++ "≰": true, ++ "≸": true, ++ "≪̸": true, ++ "⩽̸": true, ++ "≴": true, ++ "⪢̸": true, ++ "⪡̸": true, ++ "⊀": true, ++ "⪯̸": true, ++ "⋠": true, ++ "∌": true, ++ "⋫": true, ++ "⧐̸": true, ++ "⋭": true, ++ "⊏̸": true, ++ "⋢": true, ++ "⊐̸": true, ++ "⋣": true, ++ "⊂⃒": true, ++ "⊈": true, ++ "⊁": true, ++ "⪰̸": true, ++ "⋡": true, ++ "≿̸": true, ++ "⊃⃒": true, ++ "⊉": true, ++ "≁": true, ++ "≄": true, ++ "≇": true, ++ "≉": true, ++ "∤": true, ++ "𝒩": true, ++ "Ñ": true, ++ "Ñ": true, ++ "Ν": true, ++ "Œ": true, ++ "Ó": true, ++ "Ó": true, ++ "Ô": true, ++ "Ô": true, ++ "О": true, ++ "Ő": true, ++ "𝔒": true, ++ "Ò": true, ++ "Ò": true, ++ "Ō": true, ++ "Ω": true, ++ "Ο": true, ++ "𝕆": true, ++ "“": true, ++ "‘": true, ++ "⩔": true, ++ "𝒪": true, ++ "Ø": true, ++ "Ø": true, ++ "Õ": true, ++ "Õ": true, ++ "⨷": true, ++ "Ö": true, ++ "Ö": true, ++ "‾": true, ++ "⏞": true, ++ "⎴": true, ++ "⏜": true, ++ "∂": true, ++ "П": true, ++ "𝔓": true, ++ "Φ": true, ++ "Π": true, ++ "±": true, ++ "ℌ": true, ++ "ℙ": true, ++ "⪻": true, ++ "≺": true, ++ "⪯": true, ++ "≼": true, ++ "≾": true, ++ "″": true, ++ "∏": true, ++ "∷": true, ++ "∝": true, ++ "𝒫": true, ++ "Ψ": true, ++ """: true, ++ """: true, ++ "𝔔": true, ++ "ℚ": true, ++ "𝒬": true, ++ "⤐": true, ++ "®": true, ++ "®": true, ++ "Ŕ": true, ++ "⟫": true, ++ "↠": true, ++ "⤖": true, ++ "Ř": true, ++ "Ŗ": true, ++ "Р": true, ++ "ℜ": true, ++ "∋": true, ++ "⇋": true, ++ "⥯": true, ++ "ℜ": true, ++ "Ρ": true, ++ "⟩": true, ++ "→": true, ++ "⇥": true, ++ "⇄": true, ++ "⌉": true, ++ "⟧": true, ++ "⥝": true, ++ "⇂": true, ++ "⥕": true, ++ "⌋": true, ++ "⊢": true, ++ "↦": true, ++ "⥛": true, ++ "⊳": true, ++ "⧐": true, ++ "⊵": true, ++ "⥏": true, ++ "⥜": true, ++ "↾": true, ++ "⥔": true, ++ "⇀": true, ++ "⥓": true, ++ "⇒": true, ++ "ℝ": true, ++ "⥰": true, ++ "⇛": true, ++ "ℛ": true, ++ "↱": true, ++ "⧴": true, ++ "Щ": true, ++ "Ш": true, ++ "Ь": true, ++ "Ś": true, ++ "⪼": true, ++ "Š": true, ++ "Ş": true, ++ "Ŝ": true, ++ "С": true, ++ "𝔖": true, ++ "↓": true, ++ "←": true, ++ "→": true, ++ "↑": true, ++ "Σ": true, ++ "∘": true, ++ "𝕊": true, ++ "√": true, ++ "□": true, ++ "⊓": true, ++ "⊏": true, ++ "⊑": true, ++ "⊐": true, ++ "⊒": true, ++ "⊔": true, ++ "𝒮": true, ++ "⋆": true, ++ "⋐": true, ++ "⋐": true, ++ "⊆": true, ++ "≻": true, ++ "⪰": true, ++ "≽": true, ++ "≿": true, ++ "∋": true, ++ "∑": true, ++ "⋑": true, ++ "⊃": true, ++ "⊇": true, ++ "⋑": true, ++ "Þ": true, ++ "Þ": true, ++ "™": true, ++ "Ћ": true, ++ "Ц": true, ++ " ": true, ++ "Τ": true, ++ "Ť": true, ++ "Ţ": true, ++ "Т": true, ++ "𝔗": true, ++ "∴": true, ++ "Θ": true, ++ "  ": true, ++ " ": true, ++ "∼": true, ++ "≃": true, ++ "≅": true, ++ "≈": true, ++ "𝕋": true, ++ "⃛": true, ++ "𝒯": true, ++ "Ŧ": true, ++ "Ú": true, ++ "Ú": true, ++ "↟": true, ++ "⥉": true, ++ "Ў": true, ++ "Ŭ": true, ++ "Û": true, ++ "Û": true, ++ "У": true, ++ "Ű": true, ++ "𝔘": true, ++ "Ù": true, ++ "Ù": true, ++ "Ū": true, ++ "_": true, ++ "⏟": true, ++ "⎵": true, ++ "⏝": true, ++ "⋃": true, ++ "⊎": true, ++ "Ų": true, ++ "𝕌": true, ++ "↑": true, ++ "⤒": true, ++ "⇅": true, ++ "↕": true, ++ "⥮": true, ++ "⊥": true, ++ "↥": true, ++ "⇑": true, ++ "⇕": true, ++ "↖": true, ++ "↗": true, ++ "ϒ": true, ++ "Υ": true, ++ "Ů": true, ++ "𝒰": true, ++ "Ũ": true, ++ "Ü": true, ++ "Ü": true, ++ "⊫": true, ++ "⫫": true, ++ "В": true, ++ "⊩": true, ++ "⫦": true, ++ "⋁": true, ++ "‖": true, ++ "‖": true, ++ "∣": true, ++ "|": true, ++ "❘": true, ++ "≀": true, ++ " ": true, ++ "𝔙": true, ++ "𝕍": true, ++ "𝒱": true, ++ "⊪": true, ++ "Ŵ": true, ++ "⋀": true, ++ "𝔚": true, ++ "𝕎": true, ++ "𝒲": true, ++ "𝔛": true, ++ "Ξ": true, ++ "𝕏": true, ++ "𝒳": true, ++ "Я": true, ++ "Ї": true, ++ "Ю": true, ++ "Ý": true, ++ "Ý": true, ++ "Ŷ": true, ++ "Ы": true, ++ "𝔜": true, ++ "𝕐": true, ++ "𝒴": true, ++ "Ÿ": true, ++ "Ж": true, ++ "Ź": true, ++ "Ž": true, ++ "З": true, ++ "Ż": true, ++ "​": true, ++ "Ζ": true, ++ "ℨ": true, ++ "ℤ": true, ++ "𝒵": true, ++ "á": true, ++ "á": true, ++ "ă": true, ++ "∾": true, ++ "∾̳": true, ++ "∿": true, ++ "â": true, ++ "â": true, ++ "´": true, ++ "´": true, ++ "а": true, ++ "æ": true, ++ "æ": true, ++ "⁡": true, ++ "𝔞": true, ++ "à": true, ++ "à": true, ++ "ℵ": true, ++ "ℵ": true, ++ "α": true, ++ "ā": true, ++ "⨿": true, ++ "&": true, ++ "&": true, ++ "∧": true, ++ "⩕": true, ++ "⩜": true, ++ "⩘": true, ++ "⩚": true, ++ "∠": true, ++ "⦤": true, ++ "∠": true, ++ "∡": true, ++ "⦨": true, ++ "⦩": true, ++ "⦪": true, ++ "⦫": true, ++ "⦬": true, ++ "⦭": true, ++ "⦮": true, ++ "⦯": true, ++ "∟": true, ++ "⊾": true, ++ "⦝": true, ++ "∢": true, ++ "Å": true, ++ "⍼": true, ++ "ą": true, ++ "𝕒": true, ++ "≈": true, ++ "⩰": true, ++ "⩯": true, ++ "≊": true, ++ "≋": true, ++ "'": true, ++ "≈": true, ++ "≊": true, ++ "å": true, ++ "å": true, ++ "𝒶": true, ++ "*": true, ++ "≈": true, ++ "≍": true, ++ "ã": true, ++ "ã": true, ++ "ä": true, ++ "ä": true, ++ "∳": true, ++ "⨑": true, ++ "⫭": true, ++ "≌": true, ++ "϶": true, ++ "‵": true, ++ "∽": true, ++ "⋍": true, ++ "⊽": true, ++ "⌅": true, ++ "⌅": true, ++ "⎵": true, ++ "⎶": true, ++ "≌": true, ++ "б": true, ++ "„": true, ++ "∵": true, ++ "∵": true, ++ "⦰": true, ++ "϶": true, ++ "ℬ": true, ++ "β": true, ++ "ℶ": true, ++ "≬": true, ++ "𝔟": true, ++ "⋂": true, ++ "◯": true, ++ "⋃": true, ++ "⨀": true, ++ "⨁": true, ++ "⨂": true, ++ "⨆": true, ++ "★": true, ++ "▽": true, ++ "△": true, ++ "⨄": true, ++ "⋁": true, ++ "⋀": true, ++ "⤍": true, ++ "⧫": true, ++ "▪": true, ++ "▴": true, ++ "▾": true, ++ "◂": true, ++ "▸": true, ++ "␣": true, ++ "▒": true, ++ "░": true, ++ "▓": true, ++ "█": true, ++ "=⃥": true, ++ "≡⃥": true, ++ "⌐": true, ++ "𝕓": true, ++ "⊥": true, ++ "⊥": true, ++ "⋈": true, ++ "╗": true, ++ "╔": true, ++ "╖": true, ++ "╓": true, ++ "═": true, ++ "╦": true, ++ "╩": true, ++ "╤": true, ++ "╧": true, ++ "╝": true, ++ "╚": true, ++ "╜": true, ++ "╙": true, ++ "║": true, ++ "╬": true, ++ "╣": true, ++ "╠": true, ++ "╫": true, ++ "╢": true, ++ "╟": true, ++ "⧉": true, ++ "╕": true, ++ "╒": true, ++ "┐": true, ++ "┌": true, ++ "─": true, ++ "╥": true, ++ "╨": true, ++ "┬": true, ++ "┴": true, ++ "⊟": true, ++ "⊞": true, ++ "⊠": true, ++ "╛": true, ++ "╘": true, ++ "┘": true, ++ "└": true, ++ "│": true, ++ "╪": true, ++ "╡": true, ++ "╞": true, ++ "┼": true, ++ "┤": true, ++ "├": true, ++ "‵": true, ++ "˘": true, ++ "¦": true, ++ "¦": true, ++ "𝒷": true, ++ "⁏": true, ++ "∽": true, ++ "⋍": true, ++ "\": true, ++ "⧅": true, ++ "⟈": true, ++ "•": true, ++ "•": true, ++ "≎": true, ++ "⪮": true, ++ "≏": true, ++ "≏": true, ++ "ć": true, ++ "∩": true, ++ "⩄": true, ++ "⩉": true, ++ "⩋": true, ++ "⩇": true, ++ "⩀": true, ++ "∩︀": true, ++ "⁁": true, ++ "ˇ": true, ++ "⩍": true, ++ "č": true, ++ "ç": true, ++ "ç": true, ++ "ĉ": true, ++ "⩌": true, ++ "⩐": true, ++ "ċ": true, ++ "¸": true, ++ "¸": true, ++ "⦲": true, ++ "¢": true, ++ "¢": true, ++ "·": true, ++ "𝔠": true, ++ "ч": true, ++ "✓": true, ++ "✓": true, ++ "χ": true, ++ "○": true, ++ "⧃": true, ++ "ˆ": true, ++ "≗": true, ++ "↺": true, ++ "↻": true, ++ "®": true, ++ "Ⓢ": true, ++ "⊛": true, ++ "⊚": true, ++ "⊝": true, ++ "≗": true, ++ "⨐": true, ++ "⫯": true, ++ "⧂": true, ++ "♣": true, ++ "♣": true, ++ ":": true, ++ "≔": true, ++ "≔": true, ++ ",": true, ++ "@": true, ++ "∁": true, ++ "∘": true, ++ "∁": true, ++ "ℂ": true, ++ "≅": true, ++ "⩭": true, ++ "∮": true, ++ "𝕔": true, ++ "∐": true, ++ "©": true, ++ "©": true, ++ "℗": true, ++ "↵": true, ++ "✗": true, ++ "𝒸": true, ++ "⫏": true, ++ "⫑": true, ++ "⫐": true, ++ "⫒": true, ++ "⋯": true, ++ "⤸": true, ++ "⤵": true, ++ "⋞": true, ++ "⋟": true, ++ "↶": true, ++ "⤽": true, ++ "∪": true, ++ "⩈": true, ++ "⩆": true, ++ "⩊": true, ++ "⊍": true, ++ "⩅": true, ++ "∪︀": true, ++ "↷": true, ++ "⤼": true, ++ "⋞": true, ++ "⋟": true, ++ "⋎": true, ++ "⋏": true, ++ "¤": true, ++ "¤": true, ++ "↶": true, ++ "↷": true, ++ "⋎": true, ++ "⋏": true, ++ "∲": true, ++ "∱": true, ++ "⌭": true, ++ "⇓": true, ++ "⥥": true, ++ "†": true, ++ "ℸ": true, ++ "↓": true, ++ "‐": true, ++ "⊣": true, ++ "⤏": true, ++ "˝": true, ++ "ď": true, ++ "д": true, ++ "ⅆ": true, ++ "‡": true, ++ "⇊": true, ++ "⩷": true, ++ "°": true, ++ "°": true, ++ "δ": true, ++ "⦱": true, ++ "⥿": true, ++ "𝔡": true, ++ "⇃": true, ++ "⇂": true, ++ "⋄": true, ++ "⋄": true, ++ "♦": true, ++ "♦": true, ++ "¨": true, ++ "ϝ": true, ++ "⋲": true, ++ "÷": true, ++ "÷": true, ++ "÷": true, ++ "⋇": true, ++ "⋇": true, ++ "ђ": true, ++ "⌞": true, ++ "⌍": true, ++ "$": true, ++ "𝕕": true, ++ "˙": true, ++ "≐": true, ++ "≑": true, ++ "∸": true, ++ "∔": true, ++ "⊡": true, ++ "⌆": true, ++ "↓": true, ++ "⇊": true, ++ "⇃": true, ++ "⇂": true, ++ "⤐": true, ++ "⌟": true, ++ "⌌": true, ++ "𝒹": true, ++ "ѕ": true, ++ "⧶": true, ++ "đ": true, ++ "⋱": true, ++ "▿": true, ++ "▾": true, ++ "⇵": true, ++ "⥯": true, ++ "⦦": true, ++ "џ": true, ++ "⟿": true, ++ "⩷": true, ++ "≑": true, ++ "é": true, ++ "é": true, ++ "⩮": true, ++ "ě": true, ++ "≖": true, ++ "ê": true, ++ "ê": true, ++ "≕": true, ++ "э": true, ++ "ė": true, ++ "ⅇ": true, ++ "≒": true, ++ "𝔢": true, ++ "⪚": true, ++ "è": true, ++ "è": true, ++ "⪖": true, ++ "⪘": true, ++ "⪙": true, ++ "⏧": true, ++ "ℓ": true, ++ "⪕": true, ++ "⪗": true, ++ "ē": true, ++ "∅": true, ++ "∅": true, ++ "∅": true, ++ " ": true, ++ " ": true, ++ " ": true, ++ "ŋ": true, ++ " ": true, ++ "ę": true, ++ "𝕖": true, ++ "⋕": true, ++ "⧣": true, ++ "⩱": true, ++ "ε": true, ++ "ε": true, ++ "ϵ": true, ++ "≖": true, ++ "≕": true, ++ "≂": true, ++ "⪖": true, ++ "⪕": true, ++ "=": true, ++ "≟": true, ++ "≡": true, ++ "⩸": true, ++ "⧥": true, ++ "≓": true, ++ "⥱": true, ++ "ℯ": true, ++ "≐": true, ++ "≂": true, ++ "η": true, ++ "ð": true, ++ "ð": true, ++ "ë": true, ++ "ë": true, ++ "€": true, ++ "!": true, ++ "∃": true, ++ "ℰ": true, ++ "ⅇ": true, ++ "≒": true, ++ "ф": true, ++ "♀": true, ++ "ffi": true, ++ "ff": true, ++ "ffl": true, ++ "𝔣": true, ++ "fi": true, ++ "fj": true, ++ "♭": true, ++ "fl": true, ++ "▱": true, ++ "ƒ": true, ++ "𝕗": true, ++ "∀": true, ++ "⋔": true, ++ "⫙": true, ++ "⨍": true, ++ "½": true, ++ "½": true, ++ "⅓": true, ++ "¼": true, ++ "¼": true, ++ "⅕": true, ++ "⅙": true, ++ "⅛": true, ++ "⅔": true, ++ "⅖": true, ++ "¾": true, ++ "¾": true, ++ "⅗": true, ++ "⅜": true, ++ "⅘": true, ++ "⅚": true, ++ "⅝": true, ++ "⅞": true, ++ "⁄": true, ++ "⌢": true, ++ "𝒻": true, ++ "≧": true, ++ "⪌": true, ++ "ǵ": true, ++ "γ": true, ++ "ϝ": true, ++ "⪆": true, ++ "ğ": true, ++ "ĝ": true, ++ "г": true, ++ "ġ": true, ++ "≥": true, ++ "⋛": true, ++ "≥": true, ++ "≧": true, ++ "⩾": true, ++ "⩾": true, ++ "⪩": true, ++ "⪀": true, ++ "⪂": true, ++ "⪄": true, ++ "⋛︀": true, ++ "⪔": true, ++ "𝔤": true, ++ "≫": true, ++ "⋙": true, ++ "ℷ": true, ++ "ѓ": true, ++ "≷": true, ++ "⪒": true, ++ "⪥": true, ++ "⪤": true, ++ "≩": true, ++ "⪊": true, ++ "⪊": true, ++ "⪈": true, ++ "⪈": true, ++ "≩": true, ++ "⋧": true, ++ "𝕘": true, ++ "`": true, ++ "ℊ": true, ++ "≳": true, ++ "⪎": true, ++ "⪐": true, ++ ">": true, ++ ">": true, ++ "⪧": true, ++ "⩺": true, ++ "⋗": true, ++ "⦕": true, ++ "⩼": true, ++ "⪆": true, ++ "⥸": true, ++ "⋗": true, ++ "⋛": true, ++ "⪌": true, ++ "≷": true, ++ "≳": true, ++ "≩︀": true, ++ "≩︀": true, ++ "⇔": true, ++ " ": true, ++ "½": true, ++ "ℋ": true, ++ "ъ": true, ++ "↔": true, ++ "⥈": true, ++ "↭": true, ++ "ℏ": true, ++ "ĥ": true, ++ "♥": true, ++ "♥": true, ++ "…": true, ++ "⊹": true, ++ "𝔥": true, ++ "⤥": true, ++ "⤦": true, ++ "⇿": true, ++ "∻": true, ++ "↩": true, ++ "↪": true, ++ "𝕙": true, ++ "―": true, ++ "𝒽": true, ++ "ℏ": true, ++ "ħ": true, ++ "⁃": true, ++ "‐": true, ++ "í": true, ++ "í": true, ++ "⁣": true, ++ "î": true, ++ "î": true, ++ "и": true, ++ "е": true, ++ "¡": true, ++ "¡": true, ++ "⇔": true, ++ "𝔦": true, ++ "ì": true, ++ "ì": true, ++ "ⅈ": true, ++ "⨌": true, ++ "∭": true, ++ "⧜": true, ++ "℩": true, ++ "ij": true, ++ "ī": true, ++ "ℑ": true, ++ "ℐ": true, ++ "ℑ": true, ++ "ı": true, ++ "⊷": true, ++ "Ƶ": true, ++ "∈": true, ++ "℅": true, ++ "∞": true, ++ "⧝": true, ++ "ı": true, ++ "∫": true, ++ "⊺": true, ++ "ℤ": true, ++ "⊺": true, ++ "⨗": true, ++ "⨼": true, ++ "ё": true, ++ "į": true, ++ "𝕚": true, ++ "ι": true, ++ "⨼": true, ++ "¿": true, ++ "¿": true, ++ "𝒾": true, ++ "∈": true, ++ "⋹": true, ++ "⋵": true, ++ "⋴": true, ++ "⋳": true, ++ "∈": true, ++ "⁢": true, ++ "ĩ": true, ++ "і": true, ++ "ï": true, ++ "ï": true, ++ "ĵ": true, ++ "й": true, ++ "𝔧": true, ++ "ȷ": true, ++ "𝕛": true, ++ "𝒿": true, ++ "ј": true, ++ "є": true, ++ "κ": true, ++ "ϰ": true, ++ "ķ": true, ++ "к": true, ++ "𝔨": true, ++ "ĸ": true, ++ "х": true, ++ "ќ": true, ++ "𝕜": true, ++ "𝓀": true, ++ "⇚": true, ++ "⇐": true, ++ "⤛": true, ++ "⤎": true, ++ "≦": true, ++ "⪋": true, ++ "⥢": true, ++ "ĺ": true, ++ "⦴": true, ++ "ℒ": true, ++ "λ": true, ++ "⟨": true, ++ "⦑": true, ++ "⟨": true, ++ "⪅": true, ++ "«": true, ++ "«": true, ++ "←": true, ++ "⇤": true, ++ "⤟": true, ++ "⤝": true, ++ "↩": true, ++ "↫": true, ++ "⤹": true, ++ "⥳": true, ++ "↢": true, ++ "⪫": true, ++ "⤙": true, ++ "⪭": true, ++ "⪭︀": true, ++ "⤌": true, ++ "❲": true, ++ "{": true, ++ "[": true, ++ "⦋": true, ++ "⦏": true, ++ "⦍": true, ++ "ľ": true, ++ "ļ": true, ++ "⌈": true, ++ "{": true, ++ "л": true, ++ "⤶": true, ++ "“": true, ++ "„": true, ++ "⥧": true, ++ "⥋": true, ++ "↲": true, ++ "≤": true, ++ "←": true, ++ "↢": true, ++ "↽": true, ++ "↼": true, ++ "⇇": true, ++ "↔": true, ++ "⇆": true, ++ "⇋": true, ++ "↭": true, ++ "⋋": true, ++ "⋚": true, ++ "≤": true, ++ "≦": true, ++ "⩽": true, ++ "⩽": true, ++ "⪨": true, ++ "⩿": true, ++ "⪁": true, ++ "⪃": true, ++ "⋚︀": true, ++ "⪓": true, ++ "⪅": true, ++ "⋖": true, ++ "⋚": true, ++ "⪋": true, ++ "≶": true, ++ "≲": true, ++ "⥼": true, ++ "⌊": true, ++ "𝔩": true, ++ "≶": true, ++ "⪑": true, ++ "↽": true, ++ "↼": true, ++ "⥪": true, ++ "▄": true, ++ "љ": true, ++ "≪": true, ++ "⇇": true, ++ "⌞": true, ++ "⥫": true, ++ "◺": true, ++ "ŀ": true, ++ "⎰": true, ++ "⎰": true, ++ "≨": true, ++ "⪉": true, ++ "⪉": true, ++ "⪇": true, ++ "⪇": true, ++ "≨": true, ++ "⋦": true, ++ "⟬": true, ++ "⇽": true, ++ "⟦": true, ++ "⟵": true, ++ "⟷": true, ++ "⟼": true, ++ "⟶": true, ++ "↫": true, ++ "↬": true, ++ "⦅": true, ++ "𝕝": true, ++ "⨭": true, ++ "⨴": true, ++ "∗": true, ++ "_": true, ++ "◊": true, ++ "◊": true, ++ "⧫": true, ++ "(": true, ++ "⦓": true, ++ "⇆": true, ++ "⌟": true, ++ "⇋": true, ++ "⥭": true, ++ "‎": true, ++ "⊿": true, ++ "‹": true, ++ "𝓁": true, ++ "↰": true, ++ "≲": true, ++ "⪍": true, ++ "⪏": true, ++ "[": true, ++ "‘": true, ++ "‚": true, ++ "ł": true, ++ "<": true, ++ "<": true, ++ "⪦": true, ++ "⩹": true, ++ "⋖": true, ++ "⋋": true, ++ "⋉": true, ++ "⥶": true, ++ "⩻": true, ++ "⦖": true, ++ "◃": true, ++ "⊴": true, ++ "◂": true, ++ "⥊": true, ++ "⥦": true, ++ "≨︀": true, ++ "≨︀": true, ++ "∺": true, ++ "¯": true, ++ "¯": true, ++ "♂": true, ++ "✠": true, ++ "✠": true, ++ "↦": true, ++ "↦": true, ++ "↧": true, ++ "↤": true, ++ "↥": true, ++ "▮": true, ++ "⨩": true, ++ "м": true, ++ "—": true, ++ "∡": true, ++ "𝔪": true, ++ "℧": true, ++ "µ": true, ++ "µ": true, ++ "∣": true, ++ "*": true, ++ "⫰": true, ++ "·": true, ++ "·": true, ++ "−": true, ++ "⊟": true, ++ "∸": true, ++ "⨪": true, ++ "⫛": true, ++ "…": true, ++ "∓": true, ++ "⊧": true, ++ "𝕞": true, ++ "∓": true, ++ "𝓂": true, ++ "∾": true, ++ "μ": true, ++ "⊸": true, ++ "⊸": true, ++ "⋙̸": true, ++ "≫⃒": true, ++ "≫̸": true, ++ "⇍": true, ++ "⇎": true, ++ "⋘̸": true, ++ "≪⃒": true, ++ "≪̸": true, ++ "⇏": true, ++ "⊯": true, ++ "⊮": true, ++ "∇": true, ++ "ń": true, ++ "∠⃒": true, ++ "≉": true, ++ "⩰̸": true, ++ "≋̸": true, ++ "ʼn": true, ++ "≉": true, ++ "♮": true, ++ "♮": true, ++ "ℕ": true, ++ " ": true, ++ " ": true, ++ "≎̸": true, ++ "≏̸": true, ++ "⩃": true, ++ "ň": true, ++ "ņ": true, ++ "≇": true, ++ "⩭̸": true, ++ "⩂": true, ++ "н": true, ++ "–": true, ++ "≠": true, ++ "⇗": true, ++ "⤤": true, ++ "↗": true, ++ "↗": true, ++ "≐̸": true, ++ "≢": true, ++ "⤨": true, ++ "≂̸": true, ++ "∄": true, ++ "∄": true, ++ "𝔫": true, ++ "≧̸": true, ++ "≱": true, ++ "≱": true, ++ "≧̸": true, ++ "⩾̸": true, ++ "⩾̸": true, ++ "≵": true, ++ "≯": true, ++ "≯": true, ++ "⇎": true, ++ "↮": true, ++ "⫲": true, ++ "∋": true, ++ "⋼": true, ++ "⋺": true, ++ "∋": true, ++ "њ": true, ++ "⇍": true, ++ "≦̸": true, ++ "↚": true, ++ "‥": true, ++ "≰": true, ++ "↚": true, ++ "↮": true, ++ "≰": true, ++ "≦̸": true, ++ "⩽̸": true, ++ "⩽̸": true, ++ "≮": true, ++ "≴": true, ++ "≮": true, ++ "⋪": true, ++ "⋬": true, ++ "∤": true, ++ "𝕟": true, ++ "¬": true, ++ "¬": true, ++ "∉": true, ++ "⋹̸": true, ++ "⋵̸": true, ++ "∉": true, ++ "⋷": true, ++ "⋶": true, ++ "∌": true, ++ "∌": true, ++ "⋾": true, ++ "⋽": true, ++ "∦": true, ++ "∦": true, ++ "⫽⃥": true, ++ "∂̸": true, ++ "⨔": true, ++ "⊀": true, ++ "⋠": true, ++ "⪯̸": true, ++ "⊀": true, ++ "⪯̸": true, ++ "⇏": true, ++ "↛": true, ++ "⤳̸": true, ++ "↝̸": true, ++ "↛": true, ++ "⋫": true, ++ "⋭": true, ++ "⊁": true, ++ "⋡": true, ++ "⪰̸": true, ++ "𝓃": true, ++ "∤": true, ++ "∦": true, ++ "≁": true, ++ "≄": true, ++ "≄": true, ++ "∤": true, ++ "∦": true, ++ "⋢": true, ++ "⋣": true, ++ "⊄": true, ++ "⫅̸": true, ++ "⊈": true, ++ "⊂⃒": true, ++ "⊈": true, ++ "⫅̸": true, ++ "⊁": true, ++ "⪰̸": true, ++ "⊅": true, ++ "⫆̸": true, ++ "⊉": true, ++ "⊃⃒": true, ++ "⊉": true, ++ "⫆̸": true, ++ "≹": true, ++ "ñ": true, ++ "ñ": true, ++ "≸": true, ++ "⋪": true, ++ "⋬": true, ++ "⋫": true, ++ "⋭": true, ++ "ν": true, ++ "#": true, ++ "№": true, ++ " ": true, ++ "⊭": true, ++ "⤄": true, ++ "≍⃒": true, ++ "⊬": true, ++ "≥⃒": true, ++ ">⃒": true, ++ "⧞": true, ++ "⤂": true, ++ "≤⃒": true, ++ "<⃒": true, ++ "⊴⃒": true, ++ "⤃": true, ++ "⊵⃒": true, ++ "∼⃒": true, ++ "⇖": true, ++ "⤣": true, ++ "↖": true, ++ "↖": true, ++ "⤧": true, ++ "Ⓢ": true, ++ "ó": true, ++ "ó": true, ++ "⊛": true, ++ "⊚": true, ++ "ô": true, ++ "ô": true, ++ "о": true, ++ "⊝": true, ++ "ő": true, ++ "⨸": true, ++ "⊙": true, ++ "⦼": true, ++ "œ": true, ++ "⦿": true, ++ "𝔬": true, ++ "˛": true, ++ "ò": true, ++ "ò": true, ++ "⧁": true, ++ "⦵": true, ++ "Ω": true, ++ "∮": true, ++ "↺": true, ++ "⦾": true, ++ "⦻": true, ++ "‾": true, ++ "⧀": true, ++ "ō": true, ++ "ω": true, ++ "ο": true, ++ "⦶": true, ++ "⊖": true, ++ "𝕠": true, ++ "⦷": true, ++ "⦹": true, ++ "⊕": true, ++ "∨": true, ++ "↻": true, ++ "⩝": true, ++ "ℴ": true, ++ "ℴ": true, ++ "ª": true, ++ "ª": true, ++ "º": true, ++ "º": true, ++ "⊶": true, ++ "⩖": true, ++ "⩗": true, ++ "⩛": true, ++ "ℴ": true, ++ "ø": true, ++ "ø": true, ++ "⊘": true, ++ "õ": true, ++ "õ": true, ++ "⊗": true, ++ "⨶": true, ++ "ö": true, ++ "ö": true, ++ "⌽": true, ++ "∥": true, ++ "¶": true, ++ "¶": true, ++ "∥": true, ++ "⫳": true, ++ "⫽": true, ++ "∂": true, ++ "п": true, ++ "%": true, ++ ".": true, ++ "‰": true, ++ "⊥": true, ++ "‱": true, ++ "𝔭": true, ++ "φ": true, ++ "ϕ": true, ++ "ℳ": true, ++ "☎": true, ++ "π": true, ++ "⋔": true, ++ "ϖ": true, ++ "ℏ": true, ++ "ℎ": true, ++ "ℏ": true, ++ "+": true, ++ "⨣": true, ++ "⊞": true, ++ "⨢": true, ++ "∔": true, ++ "⨥": true, ++ "⩲": true, ++ "±": true, ++ "±": true, ++ "⨦": true, ++ "⨧": true, ++ "±": true, ++ "⨕": true, ++ "𝕡": true, ++ "£": true, ++ "£": true, ++ "≺": true, ++ "⪳": true, ++ "⪷": true, ++ "≼": true, ++ "⪯": true, ++ "≺": true, ++ "⪷": true, ++ "≼": true, ++ "⪯": true, ++ "⪹": true, ++ "⪵": true, ++ "⋨": true, ++ "≾": true, ++ "′": true, ++ "ℙ": true, ++ "⪵": true, ++ "⪹": true, ++ "⋨": true, ++ "∏": true, ++ "⌮": true, ++ "⌒": true, ++ "⌓": true, ++ "∝": true, ++ "∝": true, ++ "≾": true, ++ "⊰": true, ++ "𝓅": true, ++ "ψ": true, ++ " ": true, ++ "𝔮": true, ++ "⨌": true, ++ "𝕢": true, ++ "⁗": true, ++ "𝓆": true, ++ "ℍ": true, ++ "⨖": true, ++ "?": true, ++ "≟": true, ++ """: true, ++ """: true, ++ "⇛": true, ++ "⇒": true, ++ "⤜": true, ++ "⤏": true, ++ "⥤": true, ++ "∽̱": true, ++ "ŕ": true, ++ "√": true, ++ "⦳": true, ++ "⟩": true, ++ "⦒": true, ++ "⦥": true, ++ "⟩": true, ++ "»": true, ++ "»": true, ++ "→": true, ++ "⥵": true, ++ "⇥": true, ++ "⤠": true, ++ "⤳": true, ++ "⤞": true, ++ "↪": true, ++ "↬": true, ++ "⥅": true, ++ "⥴": true, ++ "↣": true, ++ "↝": true, ++ "⤚": true, ++ "∶": true, ++ "ℚ": true, ++ "⤍": true, ++ "❳": true, ++ "}": true, ++ "]": true, ++ "⦌": true, ++ "⦎": true, ++ "⦐": true, ++ "ř": true, ++ "ŗ": true, ++ "⌉": true, ++ "}": true, ++ "р": true, ++ "⤷": true, ++ "⥩": true, ++ "”": true, ++ "”": true, ++ "↳": true, ++ "ℜ": true, ++ "ℛ": true, ++ "ℜ": true, ++ "ℝ": true, ++ "▭": true, ++ "®": true, ++ "®": true, ++ "⥽": true, ++ "⌋": true, ++ "𝔯": true, ++ "⇁": true, ++ "⇀": true, ++ "⥬": true, ++ "ρ": true, ++ "ϱ": true, ++ "→": true, ++ "↣": true, ++ "⇁": true, ++ "⇀": true, ++ "⇄": true, ++ "⇌": true, ++ "⇉": true, ++ "↝": true, ++ "⋌": true, ++ "˚": true, ++ "≓": true, ++ "⇄": true, ++ "⇌": true, ++ "‏": true, ++ "⎱": true, ++ "⎱": true, ++ "⫮": true, ++ "⟭": true, ++ "⇾": true, ++ "⟧": true, ++ "⦆": true, ++ "𝕣": true, ++ "⨮": true, ++ "⨵": true, ++ ")": true, ++ "⦔": true, ++ "⨒": true, ++ "⇉": true, ++ "›": true, ++ "𝓇": true, ++ "↱": true, ++ "]": true, ++ "’": true, ++ "’": true, ++ "⋌": true, ++ "⋊": true, ++ "▹": true, ++ "⊵": true, ++ "▸": true, ++ "⧎": true, ++ "⥨": true, ++ "℞": true, ++ "ś": true, ++ "‚": true, ++ "≻": true, ++ "⪴": true, ++ "⪸": true, ++ "š": true, ++ "≽": true, ++ "⪰": true, ++ "ş": true, ++ "ŝ": true, ++ "⪶": true, ++ "⪺": true, ++ "⋩": true, ++ "⨓": true, ++ "≿": true, ++ "с": true, ++ "⋅": true, ++ "⊡": true, ++ "⩦": true, ++ "⇘": true, ++ "⤥": true, ++ "↘": true, ++ "↘": true, ++ "§": true, ++ "§": true, ++ ";": true, ++ "⤩": true, ++ "∖": true, ++ "∖": true, ++ "✶": true, ++ "𝔰": true, ++ "⌢": true, ++ "♯": true, ++ "щ": true, ++ "ш": true, ++ "∣": true, ++ "∥": true, ++ "­": true, ++ "­": true, ++ "σ": true, ++ "ς": true, ++ "ς": true, ++ "∼": true, ++ "⩪": true, ++ "≃": true, ++ "≃": true, ++ "⪞": true, ++ "⪠": true, ++ "⪝": true, ++ "⪟": true, ++ "≆": true, ++ "⨤": true, ++ "⥲": true, ++ "←": true, ++ "∖": true, ++ "⨳": true, ++ "⧤": true, ++ "∣": true, ++ "⌣": true, ++ "⪪": true, ++ "⪬": true, ++ "⪬︀": true, ++ "ь": true, ++ "/": true, ++ "⧄": true, ++ "⌿": true, ++ "𝕤": true, ++ "♠": true, ++ "♠": true, ++ "∥": true, ++ "⊓": true, ++ "⊓︀": true, ++ "⊔": true, ++ "⊔︀": true, ++ "⊏": true, ++ "⊑": true, ++ "⊏": true, ++ "⊑": true, ++ "⊐": true, ++ "⊒": true, ++ "⊐": true, ++ "⊒": true, ++ "□": true, ++ "□": true, ++ "▪": true, ++ "▪": true, ++ "→": true, ++ "𝓈": true, ++ "∖": true, ++ "⌣": true, ++ "⋆": true, ++ "☆": true, ++ "★": true, ++ "ϵ": true, ++ "ϕ": true, ++ "¯": true, ++ "⊂": true, ++ "⫅": true, ++ "⪽": true, ++ "⊆": true, ++ "⫃": true, ++ "⫁": true, ++ "⫋": true, ++ "⊊": true, ++ "⪿": true, ++ "⥹": true, ++ "⊂": true, ++ "⊆": true, ++ "⫅": true, ++ "⊊": true, ++ "⫋": true, ++ "⫇": true, ++ "⫕": true, ++ "⫓": true, ++ "≻": true, ++ "⪸": true, ++ "≽": true, ++ "⪰": true, ++ "⪺": true, ++ "⪶": true, ++ "⋩": true, ++ "≿": true, ++ "∑": true, ++ "♪": true, ++ "¹": true, ++ "¹": true, ++ "²": true, ++ "²": true, ++ "³": true, ++ "³": true, ++ "⊃": true, ++ "⫆": true, ++ "⪾": true, ++ "⫘": true, ++ "⊇": true, ++ "⫄": true, ++ "⟉": true, ++ "⫗": true, ++ "⥻": true, ++ "⫂": true, ++ "⫌": true, ++ "⊋": true, ++ "⫀": true, ++ "⊃": true, ++ "⊇": true, ++ "⫆": true, ++ "⊋": true, ++ "⫌": true, ++ "⫈": true, ++ "⫔": true, ++ "⫖": true, ++ "⇙": true, ++ "⤦": true, ++ "↙": true, ++ "↙": true, ++ "⤪": true, ++ "ß": true, ++ "ß": true, ++ "⌖": true, ++ "τ": true, ++ "⎴": true, ++ "ť": true, ++ "ţ": true, ++ "т": true, ++ "⃛": true, ++ "⌕": true, ++ "𝔱": true, ++ "∴": true, ++ "∴": true, ++ "θ": true, ++ "ϑ": true, ++ "ϑ": true, ++ "≈": true, ++ "∼": true, ++ " ": true, ++ "≈": true, ++ "∼": true, ++ "þ": true, ++ "þ": true, ++ "˜": true, ++ "×": true, ++ "×": true, ++ "⊠": true, ++ "⨱": true, ++ "⨰": true, ++ "∭": true, ++ "⤨": true, ++ "⊤": true, ++ "⌶": true, ++ "⫱": true, ++ "𝕥": true, ++ "⫚": true, ++ "⤩": true, ++ "‴": true, ++ "™": true, ++ "▵": true, ++ "▿": true, ++ "◃": true, ++ "⊴": true, ++ "≜": true, ++ "▹": true, ++ "⊵": true, ++ "◬": true, ++ "≜": true, ++ "⨺": true, ++ "⨹": true, ++ "⧍": true, ++ "⨻": true, ++ "⏢": true, ++ "𝓉": true, ++ "ц": true, ++ "ћ": true, ++ "ŧ": true, ++ "≬": true, ++ "↞": true, ++ "↠": true, ++ "⇑": true, ++ "⥣": true, ++ "ú": true, ++ "ú": true, ++ "↑": true, ++ "ў": true, ++ "ŭ": true, ++ "û": true, ++ "û": true, ++ "у": true, ++ "⇅": true, ++ "ű": true, ++ "⥮": true, ++ "⥾": true, ++ "𝔲": true, ++ "ù": true, ++ "ù": true, ++ "↿": true, ++ "↾": true, ++ "▀": true, ++ "⌜": true, ++ "⌜": true, ++ "⌏": true, ++ "◸": true, ++ "ū": true, ++ "¨": true, ++ "¨": true, ++ "ų": true, ++ "𝕦": true, ++ "↑": true, ++ "↕": true, ++ "↿": true, ++ "↾": true, ++ "⊎": true, ++ "υ": true, ++ "ϒ": true, ++ "υ": true, ++ "⇈": true, ++ "⌝": true, ++ "⌝": true, ++ "⌎": true, ++ "ů": true, ++ "◹": true, ++ "𝓊": true, ++ "⋰": true, ++ "ũ": true, ++ "▵": true, ++ "▴": true, ++ "⇈": true, ++ "ü": true, ++ "ü": true, ++ "⦧": true, ++ "⇕": true, ++ "⫨": true, ++ "⫩": true, ++ "⊨": true, ++ "⦜": true, ++ "ϵ": true, ++ "ϰ": true, ++ "∅": true, ++ "ϕ": true, ++ "ϖ": true, ++ "∝": true, ++ "↕": true, ++ "ϱ": true, ++ "ς": true, ++ "⊊︀": true, ++ "⫋︀": true, ++ "⊋︀": true, ++ "⫌︀": true, ++ "ϑ": true, ++ "⊲": true, ++ "⊳": true, ++ "в": true, ++ "⊢": true, ++ "∨": true, ++ "⊻": true, ++ "≚": true, ++ "⋮": true, ++ "|": true, ++ "|": true, ++ "𝔳": true, ++ "⊲": true, ++ "⊂⃒": true, ++ "⊃⃒": true, ++ "𝕧": true, ++ "∝": true, ++ "⊳": true, ++ "𝓋": true, ++ "⫋︀": true, ++ "⊊︀": true, ++ "⫌︀": true, ++ "⊋︀": true, ++ "⦚": true, ++ "ŵ": true, ++ "⩟": true, ++ "∧": true, ++ "≙": true, ++ "℘": true, ++ "𝔴": true, ++ "𝕨": true, ++ "℘": true, ++ "≀": true, ++ "≀": true, ++ "𝓌": true, ++ "⋂": true, ++ "◯": true, ++ "⋃": true, ++ "▽": true, ++ "𝔵": true, ++ "⟺": true, ++ "⟷": true, ++ "ξ": true, ++ "⟸": true, ++ "⟵": true, ++ "⟼": true, ++ "⋻": true, ++ "⨀": true, ++ "𝕩": true, ++ "⨁": true, ++ "⨂": true, ++ "⟹": true, ++ "⟶": true, ++ "𝓍": true, ++ "⨆": true, ++ "⨄": true, ++ "△": true, ++ "⋁": true, ++ "⋀": true, ++ "ý": true, ++ "ý": true, ++ "я": true, ++ "ŷ": true, ++ "ы": true, ++ "¥": true, ++ "¥": true, ++ "𝔶": true, ++ "ї": true, ++ "𝕪": true, ++ "𝓎": true, ++ "ю": true, ++ "ÿ": true, ++ "ÿ": true, ++ "ź": true, ++ "ž": true, ++ "з": true, ++ "ż": true, ++ "ℨ": true, ++ "ζ": true, ++ "𝔷": true, ++ "ж": true, ++ "⇝": true, ++ "𝕫": true, ++ "𝓏": true, ++ "‍": true, ++ "‌": true, ++} +diff --git a/vendor/github.com/russross/blackfriday/v2/esc.go b/vendor/github.com/russross/blackfriday/v2/esc.go +new file mode 100644 +index 000000000000..6ab60102c9bf +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/esc.go +@@ -0,0 +1,70 @@ ++package blackfriday ++ ++import ( ++ "html" ++ "io" ++) ++ ++var htmlEscaper = [256][]byte{ ++ '&': []byte("&"), ++ '<': []byte("<"), ++ '>': []byte(">"), ++ '"': []byte("""), ++} ++ ++func escapeHTML(w io.Writer, s []byte) { ++ escapeEntities(w, s, false) ++} ++ ++func escapeAllHTML(w io.Writer, s []byte) { ++ escapeEntities(w, s, true) ++} ++ ++func escapeEntities(w io.Writer, s []byte, escapeValidEntities bool) { ++ var start, end int ++ for end < len(s) { ++ escSeq := htmlEscaper[s[end]] ++ if escSeq != nil { ++ isEntity, entityEnd := nodeIsEntity(s, end) ++ if isEntity && !escapeValidEntities { ++ w.Write(s[start : entityEnd+1]) ++ start = entityEnd + 1 ++ } else { ++ w.Write(s[start:end]) ++ w.Write(escSeq) ++ start = end + 1 ++ } ++ } ++ end++ ++ } ++ if start < len(s) && end <= len(s) { ++ w.Write(s[start:end]) ++ } ++} ++ ++func nodeIsEntity(s []byte, end int) (isEntity bool, endEntityPos int) { ++ isEntity = false ++ endEntityPos = end + 1 ++ ++ if s[end] == '&' { ++ for endEntityPos < len(s) { ++ if s[endEntityPos] == ';' { ++ if entities[string(s[end:endEntityPos+1])] { ++ isEntity = true ++ break ++ } ++ } ++ if !isalnum(s[endEntityPos]) && s[endEntityPos] != '&' && s[endEntityPos] != '#' { ++ break ++ } ++ endEntityPos++ ++ } ++ } ++ ++ return isEntity, endEntityPos ++} ++ ++func escLink(w io.Writer, text []byte) { ++ unesc := html.UnescapeString(string(text)) ++ escapeHTML(w, []byte(unesc)) ++} +diff --git a/vendor/github.com/russross/blackfriday/v2/html.go b/vendor/github.com/russross/blackfriday/v2/html.go +new file mode 100644 +index 000000000000..cb4f26e30fd5 +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/html.go +@@ -0,0 +1,952 @@ ++// ++// Blackfriday Markdown Processor ++// Available at http://github.com/russross/blackfriday ++// ++// Copyright © 2011 Russ Ross . ++// Distributed under the Simplified BSD License. ++// See README.md for details. ++// ++ ++// ++// ++// HTML rendering backend ++// ++// ++ ++package blackfriday ++ ++import ( ++ "bytes" ++ "fmt" ++ "io" ++ "regexp" ++ "strings" ++) ++ ++// HTMLFlags control optional behavior of HTML renderer. ++type HTMLFlags int ++ ++// HTML renderer configuration options. ++const ( ++ HTMLFlagsNone HTMLFlags = 0 ++ SkipHTML HTMLFlags = 1 << iota // Skip preformatted HTML blocks ++ SkipImages // Skip embedded images ++ SkipLinks // Skip all links ++ Safelink // Only link to trusted protocols ++ NofollowLinks // Only link with rel="nofollow" ++ NoreferrerLinks // Only link with rel="noreferrer" ++ NoopenerLinks // Only link with rel="noopener" ++ HrefTargetBlank // Add a blank target ++ CompletePage // Generate a complete HTML page ++ UseXHTML // Generate XHTML output instead of HTML ++ FootnoteReturnLinks // Generate a link at the end of a footnote to return to the source ++ Smartypants // Enable smart punctuation substitutions ++ SmartypantsFractions // Enable smart fractions (with Smartypants) ++ SmartypantsDashes // Enable smart dashes (with Smartypants) ++ SmartypantsLatexDashes // Enable LaTeX-style dashes (with Smartypants) ++ SmartypantsAngledQuotes // Enable angled double quotes (with Smartypants) for double quotes rendering ++ SmartypantsQuotesNBSP // Enable « French guillemets » (with Smartypants) ++ TOC // Generate a table of contents ++) ++ ++var ( ++ htmlTagRe = regexp.MustCompile("(?i)^" + htmlTag) ++) ++ ++const ( ++ htmlTag = "(?:" + openTag + "|" + closeTag + "|" + htmlComment + "|" + ++ processingInstruction + "|" + declaration + "|" + cdata + ")" ++ closeTag = "]" ++ openTag = "<" + tagName + attribute + "*" + "\\s*/?>" ++ attribute = "(?:" + "\\s+" + attributeName + attributeValueSpec + "?)" ++ attributeValue = "(?:" + unquotedValue + "|" + singleQuotedValue + "|" + doubleQuotedValue + ")" ++ attributeValueSpec = "(?:" + "\\s*=" + "\\s*" + attributeValue + ")" ++ attributeName = "[a-zA-Z_:][a-zA-Z0-9:._-]*" ++ cdata = "" ++ declaration = "]*>" ++ doubleQuotedValue = "\"[^\"]*\"" ++ htmlComment = "|" ++ processingInstruction = "[<][?].*?[?][>]" ++ singleQuotedValue = "'[^']*'" ++ tagName = "[A-Za-z][A-Za-z0-9-]*" ++ unquotedValue = "[^\"'=<>`\\x00-\\x20]+" ++) ++ ++// HTMLRendererParameters is a collection of supplementary parameters tweaking ++// the behavior of various parts of HTML renderer. ++type HTMLRendererParameters struct { ++ // Prepend this text to each relative URL. ++ AbsolutePrefix string ++ // Add this text to each footnote anchor, to ensure uniqueness. ++ FootnoteAnchorPrefix string ++ // Show this text inside the tag for a footnote return link, if the ++ // HTML_FOOTNOTE_RETURN_LINKS flag is enabled. If blank, the string ++ // [return] is used. ++ FootnoteReturnLinkContents string ++ // If set, add this text to the front of each Heading ID, to ensure ++ // uniqueness. ++ HeadingIDPrefix string ++ // If set, add this text to the back of each Heading ID, to ensure uniqueness. ++ HeadingIDSuffix string ++ // Increase heading levels: if the offset is 1,

becomes

etc. ++ // Negative offset is also valid. ++ // Resulting levels are clipped between 1 and 6. ++ HeadingLevelOffset int ++ ++ Title string // Document title (used if CompletePage is set) ++ CSS string // Optional CSS file URL (used if CompletePage is set) ++ Icon string // Optional icon file URL (used if CompletePage is set) ++ ++ Flags HTMLFlags // Flags allow customizing this renderer's behavior ++} ++ ++// HTMLRenderer is a type that implements the Renderer interface for HTML output. ++// ++// Do not create this directly, instead use the NewHTMLRenderer function. ++type HTMLRenderer struct { ++ HTMLRendererParameters ++ ++ closeTag string // how to end singleton tags: either " />" or ">" ++ ++ // Track heading IDs to prevent ID collision in a single generation. ++ headingIDs map[string]int ++ ++ lastOutputLen int ++ disableTags int ++ ++ sr *SPRenderer ++} ++ ++const ( ++ xhtmlClose = " />" ++ htmlClose = ">" ++) ++ ++// NewHTMLRenderer creates and configures an HTMLRenderer object, which ++// satisfies the Renderer interface. ++func NewHTMLRenderer(params HTMLRendererParameters) *HTMLRenderer { ++ // configure the rendering engine ++ closeTag := htmlClose ++ if params.Flags&UseXHTML != 0 { ++ closeTag = xhtmlClose ++ } ++ ++ if params.FootnoteReturnLinkContents == "" { ++ // U+FE0E is VARIATION SELECTOR-15. ++ // It suppresses automatic emoji presentation of the preceding ++ // U+21A9 LEFTWARDS ARROW WITH HOOK on iOS and iPadOS. ++ params.FootnoteReturnLinkContents = "↩\ufe0e" ++ } ++ ++ return &HTMLRenderer{ ++ HTMLRendererParameters: params, ++ ++ closeTag: closeTag, ++ headingIDs: make(map[string]int), ++ ++ sr: NewSmartypantsRenderer(params.Flags), ++ } ++} ++ ++func isHTMLTag(tag []byte, tagname string) bool { ++ found, _ := findHTMLTagPos(tag, tagname) ++ return found ++} ++ ++// Look for a character, but ignore it when it's in any kind of quotes, it ++// might be JavaScript ++func skipUntilCharIgnoreQuotes(html []byte, start int, char byte) int { ++ inSingleQuote := false ++ inDoubleQuote := false ++ inGraveQuote := false ++ i := start ++ for i < len(html) { ++ switch { ++ case html[i] == char && !inSingleQuote && !inDoubleQuote && !inGraveQuote: ++ return i ++ case html[i] == '\'': ++ inSingleQuote = !inSingleQuote ++ case html[i] == '"': ++ inDoubleQuote = !inDoubleQuote ++ case html[i] == '`': ++ inGraveQuote = !inGraveQuote ++ } ++ i++ ++ } ++ return start ++} ++ ++func findHTMLTagPos(tag []byte, tagname string) (bool, int) { ++ i := 0 ++ if i < len(tag) && tag[0] != '<' { ++ return false, -1 ++ } ++ i++ ++ i = skipSpace(tag, i) ++ ++ if i < len(tag) && tag[i] == '/' { ++ i++ ++ } ++ ++ i = skipSpace(tag, i) ++ j := 0 ++ for ; i < len(tag); i, j = i+1, j+1 { ++ if j >= len(tagname) { ++ break ++ } ++ ++ if strings.ToLower(string(tag[i]))[0] != tagname[j] { ++ return false, -1 ++ } ++ } ++ ++ if i == len(tag) { ++ return false, -1 ++ } ++ ++ rightAngle := skipUntilCharIgnoreQuotes(tag, i, '>') ++ if rightAngle >= i { ++ return true, rightAngle ++ } ++ ++ return false, -1 ++} ++ ++func skipSpace(tag []byte, i int) int { ++ for i < len(tag) && isspace(tag[i]) { ++ i++ ++ } ++ return i ++} ++ ++func isRelativeLink(link []byte) (yes bool) { ++ // a tag begin with '#' ++ if link[0] == '#' { ++ return true ++ } ++ ++ // link begin with '/' but not '//', the second maybe a protocol relative link ++ if len(link) >= 2 && link[0] == '/' && link[1] != '/' { ++ return true ++ } ++ ++ // only the root '/' ++ if len(link) == 1 && link[0] == '/' { ++ return true ++ } ++ ++ // current directory : begin with "./" ++ if bytes.HasPrefix(link, []byte("./")) { ++ return true ++ } ++ ++ // parent directory : begin with "../" ++ if bytes.HasPrefix(link, []byte("../")) { ++ return true ++ } ++ ++ return false ++} ++ ++func (r *HTMLRenderer) ensureUniqueHeadingID(id string) string { ++ for count, found := r.headingIDs[id]; found; count, found = r.headingIDs[id] { ++ tmp := fmt.Sprintf("%s-%d", id, count+1) ++ ++ if _, tmpFound := r.headingIDs[tmp]; !tmpFound { ++ r.headingIDs[id] = count + 1 ++ id = tmp ++ } else { ++ id = id + "-1" ++ } ++ } ++ ++ if _, found := r.headingIDs[id]; !found { ++ r.headingIDs[id] = 0 ++ } ++ ++ return id ++} ++ ++func (r *HTMLRenderer) addAbsPrefix(link []byte) []byte { ++ if r.AbsolutePrefix != "" && isRelativeLink(link) && link[0] != '.' { ++ newDest := r.AbsolutePrefix ++ if link[0] != '/' { ++ newDest += "/" ++ } ++ newDest += string(link) ++ return []byte(newDest) ++ } ++ return link ++} ++ ++func appendLinkAttrs(attrs []string, flags HTMLFlags, link []byte) []string { ++ if isRelativeLink(link) { ++ return attrs ++ } ++ val := []string{} ++ if flags&NofollowLinks != 0 { ++ val = append(val, "nofollow") ++ } ++ if flags&NoreferrerLinks != 0 { ++ val = append(val, "noreferrer") ++ } ++ if flags&NoopenerLinks != 0 { ++ val = append(val, "noopener") ++ } ++ if flags&HrefTargetBlank != 0 { ++ attrs = append(attrs, "target=\"_blank\"") ++ } ++ if len(val) == 0 { ++ return attrs ++ } ++ attr := fmt.Sprintf("rel=%q", strings.Join(val, " ")) ++ return append(attrs, attr) ++} ++ ++func isMailto(link []byte) bool { ++ return bytes.HasPrefix(link, []byte("mailto:")) ++} ++ ++func needSkipLink(flags HTMLFlags, dest []byte) bool { ++ if flags&SkipLinks != 0 { ++ return true ++ } ++ return flags&Safelink != 0 && !isSafeLink(dest) && !isMailto(dest) ++} ++ ++func isSmartypantable(node *Node) bool { ++ pt := node.Parent.Type ++ return pt != Link && pt != CodeBlock && pt != Code ++} ++ ++func appendLanguageAttr(attrs []string, info []byte) []string { ++ if len(info) == 0 { ++ return attrs ++ } ++ endOfLang := bytes.IndexAny(info, "\t ") ++ if endOfLang < 0 { ++ endOfLang = len(info) ++ } ++ return append(attrs, fmt.Sprintf("class=\"language-%s\"", info[:endOfLang])) ++} ++ ++func (r *HTMLRenderer) tag(w io.Writer, name []byte, attrs []string) { ++ w.Write(name) ++ if len(attrs) > 0 { ++ w.Write(spaceBytes) ++ w.Write([]byte(strings.Join(attrs, " "))) ++ } ++ w.Write(gtBytes) ++ r.lastOutputLen = 1 ++} ++ ++func footnoteRef(prefix string, node *Node) []byte { ++ urlFrag := prefix + string(slugify(node.Destination)) ++ anchor := fmt.Sprintf(`%d`, urlFrag, node.NoteID) ++ return []byte(fmt.Sprintf(`%s`, urlFrag, anchor)) ++} ++ ++func footnoteItem(prefix string, slug []byte) []byte { ++ return []byte(fmt.Sprintf(`
  • `, prefix, slug)) ++} ++ ++func footnoteReturnLink(prefix, returnLink string, slug []byte) []byte { ++ const format = ` %s` ++ return []byte(fmt.Sprintf(format, prefix, slug, returnLink)) ++} ++ ++func itemOpenCR(node *Node) bool { ++ if node.Prev == nil { ++ return false ++ } ++ ld := node.Parent.ListData ++ return !ld.Tight && ld.ListFlags&ListTypeDefinition == 0 ++} ++ ++func skipParagraphTags(node *Node) bool { ++ grandparent := node.Parent.Parent ++ if grandparent == nil || grandparent.Type != List { ++ return false ++ } ++ tightOrTerm := grandparent.Tight || node.Parent.ListFlags&ListTypeTerm != 0 ++ return grandparent.Type == List && tightOrTerm ++} ++ ++func cellAlignment(align CellAlignFlags) string { ++ switch align { ++ case TableAlignmentLeft: ++ return "left" ++ case TableAlignmentRight: ++ return "right" ++ case TableAlignmentCenter: ++ return "center" ++ default: ++ return "" ++ } ++} ++ ++func (r *HTMLRenderer) out(w io.Writer, text []byte) { ++ if r.disableTags > 0 { ++ w.Write(htmlTagRe.ReplaceAll(text, []byte{})) ++ } else { ++ w.Write(text) ++ } ++ r.lastOutputLen = len(text) ++} ++ ++func (r *HTMLRenderer) cr(w io.Writer) { ++ if r.lastOutputLen > 0 { ++ r.out(w, nlBytes) ++ } ++} ++ ++var ( ++ nlBytes = []byte{'\n'} ++ gtBytes = []byte{'>'} ++ spaceBytes = []byte{' '} ++) ++ ++var ( ++ brTag = []byte("
    ") ++ brXHTMLTag = []byte("
    ") ++ emTag = []byte("") ++ emCloseTag = []byte("") ++ strongTag = []byte("") ++ strongCloseTag = []byte("") ++ delTag = []byte("") ++ delCloseTag = []byte("") ++ ttTag = []byte("") ++ ttCloseTag = []byte("") ++ aTag = []byte("") ++ preTag = []byte("
    ")
    ++	preCloseTag        = []byte("
    ") ++ codeTag = []byte("") ++ codeCloseTag = []byte("") ++ pTag = []byte("

    ") ++ pCloseTag = []byte("

    ") ++ blockquoteTag = []byte("
    ") ++ blockquoteCloseTag = []byte("
    ") ++ hrTag = []byte("
    ") ++ hrXHTMLTag = []byte("
    ") ++ ulTag = []byte("
      ") ++ ulCloseTag = []byte("
    ") ++ olTag = []byte("
      ") ++ olCloseTag = []byte("
    ") ++ dlTag = []byte("
    ") ++ dlCloseTag = []byte("
    ") ++ liTag = []byte("
  • ") ++ liCloseTag = []byte("
  • ") ++ ddTag = []byte("
    ") ++ ddCloseTag = []byte("
    ") ++ dtTag = []byte("
    ") ++ dtCloseTag = []byte("
    ") ++ tableTag = []byte("") ++ tableCloseTag = []byte("
    ") ++ tdTag = []byte("") ++ thTag = []byte("") ++ theadTag = []byte("") ++ theadCloseTag = []byte("") ++ tbodyTag = []byte("") ++ tbodyCloseTag = []byte("") ++ trTag = []byte("") ++ trCloseTag = []byte("") ++ h1Tag = []byte("") ++ h2Tag = []byte("") ++ h3Tag = []byte("") ++ h4Tag = []byte("") ++ h5Tag = []byte("") ++ h6Tag = []byte("") ++ ++ footnotesDivBytes = []byte("\n
    \n\n") ++ footnotesCloseDivBytes = []byte("\n
    \n") ++) ++ ++func headingTagsFromLevel(level int) ([]byte, []byte) { ++ if level <= 1 { ++ return h1Tag, h1CloseTag ++ } ++ switch level { ++ case 2: ++ return h2Tag, h2CloseTag ++ case 3: ++ return h3Tag, h3CloseTag ++ case 4: ++ return h4Tag, h4CloseTag ++ case 5: ++ return h5Tag, h5CloseTag ++ } ++ return h6Tag, h6CloseTag ++} ++ ++func (r *HTMLRenderer) outHRTag(w io.Writer) { ++ if r.Flags&UseXHTML == 0 { ++ r.out(w, hrTag) ++ } else { ++ r.out(w, hrXHTMLTag) ++ } ++} ++ ++// RenderNode is a default renderer of a single node of a syntax tree. For ++// block nodes it will be called twice: first time with entering=true, second ++// time with entering=false, so that it could know when it's working on an open ++// tag and when on close. It writes the result to w. ++// ++// The return value is a way to tell the calling walker to adjust its walk ++// pattern: e.g. it can terminate the traversal by returning Terminate. Or it ++// can ask the walker to skip a subtree of this node by returning SkipChildren. ++// The typical behavior is to return GoToNext, which asks for the usual ++// traversal to the next node. ++func (r *HTMLRenderer) RenderNode(w io.Writer, node *Node, entering bool) WalkStatus { ++ attrs := []string{} ++ switch node.Type { ++ case Text: ++ if r.Flags&Smartypants != 0 { ++ var tmp bytes.Buffer ++ escapeHTML(&tmp, node.Literal) ++ r.sr.Process(w, tmp.Bytes()) ++ } else { ++ if node.Parent.Type == Link { ++ escLink(w, node.Literal) ++ } else { ++ escapeHTML(w, node.Literal) ++ } ++ } ++ case Softbreak: ++ r.cr(w) ++ // TODO: make it configurable via out(renderer.softbreak) ++ case Hardbreak: ++ if r.Flags&UseXHTML == 0 { ++ r.out(w, brTag) ++ } else { ++ r.out(w, brXHTMLTag) ++ } ++ r.cr(w) ++ case Emph: ++ if entering { ++ r.out(w, emTag) ++ } else { ++ r.out(w, emCloseTag) ++ } ++ case Strong: ++ if entering { ++ r.out(w, strongTag) ++ } else { ++ r.out(w, strongCloseTag) ++ } ++ case Del: ++ if entering { ++ r.out(w, delTag) ++ } else { ++ r.out(w, delCloseTag) ++ } ++ case HTMLSpan: ++ if r.Flags&SkipHTML != 0 { ++ break ++ } ++ r.out(w, node.Literal) ++ case Link: ++ // mark it but don't link it if it is not a safe link: no smartypants ++ dest := node.LinkData.Destination ++ if needSkipLink(r.Flags, dest) { ++ if entering { ++ r.out(w, ttTag) ++ } else { ++ r.out(w, ttCloseTag) ++ } ++ } else { ++ if entering { ++ dest = r.addAbsPrefix(dest) ++ var hrefBuf bytes.Buffer ++ hrefBuf.WriteString("href=\"") ++ escLink(&hrefBuf, dest) ++ hrefBuf.WriteByte('"') ++ attrs = append(attrs, hrefBuf.String()) ++ if node.NoteID != 0 { ++ r.out(w, footnoteRef(r.FootnoteAnchorPrefix, node)) ++ break ++ } ++ attrs = appendLinkAttrs(attrs, r.Flags, dest) ++ if len(node.LinkData.Title) > 0 { ++ var titleBuff bytes.Buffer ++ titleBuff.WriteString("title=\"") ++ escapeHTML(&titleBuff, node.LinkData.Title) ++ titleBuff.WriteByte('"') ++ attrs = append(attrs, titleBuff.String()) ++ } ++ r.tag(w, aTag, attrs) ++ } else { ++ if node.NoteID != 0 { ++ break ++ } ++ r.out(w, aCloseTag) ++ } ++ } ++ case Image: ++ if r.Flags&SkipImages != 0 { ++ return SkipChildren ++ } ++ if entering { ++ dest := node.LinkData.Destination ++ dest = r.addAbsPrefix(dest) ++ if r.disableTags == 0 { ++ //if options.safe && potentiallyUnsafe(dest) { ++ //out(w, ``)
++				//} else {
++				r.out(w, []byte(`<img src=`)) ++ } ++ } ++ case Code: ++ r.out(w, codeTag) ++ escapeAllHTML(w, node.Literal) ++ r.out(w, codeCloseTag) ++ case Document: ++ break ++ case Paragraph: ++ if skipParagraphTags(node) { ++ break ++ } ++ if entering { ++ // TODO: untangle this clusterfuck about when the newlines need ++ // to be added and when not. ++ if node.Prev != nil { ++ switch node.Prev.Type { ++ case HTMLBlock, List, Paragraph, Heading, CodeBlock, BlockQuote, HorizontalRule: ++ r.cr(w) ++ } ++ } ++ if node.Parent.Type == BlockQuote && node.Prev == nil { ++ r.cr(w) ++ } ++ r.out(w, pTag) ++ } else { ++ r.out(w, pCloseTag) ++ if !(node.Parent.Type == Item && node.Next == nil) { ++ r.cr(w) ++ } ++ } ++ case BlockQuote: ++ if entering { ++ r.cr(w) ++ r.out(w, blockquoteTag) ++ } else { ++ r.out(w, blockquoteCloseTag) ++ r.cr(w) ++ } ++ case HTMLBlock: ++ if r.Flags&SkipHTML != 0 { ++ break ++ } ++ r.cr(w) ++ r.out(w, node.Literal) ++ r.cr(w) ++ case Heading: ++ headingLevel := r.HTMLRendererParameters.HeadingLevelOffset + node.Level ++ openTag, closeTag := headingTagsFromLevel(headingLevel) ++ if entering { ++ if node.IsTitleblock { ++ attrs = append(attrs, `class="title"`) ++ } ++ if node.HeadingID != "" { ++ id := r.ensureUniqueHeadingID(node.HeadingID) ++ if r.HeadingIDPrefix != "" { ++ id = r.HeadingIDPrefix + id ++ } ++ if r.HeadingIDSuffix != "" { ++ id = id + r.HeadingIDSuffix ++ } ++ attrs = append(attrs, fmt.Sprintf(`id="%s"`, id)) ++ } ++ r.cr(w) ++ r.tag(w, openTag, attrs) ++ } else { ++ r.out(w, closeTag) ++ if !(node.Parent.Type == Item && node.Next == nil) { ++ r.cr(w) ++ } ++ } ++ case HorizontalRule: ++ r.cr(w) ++ r.outHRTag(w) ++ r.cr(w) ++ case List: ++ openTag := ulTag ++ closeTag := ulCloseTag ++ if node.ListFlags&ListTypeOrdered != 0 { ++ openTag = olTag ++ closeTag = olCloseTag ++ } ++ if node.ListFlags&ListTypeDefinition != 0 { ++ openTag = dlTag ++ closeTag = dlCloseTag ++ } ++ if entering { ++ if node.IsFootnotesList { ++ r.out(w, footnotesDivBytes) ++ r.outHRTag(w) ++ r.cr(w) ++ } ++ r.cr(w) ++ if node.Parent.Type == Item && node.Parent.Parent.Tight { ++ r.cr(w) ++ } ++ r.tag(w, openTag[:len(openTag)-1], attrs) ++ r.cr(w) ++ } else { ++ r.out(w, closeTag) ++ //cr(w) ++ //if node.parent.Type != Item { ++ // cr(w) ++ //} ++ if node.Parent.Type == Item && node.Next != nil { ++ r.cr(w) ++ } ++ if node.Parent.Type == Document || node.Parent.Type == BlockQuote { ++ r.cr(w) ++ } ++ if node.IsFootnotesList { ++ r.out(w, footnotesCloseDivBytes) ++ } ++ } ++ case Item: ++ openTag := liTag ++ closeTag := liCloseTag ++ if node.ListFlags&ListTypeDefinition != 0 { ++ openTag = ddTag ++ closeTag = ddCloseTag ++ } ++ if node.ListFlags&ListTypeTerm != 0 { ++ openTag = dtTag ++ closeTag = dtCloseTag ++ } ++ if entering { ++ if itemOpenCR(node) { ++ r.cr(w) ++ } ++ if node.ListData.RefLink != nil { ++ slug := slugify(node.ListData.RefLink) ++ r.out(w, footnoteItem(r.FootnoteAnchorPrefix, slug)) ++ break ++ } ++ r.out(w, openTag) ++ } else { ++ if node.ListData.RefLink != nil { ++ slug := slugify(node.ListData.RefLink) ++ if r.Flags&FootnoteReturnLinks != 0 { ++ r.out(w, footnoteReturnLink(r.FootnoteAnchorPrefix, r.FootnoteReturnLinkContents, slug)) ++ } ++ } ++ r.out(w, closeTag) ++ r.cr(w) ++ } ++ case CodeBlock: ++ attrs = appendLanguageAttr(attrs, node.Info) ++ r.cr(w) ++ r.out(w, preTag) ++ r.tag(w, codeTag[:len(codeTag)-1], attrs) ++ escapeAllHTML(w, node.Literal) ++ r.out(w, codeCloseTag) ++ r.out(w, preCloseTag) ++ if node.Parent.Type != Item { ++ r.cr(w) ++ } ++ case Table: ++ if entering { ++ r.cr(w) ++ r.out(w, tableTag) ++ } else { ++ r.out(w, tableCloseTag) ++ r.cr(w) ++ } ++ case TableCell: ++ openTag := tdTag ++ closeTag := tdCloseTag ++ if node.IsHeader { ++ openTag = thTag ++ closeTag = thCloseTag ++ } ++ if entering { ++ align := cellAlignment(node.Align) ++ if align != "" { ++ attrs = append(attrs, fmt.Sprintf(`align="%s"`, align)) ++ } ++ if node.Prev == nil { ++ r.cr(w) ++ } ++ r.tag(w, openTag, attrs) ++ } else { ++ r.out(w, closeTag) ++ r.cr(w) ++ } ++ case TableHead: ++ if entering { ++ r.cr(w) ++ r.out(w, theadTag) ++ } else { ++ r.out(w, theadCloseTag) ++ r.cr(w) ++ } ++ case TableBody: ++ if entering { ++ r.cr(w) ++ r.out(w, tbodyTag) ++ // XXX: this is to adhere to a rather silly test. Should fix test. ++ if node.FirstChild == nil { ++ r.cr(w) ++ } ++ } else { ++ r.out(w, tbodyCloseTag) ++ r.cr(w) ++ } ++ case TableRow: ++ if entering { ++ r.cr(w) ++ r.out(w, trTag) ++ } else { ++ r.out(w, trCloseTag) ++ r.cr(w) ++ } ++ default: ++ panic("Unknown node type " + node.Type.String()) ++ } ++ return GoToNext ++} ++ ++// RenderHeader writes HTML document preamble and TOC if requested. ++func (r *HTMLRenderer) RenderHeader(w io.Writer, ast *Node) { ++ r.writeDocumentHeader(w) ++ if r.Flags&TOC != 0 { ++ r.writeTOC(w, ast) ++ } ++} ++ ++// RenderFooter writes HTML document footer. ++func (r *HTMLRenderer) RenderFooter(w io.Writer, ast *Node) { ++ if r.Flags&CompletePage == 0 { ++ return ++ } ++ io.WriteString(w, "\n\n\n") ++} ++ ++func (r *HTMLRenderer) writeDocumentHeader(w io.Writer) { ++ if r.Flags&CompletePage == 0 { ++ return ++ } ++ ending := "" ++ if r.Flags&UseXHTML != 0 { ++ io.WriteString(w, "\n") ++ io.WriteString(w, "\n") ++ ending = " /" ++ } else { ++ io.WriteString(w, "\n") ++ io.WriteString(w, "\n") ++ } ++ io.WriteString(w, "\n") ++ io.WriteString(w, " ") ++ if r.Flags&Smartypants != 0 { ++ r.sr.Process(w, []byte(r.Title)) ++ } else { ++ escapeHTML(w, []byte(r.Title)) ++ } ++ io.WriteString(w, "\n") ++ io.WriteString(w, " \n") ++ io.WriteString(w, " \n") ++ if r.CSS != "" { ++ io.WriteString(w, " \n") ++ } ++ if r.Icon != "" { ++ io.WriteString(w, " \n") ++ } ++ io.WriteString(w, "\n") ++ io.WriteString(w, "\n\n") ++} ++ ++func (r *HTMLRenderer) writeTOC(w io.Writer, ast *Node) { ++ buf := bytes.Buffer{} ++ ++ inHeading := false ++ tocLevel := 0 ++ headingCount := 0 ++ ++ ast.Walk(func(node *Node, entering bool) WalkStatus { ++ if node.Type == Heading && !node.HeadingData.IsTitleblock { ++ inHeading = entering ++ if entering { ++ node.HeadingID = fmt.Sprintf("toc_%d", headingCount) ++ if node.Level == tocLevel { ++ buf.WriteString("\n\n
  • ") ++ } else if node.Level < tocLevel { ++ for node.Level < tocLevel { ++ tocLevel-- ++ buf.WriteString("
  • \n") ++ } ++ buf.WriteString("\n\n
  • ") ++ } else { ++ for node.Level > tocLevel { ++ tocLevel++ ++ buf.WriteString("\n") ++ } ++ ++ if buf.Len() > 0 { ++ io.WriteString(w, "\n") ++ } ++ r.lastOutputLen = buf.Len() ++} +diff --git a/vendor/github.com/russross/blackfriday/v2/inline.go b/vendor/github.com/russross/blackfriday/v2/inline.go +new file mode 100644 +index 000000000000..d45bd941726e +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/inline.go +@@ -0,0 +1,1228 @@ ++// ++// Blackfriday Markdown Processor ++// Available at http://github.com/russross/blackfriday ++// ++// Copyright © 2011 Russ Ross . ++// Distributed under the Simplified BSD License. ++// See README.md for details. ++// ++ ++// ++// Functions to parse inline elements. ++// ++ ++package blackfriday ++ ++import ( ++ "bytes" ++ "regexp" ++ "strconv" ++) ++ ++var ( ++ urlRe = `((https?|ftp):\/\/|\/)[-A-Za-z0-9+&@#\/%?=~_|!:,.;\(\)]+` ++ anchorRe = regexp.MustCompile(`^(]+")?\s?>` + urlRe + `<\/a>)`) ++ ++ // https://www.w3.org/TR/html5/syntax.html#character-references ++ // highest unicode code point in 17 planes (2^20): 1,114,112d = ++ // 7 dec digits or 6 hex digits ++ // named entity references can be 2-31 characters with stuff like < ++ // at one end and ∳ at the other. There ++ // are also sometimes numbers at the end, although this isn't inherent ++ // in the specification; there are never numbers anywhere else in ++ // current character references, though; see ¾ and ▒, etc. ++ // https://www.w3.org/TR/html5/syntax.html#named-character-references ++ // ++ // entity := "&" (named group | number ref) ";" ++ // named group := [a-zA-Z]{2,31}[0-9]{0,2} ++ // number ref := "#" (dec ref | hex ref) ++ // dec ref := [0-9]{1,7} ++ // hex ref := ("x" | "X") [0-9a-fA-F]{1,6} ++ htmlEntityRe = regexp.MustCompile(`&([a-zA-Z]{2,31}[0-9]{0,2}|#([0-9]{1,7}|[xX][0-9a-fA-F]{1,6}));`) ++) ++ ++// Functions to parse text within a block ++// Each function returns the number of chars taken care of ++// data is the complete block being rendered ++// offset is the number of valid chars before the current cursor ++ ++func (p *Markdown) inline(currBlock *Node, data []byte) { ++ // handlers might call us recursively: enforce a maximum depth ++ if p.nesting >= p.maxNesting || len(data) == 0 { ++ return ++ } ++ p.nesting++ ++ beg, end := 0, 0 ++ for end < len(data) { ++ handler := p.inlineCallback[data[end]] ++ if handler != nil { ++ if consumed, node := handler(p, data, end); consumed == 0 { ++ // No action from the callback. ++ end++ ++ } else { ++ // Copy inactive chars into the output. ++ currBlock.AppendChild(text(data[beg:end])) ++ if node != nil { ++ currBlock.AppendChild(node) ++ } ++ // Skip past whatever the callback used. ++ beg = end + consumed ++ end = beg ++ } ++ } else { ++ end++ ++ } ++ } ++ if beg < len(data) { ++ if data[end-1] == '\n' { ++ end-- ++ } ++ currBlock.AppendChild(text(data[beg:end])) ++ } ++ p.nesting-- ++} ++ ++// single and double emphasis parsing ++func emphasis(p *Markdown, data []byte, offset int) (int, *Node) { ++ data = data[offset:] ++ c := data[0] ++ ++ if len(data) > 2 && data[1] != c { ++ // whitespace cannot follow an opening emphasis; ++ // strikethrough only takes two characters '~~' ++ if c == '~' || isspace(data[1]) { ++ return 0, nil ++ } ++ ret, node := helperEmphasis(p, data[1:], c) ++ if ret == 0 { ++ return 0, nil ++ } ++ ++ return ret + 1, node ++ } ++ ++ if len(data) > 3 && data[1] == c && data[2] != c { ++ if isspace(data[2]) { ++ return 0, nil ++ } ++ ret, node := helperDoubleEmphasis(p, data[2:], c) ++ if ret == 0 { ++ return 0, nil ++ } ++ ++ return ret + 2, node ++ } ++ ++ if len(data) > 4 && data[1] == c && data[2] == c && data[3] != c { ++ if c == '~' || isspace(data[3]) { ++ return 0, nil ++ } ++ ret, node := helperTripleEmphasis(p, data, 3, c) ++ if ret == 0 { ++ return 0, nil ++ } ++ ++ return ret + 3, node ++ } ++ ++ return 0, nil ++} ++ ++func codeSpan(p *Markdown, data []byte, offset int) (int, *Node) { ++ data = data[offset:] ++ ++ nb := 0 ++ ++ // count the number of backticks in the delimiter ++ for nb < len(data) && data[nb] == '`' { ++ nb++ ++ } ++ ++ // find the next delimiter ++ i, end := 0, 0 ++ for end = nb; end < len(data) && i < nb; end++ { ++ if data[end] == '`' { ++ i++ ++ } else { ++ i = 0 ++ } ++ } ++ ++ // no matching delimiter? ++ if i < nb && end >= len(data) { ++ return 0, nil ++ } ++ ++ // trim outside whitespace ++ fBegin := nb ++ for fBegin < end && data[fBegin] == ' ' { ++ fBegin++ ++ } ++ ++ fEnd := end - nb ++ for fEnd > fBegin && data[fEnd-1] == ' ' { ++ fEnd-- ++ } ++ ++ // render the code span ++ if fBegin != fEnd { ++ code := NewNode(Code) ++ code.Literal = data[fBegin:fEnd] ++ return end, code ++ } ++ ++ return end, nil ++} ++ ++// newline preceded by two spaces becomes
    ++func maybeLineBreak(p *Markdown, data []byte, offset int) (int, *Node) { ++ origOffset := offset ++ for offset < len(data) && data[offset] == ' ' { ++ offset++ ++ } ++ ++ if offset < len(data) && data[offset] == '\n' { ++ if offset-origOffset >= 2 { ++ return offset - origOffset + 1, NewNode(Hardbreak) ++ } ++ return offset - origOffset, nil ++ } ++ return 0, nil ++} ++ ++// newline without two spaces works when HardLineBreak is enabled ++func lineBreak(p *Markdown, data []byte, offset int) (int, *Node) { ++ if p.extensions&HardLineBreak != 0 { ++ return 1, NewNode(Hardbreak) ++ } ++ return 0, nil ++} ++ ++type linkType int ++ ++const ( ++ linkNormal linkType = iota ++ linkImg ++ linkDeferredFootnote ++ linkInlineFootnote ++) ++ ++func isReferenceStyleLink(data []byte, pos int, t linkType) bool { ++ if t == linkDeferredFootnote { ++ return false ++ } ++ return pos < len(data)-1 && data[pos] == '[' && data[pos+1] != '^' ++} ++ ++func maybeImage(p *Markdown, data []byte, offset int) (int, *Node) { ++ if offset < len(data)-1 && data[offset+1] == '[' { ++ return link(p, data, offset) ++ } ++ return 0, nil ++} ++ ++func maybeInlineFootnote(p *Markdown, data []byte, offset int) (int, *Node) { ++ if offset < len(data)-1 && data[offset+1] == '[' { ++ return link(p, data, offset) ++ } ++ return 0, nil ++} ++ ++// '[': parse a link or an image or a footnote ++func link(p *Markdown, data []byte, offset int) (int, *Node) { ++ // no links allowed inside regular links, footnote, and deferred footnotes ++ if p.insideLink && (offset > 0 && data[offset-1] == '[' || len(data)-1 > offset && data[offset+1] == '^') { ++ return 0, nil ++ } ++ ++ var t linkType ++ switch { ++ // special case: ![^text] == deferred footnote (that follows something with ++ // an exclamation point) ++ case p.extensions&Footnotes != 0 && len(data)-1 > offset && data[offset+1] == '^': ++ t = linkDeferredFootnote ++ // ![alt] == image ++ case offset >= 0 && data[offset] == '!': ++ t = linkImg ++ offset++ ++ // ^[text] == inline footnote ++ // [^refId] == deferred footnote ++ case p.extensions&Footnotes != 0: ++ if offset >= 0 && data[offset] == '^' { ++ t = linkInlineFootnote ++ offset++ ++ } else if len(data)-1 > offset && data[offset+1] == '^' { ++ t = linkDeferredFootnote ++ } ++ // [text] == regular link ++ default: ++ t = linkNormal ++ } ++ ++ data = data[offset:] ++ ++ var ( ++ i = 1 ++ noteID int ++ title, link, altContent []byte ++ textHasNl = false ++ ) ++ ++ if t == linkDeferredFootnote { ++ i++ ++ } ++ ++ // look for the matching closing bracket ++ for level := 1; level > 0 && i < len(data); i++ { ++ switch { ++ case data[i] == '\n': ++ textHasNl = true ++ ++ case isBackslashEscaped(data, i): ++ continue ++ ++ case data[i] == '[': ++ level++ ++ ++ case data[i] == ']': ++ level-- ++ if level <= 0 { ++ i-- // compensate for extra i++ in for loop ++ } ++ } ++ } ++ ++ if i >= len(data) { ++ return 0, nil ++ } ++ ++ txtE := i ++ i++ ++ var footnoteNode *Node ++ ++ // skip any amount of whitespace or newline ++ // (this is much more lax than original markdown syntax) ++ for i < len(data) && isspace(data[i]) { ++ i++ ++ } ++ ++ // inline style link ++ switch { ++ case i < len(data) && data[i] == '(': ++ // skip initial whitespace ++ i++ ++ ++ for i < len(data) && isspace(data[i]) { ++ i++ ++ } ++ ++ linkB := i ++ ++ // look for link end: ' " ) ++ findlinkend: ++ for i < len(data) { ++ switch { ++ case data[i] == '\\': ++ i += 2 ++ ++ case data[i] == ')' || data[i] == '\'' || data[i] == '"': ++ break findlinkend ++ ++ default: ++ i++ ++ } ++ } ++ ++ if i >= len(data) { ++ return 0, nil ++ } ++ linkE := i ++ ++ // look for title end if present ++ titleB, titleE := 0, 0 ++ if data[i] == '\'' || data[i] == '"' { ++ i++ ++ titleB = i ++ ++ findtitleend: ++ for i < len(data) { ++ switch { ++ case data[i] == '\\': ++ i += 2 ++ ++ case data[i] == ')': ++ break findtitleend ++ ++ default: ++ i++ ++ } ++ } ++ ++ if i >= len(data) { ++ return 0, nil ++ } ++ ++ // skip whitespace after title ++ titleE = i - 1 ++ for titleE > titleB && isspace(data[titleE]) { ++ titleE-- ++ } ++ ++ // check for closing quote presence ++ if data[titleE] != '\'' && data[titleE] != '"' { ++ titleB, titleE = 0, 0 ++ linkE = i ++ } ++ } ++ ++ // remove whitespace at the end of the link ++ for linkE > linkB && isspace(data[linkE-1]) { ++ linkE-- ++ } ++ ++ // remove optional angle brackets around the link ++ if data[linkB] == '<' { ++ linkB++ ++ } ++ if data[linkE-1] == '>' { ++ linkE-- ++ } ++ ++ // build escaped link and title ++ if linkE > linkB { ++ link = data[linkB:linkE] ++ } ++ ++ if titleE > titleB { ++ title = data[titleB:titleE] ++ } ++ ++ i++ ++ ++ // reference style link ++ case isReferenceStyleLink(data, i, t): ++ var id []byte ++ altContentConsidered := false ++ ++ // look for the id ++ i++ ++ linkB := i ++ for i < len(data) && data[i] != ']' { ++ i++ ++ } ++ if i >= len(data) { ++ return 0, nil ++ } ++ linkE := i ++ ++ // find the reference ++ if linkB == linkE { ++ if textHasNl { ++ var b bytes.Buffer ++ ++ for j := 1; j < txtE; j++ { ++ switch { ++ case data[j] != '\n': ++ b.WriteByte(data[j]) ++ case data[j-1] != ' ': ++ b.WriteByte(' ') ++ } ++ } ++ ++ id = b.Bytes() ++ } else { ++ id = data[1:txtE] ++ altContentConsidered = true ++ } ++ } else { ++ id = data[linkB:linkE] ++ } ++ ++ // find the reference with matching id ++ lr, ok := p.getRef(string(id)) ++ if !ok { ++ return 0, nil ++ } ++ ++ // keep link and title from reference ++ link = lr.link ++ title = lr.title ++ if altContentConsidered { ++ altContent = lr.text ++ } ++ i++ ++ ++ // shortcut reference style link or reference or inline footnote ++ default: ++ var id []byte ++ ++ // craft the id ++ if textHasNl { ++ var b bytes.Buffer ++ ++ for j := 1; j < txtE; j++ { ++ switch { ++ case data[j] != '\n': ++ b.WriteByte(data[j]) ++ case data[j-1] != ' ': ++ b.WriteByte(' ') ++ } ++ } ++ ++ id = b.Bytes() ++ } else { ++ if t == linkDeferredFootnote { ++ id = data[2:txtE] // get rid of the ^ ++ } else { ++ id = data[1:txtE] ++ } ++ } ++ ++ footnoteNode = NewNode(Item) ++ if t == linkInlineFootnote { ++ // create a new reference ++ noteID = len(p.notes) + 1 ++ ++ var fragment []byte ++ if len(id) > 0 { ++ if len(id) < 16 { ++ fragment = make([]byte, len(id)) ++ } else { ++ fragment = make([]byte, 16) ++ } ++ copy(fragment, slugify(id)) ++ } else { ++ fragment = append([]byte("footnote-"), []byte(strconv.Itoa(noteID))...) ++ } ++ ++ ref := &reference{ ++ noteID: noteID, ++ hasBlock: false, ++ link: fragment, ++ title: id, ++ footnote: footnoteNode, ++ } ++ ++ p.notes = append(p.notes, ref) ++ ++ link = ref.link ++ title = ref.title ++ } else { ++ // find the reference with matching id ++ lr, ok := p.getRef(string(id)) ++ if !ok { ++ return 0, nil ++ } ++ ++ if t == linkDeferredFootnote { ++ lr.noteID = len(p.notes) + 1 ++ lr.footnote = footnoteNode ++ p.notes = append(p.notes, lr) ++ } ++ ++ // keep link and title from reference ++ link = lr.link ++ // if inline footnote, title == footnote contents ++ title = lr.title ++ noteID = lr.noteID ++ } ++ ++ // rewind the whitespace ++ i = txtE + 1 ++ } ++ ++ var uLink []byte ++ if t == linkNormal || t == linkImg { ++ if len(link) > 0 { ++ var uLinkBuf bytes.Buffer ++ unescapeText(&uLinkBuf, link) ++ uLink = uLinkBuf.Bytes() ++ } ++ ++ // links need something to click on and somewhere to go ++ if len(uLink) == 0 || (t == linkNormal && txtE <= 1) { ++ return 0, nil ++ } ++ } ++ ++ // call the relevant rendering function ++ var linkNode *Node ++ switch t { ++ case linkNormal: ++ linkNode = NewNode(Link) ++ linkNode.Destination = normalizeURI(uLink) ++ linkNode.Title = title ++ if len(altContent) > 0 { ++ linkNode.AppendChild(text(altContent)) ++ } else { ++ // links cannot contain other links, so turn off link parsing ++ // temporarily and recurse ++ insideLink := p.insideLink ++ p.insideLink = true ++ p.inline(linkNode, data[1:txtE]) ++ p.insideLink = insideLink ++ } ++ ++ case linkImg: ++ linkNode = NewNode(Image) ++ linkNode.Destination = uLink ++ linkNode.Title = title ++ linkNode.AppendChild(text(data[1:txtE])) ++ i++ ++ ++ case linkInlineFootnote, linkDeferredFootnote: ++ linkNode = NewNode(Link) ++ linkNode.Destination = link ++ linkNode.Title = title ++ linkNode.NoteID = noteID ++ linkNode.Footnote = footnoteNode ++ if t == linkInlineFootnote { ++ i++ ++ } ++ ++ default: ++ return 0, nil ++ } ++ ++ return i, linkNode ++} ++ ++func (p *Markdown) inlineHTMLComment(data []byte) int { ++ if len(data) < 5 { ++ return 0 ++ } ++ if data[0] != '<' || data[1] != '!' || data[2] != '-' || data[3] != '-' { ++ return 0 ++ } ++ i := 5 ++ // scan for an end-of-comment marker, across lines if necessary ++ for i < len(data) && !(data[i-2] == '-' && data[i-1] == '-' && data[i] == '>') { ++ i++ ++ } ++ // no end-of-comment marker ++ if i >= len(data) { ++ return 0 ++ } ++ return i + 1 ++} ++ ++func stripMailto(link []byte) []byte { ++ if bytes.HasPrefix(link, []byte("mailto://")) { ++ return link[9:] ++ } else if bytes.HasPrefix(link, []byte("mailto:")) { ++ return link[7:] ++ } else { ++ return link ++ } ++} ++ ++// autolinkType specifies a kind of autolink that gets detected. ++type autolinkType int ++ ++// These are the possible flag values for the autolink renderer. ++const ( ++ notAutolink autolinkType = iota ++ normalAutolink ++ emailAutolink ++) ++ ++// '<' when tags or autolinks are allowed ++func leftAngle(p *Markdown, data []byte, offset int) (int, *Node) { ++ data = data[offset:] ++ altype, end := tagLength(data) ++ if size := p.inlineHTMLComment(data); size > 0 { ++ end = size ++ } ++ if end > 2 { ++ if altype != notAutolink { ++ var uLink bytes.Buffer ++ unescapeText(&uLink, data[1:end+1-2]) ++ if uLink.Len() > 0 { ++ link := uLink.Bytes() ++ node := NewNode(Link) ++ node.Destination = link ++ if altype == emailAutolink { ++ node.Destination = append([]byte("mailto:"), link...) ++ } ++ node.AppendChild(text(stripMailto(link))) ++ return end, node ++ } ++ } else { ++ htmlTag := NewNode(HTMLSpan) ++ htmlTag.Literal = data[:end] ++ return end, htmlTag ++ } ++ } ++ ++ return end, nil ++} ++ ++// '\\' backslash escape ++var escapeChars = []byte("\\`*_{}[]()#+-.!:|&<>~") ++ ++func escape(p *Markdown, data []byte, offset int) (int, *Node) { ++ data = data[offset:] ++ ++ if len(data) > 1 { ++ if p.extensions&BackslashLineBreak != 0 && data[1] == '\n' { ++ return 2, NewNode(Hardbreak) ++ } ++ if bytes.IndexByte(escapeChars, data[1]) < 0 { ++ return 0, nil ++ } ++ ++ return 2, text(data[1:2]) ++ } ++ ++ return 2, nil ++} ++ ++func unescapeText(ob *bytes.Buffer, src []byte) { ++ i := 0 ++ for i < len(src) { ++ org := i ++ for i < len(src) && src[i] != '\\' { ++ i++ ++ } ++ ++ if i > org { ++ ob.Write(src[org:i]) ++ } ++ ++ if i+1 >= len(src) { ++ break ++ } ++ ++ ob.WriteByte(src[i+1]) ++ i += 2 ++ } ++} ++ ++// '&' escaped when it doesn't belong to an entity ++// valid entities are assumed to be anything matching &#?[A-Za-z0-9]+; ++func entity(p *Markdown, data []byte, offset int) (int, *Node) { ++ data = data[offset:] ++ ++ end := 1 ++ ++ if end < len(data) && data[end] == '#' { ++ end++ ++ } ++ ++ for end < len(data) && isalnum(data[end]) { ++ end++ ++ } ++ ++ if end < len(data) && data[end] == ';' { ++ end++ // real entity ++ } else { ++ return 0, nil // lone '&' ++ } ++ ++ ent := data[:end] ++ // undo & escaping or it will be converted to &amp; by another ++ // escaper in the renderer ++ if bytes.Equal(ent, []byte("&")) { ++ ent = []byte{'&'} ++ } ++ ++ return end, text(ent) ++} ++ ++func linkEndsWithEntity(data []byte, linkEnd int) bool { ++ entityRanges := htmlEntityRe.FindAllIndex(data[:linkEnd], -1) ++ return entityRanges != nil && entityRanges[len(entityRanges)-1][1] == linkEnd ++} ++ ++// hasPrefixCaseInsensitive is a custom implementation of ++// strings.HasPrefix(strings.ToLower(s), prefix) ++// we rolled our own because ToLower pulls in a huge machinery of lowercasing ++// anything from Unicode and that's very slow. Since this func will only be ++// used on ASCII protocol prefixes, we can take shortcuts. ++func hasPrefixCaseInsensitive(s, prefix []byte) bool { ++ if len(s) < len(prefix) { ++ return false ++ } ++ delta := byte('a' - 'A') ++ for i, b := range prefix { ++ if b != s[i] && b != s[i]+delta { ++ return false ++ } ++ } ++ return true ++} ++ ++var protocolPrefixes = [][]byte{ ++ []byte("http://"), ++ []byte("https://"), ++ []byte("ftp://"), ++ []byte("file://"), ++ []byte("mailto:"), ++} ++ ++const shortestPrefix = 6 // len("ftp://"), the shortest of the above ++ ++func maybeAutoLink(p *Markdown, data []byte, offset int) (int, *Node) { ++ // quick check to rule out most false hits ++ if p.insideLink || len(data) < offset+shortestPrefix { ++ return 0, nil ++ } ++ for _, prefix := range protocolPrefixes { ++ endOfHead := offset + 8 // 8 is the len() of the longest prefix ++ if endOfHead > len(data) { ++ endOfHead = len(data) ++ } ++ if hasPrefixCaseInsensitive(data[offset:endOfHead], prefix) { ++ return autoLink(p, data, offset) ++ } ++ } ++ return 0, nil ++} ++ ++func autoLink(p *Markdown, data []byte, offset int) (int, *Node) { ++ // Now a more expensive check to see if we're not inside an anchor element ++ anchorStart := offset ++ offsetFromAnchor := 0 ++ for anchorStart > 0 && data[anchorStart] != '<' { ++ anchorStart-- ++ offsetFromAnchor++ ++ } ++ ++ anchorStr := anchorRe.Find(data[anchorStart:]) ++ if anchorStr != nil { ++ anchorClose := NewNode(HTMLSpan) ++ anchorClose.Literal = anchorStr[offsetFromAnchor:] ++ return len(anchorStr) - offsetFromAnchor, anchorClose ++ } ++ ++ // scan backward for a word boundary ++ rewind := 0 ++ for offset-rewind > 0 && rewind <= 7 && isletter(data[offset-rewind-1]) { ++ rewind++ ++ } ++ if rewind > 6 { // longest supported protocol is "mailto" which has 6 letters ++ return 0, nil ++ } ++ ++ origData := data ++ data = data[offset-rewind:] ++ ++ if !isSafeLink(data) { ++ return 0, nil ++ } ++ ++ linkEnd := 0 ++ for linkEnd < len(data) && !isEndOfLink(data[linkEnd]) { ++ linkEnd++ ++ } ++ ++ // Skip punctuation at the end of the link ++ if (data[linkEnd-1] == '.' || data[linkEnd-1] == ',') && data[linkEnd-2] != '\\' { ++ linkEnd-- ++ } ++ ++ // But don't skip semicolon if it's a part of escaped entity: ++ if data[linkEnd-1] == ';' && data[linkEnd-2] != '\\' && !linkEndsWithEntity(data, linkEnd) { ++ linkEnd-- ++ } ++ ++ // See if the link finishes with a punctuation sign that can be closed. ++ var copen byte ++ switch data[linkEnd-1] { ++ case '"': ++ copen = '"' ++ case '\'': ++ copen = '\'' ++ case ')': ++ copen = '(' ++ case ']': ++ copen = '[' ++ case '}': ++ copen = '{' ++ default: ++ copen = 0 ++ } ++ ++ if copen != 0 { ++ bufEnd := offset - rewind + linkEnd - 2 ++ ++ openDelim := 1 ++ ++ /* Try to close the final punctuation sign in this same line; ++ * if we managed to close it outside of the URL, that means that it's ++ * not part of the URL. If it closes inside the URL, that means it ++ * is part of the URL. ++ * ++ * Examples: ++ * ++ * foo http://www.pokemon.com/Pikachu_(Electric) bar ++ * => http://www.pokemon.com/Pikachu_(Electric) ++ * ++ * foo (http://www.pokemon.com/Pikachu_(Electric)) bar ++ * => http://www.pokemon.com/Pikachu_(Electric) ++ * ++ * foo http://www.pokemon.com/Pikachu_(Electric)) bar ++ * => http://www.pokemon.com/Pikachu_(Electric)) ++ * ++ * (foo http://www.pokemon.com/Pikachu_(Electric)) bar ++ * => foo http://www.pokemon.com/Pikachu_(Electric) ++ */ ++ ++ for bufEnd >= 0 && origData[bufEnd] != '\n' && openDelim != 0 { ++ if origData[bufEnd] == data[linkEnd-1] { ++ openDelim++ ++ } ++ ++ if origData[bufEnd] == copen { ++ openDelim-- ++ } ++ ++ bufEnd-- ++ } ++ ++ if openDelim == 0 { ++ linkEnd-- ++ } ++ } ++ ++ var uLink bytes.Buffer ++ unescapeText(&uLink, data[:linkEnd]) ++ ++ if uLink.Len() > 0 { ++ node := NewNode(Link) ++ node.Destination = uLink.Bytes() ++ node.AppendChild(text(uLink.Bytes())) ++ return linkEnd, node ++ } ++ ++ return linkEnd, nil ++} ++ ++func isEndOfLink(char byte) bool { ++ return isspace(char) || char == '<' ++} ++ ++var validUris = [][]byte{[]byte("http://"), []byte("https://"), []byte("ftp://"), []byte("mailto://")} ++var validPaths = [][]byte{[]byte("/"), []byte("./"), []byte("../")} ++ ++func isSafeLink(link []byte) bool { ++ for _, path := range validPaths { ++ if len(link) >= len(path) && bytes.Equal(link[:len(path)], path) { ++ if len(link) == len(path) { ++ return true ++ } else if isalnum(link[len(path)]) { ++ return true ++ } ++ } ++ } ++ ++ for _, prefix := range validUris { ++ // TODO: handle unicode here ++ // case-insensitive prefix test ++ if len(link) > len(prefix) && bytes.Equal(bytes.ToLower(link[:len(prefix)]), prefix) && isalnum(link[len(prefix)]) { ++ return true ++ } ++ } ++ ++ return false ++} ++ ++// return the length of the given tag, or 0 is it's not valid ++func tagLength(data []byte) (autolink autolinkType, end int) { ++ var i, j int ++ ++ // a valid tag can't be shorter than 3 chars ++ if len(data) < 3 { ++ return notAutolink, 0 ++ } ++ ++ // begins with a '<' optionally followed by '/', followed by letter or number ++ if data[0] != '<' { ++ return notAutolink, 0 ++ } ++ if data[1] == '/' { ++ i = 2 ++ } else { ++ i = 1 ++ } ++ ++ if !isalnum(data[i]) { ++ return notAutolink, 0 ++ } ++ ++ // scheme test ++ autolink = notAutolink ++ ++ // try to find the beginning of an URI ++ for i < len(data) && (isalnum(data[i]) || data[i] == '.' || data[i] == '+' || data[i] == '-') { ++ i++ ++ } ++ ++ if i > 1 && i < len(data) && data[i] == '@' { ++ if j = isMailtoAutoLink(data[i:]); j != 0 { ++ return emailAutolink, i + j ++ } ++ } ++ ++ if i > 2 && i < len(data) && data[i] == ':' { ++ autolink = normalAutolink ++ i++ ++ } ++ ++ // complete autolink test: no whitespace or ' or " ++ switch { ++ case i >= len(data): ++ autolink = notAutolink ++ case autolink != notAutolink: ++ j = i ++ ++ for i < len(data) { ++ if data[i] == '\\' { ++ i += 2 ++ } else if data[i] == '>' || data[i] == '\'' || data[i] == '"' || isspace(data[i]) { ++ break ++ } else { ++ i++ ++ } ++ ++ } ++ ++ if i >= len(data) { ++ return autolink, 0 ++ } ++ if i > j && data[i] == '>' { ++ return autolink, i + 1 ++ } ++ ++ // one of the forbidden chars has been found ++ autolink = notAutolink ++ } ++ i += bytes.IndexByte(data[i:], '>') ++ if i < 0 { ++ return autolink, 0 ++ } ++ return autolink, i + 1 ++} ++ ++// look for the address part of a mail autolink and '>' ++// this is less strict than the original markdown e-mail address matching ++func isMailtoAutoLink(data []byte) int { ++ nb := 0 ++ ++ // address is assumed to be: [-@._a-zA-Z0-9]+ with exactly one '@' ++ for i := 0; i < len(data); i++ { ++ if isalnum(data[i]) { ++ continue ++ } ++ ++ switch data[i] { ++ case '@': ++ nb++ ++ ++ case '-', '.', '_': ++ break ++ ++ case '>': ++ if nb == 1 { ++ return i + 1 ++ } ++ return 0 ++ default: ++ return 0 ++ } ++ } ++ ++ return 0 ++} ++ ++// look for the next emph char, skipping other constructs ++func helperFindEmphChar(data []byte, c byte) int { ++ i := 0 ++ ++ for i < len(data) { ++ for i < len(data) && data[i] != c && data[i] != '`' && data[i] != '[' { ++ i++ ++ } ++ if i >= len(data) { ++ return 0 ++ } ++ // do not count escaped chars ++ if i != 0 && data[i-1] == '\\' { ++ i++ ++ continue ++ } ++ if data[i] == c { ++ return i ++ } ++ ++ if data[i] == '`' { ++ // skip a code span ++ tmpI := 0 ++ i++ ++ for i < len(data) && data[i] != '`' { ++ if tmpI == 0 && data[i] == c { ++ tmpI = i ++ } ++ i++ ++ } ++ if i >= len(data) { ++ return tmpI ++ } ++ i++ ++ } else if data[i] == '[' { ++ // skip a link ++ tmpI := 0 ++ i++ ++ for i < len(data) && data[i] != ']' { ++ if tmpI == 0 && data[i] == c { ++ tmpI = i ++ } ++ i++ ++ } ++ i++ ++ for i < len(data) && (data[i] == ' ' || data[i] == '\n') { ++ i++ ++ } ++ if i >= len(data) { ++ return tmpI ++ } ++ if data[i] != '[' && data[i] != '(' { // not a link ++ if tmpI > 0 { ++ return tmpI ++ } ++ continue ++ } ++ cc := data[i] ++ i++ ++ for i < len(data) && data[i] != cc { ++ if tmpI == 0 && data[i] == c { ++ return i ++ } ++ i++ ++ } ++ if i >= len(data) { ++ return tmpI ++ } ++ i++ ++ } ++ } ++ return 0 ++} ++ ++func helperEmphasis(p *Markdown, data []byte, c byte) (int, *Node) { ++ i := 0 ++ ++ // skip one symbol if coming from emph3 ++ if len(data) > 1 && data[0] == c && data[1] == c { ++ i = 1 ++ } ++ ++ for i < len(data) { ++ length := helperFindEmphChar(data[i:], c) ++ if length == 0 { ++ return 0, nil ++ } ++ i += length ++ if i >= len(data) { ++ return 0, nil ++ } ++ ++ if i+1 < len(data) && data[i+1] == c { ++ i++ ++ continue ++ } ++ ++ if data[i] == c && !isspace(data[i-1]) { ++ ++ if p.extensions&NoIntraEmphasis != 0 { ++ if !(i+1 == len(data) || isspace(data[i+1]) || ispunct(data[i+1])) { ++ continue ++ } ++ } ++ ++ emph := NewNode(Emph) ++ p.inline(emph, data[:i]) ++ return i + 1, emph ++ } ++ } ++ ++ return 0, nil ++} ++ ++func helperDoubleEmphasis(p *Markdown, data []byte, c byte) (int, *Node) { ++ i := 0 ++ ++ for i < len(data) { ++ length := helperFindEmphChar(data[i:], c) ++ if length == 0 { ++ return 0, nil ++ } ++ i += length ++ ++ if i+1 < len(data) && data[i] == c && data[i+1] == c && i > 0 && !isspace(data[i-1]) { ++ nodeType := Strong ++ if c == '~' { ++ nodeType = Del ++ } ++ node := NewNode(nodeType) ++ p.inline(node, data[:i]) ++ return i + 2, node ++ } ++ i++ ++ } ++ return 0, nil ++} ++ ++func helperTripleEmphasis(p *Markdown, data []byte, offset int, c byte) (int, *Node) { ++ i := 0 ++ origData := data ++ data = data[offset:] ++ ++ for i < len(data) { ++ length := helperFindEmphChar(data[i:], c) ++ if length == 0 { ++ return 0, nil ++ } ++ i += length ++ ++ // skip whitespace preceded symbols ++ if data[i] != c || isspace(data[i-1]) { ++ continue ++ } ++ ++ switch { ++ case i+2 < len(data) && data[i+1] == c && data[i+2] == c: ++ // triple symbol found ++ strong := NewNode(Strong) ++ em := NewNode(Emph) ++ strong.AppendChild(em) ++ p.inline(em, data[:i]) ++ return i + 3, strong ++ case (i+1 < len(data) && data[i+1] == c): ++ // double symbol found, hand over to emph1 ++ length, node := helperEmphasis(p, origData[offset-2:], c) ++ if length == 0 { ++ return 0, nil ++ } ++ return length - 2, node ++ default: ++ // single symbol found, hand over to emph2 ++ length, node := helperDoubleEmphasis(p, origData[offset-1:], c) ++ if length == 0 { ++ return 0, nil ++ } ++ return length - 1, node ++ } ++ } ++ return 0, nil ++} ++ ++func text(s []byte) *Node { ++ node := NewNode(Text) ++ node.Literal = s ++ return node ++} ++ ++func normalizeURI(s []byte) []byte { ++ return s // TODO: implement ++} +diff --git a/vendor/github.com/russross/blackfriday/v2/markdown.go b/vendor/github.com/russross/blackfriday/v2/markdown.go +new file mode 100644 +index 000000000000..58d2e4538c62 +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/markdown.go +@@ -0,0 +1,950 @@ ++// Blackfriday Markdown Processor ++// Available at http://github.com/russross/blackfriday ++// ++// Copyright © 2011 Russ Ross . ++// Distributed under the Simplified BSD License. ++// See README.md for details. ++ ++package blackfriday ++ ++import ( ++ "bytes" ++ "fmt" ++ "io" ++ "strings" ++ "unicode/utf8" ++) ++ ++// ++// Markdown parsing and processing ++// ++ ++// Version string of the package. Appears in the rendered document when ++// CompletePage flag is on. ++const Version = "2.0" ++ ++// Extensions is a bitwise or'ed collection of enabled Blackfriday's ++// extensions. ++type Extensions int ++ ++// These are the supported markdown parsing extensions. ++// OR these values together to select multiple extensions. ++const ( ++ NoExtensions Extensions = 0 ++ NoIntraEmphasis Extensions = 1 << iota // Ignore emphasis markers inside words ++ Tables // Render tables ++ FencedCode // Render fenced code blocks ++ Autolink // Detect embedded URLs that are not explicitly marked ++ Strikethrough // Strikethrough text using ~~test~~ ++ LaxHTMLBlocks // Loosen up HTML block parsing rules ++ SpaceHeadings // Be strict about prefix heading rules ++ HardLineBreak // Translate newlines into line breaks ++ TabSizeEight // Expand tabs to eight spaces instead of four ++ Footnotes // Pandoc-style footnotes ++ NoEmptyLineBeforeBlock // No need to insert an empty line to start a (code, quote, ordered list, unordered list) block ++ HeadingIDs // specify heading IDs with {#id} ++ Titleblock // Titleblock ala pandoc ++ AutoHeadingIDs // Create the heading ID from the text ++ BackslashLineBreak // Translate trailing backslashes into line breaks ++ DefinitionLists // Render definition lists ++ ++ CommonHTMLFlags HTMLFlags = UseXHTML | Smartypants | ++ SmartypantsFractions | SmartypantsDashes | SmartypantsLatexDashes ++ ++ CommonExtensions Extensions = NoIntraEmphasis | Tables | FencedCode | ++ Autolink | Strikethrough | SpaceHeadings | HeadingIDs | ++ BackslashLineBreak | DefinitionLists ++) ++ ++// ListType contains bitwise or'ed flags for list and list item objects. ++type ListType int ++ ++// These are the possible flag values for the ListItem renderer. ++// Multiple flag values may be ORed together. ++// These are mostly of interest if you are writing a new output format. ++const ( ++ ListTypeOrdered ListType = 1 << iota ++ ListTypeDefinition ++ ListTypeTerm ++ ++ ListItemContainsBlock ++ ListItemBeginningOfList // TODO: figure out if this is of any use now ++ ListItemEndOfList ++) ++ ++// CellAlignFlags holds a type of alignment in a table cell. ++type CellAlignFlags int ++ ++// These are the possible flag values for the table cell renderer. ++// Only a single one of these values will be used; they are not ORed together. ++// These are mostly of interest if you are writing a new output format. ++const ( ++ TableAlignmentLeft CellAlignFlags = 1 << iota ++ TableAlignmentRight ++ TableAlignmentCenter = (TableAlignmentLeft | TableAlignmentRight) ++) ++ ++// The size of a tab stop. ++const ( ++ TabSizeDefault = 4 ++ TabSizeDouble = 8 ++) ++ ++// blockTags is a set of tags that are recognized as HTML block tags. ++// Any of these can be included in markdown text without special escaping. ++var blockTags = map[string]struct{}{ ++ "blockquote": {}, ++ "del": {}, ++ "div": {}, ++ "dl": {}, ++ "fieldset": {}, ++ "form": {}, ++ "h1": {}, ++ "h2": {}, ++ "h3": {}, ++ "h4": {}, ++ "h5": {}, ++ "h6": {}, ++ "iframe": {}, ++ "ins": {}, ++ "math": {}, ++ "noscript": {}, ++ "ol": {}, ++ "pre": {}, ++ "p": {}, ++ "script": {}, ++ "style": {}, ++ "table": {}, ++ "ul": {}, ++ ++ // HTML5 ++ "address": {}, ++ "article": {}, ++ "aside": {}, ++ "canvas": {}, ++ "figcaption": {}, ++ "figure": {}, ++ "footer": {}, ++ "header": {}, ++ "hgroup": {}, ++ "main": {}, ++ "nav": {}, ++ "output": {}, ++ "progress": {}, ++ "section": {}, ++ "video": {}, ++} ++ ++// Renderer is the rendering interface. This is mostly of interest if you are ++// implementing a new rendering format. ++// ++// Only an HTML implementation is provided in this repository, see the README ++// for external implementations. ++type Renderer interface { ++ // RenderNode is the main rendering method. It will be called once for ++ // every leaf node and twice for every non-leaf node (first with ++ // entering=true, then with entering=false). The method should write its ++ // rendition of the node to the supplied writer w. ++ RenderNode(w io.Writer, node *Node, entering bool) WalkStatus ++ ++ // RenderHeader is a method that allows the renderer to produce some ++ // content preceding the main body of the output document. The header is ++ // understood in the broad sense here. For example, the default HTML ++ // renderer will write not only the HTML document preamble, but also the ++ // table of contents if it was requested. ++ // ++ // The method will be passed an entire document tree, in case a particular ++ // implementation needs to inspect it to produce output. ++ // ++ // The output should be written to the supplied writer w. If your ++ // implementation has no header to write, supply an empty implementation. ++ RenderHeader(w io.Writer, ast *Node) ++ ++ // RenderFooter is a symmetric counterpart of RenderHeader. ++ RenderFooter(w io.Writer, ast *Node) ++} ++ ++// Callback functions for inline parsing. One such function is defined ++// for each character that triggers a response when parsing inline data. ++type inlineParser func(p *Markdown, data []byte, offset int) (int, *Node) ++ ++// Markdown is a type that holds extensions and the runtime state used by ++// Parse, and the renderer. You can not use it directly, construct it with New. ++type Markdown struct { ++ renderer Renderer ++ referenceOverride ReferenceOverrideFunc ++ refs map[string]*reference ++ inlineCallback [256]inlineParser ++ extensions Extensions ++ nesting int ++ maxNesting int ++ insideLink bool ++ ++ // Footnotes need to be ordered as well as available to quickly check for ++ // presence. If a ref is also a footnote, it's stored both in refs and here ++ // in notes. Slice is nil if footnotes not enabled. ++ notes []*reference ++ ++ doc *Node ++ tip *Node // = doc ++ oldTip *Node ++ lastMatchedContainer *Node // = doc ++ allClosed bool ++} ++ ++func (p *Markdown) getRef(refid string) (ref *reference, found bool) { ++ if p.referenceOverride != nil { ++ r, overridden := p.referenceOverride(refid) ++ if overridden { ++ if r == nil { ++ return nil, false ++ } ++ return &reference{ ++ link: []byte(r.Link), ++ title: []byte(r.Title), ++ noteID: 0, ++ hasBlock: false, ++ text: []byte(r.Text)}, true ++ } ++ } ++ // refs are case insensitive ++ ref, found = p.refs[strings.ToLower(refid)] ++ return ref, found ++} ++ ++func (p *Markdown) finalize(block *Node) { ++ above := block.Parent ++ block.open = false ++ p.tip = above ++} ++ ++func (p *Markdown) addChild(node NodeType, offset uint32) *Node { ++ return p.addExistingChild(NewNode(node), offset) ++} ++ ++func (p *Markdown) addExistingChild(node *Node, offset uint32) *Node { ++ for !p.tip.canContain(node.Type) { ++ p.finalize(p.tip) ++ } ++ p.tip.AppendChild(node) ++ p.tip = node ++ return node ++} ++ ++func (p *Markdown) closeUnmatchedBlocks() { ++ if !p.allClosed { ++ for p.oldTip != p.lastMatchedContainer { ++ parent := p.oldTip.Parent ++ p.finalize(p.oldTip) ++ p.oldTip = parent ++ } ++ p.allClosed = true ++ } ++} ++ ++// ++// ++// Public interface ++// ++// ++ ++// Reference represents the details of a link. ++// See the documentation in Options for more details on use-case. ++type Reference struct { ++ // Link is usually the URL the reference points to. ++ Link string ++ // Title is the alternate text describing the link in more detail. ++ Title string ++ // Text is the optional text to override the ref with if the syntax used was ++ // [refid][] ++ Text string ++} ++ ++// ReferenceOverrideFunc is expected to be called with a reference string and ++// return either a valid Reference type that the reference string maps to or ++// nil. If overridden is false, the default reference logic will be executed. ++// See the documentation in Options for more details on use-case. ++type ReferenceOverrideFunc func(reference string) (ref *Reference, overridden bool) ++ ++// New constructs a Markdown processor. You can use the same With* functions as ++// for Run() to customize parser's behavior and the renderer. ++func New(opts ...Option) *Markdown { ++ var p Markdown ++ for _, opt := range opts { ++ opt(&p) ++ } ++ p.refs = make(map[string]*reference) ++ p.maxNesting = 16 ++ p.insideLink = false ++ docNode := NewNode(Document) ++ p.doc = docNode ++ p.tip = docNode ++ p.oldTip = docNode ++ p.lastMatchedContainer = docNode ++ p.allClosed = true ++ // register inline parsers ++ p.inlineCallback[' '] = maybeLineBreak ++ p.inlineCallback['*'] = emphasis ++ p.inlineCallback['_'] = emphasis ++ if p.extensions&Strikethrough != 0 { ++ p.inlineCallback['~'] = emphasis ++ } ++ p.inlineCallback['`'] = codeSpan ++ p.inlineCallback['\n'] = lineBreak ++ p.inlineCallback['['] = link ++ p.inlineCallback['<'] = leftAngle ++ p.inlineCallback['\\'] = escape ++ p.inlineCallback['&'] = entity ++ p.inlineCallback['!'] = maybeImage ++ p.inlineCallback['^'] = maybeInlineFootnote ++ if p.extensions&Autolink != 0 { ++ p.inlineCallback['h'] = maybeAutoLink ++ p.inlineCallback['m'] = maybeAutoLink ++ p.inlineCallback['f'] = maybeAutoLink ++ p.inlineCallback['H'] = maybeAutoLink ++ p.inlineCallback['M'] = maybeAutoLink ++ p.inlineCallback['F'] = maybeAutoLink ++ } ++ if p.extensions&Footnotes != 0 { ++ p.notes = make([]*reference, 0) ++ } ++ return &p ++} ++ ++// Option customizes the Markdown processor's default behavior. ++type Option func(*Markdown) ++ ++// WithRenderer allows you to override the default renderer. ++func WithRenderer(r Renderer) Option { ++ return func(p *Markdown) { ++ p.renderer = r ++ } ++} ++ ++// WithExtensions allows you to pick some of the many extensions provided by ++// Blackfriday. You can bitwise OR them. ++func WithExtensions(e Extensions) Option { ++ return func(p *Markdown) { ++ p.extensions = e ++ } ++} ++ ++// WithNoExtensions turns off all extensions and custom behavior. ++func WithNoExtensions() Option { ++ return func(p *Markdown) { ++ p.extensions = NoExtensions ++ p.renderer = NewHTMLRenderer(HTMLRendererParameters{ ++ Flags: HTMLFlagsNone, ++ }) ++ } ++} ++ ++// WithRefOverride sets an optional function callback that is called every ++// time a reference is resolved. ++// ++// In Markdown, the link reference syntax can be made to resolve a link to ++// a reference instead of an inline URL, in one of the following ways: ++// ++// * [link text][refid] ++// * [refid][] ++// ++// Usually, the refid is defined at the bottom of the Markdown document. If ++// this override function is provided, the refid is passed to the override ++// function first, before consulting the defined refids at the bottom. If ++// the override function indicates an override did not occur, the refids at ++// the bottom will be used to fill in the link details. ++func WithRefOverride(o ReferenceOverrideFunc) Option { ++ return func(p *Markdown) { ++ p.referenceOverride = o ++ } ++} ++ ++// Run is the main entry point to Blackfriday. It parses and renders a ++// block of markdown-encoded text. ++// ++// The simplest invocation of Run takes one argument, input: ++// output := Run(input) ++// This will parse the input with CommonExtensions enabled and render it with ++// the default HTMLRenderer (with CommonHTMLFlags). ++// ++// Variadic arguments opts can customize the default behavior. Since Markdown ++// type does not contain exported fields, you can not use it directly. Instead, ++// use the With* functions. For example, this will call the most basic ++// functionality, with no extensions: ++// output := Run(input, WithNoExtensions()) ++// ++// You can use any number of With* arguments, even contradicting ones. They ++// will be applied in order of appearance and the latter will override the ++// former: ++// output := Run(input, WithNoExtensions(), WithExtensions(exts), ++// WithRenderer(yourRenderer)) ++func Run(input []byte, opts ...Option) []byte { ++ r := NewHTMLRenderer(HTMLRendererParameters{ ++ Flags: CommonHTMLFlags, ++ }) ++ optList := []Option{WithRenderer(r), WithExtensions(CommonExtensions)} ++ optList = append(optList, opts...) ++ parser := New(optList...) ++ ast := parser.Parse(input) ++ var buf bytes.Buffer ++ parser.renderer.RenderHeader(&buf, ast) ++ ast.Walk(func(node *Node, entering bool) WalkStatus { ++ return parser.renderer.RenderNode(&buf, node, entering) ++ }) ++ parser.renderer.RenderFooter(&buf, ast) ++ return buf.Bytes() ++} ++ ++// Parse is an entry point to the parsing part of Blackfriday. It takes an ++// input markdown document and produces a syntax tree for its contents. This ++// tree can then be rendered with a default or custom renderer, or ++// analyzed/transformed by the caller to whatever non-standard needs they have. ++// The return value is the root node of the syntax tree. ++func (p *Markdown) Parse(input []byte) *Node { ++ p.block(input) ++ // Walk the tree and finish up some of unfinished blocks ++ for p.tip != nil { ++ p.finalize(p.tip) ++ } ++ // Walk the tree again and process inline markdown in each block ++ p.doc.Walk(func(node *Node, entering bool) WalkStatus { ++ if node.Type == Paragraph || node.Type == Heading || node.Type == TableCell { ++ p.inline(node, node.content) ++ node.content = nil ++ } ++ return GoToNext ++ }) ++ p.parseRefsToAST() ++ return p.doc ++} ++ ++func (p *Markdown) parseRefsToAST() { ++ if p.extensions&Footnotes == 0 || len(p.notes) == 0 { ++ return ++ } ++ p.tip = p.doc ++ block := p.addBlock(List, nil) ++ block.IsFootnotesList = true ++ block.ListFlags = ListTypeOrdered ++ flags := ListItemBeginningOfList ++ // Note: this loop is intentionally explicit, not range-form. This is ++ // because the body of the loop will append nested footnotes to p.notes and ++ // we need to process those late additions. Range form would only walk over ++ // the fixed initial set. ++ for i := 0; i < len(p.notes); i++ { ++ ref := p.notes[i] ++ p.addExistingChild(ref.footnote, 0) ++ block := ref.footnote ++ block.ListFlags = flags | ListTypeOrdered ++ block.RefLink = ref.link ++ if ref.hasBlock { ++ flags |= ListItemContainsBlock ++ p.block(ref.title) ++ } else { ++ p.inline(block, ref.title) ++ } ++ flags &^= ListItemBeginningOfList | ListItemContainsBlock ++ } ++ above := block.Parent ++ finalizeList(block) ++ p.tip = above ++ block.Walk(func(node *Node, entering bool) WalkStatus { ++ if node.Type == Paragraph || node.Type == Heading { ++ p.inline(node, node.content) ++ node.content = nil ++ } ++ return GoToNext ++ }) ++} ++ ++// ++// Link references ++// ++// This section implements support for references that (usually) appear ++// as footnotes in a document, and can be referenced anywhere in the document. ++// The basic format is: ++// ++// [1]: http://www.google.com/ "Google" ++// [2]: http://www.github.com/ "Github" ++// ++// Anywhere in the document, the reference can be linked by referring to its ++// label, i.e., 1 and 2 in this example, as in: ++// ++// This library is hosted on [Github][2], a git hosting site. ++// ++// Actual footnotes as specified in Pandoc and supported by some other Markdown ++// libraries such as php-markdown are also taken care of. They look like this: ++// ++// This sentence needs a bit of further explanation.[^note] ++// ++// [^note]: This is the explanation. ++// ++// Footnotes should be placed at the end of the document in an ordered list. ++// Finally, there are inline footnotes such as: ++// ++// Inline footnotes^[Also supported.] provide a quick inline explanation, ++// but are rendered at the bottom of the document. ++// ++ ++// reference holds all information necessary for a reference-style links or ++// footnotes. ++// ++// Consider this markdown with reference-style links: ++// ++// [link][ref] ++// ++// [ref]: /url/ "tooltip title" ++// ++// It will be ultimately converted to this HTML: ++// ++//

    link

    ++// ++// And a reference structure will be populated as follows: ++// ++// p.refs["ref"] = &reference{ ++// link: "/url/", ++// title: "tooltip title", ++// } ++// ++// Alternatively, reference can contain information about a footnote. Consider ++// this markdown: ++// ++// Text needing a footnote.[^a] ++// ++// [^a]: This is the note ++// ++// A reference structure will be populated as follows: ++// ++// p.refs["a"] = &reference{ ++// link: "a", ++// title: "This is the note", ++// noteID: , ++// } ++// ++// TODO: As you can see, it begs for splitting into two dedicated structures ++// for refs and for footnotes. ++type reference struct { ++ link []byte ++ title []byte ++ noteID int // 0 if not a footnote ref ++ hasBlock bool ++ footnote *Node // a link to the Item node within a list of footnotes ++ ++ text []byte // only gets populated by refOverride feature with Reference.Text ++} ++ ++func (r *reference) String() string { ++ return fmt.Sprintf("{link: %q, title: %q, text: %q, noteID: %d, hasBlock: %v}", ++ r.link, r.title, r.text, r.noteID, r.hasBlock) ++} ++ ++// Check whether or not data starts with a reference link. ++// If so, it is parsed and stored in the list of references ++// (in the render struct). ++// Returns the number of bytes to skip to move past it, ++// or zero if the first line is not a reference. ++func isReference(p *Markdown, data []byte, tabSize int) int { ++ // up to 3 optional leading spaces ++ if len(data) < 4 { ++ return 0 ++ } ++ i := 0 ++ for i < 3 && data[i] == ' ' { ++ i++ ++ } ++ ++ noteID := 0 ++ ++ // id part: anything but a newline between brackets ++ if data[i] != '[' { ++ return 0 ++ } ++ i++ ++ if p.extensions&Footnotes != 0 { ++ if i < len(data) && data[i] == '^' { ++ // we can set it to anything here because the proper noteIds will ++ // be assigned later during the second pass. It just has to be != 0 ++ noteID = 1 ++ i++ ++ } ++ } ++ idOffset := i ++ for i < len(data) && data[i] != '\n' && data[i] != '\r' && data[i] != ']' { ++ i++ ++ } ++ if i >= len(data) || data[i] != ']' { ++ return 0 ++ } ++ idEnd := i ++ // footnotes can have empty ID, like this: [^], but a reference can not be ++ // empty like this: []. Break early if it's not a footnote and there's no ID ++ if noteID == 0 && idOffset == idEnd { ++ return 0 ++ } ++ // spacer: colon (space | tab)* newline? (space | tab)* ++ i++ ++ if i >= len(data) || data[i] != ':' { ++ return 0 ++ } ++ i++ ++ for i < len(data) && (data[i] == ' ' || data[i] == '\t') { ++ i++ ++ } ++ if i < len(data) && (data[i] == '\n' || data[i] == '\r') { ++ i++ ++ if i < len(data) && data[i] == '\n' && data[i-1] == '\r' { ++ i++ ++ } ++ } ++ for i < len(data) && (data[i] == ' ' || data[i] == '\t') { ++ i++ ++ } ++ if i >= len(data) { ++ return 0 ++ } ++ ++ var ( ++ linkOffset, linkEnd int ++ titleOffset, titleEnd int ++ lineEnd int ++ raw []byte ++ hasBlock bool ++ ) ++ ++ if p.extensions&Footnotes != 0 && noteID != 0 { ++ linkOffset, linkEnd, raw, hasBlock = scanFootnote(p, data, i, tabSize) ++ lineEnd = linkEnd ++ } else { ++ linkOffset, linkEnd, titleOffset, titleEnd, lineEnd = scanLinkRef(p, data, i) ++ } ++ if lineEnd == 0 { ++ return 0 ++ } ++ ++ // a valid ref has been found ++ ++ ref := &reference{ ++ noteID: noteID, ++ hasBlock: hasBlock, ++ } ++ ++ if noteID > 0 { ++ // reusing the link field for the id since footnotes don't have links ++ ref.link = data[idOffset:idEnd] ++ // if footnote, it's not really a title, it's the contained text ++ ref.title = raw ++ } else { ++ ref.link = data[linkOffset:linkEnd] ++ ref.title = data[titleOffset:titleEnd] ++ } ++ ++ // id matches are case-insensitive ++ id := string(bytes.ToLower(data[idOffset:idEnd])) ++ ++ p.refs[id] = ref ++ ++ return lineEnd ++} ++ ++func scanLinkRef(p *Markdown, data []byte, i int) (linkOffset, linkEnd, titleOffset, titleEnd, lineEnd int) { ++ // link: whitespace-free sequence, optionally between angle brackets ++ if data[i] == '<' { ++ i++ ++ } ++ linkOffset = i ++ for i < len(data) && data[i] != ' ' && data[i] != '\t' && data[i] != '\n' && data[i] != '\r' { ++ i++ ++ } ++ linkEnd = i ++ if data[linkOffset] == '<' && data[linkEnd-1] == '>' { ++ linkOffset++ ++ linkEnd-- ++ } ++ ++ // optional spacer: (space | tab)* (newline | '\'' | '"' | '(' ) ++ for i < len(data) && (data[i] == ' ' || data[i] == '\t') { ++ i++ ++ } ++ if i < len(data) && data[i] != '\n' && data[i] != '\r' && data[i] != '\'' && data[i] != '"' && data[i] != '(' { ++ return ++ } ++ ++ // compute end-of-line ++ if i >= len(data) || data[i] == '\r' || data[i] == '\n' { ++ lineEnd = i ++ } ++ if i+1 < len(data) && data[i] == '\r' && data[i+1] == '\n' { ++ lineEnd++ ++ } ++ ++ // optional (space|tab)* spacer after a newline ++ if lineEnd > 0 { ++ i = lineEnd + 1 ++ for i < len(data) && (data[i] == ' ' || data[i] == '\t') { ++ i++ ++ } ++ } ++ ++ // optional title: any non-newline sequence enclosed in '"() alone on its line ++ if i+1 < len(data) && (data[i] == '\'' || data[i] == '"' || data[i] == '(') { ++ i++ ++ titleOffset = i ++ ++ // look for EOL ++ for i < len(data) && data[i] != '\n' && data[i] != '\r' { ++ i++ ++ } ++ if i+1 < len(data) && data[i] == '\n' && data[i+1] == '\r' { ++ titleEnd = i + 1 ++ } else { ++ titleEnd = i ++ } ++ ++ // step back ++ i-- ++ for i > titleOffset && (data[i] == ' ' || data[i] == '\t') { ++ i-- ++ } ++ if i > titleOffset && (data[i] == '\'' || data[i] == '"' || data[i] == ')') { ++ lineEnd = titleEnd ++ titleEnd = i ++ } ++ } ++ ++ return ++} ++ ++// The first bit of this logic is the same as Parser.listItem, but the rest ++// is much simpler. This function simply finds the entire block and shifts it ++// over by one tab if it is indeed a block (just returns the line if it's not). ++// blockEnd is the end of the section in the input buffer, and contents is the ++// extracted text that was shifted over one tab. It will need to be rendered at ++// the end of the document. ++func scanFootnote(p *Markdown, data []byte, i, indentSize int) (blockStart, blockEnd int, contents []byte, hasBlock bool) { ++ if i == 0 || len(data) == 0 { ++ return ++ } ++ ++ // skip leading whitespace on first line ++ for i < len(data) && data[i] == ' ' { ++ i++ ++ } ++ ++ blockStart = i ++ ++ // find the end of the line ++ blockEnd = i ++ for i < len(data) && data[i-1] != '\n' { ++ i++ ++ } ++ ++ // get working buffer ++ var raw bytes.Buffer ++ ++ // put the first line into the working buffer ++ raw.Write(data[blockEnd:i]) ++ blockEnd = i ++ ++ // process the following lines ++ containsBlankLine := false ++ ++gatherLines: ++ for blockEnd < len(data) { ++ i++ ++ ++ // find the end of this line ++ for i < len(data) && data[i-1] != '\n' { ++ i++ ++ } ++ ++ // if it is an empty line, guess that it is part of this item ++ // and move on to the next line ++ if p.isEmpty(data[blockEnd:i]) > 0 { ++ containsBlankLine = true ++ blockEnd = i ++ continue ++ } ++ ++ n := 0 ++ if n = isIndented(data[blockEnd:i], indentSize); n == 0 { ++ // this is the end of the block. ++ // we don't want to include this last line in the index. ++ break gatherLines ++ } ++ ++ // if there were blank lines before this one, insert a new one now ++ if containsBlankLine { ++ raw.WriteByte('\n') ++ containsBlankLine = false ++ } ++ ++ // get rid of that first tab, write to buffer ++ raw.Write(data[blockEnd+n : i]) ++ hasBlock = true ++ ++ blockEnd = i ++ } ++ ++ if data[blockEnd-1] != '\n' { ++ raw.WriteByte('\n') ++ } ++ ++ contents = raw.Bytes() ++ ++ return ++} ++ ++// ++// ++// Miscellaneous helper functions ++// ++// ++ ++// Test if a character is a punctuation symbol. ++// Taken from a private function in regexp in the stdlib. ++func ispunct(c byte) bool { ++ for _, r := range []byte("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~") { ++ if c == r { ++ return true ++ } ++ } ++ return false ++} ++ ++// Test if a character is a whitespace character. ++func isspace(c byte) bool { ++ return ishorizontalspace(c) || isverticalspace(c) ++} ++ ++// Test if a character is a horizontal whitespace character. ++func ishorizontalspace(c byte) bool { ++ return c == ' ' || c == '\t' ++} ++ ++// Test if a character is a vertical character. ++func isverticalspace(c byte) bool { ++ return c == '\n' || c == '\r' || c == '\f' || c == '\v' ++} ++ ++// Test if a character is letter. ++func isletter(c byte) bool { ++ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ++} ++ ++// Test if a character is a letter or a digit. ++// TODO: check when this is looking for ASCII alnum and when it should use unicode ++func isalnum(c byte) bool { ++ return (c >= '0' && c <= '9') || isletter(c) ++} ++ ++// Replace tab characters with spaces, aligning to the next TAB_SIZE column. ++// always ends output with a newline ++func expandTabs(out *bytes.Buffer, line []byte, tabSize int) { ++ // first, check for common cases: no tabs, or only tabs at beginning of line ++ i, prefix := 0, 0 ++ slowcase := false ++ for i = 0; i < len(line); i++ { ++ if line[i] == '\t' { ++ if prefix == i { ++ prefix++ ++ } else { ++ slowcase = true ++ break ++ } ++ } ++ } ++ ++ // no need to decode runes if all tabs are at the beginning of the line ++ if !slowcase { ++ for i = 0; i < prefix*tabSize; i++ { ++ out.WriteByte(' ') ++ } ++ out.Write(line[prefix:]) ++ return ++ } ++ ++ // the slow case: we need to count runes to figure out how ++ // many spaces to insert for each tab ++ column := 0 ++ i = 0 ++ for i < len(line) { ++ start := i ++ for i < len(line) && line[i] != '\t' { ++ _, size := utf8.DecodeRune(line[i:]) ++ i += size ++ column++ ++ } ++ ++ if i > start { ++ out.Write(line[start:i]) ++ } ++ ++ if i >= len(line) { ++ break ++ } ++ ++ for { ++ out.WriteByte(' ') ++ column++ ++ if column%tabSize == 0 { ++ break ++ } ++ } ++ ++ i++ ++ } ++} ++ ++// Find if a line counts as indented or not. ++// Returns number of characters the indent is (0 = not indented). ++func isIndented(data []byte, indentSize int) int { ++ if len(data) == 0 { ++ return 0 ++ } ++ if data[0] == '\t' { ++ return 1 ++ } ++ if len(data) < indentSize { ++ return 0 ++ } ++ for i := 0; i < indentSize; i++ { ++ if data[i] != ' ' { ++ return 0 ++ } ++ } ++ return indentSize ++} ++ ++// Create a url-safe slug for fragments ++func slugify(in []byte) []byte { ++ if len(in) == 0 { ++ return in ++ } ++ out := make([]byte, 0, len(in)) ++ sym := false ++ ++ for _, ch := range in { ++ if isalnum(ch) { ++ sym = false ++ out = append(out, ch) ++ } else if sym { ++ continue ++ } else { ++ out = append(out, '-') ++ sym = true ++ } ++ } ++ var a, b int ++ var ch byte ++ for a, ch = range out { ++ if ch != '-' { ++ break ++ } ++ } ++ for b = len(out) - 1; b > 0; b-- { ++ if out[b] != '-' { ++ break ++ } ++ } ++ return out[a : b+1] ++} +diff --git a/vendor/github.com/russross/blackfriday/v2/node.go b/vendor/github.com/russross/blackfriday/v2/node.go +new file mode 100644 +index 000000000000..04e6050ceeae +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/node.go +@@ -0,0 +1,360 @@ ++package blackfriday ++ ++import ( ++ "bytes" ++ "fmt" ++) ++ ++// NodeType specifies a type of a single node of a syntax tree. Usually one ++// node (and its type) corresponds to a single markdown feature, e.g. emphasis ++// or code block. ++type NodeType int ++ ++// Constants for identifying different types of nodes. See NodeType. ++const ( ++ Document NodeType = iota ++ BlockQuote ++ List ++ Item ++ Paragraph ++ Heading ++ HorizontalRule ++ Emph ++ Strong ++ Del ++ Link ++ Image ++ Text ++ HTMLBlock ++ CodeBlock ++ Softbreak ++ Hardbreak ++ Code ++ HTMLSpan ++ Table ++ TableCell ++ TableHead ++ TableBody ++ TableRow ++) ++ ++var nodeTypeNames = []string{ ++ Document: "Document", ++ BlockQuote: "BlockQuote", ++ List: "List", ++ Item: "Item", ++ Paragraph: "Paragraph", ++ Heading: "Heading", ++ HorizontalRule: "HorizontalRule", ++ Emph: "Emph", ++ Strong: "Strong", ++ Del: "Del", ++ Link: "Link", ++ Image: "Image", ++ Text: "Text", ++ HTMLBlock: "HTMLBlock", ++ CodeBlock: "CodeBlock", ++ Softbreak: "Softbreak", ++ Hardbreak: "Hardbreak", ++ Code: "Code", ++ HTMLSpan: "HTMLSpan", ++ Table: "Table", ++ TableCell: "TableCell", ++ TableHead: "TableHead", ++ TableBody: "TableBody", ++ TableRow: "TableRow", ++} ++ ++func (t NodeType) String() string { ++ return nodeTypeNames[t] ++} ++ ++// ListData contains fields relevant to a List and Item node type. ++type ListData struct { ++ ListFlags ListType ++ Tight bool // Skip

    s around list item data if true ++ BulletChar byte // '*', '+' or '-' in bullet lists ++ Delimiter byte // '.' or ')' after the number in ordered lists ++ RefLink []byte // If not nil, turns this list item into a footnote item and triggers different rendering ++ IsFootnotesList bool // This is a list of footnotes ++} ++ ++// LinkData contains fields relevant to a Link node type. ++type LinkData struct { ++ Destination []byte // Destination is what goes into a href ++ Title []byte // Title is the tooltip thing that goes in a title attribute ++ NoteID int // NoteID contains a serial number of a footnote, zero if it's not a footnote ++ Footnote *Node // If it's a footnote, this is a direct link to the footnote Node. Otherwise nil. ++} ++ ++// CodeBlockData contains fields relevant to a CodeBlock node type. ++type CodeBlockData struct { ++ IsFenced bool // Specifies whether it's a fenced code block or an indented one ++ Info []byte // This holds the info string ++ FenceChar byte ++ FenceLength int ++ FenceOffset int ++} ++ ++// TableCellData contains fields relevant to a TableCell node type. ++type TableCellData struct { ++ IsHeader bool // This tells if it's under the header row ++ Align CellAlignFlags // This holds the value for align attribute ++} ++ ++// HeadingData contains fields relevant to a Heading node type. ++type HeadingData struct { ++ Level int // This holds the heading level number ++ HeadingID string // This might hold heading ID, if present ++ IsTitleblock bool // Specifies whether it's a title block ++} ++ ++// Node is a single element in the abstract syntax tree of the parsed document. ++// It holds connections to the structurally neighboring nodes and, for certain ++// types of nodes, additional information that might be needed when rendering. ++type Node struct { ++ Type NodeType // Determines the type of the node ++ Parent *Node // Points to the parent ++ FirstChild *Node // Points to the first child, if any ++ LastChild *Node // Points to the last child, if any ++ Prev *Node // Previous sibling; nil if it's the first child ++ Next *Node // Next sibling; nil if it's the last child ++ ++ Literal []byte // Text contents of the leaf nodes ++ ++ HeadingData // Populated if Type is Heading ++ ListData // Populated if Type is List ++ CodeBlockData // Populated if Type is CodeBlock ++ LinkData // Populated if Type is Link ++ TableCellData // Populated if Type is TableCell ++ ++ content []byte // Markdown content of the block nodes ++ open bool // Specifies an open block node that has not been finished to process yet ++} ++ ++// NewNode allocates a node of a specified type. ++func NewNode(typ NodeType) *Node { ++ return &Node{ ++ Type: typ, ++ open: true, ++ } ++} ++ ++func (n *Node) String() string { ++ ellipsis := "" ++ snippet := n.Literal ++ if len(snippet) > 16 { ++ snippet = snippet[:16] ++ ellipsis = "..." ++ } ++ return fmt.Sprintf("%s: '%s%s'", n.Type, snippet, ellipsis) ++} ++ ++// Unlink removes node 'n' from the tree. ++// It panics if the node is nil. ++func (n *Node) Unlink() { ++ if n.Prev != nil { ++ n.Prev.Next = n.Next ++ } else if n.Parent != nil { ++ n.Parent.FirstChild = n.Next ++ } ++ if n.Next != nil { ++ n.Next.Prev = n.Prev ++ } else if n.Parent != nil { ++ n.Parent.LastChild = n.Prev ++ } ++ n.Parent = nil ++ n.Next = nil ++ n.Prev = nil ++} ++ ++// AppendChild adds a node 'child' as a child of 'n'. ++// It panics if either node is nil. ++func (n *Node) AppendChild(child *Node) { ++ child.Unlink() ++ child.Parent = n ++ if n.LastChild != nil { ++ n.LastChild.Next = child ++ child.Prev = n.LastChild ++ n.LastChild = child ++ } else { ++ n.FirstChild = child ++ n.LastChild = child ++ } ++} ++ ++// InsertBefore inserts 'sibling' immediately before 'n'. ++// It panics if either node is nil. ++func (n *Node) InsertBefore(sibling *Node) { ++ sibling.Unlink() ++ sibling.Prev = n.Prev ++ if sibling.Prev != nil { ++ sibling.Prev.Next = sibling ++ } ++ sibling.Next = n ++ n.Prev = sibling ++ sibling.Parent = n.Parent ++ if sibling.Prev == nil { ++ sibling.Parent.FirstChild = sibling ++ } ++} ++ ++// IsContainer returns true if 'n' can contain children. ++func (n *Node) IsContainer() bool { ++ switch n.Type { ++ case Document: ++ fallthrough ++ case BlockQuote: ++ fallthrough ++ case List: ++ fallthrough ++ case Item: ++ fallthrough ++ case Paragraph: ++ fallthrough ++ case Heading: ++ fallthrough ++ case Emph: ++ fallthrough ++ case Strong: ++ fallthrough ++ case Del: ++ fallthrough ++ case Link: ++ fallthrough ++ case Image: ++ fallthrough ++ case Table: ++ fallthrough ++ case TableHead: ++ fallthrough ++ case TableBody: ++ fallthrough ++ case TableRow: ++ fallthrough ++ case TableCell: ++ return true ++ default: ++ return false ++ } ++} ++ ++// IsLeaf returns true if 'n' is a leaf node. ++func (n *Node) IsLeaf() bool { ++ return !n.IsContainer() ++} ++ ++func (n *Node) canContain(t NodeType) bool { ++ if n.Type == List { ++ return t == Item ++ } ++ if n.Type == Document || n.Type == BlockQuote || n.Type == Item { ++ return t != Item ++ } ++ if n.Type == Table { ++ return t == TableHead || t == TableBody ++ } ++ if n.Type == TableHead || n.Type == TableBody { ++ return t == TableRow ++ } ++ if n.Type == TableRow { ++ return t == TableCell ++ } ++ return false ++} ++ ++// WalkStatus allows NodeVisitor to have some control over the tree traversal. ++// It is returned from NodeVisitor and different values allow Node.Walk to ++// decide which node to go to next. ++type WalkStatus int ++ ++const ( ++ // GoToNext is the default traversal of every node. ++ GoToNext WalkStatus = iota ++ // SkipChildren tells walker to skip all children of current node. ++ SkipChildren ++ // Terminate tells walker to terminate the traversal. ++ Terminate ++) ++ ++// NodeVisitor is a callback to be called when traversing the syntax tree. ++// Called twice for every node: once with entering=true when the branch is ++// first visited, then with entering=false after all the children are done. ++type NodeVisitor func(node *Node, entering bool) WalkStatus ++ ++// Walk is a convenience method that instantiates a walker and starts a ++// traversal of subtree rooted at n. ++func (n *Node) Walk(visitor NodeVisitor) { ++ w := newNodeWalker(n) ++ for w.current != nil { ++ status := visitor(w.current, w.entering) ++ switch status { ++ case GoToNext: ++ w.next() ++ case SkipChildren: ++ w.entering = false ++ w.next() ++ case Terminate: ++ return ++ } ++ } ++} ++ ++type nodeWalker struct { ++ current *Node ++ root *Node ++ entering bool ++} ++ ++func newNodeWalker(root *Node) *nodeWalker { ++ return &nodeWalker{ ++ current: root, ++ root: root, ++ entering: true, ++ } ++} ++ ++func (nw *nodeWalker) next() { ++ if (!nw.current.IsContainer() || !nw.entering) && nw.current == nw.root { ++ nw.current = nil ++ return ++ } ++ if nw.entering && nw.current.IsContainer() { ++ if nw.current.FirstChild != nil { ++ nw.current = nw.current.FirstChild ++ nw.entering = true ++ } else { ++ nw.entering = false ++ } ++ } else if nw.current.Next == nil { ++ nw.current = nw.current.Parent ++ nw.entering = false ++ } else { ++ nw.current = nw.current.Next ++ nw.entering = true ++ } ++} ++ ++func dump(ast *Node) { ++ fmt.Println(dumpString(ast)) ++} ++ ++func dumpR(ast *Node, depth int) string { ++ if ast == nil { ++ return "" ++ } ++ indent := bytes.Repeat([]byte("\t"), depth) ++ content := ast.Literal ++ if content == nil { ++ content = ast.content ++ } ++ result := fmt.Sprintf("%s%s(%q)\n", indent, ast.Type, content) ++ for n := ast.FirstChild; n != nil; n = n.Next { ++ result += dumpR(n, depth+1) ++ } ++ return result ++} ++ ++func dumpString(ast *Node) string { ++ return dumpR(ast, 0) ++} +diff --git a/vendor/github.com/russross/blackfriday/v2/smartypants.go b/vendor/github.com/russross/blackfriday/v2/smartypants.go +new file mode 100644 +index 000000000000..3a220e94247d +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/smartypants.go +@@ -0,0 +1,457 @@ ++// ++// Blackfriday Markdown Processor ++// Available at http://github.com/russross/blackfriday ++// ++// Copyright © 2011 Russ Ross . ++// Distributed under the Simplified BSD License. ++// See README.md for details. ++// ++ ++// ++// ++// SmartyPants rendering ++// ++// ++ ++package blackfriday ++ ++import ( ++ "bytes" ++ "io" ++) ++ ++// SPRenderer is a struct containing state of a Smartypants renderer. ++type SPRenderer struct { ++ inSingleQuote bool ++ inDoubleQuote bool ++ callbacks [256]smartCallback ++} ++ ++func wordBoundary(c byte) bool { ++ return c == 0 || isspace(c) || ispunct(c) ++} ++ ++func tolower(c byte) byte { ++ if c >= 'A' && c <= 'Z' { ++ return c - 'A' + 'a' ++ } ++ return c ++} ++ ++func isdigit(c byte) bool { ++ return c >= '0' && c <= '9' ++} ++ ++func smartQuoteHelper(out *bytes.Buffer, previousChar byte, nextChar byte, quote byte, isOpen *bool, addNBSP bool) bool { ++ // edge of the buffer is likely to be a tag that we don't get to see, ++ // so we treat it like text sometimes ++ ++ // enumerate all sixteen possibilities for (previousChar, nextChar) ++ // each can be one of {0, space, punct, other} ++ switch { ++ case previousChar == 0 && nextChar == 0: ++ // context is not any help here, so toggle ++ *isOpen = !*isOpen ++ case isspace(previousChar) && nextChar == 0: ++ // [ "] might be [ "foo...] ++ *isOpen = true ++ case ispunct(previousChar) && nextChar == 0: ++ // [!"] hmm... could be [Run!"] or [("...] ++ *isOpen = false ++ case /* isnormal(previousChar) && */ nextChar == 0: ++ // [a"] is probably a close ++ *isOpen = false ++ case previousChar == 0 && isspace(nextChar): ++ // [" ] might be [...foo" ] ++ *isOpen = false ++ case isspace(previousChar) && isspace(nextChar): ++ // [ " ] context is not any help here, so toggle ++ *isOpen = !*isOpen ++ case ispunct(previousChar) && isspace(nextChar): ++ // [!" ] is probably a close ++ *isOpen = false ++ case /* isnormal(previousChar) && */ isspace(nextChar): ++ // [a" ] this is one of the easy cases ++ *isOpen = false ++ case previousChar == 0 && ispunct(nextChar): ++ // ["!] hmm... could be ["$1.95] or ["!...] ++ *isOpen = false ++ case isspace(previousChar) && ispunct(nextChar): ++ // [ "!] looks more like [ "$1.95] ++ *isOpen = true ++ case ispunct(previousChar) && ispunct(nextChar): ++ // [!"!] context is not any help here, so toggle ++ *isOpen = !*isOpen ++ case /* isnormal(previousChar) && */ ispunct(nextChar): ++ // [a"!] is probably a close ++ *isOpen = false ++ case previousChar == 0 /* && isnormal(nextChar) */ : ++ // ["a] is probably an open ++ *isOpen = true ++ case isspace(previousChar) /* && isnormal(nextChar) */ : ++ // [ "a] this is one of the easy cases ++ *isOpen = true ++ case ispunct(previousChar) /* && isnormal(nextChar) */ : ++ // [!"a] is probably an open ++ *isOpen = true ++ default: ++ // [a'b] maybe a contraction? ++ *isOpen = false ++ } ++ ++ // Note that with the limited lookahead, this non-breaking ++ // space will also be appended to single double quotes. ++ if addNBSP && !*isOpen { ++ out.WriteString(" ") ++ } ++ ++ out.WriteByte('&') ++ if *isOpen { ++ out.WriteByte('l') ++ } else { ++ out.WriteByte('r') ++ } ++ out.WriteByte(quote) ++ out.WriteString("quo;") ++ ++ if addNBSP && *isOpen { ++ out.WriteString(" ") ++ } ++ ++ return true ++} ++ ++func (r *SPRenderer) smartSingleQuote(out *bytes.Buffer, previousChar byte, text []byte) int { ++ if len(text) >= 2 { ++ t1 := tolower(text[1]) ++ ++ if t1 == '\'' { ++ nextChar := byte(0) ++ if len(text) >= 3 { ++ nextChar = text[2] ++ } ++ if smartQuoteHelper(out, previousChar, nextChar, 'd', &r.inDoubleQuote, false) { ++ return 1 ++ } ++ } ++ ++ if (t1 == 's' || t1 == 't' || t1 == 'm' || t1 == 'd') && (len(text) < 3 || wordBoundary(text[2])) { ++ out.WriteString("’") ++ return 0 ++ } ++ ++ if len(text) >= 3 { ++ t2 := tolower(text[2]) ++ ++ if ((t1 == 'r' && t2 == 'e') || (t1 == 'l' && t2 == 'l') || (t1 == 'v' && t2 == 'e')) && ++ (len(text) < 4 || wordBoundary(text[3])) { ++ out.WriteString("’") ++ return 0 ++ } ++ } ++ } ++ ++ nextChar := byte(0) ++ if len(text) > 1 { ++ nextChar = text[1] ++ } ++ if smartQuoteHelper(out, previousChar, nextChar, 's', &r.inSingleQuote, false) { ++ return 0 ++ } ++ ++ out.WriteByte(text[0]) ++ return 0 ++} ++ ++func (r *SPRenderer) smartParens(out *bytes.Buffer, previousChar byte, text []byte) int { ++ if len(text) >= 3 { ++ t1 := tolower(text[1]) ++ t2 := tolower(text[2]) ++ ++ if t1 == 'c' && t2 == ')' { ++ out.WriteString("©") ++ return 2 ++ } ++ ++ if t1 == 'r' && t2 == ')' { ++ out.WriteString("®") ++ return 2 ++ } ++ ++ if len(text) >= 4 && t1 == 't' && t2 == 'm' && text[3] == ')' { ++ out.WriteString("™") ++ return 3 ++ } ++ } ++ ++ out.WriteByte(text[0]) ++ return 0 ++} ++ ++func (r *SPRenderer) smartDash(out *bytes.Buffer, previousChar byte, text []byte) int { ++ if len(text) >= 2 { ++ if text[1] == '-' { ++ out.WriteString("—") ++ return 1 ++ } ++ ++ if wordBoundary(previousChar) && wordBoundary(text[1]) { ++ out.WriteString("–") ++ return 0 ++ } ++ } ++ ++ out.WriteByte(text[0]) ++ return 0 ++} ++ ++func (r *SPRenderer) smartDashLatex(out *bytes.Buffer, previousChar byte, text []byte) int { ++ if len(text) >= 3 && text[1] == '-' && text[2] == '-' { ++ out.WriteString("—") ++ return 2 ++ } ++ if len(text) >= 2 && text[1] == '-' { ++ out.WriteString("–") ++ return 1 ++ } ++ ++ out.WriteByte(text[0]) ++ return 0 ++} ++ ++func (r *SPRenderer) smartAmpVariant(out *bytes.Buffer, previousChar byte, text []byte, quote byte, addNBSP bool) int { ++ if bytes.HasPrefix(text, []byte(""")) { ++ nextChar := byte(0) ++ if len(text) >= 7 { ++ nextChar = text[6] ++ } ++ if smartQuoteHelper(out, previousChar, nextChar, quote, &r.inDoubleQuote, addNBSP) { ++ return 5 ++ } ++ } ++ ++ if bytes.HasPrefix(text, []byte("�")) { ++ return 3 ++ } ++ ++ out.WriteByte('&') ++ return 0 ++} ++ ++func (r *SPRenderer) smartAmp(angledQuotes, addNBSP bool) func(*bytes.Buffer, byte, []byte) int { ++ var quote byte = 'd' ++ if angledQuotes { ++ quote = 'a' ++ } ++ ++ return func(out *bytes.Buffer, previousChar byte, text []byte) int { ++ return r.smartAmpVariant(out, previousChar, text, quote, addNBSP) ++ } ++} ++ ++func (r *SPRenderer) smartPeriod(out *bytes.Buffer, previousChar byte, text []byte) int { ++ if len(text) >= 3 && text[1] == '.' && text[2] == '.' { ++ out.WriteString("…") ++ return 2 ++ } ++ ++ if len(text) >= 5 && text[1] == ' ' && text[2] == '.' && text[3] == ' ' && text[4] == '.' { ++ out.WriteString("…") ++ return 4 ++ } ++ ++ out.WriteByte(text[0]) ++ return 0 ++} ++ ++func (r *SPRenderer) smartBacktick(out *bytes.Buffer, previousChar byte, text []byte) int { ++ if len(text) >= 2 && text[1] == '`' { ++ nextChar := byte(0) ++ if len(text) >= 3 { ++ nextChar = text[2] ++ } ++ if smartQuoteHelper(out, previousChar, nextChar, 'd', &r.inDoubleQuote, false) { ++ return 1 ++ } ++ } ++ ++ out.WriteByte(text[0]) ++ return 0 ++} ++ ++func (r *SPRenderer) smartNumberGeneric(out *bytes.Buffer, previousChar byte, text []byte) int { ++ if wordBoundary(previousChar) && previousChar != '/' && len(text) >= 3 { ++ // is it of the form digits/digits(word boundary)?, i.e., \d+/\d+\b ++ // note: check for regular slash (/) or fraction slash (⁄, 0x2044, or 0xe2 81 84 in utf-8) ++ // and avoid changing dates like 1/23/2005 into fractions. ++ numEnd := 0 ++ for len(text) > numEnd && isdigit(text[numEnd]) { ++ numEnd++ ++ } ++ if numEnd == 0 { ++ out.WriteByte(text[0]) ++ return 0 ++ } ++ denStart := numEnd + 1 ++ if len(text) > numEnd+3 && text[numEnd] == 0xe2 && text[numEnd+1] == 0x81 && text[numEnd+2] == 0x84 { ++ denStart = numEnd + 3 ++ } else if len(text) < numEnd+2 || text[numEnd] != '/' { ++ out.WriteByte(text[0]) ++ return 0 ++ } ++ denEnd := denStart ++ for len(text) > denEnd && isdigit(text[denEnd]) { ++ denEnd++ ++ } ++ if denEnd == denStart { ++ out.WriteByte(text[0]) ++ return 0 ++ } ++ if len(text) == denEnd || wordBoundary(text[denEnd]) && text[denEnd] != '/' { ++ out.WriteString("") ++ out.Write(text[:numEnd]) ++ out.WriteString("") ++ out.Write(text[denStart:denEnd]) ++ out.WriteString("") ++ return denEnd - 1 ++ } ++ } ++ ++ out.WriteByte(text[0]) ++ return 0 ++} ++ ++func (r *SPRenderer) smartNumber(out *bytes.Buffer, previousChar byte, text []byte) int { ++ if wordBoundary(previousChar) && previousChar != '/' && len(text) >= 3 { ++ if text[0] == '1' && text[1] == '/' && text[2] == '2' { ++ if len(text) < 4 || wordBoundary(text[3]) && text[3] != '/' { ++ out.WriteString("½") ++ return 2 ++ } ++ } ++ ++ if text[0] == '1' && text[1] == '/' && text[2] == '4' { ++ if len(text) < 4 || wordBoundary(text[3]) && text[3] != '/' || (len(text) >= 5 && tolower(text[3]) == 't' && tolower(text[4]) == 'h') { ++ out.WriteString("¼") ++ return 2 ++ } ++ } ++ ++ if text[0] == '3' && text[1] == '/' && text[2] == '4' { ++ if len(text) < 4 || wordBoundary(text[3]) && text[3] != '/' || (len(text) >= 6 && tolower(text[3]) == 't' && tolower(text[4]) == 'h' && tolower(text[5]) == 's') { ++ out.WriteString("¾") ++ return 2 ++ } ++ } ++ } ++ ++ out.WriteByte(text[0]) ++ return 0 ++} ++ ++func (r *SPRenderer) smartDoubleQuoteVariant(out *bytes.Buffer, previousChar byte, text []byte, quote byte) int { ++ nextChar := byte(0) ++ if len(text) > 1 { ++ nextChar = text[1] ++ } ++ if !smartQuoteHelper(out, previousChar, nextChar, quote, &r.inDoubleQuote, false) { ++ out.WriteString(""") ++ } ++ ++ return 0 ++} ++ ++func (r *SPRenderer) smartDoubleQuote(out *bytes.Buffer, previousChar byte, text []byte) int { ++ return r.smartDoubleQuoteVariant(out, previousChar, text, 'd') ++} ++ ++func (r *SPRenderer) smartAngledDoubleQuote(out *bytes.Buffer, previousChar byte, text []byte) int { ++ return r.smartDoubleQuoteVariant(out, previousChar, text, 'a') ++} ++ ++func (r *SPRenderer) smartLeftAngle(out *bytes.Buffer, previousChar byte, text []byte) int { ++ i := 0 ++ ++ for i < len(text) && text[i] != '>' { ++ i++ ++ } ++ ++ out.Write(text[:i+1]) ++ return i ++} ++ ++type smartCallback func(out *bytes.Buffer, previousChar byte, text []byte) int ++ ++// NewSmartypantsRenderer constructs a Smartypants renderer object. ++func NewSmartypantsRenderer(flags HTMLFlags) *SPRenderer { ++ var ( ++ r SPRenderer ++ ++ smartAmpAngled = r.smartAmp(true, false) ++ smartAmpAngledNBSP = r.smartAmp(true, true) ++ smartAmpRegular = r.smartAmp(false, false) ++ smartAmpRegularNBSP = r.smartAmp(false, true) ++ ++ addNBSP = flags&SmartypantsQuotesNBSP != 0 ++ ) ++ ++ if flags&SmartypantsAngledQuotes == 0 { ++ r.callbacks['"'] = r.smartDoubleQuote ++ if !addNBSP { ++ r.callbacks['&'] = smartAmpRegular ++ } else { ++ r.callbacks['&'] = smartAmpRegularNBSP ++ } ++ } else { ++ r.callbacks['"'] = r.smartAngledDoubleQuote ++ if !addNBSP { ++ r.callbacks['&'] = smartAmpAngled ++ } else { ++ r.callbacks['&'] = smartAmpAngledNBSP ++ } ++ } ++ r.callbacks['\''] = r.smartSingleQuote ++ r.callbacks['('] = r.smartParens ++ if flags&SmartypantsDashes != 0 { ++ if flags&SmartypantsLatexDashes == 0 { ++ r.callbacks['-'] = r.smartDash ++ } else { ++ r.callbacks['-'] = r.smartDashLatex ++ } ++ } ++ r.callbacks['.'] = r.smartPeriod ++ if flags&SmartypantsFractions == 0 { ++ r.callbacks['1'] = r.smartNumber ++ r.callbacks['3'] = r.smartNumber ++ } else { ++ for ch := '1'; ch <= '9'; ch++ { ++ r.callbacks[ch] = r.smartNumberGeneric ++ } ++ } ++ r.callbacks['<'] = r.smartLeftAngle ++ r.callbacks['`'] = r.smartBacktick ++ return &r ++} ++ ++// Process is the entry point of the Smartypants renderer. ++func (r *SPRenderer) Process(w io.Writer, text []byte) { ++ mark := 0 ++ for i := 0; i < len(text); i++ { ++ if action := r.callbacks[text[i]]; action != nil { ++ if i > mark { ++ w.Write(text[mark:i]) ++ } ++ previousChar := byte(0) ++ if i > 0 { ++ previousChar = text[i-1] ++ } ++ var tmp bytes.Buffer ++ i += action(&tmp, previousChar, text[i:]) ++ w.Write(tmp.Bytes()) ++ mark = i + 1 ++ } ++ } ++ if mark < len(text) { ++ w.Write(text[mark:]) ++ } ++} +diff --git a/vendor/github.com/spf13/cobra/doc/README.md b/vendor/github.com/spf13/cobra/doc/README.md +new file mode 100644 +index 000000000000..8e07baae3307 +--- /dev/null ++++ b/vendor/github.com/spf13/cobra/doc/README.md +@@ -0,0 +1,17 @@ ++# Documentation generation ++ ++- [Man page docs](./man_docs.md) ++- [Markdown docs](./md_docs.md) ++- [Rest docs](./rest_docs.md) ++- [Yaml docs](./yaml_docs.md) ++ ++## Options ++### `DisableAutoGenTag` ++ ++You may set `cmd.DisableAutoGenTag = true` ++to _entirely_ remove the auto generated string "Auto generated by spf13/cobra..." ++from any documentation source. ++ ++### `InitDefaultCompletionCmd` ++ ++You may call `cmd.InitDefaultCompletionCmd()` to document the default autocompletion command. +diff --git a/vendor/github.com/spf13/cobra/doc/man_docs.go b/vendor/github.com/spf13/cobra/doc/man_docs.go +new file mode 100644 +index 000000000000..b8c15ce88543 +--- /dev/null ++++ b/vendor/github.com/spf13/cobra/doc/man_docs.go +@@ -0,0 +1,246 @@ ++// Copyright 2013-2023 The Cobra Authors ++// ++// 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 doc ++ ++import ( ++ "bytes" ++ "fmt" ++ "io" ++ "os" ++ "path/filepath" ++ "sort" ++ "strconv" ++ "strings" ++ "time" ++ ++ "github.com/cpuguy83/go-md2man/v2/md2man" ++ "github.com/spf13/cobra" ++ "github.com/spf13/pflag" ++) ++ ++// GenManTree will generate a man page for this command and all descendants ++// in the directory given. The header may be nil. This function may not work ++// correctly if your command names have `-` in them. If you have `cmd` with two ++// subcmds, `sub` and `sub-third`, and `sub` has a subcommand called `third` ++// it is undefined which help output will be in the file `cmd-sub-third.1`. ++func GenManTree(cmd *cobra.Command, header *GenManHeader, dir string) error { ++ return GenManTreeFromOpts(cmd, GenManTreeOptions{ ++ Header: header, ++ Path: dir, ++ CommandSeparator: "-", ++ }) ++} ++ ++// GenManTreeFromOpts generates a man page for the command and all descendants. ++// The pages are written to the opts.Path directory. ++func GenManTreeFromOpts(cmd *cobra.Command, opts GenManTreeOptions) error { ++ header := opts.Header ++ if header == nil { ++ header = &GenManHeader{} ++ } ++ for _, c := range cmd.Commands() { ++ if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { ++ continue ++ } ++ if err := GenManTreeFromOpts(c, opts); err != nil { ++ return err ++ } ++ } ++ section := "1" ++ if header.Section != "" { ++ section = header.Section ++ } ++ ++ separator := "_" ++ if opts.CommandSeparator != "" { ++ separator = opts.CommandSeparator ++ } ++ basename := strings.ReplaceAll(cmd.CommandPath(), " ", separator) ++ filename := filepath.Join(opts.Path, basename+"."+section) ++ f, err := os.Create(filename) ++ if err != nil { ++ return err ++ } ++ defer f.Close() ++ ++ headerCopy := *header ++ return GenMan(cmd, &headerCopy, f) ++} ++ ++// GenManTreeOptions is the options for generating the man pages. ++// Used only in GenManTreeFromOpts. ++type GenManTreeOptions struct { ++ Header *GenManHeader ++ Path string ++ CommandSeparator string ++} ++ ++// GenManHeader is a lot like the .TH header at the start of man pages. These ++// include the title, section, date, source, and manual. We will use the ++// current time if Date is unset and will use "Auto generated by spf13/cobra" ++// if the Source is unset. ++type GenManHeader struct { ++ Title string ++ Section string ++ Date *time.Time ++ date string ++ Source string ++ Manual string ++} ++ ++// GenMan will generate a man page for the given command and write it to ++// w. The header argument may be nil, however obviously w may not. ++func GenMan(cmd *cobra.Command, header *GenManHeader, w io.Writer) error { ++ if header == nil { ++ header = &GenManHeader{} ++ } ++ if err := fillHeader(header, cmd.CommandPath(), cmd.DisableAutoGenTag); err != nil { ++ return err ++ } ++ ++ b := genMan(cmd, header) ++ _, err := w.Write(md2man.Render(b)) ++ return err ++} ++ ++func fillHeader(header *GenManHeader, name string, disableAutoGen bool) error { ++ if header.Title == "" { ++ header.Title = strings.ToUpper(strings.ReplaceAll(name, " ", "\\-")) ++ } ++ if header.Section == "" { ++ header.Section = "1" ++ } ++ if header.Date == nil { ++ now := time.Now() ++ if epoch := os.Getenv("SOURCE_DATE_EPOCH"); epoch != "" { ++ unixEpoch, err := strconv.ParseInt(epoch, 10, 64) ++ if err != nil { ++ return fmt.Errorf("invalid SOURCE_DATE_EPOCH: %v", err) ++ } ++ now = time.Unix(unixEpoch, 0) ++ } ++ header.Date = &now ++ } ++ header.date = (*header.Date).Format("Jan 2006") ++ if header.Source == "" && !disableAutoGen { ++ header.Source = "Auto generated by spf13/cobra" ++ } ++ return nil ++} ++ ++func manPreamble(buf io.StringWriter, header *GenManHeader, cmd *cobra.Command, dashedName string) { ++ description := cmd.Long ++ if len(description) == 0 { ++ description = cmd.Short ++ } ++ ++ cobra.WriteStringAndCheck(buf, fmt.Sprintf(`%% "%s" "%s" "%s" "%s" "%s" ++# NAME ++`, header.Title, header.Section, header.date, header.Source, header.Manual)) ++ cobra.WriteStringAndCheck(buf, fmt.Sprintf("%s \\- %s\n\n", dashedName, cmd.Short)) ++ cobra.WriteStringAndCheck(buf, "# SYNOPSIS\n") ++ cobra.WriteStringAndCheck(buf, fmt.Sprintf("**%s**\n\n", cmd.UseLine())) ++ cobra.WriteStringAndCheck(buf, "# DESCRIPTION\n") ++ cobra.WriteStringAndCheck(buf, description+"\n\n") ++} ++ ++func manPrintFlags(buf io.StringWriter, flags *pflag.FlagSet) { ++ flags.VisitAll(func(flag *pflag.Flag) { ++ if len(flag.Deprecated) > 0 || flag.Hidden { ++ return ++ } ++ format := "" ++ if len(flag.Shorthand) > 0 && len(flag.ShorthandDeprecated) == 0 { ++ format = fmt.Sprintf("**-%s**, **--%s**", flag.Shorthand, flag.Name) ++ } else { ++ format = fmt.Sprintf("**--%s**", flag.Name) ++ } ++ if len(flag.NoOptDefVal) > 0 { ++ format += "[" ++ } ++ if flag.Value.Type() == "string" { ++ // put quotes on the value ++ format += "=%q" ++ } else { ++ format += "=%s" ++ } ++ if len(flag.NoOptDefVal) > 0 { ++ format += "]" ++ } ++ format += "\n\t%s\n\n" ++ cobra.WriteStringAndCheck(buf, fmt.Sprintf(format, flag.DefValue, flag.Usage)) ++ }) ++} ++ ++func manPrintOptions(buf io.StringWriter, command *cobra.Command) { ++ flags := command.NonInheritedFlags() ++ if flags.HasAvailableFlags() { ++ cobra.WriteStringAndCheck(buf, "# OPTIONS\n") ++ manPrintFlags(buf, flags) ++ cobra.WriteStringAndCheck(buf, "\n") ++ } ++ flags = command.InheritedFlags() ++ if flags.HasAvailableFlags() { ++ cobra.WriteStringAndCheck(buf, "# OPTIONS INHERITED FROM PARENT COMMANDS\n") ++ manPrintFlags(buf, flags) ++ cobra.WriteStringAndCheck(buf, "\n") ++ } ++} ++ ++func genMan(cmd *cobra.Command, header *GenManHeader) []byte { ++ cmd.InitDefaultHelpCmd() ++ cmd.InitDefaultHelpFlag() ++ ++ // something like `rootcmd-subcmd1-subcmd2` ++ dashCommandName := strings.ReplaceAll(cmd.CommandPath(), " ", "-") ++ ++ buf := new(bytes.Buffer) ++ ++ manPreamble(buf, header, cmd, dashCommandName) ++ manPrintOptions(buf, cmd) ++ if len(cmd.Example) > 0 { ++ buf.WriteString("# EXAMPLE\n") ++ buf.WriteString(fmt.Sprintf("```\n%s\n```\n", cmd.Example)) ++ } ++ if hasSeeAlso(cmd) { ++ buf.WriteString("# SEE ALSO\n") ++ seealsos := make([]string, 0) ++ if cmd.HasParent() { ++ parentPath := cmd.Parent().CommandPath() ++ dashParentPath := strings.ReplaceAll(parentPath, " ", "-") ++ seealso := fmt.Sprintf("**%s(%s)**", dashParentPath, header.Section) ++ seealsos = append(seealsos, seealso) ++ cmd.VisitParents(func(c *cobra.Command) { ++ if c.DisableAutoGenTag { ++ cmd.DisableAutoGenTag = c.DisableAutoGenTag ++ } ++ }) ++ } ++ children := cmd.Commands() ++ sort.Sort(byName(children)) ++ for _, c := range children { ++ if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { ++ continue ++ } ++ seealso := fmt.Sprintf("**%s-%s(%s)**", dashCommandName, c.Name(), header.Section) ++ seealsos = append(seealsos, seealso) ++ } ++ buf.WriteString(strings.Join(seealsos, ", ") + "\n") ++ } ++ if !cmd.DisableAutoGenTag { ++ buf.WriteString(fmt.Sprintf("# HISTORY\n%s Auto generated by spf13/cobra\n", header.Date.Format("2-Jan-2006"))) ++ } ++ return buf.Bytes() ++} +diff --git a/vendor/github.com/spf13/cobra/doc/man_docs.md b/vendor/github.com/spf13/cobra/doc/man_docs.md +new file mode 100644 +index 000000000000..3709160f34f0 +--- /dev/null ++++ b/vendor/github.com/spf13/cobra/doc/man_docs.md +@@ -0,0 +1,31 @@ ++# Generating Man Pages For Your Own cobra.Command ++ ++Generating man pages from a cobra command is incredibly easy. An example is as follows: ++ ++```go ++package main ++ ++import ( ++ "log" ++ ++ "github.com/spf13/cobra" ++ "github.com/spf13/cobra/doc" ++) ++ ++func main() { ++ cmd := &cobra.Command{ ++ Use: "test", ++ Short: "my test program", ++ } ++ header := &doc.GenManHeader{ ++ Title: "MINE", ++ Section: "3", ++ } ++ err := doc.GenManTree(cmd, header, "/tmp") ++ if err != nil { ++ log.Fatal(err) ++ } ++} ++``` ++ ++That will get you a man page `/tmp/test.3` +diff --git a/vendor/github.com/spf13/cobra/doc/md_docs.go b/vendor/github.com/spf13/cobra/doc/md_docs.go +new file mode 100644 +index 000000000000..c4a27c00935b +--- /dev/null ++++ b/vendor/github.com/spf13/cobra/doc/md_docs.go +@@ -0,0 +1,156 @@ ++// Copyright 2013-2023 The Cobra Authors ++// ++// 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 doc ++ ++import ( ++ "bytes" ++ "fmt" ++ "io" ++ "os" ++ "path/filepath" ++ "sort" ++ "strings" ++ "time" ++ ++ "github.com/spf13/cobra" ++) ++ ++func printOptions(buf *bytes.Buffer, cmd *cobra.Command, name string) error { ++ flags := cmd.NonInheritedFlags() ++ flags.SetOutput(buf) ++ if flags.HasAvailableFlags() { ++ buf.WriteString("### Options\n\n```\n") ++ flags.PrintDefaults() ++ buf.WriteString("```\n\n") ++ } ++ ++ parentFlags := cmd.InheritedFlags() ++ parentFlags.SetOutput(buf) ++ if parentFlags.HasAvailableFlags() { ++ buf.WriteString("### Options inherited from parent commands\n\n```\n") ++ parentFlags.PrintDefaults() ++ buf.WriteString("```\n\n") ++ } ++ return nil ++} ++ ++// GenMarkdown creates markdown output. ++func GenMarkdown(cmd *cobra.Command, w io.Writer) error { ++ return GenMarkdownCustom(cmd, w, func(s string) string { return s }) ++} ++ ++// GenMarkdownCustom creates custom markdown output. ++func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) string) error { ++ cmd.InitDefaultHelpCmd() ++ cmd.InitDefaultHelpFlag() ++ ++ buf := new(bytes.Buffer) ++ name := cmd.CommandPath() ++ ++ buf.WriteString("## " + name + "\n\n") ++ buf.WriteString(cmd.Short + "\n\n") ++ if len(cmd.Long) > 0 { ++ buf.WriteString("### Synopsis\n\n") ++ buf.WriteString(cmd.Long + "\n\n") ++ } ++ ++ if cmd.Runnable() { ++ buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.UseLine())) ++ } ++ ++ if len(cmd.Example) > 0 { ++ buf.WriteString("### Examples\n\n") ++ buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.Example)) ++ } ++ ++ if err := printOptions(buf, cmd, name); err != nil { ++ return err ++ } ++ if hasSeeAlso(cmd) { ++ buf.WriteString("### SEE ALSO\n\n") ++ if cmd.HasParent() { ++ parent := cmd.Parent() ++ pname := parent.CommandPath() ++ link := pname + ".md" ++ link = strings.ReplaceAll(link, " ", "_") ++ buf.WriteString(fmt.Sprintf("* [%s](%s)\t - %s\n", pname, linkHandler(link), parent.Short)) ++ cmd.VisitParents(func(c *cobra.Command) { ++ if c.DisableAutoGenTag { ++ cmd.DisableAutoGenTag = c.DisableAutoGenTag ++ } ++ }) ++ } ++ ++ children := cmd.Commands() ++ sort.Sort(byName(children)) ++ ++ for _, child := range children { ++ if !child.IsAvailableCommand() || child.IsAdditionalHelpTopicCommand() { ++ continue ++ } ++ cname := name + " " + child.Name() ++ link := cname + ".md" ++ link = strings.ReplaceAll(link, " ", "_") ++ buf.WriteString(fmt.Sprintf("* [%s](%s)\t - %s\n", cname, linkHandler(link), child.Short)) ++ } ++ buf.WriteString("\n") ++ } ++ if !cmd.DisableAutoGenTag { ++ buf.WriteString("###### Auto generated by spf13/cobra on " + time.Now().Format("2-Jan-2006") + "\n") ++ } ++ _, err := buf.WriteTo(w) ++ return err ++} ++ ++// GenMarkdownTree will generate a markdown page for this command and all ++// descendants in the directory given. The header may be nil. ++// This function may not work correctly if your command names have `-` in them. ++// If you have `cmd` with two subcmds, `sub` and `sub-third`, ++// and `sub` has a subcommand called `third`, it is undefined which ++// help output will be in the file `cmd-sub-third.1`. ++func GenMarkdownTree(cmd *cobra.Command, dir string) error { ++ identity := func(s string) string { return s } ++ emptyStr := func(s string) string { return "" } ++ return GenMarkdownTreeCustom(cmd, dir, emptyStr, identity) ++} ++ ++// GenMarkdownTreeCustom is the the same as GenMarkdownTree, but ++// with custom filePrepender and linkHandler. ++func GenMarkdownTreeCustom(cmd *cobra.Command, dir string, filePrepender, linkHandler func(string) string) error { ++ for _, c := range cmd.Commands() { ++ if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { ++ continue ++ } ++ if err := GenMarkdownTreeCustom(c, dir, filePrepender, linkHandler); err != nil { ++ return err ++ } ++ } ++ ++ basename := strings.ReplaceAll(cmd.CommandPath(), " ", "_") + ".md" ++ filename := filepath.Join(dir, basename) ++ f, err := os.Create(filename) ++ if err != nil { ++ return err ++ } ++ defer f.Close() ++ ++ if _, err := io.WriteString(f, filePrepender(filename)); err != nil { ++ return err ++ } ++ if err := GenMarkdownCustom(cmd, f, linkHandler); err != nil { ++ return err ++ } ++ return nil ++} +diff --git a/vendor/github.com/spf13/cobra/doc/md_docs.md b/vendor/github.com/spf13/cobra/doc/md_docs.md +new file mode 100644 +index 000000000000..1659175cfdab +--- /dev/null ++++ b/vendor/github.com/spf13/cobra/doc/md_docs.md +@@ -0,0 +1,115 @@ ++# Generating Markdown Docs For Your Own cobra.Command ++ ++Generating Markdown pages from a cobra command is incredibly easy. An example is as follows: ++ ++```go ++package main ++ ++import ( ++ "log" ++ ++ "github.com/spf13/cobra" ++ "github.com/spf13/cobra/doc" ++) ++ ++func main() { ++ cmd := &cobra.Command{ ++ Use: "test", ++ Short: "my test program", ++ } ++ err := doc.GenMarkdownTree(cmd, "/tmp") ++ if err != nil { ++ log.Fatal(err) ++ } ++} ++``` ++ ++That will get you a Markdown document `/tmp/test.md` ++ ++## Generate markdown docs for the entire command tree ++ ++This program can actually generate docs for the kubectl command in the kubernetes project ++ ++```go ++package main ++ ++import ( ++ "log" ++ "io/ioutil" ++ "os" ++ ++ "k8s.io/kubernetes/pkg/kubectl/cmd" ++ cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" ++ ++ "github.com/spf13/cobra/doc" ++) ++ ++func main() { ++ kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard) ++ err := doc.GenMarkdownTree(kubectl, "./") ++ if err != nil { ++ log.Fatal(err) ++ } ++} ++``` ++ ++This will generate a whole series of files, one for each command in the tree, in the directory specified (in this case "./") ++ ++## Generate markdown docs for a single command ++ ++You may wish to have more control over the output, or only generate for a single command, instead of the entire command tree. If this is the case you may prefer to `GenMarkdown` instead of `GenMarkdownTree` ++ ++```go ++ out := new(bytes.Buffer) ++ err := doc.GenMarkdown(cmd, out) ++ if err != nil { ++ log.Fatal(err) ++ } ++``` ++ ++This will write the markdown doc for ONLY "cmd" into the out, buffer. ++ ++## Customize the output ++ ++Both `GenMarkdown` and `GenMarkdownTree` have alternate versions with callbacks to get some control of the output: ++ ++```go ++func GenMarkdownTreeCustom(cmd *Command, dir string, filePrepender, linkHandler func(string) string) error { ++ //... ++} ++``` ++ ++```go ++func GenMarkdownCustom(cmd *Command, out *bytes.Buffer, linkHandler func(string) string) error { ++ //... ++} ++``` ++ ++The `filePrepender` will prepend the return value given the full filepath to the rendered Markdown file. A common use case is to add front matter to use the generated documentation with [Hugo](https://gohugo.io/): ++ ++```go ++const fmTemplate = `--- ++date: %s ++title: "%s" ++slug: %s ++url: %s ++--- ++` ++ ++filePrepender := func(filename string) string { ++ now := time.Now().Format(time.RFC3339) ++ name := filepath.Base(filename) ++ base := strings.TrimSuffix(name, path.Ext(name)) ++ url := "/commands/" + strings.ToLower(base) + "/" ++ return fmt.Sprintf(fmTemplate, now, strings.Replace(base, "_", " ", -1), base, url) ++} ++``` ++ ++The `linkHandler` can be used to customize the rendered internal links to the commands, given a filename: ++ ++```go ++linkHandler := func(name string) string { ++ base := strings.TrimSuffix(name, path.Ext(name)) ++ return "/commands/" + strings.ToLower(base) + "/" ++} ++``` +diff --git a/vendor/github.com/spf13/cobra/doc/rest_docs.go b/vendor/github.com/spf13/cobra/doc/rest_docs.go +new file mode 100644 +index 000000000000..2cca6fd778de +--- /dev/null ++++ b/vendor/github.com/spf13/cobra/doc/rest_docs.go +@@ -0,0 +1,186 @@ ++// Copyright 2013-2023 The Cobra Authors ++// ++// 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 doc ++ ++import ( ++ "bytes" ++ "fmt" ++ "io" ++ "os" ++ "path/filepath" ++ "sort" ++ "strings" ++ "time" ++ ++ "github.com/spf13/cobra" ++) ++ ++func printOptionsReST(buf *bytes.Buffer, cmd *cobra.Command, name string) error { ++ flags := cmd.NonInheritedFlags() ++ flags.SetOutput(buf) ++ if flags.HasAvailableFlags() { ++ buf.WriteString("Options\n") ++ buf.WriteString("~~~~~~~\n\n::\n\n") ++ flags.PrintDefaults() ++ buf.WriteString("\n") ++ } ++ ++ parentFlags := cmd.InheritedFlags() ++ parentFlags.SetOutput(buf) ++ if parentFlags.HasAvailableFlags() { ++ buf.WriteString("Options inherited from parent commands\n") ++ buf.WriteString("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n::\n\n") ++ parentFlags.PrintDefaults() ++ buf.WriteString("\n") ++ } ++ return nil ++} ++ ++// defaultLinkHandler for default ReST hyperlink markup ++func defaultLinkHandler(name, ref string) string { ++ return fmt.Sprintf("`%s <%s.rst>`_", name, ref) ++} ++ ++// GenReST creates reStructured Text output. ++func GenReST(cmd *cobra.Command, w io.Writer) error { ++ return GenReSTCustom(cmd, w, defaultLinkHandler) ++} ++ ++// GenReSTCustom creates custom reStructured Text output. ++func GenReSTCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string, string) string) error { ++ cmd.InitDefaultHelpCmd() ++ cmd.InitDefaultHelpFlag() ++ ++ buf := new(bytes.Buffer) ++ name := cmd.CommandPath() ++ ++ short := cmd.Short ++ long := cmd.Long ++ if len(long) == 0 { ++ long = short ++ } ++ ref := strings.ReplaceAll(name, " ", "_") ++ ++ buf.WriteString(".. _" + ref + ":\n\n") ++ buf.WriteString(name + "\n") ++ buf.WriteString(strings.Repeat("-", len(name)) + "\n\n") ++ buf.WriteString(short + "\n\n") ++ buf.WriteString("Synopsis\n") ++ buf.WriteString("~~~~~~~~\n\n") ++ buf.WriteString("\n" + long + "\n\n") ++ ++ if cmd.Runnable() { ++ buf.WriteString(fmt.Sprintf("::\n\n %s\n\n", cmd.UseLine())) ++ } ++ ++ if len(cmd.Example) > 0 { ++ buf.WriteString("Examples\n") ++ buf.WriteString("~~~~~~~~\n\n") ++ buf.WriteString(fmt.Sprintf("::\n\n%s\n\n", indentString(cmd.Example, " "))) ++ } ++ ++ if err := printOptionsReST(buf, cmd, name); err != nil { ++ return err ++ } ++ if hasSeeAlso(cmd) { ++ buf.WriteString("SEE ALSO\n") ++ buf.WriteString("~~~~~~~~\n\n") ++ if cmd.HasParent() { ++ parent := cmd.Parent() ++ pname := parent.CommandPath() ++ ref = strings.ReplaceAll(pname, " ", "_") ++ buf.WriteString(fmt.Sprintf("* %s \t - %s\n", linkHandler(pname, ref), parent.Short)) ++ cmd.VisitParents(func(c *cobra.Command) { ++ if c.DisableAutoGenTag { ++ cmd.DisableAutoGenTag = c.DisableAutoGenTag ++ } ++ }) ++ } ++ ++ children := cmd.Commands() ++ sort.Sort(byName(children)) ++ ++ for _, child := range children { ++ if !child.IsAvailableCommand() || child.IsAdditionalHelpTopicCommand() { ++ continue ++ } ++ cname := name + " " + child.Name() ++ ref = strings.ReplaceAll(cname, " ", "_") ++ buf.WriteString(fmt.Sprintf("* %s \t - %s\n", linkHandler(cname, ref), child.Short)) ++ } ++ buf.WriteString("\n") ++ } ++ if !cmd.DisableAutoGenTag { ++ buf.WriteString("*Auto generated by spf13/cobra on " + time.Now().Format("2-Jan-2006") + "*\n") ++ } ++ _, err := buf.WriteTo(w) ++ return err ++} ++ ++// GenReSTTree will generate a ReST page for this command and all ++// descendants in the directory given. ++// This function may not work correctly if your command names have `-` in them. ++// If you have `cmd` with two subcmds, `sub` and `sub-third`, ++// and `sub` has a subcommand called `third`, it is undefined which ++// help output will be in the file `cmd-sub-third.1`. ++func GenReSTTree(cmd *cobra.Command, dir string) error { ++ emptyStr := func(s string) string { return "" } ++ return GenReSTTreeCustom(cmd, dir, emptyStr, defaultLinkHandler) ++} ++ ++// GenReSTTreeCustom is the the same as GenReSTTree, but ++// with custom filePrepender and linkHandler. ++func GenReSTTreeCustom(cmd *cobra.Command, dir string, filePrepender func(string) string, linkHandler func(string, string) string) error { ++ for _, c := range cmd.Commands() { ++ if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { ++ continue ++ } ++ if err := GenReSTTreeCustom(c, dir, filePrepender, linkHandler); err != nil { ++ return err ++ } ++ } ++ ++ basename := strings.ReplaceAll(cmd.CommandPath(), " ", "_") + ".rst" ++ filename := filepath.Join(dir, basename) ++ f, err := os.Create(filename) ++ if err != nil { ++ return err ++ } ++ defer f.Close() ++ ++ if _, err := io.WriteString(f, filePrepender(filename)); err != nil { ++ return err ++ } ++ if err := GenReSTCustom(cmd, f, linkHandler); err != nil { ++ return err ++ } ++ return nil ++} ++ ++// indentString adapted from: https://github.com/kr/text/blob/main/indent.go ++func indentString(s, p string) string { ++ var res []byte ++ b := []byte(s) ++ prefix := []byte(p) ++ bol := true ++ for _, c := range b { ++ if bol && c != '\n' { ++ res = append(res, prefix...) ++ } ++ res = append(res, c) ++ bol = c == '\n' ++ } ++ return string(res) ++} +diff --git a/vendor/github.com/spf13/cobra/doc/rest_docs.md b/vendor/github.com/spf13/cobra/doc/rest_docs.md +new file mode 100644 +index 000000000000..3041c573ab01 +--- /dev/null ++++ b/vendor/github.com/spf13/cobra/doc/rest_docs.md +@@ -0,0 +1,114 @@ ++# Generating ReStructured Text Docs For Your Own cobra.Command ++ ++Generating ReST pages from a cobra command is incredibly easy. An example is as follows: ++ ++```go ++package main ++ ++import ( ++ "log" ++ ++ "github.com/spf13/cobra" ++ "github.com/spf13/cobra/doc" ++) ++ ++func main() { ++ cmd := &cobra.Command{ ++ Use: "test", ++ Short: "my test program", ++ } ++ err := doc.GenReSTTree(cmd, "/tmp") ++ if err != nil { ++ log.Fatal(err) ++ } ++} ++``` ++ ++That will get you a ReST document `/tmp/test.rst` ++ ++## Generate ReST docs for the entire command tree ++ ++This program can actually generate docs for the kubectl command in the kubernetes project ++ ++```go ++package main ++ ++import ( ++ "log" ++ "io/ioutil" ++ "os" ++ ++ "k8s.io/kubernetes/pkg/kubectl/cmd" ++ cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" ++ ++ "github.com/spf13/cobra/doc" ++) ++ ++func main() { ++ kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard) ++ err := doc.GenReSTTree(kubectl, "./") ++ if err != nil { ++ log.Fatal(err) ++ } ++} ++``` ++ ++This will generate a whole series of files, one for each command in the tree, in the directory specified (in this case "./") ++ ++## Generate ReST docs for a single command ++ ++You may wish to have more control over the output, or only generate for a single command, instead of the entire command tree. If this is the case you may prefer to `GenReST` instead of `GenReSTTree` ++ ++```go ++ out := new(bytes.Buffer) ++ err := doc.GenReST(cmd, out) ++ if err != nil { ++ log.Fatal(err) ++ } ++``` ++ ++This will write the ReST doc for ONLY "cmd" into the out, buffer. ++ ++## Customize the output ++ ++Both `GenReST` and `GenReSTTree` have alternate versions with callbacks to get some control of the output: ++ ++```go ++func GenReSTTreeCustom(cmd *Command, dir string, filePrepender func(string) string, linkHandler func(string, string) string) error { ++ //... ++} ++``` ++ ++```go ++func GenReSTCustom(cmd *Command, out *bytes.Buffer, linkHandler func(string, string) string) error { ++ //... ++} ++``` ++ ++The `filePrepender` will prepend the return value given the full filepath to the rendered ReST file. A common use case is to add front matter to use the generated documentation with [Hugo](https://gohugo.io/): ++ ++```go ++const fmTemplate = `--- ++date: %s ++title: "%s" ++slug: %s ++url: %s ++--- ++` ++filePrepender := func(filename string) string { ++ now := time.Now().Format(time.RFC3339) ++ name := filepath.Base(filename) ++ base := strings.TrimSuffix(name, path.Ext(name)) ++ url := "/commands/" + strings.ToLower(base) + "/" ++ return fmt.Sprintf(fmTemplate, now, strings.Replace(base, "_", " ", -1), base, url) ++} ++``` ++ ++The `linkHandler` can be used to customize the rendered links to the commands, given a command name and reference. This is useful while converting rst to html or while generating documentation with tools like Sphinx where `:ref:` is used: ++ ++```go ++// Sphinx cross-referencing format ++linkHandler := func(name, ref string) string { ++ return fmt.Sprintf(":ref:`%s <%s>`", name, ref) ++} ++``` +diff --git a/vendor/github.com/spf13/cobra/doc/util.go b/vendor/github.com/spf13/cobra/doc/util.go +new file mode 100644 +index 000000000000..0aaa07a166d8 +--- /dev/null ++++ b/vendor/github.com/spf13/cobra/doc/util.go +@@ -0,0 +1,52 @@ ++// Copyright 2013-2023 The Cobra Authors ++// ++// 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 doc ++ ++import ( ++ "strings" ++ ++ "github.com/spf13/cobra" ++) ++ ++// Test to see if we have a reason to print See Also information in docs ++// Basically this is a test for a parent command or a subcommand which is ++// both not deprecated and not the autogenerated help command. ++func hasSeeAlso(cmd *cobra.Command) bool { ++ if cmd.HasParent() { ++ return true ++ } ++ for _, c := range cmd.Commands() { ++ if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { ++ continue ++ } ++ return true ++ } ++ return false ++} ++ ++// Temporary workaround for yaml lib generating incorrect yaml with long strings ++// that do not contain \n. ++func forceMultiLine(s string) string { ++ if len(s) > 60 && !strings.Contains(s, "\n") { ++ s = s + "\n" ++ } ++ return s ++} ++ ++type byName []*cobra.Command ++ ++func (s byName) Len() int { return len(s) } ++func (s byName) Swap(i, j int) { s[i], s[j] = s[j], s[i] } ++func (s byName) Less(i, j int) bool { return s[i].Name() < s[j].Name() } +diff --git a/vendor/github.com/spf13/cobra/doc/yaml_docs.go b/vendor/github.com/spf13/cobra/doc/yaml_docs.go +new file mode 100644 +index 000000000000..2b26d6ec0f3e +--- /dev/null ++++ b/vendor/github.com/spf13/cobra/doc/yaml_docs.go +@@ -0,0 +1,175 @@ ++// Copyright 2013-2023 The Cobra Authors ++// ++// 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 doc ++ ++import ( ++ "fmt" ++ "io" ++ "os" ++ "path/filepath" ++ "sort" ++ "strings" ++ ++ "github.com/spf13/cobra" ++ "github.com/spf13/pflag" ++ "gopkg.in/yaml.v3" ++) ++ ++type cmdOption struct { ++ Name string ++ Shorthand string `yaml:",omitempty"` ++ DefaultValue string `yaml:"default_value,omitempty"` ++ Usage string `yaml:",omitempty"` ++} ++ ++type cmdDoc struct { ++ Name string ++ Synopsis string `yaml:",omitempty"` ++ Description string `yaml:",omitempty"` ++ Usage string `yaml:",omitempty"` ++ Options []cmdOption `yaml:",omitempty"` ++ InheritedOptions []cmdOption `yaml:"inherited_options,omitempty"` ++ Example string `yaml:",omitempty"` ++ SeeAlso []string `yaml:"see_also,omitempty"` ++} ++ ++// GenYamlTree creates yaml structured ref files for this command and all descendants ++// in the directory given. This function may not work ++// correctly if your command names have `-` in them. If you have `cmd` with two ++// subcmds, `sub` and `sub-third`, and `sub` has a subcommand called `third` ++// it is undefined which help output will be in the file `cmd-sub-third.1`. ++func GenYamlTree(cmd *cobra.Command, dir string) error { ++ identity := func(s string) string { return s } ++ emptyStr := func(s string) string { return "" } ++ return GenYamlTreeCustom(cmd, dir, emptyStr, identity) ++} ++ ++// GenYamlTreeCustom creates yaml structured ref files. ++func GenYamlTreeCustom(cmd *cobra.Command, dir string, filePrepender, linkHandler func(string) string) error { ++ for _, c := range cmd.Commands() { ++ if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { ++ continue ++ } ++ if err := GenYamlTreeCustom(c, dir, filePrepender, linkHandler); err != nil { ++ return err ++ } ++ } ++ ++ basename := strings.ReplaceAll(cmd.CommandPath(), " ", "_") + ".yaml" ++ filename := filepath.Join(dir, basename) ++ f, err := os.Create(filename) ++ if err != nil { ++ return err ++ } ++ defer f.Close() ++ ++ if _, err := io.WriteString(f, filePrepender(filename)); err != nil { ++ return err ++ } ++ if err := GenYamlCustom(cmd, f, linkHandler); err != nil { ++ return err ++ } ++ return nil ++} ++ ++// GenYaml creates yaml output. ++func GenYaml(cmd *cobra.Command, w io.Writer) error { ++ return GenYamlCustom(cmd, w, func(s string) string { return s }) ++} ++ ++// GenYamlCustom creates custom yaml output. ++func GenYamlCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) string) error { ++ cmd.InitDefaultHelpCmd() ++ cmd.InitDefaultHelpFlag() ++ ++ yamlDoc := cmdDoc{} ++ yamlDoc.Name = cmd.CommandPath() ++ ++ yamlDoc.Synopsis = forceMultiLine(cmd.Short) ++ yamlDoc.Description = forceMultiLine(cmd.Long) ++ ++ if cmd.Runnable() { ++ yamlDoc.Usage = cmd.UseLine() ++ } ++ ++ if len(cmd.Example) > 0 { ++ yamlDoc.Example = cmd.Example ++ } ++ ++ flags := cmd.NonInheritedFlags() ++ if flags.HasFlags() { ++ yamlDoc.Options = genFlagResult(flags) ++ } ++ flags = cmd.InheritedFlags() ++ if flags.HasFlags() { ++ yamlDoc.InheritedOptions = genFlagResult(flags) ++ } ++ ++ if hasSeeAlso(cmd) { ++ result := []string{} ++ if cmd.HasParent() { ++ parent := cmd.Parent() ++ result = append(result, parent.CommandPath()+" - "+parent.Short) ++ } ++ children := cmd.Commands() ++ sort.Sort(byName(children)) ++ for _, child := range children { ++ if !child.IsAvailableCommand() || child.IsAdditionalHelpTopicCommand() { ++ continue ++ } ++ result = append(result, child.CommandPath()+" - "+child.Short) ++ } ++ yamlDoc.SeeAlso = result ++ } ++ ++ final, err := yaml.Marshal(&yamlDoc) ++ if err != nil { ++ fmt.Println(err) ++ os.Exit(1) ++ } ++ ++ if _, err := w.Write(final); err != nil { ++ return err ++ } ++ return nil ++} ++ ++func genFlagResult(flags *pflag.FlagSet) []cmdOption { ++ var result []cmdOption ++ ++ flags.VisitAll(func(flag *pflag.Flag) { ++ // Todo, when we mark a shorthand is deprecated, but specify an empty message. ++ // The flag.ShorthandDeprecated is empty as the shorthand is deprecated. ++ // Using len(flag.ShorthandDeprecated) > 0 can't handle this, others are ok. ++ if !(len(flag.ShorthandDeprecated) > 0) && len(flag.Shorthand) > 0 { ++ opt := cmdOption{ ++ flag.Name, ++ flag.Shorthand, ++ flag.DefValue, ++ forceMultiLine(flag.Usage), ++ } ++ result = append(result, opt) ++ } else { ++ opt := cmdOption{ ++ Name: flag.Name, ++ DefaultValue: forceMultiLine(flag.DefValue), ++ Usage: forceMultiLine(flag.Usage), ++ } ++ result = append(result, opt) ++ } ++ }) ++ ++ return result ++} +diff --git a/vendor/github.com/spf13/cobra/doc/yaml_docs.md b/vendor/github.com/spf13/cobra/doc/yaml_docs.md +new file mode 100644 +index 000000000000..172e61d12145 +--- /dev/null ++++ b/vendor/github.com/spf13/cobra/doc/yaml_docs.md +@@ -0,0 +1,112 @@ ++# Generating Yaml Docs For Your Own cobra.Command ++ ++Generating yaml files from a cobra command is incredibly easy. An example is as follows: ++ ++```go ++package main ++ ++import ( ++ "log" ++ ++ "github.com/spf13/cobra" ++ "github.com/spf13/cobra/doc" ++) ++ ++func main() { ++ cmd := &cobra.Command{ ++ Use: "test", ++ Short: "my test program", ++ } ++ err := doc.GenYamlTree(cmd, "/tmp") ++ if err != nil { ++ log.Fatal(err) ++ } ++} ++``` ++ ++That will get you a Yaml document `/tmp/test.yaml` ++ ++## Generate yaml docs for the entire command tree ++ ++This program can actually generate docs for the kubectl command in the kubernetes project ++ ++```go ++package main ++ ++import ( ++ "io/ioutil" ++ "log" ++ "os" ++ ++ "k8s.io/kubernetes/pkg/kubectl/cmd" ++ cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" ++ ++ "github.com/spf13/cobra/doc" ++) ++ ++func main() { ++ kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard) ++ err := doc.GenYamlTree(kubectl, "./") ++ if err != nil { ++ log.Fatal(err) ++ } ++} ++``` ++ ++This will generate a whole series of files, one for each command in the tree, in the directory specified (in this case "./") ++ ++## Generate yaml docs for a single command ++ ++You may wish to have more control over the output, or only generate for a single command, instead of the entire command tree. If this is the case you may prefer to `GenYaml` instead of `GenYamlTree` ++ ++```go ++ out := new(bytes.Buffer) ++ doc.GenYaml(cmd, out) ++``` ++ ++This will write the yaml doc for ONLY "cmd" into the out, buffer. ++ ++## Customize the output ++ ++Both `GenYaml` and `GenYamlTree` have alternate versions with callbacks to get some control of the output: ++ ++```go ++func GenYamlTreeCustom(cmd *Command, dir string, filePrepender, linkHandler func(string) string) error { ++ //... ++} ++``` ++ ++```go ++func GenYamlCustom(cmd *Command, out *bytes.Buffer, linkHandler func(string) string) error { ++ //... ++} ++``` ++ ++The `filePrepender` will prepend the return value given the full filepath to the rendered Yaml file. A common use case is to add front matter to use the generated documentation with [Hugo](https://gohugo.io/): ++ ++```go ++const fmTemplate = `--- ++date: %s ++title: "%s" ++slug: %s ++url: %s ++--- ++` ++ ++filePrepender := func(filename string) string { ++ now := time.Now().Format(time.RFC3339) ++ name := filepath.Base(filename) ++ base := strings.TrimSuffix(name, path.Ext(name)) ++ url := "/commands/" + strings.ToLower(base) + "/" ++ return fmt.Sprintf(fmTemplate, now, strings.Replace(base, "_", " ", -1), base, url) ++} ++``` ++ ++The `linkHandler` can be used to customize the rendered internal links to the commands, given a filename: ++ ++```go ++linkHandler := func(name string) string { ++ base := strings.TrimSuffix(name, path.Ext(name)) ++ return "/commands/" + strings.ToLower(base) + "/" ++} ++``` +diff --git a/vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go b/vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go +index f34a38e4e95f..a6b5081888ba 100644 +--- a/vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go ++++ b/vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go +@@ -1,4 +1,4 @@ +-// Copyright 2020 Google LLC ++// Copyright 2022 Google LLC + // + // Licensed under the Apache License, Version 2.0 (the "License"); + // you may not use this file except in compliance with the License. +@@ -15,7 +15,7 @@ + // Code generated by protoc-gen-go. DO NOT EDIT. + // versions: + // protoc-gen-go v1.26.0 +-// protoc v3.12.2 ++// protoc v3.21.9 + // source: google/rpc/status.proto + + package status +@@ -48,11 +48,13 @@ type Status struct { + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + +- // The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]. ++ // The status code, which should be an enum value of ++ // [google.rpc.Code][google.rpc.Code]. + Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + // A developer-facing error message, which should be in English. Any + // user-facing error message should be localized and sent in the +- // [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client. ++ // [google.rpc.Status.details][google.rpc.Status.details] field, or localized ++ // by the client. + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` + // A list of messages that carry the error details. There is a common set of + // message types for APIs to use. +diff --git a/vendor/google.golang.org/grpc/attributes/attributes.go b/vendor/google.golang.org/grpc/attributes/attributes.go +index ae13ddac14e0..02f5dc531891 100644 +--- a/vendor/google.golang.org/grpc/attributes/attributes.go ++++ b/vendor/google.golang.org/grpc/attributes/attributes.go +@@ -19,7 +19,7 @@ + // Package attributes defines a generic key/value store used in various gRPC + // components. + // +-// Experimental ++// # Experimental + // + // Notice: This package is EXPERIMENTAL and may be changed or removed in a + // later release. +diff --git a/vendor/google.golang.org/grpc/backoff.go b/vendor/google.golang.org/grpc/backoff.go +index 542594f5cc51..29475e31c979 100644 +--- a/vendor/google.golang.org/grpc/backoff.go ++++ b/vendor/google.golang.org/grpc/backoff.go +@@ -48,7 +48,7 @@ type BackoffConfig struct { + // here for more details: + // https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md. + // +-// Experimental ++// # Experimental + // + // Notice: This type is EXPERIMENTAL and may be changed or removed in a + // later release. +diff --git a/vendor/google.golang.org/grpc/balancer/balancer.go b/vendor/google.golang.org/grpc/balancer/balancer.go +index f4f9408f3852..09d61dd1b55b 100644 +--- a/vendor/google.golang.org/grpc/balancer/balancer.go ++++ b/vendor/google.golang.org/grpc/balancer/balancer.go +@@ -110,6 +110,11 @@ type SubConn interface { + UpdateAddresses([]resolver.Address) + // Connect starts the connecting for this SubConn. + Connect() ++ // GetOrBuildProducer returns a reference to the existing Producer for this ++ // ProducerBuilder in this SubConn, or, if one does not currently exist, ++ // creates a new one and returns it. Returns a close function which must ++ // be called when the Producer is no longer needed. ++ GetOrBuildProducer(ProducerBuilder) (p Producer, close func()) + } + + // NewSubConnOptions contains options to create new SubConn. +@@ -274,6 +279,14 @@ type PickResult struct { + // type, Done may not be called. May be nil if the balancer does not wish + // to be notified when the RPC completes. + Done func(DoneInfo) ++ ++ // Metadata provides a way for LB policies to inject arbitrary per-call ++ // metadata. Any metadata returned here will be merged with existing ++ // metadata added by the client application. ++ // ++ // LB policies with child policies are responsible for propagating metadata ++ // injected by their children to the ClientConn, as part of Pick(). ++ Metatada metadata.MD + } + + // TransientFailureError returns e. It exists for backward compatibility and +@@ -371,3 +384,21 @@ type ClientConnState struct { + // ErrBadResolverState may be returned by UpdateClientConnState to indicate a + // problem with the provided name resolver data. + var ErrBadResolverState = errors.New("bad resolver state") ++ ++// A ProducerBuilder is a simple constructor for a Producer. It is used by the ++// SubConn to create producers when needed. ++type ProducerBuilder interface { ++ // Build creates a Producer. The first parameter is always a ++ // grpc.ClientConnInterface (a type to allow creating RPCs/streams on the ++ // associated SubConn), but is declared as interface{} to avoid a ++ // dependency cycle. Should also return a close function that will be ++ // called when all references to the Producer have been given up. ++ Build(grpcClientConnInterface interface{}) (p Producer, close func()) ++} ++ ++// A Producer is a type shared among potentially many consumers. It is ++// associated with a SubConn, and an implementation will typically contain ++// other methods to provide additional functionality, e.g. configuration or ++// subscription registration. ++type Producer interface { ++} +diff --git a/vendor/google.golang.org/grpc/balancer/base/balancer.go b/vendor/google.golang.org/grpc/balancer/base/balancer.go +index e8dfc828aaac..3929c26d31e1 100644 +--- a/vendor/google.golang.org/grpc/balancer/base/balancer.go ++++ b/vendor/google.golang.org/grpc/balancer/base/balancer.go +@@ -157,8 +157,8 @@ func (b *baseBalancer) mergeErrors() error { + + // regeneratePicker takes a snapshot of the balancer, and generates a picker + // from it. The picker is +-// - errPicker if the balancer is in TransientFailure, +-// - built by the pickerBuilder with all READY SubConns otherwise. ++// - errPicker if the balancer is in TransientFailure, ++// - built by the pickerBuilder with all READY SubConns otherwise. + func (b *baseBalancer) regeneratePicker() { + if b.state == connectivity.TransientFailure { + b.picker = NewErrPicker(b.mergeErrors()) +diff --git a/vendor/google.golang.org/grpc/balancer/conn_state_evaluator.go b/vendor/google.golang.org/grpc/balancer/conn_state_evaluator.go +index a87b6809af38..c33413581091 100644 +--- a/vendor/google.golang.org/grpc/balancer/conn_state_evaluator.go ++++ b/vendor/google.golang.org/grpc/balancer/conn_state_evaluator.go +@@ -34,10 +34,10 @@ type ConnectivityStateEvaluator struct { + // RecordTransition records state change happening in subConn and based on that + // it evaluates what aggregated state should be. + // +-// - If at least one SubConn in Ready, the aggregated state is Ready; +-// - Else if at least one SubConn in Connecting, the aggregated state is Connecting; +-// - Else if at least one SubConn is Idle, the aggregated state is Idle; +-// - Else if at least one SubConn is TransientFailure (or there are no SubConns), the aggregated state is Transient Failure. ++// - If at least one SubConn in Ready, the aggregated state is Ready; ++// - Else if at least one SubConn in Connecting, the aggregated state is Connecting; ++// - Else if at least one SubConn is Idle, the aggregated state is Idle; ++// - Else if at least one SubConn is TransientFailure (or there are no SubConns), the aggregated state is Transient Failure. + // + // Shutdown is not considered. + func (cse *ConnectivityStateEvaluator) RecordTransition(oldState, newState connectivity.State) connectivity.State { +@@ -55,7 +55,11 @@ func (cse *ConnectivityStateEvaluator) RecordTransition(oldState, newState conne + cse.numIdle += updateVal + } + } ++ return cse.CurrentState() ++} + ++// CurrentState returns the current aggregate conn state by evaluating the counters ++func (cse *ConnectivityStateEvaluator) CurrentState() connectivity.State { + // Evaluate. + if cse.numReady > 0 { + return connectivity.Ready +diff --git a/vendor/google.golang.org/grpc/balancer_conn_wrappers.go b/vendor/google.golang.org/grpc/balancer_conn_wrappers.go +index b1c23eaae0db..0359956d36fa 100644 +--- a/vendor/google.golang.org/grpc/balancer_conn_wrappers.go ++++ b/vendor/google.golang.org/grpc/balancer_conn_wrappers.go +@@ -19,17 +19,20 @@ + package grpc + + import ( ++ "context" + "fmt" + "strings" + "sync" + + "google.golang.org/grpc/balancer" ++ "google.golang.org/grpc/codes" + "google.golang.org/grpc/connectivity" + "google.golang.org/grpc/internal/balancer/gracefulswitch" + "google.golang.org/grpc/internal/buffer" + "google.golang.org/grpc/internal/channelz" + "google.golang.org/grpc/internal/grpcsync" + "google.golang.org/grpc/resolver" ++ "google.golang.org/grpc/status" + ) + + // ccBalancerWrapper sits between the ClientConn and the Balancer. +@@ -305,7 +308,7 @@ func (ccb *ccBalancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer + channelz.Warningf(logger, ccb.cc.channelzID, "acBalancerWrapper: NewSubConn: failed to newAddrConn: %v", err) + return nil, err + } +- acbw := &acBalancerWrapper{ac: ac} ++ acbw := &acBalancerWrapper{ac: ac, producers: make(map[balancer.ProducerBuilder]*refCountedProducer)} + acbw.ac.mu.Lock() + ac.acbw = acbw + acbw.ac.mu.Unlock() +@@ -359,8 +362,9 @@ func (ccb *ccBalancerWrapper) Target() string { + // acBalancerWrapper is a wrapper on top of ac for balancers. + // It implements balancer.SubConn interface. + type acBalancerWrapper struct { +- mu sync.Mutex +- ac *addrConn ++ mu sync.Mutex ++ ac *addrConn ++ producers map[balancer.ProducerBuilder]*refCountedProducer + } + + func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) { +@@ -414,3 +418,64 @@ func (acbw *acBalancerWrapper) getAddrConn() *addrConn { + defer acbw.mu.Unlock() + return acbw.ac + } ++ ++var errSubConnNotReady = status.Error(codes.Unavailable, "SubConn not currently connected") ++ ++// NewStream begins a streaming RPC on the addrConn. If the addrConn is not ++// ready, returns errSubConnNotReady. ++func (acbw *acBalancerWrapper) NewStream(ctx context.Context, desc *StreamDesc, method string, opts ...CallOption) (ClientStream, error) { ++ transport := acbw.ac.getReadyTransport() ++ if transport == nil { ++ return nil, errSubConnNotReady ++ } ++ return newNonRetryClientStream(ctx, desc, method, transport, acbw.ac, opts...) ++} ++ ++// Invoke performs a unary RPC. If the addrConn is not ready, returns ++// errSubConnNotReady. ++func (acbw *acBalancerWrapper) Invoke(ctx context.Context, method string, args interface{}, reply interface{}, opts ...CallOption) error { ++ cs, err := acbw.NewStream(ctx, unaryStreamDesc, method, opts...) ++ if err != nil { ++ return err ++ } ++ if err := cs.SendMsg(args); err != nil { ++ return err ++ } ++ return cs.RecvMsg(reply) ++} ++ ++type refCountedProducer struct { ++ producer balancer.Producer ++ refs int // number of current refs to the producer ++ close func() // underlying producer's close function ++} ++ ++func (acbw *acBalancerWrapper) GetOrBuildProducer(pb balancer.ProducerBuilder) (balancer.Producer, func()) { ++ acbw.mu.Lock() ++ defer acbw.mu.Unlock() ++ ++ // Look up existing producer from this builder. ++ pData := acbw.producers[pb] ++ if pData == nil { ++ // Not found; create a new one and add it to the producers map. ++ p, close := pb.Build(acbw) ++ pData = &refCountedProducer{producer: p, close: close} ++ acbw.producers[pb] = pData ++ } ++ // Account for this new reference. ++ pData.refs++ ++ ++ // Return a cleanup function wrapped in a OnceFunc to remove this reference ++ // and delete the refCountedProducer from the map if the total reference ++ // count goes to zero. ++ unref := func() { ++ acbw.mu.Lock() ++ pData.refs-- ++ if pData.refs == 0 { ++ defer pData.close() // Run outside the acbw mutex ++ delete(acbw.producers, pb) ++ } ++ acbw.mu.Unlock() ++ } ++ return pData.producer, grpcsync.OnceFunc(unref) ++} +diff --git a/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go b/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go +index ed75290cdf34..66d141fce707 100644 +--- a/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go ++++ b/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go +@@ -18,14 +18,13 @@ + + // Code generated by protoc-gen-go. DO NOT EDIT. + // versions: +-// protoc-gen-go v1.25.0 ++// protoc-gen-go v1.28.1 + // protoc v3.14.0 + // source: grpc/binlog/v1/binarylog.proto + + package grpc_binarylog_v1 + + import ( +- proto "github.com/golang/protobuf/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + durationpb "google.golang.org/protobuf/types/known/durationpb" +@@ -41,10 +40,6 @@ const ( + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) + ) + +-// This is a compile-time assertion that a sufficiently up-to-date version +-// of the legacy proto package is being used. +-const _ = proto.ProtoPackageIsVersion4 +- + // Enumerates the type of event + // Note the terminology is different from the RPC semantics + // definition, but the same meaning is expressed here. +@@ -261,6 +256,7 @@ type GrpcLogEntry struct { + // according to the type of the log entry. + // + // Types that are assignable to Payload: ++ // + // *GrpcLogEntry_ClientHeader + // *GrpcLogEntry_ServerHeader + // *GrpcLogEntry_Message +@@ -694,12 +690,12 @@ func (x *Message) GetData() []byte { + // Header keys added by gRPC are omitted. To be more specific, + // implementations will not log the following entries, and this is + // not to be treated as a truncation: +-// - entries handled by grpc that are not user visible, such as those +-// that begin with 'grpc-' (with exception of grpc-trace-bin) +-// or keys like 'lb-token' +-// - transport specific entries, including but not limited to: +-// ':path', ':authority', 'content-encoding', 'user-agent', 'te', etc +-// - entries added for call credentials ++// - entries handled by grpc that are not user visible, such as those ++// that begin with 'grpc-' (with exception of grpc-trace-bin) ++// or keys like 'lb-token' ++// - transport specific entries, including but not limited to: ++// ':path', ':authority', 'content-encoding', 'user-agent', 'te', etc ++// - entries added for call credentials + // + // Implementations must always log grpc-trace-bin if it is present. + // Practically speaking it will only be visible on server side because +diff --git a/vendor/google.golang.org/grpc/channelz/channelz.go b/vendor/google.golang.org/grpc/channelz/channelz.go +index a220c47c59a5..32b7fa5794e1 100644 +--- a/vendor/google.golang.org/grpc/channelz/channelz.go ++++ b/vendor/google.golang.org/grpc/channelz/channelz.go +@@ -23,7 +23,7 @@ + // https://github.com/grpc/proposal/blob/master/A14-channelz.md, is provided by + // the `internal/channelz` package. + // +-// Experimental ++// # Experimental + // + // Notice: All APIs in this package are experimental and may be removed in a + // later release. +diff --git a/vendor/google.golang.org/grpc/clientconn.go b/vendor/google.golang.org/grpc/clientconn.go +index 779b03bca1c3..d607d4e9e243 100644 +--- a/vendor/google.golang.org/grpc/clientconn.go ++++ b/vendor/google.golang.org/grpc/clientconn.go +@@ -256,7 +256,7 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn * + if err != nil { + return nil, err + } +- cc.authority, err = determineAuthority(cc.parsedTarget.Endpoint, cc.target, cc.dopts) ++ cc.authority, err = determineAuthority(cc.parsedTarget.Endpoint(), cc.target, cc.dopts) + if err != nil { + return nil, err + } +@@ -503,7 +503,7 @@ type ClientConn struct { + // WaitForStateChange waits until the connectivity.State of ClientConn changes from sourceState or + // ctx expires. A true value is returned in former case and false in latter. + // +-// Experimental ++// # Experimental + // + // Notice: This API is EXPERIMENTAL and may be changed or removed in a + // later release. +@@ -522,7 +522,7 @@ func (cc *ClientConn) WaitForStateChange(ctx context.Context, sourceState connec + + // GetState returns the connectivity.State of ClientConn. + // +-// Experimental ++// # Experimental + // + // Notice: This API is EXPERIMENTAL and may be changed or removed in a later + // release. +@@ -534,7 +534,7 @@ func (cc *ClientConn) GetState() connectivity.State { + // the channel is idle. Does not wait for the connection attempts to begin + // before returning. + // +-// Experimental ++// # Experimental + // + // Notice: This API is EXPERIMENTAL and may be changed or removed in a later + // release. +@@ -761,7 +761,7 @@ func (cc *ClientConn) channelzMetric() *channelz.ChannelInternalMetric { + + // Target returns the target string of the ClientConn. + // +-// Experimental ++// # Experimental + // + // Notice: This API is EXPERIMENTAL and may be changed or removed in a + // later release. +@@ -788,10 +788,16 @@ func (cc *ClientConn) incrCallsFailed() { + func (ac *addrConn) connect() error { + ac.mu.Lock() + if ac.state == connectivity.Shutdown { ++ if logger.V(2) { ++ logger.Infof("connect called on shutdown addrConn; ignoring.") ++ } + ac.mu.Unlock() + return errConnClosing + } + if ac.state != connectivity.Idle { ++ if logger.V(2) { ++ logger.Infof("connect called on addrConn in non-idle state (%v); ignoring.", ac.state) ++ } + ac.mu.Unlock() + return nil + } +@@ -831,9 +837,9 @@ func equalAddresses(a, b []resolver.Address) bool { + // + // If ac is Ready, it checks whether current connected address of ac is in the + // new addrs list. +-// - If true, it updates ac.addrs and returns true. The ac will keep using +-// the existing connection. +-// - If false, it does nothing and returns false. ++// - If true, it updates ac.addrs and returns true. The ac will keep using ++// the existing connection. ++// - If false, it does nothing and returns false. + func (ac *addrConn) tryUpdateAddrs(addrs []resolver.Address) bool { + ac.mu.Lock() + defer ac.mu.Unlock() +@@ -928,7 +934,7 @@ func (cc *ClientConn) healthCheckConfig() *healthCheckConfig { + return cc.sc.healthCheckConfig + } + +-func (cc *ClientConn) getTransport(ctx context.Context, failfast bool, method string) (transport.ClientTransport, func(balancer.DoneInfo), error) { ++func (cc *ClientConn) getTransport(ctx context.Context, failfast bool, method string) (transport.ClientTransport, balancer.PickResult, error) { + return cc.blockingpicker.pick(ctx, failfast, balancer.PickInfo{ + Ctx: ctx, + FullMethodName: method, +@@ -998,7 +1004,7 @@ func (cc *ClientConn) resolveNow(o resolver.ResolveNowOptions) { + // However, if a previously unavailable network becomes available, this may be + // used to trigger an immediate reconnect. + // +-// Experimental ++// # Experimental + // + // Notice: This API is EXPERIMENTAL and may be changed or removed in a + // later release. +@@ -1228,111 +1234,79 @@ func (ac *addrConn) tryAllAddrs(addrs []resolver.Address, connectDeadline time.T + // address was not successfully connected, or updates ac appropriately with the + // new transport. + func (ac *addrConn) createTransport(addr resolver.Address, copts transport.ConnectOptions, connectDeadline time.Time) error { +- // TODO: Delete prefaceReceived and move the logic to wait for it into the +- // transport. +- prefaceReceived := grpcsync.NewEvent() +- connClosed := grpcsync.NewEvent() +- + addr.ServerName = ac.cc.getServerName(addr) + hctx, hcancel := context.WithCancel(ac.ctx) +- hcStarted := false // protected by ac.mu + +- onClose := func() { ++ onClose := func(r transport.GoAwayReason) { + ac.mu.Lock() + defer ac.mu.Unlock() +- defer connClosed.Fire() +- defer hcancel() +- if !hcStarted || hctx.Err() != nil { +- // We didn't start the health check or set the state to READY, so +- // no need to do anything else here. +- // +- // OR, we have already cancelled the health check context, meaning +- // we have already called onClose once for this transport. In this +- // case it would be dangerous to clear the transport and update the +- // state, since there may be a new transport in this addrConn. ++ // adjust params based on GoAwayReason ++ ac.adjustParams(r) ++ if ac.state == connectivity.Shutdown { ++ // Already shut down. tearDown() already cleared the transport and ++ // canceled hctx via ac.ctx, and we expected this connection to be ++ // closed, so do nothing here. ++ return ++ } ++ hcancel() ++ if ac.transport == nil { ++ // We're still connecting to this address, which could error. Do ++ // not update the connectivity state or resolve; these will happen ++ // at the end of the tryAllAddrs connection loop in the event of an ++ // error. + return + } + ac.transport = nil +- // Refresh the name resolver ++ // Refresh the name resolver on any connection loss. + ac.cc.resolveNow(resolver.ResolveNowOptions{}) +- if ac.state != connectivity.Shutdown { +- ac.updateConnectivityState(connectivity.Idle, nil) +- } +- } +- +- onGoAway := func(r transport.GoAwayReason) { +- ac.mu.Lock() +- ac.adjustParams(r) +- ac.mu.Unlock() +- onClose() ++ // Always go idle and wait for the LB policy to initiate a new ++ // connection attempt. ++ ac.updateConnectivityState(connectivity.Idle, nil) + } + + connectCtx, cancel := context.WithDeadline(ac.ctx, connectDeadline) + defer cancel() + copts.ChannelzParentID = ac.channelzID + +- newTr, err := transport.NewClientTransport(connectCtx, ac.cc.ctx, addr, copts, func() { prefaceReceived.Fire() }, onGoAway, onClose) ++ newTr, err := transport.NewClientTransport(connectCtx, ac.cc.ctx, addr, copts, onClose) + if err != nil { ++ if logger.V(2) { ++ logger.Infof("Creating new client transport to %q: %v", addr, err) ++ } + // newTr is either nil, or closed. + hcancel() + channelz.Warningf(logger, ac.channelzID, "grpc: addrConn.createTransport failed to connect to %s. Err: %v", addr, err) + return err + } + +- select { +- case <-connectCtx.Done(): +- // We didn't get the preface in time. ++ ac.mu.Lock() ++ defer ac.mu.Unlock() ++ if ac.state == connectivity.Shutdown { ++ // This can happen if the subConn was removed while in `Connecting` ++ // state. tearDown() would have set the state to `Shutdown`, but ++ // would not have closed the transport since ac.transport would not ++ // have been set at that point. ++ // ++ // We run this in a goroutine because newTr.Close() calls onClose() ++ // inline, which requires locking ac.mu. ++ // + // The error we pass to Close() is immaterial since there are no open + // streams at this point, so no trailers with error details will be sent + // out. We just need to pass a non-nil error. +- newTr.Close(transport.ErrConnClosing) +- if connectCtx.Err() == context.DeadlineExceeded { +- err := errors.New("failed to receive server preface within timeout") +- channelz.Warningf(logger, ac.channelzID, "grpc: addrConn.createTransport failed to connect to %s: %v", addr, err) +- return err +- } ++ go newTr.Close(transport.ErrConnClosing) + return nil +- case <-prefaceReceived.Done(): +- // We got the preface - huzzah! things are good. +- ac.mu.Lock() +- defer ac.mu.Unlock() +- if connClosed.HasFired() { +- // onClose called first; go idle but do nothing else. +- if ac.state != connectivity.Shutdown { +- ac.updateConnectivityState(connectivity.Idle, nil) +- } +- return nil +- } +- if ac.state == connectivity.Shutdown { +- // This can happen if the subConn was removed while in `Connecting` +- // state. tearDown() would have set the state to `Shutdown`, but +- // would not have closed the transport since ac.transport would not +- // been set at that point. +- // +- // We run this in a goroutine because newTr.Close() calls onClose() +- // inline, which requires locking ac.mu. +- // +- // The error we pass to Close() is immaterial since there are no open +- // streams at this point, so no trailers with error details will be sent +- // out. We just need to pass a non-nil error. +- go newTr.Close(transport.ErrConnClosing) +- return nil +- } +- ac.curAddr = addr +- ac.transport = newTr +- hcStarted = true +- ac.startHealthCheck(hctx) // Will set state to READY if appropriate. ++ } ++ if hctx.Err() != nil { ++ // onClose was already called for this connection, but the connection ++ // was successfully established first. Consider it a success and set ++ // the new state to Idle. ++ ac.updateConnectivityState(connectivity.Idle, nil) + return nil +- case <-connClosed.Done(): +- // The transport has already closed. If we received the preface, too, +- // this is not an error. +- select { +- case <-prefaceReceived.Done(): +- return nil +- default: +- return errors.New("connection closed before server preface received") +- } + } ++ ac.curAddr = addr ++ ac.transport = newTr ++ ac.startHealthCheck(hctx) // Will set state to READY if appropriate. ++ return nil + } + + // startHealthCheck starts the health checking stream (RPC) to watch the health +@@ -1402,7 +1376,7 @@ func (ac *addrConn) startHealthCheck(ctx context.Context) { + if status.Code(err) == codes.Unimplemented { + channelz.Error(logger, ac.channelzID, "Subchannel health check is unimplemented at server side, thus health check is disabled") + } else { +- channelz.Errorf(logger, ac.channelzID, "HealthCheckFunc exits with unexpected error %v", err) ++ channelz.Errorf(logger, ac.channelzID, "Health checking failed: %v", err) + } + } + }() +@@ -1583,7 +1557,7 @@ func (cc *ClientConn) parseTargetAndFindResolver() (resolver.Builder, error) { + channelz.Infof(logger, cc.channelzID, "dial target %q parse failed: %v", cc.target, err) + } else { + channelz.Infof(logger, cc.channelzID, "parsed dial target is: %+v", parsedTarget) +- rb = cc.getResolver(parsedTarget.Scheme) ++ rb = cc.getResolver(parsedTarget.URL.Scheme) + if rb != nil { + cc.parsedTarget = parsedTarget + return rb, nil +@@ -1604,39 +1578,26 @@ func (cc *ClientConn) parseTargetAndFindResolver() (resolver.Builder, error) { + return nil, err + } + channelz.Infof(logger, cc.channelzID, "parsed dial target is: %+v", parsedTarget) +- rb = cc.getResolver(parsedTarget.Scheme) ++ rb = cc.getResolver(parsedTarget.URL.Scheme) + if rb == nil { +- return nil, fmt.Errorf("could not get resolver for default scheme: %q", parsedTarget.Scheme) ++ return nil, fmt.Errorf("could not get resolver for default scheme: %q", parsedTarget.URL.Scheme) + } + cc.parsedTarget = parsedTarget + return rb, nil + } + + // parseTarget uses RFC 3986 semantics to parse the given target into a +-// resolver.Target struct containing scheme, authority and endpoint. Query ++// resolver.Target struct containing scheme, authority and url. Query + // params are stripped from the endpoint. + func parseTarget(target string) (resolver.Target, error) { + u, err := url.Parse(target) + if err != nil { + return resolver.Target{}, err + } +- // For targets of the form "[scheme]://[authority]/endpoint, the endpoint +- // value returned from url.Parse() contains a leading "/". Although this is +- // in accordance with RFC 3986, we do not want to break existing resolver +- // implementations which expect the endpoint without the leading "/". So, we +- // end up stripping the leading "/" here. But this will result in an +- // incorrect parsing for something like "unix:///path/to/socket". Since we +- // own the "unix" resolver, we can workaround in the unix resolver by using +- // the `URL` field instead of the `Endpoint` field. +- endpoint := u.Path +- if endpoint == "" { +- endpoint = u.Opaque +- } +- endpoint = strings.TrimPrefix(endpoint, "/") ++ + return resolver.Target{ + Scheme: u.Scheme, + Authority: u.Host, +- Endpoint: endpoint, + URL: *u, + }, nil + } +diff --git a/vendor/google.golang.org/grpc/credentials/credentials.go b/vendor/google.golang.org/grpc/credentials/credentials.go +index 96ff1877e754..5feac3aa0e41 100644 +--- a/vendor/google.golang.org/grpc/credentials/credentials.go ++++ b/vendor/google.golang.org/grpc/credentials/credentials.go +@@ -36,16 +36,16 @@ import ( + // PerRPCCredentials defines the common interface for the credentials which need to + // attach security information to every RPC (e.g., oauth2). + type PerRPCCredentials interface { +- // GetRequestMetadata gets the current request metadata, refreshing +- // tokens if required. This should be called by the transport layer on +- // each request, and the data should be populated in headers or other +- // context. If a status code is returned, it will be used as the status +- // for the RPC. uri is the URI of the entry point for the request. +- // When supported by the underlying implementation, ctx can be used for +- // timeout and cancellation. Additionally, RequestInfo data will be +- // available via ctx to this call. +- // TODO(zhaoq): Define the set of the qualified keys instead of leaving +- // it as an arbitrary string. ++ // GetRequestMetadata gets the current request metadata, refreshing tokens ++ // if required. This should be called by the transport layer on each ++ // request, and the data should be populated in headers or other ++ // context. If a status code is returned, it will be used as the status for ++ // the RPC (restricted to an allowable set of codes as defined by gRFC ++ // A54). uri is the URI of the entry point for the request. When supported ++ // by the underlying implementation, ctx can be used for timeout and ++ // cancellation. Additionally, RequestInfo data will be available via ctx ++ // to this call. TODO(zhaoq): Define the set of the qualified keys instead ++ // of leaving it as an arbitrary string. + GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) + // RequireTransportSecurity indicates whether the credentials requires + // transport security. +diff --git a/vendor/google.golang.org/grpc/credentials/tls.go b/vendor/google.golang.org/grpc/credentials/tls.go +index 784822d0560a..877b7cd21af7 100644 +--- a/vendor/google.golang.org/grpc/credentials/tls.go ++++ b/vendor/google.golang.org/grpc/credentials/tls.go +@@ -23,9 +23,9 @@ import ( + "crypto/tls" + "crypto/x509" + "fmt" +- "io/ioutil" + "net" + "net/url" ++ "os" + + credinternal "google.golang.org/grpc/internal/credentials" + ) +@@ -166,7 +166,7 @@ func NewClientTLSFromCert(cp *x509.CertPool, serverNameOverride string) Transpor + // it will override the virtual host name of authority (e.g. :authority header + // field) in requests. + func NewClientTLSFromFile(certFile, serverNameOverride string) (TransportCredentials, error) { +- b, err := ioutil.ReadFile(certFile) ++ b, err := os.ReadFile(certFile) + if err != nil { + return nil, err + } +@@ -195,7 +195,7 @@ func NewServerTLSFromFile(certFile, keyFile string) (TransportCredentials, error + // TLSChannelzSecurityValue defines the struct that TLS protocol should return + // from GetSecurityValue(), containing security info like cipher and certificate used. + // +-// Experimental ++// # Experimental + // + // Notice: This type is EXPERIMENTAL and may be changed or removed in a + // later release. +diff --git a/vendor/google.golang.org/grpc/dialoptions.go b/vendor/google.golang.org/grpc/dialoptions.go +index 9372dc322e80..4866da101c60 100644 +--- a/vendor/google.golang.org/grpc/dialoptions.go ++++ b/vendor/google.golang.org/grpc/dialoptions.go +@@ -44,6 +44,7 @@ func init() { + extraDialOptions = nil + } + internal.WithBinaryLogger = withBinaryLogger ++ internal.JoinDialOptions = newJoinDialOption + } + + // dialOptions configure a Dial call. dialOptions are set by the DialOption +@@ -111,13 +112,28 @@ func newFuncDialOption(f func(*dialOptions)) *funcDialOption { + } + } + ++type joinDialOption struct { ++ opts []DialOption ++} ++ ++func (jdo *joinDialOption) apply(do *dialOptions) { ++ for _, opt := range jdo.opts { ++ opt.apply(do) ++ } ++} ++ ++func newJoinDialOption(opts ...DialOption) DialOption { ++ return &joinDialOption{opts: opts} ++} ++ + // WithWriteBufferSize determines how much data can be batched before doing a + // write on the wire. The corresponding memory allocation for this buffer will + // be twice the size to keep syscalls low. The default value for this buffer is + // 32KB. + // +-// Zero will disable the write buffer such that each write will be on underlying +-// connection. Note: A Send call may not directly translate to a write. ++// Zero or negative values will disable the write buffer such that each write ++// will be on underlying connection. Note: A Send call may not directly ++// translate to a write. + func WithWriteBufferSize(s int) DialOption { + return newFuncDialOption(func(o *dialOptions) { + o.copts.WriteBufferSize = s +@@ -127,8 +143,9 @@ func WithWriteBufferSize(s int) DialOption { + // WithReadBufferSize lets you set the size of read buffer, this determines how + // much data can be read at most for each read syscall. + // +-// The default value for this buffer is 32KB. Zero will disable read buffer for +-// a connection so data framer can access the underlying conn directly. ++// The default value for this buffer is 32KB. Zero or negative values will ++// disable read buffer for a connection so data framer can access the ++// underlying conn directly. + func WithReadBufferSize(s int) DialOption { + return newFuncDialOption(func(o *dialOptions) { + o.copts.ReadBufferSize = s +diff --git a/vendor/google.golang.org/grpc/encoding/encoding.go b/vendor/google.golang.org/grpc/encoding/encoding.go +index 18e530fc9024..07a5861352a6 100644 +--- a/vendor/google.golang.org/grpc/encoding/encoding.go ++++ b/vendor/google.golang.org/grpc/encoding/encoding.go +@@ -19,7 +19,7 @@ + // Package encoding defines the interface for the compressor and codec, and + // functions to register and retrieve compressors and codecs. + // +-// Experimental ++// # Experimental + // + // Notice: This package is EXPERIMENTAL and may be changed or removed in a + // later release. +@@ -28,6 +28,8 @@ package encoding + import ( + "io" + "strings" ++ ++ "google.golang.org/grpc/internal/grpcutil" + ) + + // Identity specifies the optional encoding for uncompressed streams. +@@ -73,6 +75,9 @@ var registeredCompressor = make(map[string]Compressor) + // registered with the same name, the one registered last will take effect. + func RegisterCompressor(c Compressor) { + registeredCompressor[c.Name()] = c ++ if !grpcutil.IsCompressorNameRegistered(c.Name()) { ++ grpcutil.RegisteredCompressorNames = append(grpcutil.RegisteredCompressorNames, c.Name()) ++ } + } + + // GetCompressor returns Compressor for the given compressor name. +diff --git a/vendor/google.golang.org/grpc/grpclog/loggerv2.go b/vendor/google.golang.org/grpc/grpclog/loggerv2.go +index 7c1f66409034..5de66e40d365 100644 +--- a/vendor/google.golang.org/grpc/grpclog/loggerv2.go ++++ b/vendor/google.golang.org/grpc/grpclog/loggerv2.go +@@ -22,7 +22,6 @@ import ( + "encoding/json" + "fmt" + "io" +- "io/ioutil" + "log" + "os" + "strconv" +@@ -140,9 +139,9 @@ func newLoggerV2WithConfig(infoW, warningW, errorW io.Writer, c loggerV2Config) + // newLoggerV2 creates a loggerV2 to be used as default logger. + // All logs are written to stderr. + func newLoggerV2() LoggerV2 { +- errorW := ioutil.Discard +- warningW := ioutil.Discard +- infoW := ioutil.Discard ++ errorW := io.Discard ++ warningW := io.Discard ++ infoW := io.Discard + + logLevel := os.Getenv("GRPC_GO_LOG_SEVERITY_LEVEL") + switch logLevel { +@@ -242,7 +241,7 @@ func (g *loggerT) V(l int) bool { + // DepthLoggerV2, the below functions will be called with the appropriate stack + // depth set for trivial functions the logger may ignore. + // +-// Experimental ++// # Experimental + // + // Notice: This type is EXPERIMENTAL and may be changed or removed in a + // later release. +diff --git a/vendor/google.golang.org/grpc/internal/binarylog/env_config.go b/vendor/google.golang.org/grpc/internal/binarylog/env_config.go +index c5579e65065f..f9e80e27ab68 100644 +--- a/vendor/google.golang.org/grpc/internal/binarylog/env_config.go ++++ b/vendor/google.golang.org/grpc/internal/binarylog/env_config.go +@@ -30,15 +30,15 @@ import ( + // to build a new logger and assign it to binarylog.Logger. + // + // Example filter config strings: +-// - "" Nothing will be logged +-// - "*" All headers and messages will be fully logged. +-// - "*{h}" Only headers will be logged. +-// - "*{m:256}" Only the first 256 bytes of each message will be logged. +-// - "Foo/*" Logs every method in service Foo +-// - "Foo/*,-Foo/Bar" Logs every method in service Foo except method /Foo/Bar +-// - "Foo/*,Foo/Bar{m:256}" Logs the first 256 bytes of each message in method +-// /Foo/Bar, logs all headers and messages in every other method in service +-// Foo. ++// - "" Nothing will be logged ++// - "*" All headers and messages will be fully logged. ++// - "*{h}" Only headers will be logged. ++// - "*{m:256}" Only the first 256 bytes of each message will be logged. ++// - "Foo/*" Logs every method in service Foo ++// - "Foo/*,-Foo/Bar" Logs every method in service Foo except method /Foo/Bar ++// - "Foo/*,Foo/Bar{m:256}" Logs the first 256 bytes of each message in method ++// /Foo/Bar, logs all headers and messages in every other method in service ++// Foo. + // + // If two configs exist for one certain method or service, the one specified + // later overrides the previous config. +diff --git a/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go b/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go +index 179f4a26d135..d71e441778f4 100644 +--- a/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go ++++ b/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go +@@ -26,7 +26,7 @@ import ( + + "github.com/golang/protobuf/proto" + "github.com/golang/protobuf/ptypes" +- pb "google.golang.org/grpc/binarylog/grpc_binarylog_v1" ++ binlogpb "google.golang.org/grpc/binarylog/grpc_binarylog_v1" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" + ) +@@ -79,7 +79,7 @@ func NewTruncatingMethodLogger(h, m uint64) *TruncatingMethodLogger { + // Build is an internal only method for building the proto message out of the + // input event. It's made public to enable other library to reuse as much logic + // in TruncatingMethodLogger as possible. +-func (ml *TruncatingMethodLogger) Build(c LogEntryConfig) *pb.GrpcLogEntry { ++func (ml *TruncatingMethodLogger) Build(c LogEntryConfig) *binlogpb.GrpcLogEntry { + m := c.toProto() + timestamp, _ := ptypes.TimestampProto(time.Now()) + m.Timestamp = timestamp +@@ -87,11 +87,11 @@ func (ml *TruncatingMethodLogger) Build(c LogEntryConfig) *pb.GrpcLogEntry { + m.SequenceIdWithinCall = ml.idWithinCallGen.next() + + switch pay := m.Payload.(type) { +- case *pb.GrpcLogEntry_ClientHeader: ++ case *binlogpb.GrpcLogEntry_ClientHeader: + m.PayloadTruncated = ml.truncateMetadata(pay.ClientHeader.GetMetadata()) +- case *pb.GrpcLogEntry_ServerHeader: ++ case *binlogpb.GrpcLogEntry_ServerHeader: + m.PayloadTruncated = ml.truncateMetadata(pay.ServerHeader.GetMetadata()) +- case *pb.GrpcLogEntry_Message: ++ case *binlogpb.GrpcLogEntry_Message: + m.PayloadTruncated = ml.truncateMessage(pay.Message) + } + return m +@@ -102,7 +102,7 @@ func (ml *TruncatingMethodLogger) Log(c LogEntryConfig) { + ml.sink.Write(ml.Build(c)) + } + +-func (ml *TruncatingMethodLogger) truncateMetadata(mdPb *pb.Metadata) (truncated bool) { ++func (ml *TruncatingMethodLogger) truncateMetadata(mdPb *binlogpb.Metadata) (truncated bool) { + if ml.headerMaxLen == maxUInt { + return false + } +@@ -121,7 +121,7 @@ func (ml *TruncatingMethodLogger) truncateMetadata(mdPb *pb.Metadata) (truncated + // but not counted towards the size limit. + continue + } +- currentEntryLen := uint64(len(entry.Value)) ++ currentEntryLen := uint64(len(entry.GetKey())) + uint64(len(entry.GetValue())) + if currentEntryLen > bytesLimit { + break + } +@@ -132,7 +132,7 @@ func (ml *TruncatingMethodLogger) truncateMetadata(mdPb *pb.Metadata) (truncated + return truncated + } + +-func (ml *TruncatingMethodLogger) truncateMessage(msgPb *pb.Message) (truncated bool) { ++func (ml *TruncatingMethodLogger) truncateMessage(msgPb *binlogpb.Message) (truncated bool) { + if ml.messageMaxLen == maxUInt { + return false + } +@@ -145,7 +145,7 @@ func (ml *TruncatingMethodLogger) truncateMessage(msgPb *pb.Message) (truncated + + // LogEntryConfig represents the configuration for binary log entry. + type LogEntryConfig interface { +- toProto() *pb.GrpcLogEntry ++ toProto() *binlogpb.GrpcLogEntry + } + + // ClientHeader configs the binary log entry to be a ClientHeader entry. +@@ -159,10 +159,10 @@ type ClientHeader struct { + PeerAddr net.Addr + } + +-func (c *ClientHeader) toProto() *pb.GrpcLogEntry { ++func (c *ClientHeader) toProto() *binlogpb.GrpcLogEntry { + // This function doesn't need to set all the fields (e.g. seq ID). The Log + // function will set the fields when necessary. +- clientHeader := &pb.ClientHeader{ ++ clientHeader := &binlogpb.ClientHeader{ + Metadata: mdToMetadataProto(c.Header), + MethodName: c.MethodName, + Authority: c.Authority, +@@ -170,16 +170,16 @@ func (c *ClientHeader) toProto() *pb.GrpcLogEntry { + if c.Timeout > 0 { + clientHeader.Timeout = ptypes.DurationProto(c.Timeout) + } +- ret := &pb.GrpcLogEntry{ +- Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_HEADER, +- Payload: &pb.GrpcLogEntry_ClientHeader{ ++ ret := &binlogpb.GrpcLogEntry{ ++ Type: binlogpb.GrpcLogEntry_EVENT_TYPE_CLIENT_HEADER, ++ Payload: &binlogpb.GrpcLogEntry_ClientHeader{ + ClientHeader: clientHeader, + }, + } + if c.OnClientSide { +- ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT ++ ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT + } else { +- ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER ++ ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER + } + if c.PeerAddr != nil { + ret.Peer = addrToProto(c.PeerAddr) +@@ -195,19 +195,19 @@ type ServerHeader struct { + PeerAddr net.Addr + } + +-func (c *ServerHeader) toProto() *pb.GrpcLogEntry { +- ret := &pb.GrpcLogEntry{ +- Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_HEADER, +- Payload: &pb.GrpcLogEntry_ServerHeader{ +- ServerHeader: &pb.ServerHeader{ ++func (c *ServerHeader) toProto() *binlogpb.GrpcLogEntry { ++ ret := &binlogpb.GrpcLogEntry{ ++ Type: binlogpb.GrpcLogEntry_EVENT_TYPE_SERVER_HEADER, ++ Payload: &binlogpb.GrpcLogEntry_ServerHeader{ ++ ServerHeader: &binlogpb.ServerHeader{ + Metadata: mdToMetadataProto(c.Header), + }, + }, + } + if c.OnClientSide { +- ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT ++ ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT + } else { +- ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER ++ ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER + } + if c.PeerAddr != nil { + ret.Peer = addrToProto(c.PeerAddr) +@@ -223,7 +223,7 @@ type ClientMessage struct { + Message interface{} + } + +-func (c *ClientMessage) toProto() *pb.GrpcLogEntry { ++func (c *ClientMessage) toProto() *binlogpb.GrpcLogEntry { + var ( + data []byte + err error +@@ -238,19 +238,19 @@ func (c *ClientMessage) toProto() *pb.GrpcLogEntry { + } else { + grpclogLogger.Infof("binarylogging: message to log is neither proto.message nor []byte") + } +- ret := &pb.GrpcLogEntry{ +- Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_MESSAGE, +- Payload: &pb.GrpcLogEntry_Message{ +- Message: &pb.Message{ ++ ret := &binlogpb.GrpcLogEntry{ ++ Type: binlogpb.GrpcLogEntry_EVENT_TYPE_CLIENT_MESSAGE, ++ Payload: &binlogpb.GrpcLogEntry_Message{ ++ Message: &binlogpb.Message{ + Length: uint32(len(data)), + Data: data, + }, + }, + } + if c.OnClientSide { +- ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT ++ ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT + } else { +- ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER ++ ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER + } + return ret + } +@@ -263,7 +263,7 @@ type ServerMessage struct { + Message interface{} + } + +-func (c *ServerMessage) toProto() *pb.GrpcLogEntry { ++func (c *ServerMessage) toProto() *binlogpb.GrpcLogEntry { + var ( + data []byte + err error +@@ -278,19 +278,19 @@ func (c *ServerMessage) toProto() *pb.GrpcLogEntry { + } else { + grpclogLogger.Infof("binarylogging: message to log is neither proto.message nor []byte") + } +- ret := &pb.GrpcLogEntry{ +- Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_MESSAGE, +- Payload: &pb.GrpcLogEntry_Message{ +- Message: &pb.Message{ ++ ret := &binlogpb.GrpcLogEntry{ ++ Type: binlogpb.GrpcLogEntry_EVENT_TYPE_SERVER_MESSAGE, ++ Payload: &binlogpb.GrpcLogEntry_Message{ ++ Message: &binlogpb.Message{ + Length: uint32(len(data)), + Data: data, + }, + }, + } + if c.OnClientSide { +- ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT ++ ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT + } else { +- ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER ++ ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER + } + return ret + } +@@ -300,15 +300,15 @@ type ClientHalfClose struct { + OnClientSide bool + } + +-func (c *ClientHalfClose) toProto() *pb.GrpcLogEntry { +- ret := &pb.GrpcLogEntry{ +- Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_HALF_CLOSE, ++func (c *ClientHalfClose) toProto() *binlogpb.GrpcLogEntry { ++ ret := &binlogpb.GrpcLogEntry{ ++ Type: binlogpb.GrpcLogEntry_EVENT_TYPE_CLIENT_HALF_CLOSE, + Payload: nil, // No payload here. + } + if c.OnClientSide { +- ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT ++ ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT + } else { +- ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER ++ ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER + } + return ret + } +@@ -324,7 +324,7 @@ type ServerTrailer struct { + PeerAddr net.Addr + } + +-func (c *ServerTrailer) toProto() *pb.GrpcLogEntry { ++func (c *ServerTrailer) toProto() *binlogpb.GrpcLogEntry { + st, ok := status.FromError(c.Err) + if !ok { + grpclogLogger.Info("binarylogging: error in trailer is not a status error") +@@ -340,10 +340,10 @@ func (c *ServerTrailer) toProto() *pb.GrpcLogEntry { + grpclogLogger.Infof("binarylogging: failed to marshal status proto: %v", err) + } + } +- ret := &pb.GrpcLogEntry{ +- Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_TRAILER, +- Payload: &pb.GrpcLogEntry_Trailer{ +- Trailer: &pb.Trailer{ ++ ret := &binlogpb.GrpcLogEntry{ ++ Type: binlogpb.GrpcLogEntry_EVENT_TYPE_SERVER_TRAILER, ++ Payload: &binlogpb.GrpcLogEntry_Trailer{ ++ Trailer: &binlogpb.Trailer{ + Metadata: mdToMetadataProto(c.Trailer), + StatusCode: uint32(st.Code()), + StatusMessage: st.Message(), +@@ -352,9 +352,9 @@ func (c *ServerTrailer) toProto() *pb.GrpcLogEntry { + }, + } + if c.OnClientSide { +- ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT ++ ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT + } else { +- ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER ++ ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER + } + if c.PeerAddr != nil { + ret.Peer = addrToProto(c.PeerAddr) +@@ -367,15 +367,15 @@ type Cancel struct { + OnClientSide bool + } + +-func (c *Cancel) toProto() *pb.GrpcLogEntry { +- ret := &pb.GrpcLogEntry{ +- Type: pb.GrpcLogEntry_EVENT_TYPE_CANCEL, ++func (c *Cancel) toProto() *binlogpb.GrpcLogEntry { ++ ret := &binlogpb.GrpcLogEntry{ ++ Type: binlogpb.GrpcLogEntry_EVENT_TYPE_CANCEL, + Payload: nil, + } + if c.OnClientSide { +- ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT ++ ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT + } else { +- ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER ++ ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER + } + return ret + } +@@ -392,15 +392,15 @@ func metadataKeyOmit(key string) bool { + return strings.HasPrefix(key, "grpc-") + } + +-func mdToMetadataProto(md metadata.MD) *pb.Metadata { +- ret := &pb.Metadata{} ++func mdToMetadataProto(md metadata.MD) *binlogpb.Metadata { ++ ret := &binlogpb.Metadata{} + for k, vv := range md { + if metadataKeyOmit(k) { + continue + } + for _, v := range vv { + ret.Entry = append(ret.Entry, +- &pb.MetadataEntry{ ++ &binlogpb.MetadataEntry{ + Key: k, + Value: []byte(v), + }, +@@ -410,26 +410,26 @@ func mdToMetadataProto(md metadata.MD) *pb.Metadata { + return ret + } + +-func addrToProto(addr net.Addr) *pb.Address { +- ret := &pb.Address{} ++func addrToProto(addr net.Addr) *binlogpb.Address { ++ ret := &binlogpb.Address{} + switch a := addr.(type) { + case *net.TCPAddr: + if a.IP.To4() != nil { +- ret.Type = pb.Address_TYPE_IPV4 ++ ret.Type = binlogpb.Address_TYPE_IPV4 + } else if a.IP.To16() != nil { +- ret.Type = pb.Address_TYPE_IPV6 ++ ret.Type = binlogpb.Address_TYPE_IPV6 + } else { +- ret.Type = pb.Address_TYPE_UNKNOWN ++ ret.Type = binlogpb.Address_TYPE_UNKNOWN + // Do not set address and port fields. + break + } + ret.Address = a.IP.String() + ret.IpPort = uint32(a.Port) + case *net.UnixAddr: +- ret.Type = pb.Address_TYPE_UNIX ++ ret.Type = binlogpb.Address_TYPE_UNIX + ret.Address = a.String() + default: +- ret.Type = pb.Address_TYPE_UNKNOWN ++ ret.Type = binlogpb.Address_TYPE_UNKNOWN + } + return ret + } +diff --git a/vendor/google.golang.org/grpc/internal/binarylog/sink.go b/vendor/google.golang.org/grpc/internal/binarylog/sink.go +index c2fdd58b3198..264de387c2a5 100644 +--- a/vendor/google.golang.org/grpc/internal/binarylog/sink.go ++++ b/vendor/google.golang.org/grpc/internal/binarylog/sink.go +@@ -26,7 +26,7 @@ import ( + "time" + + "github.com/golang/protobuf/proto" +- pb "google.golang.org/grpc/binarylog/grpc_binarylog_v1" ++ binlogpb "google.golang.org/grpc/binarylog/grpc_binarylog_v1" + ) + + var ( +@@ -42,15 +42,15 @@ type Sink interface { + // Write will be called to write the log entry into the sink. + // + // It should be thread-safe so it can be called in parallel. +- Write(*pb.GrpcLogEntry) error ++ Write(*binlogpb.GrpcLogEntry) error + // Close will be called when the Sink is replaced by a new Sink. + Close() error + } + + type noopSink struct{} + +-func (ns *noopSink) Write(*pb.GrpcLogEntry) error { return nil } +-func (ns *noopSink) Close() error { return nil } ++func (ns *noopSink) Write(*binlogpb.GrpcLogEntry) error { return nil } ++func (ns *noopSink) Close() error { return nil } + + // newWriterSink creates a binary log sink with the given writer. + // +@@ -66,7 +66,7 @@ type writerSink struct { + out io.Writer + } + +-func (ws *writerSink) Write(e *pb.GrpcLogEntry) error { ++func (ws *writerSink) Write(e *binlogpb.GrpcLogEntry) error { + b, err := proto.Marshal(e) + if err != nil { + grpclogLogger.Errorf("binary logging: failed to marshal proto message: %v", err) +@@ -96,7 +96,7 @@ type bufferedSink struct { + done chan struct{} + } + +-func (fs *bufferedSink) Write(e *pb.GrpcLogEntry) error { ++func (fs *bufferedSink) Write(e *binlogpb.GrpcLogEntry) error { + fs.mu.Lock() + defer fs.mu.Unlock() + if !fs.flusherStarted { +diff --git a/vendor/google.golang.org/grpc/internal/channelz/types.go b/vendor/google.golang.org/grpc/internal/channelz/types.go +index ad0ce4dabf06..7b2f350e2e64 100644 +--- a/vendor/google.golang.org/grpc/internal/channelz/types.go ++++ b/vendor/google.golang.org/grpc/internal/channelz/types.go +@@ -273,10 +273,10 @@ func (c *channel) deleteSelfFromMap() (delete bool) { + + // deleteSelfIfReady tries to delete the channel itself from the channelz database. + // The delete process includes two steps: +-// 1. delete the channel from the entry relation tree, i.e. delete the channel reference from its +-// parent's child list. +-// 2. delete the channel from the map, i.e. delete the channel entirely from channelz. Lookup by id +-// will return entry not found error. ++// 1. delete the channel from the entry relation tree, i.e. delete the channel reference from its ++// parent's child list. ++// 2. delete the channel from the map, i.e. delete the channel entirely from channelz. Lookup by id ++// will return entry not found error. + func (c *channel) deleteSelfIfReady() { + if !c.deleteSelfFromTree() { + return +@@ -381,10 +381,10 @@ func (sc *subChannel) deleteSelfFromMap() (delete bool) { + + // deleteSelfIfReady tries to delete the subchannel itself from the channelz database. + // The delete process includes two steps: +-// 1. delete the subchannel from the entry relation tree, i.e. delete the subchannel reference from +-// its parent's child list. +-// 2. delete the subchannel from the map, i.e. delete the subchannel entirely from channelz. Lookup +-// by id will return entry not found error. ++// 1. delete the subchannel from the entry relation tree, i.e. delete the subchannel reference from ++// its parent's child list. ++// 2. delete the subchannel from the map, i.e. delete the subchannel entirely from channelz. Lookup ++// by id will return entry not found error. + func (sc *subChannel) deleteSelfIfReady() { + if !sc.deleteSelfFromTree() { + return +diff --git a/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go b/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go +index 6f0272543110..5ba9d94d49c2 100644 +--- a/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go ++++ b/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go +@@ -21,15 +21,42 @@ package envconfig + + import ( + "os" ++ "strconv" + "strings" + ) + +-const ( +- prefix = "GRPC_GO_" +- txtErrIgnoreStr = prefix + "IGNORE_TXT_ERRORS" +-) +- + var ( + // TXTErrIgnore is set if TXT errors should be ignored ("GRPC_GO_IGNORE_TXT_ERRORS" is not "false"). +- TXTErrIgnore = !strings.EqualFold(os.Getenv(txtErrIgnoreStr), "false") ++ TXTErrIgnore = boolFromEnv("GRPC_GO_IGNORE_TXT_ERRORS", true) ++ // AdvertiseCompressors is set if registered compressor should be advertised ++ // ("GRPC_GO_ADVERTISE_COMPRESSORS" is not "false"). ++ AdvertiseCompressors = boolFromEnv("GRPC_GO_ADVERTISE_COMPRESSORS", true) ++ // RingHashCap indicates the maximum ring size which defaults to 4096 ++ // entries but may be overridden by setting the environment variable ++ // "GRPC_RING_HASH_CAP". This does not override the default bounds ++ // checking which NACKs configs specifying ring sizes > 8*1024*1024 (~8M). ++ RingHashCap = uint64FromEnv("GRPC_RING_HASH_CAP", 4096, 1, 8*1024*1024) + ) ++ ++func boolFromEnv(envVar string, def bool) bool { ++ if def { ++ // The default is true; return true unless the variable is "false". ++ return !strings.EqualFold(os.Getenv(envVar), "false") ++ } ++ // The default is false; return false unless the variable is "true". ++ return strings.EqualFold(os.Getenv(envVar), "true") ++} ++ ++func uint64FromEnv(envVar string, def, min, max uint64) uint64 { ++ v, err := strconv.ParseUint(os.Getenv(envVar), 10, 64) ++ if err != nil { ++ return def ++ } ++ if v < min { ++ return min ++ } ++ if v > max { ++ return max ++ } ++ return v ++} +diff --git a/vendor/google.golang.org/grpc/internal/envconfig/xds.go b/vendor/google.golang.org/grpc/internal/envconfig/xds.go +index af09711a3e88..04136882c7bc 100644 +--- a/vendor/google.golang.org/grpc/internal/envconfig/xds.go ++++ b/vendor/google.golang.org/grpc/internal/envconfig/xds.go +@@ -20,7 +20,6 @@ package envconfig + + import ( + "os" +- "strings" + ) + + const ( +@@ -36,16 +35,6 @@ const ( + // + // When both bootstrap FileName and FileContent are set, FileName is used. + XDSBootstrapFileContentEnv = "GRPC_XDS_BOOTSTRAP_CONFIG" +- +- ringHashSupportEnv = "GRPC_XDS_EXPERIMENTAL_ENABLE_RING_HASH" +- clientSideSecuritySupportEnv = "GRPC_XDS_EXPERIMENTAL_SECURITY_SUPPORT" +- aggregateAndDNSSupportEnv = "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER" +- rbacSupportEnv = "GRPC_XDS_EXPERIMENTAL_RBAC" +- outlierDetectionSupportEnv = "GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION" +- federationEnv = "GRPC_EXPERIMENTAL_XDS_FEDERATION" +- rlsInXDSEnv = "GRPC_EXPERIMENTAL_XDS_RLS_LB" +- +- c2pResolverTestOnlyTrafficDirectorURIEnv = "GRPC_TEST_ONLY_GOOGLE_C2P_RESOLVER_TRAFFIC_DIRECTOR_URI" + ) + + var ( +@@ -64,38 +53,40 @@ var ( + // XDSRingHash indicates whether ring hash support is enabled, which can be + // disabled by setting the environment variable + // "GRPC_XDS_EXPERIMENTAL_ENABLE_RING_HASH" to "false". +- XDSRingHash = !strings.EqualFold(os.Getenv(ringHashSupportEnv), "false") ++ XDSRingHash = boolFromEnv("GRPC_XDS_EXPERIMENTAL_ENABLE_RING_HASH", true) + // XDSClientSideSecurity is used to control processing of security + // configuration on the client-side. + // + // Note that there is no env var protection for the server-side because we + // have a brand new API on the server-side and users explicitly need to use + // the new API to get security integration on the server. +- XDSClientSideSecurity = !strings.EqualFold(os.Getenv(clientSideSecuritySupportEnv), "false") ++ XDSClientSideSecurity = boolFromEnv("GRPC_XDS_EXPERIMENTAL_SECURITY_SUPPORT", true) + // XDSAggregateAndDNS indicates whether processing of aggregated cluster + // and DNS cluster is enabled, which can be enabled by setting the + // environment variable + // "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER" to + // "true". +- XDSAggregateAndDNS = !strings.EqualFold(os.Getenv(aggregateAndDNSSupportEnv), "false") ++ XDSAggregateAndDNS = boolFromEnv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER", true) + + // XDSRBAC indicates whether xDS configured RBAC HTTP Filter is enabled, + // which can be disabled by setting the environment variable + // "GRPC_XDS_EXPERIMENTAL_RBAC" to "false". +- XDSRBAC = !strings.EqualFold(os.Getenv(rbacSupportEnv), "false") ++ XDSRBAC = boolFromEnv("GRPC_XDS_EXPERIMENTAL_RBAC", true) + // XDSOutlierDetection indicates whether outlier detection support is + // enabled, which can be disabled by setting the environment variable + // "GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION" to "false". +- XDSOutlierDetection = !strings.EqualFold(os.Getenv(outlierDetectionSupportEnv), "false") +- // XDSFederation indicates whether federation support is enabled. +- XDSFederation = strings.EqualFold(os.Getenv(federationEnv), "true") ++ XDSOutlierDetection = boolFromEnv("GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION", true) ++ // XDSFederation indicates whether federation support is enabled, which can ++ // be enabled by setting the environment variable ++ // "GRPC_EXPERIMENTAL_XDS_FEDERATION" to "true". ++ XDSFederation = boolFromEnv("GRPC_EXPERIMENTAL_XDS_FEDERATION", false) + + // XDSRLS indicates whether processing of Cluster Specifier plugins and + // support for the RLS CLuster Specifier is enabled, which can be enabled by + // setting the environment variable "GRPC_EXPERIMENTAL_XDS_RLS_LB" to + // "true". +- XDSRLS = strings.EqualFold(os.Getenv(rlsInXDSEnv), "true") ++ XDSRLS = boolFromEnv("GRPC_EXPERIMENTAL_XDS_RLS_LB", false) + + // C2PResolverTestOnlyTrafficDirectorURI is the TD URI for testing. +- C2PResolverTestOnlyTrafficDirectorURI = os.Getenv(c2pResolverTestOnlyTrafficDirectorURIEnv) ++ C2PResolverTestOnlyTrafficDirectorURI = os.Getenv("GRPC_TEST_ONLY_GOOGLE_C2P_RESOLVER_TRAFFIC_DIRECTOR_URI") + ) +diff --git a/vendor/google.golang.org/grpc/internal/grpclog/grpclog.go b/vendor/google.golang.org/grpc/internal/grpclog/grpclog.go +index 30a3b4258fc0..b68e26a36493 100644 +--- a/vendor/google.golang.org/grpc/internal/grpclog/grpclog.go ++++ b/vendor/google.golang.org/grpc/internal/grpclog/grpclog.go +@@ -110,7 +110,7 @@ type LoggerV2 interface { + // This is a copy of the DepthLoggerV2 defined in the external grpclog package. + // It is defined here to avoid a circular dependency. + // +-// Experimental ++// # Experimental + // + // Notice: This type is EXPERIMENTAL and may be changed or removed in a + // later release. +diff --git a/vendor/google.golang.org/grpc/internal/grpcsync/oncefunc.go b/vendor/google.golang.org/grpc/internal/grpcsync/oncefunc.go +new file mode 100644 +index 000000000000..6635f7bca96d +--- /dev/null ++++ b/vendor/google.golang.org/grpc/internal/grpcsync/oncefunc.go +@@ -0,0 +1,32 @@ ++/* ++ * ++ * Copyright 2022 gRPC authors. ++ * ++ * 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 grpcsync ++ ++import ( ++ "sync" ++) ++ ++// OnceFunc returns a function wrapping f which ensures f is only executed ++// once even if the returned function is executed multiple times. ++func OnceFunc(f func()) func() { ++ var once sync.Once ++ return func() { ++ once.Do(f) ++ } ++} +diff --git a/vendor/google.golang.org/grpc/internal/grpcutil/compressor.go b/vendor/google.golang.org/grpc/internal/grpcutil/compressor.go +new file mode 100644 +index 000000000000..9f4090967980 +--- /dev/null ++++ b/vendor/google.golang.org/grpc/internal/grpcutil/compressor.go +@@ -0,0 +1,47 @@ ++/* ++ * ++ * Copyright 2022 gRPC authors. ++ * ++ * 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 grpcutil ++ ++import ( ++ "strings" ++ ++ "google.golang.org/grpc/internal/envconfig" ++) ++ ++// RegisteredCompressorNames holds names of the registered compressors. ++var RegisteredCompressorNames []string ++ ++// IsCompressorNameRegistered returns true when name is available in registry. ++func IsCompressorNameRegistered(name string) bool { ++ for _, compressor := range RegisteredCompressorNames { ++ if compressor == name { ++ return true ++ } ++ } ++ return false ++} ++ ++// RegisteredCompressors returns a string of registered compressor names ++// separated by comma. ++func RegisteredCompressors() string { ++ if !envconfig.AdvertiseCompressors { ++ return "" ++ } ++ return strings.Join(RegisteredCompressorNames, ",") ++} +diff --git a/vendor/google.golang.org/grpc/internal/grpcutil/method.go b/vendor/google.golang.org/grpc/internal/grpcutil/method.go +index e9c4af64830c..ec62b4775e5b 100644 +--- a/vendor/google.golang.org/grpc/internal/grpcutil/method.go ++++ b/vendor/google.golang.org/grpc/internal/grpcutil/method.go +@@ -25,7 +25,6 @@ import ( + + // ParseMethod splits service and method from the input. It expects format + // "/service/method". +-// + func ParseMethod(methodName string) (service, method string, _ error) { + if !strings.HasPrefix(methodName, "/") { + return "", "", errors.New("invalid method name: should start with /") +diff --git a/vendor/google.golang.org/grpc/internal/internal.go b/vendor/google.golang.org/grpc/internal/internal.go +index fd0ee3dcaf1e..0a76d9de6e02 100644 +--- a/vendor/google.golang.org/grpc/internal/internal.go ++++ b/vendor/google.golang.org/grpc/internal/internal.go +@@ -77,6 +77,9 @@ var ( + // ClearGlobalDialOptions clears the array of extra DialOption. This + // method is useful in testing and benchmarking. + ClearGlobalDialOptions func() ++ // JoinDialOptions combines the dial options passed as arguments into a ++ // single dial option. ++ JoinDialOptions interface{} // func(...grpc.DialOption) grpc.DialOption + // JoinServerOptions combines the server options passed as arguments into a + // single server option. + JoinServerOptions interface{} // func(...grpc.ServerOption) grpc.ServerOption +diff --git a/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go b/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go +index 75301c514913..09a667f33cb0 100644 +--- a/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go ++++ b/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go +@@ -116,7 +116,7 @@ type dnsBuilder struct{} + + // Build creates and starts a DNS resolver that watches the name resolution of the target. + func (b *dnsBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) { +- host, port, err := parseTarget(target.Endpoint, defaultPort) ++ host, port, err := parseTarget(target.Endpoint(), defaultPort) + if err != nil { + return nil, err + } +@@ -140,10 +140,10 @@ func (b *dnsBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts + disableServiceConfig: opts.DisableServiceConfig, + } + +- if target.Authority == "" { ++ if target.URL.Host == "" { + d.resolver = defaultResolver + } else { +- d.resolver, err = customAuthorityResolver(target.Authority) ++ d.resolver, err = customAuthorityResolver(target.URL.Host) + if err != nil { + return nil, err + } +diff --git a/vendor/google.golang.org/grpc/internal/resolver/passthrough/passthrough.go b/vendor/google.golang.org/grpc/internal/resolver/passthrough/passthrough.go +index 520d9229e1ed..afac56572ad5 100644 +--- a/vendor/google.golang.org/grpc/internal/resolver/passthrough/passthrough.go ++++ b/vendor/google.golang.org/grpc/internal/resolver/passthrough/passthrough.go +@@ -20,13 +20,20 @@ + // name without scheme back to gRPC as resolved address. + package passthrough + +-import "google.golang.org/grpc/resolver" ++import ( ++ "errors" ++ ++ "google.golang.org/grpc/resolver" ++) + + const scheme = "passthrough" + + type passthroughBuilder struct{} + + func (*passthroughBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) { ++ if target.Endpoint() == "" && opts.Dialer == nil { ++ return nil, errors.New("passthrough: received empty target in Build()") ++ } + r := &passthroughResolver{ + target: target, + cc: cc, +@@ -45,7 +52,7 @@ type passthroughResolver struct { + } + + func (r *passthroughResolver) start() { +- r.cc.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: r.target.Endpoint}}}) ++ r.cc.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: r.target.Endpoint()}}}) + } + + func (*passthroughResolver) ResolveNow(o resolver.ResolveNowOptions) {} +diff --git a/vendor/google.golang.org/grpc/internal/resolver/unix/unix.go b/vendor/google.golang.org/grpc/internal/resolver/unix/unix.go +index 7f1a702cacbe..160911687738 100644 +--- a/vendor/google.golang.org/grpc/internal/resolver/unix/unix.go ++++ b/vendor/google.golang.org/grpc/internal/resolver/unix/unix.go +@@ -34,8 +34,8 @@ type builder struct { + } + + func (b *builder) Build(target resolver.Target, cc resolver.ClientConn, _ resolver.BuildOptions) (resolver.Resolver, error) { +- if target.Authority != "" { +- return nil, fmt.Errorf("invalid (non-empty) authority: %v", target.Authority) ++ if target.URL.Host != "" { ++ return nil, fmt.Errorf("invalid (non-empty) authority: %v", target.URL.Host) + } + + // gRPC was parsing the dial target manually before PR #4817, and we +diff --git a/vendor/google.golang.org/grpc/internal/serviceconfig/serviceconfig.go b/vendor/google.golang.org/grpc/internal/serviceconfig/serviceconfig.go +index badbdbf597f3..51e733e495a3 100644 +--- a/vendor/google.golang.org/grpc/internal/serviceconfig/serviceconfig.go ++++ b/vendor/google.golang.org/grpc/internal/serviceconfig/serviceconfig.go +@@ -67,10 +67,10 @@ func (bc *BalancerConfig) MarshalJSON() ([]byte, error) { + // ServiceConfig contains a list of loadBalancingConfigs, each with a name and + // config. This method iterates through that list in order, and stops at the + // first policy that is supported. +-// - If the config for the first supported policy is invalid, the whole service +-// config is invalid. +-// - If the list doesn't contain any supported policy, the whole service config +-// is invalid. ++// - If the config for the first supported policy is invalid, the whole service ++// config is invalid. ++// - If the list doesn't contain any supported policy, the whole service config ++// is invalid. + func (bc *BalancerConfig) UnmarshalJSON(b []byte) error { + var ir intermediateBalancerConfig + err := json.Unmarshal(b, &ir) +diff --git a/vendor/google.golang.org/grpc/internal/status/status.go b/vendor/google.golang.org/grpc/internal/status/status.go +index e5c6513edd13..b0ead4f54f82 100644 +--- a/vendor/google.golang.org/grpc/internal/status/status.go ++++ b/vendor/google.golang.org/grpc/internal/status/status.go +@@ -164,3 +164,13 @@ func (e *Error) Is(target error) bool { + } + return proto.Equal(e.s.s, tse.s.s) + } ++ ++// IsRestrictedControlPlaneCode returns whether the status includes a code ++// restricted for control plane usage as defined by gRFC A54. ++func IsRestrictedControlPlaneCode(s *Status) bool { ++ switch s.Code() { ++ case codes.InvalidArgument, codes.NotFound, codes.AlreadyExists, codes.FailedPrecondition, codes.Aborted, codes.OutOfRange, codes.DataLoss: ++ return true ++ } ++ return false ++} +diff --git a/vendor/google.golang.org/grpc/internal/transport/controlbuf.go b/vendor/google.golang.org/grpc/internal/transport/controlbuf.go +index 409769f48fdc..9097385e1a6a 100644 +--- a/vendor/google.golang.org/grpc/internal/transport/controlbuf.go ++++ b/vendor/google.golang.org/grpc/internal/transport/controlbuf.go +@@ -191,7 +191,7 @@ type goAway struct { + code http2.ErrCode + debugData []byte + headsUp bool +- closeConn bool ++ closeConn error // if set, loopyWriter will exit, resulting in conn closure + } + + func (*goAway) isTransportResponseFrame() bool { return false } +@@ -209,6 +209,14 @@ type outFlowControlSizeRequest struct { + + func (*outFlowControlSizeRequest) isTransportResponseFrame() bool { return false } + ++// closeConnection is an instruction to tell the loopy writer to flush the ++// framer and exit, which will cause the transport's connection to be closed ++// (by the client or server). The transport itself will close after the reader ++// encounters the EOF caused by the connection closure. ++type closeConnection struct{} ++ ++func (closeConnection) isTransportResponseFrame() bool { return false } ++ + type outStreamState int + + const ( +@@ -408,7 +416,7 @@ func (c *controlBuffer) get(block bool) (interface{}, error) { + select { + case <-c.ch: + case <-c.done: +- return nil, ErrConnClosing ++ return nil, errors.New("transport closed by client") + } + } + } +@@ -519,18 +527,9 @@ const minBatchSize = 1000 + // As an optimization, to increase the batch size for each flush, loopy yields the processor, once + // if the batch size is too low to give stream goroutines a chance to fill it up. + func (l *loopyWriter) run() (err error) { +- defer func() { +- if err == ErrConnClosing { +- // Don't log ErrConnClosing as error since it happens +- // 1. When the connection is closed by some other known issue. +- // 2. User closed the connection. +- // 3. A graceful close of connection. +- if logger.V(logLevel) { +- logger.Infof("transport: loopyWriter.run returning. %v", err) +- } +- err = nil +- } +- }() ++ // Always flush the writer before exiting in case there are pending frames ++ // to be sent. ++ defer l.framer.writer.Flush() + for { + it, err := l.cbuf.get(true) + if err != nil { +@@ -574,7 +573,6 @@ func (l *loopyWriter) run() (err error) { + } + l.framer.writer.Flush() + break hasdata +- + } + } + } +@@ -655,19 +653,20 @@ func (l *loopyWriter) headerHandler(h *headerFrame) error { + itl: &itemList{}, + wq: h.wq, + } +- str.itl.enqueue(h) +- return l.originateStream(str) ++ return l.originateStream(str, h) + } + +-func (l *loopyWriter) originateStream(str *outStream) error { +- hdr := str.itl.dequeue().(*headerFrame) +- if err := hdr.initStream(str.id); err != nil { +- if err == ErrConnClosing { +- return err +- } +- // Other errors(errStreamDrain) need not close transport. ++func (l *loopyWriter) originateStream(str *outStream, hdr *headerFrame) error { ++ // l.draining is set when handling GoAway. In which case, we want to avoid ++ // creating new streams. ++ if l.draining { ++ // TODO: provide a better error with the reason we are in draining. ++ hdr.onOrphaned(errStreamDrain) + return nil + } ++ if err := hdr.initStream(str.id); err != nil { ++ return err ++ } + if err := l.writeHeader(str.id, hdr.endStream, hdr.hf, hdr.onWrite); err != nil { + return err + } +@@ -763,8 +762,8 @@ func (l *loopyWriter) cleanupStreamHandler(c *cleanupStream) error { + return err + } + } +- if l.side == clientSide && l.draining && len(l.estdStreams) == 0 { +- return ErrConnClosing ++ if l.draining && len(l.estdStreams) == 0 { ++ return errors.New("finished processing active streams while in draining mode") + } + return nil + } +@@ -799,7 +798,7 @@ func (l *loopyWriter) incomingGoAwayHandler(*incomingGoAway) error { + if l.side == clientSide { + l.draining = true + if len(l.estdStreams) == 0 { +- return ErrConnClosing ++ return errors.New("received GOAWAY with no active streams") + } + } + return nil +@@ -817,6 +816,13 @@ func (l *loopyWriter) goAwayHandler(g *goAway) error { + return nil + } + ++func (l *loopyWriter) closeConnectionHandler() error { ++ // Exit loopyWriter entirely by returning an error here. This will lead to ++ // the transport closing the connection, and, ultimately, transport ++ // closure. ++ return ErrConnClosing ++} ++ + func (l *loopyWriter) handle(i interface{}) error { + switch i := i.(type) { + case *incomingWindowUpdate: +@@ -845,6 +851,8 @@ func (l *loopyWriter) handle(i interface{}) error { + return l.goAwayHandler(i) + case *outFlowControlSizeRequest: + return l.outFlowControlSizeRequestHandler(i) ++ case closeConnection: ++ return l.closeConnectionHandler() + default: + return fmt.Errorf("transport: unknown control message type %T", i) + } +diff --git a/vendor/google.golang.org/grpc/internal/transport/defaults.go b/vendor/google.golang.org/grpc/internal/transport/defaults.go +index 9fa306b2e07a..bc8ee0747496 100644 +--- a/vendor/google.golang.org/grpc/internal/transport/defaults.go ++++ b/vendor/google.golang.org/grpc/internal/transport/defaults.go +@@ -47,3 +47,9 @@ const ( + defaultClientMaxHeaderListSize = uint32(16 << 20) + defaultServerMaxHeaderListSize = uint32(16 << 20) + ) ++ ++// MaxStreamID is the upper bound for the stream ID before the current ++// transport gracefully closes and new transport is created for subsequent RPCs. ++// This is set to 75% of 2^31-1. Streams are identified with an unsigned 31-bit ++// integer. It's exported so that tests can override it. ++var MaxStreamID = uint32(math.MaxInt32 * 3 / 4) +diff --git a/vendor/google.golang.org/grpc/internal/transport/handler_server.go b/vendor/google.golang.org/grpc/internal/transport/handler_server.go +index 090120925bb4..e6626bf96e7c 100644 +--- a/vendor/google.golang.org/grpc/internal/transport/handler_server.go ++++ b/vendor/google.golang.org/grpc/internal/transport/handler_server.go +@@ -46,24 +46,32 @@ import ( + "google.golang.org/grpc/status" + ) + +-// NewServerHandlerTransport returns a ServerTransport handling gRPC +-// from inside an http.Handler. It requires that the http Server +-// supports HTTP/2. ++// NewServerHandlerTransport returns a ServerTransport handling gRPC from ++// inside an http.Handler, or writes an HTTP error to w and returns an error. ++// It requires that the http Server supports HTTP/2. + func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request, stats []stats.Handler) (ServerTransport, error) { + if r.ProtoMajor != 2 { +- return nil, errors.New("gRPC requires HTTP/2") ++ msg := "gRPC requires HTTP/2" ++ http.Error(w, msg, http.StatusBadRequest) ++ return nil, errors.New(msg) + } + if r.Method != "POST" { +- return nil, errors.New("invalid gRPC request method") ++ msg := fmt.Sprintf("invalid gRPC request method %q", r.Method) ++ http.Error(w, msg, http.StatusBadRequest) ++ return nil, errors.New(msg) + } + contentType := r.Header.Get("Content-Type") + // TODO: do we assume contentType is lowercase? we did before + contentSubtype, validContentType := grpcutil.ContentSubtype(contentType) + if !validContentType { +- return nil, errors.New("invalid gRPC request content-type") ++ msg := fmt.Sprintf("invalid gRPC request content-type %q", contentType) ++ http.Error(w, msg, http.StatusUnsupportedMediaType) ++ return nil, errors.New(msg) + } + if _, ok := w.(http.Flusher); !ok { +- return nil, errors.New("gRPC requires a ResponseWriter supporting http.Flusher") ++ msg := "gRPC requires a ResponseWriter supporting http.Flusher" ++ http.Error(w, msg, http.StatusInternalServerError) ++ return nil, errors.New(msg) + } + + st := &serverHandlerTransport{ +@@ -79,7 +87,9 @@ func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request, stats []s + if v := r.Header.Get("grpc-timeout"); v != "" { + to, err := decodeTimeout(v) + if err != nil { +- return nil, status.Errorf(codes.Internal, "malformed time-out: %v", err) ++ msg := fmt.Sprintf("malformed grpc-timeout: %v", err) ++ http.Error(w, msg, http.StatusBadRequest) ++ return nil, status.Error(codes.Internal, msg) + } + st.timeoutSet = true + st.timeout = to +@@ -97,7 +107,9 @@ func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request, stats []s + for _, v := range vv { + v, err := decodeMetadataHeader(k, v) + if err != nil { +- return nil, status.Errorf(codes.Internal, "malformed binary metadata: %v", err) ++ msg := fmt.Sprintf("malformed binary metadata %q in header %q: %v", v, k, err) ++ http.Error(w, msg, http.StatusBadRequest) ++ return nil, status.Error(codes.Internal, msg) + } + metakv = append(metakv, k, v) + } +@@ -141,12 +153,15 @@ type serverHandlerTransport struct { + stats []stats.Handler + } + +-func (ht *serverHandlerTransport) Close() { +- ht.closeOnce.Do(ht.closeCloseChanOnce) ++func (ht *serverHandlerTransport) Close(err error) { ++ ht.closeOnce.Do(func() { ++ if logger.V(logLevel) { ++ logger.Infof("Closing serverHandlerTransport: %v", err) ++ } ++ close(ht.closedCh) ++ }) + } + +-func (ht *serverHandlerTransport) closeCloseChanOnce() { close(ht.closedCh) } +- + func (ht *serverHandlerTransport) RemoteAddr() net.Addr { return strAddr(ht.req.RemoteAddr) } + + // strAddr is a net.Addr backed by either a TCP "ip:port" string, or +@@ -236,7 +251,7 @@ func (ht *serverHandlerTransport) WriteStatus(s *Stream, st *status.Status) erro + }) + } + } +- ht.Close() ++ ht.Close(errors.New("finished writing status")) + return err + } + +@@ -346,7 +361,7 @@ func (ht *serverHandlerTransport) HandleStreams(startStream func(*Stream), trace + case <-ht.req.Context().Done(): + } + cancel() +- ht.Close() ++ ht.Close(errors.New("request is done processing")) + }() + + req := ht.req +@@ -442,10 +457,10 @@ func (ht *serverHandlerTransport) Drain() { + // mapRecvMsgError returns the non-nil err into the appropriate + // error value as expected by callers of *grpc.parser.recvMsg. + // In particular, in can only be: +-// * io.EOF +-// * io.ErrUnexpectedEOF +-// * of type transport.ConnectionError +-// * an error from the status package ++// - io.EOF ++// - io.ErrUnexpectedEOF ++// - of type transport.ConnectionError ++// - an error from the status package + func mapRecvMsgError(err error) error { + if err == io.EOF || err == io.ErrUnexpectedEOF { + return err +diff --git a/vendor/google.golang.org/grpc/internal/transport/http2_client.go b/vendor/google.golang.org/grpc/internal/transport/http2_client.go +index 5c2f35b24e75..79ee8aea0a21 100644 +--- a/vendor/google.golang.org/grpc/internal/transport/http2_client.go ++++ b/vendor/google.golang.org/grpc/internal/transport/http2_client.go +@@ -38,8 +38,10 @@ import ( + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/internal/channelz" + icredentials "google.golang.org/grpc/internal/credentials" ++ "google.golang.org/grpc/internal/grpcsync" + "google.golang.org/grpc/internal/grpcutil" + imetadata "google.golang.org/grpc/internal/metadata" ++ istatus "google.golang.org/grpc/internal/status" + "google.golang.org/grpc/internal/syscall" + "google.golang.org/grpc/internal/transport/networktype" + "google.golang.org/grpc/keepalive" +@@ -57,11 +59,15 @@ var clientConnectionCounter uint64 + + // http2Client implements the ClientTransport interface with HTTP2. + type http2Client struct { +- lastRead int64 // Keep this field 64-bit aligned. Accessed atomically. +- ctx context.Context +- cancel context.CancelFunc +- ctxDone <-chan struct{} // Cache the ctx.Done() chan. +- userAgent string ++ lastRead int64 // Keep this field 64-bit aligned. Accessed atomically. ++ ctx context.Context ++ cancel context.CancelFunc ++ ctxDone <-chan struct{} // Cache the ctx.Done() chan. ++ userAgent string ++ // address contains the resolver returned address for this transport. ++ // If the `ServerName` field is set, it takes precedence over `CallHdr.Host` ++ // passed to `NewStream`, when determining the :authority header. ++ address resolver.Address + md metadata.MD + conn net.Conn // underlying communication channel + loopy *loopyWriter +@@ -99,16 +105,13 @@ type http2Client struct { + maxSendHeaderListSize *uint32 + + bdpEst *bdpEstimator +- // onPrefaceReceipt is a callback that client transport calls upon +- // receiving server preface to signal that a succefull HTTP2 +- // connection was established. +- onPrefaceReceipt func() + + maxConcurrentStreams uint32 + streamQuota int64 + streamsQuotaAvailable chan struct{} + waitingStreams uint32 + nextID uint32 ++ registeredCompressors string + + // Do not access controlBuf with mu held. + mu sync.Mutex // guard the following variables +@@ -137,8 +140,7 @@ type http2Client struct { + channelzID *channelz.Identifier + czData *channelzData + +- onGoAway func(GoAwayReason) +- onClose func() ++ onClose func(GoAwayReason) + + bufferPool *bufferPool + +@@ -194,7 +196,7 @@ func isTemporary(err error) bool { + // newHTTP2Client constructs a connected ClientTransport to addr based on HTTP2 + // and starts to receive messages on it. Non-nil error returns if construction + // fails. +-func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts ConnectOptions, onPrefaceReceipt func(), onGoAway func(GoAwayReason), onClose func()) (_ *http2Client, err error) { ++func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts ConnectOptions, onClose func(GoAwayReason)) (_ *http2Client, err error) { + scheme := "http" + ctx, cancel := context.WithCancel(ctx) + defer func() { +@@ -214,14 +216,40 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts + if opts.FailOnNonTempDialError { + return nil, connectionErrorf(isTemporary(err), err, "transport: error while dialing: %v", err) + } +- return nil, connectionErrorf(true, err, "transport: Error while dialing %v", err) ++ return nil, connectionErrorf(true, err, "transport: Error while dialing: %v", err) + } ++ + // Any further errors will close the underlying connection + defer func(conn net.Conn) { + if err != nil { + conn.Close() + } + }(conn) ++ ++ // The following defer and goroutine monitor the connectCtx for cancelation ++ // and deadline. On context expiration, the connection is hard closed and ++ // this function will naturally fail as a result. Otherwise, the defer ++ // waits for the goroutine to exit to prevent the context from being ++ // monitored (and to prevent the connection from ever being closed) after ++ // returning from this function. ++ ctxMonitorDone := grpcsync.NewEvent() ++ newClientCtx, newClientDone := context.WithCancel(connectCtx) ++ defer func() { ++ newClientDone() // Awaken the goroutine below if connectCtx hasn't expired. ++ <-ctxMonitorDone.Done() // Wait for the goroutine below to exit. ++ }() ++ go func(conn net.Conn) { ++ defer ctxMonitorDone.Fire() // Signal this goroutine has exited. ++ <-newClientCtx.Done() // Block until connectCtx expires or the defer above executes. ++ if err := connectCtx.Err(); err != nil { ++ // connectCtx expired before exiting the function. Hard close the connection. ++ if logger.V(logLevel) { ++ logger.Infof("newClientTransport: aborting due to connectCtx: %v", err) ++ } ++ conn.Close() ++ } ++ }(conn) ++ + kp := opts.KeepaliveParams + // Validate keepalive parameters. + if kp.Time == 0 { +@@ -253,15 +281,7 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts + } + } + if transportCreds != nil { +- rawConn := conn +- // Pull the deadline from the connectCtx, which will be used for +- // timeouts in the authentication protocol handshake. Can ignore the +- // boolean as the deadline will return the zero value, which will make +- // the conn not timeout on I/O operations. +- deadline, _ := connectCtx.Deadline() +- rawConn.SetDeadline(deadline) +- conn, authInfo, err = transportCreds.ClientHandshake(connectCtx, addr.ServerName, rawConn) +- rawConn.SetDeadline(time.Time{}) ++ conn, authInfo, err = transportCreds.ClientHandshake(connectCtx, addr.ServerName, conn) + if err != nil { + return nil, connectionErrorf(isTemporary(err), err, "transport: authentication handshake failed: %v", err) + } +@@ -299,6 +319,8 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts + ctxDone: ctx.Done(), // Cache Done chan. + cancel: cancel, + userAgent: opts.UserAgent, ++ registeredCompressors: grpcutil.RegisteredCompressors(), ++ address: addr, + conn: conn, + remoteAddr: conn.RemoteAddr(), + localAddr: conn.LocalAddr(), +@@ -315,16 +337,14 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts + kp: kp, + statsHandlers: opts.StatsHandlers, + initialWindowSize: initialWindowSize, +- onPrefaceReceipt: onPrefaceReceipt, + nextID: 1, + maxConcurrentStreams: defaultMaxStreamsClient, + streamQuota: defaultMaxStreamsClient, + streamsQuotaAvailable: make(chan struct{}, 1), + czData: new(channelzData), +- onGoAway: onGoAway, +- onClose: onClose, + keepaliveEnabled: keepaliveEnabled, + bufferPool: newBufferPool(), ++ onClose: onClose, + } + // Add peer information to the http2client context. + t.ctx = peer.NewContext(t.ctx, t.getPeer()) +@@ -363,21 +383,32 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts + t.kpDormancyCond = sync.NewCond(&t.mu) + go t.keepalive() + } +- // Start the reader goroutine for incoming message. Each transport has +- // a dedicated goroutine which reads HTTP2 frame from network. Then it +- // dispatches the frame to the corresponding stream entity. +- go t.reader() ++ ++ // Start the reader goroutine for incoming messages. Each transport has a ++ // dedicated goroutine which reads HTTP2 frames from the network. Then it ++ // dispatches the frame to the corresponding stream entity. When the ++ // server preface is received, readerErrCh is closed. If an error occurs ++ // first, an error is pushed to the channel. This must be checked before ++ // returning from this function. ++ readerErrCh := make(chan error, 1) ++ go t.reader(readerErrCh) ++ defer func() { ++ if err == nil { ++ err = <-readerErrCh ++ } ++ if err != nil { ++ t.Close(err) ++ } ++ }() + + // Send connection preface to server. + n, err := t.conn.Write(clientPreface) + if err != nil { + err = connectionErrorf(true, err, "transport: failed to write client preface: %v", err) +- t.Close(err) + return nil, err + } + if n != len(clientPreface) { + err = connectionErrorf(true, nil, "transport: preface mismatch, wrote %d bytes; want %d", n, len(clientPreface)) +- t.Close(err) + return nil, err + } + var ss []http2.Setting +@@ -397,14 +428,12 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts + err = t.framer.fr.WriteSettings(ss...) + if err != nil { + err = connectionErrorf(true, err, "transport: failed to write initial settings frame: %v", err) +- t.Close(err) + return nil, err + } + // Adjust the connection flow control window if needed. + if delta := uint32(icwz - defaultWindowSize); delta > 0 { + if err := t.framer.fr.WriteWindowUpdate(0, delta); err != nil { + err = connectionErrorf(true, err, "transport: failed to write window update: %v", err) +- t.Close(err) + return nil, err + } + } +@@ -417,10 +446,8 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts + go func() { + t.loopy = newLoopyWriter(clientSide, t.framer, t.controlBuf, t.bdpEst) + err := t.loopy.run() +- if err != nil { +- if logger.V(logLevel) { +- logger.Errorf("transport: loopyWriter.run returning. Err: %v", err) +- } ++ if logger.V(logLevel) { ++ logger.Infof("transport: loopyWriter exited. Closing connection. Err: %v", err) + } + // Do not close the transport. Let reader goroutine handle it since + // there might be data in the buffers. +@@ -507,9 +534,22 @@ func (t *http2Client) createHeaderFields(ctx context.Context, callHdr *CallHdr) + headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-previous-rpc-attempts", Value: strconv.Itoa(callHdr.PreviousAttempts)}) + } + ++ registeredCompressors := t.registeredCompressors + if callHdr.SendCompress != "" { + headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-encoding", Value: callHdr.SendCompress}) +- headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-accept-encoding", Value: callHdr.SendCompress}) ++ // Include the outgoing compressor name when compressor is not registered ++ // via encoding.RegisterCompressor. This is possible when client uses ++ // WithCompressor dial option. ++ if !grpcutil.IsCompressorNameRegistered(callHdr.SendCompress) { ++ if registeredCompressors != "" { ++ registeredCompressors += "," ++ } ++ registeredCompressors += callHdr.SendCompress ++ } ++ } ++ ++ if registeredCompressors != "" { ++ headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-accept-encoding", Value: registeredCompressors}) + } + if dl, ok := ctx.Deadline(); ok { + // Send out timeout regardless its value. The server can detect timeout context by itself. +@@ -589,7 +629,11 @@ func (t *http2Client) getTrAuthData(ctx context.Context, audience string) (map[s + for _, c := range t.perRPCCreds { + data, err := c.GetRequestMetadata(ctx, audience) + if err != nil { +- if _, ok := status.FromError(err); ok { ++ if st, ok := status.FromError(err); ok { ++ // Restrict the code to the list allowed by gRFC A54. ++ if istatus.IsRestrictedControlPlaneCode(st) { ++ err = status.Errorf(codes.Internal, "transport: received per-RPC creds error with illegal status: %v", err) ++ } + return nil, err + } + +@@ -618,7 +662,14 @@ func (t *http2Client) getCallAuthData(ctx context.Context, audience string, call + } + data, err := callCreds.GetRequestMetadata(ctx, audience) + if err != nil { +- return nil, status.Errorf(codes.Internal, "transport: %v", err) ++ if st, ok := status.FromError(err); ok { ++ // Restrict the code to the list allowed by gRFC A54. ++ if istatus.IsRestrictedControlPlaneCode(st) { ++ err = status.Errorf(codes.Internal, "transport: received per-RPC creds error with illegal status: %v", err) ++ } ++ return nil, err ++ } ++ return nil, status.Errorf(codes.Internal, "transport: per-RPC creds failed due to error: %v", err) + } + callAuthData = make(map[string]string, len(data)) + for k, v := range data { +@@ -634,13 +685,13 @@ func (t *http2Client) getCallAuthData(ctx context.Context, audience string, call + // NewStream errors result in transparent retry, as they mean nothing went onto + // the wire. However, there are two notable exceptions: + // +-// 1. If the stream headers violate the max header list size allowed by the +-// server. It's possible this could succeed on another transport, even if +-// it's unlikely, but do not transparently retry. +-// 2. If the credentials errored when requesting their headers. In this case, +-// it's possible a retry can fix the problem, but indefinitely transparently +-// retrying is not appropriate as it is likely the credentials, if they can +-// eventually succeed, would need I/O to do so. ++// 1. If the stream headers violate the max header list size allowed by the ++// server. It's possible this could succeed on another transport, even if ++// it's unlikely, but do not transparently retry. ++// 2. If the credentials errored when requesting their headers. In this case, ++// it's possible a retry can fix the problem, but indefinitely transparently ++// retrying is not appropriate as it is likely the credentials, if they can ++// eventually succeed, would need I/O to do so. + type NewStreamError struct { + Err error + +@@ -655,6 +706,18 @@ func (e NewStreamError) Error() string { + // streams. All non-nil errors returned will be *NewStreamError. + func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream, error) { + ctx = peer.NewContext(ctx, t.getPeer()) ++ ++ // ServerName field of the resolver returned address takes precedence over ++ // Host field of CallHdr to determine the :authority header. This is because, ++ // the ServerName field takes precedence for server authentication during ++ // TLS handshake, and the :authority header should match the value used ++ // for server authentication. ++ if t.address.ServerName != "" { ++ newCallHdr := *callHdr ++ newCallHdr.Host = t.address.ServerName ++ callHdr = &newCallHdr ++ } ++ + headerFields, err := t.createHeaderFields(ctx, callHdr) + if err != nil { + return nil, &NewStreamError{Err: err, AllowTransparentRetry: false} +@@ -679,15 +742,12 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream, + endStream: false, + initStream: func(id uint32) error { + t.mu.Lock() +- if state := t.state; state != reachable { ++ // TODO: handle transport closure in loopy instead and remove this ++ // initStream is never called when transport is draining. ++ if t.state == closing { + t.mu.Unlock() +- // Do a quick cleanup. +- err := error(errStreamDrain) +- if state == closing { +- err = ErrConnClosing +- } +- cleanup(err) +- return err ++ cleanup(ErrConnClosing) ++ return ErrConnClosing + } + if channelz.IsOn() { + atomic.AddInt64(&t.czData.streamsStarted, 1) +@@ -705,6 +765,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream, + } + firstTry := true + var ch chan struct{} ++ transportDrainRequired := false + checkForStreamQuota := func(it interface{}) bool { + if t.streamQuota <= 0 { // Can go negative if server decreases it. + if firstTry { +@@ -720,6 +781,11 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream, + h := it.(*headerFrame) + h.streamID = t.nextID + t.nextID += 2 ++ ++ // Drain client transport if nextID > MaxStreamID which signals gRPC that ++ // the connection is closed and a new one must be created for subsequent RPCs. ++ transportDrainRequired = t.nextID > MaxStreamID ++ + s.id = h.streamID + s.fc = &inFlow{limit: uint32(t.initialWindowSize)} + t.mu.Lock() +@@ -799,6 +865,12 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream, + sh.HandleRPC(s.ctx, outHeader) + } + } ++ if transportDrainRequired { ++ if logger.V(logLevel) { ++ logger.Infof("transport: t.nextID > MaxStreamID. Draining") ++ } ++ t.GracefulClose() ++ } + return s, nil + } + +@@ -880,20 +952,21 @@ func (t *http2Client) closeStream(s *Stream, err error, rst bool, rstCode http2. + // Close kicks off the shutdown process of the transport. This should be called + // only once on a transport. Once it is called, the transport should not be + // accessed any more. +-// +-// This method blocks until the addrConn that initiated this transport is +-// re-connected. This happens because t.onClose() begins reconnect logic at the +-// addrConn level and blocks until the addrConn is successfully connected. + func (t *http2Client) Close(err error) { + t.mu.Lock() +- // Make sure we only Close once. ++ // Make sure we only close once. + if t.state == closing { + t.mu.Unlock() + return + } +- // Call t.onClose before setting the state to closing to prevent the client +- // from attempting to create new streams ASAP. +- t.onClose() ++ if logger.V(logLevel) { ++ logger.Infof("transport: closing: %v", err) ++ } ++ // Call t.onClose ASAP to prevent the client from attempting to create new ++ // streams. ++ if t.state != draining { ++ t.onClose(GoAwayInvalid) ++ } + t.state = closing + streams := t.activeStreams + t.activeStreams = nil +@@ -943,11 +1016,15 @@ func (t *http2Client) GracefulClose() { + t.mu.Unlock() + return + } ++ if logger.V(logLevel) { ++ logger.Infof("transport: GracefulClose called") ++ } ++ t.onClose(GoAwayInvalid) + t.state = draining + active := len(t.activeStreams) + t.mu.Unlock() + if active == 0 { +- t.Close(ErrConnClosing) ++ t.Close(connectionErrorf(true, nil, "no active streams left to process while draining")) + return + } + t.controlBuf.put(&incomingGoAway{}) +@@ -1105,7 +1182,7 @@ func (t *http2Client) handleRSTStream(f *http2.RSTStreamFrame) { + statusCode, ok := http2ErrConvTab[f.ErrCode] + if !ok { + if logger.V(logLevel) { +- logger.Warningf("transport: http2Client.handleRSTStream found no mapped gRPC status for the received http2 error %v", f.ErrCode) ++ logger.Warningf("transport: http2Client.handleRSTStream found no mapped gRPC status for the received http2 error: %v", f.ErrCode) + } + statusCode = codes.Unknown + } +@@ -1223,8 +1300,10 @@ func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) { + // Notify the clientconn about the GOAWAY before we set the state to + // draining, to allow the client to stop attempting to create streams + // before disallowing new streams on this connection. +- t.onGoAway(t.goAwayReason) +- t.state = draining ++ if t.state != draining { ++ t.onClose(t.goAwayReason) ++ t.state = draining ++ } + } + // All streams with IDs greater than the GoAwayId + // and smaller than the previous GoAway ID should be killed. +@@ -1482,33 +1561,35 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) { + t.closeStream(s, io.EOF, rst, http2.ErrCodeNo, statusGen, mdata, true) + } + +-// reader runs as a separate goroutine in charge of reading data from network +-// connection. +-// +-// TODO(zhaoq): currently one reader per transport. Investigate whether this is +-// optimal. +-// TODO(zhaoq): Check the validity of the incoming frame sequence. +-func (t *http2Client) reader() { +- defer close(t.readerDone) +- // Check the validity of server preface. ++// readServerPreface reads and handles the initial settings frame from the ++// server. ++func (t *http2Client) readServerPreface() error { + frame, err := t.framer.fr.ReadFrame() + if err != nil { +- err = connectionErrorf(true, err, "error reading server preface: %v", err) +- t.Close(err) // this kicks off resetTransport, so must be last before return +- return +- } +- t.conn.SetReadDeadline(time.Time{}) // reset deadline once we get the settings frame (we didn't time out, yay!) +- if t.keepaliveEnabled { +- atomic.StoreInt64(&t.lastRead, time.Now().UnixNano()) ++ return connectionErrorf(true, err, "error reading server preface: %v", err) + } + sf, ok := frame.(*http2.SettingsFrame) + if !ok { +- // this kicks off resetTransport, so must be last before return +- t.Close(connectionErrorf(true, nil, "initial http2 frame from server is not a settings frame: %T", frame)) +- return ++ return connectionErrorf(true, nil, "initial http2 frame from server is not a settings frame: %T", frame) + } +- t.onPrefaceReceipt() + t.handleSettings(sf, true) ++ return nil ++} ++ ++// reader verifies the server preface and reads all subsequent data from ++// network connection. If the server preface is not read successfully, an ++// error is pushed to errCh; otherwise errCh is closed with no error. ++func (t *http2Client) reader(errCh chan<- error) { ++ defer close(t.readerDone) ++ ++ if err := t.readServerPreface(); err != nil { ++ errCh <- err ++ return ++ } ++ close(errCh) ++ if t.keepaliveEnabled { ++ atomic.StoreInt64(&t.lastRead, time.Now().UnixNano()) ++ } + + // loop to keep reading incoming messages on this transport. + for { +@@ -1711,3 +1792,9 @@ func (t *http2Client) getOutFlowWindow() int64 { + return -2 + } + } ++ ++func (t *http2Client) stateForTesting() transportState { ++ t.mu.Lock() ++ defer t.mu.Unlock() ++ return t.state ++} +diff --git a/vendor/google.golang.org/grpc/internal/transport/http2_server.go b/vendor/google.golang.org/grpc/internal/transport/http2_server.go +index 3dd15647bc84..bc3da706726d 100644 +--- a/vendor/google.golang.org/grpc/internal/transport/http2_server.go ++++ b/vendor/google.golang.org/grpc/internal/transport/http2_server.go +@@ -21,6 +21,7 @@ package transport + import ( + "bytes" + "context" ++ "errors" + "fmt" + "io" + "math" +@@ -41,6 +42,7 @@ import ( + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/internal/channelz" + "google.golang.org/grpc/internal/grpcrand" ++ "google.golang.org/grpc/internal/grpcsync" + "google.golang.org/grpc/keepalive" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/peer" +@@ -101,13 +103,13 @@ type http2Server struct { + + mu sync.Mutex // guard the following + +- // drainChan is initialized when Drain() is called the first time. +- // After which the server writes out the first GoAway(with ID 2^31-1) frame. +- // Then an independent goroutine will be launched to later send the second GoAway. +- // During this time we don't want to write another first GoAway(with ID 2^31 -1) frame. +- // Thus call to Drain() will be a no-op if drainChan is already initialized since draining is +- // already underway. +- drainChan chan struct{} ++ // drainEvent is initialized when Drain() is called the first time. After ++ // which the server writes out the first GoAway(with ID 2^31-1) frame. Then ++ // an independent goroutine will be launched to later send the second ++ // GoAway. During this time we don't want to write another first GoAway(with ++ // ID 2^31 -1) frame. Thus call to Drain() will be a no-op if drainEvent is ++ // already initialized since draining is already underway. ++ drainEvent *grpcsync.Event + state transportState + activeStreams map[uint32]*Stream + // idle is the time instant when the connection went idle. +@@ -293,7 +295,7 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport, + + defer func() { + if err != nil { +- t.Close() ++ t.Close(err) + } + }() + +@@ -331,10 +333,9 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport, + go func() { + t.loopy = newLoopyWriter(serverSide, t.framer, t.controlBuf, t.bdpEst) + t.loopy.ssGoAwayHandler = t.outgoingGoAwayHandler +- if err := t.loopy.run(); err != nil { +- if logger.V(logLevel) { +- logger.Errorf("transport: loopyWriter.run returning. Err: %v", err) +- } ++ err := t.loopy.run() ++ if logger.V(logLevel) { ++ logger.Infof("transport: loopyWriter exited. Closing connection. Err: %v", err) + } + t.conn.Close() + t.controlBuf.finish() +@@ -344,8 +345,9 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport, + return t, nil + } + +-// operateHeader takes action on the decoded headers. +-func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(*Stream), traceCtx func(context.Context, string) context.Context) (fatal bool) { ++// operateHeaders takes action on the decoded headers. Returns an error if fatal ++// error encountered and transport needs to close, otherwise returns nil. ++func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(*Stream), traceCtx func(context.Context, string) context.Context) error { + // Acquire max stream ID lock for entire duration + t.maxStreamMu.Lock() + defer t.maxStreamMu.Unlock() +@@ -361,15 +363,12 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( + rstCode: http2.ErrCodeFrameSize, + onWrite: func() {}, + }) +- return false ++ return nil + } + + if streamID%2 != 1 || streamID <= t.maxStreamID { + // illegal gRPC stream id. +- if logger.V(logLevel) { +- logger.Errorf("transport: http2Server.HandleStreams received an illegal stream id: %v", streamID) +- } +- return true ++ return fmt.Errorf("received an illegal stream id: %v. headers frame: %+v", streamID, frame) + } + t.maxStreamID = streamID + +@@ -381,13 +380,14 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( + fc: &inFlow{limit: uint32(t.initialWindowSize)}, + } + var ( +- // If a gRPC Response-Headers has already been received, then it means +- // that the peer is speaking gRPC and we are in gRPC mode. +- isGRPC = false +- mdata = make(map[string][]string) +- httpMethod string +- // headerError is set if an error is encountered while parsing the headers +- headerError bool ++ // if false, content-type was missing or invalid ++ isGRPC = false ++ contentType = "" ++ mdata = make(map[string][]string) ++ httpMethod string ++ // these are set if an error is encountered while parsing the headers ++ protocolError bool ++ headerError *status.Status + + timeoutSet bool + timeout time.Duration +@@ -398,6 +398,7 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( + case "content-type": + contentSubtype, validContentType := grpcutil.ContentSubtype(hf.Value) + if !validContentType { ++ contentType = hf.Value + break + } + mdata[hf.Name] = append(mdata[hf.Name], hf.Value) +@@ -413,7 +414,7 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( + timeoutSet = true + var err error + if timeout, err = decodeTimeout(hf.Value); err != nil { +- headerError = true ++ headerError = status.Newf(codes.Internal, "malformed grpc-timeout: %v", err) + } + // "Transports must consider requests containing the Connection header + // as malformed." - A41 +@@ -421,14 +422,14 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( + if logger.V(logLevel) { + logger.Errorf("transport: http2Server.operateHeaders parsed a :connection header which makes a request malformed as per the HTTP/2 spec") + } +- headerError = true ++ protocolError = true + default: + if isReservedHeader(hf.Name) && !isWhitelistedHeader(hf.Name) { + break + } + v, err := decodeMetadataHeader(hf.Name, hf.Value) + if err != nil { +- headerError = true ++ headerError = status.Newf(codes.Internal, "malformed binary metadata %q in header %q: %v", hf.Value, hf.Name, err) + logger.Warningf("Failed to decode metadata header (%q, %q): %v", hf.Name, hf.Value, err) + break + } +@@ -447,23 +448,43 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( + logger.Errorf("transport: %v", errMsg) + } + t.controlBuf.put(&earlyAbortStream{ +- httpStatus: 400, ++ httpStatus: http.StatusBadRequest, + streamID: streamID, + contentSubtype: s.contentSubtype, + status: status.New(codes.Internal, errMsg), + rst: !frame.StreamEnded(), + }) +- return false ++ return nil + } + +- if !isGRPC || headerError { ++ if protocolError { + t.controlBuf.put(&cleanupStream{ + streamID: streamID, + rst: true, + rstCode: http2.ErrCodeProtocol, + onWrite: func() {}, + }) +- return false ++ return nil ++ } ++ if !isGRPC { ++ t.controlBuf.put(&earlyAbortStream{ ++ httpStatus: http.StatusUnsupportedMediaType, ++ streamID: streamID, ++ contentSubtype: s.contentSubtype, ++ status: status.Newf(codes.InvalidArgument, "invalid gRPC request content-type %q", contentType), ++ rst: !frame.StreamEnded(), ++ }) ++ return nil ++ } ++ if headerError != nil { ++ t.controlBuf.put(&earlyAbortStream{ ++ httpStatus: http.StatusBadRequest, ++ streamID: streamID, ++ contentSubtype: s.contentSubtype, ++ status: headerError, ++ rst: !frame.StreamEnded(), ++ }) ++ return nil + } + + // "If :authority is missing, Host must be renamed to :authority." - A41 +@@ -503,7 +524,7 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( + if t.state != reachable { + t.mu.Unlock() + s.cancel() +- return false ++ return nil + } + if uint32(len(t.activeStreams)) >= t.maxStreams { + t.mu.Unlock() +@@ -514,7 +535,7 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( + onWrite: func() {}, + }) + s.cancel() +- return false ++ return nil + } + if httpMethod != http.MethodPost { + t.mu.Unlock() +@@ -530,7 +551,7 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( + rst: !frame.StreamEnded(), + }) + s.cancel() +- return false ++ return nil + } + if t.inTapHandle != nil { + var err error +@@ -550,7 +571,7 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( + status: stat, + rst: !frame.StreamEnded(), + }) +- return false ++ return nil + } + } + t.activeStreams[streamID] = s +@@ -597,7 +618,7 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( + wq: s.wq, + }) + handle(s) +- return false ++ return nil + } + + // HandleStreams receives incoming streams using the given handler. This is +@@ -630,19 +651,16 @@ func (t *http2Server) HandleStreams(handle func(*Stream), traceCtx func(context. + continue + } + if err == io.EOF || err == io.ErrUnexpectedEOF { +- t.Close() ++ t.Close(err) + return + } +- if logger.V(logLevel) { +- logger.Warningf("transport: http2Server.HandleStreams failed to read frame: %v", err) +- } +- t.Close() ++ t.Close(err) + return + } + switch frame := frame.(type) { + case *http2.MetaHeadersFrame: +- if t.operateHeaders(frame, handle, traceCtx) { +- t.Close() ++ if err := t.operateHeaders(frame, handle, traceCtx); err != nil { ++ t.Close(err) + break + } + case *http2.DataFrame: +@@ -843,8 +861,8 @@ const ( + + func (t *http2Server) handlePing(f *http2.PingFrame) { + if f.IsAck() { +- if f.Data == goAwayPing.data && t.drainChan != nil { +- close(t.drainChan) ++ if f.Data == goAwayPing.data && t.drainEvent != nil { ++ t.drainEvent.Fire() + return + } + // Maybe it's a BDP ping. +@@ -886,10 +904,7 @@ func (t *http2Server) handlePing(f *http2.PingFrame) { + + if t.pingStrikes > maxPingStrikes { + // Send goaway and close the connection. +- if logger.V(logLevel) { +- logger.Errorf("transport: Got too many pings from the client, closing the connection.") +- } +- t.controlBuf.put(&goAway{code: http2.ErrCodeEnhanceYourCalm, debugData: []byte("too_many_pings"), closeConn: true}) ++ t.controlBuf.put(&goAway{code: http2.ErrCodeEnhanceYourCalm, debugData: []byte("too_many_pings"), closeConn: errors.New("got too many pings from the client")}) + } + } + +@@ -1153,7 +1168,7 @@ func (t *http2Server) keepalive() { + if logger.V(logLevel) { + logger.Infof("transport: closing server transport due to maximum connection age.") + } +- t.Close() ++ t.controlBuf.put(closeConnection{}) + case <-t.done: + } + return +@@ -1169,10 +1184,7 @@ func (t *http2Server) keepalive() { + continue + } + if outstandingPing && kpTimeoutLeft <= 0 { +- if logger.V(logLevel) { +- logger.Infof("transport: closing server transport due to idleness.") +- } +- t.Close() ++ t.Close(fmt.Errorf("keepalive ping not acked within timeout %s", t.kp.Time)) + return + } + if !outstandingPing { +@@ -1199,12 +1211,15 @@ func (t *http2Server) keepalive() { + // Close starts shutting down the http2Server transport. + // TODO(zhaoq): Now the destruction is not blocked on any pending streams. This + // could cause some resource issue. Revisit this later. +-func (t *http2Server) Close() { ++func (t *http2Server) Close(err error) { + t.mu.Lock() + if t.state == closing { + t.mu.Unlock() + return + } ++ if logger.V(logLevel) { ++ logger.Infof("transport: closing: %v", err) ++ } + t.state = closing + streams := t.activeStreams + t.activeStreams = nil +@@ -1295,10 +1310,10 @@ func (t *http2Server) RemoteAddr() net.Addr { + func (t *http2Server) Drain() { + t.mu.Lock() + defer t.mu.Unlock() +- if t.drainChan != nil { ++ if t.drainEvent != nil { + return + } +- t.drainChan = make(chan struct{}) ++ t.drainEvent = grpcsync.NewEvent() + t.controlBuf.put(&goAway{code: http2.ErrCodeNo, debugData: []byte{}, headsUp: true}) + } + +@@ -1319,19 +1334,20 @@ func (t *http2Server) outgoingGoAwayHandler(g *goAway) (bool, error) { + // Stop accepting more streams now. + t.state = draining + sid := t.maxStreamID ++ retErr := g.closeConn + if len(t.activeStreams) == 0 { +- g.closeConn = true ++ retErr = errors.New("second GOAWAY written and no active streams left to process") + } + t.mu.Unlock() + t.maxStreamMu.Unlock() + if err := t.framer.fr.WriteGoAway(sid, g.code, g.debugData); err != nil { + return false, err + } +- if g.closeConn { ++ if retErr != nil { + // Abruptly close the connection following the GoAway (via + // loopywriter). But flush out what's inside the buffer first. + t.framer.writer.Flush() +- return false, fmt.Errorf("transport: Connection closing") ++ return false, retErr + } + return true, nil + } +@@ -1353,7 +1369,7 @@ func (t *http2Server) outgoingGoAwayHandler(g *goAway) (bool, error) { + timer := time.NewTimer(time.Minute) + defer timer.Stop() + select { +- case <-t.drainChan: ++ case <-t.drainEvent.Done(): + case <-timer.C: + case <-t.done: + return +diff --git a/vendor/google.golang.org/grpc/internal/transport/transport.go b/vendor/google.golang.org/grpc/internal/transport/transport.go +index 6c3ba8515940..0ac77ea4f8c7 100644 +--- a/vendor/google.golang.org/grpc/internal/transport/transport.go ++++ b/vendor/google.golang.org/grpc/internal/transport/transport.go +@@ -43,6 +43,10 @@ import ( + "google.golang.org/grpc/tap" + ) + ++// ErrNoHeaders is used as a signal that a trailers only response was received, ++// and is not a real error. ++var ErrNoHeaders = errors.New("stream has no headers") ++ + const logLevel = 2 + + type bufferPool struct { +@@ -366,9 +370,15 @@ func (s *Stream) Header() (metadata.MD, error) { + return s.header.Copy(), nil + } + s.waitOnHeader() ++ + if !s.headerValid { + return nil, s.status.Err() + } ++ ++ if s.noHeaders { ++ return nil, ErrNoHeaders ++ } ++ + return s.header.Copy(), nil + } + +@@ -573,8 +583,8 @@ type ConnectOptions struct { + + // NewClientTransport establishes the transport with the required ConnectOptions + // and returns it to the caller. +-func NewClientTransport(connectCtx, ctx context.Context, addr resolver.Address, opts ConnectOptions, onPrefaceReceipt func(), onGoAway func(GoAwayReason), onClose func()) (ClientTransport, error) { +- return newHTTP2Client(connectCtx, ctx, addr, opts, onPrefaceReceipt, onGoAway, onClose) ++func NewClientTransport(connectCtx, ctx context.Context, addr resolver.Address, opts ConnectOptions, onClose func(GoAwayReason)) (ClientTransport, error) { ++ return newHTTP2Client(connectCtx, ctx, addr, opts, onClose) + } + + // Options provides additional hints and information for message +@@ -691,7 +701,7 @@ type ServerTransport interface { + // Close tears down the transport. Once it is called, the transport + // should not be accessed any more. All the pending streams and their + // handlers will be terminated asynchronously. +- Close() ++ Close(err error) + + // RemoteAddr returns the remote network address. + RemoteAddr() net.Addr +diff --git a/vendor/google.golang.org/grpc/metadata/metadata.go b/vendor/google.golang.org/grpc/metadata/metadata.go +index 98d62e0675f6..fb4a88f59bd3 100644 +--- a/vendor/google.golang.org/grpc/metadata/metadata.go ++++ b/vendor/google.golang.org/grpc/metadata/metadata.go +@@ -41,10 +41,11 @@ type MD map[string][]string + // New creates an MD from a given key-value map. + // + // Only the following ASCII characters are allowed in keys: +-// - digits: 0-9 +-// - uppercase letters: A-Z (normalized to lower) +-// - lowercase letters: a-z +-// - special characters: -_. ++// - digits: 0-9 ++// - uppercase letters: A-Z (normalized to lower) ++// - lowercase letters: a-z ++// - special characters: -_. ++// + // Uppercase letters are automatically converted to lowercase. + // + // Keys beginning with "grpc-" are reserved for grpc-internal use only and may +@@ -62,10 +63,11 @@ func New(m map[string]string) MD { + // Pairs panics if len(kv) is odd. + // + // Only the following ASCII characters are allowed in keys: +-// - digits: 0-9 +-// - uppercase letters: A-Z (normalized to lower) +-// - lowercase letters: a-z +-// - special characters: -_. ++// - digits: 0-9 ++// - uppercase letters: A-Z (normalized to lower) ++// - lowercase letters: a-z ++// - special characters: -_. ++// + // Uppercase letters are automatically converted to lowercase. + // + // Keys beginning with "grpc-" are reserved for grpc-internal use only and may +@@ -196,7 +198,7 @@ func FromIncomingContext(ctx context.Context) (MD, bool) { + // ValueFromIncomingContext returns the metadata value corresponding to the metadata + // key from the incoming metadata if it exists. Key must be lower-case. + // +-// Experimental ++// # Experimental + // + // Notice: This API is EXPERIMENTAL and may be changed or removed in a + // later release. +diff --git a/vendor/google.golang.org/grpc/picker_wrapper.go b/vendor/google.golang.org/grpc/picker_wrapper.go +index 843633c910a1..c525dc070fc6 100644 +--- a/vendor/google.golang.org/grpc/picker_wrapper.go ++++ b/vendor/google.golang.org/grpc/picker_wrapper.go +@@ -26,6 +26,7 @@ import ( + "google.golang.org/grpc/balancer" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/internal/channelz" ++ istatus "google.golang.org/grpc/internal/status" + "google.golang.org/grpc/internal/transport" + "google.golang.org/grpc/status" + ) +@@ -57,12 +58,18 @@ func (pw *pickerWrapper) updatePicker(p balancer.Picker) { + pw.mu.Unlock() + } + +-func doneChannelzWrapper(acw *acBalancerWrapper, done func(balancer.DoneInfo)) func(balancer.DoneInfo) { ++// doneChannelzWrapper performs the following: ++// - increments the calls started channelz counter ++// - wraps the done function in the passed in result to increment the calls ++// failed or calls succeeded channelz counter before invoking the actual ++// done function. ++func doneChannelzWrapper(acw *acBalancerWrapper, result *balancer.PickResult) { + acw.mu.Lock() + ac := acw.ac + acw.mu.Unlock() + ac.incrCallsStarted() +- return func(b balancer.DoneInfo) { ++ done := result.Done ++ result.Done = func(b balancer.DoneInfo) { + if b.Err != nil && b.Err != io.EOF { + ac.incrCallsFailed() + } else { +@@ -81,7 +88,7 @@ func doneChannelzWrapper(acw *acBalancerWrapper, done func(balancer.DoneInfo)) f + // - the current picker returns other errors and failfast is false. + // - the subConn returned by the current picker is not READY + // When one of these situations happens, pick blocks until the picker gets updated. +-func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.PickInfo) (transport.ClientTransport, func(balancer.DoneInfo), error) { ++func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.PickInfo) (transport.ClientTransport, balancer.PickResult, error) { + var ch chan struct{} + + var lastPickErr error +@@ -89,7 +96,7 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer. + pw.mu.Lock() + if pw.done { + pw.mu.Unlock() +- return nil, nil, ErrClientConnClosing ++ return nil, balancer.PickResult{}, ErrClientConnClosing + } + + if pw.picker == nil { +@@ -110,9 +117,9 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer. + } + switch ctx.Err() { + case context.DeadlineExceeded: +- return nil, nil, status.Error(codes.DeadlineExceeded, errStr) ++ return nil, balancer.PickResult{}, status.Error(codes.DeadlineExceeded, errStr) + case context.Canceled: +- return nil, nil, status.Error(codes.Canceled, errStr) ++ return nil, balancer.PickResult{}, status.Error(codes.Canceled, errStr) + } + case <-ch: + } +@@ -124,14 +131,17 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer. + pw.mu.Unlock() + + pickResult, err := p.Pick(info) +- + if err != nil { + if err == balancer.ErrNoSubConnAvailable { + continue + } +- if _, ok := status.FromError(err); ok { ++ if st, ok := status.FromError(err); ok { + // Status error: end the RPC unconditionally with this status. +- return nil, nil, dropError{error: err} ++ // First restrict the code to the list allowed by gRFC A54. ++ if istatus.IsRestrictedControlPlaneCode(st) { ++ err = status.Errorf(codes.Internal, "received picker error with illegal status: %v", err) ++ } ++ return nil, balancer.PickResult{}, dropError{error: err} + } + // For all other errors, wait for ready RPCs should block and other + // RPCs should fail with unavailable. +@@ -139,7 +149,7 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer. + lastPickErr = err + continue + } +- return nil, nil, status.Error(codes.Unavailable, err.Error()) ++ return nil, balancer.PickResult{}, status.Error(codes.Unavailable, err.Error()) + } + + acw, ok := pickResult.SubConn.(*acBalancerWrapper) +@@ -149,9 +159,10 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer. + } + if t := acw.getAddrConn().getReadyTransport(); t != nil { + if channelz.IsOn() { +- return t, doneChannelzWrapper(acw, pickResult.Done), nil ++ doneChannelzWrapper(acw, &pickResult) ++ return t, pickResult, nil + } +- return t, pickResult.Done, nil ++ return t, pickResult, nil + } + if pickResult.Done != nil { + // Calling done with nil error, no bytes sent and no bytes received. +diff --git a/vendor/google.golang.org/grpc/pickfirst.go b/vendor/google.golang.org/grpc/pickfirst.go +index fb7a99e0a273..fc91b4d266de 100644 +--- a/vendor/google.golang.org/grpc/pickfirst.go ++++ b/vendor/google.golang.org/grpc/pickfirst.go +@@ -51,7 +51,7 @@ type pickfirstBalancer struct { + + func (b *pickfirstBalancer) ResolverError(err error) { + if logger.V(2) { +- logger.Infof("pickfirstBalancer: ResolverError called with error %v", err) ++ logger.Infof("pickfirstBalancer: ResolverError called with error: %v", err) + } + if b.subConn == nil { + b.state = connectivity.TransientFailure +@@ -102,8 +102,8 @@ func (b *pickfirstBalancer) UpdateClientConnState(state balancer.ClientConnState + b.subConn = subConn + b.state = connectivity.Idle + b.cc.UpdateState(balancer.State{ +- ConnectivityState: connectivity.Idle, +- Picker: &picker{result: balancer.PickResult{SubConn: b.subConn}}, ++ ConnectivityState: connectivity.Connecting, ++ Picker: &picker{err: balancer.ErrNoSubConnAvailable}, + }) + b.subConn.Connect() + return nil +diff --git a/vendor/google.golang.org/grpc/preloader.go b/vendor/google.golang.org/grpc/preloader.go +index 0a1e975ad916..cd45547854f0 100644 +--- a/vendor/google.golang.org/grpc/preloader.go ++++ b/vendor/google.golang.org/grpc/preloader.go +@@ -25,7 +25,7 @@ import ( + + // PreparedMsg is responsible for creating a Marshalled and Compressed object. + // +-// Experimental ++// # Experimental + // + // Notice: This type is EXPERIMENTAL and may be changed or removed in a + // later release. +diff --git a/vendor/google.golang.org/grpc/regenerate.sh b/vendor/google.golang.org/grpc/regenerate.sh +index 99db79fafcfb..a6f26c8ab0f0 100644 +--- a/vendor/google.golang.org/grpc/regenerate.sh ++++ b/vendor/google.golang.org/grpc/regenerate.sh +@@ -57,7 +57,8 @@ LEGACY_SOURCES=( + ${WORKDIR}/grpc-proto/grpc/health/v1/health.proto + ${WORKDIR}/grpc-proto/grpc/lb/v1/load_balancer.proto + profiling/proto/service.proto +- reflection/grpc_reflection_v1alpha/reflection.proto ++ ${WORKDIR}/grpc-proto/grpc/reflection/v1alpha/reflection.proto ++ ${WORKDIR}/grpc-proto/grpc/reflection/v1/reflection.proto + ) + + # Generates only the new gRPC Service symbols +@@ -119,8 +120,4 @@ mv ${WORKDIR}/out/google.golang.org/grpc/lookup/grpc_lookup_v1/* ${WORKDIR}/out/ + # see grpc_testing_not_regenerate/README.md for details. + rm ${WORKDIR}/out/google.golang.org/grpc/reflection/grpc_testing_not_regenerate/*.pb.go + +-# grpc/testing does not have a go_package option. +-mv ${WORKDIR}/out/grpc/testing/*.pb.go interop/grpc_testing/ +-mv ${WORKDIR}/out/grpc/core/*.pb.go interop/grpc_testing/core/ +- + cp -R ${WORKDIR}/out/google.golang.org/grpc/* . +diff --git a/vendor/google.golang.org/grpc/resolver/resolver.go b/vendor/google.golang.org/grpc/resolver/resolver.go +index ca2e35a3596f..654e9ce69f4a 100644 +--- a/vendor/google.golang.org/grpc/resolver/resolver.go ++++ b/vendor/google.golang.org/grpc/resolver/resolver.go +@@ -24,6 +24,7 @@ import ( + "context" + "net" + "net/url" ++ "strings" + + "google.golang.org/grpc/attributes" + "google.golang.org/grpc/credentials" +@@ -96,7 +97,7 @@ const ( + + // Address represents a server the client connects to. + // +-// Experimental ++// # Experimental + // + // Notice: This type is EXPERIMENTAL and may be changed or removed in a + // later release. +@@ -236,20 +237,17 @@ type ClientConn interface { + // + // Examples: + // +-// - "dns://some_authority/foo.bar" +-// Target{Scheme: "dns", Authority: "some_authority", Endpoint: "foo.bar"} +-// - "foo.bar" +-// Target{Scheme: resolver.GetDefaultScheme(), Endpoint: "foo.bar"} +-// - "unknown_scheme://authority/endpoint" +-// Target{Scheme: resolver.GetDefaultScheme(), Endpoint: "unknown_scheme://authority/endpoint"} ++// - "dns://some_authority/foo.bar" ++// Target{Scheme: "dns", Authority: "some_authority", Endpoint: "foo.bar"} ++// - "foo.bar" ++// Target{Scheme: resolver.GetDefaultScheme(), Endpoint: "foo.bar"} ++// - "unknown_scheme://authority/endpoint" ++// Target{Scheme: resolver.GetDefaultScheme(), Endpoint: "unknown_scheme://authority/endpoint"} + type Target struct { + // Deprecated: use URL.Scheme instead. + Scheme string + // Deprecated: use URL.Host instead. + Authority string +- // Deprecated: use URL.Path or URL.Opaque instead. The latter is set when +- // the former is empty. +- Endpoint string + // URL contains the parsed dial target with an optional default scheme added + // to it if the original dial target contained no scheme or contained an + // unregistered scheme. Any query params specified in the original dial +@@ -257,6 +255,24 @@ type Target struct { + URL url.URL + } + ++// Endpoint retrieves endpoint without leading "/" from either `URL.Path` ++// or `URL.Opaque`. The latter is used when the former is empty. ++func (t Target) Endpoint() string { ++ endpoint := t.URL.Path ++ if endpoint == "" { ++ endpoint = t.URL.Opaque ++ } ++ // For targets of the form "[scheme]://[authority]/endpoint, the endpoint ++ // value returned from url.Parse() contains a leading "/". Although this is ++ // in accordance with RFC 3986, we do not want to break existing resolver ++ // implementations which expect the endpoint without the leading "/". So, we ++ // end up stripping the leading "/" here. But this will result in an ++ // incorrect parsing for something like "unix:///path/to/socket". Since we ++ // own the "unix" resolver, we can workaround in the unix resolver by using ++ // the `URL` field. ++ return strings.TrimPrefix(endpoint, "/") ++} ++ + // Builder creates a resolver that will be used to watch name resolution updates. + type Builder interface { + // Build creates a new resolver for the given target. +diff --git a/vendor/google.golang.org/grpc/rpc_util.go b/vendor/google.golang.org/grpc/rpc_util.go +index 5d407b004b0e..cb7020ebecd7 100644 +--- a/vendor/google.golang.org/grpc/rpc_util.go ++++ b/vendor/google.golang.org/grpc/rpc_util.go +@@ -25,7 +25,6 @@ import ( + "encoding/binary" + "fmt" + "io" +- "io/ioutil" + "math" + "strings" + "sync" +@@ -77,7 +76,7 @@ func NewGZIPCompressorWithLevel(level int) (Compressor, error) { + return &gzipCompressor{ + pool: sync.Pool{ + New: func() interface{} { +- w, err := gzip.NewWriterLevel(ioutil.Discard, level) ++ w, err := gzip.NewWriterLevel(io.Discard, level) + if err != nil { + panic(err) + } +@@ -143,7 +142,7 @@ func (d *gzipDecompressor) Do(r io.Reader) ([]byte, error) { + z.Close() + d.pool.Put(z) + }() +- return ioutil.ReadAll(z) ++ return io.ReadAll(z) + } + + func (d *gzipDecompressor) Type() string { +@@ -198,7 +197,7 @@ func Header(md *metadata.MD) CallOption { + // HeaderCallOption is a CallOption for collecting response header metadata. + // The metadata field will be populated *after* the RPC completes. + // +-// Experimental ++// # Experimental + // + // Notice: This type is EXPERIMENTAL and may be changed or removed in a + // later release. +@@ -220,7 +219,7 @@ func Trailer(md *metadata.MD) CallOption { + // TrailerCallOption is a CallOption for collecting response trailer metadata. + // The metadata field will be populated *after* the RPC completes. + // +-// Experimental ++// # Experimental + // + // Notice: This type is EXPERIMENTAL and may be changed or removed in a + // later release. +@@ -242,7 +241,7 @@ func Peer(p *peer.Peer) CallOption { + // PeerCallOption is a CallOption for collecting the identity of the remote + // peer. The peer field will be populated *after* the RPC completes. + // +-// Experimental ++// # Experimental + // + // Notice: This type is EXPERIMENTAL and may be changed or removed in a + // later release. +@@ -282,7 +281,7 @@ func FailFast(failFast bool) CallOption { + // FailFastCallOption is a CallOption for indicating whether an RPC should fail + // fast or not. + // +-// Experimental ++// # Experimental + // + // Notice: This type is EXPERIMENTAL and may be changed or removed in a + // later release. +@@ -297,7 +296,8 @@ func (o FailFastCallOption) before(c *callInfo) error { + func (o FailFastCallOption) after(c *callInfo, attempt *csAttempt) {} + + // MaxCallRecvMsgSize returns a CallOption which sets the maximum message size +-// in bytes the client can receive. ++// in bytes the client can receive. If this is not set, gRPC uses the default ++// 4MB. + func MaxCallRecvMsgSize(bytes int) CallOption { + return MaxRecvMsgSizeCallOption{MaxRecvMsgSize: bytes} + } +@@ -305,7 +305,7 @@ func MaxCallRecvMsgSize(bytes int) CallOption { + // MaxRecvMsgSizeCallOption is a CallOption that indicates the maximum message + // size in bytes the client can receive. + // +-// Experimental ++// # Experimental + // + // Notice: This type is EXPERIMENTAL and may be changed or removed in a + // later release. +@@ -320,7 +320,8 @@ func (o MaxRecvMsgSizeCallOption) before(c *callInfo) error { + func (o MaxRecvMsgSizeCallOption) after(c *callInfo, attempt *csAttempt) {} + + // MaxCallSendMsgSize returns a CallOption which sets the maximum message size +-// in bytes the client can send. ++// in bytes the client can send. If this is not set, gRPC uses the default ++// `math.MaxInt32`. + func MaxCallSendMsgSize(bytes int) CallOption { + return MaxSendMsgSizeCallOption{MaxSendMsgSize: bytes} + } +@@ -328,7 +329,7 @@ func MaxCallSendMsgSize(bytes int) CallOption { + // MaxSendMsgSizeCallOption is a CallOption that indicates the maximum message + // size in bytes the client can send. + // +-// Experimental ++// # Experimental + // + // Notice: This type is EXPERIMENTAL and may be changed or removed in a + // later release. +@@ -351,7 +352,7 @@ func PerRPCCredentials(creds credentials.PerRPCCredentials) CallOption { + // PerRPCCredsCallOption is a CallOption that indicates the per-RPC + // credentials to use for the call. + // +-// Experimental ++// # Experimental + // + // Notice: This type is EXPERIMENTAL and may be changed or removed in a + // later release. +@@ -369,7 +370,7 @@ func (o PerRPCCredsCallOption) after(c *callInfo, attempt *csAttempt) {} + // sending the request. If WithCompressor is also set, UseCompressor has + // higher priority. + // +-// Experimental ++// # Experimental + // + // Notice: This API is EXPERIMENTAL and may be changed or removed in a + // later release. +@@ -379,7 +380,7 @@ func UseCompressor(name string) CallOption { + + // CompressorCallOption is a CallOption that indicates the compressor to use. + // +-// Experimental ++// # Experimental + // + // Notice: This type is EXPERIMENTAL and may be changed or removed in a + // later release. +@@ -416,7 +417,7 @@ func CallContentSubtype(contentSubtype string) CallOption { + // ContentSubtypeCallOption is a CallOption that indicates the content-subtype + // used for marshaling messages. + // +-// Experimental ++// # Experimental + // + // Notice: This type is EXPERIMENTAL and may be changed or removed in a + // later release. +@@ -444,7 +445,7 @@ func (o ContentSubtypeCallOption) after(c *callInfo, attempt *csAttempt) {} + // This function is provided for advanced users; prefer to use only + // CallContentSubtype to select a registered codec instead. + // +-// Experimental ++// # Experimental + // + // Notice: This API is EXPERIMENTAL and may be changed or removed in a + // later release. +@@ -455,7 +456,7 @@ func ForceCodec(codec encoding.Codec) CallOption { + // ForceCodecCallOption is a CallOption that indicates the codec used for + // marshaling messages. + // +-// Experimental ++// # Experimental + // + // Notice: This type is EXPERIMENTAL and may be changed or removed in a + // later release. +@@ -480,7 +481,7 @@ func CallCustomCodec(codec Codec) CallOption { + // CustomCodecCallOption is a CallOption that indicates the codec used for + // marshaling messages. + // +-// Experimental ++// # Experimental + // + // Notice: This type is EXPERIMENTAL and may be changed or removed in a + // later release. +@@ -497,7 +498,7 @@ func (o CustomCodecCallOption) after(c *callInfo, attempt *csAttempt) {} + // MaxRetryRPCBufferSize returns a CallOption that limits the amount of memory + // used for buffering this RPC's requests for retry purposes. + // +-// Experimental ++// # Experimental + // + // Notice: This API is EXPERIMENTAL and may be changed or removed in a + // later release. +@@ -508,7 +509,7 @@ func MaxRetryRPCBufferSize(bytes int) CallOption { + // MaxRetryRPCBufferSizeCallOption is a CallOption indicating the amount of + // memory to be used for caching this RPC for retry purposes. + // +-// Experimental ++// # Experimental + // + // Notice: This type is EXPERIMENTAL and may be changed or removed in a + // later release. +@@ -548,10 +549,11 @@ type parser struct { + // format. The caller owns the returned msg memory. + // + // If there is an error, possible values are: +-// * io.EOF, when no messages remain +-// * io.ErrUnexpectedEOF +-// * of type transport.ConnectionError +-// * an error from the status package ++// - io.EOF, when no messages remain ++// - io.ErrUnexpectedEOF ++// - of type transport.ConnectionError ++// - an error from the status package ++// + // No other error values or types must be returned, which also means + // that the underlying io.Reader must not return an incompatible + // error. +@@ -710,7 +712,7 @@ func recvAndDecompress(p *parser, s *transport.Stream, dc Decompressor, maxRecei + d, size, err = decompress(compressor, d, maxReceiveMessageSize) + } + if err != nil { +- return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message %v", err) ++ return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message: %v", err) + } + if size > maxReceiveMessageSize { + // TODO: Revisit the error code. Currently keep it consistent with java +@@ -745,7 +747,7 @@ func decompress(compressor encoding.Compressor, d []byte, maxReceiveMessageSize + } + // Read from LimitReader with limit max+1. So if the underlying + // reader is over limit, the result will be bigger than max. +- d, err = ioutil.ReadAll(io.LimitReader(dcReader, int64(maxReceiveMessageSize)+1)) ++ d, err = io.ReadAll(io.LimitReader(dcReader, int64(maxReceiveMessageSize)+1)) + return d, len(d), err + } + +@@ -758,7 +760,7 @@ func recv(p *parser, c baseCodec, s *transport.Stream, dc Decompressor, m interf + return err + } + if err := c.Unmarshal(d, m); err != nil { +- return status.Errorf(codes.Internal, "grpc: failed to unmarshal the received message %v", err) ++ return status.Errorf(codes.Internal, "grpc: failed to unmarshal the received message: %v", err) + } + if payInfo != nil { + payInfo.uncompressedBytes = d +diff --git a/vendor/google.golang.org/grpc/server.go b/vendor/google.golang.org/grpc/server.go +index f4dde72b41f8..d5a6e78be44d 100644 +--- a/vendor/google.golang.org/grpc/server.go ++++ b/vendor/google.golang.org/grpc/server.go +@@ -233,10 +233,11 @@ func newJoinServerOption(opts ...ServerOption) ServerOption { + return &joinServerOption{opts: opts} + } + +-// WriteBufferSize determines how much data can be batched before doing a write on the wire. +-// The corresponding memory allocation for this buffer will be twice the size to keep syscalls low. +-// The default value for this buffer is 32KB. +-// Zero will disable the write buffer such that each write will be on underlying connection. ++// WriteBufferSize determines how much data can be batched before doing a write ++// on the wire. The corresponding memory allocation for this buffer will be ++// twice the size to keep syscalls low. The default value for this buffer is ++// 32KB. Zero or negative values will disable the write buffer such that each ++// write will be on underlying connection. + // Note: A Send call may not directly translate to a write. + func WriteBufferSize(s int) ServerOption { + return newFuncServerOption(func(o *serverOptions) { +@@ -244,11 +245,10 @@ func WriteBufferSize(s int) ServerOption { + }) + } + +-// ReadBufferSize lets you set the size of read buffer, this determines how much data can be read at most +-// for one read syscall. +-// The default value for this buffer is 32KB. +-// Zero will disable read buffer for a connection so data framer can access the underlying +-// conn directly. ++// ReadBufferSize lets you set the size of read buffer, this determines how much ++// data can be read at most for one read syscall. The default value for this ++// buffer is 32KB. Zero or negative values will disable read buffer for a ++// connection so data framer can access the underlying conn directly. + func ReadBufferSize(s int) ServerOption { + return newFuncServerOption(func(o *serverOptions) { + o.readBufferSize = s +@@ -942,7 +942,7 @@ func (s *Server) newHTTP2Transport(c net.Conn) transport.ServerTransport { + } + + func (s *Server) serveStreams(st transport.ServerTransport) { +- defer st.Close() ++ defer st.Close(errors.New("finished serving streams for the server transport")) + var wg sync.WaitGroup + + var roundRobinCounter uint32 +@@ -1008,7 +1008,8 @@ var _ http.Handler = (*Server)(nil) + func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { + st, err := transport.NewServerHandlerTransport(w, r, s.opts.statsHandlers) + if err != nil { +- http.Error(w, err.Error(), http.StatusInternalServerError) ++ // Errors returned from transport.NewServerHandlerTransport have ++ // already been written to w. + return + } + if !s.addConn(listenerAddressForServeHTTP, st) { +@@ -1046,7 +1047,7 @@ func (s *Server) addConn(addr string, st transport.ServerTransport) bool { + s.mu.Lock() + defer s.mu.Unlock() + if s.conns == nil { +- st.Close() ++ st.Close(errors.New("Server.addConn called when server has already been stopped")) + return false + } + if s.drain { +@@ -1150,21 +1151,16 @@ func chainUnaryServerInterceptors(s *Server) { + + func chainUnaryInterceptors(interceptors []UnaryServerInterceptor) UnaryServerInterceptor { + return func(ctx context.Context, req interface{}, info *UnaryServerInfo, handler UnaryHandler) (interface{}, error) { +- // the struct ensures the variables are allocated together, rather than separately, since we +- // know they should be garbage collected together. This saves 1 allocation and decreases +- // time/call by about 10% on the microbenchmark. +- var state struct { +- i int +- next UnaryHandler +- } +- state.next = func(ctx context.Context, req interface{}) (interface{}, error) { +- if state.i == len(interceptors)-1 { +- return interceptors[state.i](ctx, req, info, handler) +- } +- state.i++ +- return interceptors[state.i-1](ctx, req, info, state.next) +- } +- return state.next(ctx, req) ++ return interceptors[0](ctx, req, info, getChainUnaryHandler(interceptors, 0, info, handler)) ++ } ++} ++ ++func getChainUnaryHandler(interceptors []UnaryServerInterceptor, curr int, info *UnaryServerInfo, finalHandler UnaryHandler) UnaryHandler { ++ if curr == len(interceptors)-1 { ++ return finalHandler ++ } ++ return func(ctx context.Context, req interface{}) (interface{}, error) { ++ return interceptors[curr+1](ctx, req, info, getChainUnaryHandler(interceptors, curr+1, info, finalHandler)) + } + } + +@@ -1303,7 +1299,7 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport. + d, err := recvAndDecompress(&parser{r: stream}, stream, dc, s.opts.maxReceiveMessageSize, payInfo, decomp) + if err != nil { + if e := t.WriteStatus(stream, status.Convert(err)); e != nil { +- channelz.Warningf(logger, s.channelzID, "grpc: Server.processUnaryRPC failed to write status %v", e) ++ channelz.Warningf(logger, s.channelzID, "grpc: Server.processUnaryRPC failed to write status: %v", e) + } + return err + } +@@ -1470,21 +1466,16 @@ func chainStreamServerInterceptors(s *Server) { + + func chainStreamInterceptors(interceptors []StreamServerInterceptor) StreamServerInterceptor { + return func(srv interface{}, ss ServerStream, info *StreamServerInfo, handler StreamHandler) error { +- // the struct ensures the variables are allocated together, rather than separately, since we +- // know they should be garbage collected together. This saves 1 allocation and decreases +- // time/call by about 10% on the microbenchmark. +- var state struct { +- i int +- next StreamHandler +- } +- state.next = func(srv interface{}, ss ServerStream) error { +- if state.i == len(interceptors)-1 { +- return interceptors[state.i](srv, ss, info, handler) +- } +- state.i++ +- return interceptors[state.i-1](srv, ss, info, state.next) +- } +- return state.next(srv, ss) ++ return interceptors[0](srv, ss, info, getChainStreamHandler(interceptors, 0, info, handler)) ++ } ++} ++ ++func getChainStreamHandler(interceptors []StreamServerInterceptor, curr int, info *StreamServerInfo, finalHandler StreamHandler) StreamHandler { ++ if curr == len(interceptors)-1 { ++ return finalHandler ++ } ++ return func(srv interface{}, stream ServerStream) error { ++ return interceptors[curr+1](srv, stream, info, getChainStreamHandler(interceptors, curr+1, info, finalHandler)) + } + } + +@@ -1819,7 +1810,7 @@ func (s *Server) Stop() { + } + for _, cs := range conns { + for st := range cs { +- st.Close() ++ st.Close(errors.New("Server.Stop called")) + } + } + if s.opts.numServerWorkers > 0 { +diff --git a/vendor/google.golang.org/grpc/service_config.go b/vendor/google.golang.org/grpc/service_config.go +index 01bbb2025aed..f22acace4253 100644 +--- a/vendor/google.golang.org/grpc/service_config.go ++++ b/vendor/google.golang.org/grpc/service_config.go +@@ -226,7 +226,7 @@ func parseServiceConfig(js string) *serviceconfig.ParseResult { + var rsc jsonSC + err := json.Unmarshal([]byte(js), &rsc) + if err != nil { +- logger.Warningf("grpc: parseServiceConfig error unmarshaling %s due to %v", js, err) ++ logger.Warningf("grpc: unmarshaling service config %s: %v", js, err) + return &serviceconfig.ParseResult{Err: err} + } + sc := ServiceConfig{ +@@ -254,7 +254,7 @@ func parseServiceConfig(js string) *serviceconfig.ParseResult { + } + d, err := parseDuration(m.Timeout) + if err != nil { +- logger.Warningf("grpc: parseServiceConfig error unmarshaling %s due to %v", js, err) ++ logger.Warningf("grpc: unmarshaling service config %s: %v", js, err) + return &serviceconfig.ParseResult{Err: err} + } + +@@ -263,7 +263,7 @@ func parseServiceConfig(js string) *serviceconfig.ParseResult { + Timeout: d, + } + if mc.RetryPolicy, err = convertRetryPolicy(m.RetryPolicy); err != nil { +- logger.Warningf("grpc: parseServiceConfig error unmarshaling %s due to %v", js, err) ++ logger.Warningf("grpc: unmarshaling service config %s: %v", js, err) + return &serviceconfig.ParseResult{Err: err} + } + if m.MaxRequestMessageBytes != nil { +@@ -283,13 +283,13 @@ func parseServiceConfig(js string) *serviceconfig.ParseResult { + for i, n := range *m.Name { + path, err := n.generatePath() + if err != nil { +- logger.Warningf("grpc: parseServiceConfig error unmarshaling %s due to methodConfig[%d]: %v", js, i, err) ++ logger.Warningf("grpc: error unmarshaling service config %s due to methodConfig[%d]: %v", js, i, err) + return &serviceconfig.ParseResult{Err: err} + } + + if _, ok := paths[path]; ok { + err = errDuplicatedName +- logger.Warningf("grpc: parseServiceConfig error unmarshaling %s due to methodConfig[%d]: %v", js, i, err) ++ logger.Warningf("grpc: error unmarshaling service config %s due to methodConfig[%d]: %v", js, i, err) + return &serviceconfig.ParseResult{Err: err} + } + paths[path] = struct{}{} +diff --git a/vendor/google.golang.org/grpc/serviceconfig/serviceconfig.go b/vendor/google.golang.org/grpc/serviceconfig/serviceconfig.go +index 73a2f926613e..35e7a20a04ba 100644 +--- a/vendor/google.golang.org/grpc/serviceconfig/serviceconfig.go ++++ b/vendor/google.golang.org/grpc/serviceconfig/serviceconfig.go +@@ -19,7 +19,7 @@ + // Package serviceconfig defines types and methods for operating on gRPC + // service configs. + // +-// Experimental ++// # Experimental + // + // Notice: This package is EXPERIMENTAL and may be changed or removed in a + // later release. +diff --git a/vendor/google.golang.org/grpc/status/status.go b/vendor/google.golang.org/grpc/status/status.go +index 6d163b6e3842..623be39f26ba 100644 +--- a/vendor/google.golang.org/grpc/status/status.go ++++ b/vendor/google.golang.org/grpc/status/status.go +@@ -76,14 +76,14 @@ func FromProto(s *spb.Status) *Status { + + // FromError returns a Status representation of err. + // +-// - If err was produced by this package or implements the method `GRPCStatus() +-// *Status`, the appropriate Status is returned. ++// - If err was produced by this package or implements the method `GRPCStatus() ++// *Status`, the appropriate Status is returned. + // +-// - If err is nil, a Status is returned with codes.OK and no message. ++// - If err is nil, a Status is returned with codes.OK and no message. + // +-// - Otherwise, err is an error not compatible with this package. In this +-// case, a Status is returned with codes.Unknown and err's Error() message, +-// and ok is false. ++// - Otherwise, err is an error not compatible with this package. In this ++// case, a Status is returned with codes.Unknown and err's Error() message, ++// and ok is false. + func FromError(err error) (s *Status, ok bool) { + if err == nil { + return nil, true +diff --git a/vendor/google.golang.org/grpc/stream.go b/vendor/google.golang.org/grpc/stream.go +index 0c16cfb2ea80..93231af2ac56 100644 +--- a/vendor/google.golang.org/grpc/stream.go ++++ b/vendor/google.golang.org/grpc/stream.go +@@ -39,6 +39,7 @@ import ( + imetadata "google.golang.org/grpc/internal/metadata" + iresolver "google.golang.org/grpc/internal/resolver" + "google.golang.org/grpc/internal/serviceconfig" ++ istatus "google.golang.org/grpc/internal/status" + "google.golang.org/grpc/internal/transport" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/peer" +@@ -195,6 +196,13 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth + rpcInfo := iresolver.RPCInfo{Context: ctx, Method: method} + rpcConfig, err := cc.safeConfigSelector.SelectConfig(rpcInfo) + if err != nil { ++ if st, ok := status.FromError(err); ok { ++ // Restrict the code to the list allowed by gRFC A54. ++ if istatus.IsRestrictedControlPlaneCode(st) { ++ err = status.Errorf(codes.Internal, "config selector returned illegal status: %v", err) ++ } ++ return nil, err ++ } + return nil, toRPCErr(err) + } + +@@ -408,7 +416,7 @@ func (cs *clientStream) newAttemptLocked(isTransparent bool) (*csAttempt, error) + ctx = trace.NewContext(ctx, trInfo.tr) + } + +- if cs.cc.parsedTarget.Scheme == "xds" { ++ if cs.cc.parsedTarget.URL.Scheme == "xds" { + // Add extra metadata (metadata that will be added by transport) to context + // so the balancer can see them. + ctx = grpcutil.WithExtraMetadata(ctx, metadata.Pairs( +@@ -430,7 +438,7 @@ func (a *csAttempt) getTransport() error { + cs := a.cs + + var err error +- a.t, a.done, err = cs.cc.getTransport(a.ctx, cs.callInfo.failFast, cs.callHdr.Method) ++ a.t, a.pickResult, err = cs.cc.getTransport(a.ctx, cs.callInfo.failFast, cs.callHdr.Method) + if err != nil { + if de, ok := err.(dropError); ok { + err = de.error +@@ -447,6 +455,25 @@ func (a *csAttempt) getTransport() error { + func (a *csAttempt) newStream() error { + cs := a.cs + cs.callHdr.PreviousAttempts = cs.numRetries ++ ++ // Merge metadata stored in PickResult, if any, with existing call metadata. ++ // It is safe to overwrite the csAttempt's context here, since all state ++ // maintained in it are local to the attempt. When the attempt has to be ++ // retried, a new instance of csAttempt will be created. ++ if a.pickResult.Metatada != nil { ++ // We currently do not have a function it the metadata package which ++ // merges given metadata with existing metadata in a context. Existing ++ // function `AppendToOutgoingContext()` takes a variadic argument of key ++ // value pairs. ++ // ++ // TODO: Make it possible to retrieve key value pairs from metadata.MD ++ // in a form passable to AppendToOutgoingContext(), or create a version ++ // of AppendToOutgoingContext() that accepts a metadata.MD. ++ md, _ := metadata.FromOutgoingContext(a.ctx) ++ md = metadata.Join(md, a.pickResult.Metatada) ++ a.ctx = metadata.NewOutgoingContext(a.ctx, md) ++ } ++ + s, err := a.t.NewStream(a.ctx, cs.callHdr) + if err != nil { + nse, ok := err.(*transport.NewStreamError) +@@ -521,12 +548,12 @@ type clientStream struct { + // csAttempt implements a single transport stream attempt within a + // clientStream. + type csAttempt struct { +- ctx context.Context +- cs *clientStream +- t transport.ClientTransport +- s *transport.Stream +- p *parser +- done func(balancer.DoneInfo) ++ ctx context.Context ++ cs *clientStream ++ t transport.ClientTransport ++ s *transport.Stream ++ p *parser ++ pickResult balancer.PickResult + + finished bool + dc Decompressor +@@ -744,17 +771,25 @@ func (cs *clientStream) withRetry(op func(a *csAttempt) error, onSuccess func()) + + func (cs *clientStream) Header() (metadata.MD, error) { + var m metadata.MD ++ noHeader := false + err := cs.withRetry(func(a *csAttempt) error { + var err error + m, err = a.s.Header() ++ if err == transport.ErrNoHeaders { ++ noHeader = true ++ return nil ++ } + return toRPCErr(err) + }, cs.commitAttemptLocked) ++ + if err != nil { + cs.finish(err) + return nil, err + } +- if len(cs.binlogs) != 0 && !cs.serverHeaderBinlogged { +- // Only log if binary log is on and header has not been logged. ++ ++ if len(cs.binlogs) != 0 && !cs.serverHeaderBinlogged && !noHeader { ++ // Only log if binary log is on and header has not been logged, and ++ // there is actually headers to log. + logEntry := &binarylog.ServerHeader{ + OnClientSide: true, + Header: m, +@@ -1087,12 +1122,12 @@ func (a *csAttempt) finish(err error) { + tr = a.s.Trailer() + } + +- if a.done != nil { ++ if a.pickResult.Done != nil { + br := false + if a.s != nil { + br = a.s.BytesReceived() + } +- a.done(balancer.DoneInfo{ ++ a.pickResult.Done(balancer.DoneInfo{ + Err: err, + Trailer: tr, + BytesSent: a.s != nil, +@@ -1448,6 +1483,9 @@ type ServerStream interface { + // It is safe to have a goroutine calling SendMsg and another goroutine + // calling RecvMsg on the same stream at the same time, but it is not safe + // to call SendMsg on the same stream in different goroutines. ++ // ++ // It is not safe to modify the message after calling SendMsg. Tracing ++ // libraries and stats handlers may use the message lazily. + SendMsg(m interface{}) error + // RecvMsg blocks until it receives a message into m or the stream is + // done. It returns io.EOF when the client has performed a CloseSend. On +diff --git a/vendor/google.golang.org/grpc/tap/tap.go b/vendor/google.golang.org/grpc/tap/tap.go +index dbf34e6bb5f5..bfa5dfa40e4d 100644 +--- a/vendor/google.golang.org/grpc/tap/tap.go ++++ b/vendor/google.golang.org/grpc/tap/tap.go +@@ -19,7 +19,7 @@ + // Package tap defines the function handles which are executed on the transport + // layer of gRPC-Go and related information. + // +-// Experimental ++// # Experimental + // + // Notice: This API is EXPERIMENTAL and may be changed or removed in a + // later release. +diff --git a/vendor/google.golang.org/grpc/version.go b/vendor/google.golang.org/grpc/version.go +index d472ca64307b..fe552c315be2 100644 +--- a/vendor/google.golang.org/grpc/version.go ++++ b/vendor/google.golang.org/grpc/version.go +@@ -19,4 +19,4 @@ + package grpc + + // Version is the current grpc version. +-const Version = "1.50.1" ++const Version = "1.53.0" +diff --git a/vendor/google.golang.org/grpc/vet.sh b/vendor/google.golang.org/grpc/vet.sh +index c3fc8253b13a..3728aed04fc7 100644 +--- a/vendor/google.golang.org/grpc/vet.sh ++++ b/vendor/google.golang.org/grpc/vet.sh +@@ -66,8 +66,21 @@ elif [[ "$#" -ne 0 ]]; then + die "Unknown argument(s): $*" + fi + ++# - Check that generated proto files are up to date. ++if [[ -z "${VET_SKIP_PROTO}" ]]; then ++ PATH="/home/travis/bin:${PATH}" make proto && \ ++ git status --porcelain 2>&1 | fail_on_output || \ ++ (git status; git --no-pager diff; exit 1) ++fi ++ ++if [[ -n "${VET_ONLY_PROTO}" ]]; then ++ exit 0 ++fi ++ + # - Ensure all source files contain a copyright message. +-not git grep -L "\(Copyright [0-9]\{4,\} gRPC authors\)\|DO NOT EDIT" -- '*.go' ++# (Done in two parts because Darwin "git grep" has broken support for compound ++# exclusion matches.) ++(grep -L "DO NOT EDIT" $(git grep -L "\(Copyright [0-9]\{4,\} gRPC authors\)" -- '*.go') || true) | fail_on_output + + # - Make sure all tests in grpc and grpc/test use leakcheck via Teardown. + not grep 'func Test[^(]' *_test.go +@@ -81,7 +94,7 @@ not git grep -l 'x/net/context' -- "*.go" + git grep -l '"math/rand"' -- "*.go" 2>&1 | not grep -v '^examples\|^stress\|grpcrand\|^benchmark\|wrr_test' + + # - Do not call grpclog directly. Use grpclog.Component instead. +-git grep -l 'grpclog.I\|grpclog.W\|grpclog.E\|grpclog.F\|grpclog.V' -- "*.go" | not grep -v '^grpclog/component.go\|^internal/grpctest/tlogger_test.go' ++git grep -l -e 'grpclog.I' --or -e 'grpclog.W' --or -e 'grpclog.E' --or -e 'grpclog.F' --or -e 'grpclog.V' -- "*.go" | not grep -v '^grpclog/component.go\|^internal/grpctest/tlogger_test.go' + + # - Ensure all ptypes proto packages are renamed when importing. + not git grep "\(import \|^\s*\)\"github.com/golang/protobuf/ptypes/" -- "*.go" +@@ -91,13 +104,6 @@ git grep '"github.com/envoyproxy/go-control-plane/envoy' -- '*.go' ':(exclude)*. + + misspell -error . + +-# - Check that generated proto files are up to date. +-if [[ -z "${VET_SKIP_PROTO}" ]]; then +- PATH="/home/travis/bin:${PATH}" make proto && \ +- git status --porcelain 2>&1 | fail_on_output || \ +- (git status; git --no-pager diff; exit 1) +-fi +- + # - gofmt, goimports, golint (with exceptions for generated code), go vet, + # go mod tidy. + # Perform these checks on each module inside gRPC. +@@ -109,7 +115,7 @@ for MOD_FILE in $(find . -name 'go.mod'); do + goimports -l . 2>&1 | not grep -vE "\.pb\.go" + golint ./... 2>&1 | not grep -vE "/grpc_testing_not_regenerate/.*\.pb\.go:" + +- go mod tidy ++ go mod tidy -compat=1.17 + git status --porcelain 2>&1 | fail_on_output || \ + (git status; git --no-pager diff; exit 1) + popd +@@ -119,8 +125,9 @@ done + # + # TODO(dfawley): don't use deprecated functions in examples or first-party + # plugins. ++# TODO(dfawley): enable ST1019 (duplicate imports) but allow for protobufs. + SC_OUT="$(mktemp)" +-staticcheck -go 1.9 -checks 'inherit,-ST1015' ./... > "${SC_OUT}" || true ++staticcheck -go 1.19 -checks 'inherit,-ST1015,-ST1019,-SA1019' ./... > "${SC_OUT}" || true + # Error if anything other than deprecation warnings are printed. + not grep -v "is deprecated:.*SA1019" "${SC_OUT}" + # Only ignore the following deprecated types/fields/functions. +diff --git a/vendor/google.golang.org/protobuf/encoding/protojson/doc.go b/vendor/google.golang.org/protobuf/encoding/protojson/doc.go +index 00ea2fecfb79..21d5d2cb18e1 100644 +--- a/vendor/google.golang.org/protobuf/encoding/protojson/doc.go ++++ b/vendor/google.golang.org/protobuf/encoding/protojson/doc.go +@@ -4,7 +4,7 @@ + + // Package protojson marshals and unmarshals protocol buffer messages as JSON + // format. It follows the guide at +-// https://developers.google.com/protocol-buffers/docs/proto3#json. ++// https://protobuf.dev/programming-guides/proto3#json. + // + // This package produces a different output than the standard "encoding/json" + // package, which does not operate correctly on protocol buffer messages. +diff --git a/vendor/google.golang.org/protobuf/encoding/protojson/well_known_types.go b/vendor/google.golang.org/protobuf/encoding/protojson/well_known_types.go +index c85f8469480a..6c37d417449a 100644 +--- a/vendor/google.golang.org/protobuf/encoding/protojson/well_known_types.go ++++ b/vendor/google.golang.org/protobuf/encoding/protojson/well_known_types.go +@@ -814,16 +814,22 @@ func (d decoder) unmarshalTimestamp(m protoreflect.Message) error { + return d.unexpectedTokenError(tok) + } + +- t, err := time.Parse(time.RFC3339Nano, tok.ParsedString()) ++ s := tok.ParsedString() ++ t, err := time.Parse(time.RFC3339Nano, s) + if err != nil { + return d.newError(tok.Pos(), "invalid %v value %v", genid.Timestamp_message_fullname, tok.RawString()) + } +- // Validate seconds. No need to validate nanos because time.Parse would have +- // covered that already. ++ // Validate seconds. + secs := t.Unix() + if secs < minTimestampSeconds || secs > maxTimestampSeconds { + return d.newError(tok.Pos(), "%v value out of range: %v", genid.Timestamp_message_fullname, tok.RawString()) + } ++ // Validate subseconds. ++ i := strings.LastIndexByte(s, '.') // start of subsecond field ++ j := strings.LastIndexAny(s, "Z-+") // start of timezone field ++ if i >= 0 && j >= i && j-i > len(".999999999") { ++ return d.newError(tok.Pos(), "invalid %v value %v", genid.Timestamp_message_fullname, tok.RawString()) ++ } + + fds := m.Descriptor().Fields() + fdSeconds := fds.ByNumber(genid.Timestamp_Seconds_field_number) +diff --git a/vendor/google.golang.org/protobuf/encoding/protowire/wire.go b/vendor/google.golang.org/protobuf/encoding/protowire/wire.go +index ce57f57ebd48..f4b4686cf9de 100644 +--- a/vendor/google.golang.org/protobuf/encoding/protowire/wire.go ++++ b/vendor/google.golang.org/protobuf/encoding/protowire/wire.go +@@ -3,7 +3,7 @@ + // license that can be found in the LICENSE file. + + // Package protowire parses and formats the raw wire encoding. +-// See https://developers.google.com/protocol-buffers/docs/encoding. ++// See https://protobuf.dev/programming-guides/encoding. + // + // For marshaling and unmarshaling entire protobuf messages, + // use the "google.golang.org/protobuf/proto" package instead. +@@ -29,12 +29,8 @@ const ( + ) + + // IsValid reports whether the field number is semantically valid. +-// +-// Note that while numbers within the reserved range are semantically invalid, +-// they are syntactically valid in the wire format. +-// Implementations may treat records with reserved field numbers as unknown. + func (n Number) IsValid() bool { +- return MinValidNumber <= n && n < FirstReservedNumber || LastReservedNumber < n && n <= MaxValidNumber ++ return MinValidNumber <= n && n <= MaxValidNumber + } + + // Type represents the wire type. +diff --git a/vendor/google.golang.org/protobuf/internal/encoding/json/decode.go b/vendor/google.golang.org/protobuf/internal/encoding/json/decode.go +index b13fd29e81e6..d043a6ebe0b9 100644 +--- a/vendor/google.golang.org/protobuf/internal/encoding/json/decode.go ++++ b/vendor/google.golang.org/protobuf/internal/encoding/json/decode.go +@@ -294,7 +294,7 @@ func (d *Decoder) isValueNext() bool { + } + + // consumeToken constructs a Token for given Kind with raw value derived from +-// current d.in and given size, and consumes the given size-lenght of it. ++// current d.in and given size, and consumes the given size-length of it. + func (d *Decoder) consumeToken(kind Kind, size int) Token { + tok := Token{ + kind: kind, +diff --git a/vendor/google.golang.org/protobuf/internal/encoding/text/decode.go b/vendor/google.golang.org/protobuf/internal/encoding/text/decode.go +index 427c62d037fc..87853e786d0d 100644 +--- a/vendor/google.golang.org/protobuf/internal/encoding/text/decode.go ++++ b/vendor/google.golang.org/protobuf/internal/encoding/text/decode.go +@@ -412,12 +412,13 @@ func (d *Decoder) parseFieldName() (tok Token, err error) { + // Field number. Identify if input is a valid number that is not negative + // and is decimal integer within 32-bit range. + if num := parseNumber(d.in); num.size > 0 { ++ str := num.string(d.in) + if !num.neg && num.kind == numDec { +- if _, err := strconv.ParseInt(string(d.in[:num.size]), 10, 32); err == nil { ++ if _, err := strconv.ParseInt(str, 10, 32); err == nil { + return d.consumeToken(Name, num.size, uint8(FieldNumber)), nil + } + } +- return Token{}, d.newSyntaxError("invalid field number: %s", d.in[:num.size]) ++ return Token{}, d.newSyntaxError("invalid field number: %s", str) + } + + return Token{}, d.newSyntaxError("invalid field name: %s", errId(d.in)) +diff --git a/vendor/google.golang.org/protobuf/internal/encoding/text/decode_number.go b/vendor/google.golang.org/protobuf/internal/encoding/text/decode_number.go +index 81a5d8c86139..45c81f0298e2 100644 +--- a/vendor/google.golang.org/protobuf/internal/encoding/text/decode_number.go ++++ b/vendor/google.golang.org/protobuf/internal/encoding/text/decode_number.go +@@ -15,17 +15,12 @@ func (d *Decoder) parseNumberValue() (Token, bool) { + if num.neg { + numAttrs |= isNegative + } +- strSize := num.size +- last := num.size - 1 +- if num.kind == numFloat && (d.in[last] == 'f' || d.in[last] == 'F') { +- strSize = last +- } + tok := Token{ + kind: Scalar, + attrs: numberValue, + pos: len(d.orig) - len(d.in), + raw: d.in[:num.size], +- str: string(d.in[:strSize]), ++ str: num.string(d.in), + numAttrs: numAttrs, + } + d.consume(num.size) +@@ -46,6 +41,27 @@ type number struct { + kind uint8 + neg bool + size int ++ // if neg, this is the length of whitespace and comments between ++ // the minus sign and the rest fo the number literal ++ sep int ++} ++ ++func (num number) string(data []byte) string { ++ strSize := num.size ++ last := num.size - 1 ++ if num.kind == numFloat && (data[last] == 'f' || data[last] == 'F') { ++ strSize = last ++ } ++ if num.neg && num.sep > 0 { ++ // strip whitespace/comments between negative sign and the rest ++ strLen := strSize - num.sep ++ str := make([]byte, strLen) ++ str[0] = data[0] ++ copy(str[1:], data[num.sep+1:strSize]) ++ return string(str) ++ } ++ return string(data[:strSize]) ++ + } + + // parseNumber constructs a number object from given input. It allows for the +@@ -67,19 +83,22 @@ func parseNumber(input []byte) number { + } + + // Optional - ++ var sep int + if s[0] == '-' { + neg = true + s = s[1:] + size++ ++ // Consume any whitespace or comments between the ++ // negative sign and the rest of the number ++ lenBefore := len(s) ++ s = consume(s, 0) ++ sep = lenBefore - len(s) ++ size += sep + if len(s) == 0 { + return number{} + } + } + +- // C++ allows for whitespace and comments in between the negative sign and +- // the rest of the number. This logic currently does not but is consistent +- // with v1. +- + switch { + case s[0] == '0': + if len(s) > 1 { +@@ -116,7 +135,7 @@ func parseNumber(input []byte) number { + if len(s) > 0 && !isDelim(s[0]) { + return number{} + } +- return number{kind: kind, neg: neg, size: size} ++ return number{kind: kind, neg: neg, size: size, sep: sep} + } + } + s = s[1:] +@@ -188,5 +207,5 @@ func parseNumber(input []byte) number { + return number{} + } + +- return number{kind: kind, neg: neg, size: size} ++ return number{kind: kind, neg: neg, size: size, sep: sep} + } +diff --git a/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go b/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go +index e3cdf1c20591..5c0e8f73f4e4 100644 +--- a/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go ++++ b/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go +@@ -50,6 +50,7 @@ const ( + FileDescriptorProto_Options_field_name protoreflect.Name = "options" + FileDescriptorProto_SourceCodeInfo_field_name protoreflect.Name = "source_code_info" + FileDescriptorProto_Syntax_field_name protoreflect.Name = "syntax" ++ FileDescriptorProto_Edition_field_name protoreflect.Name = "edition" + + FileDescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.name" + FileDescriptorProto_Package_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.package" +@@ -63,6 +64,7 @@ const ( + FileDescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.options" + FileDescriptorProto_SourceCodeInfo_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.source_code_info" + FileDescriptorProto_Syntax_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.syntax" ++ FileDescriptorProto_Edition_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.edition" + ) + + // Field numbers for google.protobuf.FileDescriptorProto. +@@ -79,6 +81,7 @@ const ( + FileDescriptorProto_Options_field_number protoreflect.FieldNumber = 8 + FileDescriptorProto_SourceCodeInfo_field_number protoreflect.FieldNumber = 9 + FileDescriptorProto_Syntax_field_number protoreflect.FieldNumber = 12 ++ FileDescriptorProto_Edition_field_number protoreflect.FieldNumber = 13 + ) + + // Names for google.protobuf.DescriptorProto. +@@ -494,26 +497,29 @@ const ( + + // Field names for google.protobuf.MessageOptions. + const ( +- MessageOptions_MessageSetWireFormat_field_name protoreflect.Name = "message_set_wire_format" +- MessageOptions_NoStandardDescriptorAccessor_field_name protoreflect.Name = "no_standard_descriptor_accessor" +- MessageOptions_Deprecated_field_name protoreflect.Name = "deprecated" +- MessageOptions_MapEntry_field_name protoreflect.Name = "map_entry" +- MessageOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" ++ MessageOptions_MessageSetWireFormat_field_name protoreflect.Name = "message_set_wire_format" ++ MessageOptions_NoStandardDescriptorAccessor_field_name protoreflect.Name = "no_standard_descriptor_accessor" ++ MessageOptions_Deprecated_field_name protoreflect.Name = "deprecated" ++ MessageOptions_MapEntry_field_name protoreflect.Name = "map_entry" ++ MessageOptions_DeprecatedLegacyJsonFieldConflicts_field_name protoreflect.Name = "deprecated_legacy_json_field_conflicts" ++ MessageOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" + +- MessageOptions_MessageSetWireFormat_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.message_set_wire_format" +- MessageOptions_NoStandardDescriptorAccessor_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.no_standard_descriptor_accessor" +- MessageOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.deprecated" +- MessageOptions_MapEntry_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.map_entry" +- MessageOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.uninterpreted_option" ++ MessageOptions_MessageSetWireFormat_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.message_set_wire_format" ++ MessageOptions_NoStandardDescriptorAccessor_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.no_standard_descriptor_accessor" ++ MessageOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.deprecated" ++ MessageOptions_MapEntry_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.map_entry" ++ MessageOptions_DeprecatedLegacyJsonFieldConflicts_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.deprecated_legacy_json_field_conflicts" ++ MessageOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.uninterpreted_option" + ) + + // Field numbers for google.protobuf.MessageOptions. + const ( +- MessageOptions_MessageSetWireFormat_field_number protoreflect.FieldNumber = 1 +- MessageOptions_NoStandardDescriptorAccessor_field_number protoreflect.FieldNumber = 2 +- MessageOptions_Deprecated_field_number protoreflect.FieldNumber = 3 +- MessageOptions_MapEntry_field_number protoreflect.FieldNumber = 7 +- MessageOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ++ MessageOptions_MessageSetWireFormat_field_number protoreflect.FieldNumber = 1 ++ MessageOptions_NoStandardDescriptorAccessor_field_number protoreflect.FieldNumber = 2 ++ MessageOptions_Deprecated_field_number protoreflect.FieldNumber = 3 ++ MessageOptions_MapEntry_field_number protoreflect.FieldNumber = 7 ++ MessageOptions_DeprecatedLegacyJsonFieldConflicts_field_number protoreflect.FieldNumber = 11 ++ MessageOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 + ) + + // Names for google.protobuf.FieldOptions. +@@ -528,16 +534,24 @@ const ( + FieldOptions_Packed_field_name protoreflect.Name = "packed" + FieldOptions_Jstype_field_name protoreflect.Name = "jstype" + FieldOptions_Lazy_field_name protoreflect.Name = "lazy" ++ FieldOptions_UnverifiedLazy_field_name protoreflect.Name = "unverified_lazy" + FieldOptions_Deprecated_field_name protoreflect.Name = "deprecated" + FieldOptions_Weak_field_name protoreflect.Name = "weak" ++ FieldOptions_DebugRedact_field_name protoreflect.Name = "debug_redact" ++ FieldOptions_Retention_field_name protoreflect.Name = "retention" ++ FieldOptions_Target_field_name protoreflect.Name = "target" + FieldOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" + + FieldOptions_Ctype_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.ctype" + FieldOptions_Packed_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.packed" + FieldOptions_Jstype_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.jstype" + FieldOptions_Lazy_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.lazy" ++ FieldOptions_UnverifiedLazy_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.unverified_lazy" + FieldOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.deprecated" + FieldOptions_Weak_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.weak" ++ FieldOptions_DebugRedact_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.debug_redact" ++ FieldOptions_Retention_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.retention" ++ FieldOptions_Target_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.target" + FieldOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.uninterpreted_option" + ) + +@@ -547,8 +561,12 @@ const ( + FieldOptions_Packed_field_number protoreflect.FieldNumber = 2 + FieldOptions_Jstype_field_number protoreflect.FieldNumber = 6 + FieldOptions_Lazy_field_number protoreflect.FieldNumber = 5 ++ FieldOptions_UnverifiedLazy_field_number protoreflect.FieldNumber = 15 + FieldOptions_Deprecated_field_number protoreflect.FieldNumber = 3 + FieldOptions_Weak_field_number protoreflect.FieldNumber = 10 ++ FieldOptions_DebugRedact_field_number protoreflect.FieldNumber = 16 ++ FieldOptions_Retention_field_number protoreflect.FieldNumber = 17 ++ FieldOptions_Target_field_number protoreflect.FieldNumber = 18 + FieldOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 + ) + +@@ -564,6 +582,18 @@ const ( + FieldOptions_JSType_enum_name = "JSType" + ) + ++// Full and short names for google.protobuf.FieldOptions.OptionRetention. ++const ( ++ FieldOptions_OptionRetention_enum_fullname = "google.protobuf.FieldOptions.OptionRetention" ++ FieldOptions_OptionRetention_enum_name = "OptionRetention" ++) ++ ++// Full and short names for google.protobuf.FieldOptions.OptionTargetType. ++const ( ++ FieldOptions_OptionTargetType_enum_fullname = "google.protobuf.FieldOptions.OptionTargetType" ++ FieldOptions_OptionTargetType_enum_name = "OptionTargetType" ++) ++ + // Names for google.protobuf.OneofOptions. + const ( + OneofOptions_message_name protoreflect.Name = "OneofOptions" +@@ -590,20 +620,23 @@ const ( + + // Field names for google.protobuf.EnumOptions. + const ( +- EnumOptions_AllowAlias_field_name protoreflect.Name = "allow_alias" +- EnumOptions_Deprecated_field_name protoreflect.Name = "deprecated" +- EnumOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" ++ EnumOptions_AllowAlias_field_name protoreflect.Name = "allow_alias" ++ EnumOptions_Deprecated_field_name protoreflect.Name = "deprecated" ++ EnumOptions_DeprecatedLegacyJsonFieldConflicts_field_name protoreflect.Name = "deprecated_legacy_json_field_conflicts" ++ EnumOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" + +- EnumOptions_AllowAlias_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.allow_alias" +- EnumOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.deprecated" +- EnumOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.uninterpreted_option" ++ EnumOptions_AllowAlias_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.allow_alias" ++ EnumOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.deprecated" ++ EnumOptions_DeprecatedLegacyJsonFieldConflicts_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.deprecated_legacy_json_field_conflicts" ++ EnumOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.uninterpreted_option" + ) + + // Field numbers for google.protobuf.EnumOptions. + const ( +- EnumOptions_AllowAlias_field_number protoreflect.FieldNumber = 2 +- EnumOptions_Deprecated_field_number protoreflect.FieldNumber = 3 +- EnumOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ++ EnumOptions_AllowAlias_field_number protoreflect.FieldNumber = 2 ++ EnumOptions_Deprecated_field_number protoreflect.FieldNumber = 3 ++ EnumOptions_DeprecatedLegacyJsonFieldConflicts_field_number protoreflect.FieldNumber = 6 ++ EnumOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 + ) + + // Names for google.protobuf.EnumValueOptions. +@@ -813,11 +846,13 @@ const ( + GeneratedCodeInfo_Annotation_SourceFile_field_name protoreflect.Name = "source_file" + GeneratedCodeInfo_Annotation_Begin_field_name protoreflect.Name = "begin" + GeneratedCodeInfo_Annotation_End_field_name protoreflect.Name = "end" ++ GeneratedCodeInfo_Annotation_Semantic_field_name protoreflect.Name = "semantic" + + GeneratedCodeInfo_Annotation_Path_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.path" + GeneratedCodeInfo_Annotation_SourceFile_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.source_file" + GeneratedCodeInfo_Annotation_Begin_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.begin" + GeneratedCodeInfo_Annotation_End_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.end" ++ GeneratedCodeInfo_Annotation_Semantic_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.semantic" + ) + + // Field numbers for google.protobuf.GeneratedCodeInfo.Annotation. +@@ -826,4 +861,11 @@ const ( + GeneratedCodeInfo_Annotation_SourceFile_field_number protoreflect.FieldNumber = 2 + GeneratedCodeInfo_Annotation_Begin_field_number protoreflect.FieldNumber = 3 + GeneratedCodeInfo_Annotation_End_field_number protoreflect.FieldNumber = 4 ++ GeneratedCodeInfo_Annotation_Semantic_field_number protoreflect.FieldNumber = 5 ++) ++ ++// Full and short names for google.protobuf.GeneratedCodeInfo.Annotation.Semantic. ++const ( ++ GeneratedCodeInfo_Annotation_Semantic_enum_fullname = "google.protobuf.GeneratedCodeInfo.Annotation.Semantic" ++ GeneratedCodeInfo_Annotation_Semantic_enum_name = "Semantic" + ) +diff --git a/vendor/google.golang.org/protobuf/internal/impl/convert.go b/vendor/google.golang.org/protobuf/internal/impl/convert.go +index 11a6128ba56b..185ef2efa5bf 100644 +--- a/vendor/google.golang.org/protobuf/internal/impl/convert.go ++++ b/vendor/google.golang.org/protobuf/internal/impl/convert.go +@@ -59,7 +59,6 @@ func NewConverter(t reflect.Type, fd protoreflect.FieldDescriptor) Converter { + default: + return newSingularConverter(t, fd) + } +- panic(fmt.Sprintf("invalid Go type %v for field %v", t, fd.FullName())) + } + + var ( +diff --git a/vendor/google.golang.org/protobuf/internal/strs/strings_unsafe.go b/vendor/google.golang.org/protobuf/internal/strs/strings_unsafe.go +index fea589c457e9..61a84d34185a 100644 +--- a/vendor/google.golang.org/protobuf/internal/strs/strings_unsafe.go ++++ b/vendor/google.golang.org/protobuf/internal/strs/strings_unsafe.go +@@ -87,7 +87,7 @@ func (sb *Builder) grow(n int) { + // Unlike strings.Builder, we do not need to copy over the contents + // of the old buffer since our builder provides no API for + // retrieving previously created strings. +- sb.buf = make([]byte, 2*(cap(sb.buf)+n)) ++ sb.buf = make([]byte, 0, 2*(cap(sb.buf)+n)) + } + + func (sb *Builder) last(n int) string { +diff --git a/vendor/google.golang.org/protobuf/internal/version/version.go b/vendor/google.golang.org/protobuf/internal/version/version.go +index b480c5010f1d..f7014cd51cd7 100644 +--- a/vendor/google.golang.org/protobuf/internal/version/version.go ++++ b/vendor/google.golang.org/protobuf/internal/version/version.go +@@ -51,8 +51,8 @@ import ( + // 10. Send out the CL for review and submit it. + const ( + Major = 1 +- Minor = 28 +- Patch = 1 ++ Minor = 30 ++ Patch = 0 + PreRelease = "" + ) + +diff --git a/vendor/google.golang.org/protobuf/proto/doc.go b/vendor/google.golang.org/protobuf/proto/doc.go +index 08d2a46f5352..ec71e717fe7d 100644 +--- a/vendor/google.golang.org/protobuf/proto/doc.go ++++ b/vendor/google.golang.org/protobuf/proto/doc.go +@@ -5,16 +5,13 @@ + // Package proto provides functions operating on protocol buffer messages. + // + // For documentation on protocol buffers in general, see: +-// +-// https://developers.google.com/protocol-buffers ++// https://protobuf.dev. + // + // For a tutorial on using protocol buffers with Go, see: +-// +-// https://developers.google.com/protocol-buffers/docs/gotutorial ++// https://protobuf.dev/getting-started/gotutorial. + // + // For a guide to generated Go protocol buffer code, see: +-// +-// https://developers.google.com/protocol-buffers/docs/reference/go-generated ++// https://protobuf.dev/reference/go/go-generated. + // + // # Binary serialization + // +diff --git a/vendor/google.golang.org/protobuf/proto/equal.go b/vendor/google.golang.org/protobuf/proto/equal.go +index 67948dd1df8c..1a0be1b03c73 100644 +--- a/vendor/google.golang.org/protobuf/proto/equal.go ++++ b/vendor/google.golang.org/protobuf/proto/equal.go +@@ -5,30 +5,39 @@ + package proto + + import ( +- "bytes" +- "math" + "reflect" + +- "google.golang.org/protobuf/encoding/protowire" + "google.golang.org/protobuf/reflect/protoreflect" + ) + +-// Equal reports whether two messages are equal. +-// If two messages marshal to the same bytes under deterministic serialization, +-// then Equal is guaranteed to report true. ++// Equal reports whether two messages are equal, ++// by recursively comparing the fields of the message. + // +-// Two messages are equal if they belong to the same message descriptor, +-// have the same set of populated known and extension field values, +-// and the same set of unknown fields values. If either of the top-level +-// messages are invalid, then Equal reports true only if both are invalid. ++// - Bytes fields are equal if they contain identical bytes. ++// Empty bytes (regardless of nil-ness) are considered equal. + // +-// Scalar values are compared with the equivalent of the == operator in Go, +-// except bytes values which are compared using bytes.Equal and +-// floating point values which specially treat NaNs as equal. +-// Message values are compared by recursively calling Equal. +-// Lists are equal if each element value is also equal. +-// Maps are equal if they have the same set of keys, where the pair of values +-// for each key is also equal. ++// - Floating-point fields are equal if they contain the same value. ++// Unlike the == operator, a NaN is equal to another NaN. ++// ++// - Other scalar fields are equal if they contain the same value. ++// ++// - Message fields are equal if they have ++// the same set of populated known and extension field values, and ++// the same set of unknown fields values. ++// ++// - Lists are equal if they are the same length and ++// each corresponding element is equal. ++// ++// - Maps are equal if they have the same set of keys and ++// the corresponding value for each key is equal. ++// ++// An invalid message is not equal to a valid message. ++// An invalid message is only equal to another invalid message of the ++// same type. An invalid message often corresponds to a nil pointer ++// of the concrete message type. For example, (*pb.M)(nil) is not equal ++// to &pb.M{}. ++// If two valid messages marshal to the same bytes under deterministic ++// serialization, then Equal is guaranteed to report true. + func Equal(x, y Message) bool { + if x == nil || y == nil { + return x == nil && y == nil +@@ -42,130 +51,7 @@ func Equal(x, y Message) bool { + if mx.IsValid() != my.IsValid() { + return false + } +- return equalMessage(mx, my) +-} +- +-// equalMessage compares two messages. +-func equalMessage(mx, my protoreflect.Message) bool { +- if mx.Descriptor() != my.Descriptor() { +- return false +- } +- +- nx := 0 +- equal := true +- mx.Range(func(fd protoreflect.FieldDescriptor, vx protoreflect.Value) bool { +- nx++ +- vy := my.Get(fd) +- equal = my.Has(fd) && equalField(fd, vx, vy) +- return equal +- }) +- if !equal { +- return false +- } +- ny := 0 +- my.Range(func(fd protoreflect.FieldDescriptor, vx protoreflect.Value) bool { +- ny++ +- return true +- }) +- if nx != ny { +- return false +- } +- +- return equalUnknown(mx.GetUnknown(), my.GetUnknown()) +-} +- +-// equalField compares two fields. +-func equalField(fd protoreflect.FieldDescriptor, x, y protoreflect.Value) bool { +- switch { +- case fd.IsList(): +- return equalList(fd, x.List(), y.List()) +- case fd.IsMap(): +- return equalMap(fd, x.Map(), y.Map()) +- default: +- return equalValue(fd, x, y) +- } +-} +- +-// equalMap compares two maps. +-func equalMap(fd protoreflect.FieldDescriptor, x, y protoreflect.Map) bool { +- if x.Len() != y.Len() { +- return false +- } +- equal := true +- x.Range(func(k protoreflect.MapKey, vx protoreflect.Value) bool { +- vy := y.Get(k) +- equal = y.Has(k) && equalValue(fd.MapValue(), vx, vy) +- return equal +- }) +- return equal +-} +- +-// equalList compares two lists. +-func equalList(fd protoreflect.FieldDescriptor, x, y protoreflect.List) bool { +- if x.Len() != y.Len() { +- return false +- } +- for i := x.Len() - 1; i >= 0; i-- { +- if !equalValue(fd, x.Get(i), y.Get(i)) { +- return false +- } +- } +- return true +-} +- +-// equalValue compares two singular values. +-func equalValue(fd protoreflect.FieldDescriptor, x, y protoreflect.Value) bool { +- switch fd.Kind() { +- case protoreflect.BoolKind: +- return x.Bool() == y.Bool() +- case protoreflect.EnumKind: +- return x.Enum() == y.Enum() +- case protoreflect.Int32Kind, protoreflect.Sint32Kind, +- protoreflect.Int64Kind, protoreflect.Sint64Kind, +- protoreflect.Sfixed32Kind, protoreflect.Sfixed64Kind: +- return x.Int() == y.Int() +- case protoreflect.Uint32Kind, protoreflect.Uint64Kind, +- protoreflect.Fixed32Kind, protoreflect.Fixed64Kind: +- return x.Uint() == y.Uint() +- case protoreflect.FloatKind, protoreflect.DoubleKind: +- fx := x.Float() +- fy := y.Float() +- if math.IsNaN(fx) || math.IsNaN(fy) { +- return math.IsNaN(fx) && math.IsNaN(fy) +- } +- return fx == fy +- case protoreflect.StringKind: +- return x.String() == y.String() +- case protoreflect.BytesKind: +- return bytes.Equal(x.Bytes(), y.Bytes()) +- case protoreflect.MessageKind, protoreflect.GroupKind: +- return equalMessage(x.Message(), y.Message()) +- default: +- return x.Interface() == y.Interface() +- } +-} +- +-// equalUnknown compares unknown fields by direct comparison on the raw bytes +-// of each individual field number. +-func equalUnknown(x, y protoreflect.RawFields) bool { +- if len(x) != len(y) { +- return false +- } +- if bytes.Equal([]byte(x), []byte(y)) { +- return true +- } +- +- mx := make(map[protoreflect.FieldNumber]protoreflect.RawFields) +- my := make(map[protoreflect.FieldNumber]protoreflect.RawFields) +- for len(x) > 0 { +- fnum, _, n := protowire.ConsumeField(x) +- mx[fnum] = append(mx[fnum], x[:n]...) +- x = x[n:] +- } +- for len(y) > 0 { +- fnum, _, n := protowire.ConsumeField(y) +- my[fnum] = append(my[fnum], y[:n]...) +- y = y[n:] +- } +- return reflect.DeepEqual(mx, my) ++ vx := protoreflect.ValueOfMessage(mx) ++ vy := protoreflect.ValueOfMessage(my) ++ return vx.Equal(vy) + } +diff --git a/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go b/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go +index b03c1223c4a4..54ce326df94e 100644 +--- a/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go ++++ b/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go +@@ -35,6 +35,8 @@ func (p *SourcePath) appendFileDescriptorProto(b []byte) []byte { + b = p.appendSingularField(b, "source_code_info", (*SourcePath).appendSourceCodeInfo) + case 12: + b = p.appendSingularField(b, "syntax", nil) ++ case 13: ++ b = p.appendSingularField(b, "edition", nil) + } + return b + } +@@ -236,6 +238,8 @@ func (p *SourcePath) appendMessageOptions(b []byte) []byte { + b = p.appendSingularField(b, "deprecated", nil) + case 7: + b = p.appendSingularField(b, "map_entry", nil) ++ case 11: ++ b = p.appendSingularField(b, "deprecated_legacy_json_field_conflicts", nil) + case 999: + b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) + } +@@ -279,6 +283,8 @@ func (p *SourcePath) appendEnumOptions(b []byte) []byte { + b = p.appendSingularField(b, "allow_alias", nil) + case 3: + b = p.appendSingularField(b, "deprecated", nil) ++ case 6: ++ b = p.appendSingularField(b, "deprecated_legacy_json_field_conflicts", nil) + case 999: + b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) + } +@@ -345,10 +351,18 @@ func (p *SourcePath) appendFieldOptions(b []byte) []byte { + b = p.appendSingularField(b, "jstype", nil) + case 5: + b = p.appendSingularField(b, "lazy", nil) ++ case 15: ++ b = p.appendSingularField(b, "unverified_lazy", nil) + case 3: + b = p.appendSingularField(b, "deprecated", nil) + case 10: + b = p.appendSingularField(b, "weak", nil) ++ case 16: ++ b = p.appendSingularField(b, "debug_redact", nil) ++ case 17: ++ b = p.appendSingularField(b, "retention", nil) ++ case 18: ++ b = p.appendSingularField(b, "target", nil) + case 999: + b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) + } +diff --git a/vendor/google.golang.org/protobuf/reflect/protoreflect/value.go b/vendor/google.golang.org/protobuf/reflect/protoreflect/value.go +index f31981077827..37601b781997 100644 +--- a/vendor/google.golang.org/protobuf/reflect/protoreflect/value.go ++++ b/vendor/google.golang.org/protobuf/reflect/protoreflect/value.go +@@ -148,7 +148,7 @@ type Message interface { + // be preserved in marshaling or other operations. + IsValid() bool + +- // ProtoMethods returns optional fast-path implementions of various operations. ++ // ProtoMethods returns optional fast-path implementations of various operations. + // This method may return nil. + // + // The returned methods type is identical to +diff --git a/vendor/google.golang.org/protobuf/reflect/protoreflect/value_equal.go b/vendor/google.golang.org/protobuf/reflect/protoreflect/value_equal.go +new file mode 100644 +index 000000000000..591652541f28 +--- /dev/null ++++ b/vendor/google.golang.org/protobuf/reflect/protoreflect/value_equal.go +@@ -0,0 +1,168 @@ ++// Copyright 2022 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package protoreflect ++ ++import ( ++ "bytes" ++ "fmt" ++ "math" ++ "reflect" ++ ++ "google.golang.org/protobuf/encoding/protowire" ++) ++ ++// Equal reports whether v1 and v2 are recursively equal. ++// ++// - Values of different types are always unequal. ++// ++// - Bytes values are equal if they contain identical bytes. ++// Empty bytes (regardless of nil-ness) are considered equal. ++// ++// - Floating point values are equal if they contain the same value. ++// Unlike the == operator, a NaN is equal to another NaN. ++// ++// - Enums are equal if they contain the same number. ++// Since Value does not contain an enum descriptor, ++// enum values do not consider the type of the enum. ++// ++// - Other scalar values are equal if they contain the same value. ++// ++// - Message values are equal if they belong to the same message descriptor, ++// have the same set of populated known and extension field values, ++// and the same set of unknown fields values. ++// ++// - Lists are equal if they are the same length and ++// each corresponding element is equal. ++// ++// - Maps are equal if they have the same set of keys and ++// the corresponding value for each key is equal. ++func (v1 Value) Equal(v2 Value) bool { ++ return equalValue(v1, v2) ++} ++ ++func equalValue(x, y Value) bool { ++ eqType := x.typ == y.typ ++ switch x.typ { ++ case nilType: ++ return eqType ++ case boolType: ++ return eqType && x.Bool() == y.Bool() ++ case int32Type, int64Type: ++ return eqType && x.Int() == y.Int() ++ case uint32Type, uint64Type: ++ return eqType && x.Uint() == y.Uint() ++ case float32Type, float64Type: ++ return eqType && equalFloat(x.Float(), y.Float()) ++ case stringType: ++ return eqType && x.String() == y.String() ++ case bytesType: ++ return eqType && bytes.Equal(x.Bytes(), y.Bytes()) ++ case enumType: ++ return eqType && x.Enum() == y.Enum() ++ default: ++ switch x := x.Interface().(type) { ++ case Message: ++ y, ok := y.Interface().(Message) ++ return ok && equalMessage(x, y) ++ case List: ++ y, ok := y.Interface().(List) ++ return ok && equalList(x, y) ++ case Map: ++ y, ok := y.Interface().(Map) ++ return ok && equalMap(x, y) ++ default: ++ panic(fmt.Sprintf("unknown type: %T", x)) ++ } ++ } ++} ++ ++// equalFloat compares two floats, where NaNs are treated as equal. ++func equalFloat(x, y float64) bool { ++ if math.IsNaN(x) || math.IsNaN(y) { ++ return math.IsNaN(x) && math.IsNaN(y) ++ } ++ return x == y ++} ++ ++// equalMessage compares two messages. ++func equalMessage(mx, my Message) bool { ++ if mx.Descriptor() != my.Descriptor() { ++ return false ++ } ++ ++ nx := 0 ++ equal := true ++ mx.Range(func(fd FieldDescriptor, vx Value) bool { ++ nx++ ++ vy := my.Get(fd) ++ equal = my.Has(fd) && equalValue(vx, vy) ++ return equal ++ }) ++ if !equal { ++ return false ++ } ++ ny := 0 ++ my.Range(func(fd FieldDescriptor, vx Value) bool { ++ ny++ ++ return true ++ }) ++ if nx != ny { ++ return false ++ } ++ ++ return equalUnknown(mx.GetUnknown(), my.GetUnknown()) ++} ++ ++// equalList compares two lists. ++func equalList(x, y List) bool { ++ if x.Len() != y.Len() { ++ return false ++ } ++ for i := x.Len() - 1; i >= 0; i-- { ++ if !equalValue(x.Get(i), y.Get(i)) { ++ return false ++ } ++ } ++ return true ++} ++ ++// equalMap compares two maps. ++func equalMap(x, y Map) bool { ++ if x.Len() != y.Len() { ++ return false ++ } ++ equal := true ++ x.Range(func(k MapKey, vx Value) bool { ++ vy := y.Get(k) ++ equal = y.Has(k) && equalValue(vx, vy) ++ return equal ++ }) ++ return equal ++} ++ ++// equalUnknown compares unknown fields by direct comparison on the raw bytes ++// of each individual field number. ++func equalUnknown(x, y RawFields) bool { ++ if len(x) != len(y) { ++ return false ++ } ++ if bytes.Equal([]byte(x), []byte(y)) { ++ return true ++ } ++ ++ mx := make(map[FieldNumber]RawFields) ++ my := make(map[FieldNumber]RawFields) ++ for len(x) > 0 { ++ fnum, _, n := protowire.ConsumeField(x) ++ mx[fnum] = append(mx[fnum], x[:n]...) ++ x = x[n:] ++ } ++ for len(y) > 0 { ++ fnum, _, n := protowire.ConsumeField(y) ++ my[fnum] = append(my[fnum], y[:n]...) ++ y = y[n:] ++ } ++ return reflect.DeepEqual(mx, my) ++} +diff --git a/vendor/google.golang.org/protobuf/reflect/protoreflect/value_union.go b/vendor/google.golang.org/protobuf/reflect/protoreflect/value_union.go +index ca8e28c5bc8b..08e5ef73fc0e 100644 +--- a/vendor/google.golang.org/protobuf/reflect/protoreflect/value_union.go ++++ b/vendor/google.golang.org/protobuf/reflect/protoreflect/value_union.go +@@ -54,11 +54,11 @@ import ( + // // Append a 0 to a "repeated int32" field. + // // Since the Value returned by Mutable is guaranteed to alias + // // the source message, modifying the Value modifies the message. +-// message.Mutable(fieldDesc).(List).Append(protoreflect.ValueOfInt32(0)) ++// message.Mutable(fieldDesc).List().Append(protoreflect.ValueOfInt32(0)) + // + // // Assign [0] to a "repeated int32" field by creating a new Value, + // // modifying it, and assigning it. +-// list := message.NewField(fieldDesc).(List) ++// list := message.NewField(fieldDesc).List() + // list.Append(protoreflect.ValueOfInt32(0)) + // message.Set(fieldDesc, list) + // // ERROR: Since it is not defined whether Set aliases the source, +diff --git a/vendor/google.golang.org/protobuf/reflect/protoregistry/registry.go b/vendor/google.golang.org/protobuf/reflect/protoregistry/registry.go +index 58352a6978be..aeb559774469 100644 +--- a/vendor/google.golang.org/protobuf/reflect/protoregistry/registry.go ++++ b/vendor/google.golang.org/protobuf/reflect/protoregistry/registry.go +@@ -46,7 +46,7 @@ var conflictPolicy = "panic" // "panic" | "warn" | "ignore" + // It is a variable so that the behavior is easily overridden in another file. + var ignoreConflict = func(d protoreflect.Descriptor, err error) bool { + const env = "GOLANG_PROTOBUF_REGISTRATION_CONFLICT" +- const faq = "https://developers.google.com/protocol-buffers/docs/reference/go/faq#namespace-conflict" ++ const faq = "https://protobuf.dev/reference/go/faq#namespace-conflict" + policy := conflictPolicy + if v := os.Getenv(env); v != "" { + policy = v +diff --git a/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go b/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go +index abe4ab5115bb..dac5671db003 100644 +--- a/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go ++++ b/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go +@@ -406,6 +406,152 @@ func (FieldOptions_JSType) EnumDescriptor() ([]byte, []int) { + return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{12, 1} + } + ++// If set to RETENTION_SOURCE, the option will be omitted from the binary. ++// Note: as of January 2023, support for this is in progress and does not yet ++// have an effect (b/264593489). ++type FieldOptions_OptionRetention int32 ++ ++const ( ++ FieldOptions_RETENTION_UNKNOWN FieldOptions_OptionRetention = 0 ++ FieldOptions_RETENTION_RUNTIME FieldOptions_OptionRetention = 1 ++ FieldOptions_RETENTION_SOURCE FieldOptions_OptionRetention = 2 ++) ++ ++// Enum value maps for FieldOptions_OptionRetention. ++var ( ++ FieldOptions_OptionRetention_name = map[int32]string{ ++ 0: "RETENTION_UNKNOWN", ++ 1: "RETENTION_RUNTIME", ++ 2: "RETENTION_SOURCE", ++ } ++ FieldOptions_OptionRetention_value = map[string]int32{ ++ "RETENTION_UNKNOWN": 0, ++ "RETENTION_RUNTIME": 1, ++ "RETENTION_SOURCE": 2, ++ } ++) ++ ++func (x FieldOptions_OptionRetention) Enum() *FieldOptions_OptionRetention { ++ p := new(FieldOptions_OptionRetention) ++ *p = x ++ return p ++} ++ ++func (x FieldOptions_OptionRetention) String() string { ++ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) ++} ++ ++func (FieldOptions_OptionRetention) Descriptor() protoreflect.EnumDescriptor { ++ return file_google_protobuf_descriptor_proto_enumTypes[5].Descriptor() ++} ++ ++func (FieldOptions_OptionRetention) Type() protoreflect.EnumType { ++ return &file_google_protobuf_descriptor_proto_enumTypes[5] ++} ++ ++func (x FieldOptions_OptionRetention) Number() protoreflect.EnumNumber { ++ return protoreflect.EnumNumber(x) ++} ++ ++// Deprecated: Do not use. ++func (x *FieldOptions_OptionRetention) UnmarshalJSON(b []byte) error { ++ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) ++ if err != nil { ++ return err ++ } ++ *x = FieldOptions_OptionRetention(num) ++ return nil ++} ++ ++// Deprecated: Use FieldOptions_OptionRetention.Descriptor instead. ++func (FieldOptions_OptionRetention) EnumDescriptor() ([]byte, []int) { ++ return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{12, 2} ++} ++ ++// This indicates the types of entities that the field may apply to when used ++// as an option. If it is unset, then the field may be freely used as an ++// option on any kind of entity. Note: as of January 2023, support for this is ++// in progress and does not yet have an effect (b/264593489). ++type FieldOptions_OptionTargetType int32 ++ ++const ( ++ FieldOptions_TARGET_TYPE_UNKNOWN FieldOptions_OptionTargetType = 0 ++ FieldOptions_TARGET_TYPE_FILE FieldOptions_OptionTargetType = 1 ++ FieldOptions_TARGET_TYPE_EXTENSION_RANGE FieldOptions_OptionTargetType = 2 ++ FieldOptions_TARGET_TYPE_MESSAGE FieldOptions_OptionTargetType = 3 ++ FieldOptions_TARGET_TYPE_FIELD FieldOptions_OptionTargetType = 4 ++ FieldOptions_TARGET_TYPE_ONEOF FieldOptions_OptionTargetType = 5 ++ FieldOptions_TARGET_TYPE_ENUM FieldOptions_OptionTargetType = 6 ++ FieldOptions_TARGET_TYPE_ENUM_ENTRY FieldOptions_OptionTargetType = 7 ++ FieldOptions_TARGET_TYPE_SERVICE FieldOptions_OptionTargetType = 8 ++ FieldOptions_TARGET_TYPE_METHOD FieldOptions_OptionTargetType = 9 ++) ++ ++// Enum value maps for FieldOptions_OptionTargetType. ++var ( ++ FieldOptions_OptionTargetType_name = map[int32]string{ ++ 0: "TARGET_TYPE_UNKNOWN", ++ 1: "TARGET_TYPE_FILE", ++ 2: "TARGET_TYPE_EXTENSION_RANGE", ++ 3: "TARGET_TYPE_MESSAGE", ++ 4: "TARGET_TYPE_FIELD", ++ 5: "TARGET_TYPE_ONEOF", ++ 6: "TARGET_TYPE_ENUM", ++ 7: "TARGET_TYPE_ENUM_ENTRY", ++ 8: "TARGET_TYPE_SERVICE", ++ 9: "TARGET_TYPE_METHOD", ++ } ++ FieldOptions_OptionTargetType_value = map[string]int32{ ++ "TARGET_TYPE_UNKNOWN": 0, ++ "TARGET_TYPE_FILE": 1, ++ "TARGET_TYPE_EXTENSION_RANGE": 2, ++ "TARGET_TYPE_MESSAGE": 3, ++ "TARGET_TYPE_FIELD": 4, ++ "TARGET_TYPE_ONEOF": 5, ++ "TARGET_TYPE_ENUM": 6, ++ "TARGET_TYPE_ENUM_ENTRY": 7, ++ "TARGET_TYPE_SERVICE": 8, ++ "TARGET_TYPE_METHOD": 9, ++ } ++) ++ ++func (x FieldOptions_OptionTargetType) Enum() *FieldOptions_OptionTargetType { ++ p := new(FieldOptions_OptionTargetType) ++ *p = x ++ return p ++} ++ ++func (x FieldOptions_OptionTargetType) String() string { ++ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) ++} ++ ++func (FieldOptions_OptionTargetType) Descriptor() protoreflect.EnumDescriptor { ++ return file_google_protobuf_descriptor_proto_enumTypes[6].Descriptor() ++} ++ ++func (FieldOptions_OptionTargetType) Type() protoreflect.EnumType { ++ return &file_google_protobuf_descriptor_proto_enumTypes[6] ++} ++ ++func (x FieldOptions_OptionTargetType) Number() protoreflect.EnumNumber { ++ return protoreflect.EnumNumber(x) ++} ++ ++// Deprecated: Do not use. ++func (x *FieldOptions_OptionTargetType) UnmarshalJSON(b []byte) error { ++ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) ++ if err != nil { ++ return err ++ } ++ *x = FieldOptions_OptionTargetType(num) ++ return nil ++} ++ ++// Deprecated: Use FieldOptions_OptionTargetType.Descriptor instead. ++func (FieldOptions_OptionTargetType) EnumDescriptor() ([]byte, []int) { ++ return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{12, 3} ++} ++ + // Is this method side-effect-free (or safe in HTTP parlance), or idempotent, + // or neither? HTTP based RPC implementation may choose GET verb for safe + // methods, and PUT verb for idempotent methods instead of the default POST. +@@ -442,11 +588,11 @@ func (x MethodOptions_IdempotencyLevel) String() string { + } + + func (MethodOptions_IdempotencyLevel) Descriptor() protoreflect.EnumDescriptor { +- return file_google_protobuf_descriptor_proto_enumTypes[5].Descriptor() ++ return file_google_protobuf_descriptor_proto_enumTypes[7].Descriptor() + } + + func (MethodOptions_IdempotencyLevel) Type() protoreflect.EnumType { +- return &file_google_protobuf_descriptor_proto_enumTypes[5] ++ return &file_google_protobuf_descriptor_proto_enumTypes[7] + } + + func (x MethodOptions_IdempotencyLevel) Number() protoreflect.EnumNumber { +@@ -468,6 +614,70 @@ func (MethodOptions_IdempotencyLevel) EnumDescriptor() ([]byte, []int) { + return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{17, 0} + } + ++// Represents the identified object's effect on the element in the original ++// .proto file. ++type GeneratedCodeInfo_Annotation_Semantic int32 ++ ++const ( ++ // There is no effect or the effect is indescribable. ++ GeneratedCodeInfo_Annotation_NONE GeneratedCodeInfo_Annotation_Semantic = 0 ++ // The element is set or otherwise mutated. ++ GeneratedCodeInfo_Annotation_SET GeneratedCodeInfo_Annotation_Semantic = 1 ++ // An alias to the element is returned. ++ GeneratedCodeInfo_Annotation_ALIAS GeneratedCodeInfo_Annotation_Semantic = 2 ++) ++ ++// Enum value maps for GeneratedCodeInfo_Annotation_Semantic. ++var ( ++ GeneratedCodeInfo_Annotation_Semantic_name = map[int32]string{ ++ 0: "NONE", ++ 1: "SET", ++ 2: "ALIAS", ++ } ++ GeneratedCodeInfo_Annotation_Semantic_value = map[string]int32{ ++ "NONE": 0, ++ "SET": 1, ++ "ALIAS": 2, ++ } ++) ++ ++func (x GeneratedCodeInfo_Annotation_Semantic) Enum() *GeneratedCodeInfo_Annotation_Semantic { ++ p := new(GeneratedCodeInfo_Annotation_Semantic) ++ *p = x ++ return p ++} ++ ++func (x GeneratedCodeInfo_Annotation_Semantic) String() string { ++ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) ++} ++ ++func (GeneratedCodeInfo_Annotation_Semantic) Descriptor() protoreflect.EnumDescriptor { ++ return file_google_protobuf_descriptor_proto_enumTypes[8].Descriptor() ++} ++ ++func (GeneratedCodeInfo_Annotation_Semantic) Type() protoreflect.EnumType { ++ return &file_google_protobuf_descriptor_proto_enumTypes[8] ++} ++ ++func (x GeneratedCodeInfo_Annotation_Semantic) Number() protoreflect.EnumNumber { ++ return protoreflect.EnumNumber(x) ++} ++ ++// Deprecated: Do not use. ++func (x *GeneratedCodeInfo_Annotation_Semantic) UnmarshalJSON(b []byte) error { ++ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) ++ if err != nil { ++ return err ++ } ++ *x = GeneratedCodeInfo_Annotation_Semantic(num) ++ return nil ++} ++ ++// Deprecated: Use GeneratedCodeInfo_Annotation_Semantic.Descriptor instead. ++func (GeneratedCodeInfo_Annotation_Semantic) EnumDescriptor() ([]byte, []int) { ++ return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{20, 0, 0} ++} ++ + // The protocol compiler can output a FileDescriptorSet containing the .proto + // files it parses. + type FileDescriptorSet struct { +@@ -544,8 +754,12 @@ type FileDescriptorProto struct { + // development tools. + SourceCodeInfo *SourceCodeInfo `protobuf:"bytes,9,opt,name=source_code_info,json=sourceCodeInfo" json:"source_code_info,omitempty"` + // The syntax of the proto file. +- // The supported values are "proto2" and "proto3". ++ // The supported values are "proto2", "proto3", and "editions". ++ // ++ // If `edition` is present, this value must be "editions". + Syntax *string `protobuf:"bytes,12,opt,name=syntax" json:"syntax,omitempty"` ++ // The edition of the proto file, which is an opaque string. ++ Edition *string `protobuf:"bytes,13,opt,name=edition" json:"edition,omitempty"` + } + + func (x *FileDescriptorProto) Reset() { +@@ -664,6 +878,13 @@ func (x *FileDescriptorProto) GetSyntax() string { + return "" + } + ++func (x *FileDescriptorProto) GetEdition() string { ++ if x != nil && x.Edition != nil { ++ return *x.Edition ++ } ++ return "" ++} ++ + // Describes a message type. + type DescriptorProto struct { + state protoimpl.MessageState +@@ -860,7 +1081,6 @@ type FieldDescriptorProto struct { + // For booleans, "true" or "false". + // For strings, contains the default text contents (not escaped in any way). + // For bytes, contains the C escaped value. All bytes >= 128 are escaped. +- // TODO(kenton): Base-64 encode? + DefaultValue *string `protobuf:"bytes,7,opt,name=default_value,json=defaultValue" json:"default_value,omitempty"` + // If set, gives the index of a oneof in the containing type's oneof_decl + // list. This field is a member of that oneof. +@@ -1382,22 +1602,22 @@ type FileOptions struct { + // inappropriate because proto packages do not normally start with backwards + // domain names. + JavaPackage *string `protobuf:"bytes,1,opt,name=java_package,json=javaPackage" json:"java_package,omitempty"` +- // If set, all the classes from the .proto file are wrapped in a single +- // outer class with the given name. This applies to both Proto1 +- // (equivalent to the old "--one_java_file" option) and Proto2 (where +- // a .proto always translates to a single class, but you may want to +- // explicitly choose the class name). ++ // Controls the name of the wrapper Java class generated for the .proto file. ++ // That class will always contain the .proto file's getDescriptor() method as ++ // well as any top-level extensions defined in the .proto file. ++ // If java_multiple_files is disabled, then all the other classes from the ++ // .proto file will be nested inside the single wrapper outer class. + JavaOuterClassname *string `protobuf:"bytes,8,opt,name=java_outer_classname,json=javaOuterClassname" json:"java_outer_classname,omitempty"` +- // If set true, then the Java code generator will generate a separate .java ++ // If enabled, then the Java code generator will generate a separate .java + // file for each top-level message, enum, and service defined in the .proto +- // file. Thus, these types will *not* be nested inside the outer class +- // named by java_outer_classname. However, the outer class will still be ++ // file. Thus, these types will *not* be nested inside the wrapper class ++ // named by java_outer_classname. However, the wrapper class will still be + // generated to contain the file's getDescriptor() method as well as any + // top-level extensions defined in the file. + JavaMultipleFiles *bool `protobuf:"varint,10,opt,name=java_multiple_files,json=javaMultipleFiles,def=0" json:"java_multiple_files,omitempty"` + // This option does nothing. + // +- // Deprecated: Do not use. ++ // Deprecated: Marked as deprecated in google/protobuf/descriptor.proto. + JavaGenerateEqualsAndHash *bool `protobuf:"varint,20,opt,name=java_generate_equals_and_hash,json=javaGenerateEqualsAndHash" json:"java_generate_equals_and_hash,omitempty"` + // If set true, then the Java2 code generator will generate code that + // throws an exception whenever an attempt is made to assign a non-UTF-8 +@@ -1531,7 +1751,7 @@ func (x *FileOptions) GetJavaMultipleFiles() bool { + return Default_FileOptions_JavaMultipleFiles + } + +-// Deprecated: Do not use. ++// Deprecated: Marked as deprecated in google/protobuf/descriptor.proto. + func (x *FileOptions) GetJavaGenerateEqualsAndHash() bool { + if x != nil && x.JavaGenerateEqualsAndHash != nil { + return *x.JavaGenerateEqualsAndHash +@@ -1670,10 +1890,12 @@ type MessageOptions struct { + // efficient, has fewer features, and is more complicated. + // + // The message must be defined exactly as follows: +- // message Foo { +- // option message_set_wire_format = true; +- // extensions 4 to max; +- // } ++ // ++ // message Foo { ++ // option message_set_wire_format = true; ++ // extensions 4 to max; ++ // } ++ // + // Note that the message cannot have any defined fields; MessageSets only + // have extensions. + // +@@ -1692,28 +1914,44 @@ type MessageOptions struct { + // for the message, or it will be completely ignored; in the very least, + // this is a formalization for deprecating messages. + Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"` ++ // NOTE: Do not set the option in .proto files. Always use the maps syntax ++ // instead. The option should only be implicitly set by the proto compiler ++ // parser. ++ // + // Whether the message is an automatically generated map entry type for the + // maps field. + // + // For maps fields: +- // map map_field = 1; ++ // ++ // map map_field = 1; ++ // + // The parsed descriptor looks like: +- // message MapFieldEntry { +- // option map_entry = true; +- // optional KeyType key = 1; +- // optional ValueType value = 2; +- // } +- // repeated MapFieldEntry map_field = 1; ++ // ++ // message MapFieldEntry { ++ // option map_entry = true; ++ // optional KeyType key = 1; ++ // optional ValueType value = 2; ++ // } ++ // repeated MapFieldEntry map_field = 1; + // + // Implementations may choose not to generate the map_entry=true message, but + // use a native map in the target language to hold the keys and values. + // The reflection APIs in such implementations still need to work as + // if the field is a repeated message field. +- // +- // NOTE: Do not set the option in .proto files. Always use the maps syntax +- // instead. The option should only be implicitly set by the proto compiler +- // parser. + MapEntry *bool `protobuf:"varint,7,opt,name=map_entry,json=mapEntry" json:"map_entry,omitempty"` ++ // Enable the legacy handling of JSON field name conflicts. This lowercases ++ // and strips underscored from the fields before comparison in proto3 only. ++ // The new behavior takes `json_name` into account and applies to proto2 as ++ // well. ++ // ++ // This should only be used as a temporary measure against broken builds due ++ // to the change in behavior for JSON field name conflicts. ++ // ++ // TODO(b/261750190) This is legacy behavior we plan to remove once downstream ++ // teams have had time to migrate. ++ // ++ // Deprecated: Marked as deprecated in google/protobuf/descriptor.proto. ++ DeprecatedLegacyJsonFieldConflicts *bool `protobuf:"varint,11,opt,name=deprecated_legacy_json_field_conflicts,json=deprecatedLegacyJsonFieldConflicts" json:"deprecated_legacy_json_field_conflicts,omitempty"` + // The parser stores options it doesn't recognize here. See above. + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + } +@@ -1785,6 +2023,14 @@ func (x *MessageOptions) GetMapEntry() bool { + return false + } + ++// Deprecated: Marked as deprecated in google/protobuf/descriptor.proto. ++func (x *MessageOptions) GetDeprecatedLegacyJsonFieldConflicts() bool { ++ if x != nil && x.DeprecatedLegacyJsonFieldConflicts != nil { ++ return *x.DeprecatedLegacyJsonFieldConflicts ++ } ++ return false ++} ++ + func (x *MessageOptions) GetUninterpretedOption() []*UninterpretedOption { + if x != nil { + return x.UninterpretedOption +@@ -1838,7 +2084,6 @@ type FieldOptions struct { + // call from multiple threads concurrently, while non-const methods continue + // to require exclusive access. + // +- // + // Note that implementations may choose not to check required fields within + // a lazy sub-message. That is, calling IsInitialized() on the outer message + // may return true even if the inner message has missing required fields. +@@ -1849,7 +2094,14 @@ type FieldOptions struct { + // implementation must either *always* check its required fields, or *never* + // check its required fields, regardless of whether or not the message has + // been parsed. ++ // ++ // As of May 2022, lazy verifies the contents of the byte stream during ++ // parsing. An invalid byte stream will cause the overall parsing to fail. + Lazy *bool `protobuf:"varint,5,opt,name=lazy,def=0" json:"lazy,omitempty"` ++ // unverified_lazy does no correctness checks on the byte stream. This should ++ // only be used where lazy with verification is prohibitive for performance ++ // reasons. ++ UnverifiedLazy *bool `protobuf:"varint,15,opt,name=unverified_lazy,json=unverifiedLazy,def=0" json:"unverified_lazy,omitempty"` + // Is this field deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for accessors, or it will be completely ignored; in the very least, this +@@ -1857,17 +2109,24 @@ type FieldOptions struct { + Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"` + // For Google-internal migration only. Do not use. + Weak *bool `protobuf:"varint,10,opt,name=weak,def=0" json:"weak,omitempty"` ++ // Indicate that the field value should not be printed out when using debug ++ // formats, e.g. when the field contains sensitive credentials. ++ DebugRedact *bool `protobuf:"varint,16,opt,name=debug_redact,json=debugRedact,def=0" json:"debug_redact,omitempty"` ++ Retention *FieldOptions_OptionRetention `protobuf:"varint,17,opt,name=retention,enum=google.protobuf.FieldOptions_OptionRetention" json:"retention,omitempty"` ++ Target *FieldOptions_OptionTargetType `protobuf:"varint,18,opt,name=target,enum=google.protobuf.FieldOptions_OptionTargetType" json:"target,omitempty"` + // The parser stores options it doesn't recognize here. See above. + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + } + + // Default values for FieldOptions fields. + const ( +- Default_FieldOptions_Ctype = FieldOptions_STRING +- Default_FieldOptions_Jstype = FieldOptions_JS_NORMAL +- Default_FieldOptions_Lazy = bool(false) +- Default_FieldOptions_Deprecated = bool(false) +- Default_FieldOptions_Weak = bool(false) ++ Default_FieldOptions_Ctype = FieldOptions_STRING ++ Default_FieldOptions_Jstype = FieldOptions_JS_NORMAL ++ Default_FieldOptions_Lazy = bool(false) ++ Default_FieldOptions_UnverifiedLazy = bool(false) ++ Default_FieldOptions_Deprecated = bool(false) ++ Default_FieldOptions_Weak = bool(false) ++ Default_FieldOptions_DebugRedact = bool(false) + ) + + func (x *FieldOptions) Reset() { +@@ -1930,6 +2189,13 @@ func (x *FieldOptions) GetLazy() bool { + return Default_FieldOptions_Lazy + } + ++func (x *FieldOptions) GetUnverifiedLazy() bool { ++ if x != nil && x.UnverifiedLazy != nil { ++ return *x.UnverifiedLazy ++ } ++ return Default_FieldOptions_UnverifiedLazy ++} ++ + func (x *FieldOptions) GetDeprecated() bool { + if x != nil && x.Deprecated != nil { + return *x.Deprecated +@@ -1944,6 +2210,27 @@ func (x *FieldOptions) GetWeak() bool { + return Default_FieldOptions_Weak + } + ++func (x *FieldOptions) GetDebugRedact() bool { ++ if x != nil && x.DebugRedact != nil { ++ return *x.DebugRedact ++ } ++ return Default_FieldOptions_DebugRedact ++} ++ ++func (x *FieldOptions) GetRetention() FieldOptions_OptionRetention { ++ if x != nil && x.Retention != nil { ++ return *x.Retention ++ } ++ return FieldOptions_RETENTION_UNKNOWN ++} ++ ++func (x *FieldOptions) GetTarget() FieldOptions_OptionTargetType { ++ if x != nil && x.Target != nil { ++ return *x.Target ++ } ++ return FieldOptions_TARGET_TYPE_UNKNOWN ++} ++ + func (x *FieldOptions) GetUninterpretedOption() []*UninterpretedOption { + if x != nil { + return x.UninterpretedOption +@@ -2014,6 +2301,15 @@ type EnumOptions struct { + // for the enum, or it will be completely ignored; in the very least, this + // is a formalization for deprecating enums. + Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"` ++ // Enable the legacy handling of JSON field name conflicts. This lowercases ++ // and strips underscored from the fields before comparison in proto3 only. ++ // The new behavior takes `json_name` into account and applies to proto2 as ++ // well. ++ // TODO(b/261750190) Remove this legacy behavior once downstream teams have ++ // had time to migrate. ++ // ++ // Deprecated: Marked as deprecated in google/protobuf/descriptor.proto. ++ DeprecatedLegacyJsonFieldConflicts *bool `protobuf:"varint,6,opt,name=deprecated_legacy_json_field_conflicts,json=deprecatedLegacyJsonFieldConflicts" json:"deprecated_legacy_json_field_conflicts,omitempty"` + // The parser stores options it doesn't recognize here. See above. + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + } +@@ -2069,6 +2365,14 @@ func (x *EnumOptions) GetDeprecated() bool { + return Default_EnumOptions_Deprecated + } + ++// Deprecated: Marked as deprecated in google/protobuf/descriptor.proto. ++func (x *EnumOptions) GetDeprecatedLegacyJsonFieldConflicts() bool { ++ if x != nil && x.DeprecatedLegacyJsonFieldConflicts != nil { ++ return *x.DeprecatedLegacyJsonFieldConflicts ++ } ++ return false ++} ++ + func (x *EnumOptions) GetUninterpretedOption() []*UninterpretedOption { + if x != nil { + return x.UninterpretedOption +@@ -2399,43 +2703,48 @@ type SourceCodeInfo struct { + // tools. + // + // For example, say we have a file like: +- // message Foo { +- // optional string foo = 1; +- // } ++ // ++ // message Foo { ++ // optional string foo = 1; ++ // } ++ // + // Let's look at just the field definition: +- // optional string foo = 1; +- // ^ ^^ ^^ ^ ^^^ +- // a bc de f ghi ++ // ++ // optional string foo = 1; ++ // ^ ^^ ^^ ^ ^^^ ++ // a bc de f ghi ++ // + // We have the following locations: +- // span path represents +- // [a,i) [ 4, 0, 2, 0 ] The whole field definition. +- // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). +- // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). +- // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). +- // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). ++ // ++ // span path represents ++ // [a,i) [ 4, 0, 2, 0 ] The whole field definition. ++ // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). ++ // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). ++ // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). ++ // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + // + // Notes: +- // - A location may refer to a repeated field itself (i.e. not to any +- // particular index within it). This is used whenever a set of elements are +- // logically enclosed in a single code segment. For example, an entire +- // extend block (possibly containing multiple extension definitions) will +- // have an outer location whose path refers to the "extensions" repeated +- // field without an index. +- // - Multiple locations may have the same path. This happens when a single +- // logical declaration is spread out across multiple places. The most +- // obvious example is the "extend" block again -- there may be multiple +- // extend blocks in the same scope, each of which will have the same path. +- // - A location's span is not always a subset of its parent's span. For +- // example, the "extendee" of an extension declaration appears at the +- // beginning of the "extend" block and is shared by all extensions within +- // the block. +- // - Just because a location's span is a subset of some other location's span +- // does not mean that it is a descendant. For example, a "group" defines +- // both a type and a field in a single declaration. Thus, the locations +- // corresponding to the type and field and their components will overlap. +- // - Code which tries to interpret locations should probably be designed to +- // ignore those that it doesn't understand, as more types of locations could +- // be recorded in the future. ++ // - A location may refer to a repeated field itself (i.e. not to any ++ // particular index within it). This is used whenever a set of elements are ++ // logically enclosed in a single code segment. For example, an entire ++ // extend block (possibly containing multiple extension definitions) will ++ // have an outer location whose path refers to the "extensions" repeated ++ // field without an index. ++ // - Multiple locations may have the same path. This happens when a single ++ // logical declaration is spread out across multiple places. The most ++ // obvious example is the "extend" block again -- there may be multiple ++ // extend blocks in the same scope, each of which will have the same path. ++ // - A location's span is not always a subset of its parent's span. For ++ // example, the "extendee" of an extension declaration appears at the ++ // beginning of the "extend" block and is shared by all extensions within ++ // the block. ++ // - Just because a location's span is a subset of some other location's span ++ // does not mean that it is a descendant. For example, a "group" defines ++ // both a type and a field in a single declaration. Thus, the locations ++ // corresponding to the type and field and their components will overlap. ++ // - Code which tries to interpret locations should probably be designed to ++ // ignore those that it doesn't understand, as more types of locations could ++ // be recorded in the future. + Location []*SourceCodeInfo_Location `protobuf:"bytes,1,rep,name=location" json:"location,omitempty"` + } + +@@ -2715,8 +3024,8 @@ func (x *EnumDescriptorProto_EnumReservedRange) GetEnd() int32 { + // The name of the uninterpreted option. Each string represents a segment in + // a dot-separated name. is_extension is true iff a segment represents an + // extension (denoted with parentheses in options specs in .proto files). +-// E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents +-// "foo.(bar.baz).qux". ++// E.g.,{ ["foo", false], ["bar.baz", true], ["moo", false] } represents ++// "foo.(bar.baz).moo". + type UninterpretedOption_NamePart struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache +@@ -2781,23 +3090,34 @@ type SourceCodeInfo_Location struct { + // location. + // + // Each element is a field number or an index. They form a path from +- // the root FileDescriptorProto to the place where the definition. For +- // example, this path: +- // [ 4, 3, 2, 7, 1 ] ++ // the root FileDescriptorProto to the place where the definition occurs. ++ // For example, this path: ++ // ++ // [ 4, 3, 2, 7, 1 ] ++ // + // refers to: +- // file.message_type(3) // 4, 3 +- // .field(7) // 2, 7 +- // .name() // 1 ++ // ++ // file.message_type(3) // 4, 3 ++ // .field(7) // 2, 7 ++ // .name() // 1 ++ // + // This is because FileDescriptorProto.message_type has field number 4: +- // repeated DescriptorProto message_type = 4; ++ // ++ // repeated DescriptorProto message_type = 4; ++ // + // and DescriptorProto.field has field number 2: +- // repeated FieldDescriptorProto field = 2; ++ // ++ // repeated FieldDescriptorProto field = 2; ++ // + // and FieldDescriptorProto.name has field number 1: +- // optional string name = 1; ++ // ++ // optional string name = 1; + // + // Thus, the above path gives the location of a field name. If we removed + // the last element: +- // [ 4, 3, 2, 7 ] ++ // ++ // [ 4, 3, 2, 7 ] ++ // + // this path refers to the whole field declaration (from the beginning + // of the label to the terminating semicolon). + Path []int32 `protobuf:"varint,1,rep,packed,name=path" json:"path,omitempty"` +@@ -2826,34 +3146,34 @@ type SourceCodeInfo_Location struct { + // + // Examples: + // +- // optional int32 foo = 1; // Comment attached to foo. +- // // Comment attached to bar. +- // optional int32 bar = 2; ++ // optional int32 foo = 1; // Comment attached to foo. ++ // // Comment attached to bar. ++ // optional int32 bar = 2; + // +- // optional string baz = 3; +- // // Comment attached to baz. +- // // Another line attached to baz. ++ // optional string baz = 3; ++ // // Comment attached to baz. ++ // // Another line attached to baz. + // +- // // Comment attached to qux. +- // // +- // // Another line attached to qux. +- // optional double qux = 4; ++ // // Comment attached to moo. ++ // // ++ // // Another line attached to moo. ++ // optional double moo = 4; + // +- // // Detached comment for corge. This is not leading or trailing comments +- // // to qux or corge because there are blank lines separating it from +- // // both. ++ // // Detached comment for corge. This is not leading or trailing comments ++ // // to moo or corge because there are blank lines separating it from ++ // // both. + // +- // // Detached comment for corge paragraph 2. ++ // // Detached comment for corge paragraph 2. + // +- // optional string corge = 5; +- // /* Block comment attached +- // * to corge. Leading asterisks +- // * will be removed. */ +- // /* Block comment attached to +- // * grault. */ +- // optional int32 grault = 6; ++ // optional string corge = 5; ++ // /* Block comment attached ++ // * to corge. Leading asterisks ++ // * will be removed. */ ++ // /* Block comment attached to ++ // * grault. */ ++ // optional int32 grault = 6; + // +- // // ignored detached comments. ++ // // ignored detached comments. + LeadingComments *string `protobuf:"bytes,3,opt,name=leading_comments,json=leadingComments" json:"leading_comments,omitempty"` + TrailingComments *string `protobuf:"bytes,4,opt,name=trailing_comments,json=trailingComments" json:"trailing_comments,omitempty"` + LeadingDetachedComments []string `protobuf:"bytes,6,rep,name=leading_detached_comments,json=leadingDetachedComments" json:"leading_detached_comments,omitempty"` +@@ -2940,9 +3260,10 @@ type GeneratedCodeInfo_Annotation struct { + // that relates to the identified object. + Begin *int32 `protobuf:"varint,3,opt,name=begin" json:"begin,omitempty"` + // Identifies the ending offset in bytes in the generated code that +- // relates to the identified offset. The end offset should be one past ++ // relates to the identified object. The end offset should be one past + // the last relevant byte (so the length of the text = end - begin). +- End *int32 `protobuf:"varint,4,opt,name=end" json:"end,omitempty"` ++ End *int32 `protobuf:"varint,4,opt,name=end" json:"end,omitempty"` ++ Semantic *GeneratedCodeInfo_Annotation_Semantic `protobuf:"varint,5,opt,name=semantic,enum=google.protobuf.GeneratedCodeInfo_Annotation_Semantic" json:"semantic,omitempty"` + } + + func (x *GeneratedCodeInfo_Annotation) Reset() { +@@ -3005,6 +3326,13 @@ func (x *GeneratedCodeInfo_Annotation) GetEnd() int32 { + return 0 + } + ++func (x *GeneratedCodeInfo_Annotation) GetSemantic() GeneratedCodeInfo_Annotation_Semantic { ++ if x != nil && x.Semantic != nil { ++ return *x.Semantic ++ } ++ return GeneratedCodeInfo_Annotation_NONE ++} ++ + var File_google_protobuf_descriptor_proto protoreflect.FileDescriptor + + var file_google_protobuf_descriptor_proto_rawDesc = []byte{ +@@ -3016,7 +3344,7 @@ var file_google_protobuf_descriptor_proto_rawDesc = []byte{ + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x04, 0x66, 0x69, +- 0x6c, 0x65, 0x22, 0xe4, 0x04, 0x0a, 0x13, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, ++ 0x6c, 0x65, 0x22, 0xfe, 0x04, 0x0a, 0x13, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, + 0x0a, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, +@@ -3054,330 +3382,391 @@ var file_google_protobuf_descriptor_proto_rawDesc = []byte{ + 0x75, 0x66, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, + 0x6f, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, + 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x18, 0x0c, 0x20, 0x01, 0x28, +- 0x09, 0x52, 0x06, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x22, 0xb9, 0x06, 0x0a, 0x0f, 0x44, 0x65, +- 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, +- 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, +- 0x65, 0x12, 0x3b, 0x0a, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, +- 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, +- 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, +- 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x43, +- 0x0a, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, +- 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, +- 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, +- 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, +- 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0b, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x79, +- 0x70, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, +- 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, +- 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x0a, 0x6e, 0x65, 0x73, 0x74, +- 0x65, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x41, 0x0a, 0x09, 0x65, 0x6e, 0x75, 0x6d, 0x5f, 0x74, +- 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, +- 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, +- 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, +- 0x08, 0x65, 0x6e, 0x75, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x58, 0x0a, 0x0f, 0x65, 0x78, 0x74, +- 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x05, 0x20, 0x03, +- 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, ++ 0x09, 0x52, 0x06, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x64, 0x69, ++ 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x64, 0x69, 0x74, ++ 0x69, 0x6f, 0x6e, 0x22, 0xb9, 0x06, 0x0a, 0x0f, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, ++ 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, ++ 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3b, 0x0a, 0x05, 0x66, ++ 0x69, 0x65, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, ++ 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, ++ 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, ++ 0x6f, 0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x43, 0x0a, 0x09, 0x65, 0x78, 0x74, 0x65, ++ 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, ++ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, ++ 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, ++ 0x74, 0x6f, 0x52, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, ++ 0x0b, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x03, ++ 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, +- 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, +- 0x6e, 0x67, 0x65, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, +- 0x6e, 0x67, 0x65, 0x12, 0x44, 0x0a, 0x0a, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x5f, 0x64, 0x65, 0x63, +- 0x6c, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, +- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x44, +- 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x09, +- 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65, 0x63, 0x6c, 0x12, 0x39, 0x0a, 0x07, 0x6f, 0x70, 0x74, +- 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, +- 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x73, +- 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, +- 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x55, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, +- 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x67, ++ 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x0a, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x54, 0x79, 0x70, 0x65, ++ 0x12, 0x41, 0x0a, 0x09, 0x65, 0x6e, 0x75, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, ++ 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, ++ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, ++ 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x08, 0x65, 0x6e, 0x75, 0x6d, 0x54, ++ 0x79, 0x70, 0x65, 0x12, 0x58, 0x0a, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, ++ 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, +- 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, +- 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0d, 0x72, 0x65, +- 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, +- 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x03, +- 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x4e, 0x61, 0x6d, 0x65, +- 0x1a, 0x7a, 0x0a, 0x0e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, +- 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, +- 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, +- 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x40, 0x0a, 0x07, 0x6f, 0x70, +- 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, +- 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x78, +- 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, +- 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x37, 0x0a, 0x0d, +- 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, +- 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, +- 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, +- 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0x7c, 0x0a, 0x15, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, +- 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x58, +- 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, +- 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, +- 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, +- 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, +- 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, +- 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, +- 0x80, 0x80, 0x02, 0x22, 0xc1, 0x06, 0x0a, 0x14, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, +- 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, +- 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, +- 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, +- 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, +- 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, +- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, +- 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, +- 0x61, 0x62, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x3e, 0x0a, 0x04, 0x74, +- 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, +- 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, +- 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, +- 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, +- 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, +- 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x74, 0x65, +- 0x6e, 0x64, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x74, 0x65, +- 0x6e, 0x64, 0x65, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, +- 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x66, +- 0x61, 0x75, 0x6c, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x6e, 0x65, +- 0x6f, 0x66, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, +- 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1b, 0x0a, 0x09, 0x6a, 0x73, +- 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6a, +- 0x73, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, +- 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, +- 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, +- 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, +- 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, +- 0x6e, 0x61, 0x6c, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x70, 0x72, 0x6f, 0x74, 0x6f, +- 0x33, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x22, 0xb6, 0x02, 0x0a, 0x04, 0x54, 0x79, +- 0x70, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x55, 0x42, 0x4c, +- 0x45, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x4c, 0x4f, 0x41, +- 0x54, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x36, +- 0x34, 0x10, 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x49, 0x4e, 0x54, +- 0x36, 0x34, 0x10, 0x04, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, +- 0x33, 0x32, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x58, +- 0x45, 0x44, 0x36, 0x34, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, +- 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, +- 0x5f, 0x42, 0x4f, 0x4f, 0x4c, 0x10, 0x08, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, +- 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, +- 0x5f, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x10, 0x0a, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, +- 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x10, 0x0b, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, +- 0x50, 0x45, 0x5f, 0x42, 0x59, 0x54, 0x45, 0x53, 0x10, 0x0c, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, +- 0x50, 0x45, 0x5f, 0x55, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x0d, 0x12, 0x0d, 0x0a, 0x09, 0x54, +- 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x10, 0x0e, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x59, +- 0x50, 0x45, 0x5f, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x10, 0x0f, 0x12, 0x11, 0x0a, +- 0x0d, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x36, 0x34, 0x10, 0x10, +- 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, +- 0x11, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x54, 0x36, 0x34, +- 0x10, 0x12, 0x22, 0x43, 0x0a, 0x05, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x12, 0x0a, 0x0e, 0x4c, +- 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x10, 0x01, 0x12, +- 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, +- 0x44, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x52, 0x45, 0x50, +- 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x03, 0x22, 0x63, 0x0a, 0x14, 0x4f, 0x6e, 0x65, 0x6f, 0x66, +- 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, +- 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, +- 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, +- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, +- 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, +- 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xe3, 0x02, 0x0a, +- 0x13, 0x45, 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, +- 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, +- 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, +- 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, +- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, +- 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, +- 0x74, 0x6f, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36, 0x0a, 0x07, 0x6f, 0x70, 0x74, +- 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, +- 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, +- 0x6d, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, +- 0x73, 0x12, 0x5d, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x72, 0x61, +- 0x6e, 0x67, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x67, 0x6f, 0x6f, 0x67, +- 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, +- 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, +- 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, +- 0x65, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, +- 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x6e, 0x61, 0x6d, +- 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, +- 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0x3b, 0x0a, 0x11, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x65, 0x73, +- 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, +- 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, +- 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, +- 0x6e, 0x64, 0x22, 0x83, 0x01, 0x0a, 0x18, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, +- 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, +- 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, +- 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, +- 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x07, 0x6f, +- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, +- 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, +- 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, +- 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xa7, 0x01, 0x0a, 0x16, 0x53, 0x65, 0x72, +- 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, +- 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, +- 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, +- 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, +- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, +- 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, +- 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x39, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, +- 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, +- 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, +- 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, +- 0x6e, 0x73, 0x22, 0x89, 0x02, 0x0a, 0x15, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65, 0x73, +- 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, +- 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, +- 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, +- 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, +- 0x1f, 0x0a, 0x0b, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, +- 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x54, 0x79, 0x70, 0x65, +- 0x12, 0x38, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, +- 0x0b, 0x32, 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, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x30, 0x0a, 0x10, 0x63, 0x6c, +- 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x05, +- 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0f, 0x63, 0x6c, 0x69, +- 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x12, 0x30, 0x0a, 0x10, +- 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, +- 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0f, 0x73, +- 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x22, 0x91, +- 0x09, 0x0a, 0x0b, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x21, +- 0x0a, 0x0c, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x01, +- 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6a, 0x61, 0x76, 0x61, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, +- 0x65, 0x12, 0x30, 0x0a, 0x14, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, +- 0x63, 0x6c, 0x61, 0x73, 0x73, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, +- 0x12, 0x6a, 0x61, 0x76, 0x61, 0x4f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x6e, +- 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x6d, 0x75, 0x6c, 0x74, +- 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, +- 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x11, 0x6a, 0x61, 0x76, 0x61, 0x4d, 0x75, 0x6c, +- 0x74, 0x69, 0x70, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x44, 0x0a, 0x1d, 0x6a, 0x61, +- 0x76, 0x61, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x71, 0x75, 0x61, +- 0x6c, 0x73, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x14, 0x20, 0x01, 0x28, +- 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x19, 0x6a, 0x61, 0x76, 0x61, 0x47, 0x65, 0x6e, 0x65, 0x72, +- 0x61, 0x74, 0x65, 0x45, 0x71, 0x75, 0x61, 0x6c, 0x73, 0x41, 0x6e, 0x64, 0x48, 0x61, 0x73, 0x68, +- 0x12, 0x3a, 0x0a, 0x16, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, +- 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x75, 0x74, 0x66, 0x38, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, +- 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x53, 0x74, 0x72, +- 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x74, 0x66, 0x38, 0x12, 0x53, 0x0a, 0x0c, +- 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x18, 0x09, 0x20, 0x01, +- 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, +- 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, +- 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x3a, 0x05, 0x53, +- 0x50, 0x45, 0x45, 0x44, 0x52, 0x0b, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x46, 0x6f, +- 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x6f, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, +- 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x6f, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, +- 0x12, 0x35, 0x0a, 0x13, 0x63, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, +- 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, +- 0x61, 0x6c, 0x73, 0x65, 0x52, 0x11, 0x63, 0x63, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, +- 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x15, 0x6a, 0x61, 0x76, 0x61, 0x5f, +- 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, +- 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x13, 0x6a, +- 0x61, 0x76, 0x61, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, +- 0x65, 0x73, 0x12, 0x35, 0x0a, 0x13, 0x70, 0x79, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, +- 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x3a, +- 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x11, 0x70, 0x79, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, +- 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x14, 0x70, 0x68, 0x70, ++ 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, ++ 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0e, 0x65, ++ 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x44, 0x0a, ++ 0x0a, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x5f, 0x64, 0x65, 0x63, 0x6c, 0x18, 0x08, 0x20, 0x03, 0x28, ++ 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, ++ 0x62, 0x75, 0x66, 0x2e, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, ++ 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x09, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x44, ++ 0x65, 0x63, 0x6c, 0x12, 0x39, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, ++ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, ++ 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, ++ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x55, ++ 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, ++ 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, ++ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, ++ 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, ++ 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, ++ 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, ++ 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, ++ 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0x7a, 0x0a, 0x0e, 0x45, 0x78, ++ 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, ++ 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, ++ 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, ++ 0x03, 0x65, 0x6e, 0x64, 0x12, 0x40, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, ++ 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, ++ 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, ++ 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, ++ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x37, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, ++ 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, ++ 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, ++ 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, ++ 0x7c, 0x0a, 0x15, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, ++ 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, ++ 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, ++ 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, ++ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, ++ 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, ++ 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, ++ 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0xc1, 0x06, ++ 0x0a, 0x14, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, ++ 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, ++ 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, ++ 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, ++ 0x65, 0x72, 0x12, 0x41, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, ++ 0x0e, 0x32, 0x2b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, ++ 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, ++ 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x52, 0x05, ++ 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x3e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, ++ 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, ++ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, ++ 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, ++ 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, ++ 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, ++ 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x18, 0x02, ++ 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x12, 0x23, ++ 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, ++ 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56, 0x61, ++ 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x5f, 0x69, 0x6e, 0x64, ++ 0x65, 0x78, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x49, ++ 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1b, 0x0a, 0x09, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, ++ 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6a, 0x73, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, ++ 0x65, 0x12, 0x37, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, ++ 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, ++ 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, ++ 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x72, ++ 0x6f, 0x74, 0x6f, 0x33, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x18, 0x11, 0x20, ++ 0x01, 0x28, 0x08, 0x52, 0x0e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x4f, 0x70, 0x74, 0x69, 0x6f, ++ 0x6e, 0x61, 0x6c, 0x22, 0xb6, 0x02, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0f, 0x0a, 0x0b, ++ 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x55, 0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x0e, 0x0a, ++ 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x10, 0x02, 0x12, 0x0e, 0x0a, ++ 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x03, 0x12, 0x0f, 0x0a, ++ 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x04, 0x12, 0x0e, ++ 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x05, 0x12, 0x10, ++ 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x58, 0x45, 0x44, 0x36, 0x34, 0x10, 0x06, ++ 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, ++ 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x4f, 0x4f, 0x4c, 0x10, ++ 0x08, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, ++ 0x10, 0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x52, 0x4f, 0x55, 0x50, ++ 0x10, 0x0a, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, ++ 0x47, 0x45, 0x10, 0x0b, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x59, 0x54, ++ 0x45, 0x53, 0x10, 0x0c, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x49, 0x4e, ++ 0x54, 0x33, 0x32, 0x10, 0x0d, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e, ++ 0x55, 0x4d, 0x10, 0x0e, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x46, 0x49, ++ 0x58, 0x45, 0x44, 0x33, 0x32, 0x10, 0x0f, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45, 0x5f, ++ 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x36, 0x34, 0x10, 0x10, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, ++ 0x50, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x11, 0x12, 0x0f, 0x0a, 0x0b, 0x54, ++ 0x59, 0x50, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x12, 0x22, 0x43, 0x0a, 0x05, ++ 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x4f, ++ 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42, ++ 0x45, 0x4c, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, 0x44, 0x10, 0x02, 0x12, 0x12, 0x0a, ++ 0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x52, 0x45, 0x50, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, ++ 0x03, 0x22, 0x63, 0x0a, 0x14, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, ++ 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, ++ 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, ++ 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, ++ 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, ++ 0x2e, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, ++ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xe3, 0x02, 0x0a, 0x13, 0x45, 0x6e, 0x75, 0x6d, 0x44, ++ 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, ++ 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, ++ 0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, ++ 0x0b, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, ++ 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73, ++ 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x05, 0x76, 0x61, ++ 0x6c, 0x75, 0x65, 0x12, 0x36, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, ++ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, ++ 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x4f, 0x70, 0x74, 0x69, 0x6f, ++ 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5d, 0x0a, 0x0e, 0x72, ++ 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x04, 0x20, ++ 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, ++ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, ++ 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x65, ++ 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0d, 0x72, 0x65, 0x73, ++ 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, ++ 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, ++ 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x1a, ++ 0x3b, 0x0a, 0x11, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, ++ 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, ++ 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, ++ 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0x83, 0x01, 0x0a, ++ 0x18, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, ++ 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, ++ 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, ++ 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e, ++ 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, ++ 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, ++ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, ++ 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, ++ 0x6e, 0x73, 0x22, 0xa7, 0x01, 0x0a, 0x16, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, ++ 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, ++ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, ++ 0x65, 0x12, 0x3e, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, ++ 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, ++ 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, ++ 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, ++ 0x64, 0x12, 0x39, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, ++ 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, ++ 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, ++ 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x89, 0x02, 0x0a, ++ 0x15, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, ++ 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, ++ 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e, ++ 0x70, 0x75, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, ++ 0x69, 0x6e, 0x70, 0x75, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x75, 0x74, ++ 0x70, 0x75, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, ++ 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x38, 0x0a, 0x07, 0x6f, 0x70, ++ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 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, 0x52, 0x07, 0x6f, 0x70, 0x74, ++ 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x30, 0x0a, 0x10, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, ++ 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, ++ 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, ++ 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x12, 0x30, 0x0a, 0x10, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, ++ 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, ++ 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, ++ 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x22, 0x91, 0x09, 0x0a, 0x0b, 0x46, 0x69, 0x6c, ++ 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6a, 0x61, 0x76, 0x61, ++ 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, ++ 0x6a, 0x61, 0x76, 0x61, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x6a, ++ 0x61, 0x76, 0x61, 0x5f, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x6e, ++ 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6a, 0x61, 0x76, 0x61, 0x4f, ++ 0x75, 0x74, 0x65, 0x72, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, ++ 0x13, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x66, ++ 0x69, 0x6c, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, ++ 0x65, 0x52, 0x11, 0x6a, 0x61, 0x76, 0x61, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x46, ++ 0x69, 0x6c, 0x65, 0x73, 0x12, 0x44, 0x0a, 0x1d, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x67, 0x65, 0x6e, ++ 0x65, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x73, 0x5f, 0x61, 0x6e, 0x64, ++ 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, ++ 0x19, 0x6a, 0x61, 0x76, 0x61, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x45, 0x71, 0x75, ++ 0x61, 0x6c, 0x73, 0x41, 0x6e, 0x64, 0x48, 0x61, 0x73, 0x68, 0x12, 0x3a, 0x0a, 0x16, 0x6a, 0x61, ++ 0x76, 0x61, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, ++ 0x75, 0x74, 0x66, 0x38, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, ++ 0x65, 0x52, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, ++ 0x63, 0x6b, 0x55, 0x74, 0x66, 0x38, 0x12, 0x53, 0x0a, 0x0c, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, ++ 0x7a, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x67, ++ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, ++ 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6d, ++ 0x69, 0x7a, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x3a, 0x05, 0x53, 0x50, 0x45, 0x45, 0x44, 0x52, 0x0b, ++ 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x46, 0x6f, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x67, ++ 0x6f, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, ++ 0x09, 0x67, 0x6f, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x35, 0x0a, 0x13, 0x63, 0x63, + 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, +- 0x73, 0x18, 0x2a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x12, +- 0x70, 0x68, 0x70, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, +- 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, +- 0x18, 0x17, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, +- 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x2e, 0x0a, 0x10, 0x63, 0x63, 0x5f, +- 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x72, 0x65, 0x6e, 0x61, 0x73, 0x18, 0x1f, 0x20, +- 0x01, 0x28, 0x08, 0x3a, 0x04, 0x74, 0x72, 0x75, 0x65, 0x52, 0x0e, 0x63, 0x63, 0x45, 0x6e, 0x61, +- 0x62, 0x6c, 0x65, 0x41, 0x72, 0x65, 0x6e, 0x61, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6f, 0x62, 0x6a, +- 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x24, +- 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6f, 0x62, 0x6a, 0x63, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x50, +- 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x73, 0x68, 0x61, 0x72, 0x70, 0x5f, +- 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x25, 0x20, 0x01, 0x28, 0x09, 0x52, +- 0x0f, 0x63, 0x73, 0x68, 0x61, 0x72, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, +- 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x77, 0x69, 0x66, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, +- 0x18, 0x27, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x77, 0x69, 0x66, 0x74, 0x50, 0x72, 0x65, +- 0x66, 0x69, 0x78, 0x12, 0x28, 0x0a, 0x10, 0x70, 0x68, 0x70, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, +- 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x28, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, +- 0x68, 0x70, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x23, 0x0a, +- 0x0d, 0x70, 0x68, 0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x29, +- 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x68, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, +- 0x63, 0x65, 0x12, 0x34, 0x0a, 0x16, 0x70, 0x68, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, +- 0x74, 0x61, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x2c, 0x20, 0x01, +- 0x28, 0x09, 0x52, 0x14, 0x70, 0x68, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4e, +- 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x75, 0x62, 0x79, +- 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x2d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, +- 0x72, 0x75, 0x62, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x58, 0x0a, 0x14, 0x75, +- 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, +- 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, +- 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, +- 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, +- 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, +- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x0a, 0x0c, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, +- 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x50, 0x45, 0x45, 0x44, 0x10, 0x01, +- 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x53, 0x49, 0x5a, 0x45, 0x10, 0x02, 0x12, +- 0x10, 0x0a, 0x0c, 0x4c, 0x49, 0x54, 0x45, 0x5f, 0x52, 0x55, 0x4e, 0x54, 0x49, 0x4d, 0x45, 0x10, +- 0x03, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x26, +- 0x10, 0x27, 0x22, 0xd1, 0x02, 0x0a, 0x0e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, +- 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x0a, 0x17, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, +- 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x77, 0x69, 0x72, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, +- 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x14, 0x6d, +- 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x57, 0x69, 0x72, 0x65, 0x46, 0x6f, 0x72, +- 0x6d, 0x61, 0x74, 0x12, 0x4c, 0x0a, 0x1f, 0x6e, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, +- 0x72, 0x64, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x63, +- 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, +- 0x6c, 0x73, 0x65, 0x52, 0x1c, 0x6e, 0x6f, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x44, +- 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, +- 0x72, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, +- 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, +- 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x70, 0x5f, +- 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6d, 0x61, 0x70, +- 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, ++ 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x11, ++ 0x63, 0x63, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, ++ 0x73, 0x12, 0x39, 0x0a, 0x15, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, ++ 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, ++ 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x47, 0x65, 0x6e, ++ 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x35, 0x0a, 0x13, ++ 0x70, 0x79, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, ++ 0x63, 0x65, 0x73, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, ++ 0x52, 0x11, 0x70, 0x79, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, ++ 0x63, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x14, 0x70, 0x68, 0x70, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, ++ 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x2a, 0x20, 0x01, 0x28, ++ 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x12, 0x70, 0x68, 0x70, 0x47, 0x65, 0x6e, ++ 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0a, ++ 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x17, 0x20, 0x01, 0x28, 0x08, ++ 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, ++ 0x74, 0x65, 0x64, 0x12, 0x2e, 0x0a, 0x10, 0x63, 0x63, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, ++ 0x5f, 0x61, 0x72, 0x65, 0x6e, 0x61, 0x73, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x04, 0x74, ++ 0x72, 0x75, 0x65, 0x52, 0x0e, 0x63, 0x63, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x72, 0x65, ++ 0x6e, 0x61, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6f, 0x62, 0x6a, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x73, ++ 0x73, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x24, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, ++ 0x6f, 0x62, 0x6a, 0x63, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, ++ 0x29, 0x0a, 0x10, 0x63, 0x73, 0x68, 0x61, 0x72, 0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, ++ 0x61, 0x63, 0x65, 0x18, 0x25, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x73, 0x68, 0x61, 0x72, ++ 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x77, ++ 0x69, 0x66, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x27, 0x20, 0x01, 0x28, 0x09, ++ 0x52, 0x0b, 0x73, 0x77, 0x69, 0x66, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x28, 0x0a, ++ 0x10, 0x70, 0x68, 0x70, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, ++ 0x78, 0x18, 0x28, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x68, 0x70, 0x43, 0x6c, 0x61, 0x73, ++ 0x73, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x68, 0x70, 0x5f, 0x6e, ++ 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x29, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, ++ 0x70, 0x68, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x16, ++ 0x70, 0x68, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6e, 0x61, 0x6d, ++ 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x2c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x70, 0x68, ++ 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, ++ 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x75, 0x62, 0x79, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, ++ 0x67, 0x65, 0x18, 0x2d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x75, 0x62, 0x79, 0x50, 0x61, ++ 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, + 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, +- 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, +- 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x08, 0x10, 0x09, +- 0x4a, 0x04, 0x08, 0x09, 0x10, 0x0a, 0x22, 0xe2, 0x03, 0x0a, 0x0c, 0x46, 0x69, 0x65, 0x6c, 0x64, +- 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x0a, 0x05, 0x63, 0x74, 0x79, 0x70, 0x65, +- 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, ++ 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, ++ 0x3a, 0x0a, 0x0c, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, ++ 0x09, 0x0a, 0x05, 0x53, 0x50, 0x45, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, ++ 0x44, 0x45, 0x5f, 0x53, 0x49, 0x5a, 0x45, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x4c, 0x49, 0x54, ++ 0x45, 0x5f, 0x52, 0x55, 0x4e, 0x54, 0x49, 0x4d, 0x45, 0x10, 0x03, 0x2a, 0x09, 0x08, 0xe8, 0x07, ++ 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x26, 0x10, 0x27, 0x22, 0xbb, 0x03, 0x0a, ++ 0x0e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, ++ 0x3c, 0x0a, 0x17, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x77, ++ 0x69, 0x72, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, ++ 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x14, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, ++ 0x53, 0x65, 0x74, 0x57, 0x69, 0x72, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x4c, 0x0a, ++ 0x1f, 0x6e, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x5f, 0x64, 0x65, 0x73, ++ 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, ++ 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x1c, 0x6e, ++ 0x6f, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, ++ 0x74, 0x6f, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x12, 0x25, 0x0a, 0x0a, 0x64, ++ 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, ++ 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, ++ 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x70, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, ++ 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, ++ 0x56, 0x0a, 0x26, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6c, 0x65, ++ 0x67, 0x61, 0x63, 0x79, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, ++ 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x42, ++ 0x02, 0x18, 0x01, 0x52, 0x22, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x4c, ++ 0x65, 0x67, 0x61, 0x63, 0x79, 0x4a, 0x73, 0x6f, 0x6e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, ++ 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, ++ 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, ++ 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, ++ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, ++ 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, ++ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, ++ 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x04, ++ 0x10, 0x05, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x4a, 0x04, ++ 0x08, 0x08, 0x10, 0x09, 0x4a, 0x04, 0x08, 0x09, 0x10, 0x0a, 0x22, 0xb7, 0x08, 0x0a, 0x0c, 0x46, ++ 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x0a, 0x05, 0x63, ++ 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x6f, ++ 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, ++ 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x43, 0x54, 0x79, 0x70, 0x65, 0x3a, ++ 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x52, 0x05, 0x63, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, ++ 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, ++ 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x12, 0x47, 0x0a, 0x06, 0x6a, 0x73, 0x74, 0x79, 0x70, 0x65, ++ 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, +- 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x43, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x06, 0x53, 0x54, 0x52, +- 0x49, 0x4e, 0x47, 0x52, 0x05, 0x63, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, +- 0x63, 0x6b, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, 0x61, 0x63, 0x6b, +- 0x65, 0x64, 0x12, 0x47, 0x0a, 0x06, 0x6a, 0x73, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, +- 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, +- 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, +- 0x73, 0x2e, 0x4a, 0x53, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x09, 0x4a, 0x53, 0x5f, 0x4e, 0x4f, 0x52, +- 0x4d, 0x41, 0x4c, 0x52, 0x06, 0x6a, 0x73, 0x74, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x04, 0x6c, +- 0x61, 0x7a, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, +- 0x52, 0x04, 0x6c, 0x61, 0x7a, 0x79, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, +- 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, +- 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, +- 0x04, 0x77, 0x65, 0x61, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, +- 0x73, 0x65, 0x52, 0x04, 0x77, 0x65, 0x61, 0x6b, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, +- 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, +- 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, +- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, +- 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, +- 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, +- 0x6f, 0x6e, 0x22, 0x2f, 0x0a, 0x05, 0x43, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x53, +- 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x43, 0x4f, 0x52, 0x44, 0x10, +- 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x50, 0x49, 0x45, 0x43, +- 0x45, 0x10, 0x02, 0x22, 0x35, 0x0a, 0x06, 0x4a, 0x53, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0d, 0x0a, +- 0x09, 0x4a, 0x53, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, +- 0x4a, 0x53, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4a, +- 0x53, 0x5f, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x10, 0x02, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, +- 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0x73, 0x0a, 0x0c, 0x4f, +- 0x6e, 0x65, 0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, ++ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4a, 0x53, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x09, 0x4a, 0x53, ++ 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x52, 0x06, 0x6a, 0x73, 0x74, 0x79, 0x70, 0x65, 0x12, ++ 0x19, 0x0a, 0x04, 0x6c, 0x61, 0x7a, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, ++ 0x61, 0x6c, 0x73, 0x65, 0x52, 0x04, 0x6c, 0x61, 0x7a, 0x79, 0x12, 0x2e, 0x0a, 0x0f, 0x75, 0x6e, ++ 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x6c, 0x61, 0x7a, 0x79, 0x18, 0x0f, 0x20, ++ 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0e, 0x75, 0x6e, 0x76, 0x65, ++ 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x4c, 0x61, 0x7a, 0x79, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, ++ 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, ++ 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, ++ 0x64, 0x12, 0x19, 0x0a, 0x04, 0x77, 0x65, 0x61, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a, ++ 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x04, 0x77, 0x65, 0x61, 0x6b, 0x12, 0x28, 0x0a, 0x0c, ++ 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x72, 0x65, 0x64, 0x61, 0x63, 0x74, 0x18, 0x10, 0x20, 0x01, ++ 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0b, 0x64, 0x65, 0x62, 0x75, 0x67, ++ 0x52, 0x65, 0x64, 0x61, 0x63, 0x74, 0x12, 0x4b, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x65, 0x6e, 0x74, ++ 0x69, 0x6f, 0x6e, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, ++ 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, ++ 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, ++ 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x72, 0x65, 0x74, 0x65, 0x6e, 0x74, ++ 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x12, 0x20, ++ 0x01, 0x28, 0x0e, 0x32, 0x2e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, ++ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, ++ 0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x54, ++ 0x79, 0x70, 0x65, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x58, 0x0a, 0x14, 0x75, + 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, +- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, +- 0x22, 0xc0, 0x01, 0x0a, 0x0b, 0x45, 0x6e, 0x75, 0x6d, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, +- 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, +- 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x41, 0x6c, 0x69, 0x61, +- 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, +- 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, +- 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, +- 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, +- 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, +- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, +- 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, +- 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, +- 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, +- 0x05, 0x10, 0x06, 0x22, 0x9e, 0x01, 0x0a, 0x10, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, ++ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x2f, 0x0a, 0x05, 0x43, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, ++ 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x43, 0x4f, ++ 0x52, 0x44, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x50, ++ 0x49, 0x45, 0x43, 0x45, 0x10, 0x02, 0x22, 0x35, 0x0a, 0x06, 0x4a, 0x53, 0x54, 0x79, 0x70, 0x65, ++ 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x53, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x00, 0x12, ++ 0x0d, 0x0a, 0x09, 0x4a, 0x53, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0d, ++ 0x0a, 0x09, 0x4a, 0x53, 0x5f, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x10, 0x02, 0x22, 0x55, 0x0a, ++ 0x0f, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, ++ 0x12, 0x15, 0x0a, 0x11, 0x52, 0x45, 0x54, 0x45, 0x4e, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, ++ 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x52, 0x45, 0x54, 0x45, 0x4e, ++ 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x55, 0x4e, 0x54, 0x49, 0x4d, 0x45, 0x10, 0x01, 0x12, 0x14, ++ 0x0a, 0x10, 0x52, 0x45, 0x54, 0x45, 0x4e, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x4f, 0x55, 0x52, ++ 0x43, 0x45, 0x10, 0x02, 0x22, 0x8c, 0x02, 0x0a, 0x10, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, ++ 0x61, 0x72, 0x67, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x41, 0x52, ++ 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, ++ 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, 0x50, ++ 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x1f, 0x0a, 0x1b, 0x54, 0x41, 0x52, 0x47, ++ 0x45, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x58, 0x54, 0x45, 0x4e, 0x53, 0x49, 0x4f, ++ 0x4e, 0x5f, 0x52, 0x41, 0x4e, 0x47, 0x45, 0x10, 0x02, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x41, 0x52, ++ 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, ++ 0x10, 0x03, 0x12, 0x15, 0x0a, 0x11, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, 0x50, ++ 0x45, 0x5f, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x10, 0x04, 0x12, 0x15, 0x0a, 0x11, 0x54, 0x41, 0x52, ++ 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x4e, 0x45, 0x4f, 0x46, 0x10, 0x05, ++ 0x12, 0x14, 0x0a, 0x10, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, ++ 0x45, 0x4e, 0x55, 0x4d, 0x10, 0x06, 0x12, 0x1a, 0x0a, 0x16, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, ++ 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x45, 0x4e, 0x54, 0x52, 0x59, ++ 0x10, 0x07, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, 0x50, ++ 0x45, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x10, 0x08, 0x12, 0x16, 0x0a, 0x12, 0x54, ++ 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, ++ 0x44, 0x10, 0x09, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04, ++ 0x08, 0x04, 0x10, 0x05, 0x22, 0x73, 0x0a, 0x0c, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x4f, 0x70, 0x74, ++ 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, ++ 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, ++ 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, ++ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, ++ 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, ++ 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, ++ 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x98, 0x02, 0x0a, 0x0b, 0x45, 0x6e, ++ 0x75, 0x6d, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x6c, 0x6c, ++ 0x6f, 0x77, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, ++ 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, ++ 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, ++ 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, ++ 0x64, 0x12, 0x56, 0x0a, 0x26, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, ++ 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x66, 0x69, 0x65, 0x6c, ++ 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, ++ 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x22, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, ++ 0x64, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4a, 0x73, 0x6f, 0x6e, 0x46, 0x69, 0x65, 0x6c, 0x64, ++ 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, ++ 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, ++ 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, ++ 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, ++ 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, ++ 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, ++ 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04, ++ 0x08, 0x05, 0x10, 0x06, 0x22, 0x9e, 0x01, 0x0a, 0x10, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, ++ 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, ++ 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, ++ 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, ++ 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, ++ 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, ++ 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, ++ 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, ++ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, ++ 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, ++ 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x9c, 0x01, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, +- 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, ++ 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x21, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, + 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, + 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, + 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, +@@ -3385,97 +3774,95 @@ var file_google_protobuf_descriptor_proto_rawDesc = []byte{ + 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, + 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, +- 0x80, 0x80, 0x80, 0x02, 0x22, 0x9c, 0x01, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, +- 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, +- 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x21, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, +- 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, +- 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, +- 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, ++ 0x80, 0x80, 0x80, 0x02, 0x22, 0xe0, 0x02, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, ++ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, ++ 0x61, 0x74, 0x65, 0x64, 0x18, 0x21, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, ++ 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x71, 0x0a, ++ 0x11, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x6c, 0x65, 0x76, ++ 0x65, 0x6c, 0x18, 0x22, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 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, 0x2e, 0x49, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, ++ 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x3a, 0x13, 0x49, 0x44, 0x45, 0x4d, 0x50, ++ 0x4f, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x52, 0x10, ++ 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, ++ 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, ++ 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, ++ 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, ++ 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, ++ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, ++ 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x50, 0x0a, 0x10, 0x49, 0x64, ++ 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x17, ++ 0x0a, 0x13, 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x55, 0x4e, ++ 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x4e, 0x4f, 0x5f, 0x53, 0x49, ++ 0x44, 0x45, 0x5f, 0x45, 0x46, 0x46, 0x45, 0x43, 0x54, 0x53, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, ++ 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x54, 0x10, 0x02, 0x2a, 0x09, 0x08, 0xe8, ++ 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x9a, 0x03, 0x0a, 0x13, 0x55, 0x6e, 0x69, 0x6e, ++ 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, ++ 0x41, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, +- 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, +- 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, +- 0x80, 0x80, 0x02, 0x22, 0xe0, 0x02, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, +- 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, +- 0x74, 0x65, 0x64, 0x18, 0x21, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, +- 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x71, 0x0a, 0x11, +- 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65, +- 0x6c, 0x18, 0x22, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 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, 0x2e, 0x49, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, +- 0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x3a, 0x13, 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, +- 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x52, 0x10, 0x69, +- 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, +- 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, +- 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, +- 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, +- 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, +- 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, +- 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x50, 0x0a, 0x10, 0x49, 0x64, 0x65, +- 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x17, 0x0a, +- 0x13, 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x4b, +- 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x4e, 0x4f, 0x5f, 0x53, 0x49, 0x44, +- 0x45, 0x5f, 0x45, 0x46, 0x46, 0x45, 0x43, 0x54, 0x53, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x49, +- 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x54, 0x10, 0x02, 0x2a, 0x09, 0x08, 0xe8, 0x07, +- 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x9a, 0x03, 0x0a, 0x13, 0x55, 0x6e, 0x69, 0x6e, 0x74, +- 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, +- 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, +- 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, +- 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, +- 0x6f, 0x6e, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x52, 0x04, 0x6e, 0x61, 0x6d, +- 0x65, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x5f, +- 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x69, 0x64, 0x65, +- 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c, 0x0a, 0x12, +- 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, +- 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, +- 0x76, 0x65, 0x49, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x6e, 0x65, +- 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, +- 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, +- 0x49, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x6f, 0x75, 0x62, +- 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, +- 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x73, +- 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, +- 0x0c, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x27, +- 0x0a, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, +- 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, +- 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x4a, 0x0a, 0x08, 0x4e, 0x61, 0x6d, 0x65, 0x50, +- 0x61, 0x72, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x74, +- 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, +- 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, +- 0x18, 0x02, 0x20, 0x02, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, +- 0x69, 0x6f, 0x6e, 0x22, 0xa7, 0x02, 0x0a, 0x0e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, +- 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x44, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, +- 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, +- 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, +- 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, +- 0x6f, 0x6e, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xce, 0x01, 0x0a, +- 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04, 0x70, 0x61, 0x74, +- 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02, 0x10, 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, +- 0x68, 0x12, 0x16, 0x0a, 0x04, 0x73, 0x70, 0x61, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x05, 0x42, +- 0x02, 0x10, 0x01, 0x52, 0x04, 0x73, 0x70, 0x61, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x6c, 0x65, 0x61, +- 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, +- 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, +- 0x65, 0x6e, 0x74, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, +- 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, +- 0x10, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, +- 0x73, 0x12, 0x3a, 0x0a, 0x19, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x74, +- 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, +- 0x20, 0x03, 0x28, 0x09, 0x52, 0x17, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x74, +- 0x61, 0x63, 0x68, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xd1, 0x01, +- 0x0a, 0x11, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, +- 0x6e, 0x66, 0x6f, 0x12, 0x4d, 0x0a, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, +- 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, +- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, +- 0x74, 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, +- 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, +- 0x6f, 0x6e, 0x1a, 0x6d, 0x0a, 0x0a, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, +- 0x12, 0x16, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02, +- 0x10, 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, +- 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, +- 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x65, 0x67, +- 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x12, +- 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, +- 0x64, 0x42, 0x7e, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, ++ 0x69, 0x6f, 0x6e, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x52, 0x04, 0x6e, 0x61, ++ 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, ++ 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x69, 0x64, ++ 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c, 0x0a, ++ 0x12, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, ++ 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x70, 0x6f, 0x73, 0x69, 0x74, ++ 0x69, 0x76, 0x65, 0x49, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x6e, ++ 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, ++ 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, ++ 0x65, 0x49, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x6f, 0x75, ++ 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, ++ 0x0b, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, ++ 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, ++ 0x28, 0x0c, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, ++ 0x27, 0x0a, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, ++ 0x75, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, ++ 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x4a, 0x0a, 0x08, 0x4e, 0x61, 0x6d, 0x65, ++ 0x50, 0x61, 0x72, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x70, 0x61, 0x72, ++ 0x74, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, ++ 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, ++ 0x6e, 0x18, 0x02, 0x20, 0x02, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x45, 0x78, 0x74, 0x65, 0x6e, ++ 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xa7, 0x02, 0x0a, 0x0e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, ++ 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x44, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, ++ 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67, ++ 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f, 0x75, 0x72, ++ 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, ++ 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xce, 0x01, ++ 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04, 0x70, 0x61, ++ 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02, 0x10, 0x01, 0x52, 0x04, 0x70, 0x61, ++ 0x74, 0x68, 0x12, 0x16, 0x0a, 0x04, 0x73, 0x70, 0x61, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x05, ++ 0x42, 0x02, 0x10, 0x01, 0x52, 0x04, 0x73, 0x70, 0x61, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x6c, 0x65, ++ 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, ++ 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, ++ 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, ++ 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, ++ 0x52, 0x10, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, ++ 0x74, 0x73, 0x12, 0x3a, 0x0a, 0x19, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, ++ 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, ++ 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x17, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, ++ 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xd0, ++ 0x02, 0x0a, 0x11, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, ++ 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x4d, 0x0a, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, ++ 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, ++ 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, ++ 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x41, 0x6e, 0x6e, ++ 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, ++ 0x69, 0x6f, 0x6e, 0x1a, 0xeb, 0x01, 0x0a, 0x0a, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, ++ 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, ++ 0x42, 0x02, 0x10, 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x6f, ++ 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, ++ 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x62, ++ 0x65, 0x67, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x62, 0x65, 0x67, 0x69, ++ 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, ++ 0x65, 0x6e, 0x64, 0x12, 0x52, 0x0a, 0x08, 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x18, ++ 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, ++ 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, ++ 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, ++ 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x52, 0x08, 0x73, ++ 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x22, 0x28, 0x0a, 0x08, 0x53, 0x65, 0x6d, 0x61, 0x6e, ++ 0x74, 0x69, 0x63, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x07, 0x0a, ++ 0x03, 0x53, 0x45, 0x54, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x4c, 0x49, 0x41, 0x53, 0x10, ++ 0x02, 0x42, 0x7e, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x42, 0x10, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x48, 0x01, 0x5a, 0x2d, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, +@@ -3498,7 +3885,7 @@ func file_google_protobuf_descriptor_proto_rawDescGZIP() []byte { + return file_google_protobuf_descriptor_proto_rawDescData + } + +-var file_google_protobuf_descriptor_proto_enumTypes = make([]protoimpl.EnumInfo, 6) ++var file_google_protobuf_descriptor_proto_enumTypes = make([]protoimpl.EnumInfo, 9) + var file_google_protobuf_descriptor_proto_msgTypes = make([]protoimpl.MessageInfo, 27) + var file_google_protobuf_descriptor_proto_goTypes = []interface{}{ + (FieldDescriptorProto_Type)(0), // 0: google.protobuf.FieldDescriptorProto.Type +@@ -3506,84 +3893,90 @@ var file_google_protobuf_descriptor_proto_goTypes = []interface{}{ + (FileOptions_OptimizeMode)(0), // 2: google.protobuf.FileOptions.OptimizeMode + (FieldOptions_CType)(0), // 3: google.protobuf.FieldOptions.CType + (FieldOptions_JSType)(0), // 4: google.protobuf.FieldOptions.JSType +- (MethodOptions_IdempotencyLevel)(0), // 5: google.protobuf.MethodOptions.IdempotencyLevel +- (*FileDescriptorSet)(nil), // 6: google.protobuf.FileDescriptorSet +- (*FileDescriptorProto)(nil), // 7: google.protobuf.FileDescriptorProto +- (*DescriptorProto)(nil), // 8: google.protobuf.DescriptorProto +- (*ExtensionRangeOptions)(nil), // 9: google.protobuf.ExtensionRangeOptions +- (*FieldDescriptorProto)(nil), // 10: google.protobuf.FieldDescriptorProto +- (*OneofDescriptorProto)(nil), // 11: google.protobuf.OneofDescriptorProto +- (*EnumDescriptorProto)(nil), // 12: google.protobuf.EnumDescriptorProto +- (*EnumValueDescriptorProto)(nil), // 13: google.protobuf.EnumValueDescriptorProto +- (*ServiceDescriptorProto)(nil), // 14: google.protobuf.ServiceDescriptorProto +- (*MethodDescriptorProto)(nil), // 15: google.protobuf.MethodDescriptorProto +- (*FileOptions)(nil), // 16: google.protobuf.FileOptions +- (*MessageOptions)(nil), // 17: google.protobuf.MessageOptions +- (*FieldOptions)(nil), // 18: google.protobuf.FieldOptions +- (*OneofOptions)(nil), // 19: google.protobuf.OneofOptions +- (*EnumOptions)(nil), // 20: google.protobuf.EnumOptions +- (*EnumValueOptions)(nil), // 21: google.protobuf.EnumValueOptions +- (*ServiceOptions)(nil), // 22: google.protobuf.ServiceOptions +- (*MethodOptions)(nil), // 23: google.protobuf.MethodOptions +- (*UninterpretedOption)(nil), // 24: google.protobuf.UninterpretedOption +- (*SourceCodeInfo)(nil), // 25: google.protobuf.SourceCodeInfo +- (*GeneratedCodeInfo)(nil), // 26: google.protobuf.GeneratedCodeInfo +- (*DescriptorProto_ExtensionRange)(nil), // 27: google.protobuf.DescriptorProto.ExtensionRange +- (*DescriptorProto_ReservedRange)(nil), // 28: google.protobuf.DescriptorProto.ReservedRange +- (*EnumDescriptorProto_EnumReservedRange)(nil), // 29: google.protobuf.EnumDescriptorProto.EnumReservedRange +- (*UninterpretedOption_NamePart)(nil), // 30: google.protobuf.UninterpretedOption.NamePart +- (*SourceCodeInfo_Location)(nil), // 31: google.protobuf.SourceCodeInfo.Location +- (*GeneratedCodeInfo_Annotation)(nil), // 32: google.protobuf.GeneratedCodeInfo.Annotation ++ (FieldOptions_OptionRetention)(0), // 5: google.protobuf.FieldOptions.OptionRetention ++ (FieldOptions_OptionTargetType)(0), // 6: google.protobuf.FieldOptions.OptionTargetType ++ (MethodOptions_IdempotencyLevel)(0), // 7: google.protobuf.MethodOptions.IdempotencyLevel ++ (GeneratedCodeInfo_Annotation_Semantic)(0), // 8: google.protobuf.GeneratedCodeInfo.Annotation.Semantic ++ (*FileDescriptorSet)(nil), // 9: google.protobuf.FileDescriptorSet ++ (*FileDescriptorProto)(nil), // 10: google.protobuf.FileDescriptorProto ++ (*DescriptorProto)(nil), // 11: google.protobuf.DescriptorProto ++ (*ExtensionRangeOptions)(nil), // 12: google.protobuf.ExtensionRangeOptions ++ (*FieldDescriptorProto)(nil), // 13: google.protobuf.FieldDescriptorProto ++ (*OneofDescriptorProto)(nil), // 14: google.protobuf.OneofDescriptorProto ++ (*EnumDescriptorProto)(nil), // 15: google.protobuf.EnumDescriptorProto ++ (*EnumValueDescriptorProto)(nil), // 16: google.protobuf.EnumValueDescriptorProto ++ (*ServiceDescriptorProto)(nil), // 17: google.protobuf.ServiceDescriptorProto ++ (*MethodDescriptorProto)(nil), // 18: google.protobuf.MethodDescriptorProto ++ (*FileOptions)(nil), // 19: google.protobuf.FileOptions ++ (*MessageOptions)(nil), // 20: google.protobuf.MessageOptions ++ (*FieldOptions)(nil), // 21: google.protobuf.FieldOptions ++ (*OneofOptions)(nil), // 22: google.protobuf.OneofOptions ++ (*EnumOptions)(nil), // 23: google.protobuf.EnumOptions ++ (*EnumValueOptions)(nil), // 24: google.protobuf.EnumValueOptions ++ (*ServiceOptions)(nil), // 25: google.protobuf.ServiceOptions ++ (*MethodOptions)(nil), // 26: google.protobuf.MethodOptions ++ (*UninterpretedOption)(nil), // 27: google.protobuf.UninterpretedOption ++ (*SourceCodeInfo)(nil), // 28: google.protobuf.SourceCodeInfo ++ (*GeneratedCodeInfo)(nil), // 29: google.protobuf.GeneratedCodeInfo ++ (*DescriptorProto_ExtensionRange)(nil), // 30: google.protobuf.DescriptorProto.ExtensionRange ++ (*DescriptorProto_ReservedRange)(nil), // 31: google.protobuf.DescriptorProto.ReservedRange ++ (*EnumDescriptorProto_EnumReservedRange)(nil), // 32: google.protobuf.EnumDescriptorProto.EnumReservedRange ++ (*UninterpretedOption_NamePart)(nil), // 33: google.protobuf.UninterpretedOption.NamePart ++ (*SourceCodeInfo_Location)(nil), // 34: google.protobuf.SourceCodeInfo.Location ++ (*GeneratedCodeInfo_Annotation)(nil), // 35: google.protobuf.GeneratedCodeInfo.Annotation + } + var file_google_protobuf_descriptor_proto_depIdxs = []int32{ +- 7, // 0: google.protobuf.FileDescriptorSet.file:type_name -> google.protobuf.FileDescriptorProto +- 8, // 1: google.protobuf.FileDescriptorProto.message_type:type_name -> google.protobuf.DescriptorProto +- 12, // 2: google.protobuf.FileDescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto +- 14, // 3: google.protobuf.FileDescriptorProto.service:type_name -> google.protobuf.ServiceDescriptorProto +- 10, // 4: google.protobuf.FileDescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto +- 16, // 5: google.protobuf.FileDescriptorProto.options:type_name -> google.protobuf.FileOptions +- 25, // 6: google.protobuf.FileDescriptorProto.source_code_info:type_name -> google.protobuf.SourceCodeInfo +- 10, // 7: google.protobuf.DescriptorProto.field:type_name -> google.protobuf.FieldDescriptorProto +- 10, // 8: google.protobuf.DescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto +- 8, // 9: google.protobuf.DescriptorProto.nested_type:type_name -> google.protobuf.DescriptorProto +- 12, // 10: google.protobuf.DescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto +- 27, // 11: google.protobuf.DescriptorProto.extension_range:type_name -> google.protobuf.DescriptorProto.ExtensionRange +- 11, // 12: google.protobuf.DescriptorProto.oneof_decl:type_name -> google.protobuf.OneofDescriptorProto +- 17, // 13: google.protobuf.DescriptorProto.options:type_name -> google.protobuf.MessageOptions +- 28, // 14: google.protobuf.DescriptorProto.reserved_range:type_name -> google.protobuf.DescriptorProto.ReservedRange +- 24, // 15: google.protobuf.ExtensionRangeOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption ++ 10, // 0: google.protobuf.FileDescriptorSet.file:type_name -> google.protobuf.FileDescriptorProto ++ 11, // 1: google.protobuf.FileDescriptorProto.message_type:type_name -> google.protobuf.DescriptorProto ++ 15, // 2: google.protobuf.FileDescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto ++ 17, // 3: google.protobuf.FileDescriptorProto.service:type_name -> google.protobuf.ServiceDescriptorProto ++ 13, // 4: google.protobuf.FileDescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto ++ 19, // 5: google.protobuf.FileDescriptorProto.options:type_name -> google.protobuf.FileOptions ++ 28, // 6: google.protobuf.FileDescriptorProto.source_code_info:type_name -> google.protobuf.SourceCodeInfo ++ 13, // 7: google.protobuf.DescriptorProto.field:type_name -> google.protobuf.FieldDescriptorProto ++ 13, // 8: google.protobuf.DescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto ++ 11, // 9: google.protobuf.DescriptorProto.nested_type:type_name -> google.protobuf.DescriptorProto ++ 15, // 10: google.protobuf.DescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto ++ 30, // 11: google.protobuf.DescriptorProto.extension_range:type_name -> google.protobuf.DescriptorProto.ExtensionRange ++ 14, // 12: google.protobuf.DescriptorProto.oneof_decl:type_name -> google.protobuf.OneofDescriptorProto ++ 20, // 13: google.protobuf.DescriptorProto.options:type_name -> google.protobuf.MessageOptions ++ 31, // 14: google.protobuf.DescriptorProto.reserved_range:type_name -> google.protobuf.DescriptorProto.ReservedRange ++ 27, // 15: google.protobuf.ExtensionRangeOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption + 1, // 16: google.protobuf.FieldDescriptorProto.label:type_name -> google.protobuf.FieldDescriptorProto.Label + 0, // 17: google.protobuf.FieldDescriptorProto.type:type_name -> google.protobuf.FieldDescriptorProto.Type +- 18, // 18: google.protobuf.FieldDescriptorProto.options:type_name -> google.protobuf.FieldOptions +- 19, // 19: google.protobuf.OneofDescriptorProto.options:type_name -> google.protobuf.OneofOptions +- 13, // 20: google.protobuf.EnumDescriptorProto.value:type_name -> google.protobuf.EnumValueDescriptorProto +- 20, // 21: google.protobuf.EnumDescriptorProto.options:type_name -> google.protobuf.EnumOptions +- 29, // 22: google.protobuf.EnumDescriptorProto.reserved_range:type_name -> google.protobuf.EnumDescriptorProto.EnumReservedRange +- 21, // 23: google.protobuf.EnumValueDescriptorProto.options:type_name -> google.protobuf.EnumValueOptions +- 15, // 24: google.protobuf.ServiceDescriptorProto.method:type_name -> google.protobuf.MethodDescriptorProto +- 22, // 25: google.protobuf.ServiceDescriptorProto.options:type_name -> google.protobuf.ServiceOptions +- 23, // 26: google.protobuf.MethodDescriptorProto.options:type_name -> google.protobuf.MethodOptions ++ 21, // 18: google.protobuf.FieldDescriptorProto.options:type_name -> google.protobuf.FieldOptions ++ 22, // 19: google.protobuf.OneofDescriptorProto.options:type_name -> google.protobuf.OneofOptions ++ 16, // 20: google.protobuf.EnumDescriptorProto.value:type_name -> google.protobuf.EnumValueDescriptorProto ++ 23, // 21: google.protobuf.EnumDescriptorProto.options:type_name -> google.protobuf.EnumOptions ++ 32, // 22: google.protobuf.EnumDescriptorProto.reserved_range:type_name -> google.protobuf.EnumDescriptorProto.EnumReservedRange ++ 24, // 23: google.protobuf.EnumValueDescriptorProto.options:type_name -> google.protobuf.EnumValueOptions ++ 18, // 24: google.protobuf.ServiceDescriptorProto.method:type_name -> google.protobuf.MethodDescriptorProto ++ 25, // 25: google.protobuf.ServiceDescriptorProto.options:type_name -> google.protobuf.ServiceOptions ++ 26, // 26: google.protobuf.MethodDescriptorProto.options:type_name -> google.protobuf.MethodOptions + 2, // 27: google.protobuf.FileOptions.optimize_for:type_name -> google.protobuf.FileOptions.OptimizeMode +- 24, // 28: google.protobuf.FileOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption +- 24, // 29: google.protobuf.MessageOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption ++ 27, // 28: google.protobuf.FileOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption ++ 27, // 29: google.protobuf.MessageOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption + 3, // 30: google.protobuf.FieldOptions.ctype:type_name -> google.protobuf.FieldOptions.CType + 4, // 31: google.protobuf.FieldOptions.jstype:type_name -> google.protobuf.FieldOptions.JSType +- 24, // 32: google.protobuf.FieldOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption +- 24, // 33: google.protobuf.OneofOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption +- 24, // 34: google.protobuf.EnumOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption +- 24, // 35: google.protobuf.EnumValueOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption +- 24, // 36: google.protobuf.ServiceOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption +- 5, // 37: google.protobuf.MethodOptions.idempotency_level:type_name -> google.protobuf.MethodOptions.IdempotencyLevel +- 24, // 38: google.protobuf.MethodOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption +- 30, // 39: google.protobuf.UninterpretedOption.name:type_name -> google.protobuf.UninterpretedOption.NamePart +- 31, // 40: google.protobuf.SourceCodeInfo.location:type_name -> google.protobuf.SourceCodeInfo.Location +- 32, // 41: google.protobuf.GeneratedCodeInfo.annotation:type_name -> google.protobuf.GeneratedCodeInfo.Annotation +- 9, // 42: google.protobuf.DescriptorProto.ExtensionRange.options:type_name -> google.protobuf.ExtensionRangeOptions +- 43, // [43:43] is the sub-list for method output_type +- 43, // [43:43] is the sub-list for method input_type +- 43, // [43:43] is the sub-list for extension type_name +- 43, // [43:43] is the sub-list for extension extendee +- 0, // [0:43] is the sub-list for field type_name ++ 5, // 32: google.protobuf.FieldOptions.retention:type_name -> google.protobuf.FieldOptions.OptionRetention ++ 6, // 33: google.protobuf.FieldOptions.target:type_name -> google.protobuf.FieldOptions.OptionTargetType ++ 27, // 34: google.protobuf.FieldOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption ++ 27, // 35: google.protobuf.OneofOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption ++ 27, // 36: google.protobuf.EnumOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption ++ 27, // 37: google.protobuf.EnumValueOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption ++ 27, // 38: google.protobuf.ServiceOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption ++ 7, // 39: google.protobuf.MethodOptions.idempotency_level:type_name -> google.protobuf.MethodOptions.IdempotencyLevel ++ 27, // 40: google.protobuf.MethodOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption ++ 33, // 41: google.protobuf.UninterpretedOption.name:type_name -> google.protobuf.UninterpretedOption.NamePart ++ 34, // 42: google.protobuf.SourceCodeInfo.location:type_name -> google.protobuf.SourceCodeInfo.Location ++ 35, // 43: google.protobuf.GeneratedCodeInfo.annotation:type_name -> google.protobuf.GeneratedCodeInfo.Annotation ++ 12, // 44: google.protobuf.DescriptorProto.ExtensionRange.options:type_name -> google.protobuf.ExtensionRangeOptions ++ 8, // 45: google.protobuf.GeneratedCodeInfo.Annotation.semantic:type_name -> google.protobuf.GeneratedCodeInfo.Annotation.Semantic ++ 46, // [46:46] is the sub-list for method output_type ++ 46, // [46:46] is the sub-list for method input_type ++ 46, // [46:46] is the sub-list for extension type_name ++ 46, // [46:46] is the sub-list for extension extendee ++ 0, // [0:46] is the sub-list for field type_name + } + + func init() { file_google_protobuf_descriptor_proto_init() } +@@ -3940,7 +4333,7 @@ func file_google_protobuf_descriptor_proto_init() { + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_google_protobuf_descriptor_proto_rawDesc, +- NumEnums: 6, ++ NumEnums: 9, + NumMessages: 27, + NumExtensions: 0, + NumServices: 0, +diff --git a/vendor/google.golang.org/protobuf/types/known/anypb/any.pb.go b/vendor/google.golang.org/protobuf/types/known/anypb/any.pb.go +index 8c10797b905e..a6c7a33f3336 100644 +--- a/vendor/google.golang.org/protobuf/types/known/anypb/any.pb.go ++++ b/vendor/google.golang.org/protobuf/types/known/anypb/any.pb.go +@@ -37,8 +37,7 @@ + // It is functionally a tuple of the full name of the remote message type and + // the serialized bytes of the remote message value. + // +-// +-// Constructing an Any ++// # Constructing an Any + // + // An Any message containing another message value is constructed using New: + // +@@ -48,8 +47,7 @@ + // } + // ... // make use of any + // +-// +-// Unmarshaling an Any ++// # Unmarshaling an Any + // + // With a populated Any message, the underlying message can be serialized into + // a remote concrete message value in a few ways. +@@ -95,8 +93,7 @@ + // listed in the case clauses are linked into the Go binary and therefore also + // registered in the global registry. + // +-// +-// Type checking an Any ++// # Type checking an Any + // + // In order to type check whether an Any message represents some other message, + // then use the MessageIs method: +@@ -115,7 +112,6 @@ + // } + // ... // make use of m + // } +-// + package anypb + + import ( +@@ -136,45 +132,49 @@ import ( + // + // Example 1: Pack and unpack a message in C++. + // +-// Foo foo = ...; +-// Any any; +-// any.PackFrom(foo); +-// ... +-// if (any.UnpackTo(&foo)) { +-// ... +-// } ++// Foo foo = ...; ++// Any any; ++// any.PackFrom(foo); ++// ... ++// if (any.UnpackTo(&foo)) { ++// ... ++// } + // + // Example 2: Pack and unpack a message in Java. + // +-// Foo foo = ...; +-// Any any = Any.pack(foo); +-// ... +-// if (any.is(Foo.class)) { +-// foo = any.unpack(Foo.class); +-// } +-// +-// Example 3: Pack and unpack a message in Python. +-// +-// foo = Foo(...) +-// any = Any() +-// any.Pack(foo) +-// ... +-// if any.Is(Foo.DESCRIPTOR): +-// any.Unpack(foo) +-// ... +-// +-// Example 4: Pack and unpack a message in Go +-// +-// foo := &pb.Foo{...} +-// any, err := anypb.New(foo) +-// if err != nil { +-// ... +-// } +-// ... +-// foo := &pb.Foo{} +-// if err := any.UnmarshalTo(foo); err != nil { +-// ... +-// } ++// Foo foo = ...; ++// Any any = Any.pack(foo); ++// ... ++// if (any.is(Foo.class)) { ++// foo = any.unpack(Foo.class); ++// } ++// // or ... ++// if (any.isSameTypeAs(Foo.getDefaultInstance())) { ++// foo = any.unpack(Foo.getDefaultInstance()); ++// } ++// ++// Example 3: Pack and unpack a message in Python. ++// ++// foo = Foo(...) ++// any = Any() ++// any.Pack(foo) ++// ... ++// if any.Is(Foo.DESCRIPTOR): ++// any.Unpack(foo) ++// ... ++// ++// Example 4: Pack and unpack a message in Go ++// ++// foo := &pb.Foo{...} ++// any, err := anypb.New(foo) ++// if err != nil { ++// ... ++// } ++// ... ++// foo := &pb.Foo{} ++// if err := any.UnmarshalTo(foo); err != nil { ++// ... ++// } + // + // The pack methods provided by protobuf library will by default use + // 'type.googleapis.com/full.type.name' as the type URL and the unpack +@@ -182,35 +182,33 @@ import ( + // in the type URL, for example "foo.bar.com/x/y.z" will yield type + // name "y.z". + // ++// # JSON + // +-// JSON +-// ==== + // The JSON representation of an `Any` value uses the regular + // representation of the deserialized, embedded message, with an + // additional field `@type` which contains the type URL. Example: + // +-// package google.profile; +-// message Person { +-// string first_name = 1; +-// string last_name = 2; +-// } ++// package google.profile; ++// message Person { ++// string first_name = 1; ++// string last_name = 2; ++// } + // +-// { +-// "@type": "type.googleapis.com/google.profile.Person", +-// "firstName": , +-// "lastName": +-// } ++// { ++// "@type": "type.googleapis.com/google.profile.Person", ++// "firstName": , ++// "lastName": ++// } + // + // If the embedded message type is well-known and has a custom JSON + // representation, that representation will be embedded adding a field + // `value` which holds the custom JSON in addition to the `@type` + // field. Example (for message [google.protobuf.Duration][]): + // +-// { +-// "@type": "type.googleapis.com/google.protobuf.Duration", +-// "value": "1.212s" +-// } +-// ++// { ++// "@type": "type.googleapis.com/google.protobuf.Duration", ++// "value": "1.212s" ++// } + type Any struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache +@@ -228,14 +226,14 @@ type Any struct { + // scheme `http`, `https`, or no scheme, one can optionally set up a type + // server that maps type URLs to message definitions as follows: + // +- // * If no scheme is provided, `https` is assumed. +- // * An HTTP GET on the URL must yield a [google.protobuf.Type][] +- // value in binary format, or produce an error. +- // * Applications are allowed to cache lookup results based on the +- // URL, or have them precompiled into a binary to avoid any +- // lookup. Therefore, binary compatibility needs to be preserved +- // on changes to types. (Use versioned type names to manage +- // breaking changes.) ++ // - If no scheme is provided, `https` is assumed. ++ // - An HTTP GET on the URL must yield a [google.protobuf.Type][] ++ // value in binary format, or produce an error. ++ // - Applications are allowed to cache lookup results based on the ++ // URL, or have them precompiled into a binary to avoid any ++ // lookup. Therefore, binary compatibility needs to be preserved ++ // on changes to types. (Use versioned type names to manage ++ // breaking changes.) + // + // Note: this functionality is not currently available in the official + // protobuf release, and it is not used for type URLs beginning with +@@ -243,7 +241,6 @@ type Any struct { + // + // Schemes other than `http`, `https` (or the empty scheme) might be + // used with implementation specific semantics. +- // + TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl,proto3" json:"type_url,omitempty"` + // Must be a valid serialized protocol buffer of the above specified type. + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +diff --git a/vendor/google.golang.org/protobuf/types/known/durationpb/duration.pb.go b/vendor/google.golang.org/protobuf/types/known/durationpb/duration.pb.go +index a583ca2f6c77..df709a8dd4c2 100644 +--- a/vendor/google.golang.org/protobuf/types/known/durationpb/duration.pb.go ++++ b/vendor/google.golang.org/protobuf/types/known/durationpb/duration.pb.go +@@ -35,8 +35,7 @@ + // + // The Duration message represents a signed span of time. + // +-// +-// Conversion to a Go Duration ++// # Conversion to a Go Duration + // + // The AsDuration method can be used to convert a Duration message to a + // standard Go time.Duration value: +@@ -65,15 +64,13 @@ + // the resulting value to the closest representable value (e.g., math.MaxInt64 + // for positive overflow and math.MinInt64 for negative overflow). + // +-// +-// Conversion from a Go Duration ++// # Conversion from a Go Duration + // + // The durationpb.New function can be used to construct a Duration message + // from a standard Go time.Duration value: + // + // dur := durationpb.New(d) + // ... // make use of d as a *durationpb.Duration +-// + package durationpb + + import ( +@@ -96,43 +93,43 @@ import ( + // + // Example 1: Compute Duration from two Timestamps in pseudo code. + // +-// Timestamp start = ...; +-// Timestamp end = ...; +-// Duration duration = ...; ++// Timestamp start = ...; ++// Timestamp end = ...; ++// Duration duration = ...; + // +-// duration.seconds = end.seconds - start.seconds; +-// duration.nanos = end.nanos - start.nanos; ++// duration.seconds = end.seconds - start.seconds; ++// duration.nanos = end.nanos - start.nanos; + // +-// if (duration.seconds < 0 && duration.nanos > 0) { +-// duration.seconds += 1; +-// duration.nanos -= 1000000000; +-// } else if (duration.seconds > 0 && duration.nanos < 0) { +-// duration.seconds -= 1; +-// duration.nanos += 1000000000; +-// } ++// if (duration.seconds < 0 && duration.nanos > 0) { ++// duration.seconds += 1; ++// duration.nanos -= 1000000000; ++// } else if (duration.seconds > 0 && duration.nanos < 0) { ++// duration.seconds -= 1; ++// duration.nanos += 1000000000; ++// } + // + // Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. + // +-// Timestamp start = ...; +-// Duration duration = ...; +-// Timestamp end = ...; ++// Timestamp start = ...; ++// Duration duration = ...; ++// Timestamp end = ...; + // +-// end.seconds = start.seconds + duration.seconds; +-// end.nanos = start.nanos + duration.nanos; ++// end.seconds = start.seconds + duration.seconds; ++// end.nanos = start.nanos + duration.nanos; + // +-// if (end.nanos < 0) { +-// end.seconds -= 1; +-// end.nanos += 1000000000; +-// } else if (end.nanos >= 1000000000) { +-// end.seconds += 1; +-// end.nanos -= 1000000000; +-// } ++// if (end.nanos < 0) { ++// end.seconds -= 1; ++// end.nanos += 1000000000; ++// } else if (end.nanos >= 1000000000) { ++// end.seconds += 1; ++// end.nanos -= 1000000000; ++// } + // + // Example 3: Compute Duration from datetime.timedelta in Python. + // +-// td = datetime.timedelta(days=3, minutes=10) +-// duration = Duration() +-// duration.FromTimedelta(td) ++// td = datetime.timedelta(days=3, minutes=10) ++// duration = Duration() ++// duration.FromTimedelta(td) + // + // # JSON Mapping + // +@@ -143,8 +140,6 @@ import ( + // encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should + // be expressed in JSON format as "3.000000001s", and 3 seconds and 1 + // microsecond should be expressed in JSON format as "3.000001s". +-// +-// + type Duration struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache +diff --git a/vendor/google.golang.org/protobuf/types/known/timestamppb/timestamp.pb.go b/vendor/google.golang.org/protobuf/types/known/timestamppb/timestamp.pb.go +index c9ae92132aad..61f69fc11b16 100644 +--- a/vendor/google.golang.org/protobuf/types/known/timestamppb/timestamp.pb.go ++++ b/vendor/google.golang.org/protobuf/types/known/timestamppb/timestamp.pb.go +@@ -36,8 +36,7 @@ + // The Timestamp message represents a timestamp, + // an instant in time since the Unix epoch (January 1st, 1970). + // +-// +-// Conversion to a Go Time ++// # Conversion to a Go Time + // + // The AsTime method can be used to convert a Timestamp message to a + // standard Go time.Time value in UTC: +@@ -59,8 +58,7 @@ + // ... // handle error + // } + // +-// +-// Conversion from a Go Time ++// # Conversion from a Go Time + // + // The timestamppb.New function can be used to construct a Timestamp message + // from a standard Go time.Time value: +@@ -72,7 +70,6 @@ + // + // ts := timestamppb.Now() + // ... // make use of ts as a *timestamppb.Timestamp +-// + package timestamppb + + import ( +@@ -101,52 +98,50 @@ import ( + // + // Example 1: Compute Timestamp from POSIX `time()`. + // +-// Timestamp timestamp; +-// timestamp.set_seconds(time(NULL)); +-// timestamp.set_nanos(0); ++// Timestamp timestamp; ++// timestamp.set_seconds(time(NULL)); ++// timestamp.set_nanos(0); + // + // Example 2: Compute Timestamp from POSIX `gettimeofday()`. + // +-// struct timeval tv; +-// gettimeofday(&tv, NULL); ++// struct timeval tv; ++// gettimeofday(&tv, NULL); + // +-// Timestamp timestamp; +-// timestamp.set_seconds(tv.tv_sec); +-// timestamp.set_nanos(tv.tv_usec * 1000); ++// Timestamp timestamp; ++// timestamp.set_seconds(tv.tv_sec); ++// timestamp.set_nanos(tv.tv_usec * 1000); + // + // Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. + // +-// FILETIME ft; +-// GetSystemTimeAsFileTime(&ft); +-// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; ++// FILETIME ft; ++// GetSystemTimeAsFileTime(&ft); ++// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; + // +-// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z +-// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. +-// Timestamp timestamp; +-// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); +-// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); ++// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z ++// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. ++// Timestamp timestamp; ++// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); ++// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); + // + // Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. + // +-// long millis = System.currentTimeMillis(); +-// +-// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) +-// .setNanos((int) ((millis % 1000) * 1000000)).build(); ++// long millis = System.currentTimeMillis(); + // ++// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) ++// .setNanos((int) ((millis % 1000) * 1000000)).build(); + // + // Example 5: Compute Timestamp from Java `Instant.now()`. + // +-// Instant now = Instant.now(); +-// +-// Timestamp timestamp = +-// Timestamp.newBuilder().setSeconds(now.getEpochSecond()) +-// .setNanos(now.getNano()).build(); ++// Instant now = Instant.now(); + // ++// Timestamp timestamp = ++// Timestamp.newBuilder().setSeconds(now.getEpochSecond()) ++// .setNanos(now.getNano()).build(); + // + // Example 6: Compute Timestamp from current time in Python. + // +-// timestamp = Timestamp() +-// timestamp.GetCurrentTime() ++// timestamp = Timestamp() ++// timestamp.GetCurrentTime() + // + // # JSON Mapping + // +@@ -174,8 +169,6 @@ import ( + // the Joda Time's [`ISODateTimeFormat.dateTime()`]( + // http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D + // ) to obtain a formatter capable of generating timestamps in this format. +-// +-// + type Timestamp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache +diff --git a/vendor/gopkg.in/yaml.v3/LICENSE b/vendor/gopkg.in/yaml.v3/LICENSE +new file mode 100644 +index 000000000000..2683e4bb1f24 +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/LICENSE +@@ -0,0 +1,50 @@ ++ ++This project is covered by two different licenses: MIT and Apache. ++ ++#### MIT License #### ++ ++The following files were ported to Go from C files of libyaml, and thus ++are still covered by their original MIT license, with the additional ++copyright staring in 2011 when the project was ported over: ++ ++ apic.go emitterc.go parserc.go readerc.go scannerc.go ++ writerc.go yamlh.go yamlprivateh.go ++ ++Copyright (c) 2006-2010 Kirill Simonov ++Copyright (c) 2006-2011 Kirill Simonov ++ ++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. ++ ++### Apache License ### ++ ++All the remaining project files are covered by the Apache license: ++ ++Copyright (c) 2011-2019 Canonical Ltd ++ ++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. +diff --git a/vendor/gopkg.in/yaml.v3/NOTICE b/vendor/gopkg.in/yaml.v3/NOTICE +new file mode 100644 +index 000000000000..866d74a7ad79 +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/NOTICE +@@ -0,0 +1,13 @@ ++Copyright 2011-2016 Canonical Ltd. ++ ++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. +diff --git a/vendor/gopkg.in/yaml.v3/README.md b/vendor/gopkg.in/yaml.v3/README.md +new file mode 100644 +index 000000000000..08eb1babddfa +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/README.md +@@ -0,0 +1,150 @@ ++# YAML support for the Go language ++ ++Introduction ++------------ ++ ++The yaml package enables Go programs to comfortably encode and decode YAML ++values. It was developed within [Canonical](https://www.canonical.com) as ++part of the [juju](https://juju.ubuntu.com) project, and is based on a ++pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML) ++C library to parse and generate YAML data quickly and reliably. ++ ++Compatibility ++------------- ++ ++The yaml package supports most of YAML 1.2, but preserves some behavior ++from 1.1 for backwards compatibility. ++ ++Specifically, as of v3 of the yaml package: ++ ++ - YAML 1.1 bools (_yes/no, on/off_) are supported as long as they are being ++ decoded into a typed bool value. Otherwise they behave as a string. Booleans ++ in YAML 1.2 are _true/false_ only. ++ - Octals encode and decode as _0777_ per YAML 1.1, rather than _0o777_ ++ as specified in YAML 1.2, because most parsers still use the old format. ++ Octals in the _0o777_ format are supported though, so new files work. ++ - Does not support base-60 floats. These are gone from YAML 1.2, and were ++ actually never supported by this package as it's clearly a poor choice. ++ ++and offers backwards ++compatibility with YAML 1.1 in some cases. ++1.2, including support for ++anchors, tags, map merging, etc. Multi-document unmarshalling is not yet ++implemented, and base-60 floats from YAML 1.1 are purposefully not ++supported since they're a poor design and are gone in YAML 1.2. ++ ++Installation and usage ++---------------------- ++ ++The import path for the package is *gopkg.in/yaml.v3*. ++ ++To install it, run: ++ ++ go get gopkg.in/yaml.v3 ++ ++API documentation ++----------------- ++ ++If opened in a browser, the import path itself leads to the API documentation: ++ ++ - [https://gopkg.in/yaml.v3](https://gopkg.in/yaml.v3) ++ ++API stability ++------------- ++ ++The package API for yaml v3 will remain stable as described in [gopkg.in](https://gopkg.in). ++ ++ ++License ++------- ++ ++The yaml package is licensed under the MIT and Apache License 2.0 licenses. ++Please see the LICENSE file for details. ++ ++ ++Example ++------- ++ ++```Go ++package main ++ ++import ( ++ "fmt" ++ "log" ++ ++ "gopkg.in/yaml.v3" ++) ++ ++var data = ` ++a: Easy! ++b: ++ c: 2 ++ d: [3, 4] ++` ++ ++// Note: struct fields must be public in order for unmarshal to ++// correctly populate the data. ++type T struct { ++ A string ++ B struct { ++ RenamedC int `yaml:"c"` ++ D []int `yaml:",flow"` ++ } ++} ++ ++func main() { ++ t := T{} ++ ++ err := yaml.Unmarshal([]byte(data), &t) ++ if err != nil { ++ log.Fatalf("error: %v", err) ++ } ++ fmt.Printf("--- t:\n%v\n\n", t) ++ ++ d, err := yaml.Marshal(&t) ++ if err != nil { ++ log.Fatalf("error: %v", err) ++ } ++ fmt.Printf("--- t dump:\n%s\n\n", string(d)) ++ ++ m := make(map[interface{}]interface{}) ++ ++ err = yaml.Unmarshal([]byte(data), &m) ++ if err != nil { ++ log.Fatalf("error: %v", err) ++ } ++ fmt.Printf("--- m:\n%v\n\n", m) ++ ++ d, err = yaml.Marshal(&m) ++ if err != nil { ++ log.Fatalf("error: %v", err) ++ } ++ fmt.Printf("--- m dump:\n%s\n\n", string(d)) ++} ++``` ++ ++This example will generate the following output: ++ ++``` ++--- t: ++{Easy! {2 [3 4]}} ++ ++--- t dump: ++a: Easy! ++b: ++ c: 2 ++ d: [3, 4] ++ ++ ++--- m: ++map[a:Easy! b:map[c:2 d:[3 4]]] ++ ++--- m dump: ++a: Easy! ++b: ++ c: 2 ++ d: ++ - 3 ++ - 4 ++``` ++ +diff --git a/vendor/gopkg.in/yaml.v3/apic.go b/vendor/gopkg.in/yaml.v3/apic.go +new file mode 100644 +index 000000000000..ae7d049f182a +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/apic.go +@@ -0,0 +1,747 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// Copyright (c) 2006-2010 Kirill Simonov ++// ++// 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. ++ ++package yaml ++ ++import ( ++ "io" ++) ++ ++func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) { ++ //fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens)) ++ ++ // Check if we can move the queue at the beginning of the buffer. ++ if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) { ++ if parser.tokens_head != len(parser.tokens) { ++ copy(parser.tokens, parser.tokens[parser.tokens_head:]) ++ } ++ parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head] ++ parser.tokens_head = 0 ++ } ++ parser.tokens = append(parser.tokens, *token) ++ if pos < 0 { ++ return ++ } ++ copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:]) ++ parser.tokens[parser.tokens_head+pos] = *token ++} ++ ++// Create a new parser object. ++func yaml_parser_initialize(parser *yaml_parser_t) bool { ++ *parser = yaml_parser_t{ ++ raw_buffer: make([]byte, 0, input_raw_buffer_size), ++ buffer: make([]byte, 0, input_buffer_size), ++ } ++ return true ++} ++ ++// Destroy a parser object. ++func yaml_parser_delete(parser *yaml_parser_t) { ++ *parser = yaml_parser_t{} ++} ++ ++// String read handler. ++func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { ++ if parser.input_pos == len(parser.input) { ++ return 0, io.EOF ++ } ++ n = copy(buffer, parser.input[parser.input_pos:]) ++ parser.input_pos += n ++ return n, nil ++} ++ ++// Reader read handler. ++func yaml_reader_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { ++ return parser.input_reader.Read(buffer) ++} ++ ++// Set a string input. ++func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) { ++ if parser.read_handler != nil { ++ panic("must set the input source only once") ++ } ++ parser.read_handler = yaml_string_read_handler ++ parser.input = input ++ parser.input_pos = 0 ++} ++ ++// Set a file input. ++func yaml_parser_set_input_reader(parser *yaml_parser_t, r io.Reader) { ++ if parser.read_handler != nil { ++ panic("must set the input source only once") ++ } ++ parser.read_handler = yaml_reader_read_handler ++ parser.input_reader = r ++} ++ ++// Set the source encoding. ++func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) { ++ if parser.encoding != yaml_ANY_ENCODING { ++ panic("must set the encoding only once") ++ } ++ parser.encoding = encoding ++} ++ ++// Create a new emitter object. ++func yaml_emitter_initialize(emitter *yaml_emitter_t) { ++ *emitter = yaml_emitter_t{ ++ buffer: make([]byte, output_buffer_size), ++ raw_buffer: make([]byte, 0, output_raw_buffer_size), ++ states: make([]yaml_emitter_state_t, 0, initial_stack_size), ++ events: make([]yaml_event_t, 0, initial_queue_size), ++ best_width: -1, ++ } ++} ++ ++// Destroy an emitter object. ++func yaml_emitter_delete(emitter *yaml_emitter_t) { ++ *emitter = yaml_emitter_t{} ++} ++ ++// String write handler. ++func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error { ++ *emitter.output_buffer = append(*emitter.output_buffer, buffer...) ++ return nil ++} ++ ++// yaml_writer_write_handler uses emitter.output_writer to write the ++// emitted text. ++func yaml_writer_write_handler(emitter *yaml_emitter_t, buffer []byte) error { ++ _, err := emitter.output_writer.Write(buffer) ++ return err ++} ++ ++// Set a string output. ++func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) { ++ if emitter.write_handler != nil { ++ panic("must set the output target only once") ++ } ++ emitter.write_handler = yaml_string_write_handler ++ emitter.output_buffer = output_buffer ++} ++ ++// Set a file output. ++func yaml_emitter_set_output_writer(emitter *yaml_emitter_t, w io.Writer) { ++ if emitter.write_handler != nil { ++ panic("must set the output target only once") ++ } ++ emitter.write_handler = yaml_writer_write_handler ++ emitter.output_writer = w ++} ++ ++// Set the output encoding. ++func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) { ++ if emitter.encoding != yaml_ANY_ENCODING { ++ panic("must set the output encoding only once") ++ } ++ emitter.encoding = encoding ++} ++ ++// Set the canonical output style. ++func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) { ++ emitter.canonical = canonical ++} ++ ++// Set the indentation increment. ++func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) { ++ if indent < 2 || indent > 9 { ++ indent = 2 ++ } ++ emitter.best_indent = indent ++} ++ ++// Set the preferred line width. ++func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) { ++ if width < 0 { ++ width = -1 ++ } ++ emitter.best_width = width ++} ++ ++// Set if unescaped non-ASCII characters are allowed. ++func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) { ++ emitter.unicode = unicode ++} ++ ++// Set the preferred line break character. ++func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) { ++ emitter.line_break = line_break ++} ++ ++///* ++// * Destroy a token object. ++// */ ++// ++//YAML_DECLARE(void) ++//yaml_token_delete(yaml_token_t *token) ++//{ ++// assert(token); // Non-NULL token object expected. ++// ++// switch (token.type) ++// { ++// case YAML_TAG_DIRECTIVE_TOKEN: ++// yaml_free(token.data.tag_directive.handle); ++// yaml_free(token.data.tag_directive.prefix); ++// break; ++// ++// case YAML_ALIAS_TOKEN: ++// yaml_free(token.data.alias.value); ++// break; ++// ++// case YAML_ANCHOR_TOKEN: ++// yaml_free(token.data.anchor.value); ++// break; ++// ++// case YAML_TAG_TOKEN: ++// yaml_free(token.data.tag.handle); ++// yaml_free(token.data.tag.suffix); ++// break; ++// ++// case YAML_SCALAR_TOKEN: ++// yaml_free(token.data.scalar.value); ++// break; ++// ++// default: ++// break; ++// } ++// ++// memset(token, 0, sizeof(yaml_token_t)); ++//} ++// ++///* ++// * Check if a string is a valid UTF-8 sequence. ++// * ++// * Check 'reader.c' for more details on UTF-8 encoding. ++// */ ++// ++//static int ++//yaml_check_utf8(yaml_char_t *start, size_t length) ++//{ ++// yaml_char_t *end = start+length; ++// yaml_char_t *pointer = start; ++// ++// while (pointer < end) { ++// unsigned char octet; ++// unsigned int width; ++// unsigned int value; ++// size_t k; ++// ++// octet = pointer[0]; ++// width = (octet & 0x80) == 0x00 ? 1 : ++// (octet & 0xE0) == 0xC0 ? 2 : ++// (octet & 0xF0) == 0xE0 ? 3 : ++// (octet & 0xF8) == 0xF0 ? 4 : 0; ++// value = (octet & 0x80) == 0x00 ? octet & 0x7F : ++// (octet & 0xE0) == 0xC0 ? octet & 0x1F : ++// (octet & 0xF0) == 0xE0 ? octet & 0x0F : ++// (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0; ++// if (!width) return 0; ++// if (pointer+width > end) return 0; ++// for (k = 1; k < width; k ++) { ++// octet = pointer[k]; ++// if ((octet & 0xC0) != 0x80) return 0; ++// value = (value << 6) + (octet & 0x3F); ++// } ++// if (!((width == 1) || ++// (width == 2 && value >= 0x80) || ++// (width == 3 && value >= 0x800) || ++// (width == 4 && value >= 0x10000))) return 0; ++// ++// pointer += width; ++// } ++// ++// return 1; ++//} ++// ++ ++// Create STREAM-START. ++func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) { ++ *event = yaml_event_t{ ++ typ: yaml_STREAM_START_EVENT, ++ encoding: encoding, ++ } ++} ++ ++// Create STREAM-END. ++func yaml_stream_end_event_initialize(event *yaml_event_t) { ++ *event = yaml_event_t{ ++ typ: yaml_STREAM_END_EVENT, ++ } ++} ++ ++// Create DOCUMENT-START. ++func yaml_document_start_event_initialize( ++ event *yaml_event_t, ++ version_directive *yaml_version_directive_t, ++ tag_directives []yaml_tag_directive_t, ++ implicit bool, ++) { ++ *event = yaml_event_t{ ++ typ: yaml_DOCUMENT_START_EVENT, ++ version_directive: version_directive, ++ tag_directives: tag_directives, ++ implicit: implicit, ++ } ++} ++ ++// Create DOCUMENT-END. ++func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) { ++ *event = yaml_event_t{ ++ typ: yaml_DOCUMENT_END_EVENT, ++ implicit: implicit, ++ } ++} ++ ++// Create ALIAS. ++func yaml_alias_event_initialize(event *yaml_event_t, anchor []byte) bool { ++ *event = yaml_event_t{ ++ typ: yaml_ALIAS_EVENT, ++ anchor: anchor, ++ } ++ return true ++} ++ ++// Create SCALAR. ++func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool { ++ *event = yaml_event_t{ ++ typ: yaml_SCALAR_EVENT, ++ anchor: anchor, ++ tag: tag, ++ value: value, ++ implicit: plain_implicit, ++ quoted_implicit: quoted_implicit, ++ style: yaml_style_t(style), ++ } ++ return true ++} ++ ++// Create SEQUENCE-START. ++func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool { ++ *event = yaml_event_t{ ++ typ: yaml_SEQUENCE_START_EVENT, ++ anchor: anchor, ++ tag: tag, ++ implicit: implicit, ++ style: yaml_style_t(style), ++ } ++ return true ++} ++ ++// Create SEQUENCE-END. ++func yaml_sequence_end_event_initialize(event *yaml_event_t) bool { ++ *event = yaml_event_t{ ++ typ: yaml_SEQUENCE_END_EVENT, ++ } ++ return true ++} ++ ++// Create MAPPING-START. ++func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) { ++ *event = yaml_event_t{ ++ typ: yaml_MAPPING_START_EVENT, ++ anchor: anchor, ++ tag: tag, ++ implicit: implicit, ++ style: yaml_style_t(style), ++ } ++} ++ ++// Create MAPPING-END. ++func yaml_mapping_end_event_initialize(event *yaml_event_t) { ++ *event = yaml_event_t{ ++ typ: yaml_MAPPING_END_EVENT, ++ } ++} ++ ++// Destroy an event object. ++func yaml_event_delete(event *yaml_event_t) { ++ *event = yaml_event_t{} ++} ++ ++///* ++// * Create a document object. ++// */ ++// ++//YAML_DECLARE(int) ++//yaml_document_initialize(document *yaml_document_t, ++// version_directive *yaml_version_directive_t, ++// tag_directives_start *yaml_tag_directive_t, ++// tag_directives_end *yaml_tag_directive_t, ++// start_implicit int, end_implicit int) ++//{ ++// struct { ++// error yaml_error_type_t ++// } context ++// struct { ++// start *yaml_node_t ++// end *yaml_node_t ++// top *yaml_node_t ++// } nodes = { NULL, NULL, NULL } ++// version_directive_copy *yaml_version_directive_t = NULL ++// struct { ++// start *yaml_tag_directive_t ++// end *yaml_tag_directive_t ++// top *yaml_tag_directive_t ++// } tag_directives_copy = { NULL, NULL, NULL } ++// value yaml_tag_directive_t = { NULL, NULL } ++// mark yaml_mark_t = { 0, 0, 0 } ++// ++// assert(document) // Non-NULL document object is expected. ++// assert((tag_directives_start && tag_directives_end) || ++// (tag_directives_start == tag_directives_end)) ++// // Valid tag directives are expected. ++// ++// if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error ++// ++// if (version_directive) { ++// version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t)) ++// if (!version_directive_copy) goto error ++// version_directive_copy.major = version_directive.major ++// version_directive_copy.minor = version_directive.minor ++// } ++// ++// if (tag_directives_start != tag_directives_end) { ++// tag_directive *yaml_tag_directive_t ++// if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE)) ++// goto error ++// for (tag_directive = tag_directives_start ++// tag_directive != tag_directives_end; tag_directive ++) { ++// assert(tag_directive.handle) ++// assert(tag_directive.prefix) ++// if (!yaml_check_utf8(tag_directive.handle, ++// strlen((char *)tag_directive.handle))) ++// goto error ++// if (!yaml_check_utf8(tag_directive.prefix, ++// strlen((char *)tag_directive.prefix))) ++// goto error ++// value.handle = yaml_strdup(tag_directive.handle) ++// value.prefix = yaml_strdup(tag_directive.prefix) ++// if (!value.handle || !value.prefix) goto error ++// if (!PUSH(&context, tag_directives_copy, value)) ++// goto error ++// value.handle = NULL ++// value.prefix = NULL ++// } ++// } ++// ++// DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy, ++// tag_directives_copy.start, tag_directives_copy.top, ++// start_implicit, end_implicit, mark, mark) ++// ++// return 1 ++// ++//error: ++// STACK_DEL(&context, nodes) ++// yaml_free(version_directive_copy) ++// while (!STACK_EMPTY(&context, tag_directives_copy)) { ++// value yaml_tag_directive_t = POP(&context, tag_directives_copy) ++// yaml_free(value.handle) ++// yaml_free(value.prefix) ++// } ++// STACK_DEL(&context, tag_directives_copy) ++// yaml_free(value.handle) ++// yaml_free(value.prefix) ++// ++// return 0 ++//} ++// ++///* ++// * Destroy a document object. ++// */ ++// ++//YAML_DECLARE(void) ++//yaml_document_delete(document *yaml_document_t) ++//{ ++// struct { ++// error yaml_error_type_t ++// } context ++// tag_directive *yaml_tag_directive_t ++// ++// context.error = YAML_NO_ERROR // Eliminate a compiler warning. ++// ++// assert(document) // Non-NULL document object is expected. ++// ++// while (!STACK_EMPTY(&context, document.nodes)) { ++// node yaml_node_t = POP(&context, document.nodes) ++// yaml_free(node.tag) ++// switch (node.type) { ++// case YAML_SCALAR_NODE: ++// yaml_free(node.data.scalar.value) ++// break ++// case YAML_SEQUENCE_NODE: ++// STACK_DEL(&context, node.data.sequence.items) ++// break ++// case YAML_MAPPING_NODE: ++// STACK_DEL(&context, node.data.mapping.pairs) ++// break ++// default: ++// assert(0) // Should not happen. ++// } ++// } ++// STACK_DEL(&context, document.nodes) ++// ++// yaml_free(document.version_directive) ++// for (tag_directive = document.tag_directives.start ++// tag_directive != document.tag_directives.end ++// tag_directive++) { ++// yaml_free(tag_directive.handle) ++// yaml_free(tag_directive.prefix) ++// } ++// yaml_free(document.tag_directives.start) ++// ++// memset(document, 0, sizeof(yaml_document_t)) ++//} ++// ++///** ++// * Get a document node. ++// */ ++// ++//YAML_DECLARE(yaml_node_t *) ++//yaml_document_get_node(document *yaml_document_t, index int) ++//{ ++// assert(document) // Non-NULL document object is expected. ++// ++// if (index > 0 && document.nodes.start + index <= document.nodes.top) { ++// return document.nodes.start + index - 1 ++// } ++// return NULL ++//} ++// ++///** ++// * Get the root object. ++// */ ++// ++//YAML_DECLARE(yaml_node_t *) ++//yaml_document_get_root_node(document *yaml_document_t) ++//{ ++// assert(document) // Non-NULL document object is expected. ++// ++// if (document.nodes.top != document.nodes.start) { ++// return document.nodes.start ++// } ++// return NULL ++//} ++// ++///* ++// * Add a scalar node to a document. ++// */ ++// ++//YAML_DECLARE(int) ++//yaml_document_add_scalar(document *yaml_document_t, ++// tag *yaml_char_t, value *yaml_char_t, length int, ++// style yaml_scalar_style_t) ++//{ ++// struct { ++// error yaml_error_type_t ++// } context ++// mark yaml_mark_t = { 0, 0, 0 } ++// tag_copy *yaml_char_t = NULL ++// value_copy *yaml_char_t = NULL ++// node yaml_node_t ++// ++// assert(document) // Non-NULL document object is expected. ++// assert(value) // Non-NULL value is expected. ++// ++// if (!tag) { ++// tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG ++// } ++// ++// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error ++// tag_copy = yaml_strdup(tag) ++// if (!tag_copy) goto error ++// ++// if (length < 0) { ++// length = strlen((char *)value) ++// } ++// ++// if (!yaml_check_utf8(value, length)) goto error ++// value_copy = yaml_malloc(length+1) ++// if (!value_copy) goto error ++// memcpy(value_copy, value, length) ++// value_copy[length] = '\0' ++// ++// SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark) ++// if (!PUSH(&context, document.nodes, node)) goto error ++// ++// return document.nodes.top - document.nodes.start ++// ++//error: ++// yaml_free(tag_copy) ++// yaml_free(value_copy) ++// ++// return 0 ++//} ++// ++///* ++// * Add a sequence node to a document. ++// */ ++// ++//YAML_DECLARE(int) ++//yaml_document_add_sequence(document *yaml_document_t, ++// tag *yaml_char_t, style yaml_sequence_style_t) ++//{ ++// struct { ++// error yaml_error_type_t ++// } context ++// mark yaml_mark_t = { 0, 0, 0 } ++// tag_copy *yaml_char_t = NULL ++// struct { ++// start *yaml_node_item_t ++// end *yaml_node_item_t ++// top *yaml_node_item_t ++// } items = { NULL, NULL, NULL } ++// node yaml_node_t ++// ++// assert(document) // Non-NULL document object is expected. ++// ++// if (!tag) { ++// tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG ++// } ++// ++// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error ++// tag_copy = yaml_strdup(tag) ++// if (!tag_copy) goto error ++// ++// if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error ++// ++// SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end, ++// style, mark, mark) ++// if (!PUSH(&context, document.nodes, node)) goto error ++// ++// return document.nodes.top - document.nodes.start ++// ++//error: ++// STACK_DEL(&context, items) ++// yaml_free(tag_copy) ++// ++// return 0 ++//} ++// ++///* ++// * Add a mapping node to a document. ++// */ ++// ++//YAML_DECLARE(int) ++//yaml_document_add_mapping(document *yaml_document_t, ++// tag *yaml_char_t, style yaml_mapping_style_t) ++//{ ++// struct { ++// error yaml_error_type_t ++// } context ++// mark yaml_mark_t = { 0, 0, 0 } ++// tag_copy *yaml_char_t = NULL ++// struct { ++// start *yaml_node_pair_t ++// end *yaml_node_pair_t ++// top *yaml_node_pair_t ++// } pairs = { NULL, NULL, NULL } ++// node yaml_node_t ++// ++// assert(document) // Non-NULL document object is expected. ++// ++// if (!tag) { ++// tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG ++// } ++// ++// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error ++// tag_copy = yaml_strdup(tag) ++// if (!tag_copy) goto error ++// ++// if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error ++// ++// MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end, ++// style, mark, mark) ++// if (!PUSH(&context, document.nodes, node)) goto error ++// ++// return document.nodes.top - document.nodes.start ++// ++//error: ++// STACK_DEL(&context, pairs) ++// yaml_free(tag_copy) ++// ++// return 0 ++//} ++// ++///* ++// * Append an item to a sequence node. ++// */ ++// ++//YAML_DECLARE(int) ++//yaml_document_append_sequence_item(document *yaml_document_t, ++// sequence int, item int) ++//{ ++// struct { ++// error yaml_error_type_t ++// } context ++// ++// assert(document) // Non-NULL document is required. ++// assert(sequence > 0 ++// && document.nodes.start + sequence <= document.nodes.top) ++// // Valid sequence id is required. ++// assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE) ++// // A sequence node is required. ++// assert(item > 0 && document.nodes.start + item <= document.nodes.top) ++// // Valid item id is required. ++// ++// if (!PUSH(&context, ++// document.nodes.start[sequence-1].data.sequence.items, item)) ++// return 0 ++// ++// return 1 ++//} ++// ++///* ++// * Append a pair of a key and a value to a mapping node. ++// */ ++// ++//YAML_DECLARE(int) ++//yaml_document_append_mapping_pair(document *yaml_document_t, ++// mapping int, key int, value int) ++//{ ++// struct { ++// error yaml_error_type_t ++// } context ++// ++// pair yaml_node_pair_t ++// ++// assert(document) // Non-NULL document is required. ++// assert(mapping > 0 ++// && document.nodes.start + mapping <= document.nodes.top) ++// // Valid mapping id is required. ++// assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE) ++// // A mapping node is required. ++// assert(key > 0 && document.nodes.start + key <= document.nodes.top) ++// // Valid key id is required. ++// assert(value > 0 && document.nodes.start + value <= document.nodes.top) ++// // Valid value id is required. ++// ++// pair.key = key ++// pair.value = value ++// ++// if (!PUSH(&context, ++// document.nodes.start[mapping-1].data.mapping.pairs, pair)) ++// return 0 ++// ++// return 1 ++//} ++// ++// +diff --git a/vendor/gopkg.in/yaml.v3/decode.go b/vendor/gopkg.in/yaml.v3/decode.go +new file mode 100644 +index 000000000000..0173b6982e84 +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/decode.go +@@ -0,0 +1,1000 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// ++// 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 yaml ++ ++import ( ++ "encoding" ++ "encoding/base64" ++ "fmt" ++ "io" ++ "math" ++ "reflect" ++ "strconv" ++ "time" ++) ++ ++// ---------------------------------------------------------------------------- ++// Parser, produces a node tree out of a libyaml event stream. ++ ++type parser struct { ++ parser yaml_parser_t ++ event yaml_event_t ++ doc *Node ++ anchors map[string]*Node ++ doneInit bool ++ textless bool ++} ++ ++func newParser(b []byte) *parser { ++ p := parser{} ++ if !yaml_parser_initialize(&p.parser) { ++ panic("failed to initialize YAML emitter") ++ } ++ if len(b) == 0 { ++ b = []byte{'\n'} ++ } ++ yaml_parser_set_input_string(&p.parser, b) ++ return &p ++} ++ ++func newParserFromReader(r io.Reader) *parser { ++ p := parser{} ++ if !yaml_parser_initialize(&p.parser) { ++ panic("failed to initialize YAML emitter") ++ } ++ yaml_parser_set_input_reader(&p.parser, r) ++ return &p ++} ++ ++func (p *parser) init() { ++ if p.doneInit { ++ return ++ } ++ p.anchors = make(map[string]*Node) ++ p.expect(yaml_STREAM_START_EVENT) ++ p.doneInit = true ++} ++ ++func (p *parser) destroy() { ++ if p.event.typ != yaml_NO_EVENT { ++ yaml_event_delete(&p.event) ++ } ++ yaml_parser_delete(&p.parser) ++} ++ ++// expect consumes an event from the event stream and ++// checks that it's of the expected type. ++func (p *parser) expect(e yaml_event_type_t) { ++ if p.event.typ == yaml_NO_EVENT { ++ if !yaml_parser_parse(&p.parser, &p.event) { ++ p.fail() ++ } ++ } ++ if p.event.typ == yaml_STREAM_END_EVENT { ++ failf("attempted to go past the end of stream; corrupted value?") ++ } ++ if p.event.typ != e { ++ p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ) ++ p.fail() ++ } ++ yaml_event_delete(&p.event) ++ p.event.typ = yaml_NO_EVENT ++} ++ ++// peek peeks at the next event in the event stream, ++// puts the results into p.event and returns the event type. ++func (p *parser) peek() yaml_event_type_t { ++ if p.event.typ != yaml_NO_EVENT { ++ return p.event.typ ++ } ++ // It's curious choice from the underlying API to generally return a ++ // positive result on success, but on this case return true in an error ++ // scenario. This was the source of bugs in the past (issue #666). ++ if !yaml_parser_parse(&p.parser, &p.event) || p.parser.error != yaml_NO_ERROR { ++ p.fail() ++ } ++ return p.event.typ ++} ++ ++func (p *parser) fail() { ++ var where string ++ var line int ++ if p.parser.context_mark.line != 0 { ++ line = p.parser.context_mark.line ++ // Scanner errors don't iterate line before returning error ++ if p.parser.error == yaml_SCANNER_ERROR { ++ line++ ++ } ++ } else if p.parser.problem_mark.line != 0 { ++ line = p.parser.problem_mark.line ++ // Scanner errors don't iterate line before returning error ++ if p.parser.error == yaml_SCANNER_ERROR { ++ line++ ++ } ++ } ++ if line != 0 { ++ where = "line " + strconv.Itoa(line) + ": " ++ } ++ var msg string ++ if len(p.parser.problem) > 0 { ++ msg = p.parser.problem ++ } else { ++ msg = "unknown problem parsing YAML content" ++ } ++ failf("%s%s", where, msg) ++} ++ ++func (p *parser) anchor(n *Node, anchor []byte) { ++ if anchor != nil { ++ n.Anchor = string(anchor) ++ p.anchors[n.Anchor] = n ++ } ++} ++ ++func (p *parser) parse() *Node { ++ p.init() ++ switch p.peek() { ++ case yaml_SCALAR_EVENT: ++ return p.scalar() ++ case yaml_ALIAS_EVENT: ++ return p.alias() ++ case yaml_MAPPING_START_EVENT: ++ return p.mapping() ++ case yaml_SEQUENCE_START_EVENT: ++ return p.sequence() ++ case yaml_DOCUMENT_START_EVENT: ++ return p.document() ++ case yaml_STREAM_END_EVENT: ++ // Happens when attempting to decode an empty buffer. ++ return nil ++ case yaml_TAIL_COMMENT_EVENT: ++ panic("internal error: unexpected tail comment event (please report)") ++ default: ++ panic("internal error: attempted to parse unknown event (please report): " + p.event.typ.String()) ++ } ++} ++ ++func (p *parser) node(kind Kind, defaultTag, tag, value string) *Node { ++ var style Style ++ if tag != "" && tag != "!" { ++ tag = shortTag(tag) ++ style = TaggedStyle ++ } else if defaultTag != "" { ++ tag = defaultTag ++ } else if kind == ScalarNode { ++ tag, _ = resolve("", value) ++ } ++ n := &Node{ ++ Kind: kind, ++ Tag: tag, ++ Value: value, ++ Style: style, ++ } ++ if !p.textless { ++ n.Line = p.event.start_mark.line + 1 ++ n.Column = p.event.start_mark.column + 1 ++ n.HeadComment = string(p.event.head_comment) ++ n.LineComment = string(p.event.line_comment) ++ n.FootComment = string(p.event.foot_comment) ++ } ++ return n ++} ++ ++func (p *parser) parseChild(parent *Node) *Node { ++ child := p.parse() ++ parent.Content = append(parent.Content, child) ++ return child ++} ++ ++func (p *parser) document() *Node { ++ n := p.node(DocumentNode, "", "", "") ++ p.doc = n ++ p.expect(yaml_DOCUMENT_START_EVENT) ++ p.parseChild(n) ++ if p.peek() == yaml_DOCUMENT_END_EVENT { ++ n.FootComment = string(p.event.foot_comment) ++ } ++ p.expect(yaml_DOCUMENT_END_EVENT) ++ return n ++} ++ ++func (p *parser) alias() *Node { ++ n := p.node(AliasNode, "", "", string(p.event.anchor)) ++ n.Alias = p.anchors[n.Value] ++ if n.Alias == nil { ++ failf("unknown anchor '%s' referenced", n.Value) ++ } ++ p.expect(yaml_ALIAS_EVENT) ++ return n ++} ++ ++func (p *parser) scalar() *Node { ++ var parsedStyle = p.event.scalar_style() ++ var nodeStyle Style ++ switch { ++ case parsedStyle&yaml_DOUBLE_QUOTED_SCALAR_STYLE != 0: ++ nodeStyle = DoubleQuotedStyle ++ case parsedStyle&yaml_SINGLE_QUOTED_SCALAR_STYLE != 0: ++ nodeStyle = SingleQuotedStyle ++ case parsedStyle&yaml_LITERAL_SCALAR_STYLE != 0: ++ nodeStyle = LiteralStyle ++ case parsedStyle&yaml_FOLDED_SCALAR_STYLE != 0: ++ nodeStyle = FoldedStyle ++ } ++ var nodeValue = string(p.event.value) ++ var nodeTag = string(p.event.tag) ++ var defaultTag string ++ if nodeStyle == 0 { ++ if nodeValue == "<<" { ++ defaultTag = mergeTag ++ } ++ } else { ++ defaultTag = strTag ++ } ++ n := p.node(ScalarNode, defaultTag, nodeTag, nodeValue) ++ n.Style |= nodeStyle ++ p.anchor(n, p.event.anchor) ++ p.expect(yaml_SCALAR_EVENT) ++ return n ++} ++ ++func (p *parser) sequence() *Node { ++ n := p.node(SequenceNode, seqTag, string(p.event.tag), "") ++ if p.event.sequence_style()&yaml_FLOW_SEQUENCE_STYLE != 0 { ++ n.Style |= FlowStyle ++ } ++ p.anchor(n, p.event.anchor) ++ p.expect(yaml_SEQUENCE_START_EVENT) ++ for p.peek() != yaml_SEQUENCE_END_EVENT { ++ p.parseChild(n) ++ } ++ n.LineComment = string(p.event.line_comment) ++ n.FootComment = string(p.event.foot_comment) ++ p.expect(yaml_SEQUENCE_END_EVENT) ++ return n ++} ++ ++func (p *parser) mapping() *Node { ++ n := p.node(MappingNode, mapTag, string(p.event.tag), "") ++ block := true ++ if p.event.mapping_style()&yaml_FLOW_MAPPING_STYLE != 0 { ++ block = false ++ n.Style |= FlowStyle ++ } ++ p.anchor(n, p.event.anchor) ++ p.expect(yaml_MAPPING_START_EVENT) ++ for p.peek() != yaml_MAPPING_END_EVENT { ++ k := p.parseChild(n) ++ if block && k.FootComment != "" { ++ // Must be a foot comment for the prior value when being dedented. ++ if len(n.Content) > 2 { ++ n.Content[len(n.Content)-3].FootComment = k.FootComment ++ k.FootComment = "" ++ } ++ } ++ v := p.parseChild(n) ++ if k.FootComment == "" && v.FootComment != "" { ++ k.FootComment = v.FootComment ++ v.FootComment = "" ++ } ++ if p.peek() == yaml_TAIL_COMMENT_EVENT { ++ if k.FootComment == "" { ++ k.FootComment = string(p.event.foot_comment) ++ } ++ p.expect(yaml_TAIL_COMMENT_EVENT) ++ } ++ } ++ n.LineComment = string(p.event.line_comment) ++ n.FootComment = string(p.event.foot_comment) ++ if n.Style&FlowStyle == 0 && n.FootComment != "" && len(n.Content) > 1 { ++ n.Content[len(n.Content)-2].FootComment = n.FootComment ++ n.FootComment = "" ++ } ++ p.expect(yaml_MAPPING_END_EVENT) ++ return n ++} ++ ++// ---------------------------------------------------------------------------- ++// Decoder, unmarshals a node into a provided value. ++ ++type decoder struct { ++ doc *Node ++ aliases map[*Node]bool ++ terrors []string ++ ++ stringMapType reflect.Type ++ generalMapType reflect.Type ++ ++ knownFields bool ++ uniqueKeys bool ++ decodeCount int ++ aliasCount int ++ aliasDepth int ++ ++ mergedFields map[interface{}]bool ++} ++ ++var ( ++ nodeType = reflect.TypeOf(Node{}) ++ durationType = reflect.TypeOf(time.Duration(0)) ++ stringMapType = reflect.TypeOf(map[string]interface{}{}) ++ generalMapType = reflect.TypeOf(map[interface{}]interface{}{}) ++ ifaceType = generalMapType.Elem() ++ timeType = reflect.TypeOf(time.Time{}) ++ ptrTimeType = reflect.TypeOf(&time.Time{}) ++) ++ ++func newDecoder() *decoder { ++ d := &decoder{ ++ stringMapType: stringMapType, ++ generalMapType: generalMapType, ++ uniqueKeys: true, ++ } ++ d.aliases = make(map[*Node]bool) ++ return d ++} ++ ++func (d *decoder) terror(n *Node, tag string, out reflect.Value) { ++ if n.Tag != "" { ++ tag = n.Tag ++ } ++ value := n.Value ++ if tag != seqTag && tag != mapTag { ++ if len(value) > 10 { ++ value = " `" + value[:7] + "...`" ++ } else { ++ value = " `" + value + "`" ++ } ++ } ++ d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.Line, shortTag(tag), value, out.Type())) ++} ++ ++func (d *decoder) callUnmarshaler(n *Node, u Unmarshaler) (good bool) { ++ err := u.UnmarshalYAML(n) ++ if e, ok := err.(*TypeError); ok { ++ d.terrors = append(d.terrors, e.Errors...) ++ return false ++ } ++ if err != nil { ++ fail(err) ++ } ++ return true ++} ++ ++func (d *decoder) callObsoleteUnmarshaler(n *Node, u obsoleteUnmarshaler) (good bool) { ++ terrlen := len(d.terrors) ++ err := u.UnmarshalYAML(func(v interface{}) (err error) { ++ defer handleErr(&err) ++ d.unmarshal(n, reflect.ValueOf(v)) ++ if len(d.terrors) > terrlen { ++ issues := d.terrors[terrlen:] ++ d.terrors = d.terrors[:terrlen] ++ return &TypeError{issues} ++ } ++ return nil ++ }) ++ if e, ok := err.(*TypeError); ok { ++ d.terrors = append(d.terrors, e.Errors...) ++ return false ++ } ++ if err != nil { ++ fail(err) ++ } ++ return true ++} ++ ++// d.prepare initializes and dereferences pointers and calls UnmarshalYAML ++// if a value is found to implement it. ++// It returns the initialized and dereferenced out value, whether ++// unmarshalling was already done by UnmarshalYAML, and if so whether ++// its types unmarshalled appropriately. ++// ++// If n holds a null value, prepare returns before doing anything. ++func (d *decoder) prepare(n *Node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) { ++ if n.ShortTag() == nullTag { ++ return out, false, false ++ } ++ again := true ++ for again { ++ again = false ++ if out.Kind() == reflect.Ptr { ++ if out.IsNil() { ++ out.Set(reflect.New(out.Type().Elem())) ++ } ++ out = out.Elem() ++ again = true ++ } ++ if out.CanAddr() { ++ outi := out.Addr().Interface() ++ if u, ok := outi.(Unmarshaler); ok { ++ good = d.callUnmarshaler(n, u) ++ return out, true, good ++ } ++ if u, ok := outi.(obsoleteUnmarshaler); ok { ++ good = d.callObsoleteUnmarshaler(n, u) ++ return out, true, good ++ } ++ } ++ } ++ return out, false, false ++} ++ ++func (d *decoder) fieldByIndex(n *Node, v reflect.Value, index []int) (field reflect.Value) { ++ if n.ShortTag() == nullTag { ++ return reflect.Value{} ++ } ++ for _, num := range index { ++ for { ++ if v.Kind() == reflect.Ptr { ++ if v.IsNil() { ++ v.Set(reflect.New(v.Type().Elem())) ++ } ++ v = v.Elem() ++ continue ++ } ++ break ++ } ++ v = v.Field(num) ++ } ++ return v ++} ++ ++const ( ++ // 400,000 decode operations is ~500kb of dense object declarations, or ++ // ~5kb of dense object declarations with 10000% alias expansion ++ alias_ratio_range_low = 400000 ++ ++ // 4,000,000 decode operations is ~5MB of dense object declarations, or ++ // ~4.5MB of dense object declarations with 10% alias expansion ++ alias_ratio_range_high = 4000000 ++ ++ // alias_ratio_range is the range over which we scale allowed alias ratios ++ alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low) ++) ++ ++func allowedAliasRatio(decodeCount int) float64 { ++ switch { ++ case decodeCount <= alias_ratio_range_low: ++ // allow 99% to come from alias expansion for small-to-medium documents ++ return 0.99 ++ case decodeCount >= alias_ratio_range_high: ++ // allow 10% to come from alias expansion for very large documents ++ return 0.10 ++ default: ++ // scale smoothly from 99% down to 10% over the range. ++ // this maps to 396,000 - 400,000 allowed alias-driven decodes over the range. ++ // 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps). ++ return 0.99 - 0.89*(float64(decodeCount-alias_ratio_range_low)/alias_ratio_range) ++ } ++} ++ ++func (d *decoder) unmarshal(n *Node, out reflect.Value) (good bool) { ++ d.decodeCount++ ++ if d.aliasDepth > 0 { ++ d.aliasCount++ ++ } ++ if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > allowedAliasRatio(d.decodeCount) { ++ failf("document contains excessive aliasing") ++ } ++ if out.Type() == nodeType { ++ out.Set(reflect.ValueOf(n).Elem()) ++ return true ++ } ++ switch n.Kind { ++ case DocumentNode: ++ return d.document(n, out) ++ case AliasNode: ++ return d.alias(n, out) ++ } ++ out, unmarshaled, good := d.prepare(n, out) ++ if unmarshaled { ++ return good ++ } ++ switch n.Kind { ++ case ScalarNode: ++ good = d.scalar(n, out) ++ case MappingNode: ++ good = d.mapping(n, out) ++ case SequenceNode: ++ good = d.sequence(n, out) ++ case 0: ++ if n.IsZero() { ++ return d.null(out) ++ } ++ fallthrough ++ default: ++ failf("cannot decode node with unknown kind %d", n.Kind) ++ } ++ return good ++} ++ ++func (d *decoder) document(n *Node, out reflect.Value) (good bool) { ++ if len(n.Content) == 1 { ++ d.doc = n ++ d.unmarshal(n.Content[0], out) ++ return true ++ } ++ return false ++} ++ ++func (d *decoder) alias(n *Node, out reflect.Value) (good bool) { ++ if d.aliases[n] { ++ // TODO this could actually be allowed in some circumstances. ++ failf("anchor '%s' value contains itself", n.Value) ++ } ++ d.aliases[n] = true ++ d.aliasDepth++ ++ good = d.unmarshal(n.Alias, out) ++ d.aliasDepth-- ++ delete(d.aliases, n) ++ return good ++} ++ ++var zeroValue reflect.Value ++ ++func resetMap(out reflect.Value) { ++ for _, k := range out.MapKeys() { ++ out.SetMapIndex(k, zeroValue) ++ } ++} ++ ++func (d *decoder) null(out reflect.Value) bool { ++ if out.CanAddr() { ++ switch out.Kind() { ++ case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: ++ out.Set(reflect.Zero(out.Type())) ++ return true ++ } ++ } ++ return false ++} ++ ++func (d *decoder) scalar(n *Node, out reflect.Value) bool { ++ var tag string ++ var resolved interface{} ++ if n.indicatedString() { ++ tag = strTag ++ resolved = n.Value ++ } else { ++ tag, resolved = resolve(n.Tag, n.Value) ++ if tag == binaryTag { ++ data, err := base64.StdEncoding.DecodeString(resolved.(string)) ++ if err != nil { ++ failf("!!binary value contains invalid base64 data") ++ } ++ resolved = string(data) ++ } ++ } ++ if resolved == nil { ++ return d.null(out) ++ } ++ if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() { ++ // We've resolved to exactly the type we want, so use that. ++ out.Set(resolvedv) ++ return true ++ } ++ // Perhaps we can use the value as a TextUnmarshaler to ++ // set its value. ++ if out.CanAddr() { ++ u, ok := out.Addr().Interface().(encoding.TextUnmarshaler) ++ if ok { ++ var text []byte ++ if tag == binaryTag { ++ text = []byte(resolved.(string)) ++ } else { ++ // We let any value be unmarshaled into TextUnmarshaler. ++ // That might be more lax than we'd like, but the ++ // TextUnmarshaler itself should bowl out any dubious values. ++ text = []byte(n.Value) ++ } ++ err := u.UnmarshalText(text) ++ if err != nil { ++ fail(err) ++ } ++ return true ++ } ++ } ++ switch out.Kind() { ++ case reflect.String: ++ if tag == binaryTag { ++ out.SetString(resolved.(string)) ++ return true ++ } ++ out.SetString(n.Value) ++ return true ++ case reflect.Interface: ++ out.Set(reflect.ValueOf(resolved)) ++ return true ++ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: ++ // This used to work in v2, but it's very unfriendly. ++ isDuration := out.Type() == durationType ++ ++ switch resolved := resolved.(type) { ++ case int: ++ if !isDuration && !out.OverflowInt(int64(resolved)) { ++ out.SetInt(int64(resolved)) ++ return true ++ } ++ case int64: ++ if !isDuration && !out.OverflowInt(resolved) { ++ out.SetInt(resolved) ++ return true ++ } ++ case uint64: ++ if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { ++ out.SetInt(int64(resolved)) ++ return true ++ } ++ case float64: ++ if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { ++ out.SetInt(int64(resolved)) ++ return true ++ } ++ case string: ++ if out.Type() == durationType { ++ d, err := time.ParseDuration(resolved) ++ if err == nil { ++ out.SetInt(int64(d)) ++ return true ++ } ++ } ++ } ++ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: ++ switch resolved := resolved.(type) { ++ case int: ++ if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { ++ out.SetUint(uint64(resolved)) ++ return true ++ } ++ case int64: ++ if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { ++ out.SetUint(uint64(resolved)) ++ return true ++ } ++ case uint64: ++ if !out.OverflowUint(uint64(resolved)) { ++ out.SetUint(uint64(resolved)) ++ return true ++ } ++ case float64: ++ if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) { ++ out.SetUint(uint64(resolved)) ++ return true ++ } ++ } ++ case reflect.Bool: ++ switch resolved := resolved.(type) { ++ case bool: ++ out.SetBool(resolved) ++ return true ++ case string: ++ // This offers some compatibility with the 1.1 spec (https://yaml.org/type/bool.html). ++ // It only works if explicitly attempting to unmarshal into a typed bool value. ++ switch resolved { ++ case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON": ++ out.SetBool(true) ++ return true ++ case "n", "N", "no", "No", "NO", "off", "Off", "OFF": ++ out.SetBool(false) ++ return true ++ } ++ } ++ case reflect.Float32, reflect.Float64: ++ switch resolved := resolved.(type) { ++ case int: ++ out.SetFloat(float64(resolved)) ++ return true ++ case int64: ++ out.SetFloat(float64(resolved)) ++ return true ++ case uint64: ++ out.SetFloat(float64(resolved)) ++ return true ++ case float64: ++ out.SetFloat(resolved) ++ return true ++ } ++ case reflect.Struct: ++ if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() { ++ out.Set(resolvedv) ++ return true ++ } ++ case reflect.Ptr: ++ panic("yaml internal error: please report the issue") ++ } ++ d.terror(n, tag, out) ++ return false ++} ++ ++func settableValueOf(i interface{}) reflect.Value { ++ v := reflect.ValueOf(i) ++ sv := reflect.New(v.Type()).Elem() ++ sv.Set(v) ++ return sv ++} ++ ++func (d *decoder) sequence(n *Node, out reflect.Value) (good bool) { ++ l := len(n.Content) ++ ++ var iface reflect.Value ++ switch out.Kind() { ++ case reflect.Slice: ++ out.Set(reflect.MakeSlice(out.Type(), l, l)) ++ case reflect.Array: ++ if l != out.Len() { ++ failf("invalid array: want %d elements but got %d", out.Len(), l) ++ } ++ case reflect.Interface: ++ // No type hints. Will have to use a generic sequence. ++ iface = out ++ out = settableValueOf(make([]interface{}, l)) ++ default: ++ d.terror(n, seqTag, out) ++ return false ++ } ++ et := out.Type().Elem() ++ ++ j := 0 ++ for i := 0; i < l; i++ { ++ e := reflect.New(et).Elem() ++ if ok := d.unmarshal(n.Content[i], e); ok { ++ out.Index(j).Set(e) ++ j++ ++ } ++ } ++ if out.Kind() != reflect.Array { ++ out.Set(out.Slice(0, j)) ++ } ++ if iface.IsValid() { ++ iface.Set(out) ++ } ++ return true ++} ++ ++func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) { ++ l := len(n.Content) ++ if d.uniqueKeys { ++ nerrs := len(d.terrors) ++ for i := 0; i < l; i += 2 { ++ ni := n.Content[i] ++ for j := i + 2; j < l; j += 2 { ++ nj := n.Content[j] ++ if ni.Kind == nj.Kind && ni.Value == nj.Value { ++ d.terrors = append(d.terrors, fmt.Sprintf("line %d: mapping key %#v already defined at line %d", nj.Line, nj.Value, ni.Line)) ++ } ++ } ++ } ++ if len(d.terrors) > nerrs { ++ return false ++ } ++ } ++ switch out.Kind() { ++ case reflect.Struct: ++ return d.mappingStruct(n, out) ++ case reflect.Map: ++ // okay ++ case reflect.Interface: ++ iface := out ++ if isStringMap(n) { ++ out = reflect.MakeMap(d.stringMapType) ++ } else { ++ out = reflect.MakeMap(d.generalMapType) ++ } ++ iface.Set(out) ++ default: ++ d.terror(n, mapTag, out) ++ return false ++ } ++ ++ outt := out.Type() ++ kt := outt.Key() ++ et := outt.Elem() ++ ++ stringMapType := d.stringMapType ++ generalMapType := d.generalMapType ++ if outt.Elem() == ifaceType { ++ if outt.Key().Kind() == reflect.String { ++ d.stringMapType = outt ++ } else if outt.Key() == ifaceType { ++ d.generalMapType = outt ++ } ++ } ++ ++ mergedFields := d.mergedFields ++ d.mergedFields = nil ++ ++ var mergeNode *Node ++ ++ mapIsNew := false ++ if out.IsNil() { ++ out.Set(reflect.MakeMap(outt)) ++ mapIsNew = true ++ } ++ for i := 0; i < l; i += 2 { ++ if isMerge(n.Content[i]) { ++ mergeNode = n.Content[i+1] ++ continue ++ } ++ k := reflect.New(kt).Elem() ++ if d.unmarshal(n.Content[i], k) { ++ if mergedFields != nil { ++ ki := k.Interface() ++ if mergedFields[ki] { ++ continue ++ } ++ mergedFields[ki] = true ++ } ++ kkind := k.Kind() ++ if kkind == reflect.Interface { ++ kkind = k.Elem().Kind() ++ } ++ if kkind == reflect.Map || kkind == reflect.Slice { ++ failf("invalid map key: %#v", k.Interface()) ++ } ++ e := reflect.New(et).Elem() ++ if d.unmarshal(n.Content[i+1], e) || n.Content[i+1].ShortTag() == nullTag && (mapIsNew || !out.MapIndex(k).IsValid()) { ++ out.SetMapIndex(k, e) ++ } ++ } ++ } ++ ++ d.mergedFields = mergedFields ++ if mergeNode != nil { ++ d.merge(n, mergeNode, out) ++ } ++ ++ d.stringMapType = stringMapType ++ d.generalMapType = generalMapType ++ return true ++} ++ ++func isStringMap(n *Node) bool { ++ if n.Kind != MappingNode { ++ return false ++ } ++ l := len(n.Content) ++ for i := 0; i < l; i += 2 { ++ shortTag := n.Content[i].ShortTag() ++ if shortTag != strTag && shortTag != mergeTag { ++ return false ++ } ++ } ++ return true ++} ++ ++func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) { ++ sinfo, err := getStructInfo(out.Type()) ++ if err != nil { ++ panic(err) ++ } ++ ++ var inlineMap reflect.Value ++ var elemType reflect.Type ++ if sinfo.InlineMap != -1 { ++ inlineMap = out.Field(sinfo.InlineMap) ++ elemType = inlineMap.Type().Elem() ++ } ++ ++ for _, index := range sinfo.InlineUnmarshalers { ++ field := d.fieldByIndex(n, out, index) ++ d.prepare(n, field) ++ } ++ ++ mergedFields := d.mergedFields ++ d.mergedFields = nil ++ var mergeNode *Node ++ var doneFields []bool ++ if d.uniqueKeys { ++ doneFields = make([]bool, len(sinfo.FieldsList)) ++ } ++ name := settableValueOf("") ++ l := len(n.Content) ++ for i := 0; i < l; i += 2 { ++ ni := n.Content[i] ++ if isMerge(ni) { ++ mergeNode = n.Content[i+1] ++ continue ++ } ++ if !d.unmarshal(ni, name) { ++ continue ++ } ++ sname := name.String() ++ if mergedFields != nil { ++ if mergedFields[sname] { ++ continue ++ } ++ mergedFields[sname] = true ++ } ++ if info, ok := sinfo.FieldsMap[sname]; ok { ++ if d.uniqueKeys { ++ if doneFields[info.Id] { ++ d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type())) ++ continue ++ } ++ doneFields[info.Id] = true ++ } ++ var field reflect.Value ++ if info.Inline == nil { ++ field = out.Field(info.Num) ++ } else { ++ field = d.fieldByIndex(n, out, info.Inline) ++ } ++ d.unmarshal(n.Content[i+1], field) ++ } else if sinfo.InlineMap != -1 { ++ if inlineMap.IsNil() { ++ inlineMap.Set(reflect.MakeMap(inlineMap.Type())) ++ } ++ value := reflect.New(elemType).Elem() ++ d.unmarshal(n.Content[i+1], value) ++ inlineMap.SetMapIndex(name, value) ++ } else if d.knownFields { ++ d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type())) ++ } ++ } ++ ++ d.mergedFields = mergedFields ++ if mergeNode != nil { ++ d.merge(n, mergeNode, out) ++ } ++ return true ++} ++ ++func failWantMap() { ++ failf("map merge requires map or sequence of maps as the value") ++} ++ ++func (d *decoder) merge(parent *Node, merge *Node, out reflect.Value) { ++ mergedFields := d.mergedFields ++ if mergedFields == nil { ++ d.mergedFields = make(map[interface{}]bool) ++ for i := 0; i < len(parent.Content); i += 2 { ++ k := reflect.New(ifaceType).Elem() ++ if d.unmarshal(parent.Content[i], k) { ++ d.mergedFields[k.Interface()] = true ++ } ++ } ++ } ++ ++ switch merge.Kind { ++ case MappingNode: ++ d.unmarshal(merge, out) ++ case AliasNode: ++ if merge.Alias != nil && merge.Alias.Kind != MappingNode { ++ failWantMap() ++ } ++ d.unmarshal(merge, out) ++ case SequenceNode: ++ for i := 0; i < len(merge.Content); i++ { ++ ni := merge.Content[i] ++ if ni.Kind == AliasNode { ++ if ni.Alias != nil && ni.Alias.Kind != MappingNode { ++ failWantMap() ++ } ++ } else if ni.Kind != MappingNode { ++ failWantMap() ++ } ++ d.unmarshal(ni, out) ++ } ++ default: ++ failWantMap() ++ } ++ ++ d.mergedFields = mergedFields ++} ++ ++func isMerge(n *Node) bool { ++ return n.Kind == ScalarNode && n.Value == "<<" && (n.Tag == "" || n.Tag == "!" || shortTag(n.Tag) == mergeTag) ++} +diff --git a/vendor/gopkg.in/yaml.v3/emitterc.go b/vendor/gopkg.in/yaml.v3/emitterc.go +new file mode 100644 +index 000000000000..0f47c9ca8add +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/emitterc.go +@@ -0,0 +1,2020 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// Copyright (c) 2006-2010 Kirill Simonov ++// ++// 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. ++ ++package yaml ++ ++import ( ++ "bytes" ++ "fmt" ++) ++ ++// Flush the buffer if needed. ++func flush(emitter *yaml_emitter_t) bool { ++ if emitter.buffer_pos+5 >= len(emitter.buffer) { ++ return yaml_emitter_flush(emitter) ++ } ++ return true ++} ++ ++// Put a character to the output buffer. ++func put(emitter *yaml_emitter_t, value byte) bool { ++ if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { ++ return false ++ } ++ emitter.buffer[emitter.buffer_pos] = value ++ emitter.buffer_pos++ ++ emitter.column++ ++ return true ++} ++ ++// Put a line break to the output buffer. ++func put_break(emitter *yaml_emitter_t) bool { ++ if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { ++ return false ++ } ++ switch emitter.line_break { ++ case yaml_CR_BREAK: ++ emitter.buffer[emitter.buffer_pos] = '\r' ++ emitter.buffer_pos += 1 ++ case yaml_LN_BREAK: ++ emitter.buffer[emitter.buffer_pos] = '\n' ++ emitter.buffer_pos += 1 ++ case yaml_CRLN_BREAK: ++ emitter.buffer[emitter.buffer_pos+0] = '\r' ++ emitter.buffer[emitter.buffer_pos+1] = '\n' ++ emitter.buffer_pos += 2 ++ default: ++ panic("unknown line break setting") ++ } ++ if emitter.column == 0 { ++ emitter.space_above = true ++ } ++ emitter.column = 0 ++ emitter.line++ ++ // [Go] Do this here and below and drop from everywhere else (see commented lines). ++ emitter.indention = true ++ return true ++} ++ ++// Copy a character from a string into buffer. ++func write(emitter *yaml_emitter_t, s []byte, i *int) bool { ++ if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { ++ return false ++ } ++ p := emitter.buffer_pos ++ w := width(s[*i]) ++ switch w { ++ case 4: ++ emitter.buffer[p+3] = s[*i+3] ++ fallthrough ++ case 3: ++ emitter.buffer[p+2] = s[*i+2] ++ fallthrough ++ case 2: ++ emitter.buffer[p+1] = s[*i+1] ++ fallthrough ++ case 1: ++ emitter.buffer[p+0] = s[*i+0] ++ default: ++ panic("unknown character width") ++ } ++ emitter.column++ ++ emitter.buffer_pos += w ++ *i += w ++ return true ++} ++ ++// Write a whole string into buffer. ++func write_all(emitter *yaml_emitter_t, s []byte) bool { ++ for i := 0; i < len(s); { ++ if !write(emitter, s, &i) { ++ return false ++ } ++ } ++ return true ++} ++ ++// Copy a line break character from a string into buffer. ++func write_break(emitter *yaml_emitter_t, s []byte, i *int) bool { ++ if s[*i] == '\n' { ++ if !put_break(emitter) { ++ return false ++ } ++ *i++ ++ } else { ++ if !write(emitter, s, i) { ++ return false ++ } ++ if emitter.column == 0 { ++ emitter.space_above = true ++ } ++ emitter.column = 0 ++ emitter.line++ ++ // [Go] Do this here and above and drop from everywhere else (see commented lines). ++ emitter.indention = true ++ } ++ return true ++} ++ ++// Set an emitter error and return false. ++func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t, problem string) bool { ++ emitter.error = yaml_EMITTER_ERROR ++ emitter.problem = problem ++ return false ++} ++ ++// Emit an event. ++func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool { ++ emitter.events = append(emitter.events, *event) ++ for !yaml_emitter_need_more_events(emitter) { ++ event := &emitter.events[emitter.events_head] ++ if !yaml_emitter_analyze_event(emitter, event) { ++ return false ++ } ++ if !yaml_emitter_state_machine(emitter, event) { ++ return false ++ } ++ yaml_event_delete(event) ++ emitter.events_head++ ++ } ++ return true ++} ++ ++// Check if we need to accumulate more events before emitting. ++// ++// We accumulate extra ++// - 1 event for DOCUMENT-START ++// - 2 events for SEQUENCE-START ++// - 3 events for MAPPING-START ++// ++func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool { ++ if emitter.events_head == len(emitter.events) { ++ return true ++ } ++ var accumulate int ++ switch emitter.events[emitter.events_head].typ { ++ case yaml_DOCUMENT_START_EVENT: ++ accumulate = 1 ++ break ++ case yaml_SEQUENCE_START_EVENT: ++ accumulate = 2 ++ break ++ case yaml_MAPPING_START_EVENT: ++ accumulate = 3 ++ break ++ default: ++ return false ++ } ++ if len(emitter.events)-emitter.events_head > accumulate { ++ return false ++ } ++ var level int ++ for i := emitter.events_head; i < len(emitter.events); i++ { ++ switch emitter.events[i].typ { ++ case yaml_STREAM_START_EVENT, yaml_DOCUMENT_START_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT: ++ level++ ++ case yaml_STREAM_END_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_END_EVENT, yaml_MAPPING_END_EVENT: ++ level-- ++ } ++ if level == 0 { ++ return false ++ } ++ } ++ return true ++} ++ ++// Append a directive to the directives stack. ++func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *yaml_tag_directive_t, allow_duplicates bool) bool { ++ for i := 0; i < len(emitter.tag_directives); i++ { ++ if bytes.Equal(value.handle, emitter.tag_directives[i].handle) { ++ if allow_duplicates { ++ return true ++ } ++ return yaml_emitter_set_emitter_error(emitter, "duplicate %TAG directive") ++ } ++ } ++ ++ // [Go] Do we actually need to copy this given garbage collection ++ // and the lack of deallocating destructors? ++ tag_copy := yaml_tag_directive_t{ ++ handle: make([]byte, len(value.handle)), ++ prefix: make([]byte, len(value.prefix)), ++ } ++ copy(tag_copy.handle, value.handle) ++ copy(tag_copy.prefix, value.prefix) ++ emitter.tag_directives = append(emitter.tag_directives, tag_copy) ++ return true ++} ++ ++// Increase the indentation level. ++func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool) bool { ++ emitter.indents = append(emitter.indents, emitter.indent) ++ if emitter.indent < 0 { ++ if flow { ++ emitter.indent = emitter.best_indent ++ } else { ++ emitter.indent = 0 ++ } ++ } else if !indentless { ++ // [Go] This was changed so that indentations are more regular. ++ if emitter.states[len(emitter.states)-1] == yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE { ++ // The first indent inside a sequence will just skip the "- " indicator. ++ emitter.indent += 2 ++ } else { ++ // Everything else aligns to the chosen indentation. ++ emitter.indent = emitter.best_indent*((emitter.indent+emitter.best_indent)/emitter.best_indent) ++ } ++ } ++ return true ++} ++ ++// State dispatcher. ++func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_event_t) bool { ++ switch emitter.state { ++ default: ++ case yaml_EMIT_STREAM_START_STATE: ++ return yaml_emitter_emit_stream_start(emitter, event) ++ ++ case yaml_EMIT_FIRST_DOCUMENT_START_STATE: ++ return yaml_emitter_emit_document_start(emitter, event, true) ++ ++ case yaml_EMIT_DOCUMENT_START_STATE: ++ return yaml_emitter_emit_document_start(emitter, event, false) ++ ++ case yaml_EMIT_DOCUMENT_CONTENT_STATE: ++ return yaml_emitter_emit_document_content(emitter, event) ++ ++ case yaml_EMIT_DOCUMENT_END_STATE: ++ return yaml_emitter_emit_document_end(emitter, event) ++ ++ case yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE: ++ return yaml_emitter_emit_flow_sequence_item(emitter, event, true, false) ++ ++ case yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE: ++ return yaml_emitter_emit_flow_sequence_item(emitter, event, false, true) ++ ++ case yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE: ++ return yaml_emitter_emit_flow_sequence_item(emitter, event, false, false) ++ ++ case yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE: ++ return yaml_emitter_emit_flow_mapping_key(emitter, event, true, false) ++ ++ case yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE: ++ return yaml_emitter_emit_flow_mapping_key(emitter, event, false, true) ++ ++ case yaml_EMIT_FLOW_MAPPING_KEY_STATE: ++ return yaml_emitter_emit_flow_mapping_key(emitter, event, false, false) ++ ++ case yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE: ++ return yaml_emitter_emit_flow_mapping_value(emitter, event, true) ++ ++ case yaml_EMIT_FLOW_MAPPING_VALUE_STATE: ++ return yaml_emitter_emit_flow_mapping_value(emitter, event, false) ++ ++ case yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE: ++ return yaml_emitter_emit_block_sequence_item(emitter, event, true) ++ ++ case yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE: ++ return yaml_emitter_emit_block_sequence_item(emitter, event, false) ++ ++ case yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE: ++ return yaml_emitter_emit_block_mapping_key(emitter, event, true) ++ ++ case yaml_EMIT_BLOCK_MAPPING_KEY_STATE: ++ return yaml_emitter_emit_block_mapping_key(emitter, event, false) ++ ++ case yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE: ++ return yaml_emitter_emit_block_mapping_value(emitter, event, true) ++ ++ case yaml_EMIT_BLOCK_MAPPING_VALUE_STATE: ++ return yaml_emitter_emit_block_mapping_value(emitter, event, false) ++ ++ case yaml_EMIT_END_STATE: ++ return yaml_emitter_set_emitter_error(emitter, "expected nothing after STREAM-END") ++ } ++ panic("invalid emitter state") ++} ++ ++// Expect STREAM-START. ++func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { ++ if event.typ != yaml_STREAM_START_EVENT { ++ return yaml_emitter_set_emitter_error(emitter, "expected STREAM-START") ++ } ++ if emitter.encoding == yaml_ANY_ENCODING { ++ emitter.encoding = event.encoding ++ if emitter.encoding == yaml_ANY_ENCODING { ++ emitter.encoding = yaml_UTF8_ENCODING ++ } ++ } ++ if emitter.best_indent < 2 || emitter.best_indent > 9 { ++ emitter.best_indent = 2 ++ } ++ if emitter.best_width >= 0 && emitter.best_width <= emitter.best_indent*2 { ++ emitter.best_width = 80 ++ } ++ if emitter.best_width < 0 { ++ emitter.best_width = 1<<31 - 1 ++ } ++ if emitter.line_break == yaml_ANY_BREAK { ++ emitter.line_break = yaml_LN_BREAK ++ } ++ ++ emitter.indent = -1 ++ emitter.line = 0 ++ emitter.column = 0 ++ emitter.whitespace = true ++ emitter.indention = true ++ emitter.space_above = true ++ emitter.foot_indent = -1 ++ ++ if emitter.encoding != yaml_UTF8_ENCODING { ++ if !yaml_emitter_write_bom(emitter) { ++ return false ++ } ++ } ++ emitter.state = yaml_EMIT_FIRST_DOCUMENT_START_STATE ++ return true ++} ++ ++// Expect DOCUMENT-START or STREAM-END. ++func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { ++ ++ if event.typ == yaml_DOCUMENT_START_EVENT { ++ ++ if event.version_directive != nil { ++ if !yaml_emitter_analyze_version_directive(emitter, event.version_directive) { ++ return false ++ } ++ } ++ ++ for i := 0; i < len(event.tag_directives); i++ { ++ tag_directive := &event.tag_directives[i] ++ if !yaml_emitter_analyze_tag_directive(emitter, tag_directive) { ++ return false ++ } ++ if !yaml_emitter_append_tag_directive(emitter, tag_directive, false) { ++ return false ++ } ++ } ++ ++ for i := 0; i < len(default_tag_directives); i++ { ++ tag_directive := &default_tag_directives[i] ++ if !yaml_emitter_append_tag_directive(emitter, tag_directive, true) { ++ return false ++ } ++ } ++ ++ implicit := event.implicit ++ if !first || emitter.canonical { ++ implicit = false ++ } ++ ++ if emitter.open_ended && (event.version_directive != nil || len(event.tag_directives) > 0) { ++ if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { ++ return false ++ } ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ ++ if event.version_directive != nil { ++ implicit = false ++ if !yaml_emitter_write_indicator(emitter, []byte("%YAML"), true, false, false) { ++ return false ++ } ++ if !yaml_emitter_write_indicator(emitter, []byte("1.1"), true, false, false) { ++ return false ++ } ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ ++ if len(event.tag_directives) > 0 { ++ implicit = false ++ for i := 0; i < len(event.tag_directives); i++ { ++ tag_directive := &event.tag_directives[i] ++ if !yaml_emitter_write_indicator(emitter, []byte("%TAG"), true, false, false) { ++ return false ++ } ++ if !yaml_emitter_write_tag_handle(emitter, tag_directive.handle) { ++ return false ++ } ++ if !yaml_emitter_write_tag_content(emitter, tag_directive.prefix, true) { ++ return false ++ } ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ } ++ ++ if yaml_emitter_check_empty_document(emitter) { ++ implicit = false ++ } ++ if !implicit { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ if !yaml_emitter_write_indicator(emitter, []byte("---"), true, false, false) { ++ return false ++ } ++ if emitter.canonical || true { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ } ++ ++ if len(emitter.head_comment) > 0 { ++ if !yaml_emitter_process_head_comment(emitter) { ++ return false ++ } ++ if !put_break(emitter) { ++ return false ++ } ++ } ++ ++ emitter.state = yaml_EMIT_DOCUMENT_CONTENT_STATE ++ return true ++ } ++ ++ if event.typ == yaml_STREAM_END_EVENT { ++ if emitter.open_ended { ++ if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { ++ return false ++ } ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ if !yaml_emitter_flush(emitter) { ++ return false ++ } ++ emitter.state = yaml_EMIT_END_STATE ++ return true ++ } ++ ++ return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-START or STREAM-END") ++} ++ ++// Expect the root node. ++func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *yaml_event_t) bool { ++ emitter.states = append(emitter.states, yaml_EMIT_DOCUMENT_END_STATE) ++ ++ if !yaml_emitter_process_head_comment(emitter) { ++ return false ++ } ++ if !yaml_emitter_emit_node(emitter, event, true, false, false, false) { ++ return false ++ } ++ if !yaml_emitter_process_line_comment(emitter) { ++ return false ++ } ++ if !yaml_emitter_process_foot_comment(emitter) { ++ return false ++ } ++ return true ++} ++ ++// Expect DOCUMENT-END. ++func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml_event_t) bool { ++ if event.typ != yaml_DOCUMENT_END_EVENT { ++ return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-END") ++ } ++ // [Go] Force document foot separation. ++ emitter.foot_indent = 0 ++ if !yaml_emitter_process_foot_comment(emitter) { ++ return false ++ } ++ emitter.foot_indent = -1 ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ if !event.implicit { ++ // [Go] Allocate the slice elsewhere. ++ if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { ++ return false ++ } ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ if !yaml_emitter_flush(emitter) { ++ return false ++ } ++ emitter.state = yaml_EMIT_DOCUMENT_START_STATE ++ emitter.tag_directives = emitter.tag_directives[:0] ++ return true ++} ++ ++// Expect a flow item node. ++func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool { ++ if first { ++ if !yaml_emitter_write_indicator(emitter, []byte{'['}, true, true, false) { ++ return false ++ } ++ if !yaml_emitter_increase_indent(emitter, true, false) { ++ return false ++ } ++ emitter.flow_level++ ++ } ++ ++ if event.typ == yaml_SEQUENCE_END_EVENT { ++ if emitter.canonical && !first && !trail { ++ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { ++ return false ++ } ++ } ++ emitter.flow_level-- ++ emitter.indent = emitter.indents[len(emitter.indents)-1] ++ emitter.indents = emitter.indents[:len(emitter.indents)-1] ++ if emitter.column == 0 || emitter.canonical && !first { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ if !yaml_emitter_write_indicator(emitter, []byte{']'}, false, false, false) { ++ return false ++ } ++ if !yaml_emitter_process_line_comment(emitter) { ++ return false ++ } ++ if !yaml_emitter_process_foot_comment(emitter) { ++ return false ++ } ++ emitter.state = emitter.states[len(emitter.states)-1] ++ emitter.states = emitter.states[:len(emitter.states)-1] ++ ++ return true ++ } ++ ++ if !first && !trail { ++ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { ++ return false ++ } ++ } ++ ++ if !yaml_emitter_process_head_comment(emitter) { ++ return false ++ } ++ if emitter.column == 0 { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ ++ if emitter.canonical || emitter.column > emitter.best_width { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { ++ emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE) ++ } else { ++ emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE) ++ } ++ if !yaml_emitter_emit_node(emitter, event, false, true, false, false) { ++ return false ++ } ++ if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { ++ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { ++ return false ++ } ++ } ++ if !yaml_emitter_process_line_comment(emitter) { ++ return false ++ } ++ if !yaml_emitter_process_foot_comment(emitter) { ++ return false ++ } ++ return true ++} ++ ++// Expect a flow key node. ++func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool { ++ if first { ++ if !yaml_emitter_write_indicator(emitter, []byte{'{'}, true, true, false) { ++ return false ++ } ++ if !yaml_emitter_increase_indent(emitter, true, false) { ++ return false ++ } ++ emitter.flow_level++ ++ } ++ ++ if event.typ == yaml_MAPPING_END_EVENT { ++ if (emitter.canonical || len(emitter.head_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0) && !first && !trail { ++ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { ++ return false ++ } ++ } ++ if !yaml_emitter_process_head_comment(emitter) { ++ return false ++ } ++ emitter.flow_level-- ++ emitter.indent = emitter.indents[len(emitter.indents)-1] ++ emitter.indents = emitter.indents[:len(emitter.indents)-1] ++ if emitter.canonical && !first { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ if !yaml_emitter_write_indicator(emitter, []byte{'}'}, false, false, false) { ++ return false ++ } ++ if !yaml_emitter_process_line_comment(emitter) { ++ return false ++ } ++ if !yaml_emitter_process_foot_comment(emitter) { ++ return false ++ } ++ emitter.state = emitter.states[len(emitter.states)-1] ++ emitter.states = emitter.states[:len(emitter.states)-1] ++ return true ++ } ++ ++ if !first && !trail { ++ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { ++ return false ++ } ++ } ++ ++ if !yaml_emitter_process_head_comment(emitter) { ++ return false ++ } ++ ++ if emitter.column == 0 { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ ++ if emitter.canonical || emitter.column > emitter.best_width { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ ++ if !emitter.canonical && yaml_emitter_check_simple_key(emitter) { ++ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE) ++ return yaml_emitter_emit_node(emitter, event, false, false, true, true) ++ } ++ if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, false) { ++ return false ++ } ++ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_VALUE_STATE) ++ return yaml_emitter_emit_node(emitter, event, false, false, true, false) ++} ++ ++// Expect a flow value node. ++func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool { ++ if simple { ++ if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) { ++ return false ++ } ++ } else { ++ if emitter.canonical || emitter.column > emitter.best_width { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, false) { ++ return false ++ } ++ } ++ if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { ++ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE) ++ } else { ++ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_KEY_STATE) ++ } ++ if !yaml_emitter_emit_node(emitter, event, false, false, true, false) { ++ return false ++ } ++ if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { ++ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { ++ return false ++ } ++ } ++ if !yaml_emitter_process_line_comment(emitter) { ++ return false ++ } ++ if !yaml_emitter_process_foot_comment(emitter) { ++ return false ++ } ++ return true ++} ++ ++// Expect a block item node. ++func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { ++ if first { ++ if !yaml_emitter_increase_indent(emitter, false, false) { ++ return false ++ } ++ } ++ if event.typ == yaml_SEQUENCE_END_EVENT { ++ emitter.indent = emitter.indents[len(emitter.indents)-1] ++ emitter.indents = emitter.indents[:len(emitter.indents)-1] ++ emitter.state = emitter.states[len(emitter.states)-1] ++ emitter.states = emitter.states[:len(emitter.states)-1] ++ return true ++ } ++ if !yaml_emitter_process_head_comment(emitter) { ++ return false ++ } ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ if !yaml_emitter_write_indicator(emitter, []byte{'-'}, true, false, true) { ++ return false ++ } ++ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE) ++ if !yaml_emitter_emit_node(emitter, event, false, true, false, false) { ++ return false ++ } ++ if !yaml_emitter_process_line_comment(emitter) { ++ return false ++ } ++ if !yaml_emitter_process_foot_comment(emitter) { ++ return false ++ } ++ return true ++} ++ ++// Expect a block key node. ++func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { ++ if first { ++ if !yaml_emitter_increase_indent(emitter, false, false) { ++ return false ++ } ++ } ++ if !yaml_emitter_process_head_comment(emitter) { ++ return false ++ } ++ if event.typ == yaml_MAPPING_END_EVENT { ++ emitter.indent = emitter.indents[len(emitter.indents)-1] ++ emitter.indents = emitter.indents[:len(emitter.indents)-1] ++ emitter.state = emitter.states[len(emitter.states)-1] ++ emitter.states = emitter.states[:len(emitter.states)-1] ++ return true ++ } ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ if len(emitter.line_comment) > 0 { ++ // [Go] A line comment was provided for the key. That's unusual as the ++ // scanner associates line comments with the value. Either way, ++ // save the line comment and render it appropriately later. ++ emitter.key_line_comment = emitter.line_comment ++ emitter.line_comment = nil ++ } ++ if yaml_emitter_check_simple_key(emitter) { ++ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE) ++ return yaml_emitter_emit_node(emitter, event, false, false, true, true) ++ } ++ if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, true) { ++ return false ++ } ++ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_VALUE_STATE) ++ return yaml_emitter_emit_node(emitter, event, false, false, true, false) ++} ++ ++// Expect a block value node. ++func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool { ++ if simple { ++ if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) { ++ return false ++ } ++ } else { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, true) { ++ return false ++ } ++ } ++ if len(emitter.key_line_comment) > 0 { ++ // [Go] Line comments are generally associated with the value, but when there's ++ // no value on the same line as a mapping key they end up attached to the ++ // key itself. ++ if event.typ == yaml_SCALAR_EVENT { ++ if len(emitter.line_comment) == 0 { ++ // A scalar is coming and it has no line comments by itself yet, ++ // so just let it handle the line comment as usual. If it has a ++ // line comment, we can't have both so the one from the key is lost. ++ emitter.line_comment = emitter.key_line_comment ++ emitter.key_line_comment = nil ++ } ++ } else if event.sequence_style() != yaml_FLOW_SEQUENCE_STYLE && (event.typ == yaml_MAPPING_START_EVENT || event.typ == yaml_SEQUENCE_START_EVENT) { ++ // An indented block follows, so write the comment right now. ++ emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment ++ if !yaml_emitter_process_line_comment(emitter) { ++ return false ++ } ++ emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment ++ } ++ } ++ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE) ++ if !yaml_emitter_emit_node(emitter, event, false, false, true, false) { ++ return false ++ } ++ if !yaml_emitter_process_line_comment(emitter) { ++ return false ++ } ++ if !yaml_emitter_process_foot_comment(emitter) { ++ return false ++ } ++ return true ++} ++ ++func yaml_emitter_silent_nil_event(emitter *yaml_emitter_t, event *yaml_event_t) bool { ++ return event.typ == yaml_SCALAR_EVENT && event.implicit && !emitter.canonical && len(emitter.scalar_data.value) == 0 ++} ++ ++// Expect a node. ++func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t, ++ root bool, sequence bool, mapping bool, simple_key bool) bool { ++ ++ emitter.root_context = root ++ emitter.sequence_context = sequence ++ emitter.mapping_context = mapping ++ emitter.simple_key_context = simple_key ++ ++ switch event.typ { ++ case yaml_ALIAS_EVENT: ++ return yaml_emitter_emit_alias(emitter, event) ++ case yaml_SCALAR_EVENT: ++ return yaml_emitter_emit_scalar(emitter, event) ++ case yaml_SEQUENCE_START_EVENT: ++ return yaml_emitter_emit_sequence_start(emitter, event) ++ case yaml_MAPPING_START_EVENT: ++ return yaml_emitter_emit_mapping_start(emitter, event) ++ default: ++ return yaml_emitter_set_emitter_error(emitter, ++ fmt.Sprintf("expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got %v", event.typ)) ++ } ++} ++ ++// Expect ALIAS. ++func yaml_emitter_emit_alias(emitter *yaml_emitter_t, event *yaml_event_t) bool { ++ if !yaml_emitter_process_anchor(emitter) { ++ return false ++ } ++ emitter.state = emitter.states[len(emitter.states)-1] ++ emitter.states = emitter.states[:len(emitter.states)-1] ++ return true ++} ++ ++// Expect SCALAR. ++func yaml_emitter_emit_scalar(emitter *yaml_emitter_t, event *yaml_event_t) bool { ++ if !yaml_emitter_select_scalar_style(emitter, event) { ++ return false ++ } ++ if !yaml_emitter_process_anchor(emitter) { ++ return false ++ } ++ if !yaml_emitter_process_tag(emitter) { ++ return false ++ } ++ if !yaml_emitter_increase_indent(emitter, true, false) { ++ return false ++ } ++ if !yaml_emitter_process_scalar(emitter) { ++ return false ++ } ++ emitter.indent = emitter.indents[len(emitter.indents)-1] ++ emitter.indents = emitter.indents[:len(emitter.indents)-1] ++ emitter.state = emitter.states[len(emitter.states)-1] ++ emitter.states = emitter.states[:len(emitter.states)-1] ++ return true ++} ++ ++// Expect SEQUENCE-START. ++func yaml_emitter_emit_sequence_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { ++ if !yaml_emitter_process_anchor(emitter) { ++ return false ++ } ++ if !yaml_emitter_process_tag(emitter) { ++ return false ++ } ++ if emitter.flow_level > 0 || emitter.canonical || event.sequence_style() == yaml_FLOW_SEQUENCE_STYLE || ++ yaml_emitter_check_empty_sequence(emitter) { ++ emitter.state = yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE ++ } else { ++ emitter.state = yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE ++ } ++ return true ++} ++ ++// Expect MAPPING-START. ++func yaml_emitter_emit_mapping_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { ++ if !yaml_emitter_process_anchor(emitter) { ++ return false ++ } ++ if !yaml_emitter_process_tag(emitter) { ++ return false ++ } ++ if emitter.flow_level > 0 || emitter.canonical || event.mapping_style() == yaml_FLOW_MAPPING_STYLE || ++ yaml_emitter_check_empty_mapping(emitter) { ++ emitter.state = yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE ++ } else { ++ emitter.state = yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE ++ } ++ return true ++} ++ ++// Check if the document content is an empty scalar. ++func yaml_emitter_check_empty_document(emitter *yaml_emitter_t) bool { ++ return false // [Go] Huh? ++} ++ ++// Check if the next events represent an empty sequence. ++func yaml_emitter_check_empty_sequence(emitter *yaml_emitter_t) bool { ++ if len(emitter.events)-emitter.events_head < 2 { ++ return false ++ } ++ return emitter.events[emitter.events_head].typ == yaml_SEQUENCE_START_EVENT && ++ emitter.events[emitter.events_head+1].typ == yaml_SEQUENCE_END_EVENT ++} ++ ++// Check if the next events represent an empty mapping. ++func yaml_emitter_check_empty_mapping(emitter *yaml_emitter_t) bool { ++ if len(emitter.events)-emitter.events_head < 2 { ++ return false ++ } ++ return emitter.events[emitter.events_head].typ == yaml_MAPPING_START_EVENT && ++ emitter.events[emitter.events_head+1].typ == yaml_MAPPING_END_EVENT ++} ++ ++// Check if the next node can be expressed as a simple key. ++func yaml_emitter_check_simple_key(emitter *yaml_emitter_t) bool { ++ length := 0 ++ switch emitter.events[emitter.events_head].typ { ++ case yaml_ALIAS_EVENT: ++ length += len(emitter.anchor_data.anchor) ++ case yaml_SCALAR_EVENT: ++ if emitter.scalar_data.multiline { ++ return false ++ } ++ length += len(emitter.anchor_data.anchor) + ++ len(emitter.tag_data.handle) + ++ len(emitter.tag_data.suffix) + ++ len(emitter.scalar_data.value) ++ case yaml_SEQUENCE_START_EVENT: ++ if !yaml_emitter_check_empty_sequence(emitter) { ++ return false ++ } ++ length += len(emitter.anchor_data.anchor) + ++ len(emitter.tag_data.handle) + ++ len(emitter.tag_data.suffix) ++ case yaml_MAPPING_START_EVENT: ++ if !yaml_emitter_check_empty_mapping(emitter) { ++ return false ++ } ++ length += len(emitter.anchor_data.anchor) + ++ len(emitter.tag_data.handle) + ++ len(emitter.tag_data.suffix) ++ default: ++ return false ++ } ++ return length <= 128 ++} ++ ++// Determine an acceptable scalar style. ++func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *yaml_event_t) bool { ++ ++ no_tag := len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 ++ if no_tag && !event.implicit && !event.quoted_implicit { ++ return yaml_emitter_set_emitter_error(emitter, "neither tag nor implicit flags are specified") ++ } ++ ++ style := event.scalar_style() ++ if style == yaml_ANY_SCALAR_STYLE { ++ style = yaml_PLAIN_SCALAR_STYLE ++ } ++ if emitter.canonical { ++ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE ++ } ++ if emitter.simple_key_context && emitter.scalar_data.multiline { ++ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE ++ } ++ ++ if style == yaml_PLAIN_SCALAR_STYLE { ++ if emitter.flow_level > 0 && !emitter.scalar_data.flow_plain_allowed || ++ emitter.flow_level == 0 && !emitter.scalar_data.block_plain_allowed { ++ style = yaml_SINGLE_QUOTED_SCALAR_STYLE ++ } ++ if len(emitter.scalar_data.value) == 0 && (emitter.flow_level > 0 || emitter.simple_key_context) { ++ style = yaml_SINGLE_QUOTED_SCALAR_STYLE ++ } ++ if no_tag && !event.implicit { ++ style = yaml_SINGLE_QUOTED_SCALAR_STYLE ++ } ++ } ++ if style == yaml_SINGLE_QUOTED_SCALAR_STYLE { ++ if !emitter.scalar_data.single_quoted_allowed { ++ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE ++ } ++ } ++ if style == yaml_LITERAL_SCALAR_STYLE || style == yaml_FOLDED_SCALAR_STYLE { ++ if !emitter.scalar_data.block_allowed || emitter.flow_level > 0 || emitter.simple_key_context { ++ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE ++ } ++ } ++ ++ if no_tag && !event.quoted_implicit && style != yaml_PLAIN_SCALAR_STYLE { ++ emitter.tag_data.handle = []byte{'!'} ++ } ++ emitter.scalar_data.style = style ++ return true ++} ++ ++// Write an anchor. ++func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool { ++ if emitter.anchor_data.anchor == nil { ++ return true ++ } ++ c := []byte{'&'} ++ if emitter.anchor_data.alias { ++ c[0] = '*' ++ } ++ if !yaml_emitter_write_indicator(emitter, c, true, false, false) { ++ return false ++ } ++ return yaml_emitter_write_anchor(emitter, emitter.anchor_data.anchor) ++} ++ ++// Write a tag. ++func yaml_emitter_process_tag(emitter *yaml_emitter_t) bool { ++ if len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 { ++ return true ++ } ++ if len(emitter.tag_data.handle) > 0 { ++ if !yaml_emitter_write_tag_handle(emitter, emitter.tag_data.handle) { ++ return false ++ } ++ if len(emitter.tag_data.suffix) > 0 { ++ if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) { ++ return false ++ } ++ } ++ } else { ++ // [Go] Allocate these slices elsewhere. ++ if !yaml_emitter_write_indicator(emitter, []byte("!<"), true, false, false) { ++ return false ++ } ++ if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) { ++ return false ++ } ++ if !yaml_emitter_write_indicator(emitter, []byte{'>'}, false, false, false) { ++ return false ++ } ++ } ++ return true ++} ++ ++// Write a scalar. ++func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool { ++ switch emitter.scalar_data.style { ++ case yaml_PLAIN_SCALAR_STYLE: ++ return yaml_emitter_write_plain_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) ++ ++ case yaml_SINGLE_QUOTED_SCALAR_STYLE: ++ return yaml_emitter_write_single_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) ++ ++ case yaml_DOUBLE_QUOTED_SCALAR_STYLE: ++ return yaml_emitter_write_double_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) ++ ++ case yaml_LITERAL_SCALAR_STYLE: ++ return yaml_emitter_write_literal_scalar(emitter, emitter.scalar_data.value) ++ ++ case yaml_FOLDED_SCALAR_STYLE: ++ return yaml_emitter_write_folded_scalar(emitter, emitter.scalar_data.value) ++ } ++ panic("unknown scalar style") ++} ++ ++// Write a head comment. ++func yaml_emitter_process_head_comment(emitter *yaml_emitter_t) bool { ++ if len(emitter.tail_comment) > 0 { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ if !yaml_emitter_write_comment(emitter, emitter.tail_comment) { ++ return false ++ } ++ emitter.tail_comment = emitter.tail_comment[:0] ++ emitter.foot_indent = emitter.indent ++ if emitter.foot_indent < 0 { ++ emitter.foot_indent = 0 ++ } ++ } ++ ++ if len(emitter.head_comment) == 0 { ++ return true ++ } ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ if !yaml_emitter_write_comment(emitter, emitter.head_comment) { ++ return false ++ } ++ emitter.head_comment = emitter.head_comment[:0] ++ return true ++} ++ ++// Write an line comment. ++func yaml_emitter_process_line_comment(emitter *yaml_emitter_t) bool { ++ if len(emitter.line_comment) == 0 { ++ return true ++ } ++ if !emitter.whitespace { ++ if !put(emitter, ' ') { ++ return false ++ } ++ } ++ if !yaml_emitter_write_comment(emitter, emitter.line_comment) { ++ return false ++ } ++ emitter.line_comment = emitter.line_comment[:0] ++ return true ++} ++ ++// Write a foot comment. ++func yaml_emitter_process_foot_comment(emitter *yaml_emitter_t) bool { ++ if len(emitter.foot_comment) == 0 { ++ return true ++ } ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ if !yaml_emitter_write_comment(emitter, emitter.foot_comment) { ++ return false ++ } ++ emitter.foot_comment = emitter.foot_comment[:0] ++ emitter.foot_indent = emitter.indent ++ if emitter.foot_indent < 0 { ++ emitter.foot_indent = 0 ++ } ++ return true ++} ++ ++// Check if a %YAML directive is valid. ++func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, version_directive *yaml_version_directive_t) bool { ++ if version_directive.major != 1 || version_directive.minor != 1 { ++ return yaml_emitter_set_emitter_error(emitter, "incompatible %YAML directive") ++ } ++ return true ++} ++ ++// Check if a %TAG directive is valid. ++func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t, tag_directive *yaml_tag_directive_t) bool { ++ handle := tag_directive.handle ++ prefix := tag_directive.prefix ++ if len(handle) == 0 { ++ return yaml_emitter_set_emitter_error(emitter, "tag handle must not be empty") ++ } ++ if handle[0] != '!' { ++ return yaml_emitter_set_emitter_error(emitter, "tag handle must start with '!'") ++ } ++ if handle[len(handle)-1] != '!' { ++ return yaml_emitter_set_emitter_error(emitter, "tag handle must end with '!'") ++ } ++ for i := 1; i < len(handle)-1; i += width(handle[i]) { ++ if !is_alpha(handle, i) { ++ return yaml_emitter_set_emitter_error(emitter, "tag handle must contain alphanumerical characters only") ++ } ++ } ++ if len(prefix) == 0 { ++ return yaml_emitter_set_emitter_error(emitter, "tag prefix must not be empty") ++ } ++ return true ++} ++ ++// Check if an anchor is valid. ++func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t, anchor []byte, alias bool) bool { ++ if len(anchor) == 0 { ++ problem := "anchor value must not be empty" ++ if alias { ++ problem = "alias value must not be empty" ++ } ++ return yaml_emitter_set_emitter_error(emitter, problem) ++ } ++ for i := 0; i < len(anchor); i += width(anchor[i]) { ++ if !is_alpha(anchor, i) { ++ problem := "anchor value must contain alphanumerical characters only" ++ if alias { ++ problem = "alias value must contain alphanumerical characters only" ++ } ++ return yaml_emitter_set_emitter_error(emitter, problem) ++ } ++ } ++ emitter.anchor_data.anchor = anchor ++ emitter.anchor_data.alias = alias ++ return true ++} ++ ++// Check if a tag is valid. ++func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool { ++ if len(tag) == 0 { ++ return yaml_emitter_set_emitter_error(emitter, "tag value must not be empty") ++ } ++ for i := 0; i < len(emitter.tag_directives); i++ { ++ tag_directive := &emitter.tag_directives[i] ++ if bytes.HasPrefix(tag, tag_directive.prefix) { ++ emitter.tag_data.handle = tag_directive.handle ++ emitter.tag_data.suffix = tag[len(tag_directive.prefix):] ++ return true ++ } ++ } ++ emitter.tag_data.suffix = tag ++ return true ++} ++ ++// Check if a scalar is valid. ++func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool { ++ var ( ++ block_indicators = false ++ flow_indicators = false ++ line_breaks = false ++ special_characters = false ++ tab_characters = false ++ ++ leading_space = false ++ leading_break = false ++ trailing_space = false ++ trailing_break = false ++ break_space = false ++ space_break = false ++ ++ preceded_by_whitespace = false ++ followed_by_whitespace = false ++ previous_space = false ++ previous_break = false ++ ) ++ ++ emitter.scalar_data.value = value ++ ++ if len(value) == 0 { ++ emitter.scalar_data.multiline = false ++ emitter.scalar_data.flow_plain_allowed = false ++ emitter.scalar_data.block_plain_allowed = true ++ emitter.scalar_data.single_quoted_allowed = true ++ emitter.scalar_data.block_allowed = false ++ return true ++ } ++ ++ if len(value) >= 3 && ((value[0] == '-' && value[1] == '-' && value[2] == '-') || (value[0] == '.' && value[1] == '.' && value[2] == '.')) { ++ block_indicators = true ++ flow_indicators = true ++ } ++ ++ preceded_by_whitespace = true ++ for i, w := 0, 0; i < len(value); i += w { ++ w = width(value[i]) ++ followed_by_whitespace = i+w >= len(value) || is_blank(value, i+w) ++ ++ if i == 0 { ++ switch value[i] { ++ case '#', ',', '[', ']', '{', '}', '&', '*', '!', '|', '>', '\'', '"', '%', '@', '`': ++ flow_indicators = true ++ block_indicators = true ++ case '?', ':': ++ flow_indicators = true ++ if followed_by_whitespace { ++ block_indicators = true ++ } ++ case '-': ++ if followed_by_whitespace { ++ flow_indicators = true ++ block_indicators = true ++ } ++ } ++ } else { ++ switch value[i] { ++ case ',', '?', '[', ']', '{', '}': ++ flow_indicators = true ++ case ':': ++ flow_indicators = true ++ if followed_by_whitespace { ++ block_indicators = true ++ } ++ case '#': ++ if preceded_by_whitespace { ++ flow_indicators = true ++ block_indicators = true ++ } ++ } ++ } ++ ++ if value[i] == '\t' { ++ tab_characters = true ++ } else if !is_printable(value, i) || !is_ascii(value, i) && !emitter.unicode { ++ special_characters = true ++ } ++ if is_space(value, i) { ++ if i == 0 { ++ leading_space = true ++ } ++ if i+width(value[i]) == len(value) { ++ trailing_space = true ++ } ++ if previous_break { ++ break_space = true ++ } ++ previous_space = true ++ previous_break = false ++ } else if is_break(value, i) { ++ line_breaks = true ++ if i == 0 { ++ leading_break = true ++ } ++ if i+width(value[i]) == len(value) { ++ trailing_break = true ++ } ++ if previous_space { ++ space_break = true ++ } ++ previous_space = false ++ previous_break = true ++ } else { ++ previous_space = false ++ previous_break = false ++ } ++ ++ // [Go]: Why 'z'? Couldn't be the end of the string as that's the loop condition. ++ preceded_by_whitespace = is_blankz(value, i) ++ } ++ ++ emitter.scalar_data.multiline = line_breaks ++ emitter.scalar_data.flow_plain_allowed = true ++ emitter.scalar_data.block_plain_allowed = true ++ emitter.scalar_data.single_quoted_allowed = true ++ emitter.scalar_data.block_allowed = true ++ ++ if leading_space || leading_break || trailing_space || trailing_break { ++ emitter.scalar_data.flow_plain_allowed = false ++ emitter.scalar_data.block_plain_allowed = false ++ } ++ if trailing_space { ++ emitter.scalar_data.block_allowed = false ++ } ++ if break_space { ++ emitter.scalar_data.flow_plain_allowed = false ++ emitter.scalar_data.block_plain_allowed = false ++ emitter.scalar_data.single_quoted_allowed = false ++ } ++ if space_break || tab_characters || special_characters { ++ emitter.scalar_data.flow_plain_allowed = false ++ emitter.scalar_data.block_plain_allowed = false ++ emitter.scalar_data.single_quoted_allowed = false ++ } ++ if space_break || special_characters { ++ emitter.scalar_data.block_allowed = false ++ } ++ if line_breaks { ++ emitter.scalar_data.flow_plain_allowed = false ++ emitter.scalar_data.block_plain_allowed = false ++ } ++ if flow_indicators { ++ emitter.scalar_data.flow_plain_allowed = false ++ } ++ if block_indicators { ++ emitter.scalar_data.block_plain_allowed = false ++ } ++ return true ++} ++ ++// Check if the event data is valid. ++func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_event_t) bool { ++ ++ emitter.anchor_data.anchor = nil ++ emitter.tag_data.handle = nil ++ emitter.tag_data.suffix = nil ++ emitter.scalar_data.value = nil ++ ++ if len(event.head_comment) > 0 { ++ emitter.head_comment = event.head_comment ++ } ++ if len(event.line_comment) > 0 { ++ emitter.line_comment = event.line_comment ++ } ++ if len(event.foot_comment) > 0 { ++ emitter.foot_comment = event.foot_comment ++ } ++ if len(event.tail_comment) > 0 { ++ emitter.tail_comment = event.tail_comment ++ } ++ ++ switch event.typ { ++ case yaml_ALIAS_EVENT: ++ if !yaml_emitter_analyze_anchor(emitter, event.anchor, true) { ++ return false ++ } ++ ++ case yaml_SCALAR_EVENT: ++ if len(event.anchor) > 0 { ++ if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { ++ return false ++ } ++ } ++ if len(event.tag) > 0 && (emitter.canonical || (!event.implicit && !event.quoted_implicit)) { ++ if !yaml_emitter_analyze_tag(emitter, event.tag) { ++ return false ++ } ++ } ++ if !yaml_emitter_analyze_scalar(emitter, event.value) { ++ return false ++ } ++ ++ case yaml_SEQUENCE_START_EVENT: ++ if len(event.anchor) > 0 { ++ if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { ++ return false ++ } ++ } ++ if len(event.tag) > 0 && (emitter.canonical || !event.implicit) { ++ if !yaml_emitter_analyze_tag(emitter, event.tag) { ++ return false ++ } ++ } ++ ++ case yaml_MAPPING_START_EVENT: ++ if len(event.anchor) > 0 { ++ if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { ++ return false ++ } ++ } ++ if len(event.tag) > 0 && (emitter.canonical || !event.implicit) { ++ if !yaml_emitter_analyze_tag(emitter, event.tag) { ++ return false ++ } ++ } ++ } ++ return true ++} ++ ++// Write the BOM character. ++func yaml_emitter_write_bom(emitter *yaml_emitter_t) bool { ++ if !flush(emitter) { ++ return false ++ } ++ pos := emitter.buffer_pos ++ emitter.buffer[pos+0] = '\xEF' ++ emitter.buffer[pos+1] = '\xBB' ++ emitter.buffer[pos+2] = '\xBF' ++ emitter.buffer_pos += 3 ++ return true ++} ++ ++func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool { ++ indent := emitter.indent ++ if indent < 0 { ++ indent = 0 ++ } ++ if !emitter.indention || emitter.column > indent || (emitter.column == indent && !emitter.whitespace) { ++ if !put_break(emitter) { ++ return false ++ } ++ } ++ if emitter.foot_indent == indent { ++ if !put_break(emitter) { ++ return false ++ } ++ } ++ for emitter.column < indent { ++ if !put(emitter, ' ') { ++ return false ++ } ++ } ++ emitter.whitespace = true ++ //emitter.indention = true ++ emitter.space_above = false ++ emitter.foot_indent = -1 ++ return true ++} ++ ++func yaml_emitter_write_indicator(emitter *yaml_emitter_t, indicator []byte, need_whitespace, is_whitespace, is_indention bool) bool { ++ if need_whitespace && !emitter.whitespace { ++ if !put(emitter, ' ') { ++ return false ++ } ++ } ++ if !write_all(emitter, indicator) { ++ return false ++ } ++ emitter.whitespace = is_whitespace ++ emitter.indention = (emitter.indention && is_indention) ++ emitter.open_ended = false ++ return true ++} ++ ++func yaml_emitter_write_anchor(emitter *yaml_emitter_t, value []byte) bool { ++ if !write_all(emitter, value) { ++ return false ++ } ++ emitter.whitespace = false ++ emitter.indention = false ++ return true ++} ++ ++func yaml_emitter_write_tag_handle(emitter *yaml_emitter_t, value []byte) bool { ++ if !emitter.whitespace { ++ if !put(emitter, ' ') { ++ return false ++ } ++ } ++ if !write_all(emitter, value) { ++ return false ++ } ++ emitter.whitespace = false ++ emitter.indention = false ++ return true ++} ++ ++func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byte, need_whitespace bool) bool { ++ if need_whitespace && !emitter.whitespace { ++ if !put(emitter, ' ') { ++ return false ++ } ++ } ++ for i := 0; i < len(value); { ++ var must_write bool ++ switch value[i] { ++ case ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '_', '.', '~', '*', '\'', '(', ')', '[', ']': ++ must_write = true ++ default: ++ must_write = is_alpha(value, i) ++ } ++ if must_write { ++ if !write(emitter, value, &i) { ++ return false ++ } ++ } else { ++ w := width(value[i]) ++ for k := 0; k < w; k++ { ++ octet := value[i] ++ i++ ++ if !put(emitter, '%') { ++ return false ++ } ++ ++ c := octet >> 4 ++ if c < 10 { ++ c += '0' ++ } else { ++ c += 'A' - 10 ++ } ++ if !put(emitter, c) { ++ return false ++ } ++ ++ c = octet & 0x0f ++ if c < 10 { ++ c += '0' ++ } else { ++ c += 'A' - 10 ++ } ++ if !put(emitter, c) { ++ return false ++ } ++ } ++ } ++ } ++ emitter.whitespace = false ++ emitter.indention = false ++ return true ++} ++ ++func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { ++ if len(value) > 0 && !emitter.whitespace { ++ if !put(emitter, ' ') { ++ return false ++ } ++ } ++ ++ spaces := false ++ breaks := false ++ for i := 0; i < len(value); { ++ if is_space(value, i) { ++ if allow_breaks && !spaces && emitter.column > emitter.best_width && !is_space(value, i+1) { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ i += width(value[i]) ++ } else { ++ if !write(emitter, value, &i) { ++ return false ++ } ++ } ++ spaces = true ++ } else if is_break(value, i) { ++ if !breaks && value[i] == '\n' { ++ if !put_break(emitter) { ++ return false ++ } ++ } ++ if !write_break(emitter, value, &i) { ++ return false ++ } ++ //emitter.indention = true ++ breaks = true ++ } else { ++ if breaks { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ if !write(emitter, value, &i) { ++ return false ++ } ++ emitter.indention = false ++ spaces = false ++ breaks = false ++ } ++ } ++ ++ if len(value) > 0 { ++ emitter.whitespace = false ++ } ++ emitter.indention = false ++ if emitter.root_context { ++ emitter.open_ended = true ++ } ++ ++ return true ++} ++ ++func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { ++ ++ if !yaml_emitter_write_indicator(emitter, []byte{'\''}, true, false, false) { ++ return false ++ } ++ ++ spaces := false ++ breaks := false ++ for i := 0; i < len(value); { ++ if is_space(value, i) { ++ if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 && !is_space(value, i+1) { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ i += width(value[i]) ++ } else { ++ if !write(emitter, value, &i) { ++ return false ++ } ++ } ++ spaces = true ++ } else if is_break(value, i) { ++ if !breaks && value[i] == '\n' { ++ if !put_break(emitter) { ++ return false ++ } ++ } ++ if !write_break(emitter, value, &i) { ++ return false ++ } ++ //emitter.indention = true ++ breaks = true ++ } else { ++ if breaks { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ if value[i] == '\'' { ++ if !put(emitter, '\'') { ++ return false ++ } ++ } ++ if !write(emitter, value, &i) { ++ return false ++ } ++ emitter.indention = false ++ spaces = false ++ breaks = false ++ } ++ } ++ if !yaml_emitter_write_indicator(emitter, []byte{'\''}, false, false, false) { ++ return false ++ } ++ emitter.whitespace = false ++ emitter.indention = false ++ return true ++} ++ ++func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { ++ spaces := false ++ if !yaml_emitter_write_indicator(emitter, []byte{'"'}, true, false, false) { ++ return false ++ } ++ ++ for i := 0; i < len(value); { ++ if !is_printable(value, i) || (!emitter.unicode && !is_ascii(value, i)) || ++ is_bom(value, i) || is_break(value, i) || ++ value[i] == '"' || value[i] == '\\' { ++ ++ octet := value[i] ++ ++ var w int ++ var v rune ++ switch { ++ case octet&0x80 == 0x00: ++ w, v = 1, rune(octet&0x7F) ++ case octet&0xE0 == 0xC0: ++ w, v = 2, rune(octet&0x1F) ++ case octet&0xF0 == 0xE0: ++ w, v = 3, rune(octet&0x0F) ++ case octet&0xF8 == 0xF0: ++ w, v = 4, rune(octet&0x07) ++ } ++ for k := 1; k < w; k++ { ++ octet = value[i+k] ++ v = (v << 6) + (rune(octet) & 0x3F) ++ } ++ i += w ++ ++ if !put(emitter, '\\') { ++ return false ++ } ++ ++ var ok bool ++ switch v { ++ case 0x00: ++ ok = put(emitter, '0') ++ case 0x07: ++ ok = put(emitter, 'a') ++ case 0x08: ++ ok = put(emitter, 'b') ++ case 0x09: ++ ok = put(emitter, 't') ++ case 0x0A: ++ ok = put(emitter, 'n') ++ case 0x0b: ++ ok = put(emitter, 'v') ++ case 0x0c: ++ ok = put(emitter, 'f') ++ case 0x0d: ++ ok = put(emitter, 'r') ++ case 0x1b: ++ ok = put(emitter, 'e') ++ case 0x22: ++ ok = put(emitter, '"') ++ case 0x5c: ++ ok = put(emitter, '\\') ++ case 0x85: ++ ok = put(emitter, 'N') ++ case 0xA0: ++ ok = put(emitter, '_') ++ case 0x2028: ++ ok = put(emitter, 'L') ++ case 0x2029: ++ ok = put(emitter, 'P') ++ default: ++ if v <= 0xFF { ++ ok = put(emitter, 'x') ++ w = 2 ++ } else if v <= 0xFFFF { ++ ok = put(emitter, 'u') ++ w = 4 ++ } else { ++ ok = put(emitter, 'U') ++ w = 8 ++ } ++ for k := (w - 1) * 4; ok && k >= 0; k -= 4 { ++ digit := byte((v >> uint(k)) & 0x0F) ++ if digit < 10 { ++ ok = put(emitter, digit+'0') ++ } else { ++ ok = put(emitter, digit+'A'-10) ++ } ++ } ++ } ++ if !ok { ++ return false ++ } ++ spaces = false ++ } else if is_space(value, i) { ++ if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ if is_space(value, i+1) { ++ if !put(emitter, '\\') { ++ return false ++ } ++ } ++ i += width(value[i]) ++ } else if !write(emitter, value, &i) { ++ return false ++ } ++ spaces = true ++ } else { ++ if !write(emitter, value, &i) { ++ return false ++ } ++ spaces = false ++ } ++ } ++ if !yaml_emitter_write_indicator(emitter, []byte{'"'}, false, false, false) { ++ return false ++ } ++ emitter.whitespace = false ++ emitter.indention = false ++ return true ++} ++ ++func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t, value []byte) bool { ++ if is_space(value, 0) || is_break(value, 0) { ++ indent_hint := []byte{'0' + byte(emitter.best_indent)} ++ if !yaml_emitter_write_indicator(emitter, indent_hint, false, false, false) { ++ return false ++ } ++ } ++ ++ emitter.open_ended = false ++ ++ var chomp_hint [1]byte ++ if len(value) == 0 { ++ chomp_hint[0] = '-' ++ } else { ++ i := len(value) - 1 ++ for value[i]&0xC0 == 0x80 { ++ i-- ++ } ++ if !is_break(value, i) { ++ chomp_hint[0] = '-' ++ } else if i == 0 { ++ chomp_hint[0] = '+' ++ emitter.open_ended = true ++ } else { ++ i-- ++ for value[i]&0xC0 == 0x80 { ++ i-- ++ } ++ if is_break(value, i) { ++ chomp_hint[0] = '+' ++ emitter.open_ended = true ++ } ++ } ++ } ++ if chomp_hint[0] != 0 { ++ if !yaml_emitter_write_indicator(emitter, chomp_hint[:], false, false, false) { ++ return false ++ } ++ } ++ return true ++} ++ ++func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bool { ++ if !yaml_emitter_write_indicator(emitter, []byte{'|'}, true, false, false) { ++ return false ++ } ++ if !yaml_emitter_write_block_scalar_hints(emitter, value) { ++ return false ++ } ++ if !yaml_emitter_process_line_comment(emitter) { ++ return false ++ } ++ //emitter.indention = true ++ emitter.whitespace = true ++ breaks := true ++ for i := 0; i < len(value); { ++ if is_break(value, i) { ++ if !write_break(emitter, value, &i) { ++ return false ++ } ++ //emitter.indention = true ++ breaks = true ++ } else { ++ if breaks { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ if !write(emitter, value, &i) { ++ return false ++ } ++ emitter.indention = false ++ breaks = false ++ } ++ } ++ ++ return true ++} ++ ++func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) bool { ++ if !yaml_emitter_write_indicator(emitter, []byte{'>'}, true, false, false) { ++ return false ++ } ++ if !yaml_emitter_write_block_scalar_hints(emitter, value) { ++ return false ++ } ++ if !yaml_emitter_process_line_comment(emitter) { ++ return false ++ } ++ ++ //emitter.indention = true ++ emitter.whitespace = true ++ ++ breaks := true ++ leading_spaces := true ++ for i := 0; i < len(value); { ++ if is_break(value, i) { ++ if !breaks && !leading_spaces && value[i] == '\n' { ++ k := 0 ++ for is_break(value, k) { ++ k += width(value[k]) ++ } ++ if !is_blankz(value, k) { ++ if !put_break(emitter) { ++ return false ++ } ++ } ++ } ++ if !write_break(emitter, value, &i) { ++ return false ++ } ++ //emitter.indention = true ++ breaks = true ++ } else { ++ if breaks { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ leading_spaces = is_blank(value, i) ++ } ++ if !breaks && is_space(value, i) && !is_space(value, i+1) && emitter.column > emitter.best_width { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ i += width(value[i]) ++ } else { ++ if !write(emitter, value, &i) { ++ return false ++ } ++ } ++ emitter.indention = false ++ breaks = false ++ } ++ } ++ return true ++} ++ ++func yaml_emitter_write_comment(emitter *yaml_emitter_t, comment []byte) bool { ++ breaks := false ++ pound := false ++ for i := 0; i < len(comment); { ++ if is_break(comment, i) { ++ if !write_break(emitter, comment, &i) { ++ return false ++ } ++ //emitter.indention = true ++ breaks = true ++ pound = false ++ } else { ++ if breaks && !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ if !pound { ++ if comment[i] != '#' && (!put(emitter, '#') || !put(emitter, ' ')) { ++ return false ++ } ++ pound = true ++ } ++ if !write(emitter, comment, &i) { ++ return false ++ } ++ emitter.indention = false ++ breaks = false ++ } ++ } ++ if !breaks && !put_break(emitter) { ++ return false ++ } ++ ++ emitter.whitespace = true ++ //emitter.indention = true ++ return true ++} +diff --git a/vendor/gopkg.in/yaml.v3/encode.go b/vendor/gopkg.in/yaml.v3/encode.go +new file mode 100644 +index 000000000000..de9e72a3e638 +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/encode.go +@@ -0,0 +1,577 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// ++// 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 yaml ++ ++import ( ++ "encoding" ++ "fmt" ++ "io" ++ "reflect" ++ "regexp" ++ "sort" ++ "strconv" ++ "strings" ++ "time" ++ "unicode/utf8" ++) ++ ++type encoder struct { ++ emitter yaml_emitter_t ++ event yaml_event_t ++ out []byte ++ flow bool ++ indent int ++ doneInit bool ++} ++ ++func newEncoder() *encoder { ++ e := &encoder{} ++ yaml_emitter_initialize(&e.emitter) ++ yaml_emitter_set_output_string(&e.emitter, &e.out) ++ yaml_emitter_set_unicode(&e.emitter, true) ++ return e ++} ++ ++func newEncoderWithWriter(w io.Writer) *encoder { ++ e := &encoder{} ++ yaml_emitter_initialize(&e.emitter) ++ yaml_emitter_set_output_writer(&e.emitter, w) ++ yaml_emitter_set_unicode(&e.emitter, true) ++ return e ++} ++ ++func (e *encoder) init() { ++ if e.doneInit { ++ return ++ } ++ if e.indent == 0 { ++ e.indent = 4 ++ } ++ e.emitter.best_indent = e.indent ++ yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING) ++ e.emit() ++ e.doneInit = true ++} ++ ++func (e *encoder) finish() { ++ e.emitter.open_ended = false ++ yaml_stream_end_event_initialize(&e.event) ++ e.emit() ++} ++ ++func (e *encoder) destroy() { ++ yaml_emitter_delete(&e.emitter) ++} ++ ++func (e *encoder) emit() { ++ // This will internally delete the e.event value. ++ e.must(yaml_emitter_emit(&e.emitter, &e.event)) ++} ++ ++func (e *encoder) must(ok bool) { ++ if !ok { ++ msg := e.emitter.problem ++ if msg == "" { ++ msg = "unknown problem generating YAML content" ++ } ++ failf("%s", msg) ++ } ++} ++ ++func (e *encoder) marshalDoc(tag string, in reflect.Value) { ++ e.init() ++ var node *Node ++ if in.IsValid() { ++ node, _ = in.Interface().(*Node) ++ } ++ if node != nil && node.Kind == DocumentNode { ++ e.nodev(in) ++ } else { ++ yaml_document_start_event_initialize(&e.event, nil, nil, true) ++ e.emit() ++ e.marshal(tag, in) ++ yaml_document_end_event_initialize(&e.event, true) ++ e.emit() ++ } ++} ++ ++func (e *encoder) marshal(tag string, in reflect.Value) { ++ tag = shortTag(tag) ++ if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() { ++ e.nilv() ++ return ++ } ++ iface := in.Interface() ++ switch value := iface.(type) { ++ case *Node: ++ e.nodev(in) ++ return ++ case Node: ++ if !in.CanAddr() { ++ var n = reflect.New(in.Type()).Elem() ++ n.Set(in) ++ in = n ++ } ++ e.nodev(in.Addr()) ++ return ++ case time.Time: ++ e.timev(tag, in) ++ return ++ case *time.Time: ++ e.timev(tag, in.Elem()) ++ return ++ case time.Duration: ++ e.stringv(tag, reflect.ValueOf(value.String())) ++ return ++ case Marshaler: ++ v, err := value.MarshalYAML() ++ if err != nil { ++ fail(err) ++ } ++ if v == nil { ++ e.nilv() ++ return ++ } ++ e.marshal(tag, reflect.ValueOf(v)) ++ return ++ case encoding.TextMarshaler: ++ text, err := value.MarshalText() ++ if err != nil { ++ fail(err) ++ } ++ in = reflect.ValueOf(string(text)) ++ case nil: ++ e.nilv() ++ return ++ } ++ switch in.Kind() { ++ case reflect.Interface: ++ e.marshal(tag, in.Elem()) ++ case reflect.Map: ++ e.mapv(tag, in) ++ case reflect.Ptr: ++ e.marshal(tag, in.Elem()) ++ case reflect.Struct: ++ e.structv(tag, in) ++ case reflect.Slice, reflect.Array: ++ e.slicev(tag, in) ++ case reflect.String: ++ e.stringv(tag, in) ++ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: ++ e.intv(tag, in) ++ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: ++ e.uintv(tag, in) ++ case reflect.Float32, reflect.Float64: ++ e.floatv(tag, in) ++ case reflect.Bool: ++ e.boolv(tag, in) ++ default: ++ panic("cannot marshal type: " + in.Type().String()) ++ } ++} ++ ++func (e *encoder) mapv(tag string, in reflect.Value) { ++ e.mappingv(tag, func() { ++ keys := keyList(in.MapKeys()) ++ sort.Sort(keys) ++ for _, k := range keys { ++ e.marshal("", k) ++ e.marshal("", in.MapIndex(k)) ++ } ++ }) ++} ++ ++func (e *encoder) fieldByIndex(v reflect.Value, index []int) (field reflect.Value) { ++ for _, num := range index { ++ for { ++ if v.Kind() == reflect.Ptr { ++ if v.IsNil() { ++ return reflect.Value{} ++ } ++ v = v.Elem() ++ continue ++ } ++ break ++ } ++ v = v.Field(num) ++ } ++ return v ++} ++ ++func (e *encoder) structv(tag string, in reflect.Value) { ++ sinfo, err := getStructInfo(in.Type()) ++ if err != nil { ++ panic(err) ++ } ++ e.mappingv(tag, func() { ++ for _, info := range sinfo.FieldsList { ++ var value reflect.Value ++ if info.Inline == nil { ++ value = in.Field(info.Num) ++ } else { ++ value = e.fieldByIndex(in, info.Inline) ++ if !value.IsValid() { ++ continue ++ } ++ } ++ if info.OmitEmpty && isZero(value) { ++ continue ++ } ++ e.marshal("", reflect.ValueOf(info.Key)) ++ e.flow = info.Flow ++ e.marshal("", value) ++ } ++ if sinfo.InlineMap >= 0 { ++ m := in.Field(sinfo.InlineMap) ++ if m.Len() > 0 { ++ e.flow = false ++ keys := keyList(m.MapKeys()) ++ sort.Sort(keys) ++ for _, k := range keys { ++ if _, found := sinfo.FieldsMap[k.String()]; found { ++ panic(fmt.Sprintf("cannot have key %q in inlined map: conflicts with struct field", k.String())) ++ } ++ e.marshal("", k) ++ e.flow = false ++ e.marshal("", m.MapIndex(k)) ++ } ++ } ++ } ++ }) ++} ++ ++func (e *encoder) mappingv(tag string, f func()) { ++ implicit := tag == "" ++ style := yaml_BLOCK_MAPPING_STYLE ++ if e.flow { ++ e.flow = false ++ style = yaml_FLOW_MAPPING_STYLE ++ } ++ yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style) ++ e.emit() ++ f() ++ yaml_mapping_end_event_initialize(&e.event) ++ e.emit() ++} ++ ++func (e *encoder) slicev(tag string, in reflect.Value) { ++ implicit := tag == "" ++ style := yaml_BLOCK_SEQUENCE_STYLE ++ if e.flow { ++ e.flow = false ++ style = yaml_FLOW_SEQUENCE_STYLE ++ } ++ e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)) ++ e.emit() ++ n := in.Len() ++ for i := 0; i < n; i++ { ++ e.marshal("", in.Index(i)) ++ } ++ e.must(yaml_sequence_end_event_initialize(&e.event)) ++ e.emit() ++} ++ ++// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1. ++// ++// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported ++// in YAML 1.2 and by this package, but these should be marshalled quoted for ++// the time being for compatibility with other parsers. ++func isBase60Float(s string) (result bool) { ++ // Fast path. ++ if s == "" { ++ return false ++ } ++ c := s[0] ++ if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 { ++ return false ++ } ++ // Do the full match. ++ return base60float.MatchString(s) ++} ++ ++// From http://yaml.org/type/float.html, except the regular expression there ++// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix. ++var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`) ++ ++// isOldBool returns whether s is bool notation as defined in YAML 1.1. ++// ++// We continue to force strings that YAML 1.1 would interpret as booleans to be ++// rendered as quotes strings so that the marshalled output valid for YAML 1.1 ++// parsing. ++func isOldBool(s string) (result bool) { ++ switch s { ++ case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON", ++ "n", "N", "no", "No", "NO", "off", "Off", "OFF": ++ return true ++ default: ++ return false ++ } ++} ++ ++func (e *encoder) stringv(tag string, in reflect.Value) { ++ var style yaml_scalar_style_t ++ s := in.String() ++ canUsePlain := true ++ switch { ++ case !utf8.ValidString(s): ++ if tag == binaryTag { ++ failf("explicitly tagged !!binary data must be base64-encoded") ++ } ++ if tag != "" { ++ failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag)) ++ } ++ // It can't be encoded directly as YAML so use a binary tag ++ // and encode it as base64. ++ tag = binaryTag ++ s = encodeBase64(s) ++ case tag == "": ++ // Check to see if it would resolve to a specific ++ // tag when encoded unquoted. If it doesn't, ++ // there's no need to quote it. ++ rtag, _ := resolve("", s) ++ canUsePlain = rtag == strTag && !(isBase60Float(s) || isOldBool(s)) ++ } ++ // Note: it's possible for user code to emit invalid YAML ++ // if they explicitly specify a tag and a string containing ++ // text that's incompatible with that tag. ++ switch { ++ case strings.Contains(s, "\n"): ++ if e.flow { ++ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE ++ } else { ++ style = yaml_LITERAL_SCALAR_STYLE ++ } ++ case canUsePlain: ++ style = yaml_PLAIN_SCALAR_STYLE ++ default: ++ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE ++ } ++ e.emitScalar(s, "", tag, style, nil, nil, nil, nil) ++} ++ ++func (e *encoder) boolv(tag string, in reflect.Value) { ++ var s string ++ if in.Bool() { ++ s = "true" ++ } else { ++ s = "false" ++ } ++ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) ++} ++ ++func (e *encoder) intv(tag string, in reflect.Value) { ++ s := strconv.FormatInt(in.Int(), 10) ++ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) ++} ++ ++func (e *encoder) uintv(tag string, in reflect.Value) { ++ s := strconv.FormatUint(in.Uint(), 10) ++ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) ++} ++ ++func (e *encoder) timev(tag string, in reflect.Value) { ++ t := in.Interface().(time.Time) ++ s := t.Format(time.RFC3339Nano) ++ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) ++} ++ ++func (e *encoder) floatv(tag string, in reflect.Value) { ++ // Issue #352: When formatting, use the precision of the underlying value ++ precision := 64 ++ if in.Kind() == reflect.Float32 { ++ precision = 32 ++ } ++ ++ s := strconv.FormatFloat(in.Float(), 'g', -1, precision) ++ switch s { ++ case "+Inf": ++ s = ".inf" ++ case "-Inf": ++ s = "-.inf" ++ case "NaN": ++ s = ".nan" ++ } ++ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) ++} ++ ++func (e *encoder) nilv() { ++ e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) ++} ++ ++func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t, head, line, foot, tail []byte) { ++ // TODO Kill this function. Replace all initialize calls by their underlining Go literals. ++ implicit := tag == "" ++ if !implicit { ++ tag = longTag(tag) ++ } ++ e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style)) ++ e.event.head_comment = head ++ e.event.line_comment = line ++ e.event.foot_comment = foot ++ e.event.tail_comment = tail ++ e.emit() ++} ++ ++func (e *encoder) nodev(in reflect.Value) { ++ e.node(in.Interface().(*Node), "") ++} ++ ++func (e *encoder) node(node *Node, tail string) { ++ // Zero nodes behave as nil. ++ if node.Kind == 0 && node.IsZero() { ++ e.nilv() ++ return ++ } ++ ++ // If the tag was not explicitly requested, and dropping it won't change the ++ // implicit tag of the value, don't include it in the presentation. ++ var tag = node.Tag ++ var stag = shortTag(tag) ++ var forceQuoting bool ++ if tag != "" && node.Style&TaggedStyle == 0 { ++ if node.Kind == ScalarNode { ++ if stag == strTag && node.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0 { ++ tag = "" ++ } else { ++ rtag, _ := resolve("", node.Value) ++ if rtag == stag { ++ tag = "" ++ } else if stag == strTag { ++ tag = "" ++ forceQuoting = true ++ } ++ } ++ } else { ++ var rtag string ++ switch node.Kind { ++ case MappingNode: ++ rtag = mapTag ++ case SequenceNode: ++ rtag = seqTag ++ } ++ if rtag == stag { ++ tag = "" ++ } ++ } ++ } ++ ++ switch node.Kind { ++ case DocumentNode: ++ yaml_document_start_event_initialize(&e.event, nil, nil, true) ++ e.event.head_comment = []byte(node.HeadComment) ++ e.emit() ++ for _, node := range node.Content { ++ e.node(node, "") ++ } ++ yaml_document_end_event_initialize(&e.event, true) ++ e.event.foot_comment = []byte(node.FootComment) ++ e.emit() ++ ++ case SequenceNode: ++ style := yaml_BLOCK_SEQUENCE_STYLE ++ if node.Style&FlowStyle != 0 { ++ style = yaml_FLOW_SEQUENCE_STYLE ++ } ++ e.must(yaml_sequence_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style)) ++ e.event.head_comment = []byte(node.HeadComment) ++ e.emit() ++ for _, node := range node.Content { ++ e.node(node, "") ++ } ++ e.must(yaml_sequence_end_event_initialize(&e.event)) ++ e.event.line_comment = []byte(node.LineComment) ++ e.event.foot_comment = []byte(node.FootComment) ++ e.emit() ++ ++ case MappingNode: ++ style := yaml_BLOCK_MAPPING_STYLE ++ if node.Style&FlowStyle != 0 { ++ style = yaml_FLOW_MAPPING_STYLE ++ } ++ yaml_mapping_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style) ++ e.event.tail_comment = []byte(tail) ++ e.event.head_comment = []byte(node.HeadComment) ++ e.emit() ++ ++ // The tail logic below moves the foot comment of prior keys to the following key, ++ // since the value for each key may be a nested structure and the foot needs to be ++ // processed only the entirety of the value is streamed. The last tail is processed ++ // with the mapping end event. ++ var tail string ++ for i := 0; i+1 < len(node.Content); i += 2 { ++ k := node.Content[i] ++ foot := k.FootComment ++ if foot != "" { ++ kopy := *k ++ kopy.FootComment = "" ++ k = &kopy ++ } ++ e.node(k, tail) ++ tail = foot ++ ++ v := node.Content[i+1] ++ e.node(v, "") ++ } ++ ++ yaml_mapping_end_event_initialize(&e.event) ++ e.event.tail_comment = []byte(tail) ++ e.event.line_comment = []byte(node.LineComment) ++ e.event.foot_comment = []byte(node.FootComment) ++ e.emit() ++ ++ case AliasNode: ++ yaml_alias_event_initialize(&e.event, []byte(node.Value)) ++ e.event.head_comment = []byte(node.HeadComment) ++ e.event.line_comment = []byte(node.LineComment) ++ e.event.foot_comment = []byte(node.FootComment) ++ e.emit() ++ ++ case ScalarNode: ++ value := node.Value ++ if !utf8.ValidString(value) { ++ if stag == binaryTag { ++ failf("explicitly tagged !!binary data must be base64-encoded") ++ } ++ if stag != "" { ++ failf("cannot marshal invalid UTF-8 data as %s", stag) ++ } ++ // It can't be encoded directly as YAML so use a binary tag ++ // and encode it as base64. ++ tag = binaryTag ++ value = encodeBase64(value) ++ } ++ ++ style := yaml_PLAIN_SCALAR_STYLE ++ switch { ++ case node.Style&DoubleQuotedStyle != 0: ++ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE ++ case node.Style&SingleQuotedStyle != 0: ++ style = yaml_SINGLE_QUOTED_SCALAR_STYLE ++ case node.Style&LiteralStyle != 0: ++ style = yaml_LITERAL_SCALAR_STYLE ++ case node.Style&FoldedStyle != 0: ++ style = yaml_FOLDED_SCALAR_STYLE ++ case strings.Contains(value, "\n"): ++ style = yaml_LITERAL_SCALAR_STYLE ++ case forceQuoting: ++ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE ++ } ++ ++ e.emitScalar(value, node.Anchor, tag, style, []byte(node.HeadComment), []byte(node.LineComment), []byte(node.FootComment), []byte(tail)) ++ default: ++ failf("cannot encode node with unknown kind %d", node.Kind) ++ } ++} +diff --git a/vendor/gopkg.in/yaml.v3/parserc.go b/vendor/gopkg.in/yaml.v3/parserc.go +new file mode 100644 +index 000000000000..268558a0d632 +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/parserc.go +@@ -0,0 +1,1258 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// Copyright (c) 2006-2010 Kirill Simonov ++// ++// 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. ++ ++package yaml ++ ++import ( ++ "bytes" ++) ++ ++// The parser implements the following grammar: ++// ++// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END ++// implicit_document ::= block_node DOCUMENT-END* ++// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* ++// block_node_or_indentless_sequence ::= ++// ALIAS ++// | properties (block_content | indentless_block_sequence)? ++// | block_content ++// | indentless_block_sequence ++// block_node ::= ALIAS ++// | properties block_content? ++// | block_content ++// flow_node ::= ALIAS ++// | properties flow_content? ++// | flow_content ++// properties ::= TAG ANCHOR? | ANCHOR TAG? ++// block_content ::= block_collection | flow_collection | SCALAR ++// flow_content ::= flow_collection | SCALAR ++// block_collection ::= block_sequence | block_mapping ++// flow_collection ::= flow_sequence | flow_mapping ++// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END ++// indentless_sequence ::= (BLOCK-ENTRY block_node?)+ ++// block_mapping ::= BLOCK-MAPPING_START ++// ((KEY block_node_or_indentless_sequence?)? ++// (VALUE block_node_or_indentless_sequence?)?)* ++// BLOCK-END ++// flow_sequence ::= FLOW-SEQUENCE-START ++// (flow_sequence_entry FLOW-ENTRY)* ++// flow_sequence_entry? ++// FLOW-SEQUENCE-END ++// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? ++// flow_mapping ::= FLOW-MAPPING-START ++// (flow_mapping_entry FLOW-ENTRY)* ++// flow_mapping_entry? ++// FLOW-MAPPING-END ++// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? ++ ++// Peek the next token in the token queue. ++func peek_token(parser *yaml_parser_t) *yaml_token_t { ++ if parser.token_available || yaml_parser_fetch_more_tokens(parser) { ++ token := &parser.tokens[parser.tokens_head] ++ yaml_parser_unfold_comments(parser, token) ++ return token ++ } ++ return nil ++} ++ ++// yaml_parser_unfold_comments walks through the comments queue and joins all ++// comments behind the position of the provided token into the respective ++// top-level comment slices in the parser. ++func yaml_parser_unfold_comments(parser *yaml_parser_t, token *yaml_token_t) { ++ for parser.comments_head < len(parser.comments) && token.start_mark.index >= parser.comments[parser.comments_head].token_mark.index { ++ comment := &parser.comments[parser.comments_head] ++ if len(comment.head) > 0 { ++ if token.typ == yaml_BLOCK_END_TOKEN { ++ // No heads on ends, so keep comment.head for a follow up token. ++ break ++ } ++ if len(parser.head_comment) > 0 { ++ parser.head_comment = append(parser.head_comment, '\n') ++ } ++ parser.head_comment = append(parser.head_comment, comment.head...) ++ } ++ if len(comment.foot) > 0 { ++ if len(parser.foot_comment) > 0 { ++ parser.foot_comment = append(parser.foot_comment, '\n') ++ } ++ parser.foot_comment = append(parser.foot_comment, comment.foot...) ++ } ++ if len(comment.line) > 0 { ++ if len(parser.line_comment) > 0 { ++ parser.line_comment = append(parser.line_comment, '\n') ++ } ++ parser.line_comment = append(parser.line_comment, comment.line...) ++ } ++ *comment = yaml_comment_t{} ++ parser.comments_head++ ++ } ++} ++ ++// Remove the next token from the queue (must be called after peek_token). ++func skip_token(parser *yaml_parser_t) { ++ parser.token_available = false ++ parser.tokens_parsed++ ++ parser.stream_end_produced = parser.tokens[parser.tokens_head].typ == yaml_STREAM_END_TOKEN ++ parser.tokens_head++ ++} ++ ++// Get the next event. ++func yaml_parser_parse(parser *yaml_parser_t, event *yaml_event_t) bool { ++ // Erase the event object. ++ *event = yaml_event_t{} ++ ++ // No events after the end of the stream or error. ++ if parser.stream_end_produced || parser.error != yaml_NO_ERROR || parser.state == yaml_PARSE_END_STATE { ++ return true ++ } ++ ++ // Generate the next event. ++ return yaml_parser_state_machine(parser, event) ++} ++ ++// Set parser error. ++func yaml_parser_set_parser_error(parser *yaml_parser_t, problem string, problem_mark yaml_mark_t) bool { ++ parser.error = yaml_PARSER_ERROR ++ parser.problem = problem ++ parser.problem_mark = problem_mark ++ return false ++} ++ ++func yaml_parser_set_parser_error_context(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string, problem_mark yaml_mark_t) bool { ++ parser.error = yaml_PARSER_ERROR ++ parser.context = context ++ parser.context_mark = context_mark ++ parser.problem = problem ++ parser.problem_mark = problem_mark ++ return false ++} ++ ++// State dispatcher. ++func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool { ++ //trace("yaml_parser_state_machine", "state:", parser.state.String()) ++ ++ switch parser.state { ++ case yaml_PARSE_STREAM_START_STATE: ++ return yaml_parser_parse_stream_start(parser, event) ++ ++ case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE: ++ return yaml_parser_parse_document_start(parser, event, true) ++ ++ case yaml_PARSE_DOCUMENT_START_STATE: ++ return yaml_parser_parse_document_start(parser, event, false) ++ ++ case yaml_PARSE_DOCUMENT_CONTENT_STATE: ++ return yaml_parser_parse_document_content(parser, event) ++ ++ case yaml_PARSE_DOCUMENT_END_STATE: ++ return yaml_parser_parse_document_end(parser, event) ++ ++ case yaml_PARSE_BLOCK_NODE_STATE: ++ return yaml_parser_parse_node(parser, event, true, false) ++ ++ case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: ++ return yaml_parser_parse_node(parser, event, true, true) ++ ++ case yaml_PARSE_FLOW_NODE_STATE: ++ return yaml_parser_parse_node(parser, event, false, false) ++ ++ case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: ++ return yaml_parser_parse_block_sequence_entry(parser, event, true) ++ ++ case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: ++ return yaml_parser_parse_block_sequence_entry(parser, event, false) ++ ++ case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: ++ return yaml_parser_parse_indentless_sequence_entry(parser, event) ++ ++ case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: ++ return yaml_parser_parse_block_mapping_key(parser, event, true) ++ ++ case yaml_PARSE_BLOCK_MAPPING_KEY_STATE: ++ return yaml_parser_parse_block_mapping_key(parser, event, false) ++ ++ case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE: ++ return yaml_parser_parse_block_mapping_value(parser, event) ++ ++ case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: ++ return yaml_parser_parse_flow_sequence_entry(parser, event, true) ++ ++ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE: ++ return yaml_parser_parse_flow_sequence_entry(parser, event, false) ++ ++ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: ++ return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event) ++ ++ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: ++ return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event) ++ ++ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: ++ return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event) ++ ++ case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: ++ return yaml_parser_parse_flow_mapping_key(parser, event, true) ++ ++ case yaml_PARSE_FLOW_MAPPING_KEY_STATE: ++ return yaml_parser_parse_flow_mapping_key(parser, event, false) ++ ++ case yaml_PARSE_FLOW_MAPPING_VALUE_STATE: ++ return yaml_parser_parse_flow_mapping_value(parser, event, false) ++ ++ case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: ++ return yaml_parser_parse_flow_mapping_value(parser, event, true) ++ ++ default: ++ panic("invalid parser state") ++ } ++} ++ ++// Parse the production: ++// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END ++// ************ ++func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool { ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ != yaml_STREAM_START_TOKEN { ++ return yaml_parser_set_parser_error(parser, "did not find expected ", token.start_mark) ++ } ++ parser.state = yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE ++ *event = yaml_event_t{ ++ typ: yaml_STREAM_START_EVENT, ++ start_mark: token.start_mark, ++ end_mark: token.end_mark, ++ encoding: token.encoding, ++ } ++ skip_token(parser) ++ return true ++} ++ ++// Parse the productions: ++// implicit_document ::= block_node DOCUMENT-END* ++// * ++// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* ++// ************************* ++func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool { ++ ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ ++ // Parse extra document end indicators. ++ if !implicit { ++ for token.typ == yaml_DOCUMENT_END_TOKEN { ++ skip_token(parser) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ } ++ } ++ ++ if implicit && token.typ != yaml_VERSION_DIRECTIVE_TOKEN && ++ token.typ != yaml_TAG_DIRECTIVE_TOKEN && ++ token.typ != yaml_DOCUMENT_START_TOKEN && ++ token.typ != yaml_STREAM_END_TOKEN { ++ // Parse an implicit document. ++ if !yaml_parser_process_directives(parser, nil, nil) { ++ return false ++ } ++ parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE) ++ parser.state = yaml_PARSE_BLOCK_NODE_STATE ++ ++ var head_comment []byte ++ if len(parser.head_comment) > 0 { ++ // [Go] Scan the header comment backwards, and if an empty line is found, break ++ // the header so the part before the last empty line goes into the ++ // document header, while the bottom of it goes into a follow up event. ++ for i := len(parser.head_comment) - 1; i > 0; i-- { ++ if parser.head_comment[i] == '\n' { ++ if i == len(parser.head_comment)-1 { ++ head_comment = parser.head_comment[:i] ++ parser.head_comment = parser.head_comment[i+1:] ++ break ++ } else if parser.head_comment[i-1] == '\n' { ++ head_comment = parser.head_comment[:i-1] ++ parser.head_comment = parser.head_comment[i+1:] ++ break ++ } ++ } ++ } ++ } ++ ++ *event = yaml_event_t{ ++ typ: yaml_DOCUMENT_START_EVENT, ++ start_mark: token.start_mark, ++ end_mark: token.end_mark, ++ ++ head_comment: head_comment, ++ } ++ ++ } else if token.typ != yaml_STREAM_END_TOKEN { ++ // Parse an explicit document. ++ var version_directive *yaml_version_directive_t ++ var tag_directives []yaml_tag_directive_t ++ start_mark := token.start_mark ++ if !yaml_parser_process_directives(parser, &version_directive, &tag_directives) { ++ return false ++ } ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ != yaml_DOCUMENT_START_TOKEN { ++ yaml_parser_set_parser_error(parser, ++ "did not find expected ", token.start_mark) ++ return false ++ } ++ parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE) ++ parser.state = yaml_PARSE_DOCUMENT_CONTENT_STATE ++ end_mark := token.end_mark ++ ++ *event = yaml_event_t{ ++ typ: yaml_DOCUMENT_START_EVENT, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ version_directive: version_directive, ++ tag_directives: tag_directives, ++ implicit: false, ++ } ++ skip_token(parser) ++ ++ } else { ++ // Parse the stream end. ++ parser.state = yaml_PARSE_END_STATE ++ *event = yaml_event_t{ ++ typ: yaml_STREAM_END_EVENT, ++ start_mark: token.start_mark, ++ end_mark: token.end_mark, ++ } ++ skip_token(parser) ++ } ++ ++ return true ++} ++ ++// Parse the productions: ++// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* ++// *********** ++// ++func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool { ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ ++ if token.typ == yaml_VERSION_DIRECTIVE_TOKEN || ++ token.typ == yaml_TAG_DIRECTIVE_TOKEN || ++ token.typ == yaml_DOCUMENT_START_TOKEN || ++ token.typ == yaml_DOCUMENT_END_TOKEN || ++ token.typ == yaml_STREAM_END_TOKEN { ++ parser.state = parser.states[len(parser.states)-1] ++ parser.states = parser.states[:len(parser.states)-1] ++ return yaml_parser_process_empty_scalar(parser, event, ++ token.start_mark) ++ } ++ return yaml_parser_parse_node(parser, event, true, false) ++} ++ ++// Parse the productions: ++// implicit_document ::= block_node DOCUMENT-END* ++// ************* ++// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* ++// ++func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool { ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ ++ start_mark := token.start_mark ++ end_mark := token.start_mark ++ ++ implicit := true ++ if token.typ == yaml_DOCUMENT_END_TOKEN { ++ end_mark = token.end_mark ++ skip_token(parser) ++ implicit = false ++ } ++ ++ parser.tag_directives = parser.tag_directives[:0] ++ ++ parser.state = yaml_PARSE_DOCUMENT_START_STATE ++ *event = yaml_event_t{ ++ typ: yaml_DOCUMENT_END_EVENT, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ implicit: implicit, ++ } ++ yaml_parser_set_event_comments(parser, event) ++ if len(event.head_comment) > 0 && len(event.foot_comment) == 0 { ++ event.foot_comment = event.head_comment ++ event.head_comment = nil ++ } ++ return true ++} ++ ++func yaml_parser_set_event_comments(parser *yaml_parser_t, event *yaml_event_t) { ++ event.head_comment = parser.head_comment ++ event.line_comment = parser.line_comment ++ event.foot_comment = parser.foot_comment ++ parser.head_comment = nil ++ parser.line_comment = nil ++ parser.foot_comment = nil ++ parser.tail_comment = nil ++ parser.stem_comment = nil ++} ++ ++// Parse the productions: ++// block_node_or_indentless_sequence ::= ++// ALIAS ++// ***** ++// | properties (block_content | indentless_block_sequence)? ++// ********** * ++// | block_content | indentless_block_sequence ++// * ++// block_node ::= ALIAS ++// ***** ++// | properties block_content? ++// ********** * ++// | block_content ++// * ++// flow_node ::= ALIAS ++// ***** ++// | properties flow_content? ++// ********** * ++// | flow_content ++// * ++// properties ::= TAG ANCHOR? | ANCHOR TAG? ++// ************************* ++// block_content ::= block_collection | flow_collection | SCALAR ++// ****** ++// flow_content ::= flow_collection | SCALAR ++// ****** ++func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool { ++ //defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)() ++ ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ ++ if token.typ == yaml_ALIAS_TOKEN { ++ parser.state = parser.states[len(parser.states)-1] ++ parser.states = parser.states[:len(parser.states)-1] ++ *event = yaml_event_t{ ++ typ: yaml_ALIAS_EVENT, ++ start_mark: token.start_mark, ++ end_mark: token.end_mark, ++ anchor: token.value, ++ } ++ yaml_parser_set_event_comments(parser, event) ++ skip_token(parser) ++ return true ++ } ++ ++ start_mark := token.start_mark ++ end_mark := token.start_mark ++ ++ var tag_token bool ++ var tag_handle, tag_suffix, anchor []byte ++ var tag_mark yaml_mark_t ++ if token.typ == yaml_ANCHOR_TOKEN { ++ anchor = token.value ++ start_mark = token.start_mark ++ end_mark = token.end_mark ++ skip_token(parser) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ == yaml_TAG_TOKEN { ++ tag_token = true ++ tag_handle = token.value ++ tag_suffix = token.suffix ++ tag_mark = token.start_mark ++ end_mark = token.end_mark ++ skip_token(parser) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ } ++ } else if token.typ == yaml_TAG_TOKEN { ++ tag_token = true ++ tag_handle = token.value ++ tag_suffix = token.suffix ++ start_mark = token.start_mark ++ tag_mark = token.start_mark ++ end_mark = token.end_mark ++ skip_token(parser) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ == yaml_ANCHOR_TOKEN { ++ anchor = token.value ++ end_mark = token.end_mark ++ skip_token(parser) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ } ++ } ++ ++ var tag []byte ++ if tag_token { ++ if len(tag_handle) == 0 { ++ tag = tag_suffix ++ tag_suffix = nil ++ } else { ++ for i := range parser.tag_directives { ++ if bytes.Equal(parser.tag_directives[i].handle, tag_handle) { ++ tag = append([]byte(nil), parser.tag_directives[i].prefix...) ++ tag = append(tag, tag_suffix...) ++ break ++ } ++ } ++ if len(tag) == 0 { ++ yaml_parser_set_parser_error_context(parser, ++ "while parsing a node", start_mark, ++ "found undefined tag handle", tag_mark) ++ return false ++ } ++ } ++ } ++ ++ implicit := len(tag) == 0 ++ if indentless_sequence && token.typ == yaml_BLOCK_ENTRY_TOKEN { ++ end_mark = token.end_mark ++ parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE ++ *event = yaml_event_t{ ++ typ: yaml_SEQUENCE_START_EVENT, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ anchor: anchor, ++ tag: tag, ++ implicit: implicit, ++ style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE), ++ } ++ return true ++ } ++ if token.typ == yaml_SCALAR_TOKEN { ++ var plain_implicit, quoted_implicit bool ++ end_mark = token.end_mark ++ if (len(tag) == 0 && token.style == yaml_PLAIN_SCALAR_STYLE) || (len(tag) == 1 && tag[0] == '!') { ++ plain_implicit = true ++ } else if len(tag) == 0 { ++ quoted_implicit = true ++ } ++ parser.state = parser.states[len(parser.states)-1] ++ parser.states = parser.states[:len(parser.states)-1] ++ ++ *event = yaml_event_t{ ++ typ: yaml_SCALAR_EVENT, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ anchor: anchor, ++ tag: tag, ++ value: token.value, ++ implicit: plain_implicit, ++ quoted_implicit: quoted_implicit, ++ style: yaml_style_t(token.style), ++ } ++ yaml_parser_set_event_comments(parser, event) ++ skip_token(parser) ++ return true ++ } ++ if token.typ == yaml_FLOW_SEQUENCE_START_TOKEN { ++ // [Go] Some of the events below can be merged as they differ only on style. ++ end_mark = token.end_mark ++ parser.state = yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE ++ *event = yaml_event_t{ ++ typ: yaml_SEQUENCE_START_EVENT, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ anchor: anchor, ++ tag: tag, ++ implicit: implicit, ++ style: yaml_style_t(yaml_FLOW_SEQUENCE_STYLE), ++ } ++ yaml_parser_set_event_comments(parser, event) ++ return true ++ } ++ if token.typ == yaml_FLOW_MAPPING_START_TOKEN { ++ end_mark = token.end_mark ++ parser.state = yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE ++ *event = yaml_event_t{ ++ typ: yaml_MAPPING_START_EVENT, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ anchor: anchor, ++ tag: tag, ++ implicit: implicit, ++ style: yaml_style_t(yaml_FLOW_MAPPING_STYLE), ++ } ++ yaml_parser_set_event_comments(parser, event) ++ return true ++ } ++ if block && token.typ == yaml_BLOCK_SEQUENCE_START_TOKEN { ++ end_mark = token.end_mark ++ parser.state = yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE ++ *event = yaml_event_t{ ++ typ: yaml_SEQUENCE_START_EVENT, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ anchor: anchor, ++ tag: tag, ++ implicit: implicit, ++ style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE), ++ } ++ if parser.stem_comment != nil { ++ event.head_comment = parser.stem_comment ++ parser.stem_comment = nil ++ } ++ return true ++ } ++ if block && token.typ == yaml_BLOCK_MAPPING_START_TOKEN { ++ end_mark = token.end_mark ++ parser.state = yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE ++ *event = yaml_event_t{ ++ typ: yaml_MAPPING_START_EVENT, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ anchor: anchor, ++ tag: tag, ++ implicit: implicit, ++ style: yaml_style_t(yaml_BLOCK_MAPPING_STYLE), ++ } ++ if parser.stem_comment != nil { ++ event.head_comment = parser.stem_comment ++ parser.stem_comment = nil ++ } ++ return true ++ } ++ if len(anchor) > 0 || len(tag) > 0 { ++ parser.state = parser.states[len(parser.states)-1] ++ parser.states = parser.states[:len(parser.states)-1] ++ ++ *event = yaml_event_t{ ++ typ: yaml_SCALAR_EVENT, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ anchor: anchor, ++ tag: tag, ++ implicit: implicit, ++ quoted_implicit: false, ++ style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE), ++ } ++ return true ++ } ++ ++ context := "while parsing a flow node" ++ if block { ++ context = "while parsing a block node" ++ } ++ yaml_parser_set_parser_error_context(parser, context, start_mark, ++ "did not find expected node content", token.start_mark) ++ return false ++} ++ ++// Parse the productions: ++// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END ++// ******************** *********** * ********* ++// ++func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { ++ if first { ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ parser.marks = append(parser.marks, token.start_mark) ++ skip_token(parser) ++ } ++ ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ ++ if token.typ == yaml_BLOCK_ENTRY_TOKEN { ++ mark := token.end_mark ++ prior_head_len := len(parser.head_comment) ++ skip_token(parser) ++ yaml_parser_split_stem_comment(parser, prior_head_len) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ != yaml_BLOCK_ENTRY_TOKEN && token.typ != yaml_BLOCK_END_TOKEN { ++ parser.states = append(parser.states, yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE) ++ return yaml_parser_parse_node(parser, event, true, false) ++ } else { ++ parser.state = yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE ++ return yaml_parser_process_empty_scalar(parser, event, mark) ++ } ++ } ++ if token.typ == yaml_BLOCK_END_TOKEN { ++ parser.state = parser.states[len(parser.states)-1] ++ parser.states = parser.states[:len(parser.states)-1] ++ parser.marks = parser.marks[:len(parser.marks)-1] ++ ++ *event = yaml_event_t{ ++ typ: yaml_SEQUENCE_END_EVENT, ++ start_mark: token.start_mark, ++ end_mark: token.end_mark, ++ } ++ ++ skip_token(parser) ++ return true ++ } ++ ++ context_mark := parser.marks[len(parser.marks)-1] ++ parser.marks = parser.marks[:len(parser.marks)-1] ++ return yaml_parser_set_parser_error_context(parser, ++ "while parsing a block collection", context_mark, ++ "did not find expected '-' indicator", token.start_mark) ++} ++ ++// Parse the productions: ++// indentless_sequence ::= (BLOCK-ENTRY block_node?)+ ++// *********** * ++func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool { ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ ++ if token.typ == yaml_BLOCK_ENTRY_TOKEN { ++ mark := token.end_mark ++ prior_head_len := len(parser.head_comment) ++ skip_token(parser) ++ yaml_parser_split_stem_comment(parser, prior_head_len) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ != yaml_BLOCK_ENTRY_TOKEN && ++ token.typ != yaml_KEY_TOKEN && ++ token.typ != yaml_VALUE_TOKEN && ++ token.typ != yaml_BLOCK_END_TOKEN { ++ parser.states = append(parser.states, yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE) ++ return yaml_parser_parse_node(parser, event, true, false) ++ } ++ parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE ++ return yaml_parser_process_empty_scalar(parser, event, mark) ++ } ++ parser.state = parser.states[len(parser.states)-1] ++ parser.states = parser.states[:len(parser.states)-1] ++ ++ *event = yaml_event_t{ ++ typ: yaml_SEQUENCE_END_EVENT, ++ start_mark: token.start_mark, ++ end_mark: token.start_mark, // [Go] Shouldn't this be token.end_mark? ++ } ++ return true ++} ++ ++// Split stem comment from head comment. ++// ++// When a sequence or map is found under a sequence entry, the former head comment ++// is assigned to the underlying sequence or map as a whole, not the individual ++// sequence or map entry as would be expected otherwise. To handle this case the ++// previous head comment is moved aside as the stem comment. ++func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) { ++ if stem_len == 0 { ++ return ++ } ++ ++ token := peek_token(parser) ++ if token == nil || token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN { ++ return ++ } ++ ++ parser.stem_comment = parser.head_comment[:stem_len] ++ if len(parser.head_comment) == stem_len { ++ parser.head_comment = nil ++ } else { ++ // Copy suffix to prevent very strange bugs if someone ever appends ++ // further bytes to the prefix in the stem_comment slice above. ++ parser.head_comment = append([]byte(nil), parser.head_comment[stem_len+1:]...) ++ } ++} ++ ++// Parse the productions: ++// block_mapping ::= BLOCK-MAPPING_START ++// ******************* ++// ((KEY block_node_or_indentless_sequence?)? ++// *** * ++// (VALUE block_node_or_indentless_sequence?)?)* ++// ++// BLOCK-END ++// ********* ++// ++func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { ++ if first { ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ parser.marks = append(parser.marks, token.start_mark) ++ skip_token(parser) ++ } ++ ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ ++ // [Go] A tail comment was left from the prior mapping value processed. Emit an event ++ // as it needs to be processed with that value and not the following key. ++ if len(parser.tail_comment) > 0 { ++ *event = yaml_event_t{ ++ typ: yaml_TAIL_COMMENT_EVENT, ++ start_mark: token.start_mark, ++ end_mark: token.end_mark, ++ foot_comment: parser.tail_comment, ++ } ++ parser.tail_comment = nil ++ return true ++ } ++ ++ if token.typ == yaml_KEY_TOKEN { ++ mark := token.end_mark ++ skip_token(parser) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ != yaml_KEY_TOKEN && ++ token.typ != yaml_VALUE_TOKEN && ++ token.typ != yaml_BLOCK_END_TOKEN { ++ parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_VALUE_STATE) ++ return yaml_parser_parse_node(parser, event, true, true) ++ } else { ++ parser.state = yaml_PARSE_BLOCK_MAPPING_VALUE_STATE ++ return yaml_parser_process_empty_scalar(parser, event, mark) ++ } ++ } else if token.typ == yaml_BLOCK_END_TOKEN { ++ parser.state = parser.states[len(parser.states)-1] ++ parser.states = parser.states[:len(parser.states)-1] ++ parser.marks = parser.marks[:len(parser.marks)-1] ++ *event = yaml_event_t{ ++ typ: yaml_MAPPING_END_EVENT, ++ start_mark: token.start_mark, ++ end_mark: token.end_mark, ++ } ++ yaml_parser_set_event_comments(parser, event) ++ skip_token(parser) ++ return true ++ } ++ ++ context_mark := parser.marks[len(parser.marks)-1] ++ parser.marks = parser.marks[:len(parser.marks)-1] ++ return yaml_parser_set_parser_error_context(parser, ++ "while parsing a block mapping", context_mark, ++ "did not find expected key", token.start_mark) ++} ++ ++// Parse the productions: ++// block_mapping ::= BLOCK-MAPPING_START ++// ++// ((KEY block_node_or_indentless_sequence?)? ++// ++// (VALUE block_node_or_indentless_sequence?)?)* ++// ***** * ++// BLOCK-END ++// ++// ++func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool { ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ == yaml_VALUE_TOKEN { ++ mark := token.end_mark ++ skip_token(parser) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ != yaml_KEY_TOKEN && ++ token.typ != yaml_VALUE_TOKEN && ++ token.typ != yaml_BLOCK_END_TOKEN { ++ parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_KEY_STATE) ++ return yaml_parser_parse_node(parser, event, true, true) ++ } ++ parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE ++ return yaml_parser_process_empty_scalar(parser, event, mark) ++ } ++ parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE ++ return yaml_parser_process_empty_scalar(parser, event, token.start_mark) ++} ++ ++// Parse the productions: ++// flow_sequence ::= FLOW-SEQUENCE-START ++// ******************* ++// (flow_sequence_entry FLOW-ENTRY)* ++// * ********** ++// flow_sequence_entry? ++// * ++// FLOW-SEQUENCE-END ++// ***************** ++// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? ++// * ++// ++func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { ++ if first { ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ parser.marks = append(parser.marks, token.start_mark) ++ skip_token(parser) ++ } ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { ++ if !first { ++ if token.typ == yaml_FLOW_ENTRY_TOKEN { ++ skip_token(parser) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ } else { ++ context_mark := parser.marks[len(parser.marks)-1] ++ parser.marks = parser.marks[:len(parser.marks)-1] ++ return yaml_parser_set_parser_error_context(parser, ++ "while parsing a flow sequence", context_mark, ++ "did not find expected ',' or ']'", token.start_mark) ++ } ++ } ++ ++ if token.typ == yaml_KEY_TOKEN { ++ parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE ++ *event = yaml_event_t{ ++ typ: yaml_MAPPING_START_EVENT, ++ start_mark: token.start_mark, ++ end_mark: token.end_mark, ++ implicit: true, ++ style: yaml_style_t(yaml_FLOW_MAPPING_STYLE), ++ } ++ skip_token(parser) ++ return true ++ } else if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { ++ parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE) ++ return yaml_parser_parse_node(parser, event, false, false) ++ } ++ } ++ ++ parser.state = parser.states[len(parser.states)-1] ++ parser.states = parser.states[:len(parser.states)-1] ++ parser.marks = parser.marks[:len(parser.marks)-1] ++ ++ *event = yaml_event_t{ ++ typ: yaml_SEQUENCE_END_EVENT, ++ start_mark: token.start_mark, ++ end_mark: token.end_mark, ++ } ++ yaml_parser_set_event_comments(parser, event) ++ ++ skip_token(parser) ++ return true ++} ++ ++// ++// Parse the productions: ++// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? ++// *** * ++// ++func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool { ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ != yaml_VALUE_TOKEN && ++ token.typ != yaml_FLOW_ENTRY_TOKEN && ++ token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { ++ parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE) ++ return yaml_parser_parse_node(parser, event, false, false) ++ } ++ mark := token.end_mark ++ skip_token(parser) ++ parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE ++ return yaml_parser_process_empty_scalar(parser, event, mark) ++} ++ ++// Parse the productions: ++// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? ++// ***** * ++// ++func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool { ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ == yaml_VALUE_TOKEN { ++ skip_token(parser) ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { ++ parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE) ++ return yaml_parser_parse_node(parser, event, false, false) ++ } ++ } ++ parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE ++ return yaml_parser_process_empty_scalar(parser, event, token.start_mark) ++} ++ ++// Parse the productions: ++// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? ++// * ++// ++func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool { ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE ++ *event = yaml_event_t{ ++ typ: yaml_MAPPING_END_EVENT, ++ start_mark: token.start_mark, ++ end_mark: token.start_mark, // [Go] Shouldn't this be end_mark? ++ } ++ return true ++} ++ ++// Parse the productions: ++// flow_mapping ::= FLOW-MAPPING-START ++// ****************** ++// (flow_mapping_entry FLOW-ENTRY)* ++// * ********** ++// flow_mapping_entry? ++// ****************** ++// FLOW-MAPPING-END ++// **************** ++// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? ++// * *** * ++// ++func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { ++ if first { ++ token := peek_token(parser) ++ parser.marks = append(parser.marks, token.start_mark) ++ skip_token(parser) ++ } ++ ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ ++ if token.typ != yaml_FLOW_MAPPING_END_TOKEN { ++ if !first { ++ if token.typ == yaml_FLOW_ENTRY_TOKEN { ++ skip_token(parser) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ } else { ++ context_mark := parser.marks[len(parser.marks)-1] ++ parser.marks = parser.marks[:len(parser.marks)-1] ++ return yaml_parser_set_parser_error_context(parser, ++ "while parsing a flow mapping", context_mark, ++ "did not find expected ',' or '}'", token.start_mark) ++ } ++ } ++ ++ if token.typ == yaml_KEY_TOKEN { ++ skip_token(parser) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ != yaml_VALUE_TOKEN && ++ token.typ != yaml_FLOW_ENTRY_TOKEN && ++ token.typ != yaml_FLOW_MAPPING_END_TOKEN { ++ parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_VALUE_STATE) ++ return yaml_parser_parse_node(parser, event, false, false) ++ } else { ++ parser.state = yaml_PARSE_FLOW_MAPPING_VALUE_STATE ++ return yaml_parser_process_empty_scalar(parser, event, token.start_mark) ++ } ++ } else if token.typ != yaml_FLOW_MAPPING_END_TOKEN { ++ parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE) ++ return yaml_parser_parse_node(parser, event, false, false) ++ } ++ } ++ ++ parser.state = parser.states[len(parser.states)-1] ++ parser.states = parser.states[:len(parser.states)-1] ++ parser.marks = parser.marks[:len(parser.marks)-1] ++ *event = yaml_event_t{ ++ typ: yaml_MAPPING_END_EVENT, ++ start_mark: token.start_mark, ++ end_mark: token.end_mark, ++ } ++ yaml_parser_set_event_comments(parser, event) ++ skip_token(parser) ++ return true ++} ++ ++// Parse the productions: ++// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? ++// * ***** * ++// ++func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool { ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if empty { ++ parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE ++ return yaml_parser_process_empty_scalar(parser, event, token.start_mark) ++ } ++ if token.typ == yaml_VALUE_TOKEN { ++ skip_token(parser) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_MAPPING_END_TOKEN { ++ parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_KEY_STATE) ++ return yaml_parser_parse_node(parser, event, false, false) ++ } ++ } ++ parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE ++ return yaml_parser_process_empty_scalar(parser, event, token.start_mark) ++} ++ ++// Generate an empty scalar event. ++func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml_event_t, mark yaml_mark_t) bool { ++ *event = yaml_event_t{ ++ typ: yaml_SCALAR_EVENT, ++ start_mark: mark, ++ end_mark: mark, ++ value: nil, // Empty ++ implicit: true, ++ style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE), ++ } ++ return true ++} ++ ++var default_tag_directives = []yaml_tag_directive_t{ ++ {[]byte("!"), []byte("!")}, ++ {[]byte("!!"), []byte("tag:yaml.org,2002:")}, ++} ++ ++// Parse directives. ++func yaml_parser_process_directives(parser *yaml_parser_t, ++ version_directive_ref **yaml_version_directive_t, ++ tag_directives_ref *[]yaml_tag_directive_t) bool { ++ ++ var version_directive *yaml_version_directive_t ++ var tag_directives []yaml_tag_directive_t ++ ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ ++ for token.typ == yaml_VERSION_DIRECTIVE_TOKEN || token.typ == yaml_TAG_DIRECTIVE_TOKEN { ++ if token.typ == yaml_VERSION_DIRECTIVE_TOKEN { ++ if version_directive != nil { ++ yaml_parser_set_parser_error(parser, ++ "found duplicate %YAML directive", token.start_mark) ++ return false ++ } ++ if token.major != 1 || token.minor != 1 { ++ yaml_parser_set_parser_error(parser, ++ "found incompatible YAML document", token.start_mark) ++ return false ++ } ++ version_directive = &yaml_version_directive_t{ ++ major: token.major, ++ minor: token.minor, ++ } ++ } else if token.typ == yaml_TAG_DIRECTIVE_TOKEN { ++ value := yaml_tag_directive_t{ ++ handle: token.value, ++ prefix: token.prefix, ++ } ++ if !yaml_parser_append_tag_directive(parser, value, false, token.start_mark) { ++ return false ++ } ++ tag_directives = append(tag_directives, value) ++ } ++ ++ skip_token(parser) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ } ++ ++ for i := range default_tag_directives { ++ if !yaml_parser_append_tag_directive(parser, default_tag_directives[i], true, token.start_mark) { ++ return false ++ } ++ } ++ ++ if version_directive_ref != nil { ++ *version_directive_ref = version_directive ++ } ++ if tag_directives_ref != nil { ++ *tag_directives_ref = tag_directives ++ } ++ return true ++} ++ ++// Append a tag directive to the directives stack. ++func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_tag_directive_t, allow_duplicates bool, mark yaml_mark_t) bool { ++ for i := range parser.tag_directives { ++ if bytes.Equal(value.handle, parser.tag_directives[i].handle) { ++ if allow_duplicates { ++ return true ++ } ++ return yaml_parser_set_parser_error(parser, "found duplicate %TAG directive", mark) ++ } ++ } ++ ++ // [Go] I suspect the copy is unnecessary. This was likely done ++ // because there was no way to track ownership of the data. ++ value_copy := yaml_tag_directive_t{ ++ handle: make([]byte, len(value.handle)), ++ prefix: make([]byte, len(value.prefix)), ++ } ++ copy(value_copy.handle, value.handle) ++ copy(value_copy.prefix, value.prefix) ++ parser.tag_directives = append(parser.tag_directives, value_copy) ++ return true ++} +diff --git a/vendor/gopkg.in/yaml.v3/readerc.go b/vendor/gopkg.in/yaml.v3/readerc.go +new file mode 100644 +index 000000000000..b7de0a89c462 +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/readerc.go +@@ -0,0 +1,434 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// Copyright (c) 2006-2010 Kirill Simonov ++// ++// 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. ++ ++package yaml ++ ++import ( ++ "io" ++) ++ ++// Set the reader error and return 0. ++func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool { ++ parser.error = yaml_READER_ERROR ++ parser.problem = problem ++ parser.problem_offset = offset ++ parser.problem_value = value ++ return false ++} ++ ++// Byte order marks. ++const ( ++ bom_UTF8 = "\xef\xbb\xbf" ++ bom_UTF16LE = "\xff\xfe" ++ bom_UTF16BE = "\xfe\xff" ++) ++ ++// Determine the input stream encoding by checking the BOM symbol. If no BOM is ++// found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure. ++func yaml_parser_determine_encoding(parser *yaml_parser_t) bool { ++ // Ensure that we had enough bytes in the raw buffer. ++ for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 { ++ if !yaml_parser_update_raw_buffer(parser) { ++ return false ++ } ++ } ++ ++ // Determine the encoding. ++ buf := parser.raw_buffer ++ pos := parser.raw_buffer_pos ++ avail := len(buf) - pos ++ if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] { ++ parser.encoding = yaml_UTF16LE_ENCODING ++ parser.raw_buffer_pos += 2 ++ parser.offset += 2 ++ } else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] { ++ parser.encoding = yaml_UTF16BE_ENCODING ++ parser.raw_buffer_pos += 2 ++ parser.offset += 2 ++ } else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] { ++ parser.encoding = yaml_UTF8_ENCODING ++ parser.raw_buffer_pos += 3 ++ parser.offset += 3 ++ } else { ++ parser.encoding = yaml_UTF8_ENCODING ++ } ++ return true ++} ++ ++// Update the raw buffer. ++func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool { ++ size_read := 0 ++ ++ // Return if the raw buffer is full. ++ if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) { ++ return true ++ } ++ ++ // Return on EOF. ++ if parser.eof { ++ return true ++ } ++ ++ // Move the remaining bytes in the raw buffer to the beginning. ++ if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) { ++ copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:]) ++ } ++ parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos] ++ parser.raw_buffer_pos = 0 ++ ++ // Call the read handler to fill the buffer. ++ size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)]) ++ parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read] ++ if err == io.EOF { ++ parser.eof = true ++ } else if err != nil { ++ return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1) ++ } ++ return true ++} ++ ++// Ensure that the buffer contains at least `length` characters. ++// Return true on success, false on failure. ++// ++// The length is supposed to be significantly less that the buffer size. ++func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool { ++ if parser.read_handler == nil { ++ panic("read handler must be set") ++ } ++ ++ // [Go] This function was changed to guarantee the requested length size at EOF. ++ // The fact we need to do this is pretty awful, but the description above implies ++ // for that to be the case, and there are tests ++ ++ // If the EOF flag is set and the raw buffer is empty, do nothing. ++ if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) { ++ // [Go] ACTUALLY! Read the documentation of this function above. ++ // This is just broken. To return true, we need to have the ++ // given length in the buffer. Not doing that means every single ++ // check that calls this function to make sure the buffer has a ++ // given length is Go) panicking; or C) accessing invalid memory. ++ //return true ++ } ++ ++ // Return if the buffer contains enough characters. ++ if parser.unread >= length { ++ return true ++ } ++ ++ // Determine the input encoding if it is not known yet. ++ if parser.encoding == yaml_ANY_ENCODING { ++ if !yaml_parser_determine_encoding(parser) { ++ return false ++ } ++ } ++ ++ // Move the unread characters to the beginning of the buffer. ++ buffer_len := len(parser.buffer) ++ if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len { ++ copy(parser.buffer, parser.buffer[parser.buffer_pos:]) ++ buffer_len -= parser.buffer_pos ++ parser.buffer_pos = 0 ++ } else if parser.buffer_pos == buffer_len { ++ buffer_len = 0 ++ parser.buffer_pos = 0 ++ } ++ ++ // Open the whole buffer for writing, and cut it before returning. ++ parser.buffer = parser.buffer[:cap(parser.buffer)] ++ ++ // Fill the buffer until it has enough characters. ++ first := true ++ for parser.unread < length { ++ ++ // Fill the raw buffer if necessary. ++ if !first || parser.raw_buffer_pos == len(parser.raw_buffer) { ++ if !yaml_parser_update_raw_buffer(parser) { ++ parser.buffer = parser.buffer[:buffer_len] ++ return false ++ } ++ } ++ first = false ++ ++ // Decode the raw buffer. ++ inner: ++ for parser.raw_buffer_pos != len(parser.raw_buffer) { ++ var value rune ++ var width int ++ ++ raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos ++ ++ // Decode the next character. ++ switch parser.encoding { ++ case yaml_UTF8_ENCODING: ++ // Decode a UTF-8 character. Check RFC 3629 ++ // (http://www.ietf.org/rfc/rfc3629.txt) for more details. ++ // ++ // The following table (taken from the RFC) is used for ++ // decoding. ++ // ++ // Char. number range | UTF-8 octet sequence ++ // (hexadecimal) | (binary) ++ // --------------------+------------------------------------ ++ // 0000 0000-0000 007F | 0xxxxxxx ++ // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx ++ // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx ++ // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx ++ // ++ // Additionally, the characters in the range 0xD800-0xDFFF ++ // are prohibited as they are reserved for use with UTF-16 ++ // surrogate pairs. ++ ++ // Determine the length of the UTF-8 sequence. ++ octet := parser.raw_buffer[parser.raw_buffer_pos] ++ switch { ++ case octet&0x80 == 0x00: ++ width = 1 ++ case octet&0xE0 == 0xC0: ++ width = 2 ++ case octet&0xF0 == 0xE0: ++ width = 3 ++ case octet&0xF8 == 0xF0: ++ width = 4 ++ default: ++ // The leading octet is invalid. ++ return yaml_parser_set_reader_error(parser, ++ "invalid leading UTF-8 octet", ++ parser.offset, int(octet)) ++ } ++ ++ // Check if the raw buffer contains an incomplete character. ++ if width > raw_unread { ++ if parser.eof { ++ return yaml_parser_set_reader_error(parser, ++ "incomplete UTF-8 octet sequence", ++ parser.offset, -1) ++ } ++ break inner ++ } ++ ++ // Decode the leading octet. ++ switch { ++ case octet&0x80 == 0x00: ++ value = rune(octet & 0x7F) ++ case octet&0xE0 == 0xC0: ++ value = rune(octet & 0x1F) ++ case octet&0xF0 == 0xE0: ++ value = rune(octet & 0x0F) ++ case octet&0xF8 == 0xF0: ++ value = rune(octet & 0x07) ++ default: ++ value = 0 ++ } ++ ++ // Check and decode the trailing octets. ++ for k := 1; k < width; k++ { ++ octet = parser.raw_buffer[parser.raw_buffer_pos+k] ++ ++ // Check if the octet is valid. ++ if (octet & 0xC0) != 0x80 { ++ return yaml_parser_set_reader_error(parser, ++ "invalid trailing UTF-8 octet", ++ parser.offset+k, int(octet)) ++ } ++ ++ // Decode the octet. ++ value = (value << 6) + rune(octet&0x3F) ++ } ++ ++ // Check the length of the sequence against the value. ++ switch { ++ case width == 1: ++ case width == 2 && value >= 0x80: ++ case width == 3 && value >= 0x800: ++ case width == 4 && value >= 0x10000: ++ default: ++ return yaml_parser_set_reader_error(parser, ++ "invalid length of a UTF-8 sequence", ++ parser.offset, -1) ++ } ++ ++ // Check the range of the value. ++ if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF { ++ return yaml_parser_set_reader_error(parser, ++ "invalid Unicode character", ++ parser.offset, int(value)) ++ } ++ ++ case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING: ++ var low, high int ++ if parser.encoding == yaml_UTF16LE_ENCODING { ++ low, high = 0, 1 ++ } else { ++ low, high = 1, 0 ++ } ++ ++ // The UTF-16 encoding is not as simple as one might ++ // naively think. Check RFC 2781 ++ // (http://www.ietf.org/rfc/rfc2781.txt). ++ // ++ // Normally, two subsequent bytes describe a Unicode ++ // character. However a special technique (called a ++ // surrogate pair) is used for specifying character ++ // values larger than 0xFFFF. ++ // ++ // A surrogate pair consists of two pseudo-characters: ++ // high surrogate area (0xD800-0xDBFF) ++ // low surrogate area (0xDC00-0xDFFF) ++ // ++ // The following formulas are used for decoding ++ // and encoding characters using surrogate pairs: ++ // ++ // U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF) ++ // U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF) ++ // W1 = 110110yyyyyyyyyy ++ // W2 = 110111xxxxxxxxxx ++ // ++ // where U is the character value, W1 is the high surrogate ++ // area, W2 is the low surrogate area. ++ ++ // Check for incomplete UTF-16 character. ++ if raw_unread < 2 { ++ if parser.eof { ++ return yaml_parser_set_reader_error(parser, ++ "incomplete UTF-16 character", ++ parser.offset, -1) ++ } ++ break inner ++ } ++ ++ // Get the character. ++ value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) + ++ (rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8) ++ ++ // Check for unexpected low surrogate area. ++ if value&0xFC00 == 0xDC00 { ++ return yaml_parser_set_reader_error(parser, ++ "unexpected low surrogate area", ++ parser.offset, int(value)) ++ } ++ ++ // Check for a high surrogate area. ++ if value&0xFC00 == 0xD800 { ++ width = 4 ++ ++ // Check for incomplete surrogate pair. ++ if raw_unread < 4 { ++ if parser.eof { ++ return yaml_parser_set_reader_error(parser, ++ "incomplete UTF-16 surrogate pair", ++ parser.offset, -1) ++ } ++ break inner ++ } ++ ++ // Get the next character. ++ value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) + ++ (rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8) ++ ++ // Check for a low surrogate area. ++ if value2&0xFC00 != 0xDC00 { ++ return yaml_parser_set_reader_error(parser, ++ "expected low surrogate area", ++ parser.offset+2, int(value2)) ++ } ++ ++ // Generate the value of the surrogate pair. ++ value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF) ++ } else { ++ width = 2 ++ } ++ ++ default: ++ panic("impossible") ++ } ++ ++ // Check if the character is in the allowed range: ++ // #x9 | #xA | #xD | [#x20-#x7E] (8 bit) ++ // | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit) ++ // | [#x10000-#x10FFFF] (32 bit) ++ switch { ++ case value == 0x09: ++ case value == 0x0A: ++ case value == 0x0D: ++ case value >= 0x20 && value <= 0x7E: ++ case value == 0x85: ++ case value >= 0xA0 && value <= 0xD7FF: ++ case value >= 0xE000 && value <= 0xFFFD: ++ case value >= 0x10000 && value <= 0x10FFFF: ++ default: ++ return yaml_parser_set_reader_error(parser, ++ "control characters are not allowed", ++ parser.offset, int(value)) ++ } ++ ++ // Move the raw pointers. ++ parser.raw_buffer_pos += width ++ parser.offset += width ++ ++ // Finally put the character into the buffer. ++ if value <= 0x7F { ++ // 0000 0000-0000 007F . 0xxxxxxx ++ parser.buffer[buffer_len+0] = byte(value) ++ buffer_len += 1 ++ } else if value <= 0x7FF { ++ // 0000 0080-0000 07FF . 110xxxxx 10xxxxxx ++ parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6)) ++ parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F)) ++ buffer_len += 2 ++ } else if value <= 0xFFFF { ++ // 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx ++ parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12)) ++ parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F)) ++ parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F)) ++ buffer_len += 3 ++ } else { ++ // 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx ++ parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18)) ++ parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F)) ++ parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F)) ++ parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F)) ++ buffer_len += 4 ++ } ++ ++ parser.unread++ ++ } ++ ++ // On EOF, put NUL into the buffer and return. ++ if parser.eof { ++ parser.buffer[buffer_len] = 0 ++ buffer_len++ ++ parser.unread++ ++ break ++ } ++ } ++ // [Go] Read the documentation of this function above. To return true, ++ // we need to have the given length in the buffer. Not doing that means ++ // every single check that calls this function to make sure the buffer ++ // has a given length is Go) panicking; or C) accessing invalid memory. ++ // This happens here due to the EOF above breaking early. ++ for buffer_len < length { ++ parser.buffer[buffer_len] = 0 ++ buffer_len++ ++ } ++ parser.buffer = parser.buffer[:buffer_len] ++ return true ++} +diff --git a/vendor/gopkg.in/yaml.v3/resolve.go b/vendor/gopkg.in/yaml.v3/resolve.go +new file mode 100644 +index 000000000000..64ae888057a5 +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/resolve.go +@@ -0,0 +1,326 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// ++// 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 yaml ++ ++import ( ++ "encoding/base64" ++ "math" ++ "regexp" ++ "strconv" ++ "strings" ++ "time" ++) ++ ++type resolveMapItem struct { ++ value interface{} ++ tag string ++} ++ ++var resolveTable = make([]byte, 256) ++var resolveMap = make(map[string]resolveMapItem) ++ ++func init() { ++ t := resolveTable ++ t[int('+')] = 'S' // Sign ++ t[int('-')] = 'S' ++ for _, c := range "0123456789" { ++ t[int(c)] = 'D' // Digit ++ } ++ for _, c := range "yYnNtTfFoO~" { ++ t[int(c)] = 'M' // In map ++ } ++ t[int('.')] = '.' // Float (potentially in map) ++ ++ var resolveMapList = []struct { ++ v interface{} ++ tag string ++ l []string ++ }{ ++ {true, boolTag, []string{"true", "True", "TRUE"}}, ++ {false, boolTag, []string{"false", "False", "FALSE"}}, ++ {nil, nullTag, []string{"", "~", "null", "Null", "NULL"}}, ++ {math.NaN(), floatTag, []string{".nan", ".NaN", ".NAN"}}, ++ {math.Inf(+1), floatTag, []string{".inf", ".Inf", ".INF"}}, ++ {math.Inf(+1), floatTag, []string{"+.inf", "+.Inf", "+.INF"}}, ++ {math.Inf(-1), floatTag, []string{"-.inf", "-.Inf", "-.INF"}}, ++ {"<<", mergeTag, []string{"<<"}}, ++ } ++ ++ m := resolveMap ++ for _, item := range resolveMapList { ++ for _, s := range item.l { ++ m[s] = resolveMapItem{item.v, item.tag} ++ } ++ } ++} ++ ++const ( ++ nullTag = "!!null" ++ boolTag = "!!bool" ++ strTag = "!!str" ++ intTag = "!!int" ++ floatTag = "!!float" ++ timestampTag = "!!timestamp" ++ seqTag = "!!seq" ++ mapTag = "!!map" ++ binaryTag = "!!binary" ++ mergeTag = "!!merge" ++) ++ ++var longTags = make(map[string]string) ++var shortTags = make(map[string]string) ++ ++func init() { ++ for _, stag := range []string{nullTag, boolTag, strTag, intTag, floatTag, timestampTag, seqTag, mapTag, binaryTag, mergeTag} { ++ ltag := longTag(stag) ++ longTags[stag] = ltag ++ shortTags[ltag] = stag ++ } ++} ++ ++const longTagPrefix = "tag:yaml.org,2002:" ++ ++func shortTag(tag string) string { ++ if strings.HasPrefix(tag, longTagPrefix) { ++ if stag, ok := shortTags[tag]; ok { ++ return stag ++ } ++ return "!!" + tag[len(longTagPrefix):] ++ } ++ return tag ++} ++ ++func longTag(tag string) string { ++ if strings.HasPrefix(tag, "!!") { ++ if ltag, ok := longTags[tag]; ok { ++ return ltag ++ } ++ return longTagPrefix + tag[2:] ++ } ++ return tag ++} ++ ++func resolvableTag(tag string) bool { ++ switch tag { ++ case "", strTag, boolTag, intTag, floatTag, nullTag, timestampTag: ++ return true ++ } ++ return false ++} ++ ++var yamlStyleFloat = regexp.MustCompile(`^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$`) ++ ++func resolve(tag string, in string) (rtag string, out interface{}) { ++ tag = shortTag(tag) ++ if !resolvableTag(tag) { ++ return tag, in ++ } ++ ++ defer func() { ++ switch tag { ++ case "", rtag, strTag, binaryTag: ++ return ++ case floatTag: ++ if rtag == intTag { ++ switch v := out.(type) { ++ case int64: ++ rtag = floatTag ++ out = float64(v) ++ return ++ case int: ++ rtag = floatTag ++ out = float64(v) ++ return ++ } ++ } ++ } ++ failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag)) ++ }() ++ ++ // Any data is accepted as a !!str or !!binary. ++ // Otherwise, the prefix is enough of a hint about what it might be. ++ hint := byte('N') ++ if in != "" { ++ hint = resolveTable[in[0]] ++ } ++ if hint != 0 && tag != strTag && tag != binaryTag { ++ // Handle things we can lookup in a map. ++ if item, ok := resolveMap[in]; ok { ++ return item.tag, item.value ++ } ++ ++ // Base 60 floats are a bad idea, were dropped in YAML 1.2, and ++ // are purposefully unsupported here. They're still quoted on ++ // the way out for compatibility with other parser, though. ++ ++ switch hint { ++ case 'M': ++ // We've already checked the map above. ++ ++ case '.': ++ // Not in the map, so maybe a normal float. ++ floatv, err := strconv.ParseFloat(in, 64) ++ if err == nil { ++ return floatTag, floatv ++ } ++ ++ case 'D', 'S': ++ // Int, float, or timestamp. ++ // Only try values as a timestamp if the value is unquoted or there's an explicit ++ // !!timestamp tag. ++ if tag == "" || tag == timestampTag { ++ t, ok := parseTimestamp(in) ++ if ok { ++ return timestampTag, t ++ } ++ } ++ ++ plain := strings.Replace(in, "_", "", -1) ++ intv, err := strconv.ParseInt(plain, 0, 64) ++ if err == nil { ++ if intv == int64(int(intv)) { ++ return intTag, int(intv) ++ } else { ++ return intTag, intv ++ } ++ } ++ uintv, err := strconv.ParseUint(plain, 0, 64) ++ if err == nil { ++ return intTag, uintv ++ } ++ if yamlStyleFloat.MatchString(plain) { ++ floatv, err := strconv.ParseFloat(plain, 64) ++ if err == nil { ++ return floatTag, floatv ++ } ++ } ++ if strings.HasPrefix(plain, "0b") { ++ intv, err := strconv.ParseInt(plain[2:], 2, 64) ++ if err == nil { ++ if intv == int64(int(intv)) { ++ return intTag, int(intv) ++ } else { ++ return intTag, intv ++ } ++ } ++ uintv, err := strconv.ParseUint(plain[2:], 2, 64) ++ if err == nil { ++ return intTag, uintv ++ } ++ } else if strings.HasPrefix(plain, "-0b") { ++ intv, err := strconv.ParseInt("-"+plain[3:], 2, 64) ++ if err == nil { ++ if true || intv == int64(int(intv)) { ++ return intTag, int(intv) ++ } else { ++ return intTag, intv ++ } ++ } ++ } ++ // Octals as introduced in version 1.2 of the spec. ++ // Octals from the 1.1 spec, spelled as 0777, are still ++ // decoded by default in v3 as well for compatibility. ++ // May be dropped in v4 depending on how usage evolves. ++ if strings.HasPrefix(plain, "0o") { ++ intv, err := strconv.ParseInt(plain[2:], 8, 64) ++ if err == nil { ++ if intv == int64(int(intv)) { ++ return intTag, int(intv) ++ } else { ++ return intTag, intv ++ } ++ } ++ uintv, err := strconv.ParseUint(plain[2:], 8, 64) ++ if err == nil { ++ return intTag, uintv ++ } ++ } else if strings.HasPrefix(plain, "-0o") { ++ intv, err := strconv.ParseInt("-"+plain[3:], 8, 64) ++ if err == nil { ++ if true || intv == int64(int(intv)) { ++ return intTag, int(intv) ++ } else { ++ return intTag, intv ++ } ++ } ++ } ++ default: ++ panic("internal error: missing handler for resolver table: " + string(rune(hint)) + " (with " + in + ")") ++ } ++ } ++ return strTag, in ++} ++ ++// encodeBase64 encodes s as base64 that is broken up into multiple lines ++// as appropriate for the resulting length. ++func encodeBase64(s string) string { ++ const lineLen = 70 ++ encLen := base64.StdEncoding.EncodedLen(len(s)) ++ lines := encLen/lineLen + 1 ++ buf := make([]byte, encLen*2+lines) ++ in := buf[0:encLen] ++ out := buf[encLen:] ++ base64.StdEncoding.Encode(in, []byte(s)) ++ k := 0 ++ for i := 0; i < len(in); i += lineLen { ++ j := i + lineLen ++ if j > len(in) { ++ j = len(in) ++ } ++ k += copy(out[k:], in[i:j]) ++ if lines > 1 { ++ out[k] = '\n' ++ k++ ++ } ++ } ++ return string(out[:k]) ++} ++ ++// This is a subset of the formats allowed by the regular expression ++// defined at http://yaml.org/type/timestamp.html. ++var allowedTimestampFormats = []string{ ++ "2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields. ++ "2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t". ++ "2006-1-2 15:4:5.999999999", // space separated with no time zone ++ "2006-1-2", // date only ++ // Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5" ++ // from the set of examples. ++} ++ ++// parseTimestamp parses s as a timestamp string and ++// returns the timestamp and reports whether it succeeded. ++// Timestamp formats are defined at http://yaml.org/type/timestamp.html ++func parseTimestamp(s string) (time.Time, bool) { ++ // TODO write code to check all the formats supported by ++ // http://yaml.org/type/timestamp.html instead of using time.Parse. ++ ++ // Quick check: all date formats start with YYYY-. ++ i := 0 ++ for ; i < len(s); i++ { ++ if c := s[i]; c < '0' || c > '9' { ++ break ++ } ++ } ++ if i != 4 || i == len(s) || s[i] != '-' { ++ return time.Time{}, false ++ } ++ for _, format := range allowedTimestampFormats { ++ if t, err := time.Parse(format, s); err == nil { ++ return t, true ++ } ++ } ++ return time.Time{}, false ++} +diff --git a/vendor/gopkg.in/yaml.v3/scannerc.go b/vendor/gopkg.in/yaml.v3/scannerc.go +new file mode 100644 +index 000000000000..ca0070108f4e +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/scannerc.go +@@ -0,0 +1,3038 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// Copyright (c) 2006-2010 Kirill Simonov ++// ++// 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. ++ ++package yaml ++ ++import ( ++ "bytes" ++ "fmt" ++) ++ ++// Introduction ++// ************ ++// ++// The following notes assume that you are familiar with the YAML specification ++// (http://yaml.org/spec/1.2/spec.html). We mostly follow it, although in ++// some cases we are less restrictive that it requires. ++// ++// The process of transforming a YAML stream into a sequence of events is ++// divided on two steps: Scanning and Parsing. ++// ++// The Scanner transforms the input stream into a sequence of tokens, while the ++// parser transform the sequence of tokens produced by the Scanner into a ++// sequence of parsing events. ++// ++// The Scanner is rather clever and complicated. The Parser, on the contrary, ++// is a straightforward implementation of a recursive-descendant parser (or, ++// LL(1) parser, as it is usually called). ++// ++// Actually there are two issues of Scanning that might be called "clever", the ++// rest is quite straightforward. The issues are "block collection start" and ++// "simple keys". Both issues are explained below in details. ++// ++// Here the Scanning step is explained and implemented. We start with the list ++// of all the tokens produced by the Scanner together with short descriptions. ++// ++// Now, tokens: ++// ++// STREAM-START(encoding) # The stream start. ++// STREAM-END # The stream end. ++// VERSION-DIRECTIVE(major,minor) # The '%YAML' directive. ++// TAG-DIRECTIVE(handle,prefix) # The '%TAG' directive. ++// DOCUMENT-START # '---' ++// DOCUMENT-END # '...' ++// BLOCK-SEQUENCE-START # Indentation increase denoting a block ++// BLOCK-MAPPING-START # sequence or a block mapping. ++// BLOCK-END # Indentation decrease. ++// FLOW-SEQUENCE-START # '[' ++// FLOW-SEQUENCE-END # ']' ++// BLOCK-SEQUENCE-START # '{' ++// BLOCK-SEQUENCE-END # '}' ++// BLOCK-ENTRY # '-' ++// FLOW-ENTRY # ',' ++// KEY # '?' or nothing (simple keys). ++// VALUE # ':' ++// ALIAS(anchor) # '*anchor' ++// ANCHOR(anchor) # '&anchor' ++// TAG(handle,suffix) # '!handle!suffix' ++// SCALAR(value,style) # A scalar. ++// ++// The following two tokens are "virtual" tokens denoting the beginning and the ++// end of the stream: ++// ++// STREAM-START(encoding) ++// STREAM-END ++// ++// We pass the information about the input stream encoding with the ++// STREAM-START token. ++// ++// The next two tokens are responsible for tags: ++// ++// VERSION-DIRECTIVE(major,minor) ++// TAG-DIRECTIVE(handle,prefix) ++// ++// Example: ++// ++// %YAML 1.1 ++// %TAG ! !foo ++// %TAG !yaml! tag:yaml.org,2002: ++// --- ++// ++// The correspoding sequence of tokens: ++// ++// STREAM-START(utf-8) ++// VERSION-DIRECTIVE(1,1) ++// TAG-DIRECTIVE("!","!foo") ++// TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:") ++// DOCUMENT-START ++// STREAM-END ++// ++// Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole ++// line. ++// ++// The document start and end indicators are represented by: ++// ++// DOCUMENT-START ++// DOCUMENT-END ++// ++// Note that if a YAML stream contains an implicit document (without '---' ++// and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be ++// produced. ++// ++// In the following examples, we present whole documents together with the ++// produced tokens. ++// ++// 1. An implicit document: ++// ++// 'a scalar' ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// SCALAR("a scalar",single-quoted) ++// STREAM-END ++// ++// 2. An explicit document: ++// ++// --- ++// 'a scalar' ++// ... ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// DOCUMENT-START ++// SCALAR("a scalar",single-quoted) ++// DOCUMENT-END ++// STREAM-END ++// ++// 3. Several documents in a stream: ++// ++// 'a scalar' ++// --- ++// 'another scalar' ++// --- ++// 'yet another scalar' ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// SCALAR("a scalar",single-quoted) ++// DOCUMENT-START ++// SCALAR("another scalar",single-quoted) ++// DOCUMENT-START ++// SCALAR("yet another scalar",single-quoted) ++// STREAM-END ++// ++// We have already introduced the SCALAR token above. The following tokens are ++// used to describe aliases, anchors, tag, and scalars: ++// ++// ALIAS(anchor) ++// ANCHOR(anchor) ++// TAG(handle,suffix) ++// SCALAR(value,style) ++// ++// The following series of examples illustrate the usage of these tokens: ++// ++// 1. A recursive sequence: ++// ++// &A [ *A ] ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// ANCHOR("A") ++// FLOW-SEQUENCE-START ++// ALIAS("A") ++// FLOW-SEQUENCE-END ++// STREAM-END ++// ++// 2. A tagged scalar: ++// ++// !!float "3.14" # A good approximation. ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// TAG("!!","float") ++// SCALAR("3.14",double-quoted) ++// STREAM-END ++// ++// 3. Various scalar styles: ++// ++// --- # Implicit empty plain scalars do not produce tokens. ++// --- a plain scalar ++// --- 'a single-quoted scalar' ++// --- "a double-quoted scalar" ++// --- |- ++// a literal scalar ++// --- >- ++// a folded ++// scalar ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// DOCUMENT-START ++// DOCUMENT-START ++// SCALAR("a plain scalar",plain) ++// DOCUMENT-START ++// SCALAR("a single-quoted scalar",single-quoted) ++// DOCUMENT-START ++// SCALAR("a double-quoted scalar",double-quoted) ++// DOCUMENT-START ++// SCALAR("a literal scalar",literal) ++// DOCUMENT-START ++// SCALAR("a folded scalar",folded) ++// STREAM-END ++// ++// Now it's time to review collection-related tokens. We will start with ++// flow collections: ++// ++// FLOW-SEQUENCE-START ++// FLOW-SEQUENCE-END ++// FLOW-MAPPING-START ++// FLOW-MAPPING-END ++// FLOW-ENTRY ++// KEY ++// VALUE ++// ++// The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and ++// FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}' ++// correspondingly. FLOW-ENTRY represent the ',' indicator. Finally the ++// indicators '?' and ':', which are used for denoting mapping keys and values, ++// are represented by the KEY and VALUE tokens. ++// ++// The following examples show flow collections: ++// ++// 1. A flow sequence: ++// ++// [item 1, item 2, item 3] ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// FLOW-SEQUENCE-START ++// SCALAR("item 1",plain) ++// FLOW-ENTRY ++// SCALAR("item 2",plain) ++// FLOW-ENTRY ++// SCALAR("item 3",plain) ++// FLOW-SEQUENCE-END ++// STREAM-END ++// ++// 2. A flow mapping: ++// ++// { ++// a simple key: a value, # Note that the KEY token is produced. ++// ? a complex key: another value, ++// } ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// FLOW-MAPPING-START ++// KEY ++// SCALAR("a simple key",plain) ++// VALUE ++// SCALAR("a value",plain) ++// FLOW-ENTRY ++// KEY ++// SCALAR("a complex key",plain) ++// VALUE ++// SCALAR("another value",plain) ++// FLOW-ENTRY ++// FLOW-MAPPING-END ++// STREAM-END ++// ++// A simple key is a key which is not denoted by the '?' indicator. Note that ++// the Scanner still produce the KEY token whenever it encounters a simple key. ++// ++// For scanning block collections, the following tokens are used (note that we ++// repeat KEY and VALUE here): ++// ++// BLOCK-SEQUENCE-START ++// BLOCK-MAPPING-START ++// BLOCK-END ++// BLOCK-ENTRY ++// KEY ++// VALUE ++// ++// The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation ++// increase that precedes a block collection (cf. the INDENT token in Python). ++// The token BLOCK-END denote indentation decrease that ends a block collection ++// (cf. the DEDENT token in Python). However YAML has some syntax pecularities ++// that makes detections of these tokens more complex. ++// ++// The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators ++// '-', '?', and ':' correspondingly. ++// ++// The following examples show how the tokens BLOCK-SEQUENCE-START, ++// BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner: ++// ++// 1. Block sequences: ++// ++// - item 1 ++// - item 2 ++// - ++// - item 3.1 ++// - item 3.2 ++// - ++// key 1: value 1 ++// key 2: value 2 ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// BLOCK-SEQUENCE-START ++// BLOCK-ENTRY ++// SCALAR("item 1",plain) ++// BLOCK-ENTRY ++// SCALAR("item 2",plain) ++// BLOCK-ENTRY ++// BLOCK-SEQUENCE-START ++// BLOCK-ENTRY ++// SCALAR("item 3.1",plain) ++// BLOCK-ENTRY ++// SCALAR("item 3.2",plain) ++// BLOCK-END ++// BLOCK-ENTRY ++// BLOCK-MAPPING-START ++// KEY ++// SCALAR("key 1",plain) ++// VALUE ++// SCALAR("value 1",plain) ++// KEY ++// SCALAR("key 2",plain) ++// VALUE ++// SCALAR("value 2",plain) ++// BLOCK-END ++// BLOCK-END ++// STREAM-END ++// ++// 2. Block mappings: ++// ++// a simple key: a value # The KEY token is produced here. ++// ? a complex key ++// : another value ++// a mapping: ++// key 1: value 1 ++// key 2: value 2 ++// a sequence: ++// - item 1 ++// - item 2 ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// BLOCK-MAPPING-START ++// KEY ++// SCALAR("a simple key",plain) ++// VALUE ++// SCALAR("a value",plain) ++// KEY ++// SCALAR("a complex key",plain) ++// VALUE ++// SCALAR("another value",plain) ++// KEY ++// SCALAR("a mapping",plain) ++// BLOCK-MAPPING-START ++// KEY ++// SCALAR("key 1",plain) ++// VALUE ++// SCALAR("value 1",plain) ++// KEY ++// SCALAR("key 2",plain) ++// VALUE ++// SCALAR("value 2",plain) ++// BLOCK-END ++// KEY ++// SCALAR("a sequence",plain) ++// VALUE ++// BLOCK-SEQUENCE-START ++// BLOCK-ENTRY ++// SCALAR("item 1",plain) ++// BLOCK-ENTRY ++// SCALAR("item 2",plain) ++// BLOCK-END ++// BLOCK-END ++// STREAM-END ++// ++// YAML does not always require to start a new block collection from a new ++// line. If the current line contains only '-', '?', and ':' indicators, a new ++// block collection may start at the current line. The following examples ++// illustrate this case: ++// ++// 1. Collections in a sequence: ++// ++// - - item 1 ++// - item 2 ++// - key 1: value 1 ++// key 2: value 2 ++// - ? complex key ++// : complex value ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// BLOCK-SEQUENCE-START ++// BLOCK-ENTRY ++// BLOCK-SEQUENCE-START ++// BLOCK-ENTRY ++// SCALAR("item 1",plain) ++// BLOCK-ENTRY ++// SCALAR("item 2",plain) ++// BLOCK-END ++// BLOCK-ENTRY ++// BLOCK-MAPPING-START ++// KEY ++// SCALAR("key 1",plain) ++// VALUE ++// SCALAR("value 1",plain) ++// KEY ++// SCALAR("key 2",plain) ++// VALUE ++// SCALAR("value 2",plain) ++// BLOCK-END ++// BLOCK-ENTRY ++// BLOCK-MAPPING-START ++// KEY ++// SCALAR("complex key") ++// VALUE ++// SCALAR("complex value") ++// BLOCK-END ++// BLOCK-END ++// STREAM-END ++// ++// 2. Collections in a mapping: ++// ++// ? a sequence ++// : - item 1 ++// - item 2 ++// ? a mapping ++// : key 1: value 1 ++// key 2: value 2 ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// BLOCK-MAPPING-START ++// KEY ++// SCALAR("a sequence",plain) ++// VALUE ++// BLOCK-SEQUENCE-START ++// BLOCK-ENTRY ++// SCALAR("item 1",plain) ++// BLOCK-ENTRY ++// SCALAR("item 2",plain) ++// BLOCK-END ++// KEY ++// SCALAR("a mapping",plain) ++// VALUE ++// BLOCK-MAPPING-START ++// KEY ++// SCALAR("key 1",plain) ++// VALUE ++// SCALAR("value 1",plain) ++// KEY ++// SCALAR("key 2",plain) ++// VALUE ++// SCALAR("value 2",plain) ++// BLOCK-END ++// BLOCK-END ++// STREAM-END ++// ++// YAML also permits non-indented sequences if they are included into a block ++// mapping. In this case, the token BLOCK-SEQUENCE-START is not produced: ++// ++// key: ++// - item 1 # BLOCK-SEQUENCE-START is NOT produced here. ++// - item 2 ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// BLOCK-MAPPING-START ++// KEY ++// SCALAR("key",plain) ++// VALUE ++// BLOCK-ENTRY ++// SCALAR("item 1",plain) ++// BLOCK-ENTRY ++// SCALAR("item 2",plain) ++// BLOCK-END ++// ++ ++// Ensure that the buffer contains the required number of characters. ++// Return true on success, false on failure (reader error or memory error). ++func cache(parser *yaml_parser_t, length int) bool { ++ // [Go] This was inlined: !cache(A, B) -> unread < B && !update(A, B) ++ return parser.unread >= length || yaml_parser_update_buffer(parser, length) ++} ++ ++// Advance the buffer pointer. ++func skip(parser *yaml_parser_t) { ++ if !is_blank(parser.buffer, parser.buffer_pos) { ++ parser.newlines = 0 ++ } ++ parser.mark.index++ ++ parser.mark.column++ ++ parser.unread-- ++ parser.buffer_pos += width(parser.buffer[parser.buffer_pos]) ++} ++ ++func skip_line(parser *yaml_parser_t) { ++ if is_crlf(parser.buffer, parser.buffer_pos) { ++ parser.mark.index += 2 ++ parser.mark.column = 0 ++ parser.mark.line++ ++ parser.unread -= 2 ++ parser.buffer_pos += 2 ++ parser.newlines++ ++ } else if is_break(parser.buffer, parser.buffer_pos) { ++ parser.mark.index++ ++ parser.mark.column = 0 ++ parser.mark.line++ ++ parser.unread-- ++ parser.buffer_pos += width(parser.buffer[parser.buffer_pos]) ++ parser.newlines++ ++ } ++} ++ ++// Copy a character to a string buffer and advance pointers. ++func read(parser *yaml_parser_t, s []byte) []byte { ++ if !is_blank(parser.buffer, parser.buffer_pos) { ++ parser.newlines = 0 ++ } ++ w := width(parser.buffer[parser.buffer_pos]) ++ if w == 0 { ++ panic("invalid character sequence") ++ } ++ if len(s) == 0 { ++ s = make([]byte, 0, 32) ++ } ++ if w == 1 && len(s)+w <= cap(s) { ++ s = s[:len(s)+1] ++ s[len(s)-1] = parser.buffer[parser.buffer_pos] ++ parser.buffer_pos++ ++ } else { ++ s = append(s, parser.buffer[parser.buffer_pos:parser.buffer_pos+w]...) ++ parser.buffer_pos += w ++ } ++ parser.mark.index++ ++ parser.mark.column++ ++ parser.unread-- ++ return s ++} ++ ++// Copy a line break character to a string buffer and advance pointers. ++func read_line(parser *yaml_parser_t, s []byte) []byte { ++ buf := parser.buffer ++ pos := parser.buffer_pos ++ switch { ++ case buf[pos] == '\r' && buf[pos+1] == '\n': ++ // CR LF . LF ++ s = append(s, '\n') ++ parser.buffer_pos += 2 ++ parser.mark.index++ ++ parser.unread-- ++ case buf[pos] == '\r' || buf[pos] == '\n': ++ // CR|LF . LF ++ s = append(s, '\n') ++ parser.buffer_pos += 1 ++ case buf[pos] == '\xC2' && buf[pos+1] == '\x85': ++ // NEL . LF ++ s = append(s, '\n') ++ parser.buffer_pos += 2 ++ case buf[pos] == '\xE2' && buf[pos+1] == '\x80' && (buf[pos+2] == '\xA8' || buf[pos+2] == '\xA9'): ++ // LS|PS . LS|PS ++ s = append(s, buf[parser.buffer_pos:pos+3]...) ++ parser.buffer_pos += 3 ++ default: ++ return s ++ } ++ parser.mark.index++ ++ parser.mark.column = 0 ++ parser.mark.line++ ++ parser.unread-- ++ parser.newlines++ ++ return s ++} ++ ++// Get the next token. ++func yaml_parser_scan(parser *yaml_parser_t, token *yaml_token_t) bool { ++ // Erase the token object. ++ *token = yaml_token_t{} // [Go] Is this necessary? ++ ++ // No tokens after STREAM-END or error. ++ if parser.stream_end_produced || parser.error != yaml_NO_ERROR { ++ return true ++ } ++ ++ // Ensure that the tokens queue contains enough tokens. ++ if !parser.token_available { ++ if !yaml_parser_fetch_more_tokens(parser) { ++ return false ++ } ++ } ++ ++ // Fetch the next token from the queue. ++ *token = parser.tokens[parser.tokens_head] ++ parser.tokens_head++ ++ parser.tokens_parsed++ ++ parser.token_available = false ++ ++ if token.typ == yaml_STREAM_END_TOKEN { ++ parser.stream_end_produced = true ++ } ++ return true ++} ++ ++// Set the scanner error and return false. ++func yaml_parser_set_scanner_error(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string) bool { ++ parser.error = yaml_SCANNER_ERROR ++ parser.context = context ++ parser.context_mark = context_mark ++ parser.problem = problem ++ parser.problem_mark = parser.mark ++ return false ++} ++ ++func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive bool, context_mark yaml_mark_t, problem string) bool { ++ context := "while parsing a tag" ++ if directive { ++ context = "while parsing a %TAG directive" ++ } ++ return yaml_parser_set_scanner_error(parser, context, context_mark, problem) ++} ++ ++func trace(args ...interface{}) func() { ++ pargs := append([]interface{}{"+++"}, args...) ++ fmt.Println(pargs...) ++ pargs = append([]interface{}{"---"}, args...) ++ return func() { fmt.Println(pargs...) } ++} ++ ++// Ensure that the tokens queue contains at least one token which can be ++// returned to the Parser. ++func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool { ++ // While we need more tokens to fetch, do it. ++ for { ++ // [Go] The comment parsing logic requires a lookahead of two tokens ++ // so that foot comments may be parsed in time of associating them ++ // with the tokens that are parsed before them, and also for line ++ // comments to be transformed into head comments in some edge cases. ++ if parser.tokens_head < len(parser.tokens)-2 { ++ // If a potential simple key is at the head position, we need to fetch ++ // the next token to disambiguate it. ++ head_tok_idx, ok := parser.simple_keys_by_tok[parser.tokens_parsed] ++ if !ok { ++ break ++ } else if valid, ok := yaml_simple_key_is_valid(parser, &parser.simple_keys[head_tok_idx]); !ok { ++ return false ++ } else if !valid { ++ break ++ } ++ } ++ // Fetch the next token. ++ if !yaml_parser_fetch_next_token(parser) { ++ return false ++ } ++ } ++ ++ parser.token_available = true ++ return true ++} ++ ++// The dispatcher for token fetchers. ++func yaml_parser_fetch_next_token(parser *yaml_parser_t) (ok bool) { ++ // Ensure that the buffer is initialized. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ ++ // Check if we just started scanning. Fetch STREAM-START then. ++ if !parser.stream_start_produced { ++ return yaml_parser_fetch_stream_start(parser) ++ } ++ ++ scan_mark := parser.mark ++ ++ // Eat whitespaces and comments until we reach the next token. ++ if !yaml_parser_scan_to_next_token(parser) { ++ return false ++ } ++ ++ // [Go] While unrolling indents, transform the head comments of prior ++ // indentation levels observed after scan_start into foot comments at ++ // the respective indexes. ++ ++ // Check the indentation level against the current column. ++ if !yaml_parser_unroll_indent(parser, parser.mark.column, scan_mark) { ++ return false ++ } ++ ++ // Ensure that the buffer contains at least 4 characters. 4 is the length ++ // of the longest indicators ('--- ' and '... '). ++ if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { ++ return false ++ } ++ ++ // Is it the end of the stream? ++ if is_z(parser.buffer, parser.buffer_pos) { ++ return yaml_parser_fetch_stream_end(parser) ++ } ++ ++ // Is it a directive? ++ if parser.mark.column == 0 && parser.buffer[parser.buffer_pos] == '%' { ++ return yaml_parser_fetch_directive(parser) ++ } ++ ++ buf := parser.buffer ++ pos := parser.buffer_pos ++ ++ // Is it the document start indicator? ++ if parser.mark.column == 0 && buf[pos] == '-' && buf[pos+1] == '-' && buf[pos+2] == '-' && is_blankz(buf, pos+3) { ++ return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_START_TOKEN) ++ } ++ ++ // Is it the document end indicator? ++ if parser.mark.column == 0 && buf[pos] == '.' && buf[pos+1] == '.' && buf[pos+2] == '.' && is_blankz(buf, pos+3) { ++ return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_END_TOKEN) ++ } ++ ++ comment_mark := parser.mark ++ if len(parser.tokens) > 0 && (parser.flow_level == 0 && buf[pos] == ':' || parser.flow_level > 0 && buf[pos] == ',') { ++ // Associate any following comments with the prior token. ++ comment_mark = parser.tokens[len(parser.tokens)-1].start_mark ++ } ++ defer func() { ++ if !ok { ++ return ++ } ++ if len(parser.tokens) > 0 && parser.tokens[len(parser.tokens)-1].typ == yaml_BLOCK_ENTRY_TOKEN { ++ // Sequence indicators alone have no line comments. It becomes ++ // a head comment for whatever follows. ++ return ++ } ++ if !yaml_parser_scan_line_comment(parser, comment_mark) { ++ ok = false ++ return ++ } ++ }() ++ ++ // Is it the flow sequence start indicator? ++ if buf[pos] == '[' { ++ return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_SEQUENCE_START_TOKEN) ++ } ++ ++ // Is it the flow mapping start indicator? ++ if parser.buffer[parser.buffer_pos] == '{' { ++ return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_MAPPING_START_TOKEN) ++ } ++ ++ // Is it the flow sequence end indicator? ++ if parser.buffer[parser.buffer_pos] == ']' { ++ return yaml_parser_fetch_flow_collection_end(parser, ++ yaml_FLOW_SEQUENCE_END_TOKEN) ++ } ++ ++ // Is it the flow mapping end indicator? ++ if parser.buffer[parser.buffer_pos] == '}' { ++ return yaml_parser_fetch_flow_collection_end(parser, ++ yaml_FLOW_MAPPING_END_TOKEN) ++ } ++ ++ // Is it the flow entry indicator? ++ if parser.buffer[parser.buffer_pos] == ',' { ++ return yaml_parser_fetch_flow_entry(parser) ++ } ++ ++ // Is it the block entry indicator? ++ if parser.buffer[parser.buffer_pos] == '-' && is_blankz(parser.buffer, parser.buffer_pos+1) { ++ return yaml_parser_fetch_block_entry(parser) ++ } ++ ++ // Is it the key indicator? ++ if parser.buffer[parser.buffer_pos] == '?' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) { ++ return yaml_parser_fetch_key(parser) ++ } ++ ++ // Is it the value indicator? ++ if parser.buffer[parser.buffer_pos] == ':' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) { ++ return yaml_parser_fetch_value(parser) ++ } ++ ++ // Is it an alias? ++ if parser.buffer[parser.buffer_pos] == '*' { ++ return yaml_parser_fetch_anchor(parser, yaml_ALIAS_TOKEN) ++ } ++ ++ // Is it an anchor? ++ if parser.buffer[parser.buffer_pos] == '&' { ++ return yaml_parser_fetch_anchor(parser, yaml_ANCHOR_TOKEN) ++ } ++ ++ // Is it a tag? ++ if parser.buffer[parser.buffer_pos] == '!' { ++ return yaml_parser_fetch_tag(parser) ++ } ++ ++ // Is it a literal scalar? ++ if parser.buffer[parser.buffer_pos] == '|' && parser.flow_level == 0 { ++ return yaml_parser_fetch_block_scalar(parser, true) ++ } ++ ++ // Is it a folded scalar? ++ if parser.buffer[parser.buffer_pos] == '>' && parser.flow_level == 0 { ++ return yaml_parser_fetch_block_scalar(parser, false) ++ } ++ ++ // Is it a single-quoted scalar? ++ if parser.buffer[parser.buffer_pos] == '\'' { ++ return yaml_parser_fetch_flow_scalar(parser, true) ++ } ++ ++ // Is it a double-quoted scalar? ++ if parser.buffer[parser.buffer_pos] == '"' { ++ return yaml_parser_fetch_flow_scalar(parser, false) ++ } ++ ++ // Is it a plain scalar? ++ // ++ // A plain scalar may start with any non-blank characters except ++ // ++ // '-', '?', ':', ',', '[', ']', '{', '}', ++ // '#', '&', '*', '!', '|', '>', '\'', '\"', ++ // '%', '@', '`'. ++ // ++ // In the block context (and, for the '-' indicator, in the flow context ++ // too), it may also start with the characters ++ // ++ // '-', '?', ':' ++ // ++ // if it is followed by a non-space character. ++ // ++ // The last rule is more restrictive than the specification requires. ++ // [Go] TODO Make this logic more reasonable. ++ //switch parser.buffer[parser.buffer_pos] { ++ //case '-', '?', ':', ',', '?', '-', ',', ':', ']', '[', '}', '{', '&', '#', '!', '*', '>', '|', '"', '\'', '@', '%', '-', '`': ++ //} ++ if !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '-' || ++ parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':' || ++ parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '[' || ++ parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' || ++ parser.buffer[parser.buffer_pos] == '}' || parser.buffer[parser.buffer_pos] == '#' || ++ parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '*' || ++ parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '|' || ++ parser.buffer[parser.buffer_pos] == '>' || parser.buffer[parser.buffer_pos] == '\'' || ++ parser.buffer[parser.buffer_pos] == '"' || parser.buffer[parser.buffer_pos] == '%' || ++ parser.buffer[parser.buffer_pos] == '@' || parser.buffer[parser.buffer_pos] == '`') || ++ (parser.buffer[parser.buffer_pos] == '-' && !is_blank(parser.buffer, parser.buffer_pos+1)) || ++ (parser.flow_level == 0 && ++ (parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':') && ++ !is_blankz(parser.buffer, parser.buffer_pos+1)) { ++ return yaml_parser_fetch_plain_scalar(parser) ++ } ++ ++ // If we don't determine the token type so far, it is an error. ++ return yaml_parser_set_scanner_error(parser, ++ "while scanning for the next token", parser.mark, ++ "found character that cannot start any token") ++} ++ ++func yaml_simple_key_is_valid(parser *yaml_parser_t, simple_key *yaml_simple_key_t) (valid, ok bool) { ++ if !simple_key.possible { ++ return false, true ++ } ++ ++ // The 1.2 specification says: ++ // ++ // "If the ? indicator is omitted, parsing needs to see past the ++ // implicit key to recognize it as such. To limit the amount of ++ // lookahead required, the “:” indicator must appear at most 1024 ++ // Unicode characters beyond the start of the key. In addition, the key ++ // is restricted to a single line." ++ // ++ if simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index { ++ // Check if the potential simple key to be removed is required. ++ if simple_key.required { ++ return false, yaml_parser_set_scanner_error(parser, ++ "while scanning a simple key", simple_key.mark, ++ "could not find expected ':'") ++ } ++ simple_key.possible = false ++ return false, true ++ } ++ return true, true ++} ++ ++// Check if a simple key may start at the current position and add it if ++// needed. ++func yaml_parser_save_simple_key(parser *yaml_parser_t) bool { ++ // A simple key is required at the current position if the scanner is in ++ // the block context and the current column coincides with the indentation ++ // level. ++ ++ required := parser.flow_level == 0 && parser.indent == parser.mark.column ++ ++ // ++ // If the current position may start a simple key, save it. ++ // ++ if parser.simple_key_allowed { ++ simple_key := yaml_simple_key_t{ ++ possible: true, ++ required: required, ++ token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), ++ mark: parser.mark, ++ } ++ ++ if !yaml_parser_remove_simple_key(parser) { ++ return false ++ } ++ parser.simple_keys[len(parser.simple_keys)-1] = simple_key ++ parser.simple_keys_by_tok[simple_key.token_number] = len(parser.simple_keys) - 1 ++ } ++ return true ++} ++ ++// Remove a potential simple key at the current flow level. ++func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool { ++ i := len(parser.simple_keys) - 1 ++ if parser.simple_keys[i].possible { ++ // If the key is required, it is an error. ++ if parser.simple_keys[i].required { ++ return yaml_parser_set_scanner_error(parser, ++ "while scanning a simple key", parser.simple_keys[i].mark, ++ "could not find expected ':'") ++ } ++ // Remove the key from the stack. ++ parser.simple_keys[i].possible = false ++ delete(parser.simple_keys_by_tok, parser.simple_keys[i].token_number) ++ } ++ return true ++} ++ ++// max_flow_level limits the flow_level ++const max_flow_level = 10000 ++ ++// Increase the flow level and resize the simple key list if needed. ++func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool { ++ // Reset the simple key on the next level. ++ parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{ ++ possible: false, ++ required: false, ++ token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), ++ mark: parser.mark, ++ }) ++ ++ // Increase the flow level. ++ parser.flow_level++ ++ if parser.flow_level > max_flow_level { ++ return yaml_parser_set_scanner_error(parser, ++ "while increasing flow level", parser.simple_keys[len(parser.simple_keys)-1].mark, ++ fmt.Sprintf("exceeded max depth of %d", max_flow_level)) ++ } ++ return true ++} ++ ++// Decrease the flow level. ++func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool { ++ if parser.flow_level > 0 { ++ parser.flow_level-- ++ last := len(parser.simple_keys) - 1 ++ delete(parser.simple_keys_by_tok, parser.simple_keys[last].token_number) ++ parser.simple_keys = parser.simple_keys[:last] ++ } ++ return true ++} ++ ++// max_indents limits the indents stack size ++const max_indents = 10000 ++ ++// Push the current indentation level to the stack and set the new level ++// the current column is greater than the indentation level. In this case, ++// append or insert the specified token into the token queue. ++func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, typ yaml_token_type_t, mark yaml_mark_t) bool { ++ // In the flow context, do nothing. ++ if parser.flow_level > 0 { ++ return true ++ } ++ ++ if parser.indent < column { ++ // Push the current indentation level to the stack and set the new ++ // indentation level. ++ parser.indents = append(parser.indents, parser.indent) ++ parser.indent = column ++ if len(parser.indents) > max_indents { ++ return yaml_parser_set_scanner_error(parser, ++ "while increasing indent level", parser.simple_keys[len(parser.simple_keys)-1].mark, ++ fmt.Sprintf("exceeded max depth of %d", max_indents)) ++ } ++ ++ // Create a token and insert it into the queue. ++ token := yaml_token_t{ ++ typ: typ, ++ start_mark: mark, ++ end_mark: mark, ++ } ++ if number > -1 { ++ number -= parser.tokens_parsed ++ } ++ yaml_insert_token(parser, number, &token) ++ } ++ return true ++} ++ ++// Pop indentation levels from the indents stack until the current level ++// becomes less or equal to the column. For each indentation level, append ++// the BLOCK-END token. ++func yaml_parser_unroll_indent(parser *yaml_parser_t, column int, scan_mark yaml_mark_t) bool { ++ // In the flow context, do nothing. ++ if parser.flow_level > 0 { ++ return true ++ } ++ ++ block_mark := scan_mark ++ block_mark.index-- ++ ++ // Loop through the indentation levels in the stack. ++ for parser.indent > column { ++ ++ // [Go] Reposition the end token before potential following ++ // foot comments of parent blocks. For that, search ++ // backwards for recent comments that were at the same ++ // indent as the block that is ending now. ++ stop_index := block_mark.index ++ for i := len(parser.comments) - 1; i >= 0; i-- { ++ comment := &parser.comments[i] ++ ++ if comment.end_mark.index < stop_index { ++ // Don't go back beyond the start of the comment/whitespace scan, unless column < 0. ++ // If requested indent column is < 0, then the document is over and everything else ++ // is a foot anyway. ++ break ++ } ++ if comment.start_mark.column == parser.indent+1 { ++ // This is a good match. But maybe there's a former comment ++ // at that same indent level, so keep searching. ++ block_mark = comment.start_mark ++ } ++ ++ // While the end of the former comment matches with ++ // the start of the following one, we know there's ++ // nothing in between and scanning is still safe. ++ stop_index = comment.scan_mark.index ++ } ++ ++ // Create a token and append it to the queue. ++ token := yaml_token_t{ ++ typ: yaml_BLOCK_END_TOKEN, ++ start_mark: block_mark, ++ end_mark: block_mark, ++ } ++ yaml_insert_token(parser, -1, &token) ++ ++ // Pop the indentation level. ++ parser.indent = parser.indents[len(parser.indents)-1] ++ parser.indents = parser.indents[:len(parser.indents)-1] ++ } ++ return true ++} ++ ++// Initialize the scanner and produce the STREAM-START token. ++func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool { ++ ++ // Set the initial indentation. ++ parser.indent = -1 ++ ++ // Initialize the simple key stack. ++ parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{}) ++ ++ parser.simple_keys_by_tok = make(map[int]int) ++ ++ // A simple key is allowed at the beginning of the stream. ++ parser.simple_key_allowed = true ++ ++ // We have started. ++ parser.stream_start_produced = true ++ ++ // Create the STREAM-START token and append it to the queue. ++ token := yaml_token_t{ ++ typ: yaml_STREAM_START_TOKEN, ++ start_mark: parser.mark, ++ end_mark: parser.mark, ++ encoding: parser.encoding, ++ } ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the STREAM-END token and shut down the scanner. ++func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool { ++ ++ // Force new line. ++ if parser.mark.column != 0 { ++ parser.mark.column = 0 ++ parser.mark.line++ ++ } ++ ++ // Reset the indentation level. ++ if !yaml_parser_unroll_indent(parser, -1, parser.mark) { ++ return false ++ } ++ ++ // Reset simple keys. ++ if !yaml_parser_remove_simple_key(parser) { ++ return false ++ } ++ ++ parser.simple_key_allowed = false ++ ++ // Create the STREAM-END token and append it to the queue. ++ token := yaml_token_t{ ++ typ: yaml_STREAM_END_TOKEN, ++ start_mark: parser.mark, ++ end_mark: parser.mark, ++ } ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token. ++func yaml_parser_fetch_directive(parser *yaml_parser_t) bool { ++ // Reset the indentation level. ++ if !yaml_parser_unroll_indent(parser, -1, parser.mark) { ++ return false ++ } ++ ++ // Reset simple keys. ++ if !yaml_parser_remove_simple_key(parser) { ++ return false ++ } ++ ++ parser.simple_key_allowed = false ++ ++ // Create the YAML-DIRECTIVE or TAG-DIRECTIVE token. ++ token := yaml_token_t{} ++ if !yaml_parser_scan_directive(parser, &token) { ++ return false ++ } ++ // Append the token to the queue. ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the DOCUMENT-START or DOCUMENT-END token. ++func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yaml_token_type_t) bool { ++ // Reset the indentation level. ++ if !yaml_parser_unroll_indent(parser, -1, parser.mark) { ++ return false ++ } ++ ++ // Reset simple keys. ++ if !yaml_parser_remove_simple_key(parser) { ++ return false ++ } ++ ++ parser.simple_key_allowed = false ++ ++ // Consume the token. ++ start_mark := parser.mark ++ ++ skip(parser) ++ skip(parser) ++ skip(parser) ++ ++ end_mark := parser.mark ++ ++ // Create the DOCUMENT-START or DOCUMENT-END token. ++ token := yaml_token_t{ ++ typ: typ, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ } ++ // Append the token to the queue. ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token. ++func yaml_parser_fetch_flow_collection_start(parser *yaml_parser_t, typ yaml_token_type_t) bool { ++ ++ // The indicators '[' and '{' may start a simple key. ++ if !yaml_parser_save_simple_key(parser) { ++ return false ++ } ++ ++ // Increase the flow level. ++ if !yaml_parser_increase_flow_level(parser) { ++ return false ++ } ++ ++ // A simple key may follow the indicators '[' and '{'. ++ parser.simple_key_allowed = true ++ ++ // Consume the token. ++ start_mark := parser.mark ++ skip(parser) ++ end_mark := parser.mark ++ ++ // Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token. ++ token := yaml_token_t{ ++ typ: typ, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ } ++ // Append the token to the queue. ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token. ++func yaml_parser_fetch_flow_collection_end(parser *yaml_parser_t, typ yaml_token_type_t) bool { ++ // Reset any potential simple key on the current flow level. ++ if !yaml_parser_remove_simple_key(parser) { ++ return false ++ } ++ ++ // Decrease the flow level. ++ if !yaml_parser_decrease_flow_level(parser) { ++ return false ++ } ++ ++ // No simple keys after the indicators ']' and '}'. ++ parser.simple_key_allowed = false ++ ++ // Consume the token. ++ ++ start_mark := parser.mark ++ skip(parser) ++ end_mark := parser.mark ++ ++ // Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token. ++ token := yaml_token_t{ ++ typ: typ, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ } ++ // Append the token to the queue. ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the FLOW-ENTRY token. ++func yaml_parser_fetch_flow_entry(parser *yaml_parser_t) bool { ++ // Reset any potential simple keys on the current flow level. ++ if !yaml_parser_remove_simple_key(parser) { ++ return false ++ } ++ ++ // Simple keys are allowed after ','. ++ parser.simple_key_allowed = true ++ ++ // Consume the token. ++ start_mark := parser.mark ++ skip(parser) ++ end_mark := parser.mark ++ ++ // Create the FLOW-ENTRY token and append it to the queue. ++ token := yaml_token_t{ ++ typ: yaml_FLOW_ENTRY_TOKEN, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ } ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the BLOCK-ENTRY token. ++func yaml_parser_fetch_block_entry(parser *yaml_parser_t) bool { ++ // Check if the scanner is in the block context. ++ if parser.flow_level == 0 { ++ // Check if we are allowed to start a new entry. ++ if !parser.simple_key_allowed { ++ return yaml_parser_set_scanner_error(parser, "", parser.mark, ++ "block sequence entries are not allowed in this context") ++ } ++ // Add the BLOCK-SEQUENCE-START token if needed. ++ if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_SEQUENCE_START_TOKEN, parser.mark) { ++ return false ++ } ++ } else { ++ // It is an error for the '-' indicator to occur in the flow context, ++ // but we let the Parser detect and report about it because the Parser ++ // is able to point to the context. ++ } ++ ++ // Reset any potential simple keys on the current flow level. ++ if !yaml_parser_remove_simple_key(parser) { ++ return false ++ } ++ ++ // Simple keys are allowed after '-'. ++ parser.simple_key_allowed = true ++ ++ // Consume the token. ++ start_mark := parser.mark ++ skip(parser) ++ end_mark := parser.mark ++ ++ // Create the BLOCK-ENTRY token and append it to the queue. ++ token := yaml_token_t{ ++ typ: yaml_BLOCK_ENTRY_TOKEN, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ } ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the KEY token. ++func yaml_parser_fetch_key(parser *yaml_parser_t) bool { ++ ++ // In the block context, additional checks are required. ++ if parser.flow_level == 0 { ++ // Check if we are allowed to start a new key (not nessesary simple). ++ if !parser.simple_key_allowed { ++ return yaml_parser_set_scanner_error(parser, "", parser.mark, ++ "mapping keys are not allowed in this context") ++ } ++ // Add the BLOCK-MAPPING-START token if needed. ++ if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) { ++ return false ++ } ++ } ++ ++ // Reset any potential simple keys on the current flow level. ++ if !yaml_parser_remove_simple_key(parser) { ++ return false ++ } ++ ++ // Simple keys are allowed after '?' in the block context. ++ parser.simple_key_allowed = parser.flow_level == 0 ++ ++ // Consume the token. ++ start_mark := parser.mark ++ skip(parser) ++ end_mark := parser.mark ++ ++ // Create the KEY token and append it to the queue. ++ token := yaml_token_t{ ++ typ: yaml_KEY_TOKEN, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ } ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the VALUE token. ++func yaml_parser_fetch_value(parser *yaml_parser_t) bool { ++ ++ simple_key := &parser.simple_keys[len(parser.simple_keys)-1] ++ ++ // Have we found a simple key? ++ if valid, ok := yaml_simple_key_is_valid(parser, simple_key); !ok { ++ return false ++ ++ } else if valid { ++ ++ // Create the KEY token and insert it into the queue. ++ token := yaml_token_t{ ++ typ: yaml_KEY_TOKEN, ++ start_mark: simple_key.mark, ++ end_mark: simple_key.mark, ++ } ++ yaml_insert_token(parser, simple_key.token_number-parser.tokens_parsed, &token) ++ ++ // In the block context, we may need to add the BLOCK-MAPPING-START token. ++ if !yaml_parser_roll_indent(parser, simple_key.mark.column, ++ simple_key.token_number, ++ yaml_BLOCK_MAPPING_START_TOKEN, simple_key.mark) { ++ return false ++ } ++ ++ // Remove the simple key. ++ simple_key.possible = false ++ delete(parser.simple_keys_by_tok, simple_key.token_number) ++ ++ // A simple key cannot follow another simple key. ++ parser.simple_key_allowed = false ++ ++ } else { ++ // The ':' indicator follows a complex key. ++ ++ // In the block context, extra checks are required. ++ if parser.flow_level == 0 { ++ ++ // Check if we are allowed to start a complex value. ++ if !parser.simple_key_allowed { ++ return yaml_parser_set_scanner_error(parser, "", parser.mark, ++ "mapping values are not allowed in this context") ++ } ++ ++ // Add the BLOCK-MAPPING-START token if needed. ++ if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) { ++ return false ++ } ++ } ++ ++ // Simple keys after ':' are allowed in the block context. ++ parser.simple_key_allowed = parser.flow_level == 0 ++ } ++ ++ // Consume the token. ++ start_mark := parser.mark ++ skip(parser) ++ end_mark := parser.mark ++ ++ // Create the VALUE token and append it to the queue. ++ token := yaml_token_t{ ++ typ: yaml_VALUE_TOKEN, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ } ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the ALIAS or ANCHOR token. ++func yaml_parser_fetch_anchor(parser *yaml_parser_t, typ yaml_token_type_t) bool { ++ // An anchor or an alias could be a simple key. ++ if !yaml_parser_save_simple_key(parser) { ++ return false ++ } ++ ++ // A simple key cannot follow an anchor or an alias. ++ parser.simple_key_allowed = false ++ ++ // Create the ALIAS or ANCHOR token and append it to the queue. ++ var token yaml_token_t ++ if !yaml_parser_scan_anchor(parser, &token, typ) { ++ return false ++ } ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the TAG token. ++func yaml_parser_fetch_tag(parser *yaml_parser_t) bool { ++ // A tag could be a simple key. ++ if !yaml_parser_save_simple_key(parser) { ++ return false ++ } ++ ++ // A simple key cannot follow a tag. ++ parser.simple_key_allowed = false ++ ++ // Create the TAG token and append it to the queue. ++ var token yaml_token_t ++ if !yaml_parser_scan_tag(parser, &token) { ++ return false ++ } ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens. ++func yaml_parser_fetch_block_scalar(parser *yaml_parser_t, literal bool) bool { ++ // Remove any potential simple keys. ++ if !yaml_parser_remove_simple_key(parser) { ++ return false ++ } ++ ++ // A simple key may follow a block scalar. ++ parser.simple_key_allowed = true ++ ++ // Create the SCALAR token and append it to the queue. ++ var token yaml_token_t ++ if !yaml_parser_scan_block_scalar(parser, &token, literal) { ++ return false ++ } ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens. ++func yaml_parser_fetch_flow_scalar(parser *yaml_parser_t, single bool) bool { ++ // A plain scalar could be a simple key. ++ if !yaml_parser_save_simple_key(parser) { ++ return false ++ } ++ ++ // A simple key cannot follow a flow scalar. ++ parser.simple_key_allowed = false ++ ++ // Create the SCALAR token and append it to the queue. ++ var token yaml_token_t ++ if !yaml_parser_scan_flow_scalar(parser, &token, single) { ++ return false ++ } ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the SCALAR(...,plain) token. ++func yaml_parser_fetch_plain_scalar(parser *yaml_parser_t) bool { ++ // A plain scalar could be a simple key. ++ if !yaml_parser_save_simple_key(parser) { ++ return false ++ } ++ ++ // A simple key cannot follow a flow scalar. ++ parser.simple_key_allowed = false ++ ++ // Create the SCALAR token and append it to the queue. ++ var token yaml_token_t ++ if !yaml_parser_scan_plain_scalar(parser, &token) { ++ return false ++ } ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Eat whitespaces and comments until the next token is found. ++func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool { ++ ++ scan_mark := parser.mark ++ ++ // Until the next token is not found. ++ for { ++ // Allow the BOM mark to start a line. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ if parser.mark.column == 0 && is_bom(parser.buffer, parser.buffer_pos) { ++ skip(parser) ++ } ++ ++ // Eat whitespaces. ++ // Tabs are allowed: ++ // - in the flow context ++ // - in the block context, but not at the beginning of the line or ++ // after '-', '?', or ':' (complex value). ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ ++ for parser.buffer[parser.buffer_pos] == ' ' || ((parser.flow_level > 0 || !parser.simple_key_allowed) && parser.buffer[parser.buffer_pos] == '\t') { ++ skip(parser) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ ++ // Check if we just had a line comment under a sequence entry that ++ // looks more like a header to the following content. Similar to this: ++ // ++ // - # The comment ++ // - Some data ++ // ++ // If so, transform the line comment to a head comment and reposition. ++ if len(parser.comments) > 0 && len(parser.tokens) > 1 { ++ tokenA := parser.tokens[len(parser.tokens)-2] ++ tokenB := parser.tokens[len(parser.tokens)-1] ++ comment := &parser.comments[len(parser.comments)-1] ++ if tokenA.typ == yaml_BLOCK_SEQUENCE_START_TOKEN && tokenB.typ == yaml_BLOCK_ENTRY_TOKEN && len(comment.line) > 0 && !is_break(parser.buffer, parser.buffer_pos) { ++ // If it was in the prior line, reposition so it becomes a ++ // header of the follow up token. Otherwise, keep it in place ++ // so it becomes a header of the former. ++ comment.head = comment.line ++ comment.line = nil ++ if comment.start_mark.line == parser.mark.line-1 { ++ comment.token_mark = parser.mark ++ } ++ } ++ } ++ ++ // Eat a comment until a line break. ++ if parser.buffer[parser.buffer_pos] == '#' { ++ if !yaml_parser_scan_comments(parser, scan_mark) { ++ return false ++ } ++ } ++ ++ // If it is a line break, eat it. ++ if is_break(parser.buffer, parser.buffer_pos) { ++ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { ++ return false ++ } ++ skip_line(parser) ++ ++ // In the block context, a new line may start a simple key. ++ if parser.flow_level == 0 { ++ parser.simple_key_allowed = true ++ } ++ } else { ++ break // We have found a token. ++ } ++ } ++ ++ return true ++} ++ ++// Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token. ++// ++// Scope: ++// %YAML 1.1 # a comment \n ++// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ++// %TAG !yaml! tag:yaml.org,2002: \n ++// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ++// ++func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool { ++ // Eat '%'. ++ start_mark := parser.mark ++ skip(parser) ++ ++ // Scan the directive name. ++ var name []byte ++ if !yaml_parser_scan_directive_name(parser, start_mark, &name) { ++ return false ++ } ++ ++ // Is it a YAML directive? ++ if bytes.Equal(name, []byte("YAML")) { ++ // Scan the VERSION directive value. ++ var major, minor int8 ++ if !yaml_parser_scan_version_directive_value(parser, start_mark, &major, &minor) { ++ return false ++ } ++ end_mark := parser.mark ++ ++ // Create a VERSION-DIRECTIVE token. ++ *token = yaml_token_t{ ++ typ: yaml_VERSION_DIRECTIVE_TOKEN, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ major: major, ++ minor: minor, ++ } ++ ++ // Is it a TAG directive? ++ } else if bytes.Equal(name, []byte("TAG")) { ++ // Scan the TAG directive value. ++ var handle, prefix []byte ++ if !yaml_parser_scan_tag_directive_value(parser, start_mark, &handle, &prefix) { ++ return false ++ } ++ end_mark := parser.mark ++ ++ // Create a TAG-DIRECTIVE token. ++ *token = yaml_token_t{ ++ typ: yaml_TAG_DIRECTIVE_TOKEN, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ value: handle, ++ prefix: prefix, ++ } ++ ++ // Unknown directive. ++ } else { ++ yaml_parser_set_scanner_error(parser, "while scanning a directive", ++ start_mark, "found unknown directive name") ++ return false ++ } ++ ++ // Eat the rest of the line including any comments. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ ++ for is_blank(parser.buffer, parser.buffer_pos) { ++ skip(parser) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ ++ if parser.buffer[parser.buffer_pos] == '#' { ++ // [Go] Discard this inline comment for the time being. ++ //if !yaml_parser_scan_line_comment(parser, start_mark) { ++ // return false ++ //} ++ for !is_breakz(parser.buffer, parser.buffer_pos) { ++ skip(parser) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ } ++ ++ // Check if we are at the end of the line. ++ if !is_breakz(parser.buffer, parser.buffer_pos) { ++ yaml_parser_set_scanner_error(parser, "while scanning a directive", ++ start_mark, "did not find expected comment or line break") ++ return false ++ } ++ ++ // Eat a line break. ++ if is_break(parser.buffer, parser.buffer_pos) { ++ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { ++ return false ++ } ++ skip_line(parser) ++ } ++ ++ return true ++} ++ ++// Scan the directive name. ++// ++// Scope: ++// %YAML 1.1 # a comment \n ++// ^^^^ ++// %TAG !yaml! tag:yaml.org,2002: \n ++// ^^^ ++// ++func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark_t, name *[]byte) bool { ++ // Consume the directive name. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ ++ var s []byte ++ for is_alpha(parser.buffer, parser.buffer_pos) { ++ s = read(parser, s) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ ++ // Check if the name is empty. ++ if len(s) == 0 { ++ yaml_parser_set_scanner_error(parser, "while scanning a directive", ++ start_mark, "could not find expected directive name") ++ return false ++ } ++ ++ // Check for an blank character after the name. ++ if !is_blankz(parser.buffer, parser.buffer_pos) { ++ yaml_parser_set_scanner_error(parser, "while scanning a directive", ++ start_mark, "found unexpected non-alphabetical character") ++ return false ++ } ++ *name = s ++ return true ++} ++ ++// Scan the value of VERSION-DIRECTIVE. ++// ++// Scope: ++// %YAML 1.1 # a comment \n ++// ^^^^^^ ++func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, major, minor *int8) bool { ++ // Eat whitespaces. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ for is_blank(parser.buffer, parser.buffer_pos) { ++ skip(parser) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ ++ // Consume the major version number. ++ if !yaml_parser_scan_version_directive_number(parser, start_mark, major) { ++ return false ++ } ++ ++ // Eat '.'. ++ if parser.buffer[parser.buffer_pos] != '.' { ++ return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", ++ start_mark, "did not find expected digit or '.' character") ++ } ++ ++ skip(parser) ++ ++ // Consume the minor version number. ++ if !yaml_parser_scan_version_directive_number(parser, start_mark, minor) { ++ return false ++ } ++ return true ++} ++ ++const max_number_length = 2 ++ ++// Scan the version number of VERSION-DIRECTIVE. ++// ++// Scope: ++// %YAML 1.1 # a comment \n ++// ^ ++// %YAML 1.1 # a comment \n ++// ^ ++func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark yaml_mark_t, number *int8) bool { ++ ++ // Repeat while the next character is digit. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ var value, length int8 ++ for is_digit(parser.buffer, parser.buffer_pos) { ++ // Check if the number is too long. ++ length++ ++ if length > max_number_length { ++ return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", ++ start_mark, "found extremely long version number") ++ } ++ value = value*10 + int8(as_digit(parser.buffer, parser.buffer_pos)) ++ skip(parser) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ ++ // Check if the number was present. ++ if length == 0 { ++ return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", ++ start_mark, "did not find expected version number") ++ } ++ *number = value ++ return true ++} ++ ++// Scan the value of a TAG-DIRECTIVE token. ++// ++// Scope: ++// %TAG !yaml! tag:yaml.org,2002: \n ++// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ++// ++func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, handle, prefix *[]byte) bool { ++ var handle_value, prefix_value []byte ++ ++ // Eat whitespaces. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ ++ for is_blank(parser.buffer, parser.buffer_pos) { ++ skip(parser) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ ++ // Scan a handle. ++ if !yaml_parser_scan_tag_handle(parser, true, start_mark, &handle_value) { ++ return false ++ } ++ ++ // Expect a whitespace. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ if !is_blank(parser.buffer, parser.buffer_pos) { ++ yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", ++ start_mark, "did not find expected whitespace") ++ return false ++ } ++ ++ // Eat whitespaces. ++ for is_blank(parser.buffer, parser.buffer_pos) { ++ skip(parser) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ ++ // Scan a prefix. ++ if !yaml_parser_scan_tag_uri(parser, true, nil, start_mark, &prefix_value) { ++ return false ++ } ++ ++ // Expect a whitespace or line break. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ if !is_blankz(parser.buffer, parser.buffer_pos) { ++ yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", ++ start_mark, "did not find expected whitespace or line break") ++ return false ++ } ++ ++ *handle = handle_value ++ *prefix = prefix_value ++ return true ++} ++ ++func yaml_parser_scan_anchor(parser *yaml_parser_t, token *yaml_token_t, typ yaml_token_type_t) bool { ++ var s []byte ++ ++ // Eat the indicator character. ++ start_mark := parser.mark ++ skip(parser) ++ ++ // Consume the value. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ ++ for is_alpha(parser.buffer, parser.buffer_pos) { ++ s = read(parser, s) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ ++ end_mark := parser.mark ++ ++ /* ++ * Check if length of the anchor is greater than 0 and it is followed by ++ * a whitespace character or one of the indicators: ++ * ++ * '?', ':', ',', ']', '}', '%', '@', '`'. ++ */ ++ ++ if len(s) == 0 || ++ !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '?' || ++ parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == ',' || ++ parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '}' || ++ parser.buffer[parser.buffer_pos] == '%' || parser.buffer[parser.buffer_pos] == '@' || ++ parser.buffer[parser.buffer_pos] == '`') { ++ context := "while scanning an alias" ++ if typ == yaml_ANCHOR_TOKEN { ++ context = "while scanning an anchor" ++ } ++ yaml_parser_set_scanner_error(parser, context, start_mark, ++ "did not find expected alphabetic or numeric character") ++ return false ++ } ++ ++ // Create a token. ++ *token = yaml_token_t{ ++ typ: typ, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ value: s, ++ } ++ ++ return true ++} ++ ++/* ++ * Scan a TAG token. ++ */ ++ ++func yaml_parser_scan_tag(parser *yaml_parser_t, token *yaml_token_t) bool { ++ var handle, suffix []byte ++ ++ start_mark := parser.mark ++ ++ // Check if the tag is in the canonical form. ++ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { ++ return false ++ } ++ ++ if parser.buffer[parser.buffer_pos+1] == '<' { ++ // Keep the handle as '' ++ ++ // Eat '!<' ++ skip(parser) ++ skip(parser) ++ ++ // Consume the tag value. ++ if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) { ++ return false ++ } ++ ++ // Check for '>' and eat it. ++ if parser.buffer[parser.buffer_pos] != '>' { ++ yaml_parser_set_scanner_error(parser, "while scanning a tag", ++ start_mark, "did not find the expected '>'") ++ return false ++ } ++ ++ skip(parser) ++ } else { ++ // The tag has either the '!suffix' or the '!handle!suffix' form. ++ ++ // First, try to scan a handle. ++ if !yaml_parser_scan_tag_handle(parser, false, start_mark, &handle) { ++ return false ++ } ++ ++ // Check if it is, indeed, handle. ++ if handle[0] == '!' && len(handle) > 1 && handle[len(handle)-1] == '!' { ++ // Scan the suffix now. ++ if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) { ++ return false ++ } ++ } else { ++ // It wasn't a handle after all. Scan the rest of the tag. ++ if !yaml_parser_scan_tag_uri(parser, false, handle, start_mark, &suffix) { ++ return false ++ } ++ ++ // Set the handle to '!'. ++ handle = []byte{'!'} ++ ++ // A special case: the '!' tag. Set the handle to '' and the ++ // suffix to '!'. ++ if len(suffix) == 0 { ++ handle, suffix = suffix, handle ++ } ++ } ++ } ++ ++ // Check the character which ends the tag. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ if !is_blankz(parser.buffer, parser.buffer_pos) { ++ yaml_parser_set_scanner_error(parser, "while scanning a tag", ++ start_mark, "did not find expected whitespace or line break") ++ return false ++ } ++ ++ end_mark := parser.mark ++ ++ // Create a token. ++ *token = yaml_token_t{ ++ typ: yaml_TAG_TOKEN, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ value: handle, ++ suffix: suffix, ++ } ++ return true ++} ++ ++// Scan a tag handle. ++func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, handle *[]byte) bool { ++ // Check the initial '!' character. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ if parser.buffer[parser.buffer_pos] != '!' { ++ yaml_parser_set_scanner_tag_error(parser, directive, ++ start_mark, "did not find expected '!'") ++ return false ++ } ++ ++ var s []byte ++ ++ // Copy the '!' character. ++ s = read(parser, s) ++ ++ // Copy all subsequent alphabetical and numerical characters. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ for is_alpha(parser.buffer, parser.buffer_pos) { ++ s = read(parser, s) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ ++ // Check if the trailing character is '!' and copy it. ++ if parser.buffer[parser.buffer_pos] == '!' { ++ s = read(parser, s) ++ } else { ++ // It's either the '!' tag or not really a tag handle. If it's a %TAG ++ // directive, it's an error. If it's a tag token, it must be a part of URI. ++ if directive && string(s) != "!" { ++ yaml_parser_set_scanner_tag_error(parser, directive, ++ start_mark, "did not find expected '!'") ++ return false ++ } ++ } ++ ++ *handle = s ++ return true ++} ++ ++// Scan a tag. ++func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte, start_mark yaml_mark_t, uri *[]byte) bool { ++ //size_t length = head ? strlen((char *)head) : 0 ++ var s []byte ++ hasTag := len(head) > 0 ++ ++ // Copy the head if needed. ++ // ++ // Note that we don't copy the leading '!' character. ++ if len(head) > 1 { ++ s = append(s, head[1:]...) ++ } ++ ++ // Scan the tag. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ ++ // The set of characters that may appear in URI is as follows: ++ // ++ // '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&', ++ // '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']', ++ // '%'. ++ // [Go] TODO Convert this into more reasonable logic. ++ for is_alpha(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == ';' || ++ parser.buffer[parser.buffer_pos] == '/' || parser.buffer[parser.buffer_pos] == '?' || ++ parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == '@' || ++ parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '=' || ++ parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '$' || ++ parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '.' || ++ parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '~' || ++ parser.buffer[parser.buffer_pos] == '*' || parser.buffer[parser.buffer_pos] == '\'' || ++ parser.buffer[parser.buffer_pos] == '(' || parser.buffer[parser.buffer_pos] == ')' || ++ parser.buffer[parser.buffer_pos] == '[' || parser.buffer[parser.buffer_pos] == ']' || ++ parser.buffer[parser.buffer_pos] == '%' { ++ // Check if it is a URI-escape sequence. ++ if parser.buffer[parser.buffer_pos] == '%' { ++ if !yaml_parser_scan_uri_escapes(parser, directive, start_mark, &s) { ++ return false ++ } ++ } else { ++ s = read(parser, s) ++ } ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ hasTag = true ++ } ++ ++ if !hasTag { ++ yaml_parser_set_scanner_tag_error(parser, directive, ++ start_mark, "did not find expected tag URI") ++ return false ++ } ++ *uri = s ++ return true ++} ++ ++// Decode an URI-escape sequence corresponding to a single UTF-8 character. ++func yaml_parser_scan_uri_escapes(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, s *[]byte) bool { ++ ++ // Decode the required number of characters. ++ w := 1024 ++ for w > 0 { ++ // Check for a URI-escaped octet. ++ if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) { ++ return false ++ } ++ ++ if !(parser.buffer[parser.buffer_pos] == '%' && ++ is_hex(parser.buffer, parser.buffer_pos+1) && ++ is_hex(parser.buffer, parser.buffer_pos+2)) { ++ return yaml_parser_set_scanner_tag_error(parser, directive, ++ start_mark, "did not find URI escaped octet") ++ } ++ ++ // Get the octet. ++ octet := byte((as_hex(parser.buffer, parser.buffer_pos+1) << 4) + as_hex(parser.buffer, parser.buffer_pos+2)) ++ ++ // If it is the leading octet, determine the length of the UTF-8 sequence. ++ if w == 1024 { ++ w = width(octet) ++ if w == 0 { ++ return yaml_parser_set_scanner_tag_error(parser, directive, ++ start_mark, "found an incorrect leading UTF-8 octet") ++ } ++ } else { ++ // Check if the trailing octet is correct. ++ if octet&0xC0 != 0x80 { ++ return yaml_parser_set_scanner_tag_error(parser, directive, ++ start_mark, "found an incorrect trailing UTF-8 octet") ++ } ++ } ++ ++ // Copy the octet and move the pointers. ++ *s = append(*s, octet) ++ skip(parser) ++ skip(parser) ++ skip(parser) ++ w-- ++ } ++ return true ++} ++ ++// Scan a block scalar. ++func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, literal bool) bool { ++ // Eat the indicator '|' or '>'. ++ start_mark := parser.mark ++ skip(parser) ++ ++ // Scan the additional block scalar indicators. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ ++ // Check for a chomping indicator. ++ var chomping, increment int ++ if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' { ++ // Set the chomping method and eat the indicator. ++ if parser.buffer[parser.buffer_pos] == '+' { ++ chomping = +1 ++ } else { ++ chomping = -1 ++ } ++ skip(parser) ++ ++ // Check for an indentation indicator. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ if is_digit(parser.buffer, parser.buffer_pos) { ++ // Check that the indentation is greater than 0. ++ if parser.buffer[parser.buffer_pos] == '0' { ++ yaml_parser_set_scanner_error(parser, "while scanning a block scalar", ++ start_mark, "found an indentation indicator equal to 0") ++ return false ++ } ++ ++ // Get the indentation level and eat the indicator. ++ increment = as_digit(parser.buffer, parser.buffer_pos) ++ skip(parser) ++ } ++ ++ } else if is_digit(parser.buffer, parser.buffer_pos) { ++ // Do the same as above, but in the opposite order. ++ ++ if parser.buffer[parser.buffer_pos] == '0' { ++ yaml_parser_set_scanner_error(parser, "while scanning a block scalar", ++ start_mark, "found an indentation indicator equal to 0") ++ return false ++ } ++ increment = as_digit(parser.buffer, parser.buffer_pos) ++ skip(parser) ++ ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' { ++ if parser.buffer[parser.buffer_pos] == '+' { ++ chomping = +1 ++ } else { ++ chomping = -1 ++ } ++ skip(parser) ++ } ++ } ++ ++ // Eat whitespaces and comments to the end of the line. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ for is_blank(parser.buffer, parser.buffer_pos) { ++ skip(parser) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ if parser.buffer[parser.buffer_pos] == '#' { ++ if !yaml_parser_scan_line_comment(parser, start_mark) { ++ return false ++ } ++ for !is_breakz(parser.buffer, parser.buffer_pos) { ++ skip(parser) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ } ++ ++ // Check if we are at the end of the line. ++ if !is_breakz(parser.buffer, parser.buffer_pos) { ++ yaml_parser_set_scanner_error(parser, "while scanning a block scalar", ++ start_mark, "did not find expected comment or line break") ++ return false ++ } ++ ++ // Eat a line break. ++ if is_break(parser.buffer, parser.buffer_pos) { ++ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { ++ return false ++ } ++ skip_line(parser) ++ } ++ ++ end_mark := parser.mark ++ ++ // Set the indentation level if it was specified. ++ var indent int ++ if increment > 0 { ++ if parser.indent >= 0 { ++ indent = parser.indent + increment ++ } else { ++ indent = increment ++ } ++ } ++ ++ // Scan the leading line breaks and determine the indentation level if needed. ++ var s, leading_break, trailing_breaks []byte ++ if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) { ++ return false ++ } ++ ++ // Scan the block scalar content. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ var leading_blank, trailing_blank bool ++ for parser.mark.column == indent && !is_z(parser.buffer, parser.buffer_pos) { ++ // We are at the beginning of a non-empty line. ++ ++ // Is it a trailing whitespace? ++ trailing_blank = is_blank(parser.buffer, parser.buffer_pos) ++ ++ // Check if we need to fold the leading line break. ++ if !literal && !leading_blank && !trailing_blank && len(leading_break) > 0 && leading_break[0] == '\n' { ++ // Do we need to join the lines by space? ++ if len(trailing_breaks) == 0 { ++ s = append(s, ' ') ++ } ++ } else { ++ s = append(s, leading_break...) ++ } ++ leading_break = leading_break[:0] ++ ++ // Append the remaining line breaks. ++ s = append(s, trailing_breaks...) ++ trailing_breaks = trailing_breaks[:0] ++ ++ // Is it a leading whitespace? ++ leading_blank = is_blank(parser.buffer, parser.buffer_pos) ++ ++ // Consume the current line. ++ for !is_breakz(parser.buffer, parser.buffer_pos) { ++ s = read(parser, s) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ ++ // Consume the line break. ++ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { ++ return false ++ } ++ ++ leading_break = read_line(parser, leading_break) ++ ++ // Eat the following indentation spaces and line breaks. ++ if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) { ++ return false ++ } ++ } ++ ++ // Chomp the tail. ++ if chomping != -1 { ++ s = append(s, leading_break...) ++ } ++ if chomping == 1 { ++ s = append(s, trailing_breaks...) ++ } ++ ++ // Create a token. ++ *token = yaml_token_t{ ++ typ: yaml_SCALAR_TOKEN, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ value: s, ++ style: yaml_LITERAL_SCALAR_STYLE, ++ } ++ if !literal { ++ token.style = yaml_FOLDED_SCALAR_STYLE ++ } ++ return true ++} ++ ++// Scan indentation spaces and line breaks for a block scalar. Determine the ++// indentation level if needed. ++func yaml_parser_scan_block_scalar_breaks(parser *yaml_parser_t, indent *int, breaks *[]byte, start_mark yaml_mark_t, end_mark *yaml_mark_t) bool { ++ *end_mark = parser.mark ++ ++ // Eat the indentation spaces and line breaks. ++ max_indent := 0 ++ for { ++ // Eat the indentation spaces. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ for (*indent == 0 || parser.mark.column < *indent) && is_space(parser.buffer, parser.buffer_pos) { ++ skip(parser) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ if parser.mark.column > max_indent { ++ max_indent = parser.mark.column ++ } ++ ++ // Check for a tab character messing the indentation. ++ if (*indent == 0 || parser.mark.column < *indent) && is_tab(parser.buffer, parser.buffer_pos) { ++ return yaml_parser_set_scanner_error(parser, "while scanning a block scalar", ++ start_mark, "found a tab character where an indentation space is expected") ++ } ++ ++ // Have we found a non-empty line? ++ if !is_break(parser.buffer, parser.buffer_pos) { ++ break ++ } ++ ++ // Consume the line break. ++ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { ++ return false ++ } ++ // [Go] Should really be returning breaks instead. ++ *breaks = read_line(parser, *breaks) ++ *end_mark = parser.mark ++ } ++ ++ // Determine the indentation level if needed. ++ if *indent == 0 { ++ *indent = max_indent ++ if *indent < parser.indent+1 { ++ *indent = parser.indent + 1 ++ } ++ if *indent < 1 { ++ *indent = 1 ++ } ++ } ++ return true ++} ++ ++// Scan a quoted scalar. ++func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, single bool) bool { ++ // Eat the left quote. ++ start_mark := parser.mark ++ skip(parser) ++ ++ // Consume the content of the quoted scalar. ++ var s, leading_break, trailing_breaks, whitespaces []byte ++ for { ++ // Check that there are no document indicators at the beginning of the line. ++ if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { ++ return false ++ } ++ ++ if parser.mark.column == 0 && ++ ((parser.buffer[parser.buffer_pos+0] == '-' && ++ parser.buffer[parser.buffer_pos+1] == '-' && ++ parser.buffer[parser.buffer_pos+2] == '-') || ++ (parser.buffer[parser.buffer_pos+0] == '.' && ++ parser.buffer[parser.buffer_pos+1] == '.' && ++ parser.buffer[parser.buffer_pos+2] == '.')) && ++ is_blankz(parser.buffer, parser.buffer_pos+3) { ++ yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", ++ start_mark, "found unexpected document indicator") ++ return false ++ } ++ ++ // Check for EOF. ++ if is_z(parser.buffer, parser.buffer_pos) { ++ yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", ++ start_mark, "found unexpected end of stream") ++ return false ++ } ++ ++ // Consume non-blank characters. ++ leading_blanks := false ++ for !is_blankz(parser.buffer, parser.buffer_pos) { ++ if single && parser.buffer[parser.buffer_pos] == '\'' && parser.buffer[parser.buffer_pos+1] == '\'' { ++ // Is is an escaped single quote. ++ s = append(s, '\'') ++ skip(parser) ++ skip(parser) ++ ++ } else if single && parser.buffer[parser.buffer_pos] == '\'' { ++ // It is a right single quote. ++ break ++ } else if !single && parser.buffer[parser.buffer_pos] == '"' { ++ // It is a right double quote. ++ break ++ ++ } else if !single && parser.buffer[parser.buffer_pos] == '\\' && is_break(parser.buffer, parser.buffer_pos+1) { ++ // It is an escaped line break. ++ if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) { ++ return false ++ } ++ skip(parser) ++ skip_line(parser) ++ leading_blanks = true ++ break ++ ++ } else if !single && parser.buffer[parser.buffer_pos] == '\\' { ++ // It is an escape sequence. ++ code_length := 0 ++ ++ // Check the escape character. ++ switch parser.buffer[parser.buffer_pos+1] { ++ case '0': ++ s = append(s, 0) ++ case 'a': ++ s = append(s, '\x07') ++ case 'b': ++ s = append(s, '\x08') ++ case 't', '\t': ++ s = append(s, '\x09') ++ case 'n': ++ s = append(s, '\x0A') ++ case 'v': ++ s = append(s, '\x0B') ++ case 'f': ++ s = append(s, '\x0C') ++ case 'r': ++ s = append(s, '\x0D') ++ case 'e': ++ s = append(s, '\x1B') ++ case ' ': ++ s = append(s, '\x20') ++ case '"': ++ s = append(s, '"') ++ case '\'': ++ s = append(s, '\'') ++ case '\\': ++ s = append(s, '\\') ++ case 'N': // NEL (#x85) ++ s = append(s, '\xC2') ++ s = append(s, '\x85') ++ case '_': // #xA0 ++ s = append(s, '\xC2') ++ s = append(s, '\xA0') ++ case 'L': // LS (#x2028) ++ s = append(s, '\xE2') ++ s = append(s, '\x80') ++ s = append(s, '\xA8') ++ case 'P': // PS (#x2029) ++ s = append(s, '\xE2') ++ s = append(s, '\x80') ++ s = append(s, '\xA9') ++ case 'x': ++ code_length = 2 ++ case 'u': ++ code_length = 4 ++ case 'U': ++ code_length = 8 ++ default: ++ yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", ++ start_mark, "found unknown escape character") ++ return false ++ } ++ ++ skip(parser) ++ skip(parser) ++ ++ // Consume an arbitrary escape code. ++ if code_length > 0 { ++ var value int ++ ++ // Scan the character value. ++ if parser.unread < code_length && !yaml_parser_update_buffer(parser, code_length) { ++ return false ++ } ++ for k := 0; k < code_length; k++ { ++ if !is_hex(parser.buffer, parser.buffer_pos+k) { ++ yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", ++ start_mark, "did not find expected hexdecimal number") ++ return false ++ } ++ value = (value << 4) + as_hex(parser.buffer, parser.buffer_pos+k) ++ } ++ ++ // Check the value and write the character. ++ if (value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF { ++ yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", ++ start_mark, "found invalid Unicode character escape code") ++ return false ++ } ++ if value <= 0x7F { ++ s = append(s, byte(value)) ++ } else if value <= 0x7FF { ++ s = append(s, byte(0xC0+(value>>6))) ++ s = append(s, byte(0x80+(value&0x3F))) ++ } else if value <= 0xFFFF { ++ s = append(s, byte(0xE0+(value>>12))) ++ s = append(s, byte(0x80+((value>>6)&0x3F))) ++ s = append(s, byte(0x80+(value&0x3F))) ++ } else { ++ s = append(s, byte(0xF0+(value>>18))) ++ s = append(s, byte(0x80+((value>>12)&0x3F))) ++ s = append(s, byte(0x80+((value>>6)&0x3F))) ++ s = append(s, byte(0x80+(value&0x3F))) ++ } ++ ++ // Advance the pointer. ++ for k := 0; k < code_length; k++ { ++ skip(parser) ++ } ++ } ++ } else { ++ // It is a non-escaped non-blank character. ++ s = read(parser, s) ++ } ++ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { ++ return false ++ } ++ } ++ ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ ++ // Check if we are at the end of the scalar. ++ if single { ++ if parser.buffer[parser.buffer_pos] == '\'' { ++ break ++ } ++ } else { ++ if parser.buffer[parser.buffer_pos] == '"' { ++ break ++ } ++ } ++ ++ // Consume blank characters. ++ for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { ++ if is_blank(parser.buffer, parser.buffer_pos) { ++ // Consume a space or a tab character. ++ if !leading_blanks { ++ whitespaces = read(parser, whitespaces) ++ } else { ++ skip(parser) ++ } ++ } else { ++ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { ++ return false ++ } ++ ++ // Check if it is a first line break. ++ if !leading_blanks { ++ whitespaces = whitespaces[:0] ++ leading_break = read_line(parser, leading_break) ++ leading_blanks = true ++ } else { ++ trailing_breaks = read_line(parser, trailing_breaks) ++ } ++ } ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ ++ // Join the whitespaces or fold line breaks. ++ if leading_blanks { ++ // Do we need to fold line breaks? ++ if len(leading_break) > 0 && leading_break[0] == '\n' { ++ if len(trailing_breaks) == 0 { ++ s = append(s, ' ') ++ } else { ++ s = append(s, trailing_breaks...) ++ } ++ } else { ++ s = append(s, leading_break...) ++ s = append(s, trailing_breaks...) ++ } ++ trailing_breaks = trailing_breaks[:0] ++ leading_break = leading_break[:0] ++ } else { ++ s = append(s, whitespaces...) ++ whitespaces = whitespaces[:0] ++ } ++ } ++ ++ // Eat the right quote. ++ skip(parser) ++ end_mark := parser.mark ++ ++ // Create a token. ++ *token = yaml_token_t{ ++ typ: yaml_SCALAR_TOKEN, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ value: s, ++ style: yaml_SINGLE_QUOTED_SCALAR_STYLE, ++ } ++ if !single { ++ token.style = yaml_DOUBLE_QUOTED_SCALAR_STYLE ++ } ++ return true ++} ++ ++// Scan a plain scalar. ++func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) bool { ++ ++ var s, leading_break, trailing_breaks, whitespaces []byte ++ var leading_blanks bool ++ var indent = parser.indent + 1 ++ ++ start_mark := parser.mark ++ end_mark := parser.mark ++ ++ // Consume the content of the plain scalar. ++ for { ++ // Check for a document indicator. ++ if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { ++ return false ++ } ++ if parser.mark.column == 0 && ++ ((parser.buffer[parser.buffer_pos+0] == '-' && ++ parser.buffer[parser.buffer_pos+1] == '-' && ++ parser.buffer[parser.buffer_pos+2] == '-') || ++ (parser.buffer[parser.buffer_pos+0] == '.' && ++ parser.buffer[parser.buffer_pos+1] == '.' && ++ parser.buffer[parser.buffer_pos+2] == '.')) && ++ is_blankz(parser.buffer, parser.buffer_pos+3) { ++ break ++ } ++ ++ // Check for a comment. ++ if parser.buffer[parser.buffer_pos] == '#' { ++ break ++ } ++ ++ // Consume non-blank characters. ++ for !is_blankz(parser.buffer, parser.buffer_pos) { ++ ++ // Check for indicators that may end a plain scalar. ++ if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) || ++ (parser.flow_level > 0 && ++ (parser.buffer[parser.buffer_pos] == ',' || ++ parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == '[' || ++ parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' || ++ parser.buffer[parser.buffer_pos] == '}')) { ++ break ++ } ++ ++ // Check if we need to join whitespaces and breaks. ++ if leading_blanks || len(whitespaces) > 0 { ++ if leading_blanks { ++ // Do we need to fold line breaks? ++ if leading_break[0] == '\n' { ++ if len(trailing_breaks) == 0 { ++ s = append(s, ' ') ++ } else { ++ s = append(s, trailing_breaks...) ++ } ++ } else { ++ s = append(s, leading_break...) ++ s = append(s, trailing_breaks...) ++ } ++ trailing_breaks = trailing_breaks[:0] ++ leading_break = leading_break[:0] ++ leading_blanks = false ++ } else { ++ s = append(s, whitespaces...) ++ whitespaces = whitespaces[:0] ++ } ++ } ++ ++ // Copy the character. ++ s = read(parser, s) ++ ++ end_mark = parser.mark ++ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { ++ return false ++ } ++ } ++ ++ // Is it the end? ++ if !(is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos)) { ++ break ++ } ++ ++ // Consume blank characters. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ ++ for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { ++ if is_blank(parser.buffer, parser.buffer_pos) { ++ ++ // Check for tab characters that abuse indentation. ++ if leading_blanks && parser.mark.column < indent && is_tab(parser.buffer, parser.buffer_pos) { ++ yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", ++ start_mark, "found a tab character that violates indentation") ++ return false ++ } ++ ++ // Consume a space or a tab character. ++ if !leading_blanks { ++ whitespaces = read(parser, whitespaces) ++ } else { ++ skip(parser) ++ } ++ } else { ++ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { ++ return false ++ } ++ ++ // Check if it is a first line break. ++ if !leading_blanks { ++ whitespaces = whitespaces[:0] ++ leading_break = read_line(parser, leading_break) ++ leading_blanks = true ++ } else { ++ trailing_breaks = read_line(parser, trailing_breaks) ++ } ++ } ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ ++ // Check indentation level. ++ if parser.flow_level == 0 && parser.mark.column < indent { ++ break ++ } ++ } ++ ++ // Create a token. ++ *token = yaml_token_t{ ++ typ: yaml_SCALAR_TOKEN, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ value: s, ++ style: yaml_PLAIN_SCALAR_STYLE, ++ } ++ ++ // Note that we change the 'simple_key_allowed' flag. ++ if leading_blanks { ++ parser.simple_key_allowed = true ++ } ++ return true ++} ++ ++func yaml_parser_scan_line_comment(parser *yaml_parser_t, token_mark yaml_mark_t) bool { ++ if parser.newlines > 0 { ++ return true ++ } ++ ++ var start_mark yaml_mark_t ++ var text []byte ++ ++ for peek := 0; peek < 512; peek++ { ++ if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) { ++ break ++ } ++ if is_blank(parser.buffer, parser.buffer_pos+peek) { ++ continue ++ } ++ if parser.buffer[parser.buffer_pos+peek] == '#' { ++ seen := parser.mark.index+peek ++ for { ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ if is_breakz(parser.buffer, parser.buffer_pos) { ++ if parser.mark.index >= seen { ++ break ++ } ++ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { ++ return false ++ } ++ skip_line(parser) ++ } else if parser.mark.index >= seen { ++ if len(text) == 0 { ++ start_mark = parser.mark ++ } ++ text = read(parser, text) ++ } else { ++ skip(parser) ++ } ++ } ++ } ++ break ++ } ++ if len(text) > 0 { ++ parser.comments = append(parser.comments, yaml_comment_t{ ++ token_mark: token_mark, ++ start_mark: start_mark, ++ line: text, ++ }) ++ } ++ return true ++} ++ ++func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) bool { ++ token := parser.tokens[len(parser.tokens)-1] ++ ++ if token.typ == yaml_FLOW_ENTRY_TOKEN && len(parser.tokens) > 1 { ++ token = parser.tokens[len(parser.tokens)-2] ++ } ++ ++ var token_mark = token.start_mark ++ var start_mark yaml_mark_t ++ var next_indent = parser.indent ++ if next_indent < 0 { ++ next_indent = 0 ++ } ++ ++ var recent_empty = false ++ var first_empty = parser.newlines <= 1 ++ ++ var line = parser.mark.line ++ var column = parser.mark.column ++ ++ var text []byte ++ ++ // The foot line is the place where a comment must start to ++ // still be considered as a foot of the prior content. ++ // If there's some content in the currently parsed line, then ++ // the foot is the line below it. ++ var foot_line = -1 ++ if scan_mark.line > 0 { ++ foot_line = parser.mark.line-parser.newlines+1 ++ if parser.newlines == 0 && parser.mark.column > 1 { ++ foot_line++ ++ } ++ } ++ ++ var peek = 0 ++ for ; peek < 512; peek++ { ++ if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) { ++ break ++ } ++ column++ ++ if is_blank(parser.buffer, parser.buffer_pos+peek) { ++ continue ++ } ++ c := parser.buffer[parser.buffer_pos+peek] ++ var close_flow = parser.flow_level > 0 && (c == ']' || c == '}') ++ if close_flow || is_breakz(parser.buffer, parser.buffer_pos+peek) { ++ // Got line break or terminator. ++ if close_flow || !recent_empty { ++ if close_flow || first_empty && (start_mark.line == foot_line && token.typ != yaml_VALUE_TOKEN || start_mark.column-1 < next_indent) { ++ // This is the first empty line and there were no empty lines before, ++ // so this initial part of the comment is a foot of the prior token ++ // instead of being a head for the following one. Split it up. ++ // Alternatively, this might also be the last comment inside a flow ++ // scope, so it must be a footer. ++ if len(text) > 0 { ++ if start_mark.column-1 < next_indent { ++ // If dedented it's unrelated to the prior token. ++ token_mark = start_mark ++ } ++ parser.comments = append(parser.comments, yaml_comment_t{ ++ scan_mark: scan_mark, ++ token_mark: token_mark, ++ start_mark: start_mark, ++ end_mark: yaml_mark_t{parser.mark.index + peek, line, column}, ++ foot: text, ++ }) ++ scan_mark = yaml_mark_t{parser.mark.index + peek, line, column} ++ token_mark = scan_mark ++ text = nil ++ } ++ } else { ++ if len(text) > 0 && parser.buffer[parser.buffer_pos+peek] != 0 { ++ text = append(text, '\n') ++ } ++ } ++ } ++ if !is_break(parser.buffer, parser.buffer_pos+peek) { ++ break ++ } ++ first_empty = false ++ recent_empty = true ++ column = 0 ++ line++ ++ continue ++ } ++ ++ if len(text) > 0 && (close_flow || column-1 < next_indent && column != start_mark.column) { ++ // The comment at the different indentation is a foot of the ++ // preceding data rather than a head of the upcoming one. ++ parser.comments = append(parser.comments, yaml_comment_t{ ++ scan_mark: scan_mark, ++ token_mark: token_mark, ++ start_mark: start_mark, ++ end_mark: yaml_mark_t{parser.mark.index + peek, line, column}, ++ foot: text, ++ }) ++ scan_mark = yaml_mark_t{parser.mark.index + peek, line, column} ++ token_mark = scan_mark ++ text = nil ++ } ++ ++ if parser.buffer[parser.buffer_pos+peek] != '#' { ++ break ++ } ++ ++ if len(text) == 0 { ++ start_mark = yaml_mark_t{parser.mark.index + peek, line, column} ++ } else { ++ text = append(text, '\n') ++ } ++ ++ recent_empty = false ++ ++ // Consume until after the consumed comment line. ++ seen := parser.mark.index+peek ++ for { ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ if is_breakz(parser.buffer, parser.buffer_pos) { ++ if parser.mark.index >= seen { ++ break ++ } ++ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { ++ return false ++ } ++ skip_line(parser) ++ } else if parser.mark.index >= seen { ++ text = read(parser, text) ++ } else { ++ skip(parser) ++ } ++ } ++ ++ peek = 0 ++ column = 0 ++ line = parser.mark.line ++ next_indent = parser.indent ++ if next_indent < 0 { ++ next_indent = 0 ++ } ++ } ++ ++ if len(text) > 0 { ++ parser.comments = append(parser.comments, yaml_comment_t{ ++ scan_mark: scan_mark, ++ token_mark: start_mark, ++ start_mark: start_mark, ++ end_mark: yaml_mark_t{parser.mark.index + peek - 1, line, column}, ++ head: text, ++ }) ++ } ++ return true ++} +diff --git a/vendor/gopkg.in/yaml.v3/sorter.go b/vendor/gopkg.in/yaml.v3/sorter.go +new file mode 100644 +index 000000000000..9210ece7e972 +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/sorter.go +@@ -0,0 +1,134 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// ++// 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 yaml ++ ++import ( ++ "reflect" ++ "unicode" ++) ++ ++type keyList []reflect.Value ++ ++func (l keyList) Len() int { return len(l) } ++func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } ++func (l keyList) Less(i, j int) bool { ++ a := l[i] ++ b := l[j] ++ ak := a.Kind() ++ bk := b.Kind() ++ for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() { ++ a = a.Elem() ++ ak = a.Kind() ++ } ++ for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() { ++ b = b.Elem() ++ bk = b.Kind() ++ } ++ af, aok := keyFloat(a) ++ bf, bok := keyFloat(b) ++ if aok && bok { ++ if af != bf { ++ return af < bf ++ } ++ if ak != bk { ++ return ak < bk ++ } ++ return numLess(a, b) ++ } ++ if ak != reflect.String || bk != reflect.String { ++ return ak < bk ++ } ++ ar, br := []rune(a.String()), []rune(b.String()) ++ digits := false ++ for i := 0; i < len(ar) && i < len(br); i++ { ++ if ar[i] == br[i] { ++ digits = unicode.IsDigit(ar[i]) ++ continue ++ } ++ al := unicode.IsLetter(ar[i]) ++ bl := unicode.IsLetter(br[i]) ++ if al && bl { ++ return ar[i] < br[i] ++ } ++ if al || bl { ++ if digits { ++ return al ++ } else { ++ return bl ++ } ++ } ++ var ai, bi int ++ var an, bn int64 ++ if ar[i] == '0' || br[i] == '0' { ++ for j := i - 1; j >= 0 && unicode.IsDigit(ar[j]); j-- { ++ if ar[j] != '0' { ++ an = 1 ++ bn = 1 ++ break ++ } ++ } ++ } ++ for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ { ++ an = an*10 + int64(ar[ai]-'0') ++ } ++ for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ { ++ bn = bn*10 + int64(br[bi]-'0') ++ } ++ if an != bn { ++ return an < bn ++ } ++ if ai != bi { ++ return ai < bi ++ } ++ return ar[i] < br[i] ++ } ++ return len(ar) < len(br) ++} ++ ++// keyFloat returns a float value for v if it is a number/bool ++// and whether it is a number/bool or not. ++func keyFloat(v reflect.Value) (f float64, ok bool) { ++ switch v.Kind() { ++ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: ++ return float64(v.Int()), true ++ case reflect.Float32, reflect.Float64: ++ return v.Float(), true ++ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: ++ return float64(v.Uint()), true ++ case reflect.Bool: ++ if v.Bool() { ++ return 1, true ++ } ++ return 0, true ++ } ++ return 0, false ++} ++ ++// numLess returns whether a < b. ++// a and b must necessarily have the same kind. ++func numLess(a, b reflect.Value) bool { ++ switch a.Kind() { ++ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: ++ return a.Int() < b.Int() ++ case reflect.Float32, reflect.Float64: ++ return a.Float() < b.Float() ++ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: ++ return a.Uint() < b.Uint() ++ case reflect.Bool: ++ return !a.Bool() && b.Bool() ++ } ++ panic("not a number") ++} +diff --git a/vendor/gopkg.in/yaml.v3/writerc.go b/vendor/gopkg.in/yaml.v3/writerc.go +new file mode 100644 +index 000000000000..b8a116bf9a22 +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/writerc.go +@@ -0,0 +1,48 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// Copyright (c) 2006-2010 Kirill Simonov ++// ++// 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. ++ ++package yaml ++ ++// Set the writer error and return false. ++func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool { ++ emitter.error = yaml_WRITER_ERROR ++ emitter.problem = problem ++ return false ++} ++ ++// Flush the output buffer. ++func yaml_emitter_flush(emitter *yaml_emitter_t) bool { ++ if emitter.write_handler == nil { ++ panic("write handler not set") ++ } ++ ++ // Check if the buffer is empty. ++ if emitter.buffer_pos == 0 { ++ return true ++ } ++ ++ if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil { ++ return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) ++ } ++ emitter.buffer_pos = 0 ++ return true ++} +diff --git a/vendor/gopkg.in/yaml.v3/yaml.go b/vendor/gopkg.in/yaml.v3/yaml.go +new file mode 100644 +index 000000000000..8cec6da48d3e +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/yaml.go +@@ -0,0 +1,698 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// ++// 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 yaml implements YAML support for the Go language. ++// ++// Source code and other details for the project are available at GitHub: ++// ++// https://github.com/go-yaml/yaml ++// ++package yaml ++ ++import ( ++ "errors" ++ "fmt" ++ "io" ++ "reflect" ++ "strings" ++ "sync" ++ "unicode/utf8" ++) ++ ++// The Unmarshaler interface may be implemented by types to customize their ++// behavior when being unmarshaled from a YAML document. ++type Unmarshaler interface { ++ UnmarshalYAML(value *Node) error ++} ++ ++type obsoleteUnmarshaler interface { ++ UnmarshalYAML(unmarshal func(interface{}) error) error ++} ++ ++// The Marshaler interface may be implemented by types to customize their ++// behavior when being marshaled into a YAML document. The returned value ++// is marshaled in place of the original value implementing Marshaler. ++// ++// If an error is returned by MarshalYAML, the marshaling procedure stops ++// and returns with the provided error. ++type Marshaler interface { ++ MarshalYAML() (interface{}, error) ++} ++ ++// Unmarshal decodes the first document found within the in byte slice ++// and assigns decoded values into the out value. ++// ++// Maps and pointers (to a struct, string, int, etc) are accepted as out ++// values. If an internal pointer within a struct is not initialized, ++// the yaml package will initialize it if necessary for unmarshalling ++// the provided data. The out parameter must not be nil. ++// ++// The type of the decoded values should be compatible with the respective ++// values in out. If one or more values cannot be decoded due to a type ++// mismatches, decoding continues partially until the end of the YAML ++// content, and a *yaml.TypeError is returned with details for all ++// missed values. ++// ++// Struct fields are only unmarshalled if they are exported (have an ++// upper case first letter), and are unmarshalled using the field name ++// lowercased as the default key. Custom keys may be defined via the ++// "yaml" name in the field tag: the content preceding the first comma ++// is used as the key, and the following comma-separated options are ++// used to tweak the marshalling process (see Marshal). ++// Conflicting names result in a runtime error. ++// ++// For example: ++// ++// type T struct { ++// F int `yaml:"a,omitempty"` ++// B int ++// } ++// var t T ++// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t) ++// ++// See the documentation of Marshal for the format of tags and a list of ++// supported tag options. ++// ++func Unmarshal(in []byte, out interface{}) (err error) { ++ return unmarshal(in, out, false) ++} ++ ++// A Decoder reads and decodes YAML values from an input stream. ++type Decoder struct { ++ parser *parser ++ knownFields bool ++} ++ ++// NewDecoder returns a new decoder that reads from r. ++// ++// The decoder introduces its own buffering and may read ++// data from r beyond the YAML values requested. ++func NewDecoder(r io.Reader) *Decoder { ++ return &Decoder{ ++ parser: newParserFromReader(r), ++ } ++} ++ ++// KnownFields ensures that the keys in decoded mappings to ++// exist as fields in the struct being decoded into. ++func (dec *Decoder) KnownFields(enable bool) { ++ dec.knownFields = enable ++} ++ ++// Decode reads the next YAML-encoded value from its input ++// and stores it in the value pointed to by v. ++// ++// See the documentation for Unmarshal for details about the ++// conversion of YAML into a Go value. ++func (dec *Decoder) Decode(v interface{}) (err error) { ++ d := newDecoder() ++ d.knownFields = dec.knownFields ++ defer handleErr(&err) ++ node := dec.parser.parse() ++ if node == nil { ++ return io.EOF ++ } ++ out := reflect.ValueOf(v) ++ if out.Kind() == reflect.Ptr && !out.IsNil() { ++ out = out.Elem() ++ } ++ d.unmarshal(node, out) ++ if len(d.terrors) > 0 { ++ return &TypeError{d.terrors} ++ } ++ return nil ++} ++ ++// Decode decodes the node and stores its data into the value pointed to by v. ++// ++// See the documentation for Unmarshal for details about the ++// conversion of YAML into a Go value. ++func (n *Node) Decode(v interface{}) (err error) { ++ d := newDecoder() ++ defer handleErr(&err) ++ out := reflect.ValueOf(v) ++ if out.Kind() == reflect.Ptr && !out.IsNil() { ++ out = out.Elem() ++ } ++ d.unmarshal(n, out) ++ if len(d.terrors) > 0 { ++ return &TypeError{d.terrors} ++ } ++ return nil ++} ++ ++func unmarshal(in []byte, out interface{}, strict bool) (err error) { ++ defer handleErr(&err) ++ d := newDecoder() ++ p := newParser(in) ++ defer p.destroy() ++ node := p.parse() ++ if node != nil { ++ v := reflect.ValueOf(out) ++ if v.Kind() == reflect.Ptr && !v.IsNil() { ++ v = v.Elem() ++ } ++ d.unmarshal(node, v) ++ } ++ if len(d.terrors) > 0 { ++ return &TypeError{d.terrors} ++ } ++ return nil ++} ++ ++// Marshal serializes the value provided into a YAML document. The structure ++// of the generated document will reflect the structure of the value itself. ++// Maps and pointers (to struct, string, int, etc) are accepted as the in value. ++// ++// Struct fields are only marshalled if they are exported (have an upper case ++// first letter), and are marshalled using the field name lowercased as the ++// default key. Custom keys may be defined via the "yaml" name in the field ++// tag: the content preceding the first comma is used as the key, and the ++// following comma-separated options are used to tweak the marshalling process. ++// Conflicting names result in a runtime error. ++// ++// The field tag format accepted is: ++// ++// `(...) yaml:"[][,[,]]" (...)` ++// ++// The following flags are currently supported: ++// ++// omitempty Only include the field if it's not set to the zero ++// value for the type or to empty slices or maps. ++// Zero valued structs will be omitted if all their public ++// fields are zero, unless they implement an IsZero ++// method (see the IsZeroer interface type), in which ++// case the field will be excluded if IsZero returns true. ++// ++// flow Marshal using a flow style (useful for structs, ++// sequences and maps). ++// ++// inline Inline the field, which must be a struct or a map, ++// causing all of its fields or keys to be processed as if ++// they were part of the outer struct. For maps, keys must ++// not conflict with the yaml keys of other struct fields. ++// ++// In addition, if the key is "-", the field is ignored. ++// ++// For example: ++// ++// type T struct { ++// F int `yaml:"a,omitempty"` ++// B int ++// } ++// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n" ++// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n" ++// ++func Marshal(in interface{}) (out []byte, err error) { ++ defer handleErr(&err) ++ e := newEncoder() ++ defer e.destroy() ++ e.marshalDoc("", reflect.ValueOf(in)) ++ e.finish() ++ out = e.out ++ return ++} ++ ++// An Encoder writes YAML values to an output stream. ++type Encoder struct { ++ encoder *encoder ++} ++ ++// NewEncoder returns a new encoder that writes to w. ++// The Encoder should be closed after use to flush all data ++// to w. ++func NewEncoder(w io.Writer) *Encoder { ++ return &Encoder{ ++ encoder: newEncoderWithWriter(w), ++ } ++} ++ ++// Encode writes the YAML encoding of v to the stream. ++// If multiple items are encoded to the stream, the ++// second and subsequent document will be preceded ++// with a "---" document separator, but the first will not. ++// ++// See the documentation for Marshal for details about the conversion of Go ++// values to YAML. ++func (e *Encoder) Encode(v interface{}) (err error) { ++ defer handleErr(&err) ++ e.encoder.marshalDoc("", reflect.ValueOf(v)) ++ return nil ++} ++ ++// Encode encodes value v and stores its representation in n. ++// ++// See the documentation for Marshal for details about the ++// conversion of Go values into YAML. ++func (n *Node) Encode(v interface{}) (err error) { ++ defer handleErr(&err) ++ e := newEncoder() ++ defer e.destroy() ++ e.marshalDoc("", reflect.ValueOf(v)) ++ e.finish() ++ p := newParser(e.out) ++ p.textless = true ++ defer p.destroy() ++ doc := p.parse() ++ *n = *doc.Content[0] ++ return nil ++} ++ ++// SetIndent changes the used indentation used when encoding. ++func (e *Encoder) SetIndent(spaces int) { ++ if spaces < 0 { ++ panic("yaml: cannot indent to a negative number of spaces") ++ } ++ e.encoder.indent = spaces ++} ++ ++// Close closes the encoder by writing any remaining data. ++// It does not write a stream terminating string "...". ++func (e *Encoder) Close() (err error) { ++ defer handleErr(&err) ++ e.encoder.finish() ++ return nil ++} ++ ++func handleErr(err *error) { ++ if v := recover(); v != nil { ++ if e, ok := v.(yamlError); ok { ++ *err = e.err ++ } else { ++ panic(v) ++ } ++ } ++} ++ ++type yamlError struct { ++ err error ++} ++ ++func fail(err error) { ++ panic(yamlError{err}) ++} ++ ++func failf(format string, args ...interface{}) { ++ panic(yamlError{fmt.Errorf("yaml: "+format, args...)}) ++} ++ ++// A TypeError is returned by Unmarshal when one or more fields in ++// the YAML document cannot be properly decoded into the requested ++// types. When this error is returned, the value is still ++// unmarshaled partially. ++type TypeError struct { ++ Errors []string ++} ++ ++func (e *TypeError) Error() string { ++ return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n ")) ++} ++ ++type Kind uint32 ++ ++const ( ++ DocumentNode Kind = 1 << iota ++ SequenceNode ++ MappingNode ++ ScalarNode ++ AliasNode ++) ++ ++type Style uint32 ++ ++const ( ++ TaggedStyle Style = 1 << iota ++ DoubleQuotedStyle ++ SingleQuotedStyle ++ LiteralStyle ++ FoldedStyle ++ FlowStyle ++) ++ ++// Node represents an element in the YAML document hierarchy. While documents ++// are typically encoded and decoded into higher level types, such as structs ++// and maps, Node is an intermediate representation that allows detailed ++// control over the content being decoded or encoded. ++// ++// It's worth noting that although Node offers access into details such as ++// line numbers, colums, and comments, the content when re-encoded will not ++// have its original textual representation preserved. An effort is made to ++// render the data plesantly, and to preserve comments near the data they ++// describe, though. ++// ++// Values that make use of the Node type interact with the yaml package in the ++// same way any other type would do, by encoding and decoding yaml data ++// directly or indirectly into them. ++// ++// For example: ++// ++// var person struct { ++// Name string ++// Address yaml.Node ++// } ++// err := yaml.Unmarshal(data, &person) ++// ++// Or by itself: ++// ++// var person Node ++// err := yaml.Unmarshal(data, &person) ++// ++type Node struct { ++ // Kind defines whether the node is a document, a mapping, a sequence, ++ // a scalar value, or an alias to another node. The specific data type of ++ // scalar nodes may be obtained via the ShortTag and LongTag methods. ++ Kind Kind ++ ++ // Style allows customizing the apperance of the node in the tree. ++ Style Style ++ ++ // Tag holds the YAML tag defining the data type for the value. ++ // When decoding, this field will always be set to the resolved tag, ++ // even when it wasn't explicitly provided in the YAML content. ++ // When encoding, if this field is unset the value type will be ++ // implied from the node properties, and if it is set, it will only ++ // be serialized into the representation if TaggedStyle is used or ++ // the implicit tag diverges from the provided one. ++ Tag string ++ ++ // Value holds the unescaped and unquoted represenation of the value. ++ Value string ++ ++ // Anchor holds the anchor name for this node, which allows aliases to point to it. ++ Anchor string ++ ++ // Alias holds the node that this alias points to. Only valid when Kind is AliasNode. ++ Alias *Node ++ ++ // Content holds contained nodes for documents, mappings, and sequences. ++ Content []*Node ++ ++ // HeadComment holds any comments in the lines preceding the node and ++ // not separated by an empty line. ++ HeadComment string ++ ++ // LineComment holds any comments at the end of the line where the node is in. ++ LineComment string ++ ++ // FootComment holds any comments following the node and before empty lines. ++ FootComment string ++ ++ // Line and Column hold the node position in the decoded YAML text. ++ // These fields are not respected when encoding the node. ++ Line int ++ Column int ++} ++ ++// IsZero returns whether the node has all of its fields unset. ++func (n *Node) IsZero() bool { ++ return n.Kind == 0 && n.Style == 0 && n.Tag == "" && n.Value == "" && n.Anchor == "" && n.Alias == nil && n.Content == nil && ++ n.HeadComment == "" && n.LineComment == "" && n.FootComment == "" && n.Line == 0 && n.Column == 0 ++} ++ ++ ++// LongTag returns the long form of the tag that indicates the data type for ++// the node. If the Tag field isn't explicitly defined, one will be computed ++// based on the node properties. ++func (n *Node) LongTag() string { ++ return longTag(n.ShortTag()) ++} ++ ++// ShortTag returns the short form of the YAML tag that indicates data type for ++// the node. If the Tag field isn't explicitly defined, one will be computed ++// based on the node properties. ++func (n *Node) ShortTag() string { ++ if n.indicatedString() { ++ return strTag ++ } ++ if n.Tag == "" || n.Tag == "!" { ++ switch n.Kind { ++ case MappingNode: ++ return mapTag ++ case SequenceNode: ++ return seqTag ++ case AliasNode: ++ if n.Alias != nil { ++ return n.Alias.ShortTag() ++ } ++ case ScalarNode: ++ tag, _ := resolve("", n.Value) ++ return tag ++ case 0: ++ // Special case to make the zero value convenient. ++ if n.IsZero() { ++ return nullTag ++ } ++ } ++ return "" ++ } ++ return shortTag(n.Tag) ++} ++ ++func (n *Node) indicatedString() bool { ++ return n.Kind == ScalarNode && ++ (shortTag(n.Tag) == strTag || ++ (n.Tag == "" || n.Tag == "!") && n.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0) ++} ++ ++// SetString is a convenience function that sets the node to a string value ++// and defines its style in a pleasant way depending on its content. ++func (n *Node) SetString(s string) { ++ n.Kind = ScalarNode ++ if utf8.ValidString(s) { ++ n.Value = s ++ n.Tag = strTag ++ } else { ++ n.Value = encodeBase64(s) ++ n.Tag = binaryTag ++ } ++ if strings.Contains(n.Value, "\n") { ++ n.Style = LiteralStyle ++ } ++} ++ ++// -------------------------------------------------------------------------- ++// Maintain a mapping of keys to structure field indexes ++ ++// The code in this section was copied from mgo/bson. ++ ++// structInfo holds details for the serialization of fields of ++// a given struct. ++type structInfo struct { ++ FieldsMap map[string]fieldInfo ++ FieldsList []fieldInfo ++ ++ // InlineMap is the number of the field in the struct that ++ // contains an ,inline map, or -1 if there's none. ++ InlineMap int ++ ++ // InlineUnmarshalers holds indexes to inlined fields that ++ // contain unmarshaler values. ++ InlineUnmarshalers [][]int ++} ++ ++type fieldInfo struct { ++ Key string ++ Num int ++ OmitEmpty bool ++ Flow bool ++ // Id holds the unique field identifier, so we can cheaply ++ // check for field duplicates without maintaining an extra map. ++ Id int ++ ++ // Inline holds the field index if the field is part of an inlined struct. ++ Inline []int ++} ++ ++var structMap = make(map[reflect.Type]*structInfo) ++var fieldMapMutex sync.RWMutex ++var unmarshalerType reflect.Type ++ ++func init() { ++ var v Unmarshaler ++ unmarshalerType = reflect.ValueOf(&v).Elem().Type() ++} ++ ++func getStructInfo(st reflect.Type) (*structInfo, error) { ++ fieldMapMutex.RLock() ++ sinfo, found := structMap[st] ++ fieldMapMutex.RUnlock() ++ if found { ++ return sinfo, nil ++ } ++ ++ n := st.NumField() ++ fieldsMap := make(map[string]fieldInfo) ++ fieldsList := make([]fieldInfo, 0, n) ++ inlineMap := -1 ++ inlineUnmarshalers := [][]int(nil) ++ for i := 0; i != n; i++ { ++ field := st.Field(i) ++ if field.PkgPath != "" && !field.Anonymous { ++ continue // Private field ++ } ++ ++ info := fieldInfo{Num: i} ++ ++ tag := field.Tag.Get("yaml") ++ if tag == "" && strings.Index(string(field.Tag), ":") < 0 { ++ tag = string(field.Tag) ++ } ++ if tag == "-" { ++ continue ++ } ++ ++ inline := false ++ fields := strings.Split(tag, ",") ++ if len(fields) > 1 { ++ for _, flag := range fields[1:] { ++ switch flag { ++ case "omitempty": ++ info.OmitEmpty = true ++ case "flow": ++ info.Flow = true ++ case "inline": ++ inline = true ++ default: ++ return nil, errors.New(fmt.Sprintf("unsupported flag %q in tag %q of type %s", flag, tag, st)) ++ } ++ } ++ tag = fields[0] ++ } ++ ++ if inline { ++ switch field.Type.Kind() { ++ case reflect.Map: ++ if inlineMap >= 0 { ++ return nil, errors.New("multiple ,inline maps in struct " + st.String()) ++ } ++ if field.Type.Key() != reflect.TypeOf("") { ++ return nil, errors.New("option ,inline needs a map with string keys in struct " + st.String()) ++ } ++ inlineMap = info.Num ++ case reflect.Struct, reflect.Ptr: ++ ftype := field.Type ++ for ftype.Kind() == reflect.Ptr { ++ ftype = ftype.Elem() ++ } ++ if ftype.Kind() != reflect.Struct { ++ return nil, errors.New("option ,inline may only be used on a struct or map field") ++ } ++ if reflect.PtrTo(ftype).Implements(unmarshalerType) { ++ inlineUnmarshalers = append(inlineUnmarshalers, []int{i}) ++ } else { ++ sinfo, err := getStructInfo(ftype) ++ if err != nil { ++ return nil, err ++ } ++ for _, index := range sinfo.InlineUnmarshalers { ++ inlineUnmarshalers = append(inlineUnmarshalers, append([]int{i}, index...)) ++ } ++ for _, finfo := range sinfo.FieldsList { ++ if _, found := fieldsMap[finfo.Key]; found { ++ msg := "duplicated key '" + finfo.Key + "' in struct " + st.String() ++ return nil, errors.New(msg) ++ } ++ if finfo.Inline == nil { ++ finfo.Inline = []int{i, finfo.Num} ++ } else { ++ finfo.Inline = append([]int{i}, finfo.Inline...) ++ } ++ finfo.Id = len(fieldsList) ++ fieldsMap[finfo.Key] = finfo ++ fieldsList = append(fieldsList, finfo) ++ } ++ } ++ default: ++ return nil, errors.New("option ,inline may only be used on a struct or map field") ++ } ++ continue ++ } ++ ++ if tag != "" { ++ info.Key = tag ++ } else { ++ info.Key = strings.ToLower(field.Name) ++ } ++ ++ if _, found = fieldsMap[info.Key]; found { ++ msg := "duplicated key '" + info.Key + "' in struct " + st.String() ++ return nil, errors.New(msg) ++ } ++ ++ info.Id = len(fieldsList) ++ fieldsList = append(fieldsList, info) ++ fieldsMap[info.Key] = info ++ } ++ ++ sinfo = &structInfo{ ++ FieldsMap: fieldsMap, ++ FieldsList: fieldsList, ++ InlineMap: inlineMap, ++ InlineUnmarshalers: inlineUnmarshalers, ++ } ++ ++ fieldMapMutex.Lock() ++ structMap[st] = sinfo ++ fieldMapMutex.Unlock() ++ return sinfo, nil ++} ++ ++// IsZeroer is used to check whether an object is zero to ++// determine whether it should be omitted when marshaling ++// with the omitempty flag. One notable implementation ++// is time.Time. ++type IsZeroer interface { ++ IsZero() bool ++} ++ ++func isZero(v reflect.Value) bool { ++ kind := v.Kind() ++ if z, ok := v.Interface().(IsZeroer); ok { ++ if (kind == reflect.Ptr || kind == reflect.Interface) && v.IsNil() { ++ return true ++ } ++ return z.IsZero() ++ } ++ switch kind { ++ case reflect.String: ++ return len(v.String()) == 0 ++ case reflect.Interface, reflect.Ptr: ++ return v.IsNil() ++ case reflect.Slice: ++ return v.Len() == 0 ++ case reflect.Map: ++ return v.Len() == 0 ++ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: ++ return v.Int() == 0 ++ case reflect.Float32, reflect.Float64: ++ return v.Float() == 0 ++ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: ++ return v.Uint() == 0 ++ case reflect.Bool: ++ return !v.Bool() ++ case reflect.Struct: ++ vt := v.Type() ++ for i := v.NumField() - 1; i >= 0; i-- { ++ if vt.Field(i).PkgPath != "" { ++ continue // Private field ++ } ++ if !isZero(v.Field(i)) { ++ return false ++ } ++ } ++ return true ++ } ++ return false ++} +diff --git a/vendor/gopkg.in/yaml.v3/yamlh.go b/vendor/gopkg.in/yaml.v3/yamlh.go +new file mode 100644 +index 000000000000..7c6d00770619 +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/yamlh.go +@@ -0,0 +1,807 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// Copyright (c) 2006-2010 Kirill Simonov ++// ++// 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. ++ ++package yaml ++ ++import ( ++ "fmt" ++ "io" ++) ++ ++// The version directive data. ++type yaml_version_directive_t struct { ++ major int8 // The major version number. ++ minor int8 // The minor version number. ++} ++ ++// The tag directive data. ++type yaml_tag_directive_t struct { ++ handle []byte // The tag handle. ++ prefix []byte // The tag prefix. ++} ++ ++type yaml_encoding_t int ++ ++// The stream encoding. ++const ( ++ // Let the parser choose the encoding. ++ yaml_ANY_ENCODING yaml_encoding_t = iota ++ ++ yaml_UTF8_ENCODING // The default UTF-8 encoding. ++ yaml_UTF16LE_ENCODING // The UTF-16-LE encoding with BOM. ++ yaml_UTF16BE_ENCODING // The UTF-16-BE encoding with BOM. ++) ++ ++type yaml_break_t int ++ ++// Line break types. ++const ( ++ // Let the parser choose the break type. ++ yaml_ANY_BREAK yaml_break_t = iota ++ ++ yaml_CR_BREAK // Use CR for line breaks (Mac style). ++ yaml_LN_BREAK // Use LN for line breaks (Unix style). ++ yaml_CRLN_BREAK // Use CR LN for line breaks (DOS style). ++) ++ ++type yaml_error_type_t int ++ ++// Many bad things could happen with the parser and emitter. ++const ( ++ // No error is produced. ++ yaml_NO_ERROR yaml_error_type_t = iota ++ ++ yaml_MEMORY_ERROR // Cannot allocate or reallocate a block of memory. ++ yaml_READER_ERROR // Cannot read or decode the input stream. ++ yaml_SCANNER_ERROR // Cannot scan the input stream. ++ yaml_PARSER_ERROR // Cannot parse the input stream. ++ yaml_COMPOSER_ERROR // Cannot compose a YAML document. ++ yaml_WRITER_ERROR // Cannot write to the output stream. ++ yaml_EMITTER_ERROR // Cannot emit a YAML stream. ++) ++ ++// The pointer position. ++type yaml_mark_t struct { ++ index int // The position index. ++ line int // The position line. ++ column int // The position column. ++} ++ ++// Node Styles ++ ++type yaml_style_t int8 ++ ++type yaml_scalar_style_t yaml_style_t ++ ++// Scalar styles. ++const ( ++ // Let the emitter choose the style. ++ yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = 0 ++ ++ yaml_PLAIN_SCALAR_STYLE yaml_scalar_style_t = 1 << iota // The plain scalar style. ++ yaml_SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style. ++ yaml_DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style. ++ yaml_LITERAL_SCALAR_STYLE // The literal scalar style. ++ yaml_FOLDED_SCALAR_STYLE // The folded scalar style. ++) ++ ++type yaml_sequence_style_t yaml_style_t ++ ++// Sequence styles. ++const ( ++ // Let the emitter choose the style. ++ yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota ++ ++ yaml_BLOCK_SEQUENCE_STYLE // The block sequence style. ++ yaml_FLOW_SEQUENCE_STYLE // The flow sequence style. ++) ++ ++type yaml_mapping_style_t yaml_style_t ++ ++// Mapping styles. ++const ( ++ // Let the emitter choose the style. ++ yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota ++ ++ yaml_BLOCK_MAPPING_STYLE // The block mapping style. ++ yaml_FLOW_MAPPING_STYLE // The flow mapping style. ++) ++ ++// Tokens ++ ++type yaml_token_type_t int ++ ++// Token types. ++const ( ++ // An empty token. ++ yaml_NO_TOKEN yaml_token_type_t = iota ++ ++ yaml_STREAM_START_TOKEN // A STREAM-START token. ++ yaml_STREAM_END_TOKEN // A STREAM-END token. ++ ++ yaml_VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token. ++ yaml_TAG_DIRECTIVE_TOKEN // A TAG-DIRECTIVE token. ++ yaml_DOCUMENT_START_TOKEN // A DOCUMENT-START token. ++ yaml_DOCUMENT_END_TOKEN // A DOCUMENT-END token. ++ ++ yaml_BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token. ++ yaml_BLOCK_MAPPING_START_TOKEN // A BLOCK-SEQUENCE-END token. ++ yaml_BLOCK_END_TOKEN // A BLOCK-END token. ++ ++ yaml_FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token. ++ yaml_FLOW_SEQUENCE_END_TOKEN // A FLOW-SEQUENCE-END token. ++ yaml_FLOW_MAPPING_START_TOKEN // A FLOW-MAPPING-START token. ++ yaml_FLOW_MAPPING_END_TOKEN // A FLOW-MAPPING-END token. ++ ++ yaml_BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token. ++ yaml_FLOW_ENTRY_TOKEN // A FLOW-ENTRY token. ++ yaml_KEY_TOKEN // A KEY token. ++ yaml_VALUE_TOKEN // A VALUE token. ++ ++ yaml_ALIAS_TOKEN // An ALIAS token. ++ yaml_ANCHOR_TOKEN // An ANCHOR token. ++ yaml_TAG_TOKEN // A TAG token. ++ yaml_SCALAR_TOKEN // A SCALAR token. ++) ++ ++func (tt yaml_token_type_t) String() string { ++ switch tt { ++ case yaml_NO_TOKEN: ++ return "yaml_NO_TOKEN" ++ case yaml_STREAM_START_TOKEN: ++ return "yaml_STREAM_START_TOKEN" ++ case yaml_STREAM_END_TOKEN: ++ return "yaml_STREAM_END_TOKEN" ++ case yaml_VERSION_DIRECTIVE_TOKEN: ++ return "yaml_VERSION_DIRECTIVE_TOKEN" ++ case yaml_TAG_DIRECTIVE_TOKEN: ++ return "yaml_TAG_DIRECTIVE_TOKEN" ++ case yaml_DOCUMENT_START_TOKEN: ++ return "yaml_DOCUMENT_START_TOKEN" ++ case yaml_DOCUMENT_END_TOKEN: ++ return "yaml_DOCUMENT_END_TOKEN" ++ case yaml_BLOCK_SEQUENCE_START_TOKEN: ++ return "yaml_BLOCK_SEQUENCE_START_TOKEN" ++ case yaml_BLOCK_MAPPING_START_TOKEN: ++ return "yaml_BLOCK_MAPPING_START_TOKEN" ++ case yaml_BLOCK_END_TOKEN: ++ return "yaml_BLOCK_END_TOKEN" ++ case yaml_FLOW_SEQUENCE_START_TOKEN: ++ return "yaml_FLOW_SEQUENCE_START_TOKEN" ++ case yaml_FLOW_SEQUENCE_END_TOKEN: ++ return "yaml_FLOW_SEQUENCE_END_TOKEN" ++ case yaml_FLOW_MAPPING_START_TOKEN: ++ return "yaml_FLOW_MAPPING_START_TOKEN" ++ case yaml_FLOW_MAPPING_END_TOKEN: ++ return "yaml_FLOW_MAPPING_END_TOKEN" ++ case yaml_BLOCK_ENTRY_TOKEN: ++ return "yaml_BLOCK_ENTRY_TOKEN" ++ case yaml_FLOW_ENTRY_TOKEN: ++ return "yaml_FLOW_ENTRY_TOKEN" ++ case yaml_KEY_TOKEN: ++ return "yaml_KEY_TOKEN" ++ case yaml_VALUE_TOKEN: ++ return "yaml_VALUE_TOKEN" ++ case yaml_ALIAS_TOKEN: ++ return "yaml_ALIAS_TOKEN" ++ case yaml_ANCHOR_TOKEN: ++ return "yaml_ANCHOR_TOKEN" ++ case yaml_TAG_TOKEN: ++ return "yaml_TAG_TOKEN" ++ case yaml_SCALAR_TOKEN: ++ return "yaml_SCALAR_TOKEN" ++ } ++ return "" ++} ++ ++// The token structure. ++type yaml_token_t struct { ++ // The token type. ++ typ yaml_token_type_t ++ ++ // The start/end of the token. ++ start_mark, end_mark yaml_mark_t ++ ++ // The stream encoding (for yaml_STREAM_START_TOKEN). ++ encoding yaml_encoding_t ++ ++ // The alias/anchor/scalar value or tag/tag directive handle ++ // (for yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN, yaml_TAG_TOKEN, yaml_TAG_DIRECTIVE_TOKEN). ++ value []byte ++ ++ // The tag suffix (for yaml_TAG_TOKEN). ++ suffix []byte ++ ++ // The tag directive prefix (for yaml_TAG_DIRECTIVE_TOKEN). ++ prefix []byte ++ ++ // The scalar style (for yaml_SCALAR_TOKEN). ++ style yaml_scalar_style_t ++ ++ // The version directive major/minor (for yaml_VERSION_DIRECTIVE_TOKEN). ++ major, minor int8 ++} ++ ++// Events ++ ++type yaml_event_type_t int8 ++ ++// Event types. ++const ( ++ // An empty event. ++ yaml_NO_EVENT yaml_event_type_t = iota ++ ++ yaml_STREAM_START_EVENT // A STREAM-START event. ++ yaml_STREAM_END_EVENT // A STREAM-END event. ++ yaml_DOCUMENT_START_EVENT // A DOCUMENT-START event. ++ yaml_DOCUMENT_END_EVENT // A DOCUMENT-END event. ++ yaml_ALIAS_EVENT // An ALIAS event. ++ yaml_SCALAR_EVENT // A SCALAR event. ++ yaml_SEQUENCE_START_EVENT // A SEQUENCE-START event. ++ yaml_SEQUENCE_END_EVENT // A SEQUENCE-END event. ++ yaml_MAPPING_START_EVENT // A MAPPING-START event. ++ yaml_MAPPING_END_EVENT // A MAPPING-END event. ++ yaml_TAIL_COMMENT_EVENT ++) ++ ++var eventStrings = []string{ ++ yaml_NO_EVENT: "none", ++ yaml_STREAM_START_EVENT: "stream start", ++ yaml_STREAM_END_EVENT: "stream end", ++ yaml_DOCUMENT_START_EVENT: "document start", ++ yaml_DOCUMENT_END_EVENT: "document end", ++ yaml_ALIAS_EVENT: "alias", ++ yaml_SCALAR_EVENT: "scalar", ++ yaml_SEQUENCE_START_EVENT: "sequence start", ++ yaml_SEQUENCE_END_EVENT: "sequence end", ++ yaml_MAPPING_START_EVENT: "mapping start", ++ yaml_MAPPING_END_EVENT: "mapping end", ++ yaml_TAIL_COMMENT_EVENT: "tail comment", ++} ++ ++func (e yaml_event_type_t) String() string { ++ if e < 0 || int(e) >= len(eventStrings) { ++ return fmt.Sprintf("unknown event %d", e) ++ } ++ return eventStrings[e] ++} ++ ++// The event structure. ++type yaml_event_t struct { ++ ++ // The event type. ++ typ yaml_event_type_t ++ ++ // The start and end of the event. ++ start_mark, end_mark yaml_mark_t ++ ++ // The document encoding (for yaml_STREAM_START_EVENT). ++ encoding yaml_encoding_t ++ ++ // The version directive (for yaml_DOCUMENT_START_EVENT). ++ version_directive *yaml_version_directive_t ++ ++ // The list of tag directives (for yaml_DOCUMENT_START_EVENT). ++ tag_directives []yaml_tag_directive_t ++ ++ // The comments ++ head_comment []byte ++ line_comment []byte ++ foot_comment []byte ++ tail_comment []byte ++ ++ // The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT). ++ anchor []byte ++ ++ // The tag (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). ++ tag []byte ++ ++ // The scalar value (for yaml_SCALAR_EVENT). ++ value []byte ++ ++ // Is the document start/end indicator implicit, or the tag optional? ++ // (for yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_SCALAR_EVENT). ++ implicit bool ++ ++ // Is the tag optional for any non-plain style? (for yaml_SCALAR_EVENT). ++ quoted_implicit bool ++ ++ // The style (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). ++ style yaml_style_t ++} ++ ++func (e *yaml_event_t) scalar_style() yaml_scalar_style_t { return yaml_scalar_style_t(e.style) } ++func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return yaml_sequence_style_t(e.style) } ++func (e *yaml_event_t) mapping_style() yaml_mapping_style_t { return yaml_mapping_style_t(e.style) } ++ ++// Nodes ++ ++const ( ++ yaml_NULL_TAG = "tag:yaml.org,2002:null" // The tag !!null with the only possible value: null. ++ yaml_BOOL_TAG = "tag:yaml.org,2002:bool" // The tag !!bool with the values: true and false. ++ yaml_STR_TAG = "tag:yaml.org,2002:str" // The tag !!str for string values. ++ yaml_INT_TAG = "tag:yaml.org,2002:int" // The tag !!int for integer values. ++ yaml_FLOAT_TAG = "tag:yaml.org,2002:float" // The tag !!float for float values. ++ yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values. ++ ++ yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences. ++ yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping. ++ ++ // Not in original libyaml. ++ yaml_BINARY_TAG = "tag:yaml.org,2002:binary" ++ yaml_MERGE_TAG = "tag:yaml.org,2002:merge" ++ ++ yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str. ++ yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq. ++ yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map. ++) ++ ++type yaml_node_type_t int ++ ++// Node types. ++const ( ++ // An empty node. ++ yaml_NO_NODE yaml_node_type_t = iota ++ ++ yaml_SCALAR_NODE // A scalar node. ++ yaml_SEQUENCE_NODE // A sequence node. ++ yaml_MAPPING_NODE // A mapping node. ++) ++ ++// An element of a sequence node. ++type yaml_node_item_t int ++ ++// An element of a mapping node. ++type yaml_node_pair_t struct { ++ key int // The key of the element. ++ value int // The value of the element. ++} ++ ++// The node structure. ++type yaml_node_t struct { ++ typ yaml_node_type_t // The node type. ++ tag []byte // The node tag. ++ ++ // The node data. ++ ++ // The scalar parameters (for yaml_SCALAR_NODE). ++ scalar struct { ++ value []byte // The scalar value. ++ length int // The length of the scalar value. ++ style yaml_scalar_style_t // The scalar style. ++ } ++ ++ // The sequence parameters (for YAML_SEQUENCE_NODE). ++ sequence struct { ++ items_data []yaml_node_item_t // The stack of sequence items. ++ style yaml_sequence_style_t // The sequence style. ++ } ++ ++ // The mapping parameters (for yaml_MAPPING_NODE). ++ mapping struct { ++ pairs_data []yaml_node_pair_t // The stack of mapping pairs (key, value). ++ pairs_start *yaml_node_pair_t // The beginning of the stack. ++ pairs_end *yaml_node_pair_t // The end of the stack. ++ pairs_top *yaml_node_pair_t // The top of the stack. ++ style yaml_mapping_style_t // The mapping style. ++ } ++ ++ start_mark yaml_mark_t // The beginning of the node. ++ end_mark yaml_mark_t // The end of the node. ++ ++} ++ ++// The document structure. ++type yaml_document_t struct { ++ ++ // The document nodes. ++ nodes []yaml_node_t ++ ++ // The version directive. ++ version_directive *yaml_version_directive_t ++ ++ // The list of tag directives. ++ tag_directives_data []yaml_tag_directive_t ++ tag_directives_start int // The beginning of the tag directives list. ++ tag_directives_end int // The end of the tag directives list. ++ ++ start_implicit int // Is the document start indicator implicit? ++ end_implicit int // Is the document end indicator implicit? ++ ++ // The start/end of the document. ++ start_mark, end_mark yaml_mark_t ++} ++ ++// The prototype of a read handler. ++// ++// The read handler is called when the parser needs to read more bytes from the ++// source. The handler should write not more than size bytes to the buffer. ++// The number of written bytes should be set to the size_read variable. ++// ++// [in,out] data A pointer to an application data specified by ++// yaml_parser_set_input(). ++// [out] buffer The buffer to write the data from the source. ++// [in] size The size of the buffer. ++// [out] size_read The actual number of bytes read from the source. ++// ++// On success, the handler should return 1. If the handler failed, ++// the returned value should be 0. On EOF, the handler should set the ++// size_read to 0 and return 1. ++type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error) ++ ++// This structure holds information about a potential simple key. ++type yaml_simple_key_t struct { ++ possible bool // Is a simple key possible? ++ required bool // Is a simple key required? ++ token_number int // The number of the token. ++ mark yaml_mark_t // The position mark. ++} ++ ++// The states of the parser. ++type yaml_parser_state_t int ++ ++const ( ++ yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota ++ ++ yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE // Expect the beginning of an implicit document. ++ yaml_PARSE_DOCUMENT_START_STATE // Expect DOCUMENT-START. ++ yaml_PARSE_DOCUMENT_CONTENT_STATE // Expect the content of a document. ++ yaml_PARSE_DOCUMENT_END_STATE // Expect DOCUMENT-END. ++ yaml_PARSE_BLOCK_NODE_STATE // Expect a block node. ++ yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE // Expect a block node or indentless sequence. ++ yaml_PARSE_FLOW_NODE_STATE // Expect a flow node. ++ yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a block sequence. ++ yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE // Expect an entry of a block sequence. ++ yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE // Expect an entry of an indentless sequence. ++ yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. ++ yaml_PARSE_BLOCK_MAPPING_KEY_STATE // Expect a block mapping key. ++ yaml_PARSE_BLOCK_MAPPING_VALUE_STATE // Expect a block mapping value. ++ yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a flow sequence. ++ yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE // Expect an entry of a flow sequence. ++ yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE // Expect a key of an ordered mapping. ++ yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping. ++ yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE // Expect the and of an ordered mapping entry. ++ yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. ++ yaml_PARSE_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. ++ yaml_PARSE_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. ++ yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE // Expect an empty value of a flow mapping. ++ yaml_PARSE_END_STATE // Expect nothing. ++) ++ ++func (ps yaml_parser_state_t) String() string { ++ switch ps { ++ case yaml_PARSE_STREAM_START_STATE: ++ return "yaml_PARSE_STREAM_START_STATE" ++ case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE: ++ return "yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE" ++ case yaml_PARSE_DOCUMENT_START_STATE: ++ return "yaml_PARSE_DOCUMENT_START_STATE" ++ case yaml_PARSE_DOCUMENT_CONTENT_STATE: ++ return "yaml_PARSE_DOCUMENT_CONTENT_STATE" ++ case yaml_PARSE_DOCUMENT_END_STATE: ++ return "yaml_PARSE_DOCUMENT_END_STATE" ++ case yaml_PARSE_BLOCK_NODE_STATE: ++ return "yaml_PARSE_BLOCK_NODE_STATE" ++ case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: ++ return "yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE" ++ case yaml_PARSE_FLOW_NODE_STATE: ++ return "yaml_PARSE_FLOW_NODE_STATE" ++ case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: ++ return "yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE" ++ case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: ++ return "yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE" ++ case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: ++ return "yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE" ++ case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: ++ return "yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE" ++ case yaml_PARSE_BLOCK_MAPPING_KEY_STATE: ++ return "yaml_PARSE_BLOCK_MAPPING_KEY_STATE" ++ case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE: ++ return "yaml_PARSE_BLOCK_MAPPING_VALUE_STATE" ++ case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: ++ return "yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE" ++ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE: ++ return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE" ++ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: ++ return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE" ++ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: ++ return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE" ++ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: ++ return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE" ++ case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: ++ return "yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE" ++ case yaml_PARSE_FLOW_MAPPING_KEY_STATE: ++ return "yaml_PARSE_FLOW_MAPPING_KEY_STATE" ++ case yaml_PARSE_FLOW_MAPPING_VALUE_STATE: ++ return "yaml_PARSE_FLOW_MAPPING_VALUE_STATE" ++ case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: ++ return "yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE" ++ case yaml_PARSE_END_STATE: ++ return "yaml_PARSE_END_STATE" ++ } ++ return "" ++} ++ ++// This structure holds aliases data. ++type yaml_alias_data_t struct { ++ anchor []byte // The anchor. ++ index int // The node id. ++ mark yaml_mark_t // The anchor mark. ++} ++ ++// The parser structure. ++// ++// All members are internal. Manage the structure using the ++// yaml_parser_ family of functions. ++type yaml_parser_t struct { ++ ++ // Error handling ++ ++ error yaml_error_type_t // Error type. ++ ++ problem string // Error description. ++ ++ // The byte about which the problem occurred. ++ problem_offset int ++ problem_value int ++ problem_mark yaml_mark_t ++ ++ // The error context. ++ context string ++ context_mark yaml_mark_t ++ ++ // Reader stuff ++ ++ read_handler yaml_read_handler_t // Read handler. ++ ++ input_reader io.Reader // File input data. ++ input []byte // String input data. ++ input_pos int ++ ++ eof bool // EOF flag ++ ++ buffer []byte // The working buffer. ++ buffer_pos int // The current position of the buffer. ++ ++ unread int // The number of unread characters in the buffer. ++ ++ newlines int // The number of line breaks since last non-break/non-blank character ++ ++ raw_buffer []byte // The raw buffer. ++ raw_buffer_pos int // The current position of the buffer. ++ ++ encoding yaml_encoding_t // The input encoding. ++ ++ offset int // The offset of the current position (in bytes). ++ mark yaml_mark_t // The mark of the current position. ++ ++ // Comments ++ ++ head_comment []byte // The current head comments ++ line_comment []byte // The current line comments ++ foot_comment []byte // The current foot comments ++ tail_comment []byte // Foot comment that happens at the end of a block. ++ stem_comment []byte // Comment in item preceding a nested structure (list inside list item, etc) ++ ++ comments []yaml_comment_t // The folded comments for all parsed tokens ++ comments_head int ++ ++ // Scanner stuff ++ ++ stream_start_produced bool // Have we started to scan the input stream? ++ stream_end_produced bool // Have we reached the end of the input stream? ++ ++ flow_level int // The number of unclosed '[' and '{' indicators. ++ ++ tokens []yaml_token_t // The tokens queue. ++ tokens_head int // The head of the tokens queue. ++ tokens_parsed int // The number of tokens fetched from the queue. ++ token_available bool // Does the tokens queue contain a token ready for dequeueing. ++ ++ indent int // The current indentation level. ++ indents []int // The indentation levels stack. ++ ++ simple_key_allowed bool // May a simple key occur at the current position? ++ simple_keys []yaml_simple_key_t // The stack of simple keys. ++ simple_keys_by_tok map[int]int // possible simple_key indexes indexed by token_number ++ ++ // Parser stuff ++ ++ state yaml_parser_state_t // The current parser state. ++ states []yaml_parser_state_t // The parser states stack. ++ marks []yaml_mark_t // The stack of marks. ++ tag_directives []yaml_tag_directive_t // The list of TAG directives. ++ ++ // Dumper stuff ++ ++ aliases []yaml_alias_data_t // The alias data. ++ ++ document *yaml_document_t // The currently parsed document. ++} ++ ++type yaml_comment_t struct { ++ ++ scan_mark yaml_mark_t // Position where scanning for comments started ++ token_mark yaml_mark_t // Position after which tokens will be associated with this comment ++ start_mark yaml_mark_t // Position of '#' comment mark ++ end_mark yaml_mark_t // Position where comment terminated ++ ++ head []byte ++ line []byte ++ foot []byte ++} ++ ++// Emitter Definitions ++ ++// The prototype of a write handler. ++// ++// The write handler is called when the emitter needs to flush the accumulated ++// characters to the output. The handler should write @a size bytes of the ++// @a buffer to the output. ++// ++// @param[in,out] data A pointer to an application data specified by ++// yaml_emitter_set_output(). ++// @param[in] buffer The buffer with bytes to be written. ++// @param[in] size The size of the buffer. ++// ++// @returns On success, the handler should return @c 1. If the handler failed, ++// the returned value should be @c 0. ++// ++type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error ++ ++type yaml_emitter_state_t int ++ ++// The emitter states. ++const ( ++ // Expect STREAM-START. ++ yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota ++ ++ yaml_EMIT_FIRST_DOCUMENT_START_STATE // Expect the first DOCUMENT-START or STREAM-END. ++ yaml_EMIT_DOCUMENT_START_STATE // Expect DOCUMENT-START or STREAM-END. ++ yaml_EMIT_DOCUMENT_CONTENT_STATE // Expect the content of a document. ++ yaml_EMIT_DOCUMENT_END_STATE // Expect DOCUMENT-END. ++ yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a flow sequence. ++ yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE // Expect the next item of a flow sequence, with the comma already written out ++ yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE // Expect an item of a flow sequence. ++ yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. ++ yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE // Expect the next key of a flow mapping, with the comma already written out ++ yaml_EMIT_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. ++ yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a flow mapping. ++ yaml_EMIT_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. ++ yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a block sequence. ++ yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE // Expect an item of a block sequence. ++ yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. ++ yaml_EMIT_BLOCK_MAPPING_KEY_STATE // Expect the key of a block mapping. ++ yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping. ++ yaml_EMIT_BLOCK_MAPPING_VALUE_STATE // Expect a value of a block mapping. ++ yaml_EMIT_END_STATE // Expect nothing. ++) ++ ++// The emitter structure. ++// ++// All members are internal. Manage the structure using the @c yaml_emitter_ ++// family of functions. ++type yaml_emitter_t struct { ++ ++ // Error handling ++ ++ error yaml_error_type_t // Error type. ++ problem string // Error description. ++ ++ // Writer stuff ++ ++ write_handler yaml_write_handler_t // Write handler. ++ ++ output_buffer *[]byte // String output data. ++ output_writer io.Writer // File output data. ++ ++ buffer []byte // The working buffer. ++ buffer_pos int // The current position of the buffer. ++ ++ raw_buffer []byte // The raw buffer. ++ raw_buffer_pos int // The current position of the buffer. ++ ++ encoding yaml_encoding_t // The stream encoding. ++ ++ // Emitter stuff ++ ++ canonical bool // If the output is in the canonical style? ++ best_indent int // The number of indentation spaces. ++ best_width int // The preferred width of the output lines. ++ unicode bool // Allow unescaped non-ASCII characters? ++ line_break yaml_break_t // The preferred line break. ++ ++ state yaml_emitter_state_t // The current emitter state. ++ states []yaml_emitter_state_t // The stack of states. ++ ++ events []yaml_event_t // The event queue. ++ events_head int // The head of the event queue. ++ ++ indents []int // The stack of indentation levels. ++ ++ tag_directives []yaml_tag_directive_t // The list of tag directives. ++ ++ indent int // The current indentation level. ++ ++ flow_level int // The current flow level. ++ ++ root_context bool // Is it the document root context? ++ sequence_context bool // Is it a sequence context? ++ mapping_context bool // Is it a mapping context? ++ simple_key_context bool // Is it a simple mapping key context? ++ ++ line int // The current line. ++ column int // The current column. ++ whitespace bool // If the last character was a whitespace? ++ indention bool // If the last character was an indentation character (' ', '-', '?', ':')? ++ open_ended bool // If an explicit document end is required? ++ ++ space_above bool // Is there's an empty line above? ++ foot_indent int // The indent used to write the foot comment above, or -1 if none. ++ ++ // Anchor analysis. ++ anchor_data struct { ++ anchor []byte // The anchor value. ++ alias bool // Is it an alias? ++ } ++ ++ // Tag analysis. ++ tag_data struct { ++ handle []byte // The tag handle. ++ suffix []byte // The tag suffix. ++ } ++ ++ // Scalar analysis. ++ scalar_data struct { ++ value []byte // The scalar value. ++ multiline bool // Does the scalar contain line breaks? ++ flow_plain_allowed bool // Can the scalar be expessed in the flow plain style? ++ block_plain_allowed bool // Can the scalar be expressed in the block plain style? ++ single_quoted_allowed bool // Can the scalar be expressed in the single quoted style? ++ block_allowed bool // Can the scalar be expressed in the literal or folded styles? ++ style yaml_scalar_style_t // The output style. ++ } ++ ++ // Comments ++ head_comment []byte ++ line_comment []byte ++ foot_comment []byte ++ tail_comment []byte ++ ++ key_line_comment []byte ++ ++ // Dumper stuff ++ ++ opened bool // If the stream was already opened? ++ closed bool // If the stream was already closed? ++ ++ // The information associated with the document nodes. ++ anchors *struct { ++ references int // The number of references. ++ anchor int // The anchor id. ++ serialized bool // If the node has been emitted? ++ } ++ ++ last_anchor_id int // The last assigned anchor id. ++ ++ document *yaml_document_t // The currently emitted document. ++} +diff --git a/vendor/gopkg.in/yaml.v3/yamlprivateh.go b/vendor/gopkg.in/yaml.v3/yamlprivateh.go +new file mode 100644 +index 000000000000..e88f9c54aecb +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/yamlprivateh.go +@@ -0,0 +1,198 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// Copyright (c) 2006-2010 Kirill Simonov ++// ++// 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. ++ ++package yaml ++ ++const ( ++ // The size of the input raw buffer. ++ input_raw_buffer_size = 512 ++ ++ // The size of the input buffer. ++ // It should be possible to decode the whole raw buffer. ++ input_buffer_size = input_raw_buffer_size * 3 ++ ++ // The size of the output buffer. ++ output_buffer_size = 128 ++ ++ // The size of the output raw buffer. ++ // It should be possible to encode the whole output buffer. ++ output_raw_buffer_size = (output_buffer_size*2 + 2) ++ ++ // The size of other stacks and queues. ++ initial_stack_size = 16 ++ initial_queue_size = 16 ++ initial_string_size = 16 ++) ++ ++// Check if the character at the specified position is an alphabetical ++// character, a digit, '_', or '-'. ++func is_alpha(b []byte, i int) bool { ++ return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-' ++} ++ ++// Check if the character at the specified position is a digit. ++func is_digit(b []byte, i int) bool { ++ return b[i] >= '0' && b[i] <= '9' ++} ++ ++// Get the value of a digit. ++func as_digit(b []byte, i int) int { ++ return int(b[i]) - '0' ++} ++ ++// Check if the character at the specified position is a hex-digit. ++func is_hex(b []byte, i int) bool { ++ return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f' ++} ++ ++// Get the value of a hex-digit. ++func as_hex(b []byte, i int) int { ++ bi := b[i] ++ if bi >= 'A' && bi <= 'F' { ++ return int(bi) - 'A' + 10 ++ } ++ if bi >= 'a' && bi <= 'f' { ++ return int(bi) - 'a' + 10 ++ } ++ return int(bi) - '0' ++} ++ ++// Check if the character is ASCII. ++func is_ascii(b []byte, i int) bool { ++ return b[i] <= 0x7F ++} ++ ++// Check if the character at the start of the buffer can be printed unescaped. ++func is_printable(b []byte, i int) bool { ++ return ((b[i] == 0x0A) || // . == #x0A ++ (b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E ++ (b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF ++ (b[i] > 0xC2 && b[i] < 0xED) || ++ (b[i] == 0xED && b[i+1] < 0xA0) || ++ (b[i] == 0xEE) || ++ (b[i] == 0xEF && // #xE000 <= . <= #xFFFD ++ !(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF ++ !(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF)))) ++} ++ ++// Check if the character at the specified position is NUL. ++func is_z(b []byte, i int) bool { ++ return b[i] == 0x00 ++} ++ ++// Check if the beginning of the buffer is a BOM. ++func is_bom(b []byte, i int) bool { ++ return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF ++} ++ ++// Check if the character at the specified position is space. ++func is_space(b []byte, i int) bool { ++ return b[i] == ' ' ++} ++ ++// Check if the character at the specified position is tab. ++func is_tab(b []byte, i int) bool { ++ return b[i] == '\t' ++} ++ ++// Check if the character at the specified position is blank (space or tab). ++func is_blank(b []byte, i int) bool { ++ //return is_space(b, i) || is_tab(b, i) ++ return b[i] == ' ' || b[i] == '\t' ++} ++ ++// Check if the character at the specified position is a line break. ++func is_break(b []byte, i int) bool { ++ return (b[i] == '\r' || // CR (#xD) ++ b[i] == '\n' || // LF (#xA) ++ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) ++ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) ++ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029) ++} ++ ++func is_crlf(b []byte, i int) bool { ++ return b[i] == '\r' && b[i+1] == '\n' ++} ++ ++// Check if the character is a line break or NUL. ++func is_breakz(b []byte, i int) bool { ++ //return is_break(b, i) || is_z(b, i) ++ return ( ++ // is_break: ++ b[i] == '\r' || // CR (#xD) ++ b[i] == '\n' || // LF (#xA) ++ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) ++ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) ++ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) ++ // is_z: ++ b[i] == 0) ++} ++ ++// Check if the character is a line break, space, or NUL. ++func is_spacez(b []byte, i int) bool { ++ //return is_space(b, i) || is_breakz(b, i) ++ return ( ++ // is_space: ++ b[i] == ' ' || ++ // is_breakz: ++ b[i] == '\r' || // CR (#xD) ++ b[i] == '\n' || // LF (#xA) ++ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) ++ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) ++ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) ++ b[i] == 0) ++} ++ ++// Check if the character is a line break, space, tab, or NUL. ++func is_blankz(b []byte, i int) bool { ++ //return is_blank(b, i) || is_breakz(b, i) ++ return ( ++ // is_blank: ++ b[i] == ' ' || b[i] == '\t' || ++ // is_breakz: ++ b[i] == '\r' || // CR (#xD) ++ b[i] == '\n' || // LF (#xA) ++ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) ++ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) ++ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) ++ b[i] == 0) ++} ++ ++// Determine the width of the character. ++func width(b byte) int { ++ // Don't replace these by a switch without first ++ // confirming that it is being inlined. ++ if b&0x80 == 0x00 { ++ return 1 ++ } ++ if b&0xE0 == 0xC0 { ++ return 2 ++ } ++ if b&0xF0 == 0xE0 { ++ return 3 ++ } ++ if b&0xF8 == 0xF0 { ++ return 4 ++ } ++ return 0 ++ ++} +diff --git a/vendor/modules.txt b/vendor/modules.txt +index e58eff8021d8..799286522ca1 100644 +--- a/vendor/modules.txt ++++ b/vendor/modules.txt +@@ -9,7 +9,7 @@ github.com/Microsoft/go-winio/pkg/guid + # github.com/beorn7/perks v1.0.1 + ## explicit; go 1.11 + github.com/beorn7/perks/quantile +-# github.com/cespare/xxhash/v2 v2.1.2 ++# github.com/cespare/xxhash/v2 v2.2.0 + ## explicit; go 1.11 + github.com/cespare/xxhash/v2 + # github.com/containerd/containerd v1.6.21 +@@ -18,9 +18,17 @@ github.com/containerd/containerd/errdefs + github.com/containerd/containerd/log + github.com/containerd/containerd/pkg/userns + github.com/containerd/containerd/platforms ++# github.com/cpuguy83/go-md2man/v2 v2.0.3 ++## explicit; go 1.11 ++github.com/cpuguy83/go-md2man/v2 ++github.com/cpuguy83/go-md2man/v2/md2man + # github.com/creack/pty v1.1.18 + ## explicit; go 1.13 + github.com/creack/pty ++# github.com/docker/cli-docs-tool v0.6.0 ++## explicit; go 1.18 ++github.com/docker/cli-docs-tool ++github.com/docker/cli-docs-tool/annotation + # github.com/docker/distribution v2.8.2+incompatible + ## explicit + github.com/docker/distribution +@@ -224,12 +232,16 @@ github.com/prometheus/procfs/internal/util + # github.com/rivo/uniseg v0.2.0 + ## explicit; go 1.12 + github.com/rivo/uniseg ++# github.com/russross/blackfriday/v2 v2.1.0 ++## explicit ++github.com/russross/blackfriday/v2 + # github.com/sirupsen/logrus v1.9.3 + ## explicit; go 1.13 + github.com/sirupsen/logrus + # github.com/spf13/cobra v1.7.0 + ## explicit; go 1.15 + github.com/spf13/cobra ++github.com/spf13/cobra/doc + # github.com/spf13/pflag v1.0.5 + ## explicit; go 1.12 + github.com/spf13/pflag +@@ -300,10 +312,10 @@ golang.org/x/text/width + # golang.org/x/time v0.3.0 + ## explicit + golang.org/x/time/rate +-# google.golang.org/genproto v0.0.0-20220706185917-7780775163c4 +-## explicit; go 1.15 ++# google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 ++## explicit; go 1.19 + google.golang.org/genproto/googleapis/rpc/status +-# google.golang.org/grpc v1.50.1 ++# google.golang.org/grpc v1.53.0 + ## explicit; go 1.17 + google.golang.org/grpc + google.golang.org/grpc/attributes +@@ -353,7 +365,7 @@ google.golang.org/grpc/serviceconfig + google.golang.org/grpc/stats + google.golang.org/grpc/status + google.golang.org/grpc/tap +-# google.golang.org/protobuf v1.28.1 ++# google.golang.org/protobuf v1.30.0 + ## explicit; go 1.11 + google.golang.org/protobuf/encoding/protojson + google.golang.org/protobuf/encoding/prototext +@@ -390,6 +402,9 @@ google.golang.org/protobuf/types/known/timestamppb + # gopkg.in/yaml.v2 v2.4.0 + ## explicit; go 1.15 + gopkg.in/yaml.v2 ++# gopkg.in/yaml.v3 v3.0.1 ++## explicit ++gopkg.in/yaml.v3 + # gotest.tools/v3 v3.5.0 + ## explicit; go 1.17 + gotest.tools/v3/assert +-- +2.46.0 + diff --git a/docker-24.0.9_ce_fca702de7f71.tar.xz b/docker-24.0.9_ce_fca702de7f71.tar.xz new file mode 100644 index 0000000..50304e6 --- /dev/null +++ b/docker-24.0.9_ce_fca702de7f71.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7d44fcc3eb6e78a8424bdc3c3bdda65fee9555d1c28841e53a9fe4bb6a1f9e1b +size 8852852 diff --git a/docker-audit.rules b/docker-audit.rules new file mode 100644 index 0000000..363341e --- /dev/null +++ b/docker-audit.rules @@ -0,0 +1,27 @@ +## +# Audit rules based on CIS Docker 1.6 Benchmark v1.0.0 +# https://benchmarks.cisecurity.org/tools2/docker/CIS_Docker_1.6_Benchmark_v1.0.0.pdf +# Not all of these apply to SUSE. +# 1.8 Audit docker daemon +-w /usr/bin/docker -k docker +# 1.9 Audit Docker files and directories +-w /var/lib/docker -k docker +# 1.10 Audit /etc/docker +-w /etc/docker -k docker +# 1.11 Audit Docker files and directories - docker-registry.service +-w /usr/lib/systemd/system/docker-registry.service -k docker +# 1.12 Audit Docker files and directories - docker.service +-w /usr/lib/systemd/system/docker.service -k docker +# 1.13 Audit Docker files and directories - /var/run/docker.sock +-w /var/run/docker.sock -k docker +# 1.14 Audit Docker files and directories - /etc/sysconfig/docker +-w /etc/sysconfig/docker -k docker +# 1.15 Audit Docker files and directories - /etc/sysconfig/docker-network +-w /etc/sysconfig/docker-network -k docker +# 1.16 Audit Docker files and directories - /etc/sysconfig/docker-registry +-w /etc/sysconfig/docker-registry -k docker +# 1.17 Audit Docker files and directories - /etc/sysconfig/docker-storage +-w /etc/sysconfig/docker-storage -k docker +# 1.18 Audit Docker files and directories - /etc/default/docker +-w /etc/default/docker -k docker +## end docker audit rules diff --git a/docker-buildx-0.17.1.tar.xz b/docker-buildx-0.17.1.tar.xz new file mode 100644 index 0000000..a0ad0be --- /dev/null +++ b/docker-buildx-0.17.1.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fd0f81752a02e20b611f95a35718bdc44eb1e203e0fd80d7afb87dfd8135c300 +size 6445376 diff --git a/docker-buildx-0.19.2.tar.xz b/docker-buildx-0.19.2.tar.xz new file mode 100644 index 0000000..d69b8f4 --- /dev/null +++ b/docker-buildx-0.19.2.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d915e0d1a81e1ec04bd2d37223e46d8e0438d326d713cde9d059ff2e809bf5b2 +size 6479440 diff --git a/docker-buildx-0.19.3.tar.xz b/docker-buildx-0.19.3.tar.xz new file mode 100644 index 0000000..6fe2807 --- /dev/null +++ b/docker-buildx-0.19.3.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e6efae9f26c3d94c2f73aa22197aa1b7e97c1c81bc73ac5e38f165753373bf0a +size 6480184 diff --git a/docker-cli-24.0.9_ce.tar.xz b/docker-cli-24.0.9_ce.tar.xz new file mode 100644 index 0000000..8e49f40 --- /dev/null +++ b/docker-cli-24.0.9_ce.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ac6c8ab1af0347391974301f29ee5ca27630919d143301cfba87e472c8a27e5 +size 3563448 diff --git a/docker-daemon.json b/docker-daemon.json new file mode 100644 index 0000000..3661a83 --- /dev/null +++ b/docker-daemon.json @@ -0,0 +1,8 @@ +{ + "log-level": "warn", + "log-driver": "json-file", + "log-opts": { + "max-size": "10m", + "max-file": "5" + } +} diff --git a/docker-integration.sh b/docker-integration.sh new file mode 100644 index 0000000..07282d8 --- /dev/null +++ b/docker-integration.sh @@ -0,0 +1,294 @@ +#!/bin/bash +# docker-integration: run Docker's integration tests +# Copyright (C) 2024 SUSE 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. + +set -Eeuo pipefail + +TESTDIR=/usr/src/docker-test +TEST_SRCDIR="$TESTDIR/src" +TEST_BINDIR="$TESTDIR/bin" + +TMPROOT="$(mktemp --tmpdir -d docker-integration-tmpdir.XXXXXX)" +TMPDIR="$TMPROOT/tmp" +DEST="$TMPROOT/dest" + +mkdir -p "$TMPDIR" "$TEST_BINDIR" "$DEST" +chmod 1777 "$TMPDIR" +chmod 777 "$TMPROOT" + +function usage() { + cat >&2 <<-EOF + docker-integration.sh [-Av] [-r TestName] [-t timeout] [...] + + Arguments: + -A + Run all tests (do not fail on first suite failure). + -v + Run tests in verbose mode (go test -v). + -r + Only run tests that match the given regular expression (go test -run). + -t + Set the per-suite timeout to (go test -timeout). + ... + Only run the given test suites in /usr/src/docker-test. The + default is to run all test suites + + Examples: + + Run the build and network integration tests with a 60 minute timeout: + + ./docker-integration.sh -t 60m integration/build integration/network + + Run all of the tests in verbose mode with a 6 hour timeout: + + ./docker-integration.sh -Av -t 360m + + This script is maintained by openSUSE in the Virtualization:containers + project, and is only intended to be used by openSUSE developers. + EOF + exit "${1:-1}" +} + +fail_fast=1 +verbose= +filter= +timeout=20m +while getopts "Ahr:t:v" opt; do + case "$opt" in + A) + fail_fast= + ;; + v) + verbose=1 + ;; + r) + filter="$OPTARG" + ;; + t) + timeout="$OPTARG" + ;; + h) + usage 0 + ;; + :) + echo "Missing argument: -$OPTARG" >&2 + usage 1 + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + usage 1 + ;; + esac +done + +pushd "$TEST_SRCDIR" + +if [ "$OPTIND" -le "$#" ]; then + SUITES=("${@:$OPTIND:$(($#+1))}") +else + readarray -t SUITES <<<"$(find . -type f -name test.main -printf "%h\n")" +fi +echo "Planning to run suites {${SUITES[*]}}." + +# Download the frozen images. +if ! [ -d /docker-frozen-images ]; then + # TODO: Get the hashes from /usr/src/docker-test/Dockerfile... + contrib/download-frozen-image-v2.sh "$TMPDIR/docker-frozen-images" \ + busybox:latest@sha256:95cf004f559831017cdf4628aaf1bb30133677be8702a8c5f2994629f637a209 \ + busybox:glibc@sha256:1f81263701cddf6402afe9f33fca0266d9fff379e59b1748f33d3072da71ee85 \ + debian:bookworm-slim@sha256:2bc5c236e9b262645a323e9088dfa3bb1ecb16cc75811daf40a23a824d665be9 \ + hello-world:latest@sha256:d58e752213a51785838f9eed2b7a498ffa1cb3aa7f946dda11af39286c3db9a9 \ + arm32v7/hello-world:latest@sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1 + sudo cp -r "$TMPDIR/docker-frozen-images" / +fi + +# Create binaries in $TEST_BINDIR. +if ! [ -e "$TEST_BINDIR/docker-basic-plugin" ]; then + ( + pushd "$TEST_SRCDIR/testutil/fixtures/plugin/basic" + + [ -f go.mod ] || go mod init docker-basic-plugin + go build -o "$TEST_BINDIR/docker-basic-plugin" . + ) +fi +if ! [ -e "$TEST_BINDIR/registry-v2" ]; then + # The v2.x tags of Docker registry don't use go.mod, and pre-date the move + # to github.com/distribution, so we need to create a fake GOPATH with the + # old github.com/docker/distribution import path. + ( + # shellcheck disable=SC2030 + GOPATH="$(mktemp -d -p "$TMPROOT" distribution-build-gopath.XXXXXX)" + export GOPATH + pushd "$GOPATH" + + git clone \ + --depth=1 --branch=v2.8.3 \ + https://github.com/distribution/distribution.git \ + src/github.com/docker/distribution + + pushd src/github.com/docker/distribution + + GO111MODULE=off go build -o "$TEST_BINDIR/registry-v2" ./cmd/registry + ) +fi +if ! [ -e "$TEST_BINDIR/ctr" ]; then + containerd-ctr --help >/dev/null + ln -sf "$(which containerd-ctr)" "$TEST_BINDIR/ctr" +fi +if ! [ -e "$TEST_BINDIR/docker" ]; then + # The integration-cli tests require a Docker 17.06.2 client (from 2017). + # This is mainly because the tests are all based on the specific output the + # client gives, and some tests fail on modern client versions. + ( + # shellcheck disable=SC2030 + GOPATH="$(mktemp -d -p "$TMPROOT" docker-cli-build-gopath.XXXXXX)" + export GOPATH + pushd "$GOPATH" + + # This tag also comes from the time when this was called + # github.com/docker/docker-ce-packaging, so we need to work around this + # by moving the cli component into the right path... + git clone \ + --depth=1 --branch=v17.06.2-ce \ + https://github.com/docker/cli.git \ + src/github.com/docker/docker-ce-packaging + mv \ + src/github.com/docker/docker-ce-packaging/components/cli \ + src/github.com/docker/cli + + pushd src/github.com/docker/cli + GO111MODULE=off go build -o "$TEST_BINDIR/docker" ./cmd/docker + ) +fi + +# Create an unprivilegeduser account for tests. +if ! ( grep unprivilegeduser /etc/passwd &>/dev/null ); then + useradd --create-home --gid docker unprivilegeduser +fi + +# Disable SUSE secrets for tests, as some tests (TestDiff from +# integration/container) will fail if we have secrets injected. +[ -e /etc/docker/suse-secrets-enable ] && \ + mv -nv /etc/docker/suse-secrets-enable{,-DISABLED} +sudo systemctl restart docker + +# Make sure docker-buildx is disabled. +[ -e /usr/lib/docker/cli-plugins/docker-buildx ] && \ + mv -nv /usr/lib/docker/cli-plugins/docker-buildx{,-DISABLED} + +# Disable any daemon configurations. +[ -e /etc/docker/daemon.json ] && \ + mv -nv /etc/docker/daemon.json{,.DISABLED} + +set -x + +# In order for< gotest.tools/v3/assert> to parse the source and give us useful +# error messages, we have to create a fake source directory that points at +# $TEST_SRCDIR. This path is replaced with %{docker_builddir} during the +# docker.spec build. +__DOCKER_BUILDIR="@@docker_builddir@@" +DOCKER_BUILDDIR="${DOCKER_BUILDDIR:-$__DOCKER_BUILDIR}" +sudo rm -rvf "$DOCKER_BUILDDIR" +sudo mkdir -p "$(dirname "$DOCKER_BUILDDIR")" +sudo ln -svf "$TEST_SRCDIR" "$DOCKER_BUILDDIR" + +# Clean up any old containers/images/networks/volumes before running the tests. +# We need to do this *BEFORE* we set PATH, as the outdated $TEST_BINDIR/docker +# doesn't support some of these commands. +docker container prune -f +docker image prune -af +#docker buildx prune -af +docker network prune -f +docker volume prune -af +[ -z "$(docker plugin ls -q)" ] || docker plugin ls -q | xargs docker plugin rm -f +docker system prune -af + +export DOCKERFILE="$TEST_SRCDIR/Dockerfile" +export TMPDIR="$TMPDIR" +export TEMP="$TMPDIR" +export HOME="$TMPDIR/fake-home" +export DEST="$TEST_SRCDIR/bundles/dummy-dir" +export ABS_DEST="$DEST" +export PATH="$TEST_BINDIR:$PATH" + +export TZ=UTC +export DOCKER_INTEGRATION_DAEMON_DEST="$ABS_DEST" +export DOCKER_HOST=unix:///run/docker.sock +export DOCKER_GRAPHDRIVER=overlay2 +export DOCKER_USERLANDPROXY=true +export DOCKER_REMAP_ROOT="${DOCKER_REMAP_ROOT:-}" +export DOCKER_TMPDIR="$TMPDIR" + +set +x + +# Make sure that we have a dummy "destination" directory for tests. +rm -rf "$DOCKER_INTEGRATION_DAEMON_DEST" +mkdir -p "$DOCKER_INTEGRATION_DAEMON_DEST" + +# Install the emptyfs images. +sh ./hack/make/.build-empty-images + +ls -la "$TMPROOT" + +success=0 +failed_suites=() +for suite_name in "${SUITES[@]}"; do + suite_name="${suite_name#*./}" + pushd "$TEST_SRCDIR/$suite_name" + + test_flags=() + [ -n "$verbose" ] && test_flags+=("-test.v") + [ -n "$filter" ] && test_flags+=("-test.run" "$filter") + + if [[ "$suite_name" == "integration-cli" ]]; then + # We need to disable docker-buildx for the integration-cli tests + # because otherwise the "docker build" command will use the wrong + # builder and the output won't match what the tests expect. + timeout=360m + fi + test_flags+=("-test.timeout" "$timeout") + + echo "Running suite $suite_name (${test_flags[*]}) [success=$success fail=${#failed_suites[@]}]" + + set -x +e + sudo -E HOME="$HOME" TMPDIR="$TMPDIR" PATH="$PATH" \ + ./test.main "${test_flags[@]}" + err="$?" + if (( err != 0 )); then + [ -z "$fail_fast" ] || exit "$err" + failed_suites+=("$suite_name") + else + (( success++ )) + fi + set +x -e + + popd +done + +[ -e /usr/lib/docker/cli-plugins/docker-buildx-DISABLED ] && \ + mv -nv /usr/lib/docker/cli-plugins/docker-buildx{-DISABLED,} + +[ -e /etc/docker/suse-secrets-enable-DISABLED ] && \ + mv -nv /etc/docker/suse-secrets-enable{-DISABLED,} + +[ -e /etc/docker/daemon.json.DISABLED ] && \ + mv -nv /etc/docker/daemon.json{.DISABLED,} + +echo "Suite results: $success success(es) ${#failed_suites[*]} failure(s)." +if (( ${#failed_suites[@]} > 0 )); then + echo "Failed suites:" + printf " - %s\n" "${failed_suites[@]}" + exit 1 +fi diff --git a/docker-rpmlintrc b/docker-rpmlintrc new file mode 100644 index 0000000..65d137c --- /dev/null +++ b/docker-rpmlintrc @@ -0,0 +1,7 @@ +addFilter("^docker-(stable-)?bash-completion.noarch: (E|W): non-executable-script /usr/share/bash-completion/completions/docker") +addFilter("^docker-(stable-)?zsh-completion.noarch: W: non-conffile-in-etc /etc/zsh_completion.d/_docker") + +# The docker-integration-tests-devel package contains all of the source code of +# Docker, which causes a bunch of warnings. Note that +# docker-integration-tests-devel is used internally and isn't actually shipped. +addFilter("^docker-(stable-)?integration-tests-devel\..*: (E|W): .*") diff --git a/docker-stable.changes b/docker-stable.changes new file mode 100644 index 0000000..2a68825 --- /dev/null +++ b/docker-stable.changes @@ -0,0 +1,120 @@ +------------------------------------------------------------------- +Tue Dec 17 13:20:39 UTC 2024 - Aleksa Sarai + +- Update to docker-buildx 0.19.3. See upstream changelog online at + + +------------------------------------------------------------------- +Wed Dec 11 10:14:56 UTC 2024 - Aleksa Sarai + +- Update docker-buildx to v0.19.2. See upstream changelog online at + . + + Some notable changelogs from the last update: + * + * +- Update to Go 1.22. + +------------------------------------------------------------------- +Wed Dec 11 05:39:42 UTC 2024 - Aleksa Sarai + +- Add a new toggle file /etc/docker/suse-secrets-enable which allows users to + disable the SUSEConnect integration with Docker (which creates special mounts + in /run/secrets to allow container-suseconnect to authenticate containers + with registries on registered hosts). bsc#1231348 bsc#1232999 + + In order to disable these mounts, just do + + echo 0 > /etc/docker/suse-secrets-enable + + and restart Docker. In order to re-enable them, just do + + echo 1 > /etc/docker/suse-secrets-enable + + and restart Docker. Docker will output information on startup to tell you + whether the SUSE secrets feature is enabled or not. + + * 0002-SECRETS-SUSE-implement-SUSE-container-secrets.patch + +------------------------------------------------------------------- +Wed Nov 27 12:10:42 UTC 2024 - Aleksa Sarai + +- Disable docker-buildx builds for SLES. It turns out that build containers + with docker-buildx don't currently get the SUSE secrets mounts applied, + meaning that container-suseconnect doesn't work when building images. + bsc#1233819 + +------------------------------------------------------------------- +Wed Nov 20 05:34:38 UTC 2024 - Aleksa Sarai + +- Add docker-integration-tests-devel subpackage for building and running the + upstream Docker integration tests on machines to test that Docker works + properly. Users should not install this package. +- docker-rpmlintrc updated to include allow-list for all of the integration + tests package, since it contains a bunch of stuff that wouldn't normally be + allowed. +- Rebased patches: + * 0001-SECRETS-daemon-allow-directory-creation-in-run-secre.patch + * 0002-SECRETS-SUSE-implement-SUSE-container-secrets.patch + * 0003-BUILD-SLE12-revert-graphdriver-btrfs-use-kernel-UAPI.patch + * 0004-bsc1073877-apparmor-clobber-docker-default-profile-o.patch + * 0005-SLE12-revert-apparmor-remove-version-conditionals-fr.patch + * 0006-CVE-2024-23653-update-buildkit-to-include-CVE-patche.patch + * 0007-bsc1221916-update-to-patched-buildkit-version-to-fix.patch + * 0008-bsc1214855-volume-use-AtomicWriteFile-to-save-volume.patch + * 0009-CVE-2024-41110-AuthZ-plugin-securty-fixes.patch +- Added patches: + + 0010-TESTS-backport-fixes-for-integration-tests.patch + +------------------------------------------------------------------- +Tue Nov 12 06:34:28 UTC 2024 - Aleksa Sarai + +- Remove DOCKER_NETWORK_OPTS from docker.service. This was removed from + sysconfig a long time ago, and apparently this causes issues with systemd in + some cases. +- Update --add-runtime to point to correct binary path. + +------------------------------------------------------------------- +Wed Oct 16 22:24:52 UTC 2024 - Aleksa Sarai + +- Further merge docker and docker-stable specfiles to minimise the differences. + The main thing is that we now include both halves of the + Conflicts/Provides/Obsoletes dance in both specfiles. + +------------------------------------------------------------------- +Wed Oct 16 05:37:14 UTC 2024 - Aleksa Sarai + +- Update to docker-buildx v0.17.1 to match standalone docker-buildx package we + are replacing. See upstream changelog online at + + +------------------------------------------------------------------- +Sat Sep 7 13:10:30 UTC 2024 - Aleksa Sarai + +- Import specfile changes for docker-buildx as well as the changes to help + reduce specfile differences between docker-stable and docker. bsc#1230331 + bsc#1230333 + +------------------------------------------------------------------- +Wed Aug 14 03:21:00 UTC 2024 - Aleksa Sarai + +- Backport patch for CVE-2024-41110. bsc#1228324 + + 0009-CVE-2024-41110-AuthZ-plugin-securty-fixes.patch + +------------------------------------------------------------------- +Wed Jun 16 04:18:11 UTC 2024 - Aleksa Sarai + +- Initial docker-stable release, forked from Docker 24.0.6-ce release + (packaged on 2023-10-11). +- Update to Docker 24.0.9-ce, which is the latest version of the 24.0.x branch. + It seems likely this will be the last upstream version of the 24.0.x branch + (it seems Mirantis is going to do LTS for 23.0.x, not 24.0.x). + +- Fix BuildKit's symlink resolution logic to correctly handle non-lexical + symlinks. Backport of and + . bsc#1221916 + + 0007-bsc1221916-update-to-patched-buildkit-version-to-fix.patch +- Write volume options atomically so sudden system crashes won't result in + future Docker starts failing due to empty files. Backport of + . bsc#1214855 + + 0008-bsc1214855-volume-use-AtomicWriteFile-to-save-volume.patch diff --git a/docker-stable.spec b/docker-stable.spec new file mode 100644 index 0000000..9c1c226 --- /dev/null +++ b/docker-stable.spec @@ -0,0 +1,643 @@ +# +# spec file for package docker-stable +# +# Copyright (c) 2024 SUSE LLC +# +# All modifications and additions to the file contributed by third parties +# remain the property of their copyright owners, unless otherwise agreed +# upon. The license for this file, and modifications and additions to the +# file, is the same license as for the pristine package itself (unless the +# license for the pristine package is not an Open Source License, in which +# case the license is the MIT License). An "Open Source License" is a +# license that conforms to the Open Source Definition (Version 1.9) +# published by the Open Source Initiative. + +# Please submit bugfixes or comments via https://bugs.opensuse.org/ +# +# nodebuginfo + + +%bcond_without apparmor + +# This subpackage is only used for testing by developers, and shouldn't be +# built for actual users. +%bcond_with integration_tests + +%if 0%{?is_opensuse} == 0 +# SUSEConnect support ("SUSE secrets") only makes sense for SLES hosts. +%bcond_without suseconnect +# There is currently a known bug between buildx and SUSE secrets, so we don't +# package docker-buildx for SLES. bsc#1233819 +%bcond_with buildx +%else +%bcond_with suseconnect +%bcond_without buildx +%endif + +# The flavour is defined with a macro to try to keep docker and docker-stable +# as similar as possible, to make maintenance a little easier. +%define flavour -stable + +# Where important update information will be stored, such that an administrator +# is guaranteed to see the relevant warning. +%define update_messages %{_localstatedir}/adm/update-messages/%{name}-%{version}-%{release} + +# Test binaries. +%define testdir /usr/src/docker-test + +#Compat macro for new _fillupdir macro introduced in Nov 2017 +%if ! %{defined _fillupdir} + %define _fillupdir /var/adm/fillup-templates +%endif + +# MANUAL: This needs to be updated with every docker update. +%define docker_real_version 24.0.9 +%define docker_git_version fca702de7f71 +%define docker_version %{docker_real_version}_ce +# This "nice version" is so that docker --version gives a result that can be +# parsed by other people. boo#1182476 +%define docker_nice_version %{docker_real_version}-ce + +%if %{with buildx} +# MANUAL: This needs to be updated with every docker-buildx update. +%define buildx_version 0.19.3 +%endif + +# Used when generating the "build" information for Docker version. The value of +# git_commit_epoch is unused here (we use SOURCE_DATE_EPOCH, which rpm +# helpfully injects into our build environment from the changelog). If you want +# to generate a new git_commit_epoch, use this: +# $ date --date="$(git show --format=fuller --date=iso $COMMIT_ID | grep -oP '(?<=^CommitDate: ).*')" '+%s' +%define git_commit_epoch 1706746343 + +# NOTE: We are using Docker 24 as the base for docker-stable because that +# happened to be the version we released when we started working on +# docker-stable. Unfortunately (at time of writing) the Mirantis-supported +# Docker LTS is based on Docker 23[1] so when we decide to update this (in +# 2027) we should try to match the Mirantis-supported version then. +# +# [1]: https://docs.mirantis.com/mcr/23.0/compat-matrix/maintenance-lifecycle.html + +Name: docker%{flavour} +Version: %{docker_version} +Release: 0 +Summary: The Moby-project Linux container runtime +License: Apache-2.0 +Group: System/Management +URL: http://www.docker.io +Source: docker-%{docker_version}_%{docker_git_version}.tar.xz +Source1: docker-cli-%{docker_version}.tar.xz +Source3: docker-rpmlintrc +# TODO: Move these source files to somewhere nicer. +Source100: docker.service +Source101: docker.socket +Source110: 80-docker.rules +Source120: sysconfig.docker +Source130: README_SUSE.md +Source140: docker-audit.rules +Source150: docker-daemon.json +Source160: docker.sysusers +# docker-integration-tests-devel +Source900: docker-integration.sh +# NOTE: All of these patches are maintained in +# in the suse-v branch. Make sure you update the patches in that +# branch and then git-format-patch the patch here. +# SUSE-FEATURE: Adds the /run/secrets mountpoint inside all Docker containers +# which is not snapshotted when images are committed. +Patch100: 0001-SECRETS-daemon-allow-directory-creation-in-run-secre.patch +Patch101: 0002-SECRETS-SUSE-implement-SUSE-container-secrets.patch +# UPSTREAM: Revert of upstream patch to keep SLE-12 build working. +Patch200: 0003-BUILD-SLE12-revert-graphdriver-btrfs-use-kernel-UAPI.patch +# UPSTREAM: Backport of . +Patch201: 0004-bsc1073877-apparmor-clobber-docker-default-profile-o.patch +# UPSTREAM: Revert of upstream patches to make apparmor work on SLE 12. +Patch202: 0005-SLE12-revert-apparmor-remove-version-conditionals-fr.patch +# UPSTREAM: Backport of several BuildKit patches: +# CVE-2024-23651 +# CVE-2024-23652 +# CVE-2024-23653 +Patch203: 0006-CVE-2024-23653-update-buildkit-to-include-CVE-patche.patch +# UPSTREAM: Backport of and +# . bsc#1221916 +Patch204: 0007-bsc1221916-update-to-patched-buildkit-version-to-fix.patch +# UPSTREAM: Backport of . bsc#1214855 +Patch205: 0008-bsc1214855-volume-use-AtomicWriteFile-to-save-volume.patch +# UPSTREAM: Backport of +# fix. CVE-2024-41110 +Patch206: 0009-CVE-2024-41110-AuthZ-plugin-securty-fixes.patch +# UPSTREAM: Backport of and +# . +Patch299: 0010-TESTS-backport-fixes-for-integration-tests.patch +# UPSTREAM: Backport of . +Patch900: cli-0001-docs-include-required-tools-in-source-tree.patch +BuildRequires: audit +BuildRequires: bash-completion +BuildRequires: ca-certificates +BuildRequires: device-mapper-devel >= 1.2.68 +BuildRequires: fdupes +%if %{with apparmor} +BuildRequires: libapparmor-devel +%endif +BuildRequires: fish +BuildRequires: go-go-md2man +BuildRequires: libbtrfs-devel >= 3.8 +BuildRequires: libseccomp-devel >= 2.2 +BuildRequires: libtool +BuildRequires: linux-glibc-devel +BuildRequires: procps +BuildRequires: sqlite3-devel +BuildRequires: sysuser-tools +BuildRequires: zsh +BuildRequires: golang(API) = 1.22 +BuildRequires: pkgconfig(libsystemd) +%if %{with apparmor} +%if 0%{?sle_version} >= 150000 +# This conditional only works on rpm>=4.13, which SLE 12 doesn't have. But we +# don't need to support Docker+selinux for SLE 12 anyway. +Requires: (apparmor-parser or container-selinux) +# This recommends is added to make sure that even if you have container-selinux +# installed you will still be prompted to install apparmor-parser which Docker +# requires to apply AppArmor profiles (for SELinux systems this doesn't matter +# but if you switch back to AppArmor on reboot this would result in insecure +# containers). +Recommends: apparmor-parser +%else +Requires: apparmor-parser +%endif +%else +Requires: container-selinux +%endif +Requires: ca-certificates-mozilla +# The docker-proxy binary used to be in a separate package. We obsolete it, +# since now docker-proxy is maintained as part of this package. +Obsoletes: docker-libnetwork < 0.7.0.2 +Provides: docker-libnetwork = 0.7.0.2.%{docker_version} +# docker-stable cannot be used alongside docker. +%if "%{name}" == "docker-stable" +Provides: docker = %{docker_version} +Obsoletes: docker < %{docker_version} +Conflicts: docker +%else +Conflicts: docker-stable +%endif +# Required to actually run containers. We require the minimum version that is +# pinned by Docker, but in order to avoid headaches we allow for updates. +Requires: runc >= 1.1.9 +Requires: containerd >= 1.7.3 +# Needed for --init support. We don't use "tini", we use our own implementation +# which handles edge-cases better. +Requires: catatonit +# Provides mkfs.ext4 - used by Docker when devicemapper storage driver is used +Requires: e2fsprogs +Requires: iproute2 >= 3.5 +Requires: iptables >= 1.4 +Requires: procps +Requires: tar >= 1.26 +Requires: xz >= 4.9 +%if %{with buildx} +# Standard docker-build is deprecated, so require docker-buildx to avoid users +# hitting bugs that have long since been fixed by docker-buildx. bsc#1230331 +Requires: %{name}-buildx +%endif +%?sysusers_requires +Requires(post): %fillup_prereq +Requires(post): udev +Requires(post): shadow +# Not necessary, but must be installed when the underlying system is +# configured to use lvm and the user doesn't explicitly provide a +# different storage-driver than devicemapper +Recommends: lvm2 >= 2.2.89 +Recommends: %{name}-rootless-extras +Recommends: git-core >= 1.7 +ExcludeArch: s390 ppc + +%description +Docker complements LXC with a high-level API which operates at the process +level. It runs unix processes with strong guarantees of isolation and +repeatability across servers. + +Docker is a great building block for automating distributed systems: large-scale +web deployments, database clusters, continuous deployment systems, private PaaS, +service-oriented architectures, etc. + +%if %{with buildx} +%package buildx +Version: %{buildx_version} +Summary: Docker CLI plugin for extended build capabilities with BuildKit +License: Apache-2.0 +URL: https://github.com/docker/buildx +Source500: docker-buildx-%{buildx_version}.tar.xz +Group: System/Management +Requires: %{name} >= 19.03.0_ce +# docker-stable cannot be used alongside docker. +%if "%{name}" == "docker-stable" +Provides: docker-buildx = %{buildx_version} +Obsoletes: docker-buildx < %{buildx_version} +Conflicts: docker-buildx +%else +Conflicts: docker-stable-buildx +%endif + +%description buildx +buildx is a Docker CLI plugin for extended build capabilities with BuildKit. + +Key features: +- Familiar UI from docker build +- Full BuildKit capabilities with container driver +- Multiple builder instance support +- Multi-node builds for cross-platform images +- Compose build support +- High-level build constructs (bake) +- In-container driver support (both Docker and Kubernetes) +%endif + +%package rootless-extras +Summary: Rootless support for Docker +Group: System/Management +Requires: %{name} = %{docker_version} +Requires: fuse-overlayfs >= 0.7 +Requires: rootlesskit +Requires: slirp4netns >= 0.4 +BuildArch: noarch +# docker-stable cannot be used alongside docker. +%if "%{name}" == "docker-stable" +Provides: docker-rootless-extras = %{docker_version} +Obsoletes: docker-rootless-extras < %{docker_version} +Conflicts: docker-rootless-extras +%else +Conflicts: docker-stable-rootless-extras +%endif + +%description rootless-extras +Rootless support for Docker. +Use dockerd-rootless.sh to run the daemon. +Use dockerd-rootless-setuptool.sh to setup systemd for dockerd-rootless.sh. + +%if %{with integration_tests} +%package integration-tests-devel +Summary: Rootless support for Docker +Group: TestSuite +Requires: %{name} = %{docker_version} +Requires: containerd-ctr +Requires: curl +Requires: gcc +Requires: git +Requires: glibc-devel-static +Requires: go +Requires: jq +Requires: libcap-progs + +%description integration-tests-devel +Integration testing binaries for Docker. + +THIS PACKAGE SHOULD NOT BE INSTALLED BY END-USERS, IT IS ONLY INTENDED FOR +INTERNAL DEVELOPMENT OF THE DOCKER PACKAGE FOR (OPEN)SUSE. +%endif + +%package bash-completion +Summary: Bash Completion for %{name} +Group: System/Shells +Requires: %{name} = %{docker_version} +Requires: bash-completion +Supplements: packageand(%{name}:bash-completion) +BuildArch: noarch +# docker-stable cannot be used alongside docker. +%if "%{name}" == "docker-stable" +Provides: docker-bash-completion = %{docker_version} +Obsoletes: docker-bash-completion < %{docker_version} +Conflicts: docker-bash-completion +%else +Conflicts: docker-stable-bash-completion +%endif + +%description bash-completion +Bash command line completion support for %{name}. + +%package zsh-completion +Summary: Zsh Completion for %{name} +Group: System/Shells +Requires: %{name} = %{docker_version} +Requires: zsh +Supplements: packageand(%{name}:zsh) +BuildArch: noarch +# docker-stable cannot be used alongside docker. +%if "%{name}" == "docker-stable" +Provides: docker-zsh-completion = %{docker_version} +Obsoletes: docker-zsh-completion < %{docker_version} +Conflicts: docker-zsh-completion +%else +Conflicts: docker-stable-zsh-completion +%endif + +%description zsh-completion +Zsh command line completion support for %{name}. + +%package fish-completion +Summary: Fish completion for %{name} +Group: System/Shells +Requires: %{name} = %{docker_version} +Requires: fish +Supplements: packageand(%{name}:fish) +BuildArch: noarch +# docker-stable cannot be used alongside docker. +%if "%{name}" == "docker-stable" +Provides: docker-fish-completion = %{docker_version} +Obsoletes: docker-fish-completion < %{docker_version} +Conflicts: docker-fish-completion +%else +Conflicts: docker-stable-fish-completion +%endif + +%description fish-completion +Fish command line completion support for %{name}. + +%prep +# docker-cli +%define cli_builddir %{_builddir}/docker-cli-%{docker_version} +%setup -q -T -b 1 -n docker-cli-%{docker_version} +[ "%{cli_builddir}" = "$PWD" ] +# offline manpages +%patch -P900 -p1 + +%if %{with buildx} +# docker-buildx +%define buildx_builddir %{_builddir}/docker-buildx-%{buildx_version} +%setup -q -T -b 500 -n docker-buildx-%{buildx_version} +[ "%{buildx_builddir}" = "$PWD" ] +%endif + +# docker +%define docker_builddir %{_builddir}/docker-%{docker_version}_%{docker_git_version} +%setup -q -n docker-%{docker_version}_%{docker_git_version} +[ "%{docker_builddir}" = "$PWD" ] +# README_SUSE.md for documentation. +cp %{SOURCE130} . + +%if %{with suseconnect} +# PATCH-SUSE: Secrets patches. +%patch -P100 -p1 +%patch -P101 -p1 +%endif +%if 0%{?sle_version} == 120000 +# Patches to build on SLE-12. +%patch -P200 -p1 +%endif +# bsc#1099277 +%patch -P201 -p1 +# Solves apparmor issues on SLE-12, but okay for newer SLE versions too. +%patch -P202 -p1 +# bsc#1221916 +%patch -P203 -p1 +# bsc#1214855 +%patch -P204 -p1 +# bsc#1214855 +%patch -P205 -p1 +# CVE-2024-41110 +%patch -P206 -p1 +%if %{with integration_tests} +# integration-tests patches +%patch -P299 -p1 +%endif + +%build +%sysusers_generate_pre %{SOURCE160} %{name} docker.conf + +BUILDTAGS="exclude_graphdriver_aufs apparmor selinux seccomp pkcs11" +%if 0%{?sle_version} == 120000 + # Allow us to build with older distros but still have deferred removal + # support at runtime. We only use this when building on SLE12, because + # later openSUSE/SLE versions have a new enough libdevicemapper to not + # require the runtime checking. + BUILDTAGS="libdm_dlsym_deferred_remove $BUILDTAGS" +%endif + +export AUTO_GOPATH=1 +# Make sure we always build PIC code. bsc#1048046 +export BUILDFLAGS="-buildmode=pie" +# Specify all of the versioning information. We use SOURCE_DATE_EPOCH if it's +# been injected by rpmbuild, otherwise we use the hardcoded git_commit_epoch +# generated above. boo#1064781 +export VERSION="%{docker_nice_version}" +export DOCKER_GITCOMMIT="%{docker_git_version}" +export GITCOMMIT="%{docker_git_version}" +export SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-%{git_commit_epoch}}" +export BUILDTIME="$(date -u -d "@$SOURCE_DATE_EPOCH" --rfc-3339 ns 2>/dev/null | sed -e 's/ /T/')" + +################### +## DOCKER ENGINE ## +################### + +pushd "%{docker_builddir}" +# use go module for build +ln -s {vendor,go}.mod +ln -s {vendor,go}.sum +./hack/make.sh dynbinary + +%if %{with integration_tests} +# build test binaries for integration tests +readarray -t integration_dirs \ + <<<"$(go list -test -f '{{- if ne .ForTest "" -}}{{- .Dir -}}{{- end -}}' ./integration/... ./integration-cli/...)" +for dir in "${integration_dirs[@]}" +do + pushd "$dir" + go test -c -buildmode=pie -tags "$BUILDTAGS" -o test.main . + popd +done +# Update __DOCKER_BUILDIR in the integration testing script. +sed -i 's|^__DOCKER_BUILDIR=.*|__DOCKER_BUILDIR=%{docker_builddir}|g' "%{SOURCE900}" +%endif + +popd + +################### +## DOCKER CLIENT ## +################### + +pushd "%{cli_builddir}" +# use go module for build +ln -s {vendor,go}.mod +ln -s {vendor,go}.sum +make DISABLE_WARN_OUTSIDE_CONTAINER=1 dynbinary manpages +popd + +%if %{with buildx} +################### +## DOCKER BUILDX ## +################### + +pushd "%{buildx_builddir}" +make \ + CGO_ENABLED=1 \ + VERSION="%{buildx_version}" \ + REVISION="v%{buildx_version}" \ + GO_EXTRA_FLAGS="-buildmode=pie" \ + build +popd +%endif + +%install +install -Dd -m0755 \ + %{buildroot}%{_sysconfdir}/init.d \ + %{buildroot}%{_bindir} \ + %{buildroot}%{_sbindir} + +# docker daemon +install -D -m0755 %{docker_builddir}/bundles/dynbinary-daemon/dockerd %{buildroot}/%{_bindir}/dockerd +# docker proxy +install -D -m0755 %{docker_builddir}/bundles/dynbinary-daemon/docker-proxy %{buildroot}/%{_bindir}/docker-proxy + +# cli-plugins/ +install -d %{buildroot}/usr/lib/docker/cli-plugins +%if %{with buildx} +# buildx plugin +install -D -m0755 %{buildx_builddir}/bin/build/docker-buildx %{buildroot}/usr/lib/docker/cli-plugins/docker-buildx +%endif + +# /var/lib/docker +install -d %{buildroot}/%{_localstatedir}/lib/docker +# daemon.json config file +install -D -m0644 %{SOURCE150} %{buildroot}%{_sysconfdir}/docker/daemon.json +%if %{with suseconnect} +# SUSE-specific config file +echo 1 > %{buildroot}%{_sysconfdir}/docker/suse-secrets-enable +%endif + +# docker cli +install -D -m0755 %{cli_builddir}/build/docker %{buildroot}/%{_bindir}/docker +install -D -m0644 %{cli_builddir}/contrib/completion/bash/docker "%{buildroot}%{_datarootdir}/bash-completion/completions/docker" +install -D -m0644 %{cli_builddir}/contrib/completion/zsh/_docker "%{buildroot}%{_sysconfdir}/zsh_completion.d/_docker" +install -D -m0644 %{cli_builddir}/contrib/completion/fish/docker.fish "%{buildroot}/%{_datadir}/fish/vendor_completions.d/docker.fish" + +# systemd service +install -D -m0644 %{SOURCE100} %{buildroot}%{_unitdir}/docker.service +install -D -m0644 %{SOURCE101} %{buildroot}%{_unitdir}/docker.socket +ln -sf service %{buildroot}%{_sbindir}/rcdocker + +# udev rules that prevents dolphin to show all docker devices and slows down +# upstream report https://bugs.kde.org/show_bug.cgi?id=329930 +install -D -m0644 %{SOURCE110} %{buildroot}%{_udevrulesdir}/80-docker.rules + +# audit rules +install -D -m0640 %{SOURCE140} %{buildroot}%{_sysconfdir}/audit/rules.d/docker.rules + +# sysconfig file +install -D -m0644 %{SOURCE120} %{buildroot}%{_fillupdir}/sysconfig.docker + +# install manpages (using the ones from the engine) +install -d %{buildroot}%{_mandir}/man1 +install -p -m0644 %{cli_builddir}/man/man1/*.1 %{buildroot}%{_mandir}/man1 +install -d %{buildroot}%{_mandir}/man5 +install -p -m0644 %{cli_builddir}/man/man5/Dockerfile.5 %{buildroot}%{_mandir}/man5 +install -d %{buildroot}%{_mandir}/man8 +install -p -m0644 %{cli_builddir}/man/man8/*.8 %{buildroot}%{_mandir}/man8 + +# sysusers.d +install -D -m0644 %{SOURCE160} %{buildroot}%{_sysusersdir}/docker.conf + +# rootless extras +install -D -p -m 0755 contrib/dockerd-rootless.sh %{buildroot}/%{_bindir}/dockerd-rootless.sh +install -D -p -m 0755 contrib/dockerd-rootless-setuptool.sh %{buildroot}/%{_bindir}/dockerd-rootless-setuptool.sh + +%if %{with integration_tests} +# integration tests +install -d %{buildroot}%{testdir} +cp -ar %{docker_builddir} %{buildroot}%{testdir}/src +install -d %{buildroot}%{testdir}/bin +install -D -p -m 0755 %{SOURCE900} %{buildroot}%{testdir}/docker-integration.sh +# remove all of the non-test binaries in bundles/ +rm -rfv %{buildroot}%{testdir}/src/bundles/ +%endif + +%fdupes %{buildroot} + +%pre -f %{name}.pre +# /etc/sub[ug]id should exist already (it's part of shadow-utils), but older +# distros don't have it. Docker just parses it and doesn't need any special +# shadow-utils helpers. +touch /etc/subuid /etc/subgid ||: + +# "useradd -r" doesn't add sub[ug]ids so we manually add some. Hopefully there +# aren't any conflicts here, because usermod doesn't provide the same "get +# unusued range" feature that dockremap does. +grep -q '^dockremap:' /etc/subuid || \ + usermod -v 100000000-200000000 dockremap &>/dev/null || \ + echo "dockremap:100000000:100000001" >>/etc/subuid ||: +grep -q '^dockremap:' /etc/subgid || \ + usermod -w 100000000-200000000 dockremap &>/dev/null || \ + echo "dockremap:100000000:100000001" >>/etc/subgid ||: + +%service_add_pre docker.service docker.socket + +%post +%service_add_post docker.service docker.socket +%{fillup_only -n docker} + +%preun +%service_del_preun docker.service docker.socket + +%postun +%service_del_postun docker.service docker.socket + +%files +%defattr(-,root,root) +%doc README.md README_SUSE.md +%license LICENSE +%{_bindir}/docker +%{_bindir}/dockerd +%{_bindir}/docker-proxy +%{_sbindir}/rcdocker +%dir %{_localstatedir}/lib/docker/ + +%dir /usr/lib/docker +%dir /usr/lib/docker/cli-plugins + +%{_unitdir}/docker.service +%{_unitdir}/docker.socket +%{_sysusersdir}/docker.conf + +%dir %{_sysconfdir}/docker +%config(noreplace) %{_sysconfdir}/docker/daemon.json +%if %{with suseconnect} +%config(noreplace) %{_sysconfdir}/docker/suse-secrets-enable +%endif +%{_fillupdir}/sysconfig.docker + +%dir %attr(750,root,root) %{_sysconfdir}/audit/rules.d +%config %{_sysconfdir}/audit/rules.d/docker.rules +%{_udevrulesdir}/80-docker.rules + +%{_mandir}/man1/docker-*.1%{ext_man} +%{_mandir}/man1/docker.1%{ext_man} +%{_mandir}/man5/Dockerfile.5%{ext_man} +%{_mandir}/man8/dockerd.8%{ext_man} + +%if %{with buildx} +%files buildx +%defattr(-,root,root) +/usr/lib/docker/cli-plugins/docker-buildx +%endif + +%files rootless-extras +%defattr(-,root,root) +%{_bindir}/dockerd-rootless.sh +%{_bindir}/dockerd-rootless-setuptool.sh + +%if %{with integration_tests} +%files integration-tests-devel +%defattr(-,root,root) +%{testdir} +%endif + +%files bash-completion +%defattr(-,root,root) +%{_datarootdir}/bash-completion/completions/docker + +%files zsh-completion +%defattr(-,root,root) +%{_sysconfdir}/zsh_completion.d/_docker + +%files fish-completion +%defattr(-,root,root) +%{_datadir}/fish/vendor_completions.d/docker.fish + +%changelog diff --git a/docker.service b/docker.service new file mode 100644 index 0000000..1dd8b4d --- /dev/null +++ b/docker.service @@ -0,0 +1,45 @@ +[Unit] +Description=Docker Application Container Engine +Documentation=http://docs.docker.com +After=network.target lvm2-monitor.service firewalld.service +# We don't use the docker socket activation, but doing this ensures that the +# docker.socket unit is alive while Docker is (docker.socket has BindsTo, so we +# only need a weak requirement to make sure starting docker.service also +# "starts" the socket service). Forcefully stopping docker.socket will not +# cause docker to die, but there's no nice workaround for that. +Wants=docker.socket + +[Service] +EnvironmentFile=/etc/sysconfig/docker + +# While Docker has support for socket activation (-H fd://), this is not +# enabled by default because enabling socket activation means that on boot your +# containers won't start until someone tries to administer the Docker daemon. +Type=notify +ExecStart=/usr/bin/dockerd --add-runtime oci=/usr/sbin/runc $DOCKER_OPTS +ExecReload=/bin/kill -s HUP $MAINPID + +# Having non-zero Limit*s causes performance problems due to accounting overhead +# in the kernel. We recommend using cgroups to do container-local accounting. +LimitNOFILE=1048576 +LimitNPROC=infinity +LimitCORE=infinity + +# Uncomment TasksMax if your systemd version supports it. +# Only systemd 226 and above support this property. +TasksMax=infinity + +# Set delegate yes so that systemd does not reset the cgroups of docker containers +# Only systemd 218 and above support this property. +Delegate=yes + +# Kill only the docker process, not all processes in the cgroup. +KillMode=process + +# Restart the docker process if it exits prematurely. +Restart=on-failure +StartLimitBurst=3 +StartLimitInterval=60s + +[Install] +WantedBy=multi-user.target diff --git a/docker.socket b/docker.socket new file mode 100644 index 0000000..13fe927 --- /dev/null +++ b/docker.socket @@ -0,0 +1,18 @@ +[Unit] +Description=Docker Socket for the API +# We use BindsTo in order to make sure that you cannot use socket-activation +# with Docker (Docker must always start at boot if enabled, otherwise +# containers will not run until some administrator interacts with Docker). +BindsTo=docker.service + +[Socket] +# If /var/run is not implemented as a symlink to /run, you may need to +# specify ListenStream=/var/run/docker.sock instead. +ListenStream=/run/docker.sock +SocketMode=0660 +SocketUser=root +SocketGroup=docker + +[Install] +WantedBy=sockets.target + diff --git a/docker.sysusers b/docker.sysusers new file mode 100644 index 0000000..82b8e64 --- /dev/null +++ b/docker.sysusers @@ -0,0 +1,3 @@ +#Type Name ID GECOS Home directory Shell +g docker - - - - +u dockremap - 'docker --userns-remap=default' - - diff --git a/sysconfig.docker b/sysconfig.docker new file mode 100644 index 0000000..f089e52 --- /dev/null +++ b/sysconfig.docker @@ -0,0 +1,8 @@ + +## Path : System/Management +## Description : Extra cli switches for docker daemon +## Type : string +## Default : "" +## ServiceRestart : docker +# +DOCKER_OPTS=""