@@ -5,11 +5,6 @@ import (
55 "context"
66 "errors"
77 "fmt"
8- "github.com/distribution/distribution/v3/internal/dcontext"
9- storagedriver "github.com/distribution/distribution/v3/registry/storage/driver"
10- "github.com/distribution/distribution/v3/registry/storage/driver/base"
11- "github.com/distribution/distribution/v3/registry/storage/driver/factory"
12- "github.com/tencentyun/cos-go-sdk-v5"
138 "io"
149 "net/http"
1510 "net/url"
@@ -18,6 +13,12 @@ import (
1813 "strings"
1914 "sync"
2015 "time"
16+
17+ "github.com/distribution/distribution/v3/internal/dcontext"
18+ storagedriver "github.com/distribution/distribution/v3/registry/storage/driver"
19+ "github.com/distribution/distribution/v3/registry/storage/driver/base"
20+ "github.com/distribution/distribution/v3/registry/storage/driver/factory"
21+ "github.com/tencentyun/cos-go-sdk-v5"
2122)
2223
2324const (
@@ -286,7 +287,10 @@ func (d *driver) Stat(ctx context.Context, path string) (storagedriver.FileInfo,
286287 }
287288 // file info
288289 size , err := strconv .ParseInt (res .Header .Get ("Content-Length" ), 10 , 64 )
289- modTime , err := time .Parse (time .RFC1123 , res .Header .Get ("Last-Modified" ))
290+ if err != nil {
291+ return nil , err
292+ }
293+ modTime , err := ParseTime (res .Header .Get ("Last-Modified" ))
290294 if err != nil {
291295 return nil , err
292296 }
@@ -374,7 +378,7 @@ func (d *driver) copy(ctx context.Context, sourcePath, destPath string) error {
374378 return nil
375379 }
376380 // file size is larger than 32MB
377- v , _ , err := d .cosClient .Object .InitiateMultipartUpload (ctx , key , & cos.InitiateMultipartUploadOptions {
381+ v , _ , _ := d .cosClient .Object .InitiateMultipartUpload (ctx , key , & cos.InitiateMultipartUploadOptions {
378382 ObjectPutHeaderOptions : & cos.ObjectPutHeaderOptions {
379383 ContentType : contentType ,
380384 },
@@ -524,6 +528,8 @@ func (d *driver) doWalk(parentCtx context.Context, objectCount *int64, from, sta
524528 var retError error
525529 // the most recent skip directory to avoid walking over undesirable files
526530 var prevSkipDir string
531+ // the most recent directory walked for de-duplication
532+ var prevDir string
527533
528534 key := d .pathToKey (from )
529535 opt := & cos.BucketGetOptions {
@@ -532,7 +538,7 @@ func (d *driver) doWalk(parentCtx context.Context, objectCount *int64, from, sta
532538 Marker : d .pathToKey (startAfter ),
533539 }
534540 ctx , done := dcontext .WithTrace (parentCtx )
535- defer done ("cos.Bucket.Get(%s )" , opt )
541+ defer done ("cos.Bucket.Get(%+v )" , opt )
536542 isTruncated := true
537543 for isTruncated {
538544 // list all the objects
@@ -541,30 +547,45 @@ func (d *driver) doWalk(parentCtx context.Context, objectCount *int64, from, sta
541547 return err
542548 }
543549 walkInfos := make ([]storagedriver.FileInfoInternal , 0 , len (res .Contents ))
550+ prevDir = from
544551 for _ , content := range res .Contents {
545- if strings .HasSuffix (content .Key , "/" ) { // directory
552+ // COS returns only objects, without directories
553+ path := d .keyToPath (content .Key )
554+
555+ // get a list of all directories between the previous
556+ dirs := DirectoryDiff (prevDir , path )
557+ for _ , dir := range dirs {
546558 walkInfos = append (walkInfos , storagedriver.FileInfoInternal {
547559 FileInfoFields : storagedriver.FileInfoFields {
548560 IsDir : true ,
549- Path : strings .TrimRight (content .Key , "/" ),
550- },
551- })
552- } else { // file object
553- // last modification time
554- modTime , err := time .Parse (time .RFC1123 , content .LastModified )
555- if err != nil {
556- return err
557- }
558- walkInfos = append (walkInfos , storagedriver.FileInfoInternal {
559- FileInfoFields : storagedriver.FileInfoFields {
560- IsDir : false ,
561- Size : content .Size ,
562- ModTime : modTime ,
563- Path : content .Key ,
561+ Path : dir ,
564562 },
565563 })
564+ prevDir = dir
565+ }
566+
567+ // corner case
568+ if strings .HasSuffix (path , "/" ) {
569+ continue
566570 }
571+
572+ modTime , err := ParseTime (content .LastModified )
573+ if err != nil {
574+ return err
575+ }
576+
577+ walkInfos = append (walkInfos , storagedriver.FileInfoInternal {
578+ FileInfoFields : storagedriver.FileInfoFields {
579+ IsDir : false ,
580+ Size : content .Size ,
581+ ModTime : modTime ,
582+ Path : path ,
583+ },
584+ })
567585 }
586+
587+ // according to the files, append directories
588+
568589 isTruncated = res .IsTruncated
569590 opt .Marker = res .NextMarker
570591 // iterative
@@ -600,14 +621,12 @@ func (d *driver) doWalk(parentCtx context.Context, objectCount *int64, from, sta
600621
601622// add the prefix
602623func (d * driver ) pathToKey (path string ) string {
603- // Important! delete the root prefix
604- newPath := strings .TrimPrefix (path , d .rootDirectory )
605- return strings .TrimLeft (strings .TrimRight (d .rootDirectory , "/" )+ newPath , "/" )
624+ return PathToKey (d .rootDirectory , path )
606625}
607626
608627// remove the prefix
609628func (d * driver ) keyToPath (key string ) string {
610- return "/" + strings . TrimRight ( strings . TrimPrefix ( key , d .rootDirectory ), "/" )
629+ return KeyToPath ( d .rootDirectory , key )
611630}
612631
613632var _ storagedriver.FileWriter = & writer {}
0 commit comments