diff --git a/types/referrer/referrer.go b/types/referrer/referrer.go index 6069e8f..03a6be4 100644 --- a/types/referrer/referrer.go +++ b/types/referrer/referrer.go @@ -4,6 +4,7 @@ package referrer import ( "bytes" "fmt" + "regexp" "slices" "sort" "text/tabwriter" @@ -151,12 +152,9 @@ func FallbackTag(r ref.Ref) (ref.Ref, error) { if err != nil { return r, fmt.Errorf("failed to parse digest for referrers: %w", err) } - rr := r.SetTag(fmt.Sprintf("%s-%s", dig.Algorithm(), stringMax(dig.Hex(), 64))) - return rr, nil -} -func stringMax(s string, max int) string { - if len(s) <= max { - return s - } - return s[:max] + replaceRE := regexp.MustCompile(`[^a-zA-Z0-9._-]`) + algo := replaceRE.ReplaceAllString(string(dig.Algorithm()), "-") + hash := replaceRE.ReplaceAllString(string(dig.Hex()), "-") + rOut := r.SetTag(fmt.Sprintf("%.32s-%.64s", algo, hash)) + return rOut, nil } diff --git a/types/referrer/referrer_test.go b/types/referrer/referrer_test.go index 121f18e..304089e 100644 --- a/types/referrer/referrer_test.go +++ b/types/referrer/referrer_test.go @@ -2,6 +2,7 @@ package referrer import ( "errors" + "fmt" "strings" "testing" @@ -362,6 +363,79 @@ func TestDelete(t *testing.T) { } } +func TestFallback(t *testing.T) { + t.Parallel() + dig256 := digest.SHA256.FromString("test") + dig512 := digest.SHA512.FromString("test") + digInvalid := "invalid+algorithm:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + fb256 := fmt.Sprintf("%s-%s", dig256.Algorithm(), dig256.Hex()) + fb512 := fmt.Sprintf("%s-%.64s", dig512.Algorithm(), dig512.Hex()) + rRef, err := ref.New("registry.example.org/proj") + if err != nil { + t.Fatalf("failed to set ref: %v", err) + } + oRef, err := ref.New("ocidir://path/to/proj") + if err != nil { + t.Fatalf("failed to set ref: %v", err) + } + tt := []struct { + name string + r ref.Ref + err error + expect ref.Ref + }{ + { + name: "reg-sha256", + r: rRef.SetDigest(dig256.String()), + expect: rRef.SetTag(fb256), + }, + { + name: "reg-sha512", + r: rRef.SetDigest(dig512.String()), + expect: rRef.SetTag(fb512), + }, + { + name: "reg-invalid", + r: rRef.SetDigest(digInvalid), + err: digest.ErrDigestUnsupported, + }, + { + name: "ocidir-sha256", + r: oRef.SetDigest(dig256.String()), + expect: oRef.SetTag(fb256), + }, + { + name: "ocidir-sha512", + r: oRef.SetDigest(dig512.String()), + expect: oRef.SetTag(fb512), + }, + { + name: "ocidir-invalid", + r: oRef.SetDigest(digInvalid), + err: digest.ErrDigestUnsupported, + }, + } + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + out, err := FallbackTag(tc.r) + if tc.err != nil { + if err == nil { + t.Errorf("did not return expected error: %v", tc.err) + } else if !errors.Is(err, tc.err) { + t.Errorf("unexpected error, expected: %v, received: %v", tc.err, err) + } + return + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if out.CommonName() != tc.expect.CommonName() { + t.Errorf("expected %s, received %s", tc.expect.CommonName(), out.CommonName()) + } + }) + } +} + func TestMarshal(t *testing.T) { t.Parallel() rl := &ReferrerList{