vendor: bump distribution to 568bf038af

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
Tonis Tiigi 2015-12-03 13:36:31 -08:00
parent 4d849619d4
commit 53cd579b6e
12 changed files with 138 additions and 84 deletions

View File

@ -40,7 +40,7 @@ clone git github.com/hashicorp/consul v0.5.2
clone git github.com/boltdb/bolt v1.1.0 clone git github.com/boltdb/bolt v1.1.0
# get graph and distribution packages # get graph and distribution packages
clone git github.com/docker/distribution c6c9194e9c6097f84b0ff468a741086ff7704aa3 clone git github.com/docker/distribution 568bf038af6d65b376165d02886b1c7fcaef1f61
clone git github.com/vbatts/tar-split v0.9.11 clone git github.com/vbatts/tar-split v0.9.11
clone git github.com/docker/notary 45de2828b5e0083bfb4e9a5a781eddb05e2ef9d0 clone git github.com/docker/notary 45de2828b5e0083bfb4e9a5a781eddb05e2ef9d0

View File

@ -1,4 +1,5 @@
Aaron Lehmann <aaron.lehmann@docker.com> Aaron Lehmann <aaron.lehmann@docker.com>
Aaron Vinson <avinson.public@gmail.com>
Adam Enger <adamenger@gmail.com> Adam Enger <adamenger@gmail.com>
Adrian Mouat <adrian.mouat@gmail.com> Adrian Mouat <adrian.mouat@gmail.com>
Ahmet Alp Balkan <ahmetalpbalkan@gmail.com> Ahmet Alp Balkan <ahmetalpbalkan@gmail.com>
@ -10,6 +11,7 @@ Andy Goldstein <agoldste@redhat.com>
Anton Tiurin <noxiouz@yandex.ru> Anton Tiurin <noxiouz@yandex.ru>
Antonio Mercado <amercado@thinknode.com> Antonio Mercado <amercado@thinknode.com>
Arnaud Porterie <arnaud.porterie@docker.com> Arnaud Porterie <arnaud.porterie@docker.com>
Arthur Baars <arthur@semmle.com>
Ayose Cazorla <ayosec@gmail.com> Ayose Cazorla <ayosec@gmail.com>
BadZen <dave.trombley@gmail.com> BadZen <dave.trombley@gmail.com>
Ben Firshman <ben@firshman.co.uk> Ben Firshman <ben@firshman.co.uk>
@ -25,15 +27,20 @@ David Lawrence <david.lawrence@docker.com>
David Verhasselt <david@crowdway.com> David Verhasselt <david@crowdway.com>
David Xia <dxia@spotify.com> David Xia <dxia@spotify.com>
davidli <wenquan.li@hp.com> davidli <wenquan.li@hp.com>
Dejan Golja <dejan@golja.org>
Derek McGowan <derek@mcgstyle.net> Derek McGowan <derek@mcgstyle.net>
Diogo Mónica <diogo.monica@gmail.com> Diogo Mónica <diogo.monica@gmail.com>
Donald Huang <don.hcd@gmail.com> Donald Huang <don.hcd@gmail.com>
Doug Davis <dug@us.ibm.com> Doug Davis <dug@us.ibm.com>
Florentin Raud <florentin.raud@gmail.com> Florentin Raud <florentin.raud@gmail.com>
Frederick F. Kautz IV <fkautz@alumni.cmu.edu> Frederick F. Kautz IV <fkautz@alumni.cmu.edu>
harche <harche@users.noreply.github.com>
Henri Gomez <henri.gomez@gmail.com> Henri Gomez <henri.gomez@gmail.com>
Hu Keping <hukeping@huawei.com> Hu Keping <hukeping@huawei.com>
Hua Wang <wanghua.humble@gmail.com>
Ian Babrou <ibobrik@gmail.com> Ian Babrou <ibobrik@gmail.com>
Jack Griffin <jackpg14@gmail.com>
Jason Freidman <jason.freidman@gmail.com>
Jeff Nickoloff <jeff@allingeek.com> Jeff Nickoloff <jeff@allingeek.com>
Jessie Frazelle <jfrazelle@users.noreply.github.com> Jessie Frazelle <jfrazelle@users.noreply.github.com>
Jianqing Wang <tsing@jianqing.org> Jianqing Wang <tsing@jianqing.org>
@ -44,15 +51,19 @@ Julien Fernandez <julien.fernandez@gmail.com>
Kelsey Hightower <kelsey.hightower@gmail.com> Kelsey Hightower <kelsey.hightower@gmail.com>
Kenneth Lim <kennethlimcp@gmail.com> Kenneth Lim <kennethlimcp@gmail.com>
Li Yi <denverdino@gmail.com> Li Yi <denverdino@gmail.com>
Louis Kottmann <louis.kottmann@gmail.com>
Luke Carpenter <x@rubynerd.net> Luke Carpenter <x@rubynerd.net>
Mary Anthony <mary@docker.com> Mary Anthony <mary@docker.com>
Matt Bentley <mbentley@mbentley.net> Matt Bentley <mbentley@mbentley.net>
Matt Moore <mattmoor@google.com>
Matt Robenolt <matt@ydekproductions.com> Matt Robenolt <matt@ydekproductions.com>
Michael Prokop <mika@grml.org> Michael Prokop <mika@grml.org>
Miquel Sabaté <msabate@suse.com>
moxiegirl <mary@docker.com> moxiegirl <mary@docker.com>
Nathan Sullivan <nathan@nightsys.net> Nathan Sullivan <nathan@nightsys.net>
nevermosby <robolwq@qq.com> nevermosby <robolwq@qq.com>
Nghia Tran <tcnghia@gmail.com> Nghia Tran <tcnghia@gmail.com>
Nuutti Kotivuori <nuutti.kotivuori@poplatek.fi>
Oilbeater <liumengxinfly@gmail.com> Oilbeater <liumengxinfly@gmail.com>
Olivier Gambier <olivier@docker.com> Olivier Gambier <olivier@docker.com>
Olivier Jacques <olivier.jacques@hp.com> Olivier Jacques <olivier.jacques@hp.com>
@ -60,20 +71,27 @@ Patrick Devine <patrick.devine@docker.com>
Philip Misiowiec <philip@atlashealth.com> Philip Misiowiec <philip@atlashealth.com>
Richard Scothern <richard.scothern@docker.com> Richard Scothern <richard.scothern@docker.com>
Sebastiaan van Stijn <github@gone.nl> Sebastiaan van Stijn <github@gone.nl>
Sharif Nassar <mrwacky42@users.noreply.github.com>
Sharif Nassar <sharif@mrwacky.com>
Shawn Falkner-Horine <dreadpirateshawn@gmail.com> Shawn Falkner-Horine <dreadpirateshawn@gmail.com>
Shreyas Karnik <karnik.shreyas@gmail.com> Shreyas Karnik <karnik.shreyas@gmail.com>
Simon Thulbourn <simon+github@thulbourn.com> Simon Thulbourn <simon+github@thulbourn.com>
Spencer Rinehart <anubis@overthemonkey.com> Spencer Rinehart <anubis@overthemonkey.com>
Stephen J Day <stephen.day@docker.com> Stephen J Day <stephen.day@docker.com>
Sungho Moon <sungho.moon@navercorp.com>
Sven Dowideit <SvenDowideit@home.org.au>
Sylvain Baubeau <sbaubeau@redhat.com> Sylvain Baubeau <sbaubeau@redhat.com>
tgic <farmer1992@gmail.com> tgic <farmer1992@gmail.com>
Thomas Sjögren <konstruktoid@users.noreply.github.com> Thomas Sjögren <konstruktoid@users.noreply.github.com>
Tianon Gravi <admwiggin@gmail.com> Tianon Gravi <admwiggin@gmail.com>
Tibor Vass <teabee89@gmail.com> Tibor Vass <teabee89@gmail.com>
Troels Thomsen <troels@thomsen.io>
Vincent Batts <vbatts@redhat.com> Vincent Batts <vbatts@redhat.com>
Vincent Demeester <vincent@sbr.pm> Vincent Demeester <vincent@sbr.pm>
Vincent Giersch <vincent.giersch@ovh.net> Vincent Giersch <vincent.giersch@ovh.net>
Vincent Giersch <vincent@giersch.fr>
W. Trevor King <wking@tremily.us> W. Trevor King <wking@tremily.us>
xg.song <xg.song@venusource.com>
xiekeyang <xiekeyang@huawei.com> xiekeyang <xiekeyang@huawei.com>
Yann ROBERT <yann.robert@anantaplex.fr> Yann ROBERT <yann.robert@anantaplex.fr>
yuzou <zouyu7@huawei.com> yuzou <zouyu7@huawei.com>

