From 691c01963b82f49847428b224a4f35e64d87ed3a Mon Sep 17 00:00:00 2001 From: greatroar <61184462+greatroar@users.noreply.github.com> Date: Fri, 25 Aug 2023 15:14:48 +0200 Subject: [PATCH] internal/restic: Return summary from BlobSet.String Fixes #4449: error messages from prune were too long to fit in scroll buffers. --- internal/restic/blob_set.go | 32 ++++++++++++++++++++++++++------ internal/restic/blob_set_test.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 6 deletions(-) create mode 100644 internal/restic/blob_set_test.go diff --git a/internal/restic/blob_set.go b/internal/restic/blob_set.go index acacd57d4..928d0fb68 100644 --- a/internal/restic/blob_set.go +++ b/internal/restic/blob_set.go @@ -1,6 +1,10 @@ package restic -import "sort" +import ( + "fmt" + "sort" + "strings" +) // BlobSet is a set of blobs. type BlobSet map[BlobHandle]struct{} @@ -103,11 +107,27 @@ func (s BlobSet) List() BlobHandles { return list } +// String produces a human-readable representation of ids. +// It is meant for producing error messages, +// so it only returns a summary if ids is long. func (s BlobSet) String() string { - str := s.List().String() - if len(str) < 2 { - return "{}" - } + const maxelems = 10 - return "{" + str[1:len(str)-1] + "}" + sb := new(strings.Builder) + sb.WriteByte('{') + n := 0 + for k := range s { + if n != 0 { + sb.WriteByte(' ') + } + sb.WriteString(k.String()) + + if n++; n == maxelems { + fmt.Fprintf(sb, " (%d more)", len(s)-n-1) + break + } + } + sb.WriteByte('}') + + return sb.String() } diff --git a/internal/restic/blob_set_test.go b/internal/restic/blob_set_test.go new file mode 100644 index 000000000..e26b48fe9 --- /dev/null +++ b/internal/restic/blob_set_test.go @@ -0,0 +1,32 @@ +package restic + +import ( + "math/rand" + "regexp" + "testing" + + rtest "github.com/restic/restic/internal/test" +) + +func TestBlobSetString(t *testing.T) { + s := NewBlobSet() + + rtest.Equals(t, "{}", s.String()) + + id, _ := ParseID( + "1111111111111111111111111111111111111111111111111111111111111111") + s.Insert(BlobHandle{ID: id, Type: TreeBlob}) + rtest.Equals(t, "{}", s.String()) + + var h BlobHandle + for i := 0; i < 100; i++ { + h.Type = DataBlob + _, _ = rand.Read(h.ID[:]) + s.Insert(h) + } + + r := regexp.MustCompile( + `^{(?:<(?:data|tree)/[0-9a-f]{8}> ){10}\(90 more\)}$`) + str := s.String() + rtest.Assert(t, r.MatchString(str), "%q doesn't match pattern", str) +}