#' Get Drive files by path or id
#'
#' Retrieves metadata for files specified via `path` or via file `id`. This
#' function is quite straightforward if you specify files by `id`. But there are
#' some important considerations when you specify your target files by `path`.
#' See below for more. If the target files are specified via `path`, the
#' returned [`dribble`] will include a `path` column.
#' @section Getting by `path`:
#'
#' Google Drive does NOT behave like your local file system! File and folder
#' names need not be unique, even at a given level of the hierarchy. This
#' means that a single path can describe multiple files (or 0 or exactly 1).
#'
#' A single file can also be compatible with multiple paths, i.e. one path
#' could be more specific than the other. A file located at `~/alfa/bravo` can
#' be found as `bravo`, `alfa/bravo`, and `~/alfa/bravo`. If all 3 of those
#' were included in the input `path`, they would be represented by a
#' **single** row in the output.
#'
#' It's best to think of `drive_get()` as a setwise operation when using file
#' paths. Do not assume that the `i`-th input path corresponds to row `i` in
#' the output (although it often does!). If there's not a 1-to-1 relationship
#' between the input and output, this will be announced in a message.
#'
#' `drive_get()` performs just enough path resolution to uniquely identify a
#' file compatible with each input `path`, for all `path`s at once. If you
#' absolutely want the full canonical path, run the output of `drive_get()`
#' through [`drive_reveal(d, "path")`][drive_reveal()]`.
#'
#' @section Files that you don't own:
#'
#' If you want to get a file via `path` and it's not necessarily on your My
#' Drive, you may need to specify the `shared_drive` or `corpus` arguments to
#' search other collections of items. Read more about [shared
#' drives][shared_drives].
#'
#' @seealso To add path information to any [`dribble`] that lacks it, use
#' [`drive_reveal(d, "path")`][drive_reveal()]. To list the contents of a
#' folder, use [drive_ls()]. For general searching, use [drive_find()].
#'
#' Wraps the `files.get` endpoint and, if you specify files by name or
#' path, also calls `files.list`:
#' * <https://developers.google.com/drive/api/v3/reference/files/get>
#' * <https://developers.google.com/drive/api/v3/reference/files/list>
#'
#' @param path Character vector of path(s) to get. Use a trailing slash to
#' indicate explicitly that a path is a folder, which can disambiguate if
#' there is a file of the same name (yes this is possible on Drive!). If
#' `path` appears to contain Drive URLs or is explicitly marked with
#' [as_id()], it is treated as if it was provided via the `id` argument.
#' @param id Character vector of Drive file ids or URLs (it is first processed
#' with [as_id()]). If both `path` and `id` are non-`NULL`, `id` is silently
#' ignored.
#' @template shared_drive-singular
#' @template corpus
#' @template verbose
#' @template team_drive-singular
#'
#' @eval return_dribble(extras = "If the target files were specified via `path`,
#' there will be a `path` column.")
#' @export
#'
#' @examplesIf drive_has_token()
#' # get info about your "My Drive" root folder
#' drive_get("~/")
#' # the API reserves the file id "root" for your root folder
#' drive_get(id = "root")
#' drive_get(id = "root") %>% drive_reveal("path")
#'
#' # set up some files to get by path
#' alfalfa <- drive_mkdir("alfalfa")
#' broccoli <- drive_upload(
#' drive_example_local("chicken.txt"),
#' name = "broccoli", path = alfalfa
#' )
#' drive_get("broccoli")
#' drive_get("alfalfa/broccoli")
#' drive_get("~/alfalfa/broccoli")
#' drive_get(c("broccoli", "alfalfa/", "~/alfalfa/broccoli"))
#'
#' # Clean up
#' drive_rm(alfalfa)
#'
#' \dontrun{
#' # The examples below are indicative of correct syntax.
#' # But note these will generally result in an error or a
#' # 0-row dribble, unless you replace the inputs with paths
#' # or file ids that exist in your Drive.
#'
#' # multiple names
#' drive_get(c("abc", "def"))
#'
#' # multiple names, one of which must be a folder
#' drive_get(c("abc", "def/"))
#'
#' # query by file id(s)
#' drive_get(id = "abcdefgeh123456789")
#' drive_get(as_id("abcdefgeh123456789"))
#' drive_get(id = c("abcdefgh123456789", "jklmnopq123456789"))
#'
#' # apply to a browser URL for, e.g., a Google Sheet
#' my_url <- "https://docs.google.com/spreadsheets/d/FILE_ID/edit#gid=SHEET_ID"
#' drive_get(my_url)
#' drive_get(as_id(my_url))
#' drive_get(id = my_url)
#'
#' # access the shared drive named "foo"
#' # shared_drive params must be specified if getting by path
#' foo <- shared_drive_get("foo")
#' drive_get(c("this.jpg", "that-file"), shared_drive = foo)
#' # shared_drive params are not necessary if getting by id
#' drive_get(as_id("123456789"))
#'
#' # search all shared drives and other files user has accessed
#' drive_get(c("this.jpg", "that-file"), corpus = "allDrives")
#' }
drive_get <- function(path = NULL,
id = NULL,
shared_drive = NULL,
corpus = NULL,
verbose = deprecated(),
team_drive = deprecated()) {
warn_for_verbose(verbose)
if (length(path) + length(id) == 0) {
return(dribble_with_path())
}
stopifnot(is.null(path) || is.character(path))
stopifnot(is.null(id) || is.character(id))
if (lifecycle::is_present(team_drive)) {
lifecycle::deprecate_warn(
"2.0.0",
"drive_get(team_drive)",
"drive_get(shared_drive)"
)
shared_drive <- shared_drive %||% team_drive
}
if (!is.null(path) && any(is_drive_url(path))) {
path <- as_id(path)
}
if (!is.null(path) && is_drive_id(path)) {
id <- path
path <- NULL
}
if (is.null(path)) {
as_dribble(map(as_id(id), get_one_file_id))
} else {
drive_get_path(path, shared_drive, corpus)
}
}
get_one_file_id <- function(id) {
if (is.na(id)) {
drive_abort("Can't {.fun drive_get} a file when {.arg id} is {.code NA}.")
}
# drive_id validity checks catch the id = "" case, but just FYI:
# when id = "", drive.files.get actually becomes a call to drive.files.list
# and, therefore, returns 100 files by default; this is a bad thing
request <- request_generate(
endpoint = "drive.files.get",
params = list(
fileId = id,
fields = "*"
)
)
response <- request_make(request)
gargle::response_process(response)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.