View File

@ -1,4 +1,8 @@
Solomon Hykes <solomon@docker.com> (@shykes) Solomon Hykes <solomon@docker.com> (@shykes)
Olivier Gambier <olivier@docker.com> (@dmp42) Olivier Gambier <olivier@docker.com> (@dmp42)
Sam Alba <sam@docker.com> (@samalba)
Stephen Day <stephen.day@docker.com> (@stevvooe) Stephen Day <stephen.day@docker.com> (@stevvooe)
Derek McGowan <derek@mcgstyle.net> (@dmcgowan)
Richard Scothern <richard.scothern@gmail.com> (@richardscothern)
Aaron Lehmann <aaron.lehmann@docker.com> (@aaronlehmann)

View File

@ -11,7 +11,7 @@ ifeq (${DISABLE_OPTIMIZATION},true)
VERSION:="$(VERSION)-noopt" VERSION:="$(VERSION)-noopt"
endif endif
GO_LDFLAGS=-ldflags "-X `go list ./version`.Version $(VERSION)" GO_LDFLAGS=-ldflags "-X `go list ./version`.Version=$(VERSION)"
.PHONY: clean all fmt vet lint build test binaries .PHONY: clean all fmt vet lint build test binaries
.DEFAULT: default .DEFAULT: default

View File

