Procházet zdrojové kódy

Update docker/distribution dependency

Signed-off-by: Stephen J Day <stephen.day@docker.com>
Stephen J Day před 10 roky
rodič
revize
bfd5202c17

+ 1 - 1
hack/vendor.sh

@@ -32,7 +32,7 @@ clone git github.com/coreos/go-etcd v2.0.0
 clone git github.com/hashicorp/consul v0.5.2
 clone git github.com/hashicorp/consul v0.5.2
 
 
 # get distribution packages
 # get distribution packages
-clone git github.com/docker/distribution b9eeb328080d367dbde850ec6e94f1e4ac2b5efe
+clone git github.com/docker/distribution 419bbc2da637d9b2a812be78ef8436df7caac70d
 
 
 clone git github.com/docker/libcontainer v2.2.1
 clone git github.com/docker/libcontainer v2.2.1
 # libcontainer deps (see src/github.com/docker/libcontainer/update-vendor.sh)
 # libcontainer deps (see src/github.com/docker/libcontainer/update-vendor.sh)

+ 229 - 0
vendor/src/github.com/docker/distribution/registry/api/errcode/errors.go

@@ -0,0 +1,229 @@
+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
+
+// ErrorCode just returns itself
+func (ec ErrorCode) ErrorCode() ErrorCode {
+	return ec
+}
+
+// Error returns the ID/Value
+func (ec ErrorCode) Error() string {
+	return ec.Descriptor().Value
+}
+
+// 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
+}
+
+// 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 {
+	if err, ok := detail.(error); ok {
+		detail = err.Error()
+	}
+
+	return Error{
+		Code:   ec,
+		Detail: detail,
+	}
+}
+
+// Error provides a wrapper around ErrorCode with extra Details provided.
+type Error struct {
+	Code   ErrorCode   `json:"code"`
+	Detail interface{} `json:"detail,omitempty"`
+}
+
+// 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",
+		strings.ToLower(strings.Replace(e.Code.String(), "_", " ", -1)),
+		e.Code.Message())
+}
+
+// Message returned the human-readable error message for this Error
+func (e Error) Message() string {
+	return e.Code.Message()
+}
+
+// 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
+
+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)
+}
+
+// jsonError extends Error with 'Message' so that we can include the
+// error text, just in case the receiver of the JSON doesn't have this
+// particular ErrorCode registered
+type jsonError struct {
+	Code    ErrorCode   `json:"code"`
+	Message string      `json:"message"`
+	Detail  interface{} `json:"detail,omitempty"`
+}
+
+// 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 []jsonError `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)
+
+		}
+
+		tmpErrs.Errors = append(tmpErrs.Errors, jsonError{
+			Code:    err.Code,
+			Message: err.Message(),
+			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 []jsonError
+	}
+
+	if err := json.Unmarshal(data, &tmpErrs); err != nil {
+		return err
+	}
+
+	var newErrs Errors
+	for _, daErr := range tmpErrs.Errors {
+		if daErr.Detail == nil {
+			// 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,
+				Detail: daErr.Detail,
+			})
+		}
+	}
+
+	*errs = newErrs
+	return nil
+}

+ 86 - 0
vendor/src/github.com/docker/distribution/registry/api/errcode/register.go

@@ -0,0 +1,86 @@
+package errcode
+
+import (
+	"fmt"
+	"net/http"
+	"sort"
+	"sync"
+)
+
+var (
+	errorCodeToDescriptors = map[ErrorCode]ErrorDescriptor{}
+	idToDescriptors        = map[string]ErrorDescriptor{}
+	groupToDescriptors     = map[string][]ErrorDescriptor{}
+)
+
+// 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
+var 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,
+})
+
+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
+}

+ 43 - 203
vendor/src/github.com/docker/distribution/registry/api/v2/descriptors.go

@@ -5,6 +5,7 @@ import (
 	"regexp"
 	"regexp"
 
 
 	"github.com/docker/distribution/digest"
 	"github.com/docker/distribution/digest"
+	"github.com/docker/distribution/registry/api/errcode"
 )
 )
 
 
 var (
 var (
@@ -16,12 +17,12 @@ var (
 		Description: `Name of the target repository.`,
 		Description: `Name of the target repository.`,
 	}
 	}
 
 
-	tagParameterDescriptor = ParameterDescriptor{
-		Name:        "tag",
+	referenceParameterDescriptor = ParameterDescriptor{
+		Name:        "reference",
 		Type:        "string",
 		Type:        "string",
 		Format:      TagNameRegexp.String(),
 		Format:      TagNameRegexp.String(),
 		Required:    true,
 		Required:    true,
-		Description: `Tag of the target manifiest.`,
+		Description: `Tag or digest of the target manifest.`,
 	}
 	}
 
 
 	uuidParameterDescriptor = ParameterDescriptor{
 	uuidParameterDescriptor = ParameterDescriptor{
@@ -98,7 +99,7 @@ var (
 				Format:      "<length>",
 				Format:      "<length>",
 			},
 			},
 		},
 		},
