-
Notifications
You must be signed in to change notification settings - Fork 46
/
Copy pathdrive_update.R
139 lines (128 loc) · 3.9 KB
/
drive_update.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#' Update an existing Drive file
#'
#' Update an existing Drive file id with new content ("media" in Drive
#' API-speak), new metadata, or both. To create a new file or update existing,
#' depending on whether the Drive file already exists, see [drive_put()].
#'
#' @seealso Wraps the `files.update` endpoint:
#' * <https://developers.google.com/drive/api/v3/reference/files/update>
#'
#' This function supports media upload:
#' * <https://developers.google.com/drive/api/v3/manage-uploads>
#'
#' @template file-singular
#' @template media
#' @template dots-metadata
#' @template verbose
#'
#' @eval return_dribble()
#' @export
#'
#' @examplesIf drive_has_token()
#' # Create a new file, so we can update it
#' x <- drive_example_remote("chicken.csv") %>%
#' drive_cp()
#'
#' # Update the file with new media
#' x <- x %>%
#' drive_update(drive_example_local("chicken.txt"))
#'
#' # Update the file with new metadata.
#' # Notice here `name` is not an argument of `drive_update()`, we are passing
#' # this to the API via the `...``
#' x <- x %>%
#' drive_update(name = "CHICKENS!")
#'
#' # Update the file with new media AND new metadata
#' x <- x %>%
#' drive_update(
#' drive_example_local("chicken.txt"),
#' name = "chicken-poem-again.txt"
#' )
#'
#' # Clean up
#' drive_rm(x)
drive_update <- function(file,
media = NULL,
...,
verbose = deprecated()) {
warn_for_verbose(verbose)
if ((!is.null(media)) && (!file.exists(media))) {
drive_abort(c(
"No file exists at the local {.arg media} path:",
bulletize(gargle_map_cli(media, "{.path <<x>>}"), bullet = "x")
))
}
file <- as_dribble(file)
file <- confirm_single_file(file)
meta <- toCamel(list2(...))
if (is.null(media) && length(meta) == 0) {
drive_bullets(c(
"!" = "No updates specified."
))
return(invisible(file))
}
meta[["fields"]] <- meta[["fields"]] %||% "*"
if (is.null(media)) {
out <- drive_update_metadata(file, meta)
} else {
if (length(meta) == 0) {
out <- drive_update_media(file, media)
} else {
media <- enc2utf8(media)
out <- drive_update_multipart(file, media, meta)
}
}
drive_bullets(c("File updated:", bulletize(gargle_map_cli(out))))
invisible(out)
}
## currently this can never be called, because we always send fields
drive_update_media <- function(file, media) {
request <- request_generate(
endpoint = "drive.files.update.media",
params = list(
fileId = file$id,
uploadType = "media",
fields = "*"
)
)
## media uploads have unique body situations, so customizing here.
request$body <- httr::upload_file(path = media)
response <- request_make(request)
as_dribble(list(gargle::response_process(response)))
}
drive_update_metadata <- function(file, meta) {
params <- meta %||% list()
params$fileId <- file$id
request <- request_generate(
endpoint = "drive.files.update",
params = params
)
response <- request_make(request)
as_dribble(list(gargle::response_process(response)))
}
drive_update_multipart <- function(file, media, meta) {
# We include the metadata here even though it's overwritten below,
# so that request_generate() still validates it.
params <- meta %||% list()
params$fileId <- file$id
params$uploadType <- "multipart"
request <- request_generate(
endpoint = "drive.files.update.media",
params = params
)
meta_file <- withr::local_file(
tempfile("drive-update-meta", fileext = ".json")
)
write_utf8(jsonlite::toJSON(meta), meta_file)
## media uploads have unique body situations, so customizing here.
request$body <- list(
metadata = httr::upload_file(
path = meta_file,
type = "application/json; charset=UTF-8"
),
media = httr::upload_file(path = media)
)
response <- request_make(request, encode = "multipart")
as_dribble(list(gargle::response_process(response)))
}