Lots of various golint fixes
Changes some names to match go conventions Comments all exported methods Removes dot importsmaster
							parent
							
								
									b5cf681458
								
							
						
					
					
						commit
						88795e0a14
					
				| 
						 | 
					@ -79,7 +79,7 @@ type clientImpl struct {
 | 
				
			||||||
// TODO(bbland): use consistent route generation between server and client
 | 
					// TODO(bbland): use consistent route generation between server and client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (r *clientImpl) GetImageManifest(name, tag string) (*registry.ImageManifest, error) {
 | 
					func (r *clientImpl) GetImageManifest(name, tag string) (*registry.ImageManifest, error) {
 | 
				
			||||||
	response, err := http.Get(r.imageManifestUrl(name, tag))
 | 
						response, err := http.Get(r.imageManifestURL(name, tag))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -100,7 +100,7 @@ func (r *clientImpl) GetImageManifest(name, tag string) (*registry.ImageManifest
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return nil, errors
 | 
							return nil, errors
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return nil, ®istry.UnexpectedHttpStatusError{Status: response.Status}
 | 
							return nil, ®istry.UnexpectedHTTPStatusError{Status: response.Status}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	decoder := json.NewDecoder(response.Body)
 | 
						decoder := json.NewDecoder(response.Body)
 | 
				
			||||||
| 
						 | 
					@ -120,7 +120,7 @@ func (r *clientImpl) PutImageManifest(name, tag string, manifest *registry.Image
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	putRequest, err := http.NewRequest("PUT",
 | 
						putRequest, err := http.NewRequest("PUT",
 | 
				
			||||||
		r.imageManifestUrl(name, tag), bytes.NewReader(manifestBytes))
 | 
							r.imageManifestURL(name, tag), bytes.NewReader(manifestBytes))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -144,13 +144,13 @@ func (r *clientImpl) PutImageManifest(name, tag string, manifest *registry.Image
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return errors
 | 
							return errors
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return ®istry.UnexpectedHttpStatusError{Status: response.Status}
 | 
							return ®istry.UnexpectedHTTPStatusError{Status: response.Status}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (r *clientImpl) DeleteImage(name, tag string) error {
 | 
					func (r *clientImpl) DeleteImage(name, tag string) error {
 | 
				
			||||||
	deleteRequest, err := http.NewRequest("DELETE",
 | 
						deleteRequest, err := http.NewRequest("DELETE",
 | 
				
			||||||
		r.imageManifestUrl(name, tag), nil)
 | 
							r.imageManifestURL(name, tag), nil)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -176,7 +176,7 @@ func (r *clientImpl) DeleteImage(name, tag string) error {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return errors
 | 
							return errors
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return ®istry.UnexpectedHttpStatusError{Status: response.Status}
 | 
							return ®istry.UnexpectedHTTPStatusError{Status: response.Status}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
| 
						 | 
					@ -204,7 +204,7 @@ func (r *clientImpl) ListImageTags(name string) ([]string, error) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return nil, errors
 | 
							return nil, errors
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return nil, ®istry.UnexpectedHttpStatusError{Status: response.Status}
 | 
							return nil, ®istry.UnexpectedHTTPStatusError{Status: response.Status}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tags := struct {
 | 
						tags := struct {
 | 
				
			||||||
| 
						 | 
					@ -258,7 +258,7 @@ func (r *clientImpl) GetImageLayer(name, tarsum string, byteOffset int) (io.Read
 | 
				
			||||||
		return nil, 0, errors
 | 
							return nil, 0, errors
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		response.Body.Close()
 | 
							response.Body.Close()
 | 
				
			||||||
		return nil, 0, ®istry.UnexpectedHttpStatusError{Status: response.Status}
 | 
							return nil, 0, ®istry.UnexpectedHTTPStatusError{Status: response.Status}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -290,7 +290,7 @@ func (r *clientImpl) InitiateLayerUpload(name, tarsum string) (string, error) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return "", errors
 | 
							return "", errors
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return "", ®istry.UnexpectedHttpStatusError{Status: response.Status}
 | 
							return "", ®istry.UnexpectedHTTPStatusError{Status: response.Status}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -316,7 +316,7 @@ func (r *clientImpl) GetLayerUploadStatus(location string) (int, int, error) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return 0, 0, errors
 | 
							return 0, 0, errors
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return 0, 0, ®istry.UnexpectedHttpStatusError{Status: response.Status}
 | 
							return 0, 0, ®istry.UnexpectedHTTPStatusError{Status: response.Status}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -358,7 +358,7 @@ func (r *clientImpl) UploadLayer(location string, layer io.ReadCloser, length in
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return errors
 | 
							return errors
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return ®istry.UnexpectedHttpStatusError{Status: response.Status}
 | 
							return ®istry.UnexpectedHTTPStatusError{Status: response.Status}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -409,7 +409,7 @@ func (r *clientImpl) UploadLayerChunk(location string, layerChunk io.ReadCloser,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return errors
 | 
							return errors
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return ®istry.UnexpectedHttpStatusError{Status: response.Status}
 | 
							return ®istry.UnexpectedHTTPStatusError{Status: response.Status}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -451,7 +451,7 @@ func (r *clientImpl) FinishChunkedLayerUpload(location string, length int, check
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return errors
 | 
							return errors
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return ®istry.UnexpectedHttpStatusError{Status: response.Status}
 | 
							return ®istry.UnexpectedHTTPStatusError{Status: response.Status}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -483,13 +483,13 @@ func (r *clientImpl) CancelLayerUpload(location string) error {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return errors
 | 
							return errors
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return ®istry.UnexpectedHttpStatusError{Status: response.Status}
 | 
							return ®istry.UnexpectedHTTPStatusError{Status: response.Status}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// imageManifestUrl is a helper method for returning the full url to an image
 | 
					// imageManifestURL is a helper method for returning the full url to an image
 | 
				
			||||||
// manifest
 | 
					// manifest
 | 
				
			||||||
func (r *clientImpl) imageManifestUrl(name, tag string) string {
 | 
					func (r *clientImpl) imageManifestURL(name, tag string) string {
 | 
				
			||||||
	return fmt.Sprintf("%s/v2/%s/image/%s", r.Endpoint, name, tag)
 | 
						return fmt.Sprintf("%s/v2/%s/image/%s", r.Endpoint, name, tag)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,11 +7,24 @@ import (
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
 | 
						// RepositoryNameComponentMinLength is the minimum number of characters in a
 | 
				
			||||||
 | 
						// single repository name slash-delimited component
 | 
				
			||||||
	RepositoryNameComponentMinLength = 2
 | 
						RepositoryNameComponentMinLength = 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// RepositoryNameComponentMaxLength is the maximum number of characters in a
 | 
				
			||||||
 | 
						// single repository name slash-delimited component
 | 
				
			||||||
	RepositoryNameComponentMaxLength = 30
 | 
						RepositoryNameComponentMaxLength = 30
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// RepositoryNameMinComponents is the minimum number of slash-delimited
 | 
				
			||||||
 | 
						// components that a repository name must have
 | 
				
			||||||
	RepositoryNameMinComponents = 2
 | 
						RepositoryNameMinComponents = 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// RepositoryNameMaxComponents is the maximum number of slash-delimited
 | 
				
			||||||
 | 
						// components that a repository name must have
 | 
				
			||||||
	RepositoryNameMaxComponents = 5
 | 
						RepositoryNameMaxComponents = 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// RepositoryNameTotalLengthMax is the maximum total number of characters in
 | 
				
			||||||
 | 
						// a repository name
 | 
				
			||||||
	RepositoryNameTotalLengthMax = 255
 | 
						RepositoryNameTotalLengthMax = 255
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,6 +32,9 @@ const (
 | 
				
			||||||
// start with at least two letters or numbers, with following parts able to
 | 
					// start with at least two letters or numbers, with following parts able to
 | 
				
			||||||
// separated by one period, dash or underscore.
 | 
					// separated by one period, dash or underscore.
 | 
				
			||||||
var RepositoryNameComponentRegexp = regexp.MustCompile(`[a-z0-9]+(?:[._-][a-z0-9]+)*`)
 | 
					var RepositoryNameComponentRegexp = regexp.MustCompile(`[a-z0-9]+(?:[._-][a-z0-9]+)*`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RepositoryNameComponentAnchoredRegexp is the version of
 | 
				
			||||||
 | 
					// RepositoryNameComponentRegexp which must completely match the content
 | 
				
			||||||
var RepositoryNameComponentAnchoredRegexp = regexp.MustCompile(`^` + RepositoryNameComponentRegexp.String() + `$`)
 | 
					var RepositoryNameComponentAnchoredRegexp = regexp.MustCompile(`^` + RepositoryNameComponentRegexp.String() + `$`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO(stevvooe): RepositoryName needs to be limited to some fixed length.
 | 
					// TODO(stevvooe): RepositoryName needs to be limited to some fixed length.
 | 
				
			||||||
| 
						 | 
					@ -35,13 +51,30 @@ var TagNameRegexp = regexp.MustCompile(`[\w][\w.-]{0,127}`)
 | 
				
			||||||
// TODO(stevvooe): Contribute these exports back to core, so they are shared.
 | 
					// TODO(stevvooe): Contribute these exports back to core, so they are shared.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
 | 
						// ErrRepositoryNameComponentShort is returned when a repository name
 | 
				
			||||||
 | 
						// contains a component which is shorter than
 | 
				
			||||||
 | 
						// RepositoryNameComponentMinLength
 | 
				
			||||||
	ErrRepositoryNameComponentShort = fmt.Errorf("respository name component must be %v or more characters", RepositoryNameComponentMinLength)
 | 
						ErrRepositoryNameComponentShort = fmt.Errorf("respository name component must be %v or more characters", RepositoryNameComponentMinLength)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ErrRepositoryNameComponentLong is returned when a repository name
 | 
				
			||||||
 | 
						// contains a component which is longer than
 | 
				
			||||||
 | 
						// RepositoryNameComponentMaxLength
 | 
				
			||||||
	ErrRepositoryNameComponentLong = fmt.Errorf("respository name component must be %v characters or less", RepositoryNameComponentMaxLength)
 | 
						ErrRepositoryNameComponentLong = fmt.Errorf("respository name component must be %v characters or less", RepositoryNameComponentMaxLength)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ErrRepositoryNameMissingComponents is returned when a repository name
 | 
				
			||||||
 | 
						// contains fewer than RepositoryNameMinComponents components
 | 
				
			||||||
	ErrRepositoryNameMissingComponents = fmt.Errorf("repository name must have at least %v components", RepositoryNameMinComponents)
 | 
						ErrRepositoryNameMissingComponents = fmt.Errorf("repository name must have at least %v components", RepositoryNameMinComponents)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ErrRepositoryNameTooManyComponents is returned when a repository name
 | 
				
			||||||
 | 
						// contains more than RepositoryNameMaxComponents components
 | 
				
			||||||
	ErrRepositoryNameTooManyComponents = fmt.Errorf("repository name %v or less components", RepositoryNameMaxComponents)
 | 
						ErrRepositoryNameTooManyComponents = fmt.Errorf("repository name %v or less components", RepositoryNameMaxComponents)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ErrRepositoryNameLong is returned when a repository name is longer than
 | 
				
			||||||
 | 
						// RepositoryNameTotalLengthMax
 | 
				
			||||||
	ErrRepositoryNameLong = fmt.Errorf("repository name must not be more than %v characters", RepositoryNameTotalLengthMax)
 | 
						ErrRepositoryNameLong = fmt.Errorf("repository name must not be more than %v characters", RepositoryNameTotalLengthMax)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ErrRepositoryNameComponentInvalid is returned when a repository name does
 | 
				
			||||||
 | 
						// not match RepositoryNameComponentRegexp
 | 
				
			||||||
	ErrRepositoryNameComponentInvalid = fmt.Errorf("repository name component must match %q", RepositoryNameComponentRegexp.String())
 | 
						ErrRepositoryNameComponentInvalid = fmt.Errorf("repository name component must match %q", RepositoryNameComponentRegexp.String())
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,6 +25,8 @@ type TarSumInfo struct {
 | 
				
			||||||
	Digest string
 | 
						Digest string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// InvalidTarSumError provides informations about a TarSum that cannot be parsed
 | 
				
			||||||
 | 
					// by ParseTarSum.
 | 
				
			||||||
type InvalidTarSumError struct {
 | 
					type InvalidTarSumError struct {
 | 
				
			||||||
	TarSum string
 | 
						TarSum string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,9 +23,9 @@ type Configuration struct {
 | 
				
			||||||
	Storage Storage `yaml:"storage"`
 | 
						Storage Storage `yaml:"storage"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// v_0_1_Configuration is a Version 0.1 Configuration struct
 | 
					// v0_1Configuration is a Version 0.1 Configuration struct
 | 
				
			||||||
// This is currently aliased to Configuration, as it is the current version
 | 
					// This is currently aliased to Configuration, as it is the current version
 | 
				
			||||||
type v_0_1_Configuration Configuration
 | 
					type v0_1Configuration Configuration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Version is a major/minor version pair of the form Major.Minor
 | 
					// Version is a major/minor version pair of the form Major.Minor
 | 
				
			||||||
// Major version upgrades indicate structure or type changes
 | 
					// Major version upgrades indicate structure or type changes
 | 
				
			||||||
| 
						 | 
					@ -195,7 +195,7 @@ func Parse(in []byte) (*Configuration, error) {
 | 
				
			||||||
	// Parse the remainder of the configuration depending on the provided version
 | 
						// Parse the remainder of the configuration depending on the provided version
 | 
				
			||||||
	switch untypedConfig.Version {
 | 
						switch untypedConfig.Version {
 | 
				
			||||||
	case "0.1":
 | 
						case "0.1":
 | 
				
			||||||
		config, err = parseV_0_1_Registry(in)
 | 
							config, err = parseV0_1Registry(in)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -206,11 +206,11 @@ func Parse(in []byte) (*Configuration, error) {
 | 
				
			||||||
	return config, nil
 | 
						return config, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// parseV_0_1_Registry parses a registry Configuration for Version 0.1
 | 
					// parseV0_1Registry parses a registry Configuration for Version 0.1
 | 
				
			||||||
func parseV_0_1_Registry(in []byte) (*Configuration, error) {
 | 
					func parseV0_1Registry(in []byte) (*Configuration, error) {
 | 
				
			||||||
	envMap := getEnvMap()
 | 
						envMap := getEnvMap()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var config v_0_1_Configuration
 | 
						var config v0_1Configuration
 | 
				
			||||||
	err := yaml.Unmarshal(in, &config)
 | 
						err := yaml.Unmarshal(in, &config)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@ import (
 | 
				
			||||||
// Hook up gocheck into the "go test" runner
 | 
					// Hook up gocheck into the "go test" runner
 | 
				
			||||||
func Test(t *testing.T) { TestingT(t) }
 | 
					func Test(t *testing.T) { TestingT(t) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// configStruct is a canonical example configuration, which should map to configYamlV_0_1
 | 
					// configStruct is a canonical example configuration, which should map to configYamlV0_1
 | 
				
			||||||
var configStruct = Configuration{
 | 
					var configStruct = Configuration{
 | 
				
			||||||
	Version:  "0.1",
 | 
						Version:  "0.1",
 | 
				
			||||||
	Loglevel: "info",
 | 
						Loglevel: "info",
 | 
				
			||||||
| 
						 | 
					@ -31,8 +31,8 @@ var configStruct = Configuration{
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// configYamlV_0_1 is a Version 0.1 yaml document representing configStruct
 | 
					// configYamlV0_1 is a Version 0.1 yaml document representing configStruct
 | 
				
			||||||
var configYamlV_0_1 = `
 | 
					var configYamlV0_1 = `
 | 
				
			||||||
version: 0.1
 | 
					version: 0.1
 | 
				
			||||||
loglevel: info
 | 
					loglevel: info
 | 
				
			||||||
storage:
 | 
					storage:
 | 
				
			||||||
| 
						 | 
					@ -48,9 +48,9 @@ storage:
 | 
				
			||||||
    port: ~
 | 
					    port: ~
 | 
				
			||||||
`
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// inmemoryConfigYamlV_0_1 is a Version 0.1 yaml document specifying an inmemory storage driver with
 | 
					// inmemoryConfigYamlV0_1 is a Version 0.1 yaml document specifying an inmemory storage driver with
 | 
				
			||||||
// no parameters
 | 
					// no parameters
 | 
				
			||||||
var inmemoryConfigYamlV_0_1 = `
 | 
					var inmemoryConfigYamlV0_1 = `
 | 
				
			||||||
version: 0.1
 | 
					version: 0.1
 | 
				
			||||||
loglevel: info
 | 
					loglevel: info
 | 
				
			||||||
storage: inmemory
 | 
					storage: inmemory
 | 
				
			||||||
| 
						 | 
					@ -77,9 +77,9 @@ func (suite *ConfigSuite) TestMarshalRoundtrip(c *C) {
 | 
				
			||||||
	c.Assert(config, DeepEquals, suite.expectedConfig)
 | 
						c.Assert(config, DeepEquals, suite.expectedConfig)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TestParseSimple validates that configYamlV_0_1 can be parsed into a struct matching configStruct
 | 
					// TestParseSimple validates that configYamlV0_1 can be parsed into a struct matching configStruct
 | 
				
			||||||
func (suite *ConfigSuite) TestParseSimple(c *C) {
 | 
					func (suite *ConfigSuite) TestParseSimple(c *C) {
 | 
				
			||||||
	config, err := Parse([]byte(configYamlV_0_1))
 | 
						config, err := Parse([]byte(configYamlV0_1))
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, IsNil)
 | 
				
			||||||
	c.Assert(config, DeepEquals, suite.expectedConfig)
 | 
						c.Assert(config, DeepEquals, suite.expectedConfig)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -89,7 +89,7 @@ func (suite *ConfigSuite) TestParseSimple(c *C) {
 | 
				
			||||||
func (suite *ConfigSuite) TestParseInmemory(c *C) {
 | 
					func (suite *ConfigSuite) TestParseInmemory(c *C) {
 | 
				
			||||||
	suite.expectedConfig.Storage = Storage{"inmemory": Parameters{}}
 | 
						suite.expectedConfig.Storage = Storage{"inmemory": Parameters{}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	config, err := Parse([]byte(inmemoryConfigYamlV_0_1))
 | 
						config, err := Parse([]byte(inmemoryConfigYamlV0_1))
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, IsNil)
 | 
				
			||||||
	c.Assert(config, DeepEquals, suite.expectedConfig)
 | 
						c.Assert(config, DeepEquals, suite.expectedConfig)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -100,7 +100,7 @@ func (suite *ConfigSuite) TestParseWithSameEnvStorage(c *C) {
 | 
				
			||||||
	os.Setenv("REGISTRY_STORAGE", "s3")
 | 
						os.Setenv("REGISTRY_STORAGE", "s3")
 | 
				
			||||||
	os.Setenv("REGISTRY_STORAGE_S3_REGION", "us-east-1")
 | 
						os.Setenv("REGISTRY_STORAGE_S3_REGION", "us-east-1")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	config, err := Parse([]byte(configYamlV_0_1))
 | 
						config, err := Parse([]byte(configYamlV0_1))
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, IsNil)
 | 
				
			||||||
	c.Assert(config, DeepEquals, suite.expectedConfig)
 | 
						c.Assert(config, DeepEquals, suite.expectedConfig)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -117,7 +117,7 @@ func (suite *ConfigSuite) TestParseWithDifferentEnvStorageParams(c *C) {
 | 
				
			||||||
	os.Setenv("REGISTRY_STORAGE_S3_SECURE", "true")
 | 
						os.Setenv("REGISTRY_STORAGE_S3_SECURE", "true")
 | 
				
			||||||
	os.Setenv("REGISTRY_STORAGE_S3_NEWPARAM", "some Value")
 | 
						os.Setenv("REGISTRY_STORAGE_S3_NEWPARAM", "some Value")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	config, err := Parse([]byte(configYamlV_0_1))
 | 
						config, err := Parse([]byte(configYamlV0_1))
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, IsNil)
 | 
				
			||||||
	c.Assert(config, DeepEquals, suite.expectedConfig)
 | 
						c.Assert(config, DeepEquals, suite.expectedConfig)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -129,7 +129,7 @@ func (suite *ConfigSuite) TestParseWithDifferentEnvStorageType(c *C) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	os.Setenv("REGISTRY_STORAGE", "inmemory")
 | 
						os.Setenv("REGISTRY_STORAGE", "inmemory")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	config, err := Parse([]byte(configYamlV_0_1))
 | 
						config, err := Parse([]byte(configYamlV0_1))
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, IsNil)
 | 
				
			||||||
	c.Assert(config, DeepEquals, suite.expectedConfig)
 | 
						c.Assert(config, DeepEquals, suite.expectedConfig)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -144,7 +144,7 @@ func (suite *ConfigSuite) TestParseWithDifferentEnvStorageTypeAndParams(c *C) {
 | 
				
			||||||
	os.Setenv("REGISTRY_STORAGE", "filesystem")
 | 
						os.Setenv("REGISTRY_STORAGE", "filesystem")
 | 
				
			||||||
	os.Setenv("REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY", "/tmp/testroot")
 | 
						os.Setenv("REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY", "/tmp/testroot")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	config, err := Parse([]byte(configYamlV_0_1))
 | 
						config, err := Parse([]byte(configYamlV0_1))
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, IsNil)
 | 
				
			||||||
	c.Assert(config, DeepEquals, suite.expectedConfig)
 | 
						c.Assert(config, DeepEquals, suite.expectedConfig)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -154,7 +154,7 @@ func (suite *ConfigSuite) TestParseWithDifferentEnvStorageTypeAndParams(c *C) {
 | 
				
			||||||
func (suite *ConfigSuite) TestParseWithSameEnvLoglevel(c *C) {
 | 
					func (suite *ConfigSuite) TestParseWithSameEnvLoglevel(c *C) {
 | 
				
			||||||
	os.Setenv("REGISTRY_LOGLEVEL", "info")
 | 
						os.Setenv("REGISTRY_LOGLEVEL", "info")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	config, err := Parse([]byte(configYamlV_0_1))
 | 
						config, err := Parse([]byte(configYamlV0_1))
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, IsNil)
 | 
				
			||||||
	c.Assert(config, DeepEquals, suite.expectedConfig)
 | 
						c.Assert(config, DeepEquals, suite.expectedConfig)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -166,7 +166,7 @@ func (suite *ConfigSuite) TestParseWithDifferentEnvLoglevel(c *C) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	os.Setenv("REGISTRY_LOGLEVEL", "error")
 | 
						os.Setenv("REGISTRY_LOGLEVEL", "error")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	config, err := Parse([]byte(configYamlV_0_1))
 | 
						config, err := Parse([]byte(configYamlV0_1))
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, IsNil)
 | 
				
			||||||
	c.Assert(config, DeepEquals, suite.expectedConfig)
 | 
						c.Assert(config, DeepEquals, suite.expectedConfig)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										54
									
								
								errors.go
								
								
								
								
							
							
						
						
									
										54
									
								
								errors.go
								
								
								
								
							| 
						 | 
					@ -10,18 +10,43 @@ import (
 | 
				
			||||||
type ErrorCode int
 | 
					type ErrorCode int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
 | 
						// ErrorCodeUnknown is a catch-all for errors not defined below.
 | 
				
			||||||
	ErrorCodeUnknown ErrorCode = iota
 | 
						ErrorCodeUnknown ErrorCode = iota
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// The following errors can happen during a layer upload.
 | 
						// The following errors can happen during a layer upload.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ErrorCodeInvalidChecksum is returned when uploading a layer if the
 | 
				
			||||||
 | 
						// provided checksum does not match the layer contents.
 | 
				
			||||||
	ErrorCodeInvalidChecksum
 | 
						ErrorCodeInvalidChecksum
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ErrorCodeInvalidLength is returned when uploading a layer if the provided
 | 
				
			||||||
 | 
						// length does not match the content length.
 | 
				
			||||||
	ErrorCodeInvalidLength
 | 
						ErrorCodeInvalidLength
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ErrorCodeInvalidTarsum is returned when the provided tarsum does not
 | 
				
			||||||
 | 
						// match the computed tarsum of the contents.
 | 
				
			||||||
	ErrorCodeInvalidTarsum
 | 
						ErrorCodeInvalidTarsum
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// The following errors can happen during manifest upload.
 | 
						// The following errors can happen during manifest upload.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ErrorCodeInvalidName is returned when the name in the manifest does not
 | 
				
			||||||
 | 
						// match the provided name.
 | 
				
			||||||
	ErrorCodeInvalidName
 | 
						ErrorCodeInvalidName
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ErrorCodeInvalidTag is returned when the tag in the manifest does not
 | 
				
			||||||
 | 
						// match the provided tag.
 | 
				
			||||||
	ErrorCodeInvalidTag
 | 
						ErrorCodeInvalidTag
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ErrorCodeUnverifiedManifest is returned when the manifest fails signature
 | 
				
			||||||
 | 
						// validation.
 | 
				
			||||||
	ErrorCodeUnverifiedManifest
 | 
						ErrorCodeUnverifiedManifest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ErrorCodeUnknownLayer is returned when the manifest references a
 | 
				
			||||||
 | 
						// nonexistent layer.
 | 
				
			||||||
	ErrorCodeUnknownLayer
 | 
						ErrorCodeUnknownLayer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ErrorCodeUntrustedSignature is returned when the manifest is signed by an
 | 
				
			||||||
 | 
						// untrusted source.
 | 
				
			||||||
	ErrorCodeUntrustedSignature
 | 
						ErrorCodeUntrustedSignature
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -83,6 +108,7 @@ func (ec ErrorCode) String() string {
 | 
				
			||||||
	return s
 | 
						return s
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Message returned the human-readable error message for this error code.
 | 
				
			||||||
func (ec ErrorCode) Message() string {
 | 
					func (ec ErrorCode) Message() string {
 | 
				
			||||||
	m, ok := errorCodesMessages[ec]
 | 
						m, ok := errorCodesMessages[ec]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -93,16 +119,20 @@ func (ec ErrorCode) Message() string {
 | 
				
			||||||
	return m
 | 
						return m
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MarshalText encodes the receiver into UTF-8-encoded text and returns the
 | 
				
			||||||
 | 
					// result.
 | 
				
			||||||
func (ec ErrorCode) MarshalText() (text []byte, err error) {
 | 
					func (ec ErrorCode) MarshalText() (text []byte, err error) {
 | 
				
			||||||
	return []byte(ec.String()), nil
 | 
						return []byte(ec.String()), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// UnmarshalText decodes the form generated by MarshalText.
 | 
				
			||||||
func (ec *ErrorCode) UnmarshalText(text []byte) error {
 | 
					func (ec *ErrorCode) UnmarshalText(text []byte) error {
 | 
				
			||||||
	*ec = stringToErrorCode[string(text)]
 | 
						*ec = stringToErrorCode[string(text)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Error provides a wrapper around ErrorCode with extra Details provided.
 | 
				
			||||||
type Error struct {
 | 
					type Error struct {
 | 
				
			||||||
	Code    ErrorCode   `json:"code,omitempty"`
 | 
						Code    ErrorCode   `json:"code,omitempty"`
 | 
				
			||||||
	Message string      `json:"message,omitempty"`
 | 
						Message string      `json:"message,omitempty"`
 | 
				
			||||||
| 
						 | 
					@ -173,7 +203,7 @@ type DetailUnknownLayer struct {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RepositoryNotFoundError is returned when making an operation against a
 | 
					// RepositoryNotFoundError is returned when making an operation against a
 | 
				
			||||||
// repository that does not exist in the registry
 | 
					// repository that does not exist in the registry.
 | 
				
			||||||
type RepositoryNotFoundError struct {
 | 
					type RepositoryNotFoundError struct {
 | 
				
			||||||
	Name string
 | 
						Name string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -183,7 +213,7 @@ func (e *RepositoryNotFoundError) Error() string {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ImageManifestNotFoundError is returned when making an operation against a
 | 
					// ImageManifestNotFoundError is returned when making an operation against a
 | 
				
			||||||
// given image manifest that does not exist in the registry
 | 
					// given image manifest that does not exist in the registry.
 | 
				
			||||||
type ImageManifestNotFoundError struct {
 | 
					type ImageManifestNotFoundError struct {
 | 
				
			||||||
	Name string
 | 
						Name string
 | 
				
			||||||
	Tag  string
 | 
						Tag  string
 | 
				
			||||||
| 
						 | 
					@ -195,7 +225,7 @@ func (e *ImageManifestNotFoundError) Error() string {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// LayerAlreadyExistsError is returned when attempting to create a new layer
 | 
					// LayerAlreadyExistsError is returned when attempting to create a new layer
 | 
				
			||||||
// that already exists in the registry
 | 
					// that already exists in the registry.
 | 
				
			||||||
type LayerAlreadyExistsError struct {
 | 
					type LayerAlreadyExistsError struct {
 | 
				
			||||||
	Name   string
 | 
						Name   string
 | 
				
			||||||
	TarSum string
 | 
						TarSum string
 | 
				
			||||||
| 
						 | 
					@ -207,7 +237,7 @@ func (e *LayerAlreadyExistsError) Error() string {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// LayerNotFoundError is returned when making an operation against a given image
 | 
					// LayerNotFoundError is returned when making an operation against a given image
 | 
				
			||||||
// layer that does not exist in the registry
 | 
					// layer that does not exist in the registry.
 | 
				
			||||||
type LayerNotFoundError struct {
 | 
					type LayerNotFoundError struct {
 | 
				
			||||||
	Name   string
 | 
						Name   string
 | 
				
			||||||
	TarSum string
 | 
						TarSum string
 | 
				
			||||||
| 
						 | 
					@ -221,7 +251,7 @@ func (e *LayerNotFoundError) Error() string {
 | 
				
			||||||
// LayerUploadNotFoundError is returned when making a layer upload operation
 | 
					// LayerUploadNotFoundError is returned when making a layer upload operation
 | 
				
			||||||
// against an invalid layer upload location url
 | 
					// against an invalid layer upload location url
 | 
				
			||||||
// This may be the result of using a cancelled, completed, or stale upload
 | 
					// This may be the result of using a cancelled, completed, or stale upload
 | 
				
			||||||
// locationn
 | 
					// location.
 | 
				
			||||||
type LayerUploadNotFoundError struct {
 | 
					type LayerUploadNotFoundError struct {
 | 
				
			||||||
	Location string
 | 
						Location string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -232,9 +262,9 @@ func (e *LayerUploadNotFoundError) Error() string {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// LayerUploadInvalidRangeError is returned when attempting to upload an image
 | 
					// LayerUploadInvalidRangeError is returned when attempting to upload an image
 | 
				
			||||||
// layer chunk that is out of order
 | 
					// layer chunk that is out of order.
 | 
				
			||||||
// This provides the known LayerSize and LastValidRange which can be used to
 | 
					// This provides the known LayerSize and LastValidRange which can be used to
 | 
				
			||||||
// resume the upload
 | 
					// resume the upload.
 | 
				
			||||||
type LayerUploadInvalidRangeError struct {
 | 
					type LayerUploadInvalidRangeError struct {
 | 
				
			||||||
	Location       string
 | 
						Location       string
 | 
				
			||||||
	LastValidRange int
 | 
						LastValidRange int
 | 
				
			||||||
| 
						 | 
					@ -247,12 +277,12 @@ func (e *LayerUploadInvalidRangeError) Error() string {
 | 
				
			||||||
		e.Location, e.LastValidRange, e.LayerSize)
 | 
							e.Location, e.LastValidRange, e.LayerSize)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UnexpectedHttpStatusError is returned when an unexpected http status is
 | 
					// UnexpectedHTTPStatusError is returned when an unexpected HTTP status is
 | 
				
			||||||
// returned when making a registry api call
 | 
					// returned when making a registry api call.
 | 
				
			||||||
type UnexpectedHttpStatusError struct {
 | 
					type UnexpectedHTTPStatusError struct {
 | 
				
			||||||
	Status string
 | 
						Status string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (e *UnexpectedHttpStatusError) Error() string {
 | 
					func (e *UnexpectedHTTPStatusError) Error() string {
 | 
				
			||||||
	return fmt.Sprintf("Received unexpected http status: %s", e.Status)
 | 
						return fmt.Sprintf("Received unexpected HTTP status: %s", e.Status)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,6 +36,7 @@ type ImageManifest struct {
 | 
				
			||||||
// imageManifest is used to avoid recursion in unmarshaling
 | 
					// imageManifest is used to avoid recursion in unmarshaling
 | 
				
			||||||
type imageManifest ImageManifest
 | 
					type imageManifest ImageManifest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// UnmarshalJSON populates a new ImageManifest struct from JSON data.
 | 
				
			||||||
func (m *ImageManifest) UnmarshalJSON(b []byte) error {
 | 
					func (m *ImageManifest) UnmarshalJSON(b []byte) error {
 | 
				
			||||||
	var manifest imageManifest
 | 
						var manifest imageManifest
 | 
				
			||||||
	err := json.Unmarshal(b, &manifest)
 | 
						err := json.Unmarshal(b, &manifest)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,3 @@
 | 
				
			||||||
// This package contains storage services for use in the registry application.
 | 
					// Package storage contains storage services for use in the registry
 | 
				
			||||||
// It should be considered an internal package, as of Go 1.4.
 | 
					// application. It should be considered an internal package, as of Go 1.4.
 | 
				
			||||||
package storage
 | 
					package storage
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,11 +11,11 @@ import (
 | 
				
			||||||
	"github.com/docker/docker-registry/storagedriver/factory"
 | 
						"github.com/docker/docker-registry/storagedriver/factory"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const DriverName = "filesystem"
 | 
					const driverName = "filesystem"
 | 
				
			||||||
const DefaultRootDirectory = "/tmp/registry/storage"
 | 
					const defaultRootDirectory = "/tmp/registry/storage"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	factory.Register(DriverName, &filesystemDriverFactory{})
 | 
						factory.Register(driverName, &filesystemDriverFactory{})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// filesystemDriverFactory implements the factory.StorageDriverFactory interface
 | 
					// filesystemDriverFactory implements the factory.StorageDriverFactory interface
 | 
				
			||||||
| 
						 | 
					@ -25,17 +25,17 @@ func (factory *filesystemDriverFactory) Create(parameters map[string]string) (st
 | 
				
			||||||
	return FromParameters(parameters), nil
 | 
						return FromParameters(parameters), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// FilesystemDriver is a storagedriver.StorageDriver implementation backed by a local filesystem
 | 
					// Driver is a storagedriver.StorageDriver implementation backed by a local
 | 
				
			||||||
// All provided paths will be subpaths of the RootDirectory
 | 
					// filesystem. All provided paths will be subpaths of the RootDirectory
 | 
				
			||||||
type FilesystemDriver struct {
 | 
					type Driver struct {
 | 
				
			||||||
	rootDirectory string
 | 
						rootDirectory string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// FromParameters constructs a new FilesystemDriver with a given parameters map
 | 
					// FromParameters constructs a new Driver with a given parameters map
 | 
				
			||||||
// Optional Parameters:
 | 
					// Optional Parameters:
 | 
				
			||||||
// - rootdirectory
 | 
					// - rootdirectory
 | 
				
			||||||
func FromParameters(parameters map[string]string) *FilesystemDriver {
 | 
					func FromParameters(parameters map[string]string) *Driver {
 | 
				
			||||||
	var rootDirectory = DefaultRootDirectory
 | 
						var rootDirectory = defaultRootDirectory
 | 
				
			||||||
	if parameters != nil {
 | 
						if parameters != nil {
 | 
				
			||||||
		rootDir, ok := parameters["rootdirectory"]
 | 
							rootDir, ok := parameters["rootdirectory"]
 | 
				
			||||||
		if ok {
 | 
							if ok {
 | 
				
			||||||
| 
						 | 
					@ -45,19 +45,20 @@ func FromParameters(parameters map[string]string) *FilesystemDriver {
 | 
				
			||||||
	return New(rootDirectory)
 | 
						return New(rootDirectory)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// New constructs a new FilesystemDriver with a given rootDirectory
 | 
					// New constructs a new Driver with a given rootDirectory
 | 
				
			||||||
func New(rootDirectory string) *FilesystemDriver {
 | 
					func New(rootDirectory string) *Driver {
 | 
				
			||||||
	return &FilesystemDriver{rootDirectory}
 | 
						return &Driver{rootDirectory}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// subPath returns the absolute path of a key within the FilesystemDriver's storage
 | 
					// subPath returns the absolute path of a key within the Driver's storage
 | 
				
			||||||
func (d *FilesystemDriver) subPath(subPath string) string {
 | 
					func (d *Driver) subPath(subPath string) string {
 | 
				
			||||||
	return path.Join(d.rootDirectory, subPath)
 | 
						return path.Join(d.rootDirectory, subPath)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Implement the storagedriver.StorageDriver interface
 | 
					// Implement the storagedriver.StorageDriver interface
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *FilesystemDriver) GetContent(path string) ([]byte, error) {
 | 
					// GetContent retrieves the content stored at "path" as a []byte.
 | 
				
			||||||
 | 
					func (d *Driver) GetContent(path string) ([]byte, error) {
 | 
				
			||||||
	contents, err := ioutil.ReadFile(d.subPath(path))
 | 
						contents, err := ioutil.ReadFile(d.subPath(path))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, storagedriver.PathNotFoundError{Path: path}
 | 
							return nil, storagedriver.PathNotFoundError{Path: path}
 | 
				
			||||||
| 
						 | 
					@ -65,7 +66,8 @@ func (d *FilesystemDriver) GetContent(path string) ([]byte, error) {
 | 
				
			||||||
	return contents, nil
 | 
						return contents, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *FilesystemDriver) PutContent(subPath string, contents []byte) error {
 | 
					// PutContent stores the []byte content at a location designated by "path".
 | 
				
			||||||
 | 
					func (d *Driver) PutContent(subPath string, contents []byte) error {
 | 
				
			||||||
	fullPath := d.subPath(subPath)
 | 
						fullPath := d.subPath(subPath)
 | 
				
			||||||
	parentDir := path.Dir(fullPath)
 | 
						parentDir := path.Dir(fullPath)
 | 
				
			||||||
	err := os.MkdirAll(parentDir, 0755)
 | 
						err := os.MkdirAll(parentDir, 0755)
 | 
				
			||||||
| 
						 | 
					@ -77,7 +79,9 @@ func (d *FilesystemDriver) PutContent(subPath string, contents []byte) error {
 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *FilesystemDriver) ReadStream(path string, offset uint64) (io.ReadCloser, error) {
 | 
					// ReadStream retrieves an io.ReadCloser for the content stored at "path" with a
 | 
				
			||||||
 | 
					// given byte offset.
 | 
				
			||||||
 | 
					func (d *Driver) ReadStream(path string, offset uint64) (io.ReadCloser, error) {
 | 
				
			||||||
	file, err := os.OpenFile(d.subPath(path), os.O_RDONLY, 0644)
 | 
						file, err := os.OpenFile(d.subPath(path), os.O_RDONLY, 0644)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
| 
						 | 
					@ -95,7 +99,9 @@ func (d *FilesystemDriver) ReadStream(path string, offset uint64) (io.ReadCloser
 | 
				
			||||||
	return file, nil
 | 
						return file, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *FilesystemDriver) WriteStream(subPath string, offset, size uint64, reader io.ReadCloser) error {
 | 
					// WriteStream stores the contents of the provided io.ReadCloser at a location
 | 
				
			||||||
 | 
					// designated by the given path.
 | 
				
			||||||
 | 
					func (d *Driver) WriteStream(subPath string, offset, size uint64, reader io.ReadCloser) error {
 | 
				
			||||||
	defer reader.Close()
 | 
						defer reader.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	resumableOffset, err := d.CurrentSize(subPath)
 | 
						resumableOffset, err := d.CurrentSize(subPath)
 | 
				
			||||||
| 
						 | 
					@ -154,7 +160,9 @@ func (d *FilesystemDriver) WriteStream(subPath string, offset, size uint64, read
 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *FilesystemDriver) CurrentSize(subPath string) (uint64, error) {
 | 
					// CurrentSize retrieves the curernt size in bytes of the object at the given
 | 
				
			||||||
 | 
					// path.
 | 
				
			||||||
 | 
					func (d *Driver) CurrentSize(subPath string) (uint64, error) {
 | 
				
			||||||
	fullPath := d.subPath(subPath)
 | 
						fullPath := d.subPath(subPath)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fileInfo, err := os.Stat(fullPath)
 | 
						fileInfo, err := os.Stat(fullPath)
 | 
				
			||||||
| 
						 | 
					@ -166,7 +174,9 @@ func (d *FilesystemDriver) CurrentSize(subPath string) (uint64, error) {
 | 
				
			||||||
	return uint64(fileInfo.Size()), nil
 | 
						return uint64(fileInfo.Size()), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *FilesystemDriver) List(subPath string) ([]string, error) {
 | 
					// List returns a list of the objects that are direct descendants of the given
 | 
				
			||||||
 | 
					// path.
 | 
				
			||||||
 | 
					func (d *Driver) List(subPath string) ([]string, error) {
 | 
				
			||||||
	subPath = strings.TrimRight(subPath, "/")
 | 
						subPath = strings.TrimRight(subPath, "/")
 | 
				
			||||||
	fullPath := d.subPath(subPath)
 | 
						fullPath := d.subPath(subPath)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -188,12 +198,15 @@ func (d *FilesystemDriver) List(subPath string) ([]string, error) {
 | 
				
			||||||
	return keys, nil
 | 
						return keys, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *FilesystemDriver) Move(sourcePath string, destPath string) error {
 | 
					// Move moves an object stored at sourcePath to destPath, removing the original
 | 
				
			||||||
 | 
					// object.
 | 
				
			||||||
 | 
					func (d *Driver) Move(sourcePath string, destPath string) error {
 | 
				
			||||||
	err := os.Rename(d.subPath(sourcePath), d.subPath(destPath))
 | 
						err := os.Rename(d.subPath(sourcePath), d.subPath(destPath))
 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *FilesystemDriver) Delete(subPath string) error {
 | 
					// Delete recursively deletes all objects stored at "path" and its subpaths.
 | 
				
			||||||
 | 
					func (d *Driver) Delete(subPath string) error {
 | 
				
			||||||
	fullPath := d.subPath(subPath)
 | 
						fullPath := d.subPath(subPath)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err := os.Stat(fullPath)
 | 
						_, err := os.Stat(fullPath)
 | 
				
			||||||
| 
						 | 
					@ -20,5 +20,5 @@ func init() {
 | 
				
			||||||
		return New(rootDirectory), nil
 | 
							return New(rootDirectory), nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	testsuites.RegisterInProcessSuite(filesystemDriverConstructor, testsuites.NeverSkip)
 | 
						testsuites.RegisterInProcessSuite(filesystemDriverConstructor, testsuites.NeverSkip)
 | 
				
			||||||
	testsuites.RegisterIPCSuite(DriverName, map[string]string{"rootdirectory": rootDirectory}, testsuites.NeverSkip)
 | 
						testsuites.RegisterIPCSuite(driverName, map[string]string{"rootdirectory": rootDirectory}, testsuites.NeverSkip)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -13,34 +13,35 @@ import (
 | 
				
			||||||
	"github.com/docker/docker-registry/storagedriver/factory"
 | 
						"github.com/docker/docker-registry/storagedriver/factory"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const DriverName = "inmemory"
 | 
					const driverName = "inmemory"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	factory.Register(DriverName, &inMemoryDriverFactory{})
 | 
						factory.Register(driverName, &inMemoryDriverFactory{})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// inMemoryDriverFacotry implements the factory.StorageDriverFactory interface
 | 
					// inMemoryDriverFacotry implements the factory.StorageDriverFactory interface.
 | 
				
			||||||
type inMemoryDriverFactory struct{}
 | 
					type inMemoryDriverFactory struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (factory *inMemoryDriverFactory) Create(parameters map[string]string) (storagedriver.StorageDriver, error) {
 | 
					func (factory *inMemoryDriverFactory) Create(parameters map[string]string) (storagedriver.StorageDriver, error) {
 | 
				
			||||||
	return New(), nil
 | 
						return New(), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// InMemoryDriver is a storagedriver.StorageDriver implementation backed by a local map
 | 
					// Driver is a storagedriver.StorageDriver implementation backed by a local map.
 | 
				
			||||||
// Intended solely for example and testing purposes
 | 
					// Intended solely for example and testing purposes.
 | 
				
			||||||
type InMemoryDriver struct {
 | 
					type Driver struct {
 | 
				
			||||||
	storage map[string][]byte
 | 
						storage map[string][]byte
 | 
				
			||||||
	mutex   sync.RWMutex
 | 
						mutex   sync.RWMutex
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// New constructs a new InMemoryDriver
 | 
					// New constructs a new Driver.
 | 
				
			||||||
func New() *InMemoryDriver {
 | 
					func New() *Driver {
 | 
				
			||||||
	return &InMemoryDriver{storage: make(map[string][]byte)}
 | 
						return &Driver{storage: make(map[string][]byte)}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Implement the storagedriver.StorageDriver interface
 | 
					// Implement the storagedriver.StorageDriver interface.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *InMemoryDriver) GetContent(path string) ([]byte, error) {
 | 
					// GetContent retrieves the content stored at "path" as a []byte.
 | 
				
			||||||
 | 
					func (d *Driver) GetContent(path string) ([]byte, error) {
 | 
				
			||||||
	d.mutex.RLock()
 | 
						d.mutex.RLock()
 | 
				
			||||||
	defer d.mutex.RUnlock()
 | 
						defer d.mutex.RUnlock()
 | 
				
			||||||
	contents, ok := d.storage[path]
 | 
						contents, ok := d.storage[path]
 | 
				
			||||||
| 
						 | 
					@ -50,14 +51,17 @@ func (d *InMemoryDriver) GetContent(path string) ([]byte, error) {
 | 
				
			||||||
	return contents, nil
 | 
						return contents, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *InMemoryDriver) PutContent(path string, contents []byte) error {
 | 
					// PutContent stores the []byte content at a location designated by "path".
 | 
				
			||||||
 | 
					func (d *Driver) PutContent(path string, contents []byte) error {
 | 
				
			||||||
	d.mutex.Lock()
 | 
						d.mutex.Lock()
 | 
				
			||||||
	defer d.mutex.Unlock()
 | 
						defer d.mutex.Unlock()
 | 
				
			||||||
	d.storage[path] = contents
 | 
						d.storage[path] = contents
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *InMemoryDriver) ReadStream(path string, offset uint64) (io.ReadCloser, error) {
 | 
					// ReadStream retrieves an io.ReadCloser for the content stored at "path" with a
 | 
				
			||||||
 | 
					// given byte offset.
 | 
				
			||||||
 | 
					func (d *Driver) ReadStream(path string, offset uint64) (io.ReadCloser, error) {
 | 
				
			||||||
	d.mutex.RLock()
 | 
						d.mutex.RLock()
 | 
				
			||||||
	defer d.mutex.RUnlock()
 | 
						defer d.mutex.RUnlock()
 | 
				
			||||||
	contents, err := d.GetContent(path)
 | 
						contents, err := d.GetContent(path)
 | 
				
			||||||
| 
						 | 
					@ -73,7 +77,9 @@ func (d *InMemoryDriver) ReadStream(path string, offset uint64) (io.ReadCloser,
 | 
				
			||||||
	return ioutil.NopCloser(bytes.NewReader(buf)), nil
 | 
						return ioutil.NopCloser(bytes.NewReader(buf)), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *InMemoryDriver) WriteStream(path string, offset, size uint64, reader io.ReadCloser) error {
 | 
					// WriteStream stores the contents of the provided io.ReadCloser at a location
 | 
				
			||||||
 | 
					// designated by the given path.
 | 
				
			||||||
 | 
					func (d *Driver) WriteStream(path string, offset, size uint64, reader io.ReadCloser) error {
 | 
				
			||||||
	defer reader.Close()
 | 
						defer reader.Close()
 | 
				
			||||||
	d.mutex.RLock()
 | 
						d.mutex.RLock()
 | 
				
			||||||
	defer d.mutex.RUnlock()
 | 
						defer d.mutex.RUnlock()
 | 
				
			||||||
| 
						 | 
					@ -100,7 +106,9 @@ func (d *InMemoryDriver) WriteStream(path string, offset, size uint64, reader io
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *InMemoryDriver) CurrentSize(path string) (uint64, error) {
 | 
					// CurrentSize retrieves the curernt size in bytes of the object at the given
 | 
				
			||||||
 | 
					// path.
 | 
				
			||||||
 | 
					func (d *Driver) CurrentSize(path string) (uint64, error) {
 | 
				
			||||||
	d.mutex.RLock()
 | 
						d.mutex.RLock()
 | 
				
			||||||
	defer d.mutex.RUnlock()
 | 
						defer d.mutex.RUnlock()
 | 
				
			||||||
	contents, ok := d.storage[path]
 | 
						contents, ok := d.storage[path]
 | 
				
			||||||
| 
						 | 
					@ -110,7 +118,9 @@ func (d *InMemoryDriver) CurrentSize(path string) (uint64, error) {
 | 
				
			||||||
	return uint64(len(contents)), nil
 | 
						return uint64(len(contents)), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *InMemoryDriver) List(path string) ([]string, error) {
 | 
					// List returns a list of the objects that are direct descendants of the given
 | 
				
			||||||
 | 
					// path.
 | 
				
			||||||
 | 
					func (d *Driver) List(path string) ([]string, error) {
 | 
				
			||||||
	subPathMatcher, err := regexp.Compile(fmt.Sprintf("^%s/[^/]+", path))
 | 
						subPathMatcher, err := regexp.Compile(fmt.Sprintf("^%s/[^/]+", path))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
| 
						 | 
					@ -133,7 +143,9 @@ func (d *InMemoryDriver) List(path string) ([]string, error) {
 | 
				
			||||||
	return keys, nil
 | 
						return keys, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *InMemoryDriver) Move(sourcePath string, destPath string) error {
 | 
					// Move moves an object stored at sourcePath to destPath, removing the original
 | 
				
			||||||
 | 
					// object.
 | 
				
			||||||
 | 
					func (d *Driver) Move(sourcePath string, destPath string) error {
 | 
				
			||||||
	d.mutex.Lock()
 | 
						d.mutex.Lock()
 | 
				
			||||||
	defer d.mutex.Unlock()
 | 
						defer d.mutex.Unlock()
 | 
				
			||||||
	contents, ok := d.storage[sourcePath]
 | 
						contents, ok := d.storage[sourcePath]
 | 
				
			||||||
| 
						 | 
					@ -145,10 +157,11 @@ func (d *InMemoryDriver) Move(sourcePath string, destPath string) error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *InMemoryDriver) Delete(path string) error {
 | 
					// Delete recursively deletes all objects stored at "path" and its subpaths.
 | 
				
			||||||
 | 
					func (d *Driver) Delete(path string) error {
 | 
				
			||||||
	d.mutex.Lock()
 | 
						d.mutex.Lock()
 | 
				
			||||||
	defer d.mutex.Unlock()
 | 
						defer d.mutex.Unlock()
 | 
				
			||||||
	subPaths := make([]string, 0)
 | 
						var subPaths []string
 | 
				
			||||||
	for k := range d.storage {
 | 
						for k := range d.storage {
 | 
				
			||||||
		if strings.HasPrefix(k, path) {
 | 
							if strings.HasPrefix(k, path) {
 | 
				
			||||||
			subPaths = append(subPaths, k)
 | 
								subPaths = append(subPaths, k)
 | 
				
			||||||
| 
						 | 
					@ -5,16 +5,17 @@ import (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/docker/docker-registry/storagedriver"
 | 
						"github.com/docker/docker-registry/storagedriver"
 | 
				
			||||||
	"github.com/docker/docker-registry/storagedriver/testsuites"
 | 
						"github.com/docker/docker-registry/storagedriver/testsuites"
 | 
				
			||||||
	. "gopkg.in/check.v1"
 | 
					
 | 
				
			||||||
 | 
						"gopkg.in/check.v1"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Hook up gocheck into the "go test" runner.
 | 
					// Hook up gocheck into the "go test" runner.
 | 
				
			||||||
func Test(t *testing.T) { TestingT(t) }
 | 
					func Test(t *testing.T) { check.TestingT(t) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	inmemoryDriverConstructor := func() (storagedriver.StorageDriver, error) {
 | 
						inmemoryDriverConstructor := func() (storagedriver.StorageDriver, error) {
 | 
				
			||||||
		return New(), nil
 | 
							return New(), nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	testsuites.RegisterInProcessSuite(inmemoryDriverConstructor, testsuites.NeverSkip)
 | 
						testsuites.RegisterInProcessSuite(inmemoryDriverConstructor, testsuites.NeverSkip)
 | 
				
			||||||
	testsuites.RegisterIPCSuite(DriverName, nil, testsuites.NeverSkip)
 | 
						testsuites.RegisterIPCSuite(driverName, nil, testsuites.NeverSkip)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -173,6 +173,7 @@ func (driver *StorageDriverClient) Stop() error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Implement the storagedriver.StorageDriver interface over IPC
 | 
					// Implement the storagedriver.StorageDriver interface over IPC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetContent retrieves the content stored at "path" as a []byte.
 | 
				
			||||||
func (driver *StorageDriverClient) GetContent(path string) ([]byte, error) {
 | 
					func (driver *StorageDriverClient) GetContent(path string) ([]byte, error) {
 | 
				
			||||||
	if err := driver.exited(); err != nil {
 | 
						if err := driver.exited(); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
| 
						 | 
					@ -204,6 +205,7 @@ func (driver *StorageDriverClient) GetContent(path string) ([]byte, error) {
 | 
				
			||||||
	return contents, nil
 | 
						return contents, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PutContent stores the []byte content at a location designated by "path".
 | 
				
			||||||
func (driver *StorageDriverClient) PutContent(path string, contents []byte) error {
 | 
					func (driver *StorageDriverClient) PutContent(path string, contents []byte) error {
 | 
				
			||||||
	if err := driver.exited(); err != nil {
 | 
						if err := driver.exited(); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
| 
						 | 
					@ -230,6 +232,8 @@ func (driver *StorageDriverClient) PutContent(path string, contents []byte) erro
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ReadStream retrieves an io.ReadCloser for the content stored at "path" with a
 | 
				
			||||||
 | 
					// given byte offset.
 | 
				
			||||||
func (driver *StorageDriverClient) ReadStream(path string, offset uint64) (io.ReadCloser, error) {
 | 
					func (driver *StorageDriverClient) ReadStream(path string, offset uint64) (io.ReadCloser, error) {
 | 
				
			||||||
	if err := driver.exited(); err != nil {
 | 
						if err := driver.exited(); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
| 
						 | 
					@ -255,6 +259,8 @@ func (driver *StorageDriverClient) ReadStream(path string, offset uint64) (io.Re
 | 
				
			||||||
	return response.Reader, nil
 | 
						return response.Reader, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// WriteStream stores the contents of the provided io.ReadCloser at a location
 | 
				
			||||||
 | 
					// designated by the given path.
 | 
				
			||||||
func (driver *StorageDriverClient) WriteStream(path string, offset, size uint64, reader io.ReadCloser) error {
 | 
					func (driver *StorageDriverClient) WriteStream(path string, offset, size uint64, reader io.ReadCloser) error {
 | 
				
			||||||
	if err := driver.exited(); err != nil {
 | 
						if err := driver.exited(); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
| 
						 | 
					@ -280,6 +286,8 @@ func (driver *StorageDriverClient) WriteStream(path string, offset, size uint64,
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CurrentSize retrieves the curernt size in bytes of the object at the given
 | 
				
			||||||
 | 
					// path.
 | 
				
			||||||
func (driver *StorageDriverClient) CurrentSize(path string) (uint64, error) {
 | 
					func (driver *StorageDriverClient) CurrentSize(path string) (uint64, error) {
 | 
				
			||||||
	if err := driver.exited(); err != nil {
 | 
						if err := driver.exited(); err != nil {
 | 
				
			||||||
		return 0, err
 | 
							return 0, err
 | 
				
			||||||
| 
						 | 
					@ -305,6 +313,8 @@ func (driver *StorageDriverClient) CurrentSize(path string) (uint64, error) {
 | 
				
			||||||
	return response.Position, nil
 | 
						return response.Position, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// List returns a list of the objects that are direct descendants of the given
 | 
				
			||||||
 | 
					// path.
 | 
				
			||||||
func (driver *StorageDriverClient) List(path string) ([]string, error) {
 | 
					func (driver *StorageDriverClient) List(path string) ([]string, error) {
 | 
				
			||||||
	if err := driver.exited(); err != nil {
 | 
						if err := driver.exited(); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
| 
						 | 
					@ -330,6 +340,8 @@ func (driver *StorageDriverClient) List(path string) ([]string, error) {
 | 
				
			||||||
	return response.Keys, nil
 | 
						return response.Keys, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Move moves an object stored at sourcePath to destPath, removing the original
 | 
				
			||||||
 | 
					// object.
 | 
				
			||||||
func (driver *StorageDriverClient) Move(sourcePath string, destPath string) error {
 | 
					func (driver *StorageDriverClient) Move(sourcePath string, destPath string) error {
 | 
				
			||||||
	if err := driver.exited(); err != nil {
 | 
						if err := driver.exited(); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
| 
						 | 
					@ -355,6 +367,7 @@ func (driver *StorageDriverClient) Move(sourcePath string, destPath string) erro
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Delete recursively deletes all objects stored at "path" and its subpaths.
 | 
				
			||||||
func (driver *StorageDriverClient) Delete(path string) error {
 | 
					func (driver *StorageDriverClient) Delete(path string) error {
 | 
				
			||||||
	if err := driver.exited(); err != nil {
 | 
						if err := driver.exited(); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,10 +9,10 @@ import (
 | 
				
			||||||
	"github.com/docker/libchan"
 | 
						"github.com/docker/libchan"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// IPCStorageDriver is the interface which IPC storage drivers must implement. As external storage
 | 
					// StorageDriver is the interface which IPC storage drivers must implement. As external storage
 | 
				
			||||||
// drivers may be defined to use a different version of the storagedriver.StorageDriver interface,
 | 
					// drivers may be defined to use a different version of the storagedriver.StorageDriver interface,
 | 
				
			||||||
// we use an additional version check to determine compatiblity.
 | 
					// we use an additional version check to determine compatiblity.
 | 
				
			||||||
type IPCStorageDriver interface {
 | 
					type StorageDriver interface {
 | 
				
			||||||
	// Version returns the storagedriver.StorageDriver interface version which this storage driver
 | 
						// Version returns the storagedriver.StorageDriver interface version which this storage driver
 | 
				
			||||||
	// implements, which is used to determine driver compatibility
 | 
						// implements, which is used to determine driver compatibility
 | 
				
			||||||
	Version() (storagedriver.Version, error)
 | 
						Version() (storagedriver.Version, error)
 | 
				
			||||||
| 
						 | 
					@ -36,23 +36,25 @@ type Request struct {
 | 
				
			||||||
	ResponseChannel libchan.Sender
 | 
						ResponseChannel libchan.Sender
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type responseError struct {
 | 
					// ResponseError is a serializable error type.
 | 
				
			||||||
 | 
					type ResponseError struct {
 | 
				
			||||||
	Type    string
 | 
						Type    string
 | 
				
			||||||
	Message string
 | 
						Message string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ResponseError wraps an error in a serializable struct containing the error's type and message
 | 
					// WrapError wraps an error in a serializable struct containing the error's type
 | 
				
			||||||
func ResponseError(err error) *responseError {
 | 
					// and message.
 | 
				
			||||||
 | 
					func WrapError(err error) *ResponseError {
 | 
				
			||||||
	if err == nil {
 | 
						if err == nil {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return &responseError{
 | 
						return &ResponseError{
 | 
				
			||||||
		Type:    reflect.TypeOf(err).String(),
 | 
							Type:    reflect.TypeOf(err).String(),
 | 
				
			||||||
		Message: err.Error(),
 | 
							Message: err.Error(),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (err *responseError) Error() string {
 | 
					func (err *ResponseError) Error() string {
 | 
				
			||||||
	return fmt.Sprintf("%s: %s", err.Type, err.Message)
 | 
						return fmt.Sprintf("%s: %s", err.Type, err.Message)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -61,38 +63,38 @@ func (err *responseError) Error() string {
 | 
				
			||||||
// VersionResponse is a response for a Version request
 | 
					// VersionResponse is a response for a Version request
 | 
				
			||||||
type VersionResponse struct {
 | 
					type VersionResponse struct {
 | 
				
			||||||
	Version storagedriver.Version
 | 
						Version storagedriver.Version
 | 
				
			||||||
	Error   *responseError
 | 
						Error   *ResponseError
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ReadStreamResponse is a response for a ReadStream request
 | 
					// ReadStreamResponse is a response for a ReadStream request
 | 
				
			||||||
type ReadStreamResponse struct {
 | 
					type ReadStreamResponse struct {
 | 
				
			||||||
	Reader io.ReadCloser
 | 
						Reader io.ReadCloser
 | 
				
			||||||
	Error  *responseError
 | 
						Error  *ResponseError
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// WriteStreamResponse is a response for a WriteStream request
 | 
					// WriteStreamResponse is a response for a WriteStream request
 | 
				
			||||||
type WriteStreamResponse struct {
 | 
					type WriteStreamResponse struct {
 | 
				
			||||||
	Error *responseError
 | 
						Error *ResponseError
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// CurrentSizeResponse is a response for a CurrentSize request
 | 
					// CurrentSizeResponse is a response for a CurrentSize request
 | 
				
			||||||
type CurrentSizeResponse struct {
 | 
					type CurrentSizeResponse struct {
 | 
				
			||||||
	Position uint64
 | 
						Position uint64
 | 
				
			||||||
	Error    *responseError
 | 
						Error    *ResponseError
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ListResponse is a response for a List request
 | 
					// ListResponse is a response for a List request
 | 
				
			||||||
type ListResponse struct {
 | 
					type ListResponse struct {
 | 
				
			||||||
	Keys  []string
 | 
						Keys  []string
 | 
				
			||||||
	Error *responseError
 | 
						Error *ResponseError
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// MoveResponse is a response for a Move request
 | 
					// MoveResponse is a response for a Move request
 | 
				
			||||||
type MoveResponse struct {
 | 
					type MoveResponse struct {
 | 
				
			||||||
	Error *responseError
 | 
						Error *ResponseError
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DeleteResponse is a response for a Delete request
 | 
					// DeleteResponse is a response for a Delete request
 | 
				
			||||||
type DeleteResponse struct {
 | 
					type DeleteResponse struct {
 | 
				
			||||||
	Error *responseError
 | 
						Error *ResponseError
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,7 +33,9 @@ func StorageDriverServer(driver storagedriver.StorageDriver) error {
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		for {
 | 
							for {
 | 
				
			||||||
			receiver, err := transport.WaitReceiveChannel()
 | 
								receiver, err := transport.WaitReceiveChannel()
 | 
				
			||||||
			if err != nil {
 | 
								if err == io.EOF {
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								} else if err != nil {
 | 
				
			||||||
				panic(err)
 | 
									panic(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			go receive(driver, receiver)
 | 
								go receive(driver, receiver)
 | 
				
			||||||
| 
						 | 
					@ -49,7 +51,9 @@ func receive(driver storagedriver.StorageDriver, receiver libchan.Receiver) {
 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
		var request Request
 | 
							var request Request
 | 
				
			||||||
		err := receiver.Receive(&request)
 | 
							err := receiver.Receive(&request)
 | 
				
			||||||
		if err != nil {
 | 
							if err == io.EOF {
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							} else if err != nil {
 | 
				
			||||||
			panic(err)
 | 
								panic(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		go handleRequest(driver, request)
 | 
							go handleRequest(driver, request)
 | 
				
			||||||
| 
						 | 
					@ -70,7 +74,7 @@ func handleRequest(driver storagedriver.StorageDriver, request Request) {
 | 
				
			||||||
		content, err := driver.GetContent(path)
 | 
							content, err := driver.GetContent(path)
 | 
				
			||||||
		var response ReadStreamResponse
 | 
							var response ReadStreamResponse
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			response = ReadStreamResponse{Error: ResponseError(err)}
 | 
								response = ReadStreamResponse{Error: WrapError(err)}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			response = ReadStreamResponse{Reader: ioutil.NopCloser(bytes.NewReader(content))}
 | 
								response = ReadStreamResponse{Reader: ioutil.NopCloser(bytes.NewReader(content))}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -87,7 +91,7 @@ func handleRequest(driver storagedriver.StorageDriver, request Request) {
 | 
				
			||||||
			err = driver.PutContent(path, contents)
 | 
								err = driver.PutContent(path, contents)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		response := WriteStreamResponse{
 | 
							response := WriteStreamResponse{
 | 
				
			||||||
			Error: ResponseError(err),
 | 
								Error: WrapError(err),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		err = request.ResponseChannel.Send(&response)
 | 
							err = request.ResponseChannel.Send(&response)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
| 
						 | 
					@ -100,7 +104,7 @@ func handleRequest(driver storagedriver.StorageDriver, request Request) {
 | 
				
			||||||
		reader, err := driver.ReadStream(path, offset)
 | 
							reader, err := driver.ReadStream(path, offset)
 | 
				
			||||||
		var response ReadStreamResponse
 | 
							var response ReadStreamResponse
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			response = ReadStreamResponse{Error: ResponseError(err)}
 | 
								response = ReadStreamResponse{Error: WrapError(err)}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			response = ReadStreamResponse{Reader: ioutil.NopCloser(reader)}
 | 
								response = ReadStreamResponse{Reader: ioutil.NopCloser(reader)}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -117,7 +121,7 @@ func handleRequest(driver storagedriver.StorageDriver, request Request) {
 | 
				
			||||||
		reader, _ := request.Parameters["Reader"].(io.ReadCloser)
 | 
							reader, _ := request.Parameters["Reader"].(io.ReadCloser)
 | 
				
			||||||
		err := driver.WriteStream(path, offset, size, reader)
 | 
							err := driver.WriteStream(path, offset, size, reader)
 | 
				
			||||||
		response := WriteStreamResponse{
 | 
							response := WriteStreamResponse{
 | 
				
			||||||
			Error: ResponseError(err),
 | 
								Error: WrapError(err),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		err = request.ResponseChannel.Send(&response)
 | 
							err = request.ResponseChannel.Send(&response)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
| 
						 | 
					@ -128,7 +132,7 @@ func handleRequest(driver storagedriver.StorageDriver, request Request) {
 | 
				
			||||||
		position, err := driver.CurrentSize(path)
 | 
							position, err := driver.CurrentSize(path)
 | 
				
			||||||
		response := CurrentSizeResponse{
 | 
							response := CurrentSizeResponse{
 | 
				
			||||||
			Position: position,
 | 
								Position: position,
 | 
				
			||||||
			Error:    ResponseError(err),
 | 
								Error:    WrapError(err),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		err = request.ResponseChannel.Send(&response)
 | 
							err = request.ResponseChannel.Send(&response)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
| 
						 | 
					@ -139,7 +143,7 @@ func handleRequest(driver storagedriver.StorageDriver, request Request) {
 | 
				
			||||||
		keys, err := driver.List(path)
 | 
							keys, err := driver.List(path)
 | 
				
			||||||
		response := ListResponse{
 | 
							response := ListResponse{
 | 
				
			||||||
			Keys:  keys,
 | 
								Keys:  keys,
 | 
				
			||||||
			Error: ResponseError(err),
 | 
								Error: WrapError(err),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		err = request.ResponseChannel.Send(&response)
 | 
							err = request.ResponseChannel.Send(&response)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
| 
						 | 
					@ -150,7 +154,7 @@ func handleRequest(driver storagedriver.StorageDriver, request Request) {
 | 
				
			||||||
		destPath, _ := request.Parameters["DestPath"].(string)
 | 
							destPath, _ := request.Parameters["DestPath"].(string)
 | 
				
			||||||
		err := driver.Move(sourcePath, destPath)
 | 
							err := driver.Move(sourcePath, destPath)
 | 
				
			||||||
		response := MoveResponse{
 | 
							response := MoveResponse{
 | 
				
			||||||
			Error: ResponseError(err),
 | 
								Error: WrapError(err),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		err = request.ResponseChannel.Send(&response)
 | 
							err = request.ResponseChannel.Send(&response)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
| 
						 | 
					@ -160,7 +164,7 @@ func handleRequest(driver storagedriver.StorageDriver, request Request) {
 | 
				
			||||||
		path, _ := request.Parameters["Path"].(string)
 | 
							path, _ := request.Parameters["Path"].(string)
 | 
				
			||||||
		err := driver.Delete(path)
 | 
							err := driver.Delete(path)
 | 
				
			||||||
		response := DeleteResponse{
 | 
							response := DeleteResponse{
 | 
				
			||||||
			Error: ResponseError(err),
 | 
								Error: WrapError(err),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		err = request.ResponseChannel.Send(&response)
 | 
							err = request.ResponseChannel.Send(&response)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,7 +13,7 @@ import (
 | 
				
			||||||
	"github.com/docker/docker-registry/storagedriver/factory"
 | 
						"github.com/docker/docker-registry/storagedriver/factory"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const DriverName = "s3"
 | 
					const driverName = "s3"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// minChunkSize defines the minimum multipart upload chunk size
 | 
					// minChunkSize defines the minimum multipart upload chunk size
 | 
				
			||||||
// S3 API requires multipart upload chunks to be at least 5MB
 | 
					// S3 API requires multipart upload chunks to be at least 5MB
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,7 @@ const minChunkSize = uint64(5 * 1024 * 1024)
 | 
				
			||||||
const listPartsMax = 1000
 | 
					const listPartsMax = 1000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	factory.Register(DriverName, &s3DriverFactory{})
 | 
						factory.Register(driverName, &s3DriverFactory{})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// s3DriverFactory implements the factory.StorageDriverFactory interface
 | 
					// s3DriverFactory implements the factory.StorageDriverFactory interface
 | 
				
			||||||
| 
						 | 
					@ -33,22 +33,22 @@ func (factory *s3DriverFactory) Create(parameters map[string]string) (storagedri
 | 
				
			||||||
	return FromParameters(parameters)
 | 
						return FromParameters(parameters)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// S3Driver is a storagedriver.StorageDriver implementation backed by Amazon S3
 | 
					// Driver is a storagedriver.StorageDriver implementation backed by Amazon S3
 | 
				
			||||||
// Objects are stored at absolute keys in the provided bucket
 | 
					// Objects are stored at absolute keys in the provided bucket
 | 
				
			||||||
type S3Driver struct {
 | 
					type Driver struct {
 | 
				
			||||||
	S3      *s3.S3
 | 
						S3      *s3.S3
 | 
				
			||||||
	Bucket  *s3.Bucket
 | 
						Bucket  *s3.Bucket
 | 
				
			||||||
	Encrypt bool
 | 
						Encrypt bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// FromParameters constructs a new S3Driver with a given parameters map
 | 
					// FromParameters constructs a new Driver with a given parameters map
 | 
				
			||||||
// Required parameters:
 | 
					// Required parameters:
 | 
				
			||||||
// - accesskey
 | 
					// - accesskey
 | 
				
			||||||
// - secretkey
 | 
					// - secretkey
 | 
				
			||||||
// - region
 | 
					// - region
 | 
				
			||||||
// - bucket
 | 
					// - bucket
 | 
				
			||||||
// - encrypt
 | 
					// - encrypt
 | 
				
			||||||
func FromParameters(parameters map[string]string) (*S3Driver, error) {
 | 
					func FromParameters(parameters map[string]string) (*Driver, error) {
 | 
				
			||||||
	accessKey, ok := parameters["accesskey"]
 | 
						accessKey, ok := parameters["accesskey"]
 | 
				
			||||||
	if !ok || accessKey == "" {
 | 
						if !ok || accessKey == "" {
 | 
				
			||||||
		return nil, fmt.Errorf("No accesskey parameter provided")
 | 
							return nil, fmt.Errorf("No accesskey parameter provided")
 | 
				
			||||||
| 
						 | 
					@ -85,9 +85,9 @@ func FromParameters(parameters map[string]string) (*S3Driver, error) {
 | 
				
			||||||
	return New(accessKey, secretKey, region, encryptBool, bucket)
 | 
						return New(accessKey, secretKey, region, encryptBool, bucket)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// New constructs a new S3Driver with the given AWS credentials, region, encryption flag, and
 | 
					// New constructs a new Driver with the given AWS credentials, region, encryption flag, and
 | 
				
			||||||
// bucketName
 | 
					// bucketName
 | 
				
			||||||
func New(accessKey string, secretKey string, region aws.Region, encrypt bool, bucketName string) (*S3Driver, error) {
 | 
					func New(accessKey string, secretKey string, region aws.Region, encrypt bool, bucketName string) (*Driver, error) {
 | 
				
			||||||
	auth := aws.Auth{AccessKey: accessKey, SecretKey: secretKey}
 | 
						auth := aws.Auth{AccessKey: accessKey, SecretKey: secretKey}
 | 
				
			||||||
	s3obj := s3.New(auth, region)
 | 
						s3obj := s3.New(auth, region)
 | 
				
			||||||
	bucket := s3obj.Bucket(bucketName)
 | 
						bucket := s3obj.Bucket(bucketName)
 | 
				
			||||||
| 
						 | 
					@ -99,20 +99,24 @@ func New(accessKey string, secretKey string, region aws.Region, encrypt bool, bu
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &S3Driver{s3obj, bucket, encrypt}, nil
 | 
						return &Driver{s3obj, bucket, encrypt}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Implement the storagedriver.StorageDriver interface
 | 
					// Implement the storagedriver.StorageDriver interface
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *S3Driver) GetContent(path string) ([]byte, error) {
 | 
					// GetContent retrieves the content stored at "path" as a []byte.
 | 
				
			||||||
 | 
					func (d *Driver) GetContent(path string) ([]byte, error) {
 | 
				
			||||||
	return d.Bucket.Get(path)
 | 
						return d.Bucket.Get(path)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *S3Driver) PutContent(path string, contents []byte) error {
 | 
					// PutContent stores the []byte content at a location designated by "path".
 | 
				
			||||||
 | 
					func (d *Driver) PutContent(path string, contents []byte) error {
 | 
				
			||||||
	return d.Bucket.Put(path, contents, d.getContentType(), getPermissions(), d.getOptions())
 | 
						return d.Bucket.Put(path, contents, d.getContentType(), getPermissions(), d.getOptions())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *S3Driver) ReadStream(path string, offset uint64) (io.ReadCloser, error) {
 | 
					// ReadStream retrieves an io.ReadCloser for the content stored at "path" with a
 | 
				
			||||||
 | 
					// given byte offset.
 | 
				
			||||||
 | 
					func (d *Driver) ReadStream(path string, offset uint64) (io.ReadCloser, error) {
 | 
				
			||||||
	headers := make(http.Header)
 | 
						headers := make(http.Header)
 | 
				
			||||||
	headers.Add("Range", "bytes="+strconv.FormatUint(offset, 10)+"-")
 | 
						headers.Add("Range", "bytes="+strconv.FormatUint(offset, 10)+"-")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -124,7 +128,9 @@ func (d *S3Driver) ReadStream(path string, offset uint64) (io.ReadCloser, error)
 | 
				
			||||||
	return nil, err
 | 
						return nil, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *S3Driver) WriteStream(path string, offset, size uint64, reader io.ReadCloser) error {
 | 
					// WriteStream stores the contents of the provided io.ReadCloser at a location
 | 
				
			||||||
 | 
					// designated by the given path.
 | 
				
			||||||
 | 
					func (d *Driver) WriteStream(path string, offset, size uint64, reader io.ReadCloser) error {
 | 
				
			||||||
	defer reader.Close()
 | 
						defer reader.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	chunkSize := minChunkSize
 | 
						chunkSize := minChunkSize
 | 
				
			||||||
| 
						 | 
					@ -177,7 +183,9 @@ func (d *S3Driver) WriteStream(path string, offset, size uint64, reader io.ReadC
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *S3Driver) CurrentSize(path string) (uint64, error) {
 | 
					// CurrentSize retrieves the curernt size in bytes of the object at the given
 | 
				
			||||||
 | 
					// path.
 | 
				
			||||||
 | 
					func (d *Driver) CurrentSize(path string) (uint64, error) {
 | 
				
			||||||
	_, parts, err := d.getAllParts(path)
 | 
						_, parts, err := d.getAllParts(path)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return 0, err
 | 
							return 0, err
 | 
				
			||||||
| 
						 | 
					@ -190,7 +198,9 @@ func (d *S3Driver) CurrentSize(path string) (uint64, error) {
 | 
				
			||||||
	return (((uint64(len(parts)) - 1) * uint64(parts[0].Size)) + uint64(parts[len(parts)-1].Size)), nil
 | 
						return (((uint64(len(parts)) - 1) * uint64(parts[0].Size)) + uint64(parts[len(parts)-1].Size)), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *S3Driver) List(path string) ([]string, error) {
 | 
					// List returns a list of the objects that are direct descendants of the given
 | 
				
			||||||
 | 
					// path.
 | 
				
			||||||
 | 
					func (d *Driver) List(path string) ([]string, error) {
 | 
				
			||||||
	if path[len(path)-1] != '/' {
 | 
						if path[len(path)-1] != '/' {
 | 
				
			||||||
		path = path + "/"
 | 
							path = path + "/"
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -224,7 +234,9 @@ func (d *S3Driver) List(path string) ([]string, error) {
 | 
				
			||||||
	return append(files, directories...), nil
 | 
						return append(files, directories...), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *S3Driver) Move(sourcePath string, destPath string) error {
 | 
					// Move moves an object stored at sourcePath to destPath, removing the original
 | 
				
			||||||
 | 
					// object.
 | 
				
			||||||
 | 
					func (d *Driver) Move(sourcePath string, destPath string) error {
 | 
				
			||||||
	/* This is terrible, but aws doesn't have an actual move. */
 | 
						/* This is terrible, but aws doesn't have an actual move. */
 | 
				
			||||||
	_, err := d.Bucket.PutCopy(destPath, getPermissions(),
 | 
						_, err := d.Bucket.PutCopy(destPath, getPermissions(),
 | 
				
			||||||
		s3.CopyOptions{Options: d.getOptions(), MetadataDirective: "", ContentType: d.getContentType()},
 | 
							s3.CopyOptions{Options: d.getOptions(), MetadataDirective: "", ContentType: d.getContentType()},
 | 
				
			||||||
| 
						 | 
					@ -236,7 +248,8 @@ func (d *S3Driver) Move(sourcePath string, destPath string) error {
 | 
				
			||||||
	return d.Delete(sourcePath)
 | 
						return d.Delete(sourcePath)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *S3Driver) Delete(path string) error {
 | 
					// Delete recursively deletes all objects stored at "path" and its subpaths.
 | 
				
			||||||
 | 
					func (d *Driver) Delete(path string) error {
 | 
				
			||||||
	listResponse, err := d.Bucket.List(path, "", "", listPartsMax)
 | 
						listResponse, err := d.Bucket.List(path, "", "", listPartsMax)
 | 
				
			||||||
	if err != nil || len(listResponse.Contents) == 0 {
 | 
						if err != nil || len(listResponse.Contents) == 0 {
 | 
				
			||||||
		return storagedriver.PathNotFoundError{Path: path}
 | 
							return storagedriver.PathNotFoundError{Path: path}
 | 
				
			||||||
| 
						 | 
					@ -263,30 +276,29 @@ func (d *S3Driver) Delete(path string) error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *S3Driver) getHighestIdMulti(path string) (multi *s3.Multi, err error) {
 | 
					func (d *Driver) getHighestIDMulti(path string) (multi *s3.Multi, err error) {
 | 
				
			||||||
	multis, _, err := d.Bucket.ListMulti(path, "")
 | 
						multis, _, err := d.Bucket.ListMulti(path, "")
 | 
				
			||||||
	if err != nil && !hasCode(err, "NoSuchUpload") {
 | 
						if err != nil && !hasCode(err, "NoSuchUpload") {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uploadId := ""
 | 
						uploadID := ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(multis) > 0 {
 | 
						if len(multis) > 0 {
 | 
				
			||||||
		for _, m := range multis {
 | 
							for _, m := range multis {
 | 
				
			||||||
			if m.Key == path && m.UploadId >= uploadId {
 | 
								if m.Key == path && m.UploadId >= uploadID {
 | 
				
			||||||
				uploadId = m.UploadId
 | 
									uploadID = m.UploadId
 | 
				
			||||||
				multi = m
 | 
									multi = m
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return multi, nil
 | 
							return multi, nil
 | 
				
			||||||
	} else {
 | 
						}
 | 
				
			||||||
		multi, err := d.Bucket.InitMulti(path, d.getContentType(), getPermissions(), d.getOptions())
 | 
						multi, err = d.Bucket.InitMulti(path, d.getContentType(), getPermissions(), d.getOptions())
 | 
				
			||||||
	return multi, err
 | 
						return multi, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *S3Driver) getAllParts(path string) (*s3.Multi, []s3.Part, error) {
 | 
					func (d *Driver) getAllParts(path string) (*s3.Multi, []s3.Part, error) {
 | 
				
			||||||
	multi, err := d.getHighestIdMulti(path)
 | 
						multi, err := d.getHighestIDMulti(path)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, nil, err
 | 
							return nil, nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -300,7 +312,7 @@ func hasCode(err error, code string) bool {
 | 
				
			||||||
	return ok && s3err.Code == code
 | 
						return ok && s3err.Code == code
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *S3Driver) getOptions() s3.Options {
 | 
					func (d *Driver) getOptions() s3.Options {
 | 
				
			||||||
	return s3.Options{SSE: d.Encrypt}
 | 
						return s3.Options{SSE: d.Encrypt}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -308,6 +320,6 @@ func getPermissions() s3.ACL {
 | 
				
			||||||
	return s3.Private
 | 
						return s3.Private
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *S3Driver) getContentType() string {
 | 
					func (d *Driver) getContentType() string {
 | 
				
			||||||
	return "application/octet-stream"
 | 
						return "application/octet-stream"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,11 +8,12 @@ import (
 | 
				
			||||||
	"github.com/crowdmob/goamz/aws"
 | 
						"github.com/crowdmob/goamz/aws"
 | 
				
			||||||
	"github.com/docker/docker-registry/storagedriver"
 | 
						"github.com/docker/docker-registry/storagedriver"
 | 
				
			||||||
	"github.com/docker/docker-registry/storagedriver/testsuites"
 | 
						"github.com/docker/docker-registry/storagedriver/testsuites"
 | 
				
			||||||
	. "gopkg.in/check.v1"
 | 
					
 | 
				
			||||||
 | 
						"gopkg.in/check.v1"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Hook up gocheck into the "go test" runner.
 | 
					// Hook up gocheck into the "go test" runner.
 | 
				
			||||||
func Test(t *testing.T) { TestingT(t) }
 | 
					func Test(t *testing.T) { check.TestingT(t) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	accessKey := os.Getenv("AWS_ACCESS_KEY")
 | 
						accessKey := os.Getenv("AWS_ACCESS_KEY")
 | 
				
			||||||
| 
						 | 
					@ -38,7 +39,7 @@ func init() {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	testsuites.RegisterInProcessSuite(s3DriverConstructor, skipCheck)
 | 
						testsuites.RegisterInProcessSuite(s3DriverConstructor, skipCheck)
 | 
				
			||||||
	testsuites.RegisterIPCSuite(DriverName, map[string]string{
 | 
						testsuites.RegisterIPCSuite(driverName, map[string]string{
 | 
				
			||||||
		"accesskey": accessKey,
 | 
							"accesskey": accessKey,
 | 
				
			||||||
		"secretkey": secretKey,
 | 
							"secretkey": secretKey,
 | 
				
			||||||
		"region":    region,
 | 
							"region":    region,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,67 +7,73 @@ import (
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Version is a string representing the storage driver version, of the form Major.Minor.
 | 
					// Version is a string representing the storage driver version, of the form
 | 
				
			||||||
// The registry must accept storage drivers with equal major version and greater minor version,
 | 
					// Major.Minor.
 | 
				
			||||||
// but may not be compatible with older storage driver versions.
 | 
					// The registry must accept storage drivers with equal major version and greater
 | 
				
			||||||
 | 
					// minor version, but may not be compatible with older storage driver versions.
 | 
				
			||||||
type Version string
 | 
					type Version string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Major returns the major (primary) component of a version
 | 
					// Major returns the major (primary) component of a version.
 | 
				
			||||||
func (version Version) Major() uint {
 | 
					func (version Version) Major() uint {
 | 
				
			||||||
	majorPart := strings.Split(string(version), ".")[0]
 | 
						majorPart := strings.Split(string(version), ".")[0]
 | 
				
			||||||
	major, _ := strconv.ParseUint(majorPart, 10, 0)
 | 
						major, _ := strconv.ParseUint(majorPart, 10, 0)
 | 
				
			||||||
	return uint(major)
 | 
						return uint(major)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Minor returns the minor (secondary) component of a version
 | 
					// Minor returns the minor (secondary) component of a version.
 | 
				
			||||||
func (version Version) Minor() uint {
 | 
					func (version Version) Minor() uint {
 | 
				
			||||||
	minorPart := strings.Split(string(version), ".")[1]
 | 
						minorPart := strings.Split(string(version), ".")[1]
 | 
				
			||||||
	minor, _ := strconv.ParseUint(minorPart, 10, 0)
 | 
						minor, _ := strconv.ParseUint(minorPart, 10, 0)
 | 
				
			||||||
	return uint(minor)
 | 
						return uint(minor)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// CurrentVersion is the current storage driver Version
 | 
					// CurrentVersion is the current storage driver Version.
 | 
				
			||||||
const CurrentVersion Version = "0.1"
 | 
					const CurrentVersion Version = "0.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// StorageDriver defines methods that a Storage Driver must implement for a filesystem-like
 | 
					// StorageDriver defines methods that a Storage Driver must implement for a
 | 
				
			||||||
// key/value object storage
 | 
					// filesystem-like key/value object storage.
 | 
				
			||||||
type StorageDriver interface {
 | 
					type StorageDriver interface {
 | 
				
			||||||
	// GetContent retrieves the content stored at "path" as a []byte
 | 
						// GetContent retrieves the content stored at "path" as a []byte.
 | 
				
			||||||
	// Should primarily be used for small objects
 | 
						// This should primarily be used for small objects.
 | 
				
			||||||
	GetContent(path string) ([]byte, error)
 | 
						GetContent(path string) ([]byte, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// PutContent stores the []byte content at a location designated by "path"
 | 
						// PutContent stores the []byte content at a location designated by "path".
 | 
				
			||||||
	// Should primarily be used for small objects
 | 
						// This should primarily be used for small objects.
 | 
				
			||||||
	PutContent(path string, content []byte) error
 | 
						PutContent(path string, content []byte) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// ReadStream retrieves an io.ReadCloser for the content stored at "path" with a given byte
 | 
						// ReadStream retrieves an io.ReadCloser for the content stored at "path"
 | 
				
			||||||
	// offset
 | 
						// with a given byte offset.
 | 
				
			||||||
	// May be used to resume reading a stream by providing a nonzero offset
 | 
						// May be used to resume reading a stream by providing a nonzero offset.
 | 
				
			||||||
	ReadStream(path string, offset uint64) (io.ReadCloser, error)
 | 
						ReadStream(path string, offset uint64) (io.ReadCloser, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// WriteStream stores the contents of the provided io.ReadCloser at a location designated by
 | 
						// WriteStream stores the contents of the provided io.ReadCloser at a
 | 
				
			||||||
	// the given path
 | 
						// location designated by the given path.
 | 
				
			||||||
	// The driver will know it has received the full contents when it has read "size" bytes
 | 
						// The driver will know it has received the full contents when it has read
 | 
				
			||||||
	// May be used to resume writing a stream by providing a nonzero offset
 | 
						// "size" bytes.
 | 
				
			||||||
	// The offset must be no larger than the CurrentSize for this path
 | 
						// May be used to resume writing a stream by providing a nonzero offset.
 | 
				
			||||||
 | 
						// The offset must be no larger than the CurrentSize for this path.
 | 
				
			||||||
	WriteStream(path string, offset, size uint64, readCloser io.ReadCloser) error
 | 
						WriteStream(path string, offset, size uint64, readCloser io.ReadCloser) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// CurrentSize retrieves the curernt size in bytes of the object at the given path
 | 
						// CurrentSize retrieves the curernt size in bytes of the object at the
 | 
				
			||||||
	// It should be safe to read or write anywhere up to this point
 | 
						// given path.
 | 
				
			||||||
 | 
						// It should be safe to read or write anywhere up to this point.
 | 
				
			||||||
	CurrentSize(path string) (uint64, error)
 | 
						CurrentSize(path string) (uint64, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// List returns a list of the objects that are direct descendants of the given path
 | 
						// List returns a list of the objects that are direct descendants of the
 | 
				
			||||||
 | 
						//given path.
 | 
				
			||||||
	List(path string) ([]string, error)
 | 
						List(path string) ([]string, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Move moves an object stored at sourcePath to destPath, removing the original object
 | 
						// Move moves an object stored at sourcePath to destPath, removing the
 | 
				
			||||||
	// Note: This may be no more efficient than a copy followed by a delete for many implementations
 | 
						// original object.
 | 
				
			||||||
 | 
						// Note: This may be no more efficient than a copy followed by a delete for
 | 
				
			||||||
 | 
						// many implementations.
 | 
				
			||||||
	Move(sourcePath string, destPath string) error
 | 
						Move(sourcePath string, destPath string) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Delete recursively deletes all objects stored at "path" and its subpaths
 | 
						// Delete recursively deletes all objects stored at "path" and its subpaths.
 | 
				
			||||||
	Delete(path string) error
 | 
						Delete(path string) error
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// PathNotFoundError is returned when operating on a nonexistent path
 | 
					// PathNotFoundError is returned when operating on a nonexistent path.
 | 
				
			||||||
type PathNotFoundError struct {
 | 
					type PathNotFoundError struct {
 | 
				
			||||||
	Path string
 | 
						Path string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -76,7 +82,8 @@ func (err PathNotFoundError) Error() string {
 | 
				
			||||||
	return fmt.Sprintf("Path not found: %s", err.Path)
 | 
						return fmt.Sprintf("Path not found: %s", err.Path)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// InvalidOffsetError is returned when attempting to read or write from an invalid offset
 | 
					// InvalidOffsetError is returned when attempting to read or write from an
 | 
				
			||||||
 | 
					// invalid offset.
 | 
				
			||||||
type InvalidOffsetError struct {
 | 
					type InvalidOffsetError struct {
 | 
				
			||||||
	Path   string
 | 
						Path   string
 | 
				
			||||||
	Offset uint64
 | 
						Offset uint64
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,15 +11,15 @@ import (
 | 
				
			||||||
	"github.com/docker/docker-registry/storagedriver"
 | 
						"github.com/docker/docker-registry/storagedriver"
 | 
				
			||||||
	"github.com/docker/docker-registry/storagedriver/ipc"
 | 
						"github.com/docker/docker-registry/storagedriver/ipc"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	. "gopkg.in/check.v1"
 | 
						"gopkg.in/check.v1"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Hook up gocheck into the "go test" runner
 | 
					// Test hooks up gocheck into the "go test" runner.
 | 
				
			||||||
func Test(t *testing.T) { TestingT(t) }
 | 
					func Test(t *testing.T) { check.TestingT(t) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RegisterInProcessSuite registers an in-process storage driver test suite with the go test runner
 | 
					// RegisterInProcessSuite registers an in-process storage driver test suite with the go test runner
 | 
				
			||||||
func RegisterInProcessSuite(driverConstructor DriverConstructor, skipCheck SkipCheck) {
 | 
					func RegisterInProcessSuite(driverConstructor DriverConstructor, skipCheck SkipCheck) {
 | 
				
			||||||
	Suite(&DriverSuite{
 | 
						check.Suite(&DriverSuite{
 | 
				
			||||||
		Constructor: driverConstructor,
 | 
							Constructor: driverConstructor,
 | 
				
			||||||
		SkipCheck:   skipCheck,
 | 
							SkipCheck:   skipCheck,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
| 
						 | 
					@ -50,7 +50,7 @@ func RegisterIPCSuite(driverName string, ipcParams map[string]string, skipCheck
 | 
				
			||||||
		driverClient := suite.StorageDriver.(*ipc.StorageDriverClient)
 | 
							driverClient := suite.StorageDriver.(*ipc.StorageDriverClient)
 | 
				
			||||||
		return driverClient.Stop()
 | 
							return driverClient.Stop()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	Suite(suite)
 | 
						check.Suite(suite)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SkipCheck is a function used to determine if a test suite should be skipped
 | 
					// SkipCheck is a function used to determine if a test suite should be skipped
 | 
				
			||||||
| 
						 | 
					@ -75,77 +75,93 @@ type DriverSuite struct {
 | 
				
			||||||
	storagedriver.StorageDriver
 | 
						storagedriver.StorageDriver
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *DriverSuite) SetUpSuite(c *C) {
 | 
					// SetUpSuite sets up the gocheck test suite
 | 
				
			||||||
 | 
					func (suite *DriverSuite) SetUpSuite(c *check.C) {
 | 
				
			||||||
	if reason := suite.SkipCheck(); reason != "" {
 | 
						if reason := suite.SkipCheck(); reason != "" {
 | 
				
			||||||
		c.Skip(reason)
 | 
							c.Skip(reason)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	d, err := suite.Constructor()
 | 
						d, err := suite.Constructor()
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
	suite.StorageDriver = d
 | 
						suite.StorageDriver = d
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *DriverSuite) TearDownSuite(c *C) {
 | 
					// TearDownSuite tears down the gocheck test suite
 | 
				
			||||||
 | 
					func (suite *DriverSuite) TearDownSuite(c *check.C) {
 | 
				
			||||||
	if suite.Teardown != nil {
 | 
						if suite.Teardown != nil {
 | 
				
			||||||
		err := suite.Teardown()
 | 
							err := suite.Teardown()
 | 
				
			||||||
		c.Assert(err, IsNil)
 | 
							c.Assert(err, check.IsNil)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *DriverSuite) TestWriteRead1(c *C) {
 | 
					// TestWriteRead1 tests a simple write-read workflow
 | 
				
			||||||
 | 
					func (suite *DriverSuite) TestWriteRead1(c *check.C) {
 | 
				
			||||||
	filename := randomString(32)
 | 
						filename := randomString(32)
 | 
				
			||||||
	contents := []byte("a")
 | 
						contents := []byte("a")
 | 
				
			||||||
	suite.writeReadCompare(c, filename, contents, contents)
 | 
						suite.writeReadCompare(c, filename, contents, contents)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *DriverSuite) TestWriteRead2(c *C) {
 | 
					// TestWriteRead2 tests a simple write-read workflow with unicode data
 | 
				
			||||||
 | 
					func (suite *DriverSuite) TestWriteRead2(c *check.C) {
 | 
				
			||||||
	filename := randomString(32)
 | 
						filename := randomString(32)
 | 
				
			||||||
	contents := []byte("\xc3\x9f")
 | 
						contents := []byte("\xc3\x9f")
 | 
				
			||||||
	suite.writeReadCompare(c, filename, contents, contents)
 | 
						suite.writeReadCompare(c, filename, contents, contents)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *DriverSuite) TestWriteRead3(c *C) {
 | 
					// TestWriteRead3 tests a simple write-read workflow with a small string
 | 
				
			||||||
 | 
					func (suite *DriverSuite) TestWriteRead3(c *check.C) {
 | 
				
			||||||
	filename := randomString(32)
 | 
						filename := randomString(32)
 | 
				
			||||||
	contents := []byte(randomString(32))
 | 
						contents := []byte(randomString(32))
 | 
				
			||||||
	suite.writeReadCompare(c, filename, contents, contents)
 | 
						suite.writeReadCompare(c, filename, contents, contents)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *DriverSuite) TestWriteRead4(c *C) {
 | 
					// TestWriteRead4 tests a simple write-read workflow with 1MB of data
 | 
				
			||||||
 | 
					func (suite *DriverSuite) TestWriteRead4(c *check.C) {
 | 
				
			||||||
	filename := randomString(32)
 | 
						filename := randomString(32)
 | 
				
			||||||
	contents := []byte(randomString(1024 * 1024))
 | 
						contents := []byte(randomString(1024 * 1024))
 | 
				
			||||||
	suite.writeReadCompare(c, filename, contents, contents)
 | 
						suite.writeReadCompare(c, filename, contents, contents)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *DriverSuite) TestReadNonexistent(c *C) {
 | 
					// TestReadNonexistent tests reading content from an empty path
 | 
				
			||||||
 | 
					func (suite *DriverSuite) TestReadNonexistent(c *check.C) {
 | 
				
			||||||
	filename := randomString(32)
 | 
						filename := randomString(32)
 | 
				
			||||||
	_, err := suite.StorageDriver.GetContent(filename)
 | 
						_, err := suite.StorageDriver.GetContent(filename)
 | 
				
			||||||
	c.Assert(err, NotNil)
 | 
						c.Assert(err, check.NotNil)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *DriverSuite) TestWriteReadStreams1(c *C) {
 | 
					// TestWriteReadStreams1 tests a simple write-read streaming workflow
 | 
				
			||||||
 | 
					func (suite *DriverSuite) TestWriteReadStreams1(c *check.C) {
 | 
				
			||||||
	filename := randomString(32)
 | 
						filename := randomString(32)
 | 
				
			||||||
	contents := []byte("a")
 | 
						contents := []byte("a")
 | 
				
			||||||
	suite.writeReadCompareStreams(c, filename, contents, contents)
 | 
						suite.writeReadCompareStreams(c, filename, contents, contents)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *DriverSuite) TestWriteReadStreams2(c *C) {
 | 
					// TestWriteReadStreams2 tests a simple write-read streaming workflow with
 | 
				
			||||||
 | 
					// unicode data
 | 
				
			||||||
 | 
					func (suite *DriverSuite) TestWriteReadStreams2(c *check.C) {
 | 
				
			||||||
	filename := randomString(32)
 | 
						filename := randomString(32)
 | 
				
			||||||
	contents := []byte("\xc3\x9f")
 | 
						contents := []byte("\xc3\x9f")
 | 
				
			||||||
	suite.writeReadCompareStreams(c, filename, contents, contents)
 | 
						suite.writeReadCompareStreams(c, filename, contents, contents)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *DriverSuite) TestWriteReadStreams3(c *C) {
 | 
					// TestWriteReadStreams3 tests a simple write-read streaming workflow with a
 | 
				
			||||||
 | 
					// small amount of data
 | 
				
			||||||
 | 
					func (suite *DriverSuite) TestWriteReadStreams3(c *check.C) {
 | 
				
			||||||
	filename := randomString(32)
 | 
						filename := randomString(32)
 | 
				
			||||||
	contents := []byte(randomString(32))
 | 
						contents := []byte(randomString(32))
 | 
				
			||||||
	suite.writeReadCompareStreams(c, filename, contents, contents)
 | 
						suite.writeReadCompareStreams(c, filename, contents, contents)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *DriverSuite) TestWriteReadStreams4(c *C) {
 | 
					// TestWriteReadStreams4 tests a simple write-read streaming workflow with 1MB
 | 
				
			||||||
 | 
					// of data
 | 
				
			||||||
 | 
					func (suite *DriverSuite) TestWriteReadStreams4(c *check.C) {
 | 
				
			||||||
	filename := randomString(32)
 | 
						filename := randomString(32)
 | 
				
			||||||
	contents := []byte(randomString(1024 * 1024))
 | 
						contents := []byte(randomString(1024 * 1024))
 | 
				
			||||||
	suite.writeReadCompareStreams(c, filename, contents, contents)
 | 
						suite.writeReadCompareStreams(c, filename, contents, contents)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *DriverSuite) TestContinueStreamAppend(c *C) {
 | 
					// TestContinueStreamAppend tests that a stream write can be appended to without
 | 
				
			||||||
 | 
					// corrupting the data
 | 
				
			||||||
 | 
					func (suite *DriverSuite) TestContinueStreamAppend(c *check.C) {
 | 
				
			||||||
	filename := randomString(32)
 | 
						filename := randomString(32)
 | 
				
			||||||
	defer suite.StorageDriver.Delete(filename)
 | 
						defer suite.StorageDriver.Delete(filename)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -158,31 +174,33 @@ func (suite *DriverSuite) TestContinueStreamAppend(c *C) {
 | 
				
			||||||
	fullContents := append(append(contentsChunk1, contentsChunk2...), contentsChunk3...)
 | 
						fullContents := append(append(contentsChunk1, contentsChunk2...), contentsChunk3...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err := suite.StorageDriver.WriteStream(filename, 0, 3*chunkSize, ioutil.NopCloser(bytes.NewReader(contentsChunk1)))
 | 
						err := suite.StorageDriver.WriteStream(filename, 0, 3*chunkSize, ioutil.NopCloser(bytes.NewReader(contentsChunk1)))
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	offset, err := suite.StorageDriver.CurrentSize(filename)
 | 
						offset, err := suite.StorageDriver.CurrentSize(filename)
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
	if offset > chunkSize {
 | 
						if offset > chunkSize {
 | 
				
			||||||
		c.Fatalf("Offset too large, %d > %d", offset, chunkSize)
 | 
							c.Fatalf("Offset too large, %d > %d", offset, chunkSize)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	err = suite.StorageDriver.WriteStream(filename, offset, 3*chunkSize, ioutil.NopCloser(bytes.NewReader(fullContents[offset:2*chunkSize])))
 | 
						err = suite.StorageDriver.WriteStream(filename, offset, 3*chunkSize, ioutil.NopCloser(bytes.NewReader(fullContents[offset:2*chunkSize])))
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	offset, err = suite.StorageDriver.CurrentSize(filename)
 | 
						offset, err = suite.StorageDriver.CurrentSize(filename)
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
	if offset > 2*chunkSize {
 | 
						if offset > 2*chunkSize {
 | 
				
			||||||
		c.Fatalf("Offset too large, %d > %d", offset, 2*chunkSize)
 | 
							c.Fatalf("Offset too large, %d > %d", offset, 2*chunkSize)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = suite.StorageDriver.WriteStream(filename, offset, 3*chunkSize, ioutil.NopCloser(bytes.NewReader(fullContents[offset:])))
 | 
						err = suite.StorageDriver.WriteStream(filename, offset, 3*chunkSize, ioutil.NopCloser(bytes.NewReader(fullContents[offset:])))
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	received, err := suite.StorageDriver.GetContent(filename)
 | 
						received, err := suite.StorageDriver.GetContent(filename)
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
	c.Assert(received, DeepEquals, fullContents)
 | 
						c.Assert(received, check.DeepEquals, fullContents)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *DriverSuite) TestReadStreamWithOffset(c *C) {
 | 
					// TestReadStreamWithOffset tests that the appropriate data is streamed when
 | 
				
			||||||
 | 
					// reading with a given offset
 | 
				
			||||||
 | 
					func (suite *DriverSuite) TestReadStreamWithOffset(c *check.C) {
 | 
				
			||||||
	filename := randomString(32)
 | 
						filename := randomString(32)
 | 
				
			||||||
	defer suite.StorageDriver.Delete(filename)
 | 
						defer suite.StorageDriver.Delete(filename)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -193,43 +211,46 @@ func (suite *DriverSuite) TestReadStreamWithOffset(c *C) {
 | 
				
			||||||
	contentsChunk3 := []byte(randomString(chunkSize))
 | 
						contentsChunk3 := []byte(randomString(chunkSize))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err := suite.StorageDriver.PutContent(filename, append(append(contentsChunk1, contentsChunk2...), contentsChunk3...))
 | 
						err := suite.StorageDriver.PutContent(filename, append(append(contentsChunk1, contentsChunk2...), contentsChunk3...))
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	reader, err := suite.StorageDriver.ReadStream(filename, 0)
 | 
						reader, err := suite.StorageDriver.ReadStream(filename, 0)
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
	defer reader.Close()
 | 
						defer reader.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	readContents, err := ioutil.ReadAll(reader)
 | 
						readContents, err := ioutil.ReadAll(reader)
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c.Assert(readContents, DeepEquals, append(append(contentsChunk1, contentsChunk2...), contentsChunk3...))
 | 
						c.Assert(readContents, check.DeepEquals, append(append(contentsChunk1, contentsChunk2...), contentsChunk3...))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	reader, err = suite.StorageDriver.ReadStream(filename, chunkSize)
 | 
						reader, err = suite.StorageDriver.ReadStream(filename, chunkSize)
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
	defer reader.Close()
 | 
						defer reader.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	readContents, err = ioutil.ReadAll(reader)
 | 
						readContents, err = ioutil.ReadAll(reader)
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c.Assert(readContents, DeepEquals, append(contentsChunk2, contentsChunk3...))
 | 
						c.Assert(readContents, check.DeepEquals, append(contentsChunk2, contentsChunk3...))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	reader, err = suite.StorageDriver.ReadStream(filename, chunkSize*2)
 | 
						reader, err = suite.StorageDriver.ReadStream(filename, chunkSize*2)
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
	defer reader.Close()
 | 
						defer reader.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	readContents, err = ioutil.ReadAll(reader)
 | 
						readContents, err = ioutil.ReadAll(reader)
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c.Assert(readContents, DeepEquals, contentsChunk3)
 | 
						c.Assert(readContents, check.DeepEquals, contentsChunk3)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *DriverSuite) TestReadNonexistentStream(c *C) {
 | 
					// TestReadNonexistentStream tests that reading a stream for a nonexistent path
 | 
				
			||||||
 | 
					// fails
 | 
				
			||||||
 | 
					func (suite *DriverSuite) TestReadNonexistentStream(c *check.C) {
 | 
				
			||||||
	filename := randomString(32)
 | 
						filename := randomString(32)
 | 
				
			||||||
	_, err := suite.StorageDriver.ReadStream(filename, 0)
 | 
						_, err := suite.StorageDriver.ReadStream(filename, 0)
 | 
				
			||||||
	c.Assert(err, NotNil)
 | 
						c.Assert(err, check.NotNil)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *DriverSuite) TestList(c *C) {
 | 
					// TestList checks the returned list of keys after populating a directory tree
 | 
				
			||||||
 | 
					func (suite *DriverSuite) TestList(c *check.C) {
 | 
				
			||||||
	rootDirectory := randomString(uint64(8 + rand.Intn(8)))
 | 
						rootDirectory := randomString(uint64(8 + rand.Intn(8)))
 | 
				
			||||||
	defer suite.StorageDriver.Delete(rootDirectory)
 | 
						defer suite.StorageDriver.Delete(rootDirectory)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -239,22 +260,24 @@ func (suite *DriverSuite) TestList(c *C) {
 | 
				
			||||||
		childFile := parentDirectory + "/" + randomString(uint64(8+rand.Intn(8)))
 | 
							childFile := parentDirectory + "/" + randomString(uint64(8+rand.Intn(8)))
 | 
				
			||||||
		childFiles[i] = childFile
 | 
							childFiles[i] = childFile
 | 
				
			||||||
		err := suite.StorageDriver.PutContent(childFile, []byte(randomString(32)))
 | 
							err := suite.StorageDriver.PutContent(childFile, []byte(randomString(32)))
 | 
				
			||||||
		c.Assert(err, IsNil)
 | 
							c.Assert(err, check.IsNil)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	sort.Strings(childFiles)
 | 
						sort.Strings(childFiles)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	keys, err := suite.StorageDriver.List(rootDirectory)
 | 
						keys, err := suite.StorageDriver.List(rootDirectory)
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
	c.Assert(keys, DeepEquals, []string{parentDirectory})
 | 
						c.Assert(keys, check.DeepEquals, []string{parentDirectory})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	keys, err = suite.StorageDriver.List(parentDirectory)
 | 
						keys, err = suite.StorageDriver.List(parentDirectory)
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sort.Strings(keys)
 | 
						sort.Strings(keys)
 | 
				
			||||||
	c.Assert(keys, DeepEquals, childFiles)
 | 
						c.Assert(keys, check.DeepEquals, childFiles)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *DriverSuite) TestMove(c *C) {
 | 
					// TestMove checks that a moved object no longer exists at the source path and
 | 
				
			||||||
 | 
					// does exist at the destination
 | 
				
			||||||
 | 
					func (suite *DriverSuite) TestMove(c *check.C) {
 | 
				
			||||||
	contents := []byte(randomString(32))
 | 
						contents := []byte(randomString(32))
 | 
				
			||||||
	sourcePath := randomString(32)
 | 
						sourcePath := randomString(32)
 | 
				
			||||||
	destPath := randomString(32)
 | 
						destPath := randomString(32)
 | 
				
			||||||
| 
						 | 
					@ -263,50 +286,55 @@ func (suite *DriverSuite) TestMove(c *C) {
 | 
				
			||||||
	defer suite.StorageDriver.Delete(destPath)
 | 
						defer suite.StorageDriver.Delete(destPath)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err := suite.StorageDriver.PutContent(sourcePath, contents)
 | 
						err := suite.StorageDriver.PutContent(sourcePath, contents)
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = suite.StorageDriver.Move(sourcePath, destPath)
 | 
						err = suite.StorageDriver.Move(sourcePath, destPath)
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	received, err := suite.StorageDriver.GetContent(destPath)
 | 
						received, err := suite.StorageDriver.GetContent(destPath)
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
	c.Assert(received, DeepEquals, contents)
 | 
						c.Assert(received, check.DeepEquals, contents)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err = suite.StorageDriver.GetContent(sourcePath)
 | 
						_, err = suite.StorageDriver.GetContent(sourcePath)
 | 
				
			||||||
	c.Assert(err, NotNil)
 | 
						c.Assert(err, check.NotNil)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *DriverSuite) TestMoveNonexistent(c *C) {
 | 
					// TestMoveNonexistent checks that moving a nonexistent key fails
 | 
				
			||||||
 | 
					func (suite *DriverSuite) TestMoveNonexistent(c *check.C) {
 | 
				
			||||||
	sourcePath := randomString(32)
 | 
						sourcePath := randomString(32)
 | 
				
			||||||
	destPath := randomString(32)
 | 
						destPath := randomString(32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err := suite.StorageDriver.Move(sourcePath, destPath)
 | 
						err := suite.StorageDriver.Move(sourcePath, destPath)
 | 
				
			||||||
	c.Assert(err, NotNil)
 | 
						c.Assert(err, check.NotNil)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *DriverSuite) TestRemove(c *C) {
 | 
					// TestDelete checks that the delete operation removes data from the storage
 | 
				
			||||||
 | 
					// driver
 | 
				
			||||||
 | 
					func (suite *DriverSuite) TestDelete(c *check.C) {
 | 
				
			||||||
	filename := randomString(32)
 | 
						filename := randomString(32)
 | 
				
			||||||
	contents := []byte(randomString(32))
 | 
						contents := []byte(randomString(32))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	defer suite.StorageDriver.Delete(filename)
 | 
						defer suite.StorageDriver.Delete(filename)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err := suite.StorageDriver.PutContent(filename, contents)
 | 
						err := suite.StorageDriver.PutContent(filename, contents)
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = suite.StorageDriver.Delete(filename)
 | 
						err = suite.StorageDriver.Delete(filename)
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err = suite.StorageDriver.GetContent(filename)
 | 
						_, err = suite.StorageDriver.GetContent(filename)
 | 
				
			||||||
	c.Assert(err, NotNil)
 | 
						c.Assert(err, check.NotNil)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *DriverSuite) TestRemoveNonexistent(c *C) {
 | 
					// TestDeleteNonexistent checks that removing a nonexistent key fails
 | 
				
			||||||
 | 
					func (suite *DriverSuite) TestDeleteNonexistent(c *check.C) {
 | 
				
			||||||
	filename := randomString(32)
 | 
						filename := randomString(32)
 | 
				
			||||||
	err := suite.StorageDriver.Delete(filename)
 | 
						err := suite.StorageDriver.Delete(filename)
 | 
				
			||||||
	c.Assert(err, NotNil)
 | 
						c.Assert(err, check.NotNil)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *DriverSuite) TestRemoveFolder(c *C) {
 | 
					// TestDeleteFolder checks that deleting a folder removes all child elements
 | 
				
			||||||
 | 
					func (suite *DriverSuite) TestDeleteFolder(c *check.C) {
 | 
				
			||||||
	dirname := randomString(32)
 | 
						dirname := randomString(32)
 | 
				
			||||||
	filename1 := randomString(32)
 | 
						filename1 := randomString(32)
 | 
				
			||||||
	filename2 := randomString(32)
 | 
						filename2 := randomString(32)
 | 
				
			||||||
| 
						 | 
					@ -316,47 +344,47 @@ func (suite *DriverSuite) TestRemoveFolder(c *C) {
 | 
				
			||||||
	defer suite.StorageDriver.Delete(path.Join(dirname, filename2))
 | 
						defer suite.StorageDriver.Delete(path.Join(dirname, filename2))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err := suite.StorageDriver.PutContent(path.Join(dirname, filename1), contents)
 | 
						err := suite.StorageDriver.PutContent(path.Join(dirname, filename1), contents)
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = suite.StorageDriver.PutContent(path.Join(dirname, filename2), contents)
 | 
						err = suite.StorageDriver.PutContent(path.Join(dirname, filename2), contents)
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = suite.StorageDriver.Delete(dirname)
 | 
						err = suite.StorageDriver.Delete(dirname)
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err = suite.StorageDriver.GetContent(path.Join(dirname, filename1))
 | 
						_, err = suite.StorageDriver.GetContent(path.Join(dirname, filename1))
 | 
				
			||||||
	c.Assert(err, NotNil)
 | 
						c.Assert(err, check.NotNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err = suite.StorageDriver.GetContent(path.Join(dirname, filename2))
 | 
						_, err = suite.StorageDriver.GetContent(path.Join(dirname, filename2))
 | 
				
			||||||
	c.Assert(err, NotNil)
 | 
						c.Assert(err, check.NotNil)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *DriverSuite) writeReadCompare(c *C, filename string, contents, expected []byte) {
 | 
					func (suite *DriverSuite) writeReadCompare(c *check.C, filename string, contents, expected []byte) {
 | 
				
			||||||
	defer suite.StorageDriver.Delete(filename)
 | 
						defer suite.StorageDriver.Delete(filename)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err := suite.StorageDriver.PutContent(filename, contents)
 | 
						err := suite.StorageDriver.PutContent(filename, contents)
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	readContents, err := suite.StorageDriver.GetContent(filename)
 | 
						readContents, err := suite.StorageDriver.GetContent(filename)
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c.Assert(readContents, DeepEquals, contents)
 | 
						c.Assert(readContents, check.DeepEquals, contents)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (suite *DriverSuite) writeReadCompareStreams(c *C, filename string, contents, expected []byte) {
 | 
					func (suite *DriverSuite) writeReadCompareStreams(c *check.C, filename string, contents, expected []byte) {
 | 
				
			||||||
	defer suite.StorageDriver.Delete(filename)
 | 
						defer suite.StorageDriver.Delete(filename)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err := suite.StorageDriver.WriteStream(filename, 0, uint64(len(contents)), ioutil.NopCloser(bytes.NewReader(contents)))
 | 
						err := suite.StorageDriver.WriteStream(filename, 0, uint64(len(contents)), ioutil.NopCloser(bytes.NewReader(contents)))
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	reader, err := suite.StorageDriver.ReadStream(filename, 0)
 | 
						reader, err := suite.StorageDriver.ReadStream(filename, 0)
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
	defer reader.Close()
 | 
						defer reader.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	readContents, err := ioutil.ReadAll(reader)
 | 
						readContents, err := ioutil.ReadAll(reader)
 | 
				
			||||||
	c.Assert(err, IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c.Assert(readContents, DeepEquals, contents)
 | 
						c.Assert(readContents, check.DeepEquals, contents)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var pathChars = []byte("abcdefghijklmnopqrstuvwxyz")
 | 
					var pathChars = []byte("abcdefghijklmnopqrstuvwxyz")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue