providers: remove hypersh provider (#524)
Hyper.sh was shutdown on Jan 16, 2019. https://blog.hyper.sh/close_hyper_sh.html Signed-off-by: Paulo Pires <pjpires@gmail.com>
This commit is contained in:
201
vendor/github.com/cloudfoundry-incubator/candiedyaml/LICENSE
generated
vendored
201
vendor/github.com/cloudfoundry-incubator/candiedyaml/LICENSE
generated
vendored
@@ -1,201 +0,0 @@
|
||||
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.
|
||||
18
vendor/github.com/cloudfoundry-incubator/candiedyaml/NOTICE
generated
vendored
18
vendor/github.com/cloudfoundry-incubator/candiedyaml/NOTICE
generated
vendored
@@ -1,18 +0,0 @@
|
||||
Copyright (c) 2015-Present CloudFoundry.org Foundation, Inc. All Rights Reserved.
|
||||
|
||||
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.
|
||||
|
||||
This project may include a number of subcomponents with separate
|
||||
copyright notices and license terms. Your use of these subcomponents
|
||||
is subject to the terms and conditions of each subcomponent's license,
|
||||
as noted in the LICENSE file.
|
||||
834
vendor/github.com/cloudfoundry-incubator/candiedyaml/api.go
generated
vendored
834
vendor/github.com/cloudfoundry-incubator/candiedyaml/api.go
generated
vendored
@@ -1,834 +0,0 @@
|
||||
/*
|
||||
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 candiedyaml
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
/*
|
||||
* Create a new parser object.
|
||||
*/
|
||||
|
||||
func yaml_parser_initialize(parser *yaml_parser_t) bool {
|
||||
*parser = yaml_parser_t{
|
||||
raw_buffer: make([]byte, 0, INPUT_RAW_BUFFER_SIZE),
|
||||
buffer: make([]byte, 0, INPUT_BUFFER_SIZE),
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy a parser object.
|
||||
*/
|
||||
func yaml_parser_delete(parser *yaml_parser_t) {
|
||||
*parser = yaml_parser_t{}
|
||||
}
|
||||
|
||||
/*
|
||||
* String read handler.
|
||||
*/
|
||||
|
||||
func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (int, error) {
|
||||
if parser.input_pos == len(parser.input) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
n := copy(buffer, parser.input[parser.input_pos:])
|
||||
parser.input_pos += n
|
||||
return n, nil
|
||||
}
|
||||
|
||||
/*
|
||||
* File read handler.
|
||||
*/
|
||||
|
||||
func yaml_file_read_handler(parser *yaml_parser_t, buffer []byte) (int, error) {
|
||||
return parser.input_reader.Read(buffer)
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a string input.
|
||||
*/
|
||||
|
||||
func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) {
|
||||
if parser.read_handler != nil {
|
||||
panic("input already set")
|
||||
}
|
||||
|
||||
parser.read_handler = yaml_string_read_handler
|
||||
|
||||
parser.input = input
|
||||
parser.input_pos = 0
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a reader input
|
||||
*/
|
||||
func yaml_parser_set_input_reader(parser *yaml_parser_t, reader io.Reader) {
|
||||
if parser.read_handler != nil {
|
||||
panic("input already set")
|
||||
}
|
||||
|
||||
parser.read_handler = yaml_file_read_handler
|
||||
parser.input_reader = reader
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a generic input.
|
||||
*/
|
||||
|
||||
func yaml_parser_set_input(parser *yaml_parser_t, handler yaml_read_handler_t) {
|
||||
if parser.read_handler != nil {
|
||||
panic("input already set")
|
||||
}
|
||||
|
||||
parser.read_handler = handler
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the source encoding.
|
||||
*/
|
||||
|
||||
func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) {
|
||||
if parser.encoding != yaml_ANY_ENCODING {
|
||||
panic("encoding already set")
|
||||
}
|
||||
|
||||
parser.encoding = encoding
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new emitter object.
|
||||
*/
|
||||
|
||||
func yaml_emitter_initialize(emitter *yaml_emitter_t) {
|
||||
*emitter = yaml_emitter_t{
|
||||
buffer: make([]byte, OUTPUT_BUFFER_SIZE),
|
||||
raw_buffer: make([]byte, 0, OUTPUT_RAW_BUFFER_SIZE),
|
||||
states: make([]yaml_emitter_state_t, 0, INITIAL_STACK_SIZE),
|
||||
events: make([]yaml_event_t, 0, INITIAL_QUEUE_SIZE),
|
||||
}
|
||||
}
|
||||
|
||||
func yaml_emitter_delete(emitter *yaml_emitter_t) {
|
||||
*emitter = yaml_emitter_t{}
|
||||
}
|
||||
|
||||
/*
|
||||
* String write handler.
|
||||
*/
|
||||
|
||||
func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
|
||||
*emitter.output_buffer = append(*emitter.output_buffer, buffer...)
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
* File write handler.
|
||||
*/
|
||||
|
||||
func yaml_writer_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
|
||||
_, err := emitter.output_writer.Write(buffer)
|
||||
return err
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a string output.
|
||||
*/
|
||||
|
||||
func yaml_emitter_set_output_string(emitter *yaml_emitter_t, buffer *[]byte) {
|
||||
if emitter.write_handler != nil {
|
||||
panic("output already set")
|
||||
}
|
||||
|
||||
emitter.write_handler = yaml_string_write_handler
|
||||
emitter.output_buffer = buffer
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a file output.
|
||||
*/
|
||||
|
||||
func yaml_emitter_set_output_writer(emitter *yaml_emitter_t, w io.Writer) {
|
||||
if emitter.write_handler != nil {
|
||||
panic("output already set")
|
||||
}
|
||||
|
||||
emitter.write_handler = yaml_writer_write_handler
|
||||
emitter.output_writer = w
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a generic output handler.
|
||||
*/
|
||||
|
||||
func yaml_emitter_set_output(emitter *yaml_emitter_t, handler yaml_write_handler_t) {
|
||||
if emitter.write_handler != nil {
|
||||
panic("output already set")
|
||||
}
|
||||
|
||||
emitter.write_handler = handler
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the output encoding.
|
||||
*/
|
||||
|
||||
func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) {
|
||||
if emitter.encoding != yaml_ANY_ENCODING {
|
||||
panic("encoding already set")
|
||||
}
|
||||
|
||||
emitter.encoding = encoding
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the canonical output style.
|
||||
*/
|
||||
|
||||
func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) {
|
||||
emitter.canonical = canonical
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the indentation increment.
|
||||
*/
|
||||
|
||||
func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) {
|
||||
if indent < 2 || indent > 9 {
|
||||
indent = 2
|
||||
}
|
||||
emitter.best_indent = indent
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the preferred line width.
|
||||
*/
|
||||
|
||||
func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) {
|
||||
if width < 0 {
|
||||
width = -1
|
||||
}
|
||||
emitter.best_width = width
|
||||
}
|
||||
|
||||
/*
|
||||
* Set if unescaped non-ASCII characters are allowed.
|
||||
*/
|
||||
|
||||
func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) {
|
||||
emitter.unicode = unicode
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the preferred line break character.
|
||||
*/
|
||||
|
||||
func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) {
|
||||
emitter.line_break = line_break
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy a token object.
|
||||
*/
|
||||
|
||||
// yaml_DECLARE(void)
|
||||
// yaml_token_delete(yaml_token_t *token)
|
||||
// {
|
||||
// assert(token); /* Non-NULL token object expected. */
|
||||
//
|
||||
// switch (token.type)
|
||||
// {
|
||||
// case yaml_TAG_DIRECTIVE_TOKEN:
|
||||
// yaml_free(token.data.tag_directive.handle);
|
||||
// yaml_free(token.data.tag_directive.prefix);
|
||||
// break;
|
||||
//
|
||||
// case yaml_ALIAS_TOKEN:
|
||||
// yaml_free(token.data.alias.value);
|
||||
// break;
|
||||
//
|
||||
// case yaml_ANCHOR_TOKEN:
|
||||
// yaml_free(token.data.anchor.value);
|
||||
// break;
|
||||
//
|
||||
// case yaml_TAG_TOKEN:
|
||||
// yaml_free(token.data.tag.handle);
|
||||
// yaml_free(token.data.tag.suffix);
|
||||
// break;
|
||||
//
|
||||
// case yaml_SCALAR_TOKEN:
|
||||
// yaml_free(token.data.scalar.value);
|
||||
// break;
|
||||
//
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// memset(token, 0, sizeof(yaml_token_t));
|
||||
// }
|
||||
|
||||
/*
|
||||
* Check if a string is a valid UTF-8 sequence.
|
||||
*
|
||||
* Check 'reader.c' for more details on UTF-8 encoding.
|
||||
*/
|
||||
|
||||
// static int
|
||||
// yaml_check_utf8(yaml_char_t *start, size_t length)
|
||||
// {
|
||||
// yaml_char_t *end = start+length;
|
||||
// yaml_char_t *pointer = start;
|
||||
//
|
||||
// while (pointer < end) {
|
||||
// unsigned char octet;
|
||||
// unsigned int width;
|
||||
// unsigned int value;
|
||||
// size_t k;
|
||||
//
|
||||
// octet = pointer[0];
|
||||
// width = (octet & 0x80) == 0x00 ? 1 :
|
||||
// (octet & 0xE0) == 0xC0 ? 2 :
|
||||
// (octet & 0xF0) == 0xE0 ? 3 :
|
||||
// (octet & 0xF8) == 0xF0 ? 4 : 0;
|
||||
// value = (octet & 0x80) == 0x00 ? octet & 0x7F :
|
||||
// (octet & 0xE0) == 0xC0 ? octet & 0x1F :
|
||||
// (octet & 0xF0) == 0xE0 ? octet & 0x0F :
|
||||
// (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
|
||||
// if (!width) return 0;
|
||||
// if (pointer+width > end) return 0;
|
||||
// for (k = 1; k < width; k ++) {
|
||||
// octet = pointer[k];
|
||||
// if ((octet & 0xC0) != 0x80) return 0;
|
||||
// value = (value << 6) + (octet & 0x3F);
|
||||
// }
|
||||
// if (!((width == 1) ||
|
||||
// (width == 2 && value >= 0x80) ||
|
||||
// (width == 3 && value >= 0x800) ||
|
||||
// (width == 4 && value >= 0x10000))) return 0;
|
||||
//
|
||||
// pointer += width;
|
||||
// }
|
||||
//
|
||||
// return 1;
|
||||
// }
|
||||
|
||||
/*
|
||||
* Create STREAM-START.
|
||||
*/
|
||||
|
||||
func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) {
|
||||
*event = yaml_event_t{
|
||||
event_type: yaml_STREAM_START_EVENT,
|
||||
encoding: encoding,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create STREAM-END.
|
||||
*/
|
||||
|
||||
func yaml_stream_end_event_initialize(event *yaml_event_t) {
|
||||
*event = yaml_event_t{
|
||||
event_type: yaml_STREAM_END_EVENT,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create DOCUMENT-START.
|
||||
*/
|
||||
|
||||
func yaml_document_start_event_initialize(event *yaml_event_t,
|
||||
version_directive *yaml_version_directive_t,
|
||||
tag_directives []yaml_tag_directive_t,
|
||||
implicit bool) {
|
||||
*event = yaml_event_t{
|
||||
event_type: yaml_DOCUMENT_START_EVENT,
|
||||
version_directive: version_directive,
|
||||
tag_directives: tag_directives,
|
||||
implicit: implicit,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create DOCUMENT-END.
|
||||
*/
|
||||
|
||||
func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) {
|
||||
*event = yaml_event_t{
|
||||
event_type: yaml_DOCUMENT_END_EVENT,
|
||||
implicit: implicit,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create ALIAS.
|
||||
*/
|
||||
|
||||
func yaml_alias_event_initialize(event *yaml_event_t, anchor []byte) {
|
||||
*event = yaml_event_t{
|
||||
event_type: yaml_ALIAS_EVENT,
|
||||
anchor: anchor,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create SCALAR.
|
||||
*/
|
||||
|
||||
func yaml_scalar_event_initialize(event *yaml_event_t,
|
||||
anchor []byte, tag []byte,
|
||||
value []byte,
|
||||
plain_implicit bool, quoted_implicit bool,
|
||||
style yaml_scalar_style_t) {
|
||||
|
||||
*event = yaml_event_t{
|
||||
event_type: yaml_SCALAR_EVENT,
|
||||
anchor: anchor,
|
||||
tag: tag,
|
||||
value: value,
|
||||
implicit: plain_implicit,
|
||||
quoted_implicit: quoted_implicit,
|
||||
style: yaml_style_t(style),
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create SEQUENCE-START.
|
||||
*/
|
||||
|
||||
func yaml_sequence_start_event_initialize(event *yaml_event_t,
|
||||
anchor []byte, tag []byte, implicit bool, style yaml_sequence_style_t) {
|
||||
*event = yaml_event_t{
|
||||
event_type: yaml_SEQUENCE_START_EVENT,
|
||||
anchor: anchor,
|
||||
tag: tag,
|
||||
implicit: implicit,
|
||||
style: yaml_style_t(style),
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create SEQUENCE-END.
|
||||
*/
|
||||
|
||||
func yaml_sequence_end_event_initialize(event *yaml_event_t) {
|
||||
*event = yaml_event_t{
|
||||
event_type: yaml_SEQUENCE_END_EVENT,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create MAPPING-START.
|
||||
*/
|
||||
|
||||
func yaml_mapping_start_event_initialize(event *yaml_event_t,
|
||||
anchor []byte, tag []byte, implicit bool, style yaml_mapping_style_t) {
|
||||
*event = yaml_event_t{
|
||||
event_type: yaml_MAPPING_START_EVENT,
|
||||
anchor: anchor,
|
||||
tag: tag,
|
||||
implicit: implicit,
|
||||
style: yaml_style_t(style),
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create MAPPING-END.
|
||||
*/
|
||||
|
||||
func yaml_mapping_end_event_initialize(event *yaml_event_t) {
|
||||
*event = yaml_event_t{
|
||||
event_type: yaml_MAPPING_END_EVENT,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy an event object.
|
||||
*/
|
||||
|
||||
func yaml_event_delete(event *yaml_event_t) {
|
||||
*event = yaml_event_t{}
|
||||
}
|
||||
|
||||
// /*
|
||||
// * Create a document object.
|
||||
// */
|
||||
//
|
||||
// func yaml_document_initialize(document *yaml_document_t,
|
||||
// version_directive *yaml_version_directive_t,
|
||||
// tag_directives []yaml_tag_directive_t,
|
||||
// start_implicit, end_implicit bool) bool {
|
||||
//
|
||||
//
|
||||
// {
|
||||
// struct {
|
||||
// YAML_error_type_t error;
|
||||
// } context;
|
||||
// struct {
|
||||
// yaml_node_t *start;
|
||||
// yaml_node_t *end;
|
||||
// yaml_node_t *top;
|
||||
// } nodes = { NULL, NULL, NULL };
|
||||
// yaml_version_directive_t *version_directive_copy = NULL;
|
||||
// struct {
|
||||
// yaml_tag_directive_t *start;
|
||||
// yaml_tag_directive_t *end;
|
||||
// yaml_tag_directive_t *top;
|
||||
// } tag_directives_copy = { NULL, NULL, NULL };
|
||||
// yaml_tag_directive_t value = { NULL, NULL };
|
||||
// YAML_mark_t mark = { 0, 0, 0 };
|
||||
//
|
||||
// assert(document); /* Non-NULL document object is expected. */
|
||||
// assert((tag_directives_start && tag_directives_end) ||
|
||||
// (tag_directives_start == tag_directives_end));
|
||||
// /* Valid tag directives are expected. */
|
||||
//
|
||||
// if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error;
|
||||
//
|
||||
// if (version_directive) {
|
||||
// version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t));
|
||||
// if (!version_directive_copy) goto error;
|
||||
// version_directive_copy.major = version_directive.major;
|
||||
// version_directive_copy.minor = version_directive.minor;
|
||||
// }
|
||||
//
|
||||
// if (tag_directives_start != tag_directives_end) {
|
||||
// yaml_tag_directive_t *tag_directive;
|
||||
// if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
|
||||
// goto error;
|
||||
// for (tag_directive = tag_directives_start;
|
||||
// tag_directive != tag_directives_end; tag_directive ++) {
|
||||
// assert(tag_directive.handle);
|
||||
// assert(tag_directive.prefix);
|
||||
// if (!yaml_check_utf8(tag_directive.handle,
|
||||
// strlen((char *)tag_directive.handle)))
|
||||
// goto error;
|
||||
// if (!yaml_check_utf8(tag_directive.prefix,
|
||||
// strlen((char *)tag_directive.prefix)))
|
||||
// goto error;
|
||||
// value.handle = yaml_strdup(tag_directive.handle);
|
||||
// value.prefix = yaml_strdup(tag_directive.prefix);
|
||||
// if (!value.handle || !value.prefix) goto error;
|
||||
// if (!PUSH(&context, tag_directives_copy, value))
|
||||
// goto error;
|
||||
// value.handle = NULL;
|
||||
// value.prefix = NULL;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy,
|
||||
// tag_directives_copy.start, tag_directives_copy.top,
|
||||
// start_implicit, end_implicit, mark, mark);
|
||||
//
|
||||
// return 1;
|
||||
//
|
||||
// error:
|
||||
// STACK_DEL(&context, nodes);
|
||||
// yaml_free(version_directive_copy);
|
||||
// while (!STACK_EMPTY(&context, tag_directives_copy)) {
|
||||
// yaml_tag_directive_t value = POP(&context, tag_directives_copy);
|
||||
// yaml_free(value.handle);
|
||||
// yaml_free(value.prefix);
|
||||
// }
|
||||
// STACK_DEL(&context, tag_directives_copy);
|
||||
// yaml_free(value.handle);
|
||||
// yaml_free(value.prefix);
|
||||
//
|
||||
// return 0;
|
||||
// }
|
||||
//
|
||||
// /*
|
||||
// * Destroy a document object.
|
||||
// */
|
||||
//
|
||||
// yaml_DECLARE(void)
|
||||
// yaml_document_delete(document *yaml_document_t)
|
||||
// {
|
||||
// struct {
|
||||
// YAML_error_type_t error;
|
||||
// } context;
|
||||
// yaml_tag_directive_t *tag_directive;
|
||||
//
|
||||
// context.error = yaml_NO_ERROR; /* Eliminate a compliler warning. */
|
||||
//
|
||||
// assert(document); /* Non-NULL document object is expected. */
|
||||
//
|
||||
// while (!STACK_EMPTY(&context, document.nodes)) {
|
||||
// yaml_node_t node = POP(&context, document.nodes);
|
||||
// yaml_free(node.tag);
|
||||
// switch (node.type) {
|
||||
// case yaml_SCALAR_NODE:
|
||||
// yaml_free(node.data.scalar.value);
|
||||
// break;
|
||||
// case yaml_SEQUENCE_NODE:
|
||||
// STACK_DEL(&context, node.data.sequence.items);
|
||||
// break;
|
||||
// case yaml_MAPPING_NODE:
|
||||
// STACK_DEL(&context, node.data.mapping.pairs);
|
||||
// break;
|
||||
// default:
|
||||
// assert(0); /* Should not happen. */
|
||||
// }
|
||||
// }
|
||||
// STACK_DEL(&context, document.nodes);
|
||||
//
|
||||
// yaml_free(document.version_directive);
|
||||
// for (tag_directive = document.tag_directives.start;
|
||||
// tag_directive != document.tag_directives.end;
|
||||
// tag_directive++) {
|
||||
// yaml_free(tag_directive.handle);
|
||||
// yaml_free(tag_directive.prefix);
|
||||
// }
|
||||
// yaml_free(document.tag_directives.start);
|
||||
//
|
||||
// memset(document, 0, sizeof(yaml_document_t));
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Get a document node.
|
||||
// */
|
||||
//
|
||||
// yaml_DECLARE(yaml_node_t *)
|
||||
// yaml_document_get_node(document *yaml_document_t, int index)
|
||||
// {
|
||||
// assert(document); /* Non-NULL document object is expected. */
|
||||
//
|
||||
// if (index > 0 && document.nodes.start + index <= document.nodes.top) {
|
||||
// return document.nodes.start + index - 1;
|
||||
// }
|
||||
// return NULL;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Get the root object.
|
||||
// */
|
||||
//
|
||||
// yaml_DECLARE(yaml_node_t *)
|
||||
// yaml_document_get_root_node(document *yaml_document_t)
|
||||
// {
|
||||
// assert(document); /* Non-NULL document object is expected. */
|
||||
//
|
||||
// if (document.nodes.top != document.nodes.start) {
|
||||
// return document.nodes.start;
|
||||
// }
|
||||
// return NULL;
|
||||
// }
|
||||
//
|
||||
// /*
|
||||
// * Add a scalar node to a document.
|
||||
// */
|
||||
//
|
||||
// yaml_DECLARE(int)
|
||||
// yaml_document_add_scalar(document *yaml_document_t,
|
||||
// yaml_char_t *tag, yaml_char_t *value, int length,
|
||||
// yaml_scalar_style_t style)
|
||||
// {
|
||||
// struct {
|
||||
// YAML_error_type_t error;
|
||||
// } context;
|
||||
// YAML_mark_t mark = { 0, 0, 0 };
|
||||
// yaml_char_t *tag_copy = NULL;
|
||||
// yaml_char_t *value_copy = NULL;
|
||||
// yaml_node_t node;
|
||||
//
|
||||
// assert(document); /* Non-NULL document object is expected. */
|
||||
// assert(value); /* Non-NULL value is expected. */
|
||||
//
|
||||
// if (!tag) {
|
||||
// tag = (yaml_char_t *)yaml_DEFAULT_SCALAR_TAG;
|
||||
// }
|
||||
//
|
||||
// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
|
||||
// tag_copy = yaml_strdup(tag);
|
||||
// if (!tag_copy) goto error;
|
||||
//
|
||||
// if (length < 0) {
|
||||
// length = strlen((char *)value);
|
||||
// }
|
||||
//
|
||||
// if (!yaml_check_utf8(value, length)) goto error;
|
||||
// value_copy = yaml_malloc(length+1);
|
||||
// if (!value_copy) goto error;
|
||||
// memcpy(value_copy, value, length);
|
||||
// value_copy[length] = '\0';
|
||||
//
|
||||
// SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark);
|
||||
// if (!PUSH(&context, document.nodes, node)) goto error;
|
||||
//
|
||||
// return document.nodes.top - document.nodes.start;
|
||||
//
|
||||
// error:
|
||||
// yaml_free(tag_copy);
|
||||
// yaml_free(value_copy);
|
||||
//
|
||||
// return 0;
|
||||
// }
|
||||
//
|
||||
// /*
|
||||
// * Add a sequence node to a document.
|
||||
// */
|
||||
//
|
||||
// yaml_DECLARE(int)
|
||||
// yaml_document_add_sequence(document *yaml_document_t,
|
||||
// yaml_char_t *tag, yaml_sequence_style_t style)
|
||||
// {
|
||||
// struct {
|
||||
// YAML_error_type_t error;
|
||||
// } context;
|
||||
// YAML_mark_t mark = { 0, 0, 0 };
|
||||
// yaml_char_t *tag_copy = NULL;
|
||||
// struct {
|
||||
// yaml_node_item_t *start;
|
||||
// yaml_node_item_t *end;
|
||||
// yaml_node_item_t *top;
|
||||
// } items = { NULL, NULL, NULL };
|
||||
// yaml_node_t node;
|
||||
//
|
||||
// assert(document); /* Non-NULL document object is expected. */
|
||||
//
|
||||
// if (!tag) {
|
||||
// tag = (yaml_char_t *)yaml_DEFAULT_SEQUENCE_TAG;
|
||||
// }
|
||||
//
|
||||
// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
|
||||
// tag_copy = yaml_strdup(tag);
|
||||
// if (!tag_copy) goto error;
|
||||
//
|
||||
// if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error;
|
||||
//
|
||||
// SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end,
|
||||
// style, mark, mark);
|
||||
// if (!PUSH(&context, document.nodes, node)) goto error;
|
||||
//
|
||||
// return document.nodes.top - document.nodes.start;
|
||||
//
|
||||
// error:
|
||||
// STACK_DEL(&context, items);
|
||||
// yaml_free(tag_copy);
|
||||
//
|
||||
// return 0;
|
||||
// }
|
||||
//
|
||||
// /*
|
||||
// * Add a mapping node to a document.
|
||||
// */
|
||||
//
|
||||
// yaml_DECLARE(int)
|
||||
// yaml_document_add_mapping(document *yaml_document_t,
|
||||
// yaml_char_t *tag, yaml_mapping_style_t style)
|
||||
// {
|
||||
// struct {
|
||||
// YAML_error_type_t error;
|
||||
// } context;
|
||||
// YAML_mark_t mark = { 0, 0, 0 };
|
||||
// yaml_char_t *tag_copy = NULL;
|
||||
// struct {
|
||||
// yaml_node_pair_t *start;
|
||||
// yaml_node_pair_t *end;
|
||||
// yaml_node_pair_t *top;
|
||||
// } pairs = { NULL, NULL, NULL };
|
||||
// yaml_node_t node;
|
||||
//
|
||||
// assert(document); /* Non-NULL document object is expected. */
|
||||
//
|
||||
// if (!tag) {
|
||||
// tag = (yaml_char_t *)yaml_DEFAULT_MAPPING_TAG;
|
||||
// }
|
||||
//
|
||||
// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
|
||||
// tag_copy = yaml_strdup(tag);
|
||||
// if (!tag_copy) goto error;
|
||||
//
|
||||
// if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error;
|
||||
//
|
||||
// MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end,
|
||||
// style, mark, mark);
|
||||
// if (!PUSH(&context, document.nodes, node)) goto error;
|
||||
//
|
||||
// return document.nodes.top - document.nodes.start;
|
||||
//
|
||||
// error:
|
||||
// STACK_DEL(&context, pairs);
|
||||
// yaml_free(tag_copy);
|
||||
//
|
||||
// return 0;
|
||||
// }
|
||||
//
|
||||
// /*
|
||||
// * Append an item to a sequence node.
|
||||
// */
|
||||
//
|
||||
// yaml_DECLARE(int)
|
||||
// yaml_document_append_sequence_item(document *yaml_document_t,
|
||||
// int sequence, int item)
|
||||
// {
|
||||
// struct {
|
||||
// YAML_error_type_t error;
|
||||
// } context;
|
||||
//
|
||||
// assert(document); /* Non-NULL document is required. */
|
||||
// assert(sequence > 0
|
||||
// && document.nodes.start + sequence <= document.nodes.top);
|
||||
// /* Valid sequence id is required. */
|
||||
// assert(document.nodes.start[sequence-1].type == yaml_SEQUENCE_NODE);
|
||||
// /* A sequence node is required. */
|
||||
// assert(item > 0 && document.nodes.start + item <= document.nodes.top);
|
||||
// /* Valid item id is required. */
|
||||
//
|
||||
// if (!PUSH(&context,
|
||||
// document.nodes.start[sequence-1].data.sequence.items, item))
|
||||
// return 0;
|
||||
//
|
||||
// return 1;
|
||||
// }
|
||||
//
|
||||
// /*
|
||||
// * Append a pair of a key and a value to a mapping node.
|
||||
// */
|
||||
//
|
||||
// yaml_DECLARE(int)
|
||||
// yaml_document_append_mapping_pair(document *yaml_document_t,
|
||||
// int mapping, int key, int value)
|
||||
// {
|
||||
// struct {
|
||||
// YAML_error_type_t error;
|
||||
// } context;
|
||||
//
|
||||
// yaml_node_pair_t pair;
|
||||
//
|
||||
// assert(document); /* Non-NULL document is required. */
|
||||
// assert(mapping > 0
|
||||
// && document.nodes.start + mapping <= document.nodes.top);
|
||||
// /* Valid mapping id is required. */
|
||||
// assert(document.nodes.start[mapping-1].type == yaml_MAPPING_NODE);
|
||||
// /* A mapping node is required. */
|
||||
// assert(key > 0 && document.nodes.start + key <= document.nodes.top);
|
||||
// /* Valid key id is required. */
|
||||
// assert(value > 0 && document.nodes.start + value <= document.nodes.top);
|
||||
// /* Valid value id is required. */
|
||||
//
|
||||
// pair.key = key;
|
||||
// pair.value = value;
|
||||
//
|
||||
// if (!PUSH(&context,
|
||||
// document.nodes.start[mapping-1].data.mapping.pairs, pair))
|
||||
// return 0;
|
||||
//
|
||||
// return 1;
|
||||
// }
|
||||
//
|
||||
622
vendor/github.com/cloudfoundry-incubator/candiedyaml/decode.go
generated
vendored
622
vendor/github.com/cloudfoundry-incubator/candiedyaml/decode.go
generated
vendored
@@ -1,622 +0,0 @@
|
||||
/*
|
||||
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 candiedyaml
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Unmarshaler interface {
|
||||
UnmarshalYAML(tag string, value interface{}) error
|
||||
}
|
||||
|
||||
// A Number represents a JSON number literal.
|
||||
type Number string
|
||||
|
||||
// String returns the literal text of the number.
|
||||
func (n Number) String() string { return string(n) }
|
||||
|
||||
// Float64 returns the number as a float64.
|
||||
func (n Number) Float64() (float64, error) {
|
||||
return strconv.ParseFloat(string(n), 64)
|
||||
}
|
||||
|
||||
// Int64 returns the number as an int64.
|
||||
func (n Number) Int64() (int64, error) {
|
||||
return strconv.ParseInt(string(n), 10, 64)
|
||||
}
|
||||
|
||||
type Decoder struct {
|
||||
parser yaml_parser_t
|
||||
event yaml_event_t
|
||||
replay_events []yaml_event_t
|
||||
useNumber bool
|
||||
|
||||
anchors map[string][]yaml_event_t
|
||||
tracking_anchors [][]yaml_event_t
|
||||
}
|
||||
|
||||
type ParserError struct {
|
||||
ErrorType YAML_error_type_t
|
||||
Context string
|
||||
ContextMark YAML_mark_t
|
||||
Problem string
|
||||
ProblemMark YAML_mark_t
|
||||
}
|
||||
|
||||
func (e *ParserError) Error() string {
|
||||
return fmt.Sprintf("yaml: [%s] %s at line %d, column %d", e.Context, e.Problem, e.ProblemMark.line+1, e.ProblemMark.column+1)
|
||||
}
|
||||
|
||||
type UnexpectedEventError struct {
|
||||
Value string
|
||||
EventType yaml_event_type_t
|
||||
At YAML_mark_t
|
||||
}
|
||||
|
||||
func (e *UnexpectedEventError) Error() string {
|
||||
return fmt.Sprintf("yaml: Unexpect event [%d]: '%s' at line %d, column %d", e.EventType, e.Value, e.At.line+1, e.At.column+1)
|
||||
}
|
||||
|
||||
func recovery(err *error) {
|
||||
if r := recover(); r != nil {
|
||||
if _, ok := r.(runtime.Error); ok {
|
||||
panic(r)
|
||||
}
|
||||
|
||||
var tmpError error
|
||||
switch r := r.(type) {
|
||||
case error:
|
||||
tmpError = r
|
||||
case string:
|
||||
tmpError = errors.New(r)
|
||||
default:
|
||||
tmpError = errors.New("Unknown panic: " + reflect.ValueOf(r).String())
|
||||
}
|
||||
|
||||
*err = tmpError
|
||||
}
|
||||
}
|
||||
|
||||
func Unmarshal(data []byte, v interface{}) error {
|
||||
d := NewDecoder(bytes.NewBuffer(data))
|
||||
return d.Decode(v)
|
||||
}
|
||||
|
||||
func NewDecoder(r io.Reader) *Decoder {
|
||||
d := &Decoder{
|
||||
anchors: make(map[string][]yaml_event_t),
|
||||
tracking_anchors: make([][]yaml_event_t, 1),
|
||||
}
|
||||
yaml_parser_initialize(&d.parser)
|
||||
yaml_parser_set_input_reader(&d.parser, r)
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *Decoder) Decode(v interface{}) (err error) {
|
||||
defer recovery(&err)
|
||||
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.Kind() != reflect.Ptr || rv.IsNil() {
|
||||
return fmt.Errorf("Expected a pointer or nil but was a %s at %s", rv.String(), d.event.start_mark)
|
||||
}
|
||||
|
||||
if d.event.event_type == yaml_NO_EVENT {
|
||||
d.nextEvent()
|
||||
|
||||
if d.event.event_type != yaml_STREAM_START_EVENT {
|
||||
return errors.New("Invalid stream")
|
||||
}
|
||||
|
||||
d.nextEvent()
|
||||
}
|
||||
|
||||
d.document(rv)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) UseNumber() { d.useNumber = true }
|
||||
|
||||
func (d *Decoder) error(err error) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
func (d *Decoder) nextEvent() {
|
||||
if d.event.event_type == yaml_STREAM_END_EVENT {
|
||||
d.error(errors.New("The stream is closed"))
|
||||
}
|
||||
|
||||
if d.replay_events != nil {
|
||||
d.event = d.replay_events[0]
|
||||
if len(d.replay_events) == 1 {
|
||||
d.replay_events = nil
|
||||
} else {
|
||||
d.replay_events = d.replay_events[1:]
|
||||
}
|
||||
} else {
|
||||
if !yaml_parser_parse(&d.parser, &d.event) {
|
||||
yaml_event_delete(&d.event)
|
||||
|
||||
d.error(&ParserError{
|
||||
ErrorType: d.parser.error,
|
||||
Context: d.parser.context,
|
||||
ContextMark: d.parser.context_mark,
|
||||
Problem: d.parser.problem,
|
||||
ProblemMark: d.parser.problem_mark,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
last := len(d.tracking_anchors)
|
||||
// skip aliases when tracking an anchor
|
||||
if last > 0 && d.event.event_type != yaml_ALIAS_EVENT {
|
||||
d.tracking_anchors[last-1] = append(d.tracking_anchors[last-1], d.event)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Decoder) document(rv reflect.Value) {
|
||||
if d.event.event_type != yaml_DOCUMENT_START_EVENT {
|
||||
d.error(fmt.Errorf("Expected document start at %s", d.event.start_mark))
|
||||
}
|
||||
|
||||
d.nextEvent()
|
||||
d.parse(rv)
|
||||
|
||||
if d.event.event_type != yaml_DOCUMENT_END_EVENT {
|
||||
d.error(fmt.Errorf("Expected document end at %s", d.event.start_mark))
|
||||
}
|
||||
|
||||
d.nextEvent()
|
||||
}
|
||||
|
||||
func (d *Decoder) parse(rv reflect.Value) {
|
||||
if !rv.IsValid() {
|
||||
// skip ahead since we cannot store
|
||||
d.valueInterface()
|
||||
return
|
||||
}
|
||||
|
||||
anchor := string(d.event.anchor)
|
||||
switch d.event.event_type {
|
||||
case yaml_SEQUENCE_START_EVENT:
|
||||
d.begin_anchor(anchor)
|
||||
d.sequence(rv)
|
||||
d.end_anchor(anchor)
|
||||
case yaml_MAPPING_START_EVENT:
|
||||
d.begin_anchor(anchor)
|
||||
d.mapping(rv)
|
||||
d.end_anchor(anchor)
|
||||
case yaml_SCALAR_EVENT:
|
||||
d.begin_anchor(anchor)
|
||||
d.scalar(rv)
|
||||
d.end_anchor(anchor)
|
||||
case yaml_ALIAS_EVENT:
|
||||
d.alias(rv)
|
||||
case yaml_DOCUMENT_END_EVENT:
|
||||
default:
|
||||
d.error(&UnexpectedEventError{
|
||||
Value: string(d.event.value),
|
||||
EventType: d.event.event_type,
|
||||
At: d.event.start_mark,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Decoder) begin_anchor(anchor string) {
|
||||
if anchor != "" {
|
||||
events := []yaml_event_t{d.event}
|
||||
d.tracking_anchors = append(d.tracking_anchors, events)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Decoder) end_anchor(anchor string) {
|
||||
if anchor != "" {
|
||||
events := d.tracking_anchors[len(d.tracking_anchors)-1]
|
||||
d.tracking_anchors = d.tracking_anchors[0 : len(d.tracking_anchors)-1]
|
||||
// remove the anchor, replaying events shouldn't have anchors
|
||||
events[0].anchor = nil
|
||||
// we went one too many, remove the extra event
|
||||
events = events[:len(events)-1]
|
||||
// if nested, append to all the other anchors
|
||||
for i, e := range d.tracking_anchors {
|
||||
d.tracking_anchors[i] = append(e, events...)
|
||||
}
|
||||
d.anchors[anchor] = events
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Decoder) indirect(v reflect.Value, decodingNull bool) (Unmarshaler, reflect.Value) {
|
||||
// If v is a named type and is addressable,
|
||||
// start with its address, so that if the type has pointer methods,
|
||||
// we find them.
|
||||
if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
|
||||
v = v.Addr()
|
||||
}
|
||||
for {
|
||||
// Load value from interface, but only if the result will be
|
||||
// usefully addressable.
|
||||
if v.Kind() == reflect.Interface && !v.IsNil() {
|
||||
e := v.Elem()
|
||||
if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
|
||||
v = e
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if v.Kind() != reflect.Ptr {
|
||||
break
|
||||
}
|
||||
|
||||
if v.Elem().Kind() != reflect.Ptr && decodingNull && v.CanSet() {
|
||||
break
|
||||
}
|
||||
|
||||
if v.IsNil() {
|
||||
v.Set(reflect.New(v.Type().Elem()))
|
||||
}
|
||||
|
||||
if v.Type().NumMethod() > 0 {
|
||||
if u, ok := v.Interface().(Unmarshaler); ok {
|
||||
var temp interface{}
|
||||
return u, reflect.ValueOf(&temp)
|
||||
}
|
||||
}
|
||||
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
return nil, v
|
||||
}
|
||||
|
||||
func (d *Decoder) sequence(v reflect.Value) {
|
||||
if d.event.event_type != yaml_SEQUENCE_START_EVENT {
|
||||
d.error(fmt.Errorf("Expected sequence start at %s", d.event.start_mark))
|
||||
}
|
||||
|
||||
u, pv := d.indirect(v, false)
|
||||
if u != nil {
|
||||
defer func() {
|
||||
if err := u.UnmarshalYAML(yaml_SEQ_TAG, pv.Interface()); err != nil {
|
||||
d.error(err)
|
||||
}
|
||||
}()
|
||||
_, pv = d.indirect(pv, false)
|
||||
}
|
||||
|
||||
v = pv
|
||||
|
||||
// Check type of target.
|
||||
switch v.Kind() {
|
||||
case reflect.Interface:
|
||||
if v.NumMethod() == 0 {
|
||||
// Decoding into nil interface? Switch to non-reflect code.
|
||||
v.Set(reflect.ValueOf(d.sequenceInterface()))
|
||||
return
|
||||
}
|
||||
// Otherwise it's invalid.
|
||||
fallthrough
|
||||
default:
|
||||
d.error(fmt.Errorf("Expected an array, slice or interface{} but was a %s at %s", v, d.event.start_mark))
|
||||
case reflect.Array:
|
||||
case reflect.Slice:
|
||||
break
|
||||
}
|
||||
|
||||
d.nextEvent()
|
||||
|
||||
i := 0
|
||||
done:
|
||||
for {
|
||||
switch d.event.event_type {
|
||||
case yaml_SEQUENCE_END_EVENT, yaml_DOCUMENT_END_EVENT:
|
||||
break done
|
||||
}
|
||||
|
||||
// Get element of array, growing if necessary.
|
||||
if v.Kind() == reflect.Slice {
|
||||
// Grow slice if necessary
|
||||
if i >= v.Cap() {
|
||||
newcap := v.Cap() + v.Cap()/2
|
||||
if newcap < 4 {
|
||||
newcap = 4
|
||||
}
|
||||
newv := reflect.MakeSlice(v.Type(), v.Len(), newcap)
|
||||
reflect.Copy(newv, v)
|
||||
v.Set(newv)
|
||||
}
|
||||
if i >= v.Len() {
|
||||
v.SetLen(i + 1)
|
||||
}
|
||||
}
|
||||
|
||||
if i < v.Len() {
|
||||
// Decode into element.
|
||||
d.parse(v.Index(i))
|
||||
} else {
|
||||
// Ran out of fixed array: skip.
|
||||
d.parse(reflect.Value{})
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
if i < v.Len() {
|
||||
if v.Kind() == reflect.Array {
|
||||
// Array. Zero the rest.
|
||||
z := reflect.Zero(v.Type().Elem())
|
||||
for ; i < v.Len(); i++ {
|
||||
v.Index(i).Set(z)
|
||||
}
|
||||
} else {
|
||||
v.SetLen(i)
|
||||
}
|
||||
}
|
||||
if i == 0 && v.Kind() == reflect.Slice {
|
||||
v.Set(reflect.MakeSlice(v.Type(), 0, 0))
|
||||
}
|
||||
|
||||
if d.event.event_type != yaml_DOCUMENT_END_EVENT {
|
||||
d.nextEvent()
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Decoder) mapping(v reflect.Value) {
|
||||
u, pv := d.indirect(v, false)
|
||||
if u != nil {
|
||||
defer func() {
|
||||
if err := u.UnmarshalYAML(yaml_MAP_TAG, pv.Interface()); err != nil {
|
||||
d.error(err)
|
||||
}
|
||||
}()
|
||||
_, pv = d.indirect(pv, false)
|
||||
}
|
||||
v = pv
|
||||
|
||||
// Decoding into nil interface? Switch to non-reflect code.
|
||||
if v.Kind() == reflect.Interface && v.NumMethod() == 0 {
|
||||
v.Set(reflect.ValueOf(d.mappingInterface()))
|
||||
return
|
||||
}
|
||||
|
||||
// Check type of target: struct or map[X]Y
|
||||
switch v.Kind() {
|
||||
case reflect.Struct:
|
||||
d.mappingStruct(v)
|
||||
return
|
||||
case reflect.Map:
|
||||
default:
|
||||
d.error(fmt.Errorf("Expected a struct or map but was a %s at %s ", v, d.event.start_mark))
|
||||
}
|
||||
|
||||
mapt := v.Type()
|
||||
if v.IsNil() {
|
||||
v.Set(reflect.MakeMap(mapt))
|
||||
}
|
||||
|
||||
d.nextEvent()
|
||||
|
||||
keyt := mapt.Key()
|
||||
mapElemt := mapt.Elem()
|
||||
|
||||
var mapElem reflect.Value
|
||||
done:
|
||||
for {
|
||||
switch d.event.event_type {
|
||||
case yaml_MAPPING_END_EVENT:
|
||||
break done
|
||||
case yaml_DOCUMENT_END_EVENT:
|
||||
return
|
||||
}
|
||||
|
||||
key := reflect.New(keyt)
|
||||
d.parse(key.Elem())
|
||||
|
||||
if !mapElem.IsValid() {
|
||||
mapElem = reflect.New(mapElemt).Elem()
|
||||
} else {
|
||||
mapElem.Set(reflect.Zero(mapElemt))
|
||||
}
|
||||
|
||||
d.parse(mapElem)
|
||||
|
||||
v.SetMapIndex(key.Elem(), mapElem)
|
||||
}
|
||||
|
||||
d.nextEvent()
|
||||
}
|
||||
|
||||
func (d *Decoder) mappingStruct(v reflect.Value) {
|
||||
|
||||
structt := v.Type()
|
||||
fields := cachedTypeFields(structt)
|
||||
|
||||
d.nextEvent()
|
||||
|
||||
done:
|
||||
for {
|
||||
switch d.event.event_type {
|
||||
case yaml_MAPPING_END_EVENT:
|
||||
break done
|
||||
case yaml_DOCUMENT_END_EVENT:
|
||||
return
|
||||
}
|
||||
|
||||
key := ""
|
||||
d.parse(reflect.ValueOf(&key))
|
||||
|
||||
// Figure out field corresponding to key.
|
||||
var subv reflect.Value
|
||||
|
||||
var f *field
|
||||
for i := range fields {
|
||||
ff := &fields[i]
|
||||
if ff.name == key {
|
||||
f = ff
|
||||
break
|
||||
}
|
||||
|
||||
if f == nil && strings.EqualFold(ff.name, key) {
|
||||
f = ff
|
||||
}
|
||||
}
|
||||
|
||||
if f != nil {
|
||||
subv = v
|
||||
for _, i := range f.index {
|
||||
if subv.Kind() == reflect.Ptr {
|
||||
if subv.IsNil() {
|
||||
subv.Set(reflect.New(subv.Type().Elem()))
|
||||
}
|
||||
subv = subv.Elem()
|
||||
}
|
||||
subv = subv.Field(i)
|
||||
}
|
||||
}
|
||||
d.parse(subv)
|
||||
}
|
||||
|
||||
d.nextEvent()
|
||||
}
|
||||
|
||||
func (d *Decoder) scalar(v reflect.Value) {
|
||||
val := string(d.event.value)
|
||||
wantptr := null_values[val]
|
||||
|
||||
u, pv := d.indirect(v, wantptr)
|
||||
|
||||
var tag string
|
||||
if u != nil {
|
||||
defer func() {
|
||||
if err := u.UnmarshalYAML(tag, pv.Interface()); err != nil {
|
||||
d.error(err)
|
||||
}
|
||||
}()
|
||||
|
||||
_, pv = d.indirect(pv, wantptr)
|
||||
}
|
||||
v = pv
|
||||
|
||||
var err error
|
||||
tag, err = resolve(d.event, v, d.useNumber)
|
||||
if err != nil {
|
||||
d.error(err)
|
||||
}
|
||||
|
||||
d.nextEvent()
|
||||
}
|
||||
|
||||
func (d *Decoder) alias(rv reflect.Value) {
|
||||
val, ok := d.anchors[string(d.event.anchor)]
|
||||
if !ok {
|
||||
d.error(fmt.Errorf("missing anchor: '%s' at %s", d.event.anchor, d.event.start_mark))
|
||||
}
|
||||
|
||||
d.replay_events = val
|
||||
d.nextEvent()
|
||||
d.parse(rv)
|
||||
}
|
||||
|
||||
func (d *Decoder) valueInterface() interface{} {
|
||||
var v interface{}
|
||||
|
||||
anchor := string(d.event.anchor)
|
||||
switch d.event.event_type {
|
||||
case yaml_SEQUENCE_START_EVENT:
|
||||
d.begin_anchor(anchor)
|
||||
v = d.sequenceInterface()
|
||||
case yaml_MAPPING_START_EVENT:
|
||||
d.begin_anchor(anchor)
|
||||
v = d.mappingInterface()
|
||||
case yaml_SCALAR_EVENT:
|
||||
d.begin_anchor(anchor)
|
||||
v = d.scalarInterface()
|
||||
case yaml_ALIAS_EVENT:
|
||||
rv := reflect.ValueOf(&v)
|
||||
d.alias(rv)
|
||||
return v
|
||||
case yaml_DOCUMENT_END_EVENT:
|
||||
d.error(&UnexpectedEventError{
|
||||
Value: string(d.event.value),
|
||||
EventType: d.event.event_type,
|
||||
At: d.event.start_mark,
|
||||
})
|
||||
|
||||
}
|
||||
d.end_anchor(anchor)
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
func (d *Decoder) scalarInterface() interface{} {
|
||||
_, v := resolveInterface(d.event, d.useNumber)
|
||||
|
||||
d.nextEvent()
|
||||
return v
|
||||
}
|
||||
|
||||
// sequenceInterface is like sequence but returns []interface{}.
|
||||
func (d *Decoder) sequenceInterface() []interface{} {
|
||||
var v = make([]interface{}, 0)
|
||||
|
||||
d.nextEvent()
|
||||
|
||||
done:
|
||||
for {
|
||||
switch d.event.event_type {
|
||||
case yaml_SEQUENCE_END_EVENT, yaml_DOCUMENT_END_EVENT:
|
||||
break done
|
||||
}
|
||||
|
||||
v = append(v, d.valueInterface())
|
||||
}
|
||||
|
||||
if d.event.event_type != yaml_DOCUMENT_END_EVENT {
|
||||
d.nextEvent()
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
// mappingInterface is like mapping but returns map[interface{}]interface{}.
|
||||
func (d *Decoder) mappingInterface() map[interface{}]interface{} {
|
||||
m := make(map[interface{}]interface{})
|
||||
|
||||
d.nextEvent()
|
||||
|
||||
done:
|
||||
for {
|
||||
switch d.event.event_type {
|
||||
case yaml_MAPPING_END_EVENT, yaml_DOCUMENT_END_EVENT:
|
||||
break done
|
||||
}
|
||||
|
||||
key := d.valueInterface()
|
||||
|
||||
// Read value.
|
||||
m[key] = d.valueInterface()
|
||||
}
|
||||
|
||||
if d.event.event_type != yaml_DOCUMENT_END_EVENT {
|
||||
d.nextEvent()
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
2072
vendor/github.com/cloudfoundry-incubator/candiedyaml/emitter.go
generated
vendored
2072
vendor/github.com/cloudfoundry-incubator/candiedyaml/emitter.go
generated
vendored
File diff suppressed because it is too large
Load Diff
395
vendor/github.com/cloudfoundry-incubator/candiedyaml/encode.go
generated
vendored
395
vendor/github.com/cloudfoundry-incubator/candiedyaml/encode.go
generated
vendored
@@ -1,395 +0,0 @@
|
||||
/*
|
||||
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 candiedyaml
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"io"
|
||||
"math"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
timeTimeType = reflect.TypeOf(time.Time{})
|
||||
marshalerType = reflect.TypeOf(new(Marshaler)).Elem()
|
||||
numberType = reflect.TypeOf(Number(""))
|
||||
nonPrintable = regexp.MustCompile("[^\t\n\r\u0020-\u007E\u0085\u00A0-\uD7FF\uE000-\uFFFD]")
|
||||
multiline = regexp.MustCompile("\n|\u0085|\u2028|\u2029")
|
||||
|
||||
shortTags = map[string]string{
|
||||
yaml_NULL_TAG: "!!null",
|
||||
yaml_BOOL_TAG: "!!bool",
|
||||
yaml_STR_TAG: "!!str",
|
||||
yaml_INT_TAG: "!!int",
|
||||
yaml_FLOAT_TAG: "!!float",
|
||||
yaml_TIMESTAMP_TAG: "!!timestamp",
|
||||
yaml_SEQ_TAG: "!!seq",
|
||||
yaml_MAP_TAG: "!!map",
|
||||
yaml_BINARY_TAG: "!!binary",
|
||||
}
|
||||
)
|
||||
|
||||
type Marshaler interface {
|
||||
MarshalYAML() (tag string, value interface{}, err error)
|
||||
}
|
||||
|
||||
// An Encoder writes JSON objects to an output stream.
|
||||
type Encoder struct {
|
||||
w io.Writer
|
||||
emitter yaml_emitter_t
|
||||
event yaml_event_t
|
||||
flow bool
|
||||
err error
|
||||
}
|
||||
|
||||
func Marshal(v interface{}) ([]byte, error) {
|
||||
b := bytes.Buffer{}
|
||||
e := NewEncoder(&b)
|
||||
err := e.Encode(v)
|
||||
return b.Bytes(), err
|
||||
}
|
||||
|
||||
// NewEncoder returns a new encoder that writes to w.
|
||||
func NewEncoder(w io.Writer) *Encoder {
|
||||
e := &Encoder{w: w}
|
||||
yaml_emitter_initialize(&e.emitter)
|
||||
yaml_emitter_set_output_writer(&e.emitter, e.w)
|
||||
yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING)
|
||||
e.emit()
|
||||
yaml_document_start_event_initialize(&e.event, nil, nil, true)
|
||||
e.emit()
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Encoder) Encode(v interface{}) (err error) {
|
||||
defer recovery(&err)
|
||||
|
||||
if e.err != nil {
|
||||
return e.err
|
||||
}
|
||||
|
||||
e.marshal("", reflect.ValueOf(v), true)
|
||||
|
||||
yaml_document_end_event_initialize(&e.event, true)
|
||||
e.emit()
|
||||
e.emitter.open_ended = false
|
||||
yaml_stream_end_event_initialize(&e.event)
|
||||
e.emit()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Encoder) emit() {
|
||||
if !yaml_emitter_emit(&e.emitter, &e.event) {
|
||||
panic("bad emit")
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Encoder) marshal(tag string, v reflect.Value, allowAddr bool) {
|
||||
vt := v.Type()
|
||||
|
||||
if vt.Implements(marshalerType) {
|
||||
e.emitMarshaler(tag, v)
|
||||
return
|
||||
}
|
||||
|
||||
if vt.Kind() != reflect.Ptr && allowAddr {
|
||||
if reflect.PtrTo(vt).Implements(marshalerType) {
|
||||
e.emitAddrMarshaler(tag, v)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
switch v.Kind() {
|
||||
case reflect.Interface:
|
||||
if v.IsNil() {
|
||||
e.emitNil()
|
||||
} else {
|
||||
e.marshal(tag, v.Elem(), allowAddr)
|
||||
}
|
||||
case reflect.Map:
|
||||
e.emitMap(tag, v)
|
||||
case reflect.Ptr:
|
||||
if v.IsNil() {
|
||||
e.emitNil()
|
||||
} else {
|
||||
e.marshal(tag, v.Elem(), true)
|
||||
}
|
||||
case reflect.Struct:
|
||||
e.emitStruct(tag, v)
|
||||
case reflect.Slice:
|
||||
e.emitSlice(tag, v)
|
||||
case reflect.String:
|
||||
e.emitString(tag, v)
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
e.emitInt(tag, v)
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
e.emitUint(tag, v)
|
||||
case reflect.Float32, reflect.Float64:
|
||||
e.emitFloat(tag, v)
|
||||
case reflect.Bool:
|
||||
e.emitBool(tag, v)
|
||||
default:
|
||||
panic("Can't marshal type yet: " + v.Type().String())
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Encoder) emitMap(tag string, v reflect.Value) {
|
||||
e.mapping(tag, func() {
|
||||
var keys stringValues = v.MapKeys()
|
||||
sort.Sort(keys)
|
||||
for _, k := range keys {
|
||||
e.marshal("", k, true)
|
||||
e.marshal("", v.MapIndex(k), true)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Encoder) emitStruct(tag string, v reflect.Value) {
|
||||
if v.Type() == timeTimeType {
|
||||
e.emitTime(tag, v)
|
||||
return
|
||||
}
|
||||
|
||||
fields := cachedTypeFields(v.Type())
|
||||
|
||||
e.mapping(tag, func() {
|
||||
for _, f := range fields {
|
||||
fv := fieldByIndex(v, f.index)
|
||||
if !fv.IsValid() || f.omitEmpty && isEmptyValue(fv) {
|
||||
continue
|
||||
}
|
||||
|
||||
e.marshal("", reflect.ValueOf(f.name), true)
|
||||
e.flow = f.flow
|
||||
e.marshal("", fv, true)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Encoder) emitTime(tag string, v reflect.Value) {
|
||||
t := v.Interface().(time.Time)
|
||||
bytes, _ := t.MarshalText()
|
||||
e.emitScalar(string(bytes), "", tag, yaml_PLAIN_SCALAR_STYLE)
|
||||
}
|
||||
|
||||
func isEmptyValue(v reflect.Value) bool {
|
||||
switch v.Kind() {
|
||||
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
|
||||
return v.Len() == 0
|
||||
case reflect.Bool:
|
||||
return !v.Bool()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return v.Int() == 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return v.Uint() == 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float() == 0
|
||||
case reflect.Interface, reflect.Ptr:
|
||||
return v.IsNil()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (e *Encoder) mapping(tag string, f func()) {
|
||||
implicit := tag == ""
|
||||
style := yaml_BLOCK_MAPPING_STYLE
|
||||
if e.flow {
|
||||
e.flow = false
|
||||
style = yaml_FLOW_MAPPING_STYLE
|
||||
}
|
||||
yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)
|
||||
e.emit()
|
||||
|
||||
f()
|
||||
|
||||
yaml_mapping_end_event_initialize(&e.event)
|
||||
e.emit()
|
||||
}
|
||||
|
||||
func (e *Encoder) emitSlice(tag string, v reflect.Value) {
|
||||
if v.Type() == byteSliceType {
|
||||
e.emitBase64(tag, v)
|
||||
return
|
||||
}
|
||||
|
||||
implicit := tag == ""
|
||||
style := yaml_BLOCK_SEQUENCE_STYLE
|
||||
if e.flow {
|
||||
e.flow = false
|
||||
style = yaml_FLOW_SEQUENCE_STYLE
|
||||
}
|
||||
yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)
|
||||
e.emit()
|
||||
|
||||
n := v.Len()
|
||||
for i := 0; i < n; i++ {
|
||||
e.marshal("", v.Index(i), true)
|
||||
}
|
||||
|
||||
yaml_sequence_end_event_initialize(&e.event)
|
||||
e.emit()
|
||||
}
|
||||
|
||||
func (e *Encoder) emitBase64(tag string, v reflect.Value) {
|
||||
if v.IsNil() {
|
||||
e.emitNil()
|
||||
return
|
||||
}
|
||||
|
||||
s := v.Bytes()
|
||||
|
||||
dst := make([]byte, base64.StdEncoding.EncodedLen(len(s)))
|
||||
|
||||
base64.StdEncoding.Encode(dst, s)
|
||||
e.emitScalar(string(dst), "", yaml_BINARY_TAG, yaml_DOUBLE_QUOTED_SCALAR_STYLE)
|
||||
}
|
||||
|
||||
func (e *Encoder) emitString(tag string, v reflect.Value) {
|
||||
var style yaml_scalar_style_t
|
||||
s := v.String()
|
||||
|
||||
if nonPrintable.MatchString(s) {
|
||||
e.emitBase64(tag, v)
|
||||
return
|
||||
}
|
||||
|
||||
if v.Type() == numberType {
|
||||
style = yaml_PLAIN_SCALAR_STYLE
|
||||
} else {
|
||||
event := yaml_event_t{
|
||||
implicit: true,
|
||||
value: []byte(s),
|
||||
}
|
||||
|
||||
rtag, _ := resolveInterface(event, false)
|
||||
if tag == "" && rtag != yaml_STR_TAG {
|
||||
style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
|
||||
} else if multiline.MatchString(s) {
|
||||
style = yaml_LITERAL_SCALAR_STYLE
|
||||
} else {
|
||||
style = yaml_PLAIN_SCALAR_STYLE
|
||||
}
|
||||
}
|
||||
|
||||
e.emitScalar(s, "", tag, style)
|
||||
}
|
||||
|
||||
func (e *Encoder) emitBool(tag string, v reflect.Value) {
|
||||
s := strconv.FormatBool(v.Bool())
|
||||
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
|
||||
}
|
||||
|
||||
func (e *Encoder) emitInt(tag string, v reflect.Value) {
|
||||
s := strconv.FormatInt(v.Int(), 10)
|
||||
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
|
||||
}
|
||||
|
||||
func (e *Encoder) emitUint(tag string, v reflect.Value) {
|
||||
s := strconv.FormatUint(v.Uint(), 10)
|
||||
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
|
||||
}
|
||||
|
||||
func (e *Encoder) emitFloat(tag string, v reflect.Value) {
|
||||
f := v.Float()
|
||||
|
||||
var s string
|
||||
switch {
|
||||
case math.IsNaN(f):
|
||||
s = ".nan"
|
||||
case math.IsInf(f, 1):
|
||||
s = "+.inf"
|
||||
case math.IsInf(f, -1):
|
||||
s = "-.inf"
|
||||
default:
|
||||
s = strconv.FormatFloat(f, 'g', -1, v.Type().Bits())
|
||||
}
|
||||
|
||||
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
|
||||
}
|
||||
|
||||
func (e *Encoder) emitNil() {
|
||||
e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE)
|
||||
}
|
||||
|
||||
func (e *Encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t) {
|
||||
implicit := tag == ""
|
||||
if !implicit {
|
||||
style = yaml_PLAIN_SCALAR_STYLE
|
||||
}
|
||||
|
||||
stag := shortTags[tag]
|
||||
if stag == "" {
|
||||
stag = tag
|
||||
}
|
||||
|
||||
yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(stag), []byte(value), implicit, implicit, style)
|
||||
e.emit()
|
||||
}
|
||||
|
||||
func (e *Encoder) emitMarshaler(tag string, v reflect.Value) {
|
||||
if v.Kind() == reflect.Ptr && v.IsNil() {
|
||||
e.emitNil()
|
||||
return
|
||||
}
|
||||
|
||||
m := v.Interface().(Marshaler)
|
||||
if m == nil {
|
||||
e.emitNil()
|
||||
return
|
||||
}
|
||||
t, val, err := m.MarshalYAML()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if val == nil {
|
||||
e.emitNil()
|
||||
return
|
||||
}
|
||||
|
||||
e.marshal(t, reflect.ValueOf(val), false)
|
||||
}
|
||||
|
||||
func (e *Encoder) emitAddrMarshaler(tag string, v reflect.Value) {
|
||||
if !v.CanAddr() {
|
||||
e.marshal(tag, v, false)
|
||||
return
|
||||
}
|
||||
|
||||
va := v.Addr()
|
||||
if va.IsNil() {
|
||||
e.emitNil()
|
||||
return
|
||||
}
|
||||
|
||||
m := v.Interface().(Marshaler)
|
||||
t, val, err := m.MarshalYAML()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if val == nil {
|
||||
e.emitNil()
|
||||
return
|
||||
}
|
||||
|
||||
e.marshal(t, reflect.ValueOf(val), false)
|
||||
}
|
||||
1230
vendor/github.com/cloudfoundry-incubator/candiedyaml/parser.go
generated
vendored
1230
vendor/github.com/cloudfoundry-incubator/candiedyaml/parser.go
generated
vendored
File diff suppressed because it is too large
Load Diff
465
vendor/github.com/cloudfoundry-incubator/candiedyaml/reader.go
generated
vendored
465
vendor/github.com/cloudfoundry-incubator/candiedyaml/reader.go
generated
vendored
@@ -1,465 +0,0 @@
|
||||
/*
|
||||
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 candiedyaml
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
/*
|
||||
* Set the reader error and return 0.
|
||||
*/
|
||||
|
||||
func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string,
|
||||
offset int, value int) bool {
|
||||
parser.error = yaml_READER_ERROR
|
||||
parser.problem = problem
|
||||
parser.problem_offset = offset
|
||||
parser.problem_value = value
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
/*
|
||||
* Byte order marks.
|
||||
*/
|
||||
const (
|
||||
BOM_UTF8 = "\xef\xbb\xbf"
|
||||
BOM_UTF16LE = "\xff\xfe"
|
||||
BOM_UTF16BE = "\xfe\xff"
|
||||
)
|
||||
|
||||
/*
|
||||
* Determine the input stream encoding by checking the BOM symbol. If no BOM is
|
||||
* found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure.
|
||||
*/
|
||||
|
||||
func yaml_parser_determine_encoding(parser *yaml_parser_t) bool {
|
||||
/* Ensure that we had enough bytes in the raw buffer. */
|
||||
for !parser.eof &&
|
||||
len(parser.raw_buffer)-parser.raw_buffer_pos < 3 {
|
||||
if !yaml_parser_update_raw_buffer(parser) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine the encoding. */
|
||||
raw := parser.raw_buffer
|
||||
pos := parser.raw_buffer_pos
|
||||
remaining := len(raw) - pos
|
||||
if remaining >= 2 &&
|
||||
raw[pos] == BOM_UTF16LE[0] && raw[pos+1] == BOM_UTF16LE[1] {
|
||||
parser.encoding = yaml_UTF16LE_ENCODING
|
||||
parser.raw_buffer_pos += 2
|
||||
parser.offset += 2
|
||||
} else if remaining >= 2 &&
|
||||
raw[pos] == BOM_UTF16BE[0] && raw[pos+1] == BOM_UTF16BE[1] {
|
||||
parser.encoding = yaml_UTF16BE_ENCODING
|
||||
parser.raw_buffer_pos += 2
|
||||
parser.offset += 2
|
||||
} else if remaining >= 3 &&
|
||||
raw[pos] == BOM_UTF8[0] && raw[pos+1] == BOM_UTF8[1] && raw[pos+2] == BOM_UTF8[2] {
|
||||
parser.encoding = yaml_UTF8_ENCODING
|
||||
parser.raw_buffer_pos += 3
|
||||
parser.offset += 3
|
||||
} else {
|
||||
parser.encoding = yaml_UTF8_ENCODING
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the raw buffer.
|
||||
*/
|
||||
|
||||
func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool {
|
||||
size_read := 0
|
||||
|
||||
/* Return if the raw buffer is full. */
|
||||
if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) {
|
||||
return true
|
||||
}
|
||||
|
||||
/* Return on EOF. */
|
||||
|
||||
if parser.eof {
|
||||
return true
|
||||
}
|
||||
|
||||
/* Move the remaining bytes in the raw buffer to the beginning. */
|
||||
if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) {
|
||||
copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:])
|
||||
}
|
||||
parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos]
|
||||
parser.raw_buffer_pos = 0
|
||||
|
||||
/* Call the read handler to fill the buffer. */
|
||||
size_read, err := parser.read_handler(parser,
|
||||
parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)])
|
||||
parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read]
|
||||
|
||||
if err == io.EOF {
|
||||
parser.eof = true
|
||||
} else if err != nil {
|
||||
return yaml_parser_set_reader_error(parser, "input error: "+err.Error(),
|
||||
parser.offset, -1)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure that the buffer contains at least `length` characters.
|
||||
* Return 1 on success, 0 on failure.
|
||||
*
|
||||
* The length is supposed to be significantly less that the buffer size.
|
||||
*/
|
||||
|
||||
func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {
|
||||
/* Read handler must be set. */
|
||||
if parser.read_handler == nil {
|
||||
panic("read handler must be set")
|
||||
}
|
||||
|
||||
/* If the EOF flag is set and the raw buffer is empty, do nothing. */
|
||||
|
||||
if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) {
|
||||
return true
|
||||
}
|
||||
|
||||
/* Return if the buffer contains enough characters. */
|
||||
|
||||
if parser.unread >= length {
|
||||
return true
|
||||
}
|
||||
|
||||
/* Determine the input encoding if it is not known yet. */
|
||||
|
||||
if parser.encoding == yaml_ANY_ENCODING {
|
||||
if !yaml_parser_determine_encoding(parser) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/* Move the unread characters to the beginning of the buffer. */
|
||||
buffer_end := len(parser.buffer)
|
||||
if 0 < parser.buffer_pos &&
|
||||
parser.buffer_pos < buffer_end {
|
||||
copy(parser.buffer, parser.buffer[parser.buffer_pos:])
|
||||
buffer_end -= parser.buffer_pos
|
||||
parser.buffer_pos = 0
|
||||
} else if parser.buffer_pos == buffer_end {
|
||||
buffer_end = 0
|
||||
parser.buffer_pos = 0
|
||||
}
|
||||
|
||||
parser.buffer = parser.buffer[:cap(parser.buffer)]
|
||||
|
||||
/* Fill the buffer until it has enough characters. */
|
||||
first := true
|
||||
for parser.unread < length {
|
||||
/* Fill the raw buffer if necessary. */
|
||||
|
||||
if !first || parser.raw_buffer_pos == len(parser.raw_buffer) {
|
||||
if !yaml_parser_update_raw_buffer(parser) {
|
||||
parser.buffer = parser.buffer[:buffer_end]
|
||||
return false
|
||||
}
|
||||
}
|
||||
first = false
|
||||
|
||||
/* Decode the raw buffer. */
|
||||
for parser.raw_buffer_pos != len(parser.raw_buffer) {
|
||||
var value rune
|
||||
var w int
|
||||
|
||||
raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos
|
||||
incomplete := false
|
||||
|
||||
/* Decode the next character. */
|
||||
|
||||
switch parser.encoding {
|
||||
case yaml_UTF8_ENCODING:
|
||||
|
||||
/*
|
||||
* Decode a UTF-8 character. Check RFC 3629
|
||||
* (http://www.ietf.org/rfc/rfc3629.txt) for more details.
|
||||
*
|
||||
* The following table (taken from the RFC) is used for
|
||||
* decoding.
|
||||
*
|
||||
* Char. number range | UTF-8 octet sequence
|
||||
* (hexadecimal) | (binary)
|
||||
* --------------------+------------------------------------
|
||||
* 0000 0000-0000 007F | 0xxxxxxx
|
||||
* 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
|
||||
* 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
|
||||
* 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
*
|
||||
* Additionally, the characters in the range 0xD800-0xDFFF
|
||||
* are prohibited as they are reserved for use with UTF-16
|
||||
* surrogate pairs.
|
||||
*/
|
||||
|
||||
/* Determine the length of the UTF-8 sequence. */
|
||||
|
||||
octet := parser.raw_buffer[parser.raw_buffer_pos]
|
||||
w = width(octet)
|
||||
|
||||
/* Check if the leading octet is valid. */
|
||||
|
||||
if w == 0 {
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"invalid leading UTF-8 octet",
|
||||
parser.offset, int(octet))
|
||||
}
|
||||
|
||||
/* Check if the raw buffer contains an incomplete character. */
|
||||
|
||||
if w > raw_unread {
|
||||
if parser.eof {
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"incomplete UTF-8 octet sequence",
|
||||
parser.offset, -1)
|
||||
}
|
||||
incomplete = true
|
||||
break
|
||||
}
|
||||
|
||||
/* Decode the leading octet. */
|
||||
switch {
|
||||
case octet&0x80 == 0x00:
|
||||
value = rune(octet & 0x7F)
|
||||
case octet&0xE0 == 0xC0:
|
||||
value = rune(octet & 0x1F)
|
||||
case octet&0xF0 == 0xE0:
|
||||
value = rune(octet & 0x0F)
|
||||
case octet&0xF8 == 0xF0:
|
||||
value = rune(octet & 0x07)
|
||||
default:
|
||||
value = 0
|
||||
}
|
||||
|
||||
/* Check and decode the trailing octets. */
|
||||
|
||||
for k := 1; k < w; k++ {
|
||||
octet = parser.raw_buffer[parser.raw_buffer_pos+k]
|
||||
|
||||
/* Check if the octet is valid. */
|
||||
|
||||
if (octet & 0xC0) != 0x80 {
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"invalid trailing UTF-8 octet",
|
||||
parser.offset+k, int(octet))
|
||||
}
|
||||
|
||||
/* Decode the octet. */
|
||||
|
||||
value = (value << 6) + rune(octet&0x3F)
|
||||
}
|
||||
|
||||
/* Check the length of the sequence against the value. */
|
||||
switch {
|
||||
case w == 1:
|
||||
case w == 2 && value >= 0x80:
|
||||
case w == 3 && value >= 0x800:
|
||||
case w == 4 && value >= 0x10000:
|
||||
default:
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"invalid length of a UTF-8 sequence",
|
||||
parser.offset, -1)
|
||||
}
|
||||
|
||||
/* Check the range of the value. */
|
||||
|
||||
if (value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF {
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"invalid Unicode character",
|
||||
parser.offset, int(value))
|
||||
}
|
||||
case yaml_UTF16LE_ENCODING,
|
||||
yaml_UTF16BE_ENCODING:
|
||||
|
||||
var low, high int
|
||||
if parser.encoding == yaml_UTF16LE_ENCODING {
|
||||
low, high = 0, 1
|
||||
} else {
|
||||
high, low = 1, 0
|
||||
}
|
||||
|
||||
/*
|
||||
* The UTF-16 encoding is not as simple as one might
|
||||
* naively think. Check RFC 2781
|
||||
* (http://www.ietf.org/rfc/rfc2781.txt).
|
||||
*
|
||||
* Normally, two subsequent bytes describe a Unicode
|
||||
* character. However a special technique (called a
|
||||
* surrogate pair) is used for specifying character
|
||||
* values larger than 0xFFFF.
|
||||
*
|
||||
* A surrogate pair consists of two pseudo-characters:
|
||||
* high surrogate area (0xD800-0xDBFF)
|
||||
* low surrogate area (0xDC00-0xDFFF)
|
||||
*
|
||||
* The following formulas are used for decoding
|
||||
* and encoding characters using surrogate pairs:
|
||||
*
|
||||
* U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF)
|
||||
* U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF)
|
||||
* W1 = 110110yyyyyyyyyy
|
||||
* W2 = 110111xxxxxxxxxx
|
||||
*
|
||||
* where U is the character value, W1 is the high surrogate
|
||||
* area, W2 is the low surrogate area.
|
||||
*/
|
||||
|
||||
/* Check for incomplete UTF-16 character. */
|
||||
|
||||
if raw_unread < 2 {
|
||||
if parser.eof {
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"incomplete UTF-16 character",
|
||||
parser.offset, -1)
|
||||
}
|
||||
incomplete = true
|
||||
break
|
||||
}
|
||||
|
||||
/* Get the character. */
|
||||
value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) +
|
||||
(rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8)
|
||||
|
||||
/* Check for unexpected low surrogate area. */
|
||||
|
||||
if (value & 0xFC00) == 0xDC00 {
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"unexpected low surrogate area",
|
||||
parser.offset, int(value))
|
||||
}
|
||||
|
||||
/* Check for a high surrogate area. */
|
||||
|
||||
if (value & 0xFC00) == 0xD800 {
|
||||
|
||||
w = 4
|
||||
|
||||
/* Check for incomplete surrogate pair. */
|
||||
|
||||
if raw_unread < 4 {
|
||||
if parser.eof {
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"incomplete UTF-16 surrogate pair",
|
||||
parser.offset, -1)
|
||||
}
|
||||
incomplete = true
|
||||
break
|
||||
}
|
||||
|
||||
/* Get the next character. */
|
||||
|
||||
value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) +
|
||||
(rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8)
|
||||
|
||||
/* Check for a low surrogate area. */
|
||||
|
||||
if (value2 & 0xFC00) != 0xDC00 {
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"expected low surrogate area",
|
||||
parser.offset+2, int(value2))
|
||||
}
|
||||
|
||||
/* Generate the value of the surrogate pair. */
|
||||
|
||||
value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF)
|
||||
} else {
|
||||
w = 2
|
||||
}
|
||||
|
||||
break
|
||||
|
||||
default:
|
||||
panic("Impossible") /* Impossible. */
|
||||
}
|
||||
|
||||
/* Check if the raw buffer contains enough bytes to form a character. */
|
||||
|
||||
if incomplete {
|
||||
break
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the character is in the allowed range:
|
||||
* #x9 | #xA | #xD | [#x20-#x7E] (8 bit)
|
||||
* | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit)
|
||||
* | [#x10000-#x10FFFF] (32 bit)
|
||||
*/
|
||||
|
||||
if !(value == 0x09 || value == 0x0A || value == 0x0D ||
|
||||
(value >= 0x20 && value <= 0x7E) ||
|
||||
(value == 0x85) || (value >= 0xA0 && value <= 0xD7FF) ||
|
||||
(value >= 0xE000 && value <= 0xFFFD) ||
|
||||
(value >= 0x10000 && value <= 0x10FFFF)) {
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"control characters are not allowed",
|
||||
parser.offset, int(value))
|
||||
}
|
||||
|
||||
/* Move the raw pointers. */
|
||||
|
||||
parser.raw_buffer_pos += w
|
||||
parser.offset += w
|
||||
|
||||
/* Finally put the character into the buffer. */
|
||||
|
||||
/* 0000 0000-0000 007F . 0xxxxxxx */
|
||||
if value <= 0x7F {
|
||||
parser.buffer[buffer_end] = byte(value)
|
||||
} else if value <= 0x7FF {
|
||||
/* 0000 0080-0000 07FF . 110xxxxx 10xxxxxx */
|
||||
parser.buffer[buffer_end] = byte(0xC0 + (value >> 6))
|
||||
parser.buffer[buffer_end+1] = byte(0x80 + (value & 0x3F))
|
||||
} else if value <= 0xFFFF {
|
||||
/* 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx */
|
||||
parser.buffer[buffer_end] = byte(0xE0 + (value >> 12))
|
||||
parser.buffer[buffer_end+1] = byte(0x80 + ((value >> 6) & 0x3F))
|
||||
parser.buffer[buffer_end+2] = byte(0x80 + (value & 0x3F))
|
||||
} else {
|
||||
/* 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
|
||||
parser.buffer[buffer_end] = byte(0xF0 + (value >> 18))
|
||||
parser.buffer[buffer_end+1] = byte(0x80 + ((value >> 12) & 0x3F))
|
||||
parser.buffer[buffer_end+2] = byte(0x80 + ((value >> 6) & 0x3F))
|
||||
parser.buffer[buffer_end+3] = byte(0x80 + (value & 0x3F))
|
||||
}
|
||||
|
||||
buffer_end += w
|
||||
parser.unread++
|
||||
}
|
||||
|
||||
/* On EOF, put NUL into the buffer and return. */
|
||||
|
||||
if parser.eof {
|
||||
parser.buffer[buffer_end] = 0
|
||||
buffer_end++
|
||||
parser.buffer = parser.buffer[:buffer_end]
|
||||
parser.unread++
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
parser.buffer = parser.buffer[:buffer_end]
|
||||
return true
|
||||
}
|
||||
449
vendor/github.com/cloudfoundry-incubator/candiedyaml/resolver.go
generated
vendored
449
vendor/github.com/cloudfoundry-incubator/candiedyaml/resolver.go
generated
vendored
@@ -1,449 +0,0 @@
|
||||
/*
|
||||
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 candiedyaml
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var byteSliceType = reflect.TypeOf([]byte(nil))
|
||||
|
||||
var binary_tags = [][]byte{[]byte("!binary"), []byte(yaml_BINARY_TAG)}
|
||||
var bool_values map[string]bool
|
||||
var null_values map[string]bool
|
||||
|
||||
var signs = []byte{'-', '+'}
|
||||
var nulls = []byte{'~', 'n', 'N'}
|
||||
var bools = []byte{'t', 'T', 'f', 'F', 'y', 'Y', 'n', 'N', 'o', 'O'}
|
||||
|
||||
var timestamp_regexp *regexp.Regexp
|
||||
var ymd_regexp *regexp.Regexp
|
||||
|
||||
func init() {
|
||||
bool_values = make(map[string]bool)
|
||||
bool_values["y"] = true
|
||||
bool_values["yes"] = true
|
||||
bool_values["n"] = false
|
||||
bool_values["no"] = false
|
||||
bool_values["true"] = true
|
||||
bool_values["false"] = false
|
||||
bool_values["on"] = true
|
||||
bool_values["off"] = false
|
||||
|
||||
null_values = make(map[string]bool)
|
||||
null_values["~"] = true
|
||||
null_values["null"] = true
|
||||
null_values["Null"] = true
|
||||
null_values["NULL"] = true
|
||||
|
||||
timestamp_regexp = regexp.MustCompile("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:(?:[Tt]|[ \t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \t]*(?:Z|([-+][0-9][0-9]?)(?::([0-9][0-9])?)?))?)?$")
|
||||
ymd_regexp = regexp.MustCompile("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)$")
|
||||
}
|
||||
|
||||
func resolve(event yaml_event_t, v reflect.Value, useNumber bool) (string, error) {
|
||||
val := string(event.value)
|
||||
|
||||
if null_values[val] {
|
||||
v.Set(reflect.Zero(v.Type()))
|
||||
return yaml_NULL_TAG, nil
|
||||
}
|
||||
|
||||
switch v.Kind() {
|
||||
case reflect.String:
|
||||
if useNumber && v.Type() == numberType {
|
||||
tag, i := resolveInterface(event, useNumber)
|
||||
if n, ok := i.(Number); ok {
|
||||
v.Set(reflect.ValueOf(n))
|
||||
return tag, nil
|
||||
}
|
||||
return "", fmt.Errorf("Not a number: '%s' at %s", event.value, event.start_mark)
|
||||
}
|
||||
|
||||
return resolve_string(val, v, event)
|
||||
case reflect.Bool:
|
||||
return resolve_bool(val, v, event)
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return resolve_int(val, v, useNumber, event)
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return resolve_uint(val, v, useNumber, event)
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return resolve_float(val, v, useNumber, event)
|
||||
case reflect.Interface:
|
||||
_, i := resolveInterface(event, useNumber)
|
||||
if i != nil {
|
||||
v.Set(reflect.ValueOf(i))
|
||||
} else {
|
||||
v.Set(reflect.Zero(v.Type()))
|
||||
}
|
||||
|
||||
case reflect.Struct:
|
||||
return resolve_time(val, v, event)
|
||||
case reflect.Slice:
|
||||
if v.Type() != byteSliceType {
|
||||
return "", fmt.Errorf("Cannot resolve %s into %s at %s", val, v.String(), event.start_mark)
|
||||
}
|
||||
b, err := decode_binary(event.value, event)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
v.Set(reflect.ValueOf(b))
|
||||
default:
|
||||
return "", fmt.Errorf("Unknown resolution for '%s' using %s at %s", val, v.String(), event.start_mark)
|
||||
}
|
||||
|
||||
return yaml_STR_TAG, nil
|
||||
}
|
||||
|
||||
func hasBinaryTag(event yaml_event_t) bool {
|
||||
for _, tag := range binary_tags {
|
||||
if bytes.Equal(event.tag, tag) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func decode_binary(value []byte, event yaml_event_t) ([]byte, error) {
|
||||
b := make([]byte, base64.StdEncoding.DecodedLen(len(value)))
|
||||
n, err := base64.StdEncoding.Decode(b, value)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Invalid base64 text: '%s' at %s", string(b), event.start_mark)
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
|
||||
func resolve_string(val string, v reflect.Value, event yaml_event_t) (string, error) {
|
||||
if len(event.tag) > 0 {
|
||||
if hasBinaryTag(event) {
|
||||
b, err := decode_binary(event.value, event)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
val = string(b)
|
||||
}
|
||||
}
|
||||
v.SetString(val)
|
||||
return yaml_STR_TAG, nil
|
||||
}
|
||||
|
||||
func resolve_bool(val string, v reflect.Value, event yaml_event_t) (string, error) {
|
||||
b, found := bool_values[strings.ToLower(val)]
|
||||
if !found {
|
||||
return "", fmt.Errorf("Invalid boolean: '%s' at %s", val, event.start_mark)
|
||||
}
|
||||
|
||||
v.SetBool(b)
|
||||
return yaml_BOOL_TAG, nil
|
||||
}
|
||||
|
||||
func resolve_int(val string, v reflect.Value, useNumber bool, event yaml_event_t) (string, error) {
|
||||
original := val
|
||||
val = strings.Replace(val, "_", "", -1)
|
||||
var value uint64
|
||||
|
||||
isNumberValue := v.Type() == numberType
|
||||
|
||||
sign := int64(1)
|
||||
if val[0] == '-' {
|
||||
sign = -1
|
||||
val = val[1:]
|
||||
} else if val[0] == '+' {
|
||||
val = val[1:]
|
||||
}
|
||||
|
||||
base := 0
|
||||
if val == "0" {
|
||||
if isNumberValue {
|
||||
v.SetString("0")
|
||||
} else {
|
||||
v.Set(reflect.Zero(v.Type()))
|
||||
}
|
||||
|
||||
return yaml_INT_TAG, nil
|
||||
}
|
||||
|
||||
if strings.HasPrefix(val, "0o") {
|
||||
base = 8
|
||||
val = val[2:]
|
||||
}
|
||||
|
||||
value, err := strconv.ParseUint(val, base, 64)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Invalid integer: '%s' at %s", original, event.start_mark)
|
||||
}
|
||||
|
||||
var val64 int64
|
||||
if value <= math.MaxInt64 {
|
||||
val64 = int64(value)
|
||||
if sign == -1 {
|
||||
val64 = -val64
|
||||
}
|
||||
} else if sign == -1 && value == uint64(math.MaxInt64)+1 {
|
||||
val64 = math.MinInt64
|
||||
} else {
|
||||
return "", fmt.Errorf("Invalid integer: '%s' at %s", original, event.start_mark)
|
||||
}
|
||||
|
||||
if isNumberValue {
|
||||
v.SetString(strconv.FormatInt(val64, 10))
|
||||
} else {
|
||||
if v.OverflowInt(val64) {
|
||||
return "", fmt.Errorf("Invalid integer: '%s' at %s", original, event.start_mark)
|
||||
}
|
||||
v.SetInt(val64)
|
||||
}
|
||||
|
||||
return yaml_INT_TAG, nil
|
||||
}
|
||||
|
||||
func resolve_uint(val string, v reflect.Value, useNumber bool, event yaml_event_t) (string, error) {
|
||||
original := val
|
||||
val = strings.Replace(val, "_", "", -1)
|
||||
var value uint64
|
||||
|
||||
isNumberValue := v.Type() == numberType
|
||||
|
||||
if val[0] == '-' {
|
||||
return "", fmt.Errorf("Unsigned int with negative value: '%s' at %s", original, event.start_mark)
|
||||
}
|
||||
|
||||
if val[0] == '+' {
|
||||
val = val[1:]
|
||||
}
|
||||
|
||||
base := 0
|
||||
if val == "0" {
|
||||
if isNumberValue {
|
||||
v.SetString("0")
|
||||
} else {
|
||||
v.Set(reflect.Zero(v.Type()))
|
||||
}
|
||||
|
||||
return yaml_INT_TAG, nil
|
||||
}
|
||||
|
||||
if strings.HasPrefix(val, "0o") {
|
||||
base = 8
|
||||
val = val[2:]
|
||||
}
|
||||
|
||||
value, err := strconv.ParseUint(val, base, 64)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Invalid unsigned integer: '%s' at %s", val, event.start_mark)
|
||||
}
|
||||
|
||||
if isNumberValue {
|
||||
v.SetString(strconv.FormatUint(value, 10))
|
||||
} else {
|
||||
if v.OverflowUint(value) {
|
||||
return "", fmt.Errorf("Invalid unsigned integer: '%s' at %s", val, event.start_mark)
|
||||
}
|
||||
|
||||
v.SetUint(value)
|
||||
}
|
||||
|
||||
return yaml_INT_TAG, nil
|
||||
}
|
||||
|
||||
func resolve_float(val string, v reflect.Value, useNumber bool, event yaml_event_t) (string, error) {
|
||||
val = strings.Replace(val, "_", "", -1)
|
||||
var value float64
|
||||
|
||||
isNumberValue := v.Type() == numberType
|
||||
typeBits := 64
|
||||
if !isNumberValue {
|
||||
typeBits = v.Type().Bits()
|
||||
}
|
||||
|
||||
sign := 1
|
||||
if val[0] == '-' {
|
||||
sign = -1
|
||||
val = val[1:]
|
||||
} else if val[0] == '+' {
|
||||
val = val[1:]
|
||||
}
|
||||
|
||||
valLower := strings.ToLower(val)
|
||||
if valLower == ".inf" {
|
||||
value = math.Inf(sign)
|
||||
} else if valLower == ".nan" {
|
||||
value = math.NaN()
|
||||
} else {
|
||||
var err error
|
||||
value, err = strconv.ParseFloat(val, typeBits)
|
||||
value *= float64(sign)
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Invalid float: '%s' at %s", val, event.start_mark)
|
||||
}
|
||||
}
|
||||
|
||||
if isNumberValue {
|
||||
v.SetString(strconv.FormatFloat(value, 'g', -1, typeBits))
|
||||
} else {
|
||||
if v.OverflowFloat(value) {
|
||||
return "", fmt.Errorf("Invalid float: '%s' at %s", val, event.start_mark)
|
||||
}
|
||||
|
||||
v.SetFloat(value)
|
||||
}
|
||||
|
||||
return yaml_FLOAT_TAG, nil
|
||||
}
|
||||
|
||||
func resolve_time(val string, v reflect.Value, event yaml_event_t) (string, error) {
|
||||
var parsedTime time.Time
|
||||
matches := ymd_regexp.FindStringSubmatch(val)
|
||||
if len(matches) > 0 {
|
||||
year, _ := strconv.Atoi(matches[1])
|
||||
month, _ := strconv.Atoi(matches[2])
|
||||
day, _ := strconv.Atoi(matches[3])
|
||||
parsedTime = time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC)
|
||||
} else {
|
||||
matches = timestamp_regexp.FindStringSubmatch(val)
|
||||
if len(matches) == 0 {
|
||||
return "", fmt.Errorf("Invalid timestamp: '%s' at %s", val, event.start_mark)
|
||||
}
|
||||
|
||||
year, _ := strconv.Atoi(matches[1])
|
||||
month, _ := strconv.Atoi(matches[2])
|
||||
day, _ := strconv.Atoi(matches[3])
|
||||
hour, _ := strconv.Atoi(matches[4])
|
||||
min, _ := strconv.Atoi(matches[5])
|
||||
sec, _ := strconv.Atoi(matches[6])
|
||||
|
||||
nsec := 0
|
||||
if matches[7] != "" {
|
||||
millis, _ := strconv.Atoi(matches[7])
|
||||
nsec = int(time.Duration(millis) * time.Millisecond)
|
||||
}
|
||||
|
||||
loc := time.UTC
|
||||
if matches[8] != "" {
|
||||
sign := matches[8][0]
|
||||
hr, _ := strconv.Atoi(matches[8][1:])
|
||||
min := 0
|
||||
if matches[9] != "" {
|
||||
min, _ = strconv.Atoi(matches[9])
|
||||
}
|
||||
|
||||
zoneOffset := (hr*60 + min) * 60
|
||||
if sign == '-' {
|
||||
zoneOffset = -zoneOffset
|
||||
}
|
||||
|
||||
loc = time.FixedZone("", zoneOffset)
|
||||
}
|
||||
parsedTime = time.Date(year, time.Month(month), day, hour, min, sec, nsec, loc)
|
||||
}
|
||||
|
||||
v.Set(reflect.ValueOf(parsedTime))
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func resolveInterface(event yaml_event_t, useNumber bool) (string, interface{}) {
|
||||
val := string(event.value)
|
||||
if len(event.tag) == 0 && !event.implicit {
|
||||
return "", val
|
||||
}
|
||||
|
||||
if len(val) == 0 {
|
||||
return yaml_NULL_TAG, nil
|
||||
}
|
||||
|
||||
var result interface{}
|
||||
|
||||
sign := false
|
||||
c := val[0]
|
||||
switch {
|
||||
case bytes.IndexByte(signs, c) != -1:
|
||||
sign = true
|
||||
fallthrough
|
||||
case c >= '0' && c <= '9':
|
||||
i := int64(0)
|
||||
result = &i
|
||||
if useNumber {
|
||||
var n Number
|
||||
result = &n
|
||||
}
|
||||
|
||||
v := reflect.ValueOf(result).Elem()
|
||||
if _, err := resolve_int(val, v, useNumber, event); err == nil {
|
||||
return yaml_INT_TAG, v.Interface()
|
||||
}
|
||||
|
||||
f := float64(0)
|
||||
result = &f
|
||||
if useNumber {
|
||||
var n Number
|
||||
result = &n
|
||||
}
|
||||
|
||||
v = reflect.ValueOf(result).Elem()
|
||||
if _, err := resolve_float(val, v, useNumber, event); err == nil {
|
||||
return yaml_FLOAT_TAG, v.Interface()
|
||||
}
|
||||
|
||||
if !sign {
|
||||
t := time.Time{}
|
||||
if _, err := resolve_time(val, reflect.ValueOf(&t).Elem(), event); err == nil {
|
||||
return "", t
|
||||
}
|
||||
}
|
||||
case bytes.IndexByte(nulls, c) != -1:
|
||||
if null_values[val] {
|
||||
return yaml_NULL_TAG, nil
|
||||
}
|
||||
b := false
|
||||
if _, err := resolve_bool(val, reflect.ValueOf(&b).Elem(), event); err == nil {
|
||||
return yaml_BOOL_TAG, b
|
||||
}
|
||||
case c == '.':
|
||||
f := float64(0)
|
||||
result = &f
|
||||
if useNumber {
|
||||
var n Number
|
||||
result = &n
|
||||
}
|
||||
|
||||
v := reflect.ValueOf(result).Elem()
|
||||
if _, err := resolve_float(val, v, useNumber, event); err == nil {
|
||||
return yaml_FLOAT_TAG, v.Interface()
|
||||
}
|
||||
case bytes.IndexByte(bools, c) != -1:
|
||||
b := false
|
||||
if _, err := resolve_bool(val, reflect.ValueOf(&b).Elem(), event); err == nil {
|
||||
return yaml_BOOL_TAG, b
|
||||
}
|
||||
}
|
||||
|
||||
if hasBinaryTag(event) {
|
||||
bytes, err := decode_binary(event.value, event)
|
||||
if err == nil {
|
||||
return yaml_BINARY_TAG, bytes
|
||||
}
|
||||
}
|
||||
|
||||
return yaml_STR_TAG, val
|
||||
}
|
||||
62
vendor/github.com/cloudfoundry-incubator/candiedyaml/run_parser.go
generated
vendored
62
vendor/github.com/cloudfoundry-incubator/candiedyaml/run_parser.go
generated
vendored
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
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 candiedyaml
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func Run_parser(cmd string, args []string) {
|
||||
for i := 0; i < len(args); i++ {
|
||||
fmt.Printf("[%d] Scanning '%s'", i, args[i])
|
||||
file, err := os.Open(args[i])
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Invalid file '%s': %s", args[i], err.Error()))
|
||||
}
|
||||
|
||||
parser := yaml_parser_t{}
|
||||
yaml_parser_initialize(&parser)
|
||||
yaml_parser_set_input_reader(&parser, file)
|
||||
|
||||
failed := false
|
||||
token := yaml_token_t{}
|
||||
count := 0
|
||||
for {
|
||||
if !yaml_parser_scan(&parser, &token) {
|
||||
failed = true
|
||||
break
|
||||
}
|
||||
|
||||
if token.token_type == yaml_STREAM_END_TOKEN {
|
||||
break
|
||||
}
|
||||
count++
|
||||
}
|
||||
|
||||
file.Close()
|
||||
|
||||
msg := "SUCCESS"
|
||||
if failed {
|
||||
msg = "FAILED"
|
||||
if parser.error != yaml_NO_ERROR {
|
||||
m := parser.problem_mark
|
||||
fmt.Printf("ERROR: (%s) %s @ line: %d col: %d\n",
|
||||
parser.context, parser.problem, m.line, m.column)
|
||||
}
|
||||
}
|
||||
fmt.Printf("%s (%d tokens)\n", msg, count)
|
||||
}
|
||||
}
|
||||
3318
vendor/github.com/cloudfoundry-incubator/candiedyaml/scanner.go
generated
vendored
3318
vendor/github.com/cloudfoundry-incubator/candiedyaml/scanner.go
generated
vendored
File diff suppressed because it is too large
Load Diff
360
vendor/github.com/cloudfoundry-incubator/candiedyaml/tags.go
generated
vendored
360
vendor/github.com/cloudfoundry-incubator/candiedyaml/tags.go
generated
vendored
@@ -1,360 +0,0 @@
|
||||
/*
|
||||
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 candiedyaml
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// A field represents a single field found in a struct.
|
||||
type field struct {
|
||||
name string
|
||||
tag bool
|
||||
index []int
|
||||
typ reflect.Type
|
||||
omitEmpty bool
|
||||
flow bool
|
||||
}
|
||||
|
||||
// byName sorts field by name, breaking ties with depth,
|
||||
// then breaking ties with "name came from json tag", then
|
||||
// breaking ties with index sequence.
|
||||
type byName []field
|
||||
|
||||
func (x byName) Len() int { return len(x) }
|
||||
|
||||
func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||
|
||||
func (x byName) Less(i, j int) bool {
|
||||
if x[i].name != x[j].name {
|
||||
return x[i].name < x[j].name
|
||||
}
|
||||
if len(x[i].index) != len(x[j].index) {
|
||||
return len(x[i].index) < len(x[j].index)
|
||||
}
|
||||
if x[i].tag != x[j].tag {
|
||||
return x[i].tag
|
||||
}
|
||||
return byIndex(x).Less(i, j)
|
||||
}
|
||||
|
||||
// byIndex sorts field by index sequence.
|
||||
type byIndex []field
|
||||
|
||||
func (x byIndex) Len() int { return len(x) }
|
||||
|
||||
func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||
|
||||
func (x byIndex) Less(i, j int) bool {
|
||||
for k, xik := range x[i].index {
|
||||
if k >= len(x[j].index) {
|
||||
return false
|
||||
}
|
||||
if xik != x[j].index[k] {
|
||||
return xik < x[j].index[k]
|
||||
}
|
||||
}
|
||||
return len(x[i].index) < len(x[j].index)
|
||||
}
|
||||
|
||||
// typeFields returns a list of fields that JSON should recognize for the given type.
|
||||
// The algorithm is breadth-first search over the set of structs to include - the top struct
|
||||
// and then any reachable anonymous structs.
|
||||
func typeFields(t reflect.Type) []field {
|
||||
// Anonymous fields to explore at the current level and the next.
|
||||
current := []field{}
|
||||
next := []field{{typ: t}}
|
||||
|
||||
// Count of queued names for current level and the next.
|
||||
count := map[reflect.Type]int{}
|
||||
nextCount := map[reflect.Type]int{}
|
||||
|
||||
// Types already visited at an earlier level.
|
||||
visited := map[reflect.Type]bool{}
|
||||
|
||||
// Fields found.
|
||||
var fields []field
|
||||
|
||||
for len(next) > 0 {
|
||||
current, next = next, current[:0]
|
||||
count, nextCount = nextCount, map[reflect.Type]int{}
|
||||
|
||||
for _, f := range current {
|
||||
if visited[f.typ] {
|
||||
continue
|
||||
}
|
||||
visited[f.typ] = true
|
||||
|
||||
// Scan f.typ for fields to include.
|
||||
for i := 0; i < f.typ.NumField(); i++ {
|
||||
sf := f.typ.Field(i)
|
||||
if sf.PkgPath != "" { // unexported
|
||||
continue
|
||||
}
|
||||
tag := sf.Tag.Get("yaml")
|
||||
if tag == "-" {
|
||||
continue
|
||||
}
|
||||
name, opts := parseTag(tag)
|
||||
if !isValidTag(name) {
|
||||
name = ""
|
||||
}
|
||||
index := make([]int, len(f.index)+1)
|
||||
copy(index, f.index)
|
||||
index[len(f.index)] = i
|
||||
|
||||
ft := sf.Type
|
||||
if ft.Name() == "" && ft.Kind() == reflect.Ptr {
|
||||
// Follow pointer.
|
||||
ft = ft.Elem()
|
||||
}
|
||||
|
||||
// Record found field and index sequence.
|
||||
if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
|
||||
tagged := name != ""
|
||||
if name == "" {
|
||||
name = sf.Name
|
||||
}
|
||||
fields = append(fields, field{name, tagged, index, ft,
|
||||
opts.Contains("omitempty"), opts.Contains("flow")})
|
||||
if count[f.typ] > 1 {
|
||||
// If there were multiple instances, add a second,
|
||||
// so that the annihilation code will see a duplicate.
|
||||
// It only cares about the distinction between 1 or 2,
|
||||
// so don't bother generating any more copies.
|
||||
fields = append(fields, fields[len(fields)-1])
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Record new anonymous struct to explore in next round.
|
||||
nextCount[ft]++
|
||||
if nextCount[ft] == 1 {
|
||||
next = append(next, field{name: ft.Name(), index: index, typ: ft})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sort.Sort(byName(fields))
|
||||
|
||||
// Delete all fields that are hidden by the Go rules for embedded fields,
|
||||
// except that fields with JSON tags are promoted.
|
||||
|
||||
// The fields are sorted in primary order of name, secondary order
|
||||
// of field index length. Loop over names; for each name, delete
|
||||
// hidden fields by choosing the one dominant field that survives.
|
||||
out := fields[:0]
|
||||
for advance, i := 0, 0; i < len(fields); i += advance {
|
||||
// One iteration per name.
|
||||
// Find the sequence of fields with the name of this first field.
|
||||
fi := fields[i]
|
||||
name := fi.name
|
||||
for advance = 1; i+advance < len(fields); advance++ {
|
||||
fj := fields[i+advance]
|
||||
if fj.name != name {
|
||||
break
|
||||
}
|
||||
}
|
||||
if advance == 1 { // Only one field with this name
|
||||
out = append(out, fi)
|
||||
continue
|
||||
}
|
||||
dominant, ok := dominantField(fields[i : i+advance])
|
||||
if ok {
|
||||
out = append(out, dominant)
|
||||
}
|
||||
}
|
||||
|
||||
fields = out
|
||||
sort.Sort(byIndex(fields))
|
||||
|
||||
return fields
|
||||
}
|
||||
|
||||
// dominantField looks through the fields, all of which are known to
|
||||
// have the same name, to find the single field that dominates the
|
||||
// others using Go's embedding rules, modified by the presence of
|
||||
// JSON tags. If there are multiple top-level fields, the boolean
|
||||
// will be false: This condition is an error in Go and we skip all
|
||||
// the fields.
|
||||
func dominantField(fields []field) (field, bool) {
|
||||
// The fields are sorted in increasing index-length order. The winner
|
||||
// must therefore be one with the shortest index length. Drop all
|
||||
// longer entries, which is easy: just truncate the slice.
|
||||
length := len(fields[0].index)
|
||||
tagged := -1 // Index of first tagged field.
|
||||
for i, f := range fields {
|
||||
if len(f.index) > length {
|
||||
fields = fields[:i]
|
||||
break
|
||||
}
|
||||
if f.tag {
|
||||
if tagged >= 0 {
|
||||
// Multiple tagged fields at the same level: conflict.
|
||||
// Return no field.
|
||||
return field{}, false
|
||||
}
|
||||
tagged = i
|
||||
}
|
||||
}
|
||||
if tagged >= 0 {
|
||||
return fields[tagged], true
|
||||
}
|
||||
// All remaining fields have the same length. If there's more than one,
|
||||
// we have a conflict (two fields named "X" at the same level) and we
|
||||
// return no field.
|
||||
if len(fields) > 1 {
|
||||
return field{}, false
|
||||
}
|
||||
return fields[0], true
|
||||
}
|
||||
|
||||
var fieldCache struct {
|
||||
sync.RWMutex
|
||||
m map[reflect.Type][]field
|
||||
}
|
||||
|
||||
// cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
|
||||
func cachedTypeFields(t reflect.Type) []field {
|
||||
fieldCache.RLock()
|
||||
f := fieldCache.m[t]
|
||||
fieldCache.RUnlock()
|
||||
if f != nil {
|
||||
return f
|
||||
}
|
||||
|
||||
// Compute fields without lock.
|
||||
// Might duplicate effort but won't hold other computations back.
|
||||
f = typeFields(t)
|
||||
if f == nil {
|
||||
f = []field{}
|
||||
}
|
||||
|
||||
fieldCache.Lock()
|
||||
if fieldCache.m == nil {
|
||||
fieldCache.m = map[reflect.Type][]field{}
|
||||
}
|
||||
fieldCache.m[t] = f
|
||||
fieldCache.Unlock()
|
||||
return f
|
||||
}
|
||||
|
||||
// tagOptions is the string following a comma in a struct field's "json"
|
||||
// tag, or the empty string. It does not include the leading comma.
|
||||
type tagOptions string
|
||||
|
||||
func isValidTag(s string) bool {
|
||||
if s == "" {
|
||||
return false
|
||||
}
|
||||
for _, c := range s {
|
||||
switch {
|
||||
case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c):
|
||||
// Backslash and quote chars are reserved, but
|
||||
// otherwise any punctuation chars are allowed
|
||||
// in a tag name.
|
||||
default:
|
||||
if !unicode.IsLetter(c) && !unicode.IsDigit(c) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func fieldByIndex(v reflect.Value, index []int) reflect.Value {
|
||||
for _, i := range index {
|
||||
if v.Kind() == reflect.Ptr {
|
||||
if v.IsNil() {
|
||||
return reflect.Value{}
|
||||
}
|
||||
v = v.Elem()
|
||||
}
|
||||
v = v.Field(i)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func typeByIndex(t reflect.Type, index []int) reflect.Type {
|
||||
for _, i := range index {
|
||||
if t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
t = t.Field(i).Type
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// stringValues is a slice of reflect.Value holding *reflect.StringValue.
|
||||
// It implements the methods to sort by string.
|
||||
type stringValues []reflect.Value
|
||||
|
||||
func (sv stringValues) Len() int { return len(sv) }
|
||||
func (sv stringValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
|
||||
func (sv stringValues) Less(i, j int) bool {
|
||||
av, ak := getElem(sv[i])
|
||||
bv, bk := getElem(sv[j])
|
||||
if ak == reflect.String && bk == reflect.String {
|
||||
return av.String() < bv.String()
|
||||
}
|
||||
|
||||
return ak < bk
|
||||
}
|
||||
|
||||
func getElem(v reflect.Value) (reflect.Value, reflect.Kind) {
|
||||
k := v.Kind()
|
||||
for k == reflect.Interface || k == reflect.Ptr && !v.IsNil() {
|
||||
v = v.Elem()
|
||||
k = v.Kind()
|
||||
}
|
||||
|
||||
return v, k
|
||||
}
|
||||
|
||||
// parseTag splits a struct field's json tag into its name and
|
||||
// comma-separated options.
|
||||
func parseTag(tag string) (string, tagOptions) {
|
||||
if idx := strings.Index(tag, ","); idx != -1 {
|
||||
return tag[:idx], tagOptions(tag[idx+1:])
|
||||
}
|
||||
return tag, tagOptions("")
|
||||
}
|
||||
|
||||
// Contains reports whether a comma-separated list of options
|
||||
// contains a particular substr flag. substr must be surrounded by a
|
||||
// string boundary or commas.
|
||||
func (o tagOptions) Contains(optionName string) bool {
|
||||
if len(o) == 0 {
|
||||
return false
|
||||
}
|
||||
s := string(o)
|
||||
for s != "" {
|
||||
var next string
|
||||
i := strings.Index(s, ",")
|
||||
if i >= 0 {
|
||||
s, next = s[:i], s[i+1:]
|
||||
}
|
||||
if s == optionName {
|
||||
return true
|
||||
}
|
||||
s = next
|
||||
}
|
||||
return false
|
||||
}
|
||||
128
vendor/github.com/cloudfoundry-incubator/candiedyaml/writer.go
generated
vendored
128
vendor/github.com/cloudfoundry-incubator/candiedyaml/writer.go
generated
vendored
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
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 candiedyaml
|
||||
|
||||
/*
|
||||
* Set the writer error and return 0.
|
||||
*/
|
||||
|
||||
func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool {
|
||||
emitter.error = yaml_WRITER_ERROR
|
||||
emitter.problem = problem
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush the output buffer.
|
||||
*/
|
||||
|
||||
func yaml_emitter_flush(emitter *yaml_emitter_t) bool {
|
||||
if emitter.write_handler == nil {
|
||||
panic("Write handler must be set") /* Write handler must be set. */
|
||||
}
|
||||
if emitter.encoding == yaml_ANY_ENCODING {
|
||||
panic("Encoding must be set") /* Output encoding must be set. */
|
||||
}
|
||||
|
||||
/* Check if the buffer is empty. */
|
||||
|
||||
if emitter.buffer_pos == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
/* If the output encoding is UTF-8, we don't need to recode the buffer. */
|
||||
|
||||
if emitter.encoding == yaml_UTF8_ENCODING {
|
||||
if err := emitter.write_handler(emitter,
|
||||
emitter.buffer[:emitter.buffer_pos]); err != nil {
|
||||
return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
|
||||
}
|
||||
emitter.buffer_pos = 0
|
||||
return true
|
||||
}
|
||||
|
||||
/* Recode the buffer into the raw buffer. */
|
||||
|
||||
var low, high int
|
||||
if emitter.encoding == yaml_UTF16LE_ENCODING {
|
||||
low, high = 0, 1
|
||||
} else {
|
||||
high, low = 1, 0
|
||||
}
|
||||
|
||||
pos := 0
|
||||
for pos < emitter.buffer_pos {
|
||||
|
||||
/*
|
||||
* See the "reader.c" code for more details on UTF-8 encoding. Note
|
||||
* that we assume that the buffer contains a valid UTF-8 sequence.
|
||||
*/
|
||||
|
||||
/* Read the next UTF-8 character. */
|
||||
|
||||
octet := emitter.buffer[pos]
|
||||
|
||||
var w int
|
||||
var value rune
|
||||
switch {
|
||||
case octet&0x80 == 0x00:
|
||||
w, value = 1, rune(octet&0x7F)
|
||||
case octet&0xE0 == 0xC0:
|
||||
w, value = 2, rune(octet&0x1F)
|
||||
case octet&0xF0 == 0xE0:
|
||||
w, value = 3, rune(octet&0x0F)
|
||||
case octet&0xF8 == 0xF0:
|
||||
w, value = 4, rune(octet&0x07)
|
||||
}
|
||||
|
||||
for k := 1; k < w; k++ {
|
||||
octet = emitter.buffer[pos+k]
|
||||
value = (value << 6) + (rune(octet) & 0x3F)
|
||||
}
|
||||
|
||||
pos += w
|
||||
|
||||
/* Write the character. */
|
||||
|
||||
if value < 0x10000 {
|
||||
var b [2]byte
|
||||
b[high] = byte(value >> 8)
|
||||
b[low] = byte(value & 0xFF)
|
||||
emitter.raw_buffer = append(emitter.raw_buffer, b[0], b[1])
|
||||
} else {
|
||||
/* Write the character using a surrogate pair (check "reader.c"). */
|
||||
|
||||
var b [4]byte
|
||||
value -= 0x10000
|
||||
b[high] = byte(0xD8 + (value >> 18))
|
||||
b[low] = byte((value >> 10) & 0xFF)
|
||||
b[high+2] = byte(0xDC + ((value >> 8) & 0xFF))
|
||||
b[low+2] = byte(value & 0xFF)
|
||||
emitter.raw_buffer = append(emitter.raw_buffer, b[0], b[1], b[2], b[3])
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the raw buffer. */
|
||||
|
||||
// Write the raw buffer.
|
||||
if err := emitter.write_handler(emitter, emitter.raw_buffer); err != nil {
|
||||
return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
|
||||
}
|
||||
|
||||
emitter.buffer_pos = 0
|
||||
emitter.raw_buffer = emitter.raw_buffer[:0]
|
||||
return true
|
||||
}
|
||||
22
vendor/github.com/cloudfoundry-incubator/candiedyaml/yaml_definesh.go
generated
vendored
22
vendor/github.com/cloudfoundry-incubator/candiedyaml/yaml_definesh.go
generated
vendored
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
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 candiedyaml
|
||||
|
||||
const (
|
||||
yaml_VERSION_MAJOR = 0
|
||||
yaml_VERSION_MINOR = 1
|
||||
yaml_VERSION_PATCH = 6
|
||||
yaml_VERSION_STRING = "0.1.6"
|
||||
)
|
||||
891
vendor/github.com/cloudfoundry-incubator/candiedyaml/yaml_privateh.go
generated
vendored
891
vendor/github.com/cloudfoundry-incubator/candiedyaml/yaml_privateh.go
generated
vendored
@@ -1,891 +0,0 @@
|
||||
/*
|
||||
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 candiedyaml
|
||||
|
||||
const (
|
||||
INPUT_RAW_BUFFER_SIZE = 1024
|
||||
|
||||
/*
|
||||
* The size of the input buffer.
|
||||
*
|
||||
* It should be possible to decode the whole raw buffer.
|
||||
*/
|
||||
INPUT_BUFFER_SIZE = (INPUT_RAW_BUFFER_SIZE * 3)
|
||||
|
||||
/*
|
||||
* The size of the output buffer.
|
||||
*/
|
||||
|
||||
OUTPUT_BUFFER_SIZE = 512
|
||||
|
||||
/*
|
||||
* The size of the output raw buffer.
|
||||
*
|
||||
* It should be possible to encode the whole output buffer.
|
||||
*/
|
||||
|
||||
OUTPUT_RAW_BUFFER_SIZE = (OUTPUT_BUFFER_SIZE*2 + 2)
|
||||
|
||||
INITIAL_STACK_SIZE = 16
|
||||
INITIAL_QUEUE_SIZE = 16
|
||||
)
|
||||
|
||||
func width(b byte) int {
|
||||
if b&0x80 == 0 {
|
||||
return 1
|
||||
}
|
||||
|
||||
if b&0xE0 == 0xC0 {
|
||||
return 2
|
||||
}
|
||||
|
||||
if b&0xF0 == 0xE0 {
|
||||
return 3
|
||||
}
|
||||
|
||||
if b&0xF8 == 0xF0 {
|
||||
return 4
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func copy_bytes(dest []byte, dest_pos *int, src []byte, src_pos *int) {
|
||||
w := width(src[*src_pos])
|
||||
switch w {
|
||||
case 4:
|
||||
dest[*dest_pos+3] = src[*src_pos+3]
|
||||
fallthrough
|
||||
case 3:
|
||||
dest[*dest_pos+2] = src[*src_pos+2]
|
||||
fallthrough
|
||||
case 2:
|
||||
dest[*dest_pos+1] = src[*src_pos+1]
|
||||
fallthrough
|
||||
case 1:
|
||||
dest[*dest_pos] = src[*src_pos]
|
||||
default:
|
||||
panic("invalid width")
|
||||
}
|
||||
*dest_pos += w
|
||||
*src_pos += w
|
||||
}
|
||||
|
||||
// /*
|
||||
// * Check if the character at the specified position is an alphabetical
|
||||
// * character, a digit, '_', or '-'.
|
||||
// */
|
||||
|
||||
func is_alpha(b byte) bool {
|
||||
return (b >= '0' && b <= '9') ||
|
||||
(b >= 'A' && b <= 'Z') ||
|
||||
(b >= 'a' && b <= 'z') ||
|
||||
b == '_' || b == '-'
|
||||
}
|
||||
|
||||
// /*
|
||||
// * Check if the character at the specified position is a digit.
|
||||
// */
|
||||
//
|
||||
func is_digit(b byte) bool {
|
||||
return b >= '0' && b <= '9'
|
||||
}
|
||||
|
||||
// /*
|
||||
// * Get the value of a digit.
|
||||
// */
|
||||
//
|
||||
func as_digit(b byte) int {
|
||||
return int(b) - '0'
|
||||
}
|
||||
|
||||
// /*
|
||||
// * Check if the character at the specified position is a hex-digit.
|
||||
// */
|
||||
//
|
||||
func is_hex(b byte) bool {
|
||||
return (b >= '0' && b <= '9') ||
|
||||
(b >= 'A' && b <= 'F') ||
|
||||
(b >= 'a' && b <= 'f')
|
||||
}
|
||||
|
||||
//
|
||||
// /*
|
||||
// * Get the value of a hex-digit.
|
||||
// */
|
||||
//
|
||||
func as_hex(b byte) int {
|
||||
if b >= 'A' && b <= 'F' {
|
||||
return int(b) - 'A' + 10
|
||||
} else if b >= 'a' && b <= 'f' {
|
||||
return int(b) - 'a' + 10
|
||||
}
|
||||
return int(b) - '0'
|
||||
}
|
||||
|
||||
// #define AS_HEX_AT(string,offset) \
|
||||
// (((string).pointer[offset] >= (yaml_char_t) 'A' && \
|
||||
// (string).pointer[offset] <= (yaml_char_t) 'F') ? \
|
||||
// ((string).pointer[offset] - (yaml_char_t) 'A' + 10) : \
|
||||
// ((string).pointer[offset] >= (yaml_char_t) 'a' && \
|
||||
// (string).pointer[offset] <= (yaml_char_t) 'f') ? \
|
||||
// ((string).pointer[offset] - (yaml_char_t) 'a' + 10) : \
|
||||
// ((string).pointer[offset] - (yaml_char_t) '0'))
|
||||
|
||||
// /*
|
||||
// * Check if the character is a line break, space, tab, or NUL.
|
||||
// */
|
||||
func is_blankz_at(b []byte, i int) bool {
|
||||
return is_blank(b[i]) || is_breakz_at(b, i)
|
||||
}
|
||||
|
||||
// /*
|
||||
// * Check if the character at the specified position is a line break.
|
||||
// */
|
||||
func is_break_at(b []byte, i int) bool {
|
||||
return b[i] == '\r' || /* CR (#xD)*/
|
||||
b[i] == '\n' || /* LF (#xA) */
|
||||
(b[i] == 0xC2 && b[i+1] == 0x85) || /* NEL (#x85) */
|
||||
(b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8) || /* LS (#x2028) */
|
||||
(b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) /* PS (#x2029) */
|
||||
}
|
||||
|
||||
func is_breakz_at(b []byte, i int) bool {
|
||||
return is_break_at(b, i) || is_z(b[i])
|
||||
}
|
||||
|
||||
func is_crlf_at(b []byte, i int) bool {
|
||||
return b[i] == '\r' && b[i+1] == '\n'
|
||||
}
|
||||
|
||||
// /*
|
||||
// * Check if the character at the specified position is NUL.
|
||||
// */
|
||||
func is_z(b byte) bool {
|
||||
return b == 0x0
|
||||
}
|
||||
|
||||
// /*
|
||||
// * Check if the character at the specified position is space.
|
||||
// */
|
||||
func is_space(b byte) bool {
|
||||
return b == ' '
|
||||
}
|
||||
|
||||
//
|
||||
// /*
|
||||
// * Check if the character at the specified position is tab.
|
||||
// */
|
||||
func is_tab(b byte) bool {
|
||||
return b == '\t'
|
||||
}
|
||||
|
||||
// /*
|
||||
// * Check if the character at the specified position is blank (space or tab).
|
||||
// */
|
||||
func is_blank(b byte) bool {
|
||||
return is_space(b) || is_tab(b)
|
||||
}
|
||||
|
||||
// /*
|
||||
// * Check if the character is ASCII.
|
||||
// */
|
||||
func is_ascii(b byte) bool {
|
||||
return b <= '\x7f'
|
||||
}
|
||||
|
||||
// /*
|
||||
// * Check if the character can be printed unescaped.
|
||||
// */
|
||||
func is_printable_at(b []byte, i int) bool {
|
||||
return ((b[i] == 0x0A) || /* . == #x0A */
|
||||
(b[i] >= 0x20 && b[i] <= 0x7E) || /* #x20 <= . <= #x7E */
|
||||
(b[i] == 0xC2 && b[i+1] >= 0xA0) || /* #0xA0 <= . <= #xD7FF */
|
||||
(b[i] > 0xC2 && b[i] < 0xED) ||
|
||||
(b[i] == 0xED && b[i+1] < 0xA0) ||
|
||||
(b[i] == 0xEE) ||
|
||||
(b[i] == 0xEF && /* && . != #xFEFF */
|
||||
!(b[i+1] == 0xBB && b[i+2] == 0xBF) &&
|
||||
!(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF))))
|
||||
}
|
||||
|
||||
func insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) {
|
||||
// collapse the slice
|
||||
if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) {
|
||||
if parser.tokens_head != len(parser.tokens) {
|
||||
// move the tokens down
|
||||
copy(parser.tokens, parser.tokens[parser.tokens_head:])
|
||||
}
|
||||
// readjust the length
|
||||
parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head]
|
||||
parser.tokens_head = 0
|
||||
}
|
||||
|
||||
parser.tokens = append(parser.tokens, *token)
|
||||
if pos < 0 {
|
||||
return
|
||||
}
|
||||
copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:])
|
||||
parser.tokens[parser.tokens_head+pos] = *token
|
||||
}
|
||||
|
||||
// /*
|
||||
// * Check if the character at the specified position is BOM.
|
||||
// */
|
||||
//
|
||||
func is_bom_at(b []byte, i int) bool {
|
||||
return b[i] == 0xEF && b[i+1] == 0xBB && b[i+2] == 0xBF
|
||||
}
|
||||
|
||||
//
|
||||
// #ifdef HAVE_CONFIG_H
|
||||
// #include <config.h>
|
||||
// #endif
|
||||
//
|
||||
// #include "./yaml.h"
|
||||
//
|
||||
// #include <assert.h>
|
||||
// #include <limits.h>
|
||||
//
|
||||
// /*
|
||||
// * Memory management.
|
||||
// */
|
||||
//
|
||||
// yaml_DECLARE(void *)
|
||||
// yaml_malloc(size_t size);
|
||||
//
|
||||
// yaml_DECLARE(void *)
|
||||
// yaml_realloc(void *ptr, size_t size);
|
||||
//
|
||||
// yaml_DECLARE(void)
|
||||
// yaml_free(void *ptr);
|
||||
//
|
||||
// yaml_DECLARE(yaml_char_t *)
|
||||
// yaml_strdup(const yaml_char_t *);
|
||||
//
|
||||
// /*
|
||||
// * Reader: Ensure that the buffer contains at least `length` characters.
|
||||
// */
|
||||
//
|
||||
// yaml_DECLARE(int)
|
||||
// yaml_parser_update_buffer(yaml_parser_t *parser, size_t length);
|
||||
//
|
||||
// /*
|
||||
// * Scanner: Ensure that the token stack contains at least one token ready.
|
||||
// */
|
||||
//
|
||||
// yaml_DECLARE(int)
|
||||
// yaml_parser_fetch_more_tokens(yaml_parser_t *parser);
|
||||
//
|
||||
// /*
|
||||
// * The size of the input raw buffer.
|
||||
// */
|
||||
//
|
||||
// #define INPUT_RAW_BUFFER_SIZE 16384
|
||||
//
|
||||
// /*
|
||||
// * The size of the input buffer.
|
||||
// *
|
||||
// * It should be possible to decode the whole raw buffer.
|
||||
// */
|
||||
//
|
||||
// #define INPUT_BUFFER_SIZE (INPUT_RAW_BUFFER_SIZE*3)
|
||||
//
|
||||
// /*
|
||||
// * The size of the output buffer.
|
||||
// */
|
||||
//
|
||||
// #define OUTPUT_BUFFER_SIZE 16384
|
||||
//
|
||||
// /*
|
||||
// * The size of the output raw buffer.
|
||||
// *
|
||||
// * It should be possible to encode the whole output buffer.
|
||||
// */
|
||||
//
|
||||
// #define OUTPUT_RAW_BUFFER_SIZE (OUTPUT_BUFFER_SIZE*2+2)
|
||||
//
|
||||
// /*
|
||||
// * The size of other stacks and queues.
|
||||
// */
|
||||
//
|
||||
// #define INITIAL_STACK_SIZE 16
|
||||
// #define INITIAL_QUEUE_SIZE 16
|
||||
// #define INITIAL_STRING_SIZE 16
|
||||
//
|
||||
// /*
|
||||
// * Buffer management.
|
||||
// */
|
||||
//
|
||||
// #define BUFFER_INIT(context,buffer,size) \
|
||||
// (((buffer).start = yaml_malloc(size)) ? \
|
||||
// ((buffer).last = (buffer).pointer = (buffer).start, \
|
||||
// (buffer).end = (buffer).start+(size), \
|
||||
// 1) : \
|
||||
// ((context)->error = yaml_MEMORY_ERROR, \
|
||||
// 0))
|
||||
//
|
||||
// #define BUFFER_DEL(context,buffer) \
|
||||
// (yaml_free((buffer).start), \
|
||||
// (buffer).start = (buffer).pointer = (buffer).end = 0)
|
||||
//
|
||||
// /*
|
||||
// * String management.
|
||||
// */
|
||||
//
|
||||
// typedef struct {
|
||||
// yaml_char_t *start;
|
||||
// yaml_char_t *end;
|
||||
// yaml_char_t *pointer;
|
||||
// } yaml_string_t;
|
||||
//
|
||||
// yaml_DECLARE(int)
|
||||
// yaml_string_extend(yaml_char_t **start,
|
||||
// yaml_char_t **pointer, yaml_char_t **end);
|
||||
//
|
||||
// yaml_DECLARE(int)
|
||||
// yaml_string_join(
|
||||
// yaml_char_t **a_start, yaml_char_t **a_pointer, yaml_char_t **a_end,
|
||||
// yaml_char_t **b_start, yaml_char_t **b_pointer, yaml_char_t **b_end);
|
||||
//
|
||||
// #define NULL_STRING { NULL, NULL, NULL }
|
||||
//
|
||||
// #define STRING(string,length) { (string), (string)+(length), (string) }
|
||||
//
|
||||
// #define STRING_ASSIGN(value,string,length) \
|
||||
// ((value).start = (string), \
|
||||
// (value).end = (string)+(length), \
|
||||
// (value).pointer = (string))
|
||||
//
|
||||
// #define STRING_INIT(context,string,size) \
|
||||
// (((string).start = yaml_malloc(size)) ? \
|
||||
// ((string).pointer = (string).start, \
|
||||
// (string).end = (string).start+(size), \
|
||||
// memset((string).start, 0, (size)), \
|
||||
// 1) : \
|
||||
// ((context)->error = yaml_MEMORY_ERROR, \
|
||||
// 0))
|
||||
//
|
||||
// #define STRING_DEL(context,string) \
|
||||
// (yaml_free((string).start), \
|
||||
// (string).start = (string).pointer = (string).end = 0)
|
||||
//
|
||||
// #define STRING_EXTEND(context,string) \
|
||||
// (((string).pointer+5 < (string).end) \
|
||||
// || yaml_string_extend(&(string).start, \
|
||||
// &(string).pointer, &(string).end))
|
||||
//
|
||||
// #define CLEAR(context,string) \
|
||||
// ((string).pointer = (string).start, \
|
||||
// memset((string).start, 0, (string).end-(string).start))
|
||||
//
|
||||
// #define JOIN(context,string_a,string_b) \
|
||||
// ((yaml_string_join(&(string_a).start, &(string_a).pointer, \
|
||||
// &(string_a).end, &(string_b).start, \
|
||||
// &(string_b).pointer, &(string_b).end)) ? \
|
||||
// ((string_b).pointer = (string_b).start, \
|
||||
// 1) : \
|
||||
// ((context)->error = yaml_MEMORY_ERROR, \
|
||||
// 0))
|
||||
//
|
||||
// /*
|
||||
// * String check operations.
|
||||
// */
|
||||
//
|
||||
// /*
|
||||
// * Check the octet at the specified position.
|
||||
// */
|
||||
//
|
||||
// #define CHECK_AT(string,octet,offset) \
|
||||
// ((string).pointer[offset] == (yaml_char_t)(octet))
|
||||
//
|
||||
// /*
|
||||
// * Check the current octet in the buffer.
|
||||
// */
|
||||
//
|
||||
// #define CHECK(string,octet) CHECK_AT((string),(octet),0)
|
||||
//
|
||||
// /*
|
||||
// * Check if the character at the specified position is an alphabetical
|
||||
// * character, a digit, '_', or '-'.
|
||||
// */
|
||||
//
|
||||
// #define IS_ALPHA_AT(string,offset) \
|
||||
// (((string).pointer[offset] >= (yaml_char_t) '0' && \
|
||||
// (string).pointer[offset] <= (yaml_char_t) '9') || \
|
||||
// ((string).pointer[offset] >= (yaml_char_t) 'A' && \
|
||||
// (string).pointer[offset] <= (yaml_char_t) 'Z') || \
|
||||
// ((string).pointer[offset] >= (yaml_char_t) 'a' && \
|
||||
// (string).pointer[offset] <= (yaml_char_t) 'z') || \
|
||||
// (string).pointer[offset] == '_' || \
|
||||
// (string).pointer[offset] == '-')
|
||||
//
|
||||
// #define IS_ALPHA(string) IS_ALPHA_AT((string),0)
|
||||
//
|
||||
// /*
|
||||
// * Check if the character at the specified position is a digit.
|
||||
// */
|
||||
//
|
||||
// #define IS_DIGIT_AT(string,offset) \
|
||||
// (((string).pointer[offset] >= (yaml_char_t) '0' && \
|
||||
// (string).pointer[offset] <= (yaml_char_t) '9'))
|
||||
//
|
||||
// #define IS_DIGIT(string) IS_DIGIT_AT((string),0)
|
||||
//
|
||||
// /*
|
||||
// * Get the value of a digit.
|
||||
// */
|
||||
//
|
||||
// #define AS_DIGIT_AT(string,offset) \
|
||||
// ((string).pointer[offset] - (yaml_char_t) '0')
|
||||
//
|
||||
// #define AS_DIGIT(string) AS_DIGIT_AT((string),0)
|
||||
//
|
||||
// /*
|
||||
// * Check if the character at the specified position is a hex-digit.
|
||||
// */
|
||||
//
|
||||
// #define IS_HEX_AT(string,offset) \
|
||||
// (((string).pointer[offset] >= (yaml_char_t) '0' && \
|
||||
// (string).pointer[offset] <= (yaml_char_t) '9') || \
|
||||
// ((string).pointer[offset] >= (yaml_char_t) 'A' && \
|
||||
// (string).pointer[offset] <= (yaml_char_t) 'F') || \
|
||||
// ((string).pointer[offset] >= (yaml_char_t) 'a' && \
|
||||
// (string).pointer[offset] <= (yaml_char_t) 'f'))
|
||||
//
|
||||
// #define IS_HEX(string) IS_HEX_AT((string),0)
|
||||
//
|
||||
// /*
|
||||
// * Get the value of a hex-digit.
|
||||
// */
|
||||
//
|
||||
// #define AS_HEX_AT(string,offset) \
|
||||
// (((string).pointer[offset] >= (yaml_char_t) 'A' && \
|
||||
// (string).pointer[offset] <= (yaml_char_t) 'F') ? \
|
||||
// ((string).pointer[offset] - (yaml_char_t) 'A' + 10) : \
|
||||
// ((string).pointer[offset] >= (yaml_char_t) 'a' && \
|
||||
// (string).pointer[offset] <= (yaml_char_t) 'f') ? \
|
||||
// ((string).pointer[offset] - (yaml_char_t) 'a' + 10) : \
|
||||
// ((string).pointer[offset] - (yaml_char_t) '0'))
|
||||
//
|
||||
// #define AS_HEX(string) AS_HEX_AT((string),0)
|
||||
//
|
||||
// /*
|
||||
// * Check if the character is ASCII.
|
||||
// */
|
||||
//
|
||||
// #define IS_ASCII_AT(string,offset) \
|
||||
// ((string).pointer[offset] <= (yaml_char_t) '\x7F')
|
||||
//
|
||||
// #define IS_ASCII(string) IS_ASCII_AT((string),0)
|
||||
//
|
||||
// /*
|
||||
// * Check if the character can be printed unescaped.
|
||||
// */
|
||||
//
|
||||
// #define IS_PRINTABLE_AT(string,offset) \
|
||||
// (((string).pointer[offset] == 0x0A) /* . == #x0A */ \
|
||||
// || ((string).pointer[offset] >= 0x20 /* #x20 <= . <= #x7E */ \
|
||||
// && (string).pointer[offset] <= 0x7E) \
|
||||
// || ((string).pointer[offset] == 0xC2 /* #0xA0 <= . <= #xD7FF */ \
|
||||
// && (string).pointer[offset+1] >= 0xA0) \
|
||||
// || ((string).pointer[offset] > 0xC2 \
|
||||
// && (string).pointer[offset] < 0xED) \
|
||||
// || ((string).pointer[offset] == 0xED \
|
||||
// && (string).pointer[offset+1] < 0xA0) \
|
||||
// || ((string).pointer[offset] == 0xEE) \
|
||||
// || ((string).pointer[offset] == 0xEF /* #xE000 <= . <= #xFFFD */ \
|
||||
// && !((string).pointer[offset+1] == 0xBB /* && . != #xFEFF */ \
|
||||
// && (string).pointer[offset+2] == 0xBF) \
|
||||
// && !((string).pointer[offset+1] == 0xBF \
|
||||
// && ((string).pointer[offset+2] == 0xBE \
|
||||
// || (string).pointer[offset+2] == 0xBF))))
|
||||
//
|
||||
// #define IS_PRINTABLE(string) IS_PRINTABLE_AT((string),0)
|
||||
//
|
||||
// /*
|
||||
// * Check if the character at the specified position is NUL.
|
||||
// */
|
||||
//
|
||||
// #define IS_Z_AT(string,offset) CHECK_AT((string),'\0',(offset))
|
||||
//
|
||||
// #define IS_Z(string) IS_Z_AT((string),0)
|
||||
//
|
||||
// /*
|
||||
// * Check if the character at the specified position is BOM.
|
||||
// */
|
||||
//
|
||||
// #define IS_BOM_AT(string,offset) \
|
||||
// (CHECK_AT((string),'\xEF',(offset)) \
|
||||
// && CHECK_AT((string),'\xBB',(offset)+1) \
|
||||
// && CHECK_AT((string),'\xBF',(offset)+2)) /* BOM (#xFEFF) */
|
||||
//
|
||||
// #define IS_BOM(string) IS_BOM_AT(string,0)
|
||||
//
|
||||
// /*
|
||||
// * Check if the character at the specified position is space.
|
||||
// */
|
||||
//
|
||||
// #define IS_SPACE_AT(string,offset) CHECK_AT((string),' ',(offset))
|
||||
//
|
||||
// #define IS_SPACE(string) IS_SPACE_AT((string),0)
|
||||
//
|
||||
// /*
|
||||
// * Check if the character at the specified position is tab.
|
||||
// */
|
||||
//
|
||||
// #define IS_TAB_AT(string,offset) CHECK_AT((string),'\t',(offset))
|
||||
//
|
||||
// #define IS_TAB(string) IS_TAB_AT((string),0)
|
||||
//
|
||||
// /*
|
||||
// * Check if the character at the specified position is blank (space or tab).
|
||||
// */
|
||||
//
|
||||
// #define IS_BLANK_AT(string,offset) \
|
||||
// (IS_SPACE_AT((string),(offset)) || IS_TAB_AT((string),(offset)))
|
||||
//
|
||||
// #define IS_BLANK(string) IS_BLANK_AT((string),0)
|
||||
//
|
||||
// /*
|
||||
// * Check if the character at the specified position is a line break.
|
||||
// */
|
||||
//
|
||||
// #define IS_BREAK_AT(string,offset) \
|
||||
// (CHECK_AT((string),'\r',(offset)) /* CR (#xD)*/ \
|
||||
// || CHECK_AT((string),'\n',(offset)) /* LF (#xA) */ \
|
||||
// || (CHECK_AT((string),'\xC2',(offset)) \
|
||||
// && CHECK_AT((string),'\x85',(offset)+1)) /* NEL (#x85) */ \
|
||||
// || (CHECK_AT((string),'\xE2',(offset)) \
|
||||
// && CHECK_AT((string),'\x80',(offset)+1) \
|
||||
// && CHECK_AT((string),'\xA8',(offset)+2)) /* LS (#x2028) */ \
|
||||
// || (CHECK_AT((string),'\xE2',(offset)) \
|
||||
// && CHECK_AT((string),'\x80',(offset)+1) \
|
||||
// && CHECK_AT((string),'\xA9',(offset)+2))) /* PS (#x2029) */
|
||||
//
|
||||
// #define IS_BREAK(string) IS_BREAK_AT((string),0)
|
||||
//
|
||||
// #define IS_CRLF_AT(string,offset) \
|
||||
// (CHECK_AT((string),'\r',(offset)) && CHECK_AT((string),'\n',(offset)+1))
|
||||
//
|
||||
// #define IS_CRLF(string) IS_CRLF_AT((string),0)
|
||||
//
|
||||
// /*
|
||||
// * Check if the character is a line break or NUL.
|
||||
// */
|
||||
//
|
||||
// #define IS_BREAKZ_AT(string,offset) \
|
||||
// (IS_BREAK_AT((string),(offset)) || IS_Z_AT((string),(offset)))
|
||||
//
|
||||
// #define IS_BREAKZ(string) IS_BREAKZ_AT((string),0)
|
||||
//
|
||||
// /*
|
||||
// * Check if the character is a line break, space, or NUL.
|
||||
// */
|
||||
//
|
||||
// #define IS_SPACEZ_AT(string,offset) \
|
||||
// (IS_SPACE_AT((string),(offset)) || IS_BREAKZ_AT((string),(offset)))
|
||||
//
|
||||
// #define IS_SPACEZ(string) IS_SPACEZ_AT((string),0)
|
||||
//
|
||||
// /*
|
||||
// * Check if the character is a line break, space, tab, or NUL.
|
||||
// */
|
||||
//
|
||||
// #define IS_BLANKZ_AT(string,offset) \
|
||||
// (IS_BLANK_AT((string),(offset)) || IS_BREAKZ_AT((string),(offset)))
|
||||
//
|
||||
// #define IS_BLANKZ(string) IS_BLANKZ_AT((string),0)
|
||||
//
|
||||
// /*
|
||||
// * Determine the width of the character.
|
||||
// */
|
||||
//
|
||||
// #define WIDTH_AT(string,offset) \
|
||||
// (((string).pointer[offset] & 0x80) == 0x00 ? 1 : \
|
||||
// ((string).pointer[offset] & 0xE0) == 0xC0 ? 2 : \
|
||||
// ((string).pointer[offset] & 0xF0) == 0xE0 ? 3 : \
|
||||
// ((string).pointer[offset] & 0xF8) == 0xF0 ? 4 : 0)
|
||||
//
|
||||
// #define WIDTH(string) WIDTH_AT((string),0)
|
||||
//
|
||||
// /*
|
||||
// * Move the string pointer to the next character.
|
||||
// */
|
||||
//
|
||||
// #define MOVE(string) ((string).pointer += WIDTH((string)))
|
||||
//
|
||||
// /*
|
||||
// * Copy a character and move the pointers of both strings.
|
||||
// */
|
||||
//
|
||||
// #define COPY(string_a,string_b) \
|
||||
// ((*(string_b).pointer & 0x80) == 0x00 ? \
|
||||
// (*((string_a).pointer++) = *((string_b).pointer++)) : \
|
||||
// (*(string_b).pointer & 0xE0) == 0xC0 ? \
|
||||
// (*((string_a).pointer++) = *((string_b).pointer++), \
|
||||
// *((string_a).pointer++) = *((string_b).pointer++)) : \
|
||||
// (*(string_b).pointer & 0xF0) == 0xE0 ? \
|
||||
// (*((string_a).pointer++) = *((string_b).pointer++), \
|
||||
// *((string_a).pointer++) = *((string_b).pointer++), \
|
||||
// *((string_a).pointer++) = *((string_b).pointer++)) : \
|
||||
// (*(string_b).pointer & 0xF8) == 0xF0 ? \
|
||||
// (*((string_a).pointer++) = *((string_b).pointer++), \
|
||||
// *((string_a).pointer++) = *((string_b).pointer++), \
|
||||
// *((string_a).pointer++) = *((string_b).pointer++), \
|
||||
// *((string_a).pointer++) = *((string_b).pointer++)) : 0)
|
||||
//
|
||||
// /*
|
||||
// * Stack and queue management.
|
||||
// */
|
||||
//
|
||||
// yaml_DECLARE(int)
|
||||
// yaml_stack_extend(void **start, void **top, void **end);
|
||||
//
|
||||
// yaml_DECLARE(int)
|
||||
// yaml_queue_extend(void **start, void **head, void **tail, void **end);
|
||||
//
|
||||
// #define STACK_INIT(context,stack,size) \
|
||||
// (((stack).start = yaml_malloc((size)*sizeof(*(stack).start))) ? \
|
||||
// ((stack).top = (stack).start, \
|
||||
// (stack).end = (stack).start+(size), \
|
||||
// 1) : \
|
||||
// ((context)->error = yaml_MEMORY_ERROR, \
|
||||
// 0))
|
||||
//
|
||||
// #define STACK_DEL(context,stack) \
|
||||
// (yaml_free((stack).start), \
|
||||
// (stack).start = (stack).top = (stack).end = 0)
|
||||
//
|
||||
// #define STACK_EMPTY(context,stack) \
|
||||
// ((stack).start == (stack).top)
|
||||
//
|
||||
// #define PUSH(context,stack,value) \
|
||||
// (((stack).top != (stack).end \
|
||||
// || yaml_stack_extend((void **)&(stack).start, \
|
||||
// (void **)&(stack).top, (void **)&(stack).end)) ? \
|
||||
// (*((stack).top++) = value, \
|
||||
// 1) : \
|
||||
// ((context)->error = yaml_MEMORY_ERROR, \
|
||||
// 0))
|
||||
//
|
||||
// #define POP(context,stack) \
|
||||
// (*(--(stack).top))
|
||||
//
|
||||
// #define QUEUE_INIT(context,queue,size) \
|
||||
// (((queue).start = yaml_malloc((size)*sizeof(*(queue).start))) ? \
|
||||
// ((queue).head = (queue).tail = (queue).start, \
|
||||
// (queue).end = (queue).start+(size), \
|
||||
// 1) : \
|
||||
// ((context)->error = yaml_MEMORY_ERROR, \
|
||||
// 0))
|
||||
//
|
||||
// #define QUEUE_DEL(context,queue) \
|
||||
// (yaml_free((queue).start), \
|
||||
// (queue).start = (queue).head = (queue).tail = (queue).end = 0)
|
||||
//
|
||||
// #define QUEUE_EMPTY(context,queue) \
|
||||
// ((queue).head == (queue).tail)
|
||||
//
|
||||
// #define ENQUEUE(context,queue,value) \
|
||||
// (((queue).tail != (queue).end \
|
||||
// || yaml_queue_extend((void **)&(queue).start, (void **)&(queue).head, \
|
||||
// (void **)&(queue).tail, (void **)&(queue).end)) ? \
|
||||
// (*((queue).tail++) = value, \
|
||||
// 1) : \
|
||||
// ((context)->error = yaml_MEMORY_ERROR, \
|
||||
// 0))
|
||||
//
|
||||
// #define DEQUEUE(context,queue) \
|
||||
// (*((queue).head++))
|
||||
//
|
||||
// #define QUEUE_INSERT(context,queue,index,value) \
|
||||
// (((queue).tail != (queue).end \
|
||||
// || yaml_queue_extend((void **)&(queue).start, (void **)&(queue).head, \
|
||||
// (void **)&(queue).tail, (void **)&(queue).end)) ? \
|
||||
// (memmove((queue).head+(index)+1,(queue).head+(index), \
|
||||
// ((queue).tail-(queue).head-(index))*sizeof(*(queue).start)), \
|
||||
// *((queue).head+(index)) = value, \
|
||||
// (queue).tail++, \
|
||||
// 1) : \
|
||||
// ((context)->error = yaml_MEMORY_ERROR, \
|
||||
// 0))
|
||||
//
|
||||
// /*
|
||||
// * Token initializers.
|
||||
// */
|
||||
//
|
||||
// #define TOKEN_INIT(token,token_type,token_start_mark,token_end_mark) \
|
||||
// (memset(&(token), 0, sizeof(yaml_token_t)), \
|
||||
// (token).type = (token_type), \
|
||||
// (token).start_mark = (token_start_mark), \
|
||||
// (token).end_mark = (token_end_mark))
|
||||
//
|
||||
// #define STREAM_START_TOKEN_INIT(token,token_encoding,start_mark,end_mark) \
|
||||
// (TOKEN_INIT((token),yaml_STREAM_START_TOKEN,(start_mark),(end_mark)), \
|
||||
// (token).data.stream_start.encoding = (token_encoding))
|
||||
//
|
||||
// #define STREAM_END_TOKEN_INIT(token,start_mark,end_mark) \
|
||||
// (TOKEN_INIT((token),yaml_STREAM_END_TOKEN,(start_mark),(end_mark)))
|
||||
//
|
||||
// #define ALIAS_TOKEN_INIT(token,token_value,start_mark,end_mark) \
|
||||
// (TOKEN_INIT((token),yaml_ALIAS_TOKEN,(start_mark),(end_mark)), \
|
||||
// (token).data.alias.value = (token_value))
|
||||
//
|
||||
// #define ANCHOR_TOKEN_INIT(token,token_value,start_mark,end_mark) \
|
||||
// (TOKEN_INIT((token),yaml_ANCHOR_TOKEN,(start_mark),(end_mark)), \
|
||||
// (token).data.anchor.value = (token_value))
|
||||
//
|
||||
// #define TAG_TOKEN_INIT(token,token_handle,token_suffix,start_mark,end_mark) \
|
||||
// (TOKEN_INIT((token),yaml_TAG_TOKEN,(start_mark),(end_mark)), \
|
||||
// (token).data.tag.handle = (token_handle), \
|
||||
// (token).data.tag.suffix = (token_suffix))
|
||||
//
|
||||
// #define SCALAR_TOKEN_INIT(token,token_value,token_length,token_style,start_mark,end_mark) \
|
||||
// (TOKEN_INIT((token),yaml_SCALAR_TOKEN,(start_mark),(end_mark)), \
|
||||
// (token).data.scalar.value = (token_value), \
|
||||
// (token).data.scalar.length = (token_length), \
|
||||
// (token).data.scalar.style = (token_style))
|
||||
//
|
||||
// #define VERSION_DIRECTIVE_TOKEN_INIT(token,token_major,token_minor,start_mark,end_mark) \
|
||||
// (TOKEN_INIT((token),yaml_VERSION_DIRECTIVE_TOKEN,(start_mark),(end_mark)), \
|
||||
// (token).data.version_directive.major = (token_major), \
|
||||
// (token).data.version_directive.minor = (token_minor))
|
||||
//
|
||||
// #define TAG_DIRECTIVE_TOKEN_INIT(token,token_handle,token_prefix,start_mark,end_mark) \
|
||||
// (TOKEN_INIT((token),yaml_TAG_DIRECTIVE_TOKEN,(start_mark),(end_mark)), \
|
||||
// (token).data.tag_directive.handle = (token_handle), \
|
||||
// (token).data.tag_directive.prefix = (token_prefix))
|
||||
//
|
||||
// /*
|
||||
// * Event initializers.
|
||||
// */
|
||||
//
|
||||
// #define EVENT_INIT(event,event_type,event_start_mark,event_end_mark) \
|
||||
// (memset(&(event), 0, sizeof(yaml_event_t)), \
|
||||
// (event).type = (event_type), \
|
||||
// (event).start_mark = (event_start_mark), \
|
||||
// (event).end_mark = (event_end_mark))
|
||||
//
|
||||
// #define STREAM_START_EVENT_INIT(event,event_encoding,start_mark,end_mark) \
|
||||
// (EVENT_INIT((event),yaml_STREAM_START_EVENT,(start_mark),(end_mark)), \
|
||||
// (event).data.stream_start.encoding = (event_encoding))
|
||||
//
|
||||
// #define STREAM_END_EVENT_INIT(event,start_mark,end_mark) \
|
||||
// (EVENT_INIT((event),yaml_STREAM_END_EVENT,(start_mark),(end_mark)))
|
||||
//
|
||||
// #define DOCUMENT_START_EVENT_INIT(event,event_version_directive, \
|
||||
// event_tag_directives_start,event_tag_directives_end,event_implicit,start_mark,end_mark) \
|
||||
// (EVENT_INIT((event),yaml_DOCUMENT_START_EVENT,(start_mark),(end_mark)), \
|
||||
// (event).data.document_start.version_directive = (event_version_directive), \
|
||||
// (event).data.document_start.tag_directives.start = (event_tag_directives_start), \
|
||||
// (event).data.document_start.tag_directives.end = (event_tag_directives_end), \
|
||||
// (event).data.document_start.implicit = (event_implicit))
|
||||
//
|
||||
// #define DOCUMENT_END_EVENT_INIT(event,event_implicit,start_mark,end_mark) \
|
||||
// (EVENT_INIT((event),yaml_DOCUMENT_END_EVENT,(start_mark),(end_mark)), \
|
||||
// (event).data.document_end.implicit = (event_implicit))
|
||||
//
|
||||
// #define ALIAS_EVENT_INIT(event,event_anchor,start_mark,end_mark) \
|
||||
// (EVENT_INIT((event),yaml_ALIAS_EVENT,(start_mark),(end_mark)), \
|
||||
// (event).data.alias.anchor = (event_anchor))
|
||||
//
|
||||
// #define SCALAR_EVENT_INIT(event,event_anchor,event_tag,event_value,event_length, \
|
||||
// event_plain_implicit, event_quoted_implicit,event_style,start_mark,end_mark) \
|
||||
// (EVENT_INIT((event),yaml_SCALAR_EVENT,(start_mark),(end_mark)), \
|
||||
// (event).data.scalar.anchor = (event_anchor), \
|
||||
// (event).data.scalar.tag = (event_tag), \
|
||||
// (event).data.scalar.value = (event_value), \
|
||||
// (event).data.scalar.length = (event_length), \
|
||||
// (event).data.scalar.plain_implicit = (event_plain_implicit), \
|
||||
// (event).data.scalar.quoted_implicit = (event_quoted_implicit), \
|
||||
// (event).data.scalar.style = (event_style))
|
||||
//
|
||||
// #define SEQUENCE_START_EVENT_INIT(event,event_anchor,event_tag, \
|
||||
// event_implicit,event_style,start_mark,end_mark) \
|
||||
// (EVENT_INIT((event),yaml_SEQUENCE_START_EVENT,(start_mark),(end_mark)), \
|
||||
// (event).data.sequence_start.anchor = (event_anchor), \
|
||||
// (event).data.sequence_start.tag = (event_tag), \
|
||||
// (event).data.sequence_start.implicit = (event_implicit), \
|
||||
// (event).data.sequence_start.style = (event_style))
|
||||
//
|
||||
// #define SEQUENCE_END_EVENT_INIT(event,start_mark,end_mark) \
|
||||
// (EVENT_INIT((event),yaml_SEQUENCE_END_EVENT,(start_mark),(end_mark)))
|
||||
//
|
||||
// #define MAPPING_START_EVENT_INIT(event,event_anchor,event_tag, \
|
||||
// event_implicit,event_style,start_mark,end_mark) \
|
||||
// (EVENT_INIT((event),yaml_MAPPING_START_EVENT,(start_mark),(end_mark)), \
|
||||
// (event).data.mapping_start.anchor = (event_anchor), \
|
||||
// (event).data.mapping_start.tag = (event_tag), \
|
||||
// (event).data.mapping_start.implicit = (event_implicit), \
|
||||
// (event).data.mapping_start.style = (event_style))
|
||||
//
|
||||
// #define MAPPING_END_EVENT_INIT(event,start_mark,end_mark) \
|
||||
// (EVENT_INIT((event),yaml_MAPPING_END_EVENT,(start_mark),(end_mark)))
|
||||
//
|
||||
// /*
|
||||
// * Document initializer.
|
||||
// */
|
||||
//
|
||||
// #define DOCUMENT_INIT(document,document_nodes_start,document_nodes_end, \
|
||||
// document_version_directive,document_tag_directives_start, \
|
||||
// document_tag_directives_end,document_start_implicit, \
|
||||
// document_end_implicit,document_start_mark,document_end_mark) \
|
||||
// (memset(&(document), 0, sizeof(yaml_document_t)), \
|
||||
// (document).nodes.start = (document_nodes_start), \
|
||||
// (document).nodes.end = (document_nodes_end), \
|
||||
// (document).nodes.top = (document_nodes_start), \
|
||||
// (document).version_directive = (document_version_directive), \
|
||||
// (document).tag_directives.start = (document_tag_directives_start), \
|
||||
// (document).tag_directives.end = (document_tag_directives_end), \
|
||||
// (document).start_implicit = (document_start_implicit), \
|
||||
// (document).end_implicit = (document_end_implicit), \
|
||||
// (document).start_mark = (document_start_mark), \
|
||||
// (document).end_mark = (document_end_mark))
|
||||
//
|
||||
// /*
|
||||
// * Node initializers.
|
||||
// */
|
||||
//
|
||||
// #define NODE_INIT(node,node_type,node_tag,node_start_mark,node_end_mark) \
|
||||
// (memset(&(node), 0, sizeof(yaml_node_t)), \
|
||||
// (node).type = (node_type), \
|
||||
// (node).tag = (node_tag), \
|
||||
// (node).start_mark = (node_start_mark), \
|
||||
// (node).end_mark = (node_end_mark))
|
||||
//
|
||||
// #define SCALAR_NODE_INIT(node,node_tag,node_value,node_length, \
|
||||
// node_style,start_mark,end_mark) \
|
||||
// (NODE_INIT((node),yaml_SCALAR_NODE,(node_tag),(start_mark),(end_mark)), \
|
||||
// (node).data.scalar.value = (node_value), \
|
||||
// (node).data.scalar.length = (node_length), \
|
||||
// (node).data.scalar.style = (node_style))
|
||||
//
|
||||
// #define SEQUENCE_NODE_INIT(node,node_tag,node_items_start,node_items_end, \
|
||||
// node_style,start_mark,end_mark) \
|
||||
// (NODE_INIT((node),yaml_SEQUENCE_NODE,(node_tag),(start_mark),(end_mark)), \
|
||||
// (node).data.sequence.items.start = (node_items_start), \
|
||||
// (node).data.sequence.items.end = (node_items_end), \
|
||||
// (node).data.sequence.items.top = (node_items_start), \
|
||||
// (node).data.sequence.style = (node_style))
|
||||
//
|
||||
// #define MAPPING_NODE_INIT(node,node_tag,node_pairs_start,node_pairs_end, \
|
||||
// node_style,start_mark,end_mark) \
|
||||
// (NODE_INIT((node),yaml_MAPPING_NODE,(node_tag),(start_mark),(end_mark)), \
|
||||
// (node).data.mapping.pairs.start = (node_pairs_start), \
|
||||
// (node).data.mapping.pairs.end = (node_pairs_end), \
|
||||
// (node).data.mapping.pairs.top = (node_pairs_start), \
|
||||
// (node).data.mapping.style = (node_style))
|
||||
//
|
||||
953
vendor/github.com/cloudfoundry-incubator/candiedyaml/yamlh.go
generated
vendored
953
vendor/github.com/cloudfoundry-incubator/candiedyaml/yamlh.go
generated
vendored
@@ -1,953 +0,0 @@
|
||||
/*
|
||||
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 candiedyaml
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
/** The version directive data. */
|
||||
type yaml_version_directive_t struct {
|
||||
major int // The major version number
|
||||
minor int // The minor version number
|
||||
}
|
||||
|
||||
/** The tag directive data. */
|
||||
type yaml_tag_directive_t struct {
|
||||
handle []byte // The tag handle
|
||||
prefix []byte // The tag prefix
|
||||
}
|
||||
|
||||
/** The stream encoding. */
|
||||
type yaml_encoding_t int
|
||||
|
||||
const (
|
||||
/** Let the parser choose the encoding. */
|
||||
yaml_ANY_ENCODING yaml_encoding_t = iota
|
||||
/** The defau lt UTF-8 encoding. */
|
||||
yaml_UTF8_ENCODING
|
||||
/** The UTF-16-LE encoding with BOM. */
|
||||
yaml_UTF16LE_ENCODING
|
||||
/** The UTF-16-BE encoding with BOM. */
|
||||
yaml_UTF16BE_ENCODING
|
||||
)
|
||||
|
||||
/** Line break types. */
|
||||
type yaml_break_t int
|
||||
|
||||
const (
|
||||
yaml_ANY_BREAK yaml_break_t = iota /** Let the parser choose the break type. */
|
||||
yaml_CR_BREAK /** Use CR for line breaks (Mac style). */
|
||||
yaml_LN_BREAK /** Use LN for line breaks (Unix style). */
|
||||
yaml_CRLN_BREAK /** Use CR LN for line breaks (DOS style). */
|
||||
)
|
||||
|
||||
/** Many bad things could happen with the parser and emitter. */
|
||||
type YAML_error_type_t int
|
||||
|
||||
const (
|
||||
/** No error is produced. */
|
||||
yaml_NO_ERROR YAML_error_type_t = iota
|
||||
|
||||
/** Cannot allocate or reallocate a block of memory. */
|
||||
yaml_MEMORY_ERROR
|
||||
|
||||
/** Cannot read or decode the input stream. */
|
||||
yaml_READER_ERROR
|
||||
/** Cannot scan the input stream. */
|
||||
yaml_SCANNER_ERROR
|
||||
/** Cannot parse the input stream. */
|
||||
yaml_PARSER_ERROR
|
||||
/** Cannot compose a YAML document. */
|
||||
yaml_COMPOSER_ERROR
|
||||
|
||||
/** Cannot write to the output stream. */
|
||||
yaml_WRITER_ERROR
|
||||
/** Cannot emit a YAML stream. */
|
||||
yaml_EMITTER_ERROR
|
||||
)
|
||||
|
||||
/** The pointer position. */
|
||||
type YAML_mark_t struct {
|
||||
/** The position index. */
|
||||
index int
|
||||
|
||||
/** The position line. */
|
||||
line int
|
||||
|
||||
/** The position column. */
|
||||
column int
|
||||
}
|
||||
|
||||
func (m YAML_mark_t) String() string {
|
||||
return fmt.Sprintf("line %d, column %d", m.line, m.column)
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @defgroup styles Node Styles
|
||||
* @{
|
||||
*/
|
||||
|
||||
type yaml_style_t int
|
||||
|
||||
/** Scalar styles. */
|
||||
type yaml_scalar_style_t yaml_style_t
|
||||
|
||||
const (
|
||||
/** Let the emitter choose the style. */
|
||||
yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = iota
|
||||
|
||||
/** The plain scalar style. */
|
||||
yaml_PLAIN_SCALAR_STYLE
|
||||
|
||||
/** The single-quoted scalar style. */
|
||||
yaml_SINGLE_QUOTED_SCALAR_STYLE
|
||||
/** The double-quoted scalar style. */
|
||||
yaml_DOUBLE_QUOTED_SCALAR_STYLE
|
||||
|
||||
/** The literal scalar style. */
|
||||
yaml_LITERAL_SCALAR_STYLE
|
||||
/** The folded scalar style. */
|
||||
yaml_FOLDED_SCALAR_STYLE
|
||||
)
|
||||
|
||||
/** Sequence styles. */
|
||||
type yaml_sequence_style_t yaml_style_t
|
||||
|
||||
const (
|
||||
/** Let the emitter choose the style. */
|
||||
yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota
|
||||
|
||||
/** The block sequence style. */
|
||||
yaml_BLOCK_SEQUENCE_STYLE
|
||||
/** The flow sequence style. */
|
||||
yaml_FLOW_SEQUENCE_STYLE
|
||||
)
|
||||
|
||||
/** Mapping styles. */
|
||||
type yaml_mapping_style_t yaml_style_t
|
||||
|
||||
const (
|
||||
/** Let the emitter choose the style. */
|
||||
yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota
|
||||
|
||||
/** The block mapping style. */
|
||||
yaml_BLOCK_MAPPING_STYLE
|
||||
/** The flow mapping style. */
|
||||
yaml_FLOW_MAPPING_STYLE
|
||||
|
||||
/* yaml_FLOW_SET_MAPPING_STYLE */
|
||||
)
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @defgroup tokens Tokens
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Token types. */
|
||||
type yaml_token_type_t int
|
||||
|
||||
const (
|
||||
/** An empty token. */
|
||||
yaml_NO_TOKEN yaml_token_type_t = iota
|
||||
|
||||
/** A STREAM-START token. */
|
||||
yaml_STREAM_START_TOKEN
|
||||
/** A STREAM-END token. */
|
||||
yaml_STREAM_END_TOKEN
|
||||
|
||||
/** A VERSION-DIRECTIVE token. */
|
||||
yaml_VERSION_DIRECTIVE_TOKEN
|
||||
/** A TAG-DIRECTIVE token. */
|
||||
yaml_TAG_DIRECTIVE_TOKEN
|
||||
/** A DOCUMENT-START token. */
|
||||
yaml_DOCUMENT_START_TOKEN
|
||||
/** A DOCUMENT-END token. */
|
||||
yaml_DOCUMENT_END_TOKEN
|
||||
|
||||
/** A BLOCK-SEQUENCE-START token. */
|
||||
yaml_BLOCK_SEQUENCE_START_TOKEN
|
||||
/** A BLOCK-SEQUENCE-END token. */
|
||||
yaml_BLOCK_MAPPING_START_TOKEN
|
||||
/** A BLOCK-END token. */
|
||||
yaml_BLOCK_END_TOKEN
|
||||
|
||||
/** A FLOW-SEQUENCE-START token. */
|
||||
yaml_FLOW_SEQUENCE_START_TOKEN
|
||||
/** A FLOW-SEQUENCE-END token. */
|
||||
yaml_FLOW_SEQUENCE_END_TOKEN
|
||||
/** A FLOW-MAPPING-START token. */
|
||||
yaml_FLOW_MAPPING_START_TOKEN
|
||||
/** A FLOW-MAPPING-END token. */
|
||||
yaml_FLOW_MAPPING_END_TOKEN
|
||||
|
||||
/** A BLOCK-ENTRY token. */
|
||||
yaml_BLOCK_ENTRY_TOKEN
|
||||
/** A FLOW-ENTRY token. */
|
||||
yaml_FLOW_ENTRY_TOKEN
|
||||
/** A KEY token. */
|
||||
yaml_KEY_TOKEN
|
||||
/** A VALUE token. */
|
||||
yaml_VALUE_TOKEN
|
||||
|
||||
/** An ALIAS token. */
|
||||
yaml_ALIAS_TOKEN
|
||||
/** An ANCHOR token. */
|
||||
yaml_ANCHOR_TOKEN
|
||||
/** A TAG token. */
|
||||
yaml_TAG_TOKEN
|
||||
/** A SCALAR token. */
|
||||
yaml_SCALAR_TOKEN
|
||||
)
|
||||
|
||||
/** The token structure. */
|
||||
type yaml_token_t struct {
|
||||
|
||||
/** The token type. */
|
||||
token_type yaml_token_type_t
|
||||
|
||||
/** The token data. */
|
||||
/** The stream start (for @c yaml_STREAM_START_TOKEN). */
|
||||
encoding yaml_encoding_t
|
||||
|
||||
/** The alias (for @c yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN,yaml_TAG_TOKEN ). */
|
||||
/** The anchor (for @c ). */
|
||||
/** The scalar value (for @c ). */
|
||||
value []byte
|
||||
|
||||
/** The tag suffix. */
|
||||
suffix []byte
|
||||
|
||||
/** The scalar value (for @c yaml_SCALAR_TOKEN). */
|
||||
/** The scalar style. */
|
||||
style yaml_scalar_style_t
|
||||
|
||||
/** The version directive (for @c yaml_VERSION_DIRECTIVE_TOKEN). */
|
||||
version_directive yaml_version_directive_t
|
||||
|
||||
/** The tag directive (for @c yaml_TAG_DIRECTIVE_TOKEN). */
|
||||
prefix []byte
|
||||
|
||||
/** The beginning of the token. */
|
||||
start_mark YAML_mark_t
|
||||
/** The end of the token. */
|
||||
end_mark YAML_mark_t
|
||||
|
||||
major, minor int
|
||||
}
|
||||
|
||||
/**
|
||||
* @defgroup events Events
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Event types. */
|
||||
type yaml_event_type_t int
|
||||
|
||||
const (
|
||||
/** An empty event. */
|
||||
yaml_NO_EVENT yaml_event_type_t = iota
|
||||
|
||||
/** A STREAM-START event. */
|
||||
yaml_STREAM_START_EVENT
|
||||
/** A STREAM-END event. */
|
||||
yaml_STREAM_END_EVENT
|
||||
|
||||
/** A DOCUMENT-START event. */
|
||||
yaml_DOCUMENT_START_EVENT
|
||||
/** A DOCUMENT-END event. */
|
||||
yaml_DOCUMENT_END_EVENT
|
||||
|
||||
/** An ALIAS event. */
|
||||
yaml_ALIAS_EVENT
|
||||
/** A SCALAR event. */
|
||||
yaml_SCALAR_EVENT
|
||||
|
||||
/** A SEQUENCE-START event. */
|
||||
yaml_SEQUENCE_START_EVENT
|
||||
/** A SEQUENCE-END event. */
|
||||
yaml_SEQUENCE_END_EVENT
|
||||
|
||||
/** A MAPPING-START event. */
|
||||
yaml_MAPPING_START_EVENT
|
||||
/** A MAPPING-END event. */
|
||||
yaml_MAPPING_END_EVENT
|
||||
)
|
||||
|
||||
/** The event structure. */
|
||||
type yaml_event_t struct {
|
||||
|
||||
/** The event type. */
|
||||
event_type yaml_event_type_t
|
||||
|
||||
/** The stream parameters (for @c yaml_STREAM_START_EVENT). */
|
||||
encoding yaml_encoding_t
|
||||
|
||||
/** The document parameters (for @c yaml_DOCUMENT_START_EVENT). */
|
||||
version_directive *yaml_version_directive_t
|
||||
|
||||
/** The beginning and end of the tag directives list. */
|
||||
tag_directives []yaml_tag_directive_t
|
||||
|
||||
/** The document parameters (for @c yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT,yaml_MAPPING_START_EVENT). */
|
||||
/** Is the document indicator implicit? */
|
||||
implicit bool
|
||||
|
||||
/** The alias parameters (for @c yaml_ALIAS_EVENT,yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). */
|
||||
/** The anchor. */
|
||||
anchor []byte
|
||||
|
||||
/** The scalar parameters (for @c yaml_SCALAR_EVENT,yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). */
|
||||
/** The tag. */
|
||||
tag []byte
|
||||
/** The scalar value. */
|
||||
value []byte
|
||||
|
||||
/** Is the tag optional for the plain style? */
|
||||
plain_implicit bool
|
||||
/** Is the tag optional for any non-plain style? */
|
||||
quoted_implicit bool
|
||||
|
||||
/** The sequence parameters (for @c yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). */
|
||||
/** The sequence style. */
|
||||
/** The scalar style. */
|
||||
style yaml_style_t
|
||||
|
||||
/** The beginning of the event. */
|
||||
start_mark, end_mark YAML_mark_t
|
||||
}
|
||||
|
||||
/**
|
||||
* @defgroup nodes Nodes
|
||||
* @{
|
||||
*/
|
||||
|
||||
const (
|
||||
/** The tag @c !!null with the only possible value: @c null. */
|
||||
yaml_NULL_TAG = "tag:yaml.org,2002:null"
|
||||
/** The tag @c !!bool with the values: @c true and @c falce. */
|
||||
yaml_BOOL_TAG = "tag:yaml.org,2002:bool"
|
||||
/** The tag @c !!str for string values. */
|
||||
yaml_STR_TAG = "tag:yaml.org,2002:str"
|
||||
/** The tag @c !!int for integer values. */
|
||||
yaml_INT_TAG = "tag:yaml.org,2002:int"
|
||||
/** The tag @c !!float for float values. */
|
||||
yaml_FLOAT_TAG = "tag:yaml.org,2002:float"
|
||||
/** The tag @c !!timestamp for date and time values. */
|
||||
yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp"
|
||||
|
||||
/** The tag @c !!seq is used to denote sequences. */
|
||||
yaml_SEQ_TAG = "tag:yaml.org,2002:seq"
|
||||
/** The tag @c !!map is used to denote mapping. */
|
||||
yaml_MAP_TAG = "tag:yaml.org,2002:map"
|
||||
|
||||
/** The default scalar tag is @c !!str. */
|
||||
yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG
|
||||
/** The default sequence tag is @c !!seq. */
|
||||
yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG
|
||||
/** The default mapping tag is @c !!map. */
|
||||
yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG
|
||||
|
||||
yaml_BINARY_TAG = "tag:yaml.org,2002:binary"
|
||||
)
|
||||
|
||||
/** Node types. */
|
||||
type yaml_node_type_t int
|
||||
|
||||
const (
|
||||
/** An empty node. */
|
||||
yaml_NO_NODE yaml_node_type_t = iota
|
||||
|
||||
/** A scalar node. */
|
||||
yaml_SCALAR_NODE
|
||||
/** A sequence node. */
|
||||
yaml_SEQUENCE_NODE
|
||||
/** A mapping node. */
|
||||
yaml_MAPPING_NODE
|
||||
)
|
||||
|
||||
/** An element of a sequence node. */
|
||||
type yaml_node_item_t int
|
||||
|
||||
/** An element of a mapping node. */
|
||||
type yaml_node_pair_t struct {
|
||||
/** The key of the element. */
|
||||
key int
|
||||
/** The value of the element. */
|
||||
value int
|
||||
}
|
||||
|
||||
/** The node structure. */
|
||||
type yaml_node_t struct {
|
||||
|
||||
/** The node type. */
|
||||
node_type yaml_node_type_t
|
||||
|
||||
/** The node tag. */
|
||||
tag []byte
|
||||
|
||||
/** The scalar parameters (for @c yaml_SCALAR_NODE). */
|
||||
scalar struct {
|
||||
/** The scalar value. */
|
||||
value []byte
|
||||
/** The scalar style. */
|
||||
style yaml_scalar_style_t
|
||||
}
|
||||
|
||||
/** The sequence parameters (for @c yaml_SEQUENCE_NODE). */
|
||||
sequence struct {
|
||||
/** The stack of sequence items. */
|
||||
items []yaml_node_item_t
|
||||
/** The sequence style. */
|
||||
style yaml_sequence_style_t
|
||||
}
|
||||
|
||||
/** The mapping parameters (for @c yaml_MAPPING_NODE). */
|
||||
mapping struct {
|
||||
/** The stack of mapping pairs (key, value). */
|
||||
pairs []yaml_node_pair_t
|
||||
/** The mapping style. */
|
||||
style yaml_mapping_style_t
|
||||
}
|
||||
|
||||
/** The beginning of the node. */
|
||||
start_mark YAML_mark_t
|
||||
/** The end of the node. */
|
||||
end_mark YAML_mark_t
|
||||
}
|
||||
|
||||
/** The document structure. */
|
||||
type yaml_document_t struct {
|
||||
|
||||
/** The document nodes. */
|
||||
nodes []yaml_node_t
|
||||
|
||||
/** The version directive. */
|
||||
version_directive *yaml_version_directive_t
|
||||
|
||||
/** The list of tag directives. */
|
||||
tags []yaml_tag_directive_t
|
||||
|
||||
/** Is the document start indicator implicit? */
|
||||
start_implicit bool
|
||||
/** Is the document end indicator implicit? */
|
||||
end_implicit bool
|
||||
|
||||
/** The beginning of the document. */
|
||||
start_mark YAML_mark_t
|
||||
/** The end of the document. */
|
||||
end_mark YAML_mark_t
|
||||
}
|
||||
|
||||
/**
|
||||
* The prototype of a read handler.
|
||||
*
|
||||
* The read handler is called when the parser needs to read more bytes from the
|
||||
* source. The handler should write not more than @a size bytes to the @a
|
||||
* buffer. The number of written bytes should be set to the @a length variable.
|
||||
*
|
||||
* @param[in,out] data A pointer to an application data specified by
|
||||
* yaml_parser_set_input().
|
||||
* @param[out] buffer The buffer to write the data from the source.
|
||||
* @param[in] size The size of the buffer.
|
||||
* @param[out] size_read The actual number of bytes read from the source.
|
||||
*
|
||||
* @returns On success, the handler should return @c 1. If the handler failed,
|
||||
* the returned value should be @c 0. On EOF, the handler should set the
|
||||
* @a size_read to @c 0 and return @c 1.
|
||||
*/
|
||||
|
||||
type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error)
|
||||
|
||||
/**
|
||||
* This structure holds information about a potential simple key.
|
||||
*/
|
||||
|
||||
type yaml_simple_key_t struct {
|
||||
/** Is a simple key possible? */
|
||||
possible bool
|
||||
|
||||
/** Is a simple key required? */
|
||||
required bool
|
||||
|
||||
/** The number of the token. */
|
||||
token_number int
|
||||
|
||||
/** The position mark. */
|
||||
mark YAML_mark_t
|
||||
}
|
||||
|
||||
/**
|
||||
* The states of the parser.
|
||||
*/
|
||||
type yaml_parser_state_t int
|
||||
|
||||
const (
|
||||
/** Expect STREAM-START. */
|
||||
yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota
|
||||
/** Expect the beginning of an implicit document. */
|
||||
yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE
|
||||
/** Expect DOCUMENT-START. */
|
||||
yaml_PARSE_DOCUMENT_START_STATE
|
||||
/** Expect the content of a document. */
|
||||
yaml_PARSE_DOCUMENT_CONTENT_STATE
|
||||
/** Expect DOCUMENT-END. */
|
||||
yaml_PARSE_DOCUMENT_END_STATE
|
||||
/** Expect a block node. */
|
||||
yaml_PARSE_BLOCK_NODE_STATE
|
||||
/** Expect a block node or indentless sequence. */
|
||||
yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE
|
||||
/** Expect a flow node. */
|
||||
yaml_PARSE_FLOW_NODE_STATE
|
||||
/** Expect the first entry of a block sequence. */
|
||||
yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE
|
||||
/** Expect an entry of a block sequence. */
|
||||
yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE
|
||||
/** Expect an entry of an indentless sequence. */
|
||||
yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
|
||||
/** Expect the first key of a block mapping. */
|
||||
yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE
|
||||
/** Expect a block mapping key. */
|
||||
yaml_PARSE_BLOCK_MAPPING_KEY_STATE
|
||||
/** Expect a block mapping value. */
|
||||
yaml_PARSE_BLOCK_MAPPING_VALUE_STATE
|
||||
/** Expect the first entry of a flow sequence. */
|
||||
yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE
|
||||
/** Expect an entry of a flow sequence. */
|
||||
yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE
|
||||
/** Expect a key of an ordered mapping. */
|
||||
yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE
|
||||
/** Expect a value of an ordered mapping. */
|
||||
yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE
|
||||
/** Expect the and of an ordered mapping entry. */
|
||||
yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE
|
||||
/** Expect the first key of a flow mapping. */
|
||||
yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE
|
||||
/** Expect a key of a flow mapping. */
|
||||
yaml_PARSE_FLOW_MAPPING_KEY_STATE
|
||||
/** Expect a value of a flow mapping. */
|
||||
yaml_PARSE_FLOW_MAPPING_VALUE_STATE
|
||||
/** Expect an empty value of a flow mapping. */
|
||||
yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE
|
||||
/** Expect nothing. */
|
||||
yaml_PARSE_END_STATE
|
||||
)
|
||||
|
||||
/**
|
||||
* This structure holds aliases data.
|
||||
*/
|
||||
|
||||
type yaml_alias_data_t struct {
|
||||
/** The anchor. */
|
||||
anchor []byte
|
||||
/** The node id. */
|
||||
index int
|
||||
/** The anchor mark. */
|
||||
mark YAML_mark_t
|
||||
}
|
||||
|
||||
/**
|
||||
* The parser structure.
|
||||
*
|
||||
* All members are internal. Manage the structure using the @c yaml_parser_
|
||||
* family of functions.
|
||||
*/
|
||||
|
||||
type yaml_parser_t struct {
|
||||
|
||||
/**
|
||||
* @name Error handling
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Error type. */
|
||||
error YAML_error_type_t
|
||||
/** Error description. */
|
||||
problem string
|
||||
/** The byte about which the problem occured. */
|
||||
problem_offset int
|
||||
/** The problematic value (@c -1 is none). */
|
||||
problem_value int
|
||||
/** The problem position. */
|
||||
problem_mark YAML_mark_t
|
||||
/** The error context. */
|
||||
context string
|
||||
/** The context position. */
|
||||
context_mark YAML_mark_t
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @name Reader stuff
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Read handler. */
|
||||
read_handler yaml_read_handler_t
|
||||
|
||||
/** Reader input data. */
|
||||
input_reader io.Reader
|
||||
input []byte
|
||||
input_pos int
|
||||
|
||||
/** EOF flag */
|
||||
eof bool
|
||||
|
||||
/** The working buffer. */
|
||||
buffer []byte
|
||||
buffer_pos int
|
||||
|
||||
/* The number of unread characters in the buffer. */
|
||||
unread int
|
||||
|
||||
/** The raw buffer. */
|
||||
raw_buffer []byte
|
||||
raw_buffer_pos int
|
||||
|
||||
/** The input encoding. */
|
||||
encoding yaml_encoding_t
|
||||
|
||||
/** The offset of the current position (in bytes). */
|
||||
offset int
|
||||
|
||||
/** The mark of the current position. */
|
||||
mark YAML_mark_t
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @name Scanner stuff
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Have we started to scan the input stream? */
|
||||
stream_start_produced bool
|
||||
|
||||
/** Have we reached the end of the input stream? */
|
||||
stream_end_produced bool
|
||||
|
||||
/** The number of unclosed '[' and '{' indicators. */
|
||||
flow_level int
|
||||
|
||||
/** The tokens queue. */
|
||||
tokens []yaml_token_t
|
||||
tokens_head int
|
||||
|
||||
/** The number of tokens fetched from the queue. */
|
||||
tokens_parsed int
|
||||
|
||||
/* Does the tokens queue contain a token ready for dequeueing. */
|
||||
token_available bool
|
||||
|
||||
/** The indentation levels stack. */
|
||||
indents []int
|
||||
|
||||
/** The current indentation level. */
|
||||
indent int
|
||||
|
||||
/** May a simple key occur at the current position? */
|
||||
simple_key_allowed bool
|
||||
|
||||
/** The stack of simple keys. */
|
||||
simple_keys []yaml_simple_key_t
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @name Parser stuff
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** The parser states stack. */
|
||||
states []yaml_parser_state_t
|
||||
|
||||
/** The current parser state. */
|
||||
state yaml_parser_state_t
|
||||
|
||||
/** The stack of marks. */
|
||||
marks []YAML_mark_t
|
||||
|
||||
/** The list of TAG directives. */
|
||||
tag_directives []yaml_tag_directive_t
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @name Dumper stuff
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** The alias data. */
|
||||
aliases []yaml_alias_data_t
|
||||
|
||||
/** The currently parsed document. */
|
||||
document *yaml_document_t
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The prototype of a write handler.
|
||||
*
|
||||
* The write handler is called when the emitter needs to flush the accumulated
|
||||
* characters to the output. The handler should write @a size bytes of the
|
||||
* @a buffer to the output.
|
||||
*
|
||||
* @param[in,out] data A pointer to an application data specified by
|
||||
* yaml_emitter_set_output().
|
||||
* @param[in] buffer The buffer with bytes to be written.
|
||||
* @param[in] size The size of the buffer.
|
||||
*
|
||||
* @returns On success, the handler should return @c 1. If the handler failed,
|
||||
* the returned value should be @c 0.
|
||||
*/
|
||||
|
||||
type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error
|
||||
|
||||
/** The emitter states. */
|
||||
type yaml_emitter_state_t int
|
||||
|
||||
const (
|
||||
/** Expect STREAM-START. */
|
||||
yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota
|
||||
/** Expect the first DOCUMENT-START or STREAM-END. */
|
||||
yaml_EMIT_FIRST_DOCUMENT_START_STATE
|
||||
/** Expect DOCUMENT-START or STREAM-END. */
|
||||
yaml_EMIT_DOCUMENT_START_STATE
|
||||
/** Expect the content of a document. */
|
||||
yaml_EMIT_DOCUMENT_CONTENT_STATE
|
||||
/** Expect DOCUMENT-END. */
|
||||
yaml_EMIT_DOCUMENT_END_STATE
|
||||
/** Expect the first item of a flow sequence. */
|
||||
yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE
|
||||
/** Expect an item of a flow sequence. */
|
||||
yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE
|
||||
/** Expect the first key of a flow mapping. */
|
||||
yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE
|
||||
/** Expect a key of a flow mapping. */
|
||||
yaml_EMIT_FLOW_MAPPING_KEY_STATE
|
||||
/** Expect a value for a simple key of a flow mapping. */
|
||||
yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE
|
||||
/** Expect a value of a flow mapping. */
|
||||
yaml_EMIT_FLOW_MAPPING_VALUE_STATE
|
||||
/** Expect the first item of a block sequence. */
|
||||
yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE
|
||||
/** Expect an item of a block sequence. */
|
||||
yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE
|
||||
/** Expect the first key of a block mapping. */
|
||||
yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE
|
||||
/** Expect the key of a block mapping. */
|
||||
yaml_EMIT_BLOCK_MAPPING_KEY_STATE
|
||||
/** Expect a value for a simple key of a block mapping. */
|
||||
yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE
|
||||
/** Expect a value of a block mapping. */
|
||||
yaml_EMIT_BLOCK_MAPPING_VALUE_STATE
|
||||
/** Expect nothing. */
|
||||
yaml_EMIT_END_STATE
|
||||
)
|
||||
|
||||
/**
|
||||
* The emitter structure.
|
||||
*
|
||||
* All members are internal. Manage the structure using the @c yaml_emitter_
|
||||
* family of functions.
|
||||
*/
|
||||
|
||||
type yaml_emitter_t struct {
|
||||
|
||||
/**
|
||||
* @name Error handling
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Error type. */
|
||||
error YAML_error_type_t
|
||||
/** Error description. */
|
||||
problem string
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @name Writer stuff
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Write handler. */
|
||||
write_handler yaml_write_handler_t
|
||||
|
||||
/** Standard (string or file) output data. */
|
||||
output_buffer *[]byte
|
||||
output_writer io.Writer
|
||||
|
||||
/** The working buffer. */
|
||||
buffer []byte
|
||||
buffer_pos int
|
||||
|
||||
/** The raw buffer. */
|
||||
raw_buffer []byte
|
||||
raw_buffer_pos int
|
||||
|
||||
/** The stream encoding. */
|
||||
encoding yaml_encoding_t
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @name Emitter stuff
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** If the output is in the canonical style? */
|
||||
canonical bool
|
||||
/** The number of indentation spaces. */
|
||||
best_indent int
|
||||
/** The preferred width of the output lines. */
|
||||
best_width int
|
||||
/** Allow unescaped non-ASCII characters? */
|
||||
unicode bool
|
||||
/** The preferred line break. */
|
||||
line_break yaml_break_t
|
||||
|
||||
/** The stack of states. */
|
||||
states []yaml_emitter_state_t
|
||||
|
||||
/** The current emitter state. */
|
||||
state yaml_emitter_state_t
|
||||
|
||||
/** The event queue. */
|
||||
events []yaml_event_t
|
||||
events_head int
|
||||
|
||||
/** The stack of indentation levels. */
|
||||
indents []int
|
||||
|
||||
/** The list of tag directives. */
|
||||
tag_directives []yaml_tag_directive_t
|
||||
|
||||
/** The current indentation level. */
|
||||
indent int
|
||||
|
||||
/** The current flow level. */
|
||||
flow_level int
|
||||
|
||||
/** Is it the document root context? */
|
||||
root_context bool
|
||||
/** Is it a sequence context? */
|
||||
sequence_context bool
|
||||
/** Is it a mapping context? */
|
||||
mapping_context bool
|
||||
/** Is it a simple mapping key context? */
|
||||
simple_key_context bool
|
||||
|
||||
/** The current line. */
|
||||
line int
|
||||
/** The current column. */
|
||||
column int
|
||||
/** If the last character was a whitespace? */
|
||||
whitespace bool
|
||||
/** If the last character was an indentation character (' ', '-', '?', ':')? */
|
||||
indention bool
|
||||
/** If an explicit document end is required? */
|
||||
open_ended bool
|
||||
|
||||
/** Anchor analysis. */
|
||||
anchor_data struct {
|
||||
/** The anchor value. */
|
||||
anchor []byte
|
||||
/** Is it an alias? */
|
||||
alias bool
|
||||
}
|
||||
|
||||
/** Tag analysis. */
|
||||
tag_data struct {
|
||||
/** The tag handle. */
|
||||
handle []byte
|
||||
/** The tag suffix. */
|
||||
suffix []byte
|
||||
}
|
||||
|
||||
/** Scalar analysis. */
|
||||
scalar_data struct {
|
||||
/** The scalar value. */
|
||||
value []byte
|
||||
/** Does the scalar contain line breaks? */
|
||||
multiline bool
|
||||
/** Can the scalar be expessed in the flow plain style? */
|
||||
flow_plain_allowed bool
|
||||
/** Can the scalar be expressed in the block plain style? */
|
||||
block_plain_allowed bool
|
||||
/** Can the scalar be expressed in the single quoted style? */
|
||||
single_quoted_allowed bool
|
||||
/** Can the scalar be expressed in the literal or folded styles? */
|
||||
block_allowed bool
|
||||
/** The output style. */
|
||||
style yaml_scalar_style_t
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @name Dumper stuff
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** If the stream was already opened? */
|
||||
opened bool
|
||||
/** If the stream was already closed? */
|
||||
closed bool
|
||||
|
||||
/** The information associated with the document nodes. */
|
||||
anchors *struct {
|
||||
/** The number of references. */
|
||||
references int
|
||||
/** The anchor id. */
|
||||
anchor int
|
||||
/** If the node has been emitted? */
|
||||
serialized bool
|
||||
}
|
||||
|
||||
/** The last assigned anchor id. */
|
||||
last_anchor_id int
|
||||
|
||||
/** The currently emitted document. */
|
||||
document *yaml_document_t
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
}
|
||||
267
vendor/github.com/docker/distribution/registry/api/errcode/errors.go
generated
vendored
267
vendor/github.com/docker/distribution/registry/api/errcode/errors.go
generated
vendored
@@ -1,267 +0,0 @@
|
||||
package errcode
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ErrorCoder is the base interface for ErrorCode and Error allowing
|
||||
// users of each to just call ErrorCode to get the real ID of each
|
||||
type ErrorCoder interface {
|
||||
ErrorCode() ErrorCode
|
||||
}
|
||||
|
||||
// ErrorCode represents the error type. The errors are serialized via strings
|
||||
// and the integer format may change and should *never* be exported.
|
||||
type ErrorCode int
|
||||
|
||||
var _ error = ErrorCode(0)
|
||||
|
||||
// ErrorCode just returns itself
|
||||
func (ec ErrorCode) ErrorCode() ErrorCode {
|
||||
return ec
|
||||
}
|
||||
|
||||
// Error returns the ID/Value
|
||||
func (ec ErrorCode) Error() string {
|
||||
// NOTE(stevvooe): Cannot use message here since it may have unpopulated args.
|
||||
return strings.ToLower(strings.Replace(ec.String(), "_", " ", -1))
|
||||
}
|
||||
|
||||
// Descriptor returns the descriptor for the error code.
|
||||
func (ec ErrorCode) Descriptor() ErrorDescriptor {
|
||||
d, ok := errorCodeToDescriptors[ec]
|
||||
|
||||
if !ok {
|
||||
return ErrorCodeUnknown.Descriptor()
|
||||
}
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
// String returns the canonical identifier for this error code.
|
||||
func (ec ErrorCode) String() string {
|
||||
return ec.Descriptor().Value
|
||||
}
|
||||
|
||||
// Message returned the human-readable error message for this error code.
|
||||
func (ec ErrorCode) Message() string {
|
||||
return ec.Descriptor().Message
|
||||
}
|
||||
|
||||
// MarshalText encodes the receiver into UTF-8-encoded text and returns the
|
||||
// result.
|
||||
func (ec ErrorCode) MarshalText() (text []byte, err error) {
|
||||
return []byte(ec.String()), nil
|
||||
}
|
||||
|
||||
// UnmarshalText decodes the form generated by MarshalText.
|
||||
func (ec *ErrorCode) UnmarshalText(text []byte) error {
|
||||
desc, ok := idToDescriptors[string(text)]
|
||||
|
||||
if !ok {
|
||||
desc = ErrorCodeUnknown.Descriptor()
|
||||
}
|
||||
|
||||
*ec = desc.Code
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithMessage creates a new Error struct based on the passed-in info and
|
||||
// overrides the Message property.
|
||||
func (ec ErrorCode) WithMessage(message string) Error {
|
||||
return Error{
|
||||
Code: ec,
|
||||
Message: message,
|
||||
}
|
||||
}
|
||||
|
||||
// WithDetail creates a new Error struct based on the passed-in info and
|
||||
// set the Detail property appropriately
|
||||
func (ec ErrorCode) WithDetail(detail interface{}) Error {
|
||||
return Error{
|
||||
Code: ec,
|
||||
Message: ec.Message(),
|
||||
}.WithDetail(detail)
|
||||
}
|
||||
|
||||
// WithArgs creates a new Error struct and sets the Args slice
|
||||
func (ec ErrorCode) WithArgs(args ...interface{}) Error {
|
||||
return Error{
|
||||
Code: ec,
|
||||
Message: ec.Message(),
|
||||
}.WithArgs(args...)
|
||||
}
|
||||
|
||||
// Error provides a wrapper around ErrorCode with extra Details provided.
|
||||
type Error struct {
|
||||
Code ErrorCode `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Detail interface{} `json:"detail,omitempty"`
|
||||
|
||||
// TODO(duglin): See if we need an "args" property so we can do the
|
||||
// variable substitution right before showing the message to the user
|
||||
}
|
||||
|
||||
var _ error = Error{}
|
||||
|
||||
// ErrorCode returns the ID/Value of this Error
|
||||
func (e Error) ErrorCode() ErrorCode {
|
||||
return e.Code
|
||||
}
|
||||
|
||||
// Error returns a human readable representation of the error.
|
||||
func (e Error) Error() string {
|
||||
return fmt.Sprintf("%s: %s", e.Code.Error(), e.Message)
|
||||
}
|
||||
|
||||
// WithDetail will return a new Error, based on the current one, but with
|
||||
// some Detail info added
|
||||
func (e Error) WithDetail(detail interface{}) Error {
|
||||
return Error{
|
||||
Code: e.Code,
|
||||
Message: e.Message,
|
||||
Detail: detail,
|
||||
}
|
||||
}
|
||||
|
||||
// WithArgs uses the passed-in list of interface{} as the substitution
|
||||
// variables in the Error's Message string, but returns a new Error
|
||||
func (e Error) WithArgs(args ...interface{}) Error {
|
||||
return Error{
|
||||
Code: e.Code,
|
||||
Message: fmt.Sprintf(e.Code.Message(), args...),
|
||||
Detail: e.Detail,
|
||||
}
|
||||
}
|
||||
|
||||
// ErrorDescriptor provides relevant information about a given error code.
|
||||
type ErrorDescriptor struct {
|
||||
// Code is the error code that this descriptor describes.
|
||||
Code ErrorCode
|
||||
|
||||
// Value provides a unique, string key, often captilized with
|
||||
// underscores, to identify the error code. This value is used as the
|
||||
// keyed value when serializing api errors.
|
||||
Value string
|
||||
|
||||
// Message is a short, human readable decription of the error condition
|
||||
// included in API responses.
|
||||
Message string
|
||||
|
||||
// Description provides a complete account of the errors purpose, suitable
|
||||
// for use in documentation.
|
||||
Description string
|
||||
|
||||
// HTTPStatusCode provides the http status code that is associated with
|
||||
// this error condition.
|
||||
HTTPStatusCode int
|
||||
}
|
||||
|
||||
// ParseErrorCode returns the value by the string error code.
|
||||
// `ErrorCodeUnknown` will be returned if the error is not known.
|
||||
func ParseErrorCode(value string) ErrorCode {
|
||||
ed, ok := idToDescriptors[value]
|
||||
if ok {
|
||||
return ed.Code
|
||||
}
|
||||
|
||||
return ErrorCodeUnknown
|
||||
}
|
||||
|
||||
// Errors provides the envelope for multiple errors and a few sugar methods
|
||||
// for use within the application.
|
||||
type Errors []error
|
||||
|
||||
var _ error = Errors{}
|
||||
|
||||
func (errs Errors) Error() string {
|
||||
switch len(errs) {
|
||||
case 0:
|
||||
return "<nil>"
|
||||
case 1:
|
||||
return errs[0].Error()
|
||||
default:
|
||||
msg := "errors:\n"
|
||||
for _, err := range errs {
|
||||
msg += err.Error() + "\n"
|
||||
}
|
||||
return msg
|
||||
}
|
||||
}
|
||||
|
||||
// Len returns the current number of errors.
|
||||
func (errs Errors) Len() int {
|
||||
return len(errs)
|
||||
}
|
||||
|
||||
// MarshalJSON converts slice of error, ErrorCode or Error into a
|
||||
// slice of Error - then serializes
|
||||
func (errs Errors) MarshalJSON() ([]byte, error) {
|
||||
var tmpErrs struct {
|
||||
Errors []Error `json:"errors,omitempty"`
|
||||
}
|
||||
|
||||
for _, daErr := range errs {
|
||||
var err Error
|
||||
|
||||
switch daErr.(type) {
|
||||
case ErrorCode:
|
||||
err = daErr.(ErrorCode).WithDetail(nil)
|
||||
case Error:
|
||||
err = daErr.(Error)
|
||||
default:
|
||||
err = ErrorCodeUnknown.WithDetail(daErr)
|
||||
|
||||
}
|
||||
|
||||
// If the Error struct was setup and they forgot to set the
|
||||
// Message field (meaning its "") then grab it from the ErrCode
|
||||
msg := err.Message
|
||||
if msg == "" {
|
||||
msg = err.Code.Message()
|
||||
}
|
||||
|
||||
tmpErrs.Errors = append(tmpErrs.Errors, Error{
|
||||
Code: err.Code,
|
||||
Message: msg,
|
||||
Detail: err.Detail,
|
||||
})
|
||||
}
|
||||
|
||||
return json.Marshal(tmpErrs)
|
||||
}
|
||||
|
||||
// UnmarshalJSON deserializes []Error and then converts it into slice of
|
||||
// Error or ErrorCode
|
||||
func (errs *Errors) UnmarshalJSON(data []byte) error {
|
||||
var tmpErrs struct {
|
||||
Errors []Error
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(data, &tmpErrs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var newErrs Errors
|
||||
for _, daErr := range tmpErrs.Errors {
|
||||
// If Message is empty or exactly matches the Code's message string
|
||||
// then just use the Code, no need for a full Error struct
|
||||
if daErr.Detail == nil && (daErr.Message == "" || daErr.Message == daErr.Code.Message()) {
|
||||
// Error's w/o details get converted to ErrorCode
|
||||
newErrs = append(newErrs, daErr.Code)
|
||||
} else {
|
||||
// Error's w/ details are untouched
|
||||
newErrs = append(newErrs, Error{
|
||||
Code: daErr.Code,
|
||||
Message: daErr.Message,
|
||||
Detail: daErr.Detail,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
*errs = newErrs
|
||||
return nil
|
||||
}
|
||||
44
vendor/github.com/docker/distribution/registry/api/errcode/handler.go
generated
vendored
44
vendor/github.com/docker/distribution/registry/api/errcode/handler.go
generated
vendored
@@ -1,44 +0,0 @@
|
||||
package errcode
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// ServeJSON attempts to serve the errcode in a JSON envelope. It marshals err
|
||||
// and sets the content-type header to 'application/json'. It will handle
|
||||
// ErrorCoder and Errors, and if necessary will create an envelope.
|
||||
func ServeJSON(w http.ResponseWriter, err error) error {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
var sc int
|
||||
|
||||
switch errs := err.(type) {
|
||||
case Errors:
|
||||
if len(errs) < 1 {
|
||||
break
|
||||
}
|
||||
|
||||
if err, ok := errs[0].(ErrorCoder); ok {
|
||||
sc = err.ErrorCode().Descriptor().HTTPStatusCode
|
||||
}
|
||||
case ErrorCoder:
|
||||
sc = errs.ErrorCode().Descriptor().HTTPStatusCode
|
||||
err = Errors{err} // create an envelope.
|
||||
default:
|
||||
// We just have an unhandled error type, so just place in an envelope
|
||||
// and move along.
|
||||
err = Errors{err}
|
||||
}
|
||||
|
||||
if sc == 0 {
|
||||
sc = http.StatusInternalServerError
|
||||
}
|
||||
|
||||
w.WriteHeader(sc)
|
||||
|
||||
if err := json.NewEncoder(w).Encode(err); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
138
vendor/github.com/docker/distribution/registry/api/errcode/register.go
generated
vendored
138
vendor/github.com/docker/distribution/registry/api/errcode/register.go
generated
vendored
@@ -1,138 +0,0 @@
|
||||
package errcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sort"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
errorCodeToDescriptors = map[ErrorCode]ErrorDescriptor{}
|
||||
idToDescriptors = map[string]ErrorDescriptor{}
|
||||
groupToDescriptors = map[string][]ErrorDescriptor{}
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrorCodeUnknown is a generic error that can be used as a last
|
||||
// resort if there is no situation-specific error message that can be used
|
||||
ErrorCodeUnknown = Register("errcode", ErrorDescriptor{
|
||||
Value: "UNKNOWN",
|
||||
Message: "unknown error",
|
||||
Description: `Generic error returned when the error does not have an
|
||||
API classification.`,
|
||||
HTTPStatusCode: http.StatusInternalServerError,
|
||||
})
|
||||
|
||||
// ErrorCodeUnsupported is returned when an operation is not supported.
|
||||
ErrorCodeUnsupported = Register("errcode", ErrorDescriptor{
|
||||
Value: "UNSUPPORTED",
|
||||
Message: "The operation is unsupported.",
|
||||
Description: `The operation was unsupported due to a missing
|
||||
implementation or invalid set of parameters.`,
|
||||
HTTPStatusCode: http.StatusMethodNotAllowed,
|
||||
})
|
||||
|
||||
// ErrorCodeUnauthorized is returned if a request requires
|
||||
// authentication.
|
||||
ErrorCodeUnauthorized = Register("errcode", ErrorDescriptor{
|
||||
Value: "UNAUTHORIZED",
|
||||
Message: "authentication required",
|
||||
Description: `The access controller was unable to authenticate
|
||||
the client. Often this will be accompanied by a
|
||||
Www-Authenticate HTTP response header indicating how to
|
||||
authenticate.`,
|
||||
HTTPStatusCode: http.StatusUnauthorized,
|
||||
})
|
||||
|
||||
// ErrorCodeDenied is returned if a client does not have sufficient
|
||||
// permission to perform an action.
|
||||
ErrorCodeDenied = Register("errcode", ErrorDescriptor{
|
||||
Value: "DENIED",
|
||||
Message: "requested access to the resource is denied",
|
||||
Description: `The access controller denied access for the
|
||||
operation on a resource.`,
|
||||
HTTPStatusCode: http.StatusForbidden,
|
||||
})
|
||||
|
||||
// ErrorCodeUnavailable provides a common error to report unavailability
|
||||
// of a service or endpoint.
|
||||
ErrorCodeUnavailable = Register("errcode", ErrorDescriptor{
|
||||
Value: "UNAVAILABLE",
|
||||
Message: "service unavailable",
|
||||
Description: "Returned when a service is not available",
|
||||
HTTPStatusCode: http.StatusServiceUnavailable,
|
||||
})
|
||||
|
||||
// ErrorCodeTooManyRequests is returned if a client attempts too many
|
||||
// times to contact a service endpoint.
|
||||
ErrorCodeTooManyRequests = Register("errcode", ErrorDescriptor{
|
||||
Value: "TOOMANYREQUESTS",
|
||||
Message: "too many requests",
|
||||
Description: `Returned when a client attempts to contact a
|
||||
service too many times`,
|
||||
HTTPStatusCode: http.StatusTooManyRequests,
|
||||
})
|
||||
)
|
||||
|
||||
var nextCode = 1000
|
||||
var registerLock sync.Mutex
|
||||
|
||||
// Register will make the passed-in error known to the environment and
|
||||
// return a new ErrorCode
|
||||
func Register(group string, descriptor ErrorDescriptor) ErrorCode {
|
||||
registerLock.Lock()
|
||||
defer registerLock.Unlock()
|
||||
|
||||
descriptor.Code = ErrorCode(nextCode)
|
||||
|
||||
if _, ok := idToDescriptors[descriptor.Value]; ok {
|
||||
panic(fmt.Sprintf("ErrorValue %q is already registered", descriptor.Value))
|
||||
}
|
||||
if _, ok := errorCodeToDescriptors[descriptor.Code]; ok {
|
||||
panic(fmt.Sprintf("ErrorCode %v is already registered", descriptor.Code))
|
||||
}
|
||||
|
||||
groupToDescriptors[group] = append(groupToDescriptors[group], descriptor)
|
||||
errorCodeToDescriptors[descriptor.Code] = descriptor
|
||||
idToDescriptors[descriptor.Value] = descriptor
|
||||
|
||||
nextCode++
|
||||
return descriptor.Code
|
||||
}
|
||||
|
||||
type byValue []ErrorDescriptor
|
||||
|
||||
func (a byValue) Len() int { return len(a) }
|
||||
func (a byValue) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a byValue) Less(i, j int) bool { return a[i].Value < a[j].Value }
|
||||
|
||||
// GetGroupNames returns the list of Error group names that are registered
|
||||
func GetGroupNames() []string {
|
||||
keys := []string{}
|
||||
|
||||
for k := range groupToDescriptors {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return keys
|
||||
}
|
||||
|
||||
// GetErrorCodeGroup returns the named group of error descriptors
|
||||
func GetErrorCodeGroup(name string) []ErrorDescriptor {
|
||||
desc := groupToDescriptors[name]
|
||||
sort.Sort(byValue(desc))
|
||||
return desc
|
||||
}
|
||||
|
||||
// GetErrorAllDescriptors returns a slice of all ErrorDescriptors that are
|
||||
// registered, irrespective of what group they're in
|
||||
func GetErrorAllDescriptors() []ErrorDescriptor {
|
||||
result := []ErrorDescriptor{}
|
||||
|
||||
for _, group := range GetGroupNames() {
|
||||
result = append(result, GetErrorCodeGroup(group)...)
|
||||
}
|
||||
sort.Sort(byValue(result))
|
||||
return result
|
||||
}
|
||||
1596
vendor/github.com/docker/distribution/registry/api/v2/descriptors.go
generated
vendored
1596
vendor/github.com/docker/distribution/registry/api/v2/descriptors.go
generated
vendored
File diff suppressed because it is too large
Load Diff
9
vendor/github.com/docker/distribution/registry/api/v2/doc.go
generated
vendored
9
vendor/github.com/docker/distribution/registry/api/v2/doc.go
generated
vendored
@@ -1,9 +0,0 @@
|
||||
// Package v2 describes routes, urls and the error codes used in the Docker
|
||||
// Registry JSON HTTP API V2. In addition to declarations, descriptors are
|
||||
// provided for routes and error codes that can be used for implementation and
|
||||
// automatically generating documentation.
|
||||
//
|
||||
// Definitions here are considered to be locked down for the V2 registry api.
|
||||
// Any changes must be considered carefully and should not proceed without a
|
||||
// change proposal in docker core.
|
||||
package v2
|
||||
136
vendor/github.com/docker/distribution/registry/api/v2/errors.go
generated
vendored
136
vendor/github.com/docker/distribution/registry/api/v2/errors.go
generated
vendored
@@ -1,136 +0,0 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/docker/distribution/registry/api/errcode"
|
||||
)
|
||||
|
||||
const errGroup = "registry.api.v2"
|
||||
|
||||
var (
|
||||
// ErrorCodeDigestInvalid is returned when uploading a blob if the
|
||||
// provided digest does not match the blob contents.
|
||||
ErrorCodeDigestInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "DIGEST_INVALID",
|
||||
Message: "provided digest did not match uploaded content",
|
||||
Description: `When a blob is uploaded, the registry will check that
|
||||
the content matches the digest provided by the client. The error may
|
||||
include a detail structure with the key "digest", including the
|
||||
invalid digest string. This error may also be returned when a manifest
|
||||
includes an invalid layer digest.`,
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
})
|
||||
|
||||
// ErrorCodeSizeInvalid is returned when uploading a blob if the provided
|
||||
ErrorCodeSizeInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "SIZE_INVALID",
|
||||
Message: "provided length did not match content length",
|
||||
Description: `When a layer is uploaded, the provided size will be
|
||||
checked against the uploaded content. If they do not match, this error
|
||||
will be returned.`,
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
})
|
||||
|
||||
// ErrorCodeNameInvalid is returned when the name in the manifest does not
|
||||
// match the provided name.
|
||||
ErrorCodeNameInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "NAME_INVALID",
|
||||
Message: "invalid repository name",
|
||||
Description: `Invalid repository name encountered either during
|
||||
manifest validation or any API operation.`,
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
})
|
||||
|
||||
// ErrorCodeTagInvalid is returned when the tag in the manifest does not
|
||||
// match the provided tag.
|
||||
ErrorCodeTagInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "TAG_INVALID",
|
||||
Message: "manifest tag did not match URI",
|
||||
Description: `During a manifest upload, if the tag in the manifest
|
||||
does not match the uri tag, this error will be returned.`,
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
})
|
||||
|
||||
// ErrorCodeNameUnknown when the repository name is not known.
|
||||
ErrorCodeNameUnknown = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "NAME_UNKNOWN",
|
||||
Message: "repository name not known to registry",
|
||||
Description: `This is returned if the name used during an operation is
|
||||
unknown to the registry.`,
|
||||
HTTPStatusCode: http.StatusNotFound,
|
||||
})
|
||||
|
||||
// ErrorCodeManifestUnknown returned when image manifest is unknown.
|
||||
ErrorCodeManifestUnknown = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "MANIFEST_UNKNOWN",
|
||||
Message: "manifest unknown",
|
||||
Description: `This error is returned when the manifest, identified by
|
||||
name and tag is unknown to the repository.`,
|
||||
HTTPStatusCode: http.StatusNotFound,
|
||||
})
|
||||
|
||||
// ErrorCodeManifestInvalid returned when an image manifest is invalid,
|
||||
// typically during a PUT operation. This error encompasses all errors
|
||||
// encountered during manifest validation that aren't signature errors.
|
||||
ErrorCodeManifestInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "MANIFEST_INVALID",
|
||||
Message: "manifest invalid",
|
||||
Description: `During upload, manifests undergo several checks ensuring
|
||||
validity. If those checks fail, this error may be returned, unless a
|
||||
more specific error is included. The detail will contain information
|
||||
the failed validation.`,
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
})
|
||||
|
||||
// ErrorCodeManifestUnverified is returned when the manifest fails
|
||||
// signature verification.
|
||||
ErrorCodeManifestUnverified = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "MANIFEST_UNVERIFIED",
|
||||
Message: "manifest failed signature verification",
|
||||
Description: `During manifest upload, if the manifest fails signature
|
||||
verification, this error will be returned.`,
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
})
|
||||
|
||||
// ErrorCodeManifestBlobUnknown is returned when a manifest blob is
|
||||
// unknown to the registry.
|
||||
ErrorCodeManifestBlobUnknown = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "MANIFEST_BLOB_UNKNOWN",
|
||||
Message: "blob unknown to registry",
|
||||
Description: `This error may be returned when a manifest blob is
|
||||
unknown to the registry.`,
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
})
|
||||
|
||||
// ErrorCodeBlobUnknown is returned when a blob is unknown to the
|
||||
// registry. This can happen when the manifest references a nonexistent
|
||||
// layer or the result is not found by a blob fetch.
|
||||
ErrorCodeBlobUnknown = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "BLOB_UNKNOWN",
|
||||
Message: "blob unknown to registry",
|
||||
Description: `This error may be returned when a blob is unknown to the
|
||||
registry in a specified repository. This can be returned with a
|
||||
standard get or if a manifest references an unknown layer during
|
||||
upload.`,
|
||||
HTTPStatusCode: http.StatusNotFound,
|
||||
})
|
||||
|
||||
// ErrorCodeBlobUploadUnknown is returned when an upload is unknown.
|
||||
ErrorCodeBlobUploadUnknown = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "BLOB_UPLOAD_UNKNOWN",
|
||||
Message: "blob upload unknown to registry",
|
||||
Description: `If a blob upload has been cancelled or was never
|
||||
started, this error code may be returned.`,
|
||||
HTTPStatusCode: http.StatusNotFound,
|
||||
})
|
||||
|
||||
// ErrorCodeBlobUploadInvalid is returned when an upload is invalid.
|
||||
ErrorCodeBlobUploadInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "BLOB_UPLOAD_INVALID",
|
||||
Message: "blob upload invalid",
|
||||
Description: `The blob upload encountered an error and can no
|
||||
longer proceed.`,
|
||||
HTTPStatusCode: http.StatusNotFound,
|
||||
})
|
||||
)
|
||||
161
vendor/github.com/docker/distribution/registry/api/v2/headerparser.go
generated
vendored
161
vendor/github.com/docker/distribution/registry/api/v2/headerparser.go
generated
vendored
@@ -1,161 +0,0 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
var (
|
||||
// according to rfc7230
|
||||
reToken = regexp.MustCompile(`^[^"(),/:;<=>?@[\]{}[:space:][:cntrl:]]+`)
|
||||
reQuotedValue = regexp.MustCompile(`^[^\\"]+`)
|
||||
reEscapedCharacter = regexp.MustCompile(`^[[:blank:][:graph:]]`)
|
||||
)
|
||||
|
||||
// parseForwardedHeader is a benevolent parser of Forwarded header defined in rfc7239. The header contains
|
||||
// a comma-separated list of forwarding key-value pairs. Each list element is set by single proxy. The
|
||||
// function parses only the first element of the list, which is set by the very first proxy. It returns a map
|
||||
// of corresponding key-value pairs and an unparsed slice of the input string.
|
||||
//
|
||||
// Examples of Forwarded header values:
|
||||
//
|
||||
// 1. Forwarded: For=192.0.2.43; Proto=https,For="[2001:db8:cafe::17]",For=unknown
|
||||
// 2. Forwarded: for="192.0.2.43:443"; host="registry.example.org", for="10.10.05.40:80"
|
||||
//
|
||||
// The first will be parsed into {"for": "192.0.2.43", "proto": "https"} while the second into
|
||||
// {"for": "192.0.2.43:443", "host": "registry.example.org"}.
|
||||
func parseForwardedHeader(forwarded string) (map[string]string, string, error) {
|
||||
// Following are states of forwarded header parser. Any state could transition to a failure.
|
||||
const (
|
||||
// terminating state; can transition to Parameter
|
||||
stateElement = iota
|
||||
// terminating state; can transition to KeyValueDelimiter
|
||||
stateParameter
|
||||
// can transition to Value
|
||||
stateKeyValueDelimiter
|
||||
// can transition to one of { QuotedValue, PairEnd }
|
||||
stateValue
|
||||
// can transition to one of { EscapedCharacter, PairEnd }
|
||||
stateQuotedValue
|
||||
// can transition to one of { QuotedValue }
|
||||
stateEscapedCharacter
|
||||
// terminating state; can transition to one of { Parameter, Element }
|
||||
statePairEnd
|
||||
)
|
||||
|
||||
var (
|
||||
parameter string
|
||||
value string
|
||||
parse = forwarded[:]
|
||||
res = map[string]string{}
|
||||
state = stateElement
|
||||
)
|
||||
|
||||
Loop:
|
||||
for {
|
||||
// skip spaces unless in quoted value
|
||||
if state != stateQuotedValue && state != stateEscapedCharacter {
|
||||
parse = strings.TrimLeftFunc(parse, unicode.IsSpace)
|
||||
}
|
||||
|
||||
if len(parse) == 0 {
|
||||
if state != stateElement && state != statePairEnd && state != stateParameter {
|
||||
return nil, parse, fmt.Errorf("unexpected end of input")
|
||||
}
|
||||
// terminating
|
||||
break
|
||||
}
|
||||
|
||||
switch state {
|
||||
// terminate at list element delimiter
|
||||
case stateElement:
|
||||
if parse[0] == ',' {
|
||||
parse = parse[1:]
|
||||
break Loop
|
||||
}
|
||||
state = stateParameter
|
||||
|
||||
// parse parameter (the key of key-value pair)
|
||||
case stateParameter:
|
||||
match := reToken.FindString(parse)
|
||||
if len(match) == 0 {
|
||||
return nil, parse, fmt.Errorf("failed to parse token at position %d", len(forwarded)-len(parse))
|
||||
}
|
||||
parameter = strings.ToLower(match)
|
||||
parse = parse[len(match):]
|
||||
state = stateKeyValueDelimiter
|
||||
|
||||
// parse '='
|
||||
case stateKeyValueDelimiter:
|
||||
if parse[0] != '=' {
|
||||
return nil, parse, fmt.Errorf("expected '=', not '%c' at position %d", parse[0], len(forwarded)-len(parse))
|
||||
}
|
||||
parse = parse[1:]
|
||||
state = stateValue
|
||||
|
||||
// parse value or quoted value
|
||||
case stateValue:
|
||||
if parse[0] == '"' {
|
||||
parse = parse[1:]
|
||||
state = stateQuotedValue
|
||||
} else {
|
||||
value = reToken.FindString(parse)
|
||||
if len(value) == 0 {
|
||||
return nil, parse, fmt.Errorf("failed to parse value at position %d", len(forwarded)-len(parse))
|
||||
}
|
||||
if _, exists := res[parameter]; exists {
|
||||
return nil, parse, fmt.Errorf("duplicate parameter %q at position %d", parameter, len(forwarded)-len(parse))
|
||||
}
|
||||
res[parameter] = value
|
||||
parse = parse[len(value):]
|
||||
value = ""
|
||||
state = statePairEnd
|
||||
}
|
||||
|
||||
// parse a part of quoted value until the first backslash
|
||||
case stateQuotedValue:
|
||||
match := reQuotedValue.FindString(parse)
|
||||
value += match
|
||||
parse = parse[len(match):]
|
||||
switch {
|
||||
case len(parse) == 0:
|
||||
return nil, parse, fmt.Errorf("unterminated quoted string")
|
||||
case parse[0] == '"':
|
||||
res[parameter] = value
|
||||
value = ""
|
||||
parse = parse[1:]
|
||||
state = statePairEnd
|
||||
case parse[0] == '\\':
|
||||
parse = parse[1:]
|
||||
state = stateEscapedCharacter
|
||||
}
|
||||
|
||||
// parse escaped character in a quoted string, ignore the backslash
|
||||
// transition back to QuotedValue state
|
||||
case stateEscapedCharacter:
|
||||
c := reEscapedCharacter.FindString(parse)
|
||||
if len(c) == 0 {
|
||||
return nil, parse, fmt.Errorf("invalid escape sequence at position %d", len(forwarded)-len(parse)-1)
|
||||
}
|
||||
value += c
|
||||
parse = parse[1:]
|
||||
state = stateQuotedValue
|
||||
|
||||
// expect either a new key-value pair, new list or end of input
|
||||
case statePairEnd:
|
||||
switch parse[0] {
|
||||
case ';':
|
||||
parse = parse[1:]
|
||||
state = stateParameter
|
||||
case ',':
|
||||
state = stateElement
|
||||
default:
|
||||
return nil, parse, fmt.Errorf("expected ',' or ';', not %c at position %d", parse[0], len(forwarded)-len(parse))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res, parse, nil
|
||||
}
|
||||
49
vendor/github.com/docker/distribution/registry/api/v2/routes.go
generated
vendored
49
vendor/github.com/docker/distribution/registry/api/v2/routes.go
generated
vendored
@@ -1,49 +0,0 @@
|
||||
package v2
|
||||
|
||||
import "github.com/gorilla/mux"
|
||||
|
||||
// The following are definitions of the name under which all V2 routes are
|
||||
// registered. These symbols can be used to look up a route based on the name.
|
||||
const (
|
||||
RouteNameBase = "base"
|
||||
RouteNameManifest = "manifest"
|
||||
RouteNameTags = "tags"
|
||||
RouteNameBlob = "blob"
|
||||
RouteNameBlobUpload = "blob-upload"
|
||||
RouteNameBlobUploadChunk = "blob-upload-chunk"
|
||||
RouteNameCatalog = "catalog"
|
||||
)
|
||||
|
||||
var allEndpoints = []string{
|
||||
RouteNameManifest,
|
||||
RouteNameCatalog,
|
||||
RouteNameTags,
|
||||
RouteNameBlob,
|
||||
RouteNameBlobUpload,
|
||||
RouteNameBlobUploadChunk,
|
||||
}
|
||||
|
||||
// Router builds a gorilla router with named routes for the various API
|
||||
// methods. This can be used directly by both server implementations and
|
||||
// clients.
|
||||
func Router() *mux.Router {
|
||||
return RouterWithPrefix("")
|
||||
}
|
||||
|
||||
// RouterWithPrefix builds a gorilla router with a configured prefix
|
||||
// on all routes.
|
||||
func RouterWithPrefix(prefix string) *mux.Router {
|
||||
rootRouter := mux.NewRouter()
|
||||
router := rootRouter
|
||||
if prefix != "" {
|
||||
router = router.PathPrefix(prefix).Subrouter()
|
||||
}
|
||||
|
||||
router.StrictSlash(true)
|
||||
|
||||
for _, descriptor := range routeDescriptors {
|
||||
router.Path(descriptor.Path).Name(descriptor.Name)
|
||||
}
|
||||
|
||||
return rootRouter
|
||||
}
|
||||
263
vendor/github.com/docker/distribution/registry/api/v2/urls.go
generated
vendored
263
vendor/github.com/docker/distribution/registry/api/v2/urls.go
generated
vendored
@@ -1,263 +0,0 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
// URLBuilder creates registry API urls from a single base endpoint. It can be
|
||||
// used to create urls for use in a registry client or server.
|
||||
//
|
||||
// All urls will be created from the given base, including the api version.
|
||||
// For example, if a root of "/foo/" is provided, urls generated will be fall
|
||||
// under "/foo/v2/...". Most application will only provide a schema, host and
|
||||
// port, such as "https://localhost:5000/".
|
||||
type URLBuilder struct {
|
||||
root *url.URL // url root (ie http://localhost/)
|
||||
router *mux.Router
|
||||
relative bool
|
||||
}
|
||||
|
||||
// NewURLBuilder creates a URLBuilder with provided root url object.
|
||||
func NewURLBuilder(root *url.URL, relative bool) *URLBuilder {
|
||||
return &URLBuilder{
|
||||
root: root,
|
||||
router: Router(),
|
||||
relative: relative,
|
||||
}
|
||||
}
|
||||
|
||||
// NewURLBuilderFromString workes identically to NewURLBuilder except it takes
|
||||
// a string argument for the root, returning an error if it is not a valid
|
||||
// url.
|
||||
func NewURLBuilderFromString(root string, relative bool) (*URLBuilder, error) {
|
||||
u, err := url.Parse(root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewURLBuilder(u, relative), nil
|
||||
}
|
||||
|
||||
// NewURLBuilderFromRequest uses information from an *http.Request to
|
||||
// construct the root url.
|
||||
func NewURLBuilderFromRequest(r *http.Request, relative bool) *URLBuilder {
|
||||
var (
|
||||
scheme = "http"
|
||||
host = r.Host
|
||||
)
|
||||
|
||||
if r.TLS != nil {
|
||||
scheme = "https"
|
||||
} else if len(r.URL.Scheme) > 0 {
|
||||
scheme = r.URL.Scheme
|
||||
}
|
||||
|
||||
// Handle fowarded headers
|
||||
// Prefer "Forwarded" header as defined by rfc7239 if given
|
||||
// see https://tools.ietf.org/html/rfc7239
|
||||
if forwarded := r.Header.Get("Forwarded"); len(forwarded) > 0 {
|
||||
forwardedHeader, _, err := parseForwardedHeader(forwarded)
|
||||
if err == nil {
|
||||
if fproto := forwardedHeader["proto"]; len(fproto) > 0 {
|
||||
scheme = fproto
|
||||
}
|
||||
if fhost := forwardedHeader["host"]; len(fhost) > 0 {
|
||||
host = fhost
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if forwardedProto := r.Header.Get("X-Forwarded-Proto"); len(forwardedProto) > 0 {
|
||||
scheme = forwardedProto
|
||||
}
|
||||
if forwardedHost := r.Header.Get("X-Forwarded-Host"); len(forwardedHost) > 0 {
|
||||
// According to the Apache mod_proxy docs, X-Forwarded-Host can be a
|
||||
// comma-separated list of hosts, to which each proxy appends the
|
||||
// requested host. We want to grab the first from this comma-separated
|
||||
// list.
|
||||
hosts := strings.SplitN(forwardedHost, ",", 2)
|
||||
host = strings.TrimSpace(hosts[0])
|
||||
}
|
||||
}
|
||||
|
||||
basePath := routeDescriptorsMap[RouteNameBase].Path
|
||||
|
||||
requestPath := r.URL.Path
|
||||
index := strings.Index(requestPath, basePath)
|
||||
|
||||
u := &url.URL{
|
||||
Scheme: scheme,
|
||||
Host: host,
|
||||
}
|
||||
|
||||
if index > 0 {
|
||||
// N.B. index+1 is important because we want to include the trailing /
|
||||
u.Path = requestPath[0 : index+1]
|
||||
}
|
||||
|
||||
return NewURLBuilder(u, relative)
|
||||
}
|
||||
|
||||
// BuildBaseURL constructs a base url for the API, typically just "/v2/".
|
||||
func (ub *URLBuilder) BuildBaseURL() (string, error) {
|
||||
route := ub.cloneRoute(RouteNameBase)
|
||||
|
||||
baseURL, err := route.URL()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return baseURL.String(), nil
|
||||
}
|
||||
|
||||
// BuildCatalogURL constructs a url get a catalog of repositories
|
||||
func (ub *URLBuilder) BuildCatalogURL(values ...url.Values) (string, error) {
|
||||
route := ub.cloneRoute(RouteNameCatalog)
|
||||
|
||||
catalogURL, err := route.URL()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return appendValuesURL(catalogURL, values...).String(), nil
|
||||
}
|
||||
|
||||
// BuildTagsURL constructs a url to list the tags in the named repository.
|
||||
func (ub *URLBuilder) BuildTagsURL(name reference.Named) (string, error) {
|
||||
route := ub.cloneRoute(RouteNameTags)
|
||||
|
||||
tagsURL, err := route.URL("name", name.Name())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return tagsURL.String(), nil
|
||||
}
|
||||
|
||||
// BuildManifestURL constructs a url for the manifest identified by name and
|
||||
// reference. The argument reference may be either a tag or digest.
|
||||
func (ub *URLBuilder) BuildManifestURL(ref reference.Named) (string, error) {
|
||||
route := ub.cloneRoute(RouteNameManifest)
|
||||
|
||||
tagOrDigest := ""
|
||||
switch v := ref.(type) {
|
||||
case reference.Tagged:
|
||||
tagOrDigest = v.Tag()
|
||||
case reference.Digested:
|
||||
tagOrDigest = v.Digest().String()
|
||||
}
|
||||
|
||||
manifestURL, err := route.URL("name", ref.Name(), "reference", tagOrDigest)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return manifestURL.String(), nil
|
||||
}
|
||||
|
||||
// BuildBlobURL constructs the url for the blob identified by name and dgst.
|
||||
func (ub *URLBuilder) BuildBlobURL(ref reference.Canonical) (string, error) {
|
||||
route := ub.cloneRoute(RouteNameBlob)
|
||||
|
||||
layerURL, err := route.URL("name", ref.Name(), "digest", ref.Digest().String())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return layerURL.String(), nil
|
||||
}
|
||||
|
||||
// BuildBlobUploadURL constructs a url to begin a blob upload in the
|
||||
// repository identified by name.
|
||||
func (ub *URLBuilder) BuildBlobUploadURL(name reference.Named, values ...url.Values) (string, error) {
|
||||
route := ub.cloneRoute(RouteNameBlobUpload)
|
||||
|
||||
uploadURL, err := route.URL("name", name.Name())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return appendValuesURL(uploadURL, values...).String(), nil
|
||||
}
|
||||
|
||||
// BuildBlobUploadChunkURL constructs a url for the upload identified by uuid,
|
||||
// including any url values. This should generally not be used by clients, as
|
||||
// this url is provided by server implementations during the blob upload
|
||||
// process.
|
||||
func (ub *URLBuilder) BuildBlobUploadChunkURL(name reference.Named, uuid string, values ...url.Values) (string, error) {
|
||||
route := ub.cloneRoute(RouteNameBlobUploadChunk)
|
||||
|
||||
uploadURL, err := route.URL("name", name.Name(), "uuid", uuid)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return appendValuesURL(uploadURL, values...).String(), nil
|
||||
}
|
||||
|
||||
// clondedRoute returns a clone of the named route from the router. Routes
|
||||
// must be cloned to avoid modifying them during url generation.
|
||||
func (ub *URLBuilder) cloneRoute(name string) clonedRoute {
|
||||
route := new(mux.Route)
|
||||
root := new(url.URL)
|
||||
|
||||
*route = *ub.router.GetRoute(name) // clone the route
|
||||
*root = *ub.root
|
||||
|
||||
return clonedRoute{Route: route, root: root, relative: ub.relative}
|
||||
}
|
||||
|
||||
type clonedRoute struct {
|
||||
*mux.Route
|
||||
root *url.URL
|
||||
relative bool
|
||||
}
|
||||
|
||||
func (cr clonedRoute) URL(pairs ...string) (*url.URL, error) {
|
||||
routeURL, err := cr.Route.URL(pairs...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cr.relative {
|
||||
return routeURL, nil
|
||||
}
|
||||
|
||||
if routeURL.Scheme == "" && routeURL.User == nil && routeURL.Host == "" {
|
||||
routeURL.Path = routeURL.Path[1:]
|
||||
}
|
||||
|
||||
url := cr.root.ResolveReference(routeURL)
|
||||
url.Scheme = cr.root.Scheme
|
||||
return url, nil
|
||||
}
|
||||
|
||||
// appendValuesURL appends the parameters to the url.
|
||||
func appendValuesURL(u *url.URL, values ...url.Values) *url.URL {
|
||||
merged := u.Query()
|
||||
|
||||
for _, v := range values {
|
||||
for k, vv := range v {
|
||||
merged[k] = append(merged[k], vv...)
|
||||
}
|
||||
}
|
||||
|
||||
u.RawQuery = merged.Encode()
|
||||
return u
|
||||
}
|
||||
|
||||
// appendValues appends the parameters to the url. Panics if the string is not
|
||||
// a url.
|
||||
func appendValues(u string, values ...url.Values) string {
|
||||
up, err := url.Parse(u)
|
||||
|
||||
if err != nil {
|
||||
panic(err) // should never happen
|
||||
}
|
||||
|
||||
return appendValuesURL(up, values...).String()
|
||||
}
|
||||
27
vendor/github.com/docker/distribution/registry/client/auth/challenge/addr.go
generated
vendored
27
vendor/github.com/docker/distribution/registry/client/auth/challenge/addr.go
generated
vendored
@@ -1,27 +0,0 @@
|
||||
package challenge
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// FROM: https://golang.org/src/net/http/http.go
|
||||
// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
|
||||
// return true if the string includes a port.
|
||||
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
|
||||
|
||||
// FROM: http://golang.org/src/net/http/transport.go
|
||||
var portMap = map[string]string{
|
||||
"http": "80",
|
||||
"https": "443",
|
||||
}
|
||||
|
||||
// canonicalAddr returns url.Host but always with a ":port" suffix
|
||||
// FROM: http://golang.org/src/net/http/transport.go
|
||||
func canonicalAddr(url *url.URL) string {
|
||||
addr := url.Host
|
||||
if !hasPort(addr) {
|
||||
return addr + ":" + portMap[url.Scheme]
|
||||
}
|
||||
return addr
|
||||
}
|
||||
237
vendor/github.com/docker/distribution/registry/client/auth/challenge/authchallenge.go
generated
vendored
237
vendor/github.com/docker/distribution/registry/client/auth/challenge/authchallenge.go
generated
vendored
@@ -1,237 +0,0 @@
|
||||
package challenge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Challenge carries information from a WWW-Authenticate response header.
|
||||
// See RFC 2617.
|
||||
type Challenge struct {
|
||||
// Scheme is the auth-scheme according to RFC 2617
|
||||
Scheme string
|
||||
|
||||
// Parameters are the auth-params according to RFC 2617
|
||||
Parameters map[string]string
|
||||
}
|
||||
|
||||
// Manager manages the challenges for endpoints.
|
||||
// The challenges are pulled out of HTTP responses. Only
|
||||
// responses which expect challenges should be added to
|
||||
// the manager, since a non-unauthorized request will be
|
||||
// viewed as not requiring challenges.
|
||||
type Manager interface {
|
||||
// GetChallenges returns the challenges for the given
|
||||
// endpoint URL.
|
||||
GetChallenges(endpoint url.URL) ([]Challenge, error)
|
||||
|
||||
// AddResponse adds the response to the challenge
|
||||
// manager. The challenges will be parsed out of
|
||||
// the WWW-Authenicate headers and added to the
|
||||
// URL which was produced the response. If the
|
||||
// response was authorized, any challenges for the
|
||||
// endpoint will be cleared.
|
||||
AddResponse(resp *http.Response) error
|
||||
}
|
||||
|
||||
// NewSimpleManager returns an instance of
|
||||
// Manger which only maps endpoints to challenges
|
||||
// based on the responses which have been added the
|
||||
// manager. The simple manager will make no attempt to
|
||||
// perform requests on the endpoints or cache the responses
|
||||
// to a backend.
|
||||
func NewSimpleManager() Manager {
|
||||
return &simpleManager{
|
||||
Challanges: make(map[string][]Challenge),
|
||||
}
|
||||
}
|
||||
|
||||
type simpleManager struct {
|
||||
sync.RWMutex
|
||||
Challanges map[string][]Challenge
|
||||
}
|
||||
|
||||
func normalizeURL(endpoint *url.URL) {
|
||||
endpoint.Host = strings.ToLower(endpoint.Host)
|
||||
endpoint.Host = canonicalAddr(endpoint)
|
||||
}
|
||||
|
||||
func (m *simpleManager) GetChallenges(endpoint url.URL) ([]Challenge, error) {
|
||||
normalizeURL(&endpoint)
|
||||
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
challenges := m.Challanges[endpoint.String()]
|
||||
return challenges, nil
|
||||
}
|
||||
|
||||
func (m *simpleManager) AddResponse(resp *http.Response) error {
|
||||
challenges := ResponseChallenges(resp)
|
||||
if resp.Request == nil {
|
||||
return fmt.Errorf("missing request reference")
|
||||
}
|
||||
urlCopy := url.URL{
|
||||
Path: resp.Request.URL.Path,
|
||||
Host: resp.Request.URL.Host,
|
||||
Scheme: resp.Request.URL.Scheme,
|
||||
}
|
||||
normalizeURL(&urlCopy)
|
||||
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
m.Challanges[urlCopy.String()] = challenges
|
||||
return nil
|
||||
}
|
||||
|
||||
// Octet types from RFC 2616.
|
||||
type octetType byte
|
||||
|
||||
var octetTypes [256]octetType
|
||||
|
||||
const (
|
||||
isToken octetType = 1 << iota
|
||||
isSpace
|
||||
)
|
||||
|
||||
func init() {
|
||||
// OCTET = <any 8-bit sequence of data>
|
||||
// CHAR = <any US-ASCII character (octets 0 - 127)>
|
||||
// CTL = <any US-ASCII control character (octets 0 - 31) and DEL (127)>
|
||||
// CR = <US-ASCII CR, carriage return (13)>
|
||||
// LF = <US-ASCII LF, linefeed (10)>
|
||||
// SP = <US-ASCII SP, space (32)>
|
||||
// HT = <US-ASCII HT, horizontal-tab (9)>
|
||||
// <"> = <US-ASCII double-quote mark (34)>
|
||||
// CRLF = CR LF
|
||||
// LWS = [CRLF] 1*( SP | HT )
|
||||
// TEXT = <any OCTET except CTLs, but including LWS>
|
||||
// separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <">
|
||||
// | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT
|
||||
// token = 1*<any CHAR except CTLs or separators>
|
||||
// qdtext = <any TEXT except <">>
|
||||
|
||||
for c := 0; c < 256; c++ {
|
||||
var t octetType
|
||||
isCtl := c <= 31 || c == 127
|
||||
isChar := 0 <= c && c <= 127
|
||||
isSeparator := strings.IndexRune(" \t\"(),/:;<=>?@[]\\{}", rune(c)) >= 0
|
||||
if strings.IndexRune(" \t\r\n", rune(c)) >= 0 {
|
||||
t |= isSpace
|
||||
}
|
||||
if isChar && !isCtl && !isSeparator {
|
||||
t |= isToken
|
||||
}
|
||||
octetTypes[c] = t
|
||||
}
|
||||
}
|
||||
|
||||
// ResponseChallenges returns a list of authorization challenges
|
||||
// for the given http Response. Challenges are only checked if
|
||||
// the response status code was a 401.
|
||||
func ResponseChallenges(resp *http.Response) []Challenge {
|
||||
if resp.StatusCode == http.StatusUnauthorized {
|
||||
// Parse the WWW-Authenticate Header and store the challenges
|
||||
// on this endpoint object.
|
||||
return parseAuthHeader(resp.Header)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseAuthHeader(header http.Header) []Challenge {
|
||||
challenges := []Challenge{}
|
||||
for _, h := range header[http.CanonicalHeaderKey("WWW-Authenticate")] {
|
||||
v, p := parseValueAndParams(h)
|
||||
if v != "" {
|
||||
challenges = append(challenges, Challenge{Scheme: v, Parameters: p})
|
||||
}
|
||||
}
|
||||
return challenges
|
||||
}
|
||||
|
||||
func parseValueAndParams(header string) (value string, params map[string]string) {
|
||||
params = make(map[string]string)
|
||||
value, s := expectToken(header)
|
||||
if value == "" {
|
||||
return
|
||||
}
|
||||
value = strings.ToLower(value)
|
||||
s = "," + skipSpace(s)
|
||||
for strings.HasPrefix(s, ",") {
|
||||
var pkey string
|
||||
pkey, s = expectToken(skipSpace(s[1:]))
|
||||
if pkey == "" {
|
||||
return
|
||||
}
|
||||
if !strings.HasPrefix(s, "=") {
|
||||
return
|
||||
}
|
||||
var pvalue string
|
||||
pvalue, s = expectTokenOrQuoted(s[1:])
|
||||
if pvalue == "" {
|
||||
return
|
||||
}
|
||||
pkey = strings.ToLower(pkey)
|
||||
params[pkey] = pvalue
|
||||
s = skipSpace(s)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func skipSpace(s string) (rest string) {
|
||||
i := 0
|
||||
for ; i < len(s); i++ {
|
||||
if octetTypes[s[i]]&isSpace == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return s[i:]
|
||||
}
|
||||
|
||||
func expectToken(s string) (token, rest string) {
|
||||
i := 0
|
||||
for ; i < len(s); i++ {
|
||||
if octetTypes[s[i]]&isToken == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return s[:i], s[i:]
|
||||
}
|
||||
|
||||
func expectTokenOrQuoted(s string) (value string, rest string) {
|
||||
if !strings.HasPrefix(s, "\"") {
|
||||
return expectToken(s)
|
||||
}
|
||||
s = s[1:]
|
||||
for i := 0; i < len(s); i++ {
|
||||
switch s[i] {
|
||||
case '"':
|
||||
return s[:i], s[i+1:]
|
||||
case '\\':
|
||||
p := make([]byte, len(s)-1)
|
||||
j := copy(p, s[:i])
|
||||
escape := true
|
||||
for i = i + 1; i < len(s); i++ {
|
||||
b := s[i]
|
||||
switch {
|
||||
case escape:
|
||||
escape = false
|
||||
p[j] = b
|
||||
j++
|
||||
case b == '\\':
|
||||
escape = true
|
||||
case b == '"':
|
||||
return string(p[:j]), s[i+1:]
|
||||
default:
|
||||
p[j] = b
|
||||
j++
|
||||
}
|
||||
}
|
||||
return "", ""
|
||||
}
|
||||
}
|
||||
return "", ""
|
||||
}
|
||||
162
vendor/github.com/docker/distribution/registry/client/blob_writer.go
generated
vendored
162
vendor/github.com/docker/distribution/registry/client/blob_writer.go
generated
vendored
@@ -1,162 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/docker/distribution"
|
||||
"github.com/docker/distribution/context"
|
||||
)
|
||||
|
||||
type httpBlobUpload struct {
|
||||
statter distribution.BlobStatter
|
||||
client *http.Client
|
||||
|
||||
uuid string
|
||||
startedAt time.Time
|
||||
|
||||
location string // always the last value of the location header.
|
||||
offset int64
|
||||
closed bool
|
||||
}
|
||||
|
||||
func (hbu *httpBlobUpload) Reader() (io.ReadCloser, error) {
|
||||
panic("Not implemented")
|
||||
}
|
||||
|
||||
func (hbu *httpBlobUpload) handleErrorResponse(resp *http.Response) error {
|
||||
if resp.StatusCode == http.StatusNotFound {
|
||||
return distribution.ErrBlobUploadUnknown
|
||||
}
|
||||
return HandleErrorResponse(resp)
|
||||
}
|
||||
|
||||
func (hbu *httpBlobUpload) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
req, err := http.NewRequest("PATCH", hbu.location, ioutil.NopCloser(r))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer req.Body.Close()
|
||||
|
||||
resp, err := hbu.client.Do(req)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if !SuccessStatus(resp.StatusCode) {
|
||||
return 0, hbu.handleErrorResponse(resp)
|
||||
}
|
||||
|
||||
hbu.uuid = resp.Header.Get("Docker-Upload-UUID")
|
||||
hbu.location, err = sanitizeLocation(resp.Header.Get("Location"), hbu.location)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
rng := resp.Header.Get("Range")
|
||||
var start, end int64
|
||||
if n, err := fmt.Sscanf(rng, "%d-%d", &start, &end); err != nil {
|
||||
return 0, err
|
||||
} else if n != 2 || end < start {
|
||||
return 0, fmt.Errorf("bad range format: %s", rng)
|
||||
}
|
||||
|
||||
return (end - start + 1), nil
|
||||
|
||||
}
|
||||
|
||||
func (hbu *httpBlobUpload) Write(p []byte) (n int, err error) {
|
||||
req, err := http.NewRequest("PATCH", hbu.location, bytes.NewReader(p))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
req.Header.Set("Content-Range", fmt.Sprintf("%d-%d", hbu.offset, hbu.offset+int64(len(p)-1)))
|
||||
req.Header.Set("Content-Length", fmt.Sprintf("%d", len(p)))
|
||||
req.Header.Set("Content-Type", "application/octet-stream")
|
||||
|
||||
resp, err := hbu.client.Do(req)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if !SuccessStatus(resp.StatusCode) {
|
||||
return 0, hbu.handleErrorResponse(resp)
|
||||
}
|
||||
|
||||
hbu.uuid = resp.Header.Get("Docker-Upload-UUID")
|
||||
hbu.location, err = sanitizeLocation(resp.Header.Get("Location"), hbu.location)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
rng := resp.Header.Get("Range")
|
||||
var start, end int
|
||||
if n, err := fmt.Sscanf(rng, "%d-%d", &start, &end); err != nil {
|
||||
return 0, err
|
||||
} else if n != 2 || end < start {
|
||||
return 0, fmt.Errorf("bad range format: %s", rng)
|
||||
}
|
||||
|
||||
return (end - start + 1), nil
|
||||
|
||||
}
|
||||
|
||||
func (hbu *httpBlobUpload) Size() int64 {
|
||||
return hbu.offset
|
||||
}
|
||||
|
||||
func (hbu *httpBlobUpload) ID() string {
|
||||
return hbu.uuid
|
||||
}
|
||||
|
||||
func (hbu *httpBlobUpload) StartedAt() time.Time {
|
||||
return hbu.startedAt
|
||||
}
|
||||
|
||||
func (hbu *httpBlobUpload) Commit(ctx context.Context, desc distribution.Descriptor) (distribution.Descriptor, error) {
|
||||
// TODO(dmcgowan): Check if already finished, if so just fetch
|
||||
req, err := http.NewRequest("PUT", hbu.location, nil)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
}
|
||||
|
||||
values := req.URL.Query()
|
||||
values.Set("digest", desc.Digest.String())
|
||||
req.URL.RawQuery = values.Encode()
|
||||
|
||||
resp, err := hbu.client.Do(req)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if !SuccessStatus(resp.StatusCode) {
|
||||
return distribution.Descriptor{}, hbu.handleErrorResponse(resp)
|
||||
}
|
||||
|
||||
return hbu.statter.Stat(ctx, desc.Digest)
|
||||
}
|
||||
|
||||
func (hbu *httpBlobUpload) Cancel(ctx context.Context) error {
|
||||
req, err := http.NewRequest("DELETE", hbu.location, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp, err := hbu.client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode == http.StatusNotFound || SuccessStatus(resp.StatusCode) {
|
||||
return nil
|
||||
}
|
||||
return hbu.handleErrorResponse(resp)
|
||||
}
|
||||
|
||||
func (hbu *httpBlobUpload) Close() error {
|
||||
hbu.closed = true
|
||||
return nil
|
||||
}
|
||||
139
vendor/github.com/docker/distribution/registry/client/errors.go
generated
vendored
139
vendor/github.com/docker/distribution/registry/client/errors.go
generated
vendored
@@ -1,139 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"github.com/docker/distribution/registry/api/errcode"
|
||||
"github.com/docker/distribution/registry/client/auth/challenge"
|
||||
)
|
||||
|
||||
// ErrNoErrorsInBody is returned when an HTTP response body parses to an empty
|
||||
// errcode.Errors slice.
|
||||
var ErrNoErrorsInBody = errors.New("no error details found in HTTP response body")
|
||||
|
||||
// UnexpectedHTTPStatusError is returned when an unexpected HTTP status is
|
||||
// returned when making a registry api call.
|
||||
type UnexpectedHTTPStatusError struct {
|
||||
Status string
|
||||
}
|
||||
|
||||
func (e *UnexpectedHTTPStatusError) Error() string {
|
||||
return fmt.Sprintf("received unexpected HTTP status: %s", e.Status)
|
||||
}
|
||||
|
||||
// UnexpectedHTTPResponseError is returned when an expected HTTP status code
|
||||
// is returned, but the content was unexpected and failed to be parsed.
|
||||
type UnexpectedHTTPResponseError struct {
|
||||
ParseErr error
|
||||
StatusCode int
|
||||
Response []byte
|
||||
}
|
||||
|
||||
func (e *UnexpectedHTTPResponseError) Error() string {
|
||||
return fmt.Sprintf("error parsing HTTP %d response body: %s: %q", e.StatusCode, e.ParseErr.Error(), string(e.Response))
|
||||
}
|
||||
|
||||
func parseHTTPErrorResponse(statusCode int, r io.Reader) error {
|
||||
var errors errcode.Errors
|
||||
body, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// For backward compatibility, handle irregularly formatted
|
||||
// messages that contain a "details" field.
|
||||
var detailsErr struct {
|
||||
Details string `json:"details"`
|
||||
}
|
||||
err = json.Unmarshal(body, &detailsErr)
|
||||
if err == nil && detailsErr.Details != "" {
|
||||
switch statusCode {
|
||||
case http.StatusUnauthorized:
|
||||
return errcode.ErrorCodeUnauthorized.WithMessage(detailsErr.Details)
|
||||
case http.StatusTooManyRequests:
|
||||
return errcode.ErrorCodeTooManyRequests.WithMessage(detailsErr.Details)
|
||||
default:
|
||||
return errcode.ErrorCodeUnknown.WithMessage(detailsErr.Details)
|
||||
}
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(body, &errors); err != nil {
|
||||
return &UnexpectedHTTPResponseError{
|
||||
ParseErr: err,
|
||||
StatusCode: statusCode,
|
||||
Response: body,
|
||||
}
|
||||
}
|
||||
|
||||
if len(errors) == 0 {
|
||||
// If there was no error specified in the body, return
|
||||
// UnexpectedHTTPResponseError.
|
||||
return &UnexpectedHTTPResponseError{
|
||||
ParseErr: ErrNoErrorsInBody,
|
||||
StatusCode: statusCode,
|
||||
Response: body,
|
||||
}
|
||||
}
|
||||
|
||||
return errors
|
||||
}
|
||||
|
||||
func makeErrorList(err error) []error {
|
||||
if errL, ok := err.(errcode.Errors); ok {
|
||||
return []error(errL)
|
||||
}
|
||||
return []error{err}
|
||||
}
|
||||
|
||||
func mergeErrors(err1, err2 error) error {
|
||||
return errcode.Errors(append(makeErrorList(err1), makeErrorList(err2)...))
|
||||
}
|
||||
|
||||
// HandleErrorResponse returns error parsed from HTTP response for an
|
||||
// unsuccessful HTTP response code (in the range 400 - 499 inclusive). An
|
||||
// UnexpectedHTTPStatusError returned for response code outside of expected
|
||||
// range.
|
||||
func HandleErrorResponse(resp *http.Response) error {
|
||||
if resp.StatusCode >= 400 && resp.StatusCode < 500 {
|
||||
// Check for OAuth errors within the `WWW-Authenticate` header first
|
||||
// See https://tools.ietf.org/html/rfc6750#section-3
|
||||
for _, c := range challenge.ResponseChallenges(resp) {
|
||||
if c.Scheme == "bearer" {
|
||||
var err errcode.Error
|
||||
// codes defined at https://tools.ietf.org/html/rfc6750#section-3.1
|
||||
switch c.Parameters["error"] {
|
||||
case "invalid_token":
|
||||
err.Code = errcode.ErrorCodeUnauthorized
|
||||
case "insufficient_scope":
|
||||
err.Code = errcode.ErrorCodeDenied
|
||||
default:
|
||||
continue
|
||||
}
|
||||
if description := c.Parameters["error_description"]; description != "" {
|
||||
err.Message = description
|
||||
} else {
|
||||
err.Message = err.Code.Message()
|
||||
}
|
||||
|
||||
return mergeErrors(err, parseHTTPErrorResponse(resp.StatusCode, resp.Body))
|
||||
}
|
||||
}
|
||||
err := parseHTTPErrorResponse(resp.StatusCode, resp.Body)
|
||||
if uErr, ok := err.(*UnexpectedHTTPResponseError); ok && resp.StatusCode == 401 {
|
||||
return errcode.ErrorCodeUnauthorized.WithDetail(uErr.Response)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return &UnexpectedHTTPStatusError{Status: resp.Status}
|
||||
}
|
||||
|
||||
// SuccessStatus returns true if the argument is a successful HTTP response
|
||||
// code (in the range 200 - 399 inclusive).
|
||||
func SuccessStatus(status int) bool {
|
||||
return status >= 200 && status <= 399
|
||||
}
|
||||
853
vendor/github.com/docker/distribution/registry/client/repository.go
generated
vendored
853
vendor/github.com/docker/distribution/registry/client/repository.go
generated
vendored
@@ -1,853 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/distribution"
|
||||
"github.com/docker/distribution/context"
|
||||
"github.com/docker/distribution/digest"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/distribution/registry/api/v2"
|
||||
"github.com/docker/distribution/registry/client/transport"
|
||||
"github.com/docker/distribution/registry/storage/cache"
|
||||
"github.com/docker/distribution/registry/storage/cache/memory"
|
||||
)
|
||||
|
||||
// Registry provides an interface for calling Repositories, which returns a catalog of repositories.
|
||||
type Registry interface {
|
||||
Repositories(ctx context.Context, repos []string, last string) (n int, err error)
|
||||
}
|
||||
|
||||
// checkHTTPRedirect is a callback that can manipulate redirected HTTP
|
||||
// requests. It is used to preserve Accept and Range headers.
|
||||
func checkHTTPRedirect(req *http.Request, via []*http.Request) error {
|
||||
if len(via) >= 10 {
|
||||
return errors.New("stopped after 10 redirects")
|
||||
}
|
||||
|
||||
if len(via) > 0 {
|
||||
for headerName, headerVals := range via[0].Header {
|
||||
if headerName != "Accept" && headerName != "Range" {
|
||||
continue
|
||||
}
|
||||
for _, val := range headerVals {
|
||||
// Don't add to redirected request if redirected
|
||||
// request already has a header with the same
|
||||
// name and value.
|
||||
hasValue := false
|
||||
for _, existingVal := range req.Header[headerName] {
|
||||
if existingVal == val {
|
||||
hasValue = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !hasValue {
|
||||
req.Header.Add(headerName, val)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewRegistry creates a registry namespace which can be used to get a listing of repositories
|
||||
func NewRegistry(ctx context.Context, baseURL string, transport http.RoundTripper) (Registry, error) {
|
||||
ub, err := v2.NewURLBuilderFromString(baseURL, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client := &http.Client{
|
||||
Transport: transport,
|
||||
Timeout: 1 * time.Minute,
|
||||
CheckRedirect: checkHTTPRedirect,
|
||||
}
|
||||
|
||||
return ®istry{
|
||||
client: client,
|
||||
ub: ub,
|
||||
context: ctx,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type registry struct {
|
||||
client *http.Client
|
||||
ub *v2.URLBuilder
|
||||
context context.Context
|
||||
}
|
||||
|
||||
// Repositories returns a lexigraphically sorted catalog given a base URL. The 'entries' slice will be filled up to the size
|
||||
// of the slice, starting at the value provided in 'last'. The number of entries will be returned along with io.EOF if there
|
||||
// are no more entries
|
||||
func (r *registry) Repositories(ctx context.Context, entries []string, last string) (int, error) {
|
||||
var numFilled int
|
||||
var returnErr error
|
||||
|
||||
values := buildCatalogValues(len(entries), last)
|
||||
u, err := r.ub.BuildCatalogURL(values)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
resp, err := r.client.Get(u)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if SuccessStatus(resp.StatusCode) {
|
||||
var ctlg struct {
|
||||
Repositories []string `json:"repositories"`
|
||||
}
|
||||
decoder := json.NewDecoder(resp.Body)
|
||||
|
||||
if err := decoder.Decode(&ctlg); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
for cnt := range ctlg.Repositories {
|
||||
entries[cnt] = ctlg.Repositories[cnt]
|
||||
}
|
||||
numFilled = len(ctlg.Repositories)
|
||||
|
||||
link := resp.Header.Get("Link")
|
||||
if link == "" {
|
||||
returnErr = io.EOF
|
||||
}
|
||||
} else {
|
||||
return 0, HandleErrorResponse(resp)
|
||||
}
|
||||
|
||||
return numFilled, returnErr
|
||||
}
|
||||
|
||||
// NewRepository creates a new Repository for the given repository name and base URL.
|
||||
func NewRepository(ctx context.Context, name reference.Named, baseURL string, transport http.RoundTripper) (distribution.Repository, error) {
|
||||
ub, err := v2.NewURLBuilderFromString(baseURL, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client := &http.Client{
|
||||
Transport: transport,
|
||||
CheckRedirect: checkHTTPRedirect,
|
||||
// TODO(dmcgowan): create cookie jar
|
||||
}
|
||||
|
||||
return &repository{
|
||||
client: client,
|
||||
ub: ub,
|
||||
name: name,
|
||||
context: ctx,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type repository struct {
|
||||
client *http.Client
|
||||
ub *v2.URLBuilder
|
||||
context context.Context
|
||||
name reference.Named
|
||||
}
|
||||
|
||||
func (r *repository) Named() reference.Named {
|
||||
return r.name
|
||||
}
|
||||
|
||||
func (r *repository) Blobs(ctx context.Context) distribution.BlobStore {
|
||||
statter := &blobStatter{
|
||||
name: r.name,
|
||||
ub: r.ub,
|
||||
client: r.client,
|
||||
}
|
||||
return &blobs{
|
||||
name: r.name,
|
||||
ub: r.ub,
|
||||
client: r.client,
|
||||
statter: cache.NewCachedBlobStatter(memory.NewInMemoryBlobDescriptorCacheProvider(), statter),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *repository) Manifests(ctx context.Context, options ...distribution.ManifestServiceOption) (distribution.ManifestService, error) {
|
||||
// todo(richardscothern): options should be sent over the wire
|
||||
return &manifests{
|
||||
name: r.name,
|
||||
ub: r.ub,
|
||||
client: r.client,
|
||||
etags: make(map[string]string),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *repository) Tags(ctx context.Context) distribution.TagService {
|
||||
return &tags{
|
||||
client: r.client,
|
||||
ub: r.ub,
|
||||
context: r.context,
|
||||
name: r.Named(),
|
||||
}
|
||||
}
|
||||
|
||||
// tags implements remote tagging operations.
|
||||
type tags struct {
|
||||
client *http.Client
|
||||
ub *v2.URLBuilder
|
||||
context context.Context
|
||||
name reference.Named
|
||||
}
|
||||
|
||||
// All returns all tags
|
||||
func (t *tags) All(ctx context.Context) ([]string, error) {
|
||||
var tags []string
|
||||
|
||||
u, err := t.ub.BuildTagsURL(t.name)
|
||||
if err != nil {
|
||||
return tags, err
|
||||
}
|
||||
|
||||
for {
|
||||
resp, err := t.client.Get(u)
|
||||
if err != nil {
|
||||
return tags, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if SuccessStatus(resp.StatusCode) {
|
||||
b, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return tags, err
|
||||
}
|
||||
|
||||
tagsResponse := struct {
|
||||
Tags []string `json:"tags"`
|
||||
}{}
|
||||
if err := json.Unmarshal(b, &tagsResponse); err != nil {
|
||||
return tags, err
|
||||
}
|
||||
tags = append(tags, tagsResponse.Tags...)
|
||||
if link := resp.Header.Get("Link"); link != "" {
|
||||
u = strings.Trim(strings.Split(link, ";")[0], "<>")
|
||||
} else {
|
||||
return tags, nil
|
||||
}
|
||||
} else {
|
||||
return tags, HandleErrorResponse(resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func descriptorFromResponse(response *http.Response) (distribution.Descriptor, error) {
|
||||
desc := distribution.Descriptor{}
|
||||
headers := response.Header
|
||||
|
||||
ctHeader := headers.Get("Content-Type")
|
||||
if ctHeader == "" {
|
||||
return distribution.Descriptor{}, errors.New("missing or empty Content-Type header")
|
||||
}
|
||||
desc.MediaType = ctHeader
|
||||
|
||||
digestHeader := headers.Get("Docker-Content-Digest")
|
||||
if digestHeader == "" {
|
||||
bytes, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
}
|
||||
_, desc, err := distribution.UnmarshalManifest(ctHeader, bytes)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
}
|
||||
return desc, nil
|
||||
}
|
||||
|
||||
dgst, err := digest.ParseDigest(digestHeader)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
}
|
||||
desc.Digest = dgst
|
||||
|
||||
lengthHeader := headers.Get("Content-Length")
|
||||
if lengthHeader == "" {
|
||||
return distribution.Descriptor{}, errors.New("missing or empty Content-Length header")
|
||||
}
|
||||
length, err := strconv.ParseInt(lengthHeader, 10, 64)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
}
|
||||
desc.Size = length
|
||||
|
||||
return desc, nil
|
||||
|
||||
}
|
||||
|
||||
// Get issues a HEAD request for a Manifest against its named endpoint in order
|
||||
// to construct a descriptor for the tag. If the registry doesn't support HEADing
|
||||
// a manifest, fallback to GET.
|
||||
func (t *tags) Get(ctx context.Context, tag string) (distribution.Descriptor, error) {
|
||||
ref, err := reference.WithTag(t.name, tag)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
}
|
||||
u, err := t.ub.BuildManifestURL(ref)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
}
|
||||
|
||||
newRequest := func(method string) (*http.Response, error) {
|
||||
req, err := http.NewRequest(method, u, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, t := range distribution.ManifestMediaTypes() {
|
||||
req.Header.Add("Accept", t)
|
||||
}
|
||||
resp, err := t.client.Do(req)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
resp, err := newRequest("HEAD")
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
switch {
|
||||
case resp.StatusCode >= 200 && resp.StatusCode < 400:
|
||||
return descriptorFromResponse(resp)
|
||||
default:
|
||||
// if the response is an error - there will be no body to decode.
|
||||
// Issue a GET request:
|
||||
// - for data from a server that does not handle HEAD
|
||||
// - to get error details in case of a failure
|
||||
resp, err = newRequest("GET")
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode >= 200 && resp.StatusCode < 400 {
|
||||
return descriptorFromResponse(resp)
|
||||
}
|
||||
return distribution.Descriptor{}, HandleErrorResponse(resp)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tags) Lookup(ctx context.Context, digest distribution.Descriptor) ([]string, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (t *tags) Tag(ctx context.Context, tag string, desc distribution.Descriptor) error {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (t *tags) Untag(ctx context.Context, tag string) error {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
type manifests struct {
|
||||
name reference.Named
|
||||
ub *v2.URLBuilder
|
||||
client *http.Client
|
||||
etags map[string]string
|
||||
}
|
||||
|
||||
func (ms *manifests) Exists(ctx context.Context, dgst digest.Digest) (bool, error) {
|
||||
ref, err := reference.WithDigest(ms.name, dgst)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
u, err := ms.ub.BuildManifestURL(ref)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := ms.client.Head(u)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if SuccessStatus(resp.StatusCode) {
|
||||
return true, nil
|
||||
} else if resp.StatusCode == http.StatusNotFound {
|
||||
return false, nil
|
||||
}
|
||||
return false, HandleErrorResponse(resp)
|
||||
}
|
||||
|
||||
// AddEtagToTag allows a client to supply an eTag to Get which will be
|
||||
// used for a conditional HTTP request. If the eTag matches, a nil manifest
|
||||
// and ErrManifestNotModified error will be returned. etag is automatically
|
||||
// quoted when added to this map.
|
||||
func AddEtagToTag(tag, etag string) distribution.ManifestServiceOption {
|
||||
return etagOption{tag, etag}
|
||||
}
|
||||
|
||||
type etagOption struct{ tag, etag string }
|
||||
|
||||
func (o etagOption) Apply(ms distribution.ManifestService) error {
|
||||
if ms, ok := ms.(*manifests); ok {
|
||||
ms.etags[o.tag] = fmt.Sprintf(`"%s"`, o.etag)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("etag options is a client-only option")
|
||||
}
|
||||
|
||||
// ReturnContentDigest allows a client to set a the content digest on
|
||||
// a successful request from the 'Docker-Content-Digest' header. This
|
||||
// returned digest is represents the digest which the registry uses
|
||||
// to refer to the content and can be used to delete the content.
|
||||
func ReturnContentDigest(dgst *digest.Digest) distribution.ManifestServiceOption {
|
||||
return contentDigestOption{dgst}
|
||||
}
|
||||
|
||||
type contentDigestOption struct{ digest *digest.Digest }
|
||||
|
||||
func (o contentDigestOption) Apply(ms distribution.ManifestService) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ms *manifests) Get(ctx context.Context, dgst digest.Digest, options ...distribution.ManifestServiceOption) (distribution.Manifest, error) {
|
||||
var (
|
||||
digestOrTag string
|
||||
ref reference.Named
|
||||
err error
|
||||
contentDgst *digest.Digest
|
||||
)
|
||||
|
||||
for _, option := range options {
|
||||
if opt, ok := option.(distribution.WithTagOption); ok {
|
||||
digestOrTag = opt.Tag
|
||||
ref, err = reference.WithTag(ms.name, opt.Tag)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if opt, ok := option.(contentDigestOption); ok {
|
||||
contentDgst = opt.digest
|
||||
} else {
|
||||
err := option.Apply(ms)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if digestOrTag == "" {
|
||||
digestOrTag = dgst.String()
|
||||
ref, err = reference.WithDigest(ms.name, dgst)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
u, err := ms.ub.BuildManifestURL(ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("GET", u, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, t := range distribution.ManifestMediaTypes() {
|
||||
req.Header.Add("Accept", t)
|
||||
}
|
||||
|
||||
if _, ok := ms.etags[digestOrTag]; ok {
|
||||
req.Header.Set("If-None-Match", ms.etags[digestOrTag])
|
||||
}
|
||||
|
||||
resp, err := ms.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode == http.StatusNotModified {
|
||||
return nil, distribution.ErrManifestNotModified
|
||||
} else if SuccessStatus(resp.StatusCode) {
|
||||
if contentDgst != nil {
|
||||
dgst, err := digest.ParseDigest(resp.Header.Get("Docker-Content-Digest"))
|
||||
if err == nil {
|
||||
*contentDgst = dgst
|
||||
}
|
||||
}
|
||||
mt := resp.Header.Get("Content-Type")
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m, _, err := distribution.UnmarshalManifest(mt, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
return nil, HandleErrorResponse(resp)
|
||||
}
|
||||
|
||||
// Put puts a manifest. A tag can be specified using an options parameter which uses some shared state to hold the
|
||||
// tag name in order to build the correct upload URL.
|
||||
func (ms *manifests) Put(ctx context.Context, m distribution.Manifest, options ...distribution.ManifestServiceOption) (digest.Digest, error) {
|
||||
ref := ms.name
|
||||
var tagged bool
|
||||
|
||||
for _, option := range options {
|
||||
if opt, ok := option.(distribution.WithTagOption); ok {
|
||||
var err error
|
||||
ref, err = reference.WithTag(ref, opt.Tag)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tagged = true
|
||||
} else {
|
||||
err := option.Apply(ms)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
}
|
||||
mediaType, p, err := m.Payload()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if !tagged {
|
||||
// generate a canonical digest and Put by digest
|
||||
_, d, err := distribution.UnmarshalManifest(mediaType, p)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
ref, err = reference.WithDigest(ref, d.Digest)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
manifestURL, err := ms.ub.BuildManifestURL(ref)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
putRequest, err := http.NewRequest("PUT", manifestURL, bytes.NewReader(p))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
putRequest.Header.Set("Content-Type", mediaType)
|
||||
|
||||
resp, err := ms.client.Do(putRequest)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if SuccessStatus(resp.StatusCode) {
|
||||
dgstHeader := resp.Header.Get("Docker-Content-Digest")
|
||||
dgst, err := digest.ParseDigest(dgstHeader)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return dgst, nil
|
||||
}
|
||||
|
||||
return "", HandleErrorResponse(resp)
|
||||
}
|
||||
|
||||
func (ms *manifests) Delete(ctx context.Context, dgst digest.Digest) error {
|
||||
ref, err := reference.WithDigest(ms.name, dgst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
u, err := ms.ub.BuildManifestURL(ref)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req, err := http.NewRequest("DELETE", u, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := ms.client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if SuccessStatus(resp.StatusCode) {
|
||||
return nil
|
||||
}
|
||||
return HandleErrorResponse(resp)
|
||||
}
|
||||
|
||||
// todo(richardscothern): Restore interface and implementation with merge of #1050
|
||||
/*func (ms *manifests) Enumerate(ctx context.Context, manifests []distribution.Manifest, last distribution.Manifest) (n int, err error) {
|
||||
panic("not supported")
|
||||
}*/
|
||||
|
||||
type blobs struct {
|
||||
name reference.Named
|
||||
ub *v2.URLBuilder
|
||||
client *http.Client
|
||||
|
||||
statter distribution.BlobDescriptorService
|
||||
distribution.BlobDeleter
|
||||
}
|
||||
|
||||
func sanitizeLocation(location, base string) (string, error) {
|
||||
baseURL, err := url.Parse(base)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
locationURL, err := url.Parse(location)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return baseURL.ResolveReference(locationURL).String(), nil
|
||||
}
|
||||
|
||||
func (bs *blobs) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
|
||||
return bs.statter.Stat(ctx, dgst)
|
||||
|
||||
}
|
||||
|
||||
func (bs *blobs) Get(ctx context.Context, dgst digest.Digest) ([]byte, error) {
|
||||
reader, err := bs.Open(ctx, dgst)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
return ioutil.ReadAll(reader)
|
||||
}
|
||||
|
||||
func (bs *blobs) Open(ctx context.Context, dgst digest.Digest) (distribution.ReadSeekCloser, error) {
|
||||
ref, err := reference.WithDigest(bs.name, dgst)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
blobURL, err := bs.ub.BuildBlobURL(ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return transport.NewHTTPReadSeeker(bs.client, blobURL,
|
||||
func(resp *http.Response) error {
|
||||
if resp.StatusCode == http.StatusNotFound {
|
||||
return distribution.ErrBlobUnknown
|
||||
}
|
||||
return HandleErrorResponse(resp)
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (bs *blobs) ServeBlob(ctx context.Context, w http.ResponseWriter, r *http.Request, dgst digest.Digest) error {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (bs *blobs) Put(ctx context.Context, mediaType string, p []byte) (distribution.Descriptor, error) {
|
||||
writer, err := bs.Create(ctx)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
}
|
||||
dgstr := digest.Canonical.New()
|
||||
n, err := io.Copy(writer, io.TeeReader(bytes.NewReader(p), dgstr.Hash()))
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
}
|
||||
if n < int64(len(p)) {
|
||||
return distribution.Descriptor{}, fmt.Errorf("short copy: wrote %d of %d", n, len(p))
|
||||
}
|
||||
|
||||
desc := distribution.Descriptor{
|
||||
MediaType: mediaType,
|
||||
Size: int64(len(p)),
|
||||
Digest: dgstr.Digest(),
|
||||
}
|
||||
|
||||
return writer.Commit(ctx, desc)
|
||||
}
|
||||
|
||||
type optionFunc func(interface{}) error
|
||||
|
||||
func (f optionFunc) Apply(v interface{}) error {
|
||||
return f(v)
|
||||
}
|
||||
|
||||
// WithMountFrom returns a BlobCreateOption which designates that the blob should be
|
||||
// mounted from the given canonical reference.
|
||||
func WithMountFrom(ref reference.Canonical) distribution.BlobCreateOption {
|
||||
return optionFunc(func(v interface{}) error {
|
||||
opts, ok := v.(*distribution.CreateOptions)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected options type: %T", v)
|
||||
}
|
||||
|
||||
opts.Mount.ShouldMount = true
|
||||
opts.Mount.From = ref
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (bs *blobs) Create(ctx context.Context, options ...distribution.BlobCreateOption) (distribution.BlobWriter, error) {
|
||||
var opts distribution.CreateOptions
|
||||
|
||||
for _, option := range options {
|
||||
err := option.Apply(&opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var values []url.Values
|
||||
|
||||
if opts.Mount.ShouldMount {
|
||||
values = append(values, url.Values{"from": {opts.Mount.From.Name()}, "mount": {opts.Mount.From.Digest().String()}})
|
||||
}
|
||||
|
||||
u, err := bs.ub.BuildBlobUploadURL(bs.name, values...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bs.client.Post(u, "", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
switch resp.StatusCode {
|
||||
case http.StatusCreated:
|
||||
desc, err := bs.statter.Stat(ctx, opts.Mount.From.Digest())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, distribution.ErrBlobMounted{From: opts.Mount.From, Descriptor: desc}
|
||||
case http.StatusAccepted:
|
||||
// TODO(dmcgowan): Check for invalid UUID
|
||||
uuid := resp.Header.Get("Docker-Upload-UUID")
|
||||
location, err := sanitizeLocation(resp.Header.Get("Location"), u)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &httpBlobUpload{
|
||||
statter: bs.statter,
|
||||
client: bs.client,
|
||||
uuid: uuid,
|
||||
startedAt: time.Now(),
|
||||
location: location,
|
||||
}, nil
|
||||
default:
|
||||
return nil, HandleErrorResponse(resp)
|
||||
}
|
||||
}
|
||||
|
||||
func (bs *blobs) Resume(ctx context.Context, id string) (distribution.BlobWriter, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (bs *blobs) Delete(ctx context.Context, dgst digest.Digest) error {
|
||||
return bs.statter.Clear(ctx, dgst)
|
||||
}
|
||||
|
||||
type blobStatter struct {
|
||||
name reference.Named
|
||||
ub *v2.URLBuilder
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
func (bs *blobStatter) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
|
||||
ref, err := reference.WithDigest(bs.name, dgst)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
}
|
||||
u, err := bs.ub.BuildBlobURL(ref)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
}
|
||||
|
||||
resp, err := bs.client.Head(u)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if SuccessStatus(resp.StatusCode) {
|
||||
lengthHeader := resp.Header.Get("Content-Length")
|
||||
if lengthHeader == "" {
|
||||
return distribution.Descriptor{}, fmt.Errorf("missing content-length header for request: %s", u)
|
||||
}
|
||||
|
||||
length, err := strconv.ParseInt(lengthHeader, 10, 64)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, fmt.Errorf("error parsing content-length: %v", err)
|
||||
}
|
||||
|
||||
return distribution.Descriptor{
|
||||
MediaType: resp.Header.Get("Content-Type"),
|
||||
Size: length,
|
||||
Digest: dgst,
|
||||
}, nil
|
||||
} else if resp.StatusCode == http.StatusNotFound {
|
||||
return distribution.Descriptor{}, distribution.ErrBlobUnknown
|
||||
}
|
||||
return distribution.Descriptor{}, HandleErrorResponse(resp)
|
||||
}
|
||||
|
||||
func buildCatalogValues(maxEntries int, last string) url.Values {
|
||||
values := url.Values{}
|
||||
|
||||
if maxEntries > 0 {
|
||||
values.Add("n", strconv.Itoa(maxEntries))
|
||||
}
|
||||
|
||||
if last != "" {
|
||||
values.Add("last", last)
|
||||
}
|
||||
|
||||
return values
|
||||
}
|
||||
|
||||
func (bs *blobStatter) Clear(ctx context.Context, dgst digest.Digest) error {
|
||||
ref, err := reference.WithDigest(bs.name, dgst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
blobURL, err := bs.ub.BuildBlobURL(ref)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("DELETE", blobURL, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := bs.client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if SuccessStatus(resp.StatusCode) {
|
||||
return nil
|
||||
}
|
||||
return HandleErrorResponse(resp)
|
||||
}
|
||||
|
||||
func (bs *blobStatter) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
|
||||
return nil
|
||||
}
|
||||
251
vendor/github.com/docker/distribution/registry/client/transport/http_reader.go
generated
vendored
251
vendor/github.com/docker/distribution/registry/client/transport/http_reader.go
generated
vendored
@@ -1,251 +0,0 @@
|
||||
package transport
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var (
|
||||
contentRangeRegexp = regexp.MustCompile(`bytes ([0-9]+)-([0-9]+)/([0-9]+|\\*)`)
|
||||
|
||||
// ErrWrongCodeForByteRange is returned if the client sends a request
|
||||
// with a Range header but the server returns a 2xx or 3xx code other
|
||||
// than 206 Partial Content.
|
||||
ErrWrongCodeForByteRange = errors.New("expected HTTP 206 from byte range request")
|
||||
)
|
||||
|
||||
// ReadSeekCloser combines io.ReadSeeker with io.Closer.
|
||||
type ReadSeekCloser interface {
|
||||
io.ReadSeeker
|
||||
io.Closer
|
||||
}
|
||||
|
||||
// NewHTTPReadSeeker handles reading from an HTTP endpoint using a GET
|
||||
// request. When seeking and starting a read from a non-zero offset
|
||||
// the a "Range" header will be added which sets the offset.
|
||||
// TODO(dmcgowan): Move this into a separate utility package
|
||||
func NewHTTPReadSeeker(client *http.Client, url string, errorHandler func(*http.Response) error) ReadSeekCloser {
|
||||
return &httpReadSeeker{
|
||||
client: client,
|
||||
url: url,
|
||||
errorHandler: errorHandler,
|
||||
}
|
||||
}
|
||||
|
||||
type httpReadSeeker struct {
|
||||
client *http.Client
|
||||
url string
|
||||
|
||||
// errorHandler creates an error from an unsuccessful HTTP response.
|
||||
// This allows the error to be created with the HTTP response body
|
||||
// without leaking the body through a returned error.
|
||||
errorHandler func(*http.Response) error
|
||||
|
||||
size int64
|
||||
|
||||
// rc is the remote read closer.
|
||||
rc io.ReadCloser
|
||||
// readerOffset tracks the offset as of the last read.
|
||||
readerOffset int64
|
||||
// seekOffset allows Seek to override the offset. Seek changes
|
||||
// seekOffset instead of changing readOffset directly so that
|
||||
// connection resets can be delayed and possibly avoided if the
|
||||
// seek is undone (i.e. seeking to the end and then back to the
|
||||
// beginning).
|
||||
seekOffset int64
|
||||
err error
|
||||
}
|
||||
|
||||
func (hrs *httpReadSeeker) Read(p []byte) (n int, err error) {
|
||||
if hrs.err != nil {
|
||||
return 0, hrs.err
|
||||
}
|
||||
|
||||
// If we sought to a different position, we need to reset the
|
||||
// connection. This logic is here instead of Seek so that if
|
||||
// a seek is undone before the next read, the connection doesn't
|
||||
// need to be closed and reopened. A common example of this is
|
||||
// seeking to the end to determine the length, and then seeking
|
||||
// back to the original position.
|
||||
if hrs.readerOffset != hrs.seekOffset {
|
||||
hrs.reset()
|
||||
}
|
||||
|
||||
hrs.readerOffset = hrs.seekOffset
|
||||
|
||||
rd, err := hrs.reader()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
n, err = rd.Read(p)
|
||||
hrs.seekOffset += int64(n)
|
||||
hrs.readerOffset += int64(n)
|
||||
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (hrs *httpReadSeeker) Seek(offset int64, whence int) (int64, error) {
|
||||
if hrs.err != nil {
|
||||
return 0, hrs.err
|
||||
}
|
||||
|
||||
lastReaderOffset := hrs.readerOffset
|
||||
|
||||
if whence == os.SEEK_SET && hrs.rc == nil {
|
||||
// If no request has been made yet, and we are seeking to an
|
||||
// absolute position, set the read offset as well to avoid an
|
||||
// unnecessary request.
|
||||
hrs.readerOffset = offset
|
||||
}
|
||||
|
||||
_, err := hrs.reader()
|
||||
if err != nil {
|
||||
hrs.readerOffset = lastReaderOffset
|
||||
return 0, err
|
||||
}
|
||||
|
||||
newOffset := hrs.seekOffset
|
||||
|
||||
switch whence {
|
||||
case os.SEEK_CUR:
|
||||
newOffset += offset
|
||||
case os.SEEK_END:
|
||||
if hrs.size < 0 {
|
||||
return 0, errors.New("content length not known")
|
||||
}
|
||||
newOffset = hrs.size + offset
|
||||
case os.SEEK_SET:
|
||||
newOffset = offset
|
||||
}
|
||||
|
||||
if newOffset < 0 {
|
||||
err = errors.New("cannot seek to negative position")
|
||||
} else {
|
||||
hrs.seekOffset = newOffset
|
||||
}
|
||||
|
||||
return hrs.seekOffset, err
|
||||
}
|
||||
|
||||
func (hrs *httpReadSeeker) Close() error {
|
||||
if hrs.err != nil {
|
||||
return hrs.err
|
||||
}
|
||||
|
||||
// close and release reader chain
|
||||
if hrs.rc != nil {
|
||||
hrs.rc.Close()
|
||||
}
|
||||
|
||||
hrs.rc = nil
|
||||
|
||||
hrs.err = errors.New("httpLayer: closed")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hrs *httpReadSeeker) reset() {
|
||||
if hrs.err != nil {
|
||||
return
|
||||
}
|
||||
if hrs.rc != nil {
|
||||
hrs.rc.Close()
|
||||
hrs.rc = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (hrs *httpReadSeeker) reader() (io.Reader, error) {
|
||||
if hrs.err != nil {
|
||||
return nil, hrs.err
|
||||
}
|
||||
|
||||
if hrs.rc != nil {
|
||||
return hrs.rc, nil
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("GET", hrs.url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if hrs.readerOffset > 0 {
|
||||
// If we are at different offset, issue a range request from there.
|
||||
req.Header.Add("Range", fmt.Sprintf("bytes=%d-", hrs.readerOffset))
|
||||
// TODO: get context in here
|
||||
// context.GetLogger(hrs.context).Infof("Range: %s", req.Header.Get("Range"))
|
||||
}
|
||||
|
||||
req.Header.Add("Accept-Encoding", "identity")
|
||||
resp, err := hrs.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Normally would use client.SuccessStatus, but that would be a cyclic
|
||||
// import
|
||||
if resp.StatusCode >= 200 && resp.StatusCode <= 399 {
|
||||
if hrs.readerOffset > 0 {
|
||||
if resp.StatusCode != http.StatusPartialContent {
|
||||
return nil, ErrWrongCodeForByteRange
|
||||
}
|
||||
|
||||
contentRange := resp.Header.Get("Content-Range")
|
||||
if contentRange == "" {
|
||||
return nil, errors.New("no Content-Range header found in HTTP 206 response")
|
||||
}
|
||||
|
||||
submatches := contentRangeRegexp.FindStringSubmatch(contentRange)
|
||||
if len(submatches) < 4 {
|
||||
return nil, fmt.Errorf("could not parse Content-Range header: %s", contentRange)
|
||||
}
|
||||
|
||||
startByte, err := strconv.ParseUint(submatches[1], 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not parse start of range in Content-Range header: %s", contentRange)
|
||||
}
|
||||
|
||||
if startByte != uint64(hrs.readerOffset) {
|
||||
return nil, fmt.Errorf("received Content-Range starting at offset %d instead of requested %d", startByte, hrs.readerOffset)
|
||||
}
|
||||
|
||||
endByte, err := strconv.ParseUint(submatches[2], 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not parse end of range in Content-Range header: %s", contentRange)
|
||||
}
|
||||
|
||||
if submatches[3] == "*" {
|
||||
hrs.size = -1
|
||||
} else {
|
||||
size, err := strconv.ParseUint(submatches[3], 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not parse total size in Content-Range header: %s", contentRange)
|
||||
}
|
||||
|
||||
if endByte+1 != size {
|
||||
return nil, fmt.Errorf("range in Content-Range stops before the end of the content: %s", contentRange)
|
||||
}
|
||||
|
||||
hrs.size = int64(size)
|
||||
}
|
||||
} else if resp.StatusCode == http.StatusOK {
|
||||
hrs.size = resp.ContentLength
|
||||
} else {
|
||||
hrs.size = -1
|
||||
}
|
||||
hrs.rc = resp.Body
|
||||
} else {
|
||||
defer resp.Body.Close()
|
||||
if hrs.errorHandler != nil {
|
||||
return nil, hrs.errorHandler(resp)
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected status resolving reader: %v", resp.Status)
|
||||
}
|
||||
|
||||
return hrs.rc, nil
|
||||
}
|
||||
147
vendor/github.com/docker/distribution/registry/client/transport/transport.go
generated
vendored
147
vendor/github.com/docker/distribution/registry/client/transport/transport.go
generated
vendored
@@ -1,147 +0,0 @@
|
||||
package transport
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// RequestModifier represents an object which will do an inplace
|
||||
// modification of an HTTP request.
|
||||
type RequestModifier interface {
|
||||
ModifyRequest(*http.Request) error
|
||||
}
|
||||
|
||||
type headerModifier http.Header
|
||||
|
||||
// NewHeaderRequestModifier returns a new RequestModifier which will
|
||||
// add the given headers to a request.
|
||||
func NewHeaderRequestModifier(header http.Header) RequestModifier {
|
||||
return headerModifier(header)
|
||||
}
|
||||
|
||||
func (h headerModifier) ModifyRequest(req *http.Request) error {
|
||||
for k, s := range http.Header(h) {
|
||||
req.Header[k] = append(req.Header[k], s...)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewTransport creates a new transport which will apply modifiers to
|
||||
// the request on a RoundTrip call.
|
||||
func NewTransport(base http.RoundTripper, modifiers ...RequestModifier) http.RoundTripper {
|
||||
return &transport{
|
||||
Modifiers: modifiers,
|
||||
Base: base,
|
||||
}
|
||||
}
|
||||
|
||||
// transport is an http.RoundTripper that makes HTTP requests after
|
||||
// copying and modifying the request
|
||||
type transport struct {
|
||||
Modifiers []RequestModifier
|
||||
Base http.RoundTripper
|
||||
|
||||
mu sync.Mutex // guards modReq
|
||||
modReq map[*http.Request]*http.Request // original -> modified
|
||||
}
|
||||
|
||||
// RoundTrip authorizes and authenticates the request with an
|
||||
// access token. If no token exists or token is expired,
|
||||
// tries to refresh/fetch a new token.
|
||||
func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
req2 := cloneRequest(req)
|
||||
for _, modifier := range t.Modifiers {
|
||||
if err := modifier.ModifyRequest(req2); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
t.setModReq(req, req2)
|
||||
res, err := t.base().RoundTrip(req2)
|
||||
if err != nil {
|
||||
t.setModReq(req, nil)
|
||||
return nil, err
|
||||
}
|
||||
res.Body = &onEOFReader{
|
||||
rc: res.Body,
|
||||
fn: func() { t.setModReq(req, nil) },
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// CancelRequest cancels an in-flight request by closing its connection.
|
||||
func (t *transport) CancelRequest(req *http.Request) {
|
||||
type canceler interface {
|
||||
CancelRequest(*http.Request)
|
||||
}
|
||||
if cr, ok := t.base().(canceler); ok {
|
||||
t.mu.Lock()
|
||||
modReq := t.modReq[req]
|
||||
delete(t.modReq, req)
|
||||
t.mu.Unlock()
|
||||
cr.CancelRequest(modReq)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *transport) base() http.RoundTripper {
|
||||
if t.Base != nil {
|
||||
return t.Base
|
||||
}
|
||||
return http.DefaultTransport
|
||||
}
|
||||
|
||||
func (t *transport) setModReq(orig, mod *http.Request) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
if t.modReq == nil {
|
||||
t.modReq = make(map[*http.Request]*http.Request)
|
||||
}
|
||||
if mod == nil {
|
||||
delete(t.modReq, orig)
|
||||
} else {
|
||||
t.modReq[orig] = mod
|
||||
}
|
||||
}
|
||||
|
||||
// cloneRequest returns a clone of the provided *http.Request.
|
||||
// The clone is a shallow copy of the struct and its Header map.
|
||||
func cloneRequest(r *http.Request) *http.Request {
|
||||
// shallow copy of the struct
|
||||
r2 := new(http.Request)
|
||||
*r2 = *r
|
||||
// deep copy of the Header
|
||||
r2.Header = make(http.Header, len(r.Header))
|
||||
for k, s := range r.Header {
|
||||
r2.Header[k] = append([]string(nil), s...)
|
||||
}
|
||||
|
||||
return r2
|
||||
}
|
||||
|
||||
type onEOFReader struct {
|
||||
rc io.ReadCloser
|
||||
fn func()
|
||||
}
|
||||
|
||||
func (r *onEOFReader) Read(p []byte) (n int, err error) {
|
||||
n, err = r.rc.Read(p)
|
||||
if err == io.EOF {
|
||||
r.runFunc()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (r *onEOFReader) Close() error {
|
||||
err := r.rc.Close()
|
||||
r.runFunc()
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *onEOFReader) runFunc() {
|
||||
if fn := r.fn; fn != nil {
|
||||
fn()
|
||||
r.fn = nil
|
||||
}
|
||||
}
|
||||
35
vendor/github.com/docker/distribution/registry/storage/cache/cache.go
generated
vendored
35
vendor/github.com/docker/distribution/registry/storage/cache/cache.go
generated
vendored
@@ -1,35 +0,0 @@
|
||||
// Package cache provides facilities to speed up access to the storage
|
||||
// backend.
|
||||
package cache
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/distribution"
|
||||
)
|
||||
|
||||
// BlobDescriptorCacheProvider provides repository scoped
|
||||
// BlobDescriptorService cache instances and a global descriptor cache.
|
||||
type BlobDescriptorCacheProvider interface {
|
||||
distribution.BlobDescriptorService
|
||||
|
||||
RepositoryScoped(repo string) (distribution.BlobDescriptorService, error)
|
||||
}
|
||||
|
||||
// ValidateDescriptor provides a helper function to ensure that caches have
|
||||
// common criteria for admitting descriptors.
|
||||
func ValidateDescriptor(desc distribution.Descriptor) error {
|
||||
if err := desc.Digest.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if desc.Size < 0 {
|
||||
return fmt.Errorf("cache: invalid length in descriptor: %v < 0", desc.Size)
|
||||
}
|
||||
|
||||
if desc.MediaType == "" {
|
||||
return fmt.Errorf("cache: empty mediatype on descriptor: %v", desc)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
101
vendor/github.com/docker/distribution/registry/storage/cache/cachedblobdescriptorstore.go
generated
vendored
101
vendor/github.com/docker/distribution/registry/storage/cache/cachedblobdescriptorstore.go
generated
vendored
@@ -1,101 +0,0 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"github.com/docker/distribution/context"
|
||||
"github.com/docker/distribution/digest"
|
||||
|
||||
"github.com/docker/distribution"
|
||||
)
|
||||
|
||||
// Metrics is used to hold metric counters
|
||||
// related to the number of times a cache was
|
||||
// hit or missed.
|
||||
type Metrics struct {
|
||||
Requests uint64
|
||||
Hits uint64
|
||||
Misses uint64
|
||||
}
|
||||
|
||||
// MetricsTracker represents a metric tracker
|
||||
// which simply counts the number of hits and misses.
|
||||
type MetricsTracker interface {
|
||||
Hit()
|
||||
Miss()
|
||||
Metrics() Metrics
|
||||
}
|
||||
|
||||
type cachedBlobStatter struct {
|
||||
cache distribution.BlobDescriptorService
|
||||
backend distribution.BlobDescriptorService
|
||||
tracker MetricsTracker
|
||||
}
|
||||
|
||||
// NewCachedBlobStatter creates a new statter which prefers a cache and
|
||||
// falls back to a backend.
|
||||
func NewCachedBlobStatter(cache distribution.BlobDescriptorService, backend distribution.BlobDescriptorService) distribution.BlobDescriptorService {
|
||||
return &cachedBlobStatter{
|
||||
cache: cache,
|
||||
backend: backend,
|
||||
}
|
||||
}
|
||||
|
||||
// NewCachedBlobStatterWithMetrics creates a new statter which prefers a cache and
|
||||
// falls back to a backend. Hits and misses will send to the tracker.
|
||||
func NewCachedBlobStatterWithMetrics(cache distribution.BlobDescriptorService, backend distribution.BlobDescriptorService, tracker MetricsTracker) distribution.BlobStatter {
|
||||
return &cachedBlobStatter{
|
||||
cache: cache,
|
||||
backend: backend,
|
||||
tracker: tracker,
|
||||
}
|
||||
}
|
||||
|
||||
func (cbds *cachedBlobStatter) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
|
||||
desc, err := cbds.cache.Stat(ctx, dgst)
|
||||
if err != nil {
|
||||
if err != distribution.ErrBlobUnknown {
|
||||
context.GetLogger(ctx).Errorf("error retrieving descriptor from cache: %v", err)
|
||||
}
|
||||
|
||||
goto fallback
|
||||
}
|
||||
|
||||
if cbds.tracker != nil {
|
||||
cbds.tracker.Hit()
|
||||
}
|
||||
return desc, nil
|
||||
fallback:
|
||||
if cbds.tracker != nil {
|
||||
cbds.tracker.Miss()
|
||||
}
|
||||
desc, err = cbds.backend.Stat(ctx, dgst)
|
||||
if err != nil {
|
||||
return desc, err
|
||||
}
|
||||
|
||||
if err := cbds.cache.SetDescriptor(ctx, dgst, desc); err != nil {
|
||||
context.GetLogger(ctx).Errorf("error adding descriptor %v to cache: %v", desc.Digest, err)
|
||||
}
|
||||
|
||||
return desc, err
|
||||
|
||||
}
|
||||
|
||||
func (cbds *cachedBlobStatter) Clear(ctx context.Context, dgst digest.Digest) error {
|
||||
err := cbds.cache.Clear(ctx, dgst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = cbds.backend.Clear(ctx, dgst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cbds *cachedBlobStatter) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
|
||||
if err := cbds.cache.SetDescriptor(ctx, dgst, desc); err != nil {
|
||||
context.GetLogger(ctx).Errorf("error adding descriptor %v to cache: %v", desc.Digest, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
179
vendor/github.com/docker/distribution/registry/storage/cache/memory/memory.go
generated
vendored
179
vendor/github.com/docker/distribution/registry/storage/cache/memory/memory.go
generated
vendored
@@ -1,179 +0,0 @@
|
||||
package memory
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/docker/distribution"
|
||||
"github.com/docker/distribution/context"
|
||||
"github.com/docker/distribution/digest"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/distribution/registry/storage/cache"
|
||||
)
|
||||
|
||||
type inMemoryBlobDescriptorCacheProvider struct {
|
||||
global *mapBlobDescriptorCache
|
||||
repositories map[string]*mapBlobDescriptorCache
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
// NewInMemoryBlobDescriptorCacheProvider returns a new mapped-based cache for
|
||||
// storing blob descriptor data.
|
||||
func NewInMemoryBlobDescriptorCacheProvider() cache.BlobDescriptorCacheProvider {
|
||||
return &inMemoryBlobDescriptorCacheProvider{
|
||||
global: newMapBlobDescriptorCache(),
|
||||
repositories: make(map[string]*mapBlobDescriptorCache),
|
||||
}
|
||||
}
|
||||
|
||||
func (imbdcp *inMemoryBlobDescriptorCacheProvider) RepositoryScoped(repo string) (distribution.BlobDescriptorService, error) {
|
||||
if _, err := reference.ParseNamed(repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
imbdcp.mu.RLock()
|
||||
defer imbdcp.mu.RUnlock()
|
||||
|
||||
return &repositoryScopedInMemoryBlobDescriptorCache{
|
||||
repo: repo,
|
||||
parent: imbdcp,
|
||||
repository: imbdcp.repositories[repo],
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (imbdcp *inMemoryBlobDescriptorCacheProvider) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
|
||||
return imbdcp.global.Stat(ctx, dgst)
|
||||
}
|
||||
|
||||
func (imbdcp *inMemoryBlobDescriptorCacheProvider) Clear(ctx context.Context, dgst digest.Digest) error {
|
||||
return imbdcp.global.Clear(ctx, dgst)
|
||||
}
|
||||
|
||||
func (imbdcp *inMemoryBlobDescriptorCacheProvider) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
|
||||
_, err := imbdcp.Stat(ctx, dgst)
|
||||
if err == distribution.ErrBlobUnknown {
|
||||
|
||||
if dgst.Algorithm() != desc.Digest.Algorithm() && dgst != desc.Digest {
|
||||
// if the digests differ, set the other canonical mapping
|
||||
if err := imbdcp.global.SetDescriptor(ctx, desc.Digest, desc); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// unknown, just set it
|
||||
return imbdcp.global.SetDescriptor(ctx, dgst, desc)
|
||||
}
|
||||
|
||||
// we already know it, do nothing
|
||||
return err
|
||||
}
|
||||
|
||||
// repositoryScopedInMemoryBlobDescriptorCache provides the request scoped
|
||||
// repository cache. Instances are not thread-safe but the delegated
|
||||
// operations are.
|
||||
type repositoryScopedInMemoryBlobDescriptorCache struct {
|
||||
repo string
|
||||
parent *inMemoryBlobDescriptorCacheProvider // allows lazy allocation of repo's map
|
||||
repository *mapBlobDescriptorCache
|
||||
}
|
||||
|
||||
func (rsimbdcp *repositoryScopedInMemoryBlobDescriptorCache) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
|
||||
rsimbdcp.parent.mu.Lock()
|
||||
repo := rsimbdcp.repository
|
||||
rsimbdcp.parent.mu.Unlock()
|
||||
|
||||
if repo == nil {
|
||||
return distribution.Descriptor{}, distribution.ErrBlobUnknown
|
||||
}
|
||||
|
||||
return repo.Stat(ctx, dgst)
|
||||
}
|
||||
|
||||
func (rsimbdcp *repositoryScopedInMemoryBlobDescriptorCache) Clear(ctx context.Context, dgst digest.Digest) error {
|
||||
rsimbdcp.parent.mu.Lock()
|
||||
repo := rsimbdcp.repository
|
||||
rsimbdcp.parent.mu.Unlock()
|
||||
|
||||
if repo == nil {
|
||||
return distribution.ErrBlobUnknown
|
||||
}
|
||||
|
||||
return repo.Clear(ctx, dgst)
|
||||
}
|
||||
|
||||
func (rsimbdcp *repositoryScopedInMemoryBlobDescriptorCache) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
|
||||
rsimbdcp.parent.mu.Lock()
|
||||
repo := rsimbdcp.repository
|
||||
if repo == nil {
|
||||
// allocate map since we are setting it now.
|
||||
var ok bool
|
||||
// have to read back value since we may have allocated elsewhere.
|
||||
repo, ok = rsimbdcp.parent.repositories[rsimbdcp.repo]
|
||||
if !ok {
|
||||
repo = newMapBlobDescriptorCache()
|
||||
rsimbdcp.parent.repositories[rsimbdcp.repo] = repo
|
||||
}
|
||||
rsimbdcp.repository = repo
|
||||
}
|
||||
rsimbdcp.parent.mu.Unlock()
|
||||
|
||||
if err := repo.SetDescriptor(ctx, dgst, desc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return rsimbdcp.parent.SetDescriptor(ctx, dgst, desc)
|
||||
}
|
||||
|
||||
// mapBlobDescriptorCache provides a simple map-based implementation of the
|
||||
// descriptor cache.
|
||||
type mapBlobDescriptorCache struct {
|
||||
descriptors map[digest.Digest]distribution.Descriptor
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
var _ distribution.BlobDescriptorService = &mapBlobDescriptorCache{}
|
||||
|
||||
func newMapBlobDescriptorCache() *mapBlobDescriptorCache {
|
||||
return &mapBlobDescriptorCache{
|
||||
descriptors: make(map[digest.Digest]distribution.Descriptor),
|
||||
}
|
||||
}
|
||||
|
||||
func (mbdc *mapBlobDescriptorCache) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
|
||||
if err := dgst.Validate(); err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
}
|
||||
|
||||
mbdc.mu.RLock()
|
||||
defer mbdc.mu.RUnlock()
|
||||
|
||||
desc, ok := mbdc.descriptors[dgst]
|
||||
if !ok {
|
||||
return distribution.Descriptor{}, distribution.ErrBlobUnknown
|
||||
}
|
||||
|
||||
return desc, nil
|
||||
}
|
||||
|
||||
func (mbdc *mapBlobDescriptorCache) Clear(ctx context.Context, dgst digest.Digest) error {
|
||||
mbdc.mu.Lock()
|
||||
defer mbdc.mu.Unlock()
|
||||
|
||||
delete(mbdc.descriptors, dgst)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mbdc *mapBlobDescriptorCache) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
|
||||
if err := dgst.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := cache.ValidateDescriptor(desc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mbdc.mu.Lock()
|
||||
defer mbdc.mu.Unlock()
|
||||
|
||||
mbdc.descriptors[dgst] = desc
|
||||
return nil
|
||||
}
|
||||
191
vendor/github.com/docker/engine-api/LICENSE
generated
vendored
191
vendor/github.com/docker/engine-api/LICENSE
generated
vendored
@@ -1,191 +0,0 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
https://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
|
||||
|
||||
Copyright 2015-2016 Docker, 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
|
||||
|
||||
https://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.
|
||||
27
vendor/github.com/docker/engine-api/client/transport/cancellable/LICENSE
generated
vendored
27
vendor/github.com/docker/engine-api/client/transport/cancellable/LICENSE
generated
vendored
@@ -1,27 +0,0 @@
|
||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
30
vendor/github.com/docker/engine-api/types/strslice/strslice.go
generated
vendored
30
vendor/github.com/docker/engine-api/types/strslice/strslice.go
generated
vendored
@@ -1,30 +0,0 @@
|
||||
package strslice
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
// StrSlice represents a string or an array of strings.
|
||||
// We need to override the json decoder to accept both options.
|
||||
type StrSlice []string
|
||||
|
||||
// UnmarshalJSON decodes the byte slice whether it's a string or an array of
|
||||
// strings. This method is needed to implement json.Unmarshaler.
|
||||
func (e *StrSlice) UnmarshalJSON(b []byte) error {
|
||||
if len(b) == 0 {
|
||||
// With no input, we preserve the existing value by returning nil and
|
||||
// leaving the target alone. This allows defining default values for
|
||||
// the type.
|
||||
return nil
|
||||
}
|
||||
|
||||
p := make([]string, 0, 1)
|
||||
if err := json.Unmarshal(b, &p); err != nil {
|
||||
var s string
|
||||
if err := json.Unmarshal(b, &s); err != nil {
|
||||
return err
|
||||
}
|
||||
p = append(p, s)
|
||||
}
|
||||
|
||||
*e = p
|
||||
return nil
|
||||
}
|
||||
202
vendor/github.com/flynn/go-shlex/COPYING
generated
vendored
202
vendor/github.com/flynn/go-shlex/COPYING
generated
vendored
@@ -1,202 +0,0 @@
|
||||
|
||||
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.
|
||||
457
vendor/github.com/flynn/go-shlex/shlex.go
generated
vendored
457
vendor/github.com/flynn/go-shlex/shlex.go
generated
vendored
@@ -1,457 +0,0 @@
|
||||
/*
|
||||
Copyright 2012 Google Inc. All Rights Reserved.
|
||||
|
||||
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 shlex
|
||||
|
||||
/*
|
||||
Package shlex implements a simple lexer which splits input in to tokens using
|
||||
shell-style rules for quoting and commenting.
|
||||
*/
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
/*
|
||||
A TokenType is a top-level token; a word, space, comment, unknown.
|
||||
*/
|
||||
type TokenType int
|
||||
|
||||
/*
|
||||
A RuneTokenType is the type of a UTF-8 character; a character, quote, space, escape.
|
||||
*/
|
||||
type RuneTokenType int
|
||||
|
||||
type lexerState int
|
||||
|
||||
type Token struct {
|
||||
tokenType TokenType
|
||||
value string
|
||||
}
|
||||
|
||||
/*
|
||||
Two tokens are equal if both their types and values are equal. A nil token can
|
||||
never equal another token.
|
||||
*/
|
||||
func (a *Token) Equal(b *Token) bool {
|
||||
if a == nil || b == nil {
|
||||
return false
|
||||
}
|
||||
if a.tokenType != b.tokenType {
|
||||
return false
|
||||
}
|
||||
return a.value == b.value
|
||||
}
|
||||
|
||||
const (
|
||||
RUNE_CHAR string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._-,/@$*()+=><:;&^%~|!?[]{}"
|
||||
RUNE_SPACE string = " \t\r\n"
|
||||
RUNE_ESCAPING_QUOTE string = "\""
|
||||
RUNE_NONESCAPING_QUOTE string = "'"
|
||||
RUNE_ESCAPE = "\\"
|
||||
RUNE_COMMENT = "#"
|
||||
|
||||
RUNETOKEN_UNKNOWN RuneTokenType = 0
|
||||
RUNETOKEN_CHAR RuneTokenType = 1
|
||||
RUNETOKEN_SPACE RuneTokenType = 2
|
||||
RUNETOKEN_ESCAPING_QUOTE RuneTokenType = 3
|
||||
RUNETOKEN_NONESCAPING_QUOTE RuneTokenType = 4
|
||||
RUNETOKEN_ESCAPE RuneTokenType = 5
|
||||
RUNETOKEN_COMMENT RuneTokenType = 6
|
||||
RUNETOKEN_EOF RuneTokenType = 7
|
||||
|
||||
TOKEN_UNKNOWN TokenType = 0
|
||||
TOKEN_WORD TokenType = 1
|
||||
TOKEN_SPACE TokenType = 2
|
||||
TOKEN_COMMENT TokenType = 3
|
||||
|
||||
STATE_START lexerState = 0
|
||||
STATE_INWORD lexerState = 1
|
||||
STATE_ESCAPING lexerState = 2
|
||||
STATE_ESCAPING_QUOTED lexerState = 3
|
||||
STATE_QUOTED_ESCAPING lexerState = 4
|
||||
STATE_QUOTED lexerState = 5
|
||||
STATE_COMMENT lexerState = 6
|
||||
|
||||
INITIAL_TOKEN_CAPACITY int = 100
|
||||
)
|
||||
|
||||
/*
|
||||
A type for classifying characters. This allows for different sorts of
|
||||
classifiers - those accepting extended non-ascii chars, or strict posix
|
||||
compatibility, for example.
|
||||
*/
|
||||
type TokenClassifier struct {
|
||||
typeMap map[int32]RuneTokenType
|
||||
}
|
||||
|
||||
func addRuneClass(typeMap *map[int32]RuneTokenType, runes string, tokenType RuneTokenType) {
|
||||
for _, rune := range runes {
|
||||
(*typeMap)[int32(rune)] = tokenType
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Create a new classifier for basic ASCII characters.
|
||||
*/
|
||||
func NewDefaultClassifier() *TokenClassifier {
|
||||
typeMap := map[int32]RuneTokenType{}
|
||||
addRuneClass(&typeMap, RUNE_CHAR, RUNETOKEN_CHAR)
|
||||
addRuneClass(&typeMap, RUNE_SPACE, RUNETOKEN_SPACE)
|
||||
addRuneClass(&typeMap, RUNE_ESCAPING_QUOTE, RUNETOKEN_ESCAPING_QUOTE)
|
||||
addRuneClass(&typeMap, RUNE_NONESCAPING_QUOTE, RUNETOKEN_NONESCAPING_QUOTE)
|
||||
addRuneClass(&typeMap, RUNE_ESCAPE, RUNETOKEN_ESCAPE)
|
||||
addRuneClass(&typeMap, RUNE_COMMENT, RUNETOKEN_COMMENT)
|
||||
return &TokenClassifier{
|
||||
typeMap: typeMap}
|
||||
}
|
||||
|
||||
func (classifier *TokenClassifier) ClassifyRune(rune int32) RuneTokenType {
|
||||
return classifier.typeMap[rune]
|
||||
}
|
||||
|
||||
/*
|
||||
A type for turning an input stream in to a sequence of strings. Whitespace and
|
||||
comments are skipped.
|
||||
*/
|
||||
type Lexer struct {
|
||||
tokenizer *Tokenizer
|
||||
}
|
||||
|
||||
/*
|
||||
Create a new lexer.
|
||||
*/
|
||||
func NewLexer(r io.Reader) (*Lexer, error) {
|
||||
|
||||
tokenizer, err := NewTokenizer(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lexer := &Lexer{tokenizer: tokenizer}
|
||||
return lexer, nil
|
||||
}
|
||||
|
||||
/*
|
||||
Return the next word, and an error value. If there are no more words, the error
|
||||
will be io.EOF.
|
||||
*/
|
||||
func (l *Lexer) NextWord() (string, error) {
|
||||
var token *Token
|
||||
var err error
|
||||
for {
|
||||
token, err = l.tokenizer.NextToken()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
switch token.tokenType {
|
||||
case TOKEN_WORD:
|
||||
{
|
||||
return token.value, nil
|
||||
}
|
||||
case TOKEN_COMMENT:
|
||||
{
|
||||
// skip comments
|
||||
}
|
||||
default:
|
||||
{
|
||||
panic(fmt.Sprintf("Unknown token type: %v", token.tokenType))
|
||||
}
|
||||
}
|
||||
}
|
||||
return "", io.EOF
|
||||
}
|
||||
|
||||
/*
|
||||
A type for turning an input stream in to a sequence of typed tokens.
|
||||
*/
|
||||
type Tokenizer struct {
|
||||
input *bufio.Reader
|
||||
classifier *TokenClassifier
|
||||
}
|
||||
|
||||
/*
|
||||
Create a new tokenizer.
|
||||
*/
|
||||
func NewTokenizer(r io.Reader) (*Tokenizer, error) {
|
||||
input := bufio.NewReader(r)
|
||||
classifier := NewDefaultClassifier()
|
||||
tokenizer := &Tokenizer{
|
||||
input: input,
|
||||
classifier: classifier}
|
||||
return tokenizer, nil
|
||||
}
|
||||
|
||||
/*
|
||||
Scan the stream for the next token.
|
||||
|
||||
This uses an internal state machine. It will panic if it encounters a character
|
||||
which it does not know how to handle.
|
||||
*/
|
||||
func (t *Tokenizer) scanStream() (*Token, error) {
|
||||
state := STATE_START
|
||||
var tokenType TokenType
|
||||
value := make([]int32, 0, INITIAL_TOKEN_CAPACITY)
|
||||
var (
|
||||
nextRune int32
|
||||
nextRuneType RuneTokenType
|
||||
err error
|
||||
)
|
||||
SCAN:
|
||||
for {
|
||||
nextRune, _, err = t.input.ReadRune()
|
||||
nextRuneType = t.classifier.ClassifyRune(nextRune)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
nextRuneType = RUNETOKEN_EOF
|
||||
err = nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
switch state {
|
||||
case STATE_START: // no runes read yet
|
||||
{
|
||||
switch nextRuneType {
|
||||
case RUNETOKEN_EOF:
|
||||
{
|
||||
return nil, io.EOF
|
||||
}
|
||||
case RUNETOKEN_CHAR:
|
||||
{
|
||||
tokenType = TOKEN_WORD
|
||||
value = append(value, nextRune)
|
||||
state = STATE_INWORD
|
||||
}
|
||||
case RUNETOKEN_SPACE:
|
||||
{
|
||||
}
|
||||
case RUNETOKEN_ESCAPING_QUOTE:
|
||||
{
|
||||
tokenType = TOKEN_WORD
|
||||
state = STATE_QUOTED_ESCAPING
|
||||
}
|
||||
case RUNETOKEN_NONESCAPING_QUOTE:
|
||||
{
|
||||
tokenType = TOKEN_WORD
|
||||
state = STATE_QUOTED
|
||||
}
|
||||
case RUNETOKEN_ESCAPE:
|
||||
{
|
||||
tokenType = TOKEN_WORD
|
||||
state = STATE_ESCAPING
|
||||
}
|
||||
case RUNETOKEN_COMMENT:
|
||||
{
|
||||
tokenType = TOKEN_COMMENT
|
||||
state = STATE_COMMENT
|
||||
}
|
||||
default:
|
||||
{
|
||||
return nil, errors.New(fmt.Sprintf("Unknown rune: %v", nextRune))
|
||||
}
|
||||
}
|
||||
}
|
||||
case STATE_INWORD: // in a regular word
|
||||
{
|
||||
switch nextRuneType {
|
||||
case RUNETOKEN_EOF:
|
||||
{
|
||||
break SCAN
|
||||
}
|
||||
case RUNETOKEN_CHAR, RUNETOKEN_COMMENT:
|
||||
{
|
||||
value = append(value, nextRune)
|
||||
}
|
||||
case RUNETOKEN_SPACE:
|
||||
{
|
||||
t.input.UnreadRune()
|
||||
break SCAN
|
||||
}
|
||||
case RUNETOKEN_ESCAPING_QUOTE:
|
||||
{
|
||||
state = STATE_QUOTED_ESCAPING
|
||||
}
|
||||
case RUNETOKEN_NONESCAPING_QUOTE:
|
||||
{
|
||||
state = STATE_QUOTED
|
||||
}
|
||||
case RUNETOKEN_ESCAPE:
|
||||
{
|
||||
state = STATE_ESCAPING
|
||||
}
|
||||
default:
|
||||
{
|
||||
return nil, errors.New(fmt.Sprintf("Uknown rune: %v", nextRune))
|
||||
}
|
||||
}
|
||||
}
|
||||
case STATE_ESCAPING: // the next rune after an escape character
|
||||
{
|
||||
switch nextRuneType {
|
||||
case RUNETOKEN_EOF:
|
||||
{
|
||||
err = errors.New("EOF found after escape character")
|
||||
break SCAN
|
||||
}
|
||||
case RUNETOKEN_CHAR, RUNETOKEN_SPACE, RUNETOKEN_ESCAPING_QUOTE, RUNETOKEN_NONESCAPING_QUOTE, RUNETOKEN_ESCAPE, RUNETOKEN_COMMENT:
|
||||
{
|
||||
state = STATE_INWORD
|
||||
value = append(value, nextRune)
|
||||
}
|
||||
default:
|
||||
{
|
||||
return nil, errors.New(fmt.Sprintf("Uknown rune: %v", nextRune))
|
||||
}
|
||||
}
|
||||
}
|
||||
case STATE_ESCAPING_QUOTED: // the next rune after an escape character, in double quotes
|
||||
{
|
||||
switch nextRuneType {
|
||||
case RUNETOKEN_EOF:
|
||||
{
|
||||
err = errors.New("EOF found after escape character")
|
||||
break SCAN
|
||||
}
|
||||
case RUNETOKEN_CHAR, RUNETOKEN_SPACE, RUNETOKEN_ESCAPING_QUOTE, RUNETOKEN_NONESCAPING_QUOTE, RUNETOKEN_ESCAPE, RUNETOKEN_COMMENT:
|
||||
{
|
||||
state = STATE_QUOTED_ESCAPING
|
||||
value = append(value, nextRune)
|
||||
}
|
||||
default:
|
||||
{
|
||||
return nil, errors.New(fmt.Sprintf("Uknown rune: %v", nextRune))
|
||||
}
|
||||
}
|
||||
}
|
||||
case STATE_QUOTED_ESCAPING: // in escaping double quotes
|
||||
{
|
||||
switch nextRuneType {
|
||||
case RUNETOKEN_EOF:
|
||||
{
|
||||
err = errors.New("EOF found when expecting closing quote.")
|
||||
break SCAN
|
||||
}
|
||||
case RUNETOKEN_CHAR, RUNETOKEN_UNKNOWN, RUNETOKEN_SPACE, RUNETOKEN_NONESCAPING_QUOTE, RUNETOKEN_COMMENT:
|
||||
{
|
||||
value = append(value, nextRune)
|
||||
}
|
||||
case RUNETOKEN_ESCAPING_QUOTE:
|
||||
{
|
||||
state = STATE_INWORD
|
||||
}
|
||||
case RUNETOKEN_ESCAPE:
|
||||
{
|
||||
state = STATE_ESCAPING_QUOTED
|
||||
}
|
||||
default:
|
||||
{
|
||||
return nil, errors.New(fmt.Sprintf("Uknown rune: %v", nextRune))
|
||||
}
|
||||
}
|
||||
}
|
||||
case STATE_QUOTED: // in non-escaping single quotes
|
||||
{
|
||||
switch nextRuneType {
|
||||
case RUNETOKEN_EOF:
|
||||
{
|
||||
err = errors.New("EOF found when expecting closing quote.")
|
||||
break SCAN
|
||||
}
|
||||
case RUNETOKEN_CHAR, RUNETOKEN_UNKNOWN, RUNETOKEN_SPACE, RUNETOKEN_ESCAPING_QUOTE, RUNETOKEN_ESCAPE, RUNETOKEN_COMMENT:
|
||||
{
|
||||
value = append(value, nextRune)
|
||||
}
|
||||
case RUNETOKEN_NONESCAPING_QUOTE:
|
||||
{
|
||||
state = STATE_INWORD
|
||||
}
|
||||
default:
|
||||
{
|
||||
return nil, errors.New(fmt.Sprintf("Uknown rune: %v", nextRune))
|
||||
}
|
||||
}
|
||||
}
|
||||
case STATE_COMMENT:
|
||||
{
|
||||
switch nextRuneType {
|
||||
case RUNETOKEN_EOF:
|
||||
{
|
||||
break SCAN
|
||||
}
|
||||
case RUNETOKEN_CHAR, RUNETOKEN_UNKNOWN, RUNETOKEN_ESCAPING_QUOTE, RUNETOKEN_ESCAPE, RUNETOKEN_COMMENT, RUNETOKEN_NONESCAPING_QUOTE:
|
||||
{
|
||||
value = append(value, nextRune)
|
||||
}
|
||||
case RUNETOKEN_SPACE:
|
||||
{
|
||||
if nextRune == '\n' {
|
||||
state = STATE_START
|
||||
break SCAN
|
||||
} else {
|
||||
value = append(value, nextRune)
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
return nil, errors.New(fmt.Sprintf("Uknown rune: %v", nextRune))
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
panic(fmt.Sprintf("Unexpected state: %v", state))
|
||||
}
|
||||
}
|
||||
}
|
||||
token := &Token{
|
||||
tokenType: tokenType,
|
||||
value: string(value)}
|
||||
return token, err
|
||||
}
|
||||
|
||||
/*
|
||||
Return the next token in the stream, and an error value. If there are no more
|
||||
tokens available, the error value will be io.EOF.
|
||||
*/
|
||||
func (t *Tokenizer) NextToken() (*Token, error) {
|
||||
return t.scanStream()
|
||||
}
|
||||
|
||||
/*
|
||||
Split a string in to a slice of strings, based upon shell-style rules for
|
||||
quoting, escaping, and spaces.
|
||||
*/
|
||||
func Split(s string) ([]string, error) {
|
||||
l, err := NewLexer(strings.NewReader(s))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
subStrings := []string{}
|
||||
for {
|
||||
word, err := l.NextWord()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return subStrings, nil
|
||||
}
|
||||
return subStrings, err
|
||||
}
|
||||
subStrings = append(subStrings, word)
|
||||
}
|
||||
return subStrings, nil
|
||||
}
|
||||
191
vendor/github.com/hyperhq/hyper-api/LICENSE
generated
vendored
191
vendor/github.com/hyperhq/hyper-api/LICENSE
generated
vendored
@@ -1,191 +0,0 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
https://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
|
||||
|
||||
Copyright 2015-2016 Docker, 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
|
||||
|
||||
https://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.
|
||||
14
vendor/github.com/hyperhq/hyper-api/client/checkpoint_create.go
generated
vendored
14
vendor/github.com/hyperhq/hyper-api/client/checkpoint_create.go
generated
vendored
@@ -1,14 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
)
|
||||
|
||||
// CheckpointCreate creates a checkpoint from the given container with the given name
|
||||
func (cli *Client) CheckpointCreate(ctx context.Context, container string, options types.CheckpointCreateOptions) error {
|
||||
resp, err := cli.post(ctx, "/containers/"+container+"/checkpoints", nil, options, nil)
|
||||
ensureReaderClosed(resp)
|
||||
return err
|
||||
}
|
||||
10
vendor/github.com/hyperhq/hyper-api/client/checkpoint_delete.go
generated
vendored
10
vendor/github.com/hyperhq/hyper-api/client/checkpoint_delete.go
generated
vendored
@@ -1,10 +0,0 @@
|
||||
package client
|
||||
|
||||
import "context"
|
||||
|
||||
// CheckpointDelete deletes the checkpoint with the given name from the given container
|
||||
func (cli *Client) CheckpointDelete(ctx context.Context, containerID string, checkpointID string) error {
|
||||
resp, err := cli.delete(ctx, "/containers/"+containerID+"/checkpoints/"+checkpointID, nil, nil)
|
||||
ensureReaderClosed(resp)
|
||||
return err
|
||||
}
|
||||
22
vendor/github.com/hyperhq/hyper-api/client/checkpoint_list.go
generated
vendored
22
vendor/github.com/hyperhq/hyper-api/client/checkpoint_list.go
generated
vendored
@@ -1,22 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"context"
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
)
|
||||
|
||||
// CheckpointList returns the volumes configured in the docker host.
|
||||
func (cli *Client) CheckpointList(ctx context.Context, container string) ([]types.Checkpoint, error) {
|
||||
var checkpoints []types.Checkpoint
|
||||
|
||||
resp, err := cli.get(ctx, "/containers/"+container+"/checkpoints", nil, nil)
|
||||
if err != nil {
|
||||
return checkpoints, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(resp.body).Decode(&checkpoints)
|
||||
ensureReaderClosed(resp)
|
||||
return checkpoints, err
|
||||
}
|
||||
153
vendor/github.com/hyperhq/hyper-api/client/client.go
generated
vendored
153
vendor/github.com/hyperhq/hyper-api/client/client.go
generated
vendored
@@ -1,153 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/go-connections/tlsconfig"
|
||||
"github.com/hyperhq/hyper-api/client/transport"
|
||||
)
|
||||
|
||||
// Client is the API client that performs all operations
|
||||
// against a docker server.
|
||||
type Client struct {
|
||||
// proto holds the client protocol i.e. unix.
|
||||
proto string
|
||||
// addr holds the client address.
|
||||
addr string
|
||||
// basePath holds the path to prepend to the requests.
|
||||
basePath string
|
||||
// transport is the interface to send request with, it implements transport.Client.
|
||||
transport transport.Client
|
||||
// Cloud's Config
|
||||
accessKey string
|
||||
secretKey string
|
||||
// version of the server to talk to.
|
||||
version string
|
||||
// custom http headers configured by users.
|
||||
customHTTPHeaders map[string]string
|
||||
|
||||
// region
|
||||
region string
|
||||
}
|
||||
|
||||
// NewEnvClient initializes a new API client based on environment variables.
|
||||
// Use DOCKER_HOST to set the url to the docker server.
|
||||
// Use DOCKER_API_VERSION to set the version of the API to reach, leave empty for latest.
|
||||
// Use DOCKER_CERT_PATH to load the tls certificates from.
|
||||
// Use DOCKER_TLS_VERIFY to enable or disable TLS verification, off by default.
|
||||
func NewEnvClient() (*Client, error) {
|
||||
var client *http.Client
|
||||
if dockerCertPath := os.Getenv("DOCKER_CERT_PATH"); dockerCertPath != "" {
|
||||
options := tlsconfig.Options{
|
||||
CAFile: filepath.Join(dockerCertPath, "ca.pem"),
|
||||
CertFile: filepath.Join(dockerCertPath, "cert.pem"),
|
||||
KeyFile: filepath.Join(dockerCertPath, "key.pem"),
|
||||
InsecureSkipVerify: os.Getenv("DOCKER_TLS_VERIFY") == "",
|
||||
}
|
||||
tlsc, err := tlsconfig.Client(options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client = &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: tlsc,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
host := os.Getenv("DOCKER_HOST")
|
||||
if host == "" {
|
||||
host = DefaultDockerHost
|
||||
}
|
||||
accessKey := os.Getenv("ACCESSKEY")
|
||||
secretKey := os.Getenv("SECRETKEY")
|
||||
region := os.Getenv("HYPER_REGION")
|
||||
return NewClient(host, os.Getenv("DOCKER_API_VERSION"), client, nil, accessKey, secretKey, region)
|
||||
}
|
||||
|
||||
// NewClient initializes a new API client for the given host and API version.
|
||||
// It won't send any version information if the version number is empty.
|
||||
// It uses the given http client as transport.
|
||||
// It also initializes the custom http headers to add to each request.
|
||||
func NewClient(host string, version string, client *http.Client, httpHeaders map[string]string, ak, sk, region string) (*Client, error) {
|
||||
proto, addr, basePath, err := ParseHost(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
transport, err := transport.NewTransportWithHTTP(proto, addr, client)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Client{
|
||||
proto: proto,
|
||||
addr: addr,
|
||||
basePath: basePath,
|
||||
transport: transport,
|
||||
accessKey: ak,
|
||||
secretKey: sk,
|
||||
version: version,
|
||||
customHTTPHeaders: httpHeaders,
|
||||
region: region,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// getAPIPath returns the versioned request path to call the api.
|
||||
// It appends the query parameters to the path if they are not empty.
|
||||
func (cli *Client) getAPIPath(p string, query url.Values) string {
|
||||
var apiPath string
|
||||
if cli.version != "" {
|
||||
v := strings.TrimPrefix(cli.version, "v")
|
||||
apiPath = fmt.Sprintf("%s/v%s%s", cli.basePath, v, p)
|
||||
} else {
|
||||
apiPath = fmt.Sprintf("%s%s", cli.basePath, p)
|
||||
}
|
||||
|
||||
u := &url.URL{
|
||||
Path: apiPath,
|
||||
}
|
||||
if len(query) > 0 {
|
||||
u.RawQuery = query.Encode()
|
||||
}
|
||||
return u.String()
|
||||
}
|
||||
|
||||
// ClientVersion returns the version string associated with this
|
||||
// instance of the Client. Note that this value can be changed
|
||||
// via the DOCKER_API_VERSION env var.
|
||||
func (cli *Client) ClientVersion() string {
|
||||
return cli.version
|
||||
}
|
||||
|
||||
// UpdateClientVersion updates the version string associated with this
|
||||
// instance of the Client.
|
||||
func (cli *Client) UpdateClientVersion(v string) {
|
||||
cli.version = v
|
||||
}
|
||||
|
||||
// ParseHost verifies that the given host strings is valid.
|
||||
func ParseHost(host string) (string, string, string, error) {
|
||||
protoAddrParts := strings.SplitN(host, "://", 2)
|
||||
if len(protoAddrParts) == 1 {
|
||||
return "", "", "", fmt.Errorf("unable to parse docker host `%s`", host)
|
||||
}
|
||||
|
||||
var basePath string
|
||||
proto, addr := protoAddrParts[0], protoAddrParts[1]
|
||||
if proto == "tcp" {
|
||||
parsed, err := url.Parse("tcp://" + addr)
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
addr = parsed.Host
|
||||
basePath = parsed.Path
|
||||
}
|
||||
return proto, addr, basePath, nil
|
||||
}
|
||||
4
vendor/github.com/hyperhq/hyper-api/client/client_darwin.go
generated
vendored
4
vendor/github.com/hyperhq/hyper-api/client/client_darwin.go
generated
vendored
@@ -1,4 +0,0 @@
|
||||
package client
|
||||
|
||||
// DefaultDockerHost defines os specific default if DOCKER_HOST is unset
|
||||
const DefaultDockerHost = "tcp://127.0.0.1:2375"
|
||||
6
vendor/github.com/hyperhq/hyper-api/client/client_unix.go
generated
vendored
6
vendor/github.com/hyperhq/hyper-api/client/client_unix.go
generated
vendored
@@ -1,6 +0,0 @@
|
||||
// +build linux freebsd solaris openbsd
|
||||
|
||||
package client
|
||||
|
||||
// DefaultDockerHost defines os specific default if DOCKER_HOST is unset
|
||||
const DefaultDockerHost = "unix:///var/run/docker.sock"
|
||||
4
vendor/github.com/hyperhq/hyper-api/client/client_windows.go
generated
vendored
4
vendor/github.com/hyperhq/hyper-api/client/client_windows.go
generated
vendored
@@ -1,4 +0,0 @@
|
||||
package client
|
||||
|
||||
// DefaultDockerHost defines os specific default if DOCKER_HOST is unset
|
||||
const DefaultDockerHost = "npipe:////./pipe/docker_engine"
|
||||
149
vendor/github.com/hyperhq/hyper-api/client/compose.go
generated
vendored
149
vendor/github.com/hyperhq/hyper-api/client/compose.go
generated
vendored
@@ -1,149 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
"github.com/hyperhq/libcompose/config"
|
||||
)
|
||||
|
||||
type composeConfigWrapper struct {
|
||||
ServiceConfigs *config.ServiceConfigs `json:"ServiceConfigs"`
|
||||
VolumeConfigs map[string]*config.VolumeConfig `json:"VolumeConfigs"`
|
||||
NetworkConfigs map[string]*config.NetworkConfig `json:"NetworkConfigs"`
|
||||
AuthConfigs map[string]types.AuthConfig `json:"auths"`
|
||||
}
|
||||
|
||||
func (cli *Client) ComposeUp(project string, services []string, c *config.ServiceConfigs, vc map[string]*config.VolumeConfig, nc map[string]*config.NetworkConfig, auth map[string]types.AuthConfig, forcerecreate, norecreate bool) (io.ReadCloser, error) {
|
||||
query := url.Values{}
|
||||
query.Set("project", project)
|
||||
if forcerecreate {
|
||||
query.Set("forcerecreate", "true")
|
||||
}
|
||||
if norecreate {
|
||||
query.Set("norecreate", "true")
|
||||
}
|
||||
if len(services) > 0 {
|
||||
query.Set("services", strings.Join(services, "}{"))
|
||||
}
|
||||
body := composeConfigWrapper{
|
||||
ServiceConfigs: c,
|
||||
VolumeConfigs: vc,
|
||||
NetworkConfigs: nc,
|
||||
AuthConfigs: auth,
|
||||
}
|
||||
resp, err := cli.post(context.Background(), "/compose/up", query, body, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.body, nil
|
||||
}
|
||||
|
||||
func (cli *Client) ComposeDown(project string, services []string, rmi string, vol, rmorphans bool) (io.ReadCloser, error) {
|
||||
|
||||
query := url.Values{}
|
||||
query.Set("project", project)
|
||||
if rmi != "" {
|
||||
query.Set("rmi", rmi)
|
||||
}
|
||||
if vol {
|
||||
query.Set("rmvol", "true")
|
||||
}
|
||||
if rmorphans {
|
||||
query.Set("rmorphans", "true")
|
||||
}
|
||||
if len(services) > 0 {
|
||||
query.Set("services", strings.Join(services, "}{"))
|
||||
}
|
||||
resp, err := cli.post(context.Background(), "/compose/down", query, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.body, nil
|
||||
}
|
||||
|
||||
func (cli *Client) ComposeCreate(project string, services []string, c *config.ServiceConfigs, vc map[string]*config.VolumeConfig, nc map[string]*config.NetworkConfig, auth map[string]types.AuthConfig, forcerecreate, norecreate bool) (io.ReadCloser, error) {
|
||||
query := url.Values{}
|
||||
query.Set("project", project)
|
||||
if forcerecreate {
|
||||
query.Set("forcerecreate", "true")
|
||||
}
|
||||
if norecreate {
|
||||
query.Set("norecreate", "true")
|
||||
}
|
||||
if len(services) > 0 {
|
||||
query.Set("services", strings.Join(services, "}{"))
|
||||
}
|
||||
body := composeConfigWrapper{
|
||||
ServiceConfigs: c,
|
||||
VolumeConfigs: vc,
|
||||
NetworkConfigs: nc,
|
||||
AuthConfigs: auth,
|
||||
}
|
||||
resp, err := cli.post(context.Background(), "/compose/create", query, body, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.body, nil
|
||||
}
|
||||
|
||||
func (cli *Client) ComposeRm(project string, services []string, rmVol bool) (io.ReadCloser, error) {
|
||||
query := url.Values{}
|
||||
query.Set("project", project)
|
||||
if rmVol {
|
||||
query.Set("rmvol", "true")
|
||||
}
|
||||
if len(services) > 0 {
|
||||
query.Set("services", strings.Join(services, "}{"))
|
||||
}
|
||||
resp, err := cli.post(context.Background(), "/compose/rm", query, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.body, nil
|
||||
}
|
||||
|
||||
func (cli *Client) ComposeStart(project string, services []string) (io.ReadCloser, error) {
|
||||
query := url.Values{}
|
||||
query.Set("project", project)
|
||||
if len(services) > 0 {
|
||||
query.Set("services", strings.Join(services, "}{"))
|
||||
}
|
||||
resp, err := cli.post(context.Background(), "/compose/start", query, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.body, nil
|
||||
}
|
||||
|
||||
func (cli *Client) ComposeStop(project string, services []string, timeout int) (io.ReadCloser, error) {
|
||||
query := url.Values{}
|
||||
query.Set("project", project)
|
||||
query.Set("seconds", fmt.Sprintf("%d", timeout))
|
||||
if len(services) > 0 {
|
||||
query.Set("services", strings.Join(services, "}{"))
|
||||
}
|
||||
resp, err := cli.post(context.Background(), "/compose/stop", query, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.body, nil
|
||||
}
|
||||
|
||||
func (cli *Client) ComposeKill(project string, services []string, signal string) (io.ReadCloser, error) {
|
||||
query := url.Values{}
|
||||
query.Set("project", project)
|
||||
query.Set("signal", signal)
|
||||
if len(services) > 0 {
|
||||
query.Set("services", strings.Join(services, "}{"))
|
||||
}
|
||||
resp, err := cli.post(context.Background(), "/compose/kill", query, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.body, nil
|
||||
}
|
||||
34
vendor/github.com/hyperhq/hyper-api/client/container_attach.go
generated
vendored
34
vendor/github.com/hyperhq/hyper-api/client/container_attach.go
generated
vendored
@@ -1,34 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
)
|
||||
|
||||
// ContainerAttach attaches a connection to a container in the server.
|
||||
// It returns a types.HijackedConnection with the hijacked connection
|
||||
// and the a reader to get output. It's up to the called to close
|
||||
// the hijacked connection by calling types.HijackedResponse.Close.
|
||||
func (cli *Client) ContainerAttach(ctx context.Context, container string, options types.ContainerAttachOptions) (types.HijackedResponse, error) {
|
||||
query := url.Values{}
|
||||
if options.Stream {
|
||||
query.Set("stream", "1")
|
||||
}
|
||||
if options.Stdin {
|
||||
query.Set("stdin", "1")
|
||||
}
|
||||
if options.Stdout {
|
||||
query.Set("stdout", "1")
|
||||
}
|
||||
if options.Stderr {
|
||||
query.Set("stderr", "1")
|
||||
}
|
||||
if options.DetachKeys != "" {
|
||||
query.Set("detachKeys", options.DetachKeys)
|
||||
}
|
||||
|
||||
headers := map[string][]string{"Content-Type": {"text/plain"}}
|
||||
return cli.postHijacked(ctx, "/containers/"+container+"/attach", query, nil, headers)
|
||||
}
|
||||
53
vendor/github.com/hyperhq/hyper-api/client/container_commit.go
generated
vendored
53
vendor/github.com/hyperhq/hyper-api/client/container_commit.go
generated
vendored
@@ -1,53 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/url"
|
||||
|
||||
distreference "github.com/docker/distribution/reference"
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
"github.com/hyperhq/hyper-api/types/reference"
|
||||
)
|
||||
|
||||
// ContainerCommit applies changes into a container and creates a new tagged image.
|
||||
func (cli *Client) ContainerCommit(ctx context.Context, container string, options types.ContainerCommitOptions) (types.ContainerCommitResponse, error) {
|
||||
var repository, tag string
|
||||
if options.Reference != "" {
|
||||
distributionRef, err := distreference.ParseNamed(options.Reference)
|
||||
if err != nil {
|
||||
return types.ContainerCommitResponse{}, err
|
||||
}
|
||||
|
||||
if _, isCanonical := distributionRef.(distreference.Canonical); isCanonical {
|
||||
return types.ContainerCommitResponse{}, errors.New("refusing to create a tag with a digest reference")
|
||||
}
|
||||
|
||||
tag = reference.GetTagFromNamedRef(distributionRef)
|
||||
repository = distributionRef.Name()
|
||||
}
|
||||
|
||||
query := url.Values{}
|
||||
query.Set("container", container)
|
||||
query.Set("repo", repository)
|
||||
query.Set("tag", tag)
|
||||
query.Set("comment", options.Comment)
|
||||
query.Set("author", options.Author)
|
||||
for _, change := range options.Changes {
|
||||
query.Add("changes", change)
|
||||
}
|
||||
if options.Pause != true {
|
||||
query.Set("pause", "0")
|
||||
}
|
||||
|
||||
var response types.ContainerCommitResponse
|
||||
resp, err := cli.post(ctx, "/commit", query, options.Config, nil)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(resp.body).Decode(&response)
|
||||
ensureReaderClosed(resp)
|
||||
return response, err
|
||||
}
|
||||
96
vendor/github.com/hyperhq/hyper-api/client/container_copy.go
generated
vendored
96
vendor/github.com/hyperhq/hyper-api/client/container_copy.go
generated
vendored
@@ -1,96 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
)
|
||||
|
||||
// ContainerStatPath returns Stat information about a path inside the container filesystem.
|
||||
func (cli *Client) ContainerStatPath(ctx context.Context, containerID, path string) (types.ContainerPathStat, error) {
|
||||
query := url.Values{}
|
||||
query.Set("path", filepath.ToSlash(path)) // Normalize the paths used in the API.
|
||||
|
||||
urlStr := fmt.Sprintf("/containers/%s/archive", containerID)
|
||||
response, err := cli.head(ctx, urlStr, query, nil)
|
||||
if err != nil {
|
||||
return types.ContainerPathStat{}, err
|
||||
}
|
||||
defer ensureReaderClosed(response)
|
||||
return getContainerPathStatFromHeader(response.header)
|
||||
}
|
||||
|
||||
// CopyToContainer copies content into the container filesystem.
|
||||
func (cli *Client) CopyToContainer(ctx context.Context, container, path string, content io.Reader, options types.CopyToContainerOptions) error {
|
||||
query := url.Values{}
|
||||
query.Set("path", filepath.ToSlash(path)) // Normalize the paths used in the API.
|
||||
// Do not allow for an existing directory to be overwritten by a non-directory and vice versa.
|
||||
if !options.AllowOverwriteDirWithFile {
|
||||
query.Set("noOverwriteDirNonDir", "true")
|
||||
}
|
||||
|
||||
apiPath := fmt.Sprintf("/containers/%s/archive", container)
|
||||
|
||||
response, err := cli.putRaw(ctx, apiPath, query, content, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer ensureReaderClosed(response)
|
||||
|
||||
if response.statusCode != http.StatusOK {
|
||||
return fmt.Errorf("unexpected status code from daemon: %d", response.statusCode)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CopyFromContainer gets the content from the container and returns it as a Reader
|
||||
// to manipulate it in the host. It's up to the caller to close the reader.
|
||||
func (cli *Client) CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) {
|
||||
query := make(url.Values, 1)
|
||||
query.Set("path", filepath.ToSlash(srcPath)) // Normalize the paths used in the API.
|
||||
|
||||
apiPath := fmt.Sprintf("/containers/%s/archive", container)
|
||||
response, err := cli.get(ctx, apiPath, query, nil)
|
||||
if err != nil {
|
||||
return nil, types.ContainerPathStat{}, err
|
||||
}
|
||||
|
||||
if response.statusCode != http.StatusOK {
|
||||
return nil, types.ContainerPathStat{}, fmt.Errorf("unexpected status code from daemon: %d", response.statusCode)
|
||||
}
|
||||
|
||||
// In order to get the copy behavior right, we need to know information
|
||||
// about both the source and the destination. The response headers include
|
||||
// stat info about the source that we can use in deciding exactly how to
|
||||
// copy it locally. Along with the stat info about the local destination,
|
||||
// we have everything we need to handle the multiple possibilities there
|
||||
// can be when copying a file/dir from one location to another file/dir.
|
||||
stat, err := getContainerPathStatFromHeader(response.header)
|
||||
if err != nil {
|
||||
return nil, stat, fmt.Errorf("unable to get resource stat from response: %s", err)
|
||||
}
|
||||
return response.body, stat, err
|
||||
}
|
||||
|
||||
func getContainerPathStatFromHeader(header http.Header) (types.ContainerPathStat, error) {
|
||||
var stat types.ContainerPathStat
|
||||
|
||||
encodedStat := header.Get("X-Docker-Container-Path-Stat")
|
||||
statDecoder := base64.NewDecoder(base64.StdEncoding, strings.NewReader(encodedStat))
|
||||
|
||||
err := json.NewDecoder(statDecoder).Decode(&stat)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("unable to decode container path stat header: %s", err)
|
||||
}
|
||||
|
||||
return stat, err
|
||||
}
|
||||
46
vendor/github.com/hyperhq/hyper-api/client/container_create.go
generated
vendored
46
vendor/github.com/hyperhq/hyper-api/client/container_create.go
generated
vendored
@@ -1,46 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"context"
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
"github.com/hyperhq/hyper-api/types/container"
|
||||
"github.com/hyperhq/hyper-api/types/network"
|
||||
)
|
||||
|
||||
type configWrapper struct {
|
||||
*container.Config
|
||||
HostConfig *container.HostConfig
|
||||
NetworkingConfig *network.NetworkingConfig
|
||||
}
|
||||
|
||||
// ContainerCreate creates a new container based in the given configuration.
|
||||
// It can be associated with a name, but it's not mandatory.
|
||||
func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (types.ContainerCreateResponse, error) {
|
||||
var response types.ContainerCreateResponse
|
||||
query := url.Values{}
|
||||
if containerName != "" {
|
||||
query.Set("name", containerName)
|
||||
}
|
||||
|
||||
body := configWrapper{
|
||||
Config: config,
|
||||
HostConfig: hostConfig,
|
||||
NetworkingConfig: networkingConfig,
|
||||
}
|
||||
|
||||
serverResp, err := cli.post(ctx, "/containers/create", query, body, nil)
|
||||
if err != nil {
|
||||
if serverResp != nil && serverResp.statusCode == 404 && strings.Contains(err.Error(), "No such image") {
|
||||
return response, imageNotFoundError{config.Image}
|
||||
}
|
||||
return response, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(serverResp.body).Decode(&response)
|
||||
ensureReaderClosed(serverResp)
|
||||
return response, err
|
||||
}
|
||||
23
vendor/github.com/hyperhq/hyper-api/client/container_diff.go
generated
vendored
23
vendor/github.com/hyperhq/hyper-api/client/container_diff.go
generated
vendored
@@ -1,23 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/url"
|
||||
|
||||
"context"
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
)
|
||||
|
||||
// ContainerDiff shows differences in a container filesystem since it was started.
|
||||
func (cli *Client) ContainerDiff(ctx context.Context, containerID string) ([]types.ContainerChange, error) {
|
||||
var changes []types.ContainerChange
|
||||
|
||||
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/changes", url.Values{}, nil)
|
||||
if err != nil {
|
||||
return changes, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(serverResp.body).Decode(&changes)
|
||||
ensureReaderClosed(serverResp)
|
||||
return changes, err
|
||||
}
|
||||
49
vendor/github.com/hyperhq/hyper-api/client/container_exec.go
generated
vendored
49
vendor/github.com/hyperhq/hyper-api/client/container_exec.go
generated
vendored
@@ -1,49 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"context"
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
)
|
||||
|
||||
// ContainerExecCreate creates a new exec configuration to run an exec process.
|
||||
func (cli *Client) ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (types.ContainerExecCreateResponse, error) {
|
||||
var response types.ContainerExecCreateResponse
|
||||
resp, err := cli.post(ctx, "/containers/"+container+"/exec", nil, config, nil)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
err = json.NewDecoder(resp.body).Decode(&response)
|
||||
ensureReaderClosed(resp)
|
||||
return response, err
|
||||
}
|
||||
|
||||
// ContainerExecStart starts an exec process already created in the docker host.
|
||||
func (cli *Client) ContainerExecStart(ctx context.Context, execID string, config types.ExecStartCheck) error {
|
||||
resp, err := cli.post(ctx, "/exec/"+execID+"/start", nil, config, nil)
|
||||
ensureReaderClosed(resp)
|
||||
return err
|
||||
}
|
||||
|
||||
// ContainerExecAttach attaches a connection to an exec process in the server.
|
||||
// It returns a types.HijackedConnection with the hijacked connection
|
||||
// and the a reader to get output. It's up to the called to close
|
||||
// the hijacked connection by calling types.HijackedResponse.Close.
|
||||
func (cli *Client) ContainerExecAttach(ctx context.Context, execID string, config types.ExecConfig) (types.HijackedResponse, error) {
|
||||
headers := map[string][]string{"Content-Type": {"application/json"}}
|
||||
return cli.postHijacked(ctx, "/exec/"+execID+"/start", nil, config, headers)
|
||||
}
|
||||
|
||||
// ContainerExecInspect returns information about a specific exec process on the docker host.
|
||||
func (cli *Client) ContainerExecInspect(ctx context.Context, execID string) (types.ContainerExecInspect, error) {
|
||||
var response types.ContainerExecInspect
|
||||
resp, err := cli.get(ctx, "/exec/"+execID+"/json", nil, nil)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(resp.body).Decode(&response)
|
||||
ensureReaderClosed(resp)
|
||||
return response, err
|
||||
}
|
||||
20
vendor/github.com/hyperhq/hyper-api/client/container_export.go
generated
vendored
20
vendor/github.com/hyperhq/hyper-api/client/container_export.go
generated
vendored
@@ -1,20 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/url"
|
||||
|
||||
"context"
|
||||
)
|
||||
|
||||
// ContainerExport retrieves the raw contents of a container
|
||||
// and returns them as an io.ReadCloser. It's up to the caller
|
||||
// to close the stream.
|
||||
func (cli *Client) ContainerExport(ctx context.Context, containerID string) (io.ReadCloser, error) {
|
||||
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/export", url.Values{}, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return serverResp.body, nil
|
||||
}
|
||||
54
vendor/github.com/hyperhq/hyper-api/client/container_inspect.go
generated
vendored
54
vendor/github.com/hyperhq/hyper-api/client/container_inspect.go
generated
vendored
@@ -1,54 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"context"
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
)
|
||||
|
||||
// ContainerInspect returns the container information.
|
||||
func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (types.ContainerJSON, error) {
|
||||
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", nil, nil)
|
||||
if err != nil {
|
||||
if serverResp.statusCode == http.StatusNotFound {
|
||||
return types.ContainerJSON{}, containerNotFoundError{containerID}
|
||||
}
|
||||
return types.ContainerJSON{}, err
|
||||
}
|
||||
|
||||
var response types.ContainerJSON
|
||||
err = json.NewDecoder(serverResp.body).Decode(&response)
|
||||
ensureReaderClosed(serverResp)
|
||||
return response, err
|
||||
}
|
||||
|
||||
// ContainerInspectWithRaw returns the container information and it's raw representation.
|
||||
func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID string, getSize bool) (types.ContainerJSON, []byte, error) {
|
||||
query := url.Values{}
|
||||
if getSize {
|
||||
query.Set("size", "1")
|
||||
}
|
||||
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", query, nil)
|
||||
if err != nil {
|
||||
if serverResp.statusCode == http.StatusNotFound {
|
||||
return types.ContainerJSON{}, nil, containerNotFoundError{containerID}
|
||||
}
|
||||
return types.ContainerJSON{}, nil, err
|
||||
}
|
||||
defer ensureReaderClosed(serverResp)
|
||||
|
||||
body, err := ioutil.ReadAll(serverResp.body)
|
||||
if err != nil {
|
||||
return types.ContainerJSON{}, nil, err
|
||||
}
|
||||
|
||||
var response types.ContainerJSON
|
||||
rdr := bytes.NewReader(body)
|
||||
err = json.NewDecoder(rdr).Decode(&response)
|
||||
return response, body, err
|
||||
}
|
||||
16
vendor/github.com/hyperhq/hyper-api/client/container_kill.go
generated
vendored
16
vendor/github.com/hyperhq/hyper-api/client/container_kill.go
generated
vendored
@@ -1,16 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// ContainerKill terminates the container process but does not remove the container from the docker host.
|
||||
func (cli *Client) ContainerKill(ctx context.Context, containerID, signal string) error {
|
||||
query := url.Values{}
|
||||
query.Set("signal", signal)
|
||||
|
||||
resp, err := cli.post(ctx, "/containers/"+containerID+"/kill", query, nil, nil)
|
||||
ensureReaderClosed(resp)
|
||||
return err
|
||||
}
|
||||
56
vendor/github.com/hyperhq/hyper-api/client/container_list.go
generated
vendored
56
vendor/github.com/hyperhq/hyper-api/client/container_list.go
generated
vendored
@@ -1,56 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"context"
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
"github.com/hyperhq/hyper-api/types/filters"
|
||||
)
|
||||
|
||||
// ContainerList returns the list of containers in the docker host.
|
||||
func (cli *Client) ContainerList(ctx context.Context, options types.ContainerListOptions) ([]types.Container, error) {
|
||||
query := url.Values{}
|
||||
|
||||
if options.All {
|
||||
query.Set("all", "1")
|
||||
}
|
||||
|
||||
if options.Limit != -1 {
|
||||
query.Set("limit", strconv.Itoa(options.Limit))
|
||||
}
|
||||
|
||||
if options.Since != "" {
|
||||
query.Set("since", options.Since)
|
||||
}
|
||||
|
||||
if options.Before != "" {
|
||||
query.Set("before", options.Before)
|
||||
}
|
||||
|
||||
if options.Size {
|
||||
query.Set("size", "1")
|
||||
}
|
||||
|
||||
if options.Filter.Len() > 0 {
|
||||
filterJSON, err := filters.ToParamWithVersion(cli.version, options.Filter)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query.Set("filters", filterJSON)
|
||||
}
|
||||
|
||||
resp, err := cli.get(ctx, "/containers/json", query, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var containers []types.Container
|
||||
err = json.NewDecoder(resp.body).Decode(&containers)
|
||||
ensureReaderClosed(resp)
|
||||
return containers, err
|
||||
}
|
||||
51
vendor/github.com/hyperhq/hyper-api/client/container_logs.go
generated
vendored
51
vendor/github.com/hyperhq/hyper-api/client/container_logs.go
generated
vendored
@@ -1,51 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
timetypes "github.com/hyperhq/hyper-api/types/time"
|
||||
)
|
||||
|
||||
// ContainerLogs returns the logs generated by a container in an io.ReadCloser.
|
||||
// It's up to the caller to close the stream.
|
||||
func (cli *Client) ContainerLogs(ctx context.Context, container string, options types.ContainerLogsOptions) (io.ReadCloser, error) {
|
||||
query := url.Values{}
|
||||
if options.ShowStdout {
|
||||
query.Set("stdout", "1")
|
||||
}
|
||||
|
||||
if options.ShowStderr {
|
||||
query.Set("stderr", "1")
|
||||
}
|
||||
|
||||
if options.Since != "" {
|
||||
ts, err := timetypes.GetTimestamp(options.Since, time.Now())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query.Set("since", ts)
|
||||
}
|
||||
|
||||
if options.Timestamps {
|
||||
query.Set("timestamps", "1")
|
||||
}
|
||||
|
||||
if options.Details {
|
||||
query.Set("details", "1")
|
||||
}
|
||||
|
||||
if options.Follow {
|
||||
query.Set("follow", "1")
|
||||
}
|
||||
query.Set("tail", options.Tail)
|
||||
|
||||
resp, err := cli.get(ctx, "/containers/"+container+"/logs", query, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.body, nil
|
||||
}
|
||||
10
vendor/github.com/hyperhq/hyper-api/client/container_pause.go
generated
vendored
10
vendor/github.com/hyperhq/hyper-api/client/container_pause.go
generated
vendored
@@ -1,10 +0,0 @@
|
||||
package client
|
||||
|
||||
import "context"
|
||||
|
||||
// ContainerPause pauses the main process of a given container without terminating it.
|
||||
func (cli *Client) ContainerPause(ctx context.Context, containerID string) error {
|
||||
resp, err := cli.post(ctx, "/containers/"+containerID+"/pause", nil, nil, nil)
|
||||
ensureReaderClosed(resp)
|
||||
return err
|
||||
}
|
||||
32
vendor/github.com/hyperhq/hyper-api/client/container_remove.go
generated
vendored
32
vendor/github.com/hyperhq/hyper-api/client/container_remove.go
generated
vendored
@@ -1,32 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/url"
|
||||
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
)
|
||||
|
||||
// ContainerRemove kills and removes a container from the docker host.
|
||||
func (cli *Client) ContainerRemove(ctx context.Context, container string, options types.ContainerRemoveOptions) ([]string, error) {
|
||||
var warnings []string
|
||||
query := url.Values{}
|
||||
if options.RemoveVolumes {
|
||||
query.Set("v", "1")
|
||||
}
|
||||
if options.RemoveLinks {
|
||||
query.Set("link", "1")
|
||||
}
|
||||
|
||||
if options.Force {
|
||||
query.Set("force", "1")
|
||||
}
|
||||
|
||||
resp, err := cli.delete(ctx, "/containers/"+container, query, nil)
|
||||
if err == nil {
|
||||
json.NewDecoder(resp.body).Decode(&warnings)
|
||||
}
|
||||
ensureReaderClosed(resp)
|
||||
return warnings, err
|
||||
}
|
||||
16
vendor/github.com/hyperhq/hyper-api/client/container_rename.go
generated
vendored
16
vendor/github.com/hyperhq/hyper-api/client/container_rename.go
generated
vendored
@@ -1,16 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
"context"
|
||||
)
|
||||
|
||||
// ContainerRename changes the name of a given container.
|
||||
func (cli *Client) ContainerRename(ctx context.Context, containerID, newContainerName string) error {
|
||||
query := url.Values{}
|
||||
query.Set("name", newContainerName)
|
||||
resp, err := cli.post(ctx, "/containers/"+containerID+"/rename", query, nil, nil)
|
||||
ensureReaderClosed(resp)
|
||||
return err
|
||||
}
|
||||
29
vendor/github.com/hyperhq/hyper-api/client/container_resize.go
generated
vendored
29
vendor/github.com/hyperhq/hyper-api/client/container_resize.go
generated
vendored
@@ -1,29 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"context"
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
)
|
||||
|
||||
// ContainerResize changes the size of the tty for a container.
|
||||
func (cli *Client) ContainerResize(ctx context.Context, containerID string, options types.ResizeOptions) error {
|
||||
return cli.resize(ctx, "/containers/"+containerID, options.Height, options.Width)
|
||||
}
|
||||
|
||||
// ContainerExecResize changes the size of the tty for an exec process running inside a container.
|
||||
func (cli *Client) ContainerExecResize(ctx context.Context, execID string, options types.ResizeOptions) error {
|
||||
return cli.resize(ctx, "/exec/"+execID, options.Height, options.Width)
|
||||
}
|
||||
|
||||
func (cli *Client) resize(ctx context.Context, basePath string, height, width int) error {
|
||||
query := url.Values{}
|
||||
query.Set("h", strconv.Itoa(height))
|
||||
query.Set("w", strconv.Itoa(width))
|
||||
|
||||
resp, err := cli.post(ctx, basePath+"/resize", query, nil, nil)
|
||||
ensureReaderClosed(resp)
|
||||
return err
|
||||
}
|
||||
19
vendor/github.com/hyperhq/hyper-api/client/container_restart.go
generated
vendored
19
vendor/github.com/hyperhq/hyper-api/client/container_restart.go
generated
vendored
@@ -1,19 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"context"
|
||||
)
|
||||
|
||||
// ContainerRestart stops and starts a container again.
|
||||
// It makes the daemon to wait for the container to be up again for
|
||||
// a specific amount of time, given the timeout.
|
||||
func (cli *Client) ContainerRestart(ctx context.Context, containerID string, timeout int) error {
|
||||
query := url.Values{}
|
||||
query.Set("t", strconv.Itoa(timeout))
|
||||
resp, err := cli.post(ctx, "/containers/"+containerID+"/restart", query, nil, nil)
|
||||
ensureReaderClosed(resp)
|
||||
return err
|
||||
}
|
||||
17
vendor/github.com/hyperhq/hyper-api/client/container_start.go
generated
vendored
17
vendor/github.com/hyperhq/hyper-api/client/container_start.go
generated
vendored
@@ -1,17 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
"context"
|
||||
)
|
||||
|
||||
// ContainerStart sends a request to the docker daemon to start a container.
|
||||
func (cli *Client) ContainerStart(ctx context.Context, containerID string, checkpointID string) error {
|
||||
query := url.Values{}
|
||||
query.Set("checkpoint", checkpointID)
|
||||
|
||||
resp, err := cli.post(ctx, "/containers/"+containerID+"/start", query, nil, nil)
|
||||
ensureReaderClosed(resp)
|
||||
return err
|
||||
}
|
||||
24
vendor/github.com/hyperhq/hyper-api/client/container_stats.go
generated
vendored
24
vendor/github.com/hyperhq/hyper-api/client/container_stats.go
generated
vendored
@@ -1,24 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/url"
|
||||
|
||||
"context"
|
||||
)
|
||||
|
||||
// ContainerStats returns near realtime stats for a given container.
|
||||
// It's up to the caller to close the io.ReadCloser returned.
|
||||
func (cli *Client) ContainerStats(ctx context.Context, containerID string, stream bool) (io.ReadCloser, error) {
|
||||
query := url.Values{}
|
||||
query.Set("stream", "0")
|
||||
if stream {
|
||||
query.Set("stream", "1")
|
||||
}
|
||||
|
||||
resp, err := cli.get(ctx, "/containers/"+containerID+"/stats", query, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.body, err
|
||||
}
|
||||
18
vendor/github.com/hyperhq/hyper-api/client/container_stop.go
generated
vendored
18
vendor/github.com/hyperhq/hyper-api/client/container_stop.go
generated
vendored
@@ -1,18 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"context"
|
||||
)
|
||||
|
||||
// ContainerStop stops a container without terminating the process.
|
||||
// The process is blocked until the container stops or the timeout expires.
|
||||
func (cli *Client) ContainerStop(ctx context.Context, containerID string, timeout int) error {
|
||||
query := url.Values{}
|
||||
query.Set("t", strconv.Itoa(timeout))
|
||||
resp, err := cli.post(ctx, "/containers/"+containerID+"/stop", query, nil, nil)
|
||||
ensureReaderClosed(resp)
|
||||
return err
|
||||
}
|
||||
28
vendor/github.com/hyperhq/hyper-api/client/container_top.go
generated
vendored
28
vendor/github.com/hyperhq/hyper-api/client/container_top.go
generated
vendored
@@ -1,28 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"context"
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
)
|
||||
|
||||
// ContainerTop shows process information from within a container.
|
||||
func (cli *Client) ContainerTop(ctx context.Context, containerID string, arguments []string) (types.ContainerProcessList, error) {
|
||||
var response types.ContainerProcessList
|
||||
query := url.Values{}
|
||||
if len(arguments) > 0 {
|
||||
query.Set("ps_args", strings.Join(arguments, " "))
|
||||
}
|
||||
|
||||
resp, err := cli.get(ctx, "/containers/"+containerID+"/top", query, nil)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(resp.body).Decode(&response)
|
||||
ensureReaderClosed(resp)
|
||||
return response, err
|
||||
}
|
||||
10
vendor/github.com/hyperhq/hyper-api/client/container_unpause.go
generated
vendored
10
vendor/github.com/hyperhq/hyper-api/client/container_unpause.go
generated
vendored
@@ -1,10 +0,0 @@
|
||||
package client
|
||||
|
||||
import "context"
|
||||
|
||||
// ContainerUnpause resumes the process execution within a container
|
||||
func (cli *Client) ContainerUnpause(ctx context.Context, containerID string) error {
|
||||
resp, err := cli.post(ctx, "/containers/"+containerID+"/unpause", nil, nil, nil)
|
||||
ensureReaderClosed(resp)
|
||||
return err
|
||||
}
|
||||
10
vendor/github.com/hyperhq/hyper-api/client/container_update.go
generated
vendored
10
vendor/github.com/hyperhq/hyper-api/client/container_update.go
generated
vendored
@@ -1,10 +0,0 @@
|
||||
package client
|
||||
|
||||
import "context"
|
||||
|
||||
// ContainerUpdate updates resources of a container
|
||||
func (cli *Client) ContainerUpdate(ctx context.Context, containerID string, updateConfig interface{}) error {
|
||||
resp, err := cli.put(ctx, "/containers/"+containerID, nil, updateConfig, nil)
|
||||
ensureReaderClosed(resp)
|
||||
return err
|
||||
}
|
||||
26
vendor/github.com/hyperhq/hyper-api/client/container_wait.go
generated
vendored
26
vendor/github.com/hyperhq/hyper-api/client/container_wait.go
generated
vendored
@@ -1,26 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"context"
|
||||
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
)
|
||||
|
||||
// ContainerWait pauses execution until a container exits.
|
||||
// It returns the API status code as response of its readiness.
|
||||
func (cli *Client) ContainerWait(ctx context.Context, containerID string) (int, error) {
|
||||
resp, err := cli.post(ctx, "/containers/"+containerID+"/wait", nil, nil, nil)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
defer ensureReaderClosed(resp)
|
||||
|
||||
var res types.ContainerWaitResponse
|
||||
if err := json.NewDecoder(resp.body).Decode(&res); err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
return res.StatusCode, nil
|
||||
}
|
||||
106
vendor/github.com/hyperhq/hyper-api/client/cron.go
generated
vendored
106
vendor/github.com/hyperhq/hyper-api/client/cron.go
generated
vendored
@@ -1,106 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"context"
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
"github.com/hyperhq/hyper-api/types/filters"
|
||||
)
|
||||
|
||||
// CronCreate creates a cron in the Hyper_.
|
||||
func (cli *Client) CronCreate(ctx context.Context, name string, sv types.Cron) (types.Cron, error) {
|
||||
var cron types.Cron
|
||||
var r = url.Values{}
|
||||
r.Set("name", name)
|
||||
resp, err := cli.post(ctx, "/crons/create", r, sv, nil)
|
||||
if err != nil {
|
||||
return cron, err
|
||||
}
|
||||
err = json.NewDecoder(resp.body).Decode(&cron)
|
||||
ensureReaderClosed(resp)
|
||||
return cron, err
|
||||
}
|
||||
|
||||
// CronDelete removes a cron from the Hyper_.
|
||||
func (cli *Client) CronDelete(ctx context.Context, id string) error {
|
||||
v := url.Values{}
|
||||
resp, err := cli.delete(ctx, "/crons/"+id, v, nil)
|
||||
ensureReaderClosed(resp)
|
||||
return err
|
||||
}
|
||||
|
||||
// CronList returns the crons configured in the docker host.
|
||||
func (cli *Client) CronList(ctx context.Context, opts types.CronListOptions) ([]types.Cron, error) {
|
||||
var crons = []types.Cron{}
|
||||
query := url.Values{}
|
||||
|
||||
if opts.Filters.Len() > 0 {
|
||||
filterJSON, err := filters.ToParamWithVersion(cli.version, opts.Filters)
|
||||
if err != nil {
|
||||
return crons, err
|
||||
}
|
||||
query.Set("filters", filterJSON)
|
||||
}
|
||||
resp, err := cli.get(ctx, "/crons", query, nil)
|
||||
if err != nil {
|
||||
return crons, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(resp.body).Decode(&crons)
|
||||
ensureReaderClosed(resp)
|
||||
return crons, err
|
||||
}
|
||||
|
||||
// CronInspect returns the information about a specific cron in the docker host.
|
||||
func (cli *Client) CronInspect(ctx context.Context, cronID string) (types.Cron, error) {
|
||||
cron, _, err := cli.CronInspectWithRaw(ctx, cronID)
|
||||
return cron, err
|
||||
}
|
||||
|
||||
// CronInspectWithRaw returns the information about a specific cron in the docker host and it's raw representation
|
||||
func (cli *Client) CronInspectWithRaw(ctx context.Context, cronID string) (types.Cron, []byte, error) {
|
||||
var cron types.Cron
|
||||
resp, err := cli.get(ctx, "/crons/"+cronID, nil, nil)
|
||||
if err != nil {
|
||||
if resp.statusCode == http.StatusNotFound {
|
||||
return cron, nil, cronNotFoundError{cronID}
|
||||
}
|
||||
return cron, nil, err
|
||||
}
|
||||
defer ensureReaderClosed(resp)
|
||||
|
||||
body, err := ioutil.ReadAll(resp.body)
|
||||
if err != nil {
|
||||
return cron, nil, err
|
||||
}
|
||||
rdr := bytes.NewReader(body)
|
||||
err = json.NewDecoder(rdr).Decode(&cron)
|
||||
return cron, body, err
|
||||
}
|
||||
|
||||
// CronHistory
|
||||
func (cli *Client) CronHistory(ctx context.Context, id, since, tail string) ([]types.Event, error) {
|
||||
var (
|
||||
es = []types.Event{}
|
||||
v = url.Values{}
|
||||
)
|
||||
if since != "" {
|
||||
v.Set("since", since)
|
||||
}
|
||||
if tail != "" {
|
||||
v.Set("tail", tail)
|
||||
}
|
||||
resp, err := cli.get(ctx, "/crons/"+id+"/history", v, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer ensureReaderClosed(resp)
|
||||
|
||||
err = json.NewDecoder(resp.body).Decode(&es)
|
||||
return es, err
|
||||
}
|
||||
165
vendor/github.com/hyperhq/hyper-api/client/errors.go
generated
vendored
165
vendor/github.com/hyperhq/hyper-api/client/errors.go
generated
vendored
@@ -1,165 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// ErrConnectionFailed is an error raised when the connection between the client and the server failed.
|
||||
var ErrConnectionFailed = errors.New("Cannot connect to the Hyper.sh server.")
|
||||
|
||||
// imageNotFoundError implements an error returned when an image is not in the docker host.
|
||||
type imageNotFoundError struct {
|
||||
imageID string
|
||||
}
|
||||
|
||||
// Error returns a string representation of an imageNotFoundError
|
||||
func (i imageNotFoundError) Error() string {
|
||||
return fmt.Sprintf("Error: No such image: %s", i.imageID)
|
||||
}
|
||||
|
||||
// IsErrImageNotFound returns true if the error is caused
|
||||
// when an image is not found in the docker host.
|
||||
func IsErrImageNotFound(err error) bool {
|
||||
_, ok := err.(imageNotFoundError)
|
||||
return ok
|
||||
}
|
||||
|
||||
// containerNotFoundError implements an error returned when a container is not in the docker host.
|
||||
type containerNotFoundError struct {
|
||||
containerID string
|
||||
}
|
||||
|
||||
// Error returns a string representation of a containerNotFoundError
|
||||
func (e containerNotFoundError) Error() string {
|
||||
return fmt.Sprintf("Error: No such container: %s", e.containerID)
|
||||
}
|
||||
|
||||
// IsErrContainerNotFound returns true if the error is caused
|
||||
// when a container is not found in the docker host.
|
||||
func IsErrContainerNotFound(err error) bool {
|
||||
_, ok := err.(containerNotFoundError)
|
||||
return ok
|
||||
}
|
||||
|
||||
// networkNotFoundError implements an error returned when a network is not in the docker host.
|
||||
type networkNotFoundError struct {
|
||||
networkID string
|
||||
}
|
||||
|
||||
// Error returns a string representation of a networkNotFoundError
|
||||
func (e networkNotFoundError) Error() string {
|
||||
return fmt.Sprintf("Error: No such network: %s", e.networkID)
|
||||
}
|
||||
|
||||
// IsErrNetworkNotFound returns true if the error is caused
|
||||
// when a network is not found in the docker host.
|
||||
func IsErrNetworkNotFound(err error) bool {
|
||||
_, ok := err.(networkNotFoundError)
|
||||
return ok
|
||||
}
|
||||
|
||||
// snapshotNotFoundError implements an error returned when a volume is not in the docker host.
|
||||
type snapshotNotFoundError struct {
|
||||
snapshotID string
|
||||
}
|
||||
|
||||
// Error returns a string representation of an networkNotFoundError
|
||||
func (e snapshotNotFoundError) Error() string {
|
||||
return fmt.Sprintf("Error: No such snapshot: %s", e.snapshotID)
|
||||
}
|
||||
|
||||
// volumeNotFoundError implements an error returned when a volume is not in the docker host.
|
||||
type volumeNotFoundError struct {
|
||||
volumeID string
|
||||
}
|
||||
|
||||
// Error returns a string representation of a networkNotFoundError
|
||||
func (e volumeNotFoundError) Error() string {
|
||||
return fmt.Sprintf("Error: No such volume: %s", e.volumeID)
|
||||
}
|
||||
|
||||
// IsErrVolumeNotFound returns true if the error is caused
|
||||
// when a volume is not found in the docker host.
|
||||
func IsErrVolumeNotFound(err error) bool {
|
||||
_, ok := err.(volumeNotFoundError)
|
||||
return ok
|
||||
}
|
||||
|
||||
// serviceNotFoundError implements an error returned when a service is not in the docker host.
|
||||
type serviceNotFoundError struct {
|
||||
serviceID string
|
||||
}
|
||||
|
||||
// Error returns a string representation of a networkNotFoundError
|
||||
func (e serviceNotFoundError) Error() string {
|
||||
return fmt.Sprintf("Error: No such service: %s", e.serviceID)
|
||||
}
|
||||
|
||||
// IsErrVolumeNotFound returns true if the error is caused
|
||||
// when a volume is not found in the docker host.
|
||||
func IsErrServiceNotFound(err error) bool {
|
||||
_, ok := err.(serviceNotFoundError)
|
||||
return ok
|
||||
}
|
||||
|
||||
// cronNotFoundError implements an error returned when a cron is not in the docker host.
|
||||
type cronNotFoundError struct {
|
||||
cronID string
|
||||
}
|
||||
|
||||
// Error returns a string representation of a networkNotFoundError
|
||||
func (e cronNotFoundError) Error() string {
|
||||
return fmt.Sprintf("Error: No such cron job: %s", e.cronID)
|
||||
}
|
||||
|
||||
// IsErrVolumeNotFound returns true if the error is caused
|
||||
// when a volume is not found in the docker host.
|
||||
func IsErrCronNotFound(err error) bool {
|
||||
_, ok := err.(cronNotFoundError)
|
||||
return ok
|
||||
}
|
||||
|
||||
// funcNotFoundError implements an error returned when a func is not in the docker host.
|
||||
type funcNotFoundError struct {
|
||||
name string
|
||||
}
|
||||
|
||||
// Error returns a string representation of a funcNotFoundError
|
||||
func (e funcNotFoundError) Error() string {
|
||||
return fmt.Sprintf("Error: No such function: %s", e.name)
|
||||
}
|
||||
|
||||
// funcCallNotFoundError implements an error returned when a func call is not in the docker host.
|
||||
type funcCallNotFoundError struct {
|
||||
id string
|
||||
}
|
||||
|
||||
// Error returns a string representation of a funcNotFoundError
|
||||
func (e funcCallNotFoundError) Error() string {
|
||||
return fmt.Sprintf("Error: No such call id: %s", e.id)
|
||||
}
|
||||
|
||||
// IsErrFuncNotFound returns true if the error is caused
|
||||
// when a func is not found in the docker host.
|
||||
func IsErrFuncNotFound(err error) bool {
|
||||
_, ok := err.(funcNotFoundError)
|
||||
return ok
|
||||
}
|
||||
|
||||
// unauthorizedError represents an authorization error in a remote registry.
|
||||
type unauthorizedError struct {
|
||||
cause error
|
||||
}
|
||||
|
||||
// Error returns a string representation of an unauthorizedError
|
||||
func (u unauthorizedError) Error() string {
|
||||
return u.cause.Error()
|
||||
}
|
||||
|
||||
// IsErrUnauthorized returns true if the error is caused
|
||||
// when a remote registry authentication fails
|
||||
func IsErrUnauthorized(err error) bool {
|
||||
_, ok := err.(unauthorizedError)
|
||||
return ok
|
||||
}
|
||||
48
vendor/github.com/hyperhq/hyper-api/client/events.go
generated
vendored
48
vendor/github.com/hyperhq/hyper-api/client/events.go
generated
vendored
@@ -1,48 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"context"
|
||||
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
"github.com/hyperhq/hyper-api/types/filters"
|
||||
timetypes "github.com/hyperhq/hyper-api/types/time"
|
||||
)
|
||||
|
||||
// Events returns a stream of events in the daemon in a ReadCloser.
|
||||
// It's up to the caller to close the stream.
|
||||
func (cli *Client) Events(ctx context.Context, options types.EventsOptions) (io.ReadCloser, error) {
|
||||
query := url.Values{}
|
||||
ref := time.Now()
|
||||
|
||||
if options.Since != "" {
|
||||
ts, err := timetypes.GetTimestamp(options.Since, ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query.Set("since", ts)
|
||||
}
|
||||
if options.Until != "" {
|
||||
ts, err := timetypes.GetTimestamp(options.Until, ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query.Set("until", ts)
|
||||
}
|
||||
if options.Filters.Len() > 0 {
|
||||
filterJSON, err := filters.ToParamWithVersion(cli.version, options.Filters)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query.Set("filters", filterJSON)
|
||||
}
|
||||
|
||||
serverResponse, err := cli.get(ctx, "/events", query, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return serverResponse.body, nil
|
||||
}
|
||||
90
vendor/github.com/hyperhq/hyper-api/client/fip.go
generated
vendored
90
vendor/github.com/hyperhq/hyper-api/client/fip.go
generated
vendored
@@ -1,90 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/url"
|
||||
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
"github.com/hyperhq/hyper-api/types/filters"
|
||||
)
|
||||
|
||||
func (cli *Client) FipAllocate(ctx context.Context, count string) ([]string, error) {
|
||||
var result []string
|
||||
var v = url.Values{}
|
||||
v.Set("count", count)
|
||||
serverResp, err := cli.post(ctx, "/fips/allocate", v, nil, nil)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
json.NewDecoder(serverResp.body).Decode(&result)
|
||||
ensureReaderClosed(serverResp)
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (cli *Client) FipRelease(ctx context.Context, ip string) error {
|
||||
var v = url.Values{}
|
||||
v.Set("ip", ip)
|
||||
_, err := cli.post(ctx, "/fips/release", v, nil, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cli *Client) FipAttach(ctx context.Context, ip, container string) error {
|
||||
var v = url.Values{}
|
||||
v.Set("ip", ip)
|
||||
v.Set("container", container)
|
||||
_, err := cli.post(ctx, "/fips/attach", v, nil, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cli *Client) FipDetach(ctx context.Context, container string) (string, error) {
|
||||
var result string
|
||||
var v = url.Values{}
|
||||
v.Set("container", container)
|
||||
resp, err := cli.post(ctx, "/fips/detach", v, nil, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
json.NewDecoder(resp.body).Decode(&result)
|
||||
ensureReaderClosed(resp)
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (cli *Client) FipList(ctx context.Context, options types.NetworkListOptions) ([]map[string]string, error) {
|
||||
query := url.Values{}
|
||||
if options.Filters.Len() > 0 {
|
||||
filterJSON, err := filters.ToParam(options.Filters)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query.Set("filters", filterJSON)
|
||||
}
|
||||
var fips []map[string]string
|
||||
resp, err := cli.get(ctx, "/fips", query, nil)
|
||||
if err != nil {
|
||||
return fips, err
|
||||
}
|
||||
err = json.NewDecoder(resp.body).Decode(&fips)
|
||||
ensureReaderClosed(resp)
|
||||
return fips, err
|
||||
}
|
||||
|
||||
func (cli *Client) FipName(ctx context.Context, ip, name string) error {
|
||||
var v = url.Values{}
|
||||
v.Set("ip", ip)
|
||||
v.Set("name", name)
|
||||
resp, err := cli.post(ctx, "/fips/name", v, nil, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ensureReaderClosed(resp)
|
||||
return nil
|
||||
}
|
||||
283
vendor/github.com/hyperhq/hyper-api/client/func.go
generated
vendored
283
vendor/github.com/hyperhq/hyper-api/client/func.go
generated
vendored
@@ -1,283 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
"github.com/hyperhq/hyper-api/types/filters"
|
||||
)
|
||||
|
||||
func newFuncEndpointRequest(region, method, subpath string, query url.Values, body io.Reader) (*http.Request, error) {
|
||||
endpoint := os.Getenv("HYPER_FUNC_ENDPOINT")
|
||||
if endpoint == "" {
|
||||
endpoint = region + ".hyperfunc.io"
|
||||
}
|
||||
apiURL, err := url.Parse(endpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
apiURL.Scheme = "https"
|
||||
apiURL.Path = path.Join(apiURL.Path, subpath)
|
||||
queryStr := query.Encode()
|
||||
if queryStr != "" {
|
||||
apiURL.RawQuery = queryStr
|
||||
}
|
||||
req, err := http.NewRequest(method, apiURL.String(), body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func funcEndpointRequestHijack(req *http.Request) (net.Conn, error) {
|
||||
req.Header.Set("Connection", "Upgrade")
|
||||
req.Header.Set("Upgrade", "tcp")
|
||||
conn, err := tls.Dial("tcp", req.URL.Host+":443", &tls.Config{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
clientConn := httputil.NewClientConn(conn, nil)
|
||||
resp, err := clientConn.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if resp.StatusCode != 101 {
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, fmt.Errorf("Error response from server: %s", bytes.TrimSpace(body))
|
||||
}
|
||||
respConn, _ := clientConn.Hijack()
|
||||
return respConn, nil
|
||||
}
|
||||
|
||||
func funcEndpointRequest(req *http.Request) (*http.Response, error) {
|
||||
client := &http.Client{Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{},
|
||||
}}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
status := resp.StatusCode
|
||||
if status < 200 || status >= 400 {
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, fmt.Errorf("Error response from server: %s", bytes.TrimSpace(body))
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (cli *Client) FuncCreate(ctx context.Context, opts types.Func) (types.Func, error) {
|
||||
var fn types.Func
|
||||
_, _, err := cli.ImageInspectWithRaw(context.Background(), opts.Config.Image, false)
|
||||
if err != nil {
|
||||
return fn, err
|
||||
}
|
||||
resp, err := cli.post(ctx, "/funcs/create", nil, opts, nil)
|
||||
if err != nil {
|
||||
return fn, err
|
||||
}
|
||||
err = json.NewDecoder(resp.body).Decode(&fn)
|
||||
ensureReaderClosed(resp)
|
||||
return fn, err
|
||||
}
|
||||
|
||||
func (cli *Client) FuncUpdate(ctx context.Context, name string, opts types.Func) (types.Func, error) {
|
||||
var fn types.Func
|
||||
resp, err := cli.put(ctx, "/funcs/"+name, nil, opts, nil)
|
||||
if err != nil {
|
||||
return fn, err
|
||||
}
|
||||
err = json.NewDecoder(resp.body).Decode(&fn)
|
||||
ensureReaderClosed(resp)
|
||||
return fn, err
|
||||
}
|
||||
|
||||
func (cli *Client) FuncDelete(ctx context.Context, name string) error {
|
||||
resp, err := cli.delete(ctx, "/funcs/"+name, nil, nil)
|
||||
ensureReaderClosed(resp)
|
||||
return err
|
||||
}
|
||||
|
||||
func (cli *Client) FuncList(ctx context.Context, opts types.FuncListOptions) ([]types.Func, error) {
|
||||
var fns = []types.Func{}
|
||||
query := url.Values{}
|
||||
|
||||
if opts.Filters.Len() > 0 {
|
||||
filterJSON, err := filters.ToParamWithVersion(cli.version, opts.Filters)
|
||||
if err != nil {
|
||||
return fns, err
|
||||
}
|
||||
query.Set("filters", filterJSON)
|
||||
}
|
||||
resp, err := cli.get(ctx, "/funcs", query, nil)
|
||||
if err != nil {
|
||||
return fns, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(resp.body).Decode(&fns)
|
||||
ensureReaderClosed(resp)
|
||||
return fns, err
|
||||
}
|
||||
|
||||
func (cli *Client) FuncInspect(ctx context.Context, name string) (types.Func, error) {
|
||||
fn, _, err := cli.FuncInspectWithRaw(ctx, name)
|
||||
return fn, err
|
||||
}
|
||||
|
||||
func (cli *Client) FuncInspectWithRaw(ctx context.Context, name string) (types.Func, []byte, error) {
|
||||
var fn types.Func
|
||||
resp, err := cli.get(ctx, "/funcs/"+name, nil, nil)
|
||||
if err != nil {
|
||||
if resp.statusCode == http.StatusNotFound {
|
||||
return fn, nil, funcNotFoundError{name}
|
||||
}
|
||||
return fn, nil, err
|
||||
}
|
||||
defer ensureReaderClosed(resp)
|
||||
|
||||
body, err := ioutil.ReadAll(resp.body)
|
||||
if err != nil {
|
||||
return fn, nil, err
|
||||
}
|
||||
rdr := bytes.NewReader(body)
|
||||
err = json.NewDecoder(rdr).Decode(&fn)
|
||||
return fn, body, err
|
||||
}
|
||||
|
||||
func (cli *Client) FuncInspectWithCallId(ctx context.Context, id string) (*types.Func, error) {
|
||||
var fn types.Func
|
||||
resp, err := cli.get(ctx, "/funcs/call/"+id, nil, nil)
|
||||
if err != nil {
|
||||
if resp.statusCode == http.StatusNotFound {
|
||||
return nil, funcCallNotFoundError{id}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
defer ensureReaderClosed(resp)
|
||||
|
||||
body, err := ioutil.ReadAll(resp.body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rdr := bytes.NewReader(body)
|
||||
err = json.NewDecoder(rdr).Decode(&fn)
|
||||
return &fn, err
|
||||
}
|
||||
|
||||
func (cli *Client) FuncCall(ctx context.Context, region, name string, stdin io.Reader, sync bool) (io.ReadCloser, error) {
|
||||
fn, _, err := cli.FuncInspectWithRaw(ctx, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
subpath := ""
|
||||
if sync {
|
||||
subpath += "/sync"
|
||||
}
|
||||
req, err := newFuncEndpointRequest(region, "POST", path.Join("call", name, fn.UUID, subpath), nil, stdin)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := funcEndpointRequest(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Body, nil
|
||||
}
|
||||
|
||||
func (cli *Client) FuncGet(ctx context.Context, region, callId string, wait bool) (io.ReadCloser, error) {
|
||||
fn, err := cli.FuncInspectWithCallId(ctx, callId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
subpath := callId
|
||||
if wait {
|
||||
subpath += "/wait"
|
||||
}
|
||||
req, err := newFuncEndpointRequest(region, "GET", path.Join("output", fn.Name, fn.UUID, subpath), nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := funcEndpointRequest(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Body, nil
|
||||
}
|
||||
|
||||
func (cli *Client) FuncLogs(ctx context.Context, region, name, callId string, follow bool, tail string) (io.ReadCloser, error) {
|
||||
fn, _, err := cli.FuncInspectWithRaw(ctx, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query := url.Values{}
|
||||
if callId != "" {
|
||||
query.Set("callid", callId)
|
||||
}
|
||||
if follow {
|
||||
query.Add("follow", strconv.FormatBool(follow))
|
||||
}
|
||||
if tail != "" {
|
||||
query.Add("tail", tail)
|
||||
}
|
||||
req, err := newFuncEndpointRequest(region, "GET", path.Join("logs", name, fn.UUID, ""), query, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if follow {
|
||||
conn, err := funcEndpointRequestHijack(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return conn.(io.ReadCloser), nil
|
||||
}
|
||||
resp, err := funcEndpointRequest(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Body, nil
|
||||
}
|
||||
|
||||
func (cli *Client) FuncStatus(ctx context.Context, region, name string) (*types.FuncStatusResponse, error) {
|
||||
fn, _, err := cli.FuncInspectWithRaw(ctx, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query := url.Values{}
|
||||
query.Set("list", strconv.FormatBool(false))
|
||||
req, err := newFuncEndpointRequest(region, "GET", path.Join("status", name, fn.UUID), query, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := funcEndpointRequest(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var ret types.FuncStatusResponse
|
||||
err = json.NewDecoder(resp.Body).Decode(&ret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ret, nil
|
||||
}
|
||||
176
vendor/github.com/hyperhq/hyper-api/client/hijack.go
generated
vendored
176
vendor/github.com/hyperhq/hyper-api/client/hijack.go
generated
vendored
@@ -1,176 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"net"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/go-connections/sockets"
|
||||
"github.com/hyperhq/hyper-api/signature"
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
)
|
||||
|
||||
// tlsClientCon holds tls information and a dialed connection.
|
||||
type tlsClientCon struct {
|
||||
*tls.Conn
|
||||
rawConn net.Conn
|
||||
}
|
||||
|
||||
func (c *tlsClientCon) CloseWrite() error {
|
||||
// Go standard tls.Conn doesn't provide the CloseWrite() method so we do it
|
||||
// on its underlying connection.
|
||||
if conn, ok := c.rawConn.(types.CloseWriter); ok {
|
||||
return conn.CloseWrite()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// postHijacked sends a POST request and hijacks the connection.
|
||||
func (cli *Client) postHijacked(ctx context.Context, path string, query url.Values, body interface{}, headers map[string][]string) (types.HijackedResponse, error) {
|
||||
bodyEncoded, err := encodeData(body)
|
||||
if err != nil {
|
||||
return types.HijackedResponse{}, err
|
||||
}
|
||||
|
||||
req, err := cli.newRequest("POST", path, query, bodyEncoded, headers)
|
||||
if err != nil {
|
||||
return types.HijackedResponse{}, err
|
||||
}
|
||||
req.URL.Host = cli.addr
|
||||
|
||||
req.Header.Set("Connection", "Upgrade")
|
||||
req.Header.Set("Upgrade", "tcp")
|
||||
|
||||
req = signature.Sign4(cli.accessKey, cli.secretKey, req, cli.region)
|
||||
conn, err := dial(cli.proto, cli.addr, cli.transport.TLSConfig())
|
||||
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "connection refused") {
|
||||
return types.HijackedResponse{}, ErrConnectionFailed
|
||||
}
|
||||
return types.HijackedResponse{}, err
|
||||
}
|
||||
|
||||
// When we set up a TCP connection for hijack, there could be long periods
|
||||
// of inactivity (a long running command with no output) that in certain
|
||||
// network setups may cause ECONNTIMEOUT, leaving the client in an unknown
|
||||
// state. Setting TCP KeepAlive on the socket connection will prohibit
|
||||
// ECONNTIMEOUT unless the socket connection truly is broken
|
||||
if tcpConn, ok := conn.(*net.TCPConn); ok {
|
||||
tcpConn.SetKeepAlive(true)
|
||||
tcpConn.SetKeepAlivePeriod(30 * time.Second)
|
||||
}
|
||||
|
||||
clientconn := httputil.NewClientConn(conn, nil)
|
||||
defer clientconn.Close()
|
||||
|
||||
// Server hijacks the connection, error 'connection closed' expected
|
||||
resp, err := clientconn.Do(req)
|
||||
|
||||
rwc, br := clientconn.Hijack()
|
||||
|
||||
return types.HijackedResponse{Conn: rwc, Reader: br, Resp: resp}, err
|
||||
}
|
||||
|
||||
func tlsDial(network, addr string, config *tls.Config) (net.Conn, error) {
|
||||
return tlsDialWithDialer(new(net.Dialer), network, addr, config)
|
||||
}
|
||||
|
||||
// We need to copy Go's implementation of tls.Dial (pkg/cryptor/tls/tls.go) in
|
||||
// order to return our custom tlsClientCon struct which holds both the tls.Conn
|
||||
// object _and_ its underlying raw connection. The rationale for this is that
|
||||
// we need to be able to close the write end of the connection when attaching,
|
||||
// which tls.Conn does not provide.
|
||||
func tlsDialWithDialer(dialer *net.Dialer, network, addr string, config *tls.Config) (net.Conn, error) {
|
||||
// We want the Timeout and Deadline values from dialer to cover the
|
||||
// whole process: TCP connection and TLS handshake. This means that we
|
||||
// also need to start our own timers now.
|
||||
timeout := dialer.Timeout
|
||||
|
||||
if !dialer.Deadline.IsZero() {
|
||||
deadlineTimeout := dialer.Deadline.Sub(time.Now())
|
||||
if timeout == 0 || deadlineTimeout < timeout {
|
||||
timeout = deadlineTimeout
|
||||
}
|
||||
}
|
||||
|
||||
var errChannel chan error
|
||||
|
||||
if timeout != 0 {
|
||||
errChannel = make(chan error, 2)
|
||||
time.AfterFunc(timeout, func() {
|
||||
errChannel <- errors.New("")
|
||||
})
|
||||
}
|
||||
|
||||
proxyDialer, err := sockets.DialerFromEnvironment(dialer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rawConn, err := proxyDialer.Dial(network, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// When we set up a TCP connection for hijack, there could be long periods
|
||||
// of inactivity (a long running command with no output) that in certain
|
||||
// network setups may cause ECONNTIMEOUT, leaving the client in an unknown
|
||||
// state. Setting TCP KeepAlive on the socket connection will prohibit
|
||||
// ECONNTIMEOUT unless the socket connection truly is broken
|
||||
if tcpConn, ok := rawConn.(*net.TCPConn); ok {
|
||||
tcpConn.SetKeepAlive(true)
|
||||
tcpConn.SetKeepAlivePeriod(30 * time.Second)
|
||||
}
|
||||
|
||||
colonPos := strings.LastIndex(addr, ":")
|
||||
if colonPos == -1 {
|
||||
colonPos = len(addr)
|
||||
}
|
||||
hostname := addr[:colonPos]
|
||||
|
||||
// If no ServerName is set, infer the ServerName
|
||||
// from the hostname we're connecting to.
|
||||
if config.ServerName == "" {
|
||||
// Make a copy to avoid polluting argument or default.
|
||||
c := *config
|
||||
c.ServerName = hostname
|
||||
config = &c
|
||||
}
|
||||
|
||||
conn := tls.Client(rawConn, config)
|
||||
|
||||
if timeout == 0 {
|
||||
err = conn.Handshake()
|
||||
} else {
|
||||
go func() {
|
||||
errChannel <- conn.Handshake()
|
||||
}()
|
||||
|
||||
err = <-errChannel
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
rawConn.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// This is Docker difference with standard's crypto/tls package: returned a
|
||||
// wrapper which holds both the TLS and raw connections.
|
||||
return &tlsClientCon{conn, rawConn}, nil
|
||||
}
|
||||
|
||||
func dial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) {
|
||||
if tlsConfig != nil && proto != "unix" && proto != "npipe" {
|
||||
// Notice this isn't Go standard's tls.Dial function
|
||||
return tlsDial(proto, addr, tlsConfig)
|
||||
}
|
||||
if proto == "npipe" {
|
||||
return sockets.DialPipe(addr, 32*time.Second)
|
||||
}
|
||||
return net.Dial(proto, addr)
|
||||
}
|
||||
119
vendor/github.com/hyperhq/hyper-api/client/image_build.go
generated
vendored
119
vendor/github.com/hyperhq/hyper-api/client/image_build.go
generated
vendored
@@ -1,119 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"context"
|
||||
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
"github.com/hyperhq/hyper-api/types/container"
|
||||
)
|
||||
|
||||
var headerRegexp = regexp.MustCompile(`\ADocker/.+\s\((.+)\)\z`)
|
||||
|
||||
// ImageBuild sends request to the daemon to build images.
|
||||
// The Body in the response implement an io.ReadCloser and it's up to the caller to
|
||||
// close it.
|
||||
func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) {
|
||||
query, err := imageBuildOptionsToQuery(options)
|
||||
if err != nil {
|
||||
return types.ImageBuildResponse{}, err
|
||||
}
|
||||
|
||||
headers := http.Header(make(map[string][]string))
|
||||
buf, err := json.Marshal(options.AuthConfigs)
|
||||
if err != nil {
|
||||
return types.ImageBuildResponse{}, err
|
||||
}
|
||||
headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf))
|
||||
headers.Set("Content-Type", "application/tar")
|
||||
|
||||
serverResp, err := cli.postRaw(ctx, "/build", query, buildContext, headers)
|
||||
if err != nil {
|
||||
return types.ImageBuildResponse{}, err
|
||||
}
|
||||
|
||||
osType := getDockerOS(serverResp.header.Get("Server"))
|
||||
|
||||
return types.ImageBuildResponse{
|
||||
Body: serverResp.body,
|
||||
OSType: osType,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func imageBuildOptionsToQuery(options types.ImageBuildOptions) (url.Values, error) {
|
||||
query := url.Values{
|
||||
"t": options.Tags,
|
||||
}
|
||||
if options.SuppressOutput {
|
||||
query.Set("q", "1")
|
||||
}
|
||||
if options.RemoteContext != "" {
|
||||
query.Set("remote", options.RemoteContext)
|
||||
}
|
||||
if options.NoCache {
|
||||
query.Set("nocache", "1")
|
||||
}
|
||||
if options.Remove {
|
||||
query.Set("rm", "1")
|
||||
} else {
|
||||
query.Set("rm", "0")
|
||||
}
|
||||
|
||||
if options.ForceRemove {
|
||||
query.Set("forcerm", "1")
|
||||
}
|
||||
|
||||
if options.PullParent {
|
||||
query.Set("pull", "1")
|
||||
}
|
||||
|
||||
if !container.Isolation.IsDefault(options.Isolation) {
|
||||
query.Set("isolation", string(options.Isolation))
|
||||
}
|
||||
|
||||
query.Set("cpusetcpus", options.CPUSetCPUs)
|
||||
query.Set("cpusetmems", options.CPUSetMems)
|
||||
query.Set("cpushares", strconv.FormatInt(options.CPUShares, 10))
|
||||
query.Set("cpuquota", strconv.FormatInt(options.CPUQuota, 10))
|
||||
query.Set("cpuperiod", strconv.FormatInt(options.CPUPeriod, 10))
|
||||
query.Set("memory", strconv.FormatInt(options.Memory, 10))
|
||||
query.Set("memswap", strconv.FormatInt(options.MemorySwap, 10))
|
||||
query.Set("cgroupparent", options.CgroupParent)
|
||||
query.Set("shmsize", strconv.FormatInt(options.ShmSize, 10))
|
||||
query.Set("dockerfile", options.Dockerfile)
|
||||
|
||||
ulimitsJSON, err := json.Marshal(options.Ulimits)
|
||||
if err != nil {
|
||||
return query, err
|
||||
}
|
||||
query.Set("ulimits", string(ulimitsJSON))
|
||||
|
||||
buildArgsJSON, err := json.Marshal(options.BuildArgs)
|
||||
if err != nil {
|
||||
return query, err
|
||||
}
|
||||
query.Set("buildargs", string(buildArgsJSON))
|
||||
|
||||
labelsJSON, err := json.Marshal(options.Labels)
|
||||
if err != nil {
|
||||
return query, err
|
||||
}
|
||||
query.Set("labels", string(labelsJSON))
|
||||
return query, nil
|
||||
}
|
||||
|
||||
func getDockerOS(serverHeader string) string {
|
||||
var osType string
|
||||
matches := headerRegexp.FindStringSubmatch(serverHeader)
|
||||
if len(matches) > 0 {
|
||||
osType = matches[1]
|
||||
}
|
||||
return osType
|
||||
}
|
||||
34
vendor/github.com/hyperhq/hyper-api/client/image_create.go
generated
vendored
34
vendor/github.com/hyperhq/hyper-api/client/image_create.go
generated
vendored
@@ -1,34 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/url"
|
||||
|
||||
"context"
|
||||
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
"github.com/hyperhq/hyper-api/types/reference"
|
||||
)
|
||||
|
||||
// ImageCreate creates a new image based in the parent options.
|
||||
// It returns the JSON content in the response body.
|
||||
func (cli *Client) ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) {
|
||||
repository, tag, err := reference.Parse(parentReference)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query := url.Values{}
|
||||
query.Set("fromImage", repository)
|
||||
query.Set("tag", tag)
|
||||
resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.body, nil
|
||||
}
|
||||
|
||||
func (cli *Client) tryImageCreate(ctx context.Context, query url.Values, registryAuth string) (*serverResponse, error) {
|
||||
headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
|
||||
return cli.post(ctx, "/images/create", query, nil, headers)
|
||||
}
|
||||
22
vendor/github.com/hyperhq/hyper-api/client/image_history.go
generated
vendored
22
vendor/github.com/hyperhq/hyper-api/client/image_history.go
generated
vendored
@@ -1,22 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/url"
|
||||
|
||||
"context"
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
)
|
||||
|
||||
// ImageHistory returns the changes in an image in history format.
|
||||
func (cli *Client) ImageHistory(ctx context.Context, imageID string) ([]types.ImageHistory, error) {
|
||||
var history []types.ImageHistory
|
||||
serverResp, err := cli.get(ctx, "/images/"+imageID+"/history", url.Values{}, nil)
|
||||
if err != nil {
|
||||
return history, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(serverResp.body).Decode(&history)
|
||||
ensureReaderClosed(serverResp)
|
||||
return history, err
|
||||
}
|
||||
37
vendor/github.com/hyperhq/hyper-api/client/image_import.go
generated
vendored
37
vendor/github.com/hyperhq/hyper-api/client/image_import.go
generated
vendored
@@ -1,37 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/url"
|
||||
|
||||
"context"
|
||||
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
)
|
||||
|
||||
// ImageImport creates a new image based in the source options.
|
||||
// It returns the JSON content in the response body.
|
||||
func (cli *Client) ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) {
|
||||
if ref != "" {
|
||||
//Check if the given image name can be resolved
|
||||
if _, err := reference.ParseNamed(ref); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
query := url.Values{}
|
||||
query.Set("fromSrc", source.SourceName)
|
||||
query.Set("repo", ref)
|
||||
query.Set("tag", options.Tag)
|
||||
query.Set("message", options.Message)
|
||||
for _, change := range options.Changes {
|
||||
query.Add("changes", change)
|
||||
}
|
||||
|
||||
resp, err := cli.postRaw(ctx, "/images/create", query, source.Source, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.body, nil
|
||||
}
|
||||
38
vendor/github.com/hyperhq/hyper-api/client/image_inspect.go
generated
vendored
38
vendor/github.com/hyperhq/hyper-api/client/image_inspect.go
generated
vendored
@@ -1,38 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"context"
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
)
|
||||
|
||||
// ImageInspectWithRaw returns the image information and its raw representation.
|
||||
func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string, getSize bool) (types.ImageInspect, []byte, error) {
|
||||
query := url.Values{}
|
||||
if getSize {
|
||||
query.Set("size", "1")
|
||||
}
|
||||
serverResp, err := cli.get(ctx, "/images/"+imageID+"/json", query, nil)
|
||||
if err != nil {
|
||||
if serverResp.statusCode == http.StatusNotFound {
|
||||
return types.ImageInspect{}, nil, imageNotFoundError{imageID}
|
||||
}
|
||||
return types.ImageInspect{}, nil, err
|
||||
}
|
||||
defer ensureReaderClosed(serverResp)
|
||||
|
||||
body, err := ioutil.ReadAll(serverResp.body)
|
||||
if err != nil {
|
||||
return types.ImageInspect{}, nil, err
|
||||
}
|
||||
|
||||
var response types.ImageInspect
|
||||
rdr := bytes.NewReader(body)
|
||||
err = json.NewDecoder(rdr).Decode(&response)
|
||||
return response, body, err
|
||||
}
|
||||
40
vendor/github.com/hyperhq/hyper-api/client/image_list.go
generated
vendored
40
vendor/github.com/hyperhq/hyper-api/client/image_list.go
generated
vendored
@@ -1,40 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/url"
|
||||
|
||||
"context"
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
"github.com/hyperhq/hyper-api/types/filters"
|
||||
)
|
||||
|
||||
// ImageList returns a list of images in the docker host.
|
||||
func (cli *Client) ImageList(ctx context.Context, options types.ImageListOptions) ([]types.Image, error) {
|
||||
var images []types.Image
|
||||
query := url.Values{}
|
||||
|
||||
if options.Filters.Len() > 0 {
|
||||
filterJSON, err := filters.ToParamWithVersion(cli.version, options.Filters)
|
||||
if err != nil {
|
||||
return images, err
|
||||
}
|
||||
query.Set("filters", filterJSON)
|
||||
}
|
||||
if options.MatchName != "" {
|
||||
// FIXME rename this parameter, to not be confused with the filters flag
|
||||
query.Set("filter", options.MatchName)
|
||||
}
|
||||
if options.All {
|
||||
query.Set("all", "1")
|
||||
}
|
||||
|
||||
serverResp, err := cli.get(ctx, "/images/json", query, nil)
|
||||
if err != nil {
|
||||
return images, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(serverResp.body).Decode(&images)
|
||||
ensureReaderClosed(serverResp)
|
||||
return images, err
|
||||
}
|
||||
22
vendor/github.com/hyperhq/hyper-api/client/image_load.go
generated
vendored
22
vendor/github.com/hyperhq/hyper-api/client/image_load.go
generated
vendored
@@ -1,22 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
"context"
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
)
|
||||
|
||||
// ImageLoad loads an image in the docker host from the client host.
|
||||
// It's up to the caller to close the io.ReadCloser returned by
|
||||
// this function.
|
||||
func (cli *Client) ImageLoad(ctx context.Context, input interface{}) (*types.ImageLoadResponse, error) {
|
||||
resp, err := cli.post(ctx, "/images/load", url.Values{}, input, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &types.ImageLoadResponse{
|
||||
Body: resp.body,
|
||||
JSON: resp.header.Get("Content-Type") == "application/json",
|
||||
}, nil
|
||||
}
|
||||
83
vendor/github.com/hyperhq/hyper-api/client/image_load_local.go
generated
vendored
83
vendor/github.com/hyperhq/hyper-api/client/image_load_local.go
generated
vendored
@@ -1,83 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"context"
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
)
|
||||
|
||||
func (cli *Client) ImageSaveTarFromDaemon(ctx context.Context, imageIDs []string) (io.ReadCloser, error) {
|
||||
query := url.Values{
|
||||
"names": imageIDs,
|
||||
}
|
||||
tr := &http.Transport{
|
||||
Dial: func(proto, addr string) (conn net.Conn, err error) {
|
||||
return net.Dial("unix", "/var/run/docker.sock")
|
||||
},
|
||||
}
|
||||
client := &http.Client{Transport: tr}
|
||||
resp, err := client.Get("http://d/images/get?" + query.Encode())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var dm struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
errHead := "Error from local docker daemon: "
|
||||
if err := json.Unmarshal(data, &dm); err != nil {
|
||||
return nil, errors.New(errHead + string(data))
|
||||
}
|
||||
return nil, errors.New(errHead + dm.Message)
|
||||
}
|
||||
return resp.Body, nil
|
||||
}
|
||||
|
||||
func (cli *Client) ImageDiff(ctx context.Context, allLayers [][]string, repoTags [][]string) (*types.ImageDiffResponse, error) {
|
||||
resp, err := cli.post(ctx, "/images/diff", nil, map[string]interface{}{
|
||||
"layers": allLayers,
|
||||
"repoTags": repoTags,
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var diffRet types.ImageDiffResponse
|
||||
err = json.NewDecoder(resp.body).Decode(&diffRet)
|
||||
ensureReaderClosed(resp)
|
||||
return &diffRet, nil
|
||||
}
|
||||
|
||||
func (cli *Client) ImageLoadLocal(ctx context.Context, quiet bool, size int64) (*types.HijackedResponse, error) {
|
||||
query := url.Values{}
|
||||
query.Add("file", "true")
|
||||
query.Add("quiet", strconv.FormatBool(quiet))
|
||||
headers := http.Header{}
|
||||
headers.Add("X-Hyper-Content-Length", strconv.FormatInt(size, 10))
|
||||
|
||||
resp, err := cli.postHijacked(ctx, "/images/load", query, nil, headers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resp.Resp != nil && resp.Resp.StatusCode != http.StatusSwitchingProtocols {
|
||||
data, err := ioutil.ReadAll(resp.Resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, errors.New("Error response from daemon: " + string(data))
|
||||
}
|
||||
|
||||
return &resp, nil
|
||||
}
|
||||
46
vendor/github.com/hyperhq/hyper-api/client/image_pull.go
generated
vendored
46
vendor/github.com/hyperhq/hyper-api/client/image_pull.go
generated
vendored
@@ -1,46 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"context"
|
||||
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
"github.com/hyperhq/hyper-api/types/reference"
|
||||
)
|
||||
|
||||
// ImagePull requests the docker host to pull an image from a remote registry.
|
||||
// It executes the privileged function if the operation is unauthorized
|
||||
// and it tries one more time.
|
||||
// It's up to the caller to handle the io.ReadCloser and close it properly.
|
||||
//
|
||||
// FIXME(vdemeester): there is currently used in a few way in docker/docker
|
||||
// - if not in trusted content, ref is used to pass the whole reference, and tag is empty
|
||||
// - if in trusted content, ref is used to pass the reference name, and tag for the digest
|
||||
func (cli *Client) ImagePull(ctx context.Context, ref string, options types.ImagePullOptions) (io.ReadCloser, error) {
|
||||
repository, tag, err := reference.Parse(ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query := url.Values{}
|
||||
query.Set("fromImage", repository)
|
||||
if tag != "" && !options.All {
|
||||
query.Set("tag", tag)
|
||||
}
|
||||
|
||||
resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth)
|
||||
if resp.statusCode == http.StatusProxyAuthRequired {
|
||||
newAuthHeader, privilegeErr := options.PrivilegeFunc()
|
||||
if privilegeErr != nil {
|
||||
return nil, privilegeErr
|
||||
}
|
||||
resp, err = cli.tryImageCreate(ctx, query, newAuthHeader)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.body, nil
|
||||
}
|
||||
54
vendor/github.com/hyperhq/hyper-api/client/image_push.go
generated
vendored
54
vendor/github.com/hyperhq/hyper-api/client/image_push.go
generated
vendored
@@ -1,54 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"context"
|
||||
|
||||
distreference "github.com/docker/distribution/reference"
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
)
|
||||
|
||||
// ImagePush requests the docker host to push an image to a remote registry.
|
||||
// It executes the privileged function if the operation is unauthorized
|
||||
// and it tries one more time.
|
||||
// It's up to the caller to handle the io.ReadCloser and close it properly.
|
||||
func (cli *Client) ImagePush(ctx context.Context, ref string, options types.ImagePushOptions) (io.ReadCloser, error) {
|
||||
distributionRef, err := distreference.ParseNamed(ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, isCanonical := distributionRef.(distreference.Canonical); isCanonical {
|
||||
return nil, errors.New("cannot push a digest reference")
|
||||
}
|
||||
|
||||
var tag = ""
|
||||
if nameTaggedRef, isNamedTagged := distributionRef.(distreference.NamedTagged); isNamedTagged {
|
||||
tag = nameTaggedRef.Tag()
|
||||
}
|
||||
|
||||
query := url.Values{}
|
||||
query.Set("tag", tag)
|
||||
|
||||
resp, err := cli.tryImagePush(ctx, distributionRef.Name(), query, options.RegistryAuth)
|
||||
if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil {
|
||||
newAuthHeader, privilegeErr := options.PrivilegeFunc()
|
||||
if privilegeErr != nil {
|
||||
return nil, privilegeErr
|
||||
}
|
||||
resp, err = cli.tryImagePush(ctx, distributionRef.Name(), query, newAuthHeader)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.body, nil
|
||||
}
|
||||
|
||||
func (cli *Client) tryImagePush(ctx context.Context, imageID string, query url.Values, registryAuth string) (*serverResponse, error) {
|
||||
headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
|
||||
return cli.post(ctx, "/images/"+imageID+"/push", query, nil, headers)
|
||||
}
|
||||
31
vendor/github.com/hyperhq/hyper-api/client/image_remove.go
generated
vendored
31
vendor/github.com/hyperhq/hyper-api/client/image_remove.go
generated
vendored
@@ -1,31 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/url"
|
||||
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
)
|
||||
|
||||
// ImageRemove removes an image from the docker host.
|
||||
func (cli *Client) ImageRemove(ctx context.Context, imageID string, options types.ImageRemoveOptions) ([]types.ImageDelete, error) {
|
||||
query := url.Values{}
|
||||
|
||||
if options.Force {
|
||||
query.Set("force", "1")
|
||||
}
|
||||
if !options.PruneChildren {
|
||||
query.Set("noprune", "1")
|
||||
}
|
||||
|
||||
resp, err := cli.delete(ctx, "/images/"+imageID, query, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var dels []types.ImageDelete
|
||||
err = json.NewDecoder(resp.body).Decode(&dels)
|
||||
ensureReaderClosed(resp)
|
||||
return dels, err
|
||||
}
|
||||
21
vendor/github.com/hyperhq/hyper-api/client/image_save.go
generated
vendored
21
vendor/github.com/hyperhq/hyper-api/client/image_save.go
generated
vendored
@@ -1,21 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// ImageSave retrieves one or more images from the docker host as an io.ReadCloser.
|
||||
// It's up to the caller to store the images and close the stream.
|
||||
func (cli *Client) ImageSave(ctx context.Context, imageIDs []string) (io.ReadCloser, error) {
|
||||
query := url.Values{
|
||||
"names": imageIDs,
|
||||
}
|
||||
|
||||
resp, err := cli.get(ctx, "/images/get", query, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.body, nil
|
||||
}
|
||||
49
vendor/github.com/hyperhq/hyper-api/client/image_search.go
generated
vendored
49
vendor/github.com/hyperhq/hyper-api/client/image_search.go
generated
vendored
@@ -1,49 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
"github.com/hyperhq/hyper-api/types/filters"
|
||||
"github.com/hyperhq/hyper-api/types/registry"
|
||||
)
|
||||
|
||||
// ImageSearch makes the docker host to search by a term in a remote registry.
|
||||
// The list of results is not sorted in any fashion.
|
||||
func (cli *Client) ImageSearch(ctx context.Context, term string, options types.ImageSearchOptions) ([]registry.SearchResult, error) {
|
||||
var results []registry.SearchResult
|
||||
query := url.Values{}
|
||||
query.Set("term", term)
|
||||
|
||||
if options.Filters.Len() > 0 {
|
||||
filterJSON, err := filters.ToParam(options.Filters)
|
||||
if err != nil {
|
||||
return results, err
|
||||
}
|
||||
query.Set("filters", filterJSON)
|
||||
}
|
||||
|
||||
resp, err := cli.tryImageSearch(ctx, query, options.RegistryAuth)
|
||||
if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil {
|
||||
newAuthHeader, privilegeErr := options.PrivilegeFunc()
|
||||
if privilegeErr != nil {
|
||||
return results, privilegeErr
|
||||
}
|
||||
resp, err = cli.tryImageSearch(ctx, query, newAuthHeader)
|
||||
}
|
||||
if err != nil {
|
||||
return results, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(resp.body).Decode(&results)
|
||||
ensureReaderClosed(resp)
|
||||
return results, err
|
||||
}
|
||||
|
||||
func (cli *Client) tryImageSearch(ctx context.Context, query url.Values, registryAuth string) (*serverResponse, error) {
|
||||
headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
|
||||
return cli.get(ctx, "/images/search", query, headers)
|
||||
}
|
||||
37
vendor/github.com/hyperhq/hyper-api/client/image_tag.go
generated
vendored
37
vendor/github.com/hyperhq/hyper-api/client/image_tag.go
generated
vendored
@@ -1,37 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
distreference "github.com/docker/distribution/reference"
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
"github.com/hyperhq/hyper-api/types/reference"
|
||||
)
|
||||
|
||||
// ImageTag tags an image in the docker host
|
||||
func (cli *Client) ImageTag(ctx context.Context, imageID, ref string, options types.ImageTagOptions) error {
|
||||
distributionRef, err := distreference.ParseNamed(ref)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error parsing reference: %q is not a valid repository/tag", ref)
|
||||
}
|
||||
|
||||
if _, isCanonical := distributionRef.(distreference.Canonical); isCanonical {
|
||||
return errors.New("refusing to create a tag with a digest reference")
|
||||
}
|
||||
|
||||
tag := reference.GetTagFromNamedRef(distributionRef)
|
||||
|
||||
query := url.Values{}
|
||||
query.Set("repo", distributionRef.Name())
|
||||
query.Set("tag", tag)
|
||||
if options.Force {
|
||||
query.Set("force", "1")
|
||||
}
|
||||
|
||||
resp, err := cli.post(ctx, "/images/"+imageID+"/tag", query, nil, nil)
|
||||
ensureReaderClosed(resp)
|
||||
return err
|
||||
}
|
||||
26
vendor/github.com/hyperhq/hyper-api/client/info.go
generated
vendored
26
vendor/github.com/hyperhq/hyper-api/client/info.go
generated
vendored
@@ -1,26 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
)
|
||||
|
||||
// Info returns information about the docker server.
|
||||
func (cli *Client) Info(ctx context.Context) (types.Info, error) {
|
||||
var info types.Info
|
||||
serverResp, err := cli.get(ctx, "/info", url.Values{}, nil)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
defer ensureReaderClosed(serverResp)
|
||||
|
||||
if err := json.NewDecoder(serverResp.body).Decode(&info); err != nil {
|
||||
return info, fmt.Errorf("Error reading remote info: %v", err)
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
139
vendor/github.com/hyperhq/hyper-api/client/interface.go
generated
vendored
139
vendor/github.com/hyperhq/hyper-api/client/interface.go
generated
vendored
@@ -1,139 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
"github.com/hyperhq/hyper-api/types/container"
|
||||
"github.com/hyperhq/hyper-api/types/filters"
|
||||
"github.com/hyperhq/hyper-api/types/network"
|
||||
"github.com/hyperhq/hyper-api/types/registry"
|
||||
"github.com/hyperhq/libcompose/config"
|
||||
)
|
||||
|
||||
// APIClient is an interface that clients that talk with a docker server must implement.
|
||||
type APIClient interface {
|
||||
ClientVersion() string
|
||||
CheckpointCreate(ctx context.Context, container string, options types.CheckpointCreateOptions) error
|
||||
CheckpointDelete(ctx context.Context, container string, checkpointID string) error
|
||||
CheckpointList(ctx context.Context, container string) ([]types.Checkpoint, error)
|
||||
ContainerAttach(ctx context.Context, container string, options types.ContainerAttachOptions) (types.HijackedResponse, error)
|
||||
ContainerCommit(ctx context.Context, container string, options types.ContainerCommitOptions) (types.ContainerCommitResponse, error)
|
||||
ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (types.ContainerCreateResponse, error)
|
||||
ContainerDiff(ctx context.Context, container string) ([]types.ContainerChange, error)
|
||||
ContainerExecAttach(ctx context.Context, execID string, config types.ExecConfig) (types.HijackedResponse, error)
|
||||
ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (types.ContainerExecCreateResponse, error)
|
||||
ContainerExecInspect(ctx context.Context, execID string) (types.ContainerExecInspect, error)
|
||||
ContainerExecResize(ctx context.Context, execID string, options types.ResizeOptions) error
|
||||
ContainerExecStart(ctx context.Context, execID string, config types.ExecStartCheck) error
|
||||
ContainerExport(ctx context.Context, container string) (io.ReadCloser, error)
|
||||
ContainerInspect(ctx context.Context, container string) (types.ContainerJSON, error)
|
||||
ContainerInspectWithRaw(ctx context.Context, container string, getSize bool) (types.ContainerJSON, []byte, error)
|
||||
ContainerKill(ctx context.Context, container, signal string) error
|
||||
ContainerList(ctx context.Context, options types.ContainerListOptions) ([]types.Container, error)
|
||||
ContainerLogs(ctx context.Context, container string, options types.ContainerLogsOptions) (io.ReadCloser, error)
|
||||
ContainerPause(ctx context.Context, container string) error
|
||||
ContainerRemove(ctx context.Context, container string, options types.ContainerRemoveOptions) ([]string, error)
|
||||
ContainerRename(ctx context.Context, container, newContainerName string) error
|
||||
ContainerResize(ctx context.Context, container string, options types.ResizeOptions) error
|
||||
ContainerRestart(ctx context.Context, container string, timeout int) error
|
||||
ContainerStatPath(ctx context.Context, container, path string) (types.ContainerPathStat, error)
|
||||
ContainerStats(ctx context.Context, container string, stream bool) (io.ReadCloser, error)
|
||||
ContainerStart(ctx context.Context, container string, checkpointID string) error
|
||||
ContainerStop(ctx context.Context, container string, timeout int) error
|
||||
ContainerTop(ctx context.Context, container string, arguments []string) (types.ContainerProcessList, error)
|
||||
ContainerUnpause(ctx context.Context, container string) error
|
||||
ContainerUpdate(ctx context.Context, container string, updateConfig interface{}) error
|
||||
ContainerWait(ctx context.Context, container string) (int, error)
|
||||
CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error)
|
||||
CopyToContainer(ctx context.Context, container, path string, content io.Reader, options types.CopyToContainerOptions) error
|
||||
Events(ctx context.Context, options types.EventsOptions) (io.ReadCloser, error)
|
||||
ImageBuild(ctx context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error)
|
||||
ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error)
|
||||
ImageHistory(ctx context.Context, image string) ([]types.ImageHistory, error)
|
||||
ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error)
|
||||
ImageInspectWithRaw(ctx context.Context, image string, getSize bool) (types.ImageInspect, []byte, error)
|
||||
ImageList(ctx context.Context, options types.ImageListOptions) ([]types.Image, error)
|
||||
ImageLoad(ctx context.Context, input interface{}) (*types.ImageLoadResponse, error)
|
||||
ImageSaveTarFromDaemon(ctx context.Context, imageIDs []string) (io.ReadCloser, error)
|
||||
ImageDiff(ctx context.Context, allLayers [][]string, repoTags [][]string) (*types.ImageDiffResponse, error)
|
||||
ImageLoadLocal(ctx context.Context, quiet bool, size int64) (*types.HijackedResponse, error)
|
||||
ImagePull(ctx context.Context, ref string, options types.ImagePullOptions) (io.ReadCloser, error)
|
||||
ImagePush(ctx context.Context, ref string, options types.ImagePushOptions) (io.ReadCloser, error)
|
||||
ImageRemove(ctx context.Context, image string, options types.ImageRemoveOptions) ([]types.ImageDelete, error)
|
||||
ImageSearch(ctx context.Context, term string, options types.ImageSearchOptions) ([]registry.SearchResult, error)
|
||||
ImageSave(ctx context.Context, images []string) (io.ReadCloser, error)
|
||||
ImageTag(ctx context.Context, image, ref string, options types.ImageTagOptions) error
|
||||
Info(ctx context.Context) (types.Info, error)
|
||||
NetworkConnect(ctx context.Context, networkID, container string, config *network.EndpointSettings) error
|
||||
NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error)
|
||||
NetworkDisconnect(ctx context.Context, networkID, container string, force bool) error
|
||||
NetworkInspect(ctx context.Context, networkID string) (types.NetworkResource, error)
|
||||
NetworkInspectWithRaw(ctx context.Context, networkID string) (types.NetworkResource, []byte, error)
|
||||
NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error)
|
||||
NetworkRemove(ctx context.Context, networkID string) error
|
||||
RegistryLogin(ctx context.Context, auth types.AuthConfig) (types.AuthResponse, error)
|
||||
ServerVersion(ctx context.Context) (types.Version, error)
|
||||
UpdateClientVersion(v string)
|
||||
VolumeCreate(ctx context.Context, options types.VolumeCreateRequest) (types.Volume, error)
|
||||
VolumeInspect(ctx context.Context, volumeID string) (types.Volume, error)
|
||||
VolumeInspectWithRaw(ctx context.Context, volumeID string) (types.Volume, []byte, error)
|
||||
VolumeList(ctx context.Context, filter filters.Args) (types.VolumesListResponse, error)
|
||||
VolumeRemove(ctx context.Context, volumeID string) error
|
||||
VolumeInitialize(ctx context.Context, options types.VolumesInitializeRequest) (types.VolumesInitializeResponse, error)
|
||||
VolumeUploadFinish(ctx context.Context, session string) error
|
||||
|
||||
SnapshotCreate(ctx context.Context, options types.SnapshotCreateRequest) (types.Snapshot, error)
|
||||
SnapshotInspect(ctx context.Context, volumeID string) (types.Snapshot, error)
|
||||
SnapshotList(ctx context.Context, filter filters.Args) (types.SnapshotsListResponse, error)
|
||||
SnapshotRemove(ctx context.Context, id string) error
|
||||
FipAllocate(ctx context.Context, count string) ([]string, error)
|
||||
FipRelease(ctx context.Context, ip string) error
|
||||
FipAttach(ctx context.Context, ip, container string) error
|
||||
FipDetach(ctx context.Context, container string) (string, error)
|
||||
FipList(ctx context.Context, opts types.NetworkListOptions) ([]map[string]string, error)
|
||||
FipName(ctx context.Context, ip, name string) error
|
||||
|
||||
SgCreate(ctx context.Context, name string, data io.Reader) error
|
||||
SgRm(ctx context.Context, name string) error
|
||||
SgUpdate(ctx context.Context, name string, data io.Reader) error
|
||||
SgInspect(ctx context.Context, name string) (*types.SecurityGroup, error)
|
||||
SgLs(ctx context.Context) ([]types.SecurityGroup, error)
|
||||
|
||||
ComposeUp(project string, services []string, c *config.ServiceConfigs, vc map[string]*config.VolumeConfig, nc map[string]*config.NetworkConfig, au map[string]types.AuthConfig, forcerecreate, norecreate bool) (io.ReadCloser, error)
|
||||
ComposeDown(p string, services []string, rmi string, vol, rmorphans bool) (io.ReadCloser, error)
|
||||
ComposeCreate(project string, services []string, c *config.ServiceConfigs, vc map[string]*config.VolumeConfig, nc map[string]*config.NetworkConfig, au map[string]types.AuthConfig, forcerecreate, norecreate bool) (io.ReadCloser, error)
|
||||
ComposeRm(p string, services []string, rmVol bool) (io.ReadCloser, error)
|
||||
ComposeStart(p string, services []string) (io.ReadCloser, error)
|
||||
ComposeStop(p string, services []string, timeout int) (io.ReadCloser, error)
|
||||
ComposeKill(p string, services []string, signal string) (io.ReadCloser, error)
|
||||
|
||||
ServiceCreate(ctx context.Context, sv types.Service) (types.Service, error)
|
||||
ServiceUpdate(ctx context.Context, name string, sv types.ServiceUpdate) (types.Service, error)
|
||||
ServiceDelete(ctx context.Context, id string, keep bool) error
|
||||
ServiceList(ctx context.Context, opts types.ServiceListOptions) ([]types.Service, error)
|
||||
ServiceInspect(ctx context.Context, serviceID string) (types.Service, error)
|
||||
ServiceInspectWithRaw(ctx context.Context, serviceID string) (types.Service, []byte, error)
|
||||
|
||||
CronCreate(ctx context.Context, n string, j types.Cron) (types.Cron, error)
|
||||
CronDelete(ctx context.Context, id string) error
|
||||
CronHistory(ctx context.Context, id, since, tail string) ([]types.Event, error)
|
||||
CronList(ctx context.Context, opts types.CronListOptions) ([]types.Cron, error)
|
||||
CronInspect(ctx context.Context, id string) (types.Cron, error)
|
||||
CronInspectWithRaw(ctx context.Context, serviceID string) (types.Cron, []byte, error)
|
||||
|
||||
FuncCreate(ctx context.Context, opts types.Func) (types.Func, error)
|
||||
FuncUpdate(ctx context.Context, name string, opts types.Func) (types.Func, error)
|
||||
FuncDelete(ctx context.Context, name string) error
|
||||
FuncList(ctx context.Context, opts types.FuncListOptions) ([]types.Func, error)
|
||||
FuncInspect(ctx context.Context, name string) (types.Func, error)
|
||||
FuncInspectWithRaw(ctx context.Context, name string) (types.Func, []byte, error)
|
||||
FuncCall(ctx context.Context, region, name string, stdin io.Reader, sync bool) (io.ReadCloser, error)
|
||||
FuncGet(ctx context.Context, region, callID string, wait bool) (io.ReadCloser, error)
|
||||
FuncLogs(ctx context.Context, region, name, callID string, follow bool, tail string) (io.ReadCloser, error)
|
||||
FuncStatus(ctx context.Context, region, name string) (*types.FuncStatusResponse, error)
|
||||
}
|
||||
|
||||
// Ensure that Client always implements APIClient.
|
||||
var _ APIClient = &Client{}
|
||||
28
vendor/github.com/hyperhq/hyper-api/client/login.go
generated
vendored
28
vendor/github.com/hyperhq/hyper-api/client/login.go
generated
vendored
@@ -1,28 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
)
|
||||
|
||||
// RegistryLogin authenticates the docker server with a given docker registry.
|
||||
// It returns UnauthorizerError when the authentication fails.
|
||||
func (cli *Client) RegistryLogin(ctx context.Context, auth types.AuthConfig) (types.AuthResponse, error) {
|
||||
resp, err := cli.post(ctx, "/auth", url.Values{}, auth, nil)
|
||||
|
||||
if resp != nil && resp.statusCode == http.StatusUnauthorized {
|
||||
return types.AuthResponse{}, unauthorizedError{err}
|
||||
}
|
||||
if err != nil {
|
||||
return types.AuthResponse{}, err
|
||||
}
|
||||
|
||||
var response types.AuthResponse
|
||||
err = json.NewDecoder(resp.body).Decode(&response)
|
||||
ensureReaderClosed(resp)
|
||||
return response, err
|
||||
}
|
||||
18
vendor/github.com/hyperhq/hyper-api/client/network_connect.go
generated
vendored
18
vendor/github.com/hyperhq/hyper-api/client/network_connect.go
generated
vendored
@@ -1,18 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
"github.com/hyperhq/hyper-api/types/network"
|
||||
)
|
||||
|
||||
// NetworkConnect connects a container to an existent network in the docker host.
|
||||
func (cli *Client) NetworkConnect(ctx context.Context, networkID, containerID string, config *network.EndpointSettings) error {
|
||||
nc := types.NetworkConnect{
|
||||
Container: containerID,
|
||||
EndpointConfig: config,
|
||||
}
|
||||
resp, err := cli.post(ctx, "/networks/"+networkID+"/connect", nil, nc, nil)
|
||||
ensureReaderClosed(resp)
|
||||
return err
|
||||
}
|
||||
25
vendor/github.com/hyperhq/hyper-api/client/network_create.go
generated
vendored
25
vendor/github.com/hyperhq/hyper-api/client/network_create.go
generated
vendored
@@ -1,25 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"context"
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
)
|
||||
|
||||
// NetworkCreate creates a new network in the docker host.
|
||||
func (cli *Client) NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) {
|
||||
networkCreateRequest := types.NetworkCreateRequest{
|
||||
NetworkCreate: options,
|
||||
Name: name,
|
||||
}
|
||||
var response types.NetworkCreateResponse
|
||||
serverResp, err := cli.post(ctx, "/networks/create", nil, networkCreateRequest, nil)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
json.NewDecoder(serverResp.body).Decode(&response)
|
||||
ensureReaderClosed(serverResp)
|
||||
return response, err
|
||||
}
|
||||
14
vendor/github.com/hyperhq/hyper-api/client/network_disconnect.go
generated
vendored
14
vendor/github.com/hyperhq/hyper-api/client/network_disconnect.go
generated
vendored
@@ -1,14 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
)
|
||||
|
||||
// NetworkDisconnect disconnects a container from an existent network in the docker host.
|
||||
func (cli *Client) NetworkDisconnect(ctx context.Context, networkID, containerID string, force bool) error {
|
||||
nd := types.NetworkDisconnect{Container: containerID, Force: force}
|
||||
resp, err := cli.post(ctx, "/networks/"+networkID+"/disconnect", nil, nd, nil)
|
||||
ensureReaderClosed(resp)
|
||||
return err
|
||||
}
|
||||
38
vendor/github.com/hyperhq/hyper-api/client/network_inspect.go
generated
vendored
38
vendor/github.com/hyperhq/hyper-api/client/network_inspect.go
generated
vendored
@@ -1,38 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"context"
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
)
|
||||
|
||||
// NetworkInspect returns the information for a specific network configured in the docker host.
|
||||
func (cli *Client) NetworkInspect(ctx context.Context, networkID string) (types.NetworkResource, error) {
|
||||
networkResource, _, err := cli.NetworkInspectWithRaw(ctx, networkID)
|
||||
return networkResource, err
|
||||
}
|
||||
|
||||
// NetworkInspectWithRaw returns the information for a specific network configured in the docker host and it's raw representation.
|
||||
func (cli *Client) NetworkInspectWithRaw(ctx context.Context, networkID string) (types.NetworkResource, []byte, error) {
|
||||
var networkResource types.NetworkResource
|
||||
resp, err := cli.get(ctx, "/networks/"+networkID, nil, nil)
|
||||
if err != nil {
|
||||
if resp.statusCode == http.StatusNotFound {
|
||||
return networkResource, nil, networkNotFoundError{networkID}
|
||||
}
|
||||
return networkResource, nil, err
|
||||
}
|
||||
defer ensureReaderClosed(resp)
|
||||
|
||||
body, err := ioutil.ReadAll(resp.body)
|
||||
if err != nil {
|
||||
return networkResource, nil, err
|
||||
}
|
||||
rdr := bytes.NewReader(body)
|
||||
err = json.NewDecoder(rdr).Decode(&networkResource)
|
||||
return networkResource, body, err
|
||||
}
|
||||
31
vendor/github.com/hyperhq/hyper-api/client/network_list.go
generated
vendored
31
vendor/github.com/hyperhq/hyper-api/client/network_list.go
generated
vendored
@@ -1,31 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/url"
|
||||
|
||||
"context"
|
||||
"github.com/hyperhq/hyper-api/types"
|
||||
"github.com/hyperhq/hyper-api/types/filters"
|
||||
)
|
||||
|
||||
// NetworkList returns the list of networks configured in the docker host.
|
||||
func (cli *Client) NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) {
|
||||
query := url.Values{}
|
||||
if options.Filters.Len() > 0 {
|
||||
filterJSON, err := filters.ToParamWithVersion(cli.version, options.Filters)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query.Set("filters", filterJSON)
|
||||
}
|
||||
var networkResources []types.NetworkResource
|
||||
resp, err := cli.get(ctx, "/networks", query, nil)
|
||||
if err != nil {
|
||||
return networkResources, err
|
||||
}
|
||||
err = json.NewDecoder(resp.body).Decode(&networkResources)
|
||||
ensureReaderClosed(resp)
|
||||
return networkResources, err
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user