├── .Rbuildignore ├── .covrignore ├── .github ├── .gitignore ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.Rmd ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE │ └── issue_template.md ├── SUPPORT.md └── workflows │ ├── R-CMD-check.yaml │ ├── pkgdown.yaml │ ├── pr-commands.yaml │ ├── test-coverage.yaml │ └── with-auth.yml ├── .gitignore ├── DESCRIPTION ├── LICENSE ├── LICENSE.md ├── NAMESPACE ├── NEWS.md ├── R ├── aaa.R ├── camelCase.R ├── compat-dplyr.R ├── compat-vctrs.R ├── deprecated.R ├── dribble.R ├── drive_about.R ├── drive_auth.R ├── drive_browse.R ├── drive_cp.R ├── drive_create.R ├── drive_download.R ├── drive_endpoints.R ├── drive_examples.R ├── drive_fields.R ├── drive_find.R ├── drive_get.R ├── drive_get_path.R ├── drive_id-class.R ├── drive_ls.R ├── drive_mime_type.R ├── drive_mkdir.R ├── drive_mv.R ├── drive_publish.R ├── drive_put.R ├── drive_read.R ├── drive_rename.R ├── drive_reveal.R ├── drive_rm.R ├── drive_share.R ├── drive_trash.R ├── drive_update.R ├── drive_upload.R ├── drive_user.R ├── googledrive-package.R ├── promote.R ├── request_generate.R ├── request_make.R ├── roxygen-templates.R ├── shared_drive_create.R ├── shared_drive_find.R ├── shared_drive_get.R ├── shared_drive_rm.R ├── shared_drive_update.R ├── shared_drives.R ├── shortcut.R ├── sysdata.rda ├── team_drive.R ├── utils-io.R ├── utils-paths.R ├── utils-pipe.R ├── utils-ui.R ├── utils.R └── zzz.R ├── README.Rmd ├── README.md ├── _pkgdown.yml ├── codecov.yml ├── cran-comments.md ├── data-raw ├── discovery-doc-ingest.R ├── drive-examples-create.R ├── drive-examples-inventory.R ├── drive-v3_2021-06-21.json ├── export-mime-type-defaults.csv ├── extension-mime-type-defaults.csv ├── file-fields.R ├── mime-types.R └── old │ ├── 20170519_drive-v3_discovery-document.json │ ├── 20170519_drive-v3_endpoints-list.json │ ├── 20170519_drive-v3_endpoints-list.rds │ ├── 20170519_drive-v3_endpoints-tibble.rds │ ├── 20170721_drive-v3_discovery-document.json │ ├── 20170721_drive-v3_endpoints-list.json │ ├── 20170721_drive-v3_endpoints-list.rds │ ├── 20170721_drive-v3_endpoints-tibble.rds │ ├── 20171110_drive-v3_discovery-document.json │ ├── 20171110_drive-v3_endpoints-list.json │ ├── 20171110_drive-v3_endpoints-list.rds │ ├── 20171110_drive-v3_endpoints-tibble.rds │ ├── discovery-doc-prep.R │ ├── drive-v3_2019-02-14.json │ ├── drive-v3_2019-07-08.json │ ├── drive-v3_2020-04-17.json │ └── drive-v3_2021-03-22.json ├── googledrive.Rproj ├── index.Rmd ├── index.md ├── inst ├── WORDLIST ├── extdata │ ├── data │ │ ├── client_secret_123.googleusercontent.com.json │ │ ├── files_fields.csv │ │ ├── mime_tbl.csv │ │ ├── remote_example_files.csv │ │ └── translate_mime_types.csv │ └── example_files │ │ ├── chicken.csv │ │ ├── chicken.jpg │ │ ├── chicken.pdf │ │ ├── chicken.txt │ │ ├── imdb_latin1.csv │ │ ├── r_about.html │ │ └── r_logo.jpg └── secret │ ├── googledrive-docs.json │ └── googledrive-testing.json ├── internal ├── 2017-08-googledrive-initial-release.Rmd ├── 2017-08-googledrive-initial-release.md ├── 2019-02-18_tidyverse-meeting.R ├── drive_upload.Rmd ├── drive_upload.md ├── googledrive-og-1280x640.png ├── googledrive.png ├── old │ ├── 01_big-picture.Rmd │ ├── 01_big-picture.md │ ├── 02_sharing_demo.Rmd │ ├── 02_sharing_demo.md │ ├── 03_publish_demo.Rmd │ ├── 03_publish_demo.md │ ├── 04_map_demo.Rmd │ ├── 04_map_demo.md │ ├── 06_dots_demo.Rmd │ ├── 06_dots_demo.md │ ├── 07_drive_ls_demo.Rmd │ └── 07_drive_ls_demo.md └── tokens.R ├── man-roxygen ├── corpus.R ├── dots-metadata.R ├── file-plural.R ├── file-singular.R ├── media.R ├── n_max.R ├── overwrite.R ├── pattern.R ├── shared-drive-description.R ├── shared_drive-plural.R ├── shared_drive-singular.R ├── team-drives-description.R ├── team_drive-plural.R ├── team_drive-singular.R └── verbose.R ├── man ├── as_dribble.Rd ├── as_shared_drive.Rd ├── deprecated-team-drive-functions.Rd ├── dribble-checks.Rd ├── dribble.Rd ├── drive_about.Rd ├── drive_auth.Rd ├── drive_auth_configure.Rd ├── drive_browse.Rd ├── drive_cp.Rd ├── drive_create.Rd ├── drive_deauth.Rd ├── drive_download.Rd ├── drive_empty_trash.Rd ├── drive_endpoints.Rd ├── drive_examples.Rd ├── drive_extension.Rd ├── drive_fields.Rd ├── drive_find.Rd ├── drive_get.Rd ├── drive_has_token.Rd ├── drive_id.Rd ├── drive_link.Rd ├── drive_ls.Rd ├── drive_mime_type.Rd ├── drive_mkdir.Rd ├── drive_mv.Rd ├── drive_publish.Rd ├── drive_put.Rd ├── drive_read_string.Rd ├── drive_rename.Rd ├── drive_reveal.Rd ├── drive_rm.Rd ├── drive_scopes.Rd ├── drive_share.Rd ├── drive_token.Rd ├── drive_trash.Rd ├── drive_update.Rd ├── drive_upload.Rd ├── drive_user.Rd ├── expose.Rd ├── figures │ ├── lifecycle-archived.svg │ ├── lifecycle-defunct.svg │ ├── lifecycle-deprecated.svg │ ├── lifecycle-experimental.svg │ ├── lifecycle-maturing.svg │ ├── lifecycle-questioning.svg │ ├── lifecycle-soft-deprecated.svg │ ├── lifecycle-stable.svg │ ├── lifecycle-superseded.svg │ └── logo.png ├── googledrive-configuration.Rd ├── googledrive-deprecated.Rd ├── googledrive-package.Rd ├── pipe.Rd ├── request_generate.Rd ├── request_make.Rd ├── shared_drive_create.Rd ├── shared_drive_find.Rd ├── shared_drive_get.Rd ├── shared_drive_rm.Rd ├── shared_drive_update.Rd ├── shared_drives.Rd ├── shortcut_create.Rd └── shortcut_resolve.Rd ├── pkgdown └── favicon │ ├── apple-touch-icon-120x120.png │ ├── apple-touch-icon-60x60.png │ ├── apple-touch-icon-76x76.png │ ├── apple-touch-icon.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ └── favicon.ico ├── revdep ├── .gitignore ├── README.md ├── cran.md ├── failures.md └── problems.md ├── tests ├── spelling.R ├── testthat.R └── testthat │ ├── .gitignore │ ├── _snaps │ ├── deprecated.md │ ├── dribble.md │ ├── drive_auth.md │ ├── drive_cp.md │ ├── drive_create.md │ ├── drive_download.md │ ├── drive_examples.md │ ├── drive_fields.md │ ├── drive_find.md │ ├── drive_get.md │ ├── drive_id-class.md │ ├── drive_ls.md │ ├── drive_mime_type.md │ ├── drive_mv.md │ ├── drive_publish.md │ ├── drive_put.md │ ├── drive_reveal.md │ ├── drive_share.md │ ├── drive_update.md │ ├── drive_upload.md │ ├── request_generate.md │ ├── shared_drives.md │ ├── shortcut.md │ ├── utils-paths.md │ └── utils-ui.md │ ├── driver.R │ ├── helper.R │ ├── setup-testing.R │ ├── test-camelCase.R │ ├── test-compat-dplyr.R │ ├── test-compat-vctrs.R │ ├── test-deprecated.R │ ├── test-dribble.R │ ├── test-drive_auth.R │ ├── test-drive_browse.R │ ├── test-drive_cp.R │ ├── test-drive_create.R │ ├── test-drive_download.R │ ├── test-drive_endpoints.R │ ├── test-drive_examples.R │ ├── test-drive_fields.R │ ├── test-drive_find.R │ ├── test-drive_get.R │ ├── test-drive_get_path.R │ ├── test-drive_id-class.R │ ├── test-drive_ls.R │ ├── test-drive_mime_type.R │ ├── test-drive_mv.R │ ├── test-drive_publish.R │ ├── test-drive_put.R │ ├── test-drive_read.R │ ├── test-drive_reveal.R │ ├── test-drive_rm.R │ ├── test-drive_share.R │ ├── test-drive_trash.R │ ├── test-drive_update.R │ ├── test-drive_upload.R │ ├── test-drive_user.R │ ├── test-fixtures │ ├── just_a_dribble.rds │ └── mix_of_files_and_teamdrives.rds │ ├── test-promote.R │ ├── test-request_generate.R │ ├── test-shared_drives.R │ ├── test-shortcut.R │ ├── test-utils-paths.R │ ├── test-utils-ui.R │ └── test-utils.R └── vignettes ├── .gitignore ├── articles ├── .gitignore ├── bring-your-own-client.Rmd ├── example-files.Rmd ├── file-identification.Rmd ├── messages-and-errors.Rmd ├── multiple-files.Rmd └── permissions.Rmd └── googledrive.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^scratch.R$ 4 | ^internal$ 5 | ^data-raw$ 6 | ^\.httr-oauth$ 7 | ^\.httr-oauth-SUSPENDED$ 8 | ^\.travis\.yml$ 9 | ^codecov\.yml$ 10 | ^appveyor\.yml$ 11 | ^README\.Rmd$ 12 | ^README-.*\.png$ 13 | ^man-roxygen$ 14 | ^docs$ 15 | ^_pkgdown\.yml$ 16 | ^index\.Rmd$ 17 | ^cran-comments\.md$ 18 | ^\.github$ 19 | ^pkgdown$ 20 | ^vignettes/articles$ 21 | ^revdep$ 22 | ^index\.md$ 23 | ^LICENSE\.md$ 24 | ^CRAN-RELEASE$ 25 | ^\.covrignore$ 26 | ^tests/testthat/all-test.+ 27 | ^CRAN-SUBMISSION$ 28 | -------------------------------------------------------------------------------- /.covrignore: -------------------------------------------------------------------------------- 1 | R/aaa.R 2 | R/deprecated.R 3 | R/dplyr-compat.R 4 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # CODEOWNERS for googledrive 2 | # https://www.tidyverse.org/development/understudies 3 | .github/CODEOWNERS @jennybc @lucymcgowan 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/issue_template.md: -------------------------------------------------------------------------------- 1 | Please briefly describe your problem and what output you expect. If you have a question, please don't use this form. Instead, ask on or . 2 | 3 | Please include a minimal reproducible example (AKA a reprex). If you've never heard of a [reprex](https://reprex.tidyverse.org/) before, start by reading . 4 | 5 | --- 6 | 7 | Brief description of the problem 8 | 9 | ```r 10 | # insert reprex here 11 | ``` 12 | -------------------------------------------------------------------------------- /.github/SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Getting help with googledrive 2 | 3 | Thanks for using googledrive. Before filing an issue, there are a few places 4 | to explore and pieces to put together to make the process as smooth as possible. 5 | 6 | Start by making a minimal **repr**oducible **ex**ample using the 7 | [reprex](https://reprex.tidyverse.org/) package. If you haven't heard of or used 8 | reprex before, you're in for a treat! Seriously, reprex will make all of your 9 | R-question-asking endeavors easier (which is a pretty insane ROI for the five to 10 | ten minutes it'll take you to learn what it's all about). For additional reprex 11 | pointers, check out the [Get help!](https://www.tidyverse.org/help/) section of 12 | the tidyverse site. 13 | 14 | Armed with your reprex, the next step is to figure out [where to ask](https://www.tidyverse.org/help/#where-to-ask). 15 | 16 | * If it's a question: start with [community.rstudio.com](https://community.rstudio.com/), 17 | and/or StackOverflow. There are more people there to answer questions. 18 | * If it's a bug: you're in the right place, file an issue. 19 | * If you're not sure: let the community help you figure it out! If your 20 | problem _is_ a bug or a feature request, you can easily return here and 21 | report it. 22 | 23 | Before opening a new issue, be sure to [search issues and pull requests](https://github.com/tidyverse/googledrive/issues) to make sure the 24 | bug hasn't been reported and/or already fixed in the development version. By 25 | default, the search will be pre-populated with `is:issue is:open`. You can 26 | [edit the qualifiers](https://help.github.com/articles/searching-issues-and-pull-requests/) 27 | (e.g. `is:pr`, `is:closed`) as needed. For example, you'd simply 28 | remove `is:open` to search _all_ issues in the repo, open or closed. 29 | 30 | 31 | If you _are_ in the right place, and need to file an issue, please review the 32 | ["File issues"](https://www.tidyverse.org/contribute/#issues) paragraph from 33 | the tidyverse contributing guidelines. 34 | 35 | Thanks for your help! 36 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | # 4 | # NOTE: This workflow is overkill for most R packages and 5 | # check-standard.yaml is likely a better choice. 6 | # usethis::use_github_action("check-standard") will install it. 7 | on: 8 | push: 9 | branches: [main, master] 10 | pull_request: 11 | branches: [main, master] 12 | 13 | name: R-CMD-check.yaml 14 | 15 | permissions: read-all 16 | 17 | jobs: 18 | R-CMD-check: 19 | runs-on: ${{ matrix.config.os }} 20 | 21 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 22 | 23 | strategy: 24 | fail-fast: false 25 | matrix: 26 | config: 27 | - {os: macos-latest, r: 'release'} 28 | 29 | - {os: windows-latest, r: 'release'} 30 | # use 4.0 or 4.1 to check with rtools40's older compiler 31 | - {os: windows-latest, r: 'oldrel-4'} 32 | 33 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 34 | - {os: ubuntu-latest, r: 'release'} 35 | - {os: ubuntu-latest, r: 'oldrel-1'} 36 | - {os: ubuntu-latest, r: 'oldrel-2'} 37 | - {os: ubuntu-latest, r: 'oldrel-3'} 38 | - {os: ubuntu-latest, r: 'oldrel-4'} 39 | 40 | env: 41 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 42 | R_KEEP_PKG_SOURCE: yes 43 | 44 | steps: 45 | - uses: actions/checkout@v4 46 | 47 | - uses: r-lib/actions/setup-pandoc@v2 48 | 49 | - uses: r-lib/actions/setup-r@v2 50 | with: 51 | r-version: ${{ matrix.config.r }} 52 | http-user-agent: ${{ matrix.config.http-user-agent }} 53 | use-public-rspm: true 54 | 55 | - uses: r-lib/actions/setup-r-dependencies@v2 56 | with: 57 | extra-packages: any::rcmdcheck 58 | needs: check 59 | 60 | - uses: r-lib/actions/check-r-package@v2 61 | with: 62 | upload-snapshots: true 63 | build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")' 64 | -------------------------------------------------------------------------------- /.github/workflows/pkgdown.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | schedule: 7 | # * is a special character in YAML so we have to quote this string 8 | # 13:30 (UTC) - 7 or 8 (offset for Pacific) = 5:30 or 6:30 am 9 | # try to avoid overlap other jobs in googledrive and googlesheets4 because quota 10 | # https://crontab.guru is your friend 11 | - cron: '30 13 * * *' 12 | release: 13 | types: [published] 14 | workflow_dispatch: 15 | 16 | name: pkgdown.yaml 17 | 18 | permissions: read-all 19 | 20 | jobs: 21 | pkgdown: 22 | runs-on: ubuntu-latest 23 | if: | 24 | github.event_name == 'schedule' || 25 | github.event_name == 'workflow_dispatch' || 26 | github.event_name == 'release' || 27 | contains(github.event.head_commit.message, '[pkgdown]') 28 | 29 | env: 30 | GOOGLEDRIVE_KEY: ${{ secrets.GOOGLEDRIVE_KEY }} 31 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 32 | permissions: 33 | contents: write 34 | steps: 35 | - uses: actions/checkout@v4 36 | 37 | - uses: r-lib/actions/setup-pandoc@v2 38 | 39 | - uses: r-lib/actions/setup-r@v2 40 | with: 41 | use-public-rspm: true 42 | 43 | - uses: r-lib/actions/setup-r-dependencies@v2 44 | with: 45 | extra-packages: any::pkgdown, local::. 46 | needs: website 47 | 48 | - name: Build site 49 | run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) 50 | shell: Rscript {0} 51 | 52 | - name: Deploy to GitHub pages 🚀 53 | if: github.event_name != 'pull_request' 54 | uses: JamesIves/github-pages-deploy-action@v4.5.0 55 | with: 56 | clean: false 57 | branch: gh-pages 58 | folder: docs 59 | -------------------------------------------------------------------------------- /.github/workflows/test-coverage.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | schedule: 9 | # * is a special character in YAML so we have to quote this string 10 | # 2am Pacific = 10am UTC 11 | # https://crontab.guru is your friend 12 | - cron: '0 10 * * *' 13 | 14 | name: test-coverage.yaml 15 | 16 | permissions: read-all 17 | 18 | jobs: 19 | test-coverage: 20 | runs-on: ubuntu-latest 21 | if: "github.event_name == 'schedule' || contains(github.event.head_commit.message, '[covr]')" 22 | 23 | env: 24 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 25 | GOOGLEDRIVE_KEY: ${{ secrets.GOOGLEDRIVE_KEY }} 26 | 27 | steps: 28 | - uses: actions/checkout@v4 29 | 30 | - uses: r-lib/actions/setup-r@v2 31 | with: 32 | use-public-rspm: true 33 | 34 | - uses: r-lib/actions/setup-r-dependencies@v2 35 | with: 36 | extra-packages: any::covr, any::xml2 37 | needs: coverage 38 | 39 | - name: Test coverage 40 | run: | 41 | cov <- covr::package_coverage( 42 | quiet = FALSE, 43 | clean = FALSE, 44 | install_path = file.path(normalizePath(Sys.getenv("RUNNER_TEMP"), winslash = "/"), "package") 45 | ) 46 | covr::to_cobertura(cov) 47 | shell: Rscript {0} 48 | 49 | - uses: codecov/codecov-action@v4 50 | with: 51 | fail_ci_if_error: ${{ github.event_name != 'pull_request' && true || false }} 52 | file: ./cobertura.xml 53 | plugin: noop 54 | disable_search: true 55 | token: ${{ secrets.CODECOV_TOKEN }} 56 | 57 | - name: Show testthat output 58 | if: always() 59 | run: | 60 | ## -------------------------------------------------------------------- 61 | find '${{ runner.temp }}/package' -name 'testthat.Rout*' -exec cat '{}' \; || true 62 | shell: bash 63 | 64 | - name: Upload test results 65 | if: failure() 66 | uses: actions/upload-artifact@v4 67 | with: 68 | name: coverage-test-failures 69 | path: ${{ runner.temp }}/package 70 | -------------------------------------------------------------------------------- /.github/workflows/with-auth.yml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: with-auth 10 | 11 | permissions: read-all 12 | 13 | jobs: 14 | with-auth: 15 | runs-on: ubuntu-latest 16 | 17 | env: 18 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 19 | 20 | steps: 21 | - uses: actions/checkout@v4 22 | 23 | - uses: r-lib/actions/setup-pandoc@v2 24 | 25 | - uses: r-lib/actions/setup-r@v2 26 | with: 27 | r-version: release 28 | http-user-agent: 'release' 29 | use-public-rspm: true 30 | 31 | - uses: r-lib/actions/setup-r-dependencies@v2 32 | with: 33 | extra-packages: any::rcmdcheck 34 | needs: check 35 | 36 | - uses: r-lib/actions/check-r-package@v2 37 | env: 38 | GOOGLEDRIVE_KEY: ${{ secrets.GOOGLEDRIVE_KEY }} 39 | with: 40 | upload-snapshots: true 41 | build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")' 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | sandbox 2 | scratch.R 3 | *.Rproj.user 4 | .Rhistory 5 | .Rproj.user 6 | .RData 7 | .httr-oauth* 8 | .Rapp.history 9 | *token.rds 10 | inst/doc 11 | docs/ 12 | internal 13 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: googledrive 2 | Title: An Interface to Google Drive 3 | Version: 2.1.1.9000 4 | Authors@R: c( 5 | person("Lucy", "D'Agostino McGowan", , role = "aut"), 6 | person("Jennifer", "Bryan", , "jenny@posit.co", role = c("aut", "cre"), 7 | comment = c(ORCID = "0000-0002-6983-2759")), 8 | person("Posit Software, PBC", role = c("cph", "fnd")) 9 | ) 10 | Description: Manage Google Drive files from R. 11 | License: MIT + file LICENSE 12 | URL: https://googledrive.tidyverse.org, 13 | https://github.com/tidyverse/googledrive 14 | BugReports: https://github.com/tidyverse/googledrive/issues 15 | Depends: 16 | R (>= 3.6) 17 | Imports: 18 | cli (>= 3.0.0), 19 | gargle (>= 1.5.0), 20 | glue (>= 1.4.2), 21 | httr, 22 | jsonlite, 23 | lifecycle, 24 | magrittr, 25 | pillar (>= 1.9.0), 26 | purrr (>= 1.0.1), 27 | rlang (>= 1.0.2), 28 | tibble (>= 2.0.0), 29 | utils, 30 | uuid, 31 | vctrs (>= 0.3.0), 32 | withr 33 | Suggests: 34 | curl, 35 | dplyr (>= 1.0.0), 36 | knitr, 37 | mockr, 38 | rmarkdown, 39 | spelling, 40 | testthat (>= 3.1.5) 41 | VignetteBuilder: 42 | knitr 43 | Config/Needs/website: 44 | tidyverse, 45 | tidyverse/tidytemplate 46 | Config/testthat/edition: 3 47 | Encoding: UTF-8 48 | Language: en-US 49 | Roxygen: list(markdown = TRUE) 50 | RoxygenNote: 7.2.3 51 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2023 2 | COPYRIGHT HOLDER: googledrive authors 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2023 googledrive authors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /R/aaa.R: -------------------------------------------------------------------------------- 1 | # environment to hold data about the Drive API 2 | .drive <- new.env(parent = emptyenv()) 3 | 4 | .drive$translate_mime_types <- 5 | system.file( 6 | "extdata", "data", "translate_mime_types.csv", 7 | package = "googledrive", 8 | mustWork = TRUE 9 | ) %>% 10 | utils::read.csv(stringsAsFactors = FALSE) %>% 11 | as_tibble() 12 | 13 | .drive$mime_tbl <- 14 | system.file( 15 | "extdata", "data", "mime_tbl.csv", 16 | package = "googledrive", 17 | mustWork = TRUE 18 | ) %>% 19 | utils::read.csv(stringsAsFactors = FALSE) %>% 20 | as_tibble() 21 | 22 | .drive$files_fields <- 23 | system.file( 24 | "extdata", "data", "files_fields.csv", 25 | package = "googledrive", 26 | mustWork = TRUE 27 | ) %>% 28 | utils::read.csv(stringsAsFactors = FALSE) %>% 29 | as_tibble() 30 | 31 | # environment to hold other data that is convenient to cache 32 | .googledrive <- new.env(parent = emptyenv()) 33 | -------------------------------------------------------------------------------- /R/camelCase.R: -------------------------------------------------------------------------------- 1 | # camelCase() and toCamel() taken from 2 | # https://github.com/r-dbi/bigrquery/blob/main/R/camelCase.R 3 | 4 | # in theory, belongs in gargle 5 | # but then we'd need to export it and I'm not sure it's worth it 6 | # https://github.com/r-lib/gargle 7 | 8 | # camelCase vs snake_case policy 9 | # ** all arguments in functions exported by googledrive shall be snake_case** 10 | # 11 | # HOWEVER, the Drive API is camelCase 12 | # both wrt parameter names and many of their string values 13 | # examples: `pageSize`, `mimeType`, `corpora = "allDrives"` 14 | # therefore, whenever we pass `...` through, we process with toCamel() 15 | # this means user can say `page_size = 20` and we send `pageSize = 20` 16 | # 17 | # we do not trumpet this snake_case to camelCase conversion in the docs, 18 | # because many of the strings/values we handle are camelCase and we ARE not 19 | # going to alter them 20 | # there's too much potential for confusion 21 | # 22 | # at this point, snake_case to camelCase is a very quiet feature 23 | camelCase <- function(x) { 24 | gsub("_(.)", "\\U\\1", x, perl = TRUE) 25 | } 26 | 27 | toCamel <- function(x) { 28 | if (is.list(x)) { 29 | x[] <- lapply(x, toCamel) 30 | } 31 | 32 | if (!is.null(names(x))) { 33 | names(x) <- camelCase(names(x)) 34 | } 35 | 36 | x 37 | } 38 | 39 | # added later 40 | snake_case <- function(x) { 41 | gsub("([a-z0-9])([A-Z])", "\\1_\\L\\2", x, perl = TRUE) 42 | } 43 | -------------------------------------------------------------------------------- /R/compat-dplyr.R: -------------------------------------------------------------------------------- 1 | dribble_maybe_reconstruct <- function(data, template) { 2 | if (dribble_is_reconstructable(data)) { 3 | # in workflowsets, davis uses new_workflow_set0(x) here 4 | new_dribble(data) 5 | } else { 6 | # @davis tells me there can be internal-to-vctrs-or-dplyr situations where 7 | # reconstruction starts with a conformable list, instead of data.frame 8 | new_tibble0(data) 9 | } 10 | } 11 | 12 | dribble_is_reconstructable <- function(data) { 13 | # see above for why this is is_list() instead of is.data.frame() 14 | is_list(data) && 15 | has_dribble_cols(data) && 16 | has_dribble_coltypes(data) && 17 | id_can_be_drive_id(data$id) && 18 | has_drive_resource(data) 19 | } 20 | 21 | new_tibble0 <- function(x, ..., class = NULL) { 22 | # Handle the 0-column case correctly by using `new_data_frame()`. 23 | # This also correctly strips any attributes except `names` off `x`. 24 | x <- new_data_frame(x) 25 | tibble::new_tibble(x, nrow = nrow(x), class = class) 26 | } 27 | -------------------------------------------------------------------------------- /R/deprecated.R: -------------------------------------------------------------------------------- 1 | #' Deprecated googledrive functions 2 | #' 3 | #' @description 4 | #' `r lifecycle::badge("deprecated")` 5 | #' 6 | #' @section `drive_auth_config()`: 7 | #' 8 | #' This function is defunct. 9 | #' * Use [drive_auth_configure()] to configure your own OAuth client or API key. 10 | #' * Use [drive_deauth()] to go into a de-authorized state. 11 | #' * Use [drive_oauth_client()] to retrieve a user-configured client, if it 12 | #' exists. 13 | #' * Use [drive_api_key()] to retrieve a user-configured API key, if it exists. 14 | #' 15 | #' @section `drive_oauth_app()`: 16 | #' 17 | #' In light of the new [gargle::gargle_oauth_client()] constructor and class of 18 | #' the same name, `drive_oauth_app()` is being replaced by 19 | #' [drive_oauth_client()]. 20 | #' 21 | #' @section `drive_example()`: 22 | #' 23 | #' This function is defunct. Access example files with [drive_examples_local()], 24 | #' [drive_example_local()], [drive_examples_remote()], and 25 | #' [drive_example_remote()]. 26 | #' 27 | #' @keywords internal 28 | #' @name googledrive-deprecated 29 | NULL 30 | 31 | #' @rdname googledrive-deprecated 32 | #' @inheritParams drive_auth_configure 33 | #' @export 34 | drive_auth_config <- function(active, app, path, api_key) { 35 | lifecycle::deprecate_stop( 36 | "1.0.0", 37 | "drive_auth_config()", 38 | details = c( 39 | "Use `drive_auth_configure()` to configure your own OAuth client or API key.", 40 | "Use `drive_deauth()` to go into a de-authorized state.", 41 | "Use `drive_oauth_client()` to retrieve a user-configured client, if it exists.", 42 | "Use `drive_api_key()` to retrieve a user-configured API key, if it exists." 43 | ) 44 | ) 45 | } 46 | 47 | #' @rdname googledrive-deprecated 48 | #' @export 49 | drive_oauth_app <- function() { 50 | lifecycle::deprecate_warn( 51 | "2.1.0", "drive_oauth_app()", "drive_oauth_client()" 52 | ) 53 | drive_oauth_client() 54 | } 55 | 56 | #' @rdname googledrive-deprecated 57 | #' @export 58 | drive_example <- function(path = NULL) { 59 | lifecycle::deprecate_stop( 60 | "2.0.0", 61 | what = "drive_example()", 62 | with = I("`drive_examples_local()` or `drive_example_local()`") 63 | ) 64 | } 65 | -------------------------------------------------------------------------------- /R/drive_about.R: -------------------------------------------------------------------------------- 1 | #' Get info on Drive capabilities 2 | #' 3 | #' Gets information about the user, the user's Drive, and system capabilities. 4 | #' This function mostly exists to power [drive_user()], which extracts the most 5 | #' useful information (the information on current user) and prints it nicely. 6 | #' 7 | #' @seealso Wraps the `about.get` endpoint: 8 | #' * 9 | #' 10 | #' @return A list representation of a Drive 11 | #' [about resource](https://developers.google.com/drive/api/v3/reference/about) 12 | #' @export 13 | #' 14 | #' @examplesIf drive_has_token() 15 | #' drive_about() 16 | #' 17 | #' # explore the export formats available for Drive files, by MIME type 18 | #' about <- drive_about() 19 | #' about[["exportFormats"]] %>% 20 | #' purrr::map(unlist) 21 | drive_about <- function() { 22 | request <- request_generate( 23 | endpoint = "drive.about.get", 24 | params = list(fields = "*") 25 | ) 26 | response <- request_make(request) 27 | gargle::response_process(response) 28 | } 29 | -------------------------------------------------------------------------------- /R/drive_browse.R: -------------------------------------------------------------------------------- 1 | #' Retrieve Drive file links 2 | #' 3 | #' Returns the `"webViewLink"` for one or more files, which is the "link for 4 | #' opening the file in a relevant Google editor or viewer in a browser". 5 | #' 6 | #' @template file-plural 7 | #' 8 | #' @return Character vector of file hyperlinks. 9 | #' @export 10 | #' @examplesIf drive_has_token() 11 | #' # get a few files into a dribble 12 | #' three_files <- drive_find(n_max = 3) 13 | #' 14 | #' # get their browser links 15 | #' drive_link(three_files) 16 | drive_link <- function(file) { 17 | file <- as_dribble(file) 18 | links <- map_chr( 19 | file$drive_resource, 20 | "webViewLink", 21 | .default = NA_character_ 22 | ) 23 | # no documented, programmatic way to get browser links for shared drives 24 | # but this seems to work ... I won't document it either, though 25 | sd <- is_shared_drive(file) 26 | links[sd] <- glue( 27 | "https://drive.google.com/drive/folders/{id}", 28 | id = as_id(file)[sd] 29 | ) 30 | links 31 | } 32 | 33 | #' Visit Drive file in browser 34 | #' 35 | #' Visits a file on Google Drive in your default browser. 36 | #' 37 | #' @template file-singular 38 | #' 39 | #' @return Character vector of file hyperlinks, from [drive_link()], invisibly. 40 | #' @export 41 | #' @examplesIf drive_has_token() && rlang::is_interactive() 42 | #' drive_find(n_max = 1) %>% drive_browse() 43 | drive_browse <- function(file = .Last.value) { 44 | file <- as_dribble(file) 45 | links <- drive_link(file) 46 | if (!interactive() || no_file(file)) { 47 | return(invisible(links)) 48 | } 49 | if (!single_file(file)) { 50 | drive_bullets(c("v" = "Browsing the first file of {nrow(file)}.")) 51 | } 52 | utils::browseURL(links[1]) 53 | invisible(links) 54 | } 55 | -------------------------------------------------------------------------------- /R/drive_endpoints.R: -------------------------------------------------------------------------------- 1 | #' List Drive endpoints 2 | #' 3 | #' @description 4 | #' The googledrive package stores a named list of Drive API v3 endpoints (or 5 | #' "methods", using Google's vocabulary) internally and these functions expose 6 | #' this data. 7 | #' * `drive_endpoint()` returns one endpoint, i.e. it uses `[[`. 8 | #' * `drive_endpoints()` returns a list of endpoints, i.e. it uses `[`. 9 | #' 10 | #' The names of this list (or the `id` sub-elements) are the nicknames that can 11 | #' be used to specify an endpoint in [request_generate()]. For each endpoint, we 12 | #' store its nickname or `id`, the associated HTTP verb, the `path`, and details 13 | #' about the parameters. This list is derived programmatically from the Drive 14 | #' API v3 Discovery Document 15 | #' (`https://www.googleapis.com/discovery/v1/apis/drive/v3/rest`) using the 16 | #' approach described in the [Discovery Documents 17 | #' section](https://gargle.r-lib.org/articles/request-helper-functions.html#discovery-documents) 18 | #' of the gargle vignette [Request helper 19 | #' functions](https://gargle.r-lib.org/articles/request-helper-functions.html). 20 | #' 21 | #' @param i The name(s) or integer index(ices) of the endpoints to return. `i` 22 | #' is optional for `drive_endpoints()` and, if not given, the entire list is 23 | #' returned. 24 | #' 25 | #' @return One or more of the Drive API v3 endpoints that are used internally by 26 | #' googledrive. 27 | #' @export 28 | #' 29 | #' @examples 30 | #' str(head(drive_endpoints(), 3), max.level = 2) 31 | #' drive_endpoint("drive.files.delete") 32 | #' drive_endpoint(4) 33 | drive_endpoints <- function(i = NULL) { 34 | if (is.null(i) || is_expose(i)) { 35 | i <- seq_along(.endpoints) 36 | } 37 | stopifnot(is.character(i) || (is.numeric(i))) 38 | .endpoints[i] 39 | } 40 | 41 | #' @rdname drive_endpoints 42 | #' @export 43 | drive_endpoint <- function(i) { 44 | stopifnot(is_string(i) || (is.numeric(i) && length(i) == 1)) 45 | .endpoints[[i]] 46 | } 47 | -------------------------------------------------------------------------------- /R/drive_mkdir.R: -------------------------------------------------------------------------------- 1 | #' Create a Drive folder 2 | #' 3 | #' Creates a new Drive folder. To update the metadata of an existing Drive file, 4 | #' including a folder, use [drive_update()]. 5 | #' 6 | #' @seealso Wraps the `files.create` endpoint: 7 | #' * 8 | #' 9 | #' @param name Name for the new folder or, optionally, a path that specifies 10 | #' an existing parent folder, as well as the new name. 11 | #' @eval param_path_known_parent("folder") 12 | #' @inheritParams drive_create 13 | #' 14 | #' @eval return_dribble() 15 | #' @export 16 | #' @examplesIf drive_has_token() 17 | #' # Create folder named 'ghi', then another below named it 'jkl' and star it 18 | #' ghi <- drive_mkdir("ghi") 19 | #' jkl <- drive_mkdir("ghi/jkl", starred = TRUE) 20 | #' 21 | #' # is 'jkl' really starred? YES 22 | #' purrr::pluck(jkl, "drive_resource", 1, "starred") 23 | #' 24 | #' # Another way to create folder 'mno' in folder 'ghi' 25 | #' drive_mkdir("mno", path = "ghi") 26 | #' 27 | #' # Yet another way to create a folder named 'pqr' in folder 'ghi', 28 | #' # this time with parent folder stored in a dribble, 29 | #' # and setting the new folder's description 30 | #' pqr <- drive_mkdir("pqr", path = ghi, description = "I am a folder") 31 | #' 32 | #' # Did we really set the description? YES 33 | #' purrr::pluck(pqr, "drive_resource", 1, "description") 34 | #' 35 | #' # `overwrite = FALSE` errors if something already exists at target filepath 36 | #' # THIS WILL ERROR! 37 | #' drive_create("name-squatter-mkdir", path = ghi) 38 | #' drive_mkdir("name-squatter-mkdir", path = ghi, overwrite = FALSE) 39 | #' 40 | #' # `overwrite = TRUE` moves the existing item to trash, then proceeds 41 | #' drive_mkdir("name-squatter-mkdir", path = ghi, overwrite = TRUE) 42 | #' 43 | #' # list everything inside 'ghi' 44 | #' drive_ls("ghi") 45 | #' 46 | #' # Clean up 47 | #' drive_rm(ghi) 48 | drive_mkdir <- function(name, 49 | path = NULL, 50 | ..., 51 | overwrite = NA, 52 | verbose = deprecated()) { 53 | warn_for_verbose(verbose) 54 | 55 | drive_create( 56 | name = name, 57 | path = path, 58 | type = "application/vnd.google-apps.folder", 59 | ..., 60 | overwrite = overwrite 61 | ) 62 | } 63 | -------------------------------------------------------------------------------- /R/drive_rename.R: -------------------------------------------------------------------------------- 1 | #' Rename a Drive file 2 | #' 3 | #' This is a wrapper for [`drive_mv()`] that only renames a file. 4 | #' If you would like to rename AND move the file, see [`drive_mv()`]. 5 | #' 6 | #' @template file-singular 7 | #' @param name Character. Name you would like the file to have. 8 | #' @template overwrite 9 | #' @template verbose 10 | #' 11 | #' @eval return_dribble() 12 | #' 13 | #' @examplesIf drive_has_token() 14 | #' # Create a file to rename 15 | #' file <- drive_create("file-to-rename") 16 | #' 17 | #' # Rename it 18 | #' file <- drive_rename(file, name = "renamed-file") 19 | #' 20 | #' # `overwrite = FALSE` errors if something already exists at target filepath 21 | #' # THIS WILL ERROR! 22 | #' drive_create("name-squatter-rename") 23 | #' drive_rename(file, name = "name-squatter-rename", overwrite = FALSE) 24 | #' 25 | #' # `overwrite = TRUE` moves the existing item to trash, then proceeds 26 | #' file <- drive_rename(file, name = "name-squatter-rename", overwrite = TRUE) 27 | #' 28 | #' # Clean up 29 | #' drive_rm(file) 30 | #' @export 31 | drive_rename <- function(file, 32 | name = NULL, 33 | overwrite = NA, 34 | verbose = deprecated()) { 35 | warn_for_verbose(verbose) 36 | drive_mv(file = file, name = name, overwrite = overwrite) 37 | } 38 | -------------------------------------------------------------------------------- /R/drive_user.R: -------------------------------------------------------------------------------- 1 | #' Get info on current user 2 | #' 3 | #' Reveals information about the user associated with the current token. This is 4 | #' a thin wrapper around [drive_about()] that just extracts the most useful 5 | #' information (the information on current user) and prints it nicely. 6 | #' 7 | #' @seealso Wraps the `about.get` endpoint: 8 | #' * 9 | #' 10 | #' @template verbose 11 | #' 12 | #' @return A list of class `drive_user`. 13 | #' @export 14 | #' @examplesIf drive_has_token() 15 | #' drive_user() 16 | #' 17 | #' # more info is returned than is printed 18 | #' user <- drive_user() 19 | #' str(user) 20 | drive_user <- function(verbose = deprecated()) { 21 | warn_for_verbose(verbose) 22 | 23 | if (!drive_has_token()) { 24 | drive_bullets(c( 25 | "i" = "Not logged in as any specific Google user." 26 | )) 27 | return(invisible()) 28 | } 29 | about <- drive_about() 30 | structure(about[["user"]], class = c("drive_user", "list")) 31 | } 32 | 33 | #' @export 34 | format.drive_user <- function(x, ...) { 35 | cli::cli_format_method( 36 | drive_bullets(c( 37 | "Logged in as:", 38 | "*" = "displayName: {.field {x[['displayName']]}}", 39 | "*" = "emailAddress: {.email {x[['emailAddress']]}}" 40 | )) 41 | ) 42 | } 43 | 44 | #' @export 45 | print.drive_user <- function(x, ...) { 46 | cli::cat_line(format(x, ...)) 47 | invisible(x) 48 | } 49 | -------------------------------------------------------------------------------- /R/promote.R: -------------------------------------------------------------------------------- 1 | # promote an element in drive_resource into a top-level column 2 | # 3 | # if you request `this_var` or `thisVar`, we look for `thisVar` in 4 | # drive_resource, but use the original input as the variable name 5 | # 6 | # if a column by that name already exists, it is overwritten in place 7 | # otherwise, the new column will be the second column, presumably after `name` 8 | # 9 | # morally, this is a lot like tidyr::hoist(), but with a more specific mandate 10 | promote <- function(d, elem) { 11 | elemCamelCase <- camelCase(elem) 12 | 13 | x <- map(d$drive_resource, elemCamelCase) 14 | absent <- all(map_lgl(x, is_null)) 15 | 16 | if (absent) { 17 | # TO DO: do we really want promote() to be this forgiving? 18 | # adds a placeholder column for elem if not present in drive_resource 19 | # ensure elem is added, even if there are zero rows 20 | val <- rep_len(list(NULL), nrow(d)) 21 | } else { 22 | val <- simplify_col(x) 23 | } 24 | 25 | put_column(d, nm = elem, val = val, .after = 1) 26 | } 27 | 28 | # simplified version of tidyr:::simplify_col() 29 | simplify_col <- function(x) { 30 | is_list <- map_lgl(x, is_list) 31 | is_vec <- map_lgl(x, ~ vec_is(.x) || is_null(.x)) 32 | is_not_vec <- !is_vec 33 | if (any(is_list | is_not_vec)) { 34 | return(x) 35 | } 36 | 37 | n <- map_int(x, vec_size) 38 | is_scalar <- n %in% c(0, 1) 39 | if (any(!is_scalar)) { 40 | return(x) 41 | } 42 | 43 | x[n == 0] <- list(NA) 44 | 45 | tryCatch( 46 | vec_c(!!!x), 47 | vctrs_error_incompatible_type = function(e) x 48 | ) 49 | } 50 | -------------------------------------------------------------------------------- /R/roxygen-templates.R: -------------------------------------------------------------------------------- 1 | # nocov start 2 | 3 | param_path <- function(thing = "THING", default_notes = "") { 4 | glue(" 5 | @param path Specifies target destination for the {thing} on Google 6 | Drive. Can be an actual path (character), a file id marked with 7 | [as_id()], or a [`dribble`]. 8 | 9 | If `path` is a shortcut to a folder, it is automatically resolved to its 10 | target folder. 11 | 12 | If `path` is given as a path (as opposed to a `dribble` or an id), it is 13 | best to explicitly indicate if it's a folder by including a trailing 14 | slash, since it cannot always be worked out from the context of the call. 15 | {default_notes}") 16 | } 17 | 18 | param_path_known_parent <- function(thing = "item") { 19 | glue(" 20 | @param path Target destination for the new {thing}, i.e. a folder or a 21 | shared drive. Can be given as an actual path (character), a file id or URL 22 | marked with [as_id()], or a [`dribble`]. Defaults to your \"My Drive\" root 23 | folder. If `path` is a shortcut to a folder, it is automatically resolved 24 | to its target folder.") 25 | } 26 | 27 | param_name <- function(thing = "THING", default_notes = "") { 28 | glue(" 29 | @param name Character, new {thing} name if not specified as part of 30 | `path`. This will force `path` to be interpreted as a folder, even if it 31 | is character and lacks a trailing slash. {default_notes}") 32 | } 33 | 34 | return_dribble <- function(item = "file", extras = "") { 35 | glue(" 36 | @return An object of class [`dribble`], a tibble with one row per {item}. 37 | {extras}") 38 | } 39 | 40 | # nocov end 41 | -------------------------------------------------------------------------------- /R/shared_drive_create.R: -------------------------------------------------------------------------------- 1 | #' Create a new shared drive 2 | #' 3 | #' @template shared-drive-description 4 | #' 5 | #' @seealso Wraps the `drives.create` endpoint: 6 | #' * 7 | #' 8 | #' @param name Character. Name of the new shared drive. Must be non-empty and not 9 | #' entirely whitespace. 10 | #' 11 | #' @eval return_dribble("shared drive") 12 | #' @export 13 | #' @examples 14 | #' \dontrun{ 15 | #' shared_drive_create("my-awesome-shared-drive") 16 | #' 17 | #' # Clean up 18 | #' shared_drive_rm("my-awesome-shared-drive") 19 | #' } 20 | shared_drive_create <- function(name) { 21 | stopifnot(is_string(name), isTRUE(nzchar(name))) 22 | request <- request_generate( 23 | "drive.drives.create", 24 | params = list( 25 | requestId = uuid::UUIDgenerate(), 26 | name = name, 27 | fields = "*" 28 | ) 29 | ) 30 | response <- request_make(request) 31 | out <- as_dribble(list(gargle::response_process(response))) 32 | 33 | drive_bullets(c("Shared drive created:", bulletize(gargle_map_cli(out)))) 34 | invisible(out) 35 | } 36 | -------------------------------------------------------------------------------- /R/shared_drive_find.R: -------------------------------------------------------------------------------- 1 | #' Find shared drives 2 | #' 3 | #' @description This is the closest googledrive function to what you get from 4 | #' visiting and clicking "Shared drives". 5 | #' @template shared-drive-description 6 | 7 | #' @seealso Wraps the `drives.list` endpoint: 8 | #' * 9 | 10 | #' @template pattern 11 | #' @template n_max 12 | #' @param ... Other parameters to pass along in the request, such as `pageSize` 13 | #' or `useDomainAdminAccess`. 14 | #' 15 | #' @eval return_dribble("shared drive") 16 | #' @export 17 | #' @examples 18 | #' \dontrun{ 19 | #' shared_drive_find() 20 | #' } 21 | shared_drive_find <- function(pattern = NULL, 22 | n_max = Inf, 23 | ...) { 24 | if (!is.null(pattern) && !(is_string(pattern))) { 25 | drive_abort("{.arg pattern} must be a character string.") 26 | } 27 | stopifnot(is.numeric(n_max), n_max >= 0, length(n_max) == 1) 28 | if (n_max < 1) { 29 | return(dribble()) 30 | } 31 | 32 | ## what could possibly come via `...` here? pageSize (or fields) 33 | params <- toCamel(list2(...)) 34 | params$fields <- params$fields %||% "*" 35 | 36 | request <- request_generate("drive.drives.list", params = params) 37 | proc_res_list <- do_paginated_request( 38 | request, 39 | n_max = n_max, 40 | n = function(x) length(x$drives) 41 | ) 42 | 43 | res_tbl <- proc_res_list %>% 44 | map("drives") %>% 45 | purrr::flatten() %>% 46 | as_dribble() 47 | 48 | if (!is.null(pattern)) { 49 | res_tbl <- res_tbl[grep(pattern, res_tbl$name), ] 50 | } 51 | if (n_max < nrow(res_tbl)) { 52 | res_tbl <- res_tbl[seq_len(n_max), ] 53 | } 54 | res_tbl 55 | } 56 | -------------------------------------------------------------------------------- /R/shared_drive_get.R: -------------------------------------------------------------------------------- 1 | #' Get shared drives by name or id 2 | #' 3 | #' @description 4 | 5 | #' Retrieve metadata for shared drives specified by name or id. Note that Google 6 | #' Drive does NOT behave like your local file system: 7 | 8 | #' * You can get zero, one, or more shared drives back for each name! Shared 9 | #' drive names need not be unique. 10 | #' @template shared-drive-description 11 | 12 | #' @param name Character vector of names. A character vector marked with 13 | #' [as_id()] is treated as if it was provided via the `id` argument. 14 | #' @param id Character vector of shared drive ids or URLs (it is first processed 15 | #' with [as_id()]). If both `name` and `id` are non-`NULL`, `id` is silently 16 | #' ignored. 17 | #' 18 | #' @eval return_dribble("shared drive") 19 | #' @export 20 | #' @examples 21 | #' \dontrun{ 22 | #' shared_drive_get("my-awesome-shared-drive") 23 | #' shared_drive_get(c("apple", "orange", "banana")) 24 | #' shared_drive_get(as_id("KCmiHLXUk9PVA-0AJNG")) 25 | #' shared_drive_get(as_id("https://drive.google.com/drive/u/0/folders/KCmiHLXUk9PVA-0AJNG")) 26 | #' shared_drive_get(id = "KCmiHLXUk9PVA-0AJNG") 27 | #' shared_drive_get(id = "https://drive.google.com/drive/u/0/folders/KCmiHLXUk9PVA-0AJNG") 28 | #' } 29 | shared_drive_get <- function(name = NULL, id = NULL) { 30 | if (length(name) + length(id) == 0) { 31 | return(dribble()) 32 | } 33 | 34 | if (!is.null(name) && is_drive_id(name)) { 35 | id <- name 36 | name <- NULL 37 | } 38 | 39 | if (!is.null(name)) { 40 | stopifnot(all(map_lgl(name, is_string))) 41 | return(shared_drive_from_name(name)) 42 | } 43 | 44 | stopifnot(is.character(id)) 45 | # TODO: use a batch request 46 | as_dribble(map(as_id(id), get_one_shared_drive_id)) 47 | } 48 | 49 | get_one_shared_drive_id <- function(id) { 50 | if (is.na(id)) { 51 | drive_abort(" 52 | Can't {.fun shared_drive_get} a shared drive when {.arg id} is {.code NA}.") 53 | } 54 | request <- request_generate( 55 | endpoint = "drive.drives.get", 56 | params = list( 57 | driveId = id, 58 | fields = "*" 59 | ) 60 | ) 61 | response <- request_make(request) 62 | gargle::response_process(response) 63 | } 64 | 65 | shared_drive_from_name <- function(name = NULL) { 66 | if (length(name) == 0) { 67 | return(dribble()) 68 | } 69 | 70 | shared_drives <- shared_drive_find() 71 | if (no_file(shared_drives)) { 72 | return(dribble()) 73 | } 74 | 75 | shared_drives <- shared_drives[shared_drives$name %in% name, ] 76 | ## TO DO: message if a name matches 0 or multiple shared drives? 77 | 78 | shared_drives[order(match(shared_drives$name, name)), ] 79 | } 80 | -------------------------------------------------------------------------------- /R/shared_drive_rm.R: -------------------------------------------------------------------------------- 1 | #' Delete shared drives 2 | #' 3 | #' @template shared-drive-description 4 | #' 5 | #' @seealso Wraps the `drives.delete` endpoint: 6 | #' * 7 | #' 8 | #' @template shared_drive-plural 9 | #' 10 | #' @return Logical vector, indicating whether the delete succeeded. 11 | #' @export 12 | #' @examples 13 | #' \dontrun{ 14 | #' # Create shared drives to remove in various ways 15 | #' shared_drive_create("testdrive-01") 16 | #' sd02 <- shared_drive_create("testdrive-02") 17 | #' shared_drive_create("testdrive-03") 18 | #' sd04 <- shared_drive_create("testdrive-04") 19 | #' 20 | #' # remove by name 21 | #' shared_drive_rm("testdrive-01") 22 | #' # remove by id 23 | #' shared_drive_rm(as_id(sd02)) 24 | #' # remove by URL (or, rather, id found in URL) 25 | #' shared_drive_rm(as_id("https://drive.google.com/drive/u/0/folders/Q5DqUk9PVA")) 26 | #' # remove by dribble 27 | #' shared_drive_rm(sd04) 28 | #' } 29 | shared_drive_rm <- function(drive = NULL) { 30 | shared_drive <- as_shared_drive(drive) 31 | if (no_file(shared_drive)) { 32 | drive_bullets(c( 33 | "!" = "No such shared drive found to delete." 34 | )) 35 | return(invisible(logical(0))) 36 | } 37 | 38 | out <- map_lgl(as_id(shared_drive), delete_one_shared_drive) 39 | 40 | if (any(out)) { 41 | successes <- shared_drive[out, ] 42 | drive_bullets(c( 43 | "Shared drive{?s} deleted:{cli::qty(nrow(successes))}", 44 | bulletize(gargle_map_cli(successes)) 45 | )) 46 | } 47 | # I'm not sure this ever comes up IRL? 48 | # Is it even possible that removal fails but there's no error? 49 | if (any(!out)) { 50 | failures <- shared_drive[!out, ] 51 | drive_bullets(c( 52 | "Shared drive{?s} NOT deleted:{cli::qty(nrow(failures))}", 53 | bulletize(gargle_map_cli(failures)) 54 | )) 55 | } 56 | invisible(out) 57 | } 58 | 59 | delete_one_shared_drive <- function(id) { 60 | request <- request_generate( 61 | endpoint = "drive.drives.delete", 62 | params = list(driveId = id) 63 | ) 64 | response <- request_make(request) 65 | gargle::response_process(response) 66 | } 67 | -------------------------------------------------------------------------------- /R/shared_drive_update.R: -------------------------------------------------------------------------------- 1 | #' Update a shared drive 2 | #' 3 | #' Update the metadata of an existing shared drive, e.g. its background image or 4 | #' theme. 5 | #' @template shared-drive-description 6 | #' 7 | #' @seealso Wraps the `drives.update` endpoint: 8 | #' * 9 | #' 10 | #' @template shared_drive-singular 11 | #' @param ... Properties to set in `name = value` form. See the "Request 12 | #' body" section of the Drive API docs for this endpoint. 13 | #' 14 | #' @eval return_dribble("shared drive") 15 | #' @export 16 | #' @examples 17 | #' \dontrun{ 18 | #' # create a shared drive 19 | #' sd <- shared_drive_create("I love themes!") 20 | #' 21 | #' # see the themes available to you 22 | #' themes <- drive_about()$driveThemes 23 | #' purrr::map_chr(themes, "id") 24 | #' 25 | #' # cycle through various themes for this shared drive 26 | #' sd <- shared_drive_update(sd, themeId = "bok_choy") 27 | #' sd <- shared_drive_update(sd, themeId = "cocktails") 28 | #' 29 | #' # Clean up 30 | #' shared_drive_rm(sd) 31 | #' } 32 | shared_drive_update <- function(shared_drive, ...) { 33 | shared_drive <- as_shared_drive(shared_drive) 34 | if (no_file(shared_drive)) { 35 | drive_bullets(c( 36 | "!" = "No such shared drive found to update." 37 | )) 38 | return(invisible(dribble())) 39 | } 40 | if (!single_file(shared_drive)) { 41 | drive_abort(c( 42 | "Can't update multiple shared drives at once:", 43 | bulletize(gargle_map_cli(shared_drive)) 44 | )) 45 | } 46 | 47 | meta <- toCamel(list2(...)) 48 | if (length(meta) == 0) { 49 | drive_bullets(c( 50 | "!" = "No updates specified." 51 | )) 52 | return(invisible(shared_drive)) 53 | } 54 | 55 | meta$fields <- meta$fields %||% "*" 56 | meta$driveId <- shared_drive$id 57 | request <- request_generate( 58 | endpoint = "drive.drives.update", 59 | params = meta 60 | ) 61 | response <- request_make(request) 62 | out <- as_dribble(list(gargle::response_process(response))) 63 | 64 | drive_bullets(c("Shared drive updated:", bulletize(gargle_map_cli(out)))) 65 | 66 | invisible(out) 67 | } 68 | -------------------------------------------------------------------------------- /R/sysdata.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tidyverse/googledrive/f806c49e62b34fc0150a7bd67fde1885ae479b9e/R/sysdata.rda -------------------------------------------------------------------------------- /R/team_drive.R: -------------------------------------------------------------------------------- 1 | #' Deprecated Team Drive functions 2 | #' 3 | #' @description 4 | #' `r lifecycle::badge('deprecated')` 5 | #' @template team-drives-description 6 | #' 7 | #' @inheritParams shared_drive_find 8 | #' @inheritParams shared_drive_get 9 | #' @inheritParams as_shared_drive 10 | #' @inheritParams is_shared_drive 11 | #' @template team_drive-plural 12 | #' 13 | #' @eval return_dribble("shared drive") 14 | #' 15 | #' @keywords internal 16 | #' @name deprecated-team-drive-functions 17 | NULL 18 | 19 | #' @export 20 | #' @rdname deprecated-team-drive-functions 21 | team_drive_find <- function(pattern = NULL, 22 | n_max = Inf, 23 | ..., 24 | verbose = deprecated()) { 25 | warn_for_verbose(verbose) 26 | lifecycle::deprecate_warn("2.0.0", "team_drive_find()", "shared_drive_find()") 27 | shared_drive_find(pattern = pattern, n_max = n_max, ...) 28 | } 29 | 30 | #' @export 31 | #' @rdname deprecated-team-drive-functions 32 | team_drive_get <- function(name = NULL, id = NULL, verbose = deprecated()) { 33 | warn_for_verbose(verbose) 34 | lifecycle::deprecate_warn("2.0.0", "team_drive_get()", "shared_drive_get()") 35 | shared_drive_get(name = name, id = id) 36 | } 37 | 38 | #' @export 39 | #' @rdname deprecated-team-drive-functions 40 | team_drive_create <- function(name, verbose = deprecated()) { 41 | warn_for_verbose(verbose) 42 | lifecycle::deprecate_warn("2.0.0", "team_drive_create()", "shared_drive_create()") 43 | shared_drive_create(name = name) 44 | } 45 | 46 | #' @export 47 | #' @rdname deprecated-team-drive-functions 48 | team_drive_rm <- function(team_drive = NULL, verbose = deprecated()) { 49 | warn_for_verbose(verbose) 50 | lifecycle::deprecate_warn("2.0.0", "team_drive_rm()", "shared_drive_rm()") 51 | shared_drive_rm(drive = team_drive) 52 | } 53 | 54 | #' @export 55 | #' @rdname deprecated-team-drive-functions 56 | team_drive_update <- function(team_drive, ..., verbose = deprecated()) { 57 | warn_for_verbose(verbose) 58 | lifecycle::deprecate_warn("2.0.0", "team_drive_update()", "shared_drive_update()") 59 | shared_drive_update(drive = team_drive, ...) 60 | } 61 | 62 | #' @export 63 | #' @rdname deprecated-team-drive-functions 64 | as_team_drive <- function(x, ...) { 65 | lifecycle::deprecate_warn("2.0.0", "as_team_drive()", "as_shared_drive()") 66 | as_shared_drive(x, ...) 67 | } 68 | 69 | #' @export 70 | #' @rdname deprecated-team-drive-functions 71 | is_team_drive <- function(d) { 72 | stopifnot(inherits(d, "dribble")) 73 | map_chr(d$drive_resource, "kind") == "drive#teamDrive" 74 | } 75 | -------------------------------------------------------------------------------- /R/utils-io.R: -------------------------------------------------------------------------------- 1 | readLines <- function(...) { 2 | drive_abort("In this house, we use {.fun read_utf8} for UTF-8 reasons.") 3 | } 4 | 5 | writeLines <- function(...) { 6 | drive_abort("In this house, we use {.fun write_utf8} for UTF-8 reasons.") 7 | } 8 | 9 | # https://github.com/gaborcsardi/rencfaq#with-base-r 10 | read_utf8 <- function(path) { 11 | opts <- options(encoding = "native.enc") 12 | withr::defer(options(opts)) 13 | x <- base::readLines(path, encoding = "UTF-8", warn = FALSE) 14 | x 15 | } 16 | 17 | # https://github.com/gaborcsardi/rencfaq#with-base-r 18 | write_utf8 <- function(text, path = NULL) { 19 | # sometimes we use writeLines() basically to print something for a snapshot 20 | if (is.null(path)) { 21 | return(base::writeLines(text)) 22 | } 23 | 24 | # step 1: ensure our text is utf8 encoded 25 | utf8 <- enc2utf8(text) 26 | upath <- enc2utf8(path) 27 | 28 | # step 2: create a connection with 'native' encoding 29 | # this signals to R that translation before writing 30 | # to the connection should be skipped 31 | con <- file(upath, open = "w+", encoding = "native.enc") 32 | withr::defer(close(con)) 33 | 34 | # step 3: write to the connection with 'useBytes = TRUE', 35 | # telling R to skip translation to the native encoding 36 | base::writeLines(utf8, con = con, useBytes = TRUE) 37 | } 38 | 39 | # used for building functions that construct Drive file names in tests ---- 40 | nm_fun <- function(context, user_run = TRUE) { 41 | user_run <- if (isTRUE(user_run)) nm_user_run() else NULL 42 | y <- purrr::compact(list(context, user_run)) 43 | function(x = character()) as.character(glue_collapse(c(x, y), sep = "-")) 44 | } 45 | 46 | nm_user_run <- function() { 47 | if (as.logical(Sys.getenv("GITHUB_ACTIONS", unset = "false"))) { 48 | glue("gha-{Sys.getenv('GITHUB_WORKFLOW')}-{Sys.getenv('GITHUB_RUN_ID')}") 49 | } else { 50 | random_id <- strsplit(uuid::UUIDgenerate(TRUE), "-")[[1]][[1]] 51 | glue("{Sys.info()['user']}-{random_id}") 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /R/utils-pipe.R: -------------------------------------------------------------------------------- 1 | #' Pipe operator 2 | #' 3 | #' See \code{magrittr::\link[magrittr]{\%>\%}} for details. 4 | #' 5 | #' @name %>% 6 | #' @rdname pipe 7 | #' @keywords internal 8 | #' @export 9 | #' @importFrom magrittr %>% 10 | #' @usage lhs \%>\% rhs 11 | NULL 12 | -------------------------------------------------------------------------------- /R/zzz.R: -------------------------------------------------------------------------------- 1 | .onLoad <- function(libname, pkgname) { 2 | 3 | # .auth is created in R/drive_auth.R 4 | # this is to insure we get an instance of gargle's AuthState using the 5 | # current, locally installed version of gargle 6 | utils::assignInMyNamespace( 7 | ".auth", 8 | gargle::init_AuthState(package = "googledrive", auth_active = TRUE) 9 | ) 10 | 11 | if (identical(Sys.getenv("IN_PKGDOWN"), "true")) { 12 | tryCatch( 13 | drive_auth_docs(), 14 | googledrive_auth_internal_error = function(e) NULL 15 | ) 16 | } 17 | 18 | # in rlang 0.4.10, `is_installed()` doesn't have `version` arg yet 19 | if (is_installed("dplyr") && utils::packageVersion("dplyr") >= "1.0.0") { 20 | s3_register( 21 | "dplyr::dplyr_reconstruct", 22 | "dribble", 23 | method = dribble_maybe_reconstruct 24 | ) 25 | } 26 | 27 | invisible() 28 | } 29 | 30 | release_bullets <- function() { 31 | c( 32 | '`devtools::build_rmd("index.Rmd")`' 33 | ) 34 | } 35 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | 6 | 7 | 8 | ```{r setup, include = FALSE} 9 | auth_success <- tryCatch( 10 | googledrive:::drive_auth_docs(), 11 | googledrive_auth_internal_error = function(e) e 12 | ) 13 | 14 | knitr::opts_chunk$set( 15 | collapse = TRUE, 16 | comment = "#>", 17 | error = TRUE, 18 | purl = googledrive::drive_has_token(), 19 | eval = googledrive::drive_has_token() 20 | ) 21 | ``` 22 | 23 | ```{r eval = !googledrive::drive_has_token(), echo = FALSE, comment = NA} 24 | googledrive:::drive_bullets(c( 25 | "Code chunks will not be evaluated, because:", 26 | strsplit(auth_success$message, split = "\n")[[1]] 27 | )) 28 | googledrive::drive_deauth() 29 | ``` 30 | 31 | # googledrive 32 | 33 | 34 | [![CRAN status](https://www.r-pkg.org/badges/version/googledrive)](https://CRAN.R-project.org/package=googledrive) 35 | [![R-CMD-check](https://github.com/tidyverse/googledrive/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/tidyverse/googledrive/actions/workflows/R-CMD-check.yaml) 36 | [![Codecov test coverage](https://codecov.io/gh/tidyverse/googledrive/branch/main/graph/badge.svg)](https://app.codecov.io/gh/tidyverse/googledrive?branch=main) 37 | 38 | 39 | ## Overview 40 | 41 | googledrive allows you to interact with files on Google Drive from R. 42 | 43 | ## Installation 44 | 45 | Install the CRAN version: 46 | 47 | ```{r, eval = FALSE} 48 | install.packages("googledrive") 49 | ``` 50 | 51 | Or install the development version from GitHub: 52 | 53 | ```{r, eval = FALSE} 54 | # install.packages("pak") 55 | pak::pak("tidyverse/googledrive") 56 | ``` 57 | 58 | ## Usage 59 | 60 | Please see the package website: 61 | 62 | Here's a teaser that uses googledrive to view some of the files you see on (up to `n_max = 25`, in this case): 63 | 64 | ```{r} 65 | library("googledrive") 66 | drive_find(n_max = 25) 67 | ``` 68 | 69 | ## Contributing 70 | 71 | If you'd like to contribute to the development of googledrive, please read [these guidelines](https://googledrive.tidyverse.org/CONTRIBUTING.html). 72 | 73 | Please note that the googledrive project is released with a [Contributor Code of Conduct](https://googledrive.tidyverse.org/CODE_OF_CONDUCT.html). By contributing to this project, you agree to abide by its terms. 74 | 75 | ## Privacy 76 | 77 | [Privacy policy](https://www.tidyverse.org/google_privacy_policy) 78 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | 3 | coverage: 4 | status: 5 | project: 6 | default: 7 | target: auto 8 | threshold: 1% 9 | informational: true 10 | patch: 11 | default: 12 | target: auto 13 | threshold: 1% 14 | informational: true 15 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | ## R CMD check results 2 | 3 | 0 errors | 0 warnings | 0 notes 4 | 5 | ## revdepcheck results 6 | 7 | We checked 17 reverse dependencies, comparing R CMD check results across CRAN and dev versions of this package. 8 | 9 | * We saw 0 new problems 10 | * We failed to check 0 packages 11 | 12 | -------------------------------------------------------------------------------- /data-raw/discovery-doc-ingest.R: -------------------------------------------------------------------------------- 1 | library(tidyverse) 2 | 3 | source( 4 | system.file("discovery-doc-ingest", "ingest-functions.R", package = "gargle") 5 | ) 6 | 7 | existing <- list_discovery_documents("drive") 8 | if (length(existing) > 1) { 9 | rlang::warn("MULTIPLE DISCOVERY DOCUMENTS FOUND. FIX THIS!") 10 | } 11 | 12 | if (length(existing) < 1) { 13 | rlang::inform("Downloading Discovery Document") 14 | x <- download_discovery_document("drive:v3") 15 | } else { 16 | msg <- glue::glue(" 17 | Using existing Discovery Document: 18 | * {existing} 19 | ") 20 | rlang::inform(msg) 21 | x <- here::here("data-raw", existing) 22 | } 23 | 24 | dd <- read_discovery_document(x) 25 | 26 | methods <- get_raw_methods(dd) 27 | 28 | methods <- methods %>% map(groom_properties, dd) 29 | methods <- methods %>% map(add_schema_params, dd) 30 | methods <- methods %>% map(add_global_params, dd) 31 | 32 | ## duplicate two methods to create a companion for media 33 | ## simpler to do this here, in data, than in wrapper functions 34 | mediafy <- function(target_id, methods) { 35 | new <- target_method <- methods[[target_id]] 36 | 37 | new$id <- paste0(target_id, ".media") 38 | new$path <- 39 | pluck(target_method, "mediaUpload", "protocols", "simple", "path") 40 | new$parameters <- c( 41 | new$parameters, 42 | uploadType = list(list(type = "string", required = TRUE, location = "query")) 43 | ) 44 | 45 | methods[[new$id]] <- new 46 | methods 47 | } 48 | 49 | methods <- mediafy("drive.files.update", methods) 50 | methods <- mediafy("drive.files.create", methods) 51 | 52 | .endpoints <- methods 53 | attr(.endpoints, "base_url") <- dd$rootUrl 54 | # View(.endpoints) 55 | 56 | usethis::use_data(.endpoints, internal = TRUE, overwrite = TRUE) 57 | -------------------------------------------------------------------------------- /data-raw/drive-examples-create.R: -------------------------------------------------------------------------------- 1 | library(here) 2 | library(glue) 3 | library(googledrive) 4 | library(tidyverse) 5 | 6 | # auth with the special-purpose service account 7 | filename <- glue("~/.R/gargle/googledrive-file-keeper.json") 8 | drive_auth(path = filename) 9 | drive_user() 10 | 11 | # files that are the pre-existing local example files 12 | x <- drive_upload(drive_example_local("chicken.csv")) 13 | drive_share_anyone(x) 14 | 15 | x <- drive_upload(drive_example_local("chicken.jpg")) 16 | drive_share_anyone(x) 17 | 18 | x <- drive_upload(drive_example_local("chicken.pdf")) 19 | drive_share_anyone(x) 20 | 21 | x <- drive_upload(drive_example_local("chicken.txt")) 22 | drive_share_anyone(x) 23 | 24 | # added June 2021; originally from 25 | # https://matthew-brett.github.io/cfd2019/data/imdblet_latin.csv", 26 | x <- drive_upload(drive_example_local("imdb_latin1.csv")) 27 | drive_share_anyone(x) 28 | 29 | # added June 2021; ships with R 30 | # https://stat.ethz.ch/R-manual/R-patched/doc/html/logo.jpg 31 | # r_logo_path <- R.home("doc/html/logo.jpg") 32 | # file.copy(r_logo_path, here("inst", "extdata", "example_files", "r_logo.jpg")) 33 | x <- drive_upload(drive_example_local("r_logo.jpg")) 34 | drive_share_anyone(x) 35 | 36 | # added June 2021; ships with R 37 | # https://stat.ethz.ch/R-manual/R-patched/doc/html/about.html 38 | # r_about_path <- R.home("doc/html/about.html") 39 | # file.copy(r_about_path, here("inst", "extdata", "example_files", "r_about.html")) 40 | x <- drive_upload(drive_example_local("r_about.html")) 41 | drive_share_anyone(x) 42 | 43 | # export 2 local examples for native Google file types 44 | x <- drive_upload( 45 | drive_example_local("chicken.txt"), 46 | type = "document", name = "chicken_doc" 47 | ) 48 | drive_share_anyone(x) 49 | 50 | x <- drive_upload( 51 | drive_example_local("chicken.csv"), 52 | type = "spreadsheet", 53 | name = "chicken_sheet" 54 | ) 55 | drive_share_anyone(x) 56 | 57 | # files I played with when writing drive_read_string() and drive_read_raw() 58 | # but, so far, have no included 59 | # curl::curl_download("https://httpbin.org/html", destfile = tfile) 60 | # curl::curl_download("https://httpbin.org/xml", destfile = tfile) 61 | # curl::curl_download("https://httpbin.org/json", destfile = tfile) 62 | -------------------------------------------------------------------------------- /data-raw/drive-examples-inventory.R: -------------------------------------------------------------------------------- 1 | # given the files owned by the googledrive-file-keeper service account, 2 | # create/update an inventory file consulted by drive_examples_remote() 3 | 4 | library(here) 5 | library(glue) 6 | library(googledrive) 7 | library(tidyverse) 8 | 9 | # auth with the special-purpose service account 10 | filename <- glue("~/.R/gargle/googledrive-file-keeper.json") 11 | drive_auth(path = filename) 12 | # user should be googledrive-file-keeper 13 | drive_user() 14 | 15 | # exclude the inventory file ... too meta! 16 | dat <- drive_find(q = "not name contains 'drive_examples_remote'") 17 | 18 | if (anyDuplicated(dat$name)) { 19 | stop("Duplicated file names! You are making a huge mistake.") 20 | } 21 | 22 | dat <- dat %>% 23 | drive_reveal("mime_type") %>% 24 | select(name, mime_type, id) %>% 25 | arrange(name, mime_type) 26 | 27 | # record in local csv, because the visibility afforded by a plain old csv file 28 | # is useful to me, e.g. easy to see change over time 29 | write_csv( 30 | dat, 31 | file = here("inst", "extdata", "data", "remote_example_files.csv") 32 | ) 33 | 34 | # keep just (name, id) for the official lookup Sheet 35 | dat2 <- dat %>% 36 | select(name, id) 37 | dat2 38 | 39 | # PUT into official inventory csv 40 | x <- tempfile(fileext = ".csv") 41 | write_csv(dat2, file = x) 42 | 43 | y <- drive_put(x, "drive_examples_remote.csv") 44 | drive_share_anyone(y) 45 | # drive_browse(y) 46 | as_id(y) 47 | # "1XiwJJdoqoZ876OoSTjsnBZ5SxxUg6gUC" 48 | -------------------------------------------------------------------------------- /data-raw/export-mime-type-defaults.csv: -------------------------------------------------------------------------------- 1 | mime_type_google, mime_type_local 2 | application/vnd.google-apps.document,application/vnd.openxmlformats-officedocument.wordprocessingml.document 3 | application/vnd.google-apps.drawing,image/png 4 | application/vnd.google-apps.form,application/zip 5 | application/vnd.google-apps.presentation,application/vnd.openxmlformats-officedocument.presentationml.presentation 6 | application/vnd.google-apps.script,application/vnd.google-apps.script+json 7 | application/vnd.google-apps.spreadsheet,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet 8 | -------------------------------------------------------------------------------- /data-raw/extension-mime-type-defaults.csv: -------------------------------------------------------------------------------- 1 | mime_type,ext 2 | text/tab-separated-values,tsv 3 | image/jpeg,jpeg 4 | image/gif,gif 5 | application/vnd.openxmlformats-officedocument.wordprocessingml.template,dotx 6 | application/vnd.openxmlformats-officedocument.wordprocessingml.document,docx 7 | application/vnd.ms-excel,xls 8 | application/vnd.sun.xml.writer,sxw 9 | text/plain,txt 10 | application/vnd.oasis.opendocument.spreadsheet,ods 11 | image/png,png 12 | application/msword,doc 13 | application/pdf,pdf 14 | application/json,json 15 | application/vnd.openxmlformats-officedocument.spreadsheetml.template,xltx 16 | application/vnd.ms-powerpoint,ppt 17 | application/rtf,rtf 18 | application/vnd.openxmlformats-officedocument.presentationml.template,potx 19 | text/html,html 20 | application/vnd.oasis.opendocument.text,odt 21 | application/vnd.openxmlformats-officedocument.presentationml.presentation,pptx 22 | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,xlsx 23 | application/vnd.openxmlformats-officedocument.presentationml.slideshow,ppsx 24 | text/csv,csv 25 | application/vnd.oasis.opendocument.presentation,odp 26 | text/richtext,rtx 27 | application/zip,zip 28 | image/svg+xml,svg -------------------------------------------------------------------------------- /data-raw/file-fields.R: -------------------------------------------------------------------------------- 1 | library(here) 2 | library(jsonlite) 3 | library(tidyverse) 4 | library(fs) 5 | 6 | json_fname <- dir_ls(here("data-raw"), regexp = "drive-v3") 7 | stopifnot(length(json_fname) == 1) 8 | dd_content <- fromJSON(json_fname) 9 | 10 | ff <- pluck(dd_content, "schemas", "File", "properties") 11 | df <- tibble( 12 | name = names(ff), 13 | desc = map_chr(ff, "description") 14 | ) 15 | 16 | write_csv(df, here("inst", "extdata", "data", "files_fields.csv")) 17 | -------------------------------------------------------------------------------- /data-raw/old/20170519_drive-v3_endpoints-list.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tidyverse/googledrive/f806c49e62b34fc0150a7bd67fde1885ae479b9e/data-raw/old/20170519_drive-v3_endpoints-list.rds -------------------------------------------------------------------------------- /data-raw/old/20170519_drive-v3_endpoints-tibble.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tidyverse/googledrive/f806c49e62b34fc0150a7bd67fde1885ae479b9e/data-raw/old/20170519_drive-v3_endpoints-tibble.rds -------------------------------------------------------------------------------- /data-raw/old/20170721_drive-v3_endpoints-list.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tidyverse/googledrive/f806c49e62b34fc0150a7bd67fde1885ae479b9e/data-raw/old/20170721_drive-v3_endpoints-list.rds -------------------------------------------------------------------------------- /data-raw/old/20170721_drive-v3_endpoints-tibble.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tidyverse/googledrive/f806c49e62b34fc0150a7bd67fde1885ae479b9e/data-raw/old/20170721_drive-v3_endpoints-tibble.rds -------------------------------------------------------------------------------- /data-raw/old/20171110_drive-v3_endpoints-list.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tidyverse/googledrive/f806c49e62b34fc0150a7bd67fde1885ae479b9e/data-raw/old/20171110_drive-v3_endpoints-list.rds -------------------------------------------------------------------------------- /data-raw/old/20171110_drive-v3_endpoints-tibble.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tidyverse/googledrive/f806c49e62b34fc0150a7bd67fde1885ae479b9e/data-raw/old/20171110_drive-v3_endpoints-tibble.rds -------------------------------------------------------------------------------- /googledrive.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageUseDevtools: Yes 20 | PackageInstallArgs: --no-multiarch --with-keep.source 21 | PackageCheckArgs: --no-vignettes --no-build-vignettes 22 | PackageRoxygenize: rd,collate,namespace 23 | -------------------------------------------------------------------------------- /inst/WORDLIST: -------------------------------------------------------------------------------- 1 | API's 2 | Auth 3 | AuthState 4 | CLI 5 | CMD 6 | Codecov 7 | Colaboratory 8 | D'Agostino 9 | GCE 10 | GCP 11 | IDEs 12 | JSON 13 | OAuth 14 | OOB 15 | ORCID 16 | PBC 17 | PUTs 18 | RESTful 19 | RStudio 20 | Tidyverse 21 | VMs 22 | appdata 23 | auth 24 | behaviour 25 | bigrquery 26 | cli 27 | cli's 28 | commenter 29 | csv 30 | de 31 | determinine 32 | dev 33 | dplyr 34 | fileOrganizer 35 | filepath 36 | funder 37 | ggplot 38 | gmailr 39 | googleapis 40 | googledrive's 41 | googlesheets 42 | https 43 | httr 44 | httr's 45 | ing 46 | lifecycle 47 | lowerCamel 48 | magrittr 49 | mockr 50 | pkgdown 51 | pre 52 | programmatically 53 | purrr 54 | readonly 55 | rebranded 56 | recency 57 | reprexes 58 | rlang's 59 | rprojroot 60 | setwise 61 | targetted 62 | testthat 63 | th 64 | threshhold 65 | tibble 66 | tibble's 67 | tidyverse 68 | un 69 | unexamined 70 | vctrs 71 | vectorization 72 | vectorized 73 | withr 74 | www 75 | -------------------------------------------------------------------------------- /inst/extdata/data/client_secret_123.googleusercontent.com.json: -------------------------------------------------------------------------------- 1 | {"installed":{"client_id":"abc.apps.googleusercontent.com","project_id":"a_project","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://accounts.google.com/o/oauth2/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"ssshh-i-am-a-secret","redirect_uris":["http://localhost"]}} 2 | -------------------------------------------------------------------------------- /inst/extdata/data/remote_example_files.csv: -------------------------------------------------------------------------------- 1 | name,mime_type,id 2 | chicken_doc,application/vnd.google-apps.document,1X9pd4nOjl33zDFfTjw-_eFL7Qb9_g6VfVFDp1PPae94 3 | chicken_sheet,application/vnd.google-apps.spreadsheet,1SeFXkr3XdzPSuWauzPdN-XnaryOYmZ7sFiUF5t-wSVU 4 | chicken.csv,text/csv,1VOh6wWbRfuQLxbLg87o58vxJt95SIiZ7 5 | chicken.jpg,image/jpeg,1b2_ZjzgvrSw0hBMgn-rnEbjp3Uq0XTKJ 6 | chicken.pdf,application/pdf,13OQcAo8hkh0Ja5Wxlmi4a8aNvPK7pDkO 7 | chicken.txt,text/plain,1wOLeWVRkTb6lDmLRiOhg9iKM7DlN762Y 8 | imdb_latin1.csv,text/csv,1YJSVa0LTaVtGrZ4eVXYrSQ4y50uFl5bw 9 | r_about.html,text/html,1sfCT0zqDz3vpZZlv_4nFlhq2WMaKqjow 10 | r_logo.jpg,image/jpeg,1J4v-iyydf1Cad3GjDkGRrynauV9JFOyW 11 | -------------------------------------------------------------------------------- /inst/extdata/example_files/chicken.csv: -------------------------------------------------------------------------------- 1 | chicken,breed,sex,motto 2 | Foghorn Leghorn,Leghorn,rooster,"That's a joke, ah say, that's a joke, son." 3 | Chicken Little,unknown,hen,"The sky is falling!" 4 | Ginger,Rhode Island Red,hen,"Listen. We'll either die free chickens or we die trying." 5 | Camilla the Chicken,Chantecler,hen,"Bawk, buck, ba-gawk." 6 | Ernie The Giant Chicken,Brahma,rooster,"Put Captain Solo in the cargo hold." 7 | -------------------------------------------------------------------------------- /inst/extdata/example_files/chicken.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tidyverse/googledrive/f806c49e62b34fc0150a7bd67fde1885ae479b9e/inst/extdata/example_files/chicken.jpg -------------------------------------------------------------------------------- /inst/extdata/example_files/chicken.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tidyverse/googledrive/f806c49e62b34fc0150a7bd67fde1885ae479b9e/inst/extdata/example_files/chicken.pdf -------------------------------------------------------------------------------- /inst/extdata/example_files/chicken.txt: -------------------------------------------------------------------------------- 1 | A chicken whose name was Chantecler 2 | Clucked in iambic pentameter 3 | It sat on a shelf, reading Song of Myself 4 | And laid eggs with a perfect diameter. 5 | 6 | —Richard Maxson 7 | -------------------------------------------------------------------------------- /inst/extdata/example_files/imdb_latin1.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tidyverse/googledrive/f806c49e62b34fc0150a7bd67fde1885ae479b9e/inst/extdata/example_files/imdb_latin1.csv -------------------------------------------------------------------------------- /inst/extdata/example_files/r_about.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | R: About R 5 | 6 | 7 | 8 | 9 | 10 | 11 |

