github.com/supabase/cli@v1.168.1/internal/storage/mv/mv.go (about) 1 package mv 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "path" 8 "strings" 9 10 "github.com/go-errors/errors" 11 "github.com/spf13/afero" 12 "github.com/supabase/cli/internal/storage/client" 13 "github.com/supabase/cli/internal/storage/ls" 14 "github.com/supabase/cli/internal/utils/flags" 15 "github.com/supabase/cli/pkg/storage" 16 ) 17 18 var ( 19 errUnsupportedMove = errors.New("Moving between buckets is unsupported") 20 errMissingPath = errors.New("You must specify an object path") 21 ) 22 23 func Run(ctx context.Context, src, dst string, recursive bool, fsys afero.Fs) error { 24 srcParsed, err := client.ParseStorageURL(src) 25 if err != nil { 26 return err 27 } 28 dstParsed, err := client.ParseStorageURL(dst) 29 if err != nil { 30 return err 31 } 32 srcBucket, srcPrefix := client.SplitBucketPrefix(srcParsed) 33 dstBucket, dstPrefix := client.SplitBucketPrefix(dstParsed) 34 if len(srcPrefix) == 0 && len(dstPrefix) == 0 { 35 return errors.New(errMissingPath) 36 } 37 if srcBucket != dstBucket { 38 return errors.New(errUnsupportedMove) 39 } 40 api, err := client.NewStorageAPI(ctx, flags.ProjectRef) 41 if err != nil { 42 return err 43 } 44 fmt.Fprintln(os.Stderr, "Moving object:", srcParsed, "=>", dstParsed) 45 data, err := api.MoveObject(ctx, srcBucket, srcPrefix, dstPrefix) 46 if err == nil { 47 fmt.Fprintln(os.Stderr, data.Message) 48 } else if strings.Contains(err.Error(), `"error":"not_found"`) && recursive { 49 return MoveStorageObjectAll(ctx, api, srcParsed+"/", dstParsed) 50 } 51 return err 52 } 53 54 // Expects srcPath to be terminated by "/" 55 func MoveStorageObjectAll(ctx context.Context, api storage.StorageAPI, srcPath, dstPath string) error { 56 _, dstPrefix := client.SplitBucketPrefix(dstPath) 57 // Cannot iterate because pagination result may be updated during move 58 count := 0 59 queue := make([]string, 0) 60 queue = append(queue, srcPath) 61 for len(queue) > 0 { 62 dirPath := queue[len(queue)-1] 63 queue = queue[:len(queue)-1] 64 paths, err := ls.ListStoragePaths(ctx, api, dirPath) 65 if err != nil { 66 return err 67 } 68 for _, objectName := range paths { 69 objectPath := dirPath + objectName 70 if strings.HasSuffix(objectName, "/") { 71 queue = append(queue, objectPath) 72 continue 73 } 74 count++ 75 relPath := strings.TrimPrefix(objectPath, srcPath) 76 srcBucket, srcPrefix := client.SplitBucketPrefix(objectPath) 77 absPath := path.Join(dstPrefix, relPath) 78 fmt.Fprintln(os.Stderr, "Moving object:", objectPath, "=>", path.Join(dstPath, relPath)) 79 if _, err := api.MoveObject(ctx, srcBucket, srcPrefix, absPath); err != nil { 80 return err 81 } 82 } 83 } 84 if count == 0 { 85 return errors.New("Object not found: " + srcPath) 86 } 87 return nil 88 }