Repository: rclone/rclone
File: backend/googlecloudstorage/googlecloudstorage.go (Go)

Code before:
					Enabled: true,
				},
			}
		}
		return f.pacer.Call(func() (bool, error) {
			insertBucket := f.svc.Buckets.Insert(f.opt.ProjectNumber, &bucket)
			if !f.opt.BucketPolicyOnly {
				insertBucket.PredefinedAcl(f.opt.BucketACL)
			}
			_, err = insertBucket.Context(ctx).Do()
			return shouldRetry(ctx, err)
		})
	}, nil)
}

// Rmdir deletes the bucket if the fs is at the root
//
// Returns an error if it isn't empty: Error 409: The bucket you tried
// to delete was not empty.
func (f *Fs) Rmdir(ctx context.Context, dir string) (err error) {
	// Add trailing slash to folder path
	dirFilePath := fmt.Sprintf("%s/", dir)
	if len(f.rootDirectory) != 0 {
		dirFilePath = fmt.Sprintf("%s/%s", f.rootDirectory, dirFilePath)
	}
	// Query directory marker object before attempting to remove it.
	e := f.pacer.Call(func() (bool, error) {
		_, e := f.svc.Objects.Get(f.rootBucket, dirFilePath).Context(ctx).Do()
		return shouldRetry(ctx, e)
	})
	if e == nil {
		// Using API directly due to trailing slash being removed before Remove() can get full path
		e := f.pacer.Call(func() (bool, error) {
			e := f.svc.Objects.Delete(f.rootBucket, dirFilePath).Context(ctx).Do()
			return shouldRetry(ctx, e)
		})
		if e != nil {
			return e
		}
	}
	bucket, directory := f.split(dir)
	if bucket == "" || directory != "" {
		return nil
	}
	return f.cache.Remove(bucket, func() error {
		return f.pacer.Call(func() (bool, error) {
			err = f.svc.Buckets.Delete(bucket).Context(ctx).Do()
			return shouldRetry(ctx, err)
		})
	})
}

Review comment (suggestion):
Why not just remove it to save an API call. It might return not found in which case you can ignore the error.

Code after:
// immediately.
//
// Don't implement this unless you have a more efficient way
// of listing recursively that doing a directory traversal.
func (f *Fs) ListR(ctx context.Context, dir string, callback fs.ListRCallback) (err error) {
	bucket, directory := f.split(dir)
	list := walk.NewListRHelper(callback)
	listR := func(bucket, directory, prefix string, addBucket bool) error {
		return f.list(ctx, bucket, directory, prefix, addBucket, true, func(remote string, object *storage.Object, isDirectory bool) error {
			entry, err := f.itemToDirEntry(ctx, remote, object, isDirectory)
			if err != nil {
				return err
			}
			return list.Add(entry)
		})
	}
	if bucket == "" {
		entries, err := f.listBuckets(ctx)
		if err != nil {
			return err
		}
		for _, entry := range entries {
			err = list.Add(entry)
			if err != nil {
				return err
			}
			bucket := entry.Remote()
			err = listR(bucket, "", f.rootDirectory, true)
			if err != nil {
				return err
			}
			// bucket must be present if listing succeeded
			f.cache.MarkOK(bucket)
		}
	} else {
		err = listR(bucket, directory, f.rootDirectory, f.rootBucket == "")
		if err != nil {
			return err
		}
		// bucket must be present if listing succeeded
		f.cache.MarkOK(bucket)
	}
	return list.Flush()
}

// Put the object into the bucket
//
// Copy the reader in to the new object which is returned.
//
// The new object may have been created if an error is returned
func (f *Fs) Put(ctx context.Context, in io.Reader, src fs.ObjectInfo, options ...fs.OpenOption) (fs.Object, error) {