Skip to content

Commit

Permalink
feat: add reverse version for listObjectVersions (#2072)
Browse files Browse the repository at this point in the history
  • Loading branch information
jiuker authored Mar 5, 2025
1 parent a9f9671 commit c34f06b
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 12 deletions.
2 changes: 2 additions & 0 deletions api-datatypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ type ObjectInfo struct {
// not to be confused with `Expires` HTTP header.
Expiration time.Time
ExpirationRuleID string
// NumVersions is the number of versions of the object.
NumVersions int

Restore *RestoreInfo

Expand Down
67 changes: 55 additions & 12 deletions api-list.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"fmt"
"net/http"
"net/url"
"slices"
"time"

"github.com/minio/minio-go/v7/pkg/s3utils"
Expand Down Expand Up @@ -421,20 +422,17 @@ func (c *Client) listObjectVersions(ctx context.Context, bucketName string, opts
var (
keyMarker = ""
versionIDMarker = ""
preName = ""
preKey = ""
perVersions []Version
numVersions int
)

for {
// Get list of objects a maximum of 1000 per request.
result, err := c.listObjectVersionsQuery(ctx, bucketName, opts, keyMarker, versionIDMarker, delimiter)
if err != nil {
sendObjectInfo(ObjectInfo{
Err: err,
})
return
send := func(vers []Version) {
if opts.WithVersions && opts.ReverseVersions {
slices.Reverse(vers)
numVersions = len(vers)
}

// If contents are available loop through and send over channel.
for _, version := range result.Versions {
for _, version := range vers {
info := ObjectInfo{
ETag: trimEtag(version.ETag),
Key: version.Key,
Expand All @@ -448,6 +446,7 @@ func (c *Client) listObjectVersions(ctx context.Context, bucketName string, opts
UserTags: version.UserTags,
UserMetadata: version.UserMetadata,
Internal: version.Internal,
NumVersions: numVersions,
}
select {
// Send object version info.
Expand All @@ -457,6 +456,38 @@ func (c *Client) listObjectVersions(ctx context.Context, bucketName string, opts
return
}
}
}
for {
// Get list of objects a maximum of 1000 per request.
result, err := c.listObjectVersionsQuery(ctx, bucketName, opts, keyMarker, versionIDMarker, delimiter)
if err != nil {
sendObjectInfo(ObjectInfo{
Err: err,
})
return
}
if opts.WithVersions && opts.ReverseVersions {
for _, version := range result.Versions {
if preName == "" {
preName = result.Name
preKey = version.Key
}
if result.Name == preName && preKey == version.Key {
// If the current name is same as previous name,
// we need to append the version to the previous version.
perVersions = append(perVersions, version)
continue
}
// Send the file versions.
send(perVersions)
perVersions = perVersions[:0]
perVersions = append(perVersions, version)
preName = result.Name
preKey = version.Key
}
} else {
send(result.Versions)
}

// Send all common prefixes if any.
// NOTE: prefixes are only present if the request is delimited.
Expand All @@ -480,10 +511,20 @@ func (c *Client) listObjectVersions(ctx context.Context, bucketName string, opts
versionIDMarker = result.NextVersionIDMarker
}

// If context is canceled, return here.
if contextCanceled(ctx) {
return
}

// Listing ends result is not truncated, return right here.
if !result.IsTruncated {
// sent the lasted file with versions
if opts.ReverseVersions && len(perVersions) > 0 {
send(perVersions)
}
return
}

}
}(resultCh)
return resultCh
Expand Down Expand Up @@ -683,6 +724,8 @@ func (c *Client) listObjectsQuery(ctx context.Context, bucketName, objectPrefix,

// ListObjectsOptions holds all options of a list object request
type ListObjectsOptions struct {
// ReverseVersions - reverse the order of the object versions
ReverseVersions bool
// Include objects versions in the listing
WithVersions bool
// Include objects metadata in the listing
Expand Down

0 comments on commit c34f06b

Please sign in to comment.