diff --git a/blobs.go b/blobs.go index 1f91ae21e..79c5fb33b 100644 --- a/blobs.go +++ b/blobs.go @@ -8,8 +8,8 @@ import ( "time" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" + "github.com/opencontainers/go-digest" ) var ( diff --git a/cmd/digest/main.go b/cmd/digest/main.go index 49426a886..9582d197f 100644 --- a/cmd/digest/main.go +++ b/cmd/digest/main.go @@ -7,8 +7,8 @@ import ( "log" "os" - "github.com/docker/distribution/digest" "github.com/docker/distribution/version" + "github.com/opencontainers/go-digest" ) var ( diff --git a/digest/algorithm.go b/digest/algorithm.go deleted file mode 100644 index e4842d9d6..000000000 --- a/digest/algorithm.go +++ /dev/null @@ -1,149 +0,0 @@ -package digest - -import ( - "crypto" - "fmt" - "hash" - "io" -) - -// Algorithm identifies and implementation of a digester by an identifier. -// Note the that this defines both the hash algorithm used and the string -// encoding. -type Algorithm string - -// supported digest types -const ( - SHA256 Algorithm = "sha256" // sha256 with hex encoding - SHA384 Algorithm = "sha384" // sha384 with hex encoding - SHA512 Algorithm = "sha512" // sha512 with hex encoding - - // Canonical is the primary digest algorithm used with the distribution - // project. Other digests may be used but this one is the primary storage - // digest. - Canonical = SHA256 -) - -var ( - // TODO(stevvooe): Follow the pattern of the standard crypto package for - // registration of digests. Effectively, we are a registerable set and - // common symbol access. - - // algorithms maps values to hash.Hash implementations. Other algorithms - // may be available but they cannot be calculated by the digest package. - algorithms = map[Algorithm]crypto.Hash{ - SHA256: crypto.SHA256, - SHA384: crypto.SHA384, - SHA512: crypto.SHA512, - } -) - -// Available returns true if the digest type is available for use. If this -// returns false, New and Hash will return nil. -func (a Algorithm) Available() bool { - h, ok := algorithms[a] - if !ok { - return false - } - - // check availability of the hash, as well - return h.Available() -} - -func (a Algorithm) String() string { - 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. -func (a *Algorithm) Set(value string) error { - if value == "" { - *a = Canonical - } else { - // just do a type conversion, support is queried with Available. - *a = Algorithm(value) - } - - if !a.Available() { - return ErrDigestUnsupported - } - - return nil -} - -// Digester returns a new digester for the specified algorithm. If the algorithm -// does not have a digester implementation, nil will be returned. This can be -// checked by calling Available before calling New. -func (a Algorithm) Digester() Digester { - return &digester{ - alg: a, - hash: a.Hash(), - } -} - -// New is deprecated. Use Algorithm.Digester. -func (a Algorithm) New() Digester { - return a.Digester() -} - -// Hash returns a new hash as used by the algorithm. If not available, the -// method will panic. Check Algorithm.Available() before calling. -func (a Algorithm) Hash() hash.Hash { - if !a.Available() { - // Empty algorithm string is invalid - if a == "" { - panic(fmt.Sprintf("empty digest algorithm, validate before calling Algorithm.Hash()")) - } - - // NOTE(stevvooe): A missing hash is usually a programming error that - // must be resolved at compile time. We don't import in the digest - // package to allow users to choose their hash implementation (such as - // when using stevvooe/resumable or a hardware accelerated package). - // - // Applications that may want to resolve the hash at runtime should - // call Algorithm.Available before call Algorithm.Hash(). - panic(fmt.Sprintf("%v not available (make sure it is imported)", a)) - } - - return algorithms[a].New() -} - -// FromReader returns the digest of the reader using the algorithm. -func (a Algorithm) FromReader(rd io.Reader) (Digest, error) { - digester := a.New() - - if _, err := io.Copy(digester.Hash(), rd); err != nil { - return "", err - } - - return digester.Digest(), nil -} - -// FromBytes digests the input and returns a Digest. -func (a Algorithm) FromBytes(p []byte) Digest { - digester := a.New() - - if _, err := digester.Hash().Write(p); err != nil { - // Writes to a Hash should never fail. None of the existing - // hash implementations in the stdlib or hashes vendored - // here can return errors from Write. Having a panic in this - // condition instead of having FromBytes return an error value - // avoids unnecessary error handling paths in all callers. - panic("write to hash function returned error: " + err.Error()) - } - - return digester.Digest() -} - -// FromString digests the string input and returns a Digest. -func (a Algorithm) FromString(s string) Digest { - return a.FromBytes([]byte(s)) -} diff --git a/digest/algorithm_test.go b/digest/algorithm_test.go deleted file mode 100644 index 12db5d13c..000000000 --- a/digest/algorithm_test.go +++ /dev/null @@ -1,100 +0,0 @@ -package digest - -import ( - "bytes" - "crypto/rand" - _ "crypto/sha256" - _ "crypto/sha512" - "flag" - "fmt" - "strings" - "testing" -) - -func TestFlagInterface(t *testing.T) { - var ( - alg Algorithm - flagSet flag.FlagSet - ) - - flagSet.Var(&alg, "algorithm", "set the digest algorithm") - for _, testcase := range []struct { - Name string - Args []string - Err error - Expected Algorithm - }{ - { - Name: "Invalid", - Args: []string{"-algorithm", "bean"}, - Err: ErrDigestUnsupported, - }, - { - Name: "Default", - Args: []string{"unrelated"}, - Expected: "sha256", - }, - { - Name: "Other", - Args: []string{"-algorithm", "sha512"}, - Expected: "sha512", - }, - } { - t.Run(testcase.Name, func(t *testing.T) { - alg = Canonical - if err := flagSet.Parse(testcase.Args); err != testcase.Err { - if testcase.Err == nil { - t.Fatal("unexpected error", err) - } - - // check that flag package returns correct error - if !strings.Contains(err.Error(), testcase.Err.Error()) { - t.Fatalf("unexpected error: %v != %v", err, testcase.Err) - } - return - } - - if alg != testcase.Expected { - t.Fatalf("unexpected algorithm: %v != %v", alg, testcase.Expected) - } - }) - } -} - -func TestFroms(t *testing.T) { - p := make([]byte, 1<<20) - rand.Read(p) - - for alg := range algorithms { - h := alg.Hash() - h.Write(p) - expected := Digest(fmt.Sprintf("%s:%x", alg, h.Sum(nil))) - readerDgst, err := alg.FromReader(bytes.NewReader(p)) - if err != nil { - t.Fatalf("error calculating hash from reader: %v", err) - } - - dgsts := []Digest{ - alg.FromBytes(p), - alg.FromString(string(p)), - readerDgst, - } - - if alg == Canonical { - readerDgst, err := FromReader(bytes.NewReader(p)) - if err != nil { - t.Fatalf("error calculating hash from reader: %v", err) - } - - dgsts = append(dgsts, - FromBytes(p), - FromString(string(p)), - readerDgst) - } - for _, dgst := range dgsts { - if dgst != expected { - t.Fatalf("unexpected digest %v != %v", dgst, expected) - } - } - } -} diff --git a/digest/digest.go b/digest/digest.go deleted file mode 100644 index df97fd016..000000000 --- a/digest/digest.go +++ /dev/null @@ -1,151 +0,0 @@ -package digest - -import ( - "fmt" - "hash" - "io" - "regexp" - "strings" -) - -const ( - // DigestSha256EmptyTar is the canonical sha256 digest of empty data - DigestSha256EmptyTar = "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" -) - -// Digest allows simple protection of hex formatted digest strings, prefixed -// by their algorithm. Strings of type Digest have some guarantee of being in -// the correct format and it provides quick access to the components of a -// digest string. -// -// The following is an example of the contents of Digest types: -// -// sha256:7173b809ca12ec5dee4506cd86be934c4596dd234ee82c0662eac04a8c2c71dc -// -// This allows to abstract the digest behind this type and work only in those -// terms. -type Digest string - -// NewDigest returns a Digest from alg and a hash.Hash object. -func NewDigest(alg Algorithm, h hash.Hash) Digest { - return NewDigestFromBytes(alg, h.Sum(nil)) -} - -// NewDigestFromBytes returns a new digest from the byte contents of p. -// Typically, this can come from hash.Hash.Sum(...) or xxx.SumXXX(...) -// functions. This is also useful for rebuilding digests from binary -// serializations. -func NewDigestFromBytes(alg Algorithm, p []byte) Digest { - return Digest(fmt.Sprintf("%s:%x", alg, p)) -} - -// NewDigestFromHex returns a Digest from alg and a the hex encoded digest. -func NewDigestFromHex(alg, hex string) Digest { - return Digest(fmt.Sprintf("%s:%s", alg, hex)) -} - -// DigestRegexp matches valid digest types. -var DigestRegexp = regexp.MustCompile(`[a-zA-Z0-9-_+.]+:[a-fA-F0-9]+`) - -// DigestRegexpAnchored matches valid digest types, anchored to the start and end of the match. -var DigestRegexpAnchored = regexp.MustCompile(`^` + DigestRegexp.String() + `$`) - -var ( - // ErrDigestInvalidFormat returned when digest format invalid. - 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 = fmt.Errorf("unsupported digest algorithm") -) - -// Parse parses s and returns the validated digest object. An error will -// be returned if the format is invalid. -func Parse(s string) (Digest, error) { - d := Digest(s) - return d, d.Validate() -} - -// ParseDigest is deprecated. Use Parse. -func ParseDigest(s string) (Digest, error) { - return Parse(s) -} - -// FromReader returns the most valid digest for the underlying content using -// the canonical digest algorithm. -func FromReader(rd io.Reader) (Digest, error) { - return Canonical.FromReader(rd) -} - -// FromBytes digests the input and returns a Digest. -func FromBytes(p []byte) Digest { - return Canonical.FromBytes(p) -} - -// FromString digests the input and returns a Digest. -func FromString(s string) Digest { - return Canonical.FromString(s) -} - -// Validate checks that the contents of d is a valid digest, returning an -// error if not. -func (d Digest) Validate() error { - s := string(d) - - i := strings.Index(s, ":") - - // validate i then run through regexp - if i < 0 || i+1 == len(s) || !DigestRegexpAnchored.MatchString(s) { - return ErrDigestInvalidFormat - } - - algorithm := Algorithm(s[:i]) - if !algorithm.Available() { - return ErrDigestUnsupported - } - - // Digests much always be hex-encoded, ensuring that their hex portion will - // always be size*2 - if algorithm.Size()*2 != len(s[i+1:]) { - return ErrDigestInvalidLength - } - - return nil -} - -// Algorithm returns the algorithm portion of the digest. This will panic if -// the underlying digest is not in a valid format. -func (d Digest) Algorithm() Algorithm { - return Algorithm(d[:d.sepIndex()]) -} - -// Verifier returns a writer object that can be used to verify a stream of -// content against the digest. If the digest is invalid, the method will panic. -func (d Digest) Verifier() Verifier { - return hashVerifier{ - hash: d.Algorithm().Hash(), - digest: d, - } -} - -// Hex returns the hex digest portion of the digest. This will panic if the -// underlying digest is not in a valid format. -func (d Digest) Hex() string { - return string(d[d.sepIndex()+1:]) -} - -func (d Digest) String() string { - return string(d) -} - -func (d Digest) sepIndex() int { - i := strings.Index(string(d), ":") - - if i < 0 { - panic(fmt.Sprintf("no ':' separator in digest %q", d)) - } - - return i -} diff --git a/digest/digest_test.go b/digest/digest_test.go deleted file mode 100644 index d85c476f3..000000000 --- a/digest/digest_test.go +++ /dev/null @@ -1,92 +0,0 @@ -package digest - -import ( - "testing" -) - -func TestParseDigest(t *testing.T) { - for _, testcase := range []struct { - input string - err error - algorithm Algorithm - hex string - }{ - { - input: "sha256:e58fcf7418d4390dec8e8fb69d88c06ec07039d651fedd3aa72af9972e7d046b", - algorithm: "sha256", - hex: "e58fcf7418d4390dec8e8fb69d88c06ec07039d651fedd3aa72af9972e7d046b", - }, - { - input: "sha384:d3fc7881460b7e22e3d172954463dddd7866d17597e7248453c48b3e9d26d9596bf9c4a9cf8072c9d5bad76e19af801d", - algorithm: "sha384", - hex: "d3fc7881460b7e22e3d172954463dddd7866d17597e7248453c48b3e9d26d9596bf9c4a9cf8072c9d5bad76e19af801d", - }, - { - // empty hex - input: "sha256:", - err: ErrDigestInvalidFormat, - }, - { - // empty hex - input: ":", - err: ErrDigestInvalidFormat, - }, - { - // just hex - input: "d41d8cd98f00b204e9800998ecf8427e", - err: ErrDigestInvalidFormat, - }, - { - // not hex - input: "sha256:d41d8cd98f00b204e9800m98ecf8427e", - err: ErrDigestInvalidFormat, - }, - { - // too short - input: "sha256:abcdef0123456789", - err: ErrDigestInvalidLength, - }, - { - // too short (from different algorithm) - input: "sha512:abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789", - err: ErrDigestInvalidLength, - }, - { - input: "foo:d41d8cd98f00b204e9800998ecf8427e", - err: ErrDigestUnsupported, - }, - } { - digest, err := Parse(testcase.input) - if err != testcase.err { - t.Fatalf("error differed from expected while parsing %q: %v != %v", testcase.input, err, testcase.err) - } - - if testcase.err != nil { - continue - } - - if digest.Algorithm() != testcase.algorithm { - t.Fatalf("incorrect algorithm for parsed digest: %q != %q", digest.Algorithm(), testcase.algorithm) - } - - if digest.Hex() != testcase.hex { - t.Fatalf("incorrect hex for parsed digest: %q != %q", digest.Hex(), testcase.hex) - } - - // Parse string return value and check equality - newParsed, err := Parse(digest.String()) - - if err != nil { - t.Fatalf("unexpected error parsing input %q: %v", testcase.input, err) - } - - if newParsed != digest { - t.Fatalf("expected equal: %q != %q", newParsed, digest) - } - - newFromHex := NewDigestFromHex(newParsed.Algorithm().String(), newParsed.Hex()) - if newFromHex != digest { - t.Fatalf("%v != %v", newFromHex, digest) - } - } -} diff --git a/digest/digester.go b/digest/digester.go deleted file mode 100644 index 918a3f919..000000000 --- a/digest/digester.go +++ /dev/null @@ -1,25 +0,0 @@ -package digest - -import "hash" - -// Digester calculates the digest of written data. Writes should go directly -// to the return value of Hash, while calling Digest will return the current -// value of the digest. -type Digester interface { - Hash() hash.Hash // provides direct access to underlying hash instance. - Digest() Digest -} - -// digester provides a simple digester definition that embeds a hasher. -type digester struct { - alg Algorithm - hash hash.Hash -} - -func (d *digester) Hash() hash.Hash { - return d.hash -} - -func (d *digester) Digest() Digest { - return NewDigest(d.alg, d.hash) -} diff --git a/digest/doc.go b/digest/doc.go deleted file mode 100644 index f64b0db32..000000000 --- a/digest/doc.go +++ /dev/null @@ -1,42 +0,0 @@ -// Package digest provides a generalized type to opaquely represent message -// digests and their operations within the registry. The Digest type is -// designed to serve as a flexible identifier in a content-addressable system. -// More importantly, it provides tools and wrappers to work with -// hash.Hash-based digests with little effort. -// -// Basics -// -// The format of a digest is simply a string with two parts, dubbed the -// "algorithm" and the "digest", separated by a colon: -// -// : -// -// An example of a sha256 digest representation follows: -// -// sha256:7173b809ca12ec5dee4506cd86be934c4596dd234ee82c0662eac04a8c2c71dc -// -// In this case, the string "sha256" is the algorithm and the hex bytes are -// the "digest". -// -// Because the Digest type is simply a string, once a valid Digest is -// obtained, comparisons are cheap, quick and simple to express with the -// standard equality operator. -// -// Verification -// -// The main benefit of using the Digest type is simple verification against a -// given digest. The Verifier interface, modeled after the stdlib hash.Hash -// interface, provides a common write sink for digest verification. After -// writing is complete, calling the Verifier.Verified method will indicate -// whether or not the stream of bytes matches the target digest. -// -// Missing Features -// -// In addition to the above, we intend to add the following features to this -// package: -// -// 1. A Digester type that supports write sink digest calculation. -// -// 2. Suspend and resume of ongoing digest calculations to support efficient digest verification in the registry. -// -package digest diff --git a/digest/verifiers.go b/digest/verifiers.go deleted file mode 100644 index df9872cf0..000000000 --- a/digest/verifiers.go +++ /dev/null @@ -1,36 +0,0 @@ -package digest - -import ( - "hash" - "io" -) - -// Verifier presents a general verification interface to be used with message -// digests and other byte stream verifications. Users instantiate a Verifier -// from one of the various methods, write the data under test to it then check -// the result with the Verified method. -type Verifier interface { - io.Writer - - // Verified will return true if the content written to Verifier matches - // the digest. - Verified() bool -} - -// NewDigestVerifier is deprecated. Please use Digest.Verifier. -func NewDigestVerifier(d Digest) (Verifier, error) { - return d.Verifier(), nil -} - -type hashVerifier struct { - digest Digest - hash hash.Hash -} - -func (hv hashVerifier) Write(p []byte) (n int, err error) { - return hv.hash.Write(p) -} - -func (hv hashVerifier) Verified() bool { - return hv.digest == NewDigest(hv.digest.Algorithm(), hv.hash) -} diff --git a/digest/verifiers_test.go b/digest/verifiers_test.go deleted file mode 100644 index 251d4fce5..000000000 --- a/digest/verifiers_test.go +++ /dev/null @@ -1,66 +0,0 @@ -package digest - -import ( - "bytes" - "crypto/rand" - "io" - "reflect" - "testing" -) - -func TestDigestVerifier(t *testing.T) { - p := make([]byte, 1<<20) - rand.Read(p) - digest := FromBytes(p) - - verifier := digest.Verifier() - - io.Copy(verifier, bytes.NewReader(p)) - - if !verifier.Verified() { - t.Fatalf("bytes not verified") - } -} - -// TestVerifierUnsupportedDigest ensures that unsupported digest validation is -// flowing through verifier creation. -func TestVerifierUnsupportedDigest(t *testing.T) { - for _, testcase := range []struct { - Name string - Digest Digest - Expected interface{} // expected panic target - }{ - { - Name: "Empty", - Digest: "", - Expected: "no ':' separator in digest \"\"", - }, - { - Name: "EmptyAlg", - Digest: ":", - Expected: "empty digest algorithm, validate before calling Algorithm.Hash()", - }, - { - Name: "Unsupported", - Digest: Digest("bean:0123456789abcdef"), - Expected: "bean not available (make sure it is imported)", - }, - { - Name: "Garbage", - Digest: Digest("sha256-garbage:pure"), - Expected: "sha256-garbage not available (make sure it is imported)", - }, - } { - t.Run(testcase.Name, func(t *testing.T) { - expected := testcase.Expected - defer func() { - recovered := recover() - if !reflect.DeepEqual(recovered, expected) { - t.Fatalf("unexpected recover: %v != %v", recovered, expected) - } - }() - - _ = testcase.Digest.Verifier() - }) - } -} diff --git a/digest/set.go b/digestset/set.go similarity index 90% rename from digest/set.go rename to digestset/set.go index 6074080fb..71327dca7 100644 --- a/digest/set.go +++ b/digestset/set.go @@ -1,10 +1,12 @@ -package digest +package digestset import ( "errors" "sort" "strings" "sync" + + digest "github.com/opencontainers/go-digest" ) var ( @@ -44,7 +46,7 @@ func NewSet() *Set { // values or short values. This function does not test equality, // rather whether the second value could match against the first // value. -func checkShortMatch(alg Algorithm, hex, shortAlg, shortHex string) bool { +func checkShortMatch(alg digest.Algorithm, hex, shortAlg, shortHex string) bool { if len(hex) == len(shortHex) { if hex != shortHex { return false @@ -64,7 +66,7 @@ func checkShortMatch(alg Algorithm, hex, shortAlg, shortHex string) bool { // If no digests could be found ErrDigestNotFound will be returned // with an empty digest value. If multiple matches are found // ErrDigestAmbiguous will be returned with an empty digest value. -func (dst *Set) Lookup(d string) (Digest, error) { +func (dst *Set) Lookup(d string) (digest.Digest, error) { dst.mutex.RLock() defer dst.mutex.RUnlock() if len(dst.entries) == 0 { @@ -72,11 +74,11 @@ func (dst *Set) Lookup(d string) (Digest, error) { } var ( searchFunc func(int) bool - alg Algorithm + alg digest.Algorithm hex string ) - dgst, err := Parse(d) - if err == ErrDigestInvalidFormat { + dgst, err := digest.Parse(d) + if err == digest.ErrDigestInvalidFormat { hex = d searchFunc = func(i int) bool { return dst.entries[i].val >= d @@ -108,7 +110,7 @@ func (dst *Set) Lookup(d string) (Digest, error) { // Add adds the given digest to the set. An error will be returned // if the given digest is invalid. If the digest already exists in the // set, this operation will be a no-op. -func (dst *Set) Add(d Digest) error { +func (dst *Set) Add(d digest.Digest) error { if err := d.Validate(); err != nil { return err } @@ -139,7 +141,7 @@ func (dst *Set) Add(d Digest) error { // Remove removes the given digest from the set. An err will be // returned if the given digest is invalid. If the digest does // not exist in the set, this operation will be a no-op. -func (dst *Set) Remove(d Digest) error { +func (dst *Set) Remove(d digest.Digest) error { if err := d.Validate(); err != nil { return err } @@ -167,10 +169,10 @@ func (dst *Set) Remove(d Digest) error { } // All returns all the digests in the set -func (dst *Set) All() []Digest { +func (dst *Set) All() []digest.Digest { dst.mutex.RLock() defer dst.mutex.RUnlock() - retValues := make([]Digest, len(dst.entries)) + retValues := make([]digest.Digest, len(dst.entries)) for i := range dst.entries { retValues[i] = dst.entries[i].digest } @@ -183,10 +185,10 @@ func (dst *Set) All() []Digest { // entire value of digest if uniqueness cannot be achieved without the // full value. This function will attempt to make short codes as short // as possible to be unique. -func ShortCodeTable(dst *Set, length int) map[Digest]string { +func ShortCodeTable(dst *Set, length int) map[digest.Digest]string { dst.mutex.RLock() defer dst.mutex.RUnlock() - m := make(map[Digest]string, len(dst.entries)) + m := make(map[digest.Digest]string, len(dst.entries)) l := length resetIdx := 0 for i := 0; i < len(dst.entries); i++ { @@ -222,9 +224,9 @@ func ShortCodeTable(dst *Set, length int) map[Digest]string { } type digestEntry struct { - alg Algorithm + alg digest.Algorithm val string - digest Digest + digest digest.Digest } type digestEntries []*digestEntry diff --git a/digest/set_test.go b/digestset/set_test.go similarity index 93% rename from digest/set_test.go rename to digestset/set_test.go index e9dab8795..89c5729d0 100644 --- a/digest/set_test.go +++ b/digestset/set_test.go @@ -1,20 +1,23 @@ -package digest +package digestset import ( "crypto/sha256" + _ "crypto/sha512" "encoding/binary" "math/rand" "testing" + + digest "github.com/opencontainers/go-digest" ) -func assertEqualDigests(t *testing.T, d1, d2 Digest) { +func assertEqualDigests(t *testing.T, d1, d2 digest.Digest) { if d1 != d2 { t.Fatalf("Digests do not match:\n\tActual: %s\n\tExpected: %s", d1, d2) } } func TestLookup(t *testing.T) { - digests := []Digest{ + digests := []digest.Digest{ "sha256:1234511111111111111111111111111111111111111111111111111111111111", "sha256:1234111111111111111111111111111111111111111111111111111111111111", "sha256:1234611111111111111111111111111111111111111111111111111111111111", @@ -88,7 +91,7 @@ func TestLookup(t *testing.T) { } func TestAddDuplication(t *testing.T) { - digests := []Digest{ + digests := []digest.Digest{ "sha256:1234111111111111111111111111111111111111111111111111111111111111", "sha256:1234511111111111111111111111111111111111111111111111111111111111", "sha256:1234611111111111111111111111111111111111111111111111111111111111", @@ -110,7 +113,7 @@ func TestAddDuplication(t *testing.T) { t.Fatal("Invalid dset size") } - if err := dset.Add(Digest("sha256:1234511111111111111111111111111111111111111111111111111111111111")); err != nil { + if err := dset.Add(digest.Digest("sha256:1234511111111111111111111111111111111111111111111111111111111111")); err != nil { t.Fatal(err) } @@ -118,7 +121,7 @@ func TestAddDuplication(t *testing.T) { t.Fatal("Duplicate digest insert allowed") } - if err := dset.Add(Digest("sha384:123451111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")); err != nil { + if err := dset.Add(digest.Digest("sha384:123451111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")); err != nil { t.Fatal(err) } @@ -170,7 +173,7 @@ func TestAll(t *testing.T) { } } - all := map[Digest]struct{}{} + all := map[digest.Digest]struct{}{} for _, dgst := range dset.All() { all[dgst] = struct{}{} } @@ -194,7 +197,7 @@ func assertEqualShort(t *testing.T, actual, expected string) { } func TestShortCodeTable(t *testing.T) { - digests := []Digest{ + digests := []digest.Digest{ "sha256:1234111111111111111111111111111111111111111111111111111111111111", "sha256:1234511111111111111111111111111111111111111111111111111111111111", "sha256:1234611111111111111111111111111111111111111111111111111111111111", @@ -227,15 +230,15 @@ func TestShortCodeTable(t *testing.T) { assertEqualShort(t, dump[digests[7]], "653") } -func createDigests(count int) ([]Digest, error) { +func createDigests(count int) ([]digest.Digest, error) { r := rand.New(rand.NewSource(25823)) - digests := make([]Digest, count) + digests := make([]digest.Digest, count) for i := range digests { h := sha256.New() if err := binary.Write(h, binary.BigEndian, r.Int63()); err != nil { return nil, err } - digests[i] = NewDigest("sha256", h) + digests[i] = digest.NewDigest("sha256", h) } return digests, nil } diff --git a/errors.go b/errors.go index c20f28113..2062a06fb 100644 --- a/errors.go +++ b/errors.go @@ -5,7 +5,7 @@ import ( "fmt" "strings" - "github.com/docker/distribution/digest" + "github.com/opencontainers/go-digest" ) // ErrAccessDenied is returned when an access to a requested resource is diff --git a/manifest/manifestlist/manifestlist.go b/manifest/manifestlist/manifestlist.go index a2082ec02..7a8cabbdb 100644 --- a/manifest/manifestlist/manifestlist.go +++ b/manifest/manifestlist/manifestlist.go @@ -6,8 +6,8 @@ import ( "fmt" "github.com/docker/distribution" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" + "github.com/opencontainers/go-digest" ) // MediaTypeManifestList specifies the mediaType for manifest lists. diff --git a/manifest/schema1/config_builder.go b/manifest/schema1/config_builder.go index 7e30eedea..9d222566c 100644 --- a/manifest/schema1/config_builder.go +++ b/manifest/schema1/config_builder.go @@ -9,10 +9,10 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" "github.com/docker/distribution/reference" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) type diffID digest.Digest diff --git a/manifest/schema1/config_builder_test.go b/manifest/schema1/config_builder_test.go index 5f9abaa9f..01f56e8b7 100644 --- a/manifest/schema1/config_builder_test.go +++ b/manifest/schema1/config_builder_test.go @@ -9,9 +9,9 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) type mockBlobService struct { diff --git a/manifest/schema1/manifest.go b/manifest/schema1/manifest.go index bff47bde0..65042a75f 100644 --- a/manifest/schema1/manifest.go +++ b/manifest/schema1/manifest.go @@ -5,9 +5,9 @@ import ( "fmt" "github.com/docker/distribution" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) const ( diff --git a/manifest/schema1/reference_builder.go b/manifest/schema1/reference_builder.go index fc1045f9e..ae4014781 100644 --- a/manifest/schema1/reference_builder.go +++ b/manifest/schema1/reference_builder.go @@ -6,10 +6,10 @@ import ( "errors" "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" "github.com/docker/distribution/reference" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) // referenceManifestBuilder is a type for constructing manifests from schema1 diff --git a/manifest/schema1/reference_builder_test.go b/manifest/schema1/reference_builder_test.go index 35db28e46..0f4d9477c 100644 --- a/manifest/schema1/reference_builder_test.go +++ b/manifest/schema1/reference_builder_test.go @@ -4,10 +4,10 @@ import ( "testing" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" "github.com/docker/distribution/reference" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) func makeSignedManifest(t *testing.T, pk libtrust.PrivateKey, refs []Reference) *SignedManifest { diff --git a/manifest/schema2/builder.go b/manifest/schema2/builder.go index 8fffc80d5..4b6ba5628 100644 --- a/manifest/schema2/builder.go +++ b/manifest/schema2/builder.go @@ -3,7 +3,7 @@ package schema2 import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" + "github.com/opencontainers/go-digest" ) // builder is a type for constructing manifests. diff --git a/manifest/schema2/builder_test.go b/manifest/schema2/builder_test.go index 9dfa5fc65..697c1bc92 100644 --- a/manifest/schema2/builder_test.go +++ b/manifest/schema2/builder_test.go @@ -6,7 +6,7 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" + "github.com/opencontainers/go-digest" ) type mockBlobService struct { diff --git a/manifest/schema2/manifest.go b/manifest/schema2/manifest.go index 8bff24eb5..a2708c750 100644 --- a/manifest/schema2/manifest.go +++ b/manifest/schema2/manifest.go @@ -6,8 +6,8 @@ import ( "fmt" "github.com/docker/distribution" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" + "github.com/opencontainers/go-digest" ) const ( diff --git a/manifests.go b/manifests.go index c4fb63450..d68e71db7 100644 --- a/manifests.go +++ b/manifests.go @@ -5,7 +5,7 @@ import ( "mime" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" + "github.com/opencontainers/go-digest" ) // Manifest represents a registry object specifying a set of diff --git a/notifications/bridge.go b/notifications/bridge.go index 502288a40..8f6386d3c 100644 --- a/notifications/bridge.go +++ b/notifications/bridge.go @@ -6,9 +6,9 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/uuid" + "github.com/opencontainers/go-digest" ) type bridge struct { diff --git a/notifications/bridge_test.go b/notifications/bridge_test.go index 0f85791c8..d29cd46a9 100644 --- a/notifications/bridge_test.go +++ b/notifications/bridge_test.go @@ -4,12 +4,12 @@ import ( "testing" "github.com/docker/distribution" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/api/v2" "github.com/docker/distribution/uuid" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) var ( diff --git a/notifications/listener.go b/notifications/listener.go index c968b98ad..25b5a800f 100644 --- a/notifications/listener.go +++ b/notifications/listener.go @@ -5,8 +5,8 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" + "github.com/opencontainers/go-digest" ) // ManifestListener describes a set of methods for listening to events related to manifests. diff --git a/notifications/listener_test.go b/notifications/listener_test.go index c7db5944e..d31321594 100644 --- a/notifications/listener_test.go +++ b/notifications/listener_test.go @@ -7,7 +7,6 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/reference" @@ -16,6 +15,7 @@ import ( "github.com/docker/distribution/registry/storage/driver/inmemory" "github.com/docker/distribution/testutil" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) func TestListener(t *testing.T) { diff --git a/reference/reference.go b/reference/reference.go index 29b949aad..52da52370 100644 --- a/reference/reference.go +++ b/reference/reference.go @@ -27,7 +27,7 @@ import ( "path" "strings" - "github.com/docker/distribution/digest" + "github.com/opencontainers/go-digest" ) const ( diff --git a/reference/reference_test.go b/reference/reference_test.go index be708c4df..9d42be0fe 100644 --- a/reference/reference_test.go +++ b/reference/reference_test.go @@ -8,7 +8,7 @@ import ( "strings" "testing" - "github.com/docker/distribution/digest" + "github.com/opencontainers/go-digest" ) func TestReferenceParse(t *testing.T) { diff --git a/registry/api/v2/descriptors.go b/registry/api/v2/descriptors.go index 9979abae6..a9616c58a 100644 --- a/registry/api/v2/descriptors.go +++ b/registry/api/v2/descriptors.go @@ -4,9 +4,9 @@ import ( "net/http" "regexp" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/api/errcode" + "github.com/opencontainers/go-digest" ) var ( diff --git a/registry/client/repository.go b/registry/client/repository.go index 55dcf4392..b82a968e2 100644 --- a/registry/client/repository.go +++ b/registry/client/repository.go @@ -15,12 +15,12 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/api/v2" "github.com/docker/distribution/registry/client/transport" "github.com/docker/distribution/registry/storage/cache" "github.com/docker/distribution/registry/storage/cache/memory" + "github.com/opencontainers/go-digest" ) // Registry provides an interface for calling Repositories, which returns a catalog of repositories. @@ -661,7 +661,7 @@ func (bs *blobs) Put(ctx context.Context, mediaType string, p []byte) (distribut if err != nil { return distribution.Descriptor{}, err } - dgstr := digest.Canonical.New() + dgstr := digest.Canonical.Digester() n, err := io.Copy(writer, io.TeeReader(bytes.NewReader(p), dgstr.Hash())) if err != nil { return distribution.Descriptor{}, err diff --git a/registry/client/repository_test.go b/registry/client/repository_test.go index a232e03ec..5aae591a8 100644 --- a/registry/client/repository_test.go +++ b/registry/client/repository_test.go @@ -16,7 +16,6 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/reference" @@ -25,6 +24,7 @@ import ( "github.com/docker/distribution/testutil" "github.com/docker/distribution/uuid" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) func testServer(rrm testutil.RequestResponseMap) (string, func()) { diff --git a/registry/handlers/api_test.go b/registry/handlers/api_test.go index d0c2def67..e1112fde5 100644 --- a/registry/handlers/api_test.go +++ b/registry/handlers/api_test.go @@ -21,7 +21,6 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/configuration" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" "github.com/docker/distribution/manifest/manifestlist" "github.com/docker/distribution/manifest/schema1" @@ -33,12 +32,18 @@ import ( "github.com/docker/distribution/testutil" "github.com/docker/libtrust" "github.com/gorilla/handlers" + "github.com/opencontainers/go-digest" ) var headerConfig = http.Header{ "X-Content-Type-Options": []string{"nosniff"}, } +const ( + // digestSha256EmptyTar is the canonical sha256 digest of empty data + digestSha256EmptyTar = "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" +) + // TestCheckAPI hits the base endpoint (/v2/) ensures we return the specified // 200 OK response. func TestCheckAPI(t *testing.T) { @@ -514,7 +519,7 @@ func testBlobAPI(t *testing.T, env *testEnv, args blobArgs) *testEnv { // Now, push just a chunk layerFile.Seek(0, 0) - canonicalDigester := digest.Canonical.New() + canonicalDigester := digest.Canonical.Digester() if _, err := io.Copy(canonicalDigester.Hash(), layerFile); err != nil { t.Fatalf("error copying to digest: %v", err) } @@ -672,7 +677,7 @@ func testBlobDelete(t *testing.T, env *testEnv, args blobArgs) { pushLayer(t, env.builder, imageName, layerDigest, uploadURLBase, layerFile) layerFile.Seek(0, os.SEEK_SET) - canonicalDigester := digest.Canonical.New() + canonicalDigester := digest.Canonical.Digester() if _, err := io.Copy(canonicalDigester.Hash(), layerFile); err != nil { t.Fatalf("error copying to digest: %v", err) } @@ -832,7 +837,7 @@ func TestManifestDeleteDisabled(t *testing.T) { } func testManifestDeleteDisabled(t *testing.T, env *testEnv, imageName reference.Named) { - ref, _ := reference.WithDigest(imageName, digest.DigestSha256EmptyTar) + ref, _ := reference.WithDigest(imageName, digestSha256EmptyTar) manifestURL, err := env.builder.BuildManifestURL(ref) if err != nil { t.Fatalf("unexpected error getting manifest url: %v", err) @@ -2072,7 +2077,7 @@ func doPushLayer(t *testing.T, ub *v2.URLBuilder, name reference.Named, dgst dig // pushLayer pushes the layer content returning the url on success. func pushLayer(t *testing.T, ub *v2.URLBuilder, name reference.Named, dgst digest.Digest, uploadURLBase string, body io.Reader) string { - digester := digest.Canonical.New() + digester := digest.Canonical.Digester() resp, err := doPushLayer(t, ub, name, dgst, uploadURLBase, io.TeeReader(body, digester.Hash())) if err != nil { @@ -2139,7 +2144,7 @@ func doPushChunk(t *testing.T, uploadURLBase string, body io.Reader) (*http.Resp uploadURL := u.String() - digester := digest.Canonical.New() + digester := digest.Canonical.Digester() req, err := http.NewRequest("PATCH", uploadURL, io.TeeReader(body, digester.Hash())) if err != nil { @@ -2405,7 +2410,7 @@ func TestRegistryAsCacheMutationAPIs(t *testing.T) { checkResponse(t, fmt.Sprintf("starting layer push to cache %v", imageName), resp, errcode.ErrorCodeUnsupported.Descriptor().HTTPStatusCode) // Blob Delete - ref, _ := reference.WithDigest(imageName, digest.DigestSha256EmptyTar) + ref, _ := reference.WithDigest(imageName, digestSha256EmptyTar) blobURL, err := env.builder.BuildBlobURL(ref) resp, err = httpDelete(blobURL) checkResponse(t, "deleting blob from cache", resp, errcode.ErrorCodeUnsupported.Descriptor().HTTPStatusCode) diff --git a/registry/handlers/blob.go b/registry/handlers/blob.go index fb250acd2..5c31cc767 100644 --- a/registry/handlers/blob.go +++ b/registry/handlers/blob.go @@ -5,10 +5,10 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/registry/api/errcode" "github.com/docker/distribution/registry/api/v2" "github.com/gorilla/handlers" + "github.com/opencontainers/go-digest" ) // blobDispatcher uses the request context to build a blobHandler. diff --git a/registry/handlers/blobupload.go b/registry/handlers/blobupload.go index 09a86fc5c..a45350e16 100644 --- a/registry/handlers/blobupload.go +++ b/registry/handlers/blobupload.go @@ -7,12 +7,12 @@ import ( "github.com/docker/distribution" ctxu "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/api/errcode" "github.com/docker/distribution/registry/api/v2" "github.com/docker/distribution/registry/storage" "github.com/gorilla/handlers" + "github.com/opencontainers/go-digest" ) // blobUploadDispatcher constructs and returns the blob upload handler for the diff --git a/registry/handlers/context.go b/registry/handlers/context.go index fb883f60d..a49ad10e6 100644 --- a/registry/handlers/context.go +++ b/registry/handlers/context.go @@ -7,10 +7,10 @@ import ( "github.com/docker/distribution" ctxu "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/registry/api/errcode" "github.com/docker/distribution/registry/api/v2" "github.com/docker/distribution/registry/auth" + "github.com/opencontainers/go-digest" "golang.org/x/net/context" ) diff --git a/registry/handlers/images.go b/registry/handlers/images.go index 5ed1e60c1..c3b8848d1 100644 --- a/registry/handlers/images.go +++ b/registry/handlers/images.go @@ -8,7 +8,6 @@ import ( "github.com/docker/distribution" ctxu "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest/manifestlist" "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/manifest/schema2" @@ -17,6 +16,7 @@ import ( "github.com/docker/distribution/registry/api/v2" "github.com/docker/distribution/registry/auth" "github.com/gorilla/handlers" + "github.com/opencontainers/go-digest" ) // These constants determine which architecture and OS to choose from a diff --git a/registry/proxy/proxyblobstore.go b/registry/proxy/proxyblobstore.go index 6cd572133..c3f1b92f1 100644 --- a/registry/proxy/proxyblobstore.go +++ b/registry/proxy/proxyblobstore.go @@ -9,9 +9,9 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/proxy/scheduler" + "github.com/opencontainers/go-digest" ) // todo(richardscothern): from cache control header or config file diff --git a/registry/proxy/proxyblobstore_test.go b/registry/proxy/proxyblobstore_test.go index 8e3a06920..15b98bf51 100644 --- a/registry/proxy/proxyblobstore_test.go +++ b/registry/proxy/proxyblobstore_test.go @@ -11,13 +11,13 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/proxy/scheduler" "github.com/docker/distribution/registry/storage" "github.com/docker/distribution/registry/storage/cache/memory" "github.com/docker/distribution/registry/storage/driver/filesystem" "github.com/docker/distribution/registry/storage/driver/inmemory" + "github.com/opencontainers/go-digest" ) var sbsMu sync.Mutex diff --git a/registry/proxy/proxymanifeststore.go b/registry/proxy/proxymanifeststore.go index f08e285db..e0a9f7d3f 100644 --- a/registry/proxy/proxymanifeststore.go +++ b/registry/proxy/proxymanifeststore.go @@ -5,9 +5,9 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/proxy/scheduler" + "github.com/opencontainers/go-digest" ) // todo(richardscothern): from cache control header or config diff --git a/registry/proxy/proxymanifeststore_test.go b/registry/proxy/proxymanifeststore_test.go index 067e845a2..35f529443 100644 --- a/registry/proxy/proxymanifeststore_test.go +++ b/registry/proxy/proxymanifeststore_test.go @@ -7,7 +7,6 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/reference" @@ -19,6 +18,7 @@ import ( "github.com/docker/distribution/registry/storage/driver/inmemory" "github.com/docker/distribution/testutil" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) type statsManifest struct { diff --git a/registry/storage/blob_test.go b/registry/storage/blob_test.go index 767526bb2..1fe57ee08 100644 --- a/registry/storage/blob_test.go +++ b/registry/storage/blob_test.go @@ -13,11 +13,11 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/storage/cache/memory" "github.com/docker/distribution/registry/storage/driver/testdriver" "github.com/docker/distribution/testutil" + "github.com/opencontainers/go-digest" ) // TestWriteSeek tests that the current file size can be @@ -530,7 +530,7 @@ func TestLayerUploadZeroLength(t *testing.T) { } bs := repository.Blobs(ctx) - simpleUpload(t, bs, []byte{}, digest.DigestSha256EmptyTar) + simpleUpload(t, bs, []byte{}, digestSha256EmptyTar) } func simpleUpload(t *testing.T, bs distribution.BlobIngester, blob []byte, expectedDigest digest.Digest) { diff --git a/registry/storage/blobserver.go b/registry/storage/blobserver.go index 2655e0113..739bf3cb3 100644 --- a/registry/storage/blobserver.go +++ b/registry/storage/blobserver.go @@ -7,8 +7,8 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/registry/storage/driver" + "github.com/opencontainers/go-digest" ) // TODO(stevvooe): This should configurable in the future. diff --git a/registry/storage/blobstore.go b/registry/storage/blobstore.go index 6ec2e66a0..9f9071ca6 100644 --- a/registry/storage/blobstore.go +++ b/registry/storage/blobstore.go @@ -5,8 +5,8 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/registry/storage/driver" + "github.com/opencontainers/go-digest" ) // blobStore implements the read side of the blob store interface over a diff --git a/registry/storage/blobwriter.go b/registry/storage/blobwriter.go index e2f03f5f9..0c598e7a8 100644 --- a/registry/storage/blobwriter.go +++ b/registry/storage/blobwriter.go @@ -10,14 +10,19 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" storagedriver "github.com/docker/distribution/registry/storage/driver" + "github.com/opencontainers/go-digest" ) var ( errResumableDigestNotAvailable = errors.New("resumable digest not available") ) +const ( + // DigestSha256EmptyTar is the canonical sha256 digest of empty data + digestSha256EmptyTar = "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" +) + // blobWriter is used to control the various aspects of resumable // blob upload. type blobWriter struct { @@ -234,7 +239,7 @@ func (bw *blobWriter) validateBlob(ctx context.Context, desc distribution.Descri // paths. We may be able to make the size-based check a stronger // guarantee, so this may be defensive. if !verified { - digester := digest.Canonical.New() + digester := digest.Canonical.Digester() verifier := desc.Digest.Verifier() // Read the file from the backend driver and validate it. @@ -318,7 +323,7 @@ func (bw *blobWriter) moveBlob(ctx context.Context, desc distribution.Descriptor // a zero-length blob into a nonzero-length blob location. To // prevent this horrid thing, we employ the hack of only allowing // to this happen for the digest of an empty tar. - if desc.Digest == digest.DigestSha256EmptyTar { + if desc.Digest == digestSha256EmptyTar { return bw.blobStore.driver.PutContent(ctx, blobPath, []byte{}) } diff --git a/registry/storage/cache/cachecheck/suite.go b/registry/storage/cache/cachecheck/suite.go index a563c02a1..0bbd52957 100644 --- a/registry/storage/cache/cachecheck/suite.go +++ b/registry/storage/cache/cachecheck/suite.go @@ -6,8 +6,8 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/registry/storage/cache" + "github.com/opencontainers/go-digest" ) // CheckBlobDescriptorCache takes a cache implementation through a common set diff --git a/registry/storage/cache/cachedblobdescriptorstore.go b/registry/storage/cache/cachedblobdescriptorstore.go index 94ca8a90c..f647616bc 100644 --- a/registry/storage/cache/cachedblobdescriptorstore.go +++ b/registry/storage/cache/cachedblobdescriptorstore.go @@ -2,7 +2,7 @@ package cache import ( "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" + "github.com/opencontainers/go-digest" "github.com/docker/distribution" ) diff --git a/registry/storage/cache/memory/memory.go b/registry/storage/cache/memory/memory.go index cf125e187..a0be5ea02 100644 --- a/registry/storage/cache/memory/memory.go +++ b/registry/storage/cache/memory/memory.go @@ -5,9 +5,9 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/storage/cache" + "github.com/opencontainers/go-digest" ) type inMemoryBlobDescriptorCacheProvider struct { diff --git a/registry/storage/cache/redis/redis.go b/registry/storage/cache/redis/redis.go index cb264b098..8ba6cb420 100644 --- a/registry/storage/cache/redis/redis.go +++ b/registry/storage/cache/redis/redis.go @@ -5,10 +5,10 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/storage/cache" "github.com/garyburd/redigo/redis" + "github.com/opencontainers/go-digest" ) // redisBlobStatService provides an implementation of diff --git a/registry/storage/catalog_test.go b/registry/storage/catalog_test.go index c69c0cdc1..754e95611 100644 --- a/registry/storage/catalog_test.go +++ b/registry/storage/catalog_test.go @@ -8,12 +8,12 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/storage/cache/memory" "github.com/docker/distribution/registry/storage/driver" "github.com/docker/distribution/registry/storage/driver/inmemory" "github.com/docker/distribution/testutil" + "github.com/opencontainers/go-digest" ) type setupEnv struct { diff --git a/digest/digester_resumable_test.go b/registry/storage/digester_resumable_test.go similarity index 83% rename from digest/digester_resumable_test.go rename to registry/storage/digester_resumable_test.go index 6ba21c801..54ece3c48 100644 --- a/digest/digester_resumable_test.go +++ b/registry/storage/digester_resumable_test.go @@ -1,10 +1,11 @@ // +build !noresumabledigest -package digest +package storage import ( "testing" + digest "github.com/opencontainers/go-digest" "github.com/stevvooe/resumable" _ "github.com/stevvooe/resumable/sha256" ) @@ -13,7 +14,7 @@ import ( // is exposed through the digester type, which is just a hash plus a Digest // method. func TestResumableDetection(t *testing.T) { - d := Canonical.New() + d := digest.Canonical.Digester() if _, ok := d.Hash().(resumable.Hash); !ok { t.Fatalf("expected digester to implement resumable.Hash: %#v, %v", d, d.Hash()) diff --git a/registry/storage/filereader_test.go b/registry/storage/filereader_test.go index 371a410d8..e522d6056 100644 --- a/registry/storage/filereader_test.go +++ b/registry/storage/filereader_test.go @@ -8,8 +8,8 @@ import ( "testing" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/registry/storage/driver/inmemory" + "github.com/opencontainers/go-digest" ) func TestSimpleRead(t *testing.T) { diff --git a/registry/storage/garbagecollect.go b/registry/storage/garbagecollect.go index 7cf0298e1..b909d4870 100644 --- a/registry/storage/garbagecollect.go +++ b/registry/storage/garbagecollect.go @@ -5,9 +5,9 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/storage/driver" + "github.com/opencontainers/go-digest" ) func emit(format string, a ...interface{}) { diff --git a/registry/storage/garbagecollect_test.go b/registry/storage/garbagecollect_test.go index 925f1a10f..a23468030 100644 --- a/registry/storage/garbagecollect_test.go +++ b/registry/storage/garbagecollect_test.go @@ -7,12 +7,12 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/storage/driver" "github.com/docker/distribution/registry/storage/driver/inmemory" "github.com/docker/distribution/testutil" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) type image struct { diff --git a/registry/storage/linkedblobstore.go b/registry/storage/linkedblobstore.go index 6a5e8d033..a1929eed3 100644 --- a/registry/storage/linkedblobstore.go +++ b/registry/storage/linkedblobstore.go @@ -8,10 +8,10 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/storage/driver" "github.com/docker/distribution/uuid" + "github.com/opencontainers/go-digest" ) // linkPathFunc describes a function that can resolve a link based on the @@ -321,7 +321,7 @@ func (lbs *linkedBlobStore) newBlobUpload(ctx context.Context, uuid, path string blobStore: lbs, id: uuid, startedAt: startedAt, - digester: digest.Canonical.New(), + digester: digest.Canonical.Digester(), fileWriter: fw, driver: lbs.driver, path: path, diff --git a/registry/storage/linkedblobstore_test.go b/registry/storage/linkedblobstore_test.go index f0f63d87b..bc5079eba 100644 --- a/registry/storage/linkedblobstore_test.go +++ b/registry/storage/linkedblobstore_test.go @@ -9,7 +9,7 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" + "github.com/opencontainers/go-digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/testutil" diff --git a/registry/storage/manifestlisthandler.go b/registry/storage/manifestlisthandler.go index e24062cd0..aee73b85f 100644 --- a/registry/storage/manifestlisthandler.go +++ b/registry/storage/manifestlisthandler.go @@ -6,8 +6,8 @@ import ( "encoding/json" "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest/manifestlist" + "github.com/opencontainers/go-digest" ) // manifestListHandler is a ManifestHandler that covers schema2 manifest lists. diff --git a/registry/storage/manifeststore.go b/registry/storage/manifeststore.go index 9e8065bb7..4cca5157a 100644 --- a/registry/storage/manifeststore.go +++ b/registry/storage/manifeststore.go @@ -6,11 +6,11 @@ import ( "encoding/json" "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" "github.com/docker/distribution/manifest/manifestlist" "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/manifest/schema2" + "github.com/opencontainers/go-digest" ) // A ManifestHandler gets and puts manifests of a particular type. diff --git a/registry/storage/manifeststore_test.go b/registry/storage/manifeststore_test.go index cbd30c044..61dc72d3b 100644 --- a/registry/storage/manifeststore_test.go +++ b/registry/storage/manifeststore_test.go @@ -8,7 +8,6 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/reference" @@ -17,6 +16,7 @@ import ( "github.com/docker/distribution/registry/storage/driver/inmemory" "github.com/docker/distribution/testutil" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) type manifestStoreTestEnv struct { diff --git a/registry/storage/paths.go b/registry/storage/paths.go index 1b142b88f..b6d9b9b56 100644 --- a/registry/storage/paths.go +++ b/registry/storage/paths.go @@ -5,7 +5,7 @@ import ( "path" "strings" - "github.com/docker/distribution/digest" + "github.com/opencontainers/go-digest" ) const ( diff --git a/registry/storage/paths_test.go b/registry/storage/paths_test.go index f739552aa..677a34b9f 100644 --- a/registry/storage/paths_test.go +++ b/registry/storage/paths_test.go @@ -3,7 +3,7 @@ package storage import ( "testing" - "github.com/docker/distribution/digest" + "github.com/opencontainers/go-digest" ) func TestPathMapper(t *testing.T) { diff --git a/registry/storage/schema2manifesthandler.go b/registry/storage/schema2manifesthandler.go index 9fe71bb4d..05c53254f 100644 --- a/registry/storage/schema2manifesthandler.go +++ b/registry/storage/schema2manifesthandler.go @@ -8,9 +8,9 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/manifest/schema2" + "github.com/opencontainers/go-digest" ) var ( diff --git a/registry/storage/signedmanifesthandler.go b/registry/storage/signedmanifesthandler.go index 30d330824..6ca1c6c8c 100644 --- a/registry/storage/signedmanifesthandler.go +++ b/registry/storage/signedmanifesthandler.go @@ -6,10 +6,10 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/reference" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) // signedManifestHandler is a ManifestHandler that covers schema1 manifests. It diff --git a/registry/storage/tagstore.go b/registry/storage/tagstore.go index 4386ffcac..d73278869 100644 --- a/registry/storage/tagstore.go +++ b/registry/storage/tagstore.go @@ -5,8 +5,8 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" storagedriver "github.com/docker/distribution/registry/storage/driver" + "github.com/opencontainers/go-digest" ) var _ distribution.TagService = &tagStore{} diff --git a/registry/storage/vacuum.go b/registry/storage/vacuum.go index 7302f733f..42c8ef605 100644 --- a/registry/storage/vacuum.go +++ b/registry/storage/vacuum.go @@ -4,8 +4,8 @@ import ( "path" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/registry/storage/driver" + "github.com/opencontainers/go-digest" ) // vacuum contains functions for cleaning up repositories and blobs diff --git a/testutil/manifests.go b/testutil/manifests.go index a77067d7c..8afe82e48 100644 --- a/testutil/manifests.go +++ b/testutil/manifests.go @@ -5,12 +5,12 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" "github.com/docker/distribution/manifest/manifestlist" "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/manifest/schema2" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) // MakeManifestList constructs a manifest list out of a list of manifest digests diff --git a/testutil/tarfile.go b/testutil/tarfile.go index a8ba01553..cb93602f3 100644 --- a/testutil/tarfile.go +++ b/testutil/tarfile.go @@ -10,7 +10,7 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" + "github.com/opencontainers/go-digest" ) // CreateRandomTarFile creates a random tarfile, returning it as an