@ -3,12 +3,15 @@
The Docker toolset to pack, ship, store, and deliver content. The Docker toolset to pack, ship, store, and deliver content.
This repository's main product is the Docker Registry 2.0 implementation This repository's main product is the Docker Registry 2.0 implementation
for storing and distributing Docker images. It supersedes the [docker/docker- for storing and distributing Docker images. It supersedes the
registry](https://github.com/docker/docker-registry) project with a new API [docker/docker-registry](https://github.com/docker/docker-registry)
design, focused around security and performance. project with a new API design, focused around security and performance.
<img src="https://www.docker.com/sites/default/files/oyster-registry-3.png" width=200px/> <img src="https://www.docker.com/sites/default/files/oyster-registry-3.png" width=200px/>
[![Circle CI](https://circleci.com/gh/docker/distribution/tree/master.svg?style=svg)](https://circleci.com/gh/docker/distribution/tree/master)
[![GoDoc](https://godoc.org/github.com/docker/distribution?status.svg)](https://godoc.org/github.com/docker/distribution)
This repository contains the following components: This repository contains the following components:
|**Component** |Description | |**Component** |Description |

View File

@ -8,19 +8,15 @@ machine:
- ceph osd pool create docker-distribution 1 - ceph osd pool create docker-distribution 1
post: post:
# Install many go versions # go
# - gvm install go1.3.3 -B --name=old - gvm install go1.5 --prefer-binary --name=stable
- gvm install go1.4.2 -B --name=stable
# - gvm install tip --name=bleed
environment: environment:
# Convenient shortcuts to "common" locations # Convenient shortcuts to "common" locations
CHECKOUT: /home/ubuntu/$CIRCLE_PROJECT_REPONAME CHECKOUT: /home/ubuntu/$CIRCLE_PROJECT_REPONAME
BASE_DIR: src/github.com/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME BASE_DIR: src/github.com/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME
# Trick circle brainflat "no absolute path" behavior # Trick circle brainflat "no absolute path" behavior
BASE_OLD: ../../../$HOME/.gvm/pkgsets/old/global/$BASE_DIR
BASE_STABLE: ../../../$HOME/.gvm/pkgsets/stable/global/$BASE_DIR BASE_STABLE: ../../../$HOME/.gvm/pkgsets/stable/global/$BASE_DIR
# BASE_BLEED: ../../../$HOME/.gvm/pkgsets/bleed/global/$BASE_DIR
DOCKER_BUILDTAGS: "include_rados include_oss include_gcs" DOCKER_BUILDTAGS: "include_rados include_oss include_gcs"
# Workaround Circle parsing dumb bugs and/or YAML wonkyness # Workaround Circle parsing dumb bugs and/or YAML wonkyness
CIRCLE_PAIN: "mode: set" CIRCLE_PAIN: "mode: set"
@ -34,37 +30,22 @@ machine:
dependencies: dependencies:
pre: pre:
# Copy the code to the gopath of all go versions # Copy the code to the gopath of all go versions
# - >
# gvm use old &&
# mkdir -p "$(dirname $BASE_OLD)" &&
# cp -R "$CHECKOUT" "$BASE_OLD"
- > - >
gvm use stable && gvm use stable &&
mkdir -p "$(dirname $BASE_STABLE)" && mkdir -p "$(dirname $BASE_STABLE)" &&
cp -R "$CHECKOUT" "$BASE_STABLE" cp -R "$CHECKOUT" "$BASE_STABLE"
# - >
# gvm use bleed &&
# mkdir -p "$(dirname $BASE_BLEED)" &&
# cp -R "$CHECKOUT" "$BASE_BLEED"
override: override:
# Install dependencies for every copied clone/go version # Install dependencies for every copied clone/go version
# - gvm use old && go get github.com/tools/godep:
# pwd: $BASE_OLD
- gvm use stable && go get github.com/tools/godep: - gvm use stable && go get github.com/tools/godep:
pwd: $BASE_STABLE pwd: $BASE_STABLE
# - gvm use bleed && go get github.com/tools/godep:
# pwd: $BASE_BLEED
post: post:
# For the stable go version, additionally install linting tools # For the stable go version, additionally install linting tools
- > - >
gvm use stable && gvm use stable &&
go get github.com/axw/gocov/gocov github.com/golang/lint/golint go get github.com/axw/gocov/gocov github.com/golang/lint/golint
# Disabling goveralls for now # Disabling goveralls for now
# go get github.com/axw/gocov/gocov github.com/mattn/goveralls github.com/golang/lint/golint # go get github.com/axw/gocov/gocov github.com/mattn/goveralls github.com/golang/lint/golint
@ -73,7 +54,6 @@ test:
# Output the go versions we are going to test # Output the go versions we are going to test
# - gvm use old && go version # - gvm use old && go version
- gvm use stable && go version - gvm use stable && go version
# - gvm use bleed && go version
# First thing: build everything. This will catch compile errors, and it's # First thing: build everything. This will catch compile errors, and it's
# also necessary for go vet to work properly (see #807). # also necessary for go vet to work properly (see #807).
@ -84,7 +64,7 @@ test:
- gvm use stable && test -z "$(gofmt -s -l . | grep -v Godeps/_workspace/src/ | tee /dev/stderr)": - gvm use stable && test -z "$(gofmt -s -l . | grep -v Godeps/_workspace/src/ | tee /dev/stderr)":
pwd: $BASE_STABLE pwd: $BASE_STABLE
# VET # VET
- gvm use stable && go vet ./...: - gvm use stable && go vet ./...:
pwd: $BASE_STABLE pwd: $BASE_STABLE
@ -93,30 +73,22 @@ test:
pwd: $BASE_STABLE pwd: $BASE_STABLE
override: override:
# Test every version we have (but stable)
# - gvm use old; godep go test -test.v -test.short ./...:
# timeout: 600
# pwd: $BASE_OLD
# - gvm use bleed; go test -test.v -test.short ./...:
# timeout: 600
# pwd: $BASE_BLEED
# Test stable, and report # Test stable, and report
# Preset the goverall report file # Preset the goverall report file
- echo "$CIRCLE_PAIN" > ~/goverage.report # - echo "$CIRCLE_PAIN" > ~/goverage.report
- gvm use stable; go list ./... | xargs -L 1 -I{} rm -f $GOPATH/src/{}/coverage.out:
pwd: $BASE_STABLE - gvm use stable; go list ./... | xargs -L 1 -I{} rm -f $GOPATH/src/{}/coverage.out:
- gvm use stable; go list -tags "$DOCKER_BUILDTAGS" ./... | xargs -L 1 -I{} godep go test -tags "$DOCKER_BUILDTAGS" -test.short -coverprofile=$GOPATH/src/{}/coverage.out {}: pwd: $BASE_STABLE
timeout: 600
pwd: $BASE_STABLE - gvm use stable; go list -tags "$DOCKER_BUILDTAGS" ./... | xargs -L 1 -I{} godep go test -tags "$DOCKER_BUILDTAGS" -test.short -coverprofile=$GOPATH/src/{}/coverage.out {}:
timeout: 600
pwd: $BASE_STABLE
post: post:
# Aggregate and report to coveralls # Aggregate and report to coveralls
- gvm use stable; go list ./... | xargs -L 1 -I{} cat "$GOPATH/src/{}/coverage.out" | grep -v "$CIRCLE_PAIN" >> ~/goverage.report: - gvm use stable; go list -tags "$DOCKER_BUILDTAGS" ./... | xargs -L 1 -I{} cat "$GOPATH/src/{}/coverage.out" | grep -v "$CIRCLE_PAIN" >> ~/goverage.report:
pwd: $BASE_STABLE pwd: $BASE_STABLE
# - gvm use stable; goveralls -service circleci -coverprofile=/home/ubuntu/goverage.report -repotoken $COVERALLS_TOKEN:
# pwd: $BASE_STABLE
## Notes ## Notes
# Disabled coveralls reporting: build breaking sending coverage data to coveralls # Disabled coveralls reporting: build breaking sending coverage data to coveralls

View File

@ -58,6 +58,9 @@ var (
// ErrDigestInvalidFormat returned when digest format invalid. // ErrDigestInvalidFormat returned when digest format invalid.
ErrDigestInvalidFormat = fmt.Errorf("invalid checksum digest format") ErrDigestInvalidFormat = fmt.Errorf("invalid checksum digest format")
// ErrDigestInvalidLength returned when digest has invalid length.
ErrDigestInvalidLength = fmt.Errorf("invalid checksum digest length")
// ErrDigestUnsupported returned when the digest algorithm is unsupported. // ErrDigestUnsupported returned when the digest algorithm is unsupported.
ErrDigestUnsupported = fmt.Errorf("unsupported digest algorithm") ErrDigestUnsupported = fmt.Errorf("unsupported digest algorithm")
) )
@ -126,8 +129,11 @@ func (d Digest) Validate() error {
return ErrDigestInvalidFormat return ErrDigestInvalidFormat
} }
switch Algorithm(s[:i]) { switch algorithm := Algorithm(s[:i]); algorithm {
case SHA256, SHA384, SHA512: case SHA256, SHA384, SHA512:
if algorithm.Size()*2 != len(s[i+1:]) {
return ErrDigestInvalidLength
}
break break
default: default:
return ErrDigestUnsupported return ErrDigestUnsupported

View File

@ -54,6 +54,15 @@ func (a Algorithm) String() string {
return string(a) return string(a)
} }
// Size returns number of bytes returned by the hash.
func (a Algorithm) Size() int {
h, ok := algorithms[a]
if !ok {
return 0
}
return h.Size()
}
// Set implemented to allow use of Algorithm as a command line flag. // Set implemented to allow use of Algorithm as a command line flag.
func (a *Algorithm) Set(value string) error { func (a *Algorithm) Set(value string) error {
if value == "" { if value == "" {

View File

@ -89,3 +89,14 @@ type ErrManifestBlobUnknown struct {
func (err ErrManifestBlobUnknown) Error() string { func (err ErrManifestBlobUnknown) Error() string {
return fmt.Sprintf("unknown blob %v on manifest", err.Digest) return fmt.Sprintf("unknown blob %v on manifest", err.Digest)
} }
// ErrManifestNameInvalid should be used to denote an invalid manifest
// name. Reason may set, indicating the cause of invalidity.
type ErrManifestNameInvalid struct {
Name string
Reason error
}
func (err ErrManifestNameInvalid) Error() string {
return fmt.Sprintf("manifest name %q invalid: %v", err.Name, err.Reason)
}

View File

@ -7,7 +7,7 @@
// //
// // repository.go // // repository.go
// repository := hostname ['/' component]+ // repository := hostname ['/' component]+
// hostname := hostcomponent [':' port-number] // hostname := hostcomponent [':' port-number]
// component := subcomponent [separator subcomponent]* // component := subcomponent [separator subcomponent]*
// subcomponent := alpha-numeric ['-'* alpha-numeric]* // subcomponent := alpha-numeric ['-'* alpha-numeric]*
// hostcomponent := [hostpart '.']* hostpart // hostcomponent := [hostpart '.']* hostpart
@ -24,7 +24,7 @@
// digest-algorithm := digest-algorithm-component [ digest-algorithm-separator digest-algorithm-component ] // digest-algorithm := digest-algorithm-component [ digest-algorithm-separator digest-algorithm-component ]
// digest-algorithm-separator := /[+.-_]/ // digest-algorithm-separator := /[+.-_]/
// digest-algorithm-component := /[A-Za-z][A-Za-z0-9]*/ // digest-algorithm-component := /[A-Za-z][A-Za-z0-9]*/
// digest-hex := /[0-9a-fA-F]{32,}/ ; Atleast 128 bit digest value // digest-hex := /[0-9a-fA-F]{32,}/ ; At least 128 bit digest value
package reference package reference
import ( import (

View File

@ -391,17 +391,18 @@ func (bs *blobs) Get(ctx context.Context, dgst digest.Digest) ([]byte, error) {
} }
func (bs *blobs) Open(ctx context.Context, dgst digest.Digest) (distribution.ReadSeekCloser, error) { func (bs *blobs) Open(ctx context.Context, dgst digest.Digest) (distribution.ReadSeekCloser, error) {
stat, err := bs.statter.Stat(ctx, dgst) blobURL, err := bs.ub.BuildBlobURL(bs.name, dgst)
if err != nil { if err != nil {
return nil, err return nil, err
} }
blobURL, err := bs.ub.BuildBlobURL(bs.name, stat.Digest) return transport.NewHTTPReadSeeker(bs.client, blobURL,
if err != nil { func(resp *http.Response) error {
return nil, err if resp.StatusCode == http.StatusNotFound {
} return distribution.ErrBlobUnknown
}
return transport.NewHTTPReadSeeker(bs.client, blobURL, stat.Size), nil return handleErrorResponse(resp)
}), nil
} }
func (bs *blobs) ServeBlob(ctx context.Context, w http.ResponseWriter, r *http.Request, dgst digest.Digest) error { func (bs *blobs) ServeBlob(ctx context.Context, w http.ResponseWriter, r *http.Request, dgst digest.Digest) error {

View File

@ -2,11 +2,9 @@ package transport
import ( import (
"bufio" "bufio"
"bytes"
"errors" "errors"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"net/http" "net/http"
"os" "os"
) )
@ -21,11 +19,11 @@ type ReadSeekCloser interface {
// request. When seeking and starting a read from a non-zero offset // request. When seeking and starting a read from a non-zero offset
// the a "Range" header will be added which sets the offset. // the a "Range" header will be added which sets the offset.
// TODO(dmcgowan): Move this into a separate utility package // TODO(dmcgowan): Move this into a separate utility package
func NewHTTPReadSeeker(client *http.Client, url string, size int64) ReadSeekCloser { func NewHTTPReadSeeker(client *http.Client, url string, errorHandler func(*http.Response) error) ReadSeekCloser {
return &httpReadSeeker{ return &httpReadSeeker{
client: client, client: client,
url: url, url: url,
size: size, errorHandler: errorHandler,
} }
} }
@ -33,12 +31,26 @@ type httpReadSeeker struct {
client *http.Client client *http.Client
url string url string
// errorHandler creates an error from an unsuccessful HTTP response.
// This allows the error to be created with the HTTP response body
// without leaking the body through a returned error.
errorHandler func(*http.Response) error
size int64 size int64
rc io.ReadCloser // remote read closer // rc is the remote read closer.
brd *bufio.Reader // internal buffered io rc io.ReadCloser
offset int64 // brd is a buffer for internal buffered io.
err error brd *bufio.Reader
// readerOffset tracks the offset as of the last read.
readerOffset int64
// seekOffset allows Seek to override the offset. Seek changes
// seekOffset instead of changing readOffset directly so that
// connection resets can be delayed and possibly avoided if the
// seek is undone (i.e. seeking to the end and then back to the
// beginning).
seekOffset int64
err error
} }
func (hrs *httpReadSeeker) Read(p []byte) (n int, err error) { func (hrs *httpReadSeeker) Read(p []byte) (n int, err error) {
@ -46,16 +58,29 @@ func (hrs *httpReadSeeker) Read(p []byte) (n int, err error) {
return 0, hrs.err return 0, hrs.err
} }
// If we seeked to a different position, we need to reset the
// connection. This logic is here instead of Seek so that if
// a seek is undone before the next read, the connection doesn't
// need to be closed and reopened. A common example of this is
// seeking to the end to determine the length, and then seeking
// back to the original position.
if hrs.readerOffset != hrs.seekOffset {
hrs.reset()
}
hrs.readerOffset = hrs.seekOffset
rd, err := hrs.reader() rd, err := hrs.reader()
if err != nil { if err != nil {
return 0, err return 0, err
} }
n, err = rd.Read(p) n, err = rd.Read(p)
hrs.offset += int64(n) hrs.seekOffset += int64(n)
hrs.readerOffset += int64(n)
// Simulate io.EOF error if we reach filesize. // Simulate io.EOF error if we reach filesize.
if err == nil && hrs.offset >= hrs.size { if err == nil && hrs.size >= 0 && hrs.readerOffset >= hrs.size {
err = io.EOF err = io.EOF
} }
@ -67,13 +92,20 @@ func (hrs *httpReadSeeker) Seek(offset int64, whence int) (int64, error) {
return 0, hrs.err return 0, hrs.err
} }
var err error _, err := hrs.reader()
newOffset := hrs.offset if err != nil {
return 0, err
}
newOffset := hrs.seekOffset
switch whence { switch whence {
case os.SEEK_CUR: case os.SEEK_CUR:
newOffset += int64(offset) newOffset += int64(offset)
case os.SEEK_END: case os.SEEK_END:
if hrs.size < 0 {
return 0, errors.New("content length not known")
}
newOffset = hrs.size + int64(offset) newOffset = hrs.size + int64(offset)
case os.SEEK_SET: case os.SEEK_SET:
newOffset = int64(offset) newOffset = int64(offset)
@ -82,15 +114,10 @@ func (hrs *httpReadSeeker) Seek(offset int64, whence int) (int64, error) {
if newOffset < 0 { if newOffset < 0 {
err = errors.New("cannot seek to negative position") err = errors.New("cannot seek to negative position")
} else { } else {
if hrs.offset != newOffset { hrs.seekOffset = newOffset
hrs.reset()
}
// No problems, set the offset.
hrs.offset = newOffset
} }
return hrs.offset, err return hrs.seekOffset, err
} }
func (hrs *httpReadSeeker) Close() error { func (hrs *httpReadSeeker) Close() error {
@ -130,17 +157,12 @@ func (hrs *httpReadSeeker) reader() (io.Reader, error) {
return hrs.brd, nil return hrs.brd, nil
} }
// If the offset is great than or equal to size, return a empty, noop reader.
if hrs.offset >= hrs.size {
return ioutil.NopCloser(bytes.NewReader([]byte{})), nil
}
req, err := http.NewRequest("GET", hrs.url, nil) req, err := http.NewRequest("GET", hrs.url, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if hrs.offset > 0 { if hrs.readerOffset > 0 {
// TODO(stevvooe): Get this working correctly. // TODO(stevvooe): Get this working correctly.
// If we are at different offset, issue a range request from there. // If we are at different offset, issue a range request from there.
@ -158,8 +180,16 @@ func (hrs *httpReadSeeker) reader() (io.Reader, error) {
// import // import
if resp.StatusCode >= 200 && resp.StatusCode <= 399 { if resp.StatusCode >= 200 && resp.StatusCode <= 399 {
hrs.rc = resp.Body hrs.rc = resp.Body
if resp.StatusCode == http.StatusOK {
hrs.size = resp.ContentLength
} else {
hrs.size = -1
}
} else { } else {
defer resp.Body.Close() defer resp.Body.Close()
if hrs.errorHandler != nil {
return nil, hrs.errorHandler(resp)
}
return nil, fmt.Errorf("unexpected status resolving reader: %v", resp.Status) return nil, fmt.Errorf("unexpected status resolving reader: %v", resp.Status)
} }