-		ErrorCodes: []ErrorCode{
+		ErrorCodes: []errcode.ErrorCode{
 			ErrorCodeUnauthorized,
 			ErrorCodeUnauthorized,
 		},
 		},
 		Body: BodyDescriptor{
 		Body: BodyDescriptor{
@@ -119,7 +120,7 @@ var (
 				Format:      "<length>",
 				Format:      "<length>",
 			},
 			},
 		},
 		},
-		ErrorCodes: []ErrorCode{
+		ErrorCodes: []errcode.ErrorCode{
 			ErrorCodeUnauthorized,
 			ErrorCodeUnauthorized,
 		},
 		},
 		Body: BodyDescriptor{
 		Body: BodyDescriptor{
@@ -171,13 +172,8 @@ const (
 var APIDescriptor = struct {
 var APIDescriptor = struct {
 	// RouteDescriptors provides a list of the routes available in the API.
 	// RouteDescriptors provides a list of the routes available in the API.
 	RouteDescriptors []RouteDescriptor
 	RouteDescriptors []RouteDescriptor
-
-	// ErrorDescriptors provides a list of the error codes and their
-	// associated documentation and metadata.
-	ErrorDescriptors []ErrorDescriptor
 }{
 }{
 	RouteDescriptors: routeDescriptors,
 	RouteDescriptors: routeDescriptors,
-	ErrorDescriptors: errorDescriptors,
 }
 }
 
 
 // RouteDescriptor describes a route specified by name.
 // RouteDescriptor describes a route specified by name.
@@ -275,7 +271,7 @@ type ResponseDescriptor struct {
 
 
 	// ErrorCodes enumerates the error codes that may be returned along with
 	// ErrorCodes enumerates the error codes that may be returned along with
 	// the response.
 	// the response.
-	ErrorCodes []ErrorCode
+	ErrorCodes []errcode.ErrorCode
 
 
 	// Body describes the body of the response, if any.
 	// Body describes the body of the response, if any.
 	Body BodyDescriptor
 	Body BodyDescriptor
@@ -317,30 +313,6 @@ type ParameterDescriptor struct {
 	Examples []string
 	Examples []string
 }
 }
 
 
-// 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
-
-	// HTTPStatusCodes provides a list of status under which this error
-	// condition may arise. If it is empty, the error condition may be seen
-	// for any status code.
-	HTTPStatusCodes []int
-}
-
 var routeDescriptors = []RouteDescriptor{
 var routeDescriptors = []RouteDescriptor{
 	{
 	{
 		Name:        RouteNameBase,
 		Name:        RouteNameBase,
@@ -374,7 +346,7 @@ var routeDescriptors = []RouteDescriptor{
 									ContentType: "application/json; charset=utf-8",
 									ContentType: "application/json; charset=utf-8",
 									Format:      errorsBody,
 									Format:      errorsBody,
 								},
 								},
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeUnauthorized,
 									ErrorCodeUnauthorized,
 								},
 								},
 							},
 							},
@@ -438,7 +410,7 @@ var routeDescriptors = []RouteDescriptor{
 									ContentType: "application/json; charset=utf-8",
 									ContentType: "application/json; charset=utf-8",
 									Format:      errorsBody,
 									Format:      errorsBody,
 								},
 								},
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeNameUnknown,
 									ErrorCodeNameUnknown,
 								},
 								},
 							},
 							},
@@ -449,7 +421,7 @@ var routeDescriptors = []RouteDescriptor{
 									ContentType: "application/json; charset=utf-8",
 									ContentType: "application/json; charset=utf-8",
 									Format:      errorsBody,
 									Format:      errorsBody,
 								},
 								},
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeUnauthorized,
 									ErrorCodeUnauthorized,
 								},
 								},
 							},
 							},
@@ -476,7 +448,7 @@ var routeDescriptors = []RouteDescriptor{
 						},
 						},
 						PathParameters: []ParameterDescriptor{
 						PathParameters: []ParameterDescriptor{
 							nameParameterDescriptor,
 							nameParameterDescriptor,
-							tagParameterDescriptor,
+							referenceParameterDescriptor,
 						},
 						},
 						Successes: []ResponseDescriptor{
 						Successes: []ResponseDescriptor{
 							{
 							{
@@ -495,7 +467,7 @@ var routeDescriptors = []RouteDescriptor{
 							{
 							{
 								Description: "The name or reference was invalid.",
 								Description: "The name or reference was invalid.",
 								StatusCode:  http.StatusBadRequest,
 								StatusCode:  http.StatusBadRequest,
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeNameInvalid,
 									ErrorCodeNameInvalid,
 									ErrorCodeTagInvalid,
 									ErrorCodeTagInvalid,
 								},
 								},
@@ -511,14 +483,14 @@ var routeDescriptors = []RouteDescriptor{
 									ContentType: "application/json; charset=utf-8",
 									ContentType: "application/json; charset=utf-8",
 									Format:      errorsBody,
 									Format:      errorsBody,
 								},
 								},
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeUnauthorized,
 									ErrorCodeUnauthorized,
 								},
 								},
 							},
 							},
 							{
 							{
 								Description: "The named manifest is not known to the registry.",
 								Description: "The named manifest is not known to the registry.",
 								StatusCode:  http.StatusNotFound,
 								StatusCode:  http.StatusNotFound,
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeNameUnknown,
 									ErrorCodeNameUnknown,
 									ErrorCodeManifestUnknown,
 									ErrorCodeManifestUnknown,
 								},
 								},