About

12 | 13 |
14 | 15 |

Introduction

16 | 17 |

R is a computer language not entirely unlike the S 18 | language developed at AT&T Bell Laboratories by Rick Becker, 19 | John Chambers and Allan Wilks. The two languages are implemented 20 | quite differently, but bear enough superficial resemblance that 21 | users should be able to switch between the two with relative ease. 22 | Currently the software is undergoing active development. Discussion 23 | of the development process is carried out on the "r-devel" mailing 24 | list. See the resources page for 25 | details on how to subscribe to this list.

26 | 27 |

We have implemented R in what we hope is a very portable 28 | fashion and in way which requires relatively little in the way of 29 | machine resources. Implementations exist for many for many members 30 | of the Unix family of operating systems, including AIX, 31 | FreeBSD, GNU/Linux, HPUX, Irix, 32 | macOS, Solaris, and Tru64. In addition there 33 | is a version for Microsoft Windows (9x, ME, NT4, 2000, 34 | XP).

35 | 36 |

Present Status

37 | 38 | The present version implements most of the functionality in the 39 | 1988 S book (the "Blue Book") and many of the applications. In 40 | addition, we have implemented much of the functionality from the 41 | 1992 S book (the "White Book"). In particular we have versions of 42 | "lm", "glm", "aov" and "loess", and versions of "gam" and "tree" 43 | are available in contributed packages. There are several manuals in 44 | the distribution, plus a comprehensive set of help pages in "output 45 | independent" form which can be used to create versions for HTML, 46 | LaTeX, text, PDF etc. 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /inst/extdata/example_files/r_logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tidyverse/googledrive/f806c49e62b34fc0150a7bd67fde1885ae479b9e/inst/extdata/example_files/r_logo.jpg -------------------------------------------------------------------------------- /internal/2019-02-18_tidyverse-meeting.R: -------------------------------------------------------------------------------- 1 | ## live demo from group meeting re: gargle stuff 2 | load_all(".") 3 | 4 | ## present myself as "RStudio Jenny" 5 | drive_find(n_max = 10) 6 | drive_find(type = "spreadsheet") 7 | 8 | ## what token am I sending? 9 | drive_token() 10 | .auth$cred 11 | 12 | ## explicitly declare this: "I want to send unauthorized requests" 13 | drive_deauth() 14 | 15 | ## what token do I send now? NONE! 16 | drive_token() 17 | 18 | ## access a world-readable document = gapminder Sheet 19 | (gapminder <- googlesheets::gs_gap_url()) 20 | 21 | (ss <- drive_get(as_id(gapminder))) 22 | 23 | drive_download(ss, "gapminder.csv", overwrite = TRUE) 24 | readLines("gapminder.csv", n = 6) 25 | 26 | ## now I want to be "Gmail Jenny" 27 | drive_auth(email = "jenny.f.bryan@gmail.com") 28 | 29 | ## notice I see different documents from "Rstudio Jenny" 30 | drive_find(n_max = 10) 31 | drive_find(type = "spreadsheet") 32 | 33 | library(googlesheets4) 34 | 35 | ## let's switch back to RStudio Jenny via a token choose 36 | drive_auth(email = NA) 37 | 38 | ## Find the 'Families' spreadsheet Hadley let us make 39 | families_ss <- drive_find("Families", type = "spreadsheet") 40 | 41 | families <- sheets_read(families_ss, n_max = 13) 42 | families 43 | View(families) 44 | 45 | ## go back to slides here 46 | 47 | ## inspect internally stored endpoints 48 | 49 | ## googledrive 50 | View(.endpoints) 51 | 52 | ## googlesheets4 53 | View(googlesheets4:::.endpoints) 54 | -------------------------------------------------------------------------------- /internal/googledrive-og-1280x640.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tidyverse/googledrive/f806c49e62b34fc0150a7bd67fde1885ae479b9e/internal/googledrive-og-1280x640.png -------------------------------------------------------------------------------- /internal/googledrive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tidyverse/googledrive/f806c49e62b34fc0150a7bd67fde1885ae479b9e/internal/googledrive.png -------------------------------------------------------------------------------- /internal/old/02_sharing_demo.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "sharing demo" 3 | author: "Lucy D’Agostino McGowan" 4 | date: "5/3/2017" 5 | output: 6 | github_document: 7 | toc: true 8 | --- 9 | 10 | This is a little demo to show how we may view sharing. 11 | 12 | ```{r, message = FALSE, warning = FALSE} 13 | library('dplyr') 14 | library('googledrive') 15 | drive_auth("drive-token.rds") 16 | ``` 17 | 18 | ```{r} 19 | write.table("This is a little demo", "demo.txt") 20 | drive_upload(from = "demo.txt", up_name = "Happy Little Demo") 21 | ``` 22 | 23 | ```{r} 24 | my_file <- drive_list("Happy Little Demo")$id %>% 25 | drive_file() 26 | ``` 27 | 28 | ## check current permissions 29 | ```{r} 30 | my_file 31 | ``` 32 | 33 | cool beans - it's private! 34 | 35 | ## change permissions (anyone with link) 36 | 37 | *all functions that will somehow change the file will output a new file, overwrite the old file with this to avoid confusion* 38 | ```{r} 39 | my_file<- my_file %>% 40 | drive_share(role = "reader", type = "anyone") 41 | ``` 42 | 43 | Let's see what that did 44 | 45 | ```{r} 46 | my_file 47 | ``` 48 | 49 | Now anyone with the link can view it 50 | 51 | ## change permissions (anyone in the `r emo::ji('world')`) 52 | 53 | ```{r} 54 | my_file <- my_file %>% 55 | drive_share(role = "reader", type = "anyone", allowFileDiscovery = "true") 56 | ``` 57 | 58 | Let's see what that did 59 | 60 | ```{r} 61 | my_file 62 | ``` 63 | 64 | ## make it easier to see 65 | 66 | I've added `access` to the Google Drive file object 67 | ```{r} 68 | my_file$access 69 | ``` 70 | 71 | ## share link 72 | 73 | you can also output a link to share 74 | ```{r} 75 | drive_share_link(my_file) 76 | ``` 77 | 78 | ## clean up 79 | 80 | ```{r} 81 | drive_delete(my_file) 82 | ``` 83 | 84 | ```{r, echo = FALSE} 85 | rm <- file.remove("demo.txt") 86 | ``` 87 | 88 | -------------------------------------------------------------------------------- /internal/old/03_publish_demo.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "publish" 3 | author: "Lucy D’Agostino McGowan" 4 | date: "5/3/2017" 5 | output: 6 | github_document: 7 | toc: true 8 | --- 9 | ```{r setup, include=FALSE} 10 | library("googledrive") 11 | library("googlesheets") 12 | library("dplyr") 13 | library("readr") 14 | ``` 15 | 16 | 17 | ## Motivation 18 | 19 | Push a table into a Sheet. 20 | 21 | Try to read it _as another user_ 22 | Assume you even have the key. 23 | You will fail. 24 | 25 | Now, as the user who owns the Sheet, publish it. 26 | 27 | Now, as the other user, try again to read it via googlesheets. You should succeed. 28 | 29 | 30 | ## Push a file into a Sheet 31 | ```{r} 32 | drive_auth("drive-token.rds") 33 | file <- drive_upload( 34 | R.home('doc/BioC_mirrors.csv'), 35 | type = "spreadsheet" 36 | ) 37 | ``` 38 | 39 | ## Check publication status (should be FALSE) 40 | ```{r} 41 | drive_show_publish(file) 42 | ``` 43 | 44 | ## get URL 45 | ```{r} 46 | url <- drive_share_link(file) 47 | url 48 | ``` 49 | 50 | ## it's published, not shared 51 | 52 | ```{r} 53 | file 54 | ``` 55 | 56 | ```{r} 57 | key <- file$id 58 | ``` 59 | 60 | ## switch to different account 61 | ```{r, eval = FALSE} 62 | gs_auth("sheets-token.rds") 63 | ``` 64 | 65 | 66 | ## this shouldn't work 67 | ```{r} 68 | try(gs_url(url, visibility = "private", lookup = FALSE)) 69 | geterrmessage() 70 | ``` 71 | 72 | ## publish it on Drive 73 | ```{r} 74 | file <- drive_publish(file) 75 | drive_show_publish(file) 76 | ``` 77 | 78 | ## try again! 79 | ```{r} 80 | gs_url(url, lookup = FALSE) 81 | ``` 82 | 83 | check again that the access - it is not shared, but it is published. 84 | 85 | ```{r} 86 | promote(file, "shared") 87 | ``` 88 | 89 | ## clean up 90 | 91 | ```{r} 92 | drive_rm(file) 93 | ``` 94 | 95 | ## Now let's try shared but not published 96 | 97 | ```{r} 98 | file <- drive_upload( 99 | R.home('doc/BioC_mirrors.csv'), 100 | type = "spreadsheet" 101 | ) 102 | ``` 103 | 104 | ```{r} 105 | file <- drive_share(file, role = "reader", type = "anyone") 106 | ``` 107 | 108 | ```{r} 109 | url <- drive_share_link(file) 110 | url 111 | ``` 112 | 113 | ## this should work! 114 | ```{r} 115 | gs_url(url, visibility = "private", lookup = FALSE) 116 | ``` 117 | 118 | It is not published, but it is shared. 119 | 120 | ```{r} 121 | file <- drive_show_publish(file) 122 | ``` 123 | 124 | -------------------------------------------------------------------------------- /internal/old/04_map_demo.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Map Demo" 3 | author: "Lucy D’Agostino McGowan" 4 | date: "5/5/2017" 5 | output: 6 | github_document: 7 | toc: true 8 | --- 9 | 10 | ```{r, message = FALSE, warning = FALSE} 11 | library("dplyr") 12 | library("googledrive") 13 | drive_auth("drive-token.rds") 14 | ``` 15 | 16 | 17 | ## we can also pull out multiple files 18 | ```{r} 19 | list_of_ids <- drive_list(pattern = "test")$id[1:10] 20 | list_of_files <- list_of_ids %>% 21 | purrr::map(drive_file) 22 | ``` 23 | 24 | ## change access 25 | ```{r} 26 | list_of_files <- list_of_files %>% 27 | purrr::map(drive_share, role = "reader", type = "anyone") 28 | ``` 29 | 30 | ## check access 31 | ```{r} 32 | list_of_files %>% purrr::map_chr("access") 33 | ``` 34 | 35 | ## delete them all! 36 | 37 | ```{r} 38 | list_of_files <- list_of_files %>% 39 | purrr::map(drive_delete) 40 | ``` 41 | 42 | -------------------------------------------------------------------------------- /internal/old/07_drive_ls_demo.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "folders_are_weird" 3 | author: "Lucy D’Agostino McGowan" 4 | date: "5/11/2017" 5 | output: github_document 6 | --- 7 | 8 | very brief demo 9 | 10 | ```{r} 11 | library(googledrive) 12 | ``` 13 | 14 | ## here is what my most recent files look like: 15 | ```{r} 16 | drive_ls() 17 | ``` 18 | Notice I have lots of folders named the same name! 19 | 20 | ## now we can query by path 21 | 22 | ```{r} 23 | drive_ls(path = "foo/bar/baz") 24 | ``` 25 | In this subdirectory, I have 2 things, a folder named `yo` and a file named `my_file`. 26 | 27 | ## can still pass other query parameters 28 | ```{r} 29 | drive_ls(path = "foo/bar/baz",q = "mimeType='application/vnd.google-apps.folder'") 30 | ``` 31 | 32 | ## can also pass patterns 33 | 34 | ```{r} 35 | drive_ls(path = "foo/bar/baz", pattern = "my_file") 36 | ``` 37 | 38 | -------------------------------------------------------------------------------- /internal/tokens.R: -------------------------------------------------------------------------------- 1 | token <- drive_auth(cache = FALSE) 2 | saveRDS(token, file = "internal/drive-token.rds") 3 | token <- gs_auth(cache = FALSE, new_user = TRUE) 4 | saveRDS(token, file = "internal/sheets-token.rds") 5 | token <- drive_auth(cache = FALSE) 6 | saveRDS(token, file = "tidyverse-noncaching-token.rds") 7 | -------------------------------------------------------------------------------- /man-roxygen/corpus.R: -------------------------------------------------------------------------------- 1 | #' @param corpus Character, specifying which collections of items to search. 2 | #' Relevant to those who work with shared drives and/or Google Workspace 3 | #' domains. If specified, must be one of `"user"`, `"drive"` (requires that 4 | #' `shared_drive` also be specified), `"allDrives"`, or `"domain"`. Read more 5 | #' about [shared drives][shared_drives]. 6 | -------------------------------------------------------------------------------- /man-roxygen/dots-metadata.R: -------------------------------------------------------------------------------- 1 | #' @param ... Named parameters to pass along to the Drive API. Has [dynamic 2 | #' dots][rlang::dyn-dots] semantics. You can affect the metadata of the target file by 3 | #' specifying properties of the Files resource via `...`. Read the "Request 4 | #' body" section of the Drive API docs for the associated endpoint to learn 5 | #' about relevant parameters. 6 | -------------------------------------------------------------------------------- /man-roxygen/file-plural.R: -------------------------------------------------------------------------------- 1 | #' @param file Something that identifies the file(s) of interest on your Google 2 | #' Drive. Can be a character vector of names/paths, a character vector of file 3 | #' ids or URLs marked with [as_id()], or a [`dribble`]. 4 | -------------------------------------------------------------------------------- /man-roxygen/file-singular.R: -------------------------------------------------------------------------------- 1 | #' @param file Something that identifies the file of interest on your Google 2 | #' Drive. Can be a name or path, a file id or URL marked with [as_id()], or a 3 | #' [`dribble`]. 4 | -------------------------------------------------------------------------------- /man-roxygen/media.R: -------------------------------------------------------------------------------- 1 | #' @param media Character, path to the local file to upload. 2 | -------------------------------------------------------------------------------- /man-roxygen/n_max.R: -------------------------------------------------------------------------------- 1 | #' @param n_max Integer. An upper bound on the number of items to return. This 2 | #' applies to the results requested from the API, which may be further 3 | #' filtered locally, via the `pattern` argument. 4 | -------------------------------------------------------------------------------- /man-roxygen/overwrite.R: -------------------------------------------------------------------------------- 1 | #' @param overwrite Logical, indicating whether to check for a pre-existing file 2 | #' at the targetted "filepath". The quotes around "filepath" refer to the fact 3 | #' that Drive does not impose a 1-to-1 relationship between filepaths and files, 4 | #' like a typical file system; read more about that in [drive_get()]. 5 | #' 6 | #' * `NA` (default): Just do the operation, even if it results in multiple 7 | #' files with the same filepath. 8 | #' * `TRUE`: Check for a pre-existing file at the filepath. If there is 9 | #' zero or one, move a pre-existing file to the trash, then carry on. Note 10 | #' that the new file does not inherit any properties from the old one, such 11 | #' as sharing or publishing settings. It will have a new file ID. An error is 12 | #' thrown if two or more pre-existing files are found. 13 | #' * `FALSE`: Error if there is any pre-existing file at the filepath. 14 | #' 15 | #' Note that existence checks, based on filepath, are expensive operations, i.e. 16 | #' they require additional API calls. 17 | 18 | -------------------------------------------------------------------------------- /man-roxygen/pattern.R: -------------------------------------------------------------------------------- 1 | #' @param pattern Character. If provided, only the items whose names match this 2 | #' regular expression are returned. This is implemented locally on the results 3 | #' returned by the API. 4 | -------------------------------------------------------------------------------- /man-roxygen/shared-drive-description.R: -------------------------------------------------------------------------------- 1 | #' @description 2 | 3 | #' A shared drive supports files owned by an organization rather than an 4 | #' individual user. Shared drives follow different sharing and ownership models 5 | #' from a specific user's "My Drive". Shared drives are the successors to the 6 | #' earlier concept of Team Drives. Learn more about [shared 7 | #' drives][shared_drives]. 8 | -------------------------------------------------------------------------------- /man-roxygen/shared_drive-plural.R: -------------------------------------------------------------------------------- 1 | #' @param drive Anything that identifies the shared drive(s) of interest. Can 2 | #' be a character vector of names, a character vector of file ids or URLs 3 | #' marked with [as_id()], or a [`dribble`] consisting only of shared drives. 4 | -------------------------------------------------------------------------------- /man-roxygen/shared_drive-singular.R: -------------------------------------------------------------------------------- 1 | #' @param shared_drive Anything that identifies one specific shared drive: its 2 | #' name, its id or URL marked with [as_id()], or a [`dribble`]. The value 3 | #' provided to `shared_drive` is pre-processed with [as_shared_drive()]. Read 4 | #' more about [shared drives][shared_drives]. 5 | -------------------------------------------------------------------------------- /man-roxygen/team-drives-description.R: -------------------------------------------------------------------------------- 1 | #' @description 2 | 3 | #' Team Drives have been rebranded as *shared drives* and, as of googledrive 4 | #' v2.0.0, all `team_drive_*()` functions have been deprecated, in favor of 5 | #' `shared_drive_*()` successors. 6 | #' 7 | #' The changes in googledrive reflect that the Team Drives resource collection 8 | #' has been deprecated in the Drive API v3, in favor of the new (shared) Drives 9 | #' resource collection. Read more 10 | 11 | #' * 12 | 13 | 14 | -------------------------------------------------------------------------------- /man-roxygen/team_drive-plural.R: -------------------------------------------------------------------------------- 1 | #' @param team_drive `r lifecycle::badge("deprecated")` Google Drive and the 2 | #' Drive API have replaced Team Drives with shared drives. 3 | -------------------------------------------------------------------------------- /man-roxygen/team_drive-singular.R: -------------------------------------------------------------------------------- 1 | #' @param team_drive `r lifecycle::badge("deprecated")` Google Drive and the 2 | #' Drive API have replaced Team Drives with shared drives. 3 | -------------------------------------------------------------------------------- /man-roxygen/verbose.R: -------------------------------------------------------------------------------- 1 | #' @param verbose `r lifecycle::badge("deprecated")` This logical argument to 2 | #' individual googledrive functions is deprecated. To globally suppress 3 | #' googledrive messaging, use `options(googledrive_quiet = TRUE)` (the default 4 | #' behaviour is to emit informational messages). To suppress messaging in a 5 | #' more limited way, use the helpers [`local_drive_quiet()`] or 6 | #' [`with_drive_quiet()`]. 7 | -------------------------------------------------------------------------------- /man/as_shared_drive.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/shared_drives.R 3 | \name{as_shared_drive} 4 | \alias{as_shared_drive} 5 | \title{Coerce to shared drive} 6 | \usage{ 7 | as_shared_drive(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{A vector of shared drive names, a vector of shared drive ids marked 11 | with \code{\link[=as_id]{as_id()}}, a list of Drives resource objects, or a suitable data 12 | frame.} 13 | 14 | \item{...}{Other arguments passed down to methods. (Not used.)} 15 | } 16 | \description{ 17 | Converts various representations of a shared drive into a 18 | \code{\link{dribble}}, the object used by googledrive to hold Drive file metadata. 19 | Shared drives can be specified via 20 | \itemize{ 21 | \item Name 22 | \item Shared drive id, marked with \code{\link[=as_id]{as_id()}} to distinguish from name 23 | \item Data frame or \code{\link{dribble}} consisting solely of shared drives 24 | \item List representing \href{https://developers.google.com/drive/api/v3/reference/drives#resource-representations}{Drives resource} 25 | objects (mostly for internal use) 26 | } 27 | 28 | A shared drive supports files owned by an organization rather than an 29 | individual user. Shared drives follow different sharing and ownership models 30 | from a specific user's "My Drive". Shared drives are the successors to the 31 | earlier concept of Team Drives. Learn more about \link[=shared_drives]{shared drives}. 32 | 33 | This is a generic function. 34 | } 35 | \examples{ 36 | \dontrun{ 37 | # specify the name 38 | as_shared_drive("abc") 39 | 40 | # specify the id (substitute one of your own!) 41 | as_shared_drive(as_id("0AOPK1X2jaNckUk9PVA")) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /man/dribble-checks.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/dribble.R 3 | \name{dribble-checks} 4 | \alias{dribble-checks} 5 | \alias{is_dribble} 6 | \alias{no_file} 7 | \alias{single_file} 8 | \alias{some_files} 9 | \alias{confirm_dribble} 10 | \alias{confirm_single_file} 11 | \alias{confirm_some_files} 12 | \alias{is_folder} 13 | \alias{is_shortcut} 14 | \alias{is_folder_shortcut} 15 | \alias{is_native} 16 | \alias{is_parental} 17 | \alias{is_mine} 18 | \alias{is_shared_drive} 19 | \title{Check facts about a dribble} 20 | \usage{ 21 | is_dribble(d) 22 | 23 | no_file(d) 24 | 25 | single_file(d) 26 | 27 | some_files(d) 28 | 29 | confirm_dribble(d) 30 | 31 | confirm_single_file(d) 32 | 33 | confirm_some_files(d) 34 | 35 | is_folder(d) 36 | 37 | is_shortcut(d) 38 | 39 | is_folder_shortcut(d) 40 | 41 | is_native(d) 42 | 43 | is_parental(d) 44 | 45 | is_mine(d) 46 | 47 | is_shared_drive(d) 48 | } 49 | \arguments{ 50 | \item{d}{A \code{\link{dribble}}.} 51 | } 52 | \description{ 53 | Sometimes you need to check things about a \code{\link{dribble}}` or about the files it 54 | represents, such as: 55 | \itemize{ 56 | \item Is it even a dribble? 57 | \item Size: Does the dribble hold exactly one file? At least one file? No file? 58 | \item File type: Is this file a folder? 59 | \item File ownership and access: Is it mine? Published? Shared? 60 | } 61 | } 62 | \examples{ 63 | \dontshow{if (drive_has_token()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} 64 | ## most of us have multiple files or folders on Google Drive 65 | d <- drive_find() 66 | is_dribble(d) 67 | no_file(d) 68 | single_file(d) 69 | some_files(d) 70 | 71 | # this will error 72 | # confirm_single_file(d) 73 | 74 | confirm_some_files(d) 75 | is_folder(d) 76 | is_mine(d) 77 | \dontshow{\}) # examplesIf} 78 | } 79 | -------------------------------------------------------------------------------- /man/dribble.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/dribble.R 3 | \name{dribble} 4 | \alias{dribble} 5 | \title{dribble object} 6 | \description{ 7 | googledrive stores the metadata for one or more Drive files or 8 | shared drives as a \code{dribble}. It is a "Drive 9 | \link[tibble:tibble-package]{tibble}" with one row per file or shared drive 10 | and, at a minimum, these columns: 11 | \itemize{ 12 | \item \code{name}: a character column containing file or shared drive names 13 | \item \code{id}: a character column of file or shared drive ids 14 | \item \code{drive_resource}: a list-column, each element of which is either a 15 | \href{https://developers.google.com/drive/api/v3/reference/files#resource-representations}{Files resource} 16 | or a \href{https://developers.google.com/drive/api/v3/reference/drives#resource-representations}{Drives resource} 17 | object. Note there is no guarantee that all documented fields are always 18 | present. We do check if the \code{kind} field is present and equal to one of 19 | \code{drive#file} or \code{drive#drive}. 20 | } 21 | 22 | The \code{dribble} format is handy because it exposes the file name, 23 | which is good for humans, but keeps it bundled with the file's unique id 24 | and other metadata, which are needed for API calls. 25 | 26 | In general, the \code{dribble} class will be retained even after 27 | manipulation, as long as the required variables are present and of the 28 | correct type. This works best for manipulations via the dplyr and vctrs 29 | packages. 30 | } 31 | \seealso{ 32 | \code{\link[=as_dribble]{as_dribble()}} 33 | } 34 | -------------------------------------------------------------------------------- /man/drive_about.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/drive_about.R 3 | \name{drive_about} 4 | \alias{drive_about} 5 | \title{Get info on Drive capabilities} 6 | \usage{ 7 | drive_about() 8 | } 9 | \value{ 10 | A list representation of a Drive 11 | \href{https://developers.google.com/drive/api/v3/reference/about}{about resource} 12 | } 13 | \description{ 14 | Gets information about the user, the user's Drive, and system capabilities. 15 | This function mostly exists to power \code{\link[=drive_user]{drive_user()}}, which extracts the most 16 | useful information (the information on current user) and prints it nicely. 17 | } 18 | \examples{ 19 | \dontshow{if (drive_has_token()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} 20 | drive_about() 21 | 22 | # explore the export formats available for Drive files, by MIME type 23 | about <- drive_about() 24 | about[["exportFormats"]] \%>\% 25 | purrr::map(unlist) 26 | \dontshow{\}) # examplesIf} 27 | } 28 | \seealso{ 29 | Wraps the \code{about.get} endpoint: 30 | \itemize{ 31 | \item \url{https://developers.google.com/drive/api/v3/reference/about/get} 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /man/drive_browse.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/drive_browse.R 3 | \name{drive_browse} 4 | \alias{drive_browse} 5 | \title{Visit Drive file in browser} 6 | \usage{ 7 | drive_browse(file = .Last.value) 8 | } 9 | \arguments{ 10 | \item{file}{Something that identifies the file of interest on your Google 11 | Drive. Can be a name or path, a file id or URL marked with \code{\link[=as_id]{as_id()}}, or a 12 | \code{\link{dribble}}.} 13 | } 14 | \value{ 15 | Character vector of file hyperlinks, from \code{\link[=drive_link]{drive_link()}}, invisibly. 16 | } 17 | \description{ 18 | Visits a file on Google Drive in your default browser. 19 | } 20 | \examples{ 21 | \dontshow{if (drive_has_token() && rlang::is_interactive()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} 22 | drive_find(n_max = 1) \%>\% drive_browse() 23 | \dontshow{\}) # examplesIf} 24 | } 25 | -------------------------------------------------------------------------------- /man/drive_deauth.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/drive_auth.R 3 | \name{drive_deauth} 4 | \alias{drive_deauth} 5 | \title{Suspend authorization} 6 | \usage{ 7 | drive_deauth() 8 | } 9 | \description{ 10 | Put googledrive into a de-authorized state. Instead of sending a token, 11 | googledrive will send an API key. This can be used to access public 12 | resources for which no Google sign-in is required. This is handy for using 13 | googledrive in a non-interactive setting to make requests that do not 14 | require a token. It will prevent the attempt to obtain a token 15 | interactively in the browser. The user can configure their own API key 16 | via \code{\link[=drive_auth_configure]{drive_auth_configure()}} and retrieve that key via 17 | \code{\link[=drive_api_key]{drive_api_key()}}. 18 | In the absence of a user-configured key, a built-in default key is used. 19 | } 20 | \examples{ 21 | \dontshow{if (rlang::is_interactive()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} 22 | drive_deauth() 23 | drive_user() 24 | 25 | # in a deauth'ed state, we can still get metadata on a world-readable file 26 | public_file <- drive_example_remote("chicken.csv") 27 | public_file 28 | # we can still download it too 29 | drive_download(public_file) 30 | \dontshow{\}) # examplesIf} 31 | } 32 | \seealso{ 33 | Other auth functions: 34 | \code{\link{drive_auth_configure}()}, 35 | \code{\link{drive_auth}()}, 36 | \code{\link{drive_scopes}()} 37 | } 38 | \concept{auth functions} 39 | -------------------------------------------------------------------------------- /man/drive_empty_trash.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/drive_trash.R 3 | \name{drive_empty_trash} 4 | \alias{drive_empty_trash} 5 | \title{Empty Drive Trash} 6 | \usage{ 7 | drive_empty_trash(verbose = deprecated()) 8 | } 9 | \arguments{ 10 | \item{verbose}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} This logical argument to 11 | individual googledrive functions is deprecated. To globally suppress 12 | googledrive messaging, use \code{options(googledrive_quiet = TRUE)} (the default 13 | behaviour is to emit informational messages). To suppress messaging in a 14 | more limited way, use the helpers \code{\link[=local_drive_quiet]{local_drive_quiet()}} or 15 | \code{\link[=with_drive_quiet]{with_drive_quiet()}}.} 16 | } 17 | \description{ 18 | Caution, this will permanently delete files in your Drive trash. 19 | } 20 | -------------------------------------------------------------------------------- /man/drive_endpoints.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/drive_endpoints.R 3 | \name{drive_endpoints} 4 | \alias{drive_endpoints} 5 | \alias{drive_endpoint} 6 | \title{List Drive endpoints} 7 | \usage{ 8 | drive_endpoints(i = NULL) 9 | 10 | drive_endpoint(i) 11 | } 12 | \arguments{ 13 | \item{i}{The name(s) or integer index(ices) of the endpoints to return. \code{i} 14 | is optional for \code{drive_endpoints()} and, if not given, the entire list is 15 | returned.} 16 | } 17 | \value{ 18 | One or more of the Drive API v3 endpoints that are used internally by 19 | googledrive. 20 | } 21 | \description{ 22 | The googledrive package stores a named list of Drive API v3 endpoints (or 23 | "methods", using Google's vocabulary) internally and these functions expose 24 | this data. 25 | \itemize{ 26 | \item \code{drive_endpoint()} returns one endpoint, i.e. it uses \code{[[}. 27 | \item \code{drive_endpoints()} returns a list of endpoints, i.e. it uses \code{[}. 28 | } 29 | 30 | The names of this list (or the \code{id} sub-elements) are the nicknames that can 31 | be used to specify an endpoint in \code{\link[=request_generate]{request_generate()}}. For each endpoint, we 32 | store its nickname or \code{id}, the associated HTTP verb, the \code{path}, and details 33 | about the parameters. This list is derived programmatically from the Drive 34 | API v3 Discovery Document 35 | (\verb{https://www.googleapis.com/discovery/v1/apis/drive/v3/rest}) using the 36 | approach described in the \href{https://gargle.r-lib.org/articles/request-helper-functions.html#discovery-documents}{Discovery Documents section} 37 | of the gargle vignette \href{https://gargle.r-lib.org/articles/request-helper-functions.html}{Request helper functions}. 38 | } 39 | \examples{ 40 | str(head(drive_endpoints(), 3), max.level = 2) 41 | drive_endpoint("drive.files.delete") 42 | drive_endpoint(4) 43 | } 44 | -------------------------------------------------------------------------------- /man/drive_examples.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/drive_examples.R 3 | \name{drive_examples} 4 | \alias{drive_examples} 5 | \alias{drive_examples_local} 6 | \alias{drive_examples_remote} 7 | \alias{drive_example_local} 8 | \alias{drive_example_remote} 9 | \title{Example files} 10 | \usage{ 11 | drive_examples_local(matches) 12 | 13 | drive_examples_remote(matches) 14 | 15 | drive_example_local(matches) 16 | 17 | drive_example_remote(matches) 18 | } 19 | \arguments{ 20 | \item{matches}{A regular expression that matches the name of the desired 21 | example file(s). This argument is optional for the plural forms 22 | (\code{drive_examples_local()} and \code{drive_examples_remote()}) and, if provided, 23 | multiple matches are allowed. The single forms (\code{drive_example_local()} and 24 | \code{drive_example_remote()}) require this argument and require that there is 25 | exactly one match.} 26 | } 27 | \value{ 28 | \itemize{ 29 | \item For \code{drive_example_local()} and \code{drive_examples_local()}, one or more local 30 | filepaths. 31 | \item For \code{drive_example_remote()} and \code{drive_examples_remote()}, a \code{dribble}. 32 | } 33 | } 34 | \description{ 35 | googledrive makes a variety of example files -- both local and remote -- 36 | available for use in examples and reprexes. These functions help you access 37 | the example files. See \code{vignette("example-files", package = "googledrive")} 38 | for more. 39 | } 40 | \examples{ 41 | drive_examples_local() \%>\% basename() 42 | drive_examples_local("chicken") \%>\% basename() 43 | drive_example_local("imdb") 44 | 45 | \dontshow{if (drive_has_token()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} 46 | drive_examples_remote() 47 | drive_examples_remote("chicken") 48 | drive_example_remote("chicken_doc") 49 | \dontshow{\}) # examplesIf} 50 | } 51 | -------------------------------------------------------------------------------- /man/drive_extension.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/drive_mime_type.R 3 | \name{drive_extension} 4 | \alias{drive_extension} 5 | \title{Lookup extension from MIME type} 6 | \usage{ 7 | drive_extension(type = NULL) 8 | } 9 | \arguments{ 10 | \item{type}{Character. MIME type or file extension.} 11 | } 12 | \value{ 13 | Character. File extension. 14 | } 15 | \description{ 16 | This is a helper to determinine which extension should be used 17 | for a file. Two types of input are acceptable: 18 | \itemize{ 19 | \item MIME types accepted by Google Drive. 20 | \item File extensions, such as "pdf", "csv", etc. (these are simply passed through). 21 | } 22 | } 23 | \examples{ 24 | 25 | ## get the extension for mime type image/jpeg 26 | drive_extension("image/jpeg") 27 | 28 | ## it's vectorized 29 | drive_extension(c("text/plain", "pdf", "image/gif")) 30 | } 31 | -------------------------------------------------------------------------------- /man/drive_fields.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/drive_fields.R 3 | \name{drive_fields} 4 | \alias{drive_fields} 5 | \alias{prep_fields} 6 | \title{Request partial resources} 7 | \usage{ 8 | drive_fields(fields = NULL, resource = "files") 9 | 10 | prep_fields(fields, resource = "files") 11 | } 12 | \arguments{ 13 | \item{fields}{Character vector of field names. If \code{resource = "files"}, they 14 | are checked for validity. Otherwise, they are passed through.} 15 | 16 | \item{resource}{Character, naming the API resource of interest. Currently, 17 | only the Files resource is anticipated.} 18 | } 19 | \value{ 20 | \code{drive_fields()}: Character vector of field names. \code{prep_fields()}: a 21 | string. 22 | } 23 | \description{ 24 | You may be able to improve the performance of your API calls by 25 | requesting only the metadata that you actually need. This function is 26 | primarily for internal use and is currently focused on the \href{https://developers.google.com/drive/api/v3/reference/files}{Files resource}. Note 27 | that high-level googledrive functions assume that the \code{name}, \code{id}, and 28 | \code{kind} fields are included, at a bare minimum. Assuming that \code{resource = "files"} (the default), input provided via \code{fields} is checked for validity 29 | against the known field names and the validated fields are returned. To see 30 | a tibble containing all possible fields and a short description of each, 31 | call \code{drive_fields(expose())}. 32 | 33 | \code{prep_fields()} prepares fields for inclusion as query 34 | parameters. 35 | } 36 | \examples{ 37 | # get a tibble of all fields for the Files resource + indicator of defaults 38 | drive_fields(expose()) 39 | 40 | # invalid fields are removed and throw warning 41 | drive_fields(c("name", "parents", "ownedByMe", "pancakes!")) 42 | 43 | # prepare fields for query 44 | prep_fields(c("name", "parents", "kind")) 45 | } 46 | \seealso{ 47 | \href{https://developers.google.com/drive/api/v3/performance}{Improve performance}, in 48 | the Drive API documentation. 49 | } 50 | -------------------------------------------------------------------------------- /man/drive_has_token.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/drive_auth.R 3 | \name{drive_has_token} 4 | \alias{drive_has_token} 5 | \title{Is there a token on hand?} 6 | \usage{ 7 | drive_has_token() 8 | } 9 | \value{ 10 | Logical. 11 | } 12 | \description{ 13 | Reports whether googledrive has stored a token, ready for use in downstream 14 | requests. 15 | } 16 | \examples{ 17 | drive_has_token() 18 | } 19 | \seealso{ 20 | Other low-level API functions: 21 | \code{\link{drive_token}()}, 22 | \code{\link{request_generate}()}, 23 | \code{\link{request_make}()} 24 | } 25 | \concept{low-level API functions} 26 | -------------------------------------------------------------------------------- /man/drive_id.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/drive_id-class.R 3 | \name{drive_id} 4 | \alias{drive_id} 5 | \alias{as_id} 6 | \title{\code{drive_id} class} 7 | \usage{ 8 | as_id(x, ...) 9 | } 10 | \arguments{ 11 | \item{x}{A character vector of file or shared drive ids or URLs, a 12 | \code{\link{dribble}}, or a suitable data frame.} 13 | 14 | \item{...}{Other arguments passed down to methods. (Not used.)} 15 | } 16 | \value{ 17 | A character vector bearing the S3 class \code{drive_id}. 18 | } 19 | \description{ 20 | \code{drive_id} is an S3 class to mark strings as Drive file ids, in order to 21 | distinguish them from Drive file names or paths. \code{as_id()} converts various 22 | inputs into an instance of \code{drive_id}. 23 | 24 | \code{as_id()} is a generic function. 25 | } 26 | \examples{ 27 | \dontshow{if (drive_has_token()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} 28 | as_id("123abc") 29 | as_id("https://docs.google.com/spreadsheets/d/qawsedrf16273849/edit#gid=12345") 30 | 31 | x <- drive_find(n_max = 3) 32 | as_id(x) 33 | \dontshow{\}) # examplesIf} 34 | } 35 | -------------------------------------------------------------------------------- /man/drive_link.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/drive_browse.R 3 | \name{drive_link} 4 | \alias{drive_link} 5 | \title{Retrieve Drive file links} 6 | \usage{ 7 | drive_link(file) 8 | } 9 | \arguments{ 10 | \item{file}{Something that identifies the file(s) of interest on your Google 11 | Drive. Can be a character vector of names/paths, a character vector of file 12 | ids or URLs marked with \code{\link[=as_id]{as_id()}}, or a \code{\link{dribble}}.} 13 | } 14 | \value{ 15 | Character vector of file hyperlinks. 16 | } 17 | \description{ 18 | Returns the \code{"webViewLink"} for one or more files, which is the "link for 19 | opening the file in a relevant Google editor or viewer in a browser". 20 | } 21 | \examples{ 22 | \dontshow{if (drive_has_token()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} 23 | # get a few files into a dribble 24 | three_files <- drive_find(n_max = 3) 25 | 26 | # get their browser links 27 | drive_link(three_files) 28 | \dontshow{\}) # examplesIf} 29 | } 30 | -------------------------------------------------------------------------------- /man/drive_ls.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/drive_ls.R 3 | \name{drive_ls} 4 | \alias{drive_ls} 5 | \title{List contents of a folder or shared drive} 6 | \usage{ 7 | drive_ls(path = NULL, ..., recursive = FALSE) 8 | } 9 | \arguments{ 10 | \item{path}{Specifies a single folder on Google Drive whose contents you want 11 | to list. Can be an actual path (character), a file id or URL marked with 12 | \code{\link[=as_id]{as_id()}}, or a \code{\link{dribble}}. If it is a shared drive or is a folder on a 13 | shared drive, it must be passed as a \code{\link{dribble}}. If \code{path} is a shortcut 14 | to a folder, it is automatically resolved to its target folder.} 15 | 16 | \item{...}{Any parameters that are valid for \code{\link[=drive_find]{drive_find()}}.} 17 | 18 | \item{recursive}{Logical, indicating if you want only direct children of 19 | \code{path} (\code{recursive = FALSE}, the default) or all children, including 20 | indirect (\code{recursive = TRUE}).} 21 | } 22 | \value{ 23 | An object of class \code{\link{dribble}}, a tibble with one row per file. 24 | } 25 | \description{ 26 | List the contents of a folder or shared drive, recursively or not. This is a 27 | thin wrapper around \code{\link[=drive_find]{drive_find()}}, that simply adds one constraint: the 28 | search is limited to direct or indirect children of \code{path}. 29 | } 30 | \examples{ 31 | \dontrun{ 32 | # get contents of the folder 'abc' (non-recursive) 33 | drive_ls("abc") 34 | 35 | # get contents of folder 'abc' whose names contain the letters 'def' 36 | drive_ls(path = "abc", pattern = "def") 37 | 38 | # get all Google spreadsheets in folder 'abc' 39 | # whose names contain the letters 'def' 40 | drive_ls(path = "abc", pattern = "def", type = "spreadsheet") 41 | 42 | # get all the files below 'abc', recursively, that are starred 43 | drive_ls(path = "abc", q = "starred = true", recursive = TRUE) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /man/drive_mime_type.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/drive_mime_type.R 3 | \name{drive_mime_type} 4 | \alias{drive_mime_type} 5 | \title{Lookup MIME type} 6 | \usage{ 7 | drive_mime_type(type = NULL) 8 | } 9 | \arguments{ 10 | \item{type}{Character. Google Drive file type, file extension, or MIME type. 11 | Pass the sentinel \code{\link[=expose]{expose()}} if you want to get the full table used for 12 | validation and lookup, i.e. all MIME types known to be relevant to the 13 | Drive API.} 14 | } 15 | \value{ 16 | Character. MIME type. 17 | } 18 | \description{ 19 | This is a helper to determine which MIME type should be used 20 | for a file. Three types of input are acceptable: 21 | \itemize{ 22 | \item Native Google Drive file types. Important examples: 23 | \itemize{ 24 | \item "document" for Google Docs 25 | \item "folder" for folders 26 | \item "presentation" for Google Slides 27 | \item "spreadsheet" for Google Sheets 28 | } 29 | \item File extensions, such as "pdf", "csv", etc. 30 | \item MIME types accepted by Google Drive (these are simply passed through). 31 | } 32 | } 33 | \examples{ 34 | ## get the mime type for Google Spreadsheets 35 | drive_mime_type("spreadsheet") 36 | 37 | ## get the mime type for jpegs 38 | drive_mime_type("jpeg") 39 | 40 | ## it's vectorized 41 | drive_mime_type(c("presentation", "pdf", "image/gif")) 42 | 43 | ## see the internal tibble of MIME types known to the Drive API 44 | drive_mime_type(expose()) 45 | } 46 | -------------------------------------------------------------------------------- /man/drive_publish.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/drive_publish.R 3 | \name{drive_publish} 4 | \alias{drive_publish} 5 | \alias{drive_unpublish} 6 | \title{Publish native Google files} 7 | \usage{ 8 | drive_publish(file, ..., verbose = deprecated()) 9 | 10 | drive_unpublish(file, ..., verbose = deprecated()) 11 | } 12 | \arguments{ 13 | \item{file}{Something that identifies the file(s) of interest on your Google 14 | Drive. Can be a character vector of names/paths, a character vector of file 15 | ids or URLs marked with \code{\link[=as_id]{as_id()}}, or a \code{\link{dribble}}.} 16 | 17 | \item{...}{Name-value pairs to add to the API request body (see API docs 18 | linked below for details). For \code{drive_publish()}, we include 19 | \code{publishAuto = TRUE} and \code{publishedOutsideDomain = TRUE}, if user does not 20 | specify other values.} 21 | 22 | \item{verbose}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} This logical argument to 23 | individual googledrive functions is deprecated. To globally suppress 24 | googledrive messaging, use \code{options(googledrive_quiet = TRUE)} (the default 25 | behaviour is to emit informational messages). To suppress messaging in a 26 | more limited way, use the helpers \code{\link[=local_drive_quiet]{local_drive_quiet()}} or 27 | \code{\link[=with_drive_quiet]{with_drive_quiet()}}.} 28 | } 29 | \value{ 30 | An object of class \code{\link{dribble}}, a tibble with one row per file. 31 | There will be extra columns, \code{published} and 32 | \code{revisions_resource}. 33 | } 34 | \description{ 35 | Publish (or un-publish) native Google files to the web. Native Google files 36 | include Google Docs, Google Sheets, and Google Slides. The returned 37 | \code{\link{dribble}} will have extra columns, \code{published} and \code{revisions_resource}. 38 | Read more in \code{\link[=drive_reveal]{drive_reveal()}}. 39 | } 40 | \examples{ 41 | \dontshow{if (drive_has_token()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} 42 | # Create a file to publish 43 | file <- drive_example_remote("chicken_sheet") \%>\% 44 | drive_cp() 45 | 46 | # Publish file 47 | file <- drive_publish(file) 48 | file$published 49 | 50 | # Unpublish file 51 | file <- drive_unpublish(file) 52 | file$published 53 | 54 | # Clean up 55 | drive_rm(file) 56 | \dontshow{\}) # examplesIf} 57 | } 58 | \seealso{ 59 | Wraps the \code{revisions.update} endpoint: 60 | \itemize{ 61 | \item \url{https://developers.google.com/drive/api/v3/reference/revisions/update} 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /man/drive_read_string.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/drive_read.R 3 | \name{drive_read_string} 4 | \alias{drive_read_string} 5 | \alias{drive_read_raw} 6 | \title{Read the content of a Drive file} 7 | \usage{ 8 | drive_read_string(file, type = NULL, encoding = NULL) 9 | 10 | drive_read_raw(file, type = NULL) 11 | } 12 | \arguments{ 13 | \item{file}{Something that identifies the file of interest on your Google 14 | Drive. Can be a name or path, a file id or URL marked with \code{\link[=as_id]{as_id()}}, or a 15 | \code{\link{dribble}}.} 16 | 17 | \item{type}{Character. Only consulted if \code{file} is a native Google file. 18 | Specifies the desired type of the exported file. Will be processed via 19 | \code{\link[=drive_mime_type]{drive_mime_type()}}, so either a file extension like \code{"pdf"} or a full MIME 20 | type like \code{"application/pdf"} is acceptable.} 21 | 22 | \item{encoding}{Passed along to \code{\link[httr:content]{httr::content()}}. Describes the encoding of 23 | the \emph{input} \code{file}.} 24 | } 25 | \value{ 26 | \itemize{ 27 | \item \code{read_drive_string()}: a UTF-8 encoded string 28 | \item \code{read_drive_raw()}: a \code{\link[=raw]{raw()}} vector 29 | } 30 | } 31 | \description{ 32 | These functions return the content of a Drive file as either a 33 | string or raw bytes. You will likely need to do additional work to parse 34 | the content into a useful R object. 35 | 36 | \code{\link[=drive_download]{drive_download()}} is the more generally useful function, but for certain 37 | file types, such as comma-separated values (MIME type \code{text/csv}), it can 38 | be handy to read data directly from Google Drive and avoid writing to disk. 39 | 40 | Just as for \code{\link[=drive_download]{drive_download()}}, native Google file types, such as Google 41 | Sheets or Docs, must be exported as a conventional MIME type. See the help 42 | for \code{\link[=drive_download]{drive_download()}} for more. 43 | } 44 | \examples{ 45 | \dontshow{if (drive_has_token()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} 46 | # comma-separated values --> data.frame or tibble 47 | (chicken_csv <- drive_example_remote("chicken.csv")) 48 | chicken_csv \%>\% 49 | drive_read_string() \%>\% 50 | read.csv(text = .) 51 | 52 | # Google Doc --> character vector 53 | (chicken_doc <- drive_example_remote("chicken_doc")) 54 | chicken_doc \%>\% 55 | # NOTE: we must specify an export MIME type 56 | drive_read_string(type = "text/plain") \%>\% 57 | strsplit(split = "(\r\n|\r|\n)") \%>\% 58 | .[[1]] 59 | \dontshow{\}) # examplesIf} 60 | } 61 | -------------------------------------------------------------------------------- /man/drive_rm.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/drive_rm.R 3 | \name{drive_rm} 4 | \alias{drive_rm} 5 | \title{Delete files from Drive} 6 | \usage{ 7 | drive_rm(..., verbose = deprecated()) 8 | } 9 | \arguments{ 10 | \item{...}{One or more Drive files, specified in any valid way, i.e. as a 11 | \code{\link{dribble}}, by name or path, or by file id or URL marked with \code{\link[=as_id]{as_id()}}. Or 12 | any combination thereof. Elements are processed with \code{\link[=as_dribble]{as_dribble()}} and 13 | row-bound prior to deletion.} 14 | 15 | \item{verbose}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} This logical argument to 16 | individual googledrive functions is deprecated. To globally suppress 17 | googledrive messaging, use \code{options(googledrive_quiet = TRUE)} (the default 18 | behaviour is to emit informational messages). To suppress messaging in a 19 | more limited way, use the helpers \code{\link[=local_drive_quiet]{local_drive_quiet()}} or 20 | \code{\link[=with_drive_quiet]{with_drive_quiet()}}.} 21 | } 22 | \value{ 23 | Logical vector, indicating whether the delete succeeded. 24 | } 25 | \description{ 26 | Caution: this will permanently delete your files! For a safer, reversible 27 | option, see \code{\link[=drive_trash]{drive_trash()}}. 28 | } 29 | \examples{ 30 | \dontshow{if (drive_has_token()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} 31 | # Target one of the official example files to copy (then remove) 32 | (src_file <- drive_example_remote("chicken.txt")) 33 | 34 | # Create a copy, then remove it by name 35 | src_file \%>\% 36 | drive_cp(name = "chicken-rm.txt") 37 | drive_rm("chicken-rm.txt") 38 | 39 | # Create several more copies 40 | x1 <- src_file \%>\% 41 | drive_cp(name = "chicken-abc.txt") 42 | drive_cp(src_file, name = "chicken-def.txt") 43 | x2 <- src_file \%>\% 44 | drive_cp(name = "chicken-ghi.txt") 45 | 46 | # Remove the copies all at once, specified in different ways 47 | drive_rm(x1, "chicken-def.txt", as_id(x2)) 48 | \dontshow{\}) # examplesIf} 49 | } 50 | \seealso{ 51 | Wraps the \code{files.delete} endpoint: 52 | \itemize{ 53 | \item \url{https://developers.google.com/drive/api/v3/reference/files/delete} 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /man/drive_scopes.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/drive_auth.R 3 | \name{drive_scopes} 4 | \alias{drive_scopes} 5 | \title{Produce scopes specific to the Drive API} 6 | \usage{ 7 | drive_scopes(scopes = NULL) 8 | } 9 | \arguments{ 10 | \item{scopes}{One or more API scopes. Each scope can be specified in full or, 11 | for Drive API-specific scopes, in an abbreviated form that is recognized by 12 | \code{\link[=drive_scopes]{drive_scopes()}}: 13 | \itemize{ 14 | \item "drive" = "https://www.googleapis.com/auth/drive" (the default) 15 | \item "full" = "https://www.googleapis.com/auth/drive" (same as "drive") 16 | \item "drive.readonly" = "https://www.googleapis.com/auth/drive.readonly" 17 | \item "drive.file" = "https://www.googleapis.com/auth/drive.file" 18 | \item "drive.appdata" = "https://www.googleapis.com/auth/drive.appdata" 19 | \item "drive.metadata" = "https://www.googleapis.com/auth/drive.metadata" 20 | \item "drive.metadata.readonly" = "https://www.googleapis.com/auth/drive.metadata.readonly" 21 | \item "drive.photos.readonly" = "https://www.googleapis.com/auth/drive.photos.readonly" 22 | \item "drive.scripts" = "https://www.googleapis.com/auth/drive.scripts 23 | } 24 | 25 | See \url{https://developers.google.com/drive/api/guides/api-specific-auth} for 26 | details on the permissions for each scope.} 27 | } 28 | \value{ 29 | A character vector of scopes. 30 | } 31 | \description{ 32 | When called with no arguments, \code{drive_scopes()} returns a named character vector 33 | of scopes associated with the Drive API. If \code{drive_scopes(scopes =)} is given, 34 | an abbreviated entry such as \code{"drive.readonly"} is expanded to a full scope 35 | (\code{"https://www.googleapis.com/auth/drive.readonly"} in this case). 36 | Unrecognized scopes are passed through unchanged. 37 | } 38 | \examples{ 39 | drive_scopes("full") 40 | drive_scopes("drive.readonly") 41 | drive_scopes() 42 | } 43 | \seealso{ 44 | \url{https://developers.google.com/drive/api/guides/api-specific-auth} for details on 45 | the permissions for each scope. 46 | 47 | Other auth functions: 48 | \code{\link{drive_auth_configure}()}, 49 | \code{\link{drive_auth}()}, 50 | \code{\link{drive_deauth}()} 51 | } 52 | \concept{auth functions} 53 | -------------------------------------------------------------------------------- /man/drive_token.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/drive_auth.R 3 | \name{drive_token} 4 | \alias{drive_token} 5 | \title{Produce configured token} 6 | \usage{ 7 | drive_token() 8 | } 9 | \value{ 10 | A \code{request} object (an S3 class provided by \link[httr:httr-package]{httr}). 11 | } 12 | \description{ 13 | For internal use or for those programming around the Drive API. 14 | Returns a token pre-processed with \code{\link[httr:config]{httr::config()}}. Most users 15 | do not need to handle tokens "by hand" or, even if they need some 16 | control, \code{\link[=drive_auth]{drive_auth()}} is what they need. If there is no current 17 | token, \code{\link[=drive_auth]{drive_auth()}} is called to either load from cache or 18 | initiate OAuth2.0 flow. 19 | If auth has been deactivated via \code{\link[=drive_deauth]{drive_deauth()}}, \code{drive_token()} 20 | returns \code{NULL}. 21 | } 22 | \examples{ 23 | \dontshow{if (drive_has_token()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} 24 | req <- request_generate( 25 | "drive.files.get", 26 | list(fileId = "abc"), 27 | token = drive_token() 28 | ) 29 | req 30 | \dontshow{\}) # examplesIf} 31 | } 32 | \seealso{ 33 | Other low-level API functions: 34 | \code{\link{drive_has_token}()}, 35 | \code{\link{request_generate}()}, 36 | \code{\link{request_make}()} 37 | } 38 | \concept{low-level API functions} 39 | -------------------------------------------------------------------------------- /man/drive_trash.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/drive_trash.R 3 | \name{drive_trash} 4 | \alias{drive_trash} 5 | \alias{drive_untrash} 6 | \title{Move Drive files to or from trash} 7 | \usage{ 8 | drive_trash(file, verbose = deprecated()) 9 | 10 | drive_untrash(file, verbose = deprecated()) 11 | } 12 | \arguments{ 13 | \item{file}{Something that identifies the file(s) of interest on your Google 14 | Drive. Can be a character vector of names/paths, a character vector of file 15 | ids or URLs marked with \code{\link[=as_id]{as_id()}}, or a \code{\link{dribble}}.} 16 | 17 | \item{verbose}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} This logical argument to 18 | individual googledrive functions is deprecated. To globally suppress 19 | googledrive messaging, use \code{options(googledrive_quiet = TRUE)} (the default 20 | behaviour is to emit informational messages). To suppress messaging in a 21 | more limited way, use the helpers \code{\link[=local_drive_quiet]{local_drive_quiet()}} or 22 | \code{\link[=with_drive_quiet]{with_drive_quiet()}}.} 23 | } 24 | \value{ 25 | An object of class \code{\link{dribble}}, a tibble with one row per file. 26 | } 27 | \description{ 28 | Move Drive files to or from trash 29 | } 30 | \examples{ 31 | \dontshow{if (drive_has_token()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} 32 | # Create a file and put it in the trash. 33 | file <- drive_example_remote("chicken.txt") \%>\% 34 | drive_cp("chicken-trash.txt") 35 | drive_trash("chicken-trash.txt") 36 | 37 | # Confirm it's in the trash 38 | drive_find(trashed = TRUE) 39 | 40 | # Remove it from the trash and confirm 41 | drive_untrash("chicken-trash.txt") 42 | drive_find(trashed = TRUE) 43 | 44 | # Clean up 45 | drive_rm("chicken-trash.txt") 46 | \dontshow{\}) # examplesIf} 47 | } 48 | -------------------------------------------------------------------------------- /man/drive_user.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/drive_user.R 3 | \name{drive_user} 4 | \alias{drive_user} 5 | \title{Get info on current user} 6 | \usage{ 7 | drive_user(verbose = deprecated()) 8 | } 9 | \arguments{ 10 | \item{verbose}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} This logical argument to 11 | individual googledrive functions is deprecated. To globally suppress 12 | googledrive messaging, use \code{options(googledrive_quiet = TRUE)} (the default 13 | behaviour is to emit informational messages). To suppress messaging in a 14 | more limited way, use the helpers \code{\link[=local_drive_quiet]{local_drive_quiet()}} or 15 | \code{\link[=with_drive_quiet]{with_drive_quiet()}}.} 16 | } 17 | \value{ 18 | A list of class \code{drive_user}. 19 | } 20 | \description{ 21 | Reveals information about the user associated with the current token. This is 22 | a thin wrapper around \code{\link[=drive_about]{drive_about()}} that just extracts the most useful 23 | information (the information on current user) and prints it nicely. 24 | } 25 | \examples{ 26 | \dontshow{if (drive_has_token()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} 27 | drive_user() 28 | 29 | # more info is returned than is printed 30 | user <- drive_user() 31 | str(user) 32 | \dontshow{\}) # examplesIf} 33 | } 34 | \seealso{ 35 | Wraps the \code{about.get} endpoint: 36 | \itemize{ 37 | \item \url{https://developers.google.com/drive/api/v3/reference/about/get} 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /man/expose.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils.R 3 | \name{expose} 4 | \alias{expose} 5 | \title{An expose object} 6 | \usage{ 7 | expose() 8 | } 9 | \description{ 10 | \code{expose()} returns a sentinel object, similar in spirit to \code{NULL}, that tells 11 | the calling function to return its internal data structure. googledrive 12 | stores a lot of information about the Drive API, MIME types, etc., internally 13 | and then exploits it in helper functions, like \code{\link[=drive_mime_type]{drive_mime_type()}}, 14 | \code{\link[=drive_fields]{drive_fields()}}, \code{\link[=drive_endpoints]{drive_endpoints()}}, etc. We use these objects to 15 | provide nice defaults, check input validity, or lookup something cryptic, 16 | like MIME type, based on something friendlier, like a file extension. Pass 17 | \code{expose()} to such a function if you want to inspect its internal object, in 18 | its full glory. This is inspired by the \code{waiver()} object in ggplot2. 19 | } 20 | \examples{ 21 | drive_mime_type(expose()) 22 | drive_fields(expose()) 23 | } 24 | \keyword{internal} 25 | -------------------------------------------------------------------------------- /man/figures/lifecycle-archived.svg: -------------------------------------------------------------------------------- 1 | 2 | lifecycle: archived 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | lifecycle 18 | 19 | archived 20 | 21 | 22 | -------------------------------------------------------------------------------- /man/figures/lifecycle-defunct.svg: -------------------------------------------------------------------------------- 1 | 2 | lifecycle: defunct 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | lifecycle 18 | 19 | defunct 20 | 21 | 22 | -------------------------------------------------------------------------------- /man/figures/lifecycle-deprecated.svg: -------------------------------------------------------------------------------- 1 | 2 | lifecycle: deprecated 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | lifecycle 18 | 19 | deprecated 20 | 21 | 22 | -------------------------------------------------------------------------------- /man/figures/lifecycle-experimental.svg: -------------------------------------------------------------------------------- 1 | 2 | lifecycle: experimental 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | lifecycle 18 | 19 | experimental 20 | 21 | 22 | -------------------------------------------------------------------------------- /man/figures/lifecycle-maturing.svg: -------------------------------------------------------------------------------- 1 | 2 | lifecycle: maturing 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | lifecycle 18 | 19 | maturing 20 | 21 | 22 | -------------------------------------------------------------------------------- /man/figures/lifecycle-questioning.svg: -------------------------------------------------------------------------------- 1 | 2 | lifecycle: questioning 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | lifecycle 18 | 19 | questioning 20 | 21 | 22 | -------------------------------------------------------------------------------- /man/figures/lifecycle-soft-deprecated.svg: -------------------------------------------------------------------------------- 1 | 2 | lifecycle: soft-deprecated 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | lifecycle 18 | 19 | soft-deprecated 20 | 21 | 22 | -------------------------------------------------------------------------------- /man/figures/lifecycle-stable.svg: -------------------------------------------------------------------------------- 1 | 2 | lifecycle: stable 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | lifecycle 21 | 22 | 25 | 26 | stable 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /man/figures/lifecycle-superseded.svg: -------------------------------------------------------------------------------- 1 | 2 | lifecycle: superseded 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | lifecycle 18 | 19 | superseded 20 | 21 | 22 | -------------------------------------------------------------------------------- /man/figures/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tidyverse/googledrive/f806c49e62b34fc0150a7bd67fde1885ae479b9e/man/figures/logo.png -------------------------------------------------------------------------------- /man/googledrive-deprecated.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/deprecated.R 3 | \name{googledrive-deprecated} 4 | \alias{googledrive-deprecated} 5 | \alias{drive_auth_config} 6 | \alias{drive_oauth_app} 7 | \alias{drive_example} 8 | \title{Deprecated googledrive functions} 9 | \usage{ 10 | drive_auth_config(active, app, path, api_key) 11 | 12 | drive_oauth_app() 13 | 14 | drive_example(path = NULL) 15 | } 16 | \arguments{ 17 | \item{app}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Replaced by the \code{client} 18 | argument.} 19 | 20 | \item{path}{JSON downloaded from \href{https://console.cloud.google.com}{Google Cloud Console}, containing a client id and 21 | secret, in one of the forms supported for the \code{txt} argument of 22 | \code{\link[jsonlite:fromJSON]{jsonlite::fromJSON()}} (typically, a file path or JSON string).} 23 | 24 | \item{api_key}{API key.} 25 | } 26 | \description{ 27 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} 28 | } 29 | \section{\code{drive_auth_config()}}{ 30 | 31 | 32 | This function is defunct. 33 | \itemize{ 34 | \item Use \code{\link[=drive_auth_configure]{drive_auth_configure()}} to configure your own OAuth client or API key. 35 | \item Use \code{\link[=drive_deauth]{drive_deauth()}} to go into a de-authorized state. 36 | \item Use \code{\link[=drive_oauth_client]{drive_oauth_client()}} to retrieve a user-configured client, if it 37 | exists. 38 | \item Use \code{\link[=drive_api_key]{drive_api_key()}} to retrieve a user-configured API key, if it exists. 39 | } 40 | } 41 | 42 | \section{\code{drive_oauth_app()}}{ 43 | 44 | 45 | In light of the new \code{\link[gargle:gargle_oauth_client_from_json]{gargle::gargle_oauth_client()}} constructor and class of 46 | the same name, \code{drive_oauth_app()} is being replaced by 47 | \code{\link[=drive_oauth_client]{drive_oauth_client()}}. 48 | } 49 | 50 | \section{\code{drive_example()}}{ 51 | 52 | 53 | This function is defunct. Access example files with \code{\link[=drive_examples_local]{drive_examples_local()}}, 54 | \code{\link[=drive_example_local]{drive_example_local()}}, \code{\link[=drive_examples_remote]{drive_examples_remote()}}, and 55 | \code{\link[=drive_example_remote]{drive_example_remote()}}. 56 | } 57 | 58 | \keyword{internal} 59 | -------------------------------------------------------------------------------- /man/googledrive-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/googledrive-package.R 3 | \docType{package} 4 | \name{googledrive-package} 5 | \alias{googledrive} 6 | \alias{googledrive-package} 7 | \title{googledrive: An Interface to Google Drive} 8 | \description{ 9 | googledrive allows you to interact with files on Google Drive 10 | from R. 11 | 12 | \code{googledrive::drive_find(n_max = 50)} lists up to 50 of the files you see 13 | in \href{https://drive.google.com}{My Drive}. You can expect to be sent to your 14 | browser here, to authenticate yourself and authorize the googledrive 15 | package to deal on your behalf with Google Drive. 16 | 17 | Most functions begin with the prefix \code{drive_}. 18 | 19 | The goal is to allow Drive access that feels similar to Unix file system 20 | utilities, e.g., \code{find}, \code{ls}, \code{mv}, \code{cp}, \code{mkdir}, and \code{rm}. 21 | 22 | The metadata for one or more Drive files is held in a \code{\link{dribble}}, a "Drive 23 | tibble". This is a data frame with one row per file. A dribble is returned 24 | (and accepted) by almost every function in googledrive. It is designed to 25 | give people what they want (file name), track what the API wants (file id), 26 | and to hold the metadata needed for general file operations. 27 | 28 | googledrive is "pipe-friendly" and, in fact, re-exports \verb{\%>\%}, but does not 29 | require its use. 30 | 31 | Please see the googledrive website for full documentation: 32 | \itemize{ 33 | \item \url{https://googledrive.tidyverse.org/index.html} 34 | } 35 | 36 | In addition to function-specific help, there are several articles which are 37 | indexed here: 38 | \itemize{ 39 | \item \href{https://googledrive.tidyverse.org/articles/index.html}{Article index} 40 | } 41 | } 42 | \seealso{ 43 | Useful links: 44 | \itemize{ 45 | \item \url{https://googledrive.tidyverse.org} 46 | \item \url{https://github.com/tidyverse/googledrive} 47 | \item Report bugs at \url{https://github.com/tidyverse/googledrive/issues} 48 | } 49 | 50 | } 51 | \author{ 52 | \strong{Maintainer}: Jennifer Bryan \email{jenny@posit.co} (\href{https://orcid.org/0000-0002-6983-2759}{ORCID}) 53 | 54 | Authors: 55 | \itemize{ 56 | \item Lucy D'Agostino McGowan 57 | } 58 | 59 | Other contributors: 60 | \itemize{ 61 | \item Posit Software, PBC [copyright holder, funder] 62 | } 63 | 64 | } 65 | \keyword{internal} 66 | -------------------------------------------------------------------------------- /man/pipe.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils-pipe.R 3 | \name{\%>\%} 4 | \alias{\%>\%} 5 | \title{Pipe operator} 6 | \usage{ 7 | lhs \%>\% rhs 8 | } 9 | \description{ 10 | See \code{magrittr::\link[magrittr]{\%>\%}} for details. 11 | } 12 | \keyword{internal} 13 | -------------------------------------------------------------------------------- /man/shared_drive_create.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/shared_drive_create.R 3 | \name{shared_drive_create} 4 | \alias{shared_drive_create} 5 | \title{Create a new shared drive} 6 | \usage{ 7 | shared_drive_create(name) 8 | } 9 | \arguments{ 10 | \item{name}{Character. Name of the new shared drive. Must be non-empty and not 11 | entirely whitespace.} 12 | } 13 | \value{ 14 | An object of class \code{\link{dribble}}, a tibble with one row per shared drive. 15 | } 16 | \description{ 17 | A shared drive supports files owned by an organization rather than an 18 | individual user. Shared drives follow different sharing and ownership models 19 | from a specific user's "My Drive". Shared drives are the successors to the 20 | earlier concept of Team Drives. Learn more about \link[=shared_drives]{shared drives}. 21 | } 22 | \examples{ 23 | \dontrun{ 24 | shared_drive_create("my-awesome-shared-drive") 25 | 26 | # Clean up 27 | shared_drive_rm("my-awesome-shared-drive") 28 | } 29 | } 30 | \seealso{ 31 | Wraps the \code{drives.create} endpoint: 32 | \itemize{ 33 | \item \url{https://developers.google.com/drive/api/v3/reference/drives/create} 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /man/shared_drive_find.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/shared_drive_find.R 3 | \name{shared_drive_find} 4 | \alias{shared_drive_find} 5 | \title{Find shared drives} 6 | \usage{ 7 | shared_drive_find(pattern = NULL, n_max = Inf, ...) 8 | } 9 | \arguments{ 10 | \item{pattern}{Character. If provided, only the items whose names match this 11 | regular expression are returned. This is implemented locally on the results 12 | returned by the API.} 13 | 14 | \item{n_max}{Integer. An upper bound on the number of items to return. This 15 | applies to the results requested from the API, which may be further 16 | filtered locally, via the \code{pattern} argument.} 17 | 18 | \item{...}{Other parameters to pass along in the request, such as \code{pageSize} 19 | or \code{useDomainAdminAccess}.} 20 | } 21 | \value{ 22 | An object of class \code{\link{dribble}}, a tibble with one row per shared drive. 23 | } 24 | \description{ 25 | This is the closest googledrive function to what you get from 26 | visiting \url{https://drive.google.com} and clicking "Shared drives". 27 | 28 | A shared drive supports files owned by an organization rather than an 29 | individual user. Shared drives follow different sharing and ownership models 30 | from a specific user's "My Drive". Shared drives are the successors to the 31 | earlier concept of Team Drives. Learn more about \link[=shared_drives]{shared drives}. 32 | } 33 | \examples{ 34 | \dontrun{ 35 | shared_drive_find() 36 | } 37 | } 38 | \seealso{ 39 | Wraps the \code{drives.list} endpoint: 40 | \itemize{ 41 | \item \url{https://developers.google.com/drive/api/v3/reference/drives/list} 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /man/shared_drive_get.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/shared_drive_get.R 3 | \name{shared_drive_get} 4 | \alias{shared_drive_get} 5 | \title{Get shared drives by name or id} 6 | \usage{ 7 | shared_drive_get(name = NULL, id = NULL) 8 | } 9 | \arguments{ 10 | \item{name}{Character vector of names. A character vector marked with 11 | \code{\link[=as_id]{as_id()}} is treated as if it was provided via the \code{id} argument.} 12 | 13 | \item{id}{Character vector of shared drive ids or URLs (it is first processed 14 | with \code{\link[=as_id]{as_id()}}). If both \code{name} and \code{id} are non-\code{NULL}, \code{id} is silently 15 | ignored.} 16 | } 17 | \value{ 18 | An object of class \code{\link{dribble}}, a tibble with one row per shared drive. 19 | } 20 | \description{ 21 | Retrieve metadata for shared drives specified by name or id. Note that Google 22 | Drive does NOT behave like your local file system: 23 | \itemize{ 24 | \item You can get zero, one, or more shared drives back for each name! Shared 25 | drive names need not be unique. 26 | } 27 | 28 | A shared drive supports files owned by an organization rather than an 29 | individual user. Shared drives follow different sharing and ownership models 30 | from a specific user's "My Drive". Shared drives are the successors to the 31 | earlier concept of Team Drives. Learn more about \link[=shared_drives]{shared drives}. 32 | } 33 | \examples{ 34 | \dontrun{ 35 | shared_drive_get("my-awesome-shared-drive") 36 | shared_drive_get(c("apple", "orange", "banana")) 37 | shared_drive_get(as_id("KCmiHLXUk9PVA-0AJNG")) 38 | shared_drive_get(as_id("https://drive.google.com/drive/u/0/folders/KCmiHLXUk9PVA-0AJNG")) 39 | shared_drive_get(id = "KCmiHLXUk9PVA-0AJNG") 40 | shared_drive_get(id = "https://drive.google.com/drive/u/0/folders/KCmiHLXUk9PVA-0AJNG") 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /man/shared_drive_rm.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/shared_drive_rm.R 3 | \name{shared_drive_rm} 4 | \alias{shared_drive_rm} 5 | \title{Delete shared drives} 6 | \usage{ 7 | shared_drive_rm(drive = NULL) 8 | } 9 | \arguments{ 10 | \item{drive}{Anything that identifies the shared drive(s) of interest. Can 11 | be a character vector of names, a character vector of file ids or URLs 12 | marked with \code{\link[=as_id]{as_id()}}, or a \code{\link{dribble}} consisting only of shared drives.} 13 | } 14 | \value{ 15 | Logical vector, indicating whether the delete succeeded. 16 | } 17 | \description{ 18 | A shared drive supports files owned by an organization rather than an 19 | individual user. Shared drives follow different sharing and ownership models 20 | from a specific user's "My Drive". Shared drives are the successors to the 21 | earlier concept of Team Drives. Learn more about \link[=shared_drives]{shared drives}. 22 | } 23 | \examples{ 24 | \dontrun{ 25 | # Create shared drives to remove in various ways 26 | shared_drive_create("testdrive-01") 27 | sd02 <- shared_drive_create("testdrive-02") 28 | shared_drive_create("testdrive-03") 29 | sd04 <- shared_drive_create("testdrive-04") 30 | 31 | # remove by name 32 | shared_drive_rm("testdrive-01") 33 | # remove by id 34 | shared_drive_rm(as_id(sd02)) 35 | # remove by URL (or, rather, id found in URL) 36 | shared_drive_rm(as_id("https://drive.google.com/drive/u/0/folders/Q5DqUk9PVA")) 37 | # remove by dribble 38 | shared_drive_rm(sd04) 39 | } 40 | } 41 | \seealso{ 42 | Wraps the \code{drives.delete} endpoint: 43 | \itemize{ 44 | \item \url{https://developers.google.com/drive/api/v3/reference/drives/delete} 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /man/shared_drive_update.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/shared_drive_update.R 3 | \name{shared_drive_update} 4 | \alias{shared_drive_update} 5 | \title{Update a shared drive} 6 | \usage{ 7 | shared_drive_update(shared_drive, ...) 8 | } 9 | \arguments{ 10 | \item{shared_drive}{Anything that identifies one specific shared drive: its 11 | name, its id or URL marked with \code{\link[=as_id]{as_id()}}, or a \code{\link{dribble}}. The value 12 | provided to \code{shared_drive} is pre-processed with \code{\link[=as_shared_drive]{as_shared_drive()}}. Read 13 | more about \link[=shared_drives]{shared drives}.} 14 | 15 | \item{...}{Properties to set in \code{name = value} form. See the "Request 16 | body" section of the Drive API docs for this endpoint.} 17 | } 18 | \value{ 19 | An object of class \code{\link{dribble}}, a tibble with one row per shared drive. 20 | } 21 | \description{ 22 | Update the metadata of an existing shared drive, e.g. its background image or 23 | theme. 24 | 25 | A shared drive supports files owned by an organization rather than an 26 | individual user. Shared drives follow different sharing and ownership models 27 | from a specific user's "My Drive". Shared drives are the successors to the 28 | earlier concept of Team Drives. Learn more about \link[=shared_drives]{shared drives}. 29 | } 30 | \examples{ 31 | \dontrun{ 32 | # create a shared drive 33 | sd <- shared_drive_create("I love themes!") 34 | 35 | # see the themes available to you 36 | themes <- drive_about()$driveThemes 37 | purrr::map_chr(themes, "id") 38 | 39 | # cycle through various themes for this shared drive 40 | sd <- shared_drive_update(sd, themeId = "bok_choy") 41 | sd <- shared_drive_update(sd, themeId = "cocktails") 42 | 43 | # Clean up 44 | shared_drive_rm(sd) 45 | } 46 | } 47 | \seealso{ 48 | Wraps the \code{drives.update} endpoint: 49 | \itemize{ 50 | \item \url{https://developers.google.com/drive/api/v3/reference/drives/update} 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tidyverse/googledrive/f806c49e62b34fc0150a7bd67fde1885ae479b9e/pkgdown/favicon/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tidyverse/googledrive/f806c49e62b34fc0150a7bd67fde1885ae479b9e/pkgdown/favicon/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tidyverse/googledrive/f806c49e62b34fc0150a7bd67fde1885ae479b9e/pkgdown/favicon/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tidyverse/googledrive/f806c49e62b34fc0150a7bd67fde1885ae479b9e/pkgdown/favicon/apple-touch-icon.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tidyverse/googledrive/f806c49e62b34fc0150a7bd67fde1885ae479b9e/pkgdown/favicon/favicon-16x16.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tidyverse/googledrive/f806c49e62b34fc0150a7bd67fde1885ae479b9e/pkgdown/favicon/favicon-32x32.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tidyverse/googledrive/f806c49e62b34fc0150a7bd67fde1885ae479b9e/pkgdown/favicon/favicon.ico -------------------------------------------------------------------------------- /revdep/.gitignore: -------------------------------------------------------------------------------- 1 | checks 2 | library 3 | checks.noindex 4 | library.noindex 5 | data.sqlite 6 | *.html 7 | cloud.noindex 8 | -------------------------------------------------------------------------------- /revdep/README.md: -------------------------------------------------------------------------------- 1 | # Revdeps 2 | 3 | -------------------------------------------------------------------------------- /revdep/cran.md: -------------------------------------------------------------------------------- 1 | ## revdepcheck results 2 | 3 | We checked 17 reverse dependencies, comparing R CMD check results across CRAN and dev versions of this package. 4 | 5 | * We saw 0 new problems 6 | * We failed to check 0 packages 7 | 8 | -------------------------------------------------------------------------------- /revdep/failures.md: -------------------------------------------------------------------------------- 1 | *Wow, no problems at all. :)* -------------------------------------------------------------------------------- /revdep/problems.md: -------------------------------------------------------------------------------- 1 | *Wow, no problems at all. :)* -------------------------------------------------------------------------------- /tests/spelling.R: -------------------------------------------------------------------------------- 1 | if (requireNamespace("spelling", quietly = TRUE)) { 2 | spelling::spell_check_test( 3 | vignettes = TRUE, error = FALSE, 4 | skip_on_cran = TRUE 5 | ) 6 | } 7 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(googledrive) 3 | 4 | test_check("googledrive") 5 | -------------------------------------------------------------------------------- /tests/testthat/.gitignore: -------------------------------------------------------------------------------- 1 | .httr-oauth 2 | testing-token.rds 3 | .Rapp.history 4 | all-test-clean.* 5 | all-test-setup.* 6 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/deprecated.md: -------------------------------------------------------------------------------- 1 | # drive_auth_config() is deprecated 2 | 3 | Code 4 | drive_auth_config() 5 | Condition 6 | Error: 7 | ! `drive_auth_config()` was deprecated in googledrive 1.0.0 and is now defunct. 8 | i Use `drive_auth_configure()` to configure your own OAuth client or API key. 9 | i Use `drive_deauth()` to go into a de-authorized state. 10 | i Use `drive_oauth_client()` to retrieve a user-configured client, if it exists. 11 | i Use `drive_api_key()` to retrieve a user-configured API key, if it exists. 12 | 13 | # drive_oauth_app() is deprecated 14 | 15 | Code 16 | absorb <- drive_oauth_app() 17 | Condition 18 | Warning: 19 | `drive_oauth_app()` was deprecated in googledrive 2.1.0. 20 | i Please use `drive_oauth_client()` instead. 21 | 22 | # drive_auth_configure(app =) is deprecated in favor of client 23 | 24 | Code 25 | drive_auth_configure(app = client) 26 | Condition 27 | Warning: 28 | The `app` argument of `drive_auth_configure()` is deprecated as of googledrive 2.1.0. 29 | i Please use the `client` argument instead. 30 | 31 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/drive_auth.md: -------------------------------------------------------------------------------- 1 | # drive_auth_configure works 2 | 3 | Code 4 | drive_auth_configure(client = gargle::gargle_client(), path = "PATH") 5 | Condition 6 | Error in `drive_auth_configure()`: 7 | ! Must supply exactly one of `client` or `path`, not both 8 | 9 | # drive_scopes() reveals Drive scopes 10 | 11 | Code 12 | drive_scopes() 13 | Output 14 | drive 15 | "https://www.googleapis.com/auth/drive" 16 | full 17 | "https://www.googleapis.com/auth/drive" 18 | drive.readonly 19 | "https://www.googleapis.com/auth/drive.readonly" 20 | drive.file 21 | "https://www.googleapis.com/auth/drive.file" 22 | drive.appdata 23 | "https://www.googleapis.com/auth/drive.appdata" 24 | drive.metadata 25 | "https://www.googleapis.com/auth/drive.metadata" 26 | drive.metadata.readonly 27 | "https://www.googleapis.com/auth/drive.metadata.readonly" 28 | drive.photos.readonly 29 | "https://www.googleapis.com/auth/drive.photos.readonly" 30 | drive.scripts 31 | "https://www.googleapis.com/auth/drive.scripts" 32 | 33 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/drive_cp.md: -------------------------------------------------------------------------------- 1 | # drive_cp() can copy file in place 2 | 3 | Code 4 | write_utf8(drive_cp_message) 5 | Output 6 | Original file: 7 | * 'i-am-a-file-TEST-drive_cp' 8 | Copied to file: 9 | * '{cp_name}' 10 | 11 | # drive_cp() can copy a file into a different folder 12 | 13 | Code 14 | write_utf8(drive_cp_message) 15 | Output 16 | Original file: 17 | * 'i-am-a-file-TEST-drive_cp' 18 | Copied to file: 19 | * 'i-am-a-folder-TEST-drive_cp/{cp_name}' 20 | 21 | # drive_cp() doesn't tolerate ambiguity in `path` 22 | 23 | Code 24 | drive_cp(file, nm_("i-am-a-folder")) 25 | Condition 26 | Error in `confirm_clear_path()`: 27 | ! Unclear if `path` specifies parent folder or full path to the new file, including its name. 28 | See `?as_dribble()` for advice on how to make this clear. 29 | 30 | # drive_cp() errors if asked to copy a folder 31 | 32 | Code 33 | drive_cp(nm_("i-am-a-folder")) 34 | Condition 35 | Error in `drive_cp()`: 36 | ! The Drive API does not copy folders or shared drives. 37 | 38 | # drive_cp() takes name, assumes path is folder if both are specified 39 | 40 | Code 41 | write_utf8(drive_cp_message) 42 | Output 43 | Original file: 44 | * 'i-am-a-file-TEST-drive_cp' 45 | Copied to file: 46 | * 'i-am-a-folder-TEST-drive_cp/{cp_name}' 47 | 48 | --- 49 | 50 | Code 51 | file_cp <- drive_cp(nm_("i-am-a-file"), path = nm_("file-name"), name = nm_( 52 | "file-name")) 53 | Condition 54 | Error in `as_parent()`: 55 | ! Parent specified via `path` is invalid: 56 | x Does not exist. 57 | 58 | --- 59 | 60 | Code 61 | file_cp <- drive_cp(nm_("i-am-a-file"), append_slash(nm_("not-unique-folder"))) 62 | Condition 63 | Error in `as_parent()`: 64 | ! Parent specified via `path` is invalid: 65 | x Doesn't uniquely identify exactly one folder or shared drive. 66 | 67 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/drive_create.md: -------------------------------------------------------------------------------- 1 | # drive_create() errors for bad input (before hitting Drive API) 2 | 3 | Code 4 | drive_create() 5 | Condition 6 | Error in `drive_create()`: 7 | ! `name` is absent but must be supplied. 8 | 9 | --- 10 | 11 | Code 12 | drive_create(letters) 13 | Condition 14 | Error in `drive_create()`: 15 | ! is_string(name) is not TRUE 16 | 17 | # drive_create() errors if parent path does not exist 18 | 19 | Code 20 | drive_create("a", path = "qweruiop") 21 | Condition 22 | Error in `as_parent()`: 23 | ! Parent specified via `path` is invalid: 24 | x Does not exist. 25 | 26 | # drive_create() errors if parent exists but is not a folder 27 | 28 | Code 29 | drive_create("a", path = x) 30 | Condition 31 | Error in `as_parent()`: 32 | ! Parent specified via `path` is invalid: 33 | x Is neither a folder nor a shared drive. 34 | 35 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/drive_download.md: -------------------------------------------------------------------------------- 1 | # drive_download() won't overwrite existing file 2 | 3 | Code 4 | withr::with_dir(tmpdir, drive_download(dribble(), path = precious_filepath)) 5 | Condition 6 | Error in `drive_download()`: 7 | ! Local `path` already exists and overwrite is `FALSE`: 8 | * 'precious-TEST-drive_download.txt' 9 | 10 | # drive_download() downloads a file and adds local_path column 11 | 12 | Code 13 | write_utf8(drive_download_message) 14 | Output 15 | File downloaded: 16 | * '{file_to_download}' 17 | Saved locally as: 18 | * '{download_filepath}' 19 | 20 | # drive_download() errors if file does not exist on Drive 21 | 22 | Code 23 | drive_download(nm_("this-should-not-exist")) 24 | Condition 25 | Error in `confirm_single_file()`: 26 | ! `file` does not identify at least one Drive file. 27 | 28 | # drive_download() converts with explicit `type` 29 | 30 | Code 31 | write_utf8(drive_download_message) 32 | Output 33 | File downloaded: 34 | * '{file_to_download}' 35 | Saved locally as: 36 | * '{download_filename}' 37 | 38 | # drive_download() converts with type implicit in `path` 39 | 40 | Code 41 | write_utf8(drive_download_message) 42 | Output 43 | File downloaded: 44 | * '{file_to_download}' 45 | Saved locally as: 46 | * '{download_filename}' 47 | 48 | # drive_download() converts using default MIME type, if necessary 49 | 50 | Code 51 | write_utf8(drive_download_message) 52 | Output 53 | File downloaded: 54 | * '{file_to_download}' 55 | Saved locally as: 56 | * '{download_filename}' 57 | 58 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/drive_examples.md: -------------------------------------------------------------------------------- 1 | # drive_example_remote() errors when >1 match 2 | 3 | Code 4 | drive_example_remote("chicken") 5 | Condition 6 | Error in `one_file()`: 7 | ! Found multiple matching remote files: 8 | * 'chicken_doc' 9 | * 'chicken_sheet' 10 | * 'chicken.csv' 11 | * 'chicken.jpg' 12 | * 'chicken.pdf' 13 | * 'chicken.txt' 14 | i Make the `matches` regular expression more specific. 15 | 16 | # drive_example_local() errors when >1 match 17 | 18 | Code 19 | drive_example_local("chicken") 20 | Condition 21 | Error in `one_file()`: 22 | ! Found multiple matching local files: 23 | * 'chicken.csv' 24 | * 'chicken.jpg' 25 | * 'chicken.pdf' 26 | * 'chicken.txt' 27 | i Make the `matches` regular expression more specific. 28 | 29 | # drive_examples_local() errors when no match 30 | 31 | Code 32 | drive_examples_local("platypus") 33 | Condition 34 | Error in `many_files()`: 35 | ! Can't find a local example file with a name that matches "platypus". 36 | 37 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/drive_fields.md: -------------------------------------------------------------------------------- 1 | # drive_fields() admits it only knows about Files fields 2 | 3 | Code 4 | out <- drive_fields(x, resource = "foo") 5 | Message 6 | ! Currently only fields for the 'files' resource can be checked for validity. 7 | Nothing done. 8 | 9 | # drive_fields() detects bad fields 10 | 11 | Code 12 | out <- drive_fields(c("name", "parents", "ownedByMe", "pancakes!")) 13 | Condition 14 | Warning: 15 | Omitting fields that are not recognized as part of the Files resource: 16 | * 'pancakes!' 17 | 18 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/drive_find.md: -------------------------------------------------------------------------------- 1 | # drive_find() errors for nonsense in `n_max` 2 | 3 | Code 4 | drive_find(n_max = "a") 5 | Condition 6 | Error in `drive_find()`: 7 | ! is.numeric(n_max) is not TRUE 8 | 9 | --- 10 | 11 | Code 12 | drive_find(n_max = 1:3) 13 | Condition 14 | Error in `drive_find()`: 15 | ! length(n_max) == 1 is not TRUE 16 | 17 | --- 18 | 19 | Code 20 | drive_find(n_max = -2) 21 | Condition 22 | Error in `drive_find()`: 23 | ! n_max >= 0 is not TRUE 24 | 25 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/drive_get.md: -------------------------------------------------------------------------------- 1 | # drive_get() 'no input' edge cases 2 | 3 | Code 4 | drive_get(id = NA_character_) 5 | Condition 6 | Error in `map()`: 7 | i In index: 1. 8 | Caused by error in `.f()`: 9 | ! Can't `drive_get()` a file when `id` is `NA`. 10 | 11 | --- 12 | 13 | Code 14 | drive_get(id = "") 15 | Condition 16 | Error in `validate_drive_id()`: 17 | ! A must match this regular expression: `^[a-zA-Z0-9_-]+$` 18 | Invalid input: 19 | x '""' 20 | 21 | --- 22 | 23 | Code 24 | dat <- drive_get("") 25 | Message 26 | ! Problem with 1 path: path is empty string 27 | ! No path resolved to exactly 1 file. 28 | 29 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/drive_ls.md: -------------------------------------------------------------------------------- 1 | # drive_ls() errors if `path` does not exist 2 | 3 | Code 4 | drive_ls(nm_("this-should-not-exist")) 5 | Condition 6 | Error in `as_parent()`: 7 | ! Parent specified via `path` is invalid: 8 | x Does not exist. 9 | 10 | # drive_ls() list contents of the target of a folder shortcut 11 | 12 | Code 13 | write_utf8(drive_ls_message) 14 | Output 15 | i Parent specified via `path` is a shortcut; resolving to its target folder 16 | i Resolved 1 shortcut found in 1 file: 17 | * '{shortcut_name}' -> '{target_name}' 18 | 19 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/drive_mime_type.md: -------------------------------------------------------------------------------- 1 | # drive_mime_type() errors for invalid input 2 | 3 | Code 4 | drive_mime_type(1) 5 | Condition 6 | Error in `drive_mime_type()`: 7 | ! `type` must be character. 8 | 9 | --- 10 | 11 | Code 12 | drive_mime_type(dribble()) 13 | Condition 14 | Error in `drive_mime_type()`: 15 | ! `type` must be character. 16 | 17 | # drive_mime_type() errors for single unrecognized input 18 | 19 | Code 20 | drive_mime_type("nonsense") 21 | Condition 22 | Error in `drive_mime_type()`: 23 | ! Unrecognized `type`: 24 | x 'nonsense' 25 | 26 | # drive_extension() errors for invalid input 27 | 28 | Code 29 | drive_extension(1) 30 | Condition 31 | Error in `drive_extension()`: 32 | ! is.character(type) is not TRUE 33 | 34 | --- 35 | 36 | Code 37 | drive_extension(dribble()) 38 | Condition 39 | Error in `drive_extension()`: 40 | ! is.character(type) is not TRUE 41 | 42 | # drive_extension() errors for single unrecognized input 43 | 44 | Code 45 | drive_extension("nonsense") 46 | Condition 47 | Error in `drive_mime_type()`: 48 | ! Unrecognized `type`: 49 | x 'nonsense' 50 | 51 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/drive_mv.md: -------------------------------------------------------------------------------- 1 | # drive_mv() can rename file 2 | 3 | Code 4 | write_utf8(drive_mv_message) 5 | Output 6 | Original file: 7 | * '{name_1}' 8 | Has been renamed: 9 | * '{name_2}' 10 | 11 | # drive_mv() can move a file into a folder given as path 12 | 13 | Code 14 | write_utf8(drive_mv_message) 15 | Output 16 | Original file: 17 | * '{mv_name}' 18 | Has been moved: 19 | * 'move-files-into-me-TEST-drive_mv/{mv_name}' 20 | 21 | # drive_mv() can move a file into a folder given as dribble 22 | 23 | Code 24 | write_utf8(drive_mv_message) 25 | Output 26 | Original file: 27 | * '{mv_name}' 28 | Has been moved: 29 | * 'move-files-into-me-TEST-drive_mv/{mv_name}' 30 | 31 | # drive_mv() can rename and move, using `path` and `name` 32 | 33 | Code 34 | write_utf8(drive_mv_message) 35 | Output 36 | Original file: 37 | * '{name_1}' 38 | Has been renamed and moved: 39 | * 'move-files-into-me-TEST-drive_mv/{name_2}' 40 | 41 | # drive_mv() can rename and move, using `path` only 42 | 43 | Code 44 | write_utf8(drive_mv_message) 45 | Output 46 | Original file: 47 | * '{name_1}' 48 | Has been renamed and moved: 49 | * 'move-files-into-me-TEST-drive_mv/{name_2}' 50 | 51 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/drive_publish.md: -------------------------------------------------------------------------------- 1 | # drive_publish() fails for non-native file type 2 | 3 | Code 4 | drive_publish(drive_pdf) 5 | Condition 6 | Error in `drive_change_publish()`: 7 | ! Only native Google files can be published. 8 | `file` includes a file with non-native MIME type 9 | * 'foo_pdf-TEST-drive_publish': 'application/pdf' 10 | i You can use `drive_share()` to change a file's sharing permissions. 11 | 12 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/drive_put.md: -------------------------------------------------------------------------------- 1 | # drive_put() works 2 | 3 | Code 4 | write_utf8(first_put) 5 | Output 6 | i No pre-existing Drive file at this path. Calling `drive_upload()`. 7 | Local file: 8 | * '{local_file}' 9 | Uploaded into Drive file: 10 | * '{put_file}' 11 | With MIME type: 12 | * 'text/plain' 13 | 14 | --- 15 | 16 | Code 17 | write_utf8(second_put) 18 | Output 19 | i A Drive file already exists at this path. Calling `drive_update()`. 20 | File updated: 21 | * '{put_file}' 22 | 23 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/drive_reveal.md: -------------------------------------------------------------------------------- 1 | # drive_reveal() works 2 | 3 | Code 4 | print(out <- drive_reveal(dat, "starred")[c("name", "starred")]) 5 | Output 6 | # A tibble: 3 x 2 7 | name starred 8 | 9 | 1 i-am-a-google-doc-TEST-drive_reveal FALSE 10 | 2 i-have-a-description-TEST-drive_reveal FALSE 11 | 3 i-am-starred-TEST-drive_reveal TRUE 12 | 13 | --- 14 | 15 | Code 16 | print(out <- drive_reveal(dat, "description")[c("name", "description")]) 17 | Output 18 | # A tibble: 3 x 2 19 | name description 20 | 21 | 1 i-am-a-google-doc-TEST-drive_reveal 22 | 2 i-have-a-description-TEST-drive_reveal description! 23 | 3 i-am-starred-TEST-drive_reveal 24 | 25 | --- 26 | 27 | Code 28 | print(out <- drive_reveal(dat, "mimeType")[c("name", "mime_type")]) 29 | Output 30 | # A tibble: 3 x 2 31 | name mime_type 32 | 33 | 1 i-am-a-google-doc-TEST-drive_reveal application/vnd.google-apps.document 34 | 2 i-have-a-description-TEST-drive_reveal text/plain 35 | 3 i-am-starred-TEST-drive_reveal text/plain 36 | 37 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/drive_share.md: -------------------------------------------------------------------------------- 1 | # drive_share() errors for invalid `role` or `type` 2 | 3 | Code 4 | drive_share(dribble(), role = "chef") 5 | Condition 6 | Error in `match.arg()`: 7 | ! 'arg' should be one of "reader", "commenter", "writer", "fileOrganizer", "owner", "organizer" 8 | 9 | --- 10 | 11 | Code 12 | drive_share(dribble(), type = "pet") 13 | Condition 14 | Error in `match.arg()`: 15 | ! 'arg' should be one of "user", "group", "domain", "anyone" 16 | 17 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/drive_update.md: -------------------------------------------------------------------------------- 1 | # drive_update() errors if local media does not exist 2 | 3 | Code 4 | drive_update(dribble(), "nope123") 5 | Condition 6 | Error in `drive_update()`: 7 | ! No file exists at the local `media` path: 8 | x 'nope123' 9 | 10 | # drive_update() informatively errors if the path does not exist 11 | 12 | Code 13 | drive_update(nm_("does-not-exist"), system.file("DESCRIPTION")) 14 | Condition 15 | Error in `confirm_single_file()`: 16 | ! `file` does not identify at least one Drive file. 17 | 18 | # drive_update() informatively errors if the path is not unique 19 | 20 | Code 21 | drive_update(nm_("not-unique"), system.file("DESCRIPTION")) 22 | Condition 23 | Error in `confirm_single_file()`: 24 | ! `file` identifies more than one Drive file. 25 | 26 | # no op if no media, no metadata 27 | 28 | Code 29 | out <- drive_update(nm_("update-fodder")) 30 | Message 31 | ! No updates specified. 32 | 33 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/drive_upload.md: -------------------------------------------------------------------------------- 1 | # drive_upload() detects non-existent file 2 | 3 | Code 4 | drive_upload("no-such-file", "File does not exist") 5 | Condition 6 | Error in `drive_upload()`: 7 | ! No file exists at the local `media` path: 8 | x 'no-such-file' 9 | 10 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/request_generate.md: -------------------------------------------------------------------------------- 1 | # request_generate() errors for unrecognized parameters 2 | 3 | Code 4 | (expect_error(request_generate(endpoint = "drive.files.list", params = params, 5 | token = NULL), class = "gargle_error_bad_params")) 6 | Output 7 | 8 | Error in `gargle::request_develop()`: 9 | ! These parameters are unknown: 10 | x 'chicken' 11 | x 'bunny' 12 | i API endpoint: 'drive.files.list' 13 | 14 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/shared_drives.md: -------------------------------------------------------------------------------- 1 | # new_corpus() checks type and length, if not-NULL 2 | 3 | Code 4 | new_corpus(driveId = c("1", "2")) 5 | Condition 6 | Error in `new_corpus()`: 7 | ! length(driveId) == 1 is not TRUE 8 | 9 | --- 10 | 11 | Code 12 | new_corpus(corpora = c("a", "b")) 13 | Condition 14 | Error in `new_corpus()`: 15 | ! is_string(corpora) is not TRUE 16 | 17 | --- 18 | 19 | Code 20 | new_corpus(includeItemsFromAllDrives = c(TRUE, FALSE)) 21 | Condition 22 | Error in `new_corpus()`: 23 | ! length(includeItemsFromAllDrives) == 1 is not TRUE 24 | 25 | # `corpora` is checked for validity 26 | 27 | Code 28 | shared_drive_params(corpora = "foo") 29 | Condition 30 | Error in `validate_corpora()`: 31 | ! Invalid value for `corpus`: 32 | x 'foo' 33 | These are the only acceptable values: 34 | * 'user' 35 | * 'drive' 36 | * 'allDrives' 37 | * 'domain' 38 | 39 | # `corpora = "drive"` requires shared drive specification 40 | 41 | Code 42 | shared_drive_params(corpora = "drive") 43 | Condition 44 | Error in `rationalize_corpus()`: 45 | ! When `corpus = "drive"`, you must also specify the `shared_drive`. 46 | 47 | # `corpora != "drive"` rejects shared drive specification 48 | 49 | Code 50 | shared_drive_params(corpora = "user", driveId = "123") 51 | Condition 52 | Error in `rationalize_corpus()`: 53 | ! When `corpus != "drive"`, you must not specify a `shared_drive`. 54 | 55 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/shortcut.md: -------------------------------------------------------------------------------- 1 | # shortcut_create() works 2 | 3 | Code 4 | write_utf8(shortcut_create_message) 5 | Output 6 | Created Drive file: 7 | * '{sc_name}' 8 | With MIME type: 9 | * 'application/vnd.google-apps.shortcut' 10 | 11 | # shortcut_create() requires `name` to control `overwrite` 12 | 13 | Code 14 | shortcut_create(nm_("top-level-file"), overwrite = FALSE) 15 | Condition 16 | Error in `shortcut_create()`: 17 | ! You must specify the shortcut's `name` in order to specify `overwrite` behaviour. 18 | 19 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/utils-paths.md: -------------------------------------------------------------------------------- 1 | # root_folder() and root_id() work 2 | 3 | Code 4 | root_folder() 5 | Output 6 | # A dribble: 1 x 3 7 | name id drive_resource 8 | 9 | 1 My Drive 0AK935f1rlmIZUk9PVA 10 | 11 | --- 12 | 13 | Code 14 | root_id() 15 | Output 16 | 17 | [1] 0AK935f1rlmIZUk9PVA 18 | 19 | # rootize_path() errors for leading slash 20 | 21 | Code 22 | rootize_path("/") 23 | Condition 24 | Error in `rootize_path()`: 25 | ! googledrive does not allow paths to start with `/` 26 | 27 | # partition_path() fails for bad input 28 | 29 | Code 30 | partition_path(letters) 31 | Condition 32 | Error in `partition_path()`: 33 | ! is_string(path) is not TRUE 34 | 35 | --- 36 | 37 | Code 38 | partition_path(dribble()) 39 | Condition 40 | Error in `partition_path()`: 41 | ! is_string(path) is not TRUE 42 | 43 | --- 44 | 45 | Code 46 | partition_path(as_id("123")) 47 | Condition 48 | Error in `partition_path()`: 49 | ! is_string(path) is not TRUE 50 | 51 | # rationalize_path_name() errors for bad `name`, before hitting API 52 | 53 | Code 54 | rationalize_path_name(name = letters) 55 | Condition 56 | Error in `rationalize_path_name()`: 57 | ! is_string(name) is not TRUE 58 | 59 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/utils-ui.md: -------------------------------------------------------------------------------- 1 | # warn_for_verbose() warns for `verbose = FALSE` w/ good message 2 | 3 | Code 4 | drive_something() 5 | Condition 6 | Warning: 7 | The `verbose` argument of `drive_something()` is deprecated as of googledrive 2.0.0. 8 | i Set `options(googledrive_quiet = TRUE)` to suppress all googledrive messages. 9 | i For finer control, use `local_drive_quiet()` or `with_drive_quiet()`. 10 | i googledrive's `verbose` argument will be removed in the future. 11 | 12 | # warn_for_verbose(FALSE) makes googledrive quiet, in scope 13 | 14 | Code 15 | drive_bullets("chatty before") 16 | Message 17 | chatty before 18 | Code 19 | drive_something() 20 | drive_bullets("chatty after") 21 | Message 22 | chatty after 23 | 24 | -------------------------------------------------------------------------------- /tests/testthat/driver.R: -------------------------------------------------------------------------------- 1 | # this script extracts code from all individual test files to do: 2 | # * test setup = create the files/folders our tests expect to find on Drive 3 | # * test cleanup = delete the above files/folder from Drive 4 | # execute this to get two R scripts: 5 | # * all-test-setup.R 6 | # * all-test-clean.R 7 | 8 | library(purrr) 9 | library(glue) 10 | library(testthat) 11 | 12 | ## grabs code from two chunks: 'nm_fun' and chunk ('clean' or 'setup') 13 | do_one <- function(r_file, chunk) { 14 | knitr::read_chunk(r_file) 15 | out <- c( 16 | knitr:::knit_code$get("nm_fun"), 17 | knitr:::knit_code$get(chunk) 18 | ) 19 | knitr:::knit_code$restore() 20 | if (length(out) == 0) { 21 | return(NULL) 22 | } 23 | c(paste("#' ##", basename(r_file)), out) 24 | } 25 | 26 | test_files <- list.files( 27 | path = test_path(), 28 | pattern = "test-.+\\.R", 29 | full.names = TRUE 30 | ) 31 | 32 | clean_code <- test_files %>% 33 | map(do_one, chunk = "clean") %>% 34 | compact() 35 | setup_code <- test_files %>% 36 | map(do_one, chunk = "setup") %>% 37 | compact() 38 | 39 | header <- " 40 | #' --- 41 | #' title: googledrive test {action} 42 | #' date: '`r format(Sys.time())`' 43 | #' output: html_document 44 | #' --- 45 | 46 | #' This script aggregates the test-related {action} code from all test files. 47 | 48 | #+ setup, include = FALSE, cache = FALSE 49 | knitr::opts_chunk$set(collapse = TRUE, comment = '#>', error = TRUE) 50 | 51 | #+ body 52 | pkgload::load_all(here::here()) 53 | source(here::here('tests', 'testthat', 'helper.R')) 54 | drive_user() 55 | 56 | ## change this to TRUE when you are really ready to do this! 57 | {ACTION} <- FALSE 58 | 59 | " 60 | 61 | writeLines( 62 | c( 63 | glue_data(list(action = "clean", ACTION = "CLEAN"), header), 64 | unlist(clean_code) 65 | ), 66 | test_path("all-test-clean.R") 67 | ) 68 | writeLines( 69 | c( 70 | glue_data(list(action = "setup", ACTION = "SETUP"), header), 71 | unlist(setup_code) 72 | ), 73 | test_path("all-test-setup.R") 74 | ) 75 | -------------------------------------------------------------------------------- /tests/testthat/helper.R: -------------------------------------------------------------------------------- 1 | auth_success <- tryCatch( 2 | drive_auth_testing(), 3 | googledrive_auth_internal_error = function(e) NULL 4 | ) 5 | if (!isTRUE(auth_success)) { 6 | drive_bullets(c( 7 | "!" = "Internal auth failed; calling {.fun drive_deauth}." 8 | )) 9 | drive_deauth() 10 | } 11 | 12 | skip_if_no_token <- function() { 13 | testthat::skip_if_not(drive_has_token(), "No Drive token") 14 | } 15 | 16 | with_mock <- function(..., .parent = parent.frame()) { 17 | mockr::with_mock(..., .parent = .parent, .env = "googledrive") 18 | } 19 | 20 | # usage: 21 | # test_fixture("something.rds") 22 | test_fixture <- function(name) testthat::test_path("test-fixtures", name) 23 | 24 | defer_drive_rm <- function(..., env = parent.frame()) { 25 | withr::defer( 26 | with_drive_quiet(drive_rm(...)), 27 | envir = env 28 | ) 29 | } 30 | 31 | # used to replace volatile filepaths and file ids in snapshot tests 32 | # may eventually be unnecessary, depending on how this works out: 33 | # https://github.com/r-lib/testthat/issues/1345 34 | # @param replace_me Should be a bare symbol that holds a fixed string 35 | scrub_filepath <- function(message, replace_me) { 36 | x <- ensym(replace_me) 37 | gsub(replace_me, paste0("{", as_string(x), "}"), message, fixed = TRUE) 38 | } 39 | 40 | scrub_file_id <- function(message) { 41 | gsub("", "", message, perl = TRUE) 42 | } 43 | 44 | expect_dribble <- function(x) { 45 | expect_s3_class(x, "dribble") 46 | } 47 | 48 | expect_bare_tibble <- function(x) { 49 | expect_s3_class(x, c("tbl_df", "tbl", "data.frame"), exact = TRUE) 50 | } 51 | -------------------------------------------------------------------------------- /tests/testthat/setup-testing.R: -------------------------------------------------------------------------------- 1 | CLEAN <- SETUP <- FALSE 2 | isFALSE <- function(x) identical(x, FALSE) 3 | 4 | with_drive_loud({ 5 | nm_ <- nm_fun("TEST-drive_something", user_run = FALSE) 6 | me_ <- nm_fun("TEST-drive_something") 7 | 8 | drive_bullets(c( 9 | "Test file naming scheme:", 10 | "*" = nm_("foo"), 11 | "*" = me_("foo") 12 | )) 13 | flush.console() 14 | Sys.sleep(1) # without this, the message still gets mixed in w/ test results 15 | }) 16 | -------------------------------------------------------------------------------- /tests/testthat/test-camelCase.R: -------------------------------------------------------------------------------- 1 | test_that("snake_case() works", { 2 | expect_equal(snake_case("name"), "name") 3 | expect_equal(snake_case("drive_resource"), "drive_resource") 4 | 5 | expect_equal(snake_case("mimeType"), "mime_type") 6 | expect_equal(snake_case("viewedByMeTime"), "viewed_by_me_time") 7 | expect_equal(snake_case("md5Checksum"), "md5_checksum") 8 | }) 9 | -------------------------------------------------------------------------------- /tests/testthat/test-deprecated.R: -------------------------------------------------------------------------------- 1 | test_that("drive_auth_config() is deprecated", { 2 | withr::local_options(lifecycle_verbosity = "warning") 3 | expect_snapshot( 4 | error = TRUE, 5 | drive_auth_config() 6 | ) 7 | }) 8 | 9 | test_that("drive_oauth_app() is deprecated", { 10 | withr::local_options(lifecycle_verbosity = "warning") 11 | expect_snapshot(absorb <- drive_oauth_app()) 12 | }) 13 | 14 | test_that("drive_auth_configure(app =) is deprecated in favor of client", { 15 | withr::local_options(lifecycle_verbosity = "warning") 16 | (original_client <- drive_oauth_client()) 17 | withr::defer(drive_auth_configure(client = original_client)) 18 | 19 | client <- gargle::gargle_oauth_client_from_json( 20 | system.file( 21 | "extdata", "client_secret_installed.googleusercontent.com.json", 22 | package = "gargle" 23 | ), 24 | name = "test-client" 25 | ) 26 | expect_snapshot( 27 | drive_auth_configure(app = client) 28 | ) 29 | expect_equal(drive_oauth_client()$name, "test-client") 30 | expect_equal(drive_oauth_client()$id, "abc.apps.googleusercontent.com") 31 | }) 32 | -------------------------------------------------------------------------------- /tests/testthat/test-drive_auth.R: -------------------------------------------------------------------------------- 1 | test_that("drive_auth_configure works", { 2 | old_client <- drive_oauth_client() 3 | old_api_key <- drive_api_key() 4 | withr::defer( 5 | drive_auth_configure(client = old_client, api_key = old_api_key) 6 | ) 7 | 8 | expect_no_error(drive_oauth_client()) 9 | expect_no_error(drive_api_key()) 10 | 11 | expect_snapshot( 12 | drive_auth_configure(client = gargle::gargle_client(), path = "PATH"), 13 | error = TRUE 14 | ) 15 | 16 | drive_auth_configure(client = gargle::gargle_client()) 17 | expect_s3_class(drive_oauth_client(), "gargle_oauth_client") 18 | 19 | drive_auth_configure(path = system.file( 20 | "extdata", "client_secret_installed.googleusercontent.com.json", 21 | package = "gargle" 22 | )) 23 | expect_s3_class(drive_oauth_client(), "gargle_oauth_client") 24 | 25 | drive_auth_configure(client = NULL) 26 | expect_null(drive_oauth_client()) 27 | 28 | drive_auth_configure(api_key = "API_KEY") 29 | expect_identical(drive_api_key(), "API_KEY") 30 | 31 | drive_auth_configure(api_key = NULL) 32 | expect_null(drive_api_key()) 33 | }) 34 | 35 | # drive_scopes() ---- 36 | test_that("drive_scopes() reveals Drive scopes", { 37 | expect_snapshot(drive_scopes()) 38 | }) 39 | 40 | test_that("drive_scopes() substitutes actual scope for short form", { 41 | expect_equal( 42 | drive_scopes(c( 43 | "full", 44 | "drive", 45 | "drive.readonly" 46 | )), 47 | c( 48 | "https://www.googleapis.com/auth/drive", 49 | "https://www.googleapis.com/auth/drive", 50 | "https://www.googleapis.com/auth/drive.readonly" 51 | ) 52 | ) 53 | }) 54 | 55 | test_that("drive_scopes() passes unrecognized scopes through", { 56 | expect_equal( 57 | drive_scopes(c( 58 | "email", 59 | "drive.metadata.readonly", 60 | "https://www.googleapis.com/auth/cloud-platform" 61 | )), 62 | c( 63 | "email", 64 | "https://www.googleapis.com/auth/drive.metadata.readonly", 65 | "https://www.googleapis.com/auth/cloud-platform" 66 | ) 67 | ) 68 | }) 69 | -------------------------------------------------------------------------------- /tests/testthat/test-drive_browse.R: -------------------------------------------------------------------------------- 1 | # ---- other ---- 2 | if (FALSE) { 3 | # how the test file was created 4 | # using shared-drive-capable token ... 5 | files <- drive_find(corpus = "allDrives", n_max = 10) 6 | sds <- shared_drive_find() 7 | x <- vec_rbind(files, sds) 8 | saveRDS(x, test_fixture("mix_of_files_and_teamdrives.rds"), version = 2) 9 | } 10 | 11 | # ---- tests ---- 12 | test_that("drive_link() extracts links for files and Team Drives, alike", { 13 | x <- readRDS(test_fixture("mix_of_files_and_teamdrives.rds")) 14 | links <- drive_link(x) 15 | expect_true(all(grepl("^https://.*\\.google\\.com/", links))) 16 | expect_identical(as_id(links), as_id(x)) 17 | }) 18 | 19 | test_that("drive_browse() passes links through", { 20 | if (interactive()) skip("interactive() is TRUE") 21 | x <- readRDS(test_fixture("mix_of_files_and_teamdrives.rds")) 22 | expect_identical(drive_browse(x), drive_link(x)) 23 | }) 24 | -------------------------------------------------------------------------------- /tests/testthat/test-drive_endpoints.R: -------------------------------------------------------------------------------- 1 | test_that("drive_endpoint(s)() work(s)", { 2 | expect_length(drive_endpoints(), length(.endpoints)) 3 | expect_length(drive_endpoints(c(1, 3, 5)), 3) 4 | nms <- names(drive_endpoints()) 5 | expect_identical(drive_endpoints(c(1, 3, 5)), drive_endpoints(nms[c(1, 3, 5)])) 6 | expect_identical(drive_endpoints(2)[[1]], drive_endpoint(2)) 7 | expect_identical(drive_endpoints(nms[2])[[1]], drive_endpoint(nms[2])) 8 | }) 9 | -------------------------------------------------------------------------------- /tests/testthat/test-drive_examples.R: -------------------------------------------------------------------------------- 1 | test_that("drive_examples_remote() lists the remote example files", { 2 | skip_if_offline() 3 | skip_on_cran() 4 | 5 | dat <- drive_examples_remote() 6 | expect_s3_class(dat, "dribble") 7 | expect_true(nrow(dat) > 0) 8 | 9 | dat <- drive_examples_remote("chicken") 10 | expect_s3_class(dat, "dribble") 11 | expect_true(nrow(dat) > 0) 12 | }) 13 | 14 | test_that("drive_example_remote() errors when >1 match", { 15 | skip_if_offline() 16 | skip_on_cran() 17 | 18 | expect_snapshot( 19 | drive_example_remote("chicken"), 20 | error = TRUE 21 | ) 22 | }) 23 | 24 | test_that("drive_examples_local() lists the local example files", { 25 | all_files <- drive_examples_local() 26 | expect_true(all(file.exists(all_files))) 27 | 28 | chicken_files <- drive_examples_local("chicken") 29 | expect_match(chicken_files, "chicken") 30 | }) 31 | 32 | test_that("drive_example_local() errors when >1 match", { 33 | expect_snapshot( 34 | drive_example_local("chicken"), 35 | error = TRUE 36 | ) 37 | }) 38 | 39 | test_that("drive_examples_local() errors when no match", { 40 | expect_snapshot( 41 | drive_examples_local("platypus"), 42 | error = TRUE 43 | ) 44 | }) 45 | -------------------------------------------------------------------------------- /tests/testthat/test-drive_fields.R: -------------------------------------------------------------------------------- 1 | # ---- tests ---- 2 | test_that("drive_fields() returns nothing, if no input", { 3 | expect_identical(drive_fields(), character()) 4 | }) 5 | 6 | test_that("drive_fields(expose()) returns full tibble of Files fields", { 7 | expect_identical( 8 | drive_fields(expose()), 9 | .drive$files_fields 10 | ) 11 | out <- drive_fields(expose(), resource = "foo") 12 | expect_identical(out, drive_fields(expose())) 13 | }) 14 | 15 | test_that("drive_fields() admits it only knows about Files fields", { 16 | local_drive_loud_and_wide() 17 | 18 | x <- letters[1:6] 19 | expect_snapshot( 20 | out <- drive_fields(x, resource = "foo") 21 | ) 22 | expect_identical(out, x) 23 | }) 24 | 25 | test_that("drive_fields() detects bad fields", { 26 | local_drive_loud_and_wide() 27 | expect_snapshot( 28 | out <- drive_fields(c("name", "parents", "ownedByMe", "pancakes!")) 29 | ) 30 | expect_identical(out, c("name", "parents", "ownedByMe")) 31 | }) 32 | 33 | test_that("prep_fields() concatenates input", { 34 | expect_identical( 35 | prep_fields(letters[1:2]), 36 | "files/a,files/b" 37 | ) 38 | expect_identical( 39 | prep_fields(letters[1:2], resource = NULL), 40 | "a,b" 41 | ) 42 | expect_identical( 43 | prep_fields(letters[1:2], resource = "blah"), 44 | "blah/a,blah/b" 45 | ) 46 | }) 47 | -------------------------------------------------------------------------------- /tests/testthat/test-drive_put.R: -------------------------------------------------------------------------------- 1 | # ---- nm_fun ---- 2 | me_ <- nm_fun("TEST-drive_put") 3 | nm_ <- nm_fun("TEST-drive_put", user_run = FALSE) 4 | 5 | # ---- clean ---- 6 | if (CLEAN) { 7 | drive_trash(c( 8 | # no current need 9 | )) 10 | } 11 | 12 | # ---- setup ---- 13 | if (SETUP) { 14 | # no current need 15 | } 16 | 17 | # ---- tests ---- 18 | 19 | test_that("drive_put() works", { 20 | skip_if_no_token() 21 | skip_if_offline() 22 | 23 | local_file <- tempfile(me_("foo"), fileext = ".txt") 24 | put_file <- basename(local_file) 25 | download_target <- tempfile(me_("download"), fileext = ".txt") 26 | withr::defer({ 27 | unlink(local_file) 28 | unlink(download_target) 29 | }) 30 | defer_drive_rm(drive_find(me_("foo"))) 31 | 32 | write_utf8(c("beginning", "middle"), local_file) 33 | 34 | local_drive_loud_and_wide() 35 | first_put <- capture.output( 36 | original <- drive_put(local_file), 37 | type = "message" 38 | ) 39 | first_put <- first_put %>% 40 | scrub_filepath(local_file) %>% 41 | scrub_filepath(put_file) %>% 42 | scrub_file_id() 43 | expect_snapshot( 44 | write_utf8(first_put) 45 | ) 46 | expect_dribble(original) 47 | 48 | with_drive_quiet( 49 | drive_download(original, path = download_target) 50 | ) 51 | expect_identical( 52 | read_utf8(local_file), 53 | read_utf8(download_target) 54 | ) 55 | 56 | cat("end", file = local_file, sep = "\n", append = TRUE) 57 | 58 | second_put <- capture.output( 59 | second <- drive_put(local_file), 60 | type = "message" 61 | ) 62 | second_put <- second_put %>% 63 | scrub_filepath(put_file) %>% 64 | scrub_file_id() 65 | expect_snapshot( 66 | write_utf8(second_put) 67 | ) 68 | expect_identical(original$id, second$id) 69 | 70 | with_drive_quiet( 71 | drive_download(original, path = download_target, overwrite = TRUE) 72 | ) 73 | expect_identical( 74 | read_utf8(local_file), 75 | read_utf8(download_target) 76 | ) 77 | 78 | with_drive_quiet( 79 | name_collider <- drive_create(basename(local_file)) 80 | ) 81 | 82 | # not easy to convert to snapshot, due to volatile file ids 83 | expect_error( 84 | drive_put(local_file), 85 | "Multiple items" 86 | ) 87 | }) 88 | -------------------------------------------------------------------------------- /tests/testthat/test-drive_read.R: -------------------------------------------------------------------------------- 1 | # ---- nm_fun ---- 2 | nm_ <- nm_fun("TEST-drive_read", user_run = FALSE) 3 | 4 | # ---- clean ---- 5 | if (CLEAN) { 6 | drive_trash(c( 7 | nm_("DESC"), 8 | nm_("chicken_doc"), 9 | nm_("imdb_latin1_csv") 10 | )) 11 | } 12 | 13 | # ---- setup ---- 14 | if (SETUP) { 15 | drive_upload(system.file("DESCRIPTION"), name = nm_("DESC")) 16 | 17 | drive_upload( 18 | drive_example_local("chicken.txt"), 19 | name = nm_("chicken_doc"), 20 | type = "document" 21 | ) 22 | 23 | tfile <- tempfile(fileext = ".csv") 24 | curl::curl_download( 25 | "https://matthew-brett.github.io/cfd2019/data/imdblet_latin.csv", 26 | destfile = tfile 27 | ) 28 | drive_upload(tfile, name = nm_("imdb_latin1_csv")) 29 | } 30 | 31 | # ---- tests ---- 32 | test_that("drive_read_string() extracts text", { 33 | skip_if_no_token() 34 | skip_if_offline() 35 | 36 | suppressMessages( 37 | r_desc <- drive_read_string(nm_("DESC")) 38 | ) 39 | r_desc <- as.list(read.dcf(textConnection(r_desc))[1, ]) 40 | expect_equal(r_desc$Package, "base") 41 | expect_equal(r_desc$Title, "The R Base Package") 42 | }) 43 | 44 | test_that("drive_read_raw() returns bytes", { 45 | skip_if_no_token() 46 | skip_if_offline() 47 | 48 | suppressMessages( 49 | r_desc_raw <- drive_read_raw(nm_("DESC")) 50 | ) 51 | suppressMessages( 52 | r_desc_string <- drive_read_string(nm_("DESC")) 53 | ) 54 | expect_equal(rawToChar(r_desc_raw), r_desc_string) 55 | }) 56 | 57 | test_that("drive_read() works on a native Google file", { 58 | skip_if_no_token() 59 | skip_if_offline() 60 | 61 | suppressMessages( 62 | chicken_poem <- drive_read_string(nm_("chicken_doc"), type = "text/plain") 63 | ) 64 | chicken_poem <- strsplit(chicken_poem, split = "(\r\n|\r|\n)")[[1]] 65 | expect_setequal( 66 | chicken_poem, 67 | read_utf8(drive_example_local("chicken.txt")) 68 | ) 69 | }) 70 | 71 | test_that("drive_read() can handle non UTF-8 input, if informed", { 72 | skip_if_no_token() 73 | skip_if_offline() 74 | 75 | suppressMessages( 76 | imdb <- drive_read_string(nm_("imdb_latin1_csv"), encoding = "latin1") 77 | ) 78 | imdb <- utils::read.csv(text = imdb, stringsAsFactors = FALSE, encoding = "UTF-8") 79 | expect_equal( 80 | names(imdb), 81 | c("Votes", "Rating", "Title", "Year", "Decade") 82 | ) 83 | leon <- "\u004C\u00E9\u006F\u006E" 84 | expect_equal(imdb$Title[[1]], leon) 85 | eight_and_a_half <- "\u0038\u00BD" 86 | expect_equal(imdb$Title[[31]], eight_and_a_half) 87 | }) 88 | -------------------------------------------------------------------------------- /tests/testthat/test-drive_reveal.R: -------------------------------------------------------------------------------- 1 | # ---- nm_fun ---- 2 | nm_ <- nm_fun("TEST-drive_reveal", user_run = FALSE) 3 | 4 | # ---- clean ---- 5 | if (CLEAN) { 6 | drive_trash(c( 7 | nm_("i-am-starred"), 8 | nm_("i-have-a-description"), 9 | nm_("i-am-a-google-doc") 10 | )) 11 | } 12 | 13 | # ---- setup ---- 14 | if (SETUP) { 15 | # some "simple" cases of digging info out of `drive_resource` 16 | f <- drive_example_local("chicken.txt") 17 | drive_upload(f, nm_("i-am-starred"), starred = TRUE) 18 | drive_upload(f, nm_("i-have-a-description"), description = "description!") 19 | drive_upload(f, nm_("i-am-a-google-doc"), type = "document") 20 | } 21 | 22 | # ---- tests ---- 23 | test_that("drive_reveal() works", { 24 | skip_if_no_token() 25 | skip_if_offline() 26 | 27 | dat <- drive_find(nm_("")) 28 | 29 | expect_snapshot( 30 | print(out <- drive_reveal(dat, "starred")[c("name", "starred")]) 31 | ) 32 | expect_true(out$starred[grepl("starred", out$name)]) 33 | 34 | expect_snapshot( 35 | print(out <- drive_reveal(dat, "description")[c("name", "description")]) 36 | ) 37 | expect_equal(out$description[grepl("description", out$name)], "description!") 38 | 39 | expect_snapshot( 40 | print(out <- drive_reveal(dat, "mimeType")[c("name", "mime_type")]) 41 | ) 42 | expect_equal( 43 | out$mime_type[grepl("google-doc", out$name)], 44 | drive_mime_type("document") 45 | ) 46 | }) 47 | 48 | test_that("drive_reveal() can return date-times", { 49 | skip_if_no_token() 50 | skip_if_offline() 51 | 52 | dat <- drive_find(nm_("")) 53 | 54 | out <- drive_reveal(dat, "created_time") 55 | expect_s3_class(out$created_time, "POSIXct") 56 | }) 57 | 58 | test_that("drive_reveal() returns list-column for non-existent `what`", { 59 | skip_if_no_token() 60 | skip_if_offline() 61 | 62 | dat <- drive_find(nm_("")) 63 | 64 | out <- drive_reveal(dat, "i_do_not_exist") 65 | expect_true(all(map_lgl(out$i_do_not_exist, is_null))) 66 | 67 | out <- drive_reveal(dat, "non_existent_time") 68 | expect_true(all(map_lgl(out$non_existent_time, is_null))) 69 | }) 70 | 71 | test_that("drive_reveal() inserts columns, even with 0 rows", { 72 | x <- dribble() 73 | x <- drive_reveal(x, "mime_type") 74 | x <- drive_reveal(x, "starred") 75 | expect_equal( 76 | names(x), 77 | c("name", "starred", "mime_type", "id", "drive_resource") 78 | ) 79 | }) 80 | -------------------------------------------------------------------------------- /tests/testthat/test-drive_rm.R: -------------------------------------------------------------------------------- 1 | # ---- tests ---- 2 | test_that("drive_rm() copes with no input", { 3 | expect_identical(drive_rm(), dribble()) 4 | }) 5 | 6 | test_that("drive_rm() copes when there are no matching files", { 7 | skip_if_no_token() 8 | skip_if_offline() 9 | 10 | expect_identical(drive_rm("non-existent-file-name"), dribble()) 11 | }) 12 | -------------------------------------------------------------------------------- /tests/testthat/test-drive_share.R: -------------------------------------------------------------------------------- 1 | # ---- nm_fun ---- 2 | me_ <- nm_fun("TEST-drive_share") 3 | nm_ <- nm_fun("TEST-drive_share", user_run = FALSE) 4 | 5 | # ---- clean ---- 6 | if (CLEAN) { 7 | drive_trash(c( 8 | nm_("mirrors-to-share"), 9 | nm_("DESC") 10 | )) 11 | } 12 | 13 | # ---- setup ---- 14 | if (SETUP) { 15 | drive_upload(system.file("DESCRIPTION"), nm_("DESC")) 16 | } 17 | 18 | # ---- tests ---- 19 | 20 | test_that("drive_share() errors for invalid `role` or `type`", { 21 | expect_snapshot(drive_share(dribble(), role = "chef"), error = TRUE) 22 | expect_snapshot(drive_share(dribble(), type = "pet"), error = TRUE) 23 | }) 24 | 25 | test_that("drive_share() adds permissions", { 26 | skip_if_no_token() 27 | skip_if_offline() 28 | defer_drive_rm(me_("mirrors-to-share")) 29 | 30 | file <- drive_upload( 31 | file.path(R.home("doc"), "BioC_mirrors.csv"), 32 | name = me_("mirrors-to-share") 33 | ) 34 | expect_false(file$drive_resource[[1]]$shared) 35 | 36 | file <- drive_share(file, role = "commenter", type = "anyone") 37 | expect_true(file$shared) 38 | perms <- file[["permissions_resource"]][[1]][["permissions"]] 39 | expect_setequal(map_chr(perms, "role"), c("owner", "commenter")) 40 | expect_setequal(map_chr(perms, "type"), c("user", "anyone")) 41 | }) 42 | -------------------------------------------------------------------------------- /tests/testthat/test-drive_trash.R: -------------------------------------------------------------------------------- 1 | # ---- nm_fun ---- 2 | me_ <- nm_fun("TEST-drive_trash") 3 | nm_ <- nm_fun("TEST-drive_trash", user_run = FALSE) 4 | 5 | # ---- setup ---- 6 | if (SETUP) { 7 | drive_upload( 8 | system.file("DESCRIPTION"), 9 | nm_("trash-fodder") 10 | ) 11 | } 12 | 13 | # ---- clean ---- 14 | if (CLEAN) { 15 | drive_trash(c( 16 | nm_("trash-fodder"), 17 | me_("trashee-1"), 18 | me_("trashee-2") 19 | )) 20 | } 21 | 22 | # ---- tests ---- 23 | test_that("drive_trash() moves files to trash and drive_untrash() undoes", { 24 | skip_if_no_token() 25 | skip_if_offline() 26 | defer_drive_rm(drive_find(me_("trashee-[12]"))) 27 | 28 | trashee1 <- drive_cp(nm_("trash-fodder"), name = me_("trashee-1")) 29 | trashee2 <- drive_cp(nm_("trash-fodder"), name = me_("trashee-2")) 30 | 31 | out <- drive_trash(c(me_("trashee-1"), me_("trashee-2"))) 32 | expect_dribble(out) 33 | expect_setequal(out$name, c(me_("trashee-1"), me_("trashee-2"))) 34 | expect_true(all(drive_reveal(out, "trashed")[["trashed"]])) 35 | 36 | out <- drive_untrash(c(me_("trashee-1"), me_("trashee-2"))) 37 | expect_dribble(out) 38 | expect_setequal(out$name, c(me_("trashee-1"), me_("trashee-2"))) 39 | expect_false(any(drive_reveal(out, "trashed")[["trashed"]])) 40 | }) 41 | -------------------------------------------------------------------------------- /tests/testthat/test-drive_update.R: -------------------------------------------------------------------------------- 1 | # ---- nm_fun ---- 2 | me_ <- nm_fun("TEST-drive_update") 3 | nm_ <- nm_fun("TEST-drive_update", user_run = FALSE) 4 | 5 | # ---- clean ---- 6 | if (CLEAN) { 7 | drive_trash(c( 8 | nm_("update-fodder"), 9 | nm_("not-unique"), 10 | nm_("does-not-exist") 11 | )) 12 | } 13 | 14 | # ---- setup ---- 15 | if (SETUP) { 16 | drive_upload(system.file("DESCRIPTION"), nm_("update-fodder")) 17 | drive_upload(system.file("DESCRIPTION"), nm_("not-unique")) 18 | drive_upload(system.file("DESCRIPTION"), nm_("not-unique")) 19 | } 20 | 21 | # ---- tests ---- 22 | test_that("drive_update() errors if local media does not exist", { 23 | expect_snapshot(drive_update(dribble(), "nope123"), error = TRUE) 24 | }) 25 | 26 | test_that("drive_update() informatively errors if the path does not exist", { 27 | skip_if_no_token() 28 | skip_if_offline() 29 | expect_snapshot( 30 | drive_update(nm_("does-not-exist"), system.file("DESCRIPTION")), 31 | error = TRUE 32 | ) 33 | }) 34 | 35 | test_that("drive_update() informatively errors if the path is not unique", { 36 | skip_if_no_token() 37 | skip_if_offline() 38 | expect_snapshot( 39 | drive_update(nm_("not-unique"), system.file("DESCRIPTION")), 40 | error = TRUE 41 | ) 42 | }) 43 | 44 | test_that("no op if no media, no metadata", { 45 | skip_if_no_token() 46 | skip_if_offline() 47 | 48 | local_drive_loud_and_wide() 49 | expect_snapshot( 50 | out <- drive_update(nm_("update-fodder")), 51 | ) 52 | expect_dribble(out) 53 | }) 54 | 55 | test_that("drive_update() can update metadata only", { 56 | skip_if_no_token() 57 | skip_if_offline() 58 | defer_drive_rm(me_("update-me")) 59 | 60 | updatee <- drive_cp(nm_("update-fodder"), name = me_("update-me")) 61 | out <- drive_update(updatee, starred = TRUE) %>% promote("starred") 62 | expect_true(out$starred) 63 | }) 64 | 65 | test_that("drive_update() uses multipart request to update media + metadata", { 66 | skip_if_no_token() 67 | skip_if_offline() 68 | defer_drive_rm(c(me_("update-me"), me_("update-me-new"))) 69 | 70 | updatee <- drive_cp(nm_("update-fodder"), name = me_("update-me")) 71 | tmp <- tempfile() 72 | now <- as.character(Sys.time()) 73 | write_utf8(now, tmp) 74 | 75 | out <- drive_update(updatee, media = tmp, name = me_("update-me-new")) 76 | expect_identical(out$id, updatee$id) 77 | drive_download(updatee, tmp, overwrite = TRUE) 78 | now_out <- read_utf8(tmp) 79 | expect_identical(now, now_out) 80 | expect_identical(out$name, me_("update-me-new")) 81 | }) 82 | -------------------------------------------------------------------------------- /tests/testthat/test-drive_user.R: -------------------------------------------------------------------------------- 1 | test_that("drive_user() reports on the user", { 2 | skip_if_no_token() 3 | skip_if_offline() 4 | 5 | user <- drive_user() 6 | expect_s3_class(user, "drive_user") 7 | expect_true(all(c("displayName", "emailAddress") %in% names(user))) 8 | }) 9 | -------------------------------------------------------------------------------- /tests/testthat/test-fixtures/just_a_dribble.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tidyverse/googledrive/f806c49e62b34fc0150a7bd67fde1885ae479b9e/tests/testthat/test-fixtures/just_a_dribble.rds -------------------------------------------------------------------------------- /tests/testthat/test-fixtures/mix_of_files_and_teamdrives.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tidyverse/googledrive/f806c49e62b34fc0150a7bd67fde1885ae479b9e/tests/testthat/test-fixtures/mix_of_files_and_teamdrives.rds -------------------------------------------------------------------------------- /tests/testthat/test-promote.R: -------------------------------------------------------------------------------- 1 | test_that("promote() works when input has zero rows", { 2 | dib <- dribble() 3 | tib <- as_tibble(dib) 4 | tib_out <- tibble::add_column(tib, bar = list(), .after = 1) 5 | dib_out <- as_dribble(tib_out) 6 | 7 | expect_identical(promote(tib, "bar"), tib_out) 8 | expect_identical(promote(dib, "bar"), dib_out) 9 | }) 10 | 11 | test_that("promote() works when elem uniformly present or absent", { 12 | x <- tibble( 13 | name = c("a", "b", "c"), 14 | id = c("1", "2", "3"), 15 | drive_resource = list( 16 | list(foo = "a1"), 17 | list(foo = "b2"), 18 | list(foo = "c3") 19 | ) 20 | ) 21 | 22 | expect_identical( 23 | promote(x, "foo"), 24 | tibble::add_column(x, foo = c("a1", "b2", "c3"), .after = 1) 25 | ) 26 | 27 | expect_identical( 28 | promote(x, "bar"), 29 | tibble::add_column(x, bar = list(NULL, NULL, NULL), .after = 1) 30 | ) 31 | }) 32 | 33 | test_that("promote() works when elem is partially present", { 34 | x <- tibble( 35 | name = c("a", "b", "c"), 36 | id = c("1", "2", "3"), 37 | drive_resource = list( 38 | list(foo = "a1", bar = TRUE), 39 | list(foo = "b2", qux = list(letter = "b")), 40 | list(foo = "c3", baz = "c3") 41 | ) 42 | ) 43 | 44 | expect_identical( 45 | promote(x, "bar"), 46 | tibble::add_column(x, bar = c(TRUE, NA, NA), .after = 1) 47 | ) 48 | expect_identical( 49 | promote(x, "qux"), 50 | tibble::add_column(x, qux = list(NULL, list(letter = "b"), NULL), .after = 1) 51 | ) 52 | expect_identical( 53 | promote(x, "baz"), 54 | tibble::add_column(x, baz = c(NA, NA, "c3"), .after = 1) 55 | ) 56 | }) 57 | 58 | test_that("promote() replaces existing element in situ", { 59 | x <- tibble( 60 | name = "a", 61 | foo = "b", 62 | bar = "c", 63 | id = "1", 64 | drive_resource = list( 65 | list(foo = "d", bar = "e") 66 | ) 67 | ) 68 | x2 <- promote(x, "foo") 69 | x3 <- promote(x2, "bar") 70 | expect_identical(x3$foo, "d") 71 | expect_identical(x3$bar, "e") 72 | }) 73 | 74 | test_that("promote() does snake_case to camelCase conversion internally", { 75 | x <- tibble( 76 | name = "name", 77 | id = "id", 78 | drive_resource = list( 79 | list(thisThat = "hi") 80 | ) 81 | ) 82 | 83 | out <- promote(x, "this_that") 84 | expect_identical(out[2], tibble(this_that = "hi")) 85 | 86 | out <- promote(x, "thisThat") 87 | expect_identical(out[2], tibble(thisThat = "hi")) 88 | }) 89 | -------------------------------------------------------------------------------- /tests/testthat/test-shared_drives.R: -------------------------------------------------------------------------------- 1 | test_that("new_corpus() checks type and length, if not-NULL", { 2 | expect_silent(new_corpus()) 3 | expect_silent( 4 | new_corpus(driveId = "1", corpora = "b", includeItemsFromAllDrives = FALSE) 5 | ) 6 | expect_snapshot(new_corpus(driveId = c("1", "2")), error = TRUE) 7 | expect_snapshot(new_corpus(corpora = c("a", "b")), error = TRUE) 8 | expect_snapshot(new_corpus(includeItemsFromAllDrives = c(TRUE, FALSE)), error = TRUE) 9 | }) 10 | 11 | test_that("`corpora` is checked for validity", { 12 | expect_silent(shared_drive_params(corpora = "user")) 13 | expect_silent(shared_drive_params(corpora = "allDrives")) 14 | expect_silent(shared_drive_params(corpora = "domain")) 15 | expect_snapshot(shared_drive_params(corpora = "foo"), error = TRUE) 16 | }) 17 | 18 | test_that('`corpora = "drive"` requires shared drive specification', { 19 | expect_snapshot(shared_drive_params(corpora = "drive"), error = TRUE) 20 | }) 21 | 22 | test_that('`corpora != "drive"` rejects shared drive specification', { 23 | expect_snapshot( 24 | shared_drive_params(corpora = "user", driveId = "123"), 25 | error = TRUE 26 | ) 27 | }) 28 | 29 | test_that("a shared drive can be specified w/ corpora", { 30 | expect_silent(shared_drive_params(corpora = "drive", driveId = "123")) 31 | }) 32 | 33 | test_that('`corpora = "drive" is inferred from shared drive specification', { 34 | out <- shared_drive_params(driveId = "123") 35 | expect_identical(out$corpora, "drive") 36 | }) 37 | -------------------------------------------------------------------------------- /tests/testthat/test-shortcut.R: -------------------------------------------------------------------------------- 1 | # ---- nm_fun ---- 2 | me_ <- nm_fun("TEST-shortcut") 3 | nm_ <- nm_fun("TEST-shortcut", user_run = FALSE) 4 | 5 | # ---- clean ---- 6 | if (CLEAN) { 7 | drive_trash(c( 8 | nm_("top-level-file"), 9 | nm_("i-am-a-folder"), 10 | nm_("good-shortcut"), 11 | nm_("bad-shortcut") 12 | )) 13 | } 14 | 15 | # ---- setup ---- 16 | if (SETUP) { 17 | good_target <- drive_upload( 18 | system.file("DESCRIPTION"), 19 | nm_("top-level-file") 20 | ) 21 | shortcut_create(good_target, name = nm_("good-shortcut"), overwrite = FALSE) 22 | 23 | drive_mkdir(nm_("i-am-a-folder"), overwrite = FALSE) 24 | 25 | bad_target <- drive_upload( 26 | system.file("DESCRIPTION"), 27 | nm_("target-to-delete") 28 | ) 29 | shortcut_create(bad_target, name = nm_("bad-shortcut"), overwrite = FALSE) 30 | drive_rm(bad_target) 31 | } 32 | 33 | # ---- tests ---- 34 | test_that("shortcut_create() works", { 35 | skip_if_no_token() 36 | skip_if_offline() 37 | 38 | target_file <- drive_get(nm_("top-level-file")) 39 | folder <- drive_get(nm_("i-am-a-folder")) 40 | sc_name <- me_("custom-named-shortcut") 41 | 42 | local_drive_loud_and_wide() 43 | shortcut_create_message <- capture.output( 44 | sc <- shortcut_create(target_file, path = folder, name = sc_name), 45 | type = "message" 46 | ) 47 | defer_drive_rm(sc) 48 | shortcut_create_message <- shortcut_create_message %>% 49 | scrub_filepath(sc_name) %>% 50 | scrub_file_id() 51 | expect_snapshot( 52 | write_utf8(shortcut_create_message) 53 | ) 54 | 55 | expect_true(is_shortcut(sc)) 56 | expect_equal( 57 | drive_reveal(sc, "parent")$id_parent, 58 | folder$id 59 | ) 60 | expect_match(sc$name, "custom-named-shortcut") 61 | }) 62 | 63 | test_that("shortcut_create() requires `name` to control `overwrite`", { 64 | skip_if_no_token() 65 | skip_if_offline() 66 | 67 | expect_snapshot( 68 | shortcut_create(nm_("top-level-file"), overwrite = FALSE), 69 | error = TRUE 70 | ) 71 | }) 72 | 73 | test_that("shortcut_resolve() works", { 74 | skip_if_no_token() 75 | skip_if_offline() 76 | 77 | target_file <- drive_get(nm_("top-level-file")) 78 | dat <- drive_find(nm_(""), type = "shortcut") 79 | dat <- shortcut_resolve(dat) 80 | 81 | expect_true(is.na(dat$name[grep("bad", dat$name_shortcut)])) 82 | expect_equal( 83 | dat$name[grep("good", dat$name_shortcut)], 84 | target_file$name 85 | ) 86 | }) 87 | -------------------------------------------------------------------------------- /tests/testthat/test-utils-ui.R: -------------------------------------------------------------------------------- 1 | test_that("warn_for_verbose() does nothing for `verbose = TRUE`", { 2 | expect_warning(warn_for_verbose(TRUE), NA) 3 | }) 4 | 5 | test_that("warn_for_verbose() warns for `verbose = FALSE` w/ good message", { 6 | drive_something <- function() { 7 | withr::local_options(lifecycle_verbosity = "warning") 8 | warn_for_verbose(FALSE) 9 | } 10 | expect_snapshot( 11 | drive_something() 12 | ) 13 | }) 14 | 15 | test_that("warn_for_verbose(FALSE) makes googledrive quiet, in scope", { 16 | withr::local_options(lifecycle_verbosity = "quiet") 17 | local_drive_loud_and_wide() 18 | drive_something <- function() { 19 | warn_for_verbose(verbose = FALSE) 20 | drive_bullets("this message should not be emitted") 21 | } 22 | 23 | expect_snapshot({ 24 | drive_bullets("chatty before") 25 | drive_something() 26 | drive_bullets("chatty after") 27 | }) 28 | }) 29 | -------------------------------------------------------------------------------- /tests/testthat/test-utils.R: -------------------------------------------------------------------------------- 1 | # ---- tests ---- 2 | test_that("put_column() adds a column in the right place", { 3 | df <- tibble(v1 = 1, v2 = 2) 4 | expect_identical( 5 | put_column(df, nm = "insert", val = 3, .after = "v1"), 6 | tibble(v1 = 1, insert = 3, v2 = 2) 7 | ) 8 | }) 9 | 10 | test_that("put_column() updates an existing column", { 11 | df <- tibble(v1 = 1, v2 = 2) 12 | expect_identical( 13 | put_column(df, nm = "v3", val = "hi"), 14 | tibble(v1 = 1, v2 = 2, v3 = "hi") 15 | ) 16 | }) 17 | 18 | test_that("put_column() works with an expression", { 19 | df <- tibble(v1 = 1, v2 = 2) 20 | stuff <- "stuff" 21 | expect_identical( 22 | put_column(df, nm = "v3", val = stuff), 23 | tibble(v1 = 1, v2 = 2, v3 = "stuff") 24 | ) 25 | }) 26 | 27 | test_that("and() protects its inputs with parentheses", { 28 | x <- c("organizerCount > 5", "memberCount > 20") 29 | expect_identical( 30 | as.character(and(c("createdTime > '2019-01-01T12:00:00'", or(x)))), 31 | "(createdTime > '2019-01-01T12:00:00') and (organizerCount > 5 or memberCount > 20)" 32 | ) 33 | }) 34 | -------------------------------------------------------------------------------- /vignettes/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.R 3 | -------------------------------------------------------------------------------- /vignettes/articles/.gitignore: -------------------------------------------------------------------------------- 1 | *_cache 2 | -------------------------------------------------------------------------------- /vignettes/articles/bring-your-own-client.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Bring your own OAuth client or API key" 3 | --- 4 | 5 | ```{r setup, include = FALSE} 6 | knitr::opts_chunk$set( 7 | collapse = TRUE, 8 | comment = "#>", 9 | error = TRUE 10 | ) 11 | ``` 12 | 13 | ## Role of the OAuth client and API key 14 | 15 | googledrive helps you obtain a token to work with the Google Drive API from R primarily through the `drive_auth()` function. Under the hood, that process relies on an OAuth client and secret, a.k.a. an "OAuth client". 16 | 17 | googledrive can also make unauthorized calls to the Google Drive API, for example accessing a file available to "Anyone with a link", by sending an API key, instead of a user token. 18 | 19 | If there is a problem with googledrive's internal OAuth client or API key or if you would prefer to use your own, you can configure this. Below we describe how. 20 | 21 | ## Get an OAuth client and tell googledrive about it 22 | 23 | Follow the instructions in the gargle article [How to get your own API credentials](https://gargle.r-lib.org/articles/get-api-credentials.html) to get an OAuth client ID and secret. Now register it with googledrive. 24 | 25 | Preferred method: Provide the path to the JSON file downloaded from the [Google Cloud Platform Console](https://console.cloud.google.com). 26 | 27 | ```{r eval = FALSE} 28 | drive_auth_configure( 29 | path = "/path/to/the/JSON/you/downloaded/from/google/dev/console.json" 30 | ) 31 | ``` 32 | 33 | It is also possible, though discouraged, to directly use the constructor `gargle::gargle_oauth_client()`. 34 | 35 | Confirm success and carry on! You can see the currently configured OAuth client like so: 36 | 37 | ```{r eval = FALSE} 38 | drive_oauth_client() 39 | ``` 40 | 41 | You should see your own client there now. 42 | 43 | For the rest of this R session, when you get a new token with `drive_auth()`, your OAuth client is used. 44 | 45 | ## Get an API key and tell googledrive about it 46 | 47 | Follow the instructions in the gargle article [How to get your own API credentials](https://gargle.r-lib.org/articles/get-api-credentials.html) to get an API key. You probably want to use the same GCP project to create both your OAuth client (above) and your API key. Now register it with googledrive. 48 | 49 | ```{r eval = FALSE} 50 | drive_auth_configure(api_key = "YOUR_API_KEY_GOES_HERE") 51 | ``` 52 | 53 | Confirm success and carry on! You can see the currently configured API key like so: 54 | 55 | ```{r eval = FALSE} 56 | drive_api_key() 57 | ``` 58 | 59 | You should see your own API key now. 60 | 61 | For the rest of this R session, if you go into a de-authorized state via `drive_deauth()`, your API key will be sent with the request. 62 | -------------------------------------------------------------------------------- /vignettes/googledrive.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "googledrive" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{googledrive} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | Please see the googledrive website for full documentation: 11 | 12 | * 13 | 14 | In addition to function-specific help, there are several articles which are indexed here: 15 | 16 | * [Article index](https://googledrive.tidyverse.org/articles/index.html) 17 | --------------------------------------------------------------------------------