Merge pull request #3186 from thaJeztah/bump_dependencies

Bump dependencies
This commit is contained in:
Akihiro Suda 2019-04-06 13:28:24 +09:00 committed by GitHub
commit 4d313c00ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
71 changed files with 2878 additions and 1010 deletions

View File

@ -3,7 +3,7 @@ github.com/containerd/console c12b1e7919c14469339a5d38f2f8ed9b64a9de23
github.com/containerd/cgroups 4994991857f9b0ae8dc439551e8bebdbb4bf66c1 github.com/containerd/cgroups 4994991857f9b0ae8dc439551e8bebdbb4bf66c1
github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40 github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
github.com/containerd/btrfs 2e1aa0ddf94f91fa282b6ed87c23bf0d64911244 github.com/containerd/btrfs af5082808c833de0e79c1e72eea9fea239364877
github.com/containerd/continuity bd77b46c8352f74eb12c85bdc01f4b90f69d66b4 github.com/containerd/continuity bd77b46c8352f74eb12c85bdc01f4b90f69d66b4
github.com/coreos/go-systemd 48702e0da86bd25e76cfef347e2adeb434a0d0a6 github.com/coreos/go-systemd 48702e0da86bd25e76cfef347e2adeb434a0d0a6
github.com/docker/go-metrics 4ea375f7759c82740c893fc030bc37088d2ec098 github.com/docker/go-metrics 4ea375f7759c82740c893fc030bc37088d2ec098
@ -17,7 +17,7 @@ github.com/prometheus/procfs cb4147076ac75738c9a7d279075a253c0cc5acbd
github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9 github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
github.com/matttproud/golang_protobuf_extensions v1.0.1 github.com/matttproud/golang_protobuf_extensions v1.0.1
github.com/gogo/protobuf v1.2.1 github.com/gogo/protobuf v1.2.1
github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef github.com/gogo/googleapis v1.2.0
github.com/golang/protobuf v1.2.0 github.com/golang/protobuf v1.2.0
github.com/opencontainers/runtime-spec 29686dbc5559d93fb1ef402eeda3e35c38d75af4 # v1.0.1-59-g29686db github.com/opencontainers/runtime-spec 29686dbc5559d93fb1ef402eeda3e35c38d75af4 # v1.0.1-59-g29686db
github.com/opencontainers/runc 029124da7af7360afa781a0234d1b083550f797c github.com/opencontainers/runc 029124da7af7360afa781a0234d1b083550f797c
@ -26,12 +26,12 @@ github.com/sirupsen/logrus v1.4.1
github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c
golang.org/x/net b3756b4b77d7b13260a0a2ec658753cf48922eac golang.org/x/net b3756b4b77d7b13260a0a2ec658753cf48922eac
google.golang.org/grpc v1.12.0 google.golang.org/grpc v1.12.0
github.com/pkg/errors v0.8.0 github.com/pkg/errors v0.8.1
github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7 github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7
golang.org/x/sys d455e41777fca6e8a5a79e34a14b8368bc11d9ba https://github.com/golang/sys golang.org/x/sys d455e41777fca6e8a5a79e34a14b8368bc11d9ba https://github.com/golang/sys
github.com/opencontainers/image-spec v1.0.1 github.com/opencontainers/image-spec v1.0.1
golang.org/x/sync 42b317875d0fa942474b76e1b46a6060d720ae6e golang.org/x/sync 42b317875d0fa942474b76e1b46a6060d720ae6e
github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895 github.com/BurntSushi/toml v0.3.1
github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0 github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0
github.com/Microsoft/go-winio c599b533b43b1363d7d7c6cfda5ede70ed73ff13 github.com/Microsoft/go-winio c599b533b43b1363d7d7c6cfda5ede70ed73ff13
github.com/Microsoft/hcsshim 8abdbb8205e4192c68b5f84c31197156f31be517 github.com/Microsoft/hcsshim 8abdbb8205e4192c68b5f84c31197156f31be517
@ -39,8 +39,8 @@ google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4 golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
github.com/containerd/ttrpc f02858b1457c5ca3aaec3a0803eb0d59f96e41d6 github.com/containerd/ttrpc f02858b1457c5ca3aaec3a0803eb0d59f96e41d6
github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16 github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16
gotest.tools v2.1.0 gotest.tools v2.3.0
github.com/google/go-cmp v0.1.0 github.com/google/go-cmp v0.2.0
go.etcd.io/bbolt v1.3.2 go.etcd.io/bbolt v1.3.2
# cri dependencies # cri dependencies
@ -77,9 +77,10 @@ k8s.io/utils c2654d5206da6b7b6ace12841e8f359bb89b443c
sigs.k8s.io/yaml v1.1.0 sigs.k8s.io/yaml v1.1.0
# zfs dependencies # zfs dependencies
github.com/containerd/zfs 9f6ef3b1fe5144bd91fe5855b4eba81bc0d17d03 github.com/containerd/zfs 31af176f2ae84fe142ef2655bf7bb2aa618b3b1f
github.com/mistifyio/go-zfs 166add352731e515512690329794ee593f1aaff2 github.com/mistifyio/go-zfs d5b163290a48f624cbf244ebe4e89ce38653064c
github.com/pborman/uuid c65b2f87fee37d1c7854c9164a450713c28d50cd github.com/pborman/uuid v1.2.0
github.com/google/uuid v1.1.1
# aufs dependencies # aufs dependencies
github.com/containerd/aufs da3cf16bfbe68ba8f114f1536a05c01528a25434 github.com/containerd/aufs f894a800659b6e11c1a13084abd1712f346e349c

View File