@@ -542,7 +514,7 @@ var routeDescriptors = []RouteDescriptor{
 						},
 						},
 						PathParameters: []ParameterDescriptor{
 						PathParameters: []ParameterDescriptor{
 							nameParameterDescriptor,
 							nameParameterDescriptor,
-							tagParameterDescriptor,
+							referenceParameterDescriptor,
 						},
 						},
 						Body: BodyDescriptor{
 						Body: BodyDescriptor{
 							ContentType: "application/json; charset=utf-8",
 							ContentType: "application/json; charset=utf-8",
@@ -573,7 +545,7 @@ var routeDescriptors = []RouteDescriptor{
 									ContentType: "application/json; charset=utf-8",
 									ContentType: "application/json; charset=utf-8",
 									Format:      errorsBody,
 									Format:      errorsBody,
 								},
 								},
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeNameInvalid,
 									ErrorCodeNameInvalid,
 									ErrorCodeTagInvalid,
 									ErrorCodeTagInvalid,
 									ErrorCodeManifestInvalid,
 									ErrorCodeManifestInvalid,
@@ -588,7 +560,7 @@ var routeDescriptors = []RouteDescriptor{
 									ContentType: "application/json; charset=utf-8",
 									ContentType: "application/json; charset=utf-8",
 									Format:      errorsBody,
 									Format:      errorsBody,
 								},
 								},
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeUnauthorized,
 									ErrorCodeUnauthorized,
 								},
 								},
 							},
 							},
