code: private void deleteInternal(List<FileInfo> itemsToDelete, List<FileInfo> bucketsToDelete)
        throws IOException {
      // TODO(user): We might need to separate out children into separate batches from parents to
      // avoid deleting a parent before somehow failing to delete a child.
  
      // Delete children before their parents.
      //
      // Note: we modify the input list, which is ok for current usage.
      // We should make a copy in case that changes in future.
      itemsToDelete.sort(FILE_INFO_PATH_COMPARATOR.reversed());
  
      if (!itemsToDelete.isEmpty()) {
        List<StorageResourceId> objectsToDelete = new ArrayList<>(itemsToDelete.size());
        for (FileInfo fileInfo : itemsToDelete) {
          // TODO(b/110833109): populate generation ID in StorageResourceId when listing infos?
          objectsToDelete.add(
              new StorageResourceId(
                  fileInfo.getItemInfo().getBucketName(),
                  fileInfo.getItemInfo().getObjectName(),
                  fileInfo.getItemInfo().getContentGeneration()));
        }
        gcs.deleteObjects(objectsToDelete);
      }
  
      if (!bucketsToDelete.isEmpty()) {
        List<String> bucketNames = new ArrayList<>(bucketsToDelete.size());
        for (FileInfo bucketInfo : bucketsToDelete) {
          StorageResourceId resourceId = bucketInfo.getItemInfo().getResourceId();
          gcs.waitForBucketEmpty(resourceId.getBucketName());
          bucketNames.add(resourceId.getBucketName());
        }
        if (options.enableBucketDelete()) {
          gcs.deleteBuckets(bucketNames);
        } else {
          logger.atInfo().log(
              "Skipping deletion of buckets because enableBucketDelete is false: %s", bucketNames);
        }
      }
    }
docs: Deletes all items in the given path list followed by all bucket items.