@ -21,3 +21,13 @@ import (
_ "github.com/containerd/containerd/snapshot/overlay" _ "github.com/containerd/containerd/snapshot/overlay"
) )
``` ```
## Project details
aufs is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE).
As a containerd sub-project, you will find the:
* [Project governance](https://github.com/containerd/project/blob/master/GOVERNANCE.md),
* [Maintainers](https://github.com/containerd/project/blob/master/MAINTAINERS),
* and [Contributing guidelines](https://github.com/containerd/project/blob/master/CONTRIBUTING.md)
information in our [`containerd/project`](https://github.com/containerd/project) repository.

View File

@ -1,3 +1,19 @@
/*
Copyright The containerd 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 aufs package aufs
import ( import (
@ -99,8 +115,7 @@ func (o *snapshotter) Update(ctx context.Context, info snapshots.Info, fieldpath
// Usage returns the resources taken by the snapshot identified by key. // Usage returns the resources taken by the snapshot identified by key.
// //
// For active snapshots, this will scan the usage of the overlay "diff" (aka // For active snapshots, this will scan the usage of directory and may take some time.
// "upper") directory and may take some time.
// //
// For committed snapshots, the value is returned from the metadata database. // For committed snapshots, the value is returned from the metadata database.
func (o *snapshotter) Usage(ctx context.Context, key string) (snapshots.Usage, error) { func (o *snapshotter) Usage(ctx context.Context, key string) (snapshots.Usage, error) {
@ -318,8 +333,7 @@ func (o *snapshotter) createSnapshot(ctx context.Context, kind snapshots.Kind, k
func (o *snapshotter) mounts(s storage.Snapshot) []mount.Mount { func (o *snapshotter) mounts(s storage.Snapshot) []mount.Mount {
if len(s.ParentIDs) == 0 { if len(s.ParentIDs) == 0 {
// if we only have one layer/no parents then just return a bind mount as overlay // if we only have one layer/no parents then just return a bind mount
// will not work
roFlag := "rw" roFlag := "rw"
if s.Kind == snapshots.KindView { if s.Kind == snapshots.KindView {
roFlag = "ro" roFlag = "ro"

View File

@ -30,9 +30,14 @@ $ ltag -t ./license-templates
The above will add the appropriate licenses to Go files. New templates will The above will add the appropriate licenses to Go files. New templates will
need to be added if other kinds of files are added. Please consult the need to be added if other kinds of files are added. Please consult the
documentation at https://github.com/ documentation at https://github.com/kunalkushwaha/ltag
# License ## Project details
The copyright to this repository is held by the The containerd Authors and the btrfs is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE).
codebase is released under the [Apache 2.0 license](LICENSE). As a containerd sub-project, you will find the:
* [Project governance](https://github.com/containerd/project/blob/master/GOVERNANCE.md),
* [Maintainers](https://github.com/containerd/project/blob/master/MAINTAINERS),
* and [Contributing guidelines](https://github.com/containerd/project/blob/master/CONTRIBUTING.md)
information in our [`containerd/project`](https://github.com/containerd/project) repository.

View File

@ -1,3 +1,19 @@
/*
Copyright The containerd 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.
*/
#include <stddef.h> #include <stddef.h>
#include <linux/magic.h> #include <linux/magic.h>
#include <btrfs/ioctl.h> #include <btrfs/ioctl.h>

View File

@ -1,3 +1,19 @@
/*
Copyright The containerd 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.
*/
/* /*
Copyright The containerd Authors Copyright The containerd Authors

View File

@ -1,3 +1,19 @@
/*
Copyright The containerd 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.
*/
#include <stddef.h> #include <stddef.h>
#include <linux/magic.h> #include <linux/magic.h>
#include <btrfs/ioctl.h> #include <btrfs/ioctl.h>

View File

@ -1,3 +1,19 @@
/*
Copyright The containerd 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.
*/
/* /*
Copyright The containerd Authors Copyright The containerd Authors

View File

@ -1,3 +1,19 @@
/*
Copyright The containerd 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.
*/
/* /*
Copyright The containerd Authors Copyright The containerd Authors

View File

@ -1,3 +1,19 @@
/*
Copyright The containerd 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.
*/
/* /*
Copyright The containerd Authors Copyright The containerd Authors

View File

@ -1,3 +1,19 @@
/*
Copyright The containerd 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.
*/
/* /*
Copyright The containerd Authors Copyright The containerd Authors

View File

@ -36,3 +36,13 @@ $ zfs create -o mountpoint=/var/lib/containerd/io.containerd.snapshotter.v1.zfs
2. Start containerd. 2. Start containerd.
3. e.g. `ctr pull --snapshotter=zfs ...` 3. e.g. `ctr pull --snapshotter=zfs ...`
## Project details
The zfs plugin is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE).
As a containerd sub-project, you will find the:
* [Project governance](https://github.com/containerd/project/blob/master/GOVERNANCE.md),
* [Maintainers](https://github.com/containerd/project/blob/master/MAINTAINERS),
* and [Contributing guidelines](https://github.com/containerd/project/blob/master/CONTRIBUTING.md)
information in our [`containerd/project`](https://github.com/containerd/project) repository.

View File

@ -1,5 +1,21 @@
// +build linux freebsd // +build linux freebsd
/*
Copyright The containerd 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 zfs package zfs
import ( import (

203
vendor/github.com/gogo/googleapis/LICENSE generated vendored Normal file
View File

@ -0,0 +1,203 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2015, Google Inc
Copyright 2018, GoGo 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.

View File

@ -3,17 +3,24 @@
package rpc package rpc
import proto "github.com/gogo/protobuf/proto" import (
import fmt "fmt" fmt "fmt"
import math "math" proto "github.com/gogo/protobuf/proto"
math "math"
import strconv "strconv" strconv "strconv"
)
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal var _ = proto.Marshal
var _ = fmt.Errorf var _ = fmt.Errorf
var _ = math.Inf var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
// The canonical error codes for Google APIs. // The canonical error codes for Google APIs.
// //
// //
@ -181,6 +188,7 @@ var Code_name = map[int32]string{
14: "UNAVAILABLE", 14: "UNAVAILABLE",
15: "DATA_LOSS", 15: "DATA_LOSS",
} }
var Code_value = map[string]int32{ var Code_value = map[string]int32{
"OK": 0, "OK": 0,
"CANCELLED": 1, "CANCELLED": 1,
@ -201,22 +209,17 @@ var Code_value = map[string]int32{
"DATA_LOSS": 15, "DATA_LOSS": 15,
} }
func (Code) EnumDescriptor() ([]byte, []int) { return fileDescriptorCode, []int{0} } func (Code) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_fe593a732623ccf0, []int{0}
}
func init() { func init() {
proto.RegisterEnum("google.rpc.Code", Code_name, Code_value) proto.RegisterEnum("google.rpc.Code", Code_name, Code_value)
} }
func (x Code) String() string {
s, ok := Code_name[int32(x)]
if ok {
return s
}
return strconv.Itoa(int(x))
}
func init() { proto.RegisterFile("google/rpc/code.proto", fileDescriptorCode) } func init() { proto.RegisterFile("google/rpc/code.proto", fileDescriptor_fe593a732623ccf0) }
var fileDescriptorCode = []byte{ var fileDescriptor_fe593a732623ccf0 = []byte{
// 393 bytes of a gzipped FileDescriptorProto // 393 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x44, 0x91, 0x3d, 0x6e, 0x13, 0x41, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x44, 0x91, 0x3d, 0x6e, 0x13, 0x41,
0x14, 0xc7, 0x3d, 0x76, 0x70, 0xe2, 0xf1, 0xd7, 0xcb, 0x84, 0x40, 0x37, 0x07, 0xa0, 0x70, 0x0a, 0x14, 0xc7, 0x3d, 0x76, 0x70, 0xe2, 0xf1, 0xd7, 0xcb, 0x84, 0x40, 0x37, 0x07, 0xa0, 0x70, 0x0a,
@ -244,3 +247,11 @@ var fileDescriptorCode = []byte{
0xf3, 0xb5, 0x3f, 0x08, 0x65, 0xf1, 0x61, 0xf8, 0xb7, 0xaa, 0xd7, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xf3, 0xb5, 0x3f, 0x08, 0x65, 0xf1, 0x61, 0xf8, 0xb7, 0xaa, 0xd7, 0x7f, 0x02, 0x00, 0x00, 0xff,
0xff, 0x03, 0xd4, 0x27, 0xff, 0xc3, 0x01, 0x00, 0x00, 0xff, 0x03, 0xd4, 0x27, 0xff, 0xc3, 0x01, 0x00, 0x00,
} }
func (x Code) String() string {
s, ok := Code_name[int32(x)]
if ok {
return s
}
return strconv.Itoa(int(x))
}

View File

@ -22,7 +22,6 @@ option java_outer_classname = "CodeProto";
option java_package = "com.google.rpc"; option java_package = "com.google.rpc";
option objc_class_prefix = "RPC"; option objc_class_prefix = "RPC";
// The canonical error codes for Google APIs. // The canonical error codes for Google APIs.
// //
// //

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,6 @@ option java_outer_classname = "ErrorDetailsProto";
option java_package = "com.google.rpc"; option java_package = "com.google.rpc";
option objc_class_prefix = "RPC"; option objc_class_prefix = "RPC";
// Describes when the clients can retry a failed request. Clients could ignore // Describes when the clients can retry a failed request. Clients could ignore
// the recommendation here or retry when this information is missing from error // the recommendation here or retry when this information is missing from error
// responses. // responses.
@ -154,7 +153,8 @@ message ResourceInfo {
// The name of the resource being accessed. For example, a shared calendar // The name of the resource being accessed. For example, a shared calendar
// name: "example.com_4fghdhgsrgh@group.calendar.google.com", if the current // name: "example.com_4fghdhgsrgh@group.calendar.google.com", if the current
// error is [google.rpc.Code.PERMISSION_DENIED][google.rpc.Code.PERMISSION_DENIED]. // error is
// [google.rpc.Code.PERMISSION_DENIED][google.rpc.Code.PERMISSION_DENIED].
string resource_name = 2; string resource_name = 2;
// The owner of the resource (optional). // The owner of the resource (optional).

View File

@ -1,37 +1,18 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT. // Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: google/rpc/status.proto // source: google/rpc/status.proto
/*
Package rpc is a generated protocol buffer package.
It is generated from these files:
google/rpc/status.proto
google/rpc/error_details.proto
google/rpc/code.proto
It has these top-level messages:
Status
RetryInfo
DebugInfo
QuotaFailure
PreconditionFailure
BadRequest
RequestInfo
ResourceInfo
Help
LocalizedMessage
*/
package rpc package rpc
import proto "github.com/gogo/protobuf/proto" import (
import fmt "fmt" bytes "bytes"
import math "math" fmt "fmt"
import google_protobuf "github.com/gogo/protobuf/types" proto "github.com/gogo/protobuf/proto"
types "github.com/gogo/protobuf/types"
import strings "strings" io "io"
import reflect "reflect" math "math"
reflect "reflect"
import io "io" strings "strings"
)
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal var _ = proto.Marshal
@ -44,24 +25,25 @@ var _ = math.Inf
// proto package needs to be updated. // proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
// The `Status` type defines a logical error model that is suitable for different // The `Status` type defines a logical error model that is suitable for
// programming environments, including REST APIs and RPC APIs. It is used by // different programming environments, including REST APIs and RPC APIs. It is
// [gRPC](https://github.com/grpc). The error model is designed to be: // used by [gRPC](https://github.com/grpc). The error model is designed to be:
// //
// - Simple to use and understand for most users // - Simple to use and understand for most users
// - Flexible enough to meet unexpected needs // - Flexible enough to meet unexpected needs
// //
// # Overview // # Overview
// //
// The `Status` message contains three pieces of data: error code, error message, // The `Status` message contains three pieces of data: error code, error
// and error details. The error code should be an enum value of // message, and error details. The error code should be an enum value of
// [google.rpc.Code][google.rpc.Code], but it may accept additional error codes if needed. The // [google.rpc.Code][google.rpc.Code], but it may accept additional error codes
// error message should be a developer-facing English message that helps // if needed. The error message should be a developer-facing English message
// developers *understand* and *resolve* the error. If a localized user-facing // that helps developers *understand* and *resolve* the error. If a localized
// error message is needed, put the localized message in the error details or // user-facing error message is needed, put the localized message in the error
// localize it in the client. The optional error details may contain arbitrary // details or localize it in the client. The optional error details may contain
// information about the error. There is a predefined set of error detail types // arbitrary information about the error. There is a predefined set of error
// in the package `google.rpc` that can be used for common error conditions. // detail types in the package `google.rpc` that can be used for common error
// conditions.
// //
// # Language mapping // # Language mapping
// //
@ -97,20 +79,53 @@ const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
// - Logging. If some API errors are stored in logs, the message `Status` could // - Logging. If some API errors are stored in logs, the message `Status` could
// be used directly after any stripping needed for security/privacy reasons. // be used directly after any stripping needed for security/privacy reasons.
type Status struct { type Status struct {
// 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"` Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
// A developer-facing error message, which should be in English. Any // A developer-facing error message, which should be in English. Any
// user-facing error message should be localized and sent in the // 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"` 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 // A list of messages that carry the error details. There is a common set of
// message types for APIs to use. // message types for APIs to use.
Details []*google_protobuf.Any `protobuf:"bytes,3,rep,name=details" json:"details,omitempty"` Details []*types.Any `protobuf:"bytes,3,rep,name=details,proto3" json:"details,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
} }
func (m *Status) Reset() { *m = Status{} } func (m *Status) Reset() { *m = Status{} }
func (*Status) ProtoMessage() {} func (*Status) ProtoMessage() {}
func (*Status) Descriptor() ([]byte, []int) { return fileDescriptorStatus, []int{0} } func (*Status) Descriptor() ([]byte, []int) {
return fileDescriptor_24d244abaf643bfe, []int{0}
}
func (m *Status) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *Status) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_Status.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalTo(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *Status) XXX_Merge(src proto.Message) {
xxx_messageInfo_Status.Merge(m, src)
}
func (m *Status) XXX_Size() int {
return m.Size()
}
func (m *Status) XXX_DiscardUnknown() {
xxx_messageInfo_Status.DiscardUnknown(m)
}
var xxx_messageInfo_Status proto.InternalMessageInfo
func (m *Status) GetCode() int32 { func (m *Status) GetCode() int32 {
if m != nil { if m != nil {
@ -126,7 +141,7 @@ func (m *Status) GetMessage() string {
return "" return ""
} }
func (m *Status) GetDetails() []*google_protobuf.Any { func (m *Status) GetDetails() []*types.Any {
if m != nil { if m != nil {
return m.Details return m.Details
} }
@ -139,6 +154,28 @@ func (*Status) XXX_MessageName() string {
func init() { func init() {
proto.RegisterType((*Status)(nil), "google.rpc.Status") proto.RegisterType((*Status)(nil), "google.rpc.Status")
} }
func init() { proto.RegisterFile("google/rpc/status.proto", fileDescriptor_24d244abaf643bfe) }
var fileDescriptor_24d244abaf643bfe = []byte{
// 235 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4f, 0xcf, 0xcf, 0x4f,
0xcf, 0x49, 0xd5, 0x2f, 0x2a, 0x48, 0xd6, 0x2f, 0x2e, 0x49, 0x2c, 0x29, 0x2d, 0xd6, 0x2b, 0x28,
0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x82, 0x48, 0xe8, 0x15, 0x15, 0x24, 0x4b, 0x49, 0x42, 0x15, 0x81,
0x65, 0x92, 0x4a, 0xd3, 0xf4, 0x13, 0xf3, 0x2a, 0x21, 0xca, 0x94, 0xd2, 0xb8, 0xd8, 0x82, 0xc1,
0xda, 0x84, 0x84, 0xb8, 0x58, 0x92, 0xf3, 0x53, 0x52, 0x25, 0x18, 0x15, 0x18, 0x35, 0x58, 0x83,
0xc0, 0x6c, 0x21, 0x09, 0x2e, 0xf6, 0xdc, 0xd4, 0xe2, 0xe2, 0xc4, 0xf4, 0x54, 0x09, 0x26, 0x05,
0x46, 0x0d, 0xce, 0x20, 0x18, 0x57, 0x48, 0x8f, 0x8b, 0x3d, 0x25, 0xb5, 0x24, 0x31, 0x33, 0xa7,
0x58, 0x82, 0x59, 0x81, 0x59, 0x83, 0xdb, 0x48, 0x44, 0x0f, 0x6a, 0x21, 0xcc, 0x12, 0x3d, 0xc7,
0xbc, 0xca, 0x20, 0x98, 0x22, 0xa7, 0xb8, 0x0b, 0x0f, 0xe5, 0x18, 0x6e, 0x3c, 0x94, 0x63, 0xf8,
0xf0, 0x50, 0x8e, 0xf1, 0xc7, 0x43, 0x39, 0xc6, 0x86, 0x47, 0x72, 0x8c, 0x2b, 0x1e, 0xc9, 0x31,
0x9e, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x2f, 0x1e, 0xc9,
0x31, 0x7c, 0x00, 0x89, 0x3f, 0x96, 0x63, 0x3c, 0xf1, 0x58, 0x8e, 0x91, 0x8b, 0x2f, 0x39, 0x3f,
0x57, 0x0f, 0xe1, 0x11, 0x27, 0x6e, 0x88, 0x5b, 0x03, 0x40, 0x56, 0x04, 0x30, 0x46, 0x31, 0x17,
0x15, 0x24, 0x2f, 0x62, 0x62, 0x0e, 0x0a, 0x70, 0x4e, 0x62, 0x03, 0x5b, 0x6b, 0x0c, 0x08, 0x00,
0x00, 0xff, 0xff, 0xaa, 0x06, 0xa1, 0xaa, 0x10, 0x01, 0x00, 0x00,
}
func (this *Status) Compare(that interface{}) int { func (this *Status) Compare(that interface{}) int {
if that == nil { if that == nil {
if this == nil { if this == nil {
@ -187,6 +224,9 @@ func (this *Status) Compare(that interface{}) int {
return c return c
} }
} }
if c := bytes.Compare(this.XXX_unrecognized, that1.XXX_unrecognized); c != 0 {
return c
}
return 0 return 0
} }
func (this *Status) Equal(that interface{}) bool { func (this *Status) Equal(that interface{}) bool {
@ -222,6 +262,9 @@ func (this *Status) Equal(that interface{}) bool {
return false return false
} }
} }
if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
return false
}
return true return true
} }
func (this *Status) GoString() string { func (this *Status) GoString() string {
@ -235,6 +278,9 @@ func (this *Status) GoString() string {
if this.Details != nil { if this.Details != nil {
s = append(s, "Details: "+fmt.Sprintf("%#v", this.Details)+",\n") s = append(s, "Details: "+fmt.Sprintf("%#v", this.Details)+",\n")
} }
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}") s = append(s, "}")
return strings.Join(s, "") return strings.Join(s, "")
} }
@ -284,6 +330,9 @@ func (m *Status) MarshalTo(dAtA []byte) (int, error) {
i += n i += n
} }
} }
if m.XXX_unrecognized != nil {
i += copy(dAtA[i:], m.XXX_unrecognized)
}
return i, nil return i, nil
} }
@ -305,12 +354,13 @@ func NewPopulatedStatus(r randyStatus, easy bool) *Status {
this.Message = string(randStringStatus(r)) this.Message = string(randStringStatus(r))
if r.Intn(10) != 0 { if r.Intn(10) != 0 {
v1 := r.Intn(5) v1 := r.Intn(5)
this.Details = make([]*google_protobuf.Any, v1) this.Details = make([]*types.Any, v1)
for i := 0; i < v1; i++ { for i := 0; i < v1; i++ {
this.Details[i] = google_protobuf.NewPopulatedAny(r, easy) this.Details[i] = types.NewPopulatedAny(r, easy)
} }
} }
if !easy && r.Intn(10) != 0 { if !easy && r.Intn(10) != 0 {
this.XXX_unrecognized = randUnrecognizedStatus(r, 4)
} }
return this return this
} }
@ -388,6 +438,9 @@ func encodeVarintPopulateStatus(dAtA []byte, v uint64) []byte {
return dAtA return dAtA
} }
func (m *Status) Size() (n int) { func (m *Status) Size() (n int) {
if m == nil {
return 0
}
var l int var l int
_ = l _ = l
if m.Code != 0 { if m.Code != 0 {
@ -403,6 +456,9 @@ func (m *Status) Size() (n int) {
n += 1 + l + sovStatus(uint64(l)) n += 1 + l + sovStatus(uint64(l))
} }
} }
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n return n
} }
@ -426,7 +482,8 @@ func (this *Status) String() string {
s := strings.Join([]string{`&Status{`, s := strings.Join([]string{`&Status{`,
`Code:` + fmt.Sprintf("%v", this.Code) + `,`, `Code:` + fmt.Sprintf("%v", this.Code) + `,`,
`Message:` + fmt.Sprintf("%v", this.Message) + `,`, `Message:` + fmt.Sprintf("%v", this.Message) + `,`,
`Details:` + strings.Replace(fmt.Sprintf("%v", this.Details), "Any", "google_protobuf.Any", 1) + `,`, `Details:` + strings.Replace(fmt.Sprintf("%v", this.Details), "Any", "types.Any", 1) + `,`,
`XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`,
`}`, `}`,
}, "") }, "")
return s return s
@ -454,7 +511,7 @@ func (m *Status) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
wire |= (uint64(b) & 0x7F) << shift wire |= uint64(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -482,7 +539,7 @@ func (m *Status) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
m.Code |= (int32(b) & 0x7F) << shift m.Code |= int32(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -501,7 +558,7 @@ func (m *Status) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift stringLen |= uint64(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -511,6 +568,9 @@ func (m *Status) Unmarshal(dAtA []byte) error {
return ErrInvalidLengthStatus return ErrInvalidLengthStatus
} }
postIndex := iNdEx + intStringLen postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthStatus
}
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
@ -530,7 +590,7 @@ func (m *Status) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
msglen |= (int(b) & 0x7F) << shift msglen |= int(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -539,10 +599,13 @@ func (m *Status) Unmarshal(dAtA []byte) error {
return ErrInvalidLengthStatus return ErrInvalidLengthStatus
} }
postIndex := iNdEx + msglen postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthStatus
}
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.Details = append(m.Details, &google_protobuf.Any{}) m.Details = append(m.Details, &types.Any{})
if err := m.Details[len(m.Details)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { if err := m.Details[len(m.Details)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
@ -556,9 +619,13 @@ func (m *Status) Unmarshal(dAtA []byte) error {
if skippy < 0 { if skippy < 0 {
return ErrInvalidLengthStatus return ErrInvalidLengthStatus
} }
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthStatus
}
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy iNdEx += skippy
} }
} }
@ -622,10 +689,13 @@ func skipStatus(dAtA []byte) (n int, err error) {
break break
} }
} }
iNdEx += length
if length < 0 { if length < 0 {
return 0, ErrInvalidLengthStatus return 0, ErrInvalidLengthStatus
} }
iNdEx += length
if iNdEx < 0 {
return 0, ErrInvalidLengthStatus
}
return iNdEx, nil return iNdEx, nil
case 3: case 3:
for { for {
@ -654,6 +724,9 @@ func skipStatus(dAtA []byte) (n int, err error) {
return 0, err return 0, err
} }
iNdEx = start + next iNdEx = start + next
if iNdEx < 0 {
return 0, ErrInvalidLengthStatus
}
} }
return iNdEx, nil return iNdEx, nil
case 4: case 4:
@ -672,24 +745,3 @@ var (
ErrInvalidLengthStatus = fmt.Errorf("proto: negative length found during unmarshaling") ErrInvalidLengthStatus = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowStatus = fmt.Errorf("proto: integer overflow") ErrIntOverflowStatus = fmt.Errorf("proto: integer overflow")
) )
func init() { proto.RegisterFile("google/rpc/status.proto", fileDescriptorStatus) }
var fileDescriptorStatus = []byte{
// 235 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4f, 0xcf, 0xcf, 0x4f,
0xcf, 0x49, 0xd5, 0x2f, 0x2a, 0x48, 0xd6, 0x2f, 0x2e, 0x49, 0x2c, 0x29, 0x2d, 0xd6, 0x2b, 0x28,
0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x82, 0x48, 0xe8, 0x15, 0x15, 0x24, 0x4b, 0x49, 0x42, 0x15, 0x81,
0x65, 0x92, 0x4a, 0xd3, 0xf4, 0x13, 0xf3, 0x2a, 0x21, 0xca, 0x94, 0xd2, 0xb8, 0xd8, 0x82, 0xc1,
0xda, 0x84, 0x84, 0xb8, 0x58, 0x92, 0xf3, 0x53, 0x52, 0x25, 0x18, 0x15, 0x18, 0x35, 0x58, 0x83,
0xc0, 0x6c, 0x21, 0x09, 0x2e, 0xf6, 0xdc, 0xd4, 0xe2, 0xe2, 0xc4, 0xf4, 0x54, 0x09, 0x26, 0x05,
0x46, 0x0d, 0xce, 0x20, 0x18, 0x57, 0x48, 0x8f, 0x8b, 0x3d, 0x25, 0xb5, 0x24, 0x31, 0x33, 0xa7,
0x58, 0x82, 0x59, 0x81, 0x59, 0x83, 0xdb, 0x48, 0x44, 0x0f, 0x6a, 0x21, 0xcc, 0x12, 0x3d, 0xc7,
0xbc, 0xca, 0x20, 0x98, 0x22, 0xa7, 0xb8, 0x0b, 0x0f, 0xe5, 0x18, 0x6e, 0x3c, 0x94, 0x63, 0xf8,
0xf0, 0x50, 0x8e, 0xf1, 0xc7, 0x43, 0x39, 0xc6, 0x86, 0x47, 0x72, 0x8c, 0x2b, 0x1e, 0xc9, 0x31,
0x9e, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x2f, 0x1e, 0xc9,
0x31, 0x7c, 0x00, 0x89, 0x3f, 0x96, 0x63, 0x3c, 0xf1, 0x58, 0x8e, 0x91, 0x8b, 0x2f, 0x39, 0x3f,
0x57, 0x0f, 0xe1, 0x11, 0x27, 0x6e, 0x88, 0x5b, 0x03, 0x40, 0x56, 0x04, 0x30, 0x46, 0x31, 0x17,
0x15, 0x24, 0x2f, 0x62, 0x62, 0x0e, 0x0a, 0x70, 0x4e, 0x62, 0x03, 0x5b, 0x6b, 0x0c, 0x08, 0x00,
0x00, 0xff, 0xff, 0xaa, 0x06, 0xa1, 0xaa, 0x10, 0x01, 0x00, 0x00,
}

View File

@ -24,25 +24,25 @@ option java_outer_classname = "StatusProto";
option java_package = "com.google.rpc"; option java_package = "com.google.rpc";
option objc_class_prefix = "RPC"; option objc_class_prefix = "RPC";
// The `Status` type defines a logical error model that is suitable for
// The `Status` type defines a logical error model that is suitable for different // different programming environments, including REST APIs and RPC APIs. It is
// programming environments, including REST APIs and RPC APIs. It is used by // used by [gRPC](https://github.com/grpc). The error model is designed to be:
// [gRPC](https://github.com/grpc). The error model is designed to be:
// //
// - Simple to use and understand for most users // - Simple to use and understand for most users
// - Flexible enough to meet unexpected needs // - Flexible enough to meet unexpected needs
// //
// # Overview // # Overview
// //
// The `Status` message contains three pieces of data: error code, error message, // The `Status` message contains three pieces of data: error code, error
// and error details. The error code should be an enum value of // message, and error details. The error code should be an enum value of
// [google.rpc.Code][google.rpc.Code], but it may accept additional error codes if needed. The // [google.rpc.Code][google.rpc.Code], but it may accept additional error codes
// error message should be a developer-facing English message that helps // if needed. The error message should be a developer-facing English message
// developers *understand* and *resolve* the error. If a localized user-facing // that helps developers *understand* and *resolve* the error. If a localized
// error message is needed, put the localized message in the error details or // user-facing error message is needed, put the localized message in the error
// localize it in the client. The optional error details may contain arbitrary // details or localize it in the client. The optional error details may contain
// information about the error. There is a predefined set of error detail types // arbitrary information about the error. There is a predefined set of error
// in the package `google.rpc` that can be used for common error conditions. // detail types in the package `google.rpc` that can be used for common error
// conditions.
// //
// # Language mapping // # Language mapping
// //
@ -78,12 +78,14 @@ option objc_class_prefix = "RPC";
// - Logging. If some API errors are stored in logs, the message `Status` could // - Logging. If some API errors are stored in logs, the message `Status` could
// be used directly after any stripping needed for security/privacy reasons. // be used directly after any stripping needed for security/privacy reasons.
message Status { message Status {
// 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].
int32 code = 1; int32 code = 1;
// A developer-facing error message, which should be in English. Any // A developer-facing error message, which should be in English. Any
// user-facing error message should be localized and sent in the // 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.
string message = 2; string message = 2;
// A list of messages that carry the error details. There is a common set of // A list of messages that carry the error details. There is a common set of

View File

@ -21,7 +21,7 @@ The primary features of `cmp` are:
equality is determined by recursively comparing the primitive kinds on both equality is determined by recursively comparing the primitive kinds on both
values, much like `reflect.DeepEqual`. Unlike `reflect.DeepEqual`, unexported values, much like `reflect.DeepEqual`. Unlike `reflect.DeepEqual`, unexported
fields are not compared by default; they result in panics unless suppressed fields are not compared by default; they result in panics unless suppressed
by using an `Ignore` option (see `cmpopts.IgnoreUnexported`) or explictly by using an `Ignore` option (see `cmpopts.IgnoreUnexported`) or explicitly
compared using the `AllowUnexported` option. compared using the `AllowUnexported` option.
See the [GoDoc documentation][godoc] for more information. See the [GoDoc documentation][godoc] for more information.

View File

@ -17,7 +17,7 @@ func equateAlways(_, _ interface{}) bool { return true }
// EquateEmpty returns a Comparer option that determines all maps and slices // EquateEmpty returns a Comparer option that determines all maps and slices
// with a length of zero to be equal, regardless of whether they are nil. // with a length of zero to be equal, regardless of whether they are nil.
// //
// EquateEmpty can be used in conjuction with SortSlices and SortMaps. // EquateEmpty can be used in conjunction with SortSlices and SortMaps.
func EquateEmpty() cmp.Option { func EquateEmpty() cmp.Option {
return cmp.FilterValues(isEmpty, cmp.Comparer(equateAlways)) return cmp.FilterValues(isEmpty, cmp.Comparer(equateAlways))
} }
@ -42,7 +42,7 @@ func isEmpty(x, y interface{}) bool {
// The mathematical expression used is equivalent to: // The mathematical expression used is equivalent to:
// |x-y| ≤ max(fraction*min(|x|, |y|), margin) // |x-y| ≤ max(fraction*min(|x|, |y|), margin)
// //
// EquateApprox can be used in conjuction with EquateNaNs. // EquateApprox can be used in conjunction with EquateNaNs.
func EquateApprox(fraction, margin float64) cmp.Option { func EquateApprox(fraction, margin float64) cmp.Option {
if margin < 0 || fraction < 0 || math.IsNaN(margin) || math.IsNaN(fraction) { if margin < 0 || fraction < 0 || math.IsNaN(margin) || math.IsNaN(fraction) {
panic("margin or fraction must be a non-negative number") panic("margin or fraction must be a non-negative number")
@ -73,7 +73,7 @@ func (a approximator) compareF32(x, y float32) bool {
// EquateNaNs returns a Comparer option that determines float32 and float64 // EquateNaNs returns a Comparer option that determines float32 and float64
// NaN values to be equal. // NaN values to be equal.
// //
// EquateNaNs can be used in conjuction with EquateApprox. // EquateNaNs can be used in conjunction with EquateApprox.
func EquateNaNs() cmp.Option { func EquateNaNs() cmp.Option {
return cmp.Options{ return cmp.Options{
cmp.FilterValues(areNaNsF64s, cmp.Comparer(equateAlways)), cmp.FilterValues(areNaNsF64s, cmp.Comparer(equateAlways)),

View File

@ -50,7 +50,7 @@ func (tf typeFilter) filter(p cmp.Path) bool {
if len(p) < 1 { if len(p) < 1 {
return false return false
} }
t := p[len(p)-1].Type() t := p.Last().Type()
for _, ti := range tf { for _, ti := range tf {
if t.AssignableTo(ti) { if t.AssignableTo(ti) {
return true return true
@ -95,7 +95,7 @@ func (tf ifaceFilter) filter(p cmp.Path) bool {
if len(p) < 1 { if len(p) < 1 {
return false return false
} }
t := p[len(p)-1].Type() t := p.Last().Type()
for _, ti := range tf { for _, ti := range tf {
if t.AssignableTo(ti) { if t.AssignableTo(ti) {
return true return true
@ -131,14 +131,11 @@ func newUnexportedFilter(typs ...interface{}) unexportedFilter {
return ux return ux
} }
func (xf unexportedFilter) filter(p cmp.Path) bool { func (xf unexportedFilter) filter(p cmp.Path) bool {
if len(p) < 2 { sf, ok := p.Index(-1).(cmp.StructField)
return false
}
sf, ok := p[len(p)-1].(cmp.StructField)
if !ok { if !ok {
return false return false
} }
return xf.m[p[len(p)-2].Type()] && !isExported(sf.Name()) return xf.m[p.Index(-2).Type()] && !isExported(sf.Name())
} }
// isExported reports whether the identifier is exported. // isExported reports whether the identifier is exported.

View File

@ -24,7 +24,7 @@ import (
// The less function does not have to be "total". That is, if !less(x, y) and // The less function does not have to be "total". That is, if !less(x, y) and
// !less(y, x) for two elements x and y, their relative order is maintained. // !less(y, x) for two elements x and y, their relative order is maintained.
// //
// SortSlices can be used in conjuction with EquateEmpty. // SortSlices can be used in conjunction with EquateEmpty.
func SortSlices(less interface{}) cmp.Option { func SortSlices(less interface{}) cmp.Option {
vf := reflect.ValueOf(less) vf := reflect.ValueOf(less)
if !function.IsType(vf.Type(), function.Less) || vf.IsNil() { if !function.IsType(vf.Type(), function.Less) || vf.IsNil() {
@ -95,7 +95,7 @@ func (ss sliceSorter) less(v reflect.Value, i, j int) bool {
// • Transitive: if !less(x, y) and !less(y, z), then !less(x, z) // • Transitive: if !less(x, y) and !less(y, z), then !less(x, z)
// • Total: if x != y, then either less(x, y) or less(y, x) // • Total: if x != y, then either less(x, y) or less(y, x)
// //
// SortMaps can be used in conjuction with EquateEmpty. // SortMaps can be used in conjunction with EquateEmpty.
func SortMaps(less interface{}) cmp.Option { func SortMaps(less interface{}) cmp.Option {
vf := reflect.ValueOf(less) vf := reflect.ValueOf(less)
if !function.IsType(vf.Type(), function.Less) || vf.IsNil() { if !function.IsType(vf.Type(), function.Less) || vf.IsNil() {

View File

@ -22,7 +22,7 @@
// equality is determined by recursively comparing the primitive kinds on both // equality is determined by recursively comparing the primitive kinds on both
// values, much like reflect.DeepEqual. Unlike reflect.DeepEqual, unexported // values, much like reflect.DeepEqual. Unlike reflect.DeepEqual, unexported
// fields are not compared by default; they result in panics unless suppressed // fields are not compared by default; they result in panics unless suppressed
// by using an Ignore option (see cmpopts.IgnoreUnexported) or explictly compared // by using an Ignore option (see cmpopts.IgnoreUnexported) or explicitly compared
// using the AllowUnexported option. // using the AllowUnexported option.
package cmp package cmp
@ -35,7 +35,7 @@ import (
"github.com/google/go-cmp/cmp/internal/value" "github.com/google/go-cmp/cmp/internal/value"
) )
// BUG: Maps with keys containing NaN values cannot be properly compared due to // BUG(dsnet): Maps with keys containing NaN values cannot be properly compared due to
// the reflection package's inability to retrieve such entries. Equal will panic // the reflection package's inability to retrieve such entries. Equal will panic
// anytime it comes across a NaN key, but this behavior may change. // anytime it comes across a NaN key, but this behavior may change.
// //
@ -61,8 +61,8 @@ var nothing = reflect.Value{}
// //
// • If the values have an Equal method of the form "(T) Equal(T) bool" or // • If the values have an Equal method of the form "(T) Equal(T) bool" or
// "(T) Equal(I) bool" where T is assignable to I, then use the result of // "(T) Equal(I) bool" where T is assignable to I, then use the result of
// x.Equal(y). Otherwise, no such method exists and evaluation proceeds to // x.Equal(y) even if x or y is nil.
// the next rule. // Otherwise, no such method exists and evaluation proceeds to the next rule.
// //
// • Lastly, try to compare x and y based on their basic kinds. // • Lastly, try to compare x and y based on their basic kinds.
// Simple kinds like booleans, integers, floats, complex numbers, strings, and // Simple kinds like booleans, integers, floats, complex numbers, strings, and
@ -304,7 +304,8 @@ func (s *state) tryOptions(vx, vy reflect.Value, t reflect.Type) bool {
// Evaluate all filters and apply the remaining options. // Evaluate all filters and apply the remaining options.
if opt := opts.filter(s, vx, vy, t); opt != nil { if opt := opts.filter(s, vx, vy, t); opt != nil {
return opt.apply(s, vx, vy) opt.apply(s, vx, vy)
return true
} }
return false return false
} }
@ -322,6 +323,7 @@ func (s *state) tryMethod(vx, vy reflect.Value, t reflect.Type) bool {
} }
func (s *state) callTRFunc(f, v reflect.Value) reflect.Value { func (s *state) callTRFunc(f, v reflect.Value) reflect.Value {
v = sanitizeValue(v, f.Type().In(0))
if !s.dynChecker.Next() { if !s.dynChecker.Next() {
return f.Call([]reflect.Value{v})[0] return f.Call([]reflect.Value{v})[0]
} }
@ -345,6 +347,8 @@ func (s *state) callTRFunc(f, v reflect.Value) reflect.Value {
} }
func (s *state) callTTBFunc(f, x, y reflect.Value) bool { func (s *state) callTTBFunc(f, x, y reflect.Value) bool {
x = sanitizeValue(x, f.Type().In(0))
y = sanitizeValue(y, f.Type().In(1))
if !s.dynChecker.Next() { if !s.dynChecker.Next() {
return f.Call([]reflect.Value{x, y})[0].Bool() return f.Call([]reflect.Value{x, y})[0].Bool()
} }
@ -372,20 +376,40 @@ func detectRaces(c chan<- reflect.Value, f reflect.Value, vs ...reflect.Value) {
ret = f.Call(vs)[0] ret = f.Call(vs)[0]
} }
// sanitizeValue converts nil interfaces of type T to those of type R,
// assuming that T is assignable to R.
// Otherwise, it returns the input value as is.
func sanitizeValue(v reflect.Value, t reflect.Type) reflect.Value {
// TODO(dsnet): Remove this hacky workaround.
// See https://golang.org/issue/22143
if v.Kind() == reflect.Interface && v.IsNil() && v.Type() != t {
return reflect.New(t).Elem()
}
return v
}
func (s *state) compareArray(vx, vy reflect.Value, t reflect.Type) { func (s *state) compareArray(vx, vy reflect.Value, t reflect.Type) {
step := &sliceIndex{pathStep{t.Elem()}, 0, 0} step := &sliceIndex{pathStep{t.Elem()}, 0, 0}
s.curPath.push(step) s.curPath.push(step)
// Compute an edit-script for slices vx and vy. // Compute an edit-script for slices vx and vy.
eq, es := diff.Difference(vx.Len(), vy.Len(), func(ix, iy int) diff.Result { es := diff.Difference(vx.Len(), vy.Len(), func(ix, iy int) diff.Result {
step.xkey, step.ykey = ix, iy step.xkey, step.ykey = ix, iy
return s.statelessCompare(vx.Index(ix), vy.Index(iy)) return s.statelessCompare(vx.Index(ix), vy.Index(iy))
}) })
// Equal or no edit-script, so report entire slices as is. // Report the entire slice as is if the arrays are of primitive kind,
if eq || es == nil { // and the arrays are different enough.
isPrimitive := false
switch t.Elem().Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
reflect.Bool, reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128:
isPrimitive = true
}
if isPrimitive && es.Dist() > (vx.Len()+vy.Len())/4 {
s.curPath.pop() // Pop first since we are reporting the whole slice s.curPath.pop() // Pop first since we are reporting the whole slice
s.report(eq, vx, vy) s.report(false, vx, vy)
return return
} }

View File

@ -50,7 +50,7 @@ import (
// //
// The series of '.', 'X', 'Y', and 'M' characters at the bottom represents // The series of '.', 'X', 'Y', and 'M' characters at the bottom represents
// the currently established path from the forward and reverse searches, // the currently established path from the forward and reverse searches,
// seperated by a '|' character. // separated by a '|' character.
const ( const (
updateDelay = 100 * time.Millisecond updateDelay = 100 * time.Millisecond

View File

@ -106,9 +106,9 @@ func (r Result) Similar() bool {
// Difference reports whether two lists of lengths nx and ny are equal // Difference reports whether two lists of lengths nx and ny are equal
// given the definition of equality provided as f. // given the definition of equality provided as f.
// //
// This function may return a edit-script, which is a sequence of operations // This function returns an edit-script, which is a sequence of operations
// needed to convert one list into the other. If non-nil, the following // needed to convert one list into the other. The following invariants for
// invariants for the edit-script are maintained: // the edit-script are maintained:
// • eq == (es.Dist()==0) // • eq == (es.Dist()==0)
// • nx == es.LenX() // • nx == es.LenX()
// • ny == es.LenY() // • ny == es.LenY()
@ -117,17 +117,7 @@ func (r Result) Similar() bool {
// produces an edit-script with a minimal Levenshtein distance). This algorithm // produces an edit-script with a minimal Levenshtein distance). This algorithm
// favors performance over optimality. The exact output is not guaranteed to // favors performance over optimality. The exact output is not guaranteed to
// be stable and may change over time. // be stable and may change over time.
func Difference(nx, ny int, f EqualFunc) (eq bool, es EditScript) { func Difference(nx, ny int, f EqualFunc) (es EditScript) {
es = searchGraph(nx, ny, f)
st := es.stats()
eq = len(es) == st.NI
if !eq && st.NI < (nx+ny)/4 {
return eq, nil // Edit-script more distracting than helpful
}
return eq, es
}
func searchGraph(nx, ny int, f EqualFunc) EditScript {
// This algorithm is based on traversing what is known as an "edit-graph". // This algorithm is based on traversing what is known as an "edit-graph".
// See Figure 1 from "An O(ND) Difference Algorithm and Its Variations" // See Figure 1 from "An O(ND) Difference Algorithm and Its Variations"
// by Eugene W. Myers. Since D can be as large as N itself, this is // by Eugene W. Myers. Since D can be as large as N itself, this is

View File

@ -8,15 +8,11 @@ package value
import ( import (
"fmt" "fmt"
"reflect" "reflect"
"strconv"
"strings" "strings"
"unicode" "unicode"
"unicode/utf8"
) )
// formatFakePointers controls whether to substitute pointer addresses with nil.
// This is used for deterministic testing.
var formatFakePointers = false
var stringerIface = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() var stringerIface = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
// Format formats the value v as a string. // Format formats the value v as a string.
@ -26,28 +22,35 @@ var stringerIface = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
// * Avoids printing struct fields that are zero // * Avoids printing struct fields that are zero
// * Prints a nil-slice as being nil, not empty // * Prints a nil-slice as being nil, not empty
// * Prints map entries in deterministic order // * Prints map entries in deterministic order
func Format(v reflect.Value, useStringer bool) string { func Format(v reflect.Value, conf FormatConfig) string {
return formatAny(v, formatConfig{useStringer, true, true, !formatFakePointers}, nil) conf.printType = true
conf.followPointers = true
conf.realPointers = true
return formatAny(v, conf, nil)
} }
type formatConfig struct { type FormatConfig struct {
useStringer bool // Should the String method be used if available? UseStringer bool // Should the String method be used if available?
printType bool // Should we print the type before the value? printType bool // Should we print the type before the value?
followPointers bool // Should we recursively follow pointers? PrintPrimitiveType bool // Should we print the type of primitives?
realPointers bool // Should we print the real address of pointers? followPointers bool // Should we recursively follow pointers?
realPointers bool // Should we print the real address of pointers?
} }
func formatAny(v reflect.Value, conf formatConfig, visited map[uintptr]bool) string { func formatAny(v reflect.Value, conf FormatConfig, visited map[uintptr]bool) string {
// TODO: Should this be a multi-line printout in certain situations? // TODO: Should this be a multi-line printout in certain situations?
if !v.IsValid() { if !v.IsValid() {
return "<non-existent>" return "<non-existent>"
} }
if conf.useStringer && v.Type().Implements(stringerIface) && v.CanInterface() { if conf.UseStringer && v.Type().Implements(stringerIface) && v.CanInterface() {
if (v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface) && v.IsNil() { if (v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface) && v.IsNil() {
return "<nil>" return "<nil>"
} }
return fmt.Sprintf("%q", v.Interface().(fmt.Stringer).String())
const stringerPrefix = "s" // Indicates that the String method was used
s := v.Interface().(fmt.Stringer).String()
return stringerPrefix + formatString(s)
} }
switch v.Kind() { switch v.Kind() {
@ -66,7 +69,7 @@ func formatAny(v reflect.Value, conf formatConfig, visited map[uintptr]bool) str
case reflect.Complex64, reflect.Complex128: case reflect.Complex64, reflect.Complex128:
return formatPrimitive(v.Type(), v.Complex(), conf) return formatPrimitive(v.Type(), v.Complex(), conf)
case reflect.String: case reflect.String:
return formatPrimitive(v.Type(), fmt.Sprintf("%q", v), conf) return formatPrimitive(v.Type(), formatString(v.String()), conf)
case reflect.UnsafePointer, reflect.Chan, reflect.Func: case reflect.UnsafePointer, reflect.Chan, reflect.Func:
return formatPointer(v, conf) return formatPointer(v, conf)
case reflect.Ptr: case reflect.Ptr:
@ -127,11 +130,13 @@ func formatAny(v reflect.Value, conf formatConfig, visited map[uintptr]bool) str
visited = insertPointer(visited, v.Pointer()) visited = insertPointer(visited, v.Pointer())
var ss []string var ss []string
subConf := conf keyConf, valConf := conf, conf
subConf.printType = v.Type().Elem().Kind() == reflect.Interface keyConf.printType = v.Type().Key().Kind() == reflect.Interface
keyConf.followPointers = false
valConf.printType = v.Type().Elem().Kind() == reflect.Interface
for _, k := range SortKeys(v.MapKeys()) { for _, k := range SortKeys(v.MapKeys()) {
sk := formatAny(k, formatConfig{realPointers: conf.realPointers}, visited) sk := formatAny(k, keyConf, visited)
sv := formatAny(v.MapIndex(k), subConf, visited) sv := formatAny(v.MapIndex(k), valConf, visited)
ss = append(ss, fmt.Sprintf("%s: %s", sk, sv)) ss = append(ss, fmt.Sprintf("%s: %s", sk, sv))
} }
s := fmt.Sprintf("{%s}", strings.Join(ss, ", ")) s := fmt.Sprintf("{%s}", strings.Join(ss, ", "))
@ -149,7 +154,7 @@ func formatAny(v reflect.Value, conf formatConfig, visited map[uintptr]bool) str
continue // Elide zero value fields continue // Elide zero value fields
} }
name := v.Type().Field(i).Name name := v.Type().Field(i).Name
subConf.useStringer = conf.useStringer && isExported(name) subConf.UseStringer = conf.UseStringer
s := formatAny(vv, subConf, visited) s := formatAny(vv, subConf, visited)
ss = append(ss, fmt.Sprintf("%s: %s", name, s)) ss = append(ss, fmt.Sprintf("%s: %s", name, s))
} }
@ -163,14 +168,33 @@ func formatAny(v reflect.Value, conf formatConfig, visited map[uintptr]bool) str
} }
} }
func formatPrimitive(t reflect.Type, v interface{}, conf formatConfig) string { func formatString(s string) string {
if conf.printType && t.PkgPath() != "" { // Use quoted string if it the same length as a raw string literal.
// Otherwise, attempt to use the raw string form.
qs := strconv.Quote(s)
if len(qs) == 1+len(s)+1 {
return qs
}
// Disallow newlines to ensure output is a single line.
// Only allow printable runes for readability purposes.
rawInvalid := func(r rune) bool {
return r == '`' || r == '\n' || !unicode.IsPrint(r)
}
if strings.IndexFunc(s, rawInvalid) < 0 {
return "`" + s + "`"
}
return qs
}
func formatPrimitive(t reflect.Type, v interface{}, conf FormatConfig) string {
if conf.printType && (conf.PrintPrimitiveType || t.PkgPath() != "") {
return fmt.Sprintf("%v(%v)", t, v) return fmt.Sprintf("%v(%v)", t, v)
} }
return fmt.Sprintf("%v", v) return fmt.Sprintf("%v", v)
} }
func formatPointer(v reflect.Value, conf formatConfig) string { func formatPointer(v reflect.Value, conf FormatConfig) string {
p := v.Pointer() p := v.Pointer()
if !conf.realPointers { if !conf.realPointers {
p = 0 // For deterministic printing purposes p = 0 // For deterministic printing purposes
@ -251,9 +275,3 @@ func isZero(v reflect.Value) bool {
} }
return false return false
} }
// isExported reports whether the identifier is exported.
func isExported(id string) bool {
r, _ := utf8.DecodeRuneInString(id)
return unicode.IsUpper(r)
}

View File

@ -24,7 +24,7 @@ func SortKeys(vs []reflect.Value) []reflect.Value {
// Deduplicate keys (fails for NaNs). // Deduplicate keys (fails for NaNs).
vs2 := vs[:1] vs2 := vs[:1]
for _, v := range vs[1:] { for _, v := range vs[1:] {
if v.Interface() != vs2[len(vs2)-1].Interface() { if isLess(vs2[len(vs2)-1], v) {
vs2 = append(vs2, v) vs2 = append(vs2, v)
} }
} }

View File

@ -38,9 +38,8 @@ type Option interface {
type applicableOption interface { type applicableOption interface {
Option Option
// apply executes the option and reports whether the option was applied. // apply executes the option, which may mutate s or panic.
// Each option may mutate s. apply(s *state, vx, vy reflect.Value)
apply(s *state, vx, vy reflect.Value) bool
} }
// coreOption represents the following types: // coreOption represents the following types:
@ -85,7 +84,7 @@ func (opts Options) filter(s *state, vx, vy reflect.Value, t reflect.Type) (out
return out return out
} }
func (opts Options) apply(s *state, _, _ reflect.Value) bool { func (opts Options) apply(s *state, _, _ reflect.Value) {
const warning = "ambiguous set of applicable options" const warning = "ambiguous set of applicable options"
const help = "consider using filters to ensure at most one Comparer or Transformer may apply" const help = "consider using filters to ensure at most one Comparer or Transformer may apply"
var ss []string var ss []string
@ -196,7 +195,7 @@ type ignore struct{ core }
func (ignore) isFiltered() bool { return false } func (ignore) isFiltered() bool { return false }
func (ignore) filter(_ *state, _, _ reflect.Value, _ reflect.Type) applicableOption { return ignore{} } func (ignore) filter(_ *state, _, _ reflect.Value, _ reflect.Type) applicableOption { return ignore{} }
func (ignore) apply(_ *state, _, _ reflect.Value) bool { return true } func (ignore) apply(_ *state, _, _ reflect.Value) { return }
func (ignore) String() string { return "Ignore()" } func (ignore) String() string { return "Ignore()" }
// invalid is a sentinel Option type to indicate that some options could not // invalid is a sentinel Option type to indicate that some options could not
@ -204,7 +203,7 @@ func (ignore) String() string
type invalid struct{ core } type invalid struct{ core }
func (invalid) filter(_ *state, _, _ reflect.Value, _ reflect.Type) applicableOption { return invalid{} } func (invalid) filter(_ *state, _, _ reflect.Value, _ reflect.Type) applicableOption { return invalid{} }
func (invalid) apply(s *state, _, _ reflect.Value) bool { func (invalid) apply(s *state, _, _ reflect.Value) {
const help = "consider using AllowUnexported or cmpopts.IgnoreUnexported" const help = "consider using AllowUnexported or cmpopts.IgnoreUnexported"
panic(fmt.Sprintf("cannot handle unexported field: %#v\n%s", s.curPath, help)) panic(fmt.Sprintf("cannot handle unexported field: %#v\n%s", s.curPath, help))
} }
@ -215,9 +214,12 @@ func (invalid) apply(s *state, _, _ reflect.Value) bool {
// The transformer f must be a function "func(T) R" that converts values of // The transformer f must be a function "func(T) R" that converts values of
// type T to those of type R and is implicitly filtered to input values // type T to those of type R and is implicitly filtered to input values
// assignable to T. The transformer must not mutate T in any way. // assignable to T. The transformer must not mutate T in any way.
// If T and R are the same type, an additional filter must be applied to //
// act as the base case to prevent an infinite recursion applying the same // To help prevent some cases of infinite recursive cycles applying the
// transform to itself (see the SortedSlice example). // same transform to the output of itself (e.g., in the case where the
// input and output types are the same), an implicit filter is added such that
// a transformer is applicable only if that exact transformer is not already
// in the tail of the Path since the last non-Transform step.
// //
// The name is a user provided label that is used as the Transform.Name in the // The name is a user provided label that is used as the Transform.Name in the
// transformation PathStep. If empty, an arbitrary name is used. // transformation PathStep. If empty, an arbitrary name is used.
@ -248,14 +250,21 @@ type transformer struct {
func (tr *transformer) isFiltered() bool { return tr.typ != nil } func (tr *transformer) isFiltered() bool { return tr.typ != nil }
func (tr *transformer) filter(_ *state, _, _ reflect.Value, t reflect.Type) applicableOption { func (tr *transformer) filter(s *state, _, _ reflect.Value, t reflect.Type) applicableOption {
for i := len(s.curPath) - 1; i >= 0; i-- {
if t, ok := s.curPath[i].(*transform); !ok {
break // Hit most recent non-Transform step
} else if tr == t.trans {
return nil // Cannot directly use same Transform
}
}
if tr.typ == nil || t.AssignableTo(tr.typ) { if tr.typ == nil || t.AssignableTo(tr.typ) {
return tr return tr
} }
return nil return nil
} }
func (tr *transformer) apply(s *state, vx, vy reflect.Value) bool { func (tr *transformer) apply(s *state, vx, vy reflect.Value) {
// Update path before calling the Transformer so that dynamic checks // Update path before calling the Transformer so that dynamic checks
// will use the updated path. // will use the updated path.
s.curPath.push(&transform{pathStep{tr.fnc.Type().Out(0)}, tr}) s.curPath.push(&transform{pathStep{tr.fnc.Type().Out(0)}, tr})
@ -264,7 +273,6 @@ func (tr *transformer) apply(s *state, vx, vy reflect.Value) bool {
vx = s.callTRFunc(tr.fnc, vx) vx = s.callTRFunc(tr.fnc, vx)
vy = s.callTRFunc(tr.fnc, vy) vy = s.callTRFunc(tr.fnc, vy)
s.compareAny(vx, vy) s.compareAny(vx, vy)
return true
} }
func (tr transformer) String() string { func (tr transformer) String() string {
@ -310,10 +318,9 @@ func (cm *comparer) filter(_ *state, _, _ reflect.Value, t reflect.Type) applica
return nil return nil
} }
func (cm *comparer) apply(s *state, vx, vy reflect.Value) bool { func (cm *comparer) apply(s *state, vx, vy reflect.Value) {
eq := s.callTTBFunc(cm.fnc, vx, vy) eq := s.callTTBFunc(cm.fnc, vx, vy)
s.report(eq, vx, vy) s.report(eq, vx, vy)
return true
} }
func (cm comparer) String() string { func (cm comparer) String() string {
@ -348,7 +355,7 @@ func (cm comparer) String() string {
// all unexported fields on specified struct types. // all unexported fields on specified struct types.
func AllowUnexported(types ...interface{}) Option { func AllowUnexported(types ...interface{}) Option {
if !supportAllowUnexported { if !supportAllowUnexported {
panic("AllowUnexported is not supported on App Engine Classic or GopherJS") panic("AllowUnexported is not supported on purego builds, Google App Engine Standard, or GopherJS")
} }
m := make(map[reflect.Type]bool) m := make(map[reflect.Type]bool)
for _, typ := range types { for _, typ := range types {

View File

@ -79,6 +79,11 @@ type (
PathStep PathStep
Name() string Name() string
Func() reflect.Value Func() reflect.Value
// Option returns the originally constructed Transformer option.
// The == operator can be used to detect the exact option used.
Option() Option
isTransform() isTransform()
} }
) )
@ -94,10 +99,21 @@ func (pa *Path) pop() {
// Last returns the last PathStep in the Path. // Last returns the last PathStep in the Path.
// If the path is empty, this returns a non-nil PathStep that reports a nil Type. // If the path is empty, this returns a non-nil PathStep that reports a nil Type.
func (pa Path) Last() PathStep { func (pa Path) Last() PathStep {
if len(pa) > 0 { return pa.Index(-1)
return pa[len(pa)-1] }
// Index returns the ith step in the Path and supports negative indexing.
// A negative index starts counting from the tail of the Path such that -1
// refers to the last step, -2 refers to the second-to-last step, and so on.
// If index is invalid, this returns a non-nil PathStep that reports a nil Type.
func (pa Path) Index(i int) PathStep {
if i < 0 {
i = len(pa) + i
} }
return pathStep{} if i < 0 || i >= len(pa) {
return pathStep{}
}
return pa[i]
} }
// String returns the simplified path to a node. // String returns the simplified path to a node.
@ -150,13 +166,12 @@ func (pa Path) GoString() string {
ssPost = append(ssPost, ")") ssPost = append(ssPost, ")")
continue continue
case *typeAssertion: case *typeAssertion:
// Elide type assertions immediately following a transform to // As a special-case, elide type assertions on anonymous types
// prevent overly verbose path printouts. // since they are typically generated dynamically and can be very
// Some transforms return interface{} because of Go's lack of // verbose. For example, some transforms return interface{} because
// generics, but typically take in and return the exact same // of Go's lack of generics, but typically take in and return the
// concrete type. Other times, the transform creates an anonymous // exact same concrete type.
// struct, which will be very verbose to print. if s.Type().PkgPath() == "" {
if _, ok := nextStep.(*transform); ok {
continue continue
} }
} }
@ -250,6 +265,7 @@ func (sf structField) Name() string { return sf.name }
func (sf structField) Index() int { return sf.idx } func (sf structField) Index() int { return sf.idx }
func (tf transform) Name() string { return tf.trans.name } func (tf transform) Name() string { return tf.trans.name }
func (tf transform) Func() reflect.Value { return tf.trans.fnc } func (tf transform) Func() reflect.Value { return tf.trans.fnc }
func (tf transform) Option() Option { return tf.trans }
func (pathStep) isPathStep() {} func (pathStep) isPathStep() {}
func (sliceIndex) isSliceIndex() {} func (sliceIndex) isSliceIndex() {}

View File

@ -30,12 +30,12 @@ func (r *defaultReporter) Report(x, y reflect.Value, eq bool, p Path) {
const maxLines = 256 const maxLines = 256
r.ndiffs++ r.ndiffs++
if r.nbytes < maxBytes && r.nlines < maxLines { if r.nbytes < maxBytes && r.nlines < maxLines {
sx := value.Format(x, true) sx := value.Format(x, value.FormatConfig{UseStringer: true})
sy := value.Format(y, true) sy := value.Format(y, value.FormatConfig{UseStringer: true})
if sx == sy { if sx == sy {
// Stringer is not helpful, so rely on more exact formatting. // Unhelpful output, so use more exact formatting.
sx = value.Format(x, false) sx = value.Format(x, value.FormatConfig{PrintPrimitiveType: true})
sy = value.Format(y, false) sy = value.Format(y, value.FormatConfig{PrintPrimitiveType: true})
} }
s := fmt.Sprintf("%#v:\n\t-: %s\n\t+: %s\n", p, sx, sy) s := fmt.Sprintf("%#v:\n\t-: %s\n\t+: %s\n", p, sx, sy)
r.diffs = append(r.diffs, s) r.diffs = append(r.diffs, s)
@ -49,5 +49,5 @@ func (r *defaultReporter) String() string {
if r.ndiffs == len(r.diffs) { if r.ndiffs == len(r.diffs) {
return s return s
} }
return fmt.Sprintf("%s... %d more differences ...", s, len(r.diffs)-r.ndiffs) return fmt.Sprintf("%s... %d more differences ...", s, r.ndiffs-len(r.diffs))
} }

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file. // license that can be found in the LICENSE.md file.
// +build appengine js // +build purego appengine js
package cmp package cmp

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file. // license that can be found in the LICENSE.md file.
// +build !appengine,!js // +build !purego,!appengine,!js
package cmp package cmp

27
vendor/github.com/google/uuid/LICENSE generated vendored Normal file
View File

@ -0,0 +1,27 @@
Copyright (c) 2009,2014 Google Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
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
OWNER 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.

19
vendor/github.com/google/uuid/README.md generated vendored Normal file
View File

@ -0,0 +1,19 @@
# uuid ![build status](https://travis-ci.org/google/uuid.svg?branch=master)
The uuid package generates and inspects UUIDs based on
[RFC 4122](http://tools.ietf.org/html/rfc4122)
and DCE 1.1: Authentication and Security Services.
This package is based on the github.com/pborman/uuid package (previously named
code.google.com/p/go-uuid). It differs from these earlier packages in that
a UUID is a 16 byte array rather than a byte slice. One loss due to this
change is the ability to represent an invalid UUID (vs a NIL UUID).
###### Install
`go get github.com/google/uuid`
###### Documentation
[![GoDoc](https://godoc.org/github.com/google/uuid?status.svg)](http://godoc.org/github.com/google/uuid)
Full `go doc` style documentation for the package can be viewed online without
installing this package by using the GoDoc site here:
http://godoc.org/github.com/google/uuid

80
vendor/github.com/google/uuid/dce.go generated vendored Normal file
View File

@ -0,0 +1,80 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"encoding/binary"
"fmt"
"os"
)
// A Domain represents a Version 2 domain
type Domain byte
// Domain constants for DCE Security (Version 2) UUIDs.
const (
Person = Domain(0)
Group = Domain(1)
Org = Domain(2)
)
// NewDCESecurity returns a DCE Security (Version 2) UUID.
//
// The domain should be one of Person, Group or Org.
// On a POSIX system the id should be the users UID for the Person
// domain and the users GID for the Group. The meaning of id for
// the domain Org or on non-POSIX systems is site defined.
//
// For a given domain/id pair the same token may be returned for up to
// 7 minutes and 10 seconds.
func NewDCESecurity(domain Domain, id uint32) (UUID, error) {
uuid, err := NewUUID()
if err == nil {
uuid[6] = (uuid[6] & 0x0f) | 0x20 // Version 2
uuid[9] = byte(domain)
binary.BigEndian.PutUint32(uuid[0:], id)
}
return uuid, err
}
// NewDCEPerson returns a DCE Security (Version 2) UUID in the person
// domain with the id returned by os.Getuid.
//
// NewDCESecurity(Person, uint32(os.Getuid()))
func NewDCEPerson() (UUID, error) {
return NewDCESecurity(Person, uint32(os.Getuid()))
}
// NewDCEGroup returns a DCE Security (Version 2) UUID in the group
// domain with the id returned by os.Getgid.
//
// NewDCESecurity(Group, uint32(os.Getgid()))
func NewDCEGroup() (UUID, error) {
return NewDCESecurity(Group, uint32(os.Getgid()))
}
// Domain returns the domain for a Version 2 UUID. Domains are only defined
// for Version 2 UUIDs.
func (uuid UUID) Domain() Domain {
return Domain(uuid[9])
}
// ID returns the id for a Version 2 UUID. IDs are only defined for Version 2
// UUIDs.
func (uuid UUID) ID() uint32 {
return binary.BigEndian.Uint32(uuid[0:4])
}
func (d Domain) String() string {
switch d {
case Person:
return "Person"
case Group:
return "Group"
case Org:
return "Org"
}
return fmt.Sprintf("Domain%d", int(d))
}

12
vendor/github.com/google/uuid/doc.go generated vendored Normal file
View File

@ -0,0 +1,12 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package uuid generates and inspects UUIDs.
//
// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security
// Services.
//
// A UUID is a 16 byte (128 bit) array. UUIDs may be used as keys to
// maps or compared directly.
package uuid

53
vendor/github.com/google/uuid/hash.go generated vendored Normal file
View File

@ -0,0 +1,53 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"crypto/md5"
"crypto/sha1"
"hash"
)
// Well known namespace IDs and UUIDs
var (
NameSpaceDNS = Must(Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8"))
NameSpaceURL = Must(Parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8"))
NameSpaceOID = Must(Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8"))
NameSpaceX500 = Must(Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8"))
Nil UUID // empty UUID, all zeros
)
// NewHash returns a new UUID derived from the hash of space concatenated with
// data generated by h. The hash should be at least 16 byte in length. The
// first 16 bytes of the hash are used to form the UUID. The version of the
// UUID will be the lower 4 bits of version. NewHash is used to implement
// NewMD5 and NewSHA1.
func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID {
h.Reset()
h.Write(space[:])
h.Write(data)
s := h.Sum(nil)
var uuid UUID
copy(uuid[:], s)
uuid[6] = (uuid[6] & 0x0f) | uint8((version&0xf)<<4)
uuid[8] = (uuid[8] & 0x3f) | 0x80 // RFC 4122 variant
return uuid
}
// NewMD5 returns a new MD5 (Version 3) UUID based on the
// supplied name space and data. It is the same as calling:
//
// NewHash(md5.New(), space, data, 3)
func NewMD5(space UUID, data []byte) UUID {
return NewHash(md5.New(), space, data, 3)
}
// NewSHA1 returns a new SHA1 (Version 5) UUID based on the
// supplied name space and data. It is the same as calling:
//
// NewHash(sha1.New(), space, data, 5)
func NewSHA1(space UUID, data []byte) UUID {
return NewHash(sha1.New(), space, data, 5)
}

37
vendor/github.com/google/uuid/marshal.go generated vendored Normal file
View File

@ -0,0 +1,37 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import "fmt"
// MarshalText implements encoding.TextMarshaler.
func (uuid UUID) MarshalText() ([]byte, error) {
var js [36]byte
encodeHex(js[:], uuid)
return js[:], nil
}
// UnmarshalText implements encoding.TextUnmarshaler.
func (uuid *UUID) UnmarshalText(data []byte) error {
id, err := ParseBytes(data)
if err == nil {
*uuid = id
}
return err
}
// MarshalBinary implements encoding.BinaryMarshaler.
func (uuid UUID) MarshalBinary() ([]byte, error) {
return uuid[:], nil
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler.
func (uuid *UUID) UnmarshalBinary(data []byte) error {
if len(data) != 16 {
return fmt.Errorf("invalid UUID (got %d bytes)", len(data))
}
copy(uuid[:], data)
return nil
}

90
vendor/github.com/google/uuid/node.go generated vendored Normal file
View File

@ -0,0 +1,90 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"sync"
)
var (
nodeMu sync.Mutex
ifname string // name of interface being used
nodeID [6]byte // hardware for version 1 UUIDs
zeroID [6]byte // nodeID with only 0's
)
// NodeInterface returns the name of the interface from which the NodeID was
// derived. The interface "user" is returned if the NodeID was set by
// SetNodeID.
func NodeInterface() string {
defer nodeMu.Unlock()
nodeMu.Lock()
return ifname
}
// SetNodeInterface selects the hardware address to be used for Version 1 UUIDs.
// If name is "" then the first usable interface found will be used or a random
// Node ID will be generated. If a named interface cannot be found then false
// is returned.
//
// SetNodeInterface never fails when name is "".
func SetNodeInterface(name string) bool {
defer nodeMu.Unlock()
nodeMu.Lock()
return setNodeInterface(name)
}
func setNodeInterface(name string) bool {
iname, addr := getHardwareInterface(name) // null implementation for js
if iname != "" && addr != nil {
ifname = iname
copy(nodeID[:], addr)
return true
}
// We found no interfaces with a valid hardware address. If name
// does not specify a specific interface generate a random Node ID
// (section 4.1.6)
if name == "" {
ifname = "random"
randomBits(nodeID[:])
return true
}
return false
}
// NodeID returns a slice of a copy of the current Node ID, setting the Node ID
// if not already set.
func NodeID() []byte {
defer nodeMu.Unlock()
nodeMu.Lock()
if nodeID == zeroID {
setNodeInterface("")
}
nid := nodeID
return nid[:]
}
// SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes
// of id are used. If id is less than 6 bytes then false is returned and the
// Node ID is not set.
func SetNodeID(id []byte) bool {
if len(id) < 6 {
return false
}
defer nodeMu.Unlock()
nodeMu.Lock()
copy(nodeID[:], id)
ifname = "user"
return true
}
// NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is
// not valid. The NodeID is only well defined for version 1 and 2 UUIDs.
func (uuid UUID) NodeID() []byte {
var node [6]byte
copy(node[:], uuid[10:])
return node[:]
}

View File

@ -26,10 +26,7 @@ func getHardwareInterface(name string) (string, []byte) {
} }
for _, ifs := range interfaces { for _, ifs := range interfaces {
if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) { if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) {
if setNodeID(ifs.HardwareAddr) { return ifs.Name, ifs.HardwareAddr
ifname = ifs.Name
return ifname, nodeID
}
} }
} }
return "", nil return "", nil

59
vendor/github.com/google/uuid/sql.go generated vendored Normal file
View File

@ -0,0 +1,59 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"database/sql/driver"
"fmt"
)
// Scan implements sql.Scanner so UUIDs can be read from databases transparently
// Currently, database types that map to string and []byte are supported. Please
// consult database-specific driver documentation for matching types.
func (uuid *UUID) Scan(src interface{}) error {
switch src := src.(type) {
case nil:
return nil
case string:
// if an empty UUID comes from a table, we return a null UUID
if src == "" {
return nil
}
// see Parse for required string format
u, err := Parse(src)
if err != nil {
return fmt.Errorf("Scan: %v", err)
}
*uuid = u
case []byte:
// if an empty UUID comes from a table, we return a null UUID
if len(src) == 0 {
return nil
}
// assumes a simple slice of bytes if 16 bytes
// otherwise attempts to parse
if len(src) != 16 {
return uuid.Scan(string(src))
}
copy((*uuid)[:], src)
default:
return fmt.Errorf("Scan: unable to scan type %T into UUID", src)
}
return nil
}
// Value implements sql.Valuer so that UUIDs can be written to databases
// transparently. Currently, UUIDs map to strings. Please consult
// database-specific driver documentation for matching types.
func (uuid UUID) Value() (driver.Value, error) {
return uuid.String(), nil
}

123
vendor/github.com/google/uuid/time.go generated vendored Normal file
View File

@ -0,0 +1,123 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"encoding/binary"
"sync"
"time"
)
// A Time represents a time as the number of 100's of nanoseconds since 15 Oct
// 1582.
type Time int64
const (
lillian = 2299160 // Julian day of 15 Oct 1582
unix = 2440587 // Julian day of 1 Jan 1970
epoch = unix - lillian // Days between epochs
g1582 = epoch * 86400 // seconds between epochs
g1582ns100 = g1582 * 10000000 // 100s of a nanoseconds between epochs
)
var (
timeMu sync.Mutex
lasttime uint64 // last time we returned
clockSeq uint16 // clock sequence for this run
timeNow = time.Now // for testing
)
// UnixTime converts t the number of seconds and nanoseconds using the Unix
// epoch of 1 Jan 1970.
func (t Time) UnixTime() (sec, nsec int64) {
sec = int64(t - g1582ns100)
nsec = (sec % 10000000) * 100
sec /= 10000000
return sec, nsec
}
// GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and
// clock sequence as well as adjusting the clock sequence as needed. An error
// is returned if the current time cannot be determined.
func GetTime() (Time, uint16, error) {
defer timeMu.Unlock()
timeMu.Lock()
return getTime()
}
func getTime() (Time, uint16, error) {
t := timeNow()
// If we don't have a clock sequence already, set one.
if clockSeq == 0 {
setClockSequence(-1)
}
now := uint64(t.UnixNano()/100) + g1582ns100
// If time has gone backwards with this clock sequence then we
// increment the clock sequence
if now <= lasttime {
clockSeq = ((clockSeq + 1) & 0x3fff) | 0x8000
}
lasttime = now
return Time(now), clockSeq, nil
}
// ClockSequence returns the current clock sequence, generating one if not
// already set. The clock sequence is only used for Version 1 UUIDs.
//
// The uuid package does not use global static storage for the clock sequence or
// the last time a UUID was generated. Unless SetClockSequence is used, a new
// random clock sequence is generated the first time a clock sequence is
// requested by ClockSequence, GetTime, or NewUUID. (section 4.2.1.1)
func ClockSequence() int {
defer timeMu.Unlock()
timeMu.Lock()
return clockSequence()
}
func clockSequence() int {
if clockSeq == 0 {
setClockSequence(-1)
}
return int(clockSeq & 0x3fff)
}
// SetClockSequence sets the clock sequence to the lower 14 bits of seq. Setting to
// -1 causes a new sequence to be generated.
func SetClockSequence(seq int) {
defer timeMu.Unlock()
timeMu.Lock()
setClockSequence(seq)
}
func setClockSequence(seq int) {
if seq == -1 {
var b [2]byte
randomBits(b[:]) // clock sequence
seq = int(b[0])<<8 | int(b[1])
}
oldSeq := clockSeq
clockSeq = uint16(seq&0x3fff) | 0x8000 // Set our variant
if oldSeq != clockSeq {
lasttime = 0
}
}
// Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in
// uuid. The time is only defined for version 1 and 2 UUIDs.
func (uuid UUID) Time() Time {
time := int64(binary.BigEndian.Uint32(uuid[0:4]))
time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32
time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48
return Time(time)
}
// ClockSequence returns the clock sequence encoded in uuid.
// The clock sequence is only well defined for version 1 and 2 UUIDs.
func (uuid UUID) ClockSequence() int {
return int(binary.BigEndian.Uint16(uuid[8:10])) & 0x3fff
}

43
vendor/github.com/google/uuid/util.go generated vendored Normal file
View File

@ -0,0 +1,43 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"io"
)
// randomBits completely fills slice b with random data.
func randomBits(b []byte) {
if _, err := io.ReadFull(rander, b); err != nil {
panic(err.Error()) // rand should never fail
}
}
// xvalues returns the value of a byte as a hexadecimal digit or 255.
var xvalues = [256]byte{
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255,
255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
}
// xtob converts hex characters x1 and x2 into a byte.
func xtob(x1, x2 byte) (byte, bool) {
b1 := xvalues[x1]
b2 := xvalues[x2]
return (b1 << 4) | b2, b1 != 255 && b2 != 255
}

245
vendor/github.com/google/uuid/uuid.go generated vendored Normal file
View File

@ -0,0 +1,245 @@
// Copyright 2018 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"bytes"
"crypto/rand"
"encoding/hex"
"errors"
"fmt"
"io"
"strings"
)
// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC
// 4122.
type UUID [16]byte
// A Version represents a UUID's version.
type Version byte
// A Variant represents a UUID's variant.
type Variant byte
// Constants returned by Variant.
const (
Invalid = Variant(iota) // Invalid UUID
RFC4122 // The variant specified in RFC4122
Reserved // Reserved, NCS backward compatibility.
Microsoft // Reserved, Microsoft Corporation backward compatibility.
Future // Reserved for future definition.
)
var rander = rand.Reader // random function
// Parse decodes s into a UUID or returns an error. Both the standard UUID
// forms of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded as well as the
// Microsoft encoding {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} and the raw hex
// encoding: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
func Parse(s string) (UUID, error) {
var uuid UUID
switch len(s) {
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
case 36:
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
case 36 + 9:
if strings.ToLower(s[:9]) != "urn:uuid:" {
return uuid, fmt.Errorf("invalid urn prefix: %q", s[:9])
}
s = s[9:]
// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
case 36 + 2:
s = s[1:]
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
case 32:
var ok bool
for i := range uuid {
uuid[i], ok = xtob(s[i*2], s[i*2+1])
if !ok {
return uuid, errors.New("invalid UUID format")
}
}
return uuid, nil
default:
return uuid, fmt.Errorf("invalid UUID length: %d", len(s))
}
// s is now at least 36 bytes long
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
return uuid, errors.New("invalid UUID format")
}
for i, x := range [16]int{
0, 2, 4, 6,
9, 11,
14, 16,
19, 21,
24, 26, 28, 30, 32, 34} {
v, ok := xtob(s[x], s[x+1])
if !ok {
return uuid, errors.New("invalid UUID format")
}
uuid[i] = v
}
return uuid, nil
}
// ParseBytes is like Parse, except it parses a byte slice instead of a string.
func ParseBytes(b []byte) (UUID, error) {
var uuid UUID
switch len(b) {
case 36: // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
case 36 + 9: // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
if !bytes.Equal(bytes.ToLower(b[:9]), []byte("urn:uuid:")) {
return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9])
}
b = b[9:]
case 36 + 2: // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
b = b[1:]
case 32: // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
var ok bool
for i := 0; i < 32; i += 2 {
uuid[i/2], ok = xtob(b[i], b[i+1])
if !ok {
return uuid, errors.New("invalid UUID format")
}
}
return uuid, nil
default:
return uuid, fmt.Errorf("invalid UUID length: %d", len(b))
}
// s is now at least 36 bytes long
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
if b[8] != '-' || b[13] != '-' || b[18] != '-' || b[23] != '-' {
return uuid, errors.New("invalid UUID format")
}
for i, x := range [16]int{
0, 2, 4, 6,
9, 11,
14, 16,
19, 21,
24, 26, 28, 30, 32, 34} {
v, ok := xtob(b[x], b[x+1])
if !ok {
return uuid, errors.New("invalid UUID format")
}
uuid[i] = v
}
return uuid, nil
}
// MustParse is like Parse but panics if the string cannot be parsed.
// It simplifies safe initialization of global variables holding compiled UUIDs.
func MustParse(s string) UUID {
uuid, err := Parse(s)
if err != nil {
panic(`uuid: Parse(` + s + `): ` + err.Error())
}
return uuid
}
// FromBytes creates a new UUID from a byte slice. Returns an error if the slice
// does not have a length of 16. The bytes are copied from the slice.
func FromBytes(b []byte) (uuid UUID, err error) {
err = uuid.UnmarshalBinary(b)
return uuid, err
}
// Must returns uuid if err is nil and panics otherwise.
func Must(uuid UUID, err error) UUID {
if err != nil {
panic(err)
}
return uuid
}
// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
// , or "" if uuid is invalid.
func (uuid UUID) String() string {
var buf [36]byte
encodeHex(buf[:], uuid)
return string(buf[:])
}
// URN returns the RFC 2141 URN form of uuid,
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, or "" if uuid is invalid.
func (uuid UUID) URN() string {
var buf [36 + 9]byte
copy(buf[:], "urn:uuid:")
encodeHex(buf[9:], uuid)
return string(buf[:])
}
func encodeHex(dst []byte, uuid UUID) {
hex.Encode(dst, uuid[:4])
dst[8] = '-'
hex.Encode(dst[9:13], uuid[4:6])
dst[13] = '-'
hex.Encode(dst[14:18], uuid[6:8])
dst[18] = '-'
hex.Encode(dst[19:23], uuid[8:10])
dst[23] = '-'
hex.Encode(dst[24:], uuid[10:])
}
// Variant returns the variant encoded in uuid.
func (uuid UUID) Variant() Variant {
switch {
case (uuid[8] & 0xc0) == 0x80:
return RFC4122
case (uuid[8] & 0xe0) == 0xc0:
return Microsoft
case (uuid[8] & 0xe0) == 0xe0:
return Future
default:
return Reserved
}
}
// Version returns the version of uuid.
func (uuid UUID) Version() Version {
return Version(uuid[6] >> 4)
}
func (v Version) String() string {
if v > 15 {
return fmt.Sprintf("BAD_VERSION_%d", v)
}
return fmt.Sprintf("VERSION_%d", v)
}
func (v Variant) String() string {
switch v {
case RFC4122:
return "RFC4122"
case Reserved:
return "Reserved"
case Microsoft:
return "Microsoft"
case Future:
return "Future"
case Invalid:
return "Invalid"
}
return fmt.Sprintf("BadVariant%d", int(v))
}
// SetRand sets the random number generator to r, which implements io.Reader.
// If r.Read returns an error when the package requests random data then
// a panic will be issued.
//
// Calling SetRand with nil sets the random number generator to the default
// generator.
func SetRand(r io.Reader) {
if r == nil {
rander = rand.Reader
return
}
rander = r
}

44
vendor/github.com/google/uuid/version1.go generated vendored Normal file
View File

@ -0,0 +1,44 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"encoding/binary"
)
// NewUUID returns a Version 1 UUID based on the current NodeID and clock
// sequence, and the current time. If the NodeID has not been set by SetNodeID
// or SetNodeInterface then it will be set automatically. If the NodeID cannot
// be set NewUUID returns nil. If clock sequence has not been set by
// SetClockSequence then it will be set automatically. If GetTime fails to
// return the current NewUUID returns nil and an error.
//
// In most cases, New should be used.
func NewUUID() (UUID, error) {
nodeMu.Lock()
if nodeID == zeroID {
setNodeInterface("")
}
nodeMu.Unlock()
var uuid UUID
now, seq, err := GetTime()
if err != nil {
return uuid, err
}
timeLow := uint32(now & 0xffffffff)
timeMid := uint16((now >> 32) & 0xffff)
timeHi := uint16((now >> 48) & 0x0fff)
timeHi |= 0x1000 // Version 1
binary.BigEndian.PutUint32(uuid[0:], timeLow)
binary.BigEndian.PutUint16(uuid[4:], timeMid)
binary.BigEndian.PutUint16(uuid[6:], timeHi)
binary.BigEndian.PutUint16(uuid[8:], seq)
copy(uuid[10:], nodeID[:])
return uuid, nil
}

38
vendor/github.com/google/uuid/version4.go generated vendored Normal file
View File

@ -0,0 +1,38 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import "io"
// New creates a new random UUID or panics. New is equivalent to
// the expression
//
// uuid.Must(uuid.NewRandom())
func New() UUID {
return Must(NewRandom())
}
// NewRandom returns a Random (Version 4) UUID.
//
// The strength of the UUIDs is based on the strength of the crypto/rand
// package.
//
// A note about uniqueness derived from the UUID Wikipedia entry:
//
// Randomly generated UUIDs have 122 random bits. One's annual risk of being
// hit by a meteorite is estimated to be one chance in 17 billion, that
// means the probability is about 0.00000000006 (6 × 1011),
// equivalent to the odds of creating a few tens of trillions of UUIDs in a
// year and having one duplicate.
func NewRandom() (UUID, error) {
var uuid UUID
_, err := io.ReadFull(rander, uuid[:])
if err != nil {
return Nil, err
}
uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4
uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10
return uuid, nil
}

View File

@ -48,7 +48,7 @@ func (c *command) Run(arg ...string) ([][]string, error) {
if err != nil { if err != nil {
return nil, &Error{ return nil, &Error{
Err: err, Err: err,
Debug: strings.Join([]string{cmd.Path, joinedArgs}, " "), Debug: strings.Join([]string{cmd.Path, joinedArgs[1:]}, " "),
Stderr: stderr.String(), Stderr: stderr.String(),
} }
} }

View File

@ -3,6 +3,8 @@ This project was automatically exported from code.google.com/p/go-uuid
# uuid ![build status](https://travis-ci.org/pborman/uuid.svg?branch=master) # uuid ![build status](https://travis-ci.org/pborman/uuid.svg?branch=master)
The uuid package generates and inspects UUIDs based on [RFC 4122](http://tools.ietf.org/html/rfc4122) and DCE 1.1: Authentication and Security Services. The uuid package generates and inspects UUIDs based on [RFC 4122](http://tools.ietf.org/html/rfc4122) and DCE 1.1: Authentication and Security Services.
This package now leverages the github.com/google/uuid package (which is based off an earlier version of this package).
###### Install ###### Install
`go get github.com/pborman/uuid` `go get github.com/pborman/uuid`

View File

@ -4,5 +4,10 @@
// The uuid package generates and inspects UUIDs. // The uuid package generates and inspects UUIDs.
// //
// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security Services. // UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security
// Services.
//
// This package is a partial wrapper around the github.com/google/uuid package.
// This package represents a UUID as []byte while github.com/google/uuid
// represents a UUID as [16]byte.
package uuid package uuid

View File

@ -7,6 +7,8 @@ package uuid
import ( import (
"errors" "errors"
"fmt" "fmt"
guuid "github.com/google/uuid"
) )
// MarshalText implements encoding.TextMarshaler. // MarshalText implements encoding.TextMarshaler.
@ -60,11 +62,11 @@ func (u Array) MarshalText() ([]byte, error) {
// UnmarshalText implements encoding.TextUnmarshaler. // UnmarshalText implements encoding.TextUnmarshaler.
func (u *Array) UnmarshalText(data []byte) error { func (u *Array) UnmarshalText(data []byte) error {
id := Parse(string(data)) id, err := guuid.ParseBytes(data)
if id == nil { if err != nil {
return errors.New("invalid UUID") return err
} }
*u = id.Array() *u = Array(id)
return nil return nil
} }

View File

@ -5,22 +5,14 @@
package uuid package uuid
import ( import (
"sync" guuid "github.com/google/uuid"
)
var (
nodeMu sync.Mutex
ifname string // name of interface being used
nodeID []byte // hardware for version 1 UUIDs
) )
// NodeInterface returns the name of the interface from which the NodeID was // NodeInterface returns the name of the interface from which the NodeID was
// derived. The interface "user" is returned if the NodeID was set by // derived. The interface "user" is returned if the NodeID was set by
// SetNodeID. // SetNodeID.
func NodeInterface() string { func NodeInterface() string {
defer nodeMu.Unlock() return guuid.NodeInterface()
nodeMu.Lock()
return ifname
} }
// SetNodeInterface selects the hardware address to be used for Version 1 UUIDs. // SetNodeInterface selects the hardware address to be used for Version 1 UUIDs.
@ -30,70 +22,20 @@ func NodeInterface() string {
// //
// SetNodeInterface never fails when name is "". // SetNodeInterface never fails when name is "".
func SetNodeInterface(name string) bool { func SetNodeInterface(name string) bool {
defer nodeMu.Unlock() return guuid.SetNodeInterface(name)
nodeMu.Lock()
if nodeID != nil {
return true
}
return setNodeInterface(name)
}
func setNodeInterface(name string) bool {
iname, addr := getHardwareInterface(name) // null implementation for js
if iname != "" && setNodeID(addr) {
ifname = iname
return true
}
// We found no interfaces with a valid hardware address. If name
// does not specify a specific interface generate a random Node ID
// (section 4.1.6)
if name == "" {
if nodeID == nil {
nodeID = make([]byte, 6)
}
randomBits(nodeID)
return true
}
return false
} }
// NodeID returns a slice of a copy of the current Node ID, setting the Node ID // NodeID returns a slice of a copy of the current Node ID, setting the Node ID
// if not already set. // if not already set.
func NodeID() []byte { func NodeID() []byte {
defer nodeMu.Unlock() return guuid.NodeID()
nodeMu.Lock()
if nodeID == nil {
setNodeInterface("")
}
nid := make([]byte, 6)
copy(nid, nodeID)
return nid
} }
// SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes // SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes
// of id are used. If id is less than 6 bytes then false is returned and the // of id are used. If id is less than 6 bytes then false is returned and the
// Node ID is not set. // Node ID is not set.
func SetNodeID(id []byte) bool { func SetNodeID(id []byte) bool {
defer nodeMu.Unlock() return guuid.SetNodeID(id)
nodeMu.Lock()
if setNodeID(id) {
ifname = "user"
return true
}
return false
}
func setNodeID(id []byte) bool {
if len(id) < 6 {
return false
}
if nodeID == nil {
nodeID = make([]byte, 6)
}
copy(nodeID, id)
return true
} }
// NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is // NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is

View File

@ -40,7 +40,9 @@ func (uuid *UUID) Scan(src interface{}) error {
// assumes a simple slice of bytes if 16 bytes // assumes a simple slice of bytes if 16 bytes
// otherwise attempts to parse // otherwise attempts to parse
if len(b) == 16 { if len(b) == 16 {
*uuid = UUID(b) parsed := make([]byte, 16)
copy(parsed, b)
*uuid = UUID(parsed)
} else { } else {
u := Parse(string(b)) u := Parse(string(b))

View File

@ -6,65 +6,18 @@ package uuid
import ( import (
"encoding/binary" "encoding/binary"
"sync"
"time" guuid "github.com/google/uuid"
) )
// A Time represents a time as the number of 100's of nanoseconds since 15 Oct // A Time represents a time as the number of 100's of nanoseconds since 15 Oct
// 1582. // 1582.
type Time int64 type Time = guuid.Time
const (
lillian = 2299160 // Julian day of 15 Oct 1582
unix = 2440587 // Julian day of 1 Jan 1970
epoch = unix - lillian // Days between epochs
g1582 = epoch * 86400 // seconds between epochs
g1582ns100 = g1582 * 10000000 // 100s of a nanoseconds between epochs
)
var (
timeMu sync.Mutex
lasttime uint64 // last time we returned
clock_seq uint16 // clock sequence for this run
timeNow = time.Now // for testing
)
// UnixTime converts t the number of seconds and nanoseconds using the Unix
// epoch of 1 Jan 1970.
func (t Time) UnixTime() (sec, nsec int64) {
sec = int64(t - g1582ns100)
nsec = (sec % 10000000) * 100
sec /= 10000000
return sec, nsec
}
// GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and // GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and
// clock sequence as well as adjusting the clock sequence as needed. An error // clock sequence as well as adjusting the clock sequence as needed. An error
// is returned if the current time cannot be determined. // is returned if the current time cannot be determined.
func GetTime() (Time, uint16, error) { func GetTime() (Time, uint16, error) { return guuid.GetTime() }
defer timeMu.Unlock()
timeMu.Lock()
return getTime()
}
func getTime() (Time, uint16, error) {
t := timeNow()
// If we don't have a clock sequence already, set one.
if clock_seq == 0 {
setClockSequence(-1)
}
now := uint64(t.UnixNano()/100) + g1582ns100
// If time has gone backwards with this clock sequence then we
// increment the clock sequence
if now <= lasttime {
clock_seq = ((clock_seq + 1) & 0x3fff) | 0x8000
}
lasttime = now
return Time(now), clock_seq, nil
}
// ClockSequence returns the current clock sequence, generating one if not // ClockSequence returns the current clock sequence, generating one if not
// already set. The clock sequence is only used for Version 1 UUIDs. // already set. The clock sequence is only used for Version 1 UUIDs.
@ -74,39 +27,11 @@ func getTime() (Time, uint16, error) {
// clock sequence is generated the first time a clock sequence is requested by // clock sequence is generated the first time a clock sequence is requested by
// ClockSequence, GetTime, or NewUUID. (section 4.2.1.1) sequence is generated // ClockSequence, GetTime, or NewUUID. (section 4.2.1.1) sequence is generated
// for // for
func ClockSequence() int { func ClockSequence() int { return guuid.ClockSequence() }
defer timeMu.Unlock()
timeMu.Lock()
return clockSequence()
}
func clockSequence() int {
if clock_seq == 0 {
setClockSequence(-1)
}
return int(clock_seq & 0x3fff)
}
// SetClockSeq sets the clock sequence to the lower 14 bits of seq. Setting to // SetClockSeq sets the clock sequence to the lower 14 bits of seq. Setting to
// -1 causes a new sequence to be generated. // -1 causes a new sequence to be generated.
func SetClockSequence(seq int) { func SetClockSequence(seq int) { guuid.SetClockSequence(seq) }
defer timeMu.Unlock()
timeMu.Lock()
setClockSequence(seq)
}
func setClockSequence(seq int) {
if seq == -1 {
var b [2]byte
randomBits(b[:]) // clock sequence
seq = int(b[0])<<8 | int(b[1])
}
old_seq := clock_seq
clock_seq = uint16(seq&0x3fff) | 0x8000 // Set our variant
if old_seq != clock_seq {
lasttime = 0
}
}
// Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in // Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in
// uuid. It returns false if uuid is not valid. The time is only well defined // uuid. It returns false if uuid is not valid. The time is only well defined

View File

@ -4,17 +4,6 @@
package uuid package uuid
import (
"io"
)
// randomBits completely fills slice b with random data.
func randomBits(b []byte) {
if _, err := io.ReadFull(rander, b); err != nil {
panic(err.Error()) // rand should never fail
}
}
// xvalues returns the value of a byte as a hexadecimal digit or 255. // xvalues returns the value of a byte as a hexadecimal digit or 255.
var xvalues = [256]byte{ var xvalues = [256]byte{
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,

View File

@ -8,9 +8,9 @@ import (
"bytes" "bytes"
"crypto/rand" "crypto/rand"
"encoding/hex" "encoding/hex"
"fmt"
"io" "io"
"strings"
guuid "github.com/google/uuid"
) )
// Array is a pass-by-value UUID that can be used as an effecient key in a map. // Array is a pass-by-value UUID that can be used as an effecient key in a map.
@ -24,7 +24,7 @@ func (uuid Array) UUID() UUID {
// String returns the string representation of uuid, // String returns the string representation of uuid,
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
func (uuid Array) String() string { func (uuid Array) String() string {
return uuid.UUID().String() return guuid.UUID(uuid).String()
} }
// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC // A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC
@ -32,18 +32,18 @@ func (uuid Array) String() string {
type UUID []byte type UUID []byte
// A Version represents a UUIDs version. // A Version represents a UUIDs version.
type Version byte type Version = guuid.Version
// A Variant represents a UUIDs variant. // A Variant represents a UUIDs variant.
type Variant byte type Variant = guuid.Variant
// Constants returned by Variant. // Constants returned by Variant.
const ( const (
Invalid = Variant(iota) // Invalid UUID Invalid = guuid.Invalid // Invalid UUID
RFC4122 // The variant specified in RFC4122 RFC4122 = guuid.RFC4122 // The variant specified in RFC4122
Reserved // Reserved, NCS backward compatibility. Reserved = guuid.Reserved // Reserved, NCS backward compatibility.
Microsoft // Reserved, Microsoft Corporation backward compatibility. Microsoft = guuid.Microsoft // Reserved, Microsoft Corporation backward compatibility.
Future // Reserved for future definition. Future = guuid.Future // Reserved for future definition.
) )
var rander = rand.Reader // random function var rander = rand.Reader // random function
@ -54,35 +54,23 @@ func New() string {
return NewRandom().String() return NewRandom().String()
} }
// Parse decodes s into a UUID or returns nil. Both the UUID form of // Parse decodes s into a UUID or returns nil. See github.com/google/uuid for
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and // the formats parsed.
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded.
func Parse(s string) UUID { func Parse(s string) UUID {
if len(s) == 36+9 { gu, err := guuid.Parse(s)
if strings.ToLower(s[:9]) != "urn:uuid:" { if err == nil {
return nil return gu[:]
}
s = s[9:]
} else if len(s) != 36 {
return nil
} }
if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' { return nil
return nil }
// ParseBytes is like Parse, except it parses a byte slice instead of a string.
func ParseBytes(b []byte) (UUID, error) {
gu, err := guuid.ParseBytes(b)
if err == nil {
return gu[:], nil
} }
var uuid [16]byte return nil, err
for i, x := range [16]int{
0, 2, 4, 6,
9, 11,
14, 16,
19, 21,
24, 26, 28, 30, 32, 34} {
if v, ok := xtob(s[x:]); !ok {
return nil
} else {
uuid[i] = v
}
}
return uuid[:]
} }
// Equal returns true if uuid1 and uuid2 are equal. // Equal returns true if uuid1 and uuid2 are equal.
@ -163,29 +151,6 @@ func (uuid UUID) Version() (Version, bool) {
return Version(uuid[6] >> 4), true return Version(uuid[6] >> 4), true
} }
func (v Version) String() string {
if v > 15 {
return fmt.Sprintf("BAD_VERSION_%d", v)
}
return fmt.Sprintf("VERSION_%d", v)
}
func (v Variant) String() string {
switch v {
case RFC4122:
return "RFC4122"
case Reserved:
return "Reserved"
case Microsoft:
return "Microsoft"
case Future:
return "Future"
case Invalid:
return "Invalid"
}
return fmt.Sprintf("BadVariant%d", int(v))
}
// SetRand sets the random number generator to r, which implements io.Reader. // SetRand sets the random number generator to r, which implements io.Reader.
// If r.Read returns an error when the package requests random data then // If r.Read returns an error when the package requests random data then
// a panic will be issued. // a panic will be issued.
@ -193,9 +158,5 @@ func (v Variant) String() string {
// Calling SetRand with nil sets the random number generator to the default // Calling SetRand with nil sets the random number generator to the default
// generator. // generator.
func SetRand(r io.Reader) { func SetRand(r io.Reader) {
if r == nil { guuid.SetRand(r)
rander = rand.Reader
return
}
rander = r
} }

View File

@ -5,7 +5,7 @@
package uuid package uuid
import ( import (
"encoding/binary" guuid "github.com/google/uuid"
) )
// NewUUID returns a Version 1 UUID based on the current NodeID and clock // NewUUID returns a Version 1 UUID based on the current NodeID and clock
@ -15,25 +15,9 @@ import (
// SetClockSequence then it will be set automatically. If GetTime fails to // SetClockSequence then it will be set automatically. If GetTime fails to
// return the current NewUUID returns nil. // return the current NewUUID returns nil.
func NewUUID() UUID { func NewUUID() UUID {
SetNodeInterface("") gu, err := guuid.NewUUID()
if err == nil {
now, seq, err := GetTime() return UUID(gu[:])
if err != nil {
return nil
} }
return nil
uuid := make([]byte, 16)
time_low := uint32(now & 0xffffffff)
time_mid := uint16((now >> 32) & 0xffff)
time_hi := uint16((now >> 48) & 0x0fff)
time_hi |= 0x1000 // Version 1
binary.BigEndian.PutUint32(uuid[0:], time_low)
binary.BigEndian.PutUint16(uuid[4:], time_mid)
binary.BigEndian.PutUint16(uuid[6:], time_hi)
binary.BigEndian.PutUint16(uuid[8:], seq)
copy(uuid[10:], nodeID)
return uuid
} }

View File

@ -4,12 +4,14 @@
package uuid package uuid
import guuid "github.com/google/uuid"
// Random returns a Random (Version 4) UUID or panics. // Random returns a Random (Version 4) UUID or panics.
// //
// The strength of the UUIDs is based on the strength of the crypto/rand // The strength of the UUIDs is based on the strength of the crypto/rand
// package. // package.
// //
// A note about uniqueness derived from from the UUID Wikipedia entry: // A note about uniqueness derived from the UUID Wikipedia entry:
// //
// Randomly generated UUIDs have 122 random bits. One's annual risk of being // Randomly generated UUIDs have 122 random bits. One's annual risk of being
// hit by a meteorite is estimated to be one chance in 17 billion, that // hit by a meteorite is estimated to be one chance in 17 billion, that
@ -17,9 +19,8 @@ package uuid
// equivalent to the odds of creating a few tens of trillions of UUIDs in a // equivalent to the odds of creating a few tens of trillions of UUIDs in a
// year and having one duplicate. // year and having one duplicate.
func NewRandom() UUID { func NewRandom() UUID {
uuid := make([]byte, 16) if gu, err := guuid.NewRandom(); err == nil {
randomBits([]byte(uuid)) return UUID(gu[:])
uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4 }
uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10 return nil
return uuid
} }

View File

@ -1,4 +1,4 @@
# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) # errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) [![Sourcegraph](https://sourcegraph.com/github.com/pkg/errors/-/badge.svg)](https://sourcegraph.com/github.com/pkg/errors?badge)
Package errors provides simple error handling primitives. Package errors provides simple error handling primitives.
@ -47,6 +47,6 @@ We welcome pull requests, bug fixes and issue reports. With that said, the bar f
Before proposing a change, please discuss your change by raising an issue. Before proposing a change, please discuss your change by raising an issue.
## Licence ## License
BSD-2-Clause BSD-2-Clause

View File

@ -6,7 +6,7 @@
// return err // return err
// } // }
// //
// which applied recursively up the call stack results in error reports // which when applied recursively up the call stack results in error reports
// without context or debugging information. The errors package allows // without context or debugging information. The errors package allows
// programmers to add context to the failure path in their code in a way // programmers to add context to the failure path in their code in a way
// that does not destroy the original value of the error. // that does not destroy the original value of the error.
@ -15,16 +15,17 @@
// //
// The errors.Wrap function returns a new error that adds context to the // The errors.Wrap function returns a new error that adds context to the
// original error by recording a stack trace at the point Wrap is called, // original error by recording a stack trace at the point Wrap is called,
// and the supplied message. For example // together with the supplied message. For example
// //
// _, err := ioutil.ReadAll(r) // _, err := ioutil.ReadAll(r)
// if err != nil { // if err != nil {
// return errors.Wrap(err, "read failed") // return errors.Wrap(err, "read failed")
// } // }
// //
// If additional control is required the errors.WithStack and errors.WithMessage // If additional control is required, the errors.WithStack and
// functions destructure errors.Wrap into its component operations of annotating // errors.WithMessage functions destructure errors.Wrap into its component
// an error with a stack trace and an a message, respectively. // operations: annotating an error with a stack trace and with a message,
// respectively.
// //
// Retrieving the cause of an error // Retrieving the cause of an error
// //
@ -38,7 +39,7 @@
// } // }
// //
// can be inspected by errors.Cause. errors.Cause will recursively retrieve // can be inspected by errors.Cause. errors.Cause will recursively retrieve
// the topmost error which does not implement causer, which is assumed to be // the topmost error that does not implement causer, which is assumed to be
// the original cause. For example: // the original cause. For example:
// //
// switch err := errors.Cause(err).(type) { // switch err := errors.Cause(err).(type) {
@ -48,16 +49,16 @@
// // unknown error // // unknown error
// } // }
// //
// causer interface is not exported by this package, but is considered a part // Although the causer interface is not exported by this package, it is
// of stable public API. // considered a part of its stable public interface.
// //
// Formatted printing of errors // Formatted printing of errors
// //
// All error values returned from this package implement fmt.Formatter and can // All error values returned from this package implement fmt.Formatter and can
// be formatted by the fmt package. The following verbs are supported // be formatted by the fmt package. The following verbs are supported:
// //
// %s print the error. If the error has a Cause it will be // %s print the error. If the error has a Cause it will be
// printed recursively // printed recursively.
// %v see %s // %v see %s
// %+v extended format. Each Frame of the error's StackTrace will // %+v extended format. Each Frame of the error's StackTrace will
// be printed in detail. // be printed in detail.
@ -65,13 +66,13 @@
// Retrieving the stack trace of an error or wrapper // Retrieving the stack trace of an error or wrapper
// //
// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are // New, Errorf, Wrap, and Wrapf record a stack trace at the point they are
// invoked. This information can be retrieved with the following interface. // invoked. This information can be retrieved with the following interface:
// //
// type stackTracer interface { // type stackTracer interface {
// StackTrace() errors.StackTrace // StackTrace() errors.StackTrace
// } // }
// //
// Where errors.StackTrace is defined as // The returned errors.StackTrace type is defined as
// //
// type StackTrace []Frame // type StackTrace []Frame
// //
@ -85,8 +86,8 @@
// } // }
// } // }
// //
// stackTracer interface is not exported by this package, but is considered a part // Although the stackTracer interface is not exported by this package, it is
// of stable public API. // considered a part of its stable public interface.
// //
// See the documentation for Frame.Format for more details. // See the documentation for Frame.Format for more details.
package errors package errors
@ -192,7 +193,7 @@ func Wrap(err error, message string) error {
} }
// Wrapf returns an error annotating err with a stack trace // Wrapf returns an error annotating err with a stack trace
// at the point Wrapf is call, and the format specifier. // at the point Wrapf is called, and the format specifier.
// If err is nil, Wrapf returns nil. // If err is nil, Wrapf returns nil.
func Wrapf(err error, format string, args ...interface{}) error { func Wrapf(err error, format string, args ...interface{}) error {
if err == nil { if err == nil {
@ -220,6 +221,18 @@ func WithMessage(err error, message string) error {
} }
} }
// WithMessagef annotates err with the format specifier.
// If err is nil, WithMessagef returns nil.
func WithMessagef(err error, format string, args ...interface{}) error {
if err == nil {
return nil
}
return &withMessage{
cause: err,
msg: fmt.Sprintf(format, args...),
}
}
type withMessage struct { type withMessage struct {
cause error cause error
msg string msg string

View File

@ -46,7 +46,8 @@ func (f Frame) line() int {
// //
// Format accepts flags that alter the printing of some verbs, as follows: // Format accepts flags that alter the printing of some verbs, as follows:
// //
// %+s path of source file relative to the compile time GOPATH // %+s function name and path of source file relative to the compile time
// GOPATH separated by \n\t (<funcname>\n\t<path>)
// %+v equivalent to %+s:%d // %+v equivalent to %+s:%d
func (f Frame) Format(s fmt.State, verb rune) { func (f Frame) Format(s fmt.State, verb rune) {
switch verb { switch verb {
@ -79,6 +80,14 @@ func (f Frame) Format(s fmt.State, verb rune) {
// StackTrace is stack of Frames from innermost (newest) to outermost (oldest). // StackTrace is stack of Frames from innermost (newest) to outermost (oldest).
type StackTrace []Frame type StackTrace []Frame
// Format formats the stack of Frames according to the fmt.Formatter interface.
//
// %s lists source files for each Frame in the stack
// %v lists the source file and line number for each Frame in the stack
//
// Format accepts flags that alter the printing of some verbs, as follows:
//
// %+v Prints filename, function, and line number for each Frame in the stack.
func (st StackTrace) Format(s fmt.State, verb rune) { func (st StackTrace) Format(s fmt.State, verb rune) {
switch verb { switch verb {
case 'v': case 'v':
@ -136,43 +145,3 @@ func funcname(name string) string {
i = strings.Index(name, ".") i = strings.Index(name, ".")
return name[i+1:] return name[i+1:]
} }
func trimGOPATH(name, file string) string {
// Here we want to get the source file path relative to the compile time
// GOPATH. As of Go 1.6.x there is no direct way to know the compiled
// GOPATH at runtime, but we can infer the number of path segments in the
// GOPATH. We note that fn.Name() returns the function name qualified by
// the import path, which does not include the GOPATH. Thus we can trim
// segments from the beginning of the file path until the number of path
// separators remaining is one more than the number of path separators in
// the function name. For example, given:
//
// GOPATH /home/user
// file /home/user/src/pkg/sub/file.go
// fn.Name() pkg/sub.Type.Method
//
// We want to produce:
//
// pkg/sub/file.go
//
// From this we can easily see that fn.Name() has one less path separator
// than our desired output. We count separators from the end of the file
// path until it finds two more than in the function name and then move
// one character forward to preserve the initial path segment without a
// leading separator.
const sep = "/"
goal := strings.Count(name, sep) + 2
i := len(file)
for n := 0; n < goal; n++ {
i = strings.LastIndex(file[:i], sep)
if i == -1 {
// not enough separators found, set i so that the slice expression
// below leaves file unmodified
i = -len(sep)
break
}
}
// get back to 0 or trim the leading separator
file = file[i+len(sep):]
return file
}

View File

@ -1,202 +1,13 @@
Copyright 2018 gotest.tools authors
Apache License Licensed under the Apache License, Version 2.0 (the "License");
Version 2.0, January 2004 you may not use this file except in compliance with the License.
http://www.apache.org/licenses/ You may obtain a copy of the License at
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION http://www.apache.org/licenses/LICENSE-2.0
1. Definitions. Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
"License" shall mean the terms and conditions for use, reproduction, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
and distribution as defined by Sections 1 through 9 of this document. See the License for the specific language governing permissions and
limitations under the License.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

View File

@ -3,7 +3,7 @@
A collection of packages to augment `testing` and support common patterns. A collection of packages to augment `testing` and support common patterns.
[![GoDoc](https://godoc.org/gotest.tools?status.svg)](https://godoc.org/gotest.tools) [![GoDoc](https://godoc.org/gotest.tools?status.svg)](https://godoc.org/gotest.tools)
[![CircleCI](https://circleci.com/gh/gotestyourself/gotestyourself/tree/master.svg?style=shield)](https://circleci.com/gh/gotestyourself/gotestyourself/tree/master) [![CircleCI](https://circleci.com/gh/gotestyourself/gotest.tools/tree/master.svg?style=shield)](https://circleci.com/gh/gotestyourself/gotest.tools/tree/master)
[![Go Reportcard](https://goreportcard.com/badge/gotest.tools)](https://goreportcard.com/report/gotest.tools) [![Go Reportcard](https://goreportcard.com/badge/gotest.tools)](https://goreportcard.com/report/gotest.tools)
@ -29,3 +29,7 @@ A collection of packages to augment `testing` and support common patterns.
* [gotest.tools/gotestsum](https://github.com/gotestyourself/gotestsum) - go test runner with custom output * [gotest.tools/gotestsum](https://github.com/gotestyourself/gotestsum) - go test runner with custom output
* [maxbrunsfeld/counterfeiter](https://github.com/maxbrunsfeld/counterfeiter) - generate fakes for interfaces * [maxbrunsfeld/counterfeiter](https://github.com/maxbrunsfeld/counterfeiter) - generate fakes for interfaces
* [jonboulle/clockwork](https://github.com/jonboulle/clockwork) - a fake clock for testing code that uses `time` * [jonboulle/clockwork](https://github.com/jonboulle/clockwork) - a fake clock for testing code that uses `time`
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md).

View File

@ -4,6 +4,7 @@ package cmp // import "gotest.tools/assert/cmp"
import ( import (
"fmt" "fmt"
"reflect" "reflect"
"regexp"
"strings" "strings"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
@ -58,6 +59,39 @@ func toResult(success bool, msg string) Result {
return ResultFailure(msg) return ResultFailure(msg)
} }
// RegexOrPattern may be either a *regexp.Regexp or a string that is a valid
// regexp pattern.
type RegexOrPattern interface{}
// Regexp succeeds if value v matches regular expression re.
//
// Example:
// assert.Assert(t, cmp.Regexp("^[0-9a-f]{32}$", str))
// r := regexp.MustCompile("^[0-9a-f]{32}$")
// assert.Assert(t, cmp.Regexp(r, str))
func Regexp(re RegexOrPattern, v string) Comparison {
match := func(re *regexp.Regexp) Result {
return toResult(
re.MatchString(v),
fmt.Sprintf("value %q does not match regexp %q", v, re.String()))
}
return func() Result {
switch regex := re.(type) {
case *regexp.Regexp:
return match(regex)
case string:
re, err := regexp.Compile(regex)
if err != nil {
return ResultFailure(err.Error())
}
return match(re)
default:
return ResultFailure(fmt.Sprintf("invalid type %T for regex pattern", regex))
}
}
}
// Equal succeeds if x == y. See assert.Equal for full documentation. // Equal succeeds if x == y. See assert.Equal for full documentation.
func Equal(x, y interface{}) Comparison { func Equal(x, y interface{}) Comparison {
return func() Result { return func() Result {
@ -186,7 +220,7 @@ func Error(err error, message string) Comparison {
return ResultFailure("expected an error, got nil") return ResultFailure("expected an error, got nil")
case err.Error() != message: case err.Error() != message:
return ResultFailure(fmt.Sprintf( return ResultFailure(fmt.Sprintf(
"expected error %q, got %+v", message, err)) "expected error %q, got %s", message, formatErrorMessage(err)))
} }
return ResultSuccess return ResultSuccess
} }
@ -201,12 +235,22 @@ func ErrorContains(err error, substring string) Comparison {
return ResultFailure("expected an error, got nil") return ResultFailure("expected an error, got nil")
case !strings.Contains(err.Error(), substring): case !strings.Contains(err.Error(), substring):
return ResultFailure(fmt.Sprintf( return ResultFailure(fmt.Sprintf(
"expected error to contain %q, got %+v", substring, err)) "expected error to contain %q, got %s", substring, formatErrorMessage(err)))
} }
return ResultSuccess return ResultSuccess
} }
} }
func formatErrorMessage(err error) string {
if _, ok := err.(interface {
Cause() error
}); ok {
return fmt.Sprintf("%q\n%+v", err, err)
}
// This error was not wrapped with github.com/pkg/errors
return fmt.Sprintf("%q", err)
}
// Nil succeeds if obj is a nil interface, pointer, or function. // Nil succeeds if obj is a nil interface, pointer, or function.
// //
// Use NilError() for comparing errors. Use Len(obj, 0) for comparing slices, // Use NilError() for comparing errors. Use Len(obj, 0) for comparing slices,

View File

@ -9,31 +9,37 @@ import (
"gotest.tools/internal/source" "gotest.tools/internal/source"
) )
// Result of a Comparison. // A Result of a Comparison.
type Result interface { type Result interface {
Success() bool Success() bool
} }
type result struct { // StringResult is an implementation of Result that reports the error message
// string verbatim and does not provide any templating or formatting of the
// message.
type StringResult struct {
success bool success bool
message string message string
} }
func (r result) Success() bool { // Success returns true if the comparison was successful.
func (r StringResult) Success() bool {
return r.success return r.success
} }
func (r result) FailureMessage() string { // FailureMessage returns the message used to provide additional information
// about the failure.
func (r StringResult) FailureMessage() string {
return r.message return r.message
} }
// ResultSuccess is a constant which is returned by a ComparisonWithResult to // ResultSuccess is a constant which is returned by a ComparisonWithResult to
// indicate success. // indicate success.
var ResultSuccess = result{success: true} var ResultSuccess = StringResult{success: true}
// ResultFailure returns a failed Result with a failure message. // ResultFailure returns a failed Result with a failure message.
func ResultFailure(message string) Result { func ResultFailure(message string) StringResult {
return result{message: message} return StringResult{message: message}
} }
// ResultFromError returns ResultSuccess if err is nil. Otherwise ResultFailure // ResultFromError returns ResultSuccess if err is nil. Otherwise ResultFailure

View File

@ -70,7 +70,6 @@ func filterPrintableExpr(args []ast.Expr) []ast.Expr {
result[i] = starExpr.X result[i] = starExpr.X
continue continue
} }
result[i] = nil
} }
return result return result
} }

View File

@ -1,4 +1,4 @@
/* Package difflib is a partial port of Python difflib module. /*Package difflib is a partial port of Python difflib module.
Original source: https://github.com/pmezard/go-difflib Original source: https://github.com/pmezard/go-difflib
@ -20,12 +20,14 @@ func max(a, b int) int {
return b return b
} }
// Match stores line numbers of size of match
type Match struct { type Match struct {
A int A int
B int B int
Size int Size int
} }
// OpCode identifies the type of diff
type OpCode struct { type OpCode struct {
Tag byte Tag byte
I1 int I1 int
@ -73,19 +75,20 @@ type SequenceMatcher struct {
opCodes []OpCode opCodes []OpCode
} }
// NewMatcher returns a new SequenceMatcher
func NewMatcher(a, b []string) *SequenceMatcher { func NewMatcher(a, b []string) *SequenceMatcher {
m := SequenceMatcher{autoJunk: true} m := SequenceMatcher{autoJunk: true}
m.SetSeqs(a, b) m.SetSeqs(a, b)
return &m return &m
} }
// Set two sequences to be compared. // SetSeqs sets two sequences to be compared.
func (m *SequenceMatcher) SetSeqs(a, b []string) { func (m *SequenceMatcher) SetSeqs(a, b []string) {
m.SetSeq1(a) m.SetSeq1(a)
m.SetSeq2(b) m.SetSeq2(b)
} }
// Set the first sequence to be compared. The second sequence to be compared is // SetSeq1 sets the first sequence to be compared. The second sequence to be compared is
// not changed. // not changed.
// //
// SequenceMatcher computes and caches detailed information about the second // SequenceMatcher computes and caches detailed information about the second
@ -103,7 +106,7 @@ func (m *SequenceMatcher) SetSeq1(a []string) {
m.opCodes = nil m.opCodes = nil
} }
// Set the second sequence to be compared. The first sequence to be compared is // SetSeq2 sets the second sequence to be compared. The first sequence to be compared is
// not changed. // not changed.
func (m *SequenceMatcher) SetSeq2(b []string) { func (m *SequenceMatcher) SetSeq2(b []string) {
if &b == &m.b { if &b == &m.b {
@ -129,12 +132,12 @@ func (m *SequenceMatcher) chainB() {
m.bJunk = map[string]struct{}{} m.bJunk = map[string]struct{}{}
if m.IsJunk != nil { if m.IsJunk != nil {
junk := m.bJunk junk := m.bJunk
for s, _ := range b2j { for s := range b2j {
if m.IsJunk(s) { if m.IsJunk(s) {
junk[s] = struct{}{} junk[s] = struct{}{}
} }
} }
for s, _ := range junk { for s := range junk {
delete(b2j, s) delete(b2j, s)
} }
} }
@ -149,7 +152,7 @@ func (m *SequenceMatcher) chainB() {
popular[s] = struct{}{} popular[s] = struct{}{}
} }
} }
for s, _ := range popular { for s := range popular {
delete(b2j, s) delete(b2j, s)
} }
} }
@ -259,7 +262,7 @@ func (m *SequenceMatcher) findLongestMatch(alo, ahi, blo, bhi int) Match {
return Match{A: besti, B: bestj, Size: bestsize} return Match{A: besti, B: bestj, Size: bestsize}
} }
// Return list of triples describing matching subsequences. // GetMatchingBlocks returns a list of triples describing matching subsequences.
// //
// Each triple is of the form (i, j, n), and means that // Each triple is of the form (i, j, n), and means that
// a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in // a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in
@ -323,7 +326,7 @@ func (m *SequenceMatcher) GetMatchingBlocks() []Match {
return m.matchingBlocks return m.matchingBlocks
} }
// Return list of 5-tuples describing how to turn a into b. // GetOpCodes returns a list of 5-tuples describing how to turn a into b.
// //
// Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple // Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple
// has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the // has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the
@ -374,7 +377,7 @@ func (m *SequenceMatcher) GetOpCodes() []OpCode {
return m.opCodes return m.opCodes
} }
// Isolate change clusters by eliminating ranges with no changes. // GetGroupedOpCodes isolates change clusters by eliminating ranges with no changes.
// //
// Return a generator of groups with up to n lines of context. // Return a generator of groups with up to n lines of context.
// Each group is in the same format as returned by GetOpCodes(). // Each group is in the same format as returned by GetOpCodes().
@ -384,7 +387,7 @@ func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode {
} }
codes := m.GetOpCodes() codes := m.GetOpCodes()
if len(codes) == 0 { if len(codes) == 0 {
codes = []OpCode{OpCode{'e', 0, 1, 0, 1}} codes = []OpCode{{'e', 0, 1, 0, 1}}
} }
// Fixup leading and trailing groups if they show no changes. // Fixup leading and trailing groups if they show no changes.
if codes[0].Tag == 'e' { if codes[0].Tag == 'e' {

View File

@ -0,0 +1,53 @@
package source
import (
"go/ast"
"go/token"
"github.com/pkg/errors"
)
func scanToDeferLine(fileset *token.FileSet, node ast.Node, lineNum int) ast.Node {
var matchedNode ast.Node
ast.Inspect(node, func(node ast.Node) bool {
switch {
case node == nil || matchedNode != nil:
return false
case fileset.Position(node.End()).Line == lineNum:
if funcLit, ok := node.(*ast.FuncLit); ok {
matchedNode = funcLit
return false
}
}
return true
})
debug("defer line node: %s", debugFormatNode{matchedNode})
return matchedNode
}
func guessDefer(node ast.Node) (ast.Node, error) {
defers := collectDefers(node)
switch len(defers) {
case 0:
return nil, errors.New("failed to expression in defer")
case 1:
return defers[0].Call, nil
default:
return nil, errors.Errorf(
"ambiguous call expression: multiple (%d) defers in call block",
len(defers))
}
}
func collectDefers(node ast.Node) []*ast.DeferStmt {
var defers []*ast.DeferStmt
ast.Inspect(node, func(node ast.Node) bool {
if d, ok := node.(*ast.DeferStmt); ok {
defers = append(defers, d)
debug("defer: %s", debugFormatNode{d})
return false
}
return true
})
return defers
}

View File

@ -24,106 +24,12 @@ func FormattedCallExprArg(stackIndex int, argPos int) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
if argPos >= len(args) {
return "", errors.New("failed to find expression")
}
return FormatNode(args[argPos]) return FormatNode(args[argPos])
} }
func getNodeAtLine(filename string, lineNum int) (ast.Node, error) {
fileset := token.NewFileSet()
astFile, err := parser.ParseFile(fileset, filename, nil, parser.AllErrors)
if err != nil {
return nil, errors.Wrapf(err, "failed to parse source file: %s", filename)
}
node := scanToLine(fileset, astFile, lineNum)
if node == nil {
return nil, errors.Errorf(
"failed to find an expression on line %d in %s", lineNum, filename)
}
return node, nil
}
func scanToLine(fileset *token.FileSet, node ast.Node, lineNum int) ast.Node {
v := &scanToLineVisitor{lineNum: lineNum, fileset: fileset}
ast.Walk(v, node)
return v.matchedNode
}
type scanToLineVisitor struct {
lineNum int
matchedNode ast.Node
fileset *token.FileSet
}
func (v *scanToLineVisitor) Visit(node ast.Node) ast.Visitor {
if node == nil || v.matchedNode != nil {
return nil
}
if v.nodePosition(node).Line == v.lineNum {
v.matchedNode = node
return nil
}
return v
}
// In golang 1.9 the line number changed from being the line where the statement
// ended to the line where the statement began.
func (v *scanToLineVisitor) nodePosition(node ast.Node) token.Position {
if goVersionBefore19 {
return v.fileset.Position(node.End())
}
return v.fileset.Position(node.Pos())
}
var goVersionBefore19 = isGOVersionBefore19()
func isGOVersionBefore19() bool {
version := runtime.Version()
// not a release version
if !strings.HasPrefix(version, "go") {
return false
}
version = strings.TrimPrefix(version, "go")
parts := strings.Split(version, ".")
if len(parts) < 2 {
return false
}
minor, err := strconv.ParseInt(parts[1], 10, 32)
return err == nil && parts[0] == "1" && minor < 9
}
func getCallExprArgs(node ast.Node) ([]ast.Expr, error) {
visitor := &callExprVisitor{}
ast.Walk(visitor, node)
if visitor.expr == nil {
return nil, errors.New("failed to find call expression")
}
return visitor.expr.Args, nil
}
type callExprVisitor struct {
expr *ast.CallExpr
}
func (v *callExprVisitor) Visit(node ast.Node) ast.Visitor {
if v.expr != nil || node == nil {
return nil
}
debug("visit (%T): %s", node, debugFormatNode{node})
if callExpr, ok := node.(*ast.CallExpr); ok {
v.expr = callExpr
return nil
}
return v
}
// FormatNode using go/format.Node and return the result as a string
func FormatNode(node ast.Node) (string, error) {
buf := new(bytes.Buffer)
err := format.Node(buf, token.NewFileSet(), node)
return buf.String(), err
}
// CallExprArgs returns the ast.Expr slice for the args of an ast.CallExpr at // CallExprArgs returns the ast.Expr slice for the args of an ast.CallExpr at
// the index in the call stack. // the index in the call stack.
func CallExprArgs(stackIndex int) ([]ast.Expr, error) { func CallExprArgs(stackIndex int) ([]ast.Expr, error) {
@ -137,12 +43,109 @@ func CallExprArgs(stackIndex int) ([]ast.Expr, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
debug("found node (%T): %s", node, debugFormatNode{node}) debug("found node: %s", debugFormatNode{node})
return getCallExprArgs(node) return getCallExprArgs(node)
} }
var debugEnabled = os.Getenv("GOTESTYOURSELF_DEBUG") != "" func getNodeAtLine(filename string, lineNum int) (ast.Node, error) {
fileset := token.NewFileSet()
astFile, err := parser.ParseFile(fileset, filename, nil, parser.AllErrors)
if err != nil {
return nil, errors.Wrapf(err, "failed to parse source file: %s", filename)
}
if node := scanToLine(fileset, astFile, lineNum); node != nil {
return node, nil
}
if node := scanToDeferLine(fileset, astFile, lineNum); node != nil {
node, err := guessDefer(node)
if err != nil || node != nil {
return node, err
}
}
return nil, errors.Errorf(
"failed to find an expression on line %d in %s", lineNum, filename)
}
func scanToLine(fileset *token.FileSet, node ast.Node, lineNum int) ast.Node {
var matchedNode ast.Node
ast.Inspect(node, func(node ast.Node) bool {
switch {
case node == nil || matchedNode != nil:
return false
case nodePosition(fileset, node).Line == lineNum:
matchedNode = node
return false
}
return true
})
return matchedNode
}
// In golang 1.9 the line number changed from being the line where the statement
// ended to the line where the statement began.
func nodePosition(fileset *token.FileSet, node ast.Node) token.Position {
if goVersionBefore19 {
return fileset.Position(node.End())
}
return fileset.Position(node.Pos())
}
var goVersionBefore19 = func() bool {
version := runtime.Version()
// not a release version
if !strings.HasPrefix(version, "go") {
return false
}
version = strings.TrimPrefix(version, "go")
parts := strings.Split(version, ".")
if len(parts) < 2 {
return false
}
minor, err := strconv.ParseInt(parts[1], 10, 32)
return err == nil && parts[0] == "1" && minor < 9
}()
func getCallExprArgs(node ast.Node) ([]ast.Expr, error) {
visitor := &callExprVisitor{}
ast.Walk(visitor, node)
if visitor.expr == nil {
return nil, errors.New("failed to find call expression")
}
debug("callExpr: %s", debugFormatNode{visitor.expr})
return visitor.expr.Args, nil
}
type callExprVisitor struct {
expr *ast.CallExpr
}
func (v *callExprVisitor) Visit(node ast.Node) ast.Visitor {
if v.expr != nil || node == nil {
return nil
}
debug("visit: %s", debugFormatNode{node})
switch typed := node.(type) {
case *ast.CallExpr:
v.expr = typed
return nil
case *ast.DeferStmt:
ast.Walk(v, typed.Call.Fun)
return nil
}
return v
}
// FormatNode using go/format.Node and return the result as a string
func FormatNode(node ast.Node) (string, error) {
buf := new(bytes.Buffer)
err := format.Node(buf, token.NewFileSet(), node)
return buf.String(), err
}
var debugEnabled = os.Getenv("GOTESTTOOLS_DEBUG") != ""
func debug(format string, args ...interface{}) { func debug(format string, args ...interface{}) {
if debugEnabled { if debugEnabled {
@ -159,5 +162,5 @@ func (n debugFormatNode) String() string {
if err != nil { if err != nil {
return fmt.Sprintf("failed to format %s: %s", n.Node, err) return fmt.Sprintf("failed to format %s: %s", n.Node, err)
} }
return out return fmt.Sprintf("(%T) %s", n.Node, out)
} }