@@ -596,7 +568,7 @@ var routeDescriptors = []RouteDescriptor{
 								Name:        "Missing Layer(s)",
 								Name:        "Missing Layer(s)",
 								Description: "One or more layers may be missing during a manifest upload. If so, the missing layers will be enumerated in the error response.",
 								Description: "One or more layers may be missing during a manifest upload. If so, the missing layers will be enumerated in the error response.",
 								StatusCode:  http.StatusBadRequest,
 								StatusCode:  http.StatusBadRequest,
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeBlobUnknown,
 									ErrorCodeBlobUnknown,
 								},
 								},
 								Body: BodyDescriptor{
 								Body: BodyDescriptor{
@@ -625,7 +597,7 @@ var routeDescriptors = []RouteDescriptor{
 										Format:      "<length>",
 										Format:      "<length>",
 									},
 									},
 								},
 								},
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeUnauthorized,
 									ErrorCodeUnauthorized,
 								},
 								},
 								Body: BodyDescriptor{
 								Body: BodyDescriptor{
@@ -639,7 +611,7 @@ var routeDescriptors = []RouteDescriptor{
 			},
 			},
 			{
 			{
 				Method:      "DELETE",
 				Method:      "DELETE",
-				Description: "Delete the manifest identified by `name` and `reference` where `reference` can be a tag or digest.",
+				Description: "Delete the manifest identified by `name` and `reference`. Note that a manifest can _only_ be deleted by `digest`.",
 				Requests: []RequestDescriptor{
 				Requests: []RequestDescriptor{
 					{
 					{
 						Headers: []ParameterDescriptor{
 						Headers: []ParameterDescriptor{
@@ -648,7 +620,7 @@ var routeDescriptors = []RouteDescriptor{
 						},
 						},
 						PathParameters: []ParameterDescriptor{
 						PathParameters: []ParameterDescriptor{
 							nameParameterDescriptor,
 							nameParameterDescriptor,
-							tagParameterDescriptor,
+							referenceParameterDescriptor,
 						},
 						},
 						Successes: []ResponseDescriptor{
 						Successes: []ResponseDescriptor{
 							{
 							{
@@ -657,10 +629,10 @@ var routeDescriptors = []RouteDescriptor{
 						},
 						},
 						Failures: []ResponseDescriptor{
 						Failures: []ResponseDescriptor{
 							{
 							{
-								Name:        "Invalid Name or Tag",
-								Description: "The specified `name` or `tag` were invalid and the delete was unable to proceed.",
+								Name:        "Invalid Name or Reference",
+								Description: "The specified `name` or `reference` were invalid and the delete was unable to proceed.",
 								StatusCode:  http.StatusBadRequest,
 								StatusCode:  http.StatusBadRequest,
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeNameInvalid,
 									ErrorCodeNameInvalid,
 									ErrorCodeTagInvalid,
 									ErrorCodeTagInvalid,
 								},
 								},
@@ -680,7 +652,7 @@ var routeDescriptors = []RouteDescriptor{
 										Format:      "<length>",
 										Format:      "<length>",
 									},
 									},
 								},
 								},
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeUnauthorized,
 									ErrorCodeUnauthorized,
 								},
 								},
 								Body: BodyDescriptor{
 								Body: BodyDescriptor{
@@ -690,9 +662,9 @@ var routeDescriptors = []RouteDescriptor{
 							},
 							},
 							{
 							{
 								Name:        "Unknown Manifest",
 								Name:        "Unknown Manifest",
-								Description: "The specified `name` or `tag` are unknown to the registry and the delete was unable to proceed. Clients can assume the manifest was already deleted if this response is returned.",
+								Description: "The specified `name` or `reference` are unknown to the registry and the delete was unable to proceed. Clients can assume the manifest was already deleted if this response is returned.",
 								StatusCode:  http.StatusNotFound,
 								StatusCode:  http.StatusNotFound,
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeNameUnknown,
 									ErrorCodeNameUnknown,
 									ErrorCodeManifestUnknown,
 									ErrorCodeManifestUnknown,
 								},
 								},
@@ -765,7 +737,7 @@ var routeDescriptors = []RouteDescriptor{
 							{
 							{
 								Description: "There was a problem with the request that needs to be addressed by the client, such as an invalid `name` or `tag`.",
 								Description: "There was a problem with the request that needs to be addressed by the client, such as an invalid `name` or `tag`.",
 								StatusCode:  http.StatusBadRequest,
 								StatusCode:  http.StatusBadRequest,
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeNameInvalid,
 									ErrorCodeNameInvalid,
 									ErrorCodeDigestInvalid,
 									ErrorCodeDigestInvalid,
 								},
 								},
@@ -782,7 +754,7 @@ var routeDescriptors = []RouteDescriptor{
 									ContentType: "application/json; charset=utf-8",
 									ContentType: "application/json; charset=utf-8",
 									Format:      errorsBody,
 									Format:      errorsBody,
 								},
 								},
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeNameUnknown,
 									ErrorCodeNameUnknown,
 									ErrorCodeBlobUnknown,
 									ErrorCodeBlobUnknown,
 								},
 								},
@@ -834,7 +806,7 @@ var routeDescriptors = []RouteDescriptor{
 							{
 							{
 								Description: "There was a problem with the request that needs to be addressed by the client, such as an invalid `name` or `tag`.",
 								Description: "There was a problem with the request that needs to be addressed by the client, such as an invalid `name` or `tag`.",
 								StatusCode:  http.StatusBadRequest,
 								StatusCode:  http.StatusBadRequest,
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeNameInvalid,
 									ErrorCodeNameInvalid,
 									ErrorCodeDigestInvalid,
 									ErrorCodeDigestInvalid,
 								},
 								},
@@ -846,7 +818,7 @@ var routeDescriptors = []RouteDescriptor{
 							unauthorizedResponse,
 							unauthorizedResponse,
 							{
 							{
 								StatusCode: http.StatusNotFound,
 								StatusCode: http.StatusNotFound,
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeNameUnknown,
 									ErrorCodeNameUnknown,
 									ErrorCodeBlobUnknown,
 									ErrorCodeBlobUnknown,
 								},
 								},
@@ -926,7 +898,7 @@ var routeDescriptors = []RouteDescriptor{
 							{
 							{
 								Name:       "Invalid Name or Digest",
 								Name:       "Invalid Name or Digest",
 								StatusCode: http.StatusBadRequest,
 								StatusCode: http.StatusBadRequest,
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeDigestInvalid,
 									ErrorCodeDigestInvalid,
 									ErrorCodeNameInvalid,
 									ErrorCodeNameInvalid,
 								},
 								},
@@ -970,7 +942,7 @@ var routeDescriptors = []RouteDescriptor{
 							{
 							{
 								Name:       "Invalid Name or Digest",
 								Name:       "Invalid Name or Digest",
 								StatusCode: http.StatusBadRequest,
 								StatusCode: http.StatusBadRequest,
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeDigestInvalid,
 									ErrorCodeDigestInvalid,
 									ErrorCodeNameInvalid,
 									ErrorCodeNameInvalid,
 								},
 								},
@@ -1024,7 +996,7 @@ var routeDescriptors = []RouteDescriptor{
 							{
 							{
 								Description: "There was an error processing the upload and it must be restarted.",
 								Description: "There was an error processing the upload and it must be restarted.",
 								StatusCode:  http.StatusBadRequest,
 								StatusCode:  http.StatusBadRequest,
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeDigestInvalid,
 									ErrorCodeDigestInvalid,
 									ErrorCodeNameInvalid,
 									ErrorCodeNameInvalid,
 									ErrorCodeBlobUploadInvalid,
 									ErrorCodeBlobUploadInvalid,
@@ -1038,7 +1010,7 @@ var routeDescriptors = []RouteDescriptor{
 							{
 							{
 								Description: "The upload is unknown to the registry. The upload must be restarted.",
 								Description: "The upload is unknown to the registry. The upload must be restarted.",
 								StatusCode:  http.StatusNotFound,
 								StatusCode:  http.StatusNotFound,
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeBlobUploadUnknown,
 									ErrorCodeBlobUploadUnknown,
 								},
 								},
 								Body: BodyDescriptor{
 								Body: BodyDescriptor{
@@ -1096,7 +1068,7 @@ var routeDescriptors = []RouteDescriptor{
 							{
 							{
 								Description: "There was an error processing the upload and it must be restarted.",
 								Description: "There was an error processing the upload and it must be restarted.",
 								StatusCode:  http.StatusBadRequest,
 								StatusCode:  http.StatusBadRequest,
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeDigestInvalid,
 									ErrorCodeDigestInvalid,
 									ErrorCodeNameInvalid,
 									ErrorCodeNameInvalid,
 									ErrorCodeBlobUploadInvalid,
 									ErrorCodeBlobUploadInvalid,
@@ -1110,7 +1082,7 @@ var routeDescriptors = []RouteDescriptor{
 							{
 							{
 								Description: "The upload is unknown to the registry. The upload must be restarted.",
 								Description: "The upload is unknown to the registry. The upload must be restarted.",
 								StatusCode:  http.StatusNotFound,
 								StatusCode:  http.StatusNotFound,
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeBlobUploadUnknown,
 									ErrorCodeBlobUploadUnknown,
 								},
 								},
 								Body: BodyDescriptor{
 								Body: BodyDescriptor{
@@ -1175,7 +1147,7 @@ var routeDescriptors = []RouteDescriptor{
 							{
 							{
 								Description: "There was an error processing the upload and it must be restarted.",
 								Description: "There was an error processing the upload and it must be restarted.",
 								StatusCode:  http.StatusBadRequest,
 								StatusCode:  http.StatusBadRequest,
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeDigestInvalid,
 									ErrorCodeDigestInvalid,
 									ErrorCodeNameInvalid,
 									ErrorCodeNameInvalid,
 									ErrorCodeBlobUploadInvalid,
 									ErrorCodeBlobUploadInvalid,
@@ -1189,7 +1161,7 @@ var routeDescriptors = []RouteDescriptor{
 							{
 							{
 								Description: "The upload is unknown to the registry. The upload must be restarted.",
 								Description: "The upload is unknown to the registry. The upload must be restarted.",
 								StatusCode:  http.StatusNotFound,
 								StatusCode:  http.StatusNotFound,
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeBlobUploadUnknown,
 									ErrorCodeBlobUploadUnknown,
 								},
 								},
 								Body: BodyDescriptor{
 								Body: BodyDescriptor{
@@ -1266,7 +1238,7 @@ var routeDescriptors = []RouteDescriptor{
 							{
 							{
 								Description: "There was an error processing the upload and it must be restarted.",
 								Description: "There was an error processing the upload and it must be restarted.",
 								StatusCode:  http.StatusBadRequest,
 								StatusCode:  http.StatusBadRequest,
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeDigestInvalid,
 									ErrorCodeDigestInvalid,
 									ErrorCodeNameInvalid,
 									ErrorCodeNameInvalid,
 									ErrorCodeBlobUploadInvalid,
 									ErrorCodeBlobUploadInvalid,
@@ -1280,7 +1252,7 @@ var routeDescriptors = []RouteDescriptor{
 							{
 							{
 								Description: "The upload is unknown to the registry. The upload must be restarted.",
 								Description: "The upload is unknown to the registry. The upload must be restarted.",
 								StatusCode:  http.StatusNotFound,
 								StatusCode:  http.StatusNotFound,
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeBlobUploadUnknown,
 									ErrorCodeBlobUploadUnknown,
 								},
 								},
 								Body: BodyDescriptor{
 								Body: BodyDescriptor{
@@ -1321,7 +1293,7 @@ var routeDescriptors = []RouteDescriptor{
 							{
 							{
 								Description: "An error was encountered processing the delete. The client may ignore this error.",
 								Description: "An error was encountered processing the delete. The client may ignore this error.",
 								StatusCode:  http.StatusBadRequest,
 								StatusCode:  http.StatusBadRequest,
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeNameInvalid,
 									ErrorCodeNameInvalid,
 									ErrorCodeBlobUploadInvalid,
 									ErrorCodeBlobUploadInvalid,
 								},
 								},
@@ -1334,7 +1306,7 @@ var routeDescriptors = []RouteDescriptor{
 							{
 							{
 								Description: "The upload is unknown to the registry. The client may ignore this error and assume the upload has been deleted.",
 								Description: "The upload is unknown to the registry. The client may ignore this error and assume the upload has been deleted.",
 								StatusCode:  http.StatusNotFound,
 								StatusCode:  http.StatusNotFound,
-								ErrorCodes: []ErrorCode{
+								ErrorCodes: []errcode.ErrorCode{
 									ErrorCodeBlobUploadUnknown,
 									ErrorCodeBlobUploadUnknown,
 								},
 								},
 								Body: BodyDescriptor{
 								Body: BodyDescriptor{
@@ -1350,143 +1322,11 @@ var routeDescriptors = []RouteDescriptor{
 	},
 	},
 }
 }
 
 
-// ErrorDescriptors provides a list of HTTP API Error codes that may be
-// encountered when interacting with the registry API.
-var errorDescriptors = []ErrorDescriptor{
-	{
-		Code:    ErrorCodeUnknown,
-		Value:   "UNKNOWN",
-		Message: "unknown error",
-		Description: `Generic error returned when the error does not have an
-		API classification.`,
-	},
-	{
-		Code:    ErrorCodeUnsupported,
-		Value:   "UNSUPPORTED",
-		Message: "The operation is unsupported.",
-		Description: `The operation was unsupported due to a missing
-		implementation or invalid set of parameters.`,
-	},
-	{
-		Code:    ErrorCodeUnauthorized,
-		Value:   "UNAUTHORIZED",
-		Message: "access to the requested resource is not authorized",
-		Description: `The access controller denied access for the operation on
-		a resource. Often this will be accompanied by a 401 Unauthorized
-		response status.`,
-	},
-	{
-		Code:    ErrorCodeDigestInvalid,
-		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.`,
-		HTTPStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
-	},
-	{
-		Code:    ErrorCodeSizeInvalid,
-		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.`,
-		HTTPStatusCodes: []int{http.StatusBadRequest},
-	},
-	{
-		Code:    ErrorCodeNameInvalid,
-		Value:   "NAME_INVALID",
-		Message: "invalid repository name",
-		Description: `Invalid repository name encountered either during
-		manifest validation or any API operation.`,
-		HTTPStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
-	},
-	{
-		Code:    ErrorCodeTagInvalid,
-		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.`,
-		HTTPStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
-	},
-	{
-		Code:    ErrorCodeNameUnknown,
-		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.`,
-		HTTPStatusCodes: []int{http.StatusNotFound},
-	},
-	{
-		Code:    ErrorCodeManifestUnknown,
-		Value:   "MANIFEST_UNKNOWN",
-		Message: "manifest unknown",
-		Description: `This error is returned when the manifest, identified by
-		name and tag is unknown to the repository.`,
-		HTTPStatusCodes: []int{http.StatusNotFound},
-	},
-	{
-		Code:    ErrorCodeManifestInvalid,
-		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.`,
-		HTTPStatusCodes: []int{http.StatusBadRequest},
-	},
-	{
-		Code:    ErrorCodeManifestUnverified,
-		Value:   "MANIFEST_UNVERIFIED",
-		Message: "manifest failed signature verification",
-		Description: `During manifest upload, if the manifest fails signature
-		verification, this error will be returned.`,
-		HTTPStatusCodes: []int{http.StatusBadRequest},
-	},
-	{
-		Code:    ErrorCodeBlobUnknown,
-		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.`,
-		HTTPStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
-	},
-
-	{
-		Code:    ErrorCodeBlobUploadUnknown,
-		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.`,
-		HTTPStatusCodes: []int{http.StatusNotFound},
-	},
-	{
-		Code:    ErrorCodeBlobUploadInvalid,
-		Value:   "BLOB_UPLOAD_INVALID",
-		Message: "blob upload invalid",
-		Description: `The blob upload encountered an error and can no
-		longer proceed.`,
-		HTTPStatusCodes: []int{http.StatusNotFound},
-	},
-}
-
-var errorCodeToDescriptors map[ErrorCode]ErrorDescriptor
-var idToDescriptors map[string]ErrorDescriptor
 var routeDescriptorsMap map[string]RouteDescriptor
 var routeDescriptorsMap map[string]RouteDescriptor
 
 
 func init() {
 func init() {
-	errorCodeToDescriptors = make(map[ErrorCode]ErrorDescriptor, len(errorDescriptors))
-	idToDescriptors = make(map[string]ErrorDescriptor, len(errorDescriptors))
 	routeDescriptorsMap = make(map[string]RouteDescriptor, len(routeDescriptors))
 	routeDescriptorsMap = make(map[string]RouteDescriptor, len(routeDescriptors))
 
 
-	for _, descriptor := range errorDescriptors {
-		errorCodeToDescriptors[descriptor.Code] = descriptor
-		idToDescriptors[descriptor.Value] = descriptor
-	}
 	for _, descriptor := range routeDescriptors {
 	for _, descriptor := range routeDescriptors {
 		routeDescriptorsMap[descriptor.Name] = descriptor
 		routeDescriptorsMap[descriptor.Name] = descriptor
 	}
 	}

+ 114 - 154
vendor/src/github.com/docker/distribution/registry/api/v2/errors.go

@@ -1,194 +1,154 @@
 package v2
 package v2
 
 
 import (
 import (
-	"fmt"
-	"strings"
-)
+	"net/http"
 
 
-// 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
+	"github.com/docker/distribution/registry/api/errcode"
+)
 
 
-const (
-	// ErrorCodeUnknown is a catch-all for errors not defined below.
-	ErrorCodeUnknown ErrorCode = iota
+const errGroup = "registry.api.v2"
 
 
+var (
 	// ErrorCodeUnsupported is returned when an operation is not supported.
 	// ErrorCodeUnsupported is returned when an operation is not supported.
-	ErrorCodeUnsupported
+	ErrorCodeUnsupported = errcode.Register(errGroup, errcode.ErrorDescriptor{
+		Value:   "UNSUPPORTED",
+		Message: "The operation is unsupported.",
+		Description: `The operation was unsupported due to a missing
+		implementation or invalid set of parameters.`,
+	})
 
 
 	// ErrorCodeUnauthorized is returned if a request is not authorized.
 	// ErrorCodeUnauthorized is returned if a request is not authorized.
-	ErrorCodeUnauthorized
+	ErrorCodeUnauthorized = errcode.Register(errGroup, errcode.ErrorDescriptor{
+		Value:   "UNAUTHORIZED",
+		Message: "access to the requested resource is not authorized",
+		Description: `The access controller denied access for the operation on
+		a resource. Often this will be accompanied by a 401 Unauthorized
+		response status.`,
+		HTTPStatusCode: http.StatusUnauthorized,
+	})
 
 
 	// ErrorCodeDigestInvalid is returned when uploading a blob if the
 	// ErrorCodeDigestInvalid is returned when uploading a blob if the
 	// provided digest does not match the blob contents.
 	// provided digest does not match the blob contents.
-	ErrorCodeDigestInvalid
+	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 is returned when uploading a blob if the provided
-	// size does not match the content length.
-	ErrorCodeSizeInvalid
+	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
 	// ErrorCodeNameInvalid is returned when the name in the manifest does not
 	// match the provided name.
 	// match the provided name.
-	ErrorCodeNameInvalid
+	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
 	// ErrorCodeTagInvalid is returned when the tag in the manifest does not
 	// match the provided tag.
 	// match the provided tag.
-	ErrorCodeTagInvalid
+	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 when the repository name is not known.
-	ErrorCodeNameUnknown
+	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 returned when image manifest is unknown.
-	ErrorCodeManifestUnknown
+	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,
 	// ErrorCodeManifestInvalid returned when an image manifest is invalid,
 	// typically during a PUT operation. This error encompasses all errors
 	// typically during a PUT operation. This error encompasses all errors
 	// encountered during manifest validation that aren't signature errors.
 	// encountered during manifest validation that aren't signature errors.
-	ErrorCodeManifestInvalid
+	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
 	// ErrorCodeManifestUnverified is returned when the manifest fails
 	// signature verfication.
 	// signature verfication.
-	ErrorCodeManifestUnverified
+	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
 	// ErrorCodeBlobUnknown is returned when a blob is unknown to the
 	// registry. This can happen when the manifest references a nonexistent
 	// registry. This can happen when the manifest references a nonexistent
 	// layer or the result is not found by a blob fetch.
 	// layer or the result is not found by a blob fetch.
-	ErrorCodeBlobUnknown
+	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 is returned when an upload is unknown.
-	ErrorCodeBlobUploadUnknown
+	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 is returned when an upload is invalid.
-	ErrorCodeBlobUploadInvalid
-)
-
-// ParseErrorCode attempts to parse the error code string, returning
-// ErrorCodeUnknown if the error is not known.
-func ParseErrorCode(s string) ErrorCode {
-	desc, ok := idToDescriptors[s]
-
-	if !ok {
-		return ErrorCodeUnknown
-	}
-
-	return desc.Code
-}
-
-// 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
-}
-
-// Error provides a wrapper around ErrorCode with extra Details provided.
-type Error struct {
-	Code    ErrorCode   `json:"code"`
-	Message string      `json:"message,omitempty"`
-	Detail  interface{} `json:"detail,omitempty"`
-}
-
-// Error returns a human readable representation of the error.
-func (e Error) Error() string {
-	return fmt.Sprintf("%s: %s",
-		strings.ToLower(strings.Replace(e.Code.String(), "_", " ", -1)),
-		e.Message)
-}
-
-// Errors provides the envelope for multiple errors and a few sugar methods
-// for use within the application.
-type Errors struct {
-	Errors []Error `json:"errors,omitempty"`
-}
-
-// Push pushes an error on to the error stack, with the optional detail
-// argument. It is a programming error (ie panic) to push more than one
-// detail at a time.
-func (errs *Errors) Push(code ErrorCode, details ...interface{}) {
-	if len(details) > 1 {
-		panic("please specify zero or one detail items for this error")
-	}
-
-	var detail interface{}
-	if len(details) > 0 {
-		detail = details[0]
-	}
-
-	if err, ok := detail.(error); ok {
-		detail = err.Error()
-	}
-
-	errs.PushErr(Error{
-		Code:    code,
-		Message: code.Message(),
-		Detail:  detail,
+	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,
 	})
 	})
-}
-
-// PushErr pushes an error interface onto the error stack.
-func (errs *Errors) PushErr(err error) {
-	switch err.(type) {
-	case Error:
-		errs.Errors = append(errs.Errors, err.(Error))
-	default:
-		errs.Errors = append(errs.Errors, Error{Message: err.Error()})
-	}
-}
-
-func (errs *Errors) Error() string {
-	switch errs.Len() {
-	case 0:
-		return "<nil>"
-	case 1:
-		return errs.Errors[0].Error()
-	default:
-		msg := "errors:\n"
-		for _, err := range errs.Errors {
-			msg += err.Error() + "\n"
-		}
-		return msg
-	}
-}
-
-// Clear clears the errors.
-func (errs *Errors) Clear() {
-	errs.Errors = errs.Errors[:0]
-}
-
-// Len returns the current number of errors.
-func (errs *Errors) Len() int {
-	return len(errs.Errors)
-}
+)

+ 11 - 28
vendor/src/github.com/docker/distribution/registry/api/v2/names.go

@@ -6,19 +6,10 @@ import (
 	"strings"
 	"strings"
 )
 )
 
 
-// TODO(stevvooe): Move these definitions back to an exported package. While
-// they are used with v2 definitions, their relevance expands beyond.
-// "distribution/names" is a candidate package.
+// TODO(stevvooe): Move these definitions to the future "reference" package.
+// While they are used with v2 definitions, their relevance expands beyond.
 
 
 const (
 const (
-	// RepositoryNameComponentMinLength is the minimum number of characters in a
-	// single repository name slash-delimited component
-	RepositoryNameComponentMinLength = 2
-
-	// RepositoryNameMinComponents is the minimum number of slash-delimited
-	// components that a repository name must have
-	RepositoryNameMinComponents = 1
-
 	// RepositoryNameTotalLengthMax is the maximum total number of characters in
 	// RepositoryNameTotalLengthMax is the maximum total number of characters in
 	// a repository name
 	// a repository name
 	RepositoryNameTotalLengthMax = 255
 	RepositoryNameTotalLengthMax = 255
@@ -40,17 +31,13 @@ var RepositoryNameRegexp = regexp.MustCompile(`(?:` + RepositoryNameComponentReg
 // TagNameRegexp matches valid tag names. From docker/docker:graph/tags.go.
 // TagNameRegexp matches valid tag names. From docker/docker:graph/tags.go.
 var TagNameRegexp = regexp.MustCompile(`[\w][\w.-]{0,127}`)
 var TagNameRegexp = regexp.MustCompile(`[\w][\w.-]{0,127}`)
 
 
-// TODO(stevvooe): Contribute these exports back to core, so they are shared.
+// TagNameAnchoredRegexp matches valid tag names, anchored at the start and
+// end of the matched string.
+var TagNameAnchoredRegexp = regexp.MustCompile("^" + TagNameRegexp.String() + "$")
 
 
 var (
 var (
-	// ErrRepositoryNameComponentShort is returned when a repository name
-	// contains a component which is shorter than
-	// RepositoryNameComponentMinLength
-	ErrRepositoryNameComponentShort = fmt.Errorf("repository name component must be %v or more characters", RepositoryNameComponentMinLength)
-
-	// ErrRepositoryNameMissingComponents is returned when a repository name
-	// contains fewer than RepositoryNameMinComponents components
-	ErrRepositoryNameMissingComponents = fmt.Errorf("repository name must have at least %v components", RepositoryNameMinComponents)
+	// ErrRepositoryNameEmpty is returned for empty, invalid repository names.
+	ErrRepositoryNameEmpty = fmt.Errorf("repository name must have at least one component")
 
 
 	// ErrRepositoryNameLong is returned when a repository name is longer than
 	// ErrRepositoryNameLong is returned when a repository name is longer than
 	// RepositoryNameTotalLengthMax
 	// RepositoryNameTotalLengthMax
@@ -76,21 +63,17 @@ var (
 // The result of the production, known as the "namespace", should be limited
 // The result of the production, known as the "namespace", should be limited
 // to 255 characters.
 // to 255 characters.
 func ValidateRepositoryName(name string) error {
 func ValidateRepositoryName(name string) error {
+	if name == "" {
+		return ErrRepositoryNameEmpty
+	}
+
 	if len(name) > RepositoryNameTotalLengthMax {
 	if len(name) > RepositoryNameTotalLengthMax {
 		return ErrRepositoryNameLong
 		return ErrRepositoryNameLong
 	}
 	}
 
 
 	components := strings.Split(name, "/")
 	components := strings.Split(name, "/")
 
 
-	if len(components) < RepositoryNameMinComponents {
-		return ErrRepositoryNameMissingComponents
-	}
-
 	for _, component := range components {
 	for _, component := range components {
-		if len(component) < RepositoryNameComponentMinLength {
-			return ErrRepositoryNameComponentShort
-		}
-
 		if !RepositoryNameComponentAnchoredRegexp.MatchString(component) {
 		if !RepositoryNameComponentAnchoredRegexp.MatchString(component) {
 			return ErrRepositoryNameComponentInvalid
 			return ErrRepositoryNameComponentInvalid
 		}
 		}