summaryrefslogtreecommitdiff
path: root/vendor/github.com
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com')
-rw-r--r--vendor/github.com/coreos/go-systemd/LICENSE191
-rw-r--r--vendor/github.com/coreos/go-systemd/NOTICE5
-rw-r--r--vendor/github.com/coreos/go-systemd/activation/files.go67
-rw-r--r--vendor/github.com/coreos/go-systemd/activation/listeners.go103
-rw-r--r--vendor/github.com/coreos/go-systemd/activation/packetconns.go38
-rw-r--r--vendor/github.com/docker/go-plugins-helpers/LICENSE202
-rw-r--r--vendor/github.com/docker/go-plugins-helpers/NOTICE19
-rw-r--r--vendor/github.com/docker/go-plugins-helpers/sdk/encoder.go37
-rw-r--r--vendor/github.com/docker/go-plugins-helpers/sdk/handler.go88
-rw-r--r--vendor/github.com/docker/go-plugins-helpers/sdk/pool.go18
-rw-r--r--vendor/github.com/docker/go-plugins-helpers/sdk/spec_file_generator.go58
-rw-r--r--vendor/github.com/docker/go-plugins-helpers/sdk/tcp_listener.go34
-rw-r--r--vendor/github.com/docker/go-plugins-helpers/sdk/unix_listener.go35
-rw-r--r--vendor/github.com/docker/go-plugins-helpers/sdk/unix_listener_nosystemd.go10
-rw-r--r--vendor/github.com/docker/go-plugins-helpers/sdk/unix_listener_systemd.go45
-rw-r--r--vendor/github.com/docker/go-plugins-helpers/sdk/unix_listener_unsupported.go16
-rw-r--r--vendor/github.com/docker/go-plugins-helpers/sdk/windows_listener.go70
-rw-r--r--vendor/github.com/docker/go-plugins-helpers/sdk/windows_listener_unsupported.go20
-rw-r--r--vendor/github.com/docker/go-plugins-helpers/sdk/windows_pipe_config.go13
-rw-r--r--vendor/github.com/docker/go-plugins-helpers/volume/README.md36
-rw-r--r--vendor/github.com/docker/go-plugins-helpers/volume/api.go230
-rw-r--r--vendor/github.com/spf13/cobra/bash_completions.go752
-rw-r--r--vendor/github.com/spf13/cobra/custom_completions.go101
-rw-r--r--vendor/github.com/spf13/cobra/fish_completions.go115
-rw-r--r--vendor/github.com/spf13/cobra/zsh_completions.go55
25 files changed, 1953 insertions, 405 deletions
diff --git a/vendor/github.com/coreos/go-systemd/LICENSE b/vendor/github.com/coreos/go-systemd/LICENSE
new file mode 100644
index 000000000..37ec93a14
--- /dev/null
+++ b/vendor/github.com/coreos/go-systemd/LICENSE
@@ -0,0 +1,191 @@
+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:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+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
+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.
diff --git a/vendor/github.com/coreos/go-systemd/NOTICE b/vendor/github.com/coreos/go-systemd/NOTICE
new file mode 100644
index 000000000..23a0ada2f
--- /dev/null
+++ b/vendor/github.com/coreos/go-systemd/NOTICE
@@ -0,0 +1,5 @@
+CoreOS Project
+Copyright 2018 CoreOS, Inc
+
+This product includes software developed at CoreOS, Inc.
+(http://www.coreos.com/).
diff --git a/vendor/github.com/coreos/go-systemd/activation/files.go b/vendor/github.com/coreos/go-systemd/activation/files.go
new file mode 100644
index 000000000..29dd18def
--- /dev/null
+++ b/vendor/github.com/coreos/go-systemd/activation/files.go
@@ -0,0 +1,67 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package activation implements primitives for systemd socket activation.
+package activation
+
+import (
+ "os"
+ "strconv"
+ "strings"
+ "syscall"
+)
+
+const (
+ // listenFdsStart corresponds to `SD_LISTEN_FDS_START`.
+ listenFdsStart = 3
+)
+
+// Files returns a slice containing a `os.File` object for each
+// file descriptor passed to this process via systemd fd-passing protocol.
+//
+// The order of the file descriptors is preserved in the returned slice.
+// `unsetEnv` is typically set to `true` in order to avoid clashes in
+// fd usage and to avoid leaking environment flags to child processes.
+func Files(unsetEnv bool) []*os.File {
+ if unsetEnv {
+ defer os.Unsetenv("LISTEN_PID")
+ defer os.Unsetenv("LISTEN_FDS")
+ defer os.Unsetenv("LISTEN_FDNAMES")
+ }
+
+ pid, err := strconv.Atoi(os.Getenv("LISTEN_PID"))
+ if err != nil || pid != os.Getpid() {
+ return nil
+ }
+
+ nfds, err := strconv.Atoi(os.Getenv("LISTEN_FDS"))
+ if err != nil || nfds == 0 {
+ return nil
+ }
+
+ names := strings.Split(os.Getenv("LISTEN_FDNAMES"), ":")
+
+ files := make([]*os.File, 0, nfds)
+ for fd := listenFdsStart; fd < listenFdsStart+nfds; fd++ {
+ syscall.CloseOnExec(fd)
+ name := "LISTEN_FD_" + strconv.Itoa(fd)
+ offset := fd - listenFdsStart
+ if offset < len(names) && len(names[offset]) > 0 {
+ name = names[offset]
+ }
+ files = append(files, os.NewFile(uintptr(fd), name))
+ }
+
+ return files
+}
diff --git a/vendor/github.com/coreos/go-systemd/activation/listeners.go b/vendor/github.com/coreos/go-systemd/activation/listeners.go
new file mode 100644
index 000000000..bb5cc2311
--- /dev/null
+++ b/vendor/github.com/coreos/go-systemd/activation/listeners.go
@@ -0,0 +1,103 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package activation
+
+import (
+ "crypto/tls"
+ "net"
+)
+
+// Listeners returns a slice containing a net.Listener for each matching socket type
+// passed to this process.
+//
+// The order of the file descriptors is preserved in the returned slice.
+// Nil values are used to fill any gaps. For example if systemd were to return file descriptors
+// corresponding with "udp, tcp, tcp", then the slice would contain {nil, net.Listener, net.Listener}
+func Listeners() ([]net.Listener, error) {
+ files := Files(true)
+ listeners := make([]net.Listener, len(files))
+
+ for i, f := range files {
+ if pc, err := net.FileListener(f); err == nil {
+ listeners[i] = pc
+ f.Close()
+ }
+ }
+ return listeners, nil
+}
+
+// ListenersWithNames maps a listener name to a set of net.Listener instances.
+func ListenersWithNames() (map[string][]net.Listener, error) {
+ files := Files(true)
+ listeners := map[string][]net.Listener{}
+
+ for _, f := range files {
+ if pc, err := net.FileListener(f); err == nil {
+ current, ok := listeners[f.Name()]
+ if !ok {
+ listeners[f.Name()] = []net.Listener{pc}
+ } else {
+ listeners[f.Name()] = append(current, pc)
+ }
+ f.Close()
+ }
+ }
+ return listeners, nil
+}
+
+// TLSListeners returns a slice containing a net.listener for each matching TCP socket type
+// passed to this process.
+// It uses default Listeners func and forces TCP sockets handlers to use TLS based on tlsConfig.
+func TLSListeners(tlsConfig *tls.Config) ([]net.Listener, error) {
+ listeners, err := Listeners()
+
+ if listeners == nil || err != nil {
+ return nil, err
+ }
+
+ if tlsConfig != nil && err == nil {
+ for i, l := range listeners {
+ // Activate TLS only for TCP sockets
+ if l.Addr().Network() == "tcp" {
+ listeners[i] = tls.NewListener(l, tlsConfig)
+ }
+ }
+ }
+
+ return listeners, err
+}
+
+// TLSListenersWithNames maps a listener name to a net.Listener with
+// the associated TLS configuration.
+func TLSListenersWithNames(tlsConfig *tls.Config) (map[string][]net.Listener, error) {
+ listeners, err := ListenersWithNames()
+
+ if listeners == nil || err != nil {
+ return nil, err
+ }
+
+ if tlsConfig != nil && err == nil {
+ for _, ll := range listeners {
+ // Activate TLS only for TCP sockets
+ for i, l := range ll {
+ if l.Addr().Network() == "tcp" {
+ ll[i] = tls.NewListener(l, tlsConfig)
+ }
+ }
+ }
+ }
+
+ return listeners, err
+}
diff --git a/vendor/github.com/coreos/go-systemd/activation/packetconns.go b/vendor/github.com/coreos/go-systemd/activation/packetconns.go
new file mode 100644
index 000000000..a97206785
--- /dev/null
+++ b/vendor/github.com/coreos/go-systemd/activation/packetconns.go
@@ -0,0 +1,38 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package activation
+
+import (
+ "net"
+)
+
+// PacketConns returns a slice containing a net.PacketConn for each matching socket type
+// passed to this process.
+//
+// The order of the file descriptors is preserved in the returned slice.
+// Nil values are used to fill any gaps. For example if systemd were to return file descriptors
+// corresponding with "udp, tcp, udp", then the slice would contain {net.PacketConn, nil, net.PacketConn}
+func PacketConns() ([]net.PacketConn, error) {
+ files := Files(true)
+ conns := make([]net.PacketConn, len(files))
+
+ for i, f := range files {
+ if pc, err := net.FilePacketConn(f); err == nil {
+ conns[i] = pc
+ f.Close()
+ }
+ }
+ return conns, nil
+}
diff --git a/vendor/github.com/docker/go-plugins-helpers/LICENSE b/vendor/github.com/docker/go-plugins-helpers/LICENSE
new file mode 100644
index 000000000..8f71f43fe
--- /dev/null
+++ b/vendor/github.com/docker/go-plugins-helpers/LICENSE
@@ -0,0 +1,202 @@
+ 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 {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.
+
diff --git a/vendor/github.com/docker/go-plugins-helpers/NOTICE b/vendor/github.com/docker/go-plugins-helpers/NOTICE
new file mode 100644
index 000000000..6e6f469ab
--- /dev/null
+++ b/vendor/github.com/docker/go-plugins-helpers/NOTICE
@@ -0,0 +1,19 @@
+Docker
+Copyright 2012-2015 Docker, Inc.
+
+This product includes software developed at Docker, Inc. (https://www.docker.com).
+
+This product contains software (https://github.com/kr/pty) developed
+by Keith Rarick, licensed under the MIT License.
+
+The following is courtesy of our legal counsel:
+
+
+Use and transfer of Docker may be subject to certain restrictions by the
+United States and other governments.
+It is your responsibility to ensure that your use and/or transfer does not
+violate applicable laws.
+
+For more information, please see https://www.bis.doc.gov
+
+See also https://www.apache.org/dev/crypto.html and/or seek legal counsel.
diff --git a/vendor/github.com/docker/go-plugins-helpers/sdk/encoder.go b/vendor/github.com/docker/go-plugins-helpers/sdk/encoder.go
new file mode 100644
index 000000000..195812a44
--- /dev/null
+++ b/vendor/github.com/docker/go-plugins-helpers/sdk/encoder.go
@@ -0,0 +1,37 @@
+package sdk
+
+import (
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+)
+
+// DefaultContentTypeV1_1 is the default content type accepted and sent by the plugins.
+const DefaultContentTypeV1_1 = "application/vnd.docker.plugins.v1.1+json"
+
+// DecodeRequest decodes an http request into a given structure.
+func DecodeRequest(w http.ResponseWriter, r *http.Request, req interface{}) (err error) {
+ if err = json.NewDecoder(r.Body).Decode(req); err != nil {
+ http.Error(w, err.Error(), http.StatusBadRequest)
+ }
+ return
+}
+
+// EncodeResponse encodes the given structure into an http response.
+func EncodeResponse(w http.ResponseWriter, res interface{}, err bool) {
+ w.Header().Set("Content-Type", DefaultContentTypeV1_1)
+ if err {
+ w.WriteHeader(http.StatusInternalServerError)
+ }
+ json.NewEncoder(w).Encode(res)
+}
+
+// StreamResponse streams a response object to the client
+func StreamResponse(w http.ResponseWriter, data io.ReadCloser) {
+ w.Header().Set("Content-Type", DefaultContentTypeV1_1)
+ if _, err := copyBuf(w, data); err != nil {
+ fmt.Printf("ERROR in stream: %v\n", err)
+ }
+ data.Close()
+}
diff --git a/vendor/github.com/docker/go-plugins-helpers/sdk/handler.go b/vendor/github.com/docker/go-plugins-helpers/sdk/handler.go
new file mode 100644
index 000000000..c0d042ed0
--- /dev/null
+++ b/vendor/github.com/docker/go-plugins-helpers/sdk/handler.go
@@ -0,0 +1,88 @@
+package sdk
+
+import (
+ "crypto/tls"
+ "fmt"
+ "net"
+ "net/http"
+ "os"
+)
+
+const activatePath = "/Plugin.Activate"
+
+// Handler is the base to create plugin handlers.
+// It initializes connections and sockets to listen to.
+type Handler struct {
+ mux *http.ServeMux
+}
+
+// NewHandler creates a new Handler with an http mux.
+func NewHandler(manifest string) Handler {
+ mux := http.NewServeMux()
+
+ mux.HandleFunc(activatePath, func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", DefaultContentTypeV1_1)
+ fmt.Fprintln(w, manifest)
+ })
+
+ return Handler{mux: mux}
+}
+
+// Serve sets up the handler to serve requests on the passed in listener
+func (h Handler) Serve(l net.Listener) error {
+ server := http.Server{
+ Addr: l.Addr().String(),
+ Handler: h.mux,
+ }
+ return server.Serve(l)
+}
+
+// ServeTCP makes the handler to listen for request in a given TCP address.
+// It also writes the spec file in the right directory for docker to read.
+// Due to constrains for running Docker in Docker on Windows, data-root directory
+// of docker daemon must be provided. To get default directory, use
+// WindowsDefaultDaemonRootDir() function. On Unix, this parameter is ignored.
+func (h Handler) ServeTCP(pluginName, addr, daemonDir string, tlsConfig *tls.Config) error {
+ l, spec, err := newTCPListener(addr, pluginName, daemonDir, tlsConfig)
+ if err != nil {
+ return err
+ }
+ if spec != "" {
+ defer os.Remove(spec)
+ }
+ return h.Serve(l)
+}
+
+// ServeUnix makes the handler to listen for requests in a unix socket.
+// It also creates the socket file in the right directory for docker to read.
+func (h Handler) ServeUnix(addr string, gid int) error {
+ l, spec, err := newUnixListener(addr, gid)
+ if err != nil {
+ return err
+ }
+ if spec != "" {
+ defer os.Remove(spec)
+ }
+ return h.Serve(l)
+}
+
+// ServeWindows makes the handler to listen for request in a Windows named pipe.
+// It also creates the spec file in the right directory for docker to read.
+// Due to constrains for running Docker in Docker on Windows, data-root directory
+// of docker daemon must be provided. To get default directory, use
+// WindowsDefaultDaemonRootDir() function. On Unix, this parameter is ignored.
+func (h Handler) ServeWindows(addr, pluginName, daemonDir string, pipeConfig *WindowsPipeConfig) error {
+ l, spec, err := newWindowsListener(addr, pluginName, daemonDir, pipeConfig)
+ if err != nil {
+ return err
+ }
+ if spec != "" {
+ defer os.Remove(spec)
+ }
+ return h.Serve(l)
+}
+
+// HandleFunc registers a function to handle a request path with.
+func (h Handler) HandleFunc(path string, fn func(w http.ResponseWriter, r *http.Request)) {
+ h.mux.HandleFunc(path, fn)
+}
diff --git a/vendor/github.com/docker/go-plugins-helpers/sdk/pool.go b/vendor/github.com/docker/go-plugins-helpers/sdk/pool.go
new file mode 100644
index 000000000..316775973
--- /dev/null
+++ b/vendor/github.com/docker/go-plugins-helpers/sdk/pool.go
@@ -0,0 +1,18 @@
+package sdk
+
+import (
+ "io"
+ "sync"
+)
+
+const buffer32K = 32 * 1024
+
+var buffer32KPool = &sync.Pool{New: func() interface{} { return make([]byte, buffer32K) }}
+
+// copyBuf uses a shared buffer pool with io.CopyBuffer
+func copyBuf(w io.Writer, r io.Reader) (int64, error) {
+ buf := buffer32KPool.Get().([]byte)
+ written, err := io.CopyBuffer(w, r, buf)
+ buffer32KPool.Put(buf)
+ return written, err
+}
diff --git a/vendor/github.com/docker/go-plugins-helpers/sdk/spec_file_generator.go b/vendor/github.com/docker/go-plugins-helpers/sdk/spec_file_generator.go
new file mode 100644
index 000000000..bc8cfc644
--- /dev/null
+++ b/vendor/github.com/docker/go-plugins-helpers/sdk/spec_file_generator.go
@@ -0,0 +1,58 @@
+package sdk
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+)
+
+type protocol string
+
+const (
+ protoTCP protocol = "tcp"
+ protoNamedPipe protocol = "npipe"
+)
+
+// PluginSpecDir returns plugin spec dir in relation to daemon root directory.
+func PluginSpecDir(daemonRoot string) string {
+ return ([]string{filepath.Join(daemonRoot, "plugins")})[0]
+}
+
+// WindowsDefaultDaemonRootDir returns default data directory of docker daemon on Windows.
+func WindowsDefaultDaemonRootDir() string {
+ return filepath.Join(os.Getenv("programdata"), "docker")
+}
+
+func createPluginSpecDirWindows(name, address, daemonRoot string) (string, error) {
+ _, err := os.Stat(daemonRoot)
+ if os.IsNotExist(err) {
+ return "", fmt.Errorf("Deamon root directory must already exist: %s", err)
+ }
+
+ pluginSpecDir := PluginSpecDir(daemonRoot)
+
+ if err := windowsCreateDirectoryWithACL(pluginSpecDir); err != nil {
+ return "", err
+ }
+ return pluginSpecDir, nil
+}
+
+func createPluginSpecDirUnix(name, address string) (string, error) {
+ pluginSpecDir := PluginSpecDir("/etc/docker")
+ if err := os.MkdirAll(pluginSpecDir, 0755); err != nil {
+ return "", err
+ }
+ return pluginSpecDir, nil
+}
+
+func writeSpecFile(name, address, pluginSpecDir string, proto protocol) (string, error) {
+ specFileDir := filepath.Join(pluginSpecDir, name+".spec")
+
+ url := string(proto) + "://" + address
+ if err := ioutil.WriteFile(specFileDir, []byte(url), 0644); err != nil {
+ return "", err
+ }
+
+ return specFileDir, nil
+}
diff --git a/vendor/github.com/docker/go-plugins-helpers/sdk/tcp_listener.go b/vendor/github.com/docker/go-plugins-helpers/sdk/tcp_listener.go
new file mode 100644
index 000000000..bad85f7fd
--- /dev/null
+++ b/vendor/github.com/docker/go-plugins-helpers/sdk/tcp_listener.go
@@ -0,0 +1,34 @@
+package sdk
+
+import (
+ "crypto/tls"
+ "net"
+ "runtime"
+
+ "github.com/docker/go-connections/sockets"
+)
+
+func newTCPListener(address, pluginName, daemonDir string, tlsConfig *tls.Config) (net.Listener, string, error) {
+ listener, err := sockets.NewTCPSocket(address, tlsConfig)
+ if err != nil {
+ return nil, "", err
+ }
+
+ addr := listener.Addr().String()
+
+ var specDir string
+ if runtime.GOOS == "windows" {
+ specDir, err = createPluginSpecDirWindows(pluginName, addr, daemonDir)
+ } else {
+ specDir, err = createPluginSpecDirUnix(pluginName, addr)
+ }
+ if err != nil {
+ return nil, "", err
+ }
+
+ specFile, err := writeSpecFile(pluginName, addr, specDir, protoTCP)
+ if err != nil {
+ return nil, "", err
+ }
+ return listener, specFile, nil
+}
diff --git a/vendor/github.com/docker/go-plugins-helpers/sdk/unix_listener.go b/vendor/github.com/docker/go-plugins-helpers/sdk/unix_listener.go
new file mode 100644
index 000000000..54b9a6d31
--- /dev/null
+++ b/vendor/github.com/docker/go-plugins-helpers/sdk/unix_listener.go
@@ -0,0 +1,35 @@
+// +build linux freebsd
+
+package sdk
+
+import (
+ "net"
+ "os"
+ "path/filepath"
+
+ "github.com/docker/go-connections/sockets"
+)
+
+const pluginSockDir = "/run/docker/plugins"
+
+func newUnixListener(pluginName string, gid int) (net.Listener, string, error) {
+ path, err := fullSocketAddress(pluginName)
+ if err != nil {
+ return nil, "", err
+ }
+ listener, err := sockets.NewUnixSocket(path, gid)
+ if err != nil {
+ return nil, "", err
+ }
+ return listener, path, nil
+}
+
+func fullSocketAddress(address string) (string, error) {
+ if err := os.MkdirAll(pluginSockDir, 0755); err != nil {
+ return "", err
+ }
+ if filepath.IsAbs(address) {
+ return address, nil
+ }
+ return filepath.Join(pluginSockDir, address+".sock"), nil
+}
diff --git a/vendor/github.com/docker/go-plugins-helpers/sdk/unix_listener_nosystemd.go b/vendor/github.com/docker/go-plugins-helpers/sdk/unix_listener_nosystemd.go
new file mode 100644
index 000000000..a798b8722
--- /dev/null
+++ b/vendor/github.com/docker/go-plugins-helpers/sdk/unix_listener_nosystemd.go
@@ -0,0 +1,10 @@
+// +build linux freebsd
+// +build nosystemd
+
+package sdk
+
+import "net"
+
+func setupSocketActivation() (net.Listener, error) {
+ return nil, nil
+}
diff --git a/vendor/github.com/docker/go-plugins-helpers/sdk/unix_listener_systemd.go b/vendor/github.com/docker/go-plugins-helpers/sdk/unix_listener_systemd.go
new file mode 100644
index 000000000..5d5d8f427
--- /dev/null
+++ b/vendor/github.com/docker/go-plugins-helpers/sdk/unix_listener_systemd.go
@@ -0,0 +1,45 @@
+// +build linux freebsd
+// +build !nosystemd
+
+package sdk
+
+import (
+ "fmt"
+ "net"
+ "os"
+
+ "github.com/coreos/go-systemd/activation"
+)
+
+// isRunningSystemd checks whether the host was booted with systemd as its init
+// system. This functions similarly to systemd's `sd_booted(3)`: internally, it
+// checks whether /run/systemd/system/ exists and is a directory.
+// http://www.freedesktop.org/software/systemd/man/sd_booted.html
+//
+// Copied from github.com/coreos/go-systemd/util.IsRunningSystemd
+func isRunningSystemd() bool {
+ fi, err := os.Lstat("/run/systemd/system")
+ if err != nil {
+ return false
+ }
+ return fi.IsDir()
+}
+
+func setupSocketActivation() (net.Listener, error) {
+ if !isRunningSystemd() {
+ return nil, nil
+ }
+ listenFds := activation.Files(false)
+ if len(listenFds) > 1 {
+ return nil, fmt.Errorf("expected only one socket from systemd, got %d", len(listenFds))
+ }
+ var listener net.Listener
+ if len(listenFds) == 1 {
+ l, err := net.FileListener(listenFds[0])
+ if err != nil {
+ return nil, err
+ }
+ listener = l
+ }
+ return listener, nil
+}
diff --git a/vendor/github.com/docker/go-plugins-helpers/sdk/unix_listener_unsupported.go b/vendor/github.com/docker/go-plugins-helpers/sdk/unix_listener_unsupported.go
new file mode 100644
index 000000000..344cf751b
--- /dev/null
+++ b/vendor/github.com/docker/go-plugins-helpers/sdk/unix_listener_unsupported.go
@@ -0,0 +1,16 @@
+// +build !linux,!freebsd
+
+package sdk
+
+import (
+ "errors"
+ "net"
+)
+
+var (
+ errOnlySupportedOnLinuxAndFreeBSD = errors.New("unix socket creation is only supported on Linux and FreeBSD")
+)
+
+func newUnixListener(pluginName string, gid int) (net.Listener, string, error) {
+ return nil, "", errOnlySupportedOnLinuxAndFreeBSD
+}
diff --git a/vendor/github.com/docker/go-plugins-helpers/sdk/windows_listener.go b/vendor/github.com/docker/go-plugins-helpers/sdk/windows_listener.go
new file mode 100644
index 000000000..b5deaba6d
--- /dev/null
+++ b/vendor/github.com/docker/go-plugins-helpers/sdk/windows_listener.go
@@ -0,0 +1,70 @@
+// +build windows
+
+package sdk
+
+import (
+ "net"
+ "os"
+ "syscall"
+ "unsafe"
+
+ "github.com/Microsoft/go-winio"
+)
+
+// Named pipes use Windows Security Descriptor Definition Language to define ACL. Following are
+// some useful definitions.
+const (
+ // This will set permissions for everyone to have full access
+ AllowEveryone = "S:(ML;;NW;;;LW)D:(A;;0x12019f;;;WD)"
+
+ // This will set permissions for Service, System, Adminstrator group and account to have full access
+ AllowServiceSystemAdmin = "D:(A;ID;FA;;;SY)(A;ID;FA;;;BA)(A;ID;FA;;;LA)(A;ID;FA;;;LS)"
+)
+
+func newWindowsListener(address, pluginName, daemonRoot string, pipeConfig *WindowsPipeConfig) (net.Listener, string, error) {
+ winioPipeConfig := winio.PipeConfig{
+ SecurityDescriptor: pipeConfig.SecurityDescriptor,
+ InputBufferSize: pipeConfig.InBufferSize,
+ OutputBufferSize: pipeConfig.OutBufferSize,
+ }
+ listener, err := winio.ListenPipe(address, &winioPipeConfig)
+ if err != nil {
+ return nil, "", err
+ }
+
+ addr := listener.Addr().String()
+
+ specDir, err := createPluginSpecDirWindows(pluginName, addr, daemonRoot)
+ if err != nil {
+ return nil, "", err
+ }
+
+ spec, err := writeSpecFile(pluginName, addr, specDir, protoNamedPipe)
+ if err != nil {
+ return nil, "", err
+ }
+ return listener, spec, nil
+}
+
+func windowsCreateDirectoryWithACL(name string) error {
+ sa := syscall.SecurityAttributes{Length: 0}
+ sddl := "D:P(A;OICI;GA;;;BA)(A;OICI;GA;;;SY)"
+ sd, err := winio.SddlToSecurityDescriptor(sddl)
+ if err != nil {
+ return &os.PathError{Op: "mkdir", Path: name, Err: err}
+ }
+ sa.Length = uint32(unsafe.Sizeof(sa))
+ sa.InheritHandle = 1
+ sa.SecurityDescriptor = uintptr(unsafe.Pointer(&sd[0]))
+
+ namep, err := syscall.UTF16PtrFromString(name)
+ if err != nil {
+ return &os.PathError{Op: "mkdir", Path: name, Err: err}
+ }
+
+ e := syscall.CreateDirectory(namep, &sa)
+ if e != nil {
+ return &os.PathError{Op: "mkdir", Path: name, Err: e}
+ }
+ return nil
+}
diff --git a/vendor/github.com/docker/go-plugins-helpers/sdk/windows_listener_unsupported.go b/vendor/github.com/docker/go-plugins-helpers/sdk/windows_listener_unsupported.go
new file mode 100644
index 000000000..0f5e113c1
--- /dev/null
+++ b/vendor/github.com/docker/go-plugins-helpers/sdk/windows_listener_unsupported.go
@@ -0,0 +1,20 @@
+// +build !windows
+
+package sdk
+
+import (
+ "errors"
+ "net"
+)
+
+var (
+ errOnlySupportedOnWindows = errors.New("named pipe creation is only supported on Windows")
+)
+
+func newWindowsListener(address, pluginName, daemonRoot string, pipeConfig *WindowsPipeConfig) (net.Listener, string, error) {
+ return nil, "", errOnlySupportedOnWindows
+}
+
+func windowsCreateDirectoryWithACL(name string) error {
+ return nil
+}
diff --git a/vendor/github.com/docker/go-plugins-helpers/sdk/windows_pipe_config.go b/vendor/github.com/docker/go-plugins-helpers/sdk/windows_pipe_config.go
new file mode 100644
index 000000000..256fa3d67
--- /dev/null
+++ b/vendor/github.com/docker/go-plugins-helpers/sdk/windows_pipe_config.go
@@ -0,0 +1,13 @@
+package sdk
+
+// WindowsPipeConfig is a helper structure for configuring named pipe parameters on Windows.
+type WindowsPipeConfig struct {
+ // SecurityDescriptor contains a Windows security descriptor in SDDL format.
+ SecurityDescriptor string
+
+ // InBufferSize in bytes.
+ InBufferSize int32
+
+ // OutBufferSize in bytes.
+ OutBufferSize int32
+}
diff --git a/vendor/github.com/docker/go-plugins-helpers/volume/README.md b/vendor/github.com/docker/go-plugins-helpers/volume/README.md
new file mode 100644
index 000000000..395aa643f
--- /dev/null
+++ b/vendor/github.com/docker/go-plugins-helpers/volume/README.md
@@ -0,0 +1,36 @@
+# Docker volume extension api.
+
+Go handler to create external volume extensions for Docker.
+
+## Usage
+
+This library is designed to be integrated in your program.
+
+1. Implement the `volume.Driver` interface.
+2. Initialize a `volume.Handler` with your implementation.
+3. Call either `ServeTCP` or `ServeUnix` from the `volume.Handler`.
+
+### Example using TCP sockets:
+
+```go
+ d := MyVolumeDriver{}
+ h := volume.NewHandler(d)
+ h.ServeTCP("test_volume", ":8080")
+```
+
+### Example using Unix sockets:
+
+```go
+ d := MyVolumeDriver{}
+ h := volume.NewHandler(d)
+ u, _ := user.Lookup("root")
+ gid, _ := strconv.Atoi(u.Gid)
+ h.ServeUnix("test_volume", gid)
+```
+
+## Full example plugins
+
+- https://github.com/calavera/docker-volume-glusterfs
+- https://github.com/calavera/docker-volume-keywhiz
+- https://github.com/quobyte/docker-volume
+- https://github.com/NimbleStorage/Nemo
diff --git a/vendor/github.com/docker/go-plugins-helpers/volume/api.go b/vendor/github.com/docker/go-plugins-helpers/volume/api.go
new file mode 100644
index 000000000..dcc2f3abf
--- /dev/null
+++ b/vendor/github.com/docker/go-plugins-helpers/volume/api.go
@@ -0,0 +1,230 @@
+package volume
+
+import (
+ "log"
+ "net/http"
+
+ "github.com/docker/go-plugins-helpers/sdk"
+)
+
+const (
+ // DefaultDockerRootDirectory is the default directory where volumes will be created.
+ DefaultDockerRootDirectory = "/var/lib/docker-volumes"
+
+ manifest = `{"Implements": ["VolumeDriver"]}`
+ createPath = "/VolumeDriver.Create"
+ getPath = "/VolumeDriver.Get"
+ listPath = "/VolumeDriver.List"
+ removePath = "/VolumeDriver.Remove"
+ hostVirtualPath = "/VolumeDriver.Path"
+ mountPath = "/VolumeDriver.Mount"
+ unmountPath = "/VolumeDriver.Unmount"
+ capabilitiesPath = "/VolumeDriver.Capabilities"
+)
+
+// CreateRequest is the structure that docker's requests are deserialized to.
+type CreateRequest struct {
+ Name string
+ Options map[string]string `json:"Opts,omitempty"`
+}
+
+// RemoveRequest structure for a volume remove request
+type RemoveRequest struct {
+ Name string
+}
+
+// MountRequest structure for a volume mount request
+type MountRequest struct {
+ Name string
+ ID string
+}
+
+// MountResponse structure for a volume mount response
+type MountResponse struct {
+ Mountpoint string
+}
+
+// UnmountRequest structure for a volume unmount request
+type UnmountRequest struct {
+ Name string
+ ID string
+}
+
+// PathRequest structure for a volume path request
+type PathRequest struct {
+ Name string
+}
+
+// PathResponse structure for a volume path response
+type PathResponse struct {
+ Mountpoint string
+}
+
+// GetRequest structure for a volume get request
+type GetRequest struct {
+ Name string
+}
+
+// GetResponse structure for a volume get response
+type GetResponse struct {
+ Volume *Volume
+}
+
+// ListResponse structure for a volume list response
+type ListResponse struct {
+ Volumes []*Volume
+}
+
+// CapabilitiesResponse structure for a volume capability response
+type CapabilitiesResponse struct {
+ Capabilities Capability
+}
+
+// Volume represents a volume object for use with `Get` and `List` requests
+type Volume struct {
+ Name string
+ Mountpoint string `json:",omitempty"`
+ CreatedAt string `json:",omitempty"`
+ Status map[string]interface{} `json:",omitempty"`
+}
+
+// Capability represents the list of capabilities a volume driver can return
+type Capability struct {
+ Scope string
+}
+
+// ErrorResponse is a formatted error message that docker can understand
+type ErrorResponse struct {
+ Err string
+}
+
+// NewErrorResponse creates an ErrorResponse with the provided message
+func NewErrorResponse(msg string) *ErrorResponse {
+ return &ErrorResponse{Err: msg}
+}
+
+// Driver represent the interface a driver must fulfill.
+type Driver interface {
+ Create(*CreateRequest) error
+ List() (*ListResponse, error)
+ Get(*GetRequest) (*GetResponse, error)
+ Remove(*RemoveRequest) error
+ Path(*PathRequest) (*PathResponse, error)
+ Mount(*MountRequest) (*MountResponse, error)
+ Unmount(*UnmountRequest) error
+ Capabilities() *CapabilitiesResponse
+}
+
+// Handler forwards requests and responses between the docker daemon and the plugin.
+type Handler struct {
+ driver Driver
+ sdk.Handler
+}
+
+// NewHandler initializes the request handler with a driver implementation.
+func NewHandler(driver Driver) *Handler {
+ h := &Handler{driver, sdk.NewHandler(manifest)}
+ h.initMux()
+ return h
+}
+
+func (h *Handler) initMux() {
+ h.HandleFunc(createPath, func(w http.ResponseWriter, r *http.Request) {
+ log.Println("Entering go-plugins-helpers createPath")
+ req := &CreateRequest{}
+ err := sdk.DecodeRequest(w, r, req)
+ if err != nil {
+ return
+ }
+ err = h.driver.Create(req)
+ if err != nil {
+ sdk.EncodeResponse(w, NewErrorResponse(err.Error()), true)
+ return
+ }
+ sdk.EncodeResponse(w, struct{}{}, false)
+ })
+ h.HandleFunc(removePath, func(w http.ResponseWriter, r *http.Request) {
+ log.Println("Entering go-plugins-helpers removePath")
+ req := &RemoveRequest{}
+ err := sdk.DecodeRequest(w, r, req)
+ if err != nil {
+ return
+ }
+ err = h.driver.Remove(req)
+ if err != nil {
+ sdk.EncodeResponse(w, NewErrorResponse(err.Error()), true)
+ return
+ }
+ sdk.EncodeResponse(w, struct{}{}, false)
+ })
+ h.HandleFunc(mountPath, func(w http.ResponseWriter, r *http.Request) {
+ log.Println("Entering go-plugins-helpers mountPath")
+ req := &MountRequest{}
+ err := sdk.DecodeRequest(w, r, req)
+ if err != nil {
+ return
+ }
+ res, err := h.driver.Mount(req)
+ if err != nil {
+ sdk.EncodeResponse(w, NewErrorResponse(err.Error()), true)
+ return
+ }
+ sdk.EncodeResponse(w, res, false)
+ })
+ h.HandleFunc(hostVirtualPath, func(w http.ResponseWriter, r *http.Request) {
+ log.Println("Entering go-plugins-helpers hostVirtualPath")
+ req := &PathRequest{}
+ err := sdk.DecodeRequest(w, r, req)
+ if err != nil {
+ return
+ }
+ res, err := h.driver.Path(req)
+ if err != nil {
+ sdk.EncodeResponse(w, NewErrorResponse(err.Error()), true)
+ return
+ }
+ sdk.EncodeResponse(w, res, false)
+ })
+ h.HandleFunc(getPath, func(w http.ResponseWriter, r *http.Request) {
+ log.Println("Entering go-plugins-helpers getPath")
+ req := &GetRequest{}
+ err := sdk.DecodeRequest(w, r, req)
+ if err != nil {
+ return
+ }
+ res, err := h.driver.Get(req)
+ if err != nil {
+ sdk.EncodeResponse(w, NewErrorResponse(err.Error()), true)
+ return
+ }
+ sdk.EncodeResponse(w, res, false)
+ })
+ h.HandleFunc(unmountPath, func(w http.ResponseWriter, r *http.Request) {
+ log.Println("Entering go-plugins-helpers unmountPath")
+ req := &UnmountRequest{}
+ err := sdk.DecodeRequest(w, r, req)
+ if err != nil {
+ return
+ }
+ err = h.driver.Unmount(req)
+ if err != nil {
+ sdk.EncodeResponse(w, NewErrorResponse(err.Error()), true)
+ return
+ }
+ sdk.EncodeResponse(w, struct{}{}, false)
+ })
+ h.HandleFunc(listPath, func(w http.ResponseWriter, r *http.Request) {
+ log.Println("Entering go-plugins-helpers listPath")
+ res, err := h.driver.List()
+ if err != nil {
+ sdk.EncodeResponse(w, NewErrorResponse(err.Error()), true)
+ return
+ }
+ sdk.EncodeResponse(w, res, false)
+ })
+
+ h.HandleFunc(capabilitiesPath, func(w http.ResponseWriter, r *http.Request) {
+ log.Println("Entering go-plugins-helpers capabilitiesPath")
+ sdk.EncodeResponse(w, h.driver.Capabilities(), false)
+ })
+}
diff --git a/vendor/github.com/spf13/cobra/bash_completions.go b/vendor/github.com/spf13/cobra/bash_completions.go
index 2ceebc552..846636d75 100644
--- a/vendor/github.com/spf13/cobra/bash_completions.go
+++ b/vendor/github.com/spf13/cobra/bash_completions.go
@@ -5,95 +5,70 @@ import (
"fmt"
"io"
"os"
+ "sort"
+ "strings"
+
+ "github.com/spf13/pflag"
)
// Annotations for Bash completion.
const (
- BashCompFilenameExt = "cobra_annotation_bash_completion_filename_extensions"
- // BashCompCustom should be avoided as it only works for bash.
- // Function RegisterFlagCompletionFunc() should be used instead.
+ BashCompFilenameExt = "cobra_annotation_bash_completion_filename_extensions"
BashCompCustom = "cobra_annotation_bash_completion_custom"
BashCompOneRequiredFlag = "cobra_annotation_bash_completion_one_required_flag"
BashCompSubdirsInDir = "cobra_annotation_bash_completion_subdirs_in_dir"
)
-// GenBashCompletion generates bash completion file and writes to the passed writer.
-func (c *Command) GenBashCompletion(w io.Writer) error {
- return c.genBashCompletion(w, false)
-}
-
-// GenBashCompletionWithDesc generates bash completion file with descriptions and writes to the passed writer.
-func (c *Command) GenBashCompletionWithDesc(w io.Writer) error {
- return c.genBashCompletion(w, true)
-}
-
-// GenBashCompletionFile generates bash completion file.
-func (c *Command) GenBashCompletionFile(filename string) error {
- return c.genBashCompletionFile(filename, false)
-}
-
-// GenBashCompletionFileWithDesc generates bash completion file with descriptions.
-func (c *Command) GenBashCompletionFileWithDesc(filename string) error {
- return c.genBashCompletionFile(filename, true)
+func writePreamble(buf *bytes.Buffer, name string) {
+ buf.WriteString(fmt.Sprintf("# bash completion for %-36s -*- shell-script -*-\n", name))
+ buf.WriteString(fmt.Sprintf(`
+__%[1]s_debug()
+{
+ if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then
+ echo "$*" >> "${BASH_COMP_DEBUG_FILE}"
+ fi
}
-func (c *Command) genBashCompletionFile(filename string, includeDesc bool) error {
- outFile, err := os.Create(filename)
- if err != nil {
- return err
- }
- defer outFile.Close()
-
- return c.genBashCompletion(outFile, includeDesc)
+# Homebrew on Macs have version 1.3 of bash-completion which doesn't include
+# _init_completion. This is a very minimal version of that function.
+__%[1]s_init_completion()
+{
+ COMPREPLY=()
+ _get_comp_words_by_ref "$@" cur prev words cword
}
-func (c *Command) genBashCompletion(w io.Writer, includeDesc bool) error {
- buf := new(bytes.Buffer)
- if len(c.BashCompletionFunction) > 0 {
- buf.WriteString(c.BashCompletionFunction + "\n")
- }
- genBashComp(buf, c.Name(), includeDesc)
-
- _, err := buf.WriteTo(w)
- return err
+__%[1]s_index_of_word()
+{
+ local w word=$1
+ shift
+ index=0
+ for w in "$@"; do
+ [[ $w = "$word" ]] && return
+ index=$((index+1))
+ done
+ index=-1
}
-func genBashComp(buf *bytes.Buffer, name string, includeDesc bool) {
- compCmd := ShellCompRequestCmd
- if !includeDesc {
- compCmd = ShellCompNoDescRequestCmd
- }
-
- buf.WriteString(fmt.Sprintf(`# bash completion for %-36[1]s -*- shell-script -*-
-
-__%[1]s_debug()
+__%[1]s_contains_word()
{
- if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then
- echo "$*" >> "${BASH_COMP_DEBUG_FILE}"
- fi
+ local w word=$1; shift
+ for w in "$@"; do
+ [[ $w = "$word" ]] && return
+ done
+ return 1
}
-__%[1]s_perform_completion()
+__%[1]s_handle_go_custom_completion()
{
- __%[1]s_debug
- __%[1]s_debug "========= starting completion logic =========="
- __%[1]s_debug "cur is ${cur}, words[*] is ${words[*]}, #words[@] is ${#words[@]}, cword is $cword"
-
- # The user could have moved the cursor backwards on the command-line.
- # We need to trigger completion from the $cword location, so we need
- # to truncate the command-line ($words) up to the $cword location.
- words=("${words[@]:0:$cword+1}")
- __%[1]s_debug "Truncated words[*]: ${words[*]},"
+ __%[1]s_debug "${FUNCNAME[0]}: cur is ${cur}, words[*] is ${words[*]}, #words[@] is ${#words[@]}"
local shellCompDirectiveError=%[3]d
local shellCompDirectiveNoSpace=%[4]d
local shellCompDirectiveNoFileComp=%[5]d
local shellCompDirectiveFilterFileExt=%[6]d
local shellCompDirectiveFilterDirs=%[7]d
- local shellCompDirectiveLegacyCustomComp=%[8]d
- local shellCompDirectiveLegacyCustomArgsComp=%[9]d
- local out requestComp lastParam lastChar comp directive args flagPrefix
+ local out requestComp lastParam lastChar comp directive args
# Prepare the command to request completions for the program.
# Calling ${words[0]} instead of directly %[1]s allows to handle aliases
@@ -102,24 +77,16 @@ __%[1]s_perform_completion()
lastParam=${words[$((${#words[@]}-1))]}
lastChar=${lastParam:$((${#lastParam}-1)):1}
- __%[1]s_debug "lastParam ${lastParam}, lastChar ${lastChar}"
+ __%[1]s_debug "${FUNCNAME[0]}: lastParam ${lastParam}, lastChar ${lastChar}"
if [ -z "${cur}" ] && [ "${lastChar}" != "=" ]; then
# If the last parameter is complete (there is a space following it)
# We add an extra empty parameter so we can indicate this to the go method.
- __%[1]s_debug "Adding extra empty parameter"
+ __%[1]s_debug "${FUNCNAME[0]}: Adding extra empty parameter"
requestComp="${requestComp} \"\""
fi
- # When completing a flag with an = (e.g., %[1]s -n=<TAB>)
- # bash focuses on the part after the =, so we need to remove
- # the flag part from $cur
- if [[ "${cur}" == -*=* ]]; then
- flagPrefix="${cur%%%%=*}="
- cur="${cur#*=}"
- fi
-
- __%[1]s_debug "Calling ${requestComp}"
+ __%[1]s_debug "${FUNCNAME[0]}: calling ${requestComp}"
# Use eval to handle any environment variables and such
out=$(eval "${requestComp}" 2>/dev/null)
@@ -131,23 +98,23 @@ __%[1]s_perform_completion()
# There is not directive specified
directive=0
fi
- __%[1]s_debug "The completion directive is: ${directive}"
- __%[1]s_debug "The completions are: ${out[*]}"
+ __%[1]s_debug "${FUNCNAME[0]}: the completion directive is: ${directive}"
+ __%[1]s_debug "${FUNCNAME[0]}: the completions are: ${out[*]}"
if [ $((directive & shellCompDirectiveError)) -ne 0 ]; then
# Error code. No completion.
- __%[1]s_debug "Received error from custom completion go code"
+ __%[1]s_debug "${FUNCNAME[0]}: received error from custom completion go code"
return
else
if [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ]; then
if [[ $(type -t compopt) = "builtin" ]]; then
- __%[1]s_debug "Activating no space"
+ __%[1]s_debug "${FUNCNAME[0]}: activating no space"
compopt -o nospace
fi
fi
if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then
if [[ $(type -t compopt) = "builtin" ]]; then
- __%[1]s_debug "Activating no file completion"
+ __%[1]s_debug "${FUNCNAME[0]}: activating no file completion"
compopt +o default
fi
fi
@@ -156,7 +123,6 @@ __%[1]s_perform_completion()
if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then
# File extension filtering
local fullFilter filter filteringCmd
-
# Do not use quotes around the $out variable or else newline
# characters will be kept.
for filter in ${out[*]}; do
@@ -168,173 +134,545 @@ __%[1]s_perform_completion()
$filteringCmd
elif [ $((directive & shellCompDirectiveFilterDirs)) -ne 0 ]; then
# File completion for directories only
-
+ local subDir
# Use printf to strip any trailing newline
- local subdir
subdir=$(printf "%%s" "${out[0]}")
if [ -n "$subdir" ]; then
__%[1]s_debug "Listing directories in $subdir"
- pushd "$subdir" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 || return
+ __%[1]s_handle_subdirs_in_dir_flag "$subdir"
else
__%[1]s_debug "Listing directories in ."
_filedir -d
fi
- elif [ $((directive & shellCompDirectiveLegacyCustomComp)) -ne 0 ]; then
- local cmd
- __%[1]s_debug "Legacy custom completion. Directive: $directive, cmds: ${out[*]}"
-
- # The following variables should get their value through the commands
- # we have received as completions and are parsing below.
- local last_command
- local nouns
-
- # Execute every command received
- while IFS='' read -r cmd; do
- __%[1]s_debug "About to execute: $cmd"
- eval "$cmd"
- done < <(printf "%%s\n" "${out[@]}")
-
- __%[1]s_debug "last_command: $last_command"
- __%[1]s_debug "nouns[0]: ${nouns[0]}, nouns[1]: ${nouns[1]}"
-
- if [ $((directive & shellCompDirectiveLegacyCustomArgsComp)) -ne 0 ]; then
- # We should call the global legacy custom completion function, if it is defined
- if declare -F __%[1]s_custom_func >/dev/null; then
- # Use command name qualified legacy custom func
- __%[1]s_debug "About to call: __%[1]s_custom_func"
- __%[1]s_custom_func
- elif declare -F __custom_func >/dev/null; then
- # Otherwise fall back to unqualified legacy custom func for compatibility
- __%[1]s_debug "About to call: __custom_func"
- __custom_func
- fi
- fi
else
- local tab
- tab=$(printf '\t')
- local longest=0
- # Look for the longest completion so that we can format things nicely
while IFS='' read -r comp; do
- comp=${comp%%%%$tab*}
- if ((${#comp}>longest)); then
- longest=${#comp}
+ COMPREPLY+=("$comp")
+ done < <(compgen -W "${out[*]}" -- "$cur")
+ fi
+}
+
+__%[1]s_handle_reply()
+{
+ __%[1]s_debug "${FUNCNAME[0]}"
+ local comp
+ case $cur in
+ -*)
+ if [[ $(type -t compopt) = "builtin" ]]; then
+ compopt -o nospace
+ fi
+ local allflags
+ if [ ${#must_have_one_flag[@]} -ne 0 ]; then
+ allflags=("${must_have_one_flag[@]}")
+ else
+ allflags=("${flags[*]} ${two_word_flags[*]}")
+ fi
+ while IFS='' read -r comp; do
+ COMPREPLY+=("$comp")
+ done < <(compgen -W "${allflags[*]}" -- "$cur")
+ if [[ $(type -t compopt) = "builtin" ]]; then
+ [[ "${COMPREPLY[0]}" == *= ]] || compopt +o nospace
fi
- done < <(printf "%%s\n" "${out[@]}")
- local completions=()
- while IFS='' read -r comp; do
- if [ -z "$comp" ]; then
- continue
+ # complete after --flag=abc
+ if [[ $cur == *=* ]]; then
+ if [[ $(type -t compopt) = "builtin" ]]; then
+ compopt +o nospace
+ fi
+
+ local index flag
+ flag="${cur%%=*}"
+ __%[1]s_index_of_word "${flag}" "${flags_with_completion[@]}"
+ COMPREPLY=()
+ if [[ ${index} -ge 0 ]]; then
+ PREFIX=""
+ cur="${cur#*=}"
+ ${flags_completion[${index}]}
+ if [ -n "${ZSH_VERSION}" ]; then
+ # zsh completion needs --flag= prefix
+ eval "COMPREPLY=( \"\${COMPREPLY[@]/#/${flag}=}\" )"
+ fi
+ fi
fi
+ return 0;
+ ;;
+ esac
+
+ # check if we are handling a flag with special work handling
+ local index
+ __%[1]s_index_of_word "${prev}" "${flags_with_completion[@]}"
+ if [[ ${index} -ge 0 ]]; then
+ ${flags_completion[${index}]}
+ return
+ fi
- __%[1]s_debug "Original comp: $comp"
- comp="$(__%[1]s_format_comp_descriptions "$comp" "$longest")"
- __%[1]s_debug "Final comp: $comp"
- completions+=("$comp")
- done < <(printf "%%s\n" "${out[@]}")
+ # we are parsing a flag and don't have a special handler, no completion
+ if [[ ${cur} != "${words[cword]}" ]]; then
+ return
+ fi
+ local completions
+ completions=("${commands[@]}")
+ if [[ ${#must_have_one_noun[@]} -ne 0 ]]; then
+ completions+=("${must_have_one_noun[@]}")
+ elif [[ -n "${has_completion_function}" ]]; then
+ # if a go completion function is provided, defer to that function
+ __%[1]s_handle_go_custom_completion
+ fi
+ if [[ ${#must_have_one_flag[@]} -ne 0 ]]; then
+ completions+=("${must_have_one_flag[@]}")
+ fi
+ while IFS='' read -r comp; do
+ COMPREPLY+=("$comp")
+ done < <(compgen -W "${completions[*]}" -- "$cur")
+
+ if [[ ${#COMPREPLY[@]} -eq 0 && ${#noun_aliases[@]} -gt 0 && ${#must_have_one_noun[@]} -ne 0 ]]; then
while IFS='' read -r comp; do
- # Although this script should only be used for bash
- # there may be programs that still convert the bash
- # script into a zsh one. To continue supporting those
- # programs, we do this single adaptation for zsh
- if [ -n "${ZSH_VERSION}" ]; then
- # zsh completion needs --flag= prefix
- COMPREPLY+=("$flagPrefix$comp")
- else
- COMPREPLY+=("$comp")
- fi
- done < <(compgen -W "${completions[*]}" -- "$cur")
-
- # If there is a single completion left, remove the description text
- if [ ${#COMPREPLY[*]} -eq 1 ]; then
- __%[1]s_debug "COMPREPLY[0]: ${COMPREPLY[0]}"
- comp="${COMPREPLY[0]%%%% *}"
- __%[1]s_debug "Removed description from single completion, which is now: ${comp}"
- COMPREPLY=()
COMPREPLY+=("$comp")
+ done < <(compgen -W "${noun_aliases[*]}" -- "$cur")
+ fi
+
+ if [[ ${#COMPREPLY[@]} -eq 0 ]]; then
+ if declare -F __%[1]s_custom_func >/dev/null; then
+ # try command name qualified custom func
+ __%[1]s_custom_func
+ else
+ # otherwise fall back to unqualified for compatibility
+ declare -F __custom_func >/dev/null && __custom_func
+ fi
+ fi
+
+ # available in bash-completion >= 2, not always present on macOS
+ if declare -F __ltrim_colon_completions >/dev/null; then
+ __ltrim_colon_completions "$cur"
+ fi
+
+ # If there is only 1 completion and it is a flag with an = it will be completed
+ # but we don't want a space after the =
+ if [[ "${#COMPREPLY[@]}" -eq "1" ]] && [[ $(type -t compopt) = "builtin" ]] && [[ "${COMPREPLY[0]}" == --*= ]]; then
+ compopt -o nospace
+ fi
+}
+
+# The arguments should be in the form "ext1|ext2|extn"
+__%[1]s_handle_filename_extension_flag()
+{
+ local ext="$1"
+ _filedir "@(${ext})"
+}
+
+__%[1]s_handle_subdirs_in_dir_flag()
+{
+ local dir="$1"
+ pushd "${dir}" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 || return
+}
+
+__%[1]s_handle_flag()
+{
+ __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}"
+
+ # if a command required a flag, and we found it, unset must_have_one_flag()
+ local flagname=${words[c]}
+ local flagvalue
+ # if the word contained an =
+ if [[ ${words[c]} == *"="* ]]; then
+ flagvalue=${flagname#*=} # take in as flagvalue after the =
+ flagname=${flagname%%=*} # strip everything after the =
+ flagname="${flagname}=" # but put the = back
+ fi
+ __%[1]s_debug "${FUNCNAME[0]}: looking for ${flagname}"
+ if __%[1]s_contains_word "${flagname}" "${must_have_one_flag[@]}"; then
+ must_have_one_flag=()
+ fi
+
+ # if you set a flag which only applies to this command, don't show subcommands
+ if __%[1]s_contains_word "${flagname}" "${local_nonpersistent_flags[@]}"; then
+ commands=()
+ fi
+
+ # keep flag value with flagname as flaghash
+ # flaghash variable is an associative array which is only supported in bash > 3.
+ if [[ -z "${BASH_VERSION}" || "${BASH_VERSINFO[0]}" -gt 3 ]]; then
+ if [ -n "${flagvalue}" ] ; then
+ flaghash[${flagname}]=${flagvalue}
+ elif [ -n "${words[ $((c+1)) ]}" ] ; then
+ flaghash[${flagname}]=${words[ $((c+1)) ]}
+ else
+ flaghash[${flagname}]="true" # pad "true" for bool flag
+ fi
+ fi
+
+ # skip the argument to a two word flag
+ if [[ ${words[c]} != *"="* ]] && __%[1]s_contains_word "${words[c]}" "${two_word_flags[@]}"; then
+ __%[1]s_debug "${FUNCNAME[0]}: found a flag ${words[c]}, skip the next argument"
+ c=$((c+1))
+ # if we are looking for a flags value, don't show commands
+ if [[ $c -eq $cword ]]; then
+ commands=()
fi
fi
- __%[1]s_handle_special_char "$cur" :
- __%[1]s_handle_special_char "$cur" =
+ c=$((c+1))
+
}
-__%[1]s_handle_special_char()
+__%[1]s_handle_noun()
{
- local comp="$1"
- local char=$2
- if [[ "$comp" == *${char}* && "$COMP_WORDBREAKS" == *${char}* ]]; then
- local word=${comp%%"${comp##*${char}}"}
- local idx=${#COMPREPLY[*]}
- while [[ $((--idx)) -ge 0 ]]; do
- COMPREPLY[$idx]=${COMPREPLY[$idx]#"$word"}
- done
+ __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}"
+
+ if __%[1]s_contains_word "${words[c]}" "${must_have_one_noun[@]}"; then
+ must_have_one_noun=()
+ elif __%[1]s_contains_word "${words[c]}" "${noun_aliases[@]}"; then
+ must_have_one_noun=()
fi
+
+ nouns+=("${words[c]}")
+ c=$((c+1))
}
-__%[1]s_format_comp_descriptions()
+__%[1]s_handle_command()
{
- local tab
- tab=$(printf '\t')
- local comp="$1"
- local longest=$2
-
- # Properly format the description string which follows a tab character if there is one
- if [[ "$comp" == *$tab* ]]; then
- desc=${comp#*$tab}
- comp=${comp%%%%$tab*}
-
- # $COLUMNS stores the current shell width.
- # Remove an extra 4 because we add 2 spaces and 2 parentheses.
- maxdesclength=$(( COLUMNS - longest - 4 ))
-
- # Make sure we can fit a description of at least 8 characters
- # if we are to align the descriptions.
- if [[ $maxdesclength -gt 8 ]]; then
- # Add the proper number of spaces to align the descriptions
- for ((i = ${#comp} ; i < longest ; i++)); do
- comp+=" "
- done
+ __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}"
+
+ local next_command
+ if [[ -n ${last_command} ]]; then
+ next_command="_${last_command}_${words[c]//:/__}"
+ else
+ if [[ $c -eq 0 ]]; then
+ next_command="_%[1]s_root_command"
else
- # Don't pad the descriptions so we can fit more text after the completion
- maxdesclength=$(( COLUMNS - ${#comp} - 4 ))
+ next_command="_${words[c]//:/__}"
fi
+ fi
+ c=$((c+1))
+ __%[1]s_debug "${FUNCNAME[0]}: looking for ${next_command}"
+ declare -F "$next_command" >/dev/null && $next_command
+}
- # If there is enough space for any description text,
- # truncate the descriptions that are too long for the shell width
- if [ $maxdesclength -gt 0 ]; then
- if [ ${#desc} -gt $maxdesclength ]; then
- desc=${desc:0:$(( maxdesclength - 1 ))}
- desc+="…"
- fi
- comp+=" ($desc)"
+__%[1]s_handle_word()
+{
+ if [[ $c -ge $cword ]]; then
+ __%[1]s_handle_reply
+ return
+ fi
+ __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}"
+ if [[ "${words[c]}" == -* ]]; then
+ __%[1]s_handle_flag
+ elif __%[1]s_contains_word "${words[c]}" "${commands[@]}"; then
+ __%[1]s_handle_command
+ elif [[ $c -eq 0 ]]; then
+ __%[1]s_handle_command
+ elif __%[1]s_contains_word "${words[c]}" "${command_aliases[@]}"; then
+ # aliashash variable is an associative array which is only supported in bash > 3.
+ if [[ -z "${BASH_VERSION}" || "${BASH_VERSINFO[0]}" -gt 3 ]]; then
+ words[c]=${aliashash[${words[c]}]}
+ __%[1]s_handle_command
+ else
+ __%[1]s_handle_noun
fi
+ else
+ __%[1]s_handle_noun
fi
+ __%[1]s_handle_word
+}
- # Must use printf to escape all special characters
- printf "%%q" "${comp}"
+`, name, ShellCompNoDescRequestCmd,
+ ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
+ ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs))
}
-__start_%[1]s()
-{
+func writePostscript(buf *bytes.Buffer, name string) {
+ name = strings.Replace(name, ":", "__", -1)
+ buf.WriteString(fmt.Sprintf("__start_%s()\n", name))
+ buf.WriteString(fmt.Sprintf(`{
local cur prev words cword
+ declare -A flaghash 2>/dev/null || :
+ declare -A aliashash 2>/dev/null || :
+ if declare -F _init_completion >/dev/null 2>&1; then
+ _init_completion -s || return
+ else
+ __%[1]s_init_completion -n "=" || return
+ fi
- COMPREPLY=()
- _get_comp_words_by_ref -n "=:" cur prev words cword
-
- __%[1]s_perform_completion
+ local c=0
+ local flags=()
+ local two_word_flags=()
+ local local_nonpersistent_flags=()
+ local flags_with_completion=()
+ local flags_completion=()
+ local commands=("%[1]s")
+ local must_have_one_flag=()
+ local must_have_one_noun=()
+ local has_completion_function
+ local last_command
+ local nouns=()
+
+ __%[1]s_handle_word
}
-if [[ $(type -t compopt) = "builtin" ]]; then
- complete -o default -F __start_%[1]s %[1]s
+`, name))
+ buf.WriteString(fmt.Sprintf(`if [[ $(type -t compopt) = "builtin" ]]; then
+ complete -o default -F __start_%s %s
else
- complete -o default -o nospace -F __start_%[1]s %[1]s
+ complete -o default -o nospace -F __start_%s %s
fi
-# ex: ts=4 sw=4 et filetype=sh
-`, name, compCmd,
- ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
- ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs,
- shellCompDirectiveLegacyCustomComp, shellCompDirectiveLegacyCustomArgsComp))
+`, name, name, name, name))
+ buf.WriteString("# ex: ts=4 sw=4 et filetype=sh\n")
+}
+
+func writeCommands(buf *bytes.Buffer, cmd *Command) {
+ buf.WriteString(" commands=()\n")
+ for _, c := range cmd.Commands() {
+ if !c.IsAvailableCommand() && c != cmd.helpCommand {
+ continue
+ }
+ buf.WriteString(fmt.Sprintf(" commands+=(%q)\n", c.Name()))
+ writeCmdAliases(buf, c)
+ }
+ buf.WriteString("\n")
+}
+
+func writeFlagHandler(buf *bytes.Buffer, name string, annotations map[string][]string, cmd *Command) {
+ for key, value := range annotations {
+ switch key {
+ case BashCompFilenameExt:
+ buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name))
+
+ var ext string
+ if len(value) > 0 {
+ ext = fmt.Sprintf("__%s_handle_filename_extension_flag ", cmd.Root().Name()) + strings.Join(value, "|")
+ } else {
+ ext = "_filedir"
+ }
+ buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", ext))
+ case BashCompCustom:
+ buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name))
+ if len(value) > 0 {
+ handlers := strings.Join(value, "; ")
+ buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", handlers))
+ } else {
+ buf.WriteString(" flags_completion+=(:)\n")
+ }
+ case BashCompSubdirsInDir:
+ buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name))
+
+ var ext string
+ if len(value) == 1 {
+ ext = fmt.Sprintf("__%s_handle_subdirs_in_dir_flag ", cmd.Root().Name()) + value[0]
+ } else {
+ ext = "_filedir -d"
+ }
+ buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", ext))
+ }
+ }
+}
+
+func writeShortFlag(buf *bytes.Buffer, flag *pflag.Flag, cmd *Command) {
+ name := flag.Shorthand
+ format := " "
+ if len(flag.NoOptDefVal) == 0 {
+ format += "two_word_"
+ }
+ format += "flags+=(\"-%s\")\n"
+ buf.WriteString(fmt.Sprintf(format, name))
+ writeFlagHandler(buf, "-"+name, flag.Annotations, cmd)
+}
+
+func writeFlag(buf *bytes.Buffer, flag *pflag.Flag, cmd *Command) {
+ name := flag.Name
+ format := " flags+=(\"--%s"
+ if len(flag.NoOptDefVal) == 0 {
+ format += "="
+ }
+ format += "\")\n"
+ buf.WriteString(fmt.Sprintf(format, name))
+ if len(flag.NoOptDefVal) == 0 {
+ format = " two_word_flags+=(\"--%s\")\n"
+ buf.WriteString(fmt.Sprintf(format, name))
+ }
+ writeFlagHandler(buf, "--"+name, flag.Annotations, cmd)
+}
+
+func writeLocalNonPersistentFlag(buf *bytes.Buffer, flag *pflag.Flag) {
+ name := flag.Name
+ format := " local_nonpersistent_flags+=(\"--%[1]s\")\n"
+ if len(flag.NoOptDefVal) == 0 {
+ format += " local_nonpersistent_flags+=(\"--%[1]s=\")\n"
+ }
+ buf.WriteString(fmt.Sprintf(format, name))
+ if len(flag.Shorthand) > 0 {
+ buf.WriteString(fmt.Sprintf(" local_nonpersistent_flags+=(\"-%s\")\n", flag.Shorthand))
+ }
+}
+
+// Setup annotations for go completions for registered flags
+func prepareCustomAnnotationsForFlags(cmd *Command) {
+ for flag := range flagCompletionFunctions {
+ // Make sure the completion script calls the __*_go_custom_completion function for
+ // every registered flag. We need to do this here (and not when the flag was registered
+ // for completion) so that we can know the root command name for the prefix
+ // of __<prefix>_go_custom_completion
+ if flag.Annotations == nil {
+ flag.Annotations = map[string][]string{}
+ }
+ flag.Annotations[BashCompCustom] = []string{fmt.Sprintf("__%[1]s_handle_go_custom_completion", cmd.Root().Name())}
+ }
+}
+
+func writeFlags(buf *bytes.Buffer, cmd *Command) {
+ prepareCustomAnnotationsForFlags(cmd)
+ buf.WriteString(` flags=()
+ two_word_flags=()
+ local_nonpersistent_flags=()
+ flags_with_completion=()
+ flags_completion=()
+
+`)
+ localNonPersistentFlags := cmd.LocalNonPersistentFlags()
+ cmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) {
+ if nonCompletableFlag(flag) {
+ return
+ }
+ writeFlag(buf, flag, cmd)
+ if len(flag.Shorthand) > 0 {
+ writeShortFlag(buf, flag, cmd)
+ }
+ // localNonPersistentFlags are used to stop the completion of subcommands when one is set
+ // if TraverseChildren is true we should allow to complete subcommands
+ if localNonPersistentFlags.Lookup(flag.Name) != nil && !cmd.Root().TraverseChildren {
+ writeLocalNonPersistentFlag(buf, flag)
+ }
+ })
+ cmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) {
+ if nonCompletableFlag(flag) {
+ return
+ }
+ writeFlag(buf, flag, cmd)
+ if len(flag.Shorthand) > 0 {
+ writeShortFlag(buf, flag, cmd)
+ }
+ })
+
+ buf.WriteString("\n")
+}
+
+func writeRequiredFlag(buf *bytes.Buffer, cmd *Command) {
+ buf.WriteString(" must_have_one_flag=()\n")
+ flags := cmd.NonInheritedFlags()
+ flags.VisitAll(func(flag *pflag.Flag) {
+ if nonCompletableFlag(flag) {
+ return
+ }
+ for key := range flag.Annotations {
+ switch key {
+ case BashCompOneRequiredFlag:
+ format := " must_have_one_flag+=(\"--%s"
+ if flag.Value.Type() != "bool" {
+ format += "="
+ }
+ format += "\")\n"
+ buf.WriteString(fmt.Sprintf(format, flag.Name))
+
+ if len(flag.Shorthand) > 0 {
+ buf.WriteString(fmt.Sprintf(" must_have_one_flag+=(\"-%s\")\n", flag.Shorthand))
+ }
+ }
+ }
+ })
+}
+
+func writeRequiredNouns(buf *bytes.Buffer, cmd *Command) {
+ buf.WriteString(" must_have_one_noun=()\n")
+ sort.Sort(sort.StringSlice(cmd.ValidArgs))
+ for _, value := range cmd.ValidArgs {
+ // Remove any description that may be included following a tab character.
+ // Descriptions are not supported by bash completion.
+ value = strings.Split(value, "\t")[0]
+ buf.WriteString(fmt.Sprintf(" must_have_one_noun+=(%q)\n", value))
+ }
+ if cmd.ValidArgsFunction != nil {
+ buf.WriteString(" has_completion_function=1\n")
+ }
+}
+
+func writeCmdAliases(buf *bytes.Buffer, cmd *Command) {
+ if len(cmd.Aliases) == 0 {
+ return
+ }
+
+ sort.Sort(sort.StringSlice(cmd.Aliases))
+
+ buf.WriteString(fmt.Sprint(` if [[ -z "${BASH_VERSION}" || "${BASH_VERSINFO[0]}" -gt 3 ]]; then`, "\n"))
+ for _, value := range cmd.Aliases {
+ buf.WriteString(fmt.Sprintf(" command_aliases+=(%q)\n", value))
+ buf.WriteString(fmt.Sprintf(" aliashash[%q]=%q\n", value, cmd.Name()))
+ }
+ buf.WriteString(` fi`)
+ buf.WriteString("\n")
+}
+func writeArgAliases(buf *bytes.Buffer, cmd *Command) {
+ buf.WriteString(" noun_aliases=()\n")
+ sort.Sort(sort.StringSlice(cmd.ArgAliases))
+ for _, value := range cmd.ArgAliases {
+ buf.WriteString(fmt.Sprintf(" noun_aliases+=(%q)\n", value))
+ }
+}
+
+func gen(buf *bytes.Buffer, cmd *Command) {
+ for _, c := range cmd.Commands() {
+ if !c.IsAvailableCommand() && c != cmd.helpCommand {
+ continue
+ }
+ gen(buf, c)
+ }
+ commandName := cmd.CommandPath()
+ commandName = strings.Replace(commandName, " ", "_", -1)
+ commandName = strings.Replace(commandName, ":", "__", -1)
+
+ if cmd.Root() == cmd {
+ buf.WriteString(fmt.Sprintf("_%s_root_command()\n{\n", commandName))
+ } else {
+ buf.WriteString(fmt.Sprintf("_%s()\n{\n", commandName))
+ }
+
+ buf.WriteString(fmt.Sprintf(" last_command=%q\n", commandName))
+ buf.WriteString("\n")
+ buf.WriteString(" command_aliases=()\n")
+ buf.WriteString("\n")
+
+ writeCommands(buf, cmd)
+ writeFlags(buf, cmd)
+ writeRequiredFlag(buf, cmd)
+ writeRequiredNouns(buf, cmd)
+ writeArgAliases(buf, cmd)
+ buf.WriteString("}\n\n")
+}
+
+// GenBashCompletion generates bash completion file and writes to the passed writer.
+func (c *Command) GenBashCompletion(w io.Writer) error {
+ buf := new(bytes.Buffer)
+ writePreamble(buf, c.Name())
+ if len(c.BashCompletionFunction) > 0 {
+ buf.WriteString(c.BashCompletionFunction + "\n")
+ }
+ gen(buf, c)
+ writePostscript(buf, c.Name())
+
+ _, err := buf.WriteTo(w)
+ return err
+}
+
+func nonCompletableFlag(flag *pflag.Flag) bool {
+ return flag.Hidden || len(flag.Deprecated) > 0
+}
+
+// GenBashCompletionFile generates bash completion file.
+func (c *Command) GenBashCompletionFile(filename string) error {
+ outFile, err := os.Create(filename)
+ if err != nil {
+ return err
+ }
+ defer outFile.Close()
+
+ return c.GenBashCompletion(outFile)
}
diff --git a/vendor/github.com/spf13/cobra/custom_completions.go b/vendor/github.com/spf13/cobra/custom_completions.go
index e2c68ae1e..f9e88e081 100644
--- a/vendor/github.com/spf13/cobra/custom_completions.go
+++ b/vendor/github.com/spf13/cobra/custom_completions.go
@@ -51,11 +51,6 @@ const (
// obtain the same behavior but only for flags.
ShellCompDirectiveFilterDirs
- // For internal use only.
- // Used to maintain backwards-compatibility with the legacy bash custom completions.
- shellCompDirectiveLegacyCustomComp
- shellCompDirectiveLegacyCustomArgsComp
-
// ===========================================================================
// All directives using iota should be above this one.
@@ -99,12 +94,6 @@ func (d ShellCompDirective) string() string {
if d&ShellCompDirectiveFilterDirs != 0 {
directives = append(directives, "ShellCompDirectiveFilterDirs")
}
- if d&shellCompDirectiveLegacyCustomComp != 0 {
- directives = append(directives, "shellCompDirectiveLegacyCustomComp")
- }
- if d&shellCompDirectiveLegacyCustomArgsComp != 0 {
- directives = append(directives, "shellCompDirectiveLegacyCustomArgsComp")
- }
if len(directives) == 0 {
directives = append(directives, "ShellCompDirectiveDefault")
}
@@ -160,6 +149,10 @@ func (c *Command) initCompleteCmd(args []string) {
fmt.Fprintln(finalCmd.OutOrStdout(), comp)
}
+ if directive >= shellCompDirectiveMaxValue {
+ directive = ShellCompDirectiveDefault
+ }
+
// As the last printout, print the completion directive for the completion script to parse.
// The directive integer must be that last character following a single colon (:).
// The completion script expects :<directive>
@@ -369,10 +362,6 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
var comps []string
comps, directive = completionFn(finalCmd, finalArgs, toComplete)
completions = append(completions, comps...)
- } else {
- // If there is no Go custom completion defined, check for legacy bash
- // custom completion to preserve backwards-compatibility
- completions, directive = checkLegacyCustomCompletion(finalCmd, finalArgs, flag, completions, directive)
}
return finalCmd, completions, directive, nil
@@ -453,16 +442,7 @@ func checkIfFlagCompletion(finalCmd *Command, args []string, lastArg string) (*p
if len(lastArg) > 0 && lastArg[0] == '-' {
if index := strings.Index(lastArg, "="); index >= 0 {
// Flag with an =
- if strings.HasPrefix(lastArg[:index], "--") {
- // Flag has full name
- flagName = lastArg[2:index]
- } else {
- // Flag is shorthand
- // We have to get the last shorthand flag name
- // e.g. `-asd` => d to provide the correct completion
- // https://github.com/spf13/cobra/issues/1257
- flagName = lastArg[index-1 : index]
- }
+ flagName = strings.TrimLeft(lastArg[:index], "-")
lastArg = lastArg[index+1:]
flagWithEqual = true
} else {
@@ -479,16 +459,8 @@ func checkIfFlagCompletion(finalCmd *Command, args []string, lastArg string) (*p
// If the flag contains an = it means it has already been fully processed,
// so we don't need to deal with it here.
if index := strings.Index(prevArg, "="); index < 0 {
- if strings.HasPrefix(prevArg, "--") {
- // Flag has full name
- flagName = prevArg[2:]
- } else {
- // Flag is shorthand
- // We have to get the last shorthand flag name
- // e.g. `-asd` => d to provide the correct completion
- // https://github.com/spf13/cobra/issues/1257
- flagName = prevArg[len(prevArg)-1:]
- }
+ flagName = strings.TrimLeft(prevArg, "-")
+
// Remove the uncompleted flag or else there could be an error created
// for an invalid value for that flag
trimmedArgs = args[:len(args)-1]
@@ -541,65 +513,6 @@ func findFlag(cmd *Command, name string) *pflag.Flag {
return cmd.Flag(name)
}
-func nonCompletableFlag(flag *pflag.Flag) bool {
- return flag.Hidden || len(flag.Deprecated) > 0
-}
-
-// This function checks if legacy bash custom completion should be performed and if so,
-// it provides the shell script with the necessary information.
-func checkLegacyCustomCompletion(cmd *Command, args []string, flag *pflag.Flag, completions []string, directive ShellCompDirective) ([]string, ShellCompDirective) {
- // Check if any legacy custom completion is defined for the program
- if len(cmd.Root().BashCompletionFunction) > 0 {
- // Legacy custom completion is only triggered if no other completions were found.
- if len(completions) == 0 {
- if flag != nil {
- // For legacy custom flag completion, we must let the script know the bash
- // functions it should call based on the content of the annotation BashCompCustom.
- if values, present := flag.Annotations[BashCompCustom]; present {
- if len(values) > 0 {
- handlers := strings.Join(values, "; ")
- // We send the commands to set the shell variables that are needed
- // for legacy custom completions followed by the functions to call
- // to perform the actual flag completion
- completions = append(prepareLegacyCustomCompletionVars(cmd, args), handlers)
- directive = directive | shellCompDirectiveLegacyCustomComp
- }
- }
- } else {
- // Check if the legacy custom_func is defined.
- // This check will work for both "__custom_func" and "__<program>_custom_func".
- // This could happen if the program defined some functions for legacy flag completion
- // but not the legacy custom_func.
- if strings.Contains(cmd.Root().BashCompletionFunction, "_custom_func") {
- // For legacy args completion, the script already knows what to call
- // so we only need to tell it the commands to set the shell variables needed
- completions = prepareLegacyCustomCompletionVars(cmd, args)
- directive = directive | shellCompDirectiveLegacyCustomComp | shellCompDirectiveLegacyCustomArgsComp
- }
- }
- }
- }
- return completions, directive
-}
-
-// The original bash completion script had some shell variables that are used by legacy bash
-// custom completions. Let's set those variables to allow those legacy custom completions
-// to continue working.
-func prepareLegacyCustomCompletionVars(cmd *Command, args []string) []string {
- var compVarCmds []string
-
- // "last_command" variable
- commandName := cmd.CommandPath()
- commandName = strings.Replace(commandName, " ", "_", -1)
- commandName = strings.Replace(commandName, ":", "__", -1)
- compVarCmds = append(compVarCmds, fmt.Sprintf("last_command=%s", commandName))
-
- // "nouns" array variable
- compVarCmds = append(compVarCmds, fmt.Sprintf("nouns=(%s)", strings.Join(args, " ")))
-
- return compVarCmds
-}
-
// CompDebug prints the specified string to the same file as where the
// completion script prints its logs.
// Note that completion printouts should never be on stdout as they would
diff --git a/vendor/github.com/spf13/cobra/fish_completions.go b/vendor/github.com/spf13/cobra/fish_completions.go
index aeaef0087..eaae9bca8 100644
--- a/vendor/github.com/spf13/cobra/fish_completions.go
+++ b/vendor/github.com/spf13/cobra/fish_completions.go
@@ -28,9 +28,9 @@ function __%[1]s_debug
end
function __%[1]s_perform_completion
- __%[1]s_debug "Starting __%[1]s_perform_completion"
+ __%[1]s_debug "Starting __%[1]s_perform_completion with: $argv"
- set args (string split -- " " (commandline -c))
+ set args (string split -- " " "$argv")
set lastArg "$args[-1]"
__%[1]s_debug "args: $args"
@@ -71,22 +71,31 @@ function __%[1]s_perform_completion
printf "%%s\n" "$directiveLine"
end
-# This function does two things:
-# - Obtain the completions and store them in the global __%[1]s_comp_results
-# - Return false if file completion should be performed
+# This function does three things:
+# 1- Obtain the completions and store them in the global __%[1]s_comp_results
+# 2- Set the __%[1]s_comp_do_file_comp flag if file completion should be performed
+# and unset it otherwise
+# 3- Return true if the completion results are not empty
function __%[1]s_prepare_completions
- __%[1]s_debug ""
- __%[1]s_debug "========= starting completion logic =========="
-
# Start fresh
+ set --erase __%[1]s_comp_do_file_comp
set --erase __%[1]s_comp_results
- set results (__%[1]s_perform_completion)
+ # Check if the command-line is already provided. This is useful for testing.
+ if not set --query __%[1]s_comp_commandLine
+ # Use the -c flag to allow for completion in the middle of the line
+ set __%[1]s_comp_commandLine (commandline -c)
+ end
+ __%[1]s_debug "commandLine is: $__%[1]s_comp_commandLine"
+
+ set results (__%[1]s_perform_completion "$__%[1]s_comp_commandLine")
+ set --erase __%[1]s_comp_commandLine
__%[1]s_debug "Completion results: $results"
if test -z "$results"
__%[1]s_debug "No completion, probably due to a failure"
# Might as well do file completion, in case it helps
+ set --global __%[1]s_comp_do_file_comp 1
return 1
end
@@ -101,8 +110,6 @@ function __%[1]s_prepare_completions
set shellCompDirectiveNoFileComp %[6]d
set shellCompDirectiveFilterFileExt %[7]d
set shellCompDirectiveFilterDirs %[8]d
- set shellCompDirectiveLegacyCustomComp %[9]d
- set shellCompDirectiveLegacyCustomArgsComp %[10]d
if test -z "$directive"
set directive 0
@@ -112,14 +119,6 @@ function __%[1]s_prepare_completions
if test $compErr -eq 1
__%[1]s_debug "Received error directive: aborting."
# Might as well do file completion, in case it helps
- return 1
- end
-
- set legacyCustom (math (math --scale 0 $directive / $shellCompDirectiveLegacyCustomComp) %% 2)
- set legacyCustomArgs (math (math --scale 0 $directive / $shellCompDirectiveLegacyCustomArgsComp) %% 2)
- if test $legacyCustom -eq 1; or test $legacyCustomArgs -eq 1
- __%[1]s_debug "Legacy bash custom completion not applicable to fish"
- # Do full file completion instead
set --global __%[1]s_comp_do_file_comp 1
return 1
end
@@ -129,6 +128,7 @@ function __%[1]s_prepare_completions
if test $filefilter -eq 1; or test $dirfilter -eq 1
__%[1]s_debug "File extension filtering or directory filtering not supported"
# Do full file completion instead
+ set --global __%[1]s_comp_do_file_comp 1
return 1
end
@@ -137,51 +137,27 @@ function __%[1]s_prepare_completions
__%[1]s_debug "nospace: $nospace, nofiles: $nofiles"
- # If we want to prevent a space, or if file completion is NOT disabled,
- # we need to count the number of valid completions.
- # To do so, we will filter on prefix as the completions we have received
- # may not already be filtered so as to allow fish to match on different
- # criteria than prefix.
- if test $nospace -ne 0; or test $nofiles -eq 0
- set prefix (commandline -t)
- __%[1]s_debug "prefix: $prefix"
-
- set completions
- for comp in $__%[1]s_comp_results
- if test (string match -e -r "^$prefix" "$comp")
- set -a completions $comp
- end
- end
- set --global __%[1]s_comp_results $completions
- __%[1]s_debug "Filtered completions are: $__%[1]s_comp_results"
-
- # Important not to quote the variable for count to work
- set numComps (count $__%[1]s_comp_results)
- __%[1]s_debug "numComps: $numComps"
-
- if test $numComps -eq 1; and test $nospace -ne 0
- # To support the "nospace" directive we trick the shell
- # by outputting an extra, longer completion.
- # We must first split on \t to get rid of the descriptions because
- # the extra character we add to the fake second completion must be
- # before the description. We don't need descriptions anyway since
- # there is only a single real completion which the shell will expand
- # immediately.
- __%[1]s_debug "Adding second completion to perform nospace directive"
- set split (string split --max 1 \t $__%[1]s_comp_results[1])
- set --global __%[1]s_comp_results $split[1] $split[1].
- __%[1]s_debug "Completions are now: $__%[1]s_comp_results"
- end
-
- if test $numComps -eq 0; and test $nofiles -eq 0
- # To be consistent with bash and zsh, we only trigger file
- # completion when there are no other completions
- __%[1]s_debug "Requesting file completion"
- return 1
- end
+ # Important not to quote the variable for count to work
+ set numComps (count $__%[1]s_comp_results)
+ __%[1]s_debug "numComps: $numComps"
+
+ if test $numComps -eq 1; and test $nospace -ne 0
+ # To support the "nospace" directive we trick the shell
+ # by outputting an extra, longer completion.
+ __%[1]s_debug "Adding second completion to perform nospace directive"
+ set --append __%[1]s_comp_results $__%[1]s_comp_results[1].
end
- return 0
+ if test $numComps -eq 0; and test $nofiles -eq 0
+ __%[1]s_debug "Requesting file completion"
+ set --global __%[1]s_comp_do_file_comp 1
+ end
+
+ # If we don't want file completion, we must return true even if there
+ # are no completions found. This is because fish will perform the last
+ # completion command, even if its condition is false, if no other
+ # completion command was triggered
+ return (not set --query __%[1]s_comp_do_file_comp)
end
# Since Fish completions are only loaded once the user triggers them, we trigger them ourselves
@@ -194,14 +170,21 @@ complete --do-complete "%[2]s " > /dev/null 2>&1
# Remove any pre-existing completions for the program since we will be handling all of them.
complete -c %[2]s -e
-# The call to __%[1]s_prepare_completions will setup __%[1]s_comp_results
-# which provides the program's completion choices.
+# The order in which the below two lines are defined is very important so that __%[1]s_prepare_completions
+# is called first. It is __%[1]s_prepare_completions that sets up the __%[1]s_comp_do_file_comp variable.
+#
+# This completion will be run second as complete commands are added FILO.
+# It triggers file completion choices when __%[1]s_comp_do_file_comp is set.
+complete -c %[2]s -n 'set --query __%[1]s_comp_do_file_comp'
+
+# This completion will be run first as complete commands are added FILO.
+# The call to __%[1]s_prepare_completions will setup both __%[1]s_comp_results and __%[1]s_comp_do_file_comp.
+# It provides the program's completion choices.
complete -c %[2]s -n '__%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results'
`, nameForVar, name, compCmd,
ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
- ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs,
- shellCompDirectiveLegacyCustomComp, shellCompDirectiveLegacyCustomArgsComp))
+ ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs))
}
// GenFishCompletion generates fish completion file and writes to the passed writer.
diff --git a/vendor/github.com/spf13/cobra/zsh_completions.go b/vendor/github.com/spf13/cobra/zsh_completions.go
index ef290e2eb..92a70394a 100644
--- a/vendor/github.com/spf13/cobra/zsh_completions.go
+++ b/vendor/github.com/spf13/cobra/zsh_completions.go
@@ -94,10 +94,8 @@ _%[1]s()
local shellCompDirectiveNoFileComp=%[5]d
local shellCompDirectiveFilterFileExt=%[6]d
local shellCompDirectiveFilterDirs=%[7]d
- local shellCompDirectiveLegacyCustomComp=%[8]d
- local shellCompDirectiveLegacyCustomArgsComp=%[9]d
- local lastParam lastChar flagPrefix requestComp out directive comp lastComp noSpace
+ local lastParam lastChar flagPrefix requestComp out directive compCount comp lastComp
local -a completions
__%[1]s_debug "\n========= starting completion logic =========="
@@ -165,6 +163,7 @@ _%[1]s()
return
fi
+ compCount=0
while IFS='\n' read -r comp; do
if [ -n "$comp" ]; then
# If requested, completions are returned with a description.
@@ -176,17 +175,13 @@ _%[1]s()
local tab=$(printf '\t')
comp=${comp//$tab/:}
+ ((compCount++))
__%[1]s_debug "Adding completion: ${comp}"
completions+=${comp}
lastComp=$comp
fi
done < <(printf "%%s\n" "${out[@]}")
- if [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ]; then
- __%[1]s_debug "Activating nospace."
- noSpace="-S ''"
- fi
-
if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then
# File extension filtering
local filteringCmd
@@ -213,40 +208,25 @@ _%[1]s()
__%[1]s_debug "Listing directories in ."
fi
- local result
_arguments '*:dirname:_files -/'" ${flagPrefix}"
- result=$?
if [ -n "$subdir" ]; then
popd >/dev/null 2>&1
fi
- return $result
- else
- __%[1]s_debug "Calling _describe"
- if eval _describe "completions" completions $flagPrefix $noSpace; then
- __%[1]s_debug "_describe found some completions"
-
- # Return the success of having called _describe
- return 0
+ elif [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ] && [ ${compCount} -eq 1 ]; then
+ __%[1]s_debug "Activating nospace."
+ # We can use compadd here as there is no description when
+ # there is only one completion.
+ compadd -S '' "${lastComp}"
+ elif [ ${compCount} -eq 0 ]; then
+ if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then
+ __%[1]s_debug "deactivating file completion"
else
- __%[1]s_debug "_describe did not find completions."
- __%[1]s_debug "Checking if we should do file completion."
- if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then
- __%[1]s_debug "deactivating file completion"
-
- # We must return an error code here to let zsh know that there were no
- # completions found by _describe; this is what will trigger other
- # matching algorithms to attempt to find completions.
- # For example zsh can match letters in the middle of words.
- return 1
- else
- # Perform file completion
- __%[1]s_debug "Activating file completion"
-
- # We must return the result of this command, so it must be the
- # last command, or else we must store its result to return it.
- _arguments '*:filename:_files'" ${flagPrefix}"
- fi
+ # Perform file completion
+ __%[1]s_debug "activating file completion"
+ _arguments '*:filename:_files'" ${flagPrefix}"
fi
+ else
+ _describe "completions" completions $(echo $flagPrefix)
fi
}
@@ -256,6 +236,5 @@ if [ "$funcstack[1]" = "_%[1]s" ]; then
fi
`, name, compCmd,
ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
- ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs,
- shellCompDirectiveLegacyCustomComp, shellCompDirectiveLegacyCustomArgsComp))
+ ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs))
}