diff --git a/R/bucket.R b/R/bucket.R index dbf9b66..4ac043c 100644 --- a/R/bucket.R +++ b/R/bucket.R @@ -261,6 +261,80 @@ aws_bucket_upload <- function( s3_path(bucket) } +#' Magically upload a folder of files or files go a bucket +#' +#' @export +#' @param path (character) one or more file paths to add to +#' the `bucket`. required. can include directories or files +#' @param remote (character) a vector of paths to use to upload +#' files in `path`. required +#' @inheritParams aws_file_copy +#' @param ... named params passed on to +#' [put_object](https://www.paws-r-sdk.com/docs/s3_put_object/) +#' @section What is magical: +#' - Exits early if folder or files do not exist +#' - Creates the bucket if it does not exist +#' - Adds files to the bucket, figuring out the key to use from +#' the supplied path +#' - Function is vectoried for the `path` argument; you can +#' pass in many paths +#' @family buckets +#' @family magicians +#' @return (character) a vector of remote s3 paths where your +#' files are located +#' @examplesIf interactive() +#' # single file, single remote path +#' bucket <- random_string("bucket") +#' demo_rds_file <- file.path(system.file(), "Meta/demo.rds") +#' six_bucket_upload(path = demo_rds_file, remote = bucket) +#' +#' ## a file and a directory - single remote path +#' library(fs) +#' tdir <- path(path_temp(), "mytmp") +#' dir_create(tdir) +#' purrr::map(letters, \(l) file_create(path(tdir, l))) +#' six_bucket_upload(path = c(demo_rds_file, tdir), remote = bucket) +#' +#' ## two files - two values passed to remote path +#' links_file <- file.path(system.file(), "Meta/links.rds") +#' six_bucket_upload(path = c(demo_rds_file, links_file), +#' remote = path(bucket, c("afile.txt", "anotherfile.txt"))) +six_bucket_upload <- function(path, remote, force = FALSE, ...) { + stop_if_not(is_character(path), "{.strong path} must be character") + stop_if_not(is_character(remote), "{.strong remote} must be character") + stop_if_not( + all(fs::file_exists(path)), + "one or more of {.strong path} don't exist" + ) + bucket <- dirname(remote[1]) + bucket_create_if_not(bucket, force) + if (!aws_bucket_exists(bucket)) { + cli_warning("bucket {.strong {bucket}} not created; exiting") + return(invisible()) + } + + # figure out the paths + if (length(remote) == 1) { + remote_paths <- remote + if (length(path) > 1) { + cli_info("recycling {.strong remote} for each {.strong path}") + remote_paths <- rep(as.character(remote), times = length(path)) + } + } else if (length(remote) > 1) { + if (length(path) != length(remote)) { + cli_abort(paste0(c("if {.strong length(remote) > 1} then ", + "{.strong length(path)} == {.strong length(remote)}"), collapse = " ")) + } else { + remote_paths <- remote + } + } + + map2(path, remote_paths, \(p, r) { + con_s3()$put_object(Bucket = bucket, Key = basename(p), Body = p, ...) + }) + s3_path(bucket, basename(remote_paths)) +} + #' List objects in an S3 bucket #' #' @export